.site-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0.7rem 1.25rem;
  /* Ink. The hero's gradient starts on this exact colour, so header and hero
     read as one block with no seam -- which is what stopped the hero looking
     dropped in. No bottom border, for the same reason. */
  background: var(--ink);
}
.wordmark { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
.site-nav a {
  color: #E6E9E6;
  font-weight: 600;
  margin-left: 1rem;
  font-size: 0.95rem;
}
.site-nav a:first-child { margin-left: 0; }
.site-nav a:hover, .site-nav a:focus, .site-nav a[aria-current="page"] {
  color: var(--paper-light); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 6px;
}

/* Dark footer, bookending the dark hero so the page reads as framed.
   The previous version stacked three uneven columns and gave links and
   plain information the same 43px row spacing, so ten items dripped down
   the page with nothing grouping them. Order of importance here is:
   brand, then the phone (the actual conversion for a local business),
   then navigation, then legal. */
.site-footer {
  background: var(--ink);
  color: #C9CFCB;
  margin-top: 3rem;
  padding: 2.5rem 1.25rem 1.75rem;
  font-size: 0.9rem;
}
.f-top {
  max-width: 900px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: 2rem 3rem;
  align-items: start;
}
.f-lockup {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  margin-bottom: 0.9rem;
}
/* Scope to the badge. A bare `.f-lockup img` also matched the tagline image
   and forced it to 40px tall, which blew it out to 551px wide and overflowed
   every page horizontally on a phone. */
.f-lockup img.mark-badge { height: 48px; }
.f-brand p { margin: 0; max-width: 36ch; line-height: 1.6; color: #9AA39D; }

.f-cta { display: flex; flex-direction: column; align-items: flex-start; gap: 0.55rem; }
.f-cta-label { font-weight: 600; font-size: 0.85rem; color: #9AA39D; }
/* Plain text, not a button: the number itself is the call to action. */
.f-phone {
  display: inline-block;
  padding: 0.55rem 0;                    /* 44px tap target without a box */
  font-family: var(--font-display);
  font-size: 1.45rem;
  letter-spacing: 0.02em;
  color: #fff;
  text-decoration: none;
  line-height: 1.1;
}
.f-mail { color: #C9CFCB; text-decoration: none; padding: 0.15rem 0; }
@media (max-width: 768px) {
  .f-mail { display: inline-block; padding: 0.55rem 0; }
  .quote-print .btn-link { min-height: 40px; }
}
a.f-phone:hover, a.f-phone:focus, a.f-mail:hover, a.f-mail:focus { color: #fff; text-decoration: underline; }
.f-hours { color: #C9CFCB; }
.f-area { color: #7F8983; font-size: 0.85rem; max-width: 34ch; }

.f-links {
  max-width: 900px;
  margin: 2rem auto 0;
  padding-top: 1.25rem;
  border-top: 1px solid #333B36;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.75rem;
}
/* Tap-target height = (font-size x line-height) + 2 x padding. Here that is
   (14.4 x 1.4) + 2p = 20.2 + 2p, so clearing the 40px floor needs p >= 0.62rem.
   0.5rem lands at 36px and 0.55rem at 38px; both fail. Do not trim this
   without redoing that arithmetic.
   Only the links carry the padding; plain information does not, which is
   what keeps the row reading as navigation rather than more prose. */
.f-links a {
  color: #C9CFCB;
  text-decoration: none;
  font-weight: 600;
  padding: 0.7rem 0;
  line-height: 1.4;
}
.f-links a:hover, .f-links a:focus { color: #fff; text-decoration: underline; }

.f-base {
  max-width: 900px;
  margin: 1.1rem auto 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.4rem 1.5rem;
  font-size: 0.8rem;
  color: #7F8983;
}
.f-base span { max-width: none; }

.hero {
  /* Bleed to the container edges, not the viewport. A viewport bleed inside
     a centered .container needs calc(50% - 50vw) margins, which is the usual
     source of horizontal overflow on phones. */
  position: relative;
  /* Full-viewport bleed with a clean bottom edge (taste pass A): the old
     fade into the paper left a grey smear across the page. */
  margin: 0 calc(50% - 50vw);
  /* 430 = half the 860px content box, same as .band, so hero text lines up
     with the page below it. */
  padding: 3.5rem max(1.25rem, calc(50vw - 430px)) 4.5rem;
  /* background-color is the fallback for the moment before the image loads
     and for the case where it is missing entirely. The hero reads fine on
     flat ink, so a 404 on the photo degrades rather than breaks. */
  background-color: var(--ink);
  --hero-fade: linear-gradient(180deg,
      var(--ink) 0%,
      rgba(14, 16, 14, 0.80) 22%,
      rgba(14, 16, 14, 0.72) 55%,
      rgba(20, 22, 18, 0.86) 100%);
  /* hero2-* replaced hero1.jpg 2026-10-13 (new name: these URLs live inside
     this stylesheet and ride its hash). Full-resolution source stays in
     assets-source/. */
  --hero-photo: url('/static/img/hero2-960.jpg');
  background-image: var(--hero-fade), var(--hero-photo);
  background-size: cover;
  background-position: center;
  color: var(--paper-light);
}
@supports (background-image: image-set(url('x.webp') type('image/webp'))) {
  .hero { --hero-photo: image-set(url('/static/img/hero2-960.webp') type('image/webp'), url('/static/img/hero2-960.jpg') type('image/jpeg')); }
}
@media (min-width: 961px) {
  .hero { --hero-photo: url('/static/img/hero2-1600.jpg'); }
  @supports (background-image: image-set(url('x.webp') type('image/webp'))) {
    .hero { --hero-photo: image-set(url('/static/img/hero2-1600.webp') type('image/webp'), url('/static/img/hero2-1600.jpg') type('image/jpeg')); }
  }
}
.hero-copy { min-width: 0; }
.hero-eyebrow {
  font-weight: 600;
  font-size: 0.95rem;
  color: rgba(255, 255, 255, 0.82);
  margin: 0 0 0.6rem;
}
.hero h1 { margin: 0 0 0.6rem; color: var(--paper-light); }
.hero .tagline {
  font-size: 1.1rem;
  max-width: 34em;
  color: var(--paper-light);
  margin: 0;
}
.hero .actions { margin-top: 1.5rem; display: flex; gap: 0.75rem; flex-wrap: wrap; }
/* The global .btn-outline is ink-on-transparent, which is invisible on the
   dark hero. Override both border and text to paper. */
.hero .actions .btn-outline {
  background: transparent;
  color: var(--paper-light);
  border: 2px solid var(--paper-light);
}
.hero .actions .btn-outline:hover { background: var(--paper-light); color: var(--ink); }
.hero-proof {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  margin: 1.75rem 0 0;
  padding: 0;
  font-size: 0.9rem;
  font-weight: 600;
}
.hero-proof-item { position: relative; padding-left: 1.4rem; }
.hero-proof-item::before {
  content: "\2713";
  position: absolute;
  left: 0;
  color: var(--paper-light);
  font-weight: 700;
}

/* Hang-tag signature component: clipped corner + hole punch, like a price tag */
.tag {
  position: relative;
  background: var(--paper-light);
  border: 1px solid var(--steel);
  padding: 1.1rem 1.2rem;
  margin: 1rem 0;
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 0 100%);
}

.services-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
  margin: 1.5rem 0;
}

.services-grid .card {
  display: block;
  color: var(--ink);
  text-decoration: none;
  margin: 0;
  transition: transform 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}
/* The global a:hover underline would drag every word in the card with it. */
.services-grid .card:hover,
.services-grid .card:focus { text-decoration: none; }
.services-grid .card h3 { color: var(--ink); }
.services-grid .card p { color: var(--steel); margin-bottom: 0.75rem; }
.services-grid .card .card-cta {
  color: var(--rust);
  font-weight: 600;
  font-size: 0.9rem;
}
@media (hover: hover) {
  .services-grid .card:hover {
    transform: translateY(-2px);
    border-color: var(--rust);
    box-shadow: 0 6px 16px rgba(27, 27, 27, 0.14);
  }
}
@media (prefers-reduced-motion: reduce) {
  .services-grid .card { transition: none; }
  .services-grid .card:hover { transform: none; }
}

.listing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 1.1rem;
  margin: 1.5rem 0;
}
.listing-grid .tag { margin: 0; }
.listing-grid .tag a { color: var(--ink); font-weight: 700; }
.listing-grid img { width: 100%; height: 160px; object-fit: cover; border: 1px solid var(--steel); display: block; margin-bottom: 0.5rem; }

.listing-photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0.6rem;
  margin: 1rem 0;
}
.listing-photos img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border: 1px solid var(--steel);
  display: block;
}

.status-available { color: var(--moss); font-weight: 700; text-transform: uppercase; font-size: 0.85rem; }
.status-asis {
  display: inline-block;
  color: var(--ink);
  background: var(--warn);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 0.75rem;
  padding: 0.1rem 0.5rem;
  border-radius: 2px;
}



.filter-bar {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  align-items: center;
  margin: 1rem 0;
}
.filter-bar select, .filter-bar input { max-width: 160px; margin: 0; }

@media (max-width: 768px) {
  .site-nav { display: none; }
  /* Left-aligned on mobile. The mark is a two-line lockup now, not a lone
     badge, so it reads as deliberate without being centred. */
  .site-header { justify-content: flex-start; }
  img.mark-badge { height: 50px; }
  img.mark-tag { height: 17px; }
  .hero { padding: 2.25rem 1.25rem 4rem; }
  .hero-proof { flex-direction: column; gap: 0.5rem; }
  /* Clear the fixed bottom bar. The footer, not .container, carries this:
     the footer is a sibling of <main> and is the last element on every
     public page, so padding the container would leave the footer itself
     hidden under the bar. */
  .site-footer { padding: 2rem 1.25rem calc(5rem + env(safe-area-inset-bottom)); }
  .f-top { grid-template-columns: 1fr; gap: 1.6rem; }
  /* Full-width call button: it is the primary action on a phone. */
  .f-phone { width: 100%; justify-content: center; font-size: 1.35rem; }
  .f-links { gap: 0.2rem 1.5rem; }
  .f-base { flex-direction: column; gap: 0.35rem; }
  .filter-bar { gap: 0.5rem; }
  .filter-bar select, .filter-bar input { max-width: none; flex: 1 1 45%; }
  .filter-bar button { flex: 1 1 100%; margin-top: 0; }
  .listing-grid .tag a { display: block; padding: 0.3rem 0; }
  .site-header { padding: 0.6rem 1.25rem; }
  /* The browser scrolls a focused input or a scrollIntoView target the
     minimum distance, which parks it flush with the viewport bottom --
     directly underneath the fixed bar, where taps hit the bar instead.
     scroll-margin-bottom is how the element tells the browser to stop
     short of the bar. */
  .form-card input,
  .form-card select,
  .form-card textarea,
  .form-card button,
  form button[type="submit"] { scroll-margin-bottom: 6rem; }
}

/* ---- Free Pickup page ---------------------------------------------------
   The form used to stand alone in a 560px column inside a 900px page, so the
   right half of every desktop render was empty and the page read as a bare
   list of boxes. The aside fills that space with the three things people ask
   before handing over a machine, and the hero gives the page the same dark
   band every other page opens with. */
.hero.hero-compact {
  padding-top: 2.75rem; padding-bottom: 2rem;
  background: var(--paper); color: var(--text);
  border-bottom: 1px solid var(--steel-light);
}
.hero.hero-compact h1, .hero.hero-compact .tagline { color: var(--text); }
.hero.hero-compact h1 { font-size: clamp(1.9rem, 5vw, 2.8rem); }
.hero.hero-compact .hero-eyebrow { color: var(--text-muted); }
.hero.hero-compact .hero-proof-item::before { color: var(--color-pass); }
.hero.hero-compact .actions .btn-outline { color: var(--text); border-color: var(--text); }
.hero.hero-compact .actions .btn-outline:hover { background: var(--text); color: var(--paper-light); }

.pickup-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 2rem 3rem;
  align-items: start;
  margin-top: 1.75rem;
}
/* .form-card is width-capped for forms that stand alone on a page. Inside the
   grid the column is the cap, so the card fills its track instead. */
.pickup-layout .form-card { max-width: none; margin: 0; }

/* Name and phone are both short. Paired, they break the column of identical
   full-width rectangles that made the form look longer than it is.
   Deliberately a min-width query rather than flex-wrap: the form column is
   ~410px wide, close enough to two 12rem fields plus the gap that wrapping
   was a coin toss. Below the breakpoint the row is a plain block and the
   fields stack full width, which is what a phone wants anyway. */
@media (min-width: 861px) {
  .field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }
}

.opt { font-weight: 400; font-size: 0.85rem; color: var(--steel); }

.pickup-aside { position: sticky; top: 1.5rem; }
.pickup-aside h2 { margin-top: 0; }

/* A real sequence, so it gets real numerals. Ink, not orange or green:
   orange means "click", green means "checked". */
.steps { list-style: none; margin: 0 0 1.5rem; padding: 0; }
.steps li {
  display: flex;
  gap: 0.85rem;
  padding: 0.8rem 0;
  border-bottom: 1px solid var(--steel-light);
}
.steps li:last-child { border-bottom: none; padding-bottom: 0; }
.steps p { margin: 0; max-width: none; }
.step-lead { display: block; font-weight: 600; }
.step-n {
  flex: none;
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--text);
  border: 1.5px solid var(--text);
  border-radius: 50%;
}

