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

/* The [hidden] attribute only carries display:none from the UA stylesheet, so
   any author rule that sets display beats it. That has now silently un-hidden
   three different components in this project, so it is settled here once. */
[hidden]{display:none!important}

/* Switzer, self-hosted. A render-blocking stylesheet on a third-party host
   means first paint depends on that host staying up; these files sit on the
   same origin as everything else. Only the two weights the site actually
   renders are shipped. Switzer is from Indian Type Foundry via Fontshare;
   check the licence at fontshare.com/fonts/switzer before redistributing. */
@font-face{font-family:'Switzer';src:url('/assets/fonts/switzer-400.woff2') format('woff2');
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Switzer';src:url('/assets/fonts/switzer-500.woff2') format('woff2');
  font-weight:500;font-style:normal;font-display:swap}

/* Anchor targets have to clear the fixed header. scroll-margin handles every
   route into a section: a nav link, a hash already in the URL on load, the
   back button. JS only ever sees the first of those. */
[id]{scroll-margin-top:92px}

:root{
  /* surfaces, neutral black, no blue cast */
  --ink:#000000; --ink2:#0a0a0a; --panel:#1a1a1a; --panel2:#262626;
  --line:#333333; --line-soft:rgba(255,255,255,.08);
  --line-strong:rgba(255,255,255,.2);
  /* accent */
  --beam:#ef0f0e; --beam-lift:#ff3a30; --beam-deep:#c00a09;
  --beam-glow:rgba(239,15,14,.18);
  /* The identity red sits at 4.43:1 under white and 4.47:1 on the ground ,
     both just under WCAG AA. These variants clear it in each direction
     without a perceptible shift in hue. */
  --beam-surface:#ea0f0e;   /* backgrounds carrying white text: 4.59:1  */
  --beam-text:#ff3a30;      /* small text, clears 4.5:1 on both the page
                               ground (5.19) and the lighter card surface
                               (4.89), so one token covers every context */
  /* type */
  --paper:#ffffff; --text:rgba(255,255,255,.72); --dim:rgba(255,255,255,.5);
  /* fonts, single family, weight does the work */
  --f-display:'Switzer','Inter',system-ui,-apple-system,sans-serif;
  --f-body:'Switzer','Inter',system-ui,-apple-system,sans-serif;
  /* geometry, sharp */
  --r:4px; --r-lg:10px; --r-card:12px;
  --wrap:1180px;
  /* --ease carries a duration as well as a curve, so it can only be used where
     no duration is given: `transition:border-color var(--ease)`. Passing it
     after an explicit duration makes the .32s a transition-DELAY. Use
     --ease-fn wherever the duration is spelled out. */
  --ease:.32s cubic-bezier(.4,0,.2,1);
  --ease-fn:cubic-bezier(.22,.61,.36,1);
}

html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  background:var(--ink);color:var(--text);
  font-family:var(--f-body);font-size:16px;line-height:1.5;letter-spacing:-.03em;
  -webkit-font-smoothing:antialiased;
}
/* Full-bleed sections intentionally extend past the viewport. `clip` contains
   them without creating a scroll container, which `hidden` would do, and a
   scroll container on an ancestor breaks position:sticky further down. */
html,body{overflow-x:hidden}
@supports (overflow:clip){ html,body{overflow-x:clip} }
img,svg,video{display:block;max-width:100%;height:auto}
a{color:inherit;text-decoration:none}
button{cursor:pointer;border:0;background:none;font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--beam);outline-offset:3px;border-radius:4px}

h1,h2,h3,h4{font-family:var(--f-display);color:var(--paper);line-height:1.1;
  letter-spacing:-.03em;font-weight:500}

.wrap{width:min(100% - 2.5rem,var(--wrap));margin-inline:auto}
/* Adjacent sections each carried 120px, so every boundary was 240px of empty
   ground and the page read as a stack of islands. */
.section{padding:clamp(56px,7vw,88px) 0}
.section--tight{padding:clamp(40px,5vw,60px) 0}
.section--alt{background:var(--ink2)}

/* ─── section header ─── */
.sec-head{max-width:60ch}
.sec-head--center{margin-inline:auto;text-align:center}
.sec-title{font-size:clamp(1.6rem,3.2vw,2.15rem);letter-spacing:-.03em;line-height:1.15;text-wrap:balance}
.sec-head--lg .sec-title{font-size:clamp(1.9rem,4vw,2.9rem)}
.sec-title em{font-style:normal;color:var(--beam)}
.sec-sub{margin-top:1rem;font-size:1rem;color:var(--dim);max-width:56ch}

/* header on the left, supporting line on the right */
.sec-row{
  display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);
  gap:clamp(1.5rem,4vw,4rem);align-items:end;
  margin-bottom:clamp(2rem,4vw,3rem);
  padding-bottom:1.75rem;border-bottom:1px solid var(--line);
}
.sec-row__aside{color:var(--dim);font-size:.95rem;max-width:44ch}

/* sticky header column beside a long list */
.split{display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);gap:clamp(2rem,6vw,5rem);align-items:start}
.split__aside{position:sticky;top:104px}

/* ─── numbered editorial list ─── */
.ladder{list-style:none;counter-reset:rung;display:grid}
.ladder__item{
  counter-increment:rung;position:relative;
  padding:1.6rem 0 1.6rem 3.5rem;border-top:1px solid var(--line);
}
.ladder__item:last-child{border-bottom:1px solid var(--line)}
.ladder__item::before{
  content:counter(rung,decimal-leading-zero);
  position:absolute;left:0;top:1.7rem;
  font-size:.8rem;color:var(--beam-text);font-variant-numeric:tabular-nums;
}
.ladder__item h3{font-size:1.15rem;margin-bottom:.4rem}
.ladder__item p{font-size:.95rem;color:var(--dim);max-width:52ch}

/* ─── service-area list ─── */
.arealist{list-style:none;display:grid;border-top:1px solid var(--line)}
.arealist__item{border-bottom:1px solid var(--line)}
.arealist__item a{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;
  gap:1rem;align-items:baseline;padding:1.35rem .25rem;
  transition:padding var(--ease),color var(--ease);
}
.arealist__item a:hover{padding-left:1rem;padding-right:1rem;background:var(--panel)}
.arealist__name{font-size:1.25rem;letter-spacing:-.02em;color:var(--paper)}
.arealist__meta{font-size:.9rem;color:var(--dim)}
.arealist__go{color:var(--beam-text);opacity:0;transition:opacity var(--ease)}
.arealist__item a:hover .arealist__go{opacity:1}

/* ─── quiet inline note (used for intentional empty states) ─── */
.note{
  border-left:2px solid var(--beam);padding:.25rem 0 .25rem 1.25rem;
  max-width:62ch;color:var(--dim);font-size:.95rem;display:grid;gap:.75rem;
}
.note strong{color:var(--paper);font-weight:500}
.note code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.88em;color:var(--beam-text)}

/* ─── buttons ─── */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  font-family:var(--f-body);font-size:.95rem;font-weight:500;letter-spacing:-.01em;
  padding:.9rem 1.6rem;border-radius:var(--r);
  transition:transform var(--ease),background var(--ease),box-shadow var(--ease),border-color var(--ease);
  border:1px solid transparent;white-space:nowrap;
}
.btn:hover{transform:translateY(-2px)}
/* A disabled button has to look disabled. Continue on the first step is dead
   until the question is answered, and at full opacity it read as a working
   button that ignored the press. */
.btn:disabled,.btn[disabled]{opacity:.42;cursor:not-allowed;box-shadow:none}
.btn:disabled:hover,.btn[disabled]:hover{transform:none;box-shadow:none}
.btn--primary{background:var(--beam-surface);color:#fff;border-color:var(--beam-surface)}
.btn--primary:hover{background:var(--beam-lift);box-shadow:0 8px 26px var(--beam-glow)}
.btn--ghost{background:rgba(255,255,255,.15);border-color:rgba(255,255,255,.2);color:var(--paper);backdrop-filter:blur(5px)}
.btn--ghost:hover{background:rgba(255,255,255,.22)}
.btn--wire{border-color:var(--beam);color:var(--beam-text)}
.btn--wire:hover{background:var(--beam-glow)}
.btn--sm{padding:.6rem 1.05rem;font-size:.75rem}
.btn--block{width:100%}

/* ══════════ HEADER ══════════ */
.hdr{
  position:fixed;inset:0 0 auto 0;z-index:900;height:68px;
  display:flex;align-items:center;
  transition:background var(--ease),box-shadow var(--ease);
}
.hdr.is-stuck{
  background:rgba(0,0,0,.85);backdrop-filter:blur(7px);
  box-shadow:0 1px 0 var(--line),0 10px 30px rgba(0,0,0,.45);
}
/* The frosted header reads well over the page. Over the near-solid drawer it
   does not: page copy stays legible through the top strip while the panel
   below it is opaque, so the two halves look mismatched. */
.hdr:has(+ .drawer.is-open){background:var(--ink2);backdrop-filter:none;box-shadow:none}
.hdr__inner{width:min(100% - 2.5rem,1320px);margin-inline:auto;
  display:flex;align-items:center;justify-content:space-between;gap:1rem}

.logo{display:flex;align-items:center;gap:.6rem;font-family:var(--f-display);
  font-size:1.25rem;font-weight:500;letter-spacing:-.01em;color:var(--paper)}
.logo b{color:var(--beam-text);font-weight:500}
.logo__mark{width:30px;height:30px;flex:none}

.nav{display:flex;align-items:center;gap:1.6rem}
.nav a{font-family:var(--f-body);font-size:.95rem;font-weight:500;
  letter-spacing:-.01em;color:var(--dim);transition:color .2s}
.nav a:hover,.nav a[aria-current="page"]{color:var(--beam-text)}

.drop{position:relative}
.drop__btn{display:inline-flex;align-items:center;gap:.35rem;
  font-family:var(--f-body);font-size:.95rem;font-weight:500;
  letter-spacing:-.01em;color:var(--dim)}
.drop__btn:hover,.drop[data-open="true"] .drop__btn{color:var(--beam-text)}
.drop__btn svg{transition:transform var(--ease)}
.drop[data-open="true"] .drop__btn svg{transform:rotate(180deg)}
.drop__menu{
  position:absolute;top:calc(100% + 14px);left:50%;translate:-50% 0;
  min-width:238px;padding:.4rem;opacity:0;visibility:hidden;
  background:rgba(17,24,32,.98);backdrop-filter:blur(14px);
  border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:0 18px 50px rgba(0,0,0,.6);
  transform:translateY(-6px);transition:all var(--ease);
}
.drop__menu::before{content:"";position:absolute;top:-14px;left:0;right:0;height:14px}
.drop[data-open="true"] .drop__menu{opacity:1;visibility:visible;transform:none}
.drop__menu a{display:block;padding:.65rem .9rem;border-radius:8px;
  font-size:.78rem;letter-spacing:0}
.drop__menu a:hover{background:var(--beam-glow);color:var(--beam-text)}

.hdr__cta{display:flex;align-items:center;gap:.55rem}
.burger{display:none;position:relative;width:42px;height:42px;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:var(--r);color:var(--paper)}

/* mobile drawer */
/* Full height rather than content height. Sized to its content the panel
   stopped partway down the screen, leaving page copy and buttons visible and
   tappable underneath it, which read as a rendering fault. */
.drawer{
  position:fixed;inset:68px 0 0 0;z-index:890;display:none;
  flex-direction:column;
  background:var(--ink2);
  border-top:1px solid var(--line);
  overscroll-behavior:contain;
  padding:.5rem 0 calc(1.25rem + env(safe-area-inset-bottom));
}
.drawer.is-open{display:flex}
/* the burger becomes a close control while the panel is open */
.burger svg{transition:opacity .18s var(--ease-fn)}
.burger[aria-expanded="true"] svg{opacity:0}
.burger[aria-expanded="true"]::before,
.burger[aria-expanded="true"]::after{
  content:"";position:absolute;width:17px;height:2px;border-radius:2px;
  background:currentColor}
.burger[aria-expanded="true"]::before{rotate:45deg}
.burger[aria-expanded="true"]::after{rotate:-45deg}
.drawer__nav{flex:1;min-height:0;overflow-y:auto}
/* :not(.btn) matters. Without it these two rules outrank .btn--primary on
   specificity and repainted the drawer's Book button in 72% white, which is
   2.83:1 on the accent red. That button is the main call to action on a
   phone. */
.drawer a:not(.btn){display:block;padding:.9rem 1.6rem;font-family:var(--f-display);
  font-size:.88rem;font-weight:500;letter-spacing:0;color:var(--text)}
.drawer a:not(.btn):hover{background:var(--beam-glow);color:var(--beam-text)}
.drawer__group{padding:.9rem 1.6rem .35rem;font-family:var(--f-display);
  font-size:.7rem;letter-spacing:0;color:var(--beam-text)}
.drawer a:not(.btn).is-sub{padding-left:2.6rem;font-size:.78rem;color:var(--dim);text-transform:none;letter-spacing:0}
.drawer__cta{display:flex;gap:.6rem;padding:1rem 1.6rem 0;margin-top:auto}
.drawer__cta .btn{flex:1}

/* ══════════ HERO ══════════ */
/* Narrow: one centred column, headline down to the before/after. Wide: the
   words on the left and the before/after beside them, which is the point at
   which a single centred column starts reading as a landing page rather than
   a business. Flat ground, no glow and no grid overlay. */
.hero{position:relative;padding:clamp(88px,10vw,132px) 0 clamp(48px,6vw,76px);
  background:var(--ink);border-bottom:1px solid var(--line)}
.hero__inner{display:grid;gap:clamp(1.75rem,3.5vw,2.5rem)}
.hero__copy{display:grid;justify-items:center;text-align:center;
  gap:clamp(1.25rem,2.6vw,1.9rem)}
.hero h1{font-size:clamp(2.3rem,6vw,4.4rem);letter-spacing:-.045em;font-weight:500;
  line-height:1.02;text-wrap:balance;max-width:16ch}
.hero h1 span{display:block;color:var(--beam)}
.hero__lede{font-size:1.02rem;color:var(--dim);max-width:54ch}
.hero__ctas{display:flex;flex-wrap:wrap;gap:.7rem;justify-content:center}
.hero__media{width:100%;margin-top:clamp(.5rem,1.5vw,1.25rem)}
.hero__media .ba{aspect-ratio:16/9}
@media(min-width:900px){ .hero__media .ba{aspect-ratio:21/9} }

/* The same width at which the header stops being a burger. Below it the hero
   is a stack and the two rules would disagree about what desktop means. */
@media(min-width:1041px){
  .hero__inner{grid-template-columns:minmax(0,1.04fr) minmax(0,1fr);
    align-items:center;gap:clamp(2.5rem,4.5vw,4rem)}
  .hero__copy{justify-items:start;text-align:left}
  /* The measure is the column now, and 16ch inside it would break the
     headline a word early. */
  .hero h1{max-width:none;font-size:clamp(2.6rem,3.6vw,3.9rem)}
  .hero__lede{max-width:44ch}
  /* Scoped to the hero because the .spec block below this one would otherwise
     win on source order and keep both of these centred. */
  .hero__copy .spec{justify-content:flex-start}
  .hero__copy .spec__item{text-align:left}
  .hero__ctas{justify-content:flex-start}
  .hero__media{margin-top:0}
  .hero__media .ba{aspect-ratio:4/3}
}
@media(max-width:560px){
  .hero__ctas{flex-direction:column;align-items:stretch;width:100%}
  .hero__ctas .btn{width:100%}
  .hero__media .ba{aspect-ratio:4/3}
}

/* Three reasons, side by side. The number carries the point and the sentence
   under it says whose number it is, so the row is skimmable without the claims
   floating free of their source. */
.whys{display:grid;grid-template-columns:repeat(auto-fit,minmax(19rem,1fr));
  gap:clamp(1.75rem,4vw,3.5rem);margin-top:clamp(2rem,4vw,3rem)}
/* The claim is one line, not a number with a caption over it. "78%" set huge
   above a small grey "light a clouded lens blocks" made somebody read the
   figure before they knew what it measured, and on a phone the label was the
   easiest thing on the screen to skip. Sized to hold a short sentence rather
   than two digits, so it still fits at 360px without breaking mid-word. */
.why__n{font-family:var(--f-display);font-size:clamp(1.7rem,5.6vw,2.5rem);
  letter-spacing:-.03em;color:var(--paper);line-height:1.12;margin-bottom:.7rem;
  text-wrap:balance}
.why__t{font-size:.97rem;color:var(--dim);line-height:1.6}
.whys__end{margin-top:clamp(1.75rem,3vw,2.5rem);padding-top:clamp(1.25rem,2.5vw,1.75rem);
  border-top:1px solid var(--line);font-size:.97rem;color:var(--dim);line-height:1.6}
.why + .why{position:relative}
@media(min-width:920px){
  .why + .why::before{content:"";position:absolute;left:calc(-1 * clamp(.75rem,1.5vw,1.4rem));
    top:.25rem;bottom:.25rem;width:1px;background:var(--line)}
}

/* hero spec strip, facts, not a sales comparison */
/* Three facts spread across the measure with a rule between, rather than packed
   into one plate. The gap is what makes them read as three separate answers. */
.spec{
  display:flex;flex-wrap:wrap;justify-content:center;
  gap:clamp(1.75rem,5vw,4.5rem);
}
.spec__item{position:relative;text-align:center;min-width:6.25rem}
.spec__item + .spec__item::before{
  content:"";position:absolute;left:calc(-1 * clamp(.875rem,2.5vw,2.25rem));
  top:.2rem;bottom:.2rem;width:1px;background:var(--line);
}
.spec__item dt{font-size:.78rem;color:var(--dim);margin-bottom:.35rem}
.spec__item dd{
  font-size:clamp(1.5rem,2.6vw,1.9rem);letter-spacing:-.03em;
  color:var(--paper);line-height:1;display:grid;gap:.4rem;
}
.spec__item dd span{font-size:.8rem;color:var(--dim);letter-spacing:0;line-height:1.3}
@media(max-width:560px){
  .spec{gap:1.5rem}
  .spec__item{min-width:5.25rem}
  .spec__item dt{font-size:.72rem}
  .spec__item dd{font-size:1.45rem}
  .spec__item dd span{font-size:.72rem}
}

/* ─── before/after drag slider ─── */
.ba{position:relative;border-radius:var(--r-lg);overflow:hidden;
  border:1px solid var(--line);background:var(--panel);
  aspect-ratio:4/3;user-select:none;touch-action:pan-y}
.ba img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.ba__after{clip-path:inset(0 0 0 var(--split,50%))}
.ba__handle{position:absolute;top:0;bottom:0;left:var(--split,50%);width:2px;
  background:var(--beam);translate:-1px 0;pointer-events:none;
  box-shadow:0 0 18px var(--beam)}
.ba__knob{position:absolute;top:50%;left:50%;translate:-50% -50%;
  width:44px;height:44px;border-radius:50%;background:var(--beam);
  display:grid;place-items:center;color:#fff;
  box-shadow:0 4px 20px rgba(0,0,0,.5)}
.ba__tag{position:absolute;bottom:.85rem;padding:.3rem .7rem;border-radius:999px;
  font-family:var(--f-display);font-size:.66rem;letter-spacing:0;background:rgba(10,10,10,.82);
  backdrop-filter:blur(6px);border:1px solid var(--line);color:var(--paper)}
.ba__tag.is-l{left:.85rem}
.ba__tag.is-r{right:.85rem;color:var(--beam-text);border-color:var(--beam)}
.ba__hint{margin-top:.75rem;text-align:center;font-size:.76rem;
  letter-spacing:0;color:var(--dim);font-family:var(--f-display)}

/* ══════════ TRUST BAR ══════════ */
.trust{border-block:1px solid var(--line);background:var(--ink2)}
.trust__row{display:flex;flex-wrap:wrap;justify-content:center;gap:clamp(1rem,4vw,3rem);
  padding:1.15rem 0}
@media(max-width:720px){
  /* Four items wrapped 2 + 1 + 1 and left the third stranded on its own line.
     A 2x2 grid keeps the rows even. */
  .trust__row{display:grid;grid-template-columns:1fr 1fr;gap:.9rem 1rem;
    padding:1.15rem .25rem;justify-items:start}
  .trust__item{font-size:.82rem}
}
.trust__item{display:inline-flex;align-items:center;gap:.55rem;
  font-family:var(--f-display);font-size:.76rem;font-weight:500;
  letter-spacing:0;color:var(--dim)}
.trust__item svg{color:var(--beam);flex:none}

/* ══════════ GALLERY ══════════ */
.shot{position:relative;border-radius:var(--r-lg);overflow:hidden;
  border:1px solid var(--line);background:var(--panel);aspect-ratio:4/3;cursor:pointer}
.shot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:opacity var(--ease)}
.shot__after{opacity:0}
.shot.is-revealed .shot__after{opacity:1}
.shot.is-revealed .shot__before{opacity:0}
/* Hover only where there is a pointer that can hover. A phone fires :hover on
   tap and then leaves it stuck on the last thing touched, so the second tap
   turned .is-revealed off and the lens stayed on the after shot anyway: the
   toggle worked and looked broken. Touch now goes through the class alone. */
@media(hover:hover){
  .shot:hover .shot__after{opacity:1}
  .shot:hover .shot__before{opacity:0}
  .shot:hover .shot__badge{color:var(--beam-text);border-color:var(--beam)}
  .shot:hover .shot__hint{opacity:0}
  .shot:hover .shot__b{display:none}
  .shot:hover .shot__a{display:inline}
}
.shot__badge{position:absolute;top:.8rem;left:.8rem;z-index:2;
  padding:.3rem .65rem;border-radius:999px;font-family:var(--f-display);
  font-size:.64rem;letter-spacing:0;
  background:rgba(10,10,10,.85);border:1px solid var(--line);color:var(--paper)}
.shot.is-revealed .shot__badge{color:var(--beam-text);border-color:var(--beam)}
/* The badge says which of the two you are looking at. It used to read
   "Before" over the after shot and only change colour, which is a label
   describing the wrong picture. */
.shot__a{display:none}
.shot.is-revealed .shot__b{display:none}
.shot.is-revealed .shot__a{display:inline}
.shot__hint{position:absolute;bottom:.8rem;right:.8rem;z-index:2;
  font-family:var(--f-display);font-size:.64rem;letter-spacing:0;color:var(--dim);transition:opacity var(--ease)}
.shot.is-revealed .shot__hint{opacity:0}

/* ══════════ REVIEWS ══════════ */
.stars{display:inline-flex;gap:.15rem;color:var(--beam)}
.reviews{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1.1rem}
.review{padding:1.6rem;border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--panel);transition:border-color var(--ease),transform var(--ease)}
.review:hover{border-color:var(--beam);transform:translateY(-3px)}
.review__body{margin:.9rem 0 1.2rem;color:var(--text)}
.review__who{font-family:var(--f-display);font-size:.85rem;letter-spacing:0;color:var(--paper)}
.review__meta{font-size:.8rem;color:var(--dim)}

/* empty-state for unpopulated sections */
.slot{padding:2.5rem 1.75rem;border:1px dashed var(--line);border-radius:var(--r-lg);
  background:var(--panel);text-align:center;color:var(--dim)}
.slot h3{font-size:1.05rem;color:var(--paper);margin-bottom:.6rem}
.slot__lead{font-size:1.05rem;color:var(--paper);margin-bottom:.6rem}
.slot__lead b{font-weight:500}
.slot code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:.85em;color:var(--beam-text);background:var(--ink);
  padding:.15rem .4rem;border-radius:4px}

/* ══════════ PRICING ══════════ */
.fineprint{margin-top:1.75rem;font-size:.82rem;color:var(--dim);text-align:center}

.addons__head{margin:3rem 0 1.25rem;font-size:1.05rem;color:var(--dim);
  font-weight:400;letter-spacing:-.01em}
.addons{display:grid;grid-template-columns:repeat(auto-fit,minmax(255px,1fr));gap:1rem;margin-top:2.5rem}
.addon{padding:1.35rem;border:1px solid var(--line);border-radius:var(--r);background:var(--ink2)}
.addon__name{font-family:var(--f-display);font-size:1.02rem;
  letter-spacing:0;color:var(--paper)}
.addon__price{font-size:.8rem;color:var(--beam-text);margin:.2rem 0 .6rem;
  font-family:var(--f-display);letter-spacing:0;}
.addon__desc{font-size:.9rem;color:var(--dim)}

/* ══════════ FAQ ══════════ */
.faq{max-width:820px;display:grid}
/* A ruled list, not ten bordered cards. The rule between rows is enough
   separation, and the question stays the loudest thing in the row. */