.dropzone {
  border: 2px dashed var(--steel);
  border-radius: 4px;
  background: var(--paper);
  padding: 1.1rem;
  text-align: center;
}
.dropzone.is-over { border-color: var(--rust); background: #FCEADF; }
.dz-prompt { display: block; margin: 0 0 0.7rem; max-width: none; font-weight: 600; }
/* The box is the control. The input stays real, so it works with JS off and
   to assistive tech, but it is visually hidden, not display:none. */
.dropzone { cursor: pointer; display: block; position: relative; font-weight: 400; }
.dropzone .dz-input { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.dropzone:focus-within { outline: 3px solid var(--rust); outline-offset: 2px; }
.dz-link { color: var(--rust-text); font-weight: 600; text-decoration: underline; }
.dz-status { display: block; margin: 0.7rem 0 0; max-width: none; font-size: 0.85rem; color: var(--steel); }
.dropzone.is-too-big { border-color: var(--rust); border-style: solid; }
.dropzone.is-too-big .dz-status { color: var(--rust-text); font-weight: 600; }

.form-foot { margin: 0.9rem 0 0; max-width: none; font-size: 0.85rem; color: var(--steel); }

.pickup-confirm { max-width: 38em; margin-top: 1.75rem; }

/* Collapses earlier than the site's 768px breakpoint on purpose: between
   768 and 860 the two tracks are narrow enough that the form fields wrap
   anyway, so the pair stops buying anything before the layout breaks. */
@media (max-width: 860px) {
  .pickup-layout { grid-template-columns: 1fr; gap: 2rem; }
  .pickup-aside { position: static; }
}

/* A finished step is stated, not counted: the numeral would imply there is
   still something to do at that position. Steel rather than green keeps the
   eye on the steps that have not happened yet. */
.step-n.is-done { background: var(--steel); border-color: var(--steel); color: #fff; font-size: 1rem; }

/* Admin entry point. Deliberately in the legal baseline and not the footer
   nav: visitors have no use for it, and it should not read as a fifth
   destination beside Inventory and Contact. */
.f-admin { color: #7F8983; margin-right: 0.9rem; }
/* Links in the baseline (the guarantee) keep its grey: dark orange on ink is 3.08:1. */
.f-base a:not(.f-admin) { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.f-admin:hover, .f-admin:focus { color: var(--warn); text-decoration: none; }

/* Shown when a photo could not be decoded. Amber, not red: the request was
   accepted, only the attachment was not. */
.photo-note {
  background: #FFF6E5;
  border-left: 4px solid var(--warn);
  padding: 0.9rem 1.1rem;
  margin: 0 0 1.5rem;
  max-width: 46em;
}

/* Same box as .listing-grid img, so a photoless card lines up with its
   neighbours instead of collapsing the row. */
.listing-photo-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 160px;
  margin-bottom: 0.5rem;
  border: 1px dashed var(--steel);
  background: var(--paper);
  color: var(--steel);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Photo viewer ------------------------------------------------------- */

/* The thumbnail is a button, so strip the button chrome and let the image
   keep the grid cell it already had. */
.listing-photos .photo-thumb {
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  display: block;
  width: 100%;
  border-radius: 0;
}
.listing-photos .photo-thumb:focus-visible { outline: 3px solid var(--rust); outline-offset: 2px; }

/* :not([hidden]) is load-bearing. A bare `display: flex` here beats the
   `hidden` attribute's display:none, which left a full-screen overlay sitting
   invisibly over the page swallowing every click on the thumbnails beneath it. */
.lightbox:not([hidden]) {
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(10, 10, 10, 0.96);
  padding: 1rem;
}
/* The grid stays scrollable behind an overlay otherwise, which on a phone
   reads as the page moving under your finger. */
body.lightbox-open { overflow: hidden; }

.lightbox-img {
  max-width: 100%;
  max-height: 88vh;
  /* contain, not cover: the thumbnail crops, the full view must not. */
  object-fit: contain;
  display: block;
}

.lightbox-btn {
  position: absolute;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 4px;
  font-size: 1.8rem;
  line-height: 1;
  /* 44px: a thumb-sized target, not a mouse-sized one. */
  min-width: 44px;
  min-height: 44px;
  cursor: pointer;
  padding: 0;
}
.lightbox-btn:hover, .lightbox-btn:focus-visible { background: var(--rust); border-color: var(--rust); }
.lightbox-close { top: 1rem; right: 1rem; }
.lightbox-prev { left: 1rem; top: 50%; transform: translateY(-50%); }
.lightbox-next { right: 1rem; top: 50%; transform: translateY(-50%); }

.lightbox-count {
  position: absolute;
  bottom: 1rem;
  left: 0;
  right: 0;
  text-align: center;
  color: #fff;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  margin: 0;
}

@media (max-width: 600px) {
  .lightbox-prev { left: 0.4rem; }
  .lightbox-next { right: 0.4rem; }
  .lightbox-img { max-height: 78vh; }
  /* Clear of the fixed bottom tab bar, which sits beneath the backdrop but
     still occupies that strip of screen. */
  .lightbox-count { bottom: calc(4.25rem + env(safe-area-inset-bottom, 0px)); }
}

/* --- Customer quote / invoice (/q/<token>) ---------------------------------
   A document, not a web page: one card with a dark branded band, the job,
   the lines, then one big number. The band prints (color forced) so a saved
   PDF still looks like it came from the shop. */
.quote-doc {
  max-width: 42rem;
  margin: 1.75rem auto 3rem;
  background: #fff;
  border: 1px solid var(--steel-light);
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 10px 30px rgba(27, 27, 27, 0.08);
}
.quote-band {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 1.1rem 1.5rem;
  background: var(--ink);
  color: var(--paper-light);
  border-bottom: 4px solid var(--rust);
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
.qb-logo { height: 54px; width: auto; display: block; }
.qb-meta { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 0.3rem; }
.quote-kicker {
  margin: 0;
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.95rem;
  color: var(--paper-light);
}
.qb-date { margin: 0; font-size: 0.85rem; color: #B9C0BC; }
.quote-status {
  margin: 0;
  padding: 0.2rem 0.65rem;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.8rem;
  background: #4B5A63;
  color: #fff;
}
.quote-status-quote { background: var(--rust); }
.quote-status-approved, .quote-status-invoice { background: var(--moss); }
.quote-status-declined, .quote-status-cancelled { background: var(--sold); }

.quote-body { padding: 1.5rem 1.75rem 1.25rem; }
.quote-for-label { margin: 0; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--steel); }
.quote-for { margin: 0.1rem 0 1.25rem; font-size: 1.75rem; }

/* Progress: a line of dots. Done steps are solid green with a tick, the
   current one is ringed orange, the rest are hollow. */
.quote-track {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  margin: 0 0 1.5rem;
  padding: 0;
  counter-reset: none;
}
.qt-step { position: relative; display: flex; flex-direction: column; align-items: center; gap: 0.35rem; text-align: center; }
/* The connector runs from this dot to the previous one. */
.qt-step + .qt-step::before {
  content: "";
  position: absolute;
  top: 0.85rem;
  right: 50%;
  width: 100%;
  height: 3px;
  background: var(--steel-light);
  z-index: 0;
}
.qt-step.is-done + .qt-step::before { background: var(--moss); }
.qt-dot {
  position: relative;
  z-index: 1;
  width: 1.75rem;
  height: 1.75rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 0.8rem;
  font-weight: 700;
  background: #fff;
  border: 2px solid var(--steel-light);
  color: var(--steel);
}
.is-done .qt-dot { background: var(--moss); border-color: var(--moss); color: #fff; }
.is-current .qt-dot { border-color: var(--rust); color: var(--rust); box-shadow: 0 0 0 4px #FCE3D3; }
.qt-label { font-size: 0.78rem; font-weight: 600; color: var(--steel); line-height: 1.2; }
.is-done .qt-label { color: var(--ink); }
.is-current .qt-label { color: var(--rust-dark); }

.quote-job {
  margin: 0 0 1.5rem;
  padding: 1rem 1.15rem;
  background: var(--paper);
  border-left: 4px solid var(--moss);
  border-radius: 4px;
}
.quote-what { margin: 0; font-weight: 700; font-size: 1.1rem; color: var(--ink); }
.quote-job-h {
  border: none;
  padding: 0;
  margin: 0.8rem 0 0.25rem;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--steel);
}
.quote-what + .quote-job-h { margin-top: 0.8rem; }
.quote-job-h:first-child { margin-top: 0; }
.quote-problem { margin: 0; max-width: none; white-space: pre-line; line-height: 1.5; }
.quote-note { margin: 0 0 1.25rem; padding: 0.8rem 1.15rem; background: var(--paper); border-left: 4px solid var(--moss); border-radius: 4px; }
.quote-note .quote-job-h { margin-top: 0; }

.quote-lines { width: 100%; border-collapse: collapse; margin: 0 0 1.25rem; }
.quote-lines th, .quote-lines td { padding: 0.6rem 0; border-bottom: 1px solid #ECEEEC; text-align: left; vertical-align: top; }
.quote-lines thead th {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--steel);
  border-bottom: 2px solid var(--ink);
}
.quote-lines .num { text-align: right; white-space: nowrap; font-family: var(--font-display); font-variant-numeric: tabular-nums; padding-left: 1rem; }
.quote-lines small { color: var(--steel); }
.ql-discount td { color: var(--moss-dark); font-weight: 600; }
/* Optional lines: a tickbox to keep or drop; dropped ones stay, muted. */
.quote-lines .ql-pick { display: inline-flex; align-items: baseline; gap: 0.5rem; cursor: pointer; }
.ql-pick input { width: 1.15rem; height: 1.15rem; flex: none; accent-color: var(--moss-dark); }
.ql-opt { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; }
.quote-lines tr.is-off td { color: var(--steel); }
.ql-pick { font-weight: inherit; color: inherit; }
.quote-lines tr.is-off td.num { text-decoration: line-through; }
.quote-lines .ql-group th { padding-top: 1.1rem; font-family: var(--font-display); font-size: 0.85rem; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--steel); border-bottom: 1px solid var(--steel-light, #c9cdd1); }
.quote-hint { color: var(--steel); font-size: 0.95rem; }
@media print { .quote-lines tr.is-off { display: none; } }
.quote-lines tfoot th { font-weight: 400; color: var(--steel); }
.quote-lines tfoot tr:last-child th, .quote-lines tfoot tr:last-child td { border-bottom: none; }

/* The number that matters, big, in its own card; the approve form lives in
   the same card so the decision and the price are read together. */
.quote-pay, .quote-sum {
  border: 2px solid var(--ink);
  border-radius: 8px;
  padding: 1.1rem 1.25rem 1.25rem;
  margin: 0 0 1.25rem;
}
.quote-pay { background: var(--surface-raised); }
.qp-total { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.qp-total span {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 1rem;
}
.qp-total strong { font-family: var(--font-display); font-variant-numeric: tabular-nums; font-size: 2rem; line-height: 1.1; }
.qp-total.is-paid strong { color: var(--moss); }
.qp-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.35rem 0;
  border-bottom: 1px solid #ECEEEC;
  font-size: 0.95rem;
}
.qp-row .num { font-family: var(--font-display); font-variant-numeric: tabular-nums; white-space: nowrap; }
.qp-row + .qp-total { margin-top: 0.5rem; }
.quote-sum .quote-ok { margin: 0.9rem 0 0; }
.quote-approve { margin-top: 1rem; }
.quote-approve .field-checkbox { align-items: flex-start; }
.quote-approve .field-checkbox input { margin-top: 0.15rem; flex: none; }
.quote-approve button[type="submit"] { width: 100%; font-size: 1.05rem; padding-top: 0.8rem; padding-bottom: 0.8rem; }
.quote-decline { margin-top: 0.75rem; text-align: center; }

.quote-notice { background: #fff4d6; border-left: 4px solid #e0a800; padding: 0.6rem 0.8rem; max-width: none; }
.quote-ok { background: #eaf6ee; border-left: 4px solid #1f7a3a; padding: 0.6rem 0.8rem; max-width: none; }
/* Admin preview of a quote: sits above and below the page, never prints. */
.quote-preview-bar { max-width: 46rem; margin: 1rem auto; padding: 0.8rem 1rem; background: #fff4d6;
  border: 2px dashed #e0a800; border-radius: 6px; }
.quote-preview-bar.is-archive { background: #eef0f2; border-color: #8a939b; }
.quote-preview-bar p { margin: 0 0 0.6rem; max-width: none; }
.qpb-actions { display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; align-items: center; }
.qpb-actions form { margin: 0; }
.qpb-actions button { width: auto; }
.qpb-to { margin: 0.5rem 0 0 !important; font-size: 0.9rem; color: var(--steel); }
@media (max-width: 600px) {
  .quote-preview-bar { margin: 0.75rem 16px; }
  .qpb-actions form, .qpb-actions button { width: 100%; }
}
.quote-error { background: #fdecee; border-left: 4px solid #b0102c; padding: 0.6rem 0.8rem; max-width: none; margin-top: 0.75rem; }
.btn-link { background: none; border: none; padding: 0; color: var(--steel, #666); text-decoration: underline; cursor: pointer; font: inherit; width: auto; }
.quote-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  margin-top: 0.5rem;
  padding-top: 1rem;
  border-top: 1px solid #ECEEEC;
  font-size: 0.9rem;
  color: var(--steel);
}
.quote-foot p { margin: 0; }

@media (max-width: 600px) {
  .quote-doc { margin: 0.75rem 0 2rem; border-radius: 0; border-left: 0; border-right: 0; box-shadow: none; }
  .quote-band { padding: 0.9rem 1rem; }
  .qb-logo { height: 42px; }
  .quote-kicker { font-size: 0.82rem; }
  .quote-body { padding: 1.25rem 1rem 1rem; }
  .quote-for { font-size: 1.45rem; }
  .qt-label { font-size: 0.7rem; }
  .qp-total strong { font-size: 1.7rem; }
  .quote-pay, .quote-sum { padding: 1rem; }
}
@media print {
  .site-header, .site-footer, footer.site-footer, .bottom-nav, .quote-approve, .quote-decline, .quote-print,
  .quote-preview-bar { display: none !important; }
  .quote-doc { border: none; margin: 0; max-width: none; box-shadow: none; border-radius: 0; }
  .quote-pay { background: none; border-color: var(--ink); }
}

/* ---- Repair & Service page ------------------------------------------------
   Same frame as Free Pickup (.pickup-layout, .steps, .dropzone). The form is
   longer, so it is cut into three numbered sections, and the issues are big
   tap targets rather than a column of tiny checkboxes. */
.form-section { border: none; margin: 0 0 1.75rem; padding: 0; min-width: 0; }
.form-section legend {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0;
  margin: 0 0 0.9rem;
  font-family: var(--font-display);
  font-size: 1.15rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink);
}
.sec-n {
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  display: grid;
  place-items: center;
  font-size: 0.95rem;
  color: var(--text);
  border: 1.5px solid var(--text);
  border-radius: 50%;
}
.sec-hint { margin: -0.4rem 0 0.7rem; max-width: none; font-size: 0.9rem; color: var(--steel); }

@media (min-width: 861px) {
  .field-row-3 { grid-template-columns: 1.3fr 1.3fr 0.8fr; }
}

.issue-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
  margin: 0 0 1rem;
}
.issue-grid-2 { margin-bottom: 0; }
/* The repair form is the longer of the two, so it takes more of the row. */
@media (min-width: 861px) {
  .service-layout { grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); gap: 2rem 2.5rem; }
}
/* Stacked on a phone, a pair's second field is .field:last-of-type and loses
   its bottom margin, which jammed it against the next label. */
@media (max-width: 860px) {
  .field-row .field:last-of-type { margin-bottom: 1rem; }
}
.issue-chip {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 3rem;
  margin: 0;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--steel-light);
  border-radius: 4px;
  background: var(--paper);
  font-weight: 600;
  font-size: 0.92rem;
  line-height: 1.25;
  cursor: pointer;
}
.issue-chip input[type="checkbox"] { flex: none; width: 20px; height: 20px; accent-color: var(--moss); }
.issue-chip:hover { border-color: var(--steel); }
.issue-chip:has(input:checked) { border-color: var(--moss); background: #E8F2E8; }
.issue-chip:has(input:focus-visible) { outline: 2px solid var(--moss); outline-offset: 2px; }

.form-error {
  margin: 0 0 1.25rem;
  max-width: none;
  padding: 0.75rem 0.9rem;
  border-left: 4px solid var(--sold);
  background: #FBE9EC;
  font-weight: 600;
}

/* ---- Service packages (/service cards, /service/book/<slug>) -------------
   Cards sell: season badge, what's in it, the price, one orange button. The
   booking page reads like a checkout: form left, order summary right (sticky),
   and on phones a total bar above the tab bar that jumps to the summary. */
.pkg-section { margin-top: 2rem; scroll-margin-top: 1rem; }
.pkg-section > h2 { margin-bottom: 0.3rem; }
.season-callout {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-4);
  margin: 0 0 var(--space-6); padding: var(--space-5);
  background: var(--surface-raised); border: 1px solid var(--steel-light); border-left: 4px solid var(--text);
}
.season-callout-text { margin: var(--space-1) 0 0; font-family: var(--font-display); font-size: 1.35rem; line-height: 1.25; }
.season-callout .btn { margin: 0; }
.pkg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr)); gap: 1.1rem; margin-top: 1.1rem; }
.pkg-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 1.15rem 1.2rem 1.2rem;
  background: #fff;
  border: 1px solid var(--steel-light);
  border-top: 4px solid var(--moss);
  border-radius: 8px;
  box-shadow: 0 6px 18px rgba(27, 27, 27, 0.06);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.pkg-card:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(27, 27, 27, 0.1); }
.pkg-card.is-featured { border-top-color: var(--rust); background: #FFF8F3; }
.pkg-card.is-diagnosis { border-top-color: var(--warn); }
.pkg-ribbon {
  position: absolute; top: -0.75rem; right: 1rem;
  background: var(--rust); color: #fff;
  font-family: var(--font-display); font-size: 0.78rem; letter-spacing: 0.08em; text-transform: uppercase;
  padding: 0.25rem 0.65rem; border-radius: 999px;
}
.pkg-top { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
.pkg-badge {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--moss-dark); background: #E8F2E8; padding: 0.2rem 0.55rem; border-radius: 999px;
  white-space: nowrap;
}
.pkg-from { font-family: var(--font-display); font-variant-numeric: tabular-nums; font-size: 1.35rem; font-weight: 700; white-space: nowrap; }
.pkg-kicker { margin: 0.6rem 0 0; font-weight: 700; color: var(--rust-dark); max-width: none; }
.pkg-name { margin: 0.55rem 0 0.2rem; font-size: 1.3rem; }
.pkg-kicker + .pkg-name { margin-top: 0.1rem; }
.pkg-sum { margin: 0; color: var(--steel); max-width: none; font-size: 0.95rem; }
.pkg-save { margin: 0.45rem 0 0; font-weight: 700; color: var(--moss-dark); max-width: none; font-size: 0.92rem; }
.pkg-includes { list-style: none; margin: 0.8rem 0 1rem; padding: 0; font-size: 0.93rem; }
.pkg-includes li { display: flex; gap: 0.45rem; padding: 0.15rem 0; }
.pkg-check { color: var(--moss); font-weight: 700; flex: none; }
.pkg-more { color: var(--steel); padding-left: 1.3rem !important; }
.pkg-book { margin-top: auto; width: 100%; text-align: center; }
.pkg-or { margin-top: 2.5rem; scroll-margin-top: 1rem; }

/* Booking page */
.bk-price-badge { margin: 0.75rem 0 0; color: var(--text-muted); max-width: none; }
.bk-price-badge strong { font-family: var(--font-display); font-variant-numeric: tabular-nums; font-size: 1.5rem; color: var(--text); }
.bk-included {
  margin: 1.5rem 0 0; padding: 1rem 1.25rem; background: #fff; border: 1px solid var(--steel-light);
  border-left: 4px solid var(--moss); border-radius: 6px;
}
.bk-included h2 { margin: 0 0 0.5rem; font-size: 1.05rem; }
.bk-included ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: 0.2rem 1.25rem; }
.bk-included li { display: flex; gap: 0.45rem; }
.bk-included-note { margin: 0.6rem 0 0; font-size: 0.88rem; color: var(--steel); max-width: none; }
#bk-form { scroll-margin-top: 1rem; }
.bk-machines { display: grid; grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr)); gap: 0.5rem; margin: 0 0 1rem; }
.bk-machine {
  position: relative; display: flex; flex-direction: column; gap: 0.15rem; margin: 0; cursor: pointer;
  padding: 0.7rem 0.8rem; border: 2px solid var(--steel-light); border-radius: 6px; background: var(--paper);
}
.bk-machine input { position: absolute; opacity: 0; pointer-events: none; }
.bk-machine-name { font-weight: 700; line-height: 1.25; }
.bk-machine-price { font-family: var(--font-display); font-variant-numeric: tabular-nums; color: var(--steel); }
.bk-machine:hover { border-color: var(--steel); }
.bk-machine:has(input:checked) { border-color: var(--rust); background: #FFF3EA; }
.bk-machine:has(input:checked) .bk-machine-price { color: var(--rust-text); font-weight: 700; }
.bk-machine:has(input:focus-visible) { outline: 2px solid var(--rust); outline-offset: 2px; }

.bk-addons { display: grid; gap: 0.5rem; }
.bk-addon {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: 0.55rem 0.7rem; border: 1px solid var(--steel-light); border-radius: 4px; background: var(--paper); margin: 0;
}
.bk-addon-name { font-weight: 600; display: flex; flex-direction: column; }
.bk-addon-name small, .bk-addon-flat small { font-weight: 400; color: var(--steel); }
.bk-addon input[type="number"] { width: 4.5rem; margin: 0; }
/* An add-on that doesn't fit the chosen machine; beats .bk-addon/.issue-chip display. */
[data-machines][hidden] { display: none; }
.bk-trips { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.5rem; margin: 0 0 1rem; }
.bk-trips .issue-chip input { accent-color: var(--moss); }

.bk-aside { position: sticky; top: 1.25rem; }
.bk-summary { margin: 0; scroll-margin-top: 1rem; }
.bk-summary-h { margin: 0 0 0.6rem; font-size: 1.1rem; }
.bk-lines { list-style: none; margin: 0 0 0.25rem; padding: 0; }
.bk-lines li { display: flex; justify-content: space-between; gap: 1rem; padding: 0.35rem 0; border-bottom: 1px solid #ECEEEC; font-size: 0.95rem; }
.bk-lines .num { font-family: var(--font-display); font-variant-numeric: tabular-nums; white-space: nowrap; }
.bk-lines .bk-muted { color: var(--steel); }
.bk-note { margin: 0.6rem 0 0; font-size: 0.9rem; color: var(--steel); max-width: none; }
.bk-summary .field { margin-top: 1rem; }
.bk-summary button[type="submit"] { width: 100%; font-size: 1.1rem; padding-top: 0.85rem; padding-bottom: 0.85rem; }
.bk-summary button[disabled] { opacity: 0.55; cursor: not-allowed; }
.bk-bar { display: none; }

@media (max-width: 860px) {
  .bk-aside { position: static; }
  /* Phone/tablet: a total bar riding just above the bottom tab bar. */
  .bk-bar {
    display: flex; justify-content: space-between; align-items: center; gap: 0.75rem;
    position: fixed; left: 0; right: 0; bottom: calc(4.1rem + env(safe-area-inset-bottom, 0px)); z-index: 40;
    padding: 0.55rem 1rem; background: var(--ink); color: var(--paper-light);
    box-shadow: 0 -4px 14px rgba(0, 0, 0, 0.2);
  }
  .bk-bar .btn { padding: 0.55rem 1rem; margin: 0; }
  .bk-bar-total strong { font-family: var(--font-display); font-variant-numeric: tabular-nums; font-size: 1.15rem; color: var(--warn); }
  /* Room for the total bar too, so it never covers the end of the footer. */
  body:has(.bk-bar) .site-footer { padding-bottom: calc(9rem + env(safe-area-inset-bottom, 0px)); }
}
@media (min-width: 769px) and (max-width: 860px) { .bk-bar { bottom: 0; } }
@media (max-width: 600px) {
  .pkg-grid { grid-template-columns: 1fr; }
  .bk-trips { grid-template-columns: 1fr; }
  .bk-machines { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ==========================================================================
   Shop-ticket system (2026-10-13). The site argues "in writing", so its
   cards look like the paperwork a good shop hands you: work orders, stamps,
   inspection sheets. Tokens only; no raw hex below this line except the
   ruled-paper line colours, which have no semantic role.
   ========================================================================== */
.eyebrow {
  display: block; margin: 0 0 var(--space-1);
  font-weight: 600; font-size: 0.95rem; color: var(--text-muted);
}
.band-ink .eyebrow { color: var(--color-highlight); }

/* Full-bleed section bands, same bleed technique as .hero. */
/* 430 = half of .container's 860px content box, so band text lines up with
   the sections between bands. */
.band { margin: 0 calc(50% - 50vw); padding: var(--space-7) max(1.25rem, calc(50vw - 430px)); }
.band-white { background: var(--surface-raised); }
.band-ink { background: var(--surface-inverse); color: var(--text-inverse); }
.band-ink h2, .band-ink h3 { color: var(--text-inverse); }
.band-ink a:not(.btn) { color: var(--color-highlight); }
.band > h2 { margin-top: 0; }

/* Work-order ticket */
.ticket-grid { display: grid; gap: var(--space-5); grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
.ticket {
  position: relative; display: flex; flex-direction: column;
  background: var(--surface-raised); border: 1.5px solid var(--text); border-radius: 2px;
  padding: 0 var(--space-5) var(--space-5);
}
.ticket-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3);
  margin: 0 calc(-1 * var(--space-5)) var(--space-4); padding: var(--space-2) var(--space-5);
  border-bottom: 2px dashed var(--text);
  font-family: var(--font-mono); font-size: 0.74rem; letter-spacing: 0.1em; text-transform: uppercase;
}
.ticket-season { color: var(--text-muted); }
.ticket-kicker { margin: 0 0 var(--space-1); font-weight: 600; color: var(--text-muted); }
.ticket-name { margin: 0 0 var(--space-2); font-size: 1.3rem; }
.ticket-sum { margin: 0 0 var(--space-3); color: var(--text-muted); }
.ticket-checks { list-style: none; margin: 0 0 var(--space-4); padding: 0; }
.ticket-checks li { position: relative; padding: 0.3rem 0 0.3rem 1.9rem; border-bottom: 1px solid #E4E7E2; }
.ticket-checks li::before {
  content: "\2713"; position: absolute; left: 0.1rem; top: 0.3rem;
  color: var(--color-pass); font-weight: 700;
}
.ticket-checks li.ticket-more { color: var(--text-muted); font-style: italic; }
.ticket-checks li.ticket-more::before { content: "+"; color: var(--text-muted); }
.ticket-save { margin: 0 0 var(--space-3); font-weight: 600; color: var(--color-pass); }
.ticket-foot {
  margin-top: auto; padding-top: var(--space-3); border-top: 1px solid var(--steel-light);
  display: flex; justify-content: space-between; align-items: center; gap: var(--space-3);
}
.ticket-price { font-family: var(--font-display); font-size: 1.6rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.ticket-price small { font-family: var(--font-body); font-size: 0.85rem; font-weight: 400; color: var(--text-muted); }
.ticket-foot .btn { margin: 0; }
.ticket.is-plan { border-color: var(--color-pass); }
.ticket-ribbon { background: var(--color-highlight); color: var(--text); padding: 0.1rem 0.45rem; font-weight: 700; }

/* Rubber stamp. One per view. */
.stamp {
  display: inline-block;
  padding: 0.2rem 0.6rem; border: 2.5px solid currentColor; border-radius: 3px;
  font-family: var(--font-mono); font-weight: 700; font-size: 0.85rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--color-pass); background: transparent;
}
.stamp-sold { color: var(--sold); }
.stamp-pass { color: var(--color-pass); }

/* Inspection sheet: ruled paper with pass marks. */
.sheet { background: var(--surface-raised); border: 1.5px solid var(--text); padding: var(--space-4) var(--space-5); }
.sheet-title { margin: 0 0 var(--space-2); font-size: 1.15rem; }
.sheet-lines { list-style: none; margin: 0; padding: 0; }
.sheet-lines li {
  display: flex; justify-content: space-between; gap: var(--space-3);
  padding: 0.45rem 0; border-bottom: 1px solid #DCE3EA;
}
.sheet-lines li::after { content: "PASS"; font-family: var(--font-mono); font-size: 0.72rem; font-weight: 700; color: var(--color-pass); align-self: center; }
.sheet-grid { display: grid; gap: var(--space-5); grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); }

/* Proof band */
.proof-band .proof-photos { margin-top: var(--space-5); }
.proof-facts { list-style: none; margin: var(--space-4) 0 0; padding: 0; border-top: 1.5px solid var(--text); }
.proof-facts li {
  display: grid; grid-template-columns: 17rem minmax(0, 1fr); gap: var(--space-1) var(--space-5);
  padding: var(--space-4) 0; border-bottom: 1px solid var(--steel-light); line-height: 1.5;
}
.proof-facts strong { font-family: var(--font-display); font-weight: 600; font-size: 1.1rem; }
@media (max-width: 640px) { .proof-facts li { grid-template-columns: 1fr; } }
.proof-photos { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); margin: 0; }
.proof-photos figure { margin: 0; position: relative; }
.proof-photos img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }
.proof-photos figcaption {
  position: absolute; left: var(--space-2); bottom: var(--space-2);
  background: var(--paper-light); color: var(--text); padding: 0.15rem 0.5rem;
  font-family: var(--font-mono); font-size: 0.75rem;
}

/* Secondary paths */
.tiles { display: grid; gap: var(--space-5); grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
.tile { display: block; padding: var(--space-4) 0 0; border-top: 1.5px solid var(--text); color: var(--text); }
.tile:hover, .tile:focus { text-decoration: none; }
.tile:hover .card-cta, .tile:focus .card-cta { text-decoration: underline; }
.tile h3 { margin: 0 0 var(--space-2); }
.tile p { color: var(--text-muted); margin: 0 0 var(--space-3); }
.tile .card-cta { color: var(--rust-text); font-weight: 600; }

/* Service area */
.area-counties { margin: var(--space-2) 0 0; font-size: 1.1rem; }

/* Closing line: one sentence with the phone, not a band of buttons. */
.closing { margin: var(--space-7) 0 0; padding-top: var(--space-5); border-top: 1px solid var(--steel-light); }
.closing p { margin: 0; font-size: 1.1rem; text-wrap: pretty; }

/* Body copy measure and size (spec 4.2) */
main.container p { max-width: 65ch; }
@media (min-width: 769px) { body { font-size: 17px; line-height: 1.6; } }

/* Tap targets (spec 4.5): issue chips, booking radios, footer links. */
.issue-chip { min-height: 44px; display: flex; align-items: center; }
.issue-chip input[type="checkbox"], .issue-chip input[type="radio"] { width: 20px; height: 20px; }
@media (max-width: 768px) {
  .f-links a, .f-base a { display: inline-block; padding: 0.7rem 0.25rem; }
}

/* The bottom nav is not rendered on booking pages, so the total bar sits on
   the screen edge instead of stacking above it (was ~130px of fixed chrome). */
@media (max-width: 860px) {
  body.no-bottom-nav .bk-bar { bottom: 0; padding-bottom: max(0.5rem, env(safe-area-inset-bottom)); }
  body.no-bottom-nav:has(.bk-bar) .site-footer { padding-bottom: calc(5rem + env(safe-area-inset-bottom, 0px)); }
}

.site-nav .nav-book { margin-left: var(--space-4); padding: 0.55rem 1rem; color: var(--paper-light); }
.site-nav .nav-book:hover, .site-nav .nav-book:focus { color: var(--paper-light); }
.site-nav .nav-phone { font-family: var(--font-display); letter-spacing: 0.03em; color: var(--warn); }

.home-section { margin: var(--space-7) 0; }
.home-section > h2, .band > h2 { margin-top: 0; }
/* A page that ends on a full-bleed band meets the footer directly, instead of
   leaving the container's bottom padding plus the footer margin as a dead strip. */
main.container > .band:last-child { margin-bottom: -2rem; }
body:has(main.container > .band:last-child) .site-footer { margin-top: 0; }
.nowrap { white-space: nowrap; }

.faq-item { border-bottom: 1px solid var(--steel-light); }
.faq-item summary {
  cursor: pointer; padding: var(--space-4) 0; min-height: 44px; font-family: var(--font-display); font-size: 1.15rem;
  letter-spacing: 0.01em; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: var(--space-4);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; flex: none; font-family: var(--font-body); font-size: 1.5rem; line-height: 1; color: var(--text-muted); }
.faq-item[open] summary::after { content: "\2212"; }
.faq-item p { margin: 0 0 var(--space-4); }

.sold-banner { display: flex; align-items: center; gap: var(--space-4); margin: var(--space-4) 0; }
.sold-banner p { margin: 0; }
.sold-card { position: relative; }
.sold-card .stamp { position: absolute; top: var(--space-3); right: var(--space-3); background: var(--paper-light); }

/* Listing photos: a swipe strip on phones; the desktop grid and the
   lightbox are unchanged. Swiping scrolls the strip, not the page. */
@media (max-width: 768px) {
  .listing-photos.carousel {
    display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: var(--space-2);
    margin: 0 calc(-1 * var(--space-4)); padding: 0 var(--space-4);
    -webkit-overflow-scrolling: touch;
  }
  .listing-photos.carousel > * { flex: 0 0 88%; scroll-snap-align: center; }
  .listing-photos.carousel img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
}
/* Keeps the seller's line and paragraph breaks from the Facebook import. */
.listing-desc { white-space: pre-line; }
.listing-guarantee { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.faq-a { padding-bottom: var(--space-4); }
.faq-cta { display: inline-block; padding: 0.6rem 0; font-weight: 600; color: var(--rust-text); }
.area-towns { margin: var(--space-1) 0 0; color: var(--text-muted); }
.faq-a .service-area { margin-bottom: var(--space-3); }

/* Taste pass A (2026-10-13): public headings. H1 keeps its capitals; section
   headings are sentence case so the page stops shouting. Scoped to <main>
   because base.css is shared with admin. Tickets and sheets stay in capitals:
   they are documents, and documents have printed headers. */
main h2, main h3 { text-transform: none; letter-spacing: 0; font-weight: 600; }
main h2 { font-size: clamp(1.45rem, 3vw, 1.9rem); }
main .ticket-name, main .sheet-title { text-transform: uppercase; letter-spacing: 0.02em; }
h1, h2 { text-wrap: balance; }

.skip-link {
  position: absolute; left: 0.75rem; top: -4rem; z-index: 100;
  background: var(--paper-light); color: var(--ink); padding: 0.6rem 1rem; font-weight: 600;
}
.skip-link:focus { top: 0.75rem; }

/* Home: who we are + what we work on (2026-10-14). */
.intro { display: grid; gap: var(--space-6); align-items: center; }
.intro-copy p { max-width: 34rem; }
.intro-photo { margin: 0; }
.intro-photo img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }
@media (min-width: 760px) { .intro { grid-template-columns: 1fr 22rem; } }
.work-grid { display: grid; gap: var(--space-5) var(--space-7); }
@media (min-width: 760px) { .work-grid { grid-template-columns: 2fr 1fr; } }
.work-grid h3 { margin: 0 0 var(--space-2); font-size: 1.05rem; }
.work-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--steel-light); }
.work-list-2 { display: grid; grid-template-columns: repeat(2, 1fr); column-gap: var(--space-5); align-content: start; }
.work-list li { border-bottom: 1px solid var(--steel-light); }
.work-list a { display: flex; justify-content: space-between; align-items: center; min-height: 44px;
  color: var(--text); font-weight: 600; }
.work-list a::after { content: "\2192"; color: var(--rust-text); font-weight: 400; }
.work-list a:hover, .work-list a:focus { text-decoration: underline; }
.work-more { margin: var(--space-5) 0 0; }

/* Mobile trims (2026-10-14). */
.bottom-nav-more { display: flex; }
.more-sheet {
  position: absolute; bottom: calc(100% + 0.4rem); left: 50%; transform: translateX(-50%);
  width: min(480px, calc(100% - 1rem)); display: grid; padding: var(--space-3) var(--space-4);
  background: var(--paper-light); border: 1px solid var(--steel-light); border-radius: 12px;
  box-shadow: 0 -6px 24px rgba(27, 27, 27, 0.12);
}
.more-sheet a:not(.btn) {
  display: flex; align-items: center; min-height: 44px; color: var(--text); font-weight: 600;
  border-bottom: 1px solid var(--steel-light);
}
.more-sheet a:last-child { border-bottom: 0; }
.more-sheet a[aria-current="page"] { color: var(--rust-text); }
.more-sheet .more-call { margin-bottom: var(--space-2); text-align: center; }
.proof-more { margin: var(--space-4) 0 0; }
@media (max-width: 600px) {
  /* Home strip only: the full checklists live on /service. */
  #services .ticket-checks { display: none; }
}
@media (max-width: 759px) {
  .work-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); border-top: 0; }
  .work-chips li { border: 0; }
  .work-chips a { min-height: 44px; padding: 0 var(--space-4); border: 1px solid var(--steel-light);
    border-radius: 999px; font-weight: 600; }
  .work-chips a::after { content: none; }
}
@media (max-width: 768px) {
  /* The bottom bar and its More sheet carry the page links on phones. Booking
     pages have no bar, so they keep the full footer. */
  body:not(.no-bottom-nav) .f-links,
  body:not(.no-bottom-nav) .f-brand p,
  body:not(.no-bottom-nav) .f-area { display: none; }
}

/* /service on phones (2026-10-14). */
.ticket-incl { display: none; }
.ticket-incl summary {
  display: flex; align-items: center; min-height: 44px; cursor: pointer; list-style: none;
  color: var(--rust-text); font-weight: 600;
}
.ticket-incl summary::-webkit-details-marker { display: none; }
.ticket-incl summary::after { content: "+"; margin-left: auto; font-size: 1.25rem; font-weight: 400; }
.ticket-incl[open] summary::after { content: "\2212"; }
@media (max-width: 600px) {
  .pkg-section .ticket > .ticket-checks { display: none; }
  .ticket-incl { display: block; margin: 0 0 var(--space-3); }
}
@media (max-width: 860px) {
  .svc-aside { display: none; }
}

/* Before & after band (_work_band.html) -------------------------------- */
.ba-lede { color: var(--text-muted); margin: 0 0 var(--space-5); max-width: 40rem; }
.ba-cards { display: grid; gap: var(--space-5); grid-template-columns: repeat(2, 1fr); }
.ba-band-lead .ba-cards { grid-template-columns: 1fr; max-width: 46rem; }
.ba-card { margin: 0; background: var(--surface); border: 1px solid var(--steel-light); border-radius: 6px; overflow: hidden; }
.ba-thumb { display: block; width: 100%; padding: 0; border: 0; background: none; border-radius: 0; cursor: zoom-in; }
.ba-thumb:focus-visible { outline: 3px solid var(--rust); outline-offset: -3px; }
.ba-thumb img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; }
.ba-thumb-square img { aspect-ratio: 1 / 1; }
.ba-card figcaption { padding: var(--space-3) var(--space-4) var(--space-4); font-size: 0.95rem; line-height: 1.5; }
.ba-card figcaption strong { display: block; font-size: 1.05rem; margin-bottom: var(--space-1); }
.ba-more { margin: var(--space-4) 0 0; }
/* Phones: a swipe strip with the next card peeking, like the listing photos. */
@media (max-width: 768px) {
  .ba-band:not(.ba-band-lead) .ba-cards {
    display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: var(--space-3);
    -webkit-overflow-scrolling: touch; padding-bottom: var(--space-2);
  }
  .ba-band:not(.ba-band-lead) .ba-card { flex: 0 0 86%; scroll-snap-align: center; }
}
/* Customer portal links (customer portal plan S1-30). */
.site-nav .nav-account { white-space: nowrap; }
@media (max-width: 1180px) { .site-nav .nav-signup { display: none; } }
/* "How will it get to us?" (2026-10-31): four answers as chips, two across. */
.trip-choice { border: 0; padding: 0; margin: 0 0 1rem; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.5rem; }
.trip-choice legend { font-weight: 600; margin-bottom: 0.4rem; }
@media (max-width: 480px) { .trip-choice { grid-template-columns: 1fr; } }