.qa{border-top:1px solid var(--line)}
.qa:last-child{border-bottom:1px solid var(--line)}
.qa__q{display:flex;align-items:center;justify-content:space-between;gap:1.25rem;
  padding:1.15rem .25rem;cursor:pointer;list-style:none;
  font-family:var(--f-display);font-size:1.02rem;font-weight:500;
  letter-spacing:-.01em;color:var(--paper);transition:color var(--ease)}
.qa__q::-webkit-details-marker{display:none}
.qa__q:hover{color:var(--beam-text)}
.qa__q i{flex:none;width:18px;height:18px;position:relative}
.qa__q i::before,.qa__q i::after{content:"";position:absolute;inset:50% 0 auto 0;
  height:2px;background:var(--beam);transition:transform var(--ease)}
.qa__q i::after{transform:rotate(90deg)}
.qa[open] .qa__q i::after{transform:rotate(0)}
.qa__a{padding:0 .25rem 1.35rem;max-width:64ch;color:var(--text);font-size:.96rem}

/* ══════════ FOOTER ══════════ */

/* sticky mobile call bar */
.callbar{position:fixed;inset:auto 0 0 0;z-index:880;display:none;
  padding:.7rem 1rem calc(.7rem + env(safe-area-inset-bottom));
  background:rgba(10,10,10,.96);backdrop-filter:blur(14px);
  border-top:1px solid var(--line)}
.callbar{display:none;gap:.55rem}
/* One thing in the bar, and it is the phone. Book already has a button in
   the header on every screen, so putting a second one here was asking the
   same question twice in the same eyeful. The number reads as a number
   rather than as the word "Call", which is most of what says a real person
   answers it: a service-area business publishes no street address. */
.callbar__book{display:none}
.callbar__call{flex:1;padding-inline:.95rem;gap:.45rem}
.callbar__call span{font-family:var(--f-display);letter-spacing:-.01em;
  font-variant-numeric:tabular-nums;font-size:1.02rem}
.callbar__call svg{width:18px;height:18px}

/* ══════════ PROSE (blog / legal) ══════════ */
.prose{max-width:74ch;font-size:1.02rem}
.prose > * + *{margin-top:1.15rem}
.prose h2{font-size:clamp(1.4rem,3.4vw,1.95rem);margin-top:2.6rem}
.prose h3{font-size:clamp(1.15rem,2.6vw,1.4rem);margin-top:2rem}
.prose ul,.prose ol{padding-left:1.3rem;display:grid;gap:.55rem}
.prose li::marker{color:var(--beam)}
.prose a{color:var(--beam-text);text-decoration:underline;text-underline-offset:3px}
.prose strong{color:var(--paper)}
.prose blockquote{border-left:2px solid var(--beam);padding-left:1.1rem;color:var(--dim);font-style:italic}
.prose table{width:100%;border-collapse:collapse;font-size:.94rem}
.prose th,.prose td{border:1px solid var(--line);padding:.65rem .8rem;text-align:left}
.prose th{background:var(--panel);color:var(--paper);font-family:var(--f-display);
  font-size:.76rem;letter-spacing:0;}

.page-head{padding:clamp(104px,13vw,160px) 0 clamp(32px,5vw,52px);
  background:var(--ink2);border-bottom:1px solid var(--line)}
.page-head h1{font-size:clamp(2rem,5.4vw,3.4rem)}
.page-head p{margin-top:1rem;color:var(--dim);max-width:62ch}
.crumbs{font-size:.78rem;color:var(--dim);margin-bottom:1rem;
  font-family:var(--f-display);letter-spacing:0;}
.crumbs a:hover{color:var(--beam-text)}

/* article cards */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.1rem}
.card{display:block;padding:1.5rem;border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--panel);transition:border-color var(--ease),transform var(--ease)}
.card:hover{border-color:var(--beam);transform:translateY(-3px)}
.card__kicker{font-family:var(--f-display);font-size:.68rem;letter-spacing:0;color:var(--beam-text)}
.card h3{font-size:1.15rem;margin:.6rem 0 .5rem}
.card p{font-size:.92rem;color:var(--dim)}

/* city chips */
.chips{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.25rem}
.chip{padding:.4rem .85rem;border:1px solid var(--line);border-radius:999px;
  font-size:.82rem;color:var(--dim);transition:all .2s}
.chip:hover{border-color:var(--beam);color:var(--beam-text)}

/* reveal-on-scroll */
/* Was .7s with var(--ease) after it, which parsed as a 320ms delay in front of
   a 700ms fade: about a second from entering view to fully readable. */
.reveal{opacity:0;transform:translateY(14px);
  transition:opacity .38s var(--ease-fn),transform .38s var(--ease-fn)}
.reveal.is-in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition-duration:.01ms!important}
  .reveal{opacity:1;transform:none}
  html{scroll-behavior:auto}
}

/* ══════════ RESPONSIVE ══════════ */
@media(max-width:900px){
  .sec-row{grid-template-columns:1fr;align-items:start;gap:1rem}
  .split{grid-template-columns:1fr;gap:2.5rem}
  .split__aside{position:static}
  .arealist__item a{grid-template-columns:minmax(0,1fr) auto}
  .arealist__meta{grid-column:1;font-size:.85rem}
}
@media(max-width:1040px){
  .nav,.hdr__cta .btn--ghost{display:none}
  .burger{display:flex}
  .ftr__top{grid-template-columns:1fr 1fr}
}
@media(max-width:720px){
  /* Book at the top, the phone at the foot, one of each. The header's own
     phone button is already gone by here, hidden with the nav at 1040px, so
     what is left to decide is which of the two the bar carries. It carries
     the number: Book is the press somebody makes deliberately and can sit at
     the top where they go looking for it, and the number is the one they
     reach for without looking, so it gets the width and the thumb. */
  /* flex, not block. As a block the two buttons were inline-flex boxes on a
     text baseline, so the one with the phone icon in it sat four pixels
     higher than the other, and gap and flex:1 did nothing at all. */
  .callbar{display:flex;align-items:stretch}

  /* And the room it takes. A bar fixed to the bottom of the screen sits on
     top of whatever the page ends with, so the last inch of every page was
     underneath it: the legal links, the back-to-top button, the end of the
     final paragraph. Nothing reserved that space, so nothing could be read
     or pressed there. */
  body{padding-bottom:calc(4.7rem + env(safe-area-inset-bottom))}
  body.is-booking{padding-bottom:0}
  .ftr__top{grid-template-columns:1fr;gap:2rem}
  .ftr__base{flex-direction:column;gap:.5rem}
}

/* ══════════════════════════════════════════════════════════
   REFERENCE-ALIGNED MOTIFS
   ══════════════════════════════════════════════════════════ */

/* control button with a fill that slides up on hover */
.slide-btn{
  position:relative;display:inline-grid;place-items:center;
  width:50px;height:50px;overflow:hidden;
  background:var(--panel2);border:1px solid var(--line);
  border-radius:var(--r);color:var(--paper);
}
.slide-btn > svg{position:relative;z-index:1}
.slide-btn::before{
  content:"";position:absolute;inset:0;background:var(--beam-surface);
  transform:translateY(100%);transition:transform var(--ease);
}
.slide-btn:hover::before{transform:translateY(0)}

/* footer headings keep the red square marker */

/* ══════════════════════════════════════════════════════════
   LAYOUT DEVICES, panels, staggers, marquees, media cards
   ══════════════════════════════════════════════════════════ */

/* ─── bordered panel: groups a section inside a card instead of a flat band ─── */
.panel{
  position:relative;
  border:1px solid var(--line);border-radius:var(--r-card);
  background:var(--panel);
  padding:clamp(2rem,5vw,5rem) clamp(1.25rem,3vw,2.5rem);
}
/* Clipping is opt-in: `overflow:hidden` turns the panel into a scroll
   container, which stops any position:sticky child from ever pinning.
   Only panels with artwork bleeding past their edge need it. */
.panel > *{position:relative;z-index:1}

/* ─── sticky editorial column beside a scrolling stack ─── */
.stack{display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);
  gap:clamp(2rem,7vw,7.5rem);align-items:start}
.stack__aside{position:sticky;top:120px}

/* ─── marquees: two rows travelling in opposite directions ─── */
.marquees{display:grid;gap:1rem;overflow:hidden;max-width:100vw;
  -webkit-mask:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
  mask:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent)}
.marquee{display:flex;gap:1rem;width:max-content;
  animation:track 46s linear infinite}
.marquee--reverse{animation-direction:reverse;animation-duration:54s}
.marquee:hover{animation-play-state:paused}

/* Swipeable. The CSS animation above is the version somebody gets with no
   JavaScript: it moves and it cannot be touched. When the script runs it
   takes the class below instead, which turns the row into a real scroller,
   so a thumb drags it with the momentum the phone already knows how to do,
   and the script pushes scrollLeft along when nobody is holding it. Doubled
   content plus a wrap at the halfway mark is what makes it endless in either
   direction. */
.marquee.is-swipe{animation:none;width:100%;overflow-x:auto;overscroll-behavior-x:contain;
  scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch}
.marquee.is-swipe::-webkit-scrollbar{display:none}
.marquee .shot{grid-column:auto;width:clamp(280px,32vw,460px);flex:none;margin:0}
@keyframes track{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media(prefers-reduced-motion:reduce){
  .marquee{animation:none;overflow-x:auto;width:100%;
    scroll-snap-type:x mandatory;padding-bottom:.5rem}
  .marquee .shot{scroll-snap-align:start}
  .marquees{-webkit-mask:none;mask:none}
}

@media(max-width:900px){
  .stack{grid-template-columns:1fr;gap:2rem}
  .stack__aside{position:static}
}

/* ══════════════════════════════════════════════════════════
   CONTAINER VARIATION
   A page whose every section spans the same box reads as one
   template no matter what sits inside it. These break the frame.
   ══════════════════════════════════════════════════════════ */

.wrap--narrow{width:min(100% - 2.5rem,720px)}
.wrap--wide{width:min(100% - 2.5rem,1400px)}

/* content deliberately off-centre */
.wrap--offset{
  width:min(100% - 2.5rem,var(--wrap));margin-inline:auto;
  display:grid;grid-template-columns:minmax(0,1fr);
}
@media(min-width:1000px){
  .wrap--offset{grid-template-columns:minmax(0,7fr) minmax(0,4fr);gap:clamp(2rem,5vw,4rem)}
  .wrap--offset > :first-child{grid-column:1}
}

/* ─── full-bleed split: media runs to the viewport edge ─── */
.bleed{display:grid;align-items:center;gap:clamp(1.5rem,4vw,3.5rem)}

/* base (mobile first) */
.bleed__media{
  position:relative;overflow:hidden;border:1px solid var(--line);
  border-radius:var(--r-card);aspect-ratio:4/3;
}
.bleed__media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.bleed__copy h2{font-size:clamp(1.7rem,3.6vw,2.6rem);letter-spacing:-.03em}
.bleed__copy p{margin-top:1rem;color:var(--dim);max-width:48ch}
.bleed__copy .btn{margin-top:1.75rem}

/* desktop: two columns with the media running off one viewport edge.
   Declared after the base rules so these win. */
@media(min-width:1000px){
  .bleed{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .bleed__media{aspect-ratio:auto;min-height:clamp(380px,40vw,540px)}
  .bleed--left .bleed__media{
    margin-left:calc(50% - 50vw);border-left:0;
    border-radius:0 var(--r-card) var(--r-card) 0;
  }
  .bleed--left .bleed__copy{padding-left:clamp(1rem,3vw,2.5rem)}
  .bleed--right .bleed__media{
    margin-right:calc(50% - 50vw);border-right:0;order:2;
    border-radius:var(--r-card) 0 0 var(--r-card);
  }
  .bleed--right .bleed__copy{order:1;padding-right:clamp(1rem,3vw,2.5rem)}
}

/* ─── oversized statement, narrow measure ─── */
/* The homepage no longer carries one of these. /services/ and the guide still
   do, so the styles stay. */
.statement{
  padding:clamp(64px,8vw,104px) 0;background:var(--ink2);
  border-block:1px solid var(--line);
}
.statement .wrap{border-left:2px solid var(--beam);
  padding-left:clamp(1.25rem,3vw,2.5rem)}
.statement p{
  font-size:clamp(1.45rem,3.2vw,2.35rem);line-height:1.22;letter-spacing:-.03em;
  color:var(--paper);max-width:24ch;text-wrap:balance;
}
.statement p em{font-style:normal;color:var(--beam)}
.statement p.statement__by{margin-top:1.5rem;font-family:var(--f-display);
  font-size:.72rem;font-weight:500;line-height:1.4;letter-spacing:.06em;
  text-transform:uppercase;color:var(--dim);max-width:none}

/* ─── article standfirst ─── */
.standfirst{
  font-size:clamp(1.15rem,2vw,1.4rem);line-height:1.45;letter-spacing:-.02em;
  color:var(--paper);border-left:2px solid var(--beam);padding-left:1.35rem;
}

/* ─── lens cross-section diagram ─── */
.xsec{
  --xs-poly:#243039;          /* clear polycarbonate body      */
  --xs-haze:#3a3222;          /* oxidised layer ground         */
  --xs-haze-line:#6b5a2e;     /* oxidation hatching            */
  --xs-fail:#8a6d22;          /* failed factory hard-coat      */
  --xs-cut:var(--beam-text);  /* the surface we sand back to   */
  --xs-seal:#2f4d5c;          /* cured ceramic layer           */
  --xs-rule:rgba(255,255,255,.45);
  margin:0;padding:clamp(1.25rem,3vw,2rem);
  border:1px solid var(--line);border-radius:var(--r-card);
  background:var(--panel);overflow-x:auto;
}
.xsec__svg{width:100%;min-width:680px;height:auto;display:block}
.xsec__step{fill:var(--beam-text);font-size:13px;font-family:var(--f-body);
  font-variant-numeric:tabular-nums}
.xsec__label{fill:var(--paper);font-size:15px;font-family:var(--f-display);letter-spacing:-.01em}
.xsec__caption{fill:rgba(255,255,255,.5);font-size:13px;font-family:var(--f-body)}
.xsec__inner{fill:rgba(255,255,255,.62);font-size:12px;font-family:var(--f-body)}

/* ══════════════════════════════════════════════════════════
   QUOTE CALCULATOR
   ══════════════════════════════════════════════════════════ */

.qgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:.75rem}
/* Year and Make are both short answers, so on a phone they share a row and
   Model, which is the long one, takes the width. Three stacked selects pushed
   the price below the fold on the very step that exists to show it. */
@media(max-width:640px){
  .qgrid{grid-template-columns:1fr 1fr}
  .qgrid > :nth-child(3){grid-column:1 / -1}
}
.field{display:grid;gap:.4rem}
/* Loud enough to read at a glance. At half-white and .72rem these were a grey
   whisper over black, and on the step where somebody is typing their address
   the label is the question. */
.field__label{font-family:var(--f-display);font-size:.8rem;font-weight:500;
  letter-spacing:.02em;color:rgba(255,255,255,.88)}
.field select{
  width:100%;padding:.8rem .9rem;font:inherit;font-size:.98rem;color:var(--paper);
  background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r);
  appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23ffffff' stroke-opacity='.55' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-position:calc(100% - 14px) 55%;
  background-size:12px 8px;background-repeat:no-repeat;padding-right:2.4rem;
}
.field select:disabled{color:var(--dim);background-color:var(--ink2);cursor:not-allowed}
.field select:hover:not(:disabled){border-color:rgba(255,255,255,.34)}
.field select:focus-visible{outline:none;border-color:var(--beam);background-color:var(--panel2)}

/* The native control is hidden from sight but stays in the accessibility tree
   and keeps arrow-key behaviour, so the card is a real radio group. */

/* ─── the estimate panel ─── */
.estimate{padding:clamp(1.6rem,4vw,2.5rem)}
.estimate__total{display:flex;align-items:baseline;gap:.6rem;flex-wrap:wrap;
  margin:.5rem 0 1.4rem;font-family:var(--f-display);
  font-size:clamp(2.6rem,7vw,3.8rem);font-weight:500;letter-spacing:-.04em;
  color:var(--beam-text);line-height:1}
.estimate__unit{font-size:.9rem;letter-spacing:0;color:var(--dim)}
.estimate__lines{list-style:none;display:grid;gap:.1rem;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.eline{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding:.75rem 0;font-size:.92rem}
.eline + .eline{border-top:1px solid var(--line-soft)}
.eline__label{color:var(--text)}
.eline__label em{display:block;margin-top:.2rem;font-style:normal;
  font-size:.8rem;color:var(--dim)}
.eline__amt{flex:none;font-family:var(--f-display);font-weight:500;color:var(--paper)}
.eline.is-zero .eline__amt{color:var(--dim);font-weight:400;font-size:.85rem}

/* A booking that covers more than one car is a short bill rather than a
   figure: each vehicle with what was done to it, the multi-car saving on its
   own line, and the total last. The nested list wraps to a second row on a
   phone, which is why the group is a grid rather than the flex row above. */
.eline--group{display:grid;grid-template-columns:1fr auto;gap:.15rem 1rem}
.eline--group > .eline__label{font-family:var(--f-display);font-weight:500;color:var(--paper)}
.eline__parts{grid-column:1/-1;list-style:none;display:grid;gap:.2rem;
  margin-top:.35rem;padding-left:.9rem;border-left:1px solid var(--line-soft)}
.eline__parts li{display:flex;justify-content:space-between;gap:1rem;
  font-size:.85rem;color:var(--dim)}
.eline--save .eline__label,
.eline--save .eline__amt{color:var(--beam-text)}
.eline--total{padding-top:.95rem}
.eline--total .eline__label,
.eline--total .eline__amt{font-family:var(--f-display);font-weight:600;font-size:1.05rem;
  color:var(--paper)}
.estimate__note{margin-top:1rem;padding:.85rem 1rem;font-size:.88rem;color:var(--text);
  background:var(--beam-glow);border:1px solid var(--beam);border-radius:var(--r)}
.estimate__disc{margin-top:1.1rem;font-size:.85rem;color:var(--dim);max-width:64ch}
.estimate__ctas{display:flex;flex-wrap:wrap;gap:.75rem;margin-top:1.6rem}
@media(max-width:560px){
  .estimate__ctas{flex-direction:column;align-items:stretch}
  .estimate__ctas .btn{width:100%}
}

/* ─── the booking page ───
   Not a page with a form on it. A shell the height of the window, and never
   any taller: a nav across the top, the question in the middle, the price and
   the button along the bottom. Nothing scrolls except the middle, and only
   when a step is genuinely taller than the space it has.

   The site header does not appear here. Seven links to somewhere else, sitting
   above a form somebody is halfway through, is a row of exits. */
body.is-booking{height:100dvh;overflow:hidden}
body.is-booking main{height:100dvh;display:flex;flex-direction:column}
/* The booking page has its own bar along the bottom. The site's call bar is
   fixed to the same edge, so where both exist, one lands on top of the other.
   The real page never renders it, but the packaged preview shares one set of
   chrome across every route and does. */
body.is-booking .callbar,
body.is-booking .pv-note{display:none}
.bookapp{flex:1;min-height:0;display:flex;flex-direction:column;background:var(--ink)}

/* One column for all three parts, so the logo, the question and the price sit
   on the same left edge, and the call button, the content and Continue sit on
   the same right one. Nothing in the shell is aligned to anything else. */
:root{--bookw:min(100% - 2.5rem,820px)}

/* the nav */
.bhead{flex:none;position:relative;background:var(--ink2);border-bottom:1px solid var(--line)}
/* Three tracks with matched outer ones, so the steps are centred on the page
   rather than centred on whatever is left between the logo and the button. */
.bhead__in{width:var(--bookw);margin-inline:auto;min-height:66px;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:1rem}
.bhead .logo{font-size:1rem;justify-self:start}
.bhead__mid{justify-self:center;min-width:0}

.bhead__call{justify-self:end;display:inline-flex;align-items:center;gap:.45rem;
  color:var(--dim);line-height:1;transition:color var(--ease)}
.bhead__call span{font-family:var(--f-display);font-size:.82rem;letter-spacing:-.01em}
.bhead__call:hover{color:var(--paper)}

/* Announced, not drawn. "Step 1 of 9" sat twelve pixels from the logo and
   told somebody starting the form that there were eight more screens after
   this one, which is the wrong first impression of a flow where half the
   steps are one tap. The bar under the header shows the same thing as a
   proportion, which reads as progress rather than as a queue. */
.bhead__count{position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;
  font-family:var(--f-display);
  font-size:.78rem;letter-spacing:.06em;text-transform:uppercase;color:var(--dim)}

/* Eight steps rather than five. The labels are what overflowed, so they go
   first and the numbered dots carry the position, which is what a progress
   rail is actually for. The count beside it says the rest. */
.bnav{display:flex;align-items:center;gap:1.4rem;list-style:none}
/* Eight steps rather than five, and eight labels do not fit beside a logo and
   a phone link at any width a laptop actually has: at 1440 the rail ended
   three pixels into "Call us". The numbered dots carry the position, which is
   what a progress rail is for, and the counter beside them says the rest in
   words. There is no width at which the labels fit: the header's inner column
   is capped at 1320px, so a wider window gives the rail no more room and a
   1920px screen collided the same way a 1440 one did. */
.bnav__label{display:none}
.bnav{gap:.7rem}
.bhead__count{display:block}
.bnav__item{display:flex;align-items:center;gap:.5rem;font-size:.83rem;color:var(--dim);
  transition:color var(--ease)}
.bnav__no{width:21px;height:21px;flex:none;display:grid;place-items:center;
  border-radius:50%;border:1px solid var(--line);font-family:var(--f-display);
  font-size:.7rem;line-height:1;
  transition:background var(--ease),border-color var(--ease),color var(--ease)}
.bnav__item.is-done{color:var(--text);cursor:pointer}
.bnav__item.is-done:hover{color:var(--paper)}
.bnav__item.is-done .bnav__no{border-color:var(--line-strong);color:var(--paper)}
.bnav__item.is-on{color:var(--paper)}
.bnav__item.is-on .bnav__no{background:var(--beam-surface);border-color:var(--beam-surface);
  color:#fff}

/* The rail, minus the sixty pixels a rail costs. */
/* Three pixels rather than two, and with a glow on the leading edge. It is
   the only thing telling somebody how far through they are now, so it has to
   read as a measure rather than as a border. */
.bhead__bar{position:absolute;inset:auto 0 -1px 0;height:3px;background:var(--line)}
.bhead__bar span{display:block;height:100%;width:0;background:var(--beam-surface);
  box-shadow:0 0 10px var(--beam-glow);border-radius:0 3px 3px 0;
  transition:width .34s var(--ease-fn)}

@media(max-width:900px){
  .bnav{display:none}
  .bhead__in{gap:.75rem;min-height:60px}
}

/* the middle */
.bmain{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}
/* min-height plus centring: short steps sit in the middle of the window, tall
   ones scroll from the top instead of having their heads cut off, which is
   what plain align-items:center does to an overflowing flex child. */
.bmain__in{width:var(--bookw);margin-inline:auto;min-height:100%;
  display:flex;flex-direction:column;justify-content:center;padding:1.6rem 0 1.8rem}
/* The details step is the one screen with more on it than a single question,
   so it gives back the breathing room the others keep and starts at the top
   rather than sitting centred. On a laptop that is the difference between a
   form you can see all of and a form you have to scroll. */
.bookapp.is-details .bmain__in{justify-content:flex-start;padding:1rem 0 1.1rem}

.book__q{font-size:clamp(1.5rem,4vw,2.2rem);margin-bottom:.4rem}
.book__sub{color:var(--dim);font-size:.94rem;max-width:56ch;margin-bottom:1.35rem}
.book__fine{font-size:.78rem;color:var(--dim);max-width:56ch}
.bform{display:grid;gap:.85rem}

/* One step at a time, and the change is a cross-fade rather than a handover.
   Every step sits in the same grid cell, so the one leaving and the one
   arriving can be on screen together for a moment instead of the page going
   briefly empty between them. [hidden] carries display:none, so a step that
   is not in play takes no space and the cell is the size of the one that is. */
.bsteps{display:grid;position:relative}

/* ── the beat between questions ──
   Three dots under the question that was just answered, for a fifth of a
   second, while the step on screen dims. It is not covering up a wait: there
   is nothing to wait for, the next question is already in the page. It is
   there because a screen that changes with no motion at all reads as a jump
   cut, and this is the form saying "got it" before it moves on. */
.bwait{grid-area:1 / 1;align-self:end;justify-self:start;transform:translateY(1.7rem);
  display:flex;gap:.42rem;align-items:center;pointer-events:none;z-index:2}
.bwait i{width:7px;height:7px;border-radius:50%;background:var(--beam);
  opacity:.25;animation:bwait 1s var(--ease-fn) infinite}
.bwait i:nth-child(2){animation-delay:.14s}
.bwait i:nth-child(3){animation-delay:.28s}
@keyframes bwait{
  0%,70%,100%{opacity:.22;transform:scale(.82)}
  35%{opacity:1;transform:scale(1)}
}
/* The question that has been answered steps back while the dots are up, so
   the eye is on the beat rather than on the answer it has finished with. */
.bookapp.is-waiting .bstep{opacity:.42;transition:opacity .14s ease-out}
.bookapp.is-waiting .bstep,.bookapp.is-waiting .bookbar__go{pointer-events:none}
@media(prefers-reduced-motion:reduce){
  .bwait i{animation:none;opacity:.6}
  .bookapp.is-waiting .bstep{opacity:1;transition:none}
}
.bstep{grid-area:1 / 1;display:grid;gap:1rem;justify-items:start;align-content:center}
.bstep > *{width:100%}
.bstep h1:focus-visible{outline:none}

/* The one leaving goes fast and on an ease-out, so most of the fade is over in
   the first few frames and it is at a tenth of its opacity by the time the new
   step is a quarter of the way in. ease-in was the wrong curve: it held a dense
   calendar at half opacity under the next step's heading. */
/* Out of the flow for its exit, and pinned to the viewport rectangle JS
   measured just before the class went on. Both steps share one grid cell, so
   while they overlapped the cell was as tall as the taller of the two and the
   step on its way out jumped sixty pixels up the screen in its last frames.
   Absolute was not enough: the cell it would have been absolute inside is
   itself centred, so it moved when the cell grew and took the pinned step with
   it. Fixed is measured against something that does not move. JS supplies
   top/left/width. */
.bstep.is-leaving{opacity:0;transform:translateY(-6px);pointer-events:none;
  position:fixed;margin:0;
  transition:opacity .08s ease-out,transform .08s ease-out}

/* An animation rather than a transition, because a transition needs its
   starting state painted first: two frames of nothing before anything moves.
   An animation runs from its own keyframes on the frame it is applied. */
.bstep.is-entering{animation:step-in .2s var(--ease-fn) both}
@keyframes step-in{
  from{opacity:0;transform:translateY(10px)}
  to{opacity:1;transform:none}
}
@media(prefers-reduced-motion:reduce){
  .bstep.is-leaving{transition:none}
  .bstep.is-entering{animation:none}
  .bhead__bar span{transition:none}
}

/* the bar */
/* The price on its own line, the two buttons splitting the width under it,
   back on the left and forward on the right. The vertical padding is set on
   the row rather than the bar, so what is above the label and what is below
   the figure are the same measurement rather than two that happen to look
   close. */
.bookbar{flex:none;background:var(--panel);border-top:1px solid var(--line);
  padding-bottom:env(safe-area-inset-bottom)}
.bookbar__in{width:var(--bookw);margin-inline:auto;display:grid;gap:.7rem;
  padding:.85rem 0 .95rem}
.bookbar__price{display:flex;align-items:baseline;gap:.45rem;flex-wrap:wrap}
.bookbar__label{width:100%;font-family:var(--f-display);font-size:.7rem;
  letter-spacing:.05em;text-transform:uppercase;color:var(--dim);
  line-height:1;margin-bottom:.32rem}
.bookbar__total{font-family:var(--f-display);font-size:1.6rem;font-weight:500;
  letter-spacing:-.04em;color:var(--beam-text);line-height:1}
.bookbar__unit{font-size:.78rem;color:var(--dim);line-height:1}

/* Half each. With one button, that one takes the row. */
.bookbar__go{display:grid;grid-template-columns:1fr 1fr;gap:.7rem}
.bookbar__go.is-one{grid-template-columns:1fr}
.bookbar__go .btn{width:100%}
/* Back is an outline, not a fill. The filled grey read heavier than an
   outlined Skip, which put the emphasis on the way out of the step rather
   than the way through it. */
.bookbar__go [data-book-back]{background:transparent;border-color:var(--line);
  color:var(--text);backdrop-filter:none}
.bookbar__go [data-book-back]:hover{background:var(--panel2);
  border-color:var(--line-strong);color:var(--paper)}

/* ── a phone on its side ──
   390 pixels of height, and the bar was taking 145 of them: the label, the
   price and the unit stacked above a full-width Continue. Both service cards
   were behind it, so the first question of the booking could not be answered
   at all in landscape.

   One row instead. The price sits on the left at the size it is everywhere
   else, the buttons sit on the right at the width they need, and the bar is
   about sixty pixels. The step above it gets its screen back. */
@media (max-height:560px) and (orientation:landscape){
  .bhead__in{min-height:48px}
  .bmain__in{padding:.9rem 0 1rem}
  .book__q{font-size:1.35rem;margin-bottom:.2rem}
  .book__sub{font-size:.88rem;margin-bottom:.8rem}

  .bookbar__in{grid-template-columns:auto 1fr;align-items:center;gap:1.1rem;
    padding-block:.55rem}
  .bookbar__price{flex-wrap:nowrap;align-items:baseline;gap:.4rem}
  .bookbar__label{width:auto;font-size:.62rem}
  .bookbar__total{font-size:1.2rem}
  .bookbar__unit{display:none}
  .bookbar__go{justify-self:end;grid-auto-flow:column;grid-template-columns:none}
  .bookbar__go .btn{width:auto;min-width:8.5rem;min-height:40px;padding-block:.6rem}
}

.bookbar__err{width:var(--bookw);margin:0 auto .9rem;padding:.6rem .85rem;
  border-radius:var(--r);font-size:.85rem;color:#ffb3b0;
  background:rgba(234,15,14,.12);border:1px solid rgba(234,15,14,.35)}

.bsum{padding:.8rem 1rem;font-size:.88rem;color:var(--text);
  background:var(--panel2);border:1px solid var(--line);border-radius:var(--r)}

/* ─── the photo step ───
   One target. Clicking anywhere on it opens the picker, because it is a label
   wrapped around the input; a file dropped on it lands on the same input; and
   a paste while the step is up goes to the same place. */
.dropzone{display:grid;justify-items:center;gap:.35rem;width:100%;cursor:pointer;
  padding:2rem 1.5rem 1.7rem;border:1.5px dashed var(--line-strong);
  border-radius:var(--r-lg);background:var(--panel);text-align:center;
  transition:border-color var(--ease),background var(--ease)}
.dropzone:hover{border-color:var(--beam);background:var(--panel2)}
.dropzone:focus-within{outline:2px solid var(--beam);outline-offset:3px}
.dropzone.is-over{border-color:var(--beam);background:var(--panel2);border-style:solid}
.dropzone__art{color:var(--dim);margin-bottom:.35rem;transition:color var(--ease)}
.dropzone:hover .dropzone__art,.dropzone.is-over .dropzone__art{color:var(--beam-text)}
.dropzone__lead{font-family:var(--f-display);font-size:1.05rem;color:var(--paper);
  letter-spacing:-.02em}
.dropzone__sub{font-size:.84rem;color:var(--dim);max-width:42ch}
/* Nobody drags a file on a phone, so the hint only appears where a pointer
   that can do it exists. */
.dropzone__drag{display:none}
@media(hover:hover) and (pointer:fine){.dropzone__drag{display:inline}}
.dropzone__go{margin-top:.75rem;pointer-events:none}
/* Three in, and the panel says so rather than silently doing nothing. */
.dropzone.is-full{opacity:.5;pointer-events:none}

.shots-add__msg{font-size:.84rem;color:var(--dim);margin-top:.7rem}
.shots-add__msg.is-bad{color:#ffb3b0}
.shots-add__list{list-style:none;display:flex;gap:.55rem;flex-wrap:wrap;margin-top:.85rem}
.shots-add__item{position:relative;width:104px;height:78px;border-radius:var(--r);
  overflow:hidden;border:1px solid var(--line);background:var(--panel2)}
.shots-add__item img{width:100%;height:100%;object-fit:cover}
/* Still going up. The tile is there from the first frame so the wait has a
   shape, and the shimmer says it is working rather than stuck. */
.shots-add__item.is-busy::after{content:'';position:absolute;inset:0;
  background:rgba(0,0,0,.45);animation:shot-wait 1.1s ease-in-out infinite}
@keyframes shot-wait{0%,100%{opacity:.25}50%{opacity:.6}}
@media(prefers-reduced-motion:reduce){
  .shots-add__item.is-busy::after{animation:none;opacity:.4}
}
.shots-add__drop{position:absolute;top:4px;right:4px;width:22px;height:22px;
  display:grid;place-items:center;border-radius:50%;font-size:15px;line-height:1;
  background:rgba(0,0,0,.72);color:#fff;z-index:1}
.shots-add__drop:hover{background:var(--beam-surface)}

/* ─── details form ─── */
.bgrid{display:grid;grid-template-columns:1fr 1fr;gap:.75rem .8rem}
.bgrid__wide{grid-column:1 / -1}
@media(max-width:560px){.bgrid{grid-template-columns:1fr}}
.field__label em{font-style:normal;text-transform:none;letter-spacing:0;
  font-weight:400;color:rgba(255,255,255,.5)}
/* Under the box, not between the label and it: a hint above the input
   pushes that field down and the two columns stop lining up. */
.field__hint{font-size:.78rem;color:rgba(255,255,255,.62)}
.field{align-content:start}
/* An error under the box it is about. A list of problems at the top of a form
   means reading the list, then hunting for the field each line refers to. */
.field__err{font-size:.78rem;color:#ffb3b0}
.consent.is-bad{border-color:rgba(234,15,14,.55)}

/* The one tick: the booking terms and permission to email, together, because
   two boxes side by side is two decisions where the customer is making one. */
.consent{display:grid;gap:.5rem;padding:1rem 1.1rem;border:1px solid var(--line-strong);
  border-radius:var(--r-lg);background:var(--panel)}
.consent__row{display:flex;gap:.75rem;align-items:flex-start;font-size:.89rem;
  line-height:1.55;color:rgba(255,255,255,.84);cursor:pointer}
.consent__row input{margin-top:.22rem;width:18px;height:18px;flex:none;
  accent-color:var(--beam);cursor:pointer}
.consent__row a{color:var(--beam-text);text-decoration:underline;text-underline-offset:3px}
.bform__fine{font-size:.78rem;line-height:1.55;color:rgba(255,255,255,.58)}

/* ─── receipt ─── */
.bdone{display:grid;gap:.75rem;justify-items:start;max-width:56ch}
.bdone__ref{font-family:var(--f-display);font-size:.74rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dim)}
.bdone__ref b{color:var(--beam-text);font-weight:500;letter-spacing:.04em}
.bdone__title{font-size:clamp(1.7rem,4.6vw,2.6rem)}
.bdone__when{font-family:var(--f-display);font-size:1.3rem;color:var(--paper);
  letter-spacing:-.03em;line-height:1.25}
.bdone__note{font-size:.94rem;color:var(--dim)}
.bdone__go{display:flex;gap:.6rem;flex-wrap:wrap;margin-top:.5rem}

/* Announced, not shown. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ─── scheduler ───
   A month calendar and a column of times beside it. Every control is a real
   button, so the keyboard and a screen reader get them for free, and
   aria-pressed carries the choice: colour alone never does.

   The grid takes one tab stop, not forty-two. Arrow keys move inside it,
   which is the pattern people already have for a calendar. */
/* The calendar is capped rather than fluid: stretched across the estimate
   page's measure the day circles grow to the size of buttons and the month
   stops reading as a month. */
.sched{display:grid;grid-template-columns:minmax(228px,372px) minmax(196px,232px);
  justify-content:start;gap:1.1rem 1.35rem;align-items:start}
.sched__status,.sched__note{grid-column:1 / -1}
.sched__status{font-size:.9rem;color:var(--dim)}
.sched__status--bad{color:var(--paper)}
.sched__retry{color:var(--beam-text);text-decoration:underline;text-underline-offset:3px}
.sched__note{font-size:.85rem;color:var(--dim)}

/* A tray, the same one the wheel gets. On the booking flow the month is
   narrower than the frame the header rail and the bottom bar draw, and centred
   with nothing round it it floated there under a heading on the left, which
   reads as adrift rather than as placed. On the manage page it puts the month
   and the wheel beside it in matching boxes instead of one bare and one not. */
.cal{display:grid;gap:.45rem;padding:.85rem 1rem 1rem;
  background:var(--ink2);border:1px solid var(--line);
  border-radius:calc(var(--r) + 5px)}
.cal__head{display:flex;align-items:center;gap:.35rem;margin-bottom:.15rem}
.cal__month{flex:1;text-align:center;font-family:var(--f-display);font-size:.95rem;
  font-weight:500;color:var(--paper);letter-spacing:-.02em}
.cal__nav{width:30px;height:30px;display:grid;place-items:center;flex:none;
  border:1px solid var(--line);border-radius:var(--r);color:var(--text);
  transition:border-color var(--ease),color var(--ease)}
.cal__nav svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round}
.cal__nav:hover:not(:disabled){border-color:var(--line-strong);color:var(--paper)}
.cal__nav:disabled{opacity:.28;cursor:not-allowed}

.cal__dows,.cal__grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px}
.cal__dow{text-align:center;font-family:var(--f-display);font-size:.64rem;
  letter-spacing:.09em;text-transform:uppercase;color:var(--dim);padding-bottom:.15rem}
.cal__pad{aspect-ratio:1}

/* A shut day is still drawn, and still readable. Removing it would make the
   month reflow every time the van fills up, and a customer scanning for a gap
   needs the shape of the week to stay put. */
.cal__day{aspect-ratio:1;display:grid;place-items:center;border-radius:50%;
  font-size:.88rem;font-variant-numeric:tabular-nums;color:var(--text);
  border:1px solid transparent;
  transition:background var(--ease),border-color var(--ease),color var(--ease)}
.cal__day.is-shut{color:rgba(255,255,255,.2);cursor:default}
.cal__day.is-open{color:var(--paper);background:var(--panel2);border-color:var(--line)}
.cal__day.is-open:hover{border-color:var(--beam);color:var(--paper)}
.cal__day.is-on,.cal__day.is-on:hover{background:var(--beam-surface);
  border-color:var(--beam-surface);color:#fff}

.times{display:grid;gap:.5rem;align-content:start;min-width:0}
.times__head{font-family:var(--f-display);font-size:.82rem;font-weight:500;
  color:var(--paper);letter-spacing:-.01em}
.times.is-empty .times__head{color:var(--dim)}

/* ── the time wheel ──
   A fixed frame with a band across the middle and the day's hours turning
   under it, the way a phone asks for a time. The band is the choice, so there
   is no separate press: where the dial stops is the time. Five rows is enough
   to see an hour either side of the one you are on, which is what makes a
   wheel legible; three on a screen too short for five.

   The rows are on a cylinder rather than in a list, so they curve away at the
   top and bottom and go edge on rather than being cut off. */
/* A tray, not a bare list. The rows above and below the band curve away and
   the ones past them are edge on, so without something drawn round it the
   control is mostly empty space and reads as a gap in the page. */
.wheel{--wheel-row:48px;--wheel-rows:5;position:relative;width:100%;max-width:320px;
  height:calc(var(--wheel-row) * var(--wheel-rows));
  background:var(--ink2);border:1px solid var(--line);
  border-radius:calc(var(--r) + 5px);padding-inline:.35rem;
  overflow:clip}
.wheel__band{position:absolute;left:.35rem;right:.35rem;top:50%;height:var(--wheel-row);
  transform:translateY(-50%);border-radius:var(--r);background:var(--panel2);
  border:1px solid var(--line-strong);pointer-events:none}

/* The drum. No scrolling anywhere in here: the rows are laid on a cylinder and
   the whole thing is turned by a finger, a trackpad or the arrow keys, which
   is what a dial is. touch-action:none because a drag on the dial is the dial
   turning and not the page moving under it. */
.wheel__stage{position:absolute;inset:0;z-index:1;perspective:900px;
  transform-style:preserve-3d;touch-action:none;cursor:grab;
  -webkit-user-select:none;user-select:none}
.wheel__stage:active{cursor:grabbing}
.wheel__stage:focus-visible{outline:2px solid var(--beam);outline-offset:-2px;
  border-radius:calc(var(--r) + 4px)}
/* Height zero at the middle of the frame, so a row turned to nothing sits
   exactly on the band. JS pushes it back by the cylinder's radius, which puts
   the middle row at depth zero and therefore at its own size. */
.wheel__track{position:absolute;top:50%;left:0;right:0;height:0;
  transform-style:preserve-3d}
.wheel__opt{position:absolute;left:0;right:0;top:calc(var(--wheel-row) / -2);
  height:var(--wheel-row);display:grid;grid-template-columns:1fr auto 1fr;
  align-items:center;cursor:pointer;backface-visibility:hidden;
  font-variant-numeric:tabular-nums;color:var(--text);
  transform-origin:50% 50%;will-change:transform,opacity}
/* Three columns rather than a centred row, so the word beside a booked hour
   hangs off to the right and every time still lines up down the middle. A
   wheel whose numbers slide sideways as you pass them is not a wheel. */
.wheel__time{grid-column:2;font-size:1.12rem;letter-spacing:-.01em}
.wheel__opt.is-on .wheel__time{color:#fff;font-weight:500}
/* The wheel carries only the hours somebody can pick. Keeping the taken ones
   on it, greyed, was meant to answer "what happened to two o'clock"; what it
   actually did was hand somebody a list of things they cannot have. */

/* Split across two steps: the month on one, that day's times on the next.

   Both are narrower than the frame the header rail and the bottom bar draw, so
   both sit in the middle of it rather than against its left edge. The photos
   step already works this way: a heading on the left and a control centred
   under it. A month capped at four hundred pixels and left-aligned in an
   eight-hundred-pixel frame leaves half the screen empty on one side, which
   reads as a mistake rather than as a margin. */
/* --calw is set by the scheduler, which measures how much room the frame has
   left and hands the month the width that fits it. 404 is the cap it starts
   from and never exceeds. */
/* --calw is the width of the month grid itself, so the cap adds back the
   tray's padding: fit() works in grid pixels and never has to know about the
   box round it. */
.sched--cal{display:block;justify-self:center;margin-inline:auto;
  max-width:calc(var(--calw,404px) + 2rem)}
.sched--times{display:block}
.sched--times .wheel{margin-inline:auto}
/* The step's own heading already names the day, so the panel's does not. */
.sched--times .times__head{display:none}
.sched--times .wheel{--wheel-row:54px;max-width:360px}
.sched--times .wheel__time{font-size:1.24rem}
/* The step's line above the wheel already carries the day and the timezone,
   and the wheel carries the time. A sentence repeating all three is one line
   too many. */
.sched--times .sched__note{display:none}

/* Short windows: a laptop with the dock and a browser chrome eating the screen
   is a smaller box than a phone held upright. Three rows still reads as a
   wheel; two does not. */
@media(max-height:660px){
  .sched--times .wheel{--wheel-row:48px;--wheel-rows:3}
}

/* On a phone the wheel goes under the calendar rather than beside it, and gets
   the full width so a thumb has something to catch. */
@media(max-width:560px){
  .sched{grid-template-columns:1fr;gap:1.1rem}
  .wheel{max-width:none}
  .cal__day{font-size:.92rem}
}

/* ─── text inputs ───
   The picker only ever needed selects. The booking form needs the rest, and
   they share one look so the two steps do not feel like two forms. */
/* A box has to look like a box before anyone types in it. Near-black on black
   inside a #333 hairline, these read as faint rectangles rather than as
   somewhere to put an answer, so the well is lifted off the page and the edge
   is drawn brightly enough to find. */
.field input[type=text],.field input[type=email],.field input[type=tel]{
  width:100%;background:var(--panel);border:1px solid var(--line-strong);
  border-radius:var(--r);
  color:var(--paper);padding:.75rem .85rem;font-size:.98rem;font-family:inherit;
  transition:border-color var(--ease),background var(--ease)}
.field input::placeholder{color:rgba(255,255,255,.46)}
.field input:hover{border-color:rgba(255,255,255,.34)}
.field input:focus-visible{outline:none;border-color:var(--beam);background:var(--panel2)}
.field input:user-invalid{border-color:rgba(234,15,14,.6)}
/* Sits here rather than with the booking page rules: the base input styles
   above set border-color at the same specificity, and whichever comes last
   wins. It came last, and the red border never appeared. */
.field.is-bad input{border-color:rgba(234,15,14,.6)}

/* ─── footer list signup ─── */
.sign{margin-top:1.4rem;display:grid;gap:.6rem}
.sign__row{display:flex;gap:.45rem}
.sign__row input{flex:1;min-width:0}
.sign__row .btn{flex:none}
.sign__consent{font-size:.78rem;color:var(--dim);line-height:1.45}
.sign__consent input{width:15px;height:15px}
.sign__msg{font-size:.8rem;color:var(--beam-text)}
.sign__msg.is-bad{color:#ffb3b0}

/* the manage page reuses .note for its one status line */
.note--bad{border-color:rgba(234,15,14,.35);color:#ffb3b0}

/* The estimate form sits in a narrow measure, but left-aligned with the page
   head rather than centred, so every page shares one left edge. */
.qcol{max-width:760px}

/* ─── numbered sequence marker ───
   Restoration then protection is a real order of operations, so the number
   carries information the old eyebrow label did not. */
.stepno{display:flex;align-items:baseline;gap:.6rem;margin-bottom:.9rem;
  font-family:var(--f-display);font-size:.78rem;font-weight:500;
  letter-spacing:.06em;text-transform:uppercase;color:var(--dim)}
.stepno span{font-size:1.5rem;font-weight:500;letter-spacing:-.02em;
  text-transform:none;color:var(--beam-text);line-height:1}

/* plain value label, replacing the red-square eyebrow */
.plabel{font-family:var(--f-display);font-size:.72rem;font-weight:500;
  letter-spacing:.06em;text-transform:uppercase;color:var(--dim)}

/* ─── closing CTA: a ruled block, not another bordered panel ─── */
.cta-close{border-top:1px solid var(--line);padding-top:clamp(2rem,4vw,3rem)}
.cta-close__body{max-width:52ch}
.cta-close__body h2{font-size:clamp(1.6rem,3.4vw,2.4rem);letter-spacing:-.03em}
.cta-close__body p{margin:.9rem 0 1.75rem;color:var(--dim)}
.cta-close__actions{display:flex;flex-wrap:wrap;gap:.75rem}
@media(max-width:560px){
  .cta-close__actions{flex-direction:column;align-items:stretch}
  .cta-close__actions .btn{width:100%}
}

/* ─── inline vehicle price picker ───
   The booking flow behind a button was invisible: nothing on the page said a
   price was one dropdown away. This puts it in the page. */
.pricebar{display:grid;gap:1.1rem;margin-top:clamp(1.5rem,3vw,2.25rem)}
.priceout{display:grid;gap:1.1rem;margin-top:clamp(1.5rem,3vw,2.25rem);
  padding-top:clamp(1.5rem,3vw,2rem);border-top:1px solid var(--line)}
.priceout__num{display:grid;gap:.5rem}
.priceout__total{display:flex;align-items:baseline;gap:.7rem;flex-wrap:wrap;
  font-family:var(--f-display);font-size:clamp(2.6rem,6vw,3.6rem);font-weight:500;
  letter-spacing:-.04em;color:var(--beam-text);line-height:1}
.priceout__unit{font-size:.9rem;letter-spacing:0;color:var(--dim)}
.priceout .estimate__lines{max-width:520px;border-top:0;border-bottom:0}
.priceout__go{display:flex;flex-wrap:wrap;gap:.75rem}
@media(min-width:900px){
  .priceout{grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    align-items:start;column-gap:clamp(2rem,5vw,4rem)}
  .priceout__go{grid-column:1/-1}
}
@media(max-width:560px){
  .priceout__go{flex-direction:column;align-items:stretch}
  .priceout__go .btn{width:100%}
}

/* ─── vehicle picker: one question per screen ───
   Three dropdowns asked the visitor to hold three things in mind at once.
   Buttons rather than selects, so a phone gets a tap instead of a picker wheel. */
.wiz{display:grid;gap:1rem}
.wiz__hint{font-size:.85rem;color:var(--dim);max-width:52ch}

/* ─── one package, two numbers ─── */
.offer{display:grid;gap:clamp(1.75rem,4vw,3rem);
  padding-top:clamp(1.5rem,3vw,2.25rem);border-top:1px solid var(--line)}
.offer__prices{display:grid;grid-template-columns:1fr 1fr;gap:clamp(1.25rem,4vw,3rem)}
.offer__amount{font-family:var(--f-display);font-size:clamp(2.6rem,7vw,4.2rem);
  font-weight:500;letter-spacing:-.045em;color:var(--beam-text);line-height:1}
.offer__for{margin-top:.5rem;font-size:.9rem;color:var(--dim)}
.offer__title{font-size:1.2rem;margin-bottom:1rem}
.offer__list{list-style:none;display:grid;gap:.7rem;max-width:52ch}
.offer__list li{display:flex;gap:.65rem;align-items:baseline;font-size:.98rem;color:var(--text)}
.offer__list svg{color:var(--beam-text);flex:none;translate:0 1px}
.offer__go{display:flex;flex-wrap:wrap;gap:.7rem;margin-top:1.75rem}
@media(min-width:900px){
  .offer{grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);
    column-gap:clamp(2.5rem,6vw,5rem);align-items:start}
  .offer__prices{grid-template-columns:1fr;gap:2rem}
}
@media(max-width:560px){
  .offer__go{flex-direction:column;align-items:stretch}
  .offer__go .btn{width:100%}
}

/* ══════════════════════════════════════════════════════════
   THE SERVICE STEP
   A choice, then a few things to tick, then the option of a
   second car. Everything on it is a button, because a tick that
   moves the total at the foot of the screen is the whole
   interaction and a form control would only get in the way.
   ══════════════════════════════════════════════════════════ */
.picks{display:grid;gap:.7rem;margin-bottom:2.25rem}
.pick{display:grid;grid-template-columns:auto 1fr auto;align-items:start;gap:.9rem;
  width:100%;text-align:left;padding:1.05rem 1.15rem;border-radius:var(--r-lg);
  border:1.5px solid var(--line);background:var(--panel);cursor:pointer;
  transition:border-color var(--ease),background var(--ease)}
.pick:hover{border-color:var(--line-strong);background:var(--panel2)}
.pick.is-on{border-color:var(--beam);background:var(--beam-glow)}
.pick__tick{width:19px;height:19px;margin-top:2px;border-radius:50%;
  border:1.5px solid var(--line-strong);position:relative;flex:none}
.pick.is-on .pick__tick{border-color:var(--beam);background:var(--beam)}
.pick.is-on .pick__tick::after{content:"";position:absolute;left:5.5px;top:2.5px;
  width:5px;height:9px;border:solid #fff;border-width:0 2px 2px 0;rotate:45deg}
.pick__body{display:grid;gap:.2rem;min-width:0}
.pick__name{font-family:var(--f-display);font-size:1.06rem;color:var(--paper);letter-spacing:-.02em}
.pick__when{font-size:.86rem;color:var(--beam-text)}
.pick__sub,.pick__sum{font-size:.88rem;color:var(--dim);line-height:1.45}
.pick__price{font-family:var(--f-display);font-size:1.25rem;color:var(--paper);
  letter-spacing:-.03em;white-space:nowrap}
/* The second car onwards: what it lists at, struck through, and what it costs
   on this order beside it. Column on a narrow card so the pair does not push
   the price off the edge, and the struck figure sits above the one that
   counts rather than beside it. */
.pick__price--cut{display:flex;flex-direction:column;align-items:flex-end;
  line-height:1.15}
.pick__was{font-size:.92rem;color:var(--dim);text-decoration-thickness:1px}
.pick__now{color:var(--beam-text)}

.extras{margin-bottom:2.25rem}
.extras__head{font-family:var(--f-display);font-size:1.15rem;color:var(--paper);
  letter-spacing:-.025em;margin-bottom:.3rem}
.extras__sub{font-size:.9rem;color:var(--dim);margin-bottom:1rem;max-width:46ch}
.extras__list{display:grid;gap:.55rem}
.extra{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:.85rem;
  width:100%;text-align:left;padding:.8rem 1rem;border-radius:var(--r);
  border:1px solid var(--line);background:var(--panel);cursor:pointer;
  transition:border-color var(--ease),background var(--ease)}
.extra:hover{border-color:var(--line-strong);background:var(--panel2)}
.extra.is-on{border-color:var(--beam);background:var(--beam-glow)}
.extra__box{width:17px;height:17px;border-radius:4px;flex:none;position:relative;
  border:1.5px solid var(--line-strong)}
.extra.is-on .extra__box{border-color:var(--beam);background:var(--beam)}
.extra.is-on .extra__box::after{content:"";position:absolute;left:4.5px;top:1.5px;
  width:4px;height:8px;border:solid #fff;border-width:0 2px 2px 0;rotate:45deg}
.extra__body{display:grid;gap:.1rem;min-width:0}
.extra__name{color:var(--paper);font-size:.97rem}
.extra__desc{font-size:.84rem;color:var(--dim);line-height:1.4}
.extra__price{color:var(--paper);font-size:.97rem;white-space:nowrap}

/* ── the add-another-car question ──
   One offer with a number in it. A list of car rows and a plus button made
   this look like paperwork; a question is an offer, and the flow returns here
   after each car so a third is the same single tap as the second. */

.sofar{list-style:none;display:grid;gap:0;margin-bottom:1.75rem;
  border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
/* Every cell placed by hand. Left to the auto-placer the price landed in the
   first column and the name in the third, so the rows read backwards. */
.sofar__i{display:grid;grid-template-columns:minmax(0,1fr) auto auto;
  align-items:center;gap:.15rem .9rem;padding:.8rem 1rem;background:var(--panel)}
.sofar__i + .sofar__i{border-top:1px solid var(--line)}
.sofar__n{grid-column:1;grid-row:1;color:var(--paper);font-size:.97rem;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sofar__w{grid-column:1;grid-row:2;font-size:.83rem;color:var(--dim)}
.sofar__p{grid-column:2;grid-row:1/span 2;color:var(--paper);font-size:.97rem;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.sofar__x{grid-column:3;grid-row:1/span 2;width:24px;height:24px;border-radius:50%;
  color:var(--dim);font-size:17px;line-height:1;display:grid;place-items:center}
.sofar__x:hover{background:var(--panel2);color:var(--paper)}
.sofar__i--save{background:var(--beam-glow)}
.sofar__i--save .sofar__n,.sofar__i--save .sofar__p{color:var(--beam-text)}

.asks{display:grid;gap:.7rem}
.ask{display:grid;gap:.2rem;width:100%;text-align:left;padding:1.05rem 1.25rem;
  border-radius:var(--r-lg);border:1.5px solid var(--line);background:var(--panel);
  cursor:pointer;transition:border-color var(--ease),background var(--ease)}
.ask:hover{border-color:var(--line-strong);background:var(--panel2)}
.ask--yes{border-color:var(--beam);background:var(--beam-glow)}
.ask--yes:hover{background:rgba(234,15,14,.18)}
.ask__t{font-family:var(--f-display);font-size:1.08rem;letter-spacing:-.02em;color:var(--paper)}
.ask--yes .ask__t{color:var(--beam-text)}
.ask__s{font-size:.88rem;color:var(--dim);line-height:1.5}

/* ── the recap on the details step ──
   The last screen before an address is handed over, so it itemises rather
   than summarises. A surprise belongs here, one tap from going back, and not
   in the confirmation email. */
.bsum{display:grid;gap:.55rem}
.recap__car + .recap__car{margin-top:.6rem;padding-top:.6rem;border-top:1px solid var(--line)}
.recap__who{font-size:.82rem;color:var(--dim);margin-bottom:.3rem}
.recap__l{display:flex;justify-content:space-between;gap:1rem;font-size:.9rem;padding:.1rem 0}
.recap__l b{color:var(--paper);font-weight:500;white-space:nowrap}
.recap__save{display:flex;justify-content:space-between;gap:1rem;margin-top:.6rem;
  padding-top:.6rem;border-top:1px solid var(--line);font-size:.92rem;color:var(--beam-text)}
.recap__save b{font-weight:500;white-space:nowrap}
.recap__when{margin-top:.7rem;padding-top:.6rem;border-top:1px solid var(--line);
  font-size:.9rem;color:var(--beam-text)}
.recap__total{display:flex;justify-content:space-between;gap:1rem;margin-top:.5rem;
  padding-top:.6rem;border-top:1px solid var(--line-strong);font-size:1.02rem}
.recap__total b{font-family:var(--f-display);color:var(--paper);letter-spacing:-.02em}

@media(max-width:560px){
  .pick{grid-template-columns:auto 1fr;row-gap:.4rem}
  .pick__price{grid-column:2;justify-self:start}
  .car__row{grid-template-columns:1fr 1fr;gap:.45rem}
  .car__f:last-child{grid-column:span 2}
}

/* ══════════════════════════════════════════════════════════
   FOOTER
   Three jobs in order of who needs them. The ask first, because
   the person who has already decided should not have to read
   past four columns of links to find a phone number. Then the
   map, for the person still looking. Then the fine print.

   The headings were styled as .ftr h3 while the markup used h2,
   so none of it applied and they rendered at page-title size,
   which is why the whole thing read as unfinished.
   ══════════════════════════════════════════════════════════ */
.ftr{background:var(--ink2);border-top:1px solid var(--line);
  padding:clamp(2.5rem,5vw,4rem) 0 1.75rem}

/* The number, reachable but not shouting. Every content page already ends in
   a CTA band with a Book button and this same number in it; a second full
   call to action stacked directly under the first weakens both, so what is
   left here is the number itself for anyone who scrolled past. */
.ftr__tel{display:inline-flex;align-items:center;gap:.55rem;margin-top:1.1rem;
  font-family:var(--f-display);font-size:1.2rem;letter-spacing:-.03em;
  color:var(--paper);transition:color .18s}
.ftr__tel:hover{color:var(--beam-text)}
.ftr__tel svg{width:16px;height:16px;flex:none;color:var(--beam-text)}

/* ── the map ── */
.ftr__cols{display:grid;grid-template-columns:1.15fr 2fr 1fr;
  gap:clamp(2rem,4vw,3.5rem)}
.ftr__blurb{margin-top:.9rem;font-size:.9rem;color:var(--dim);max-width:34ch;line-height:1.6}
.ftr__perks{list-style:none;display:flex;flex-wrap:wrap;gap:.45rem;margin-top:1.1rem}
.ftr__perks li{display:inline-flex;align-items:center;gap:.4rem;
  padding:.3rem .6rem;border:1px solid var(--line);border-radius:20px;
  font-size:.76rem;color:var(--dim);white-space:nowrap}
.ftr__perks svg{width:13px;height:13px;color:var(--beam-text);flex:none}

.ftr__nav{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:2rem}
/* Small, spaced, dim. A footer heading is a label, not a title: it exists so
   the eye can skip the three columns it does not want. */
.ftr h3{font-size:.7rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--dim);font-weight:500;margin-bottom:.85rem}
.ftr__nav ul,.ftr__sign ul{list-style:none;display:grid;gap:.4rem}
.ftr__nav a{font-size:.9rem;color:var(--text);line-height:1.5;transition:color .18s}
.ftr__nav a:hover{color:var(--beam-text)}

.ftr__sign p{font-size:.82rem;color:var(--dim);margin-bottom:.9rem;line-height:1.55;max-width:30ch}
.ftr__sign .sign__row{display:flex;gap:.4rem}
.ftr__sign input[type=email]{flex:1;min-width:0;padding:.55rem .7rem;font-size:.88rem;
  border:1px solid var(--line);border-radius:var(--r);
  background:var(--ink);color:var(--paper)}
.ftr__sign input[type=email]::placeholder{color:rgba(255,255,255,.3)}
.ftr__sign input[type=email]:focus{outline:none;border-color:var(--beam)}
/* The checkbox and its sentence on one baseline. It used to be a box one line
   wide with the label wrapping underneath it. */
.sign__consent{display:grid;grid-template-columns:auto 1fr;gap:.55rem;
  align-items:start;margin-top:.7rem;font-size:.76rem;color:var(--dim);
  line-height:1.5;cursor:pointer}
.sign__consent input{width:14px;height:14px;margin-top:2px;accent-color:var(--beam)}
.sign__msg{margin-top:.6rem;font-size:.8rem;color:var(--beam-text)}

/* ── the fine print ── */
.ftr__base{display:flex;align-items:center;flex-wrap:wrap;gap:.75rem 1.5rem;
  margin-top:clamp(2rem,4vw,3rem);padding-top:1.4rem;
  border-top:1px solid var(--line);font-size:.82rem;color:var(--dim)}
.ftr__legal{display:flex;flex-wrap:wrap;gap:1.1rem;margin-left:auto}
.ftr__legal a:hover{color:var(--beam-text)}
.ftr__top-btn{display:grid;place-items:center;width:34px;height:34px;flex:none;
  border:1px solid var(--line);border-radius:var(--r);color:var(--dim);
  transition:border-color var(--ease),color var(--ease)}
.ftr__top-btn:hover{border-color:var(--beam);color:var(--beam-text)}

@media(max-width:980px){
  .ftr__cols{grid-template-columns:1fr 1fr;gap:2.25rem}
  .ftr__nav{grid-column:span 2;order:3}
  .ftr__sign{order:2}
}
@media(max-width:620px){
  .ftr__cols{grid-template-columns:1fr}
  .ftr__nav{grid-column:auto;grid-template-columns:1fr 1fr;gap:1.75rem}
  /* Back to the order they are written in. The two-column layout above puts
     the sign-up second and the links last, which is right when they sit side
     by side; stacked, it buried the navigation under a form and made somebody
     scroll past an email box to reach the pages. */
  .ftr__nav,.ftr__sign{order:0}

  /* One alignment, not three. The copyright was centred, the legal links ran
     from the left edge, and the back-to-top button was centred again, so the
     bottom of the page read as three things that had come loose from each
     other. Stacked and centred is a decision; what was there before was the
     residue of a row that had run out of width. */
  .ftr__base{flex-direction:column;align-items:center;text-align:center;
    gap:1.15rem}
  .ftr__legal{margin-left:0;width:auto;justify-content:center;gap:.4rem 1.4rem}
}

/* ══════════════════════════════════════════════════════════
   PRICING: TWO SERVICES, THEN THE EXTRAS
   The choice between the two is the first question the booking
   flow asks, so it has to be visible before somebody starts.
   One package and a paragraph of fine print hid it.
   ══════════════════════════════════════════════════════════ */
.plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(19rem,1fr));
  gap:clamp(1rem,2vw,1.5rem);margin-top:clamp(2rem,4vw,3rem)}
.plan{display:flex;flex-direction:column;padding:clamp(1.5rem,2.5vw,2rem);
  border:1px solid var(--line);border-radius:var(--r-lg);background:var(--panel)}
/* The restoration is what most people need, so it gets the accent. Not a
   "most popular" badge: there are two, and which one is right is decided by
   the lenses rather than by what other people bought. */
.plan--lead{border-color:var(--beam);background:linear-gradient(180deg,var(--beam-glow),var(--panel) 40%)}
.plan__name{font-family:var(--f-display);font-size:1.35rem;letter-spacing:-.03em;color:var(--paper)}
.plan__when{margin-top:.25rem;font-size:.9rem;color:var(--beam-text)}
.plan__amt{font-family:var(--f-display);font-size:clamp(2.4rem,4vw,3rem);
  letter-spacing:-.04em;color:var(--paper);line-height:1;margin:1.25rem 0 .3rem}
.plan__amt span{display:block;font-family:var(--f-body);font-size:.82rem;
  letter-spacing:0;color:var(--dim);margin-top:.45rem}
.plan__sum{font-size:.95rem;color:var(--dim);line-height:1.6;margin-bottom:1.25rem}
.plan__list{list-style:none;display:grid;gap:.6rem;margin-bottom:1.5rem;flex:1}
.plan__list li{display:flex;gap:.6rem;align-items:flex-start;font-size:.92rem;color:var(--text)}
.plan__list svg{width:15px;height:15px;flex:none;margin-top:.2rem;color:var(--beam-text)}
.plan .btn{width:100%}
.plans__note{margin-top:1.1rem;font-size:.88rem;color:var(--dim);max-width:none;
  padding-left:1.5rem;border-left:2px solid var(--line)}

/* ── the extras ── */
.alsos{margin-top:clamp(2.5rem,5vw,4rem);padding-top:clamp(2rem,4vw,2.75rem);
  border-top:1px solid var(--line)}
.alsos__head{font-family:var(--f-display);font-size:1.25rem;letter-spacing:-.03em;
  color:var(--paper);margin-bottom:1.25rem}
.alsos__list{list-style:none;display:grid;gap:0}
.also{display:grid;grid-template-columns:1fr auto;gap:.15rem 1.5rem;
  padding:.95rem 0;border-bottom:1px solid var(--line)}
.also:last-child{border-bottom:0}
.also__n{color:var(--paper);font-size:1rem}
.also__p{color:var(--paper);font-size:1rem;font-variant-numeric:tabular-nums;
  text-align:right;white-space:nowrap}
.also__d{grid-column:1/-1;font-size:.88rem;color:var(--dim);line-height:1.55;max-width:60ch}
.also--save .also__p{color:var(--beam-text)}
.alsos__fine{margin-top:1.25rem;font-size:.86rem;color:var(--dim)}

@media(max-width:560px){
  .also{grid-template-columns:1fr auto}
}

/* The estimator runs on from the pricing section rather than opening its own.
   Same question, one step further in: the cards are the list price and this is
   yours. Presented as a separate section it read as being asked to consider
   the price twice. */
.section--joined{padding-top:0}
.pricenow{max-width:52ch;margin-bottom:clamp(1.5rem,3vw,2rem)}
.pricenow__h{font-family:var(--f-display);font-size:clamp(1.3rem,2.2vw,1.7rem);
  letter-spacing:-.03em;color:var(--paper);line-height:1.2}
.pricenow__p{margin-top:.5rem;font-size:.95rem;color:var(--dim);line-height:1.6}

/* A caption on each pair, naming the car and what was done to it. A wall of
   anonymous headlights is a stock-photo wall; the vehicle name is what makes
   somebody think "that is my car". Sits over the bottom of the frame so it
   does not cost the marquee any height. */
.shot__cap{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:1.6rem .85rem .7rem;
  display:grid;gap:.1rem;pointer-events:none;
  background:linear-gradient(transparent,rgba(0,0,0,.82) 55%)}
.shot__cap b{font-size:.85rem;font-weight:500;color:var(--paper);letter-spacing:-.01em}
.shot__cap span{font-size:.76rem;color:rgba(255,255,255,.62);line-height:1.35}
/* The hint sat in the same corner; move it up so they do not collide. */
.shot__hint{bottom:auto;top:.8rem;right:.8rem}

/* The one objection that stops somebody choosing: what if mine are too far
   gone. Answered beside the prices rather than in the small print, because
   small print reads as a disclaimer and this is meant to be reassurance. */
/* Two columns, because one was leaving the right half of a full-width box
   empty. The heading is short and the paragraph is long, so they sit beside
   each other rather than stacking into a narrow ribbon down the left. */
.promise{display:grid;grid-template-columns:minmax(0,15rem) minmax(0,1fr);
  align-items:start;gap:.75rem 2.5rem;
  margin-top:clamp(1.25rem,2.5vw,1.75rem);padding:1.35rem 1.5rem;
  border:1px solid rgba(57,211,83,.28);border-radius:var(--r-lg);
  background:rgba(57,211,83,.06)}
.promise__t{display:flex;align-items:flex-start;gap:.55rem;color:var(--paper);
  font-size:1.02rem;font-weight:500;letter-spacing:-.015em;line-height:1.35}
.promise__t svg{width:17px;height:17px;flex:none;margin-top:.18rem;color:#8fe3a0}
.promise__p{font-size:.93rem;color:var(--dim);line-height:1.65}
@media(max-width:760px){
  .promise{grid-template-columns:1fr;gap:.5rem}
}

/* A car row with nothing chosen yet is not being charged for, so it does not
   show a price. It used to show one, and the total in the bar included it. */
.car__amt.is-waiting{color:var(--dim);font-size:.85rem}

/* On anything with room, the disclosure is not a disclosure: the content is
   forced visible and the summary stops being a control. `open` cannot be
   taken off by CSS, so the panel starts closed and this opens it, rather
   than the other way round. */
@media(min-width:761px){
  .alsos > .alsos__list,
  .alsos > .alsos__fine{display:block}
  .alsos > .alsos__head{pointer-events:none;list-style:none}
  .alsos > .alsos__head::-webkit-details-marker{display:none}
}

/* The extras list on a phone. Five hundred pixels of things somebody can
   tick later, sitting between the prices and the rest of the page, on every
   page that carries a price list. It is a disclosure below 760px: the prices
   stay, the extras are one tap away, and the booking flow asks about every
   one of them regardless. */
@media(max-width:760px){
  .alsos{padding:0}
  .alsos__head{cursor:pointer;list-style:none;display:flex;align-items:center;gap:.5rem;
    padding:1rem .25rem;margin:0;font-size:1rem}
  .alsos__head::-webkit-details-marker{display:none}
  .alsos__head::after{content:'+';margin-left:auto;font-family:var(--f-display);
    color:var(--beam-text);font-size:1.2rem;line-height:1}
  .alsos[open] .alsos__head::after{content:'\2212'}
  /* `open` cannot be removed by CSS, so the panel is hidden by height
     instead and the summary toggles the class the browser already manages. */
  .alsos:not([open]) .alsos__list,
  .alsos:not([open]) .alsos__fine{display:none}
  .alsos__list{padding-bottom:.5rem}
}

/* ══════════════════════════════════════════════════════════
   PHONE
   Measured rather than guessed: every link, button and select
   on every page was checked at 390px against a 40px minimum,
   and the text against a 12px floor. What follows is what came
   back short.

   Most of it is padding on things that were the right size to
   read and the wrong size to hit. A footer link eighteen pixels
   tall is a link you miss twice before you get it.
   ══════════════════════════════════════════════════════════ */
@media(max-width:760px){

  /* Navigation and footer links: the text stays where it is, the
     target grows around it. */
  .ftr__nav ul,.ftr__sign ul{gap:.1rem}
  .ftr__nav a{display:inline-block;padding:.55rem 0;font-size:.95rem}
  .ftr__legal{gap:.4rem 1.1rem}
  .ftr__legal a{display:inline-block;padding:.5rem 0}
  .ftr__tel{padding:.5rem 0}
  .ftr__top-btn{width:44px;height:44px}
  .crumbs{font-size:.85rem}
  .crumbs a{display:inline-block;padding:.35rem 0}
  .logo{padding:.35rem 0}

  /* Chips are a list of places somebody taps to get to their own
     city, so they are a primary target, not decoration. */
  .chip{padding:.62rem 1rem;font-size:.9rem}

  /* Nothing under 12px. These were set small to sit quietly next to
     something larger, which works at arm's length on a desk and not
     at all on a phone. */
  .ftr h3{font-size:.78rem}
  .card__kicker{font-size:.75rem}
  .shot__hint{font-size:.75rem}
  .statement p.statement__by{font-size:.8rem}
  .sign__consent{font-size:.82rem}
  /* The box grew for the sake of a thumb and the nudge that lined it up with
     the old 14px box did not, so it sat two pixels low against its sentence. */
  .sign__consent input{width:18px;height:18px;margin-top:0}

  /* Buttons in the header. "Book Now" was 39px, which is under the
     thumb and over the line. */
  .btn{padding:.85rem 1.4rem;min-height:44px}
  .btn--sm{padding:.6rem 1rem;min-height:40px}

  /* The booking flow's own header. "Call us" was fifteen pixels tall,
     on the one screen where somebody stuck halfway through a form is
     most likely to want the phone. */
  .bhead__call{padding:.6rem .2rem}
  .bhead__call span{font-size:.9rem}

  /* Footer legal and contact links, which sit at the very bottom where a
     thumb is least accurate. Not prose links: those run inside a sentence,
     and vertical padding on an inline box overflows its line rather than
     growing it, so two links on consecutive lines were sitting on top of
     each other. Prose gets its target from the line height instead. */
  .ftr__legal a,.ftr__sign a{padding-block:.3rem}
  .prose a{padding-block:0}
  .prose{line-height:1.75}
}

/* The address under the phone in the footer. Same block the structured data
   carries, so the two cannot drift. */
.ftr__addr{margin-top:.85rem;font-style:normal;font-size:.85rem;color:var(--dim);
  line-height:1.6}
