/* Complete Waste Management Ltd — one stylesheet, no framework, no build step.

   LANE: the operator's rate card. The physical reference is the printed tariff a
   haulier hands you and the works docket that comes back signed — ruled tables,
   a masthead, packed columns, figures set in tabular numerals, evidence stapled
   to the back. Not a design portfolio piece and not a boutique.

   Everything here is DENSE ON PURPOSE. The previous build set the house
   minimalism (5rem headlines, 5.5rem section gaps, one idea per screen) and it
   read as a designer's page rather than as a company. Section gaps are down 38%,
   the h1 ceiling is down 33%, and every band now carries furniture: rules,
   tables, borders, columns.

   Colour is committed and it is HIS: both greens are sampled off his own logo
   masters, and the split between them is a measurement, not a preference.
   Ratios in the comments are computed, not estimated — see _audit/contrast.txt. */

/* ------------------------------------------------------------------ fonts */
@font-face{font-family:Anybody;src:url(/fonts/anybody.woff2)format('woff2');
  font-weight:100 900;font-style:normal;font-display:swap}
@font-face{font-family:Commissioner;src:url(/fonts/commissioner.woff2)format('woff2');
  font-weight:100 900;font-style:normal;font-display:swap}
/* size-adjusted fallbacks so the swap does not shove the layout */
@font-face{font-family:AnybodyFallback;src:local('Helvetica Neue'),local('Arial');
  size-adjust:92%;ascent-override:96%;descent-override:24%;line-gap-override:0%}
@font-face{font-family:CommissionerFallback;src:local('Helvetica Neue'),local('Arial');
  size-adjust:99%;ascent-override:97%;descent-override:26%;line-gap-override:0%}

/* ----------------------------------------------------------------- tokens */
:root{
  /* GROUND. Light-dominant, which is a deliberate break in two directions: four
     of the five reference sites John sent are green-on-dark, and four of the
     five Adamantine sites this one is measured against are dark-ground. It is
     also the register of the ONE page he actually sent when Cameron asked him
     dark or light (dunmowgroup.com, a light page).
     The tint is toward HIS green, not toward warm. Cream, sand, beige and paper
     are the saturated warm-neutral default and none of them is here. */
  --ground:#e9ece5;      /* green-tinted off-white */
  --ground-2:#dfe3d9;    /* banded rows, inset panels */
  --surface:#f8f9f6;     /* panels and cards sat on the ground */

  --dark:#111710;        /* masthead, footer, evidence bands. Green-black, never #000 */
  --dark-2:#1a2218;
  --dark-3:#263021;      /* borders and hovers on dark ONLY — see the note by --green-hi */

  /* INK. Measured against the grounds above. */
  --ink:#14180f;         /* 15.07:1 on ground · 17.02:1 on surface */
  --ink-muted:#464c40;   /*  7.43:1 on ground ·  8.39:1 on surface */
  --on-dark:#eef1ea;     /* 15.95:1 on dark */
  --on-dark-muted:#b4bdae;/*  9.39:1 on dark · 8.42:1 on dark-2 */

  /* HIS TWO GREENS, sampled off his own logo masters this session.
     #006800 is the dominant green of 064 and 065, the light-ground masters.
     #5ea21b is the dominant green of 063, the black-ground master.
     The split is not taste. It is these numbers:
       #006800 on --ground 5.90:1 PASS   ·  on --dark 2.58:1 FAIL
       #5ea21b on --dark   5.77:1 PASS   ·  on --ground 2.58:1 FAIL
     So: --green is a LIGHT-ground colour only, --green-hi is a DARK-ground
     colour only, and neither is ever used in the failing direction. --green-hi
     also measures 4.36:1 on --dark-3, under the 4.5 floor, so --dark-3 carries
     borders and hover states and never green text. */
  --green:#006800;
  --green-lift:#005400;  /* hover only, never text: 8.4:1 against white */
  --green-hi:#5ea21b;

  --rule:#c6cbc0;        /* hairline on light */
  --rule-2:#a8afa1;      /* the heavier rule: table heads, section heads */
  --rule-dark:#2c352a;

  --measure:68ch;
  --pad:clamp(1rem,3.4vw,2rem);
  --gap:clamp(2.1rem,4.2vw,3.4rem);   /* was 2.6-5.5rem. Density is the brief. */
  --gap-s:clamp(1.3rem,2.6vw,2rem);

  --ease:cubic-bezier(.22,1,.36,1);   /* ease-out-quart. No bounce anywhere. */

  --z-nav:40;--z-sub:45;--z-sticky:70;--z-bar:80;--z-skip:90;
}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--ground);color:var(--ink);
  font-family:Commissioner,CommissionerFallback,system-ui,sans-serif;
  font-size:clamp(.98rem,.95rem + .16vw,1.05rem);line-height:1.56;
  font-weight:400;letter-spacing:.001em;
  overflow-x:hidden;
}
img{max-width:100%;height:auto;display:block}
a{color:inherit}
:focus-visible{outline:3px solid var(--green);outline-offset:2px;border-radius:1px}
.on-dark :focus-visible,.mast :focus-visible,.nav :focus-visible,.ftr :focus-visible,
.topbar :focus-visible,.hero :focus-visible{outline-color:var(--green-hi)}

h1,h2,h3,h4,.dsp{
  font-family:Anybody,AnybodyFallback,system-ui,sans-serif;
  font-weight:750;line-height:1.06;letter-spacing:-.025em;
  text-wrap:balance;margin:0;
}
/* The h1 ceiling comes down from 5.1rem to 3.4rem. A 5rem headline is the single
   loudest thing that made the first build read as a portfolio piece. */
h1{font-size:clamp(2.05rem,1.42rem + 2.6vw,3.4rem)}
h2{font-size:clamp(1.4rem,1.2rem + .92vw,2.05rem)}
h3{font-size:clamp(1.06rem,.99rem + .34vw,1.28rem);letter-spacing:-.014em;font-weight:730}
h4{font-size:1rem;letter-spacing:-.008em;font-weight:730}
p{margin:0 0 .9em;max-width:var(--measure);text-wrap:pretty}
.lede{font-size:clamp(1.02rem,.98rem + .34vw,1.16rem);line-height:1.48;color:var(--ink-muted)}
.on-dark .lede{color:var(--on-dark-muted)}
strong,b{font-weight:640}

.wrap{width:min(80rem,100% - var(--pad)*2);margin-inline:auto}
.wrap-narrow{width:min(54rem,100% - var(--pad)*2);margin-inline:auto}
.band{padding-block:var(--gap)}
.band--tight{padding-block:var(--gap-s)}
.band--rule{border-top:1px solid var(--rule)}
.band--inset{background:var(--ground-2)}
.band--dark{background:var(--dark);color:var(--on-dark)}
.band--dark a{color:var(--on-dark)}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  clip-path:inset(50%);white-space:nowrap}
.num{font-variant-numeric:tabular-nums lining-nums;font-feature-settings:"tnum" 1,"lnum" 1}

.skip{position:absolute;left:-9999px;z-index:var(--z-skip)}
.skip:focus{left:.5rem;top:.5rem;position:fixed;background:var(--green);
  color:#fff;padding:.7rem 1.05rem;font-weight:700;border-radius:2px}

/* ================================================================ masthead */
/* Three stacked bars, which is what an established trade company looks like and
   what none of the five Adamantine sites has: a strip of standing detail, a
   sticky masthead carrying the number and the quote button, and a real
   navigation bar with two levels under it. */
/* Inside the <header>, so it is part of the banner landmark and sticks with it:
   the number is on screen at every scroll position, which is the whole reason a
   trade site has a bar like this. */
.topbar{background:var(--dark-2);color:var(--on-dark-muted);
  border-bottom:1px solid var(--rule-dark);font-size:.795rem;letter-spacing:.005em}
.topbar__in{display:flex;flex-wrap:wrap;gap:.25rem 1.2rem;align-items:center;
  justify-content:space-between;padding-block:.44rem;min-height:30px}
.topbar b{font-weight:600;color:var(--on-dark)}
.topbar ul{display:flex;flex-wrap:wrap;gap:.2rem 1.15rem;list-style:none;margin:0;padding:0}
.topbar a{text-decoration:none}
.topbar a:hover{color:var(--on-dark);text-decoration:underline}
.topbar__n{max-width:100%}
@media(max-width:47.99rem){
  /* On a phone the strip is one line carrying the number and nothing else: it is
     pinned, so every pixel of it is charged to the fold. The rest is in the footer. */
  .topbar__x,.topbar__n{display:none}
  .topbar__in{justify-content:flex-start;gap:.1rem .9rem;min-height:28px}
}

.mast{position:sticky;top:0;z-index:var(--z-sticky);background:var(--dark);
  color:var(--on-dark);border-bottom:1px solid var(--rule-dark)}
.mast__in{display:flex;align-items:center;gap:.7rem;justify-content:space-between;
  padding-block:.55rem}
.mast__logo{display:flex;align-items:center;min-height:44px;flex:0 1 auto;min-width:0}
.mast__logo img{width:auto;height:clamp(30px,6vw,44px)}
.mast__r{display:flex;align-items:center;gap:.5rem;flex:0 0 auto}
/* The number is set as a block of standing detail, not as a button: label above,
   figure below in tabular numerals. That is how it reads on a rate card. */
.mast__tel{display:none;text-decoration:none;line-height:1.12;padding-right:.15rem}
.mast__tel small{display:block;font-size:.7rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--on-dark-muted);font-weight:600}
.mast__tel span{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:760;
  font-size:1.24rem;letter-spacing:-.018em;color:var(--green-hi)}
.mast__tel:hover span{color:#79c02c}
@media(min-width:34rem){.mast__tel{display:block}}

/* ---------------------------------------------------------------- nav */
/* Two levels, and it runs on <details>. No JavaScript is involved anywhere in
   this navigation, so it opens with scripting off and it is keyboard-native. */
.nav{background:var(--dark-2);border-bottom:3px solid var(--green-hi);
  position:relative;z-index:var(--z-nav)}
.nav__bar{position:relative}
.nav__l1{display:flex;flex-wrap:wrap;list-style:none;margin:0;padding:0}
/* NOT position:relative below 48rem: the panel must anchor to .nav__bar and drop
   full width. Anchored to the item, it rendered as a 130px-wide column on a
   phone with every label wrapped to three lines. */
.nav__l1>li>a,.nav summary{
  display:flex;align-items:center;gap:.4rem;min-height:44px;
  padding:.5rem .85rem;color:var(--on-dark-muted);text-decoration:none;
  font-family:Anybody,AnybodyFallback,sans-serif;font-weight:640;
  font-size:.87rem;letter-spacing:-.005em;cursor:pointer;
  border-bottom:3px solid transparent;margin-bottom:-3px;
  transition:color .18s var(--ease),background .18s var(--ease)}
.nav__l1>li:first-child>a,.nav__l1>li:first-child>details>summary{padding-left:0}
@media(max-width:47.99rem){.nav__l1>li:first-child>a,
  .nav__l1>li:first-child>details>summary{padding-left:.85rem}}
.nav__l1>li>a:hover,.nav summary:hover{color:var(--on-dark);background:var(--dark-3)}
.nav__l1>li>a[aria-current=page]{color:var(--on-dark);border-bottom-color:var(--green-hi)}
.nav summary{list-style:none}
.nav summary::-webkit-details-marker{display:none}
.nav summary::after{content:"";width:.42rem;height:.42rem;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:rotate(45deg) translate(-1px,-1px);
  transition:transform .2s var(--ease);flex:0 0 auto}
.nav details[open]>summary{color:var(--on-dark);background:var(--dark-3)}
.nav details[open]>summary::after{transform:rotate(-135deg) translate(-2px,-2px)}

/* The panel is absolutely positioned, so nothing in its chain may clip it: the
   nav bar deliberately has no overflow set. On a phone it drops full width from
   the bar; from 48rem it hangs off its own item. */
.nav__sub{position:absolute;left:0;right:0;top:100%;z-index:var(--z-sub);
  background:var(--dark);border:1px solid var(--rule-dark);border-top:0;
  padding:.5rem;box-shadow:0 18px 40px -18px rgba(0,0,0,.85)}
.nav details[open]>.nav__sub{animation:navdrop .18s var(--ease) both}
@keyframes navdrop{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:none}}
.nav__cols{display:grid;gap:.5rem}
.nav__ch{margin:0 0 .25rem;padding:.4rem .75rem .3rem;font-family:Anybody,AnybodyFallback,sans-serif;
  font-size:.67rem;letter-spacing:.11em;text-transform:uppercase;font-weight:730;
  color:var(--on-dark-muted);border-bottom:1px solid var(--rule-dark);max-width:none}
.nav__sub ul{list-style:none;margin:0;padding:0;display:grid;gap:1px}
.nav__sub a{display:flex;align-items:center;padding:.62rem .75rem;text-decoration:none;
  color:var(--on-dark-muted);font-size:.9rem;line-height:1.3;min-height:44px;
  transition:background .16s var(--ease),color .16s var(--ease)}
.nav__sub a:hover,.nav__sub a:focus-visible{background:var(--dark-3);color:var(--on-dark)}
.nav__sub a b{font-weight:640;color:var(--on-dark)}
@media(min-width:48rem){
  .nav__l1>li{position:relative}
  .nav__sub{left:0;right:auto;min-width:19rem}
  .nav__sub--wide{min-width:36rem}
  .nav__sub--wide .nav__cols{grid-template-columns:1fr 1fr;gap:0 1.3rem}
  /* hover opens on a pointer device; the [open] state and :focus-within keep it
     working for keyboard and for touch */
  .nav__l1>li:hover>details>.nav__sub,
  .nav details:focus-within>.nav__sub{display:block}
  .nav details>.nav__sub{display:none}
  .nav details[open]>.nav__sub{display:block}
}

/* ------------------------------------------------------------------ hero */
/* Headline OVER the photograph on a measured gradient, per the house standard.
   What is NOT the house standard, and is the point: the tariff panel sits in the
   hero beside the headline, so his published prices are on screen at nought
   screens deep. Nobody in his reference set and nobody in this estate does that. */
.hero{position:relative;isolation:isolate;overflow:hidden;background:var(--dark)}
.hero__img{position:absolute;inset:0;z-index:-2}
.hero__img img{width:100%;height:100%;object-fit:cover;object-position:50% 58%}
/* Measured against the REAL pixels of the photograph, not guessed. The first
   pass ran to .94 across the whole frame and buried the photograph, which on
   this client is the product. It now runs strong only where type sits: on a
   phone that is a vertical scrim with the top left clear, and from 64rem a
   diagonal that opens out between the headline column and the tariff panel. */
/* The stops are in PIXELS, not percentages, because what has to be covered is a
   fixed distance: the headline box begins at the hero's padding-top and the
   scrim has to be opaque by then whatever the photograph or the hero height.
   The first pass used percentage stops, left the top of the frame at .22 alpha,
   and 11.78% of the pixels behind the home headline fell under the 3.0 floor
   against a white sky. Measured again in _audit/hero-contrast.txt: worst pixel
   on any of the eleven heroes is now well clear of it. */
.hero::after{content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to bottom,
    rgba(12,17,11,.30) 0,rgba(12,17,11,.55) 26px,rgba(12,17,11,.88) 54px,
    rgba(12,17,11,.90) 60%,rgba(12,17,11,.95) 100%)}
/* The HOME hero now carries the lockup, and the lockup starts higher up the frame
   than the headline ever did, so the ramp has to be finished sooner. .88 by 54px
   instead of 76px. The number is not a preference: his mark has three inks and the
   darkest of them, the shaded facet of the W and the M, measures 2.84:1 on the pure
   black of his own master and 2.46:1 on --dark where the masthead mark already
   ships. .88 by 54px is what puts the hero ground AT that 2.46 rather than under it.
   See _audit/mark-contrast.txt for all three inks at both widths. */
.hero--brand::after{background:linear-gradient(to bottom,
    rgba(12,17,11,.30) 0,rgba(12,17,11,.62) 30px,rgba(12,17,11,.93) 64px,
    rgba(12,17,11,.93) 260px,rgba(12,17,11,.86) 430px,
    rgba(12,17,11,.90) 62%,rgba(12,17,11,.95) 100%)}
@media(min-width:64rem){
  /* From 64rem the headline has its own column, so the scrim can open out to the
     right of it. It stays at or above .78 across the whole width the headline can
     occupy (17ch, so about 39% of the frame) and only then falls away. */
  .hero::after{background:
    linear-gradient(96deg,rgba(12,17,11,.95) 0%,rgba(12,17,11,.92) 30%,
      rgba(12,17,11,.86) 40%,rgba(12,17,11,.50) 50%,rgba(12,17,11,.24) 62%,
      rgba(12,17,11,.18) 82%,rgba(12,17,11,.30) 100%),
    linear-gradient(to top,rgba(12,17,11,.40) 0%,rgba(12,17,11,.06) 44%,
      rgba(12,17,11,0) 74%)}
}
.hero__in{padding-block:clamp(4.4rem,18vw,5.4rem) clamp(1.7rem,4.4vw,3rem);display:grid;gap:clamp(1.4rem,3vw,2.4rem);
  align-items:end;color:var(--on-dark)}
.hero h1{max-width:17ch;color:#fff}
.hero__lede{max-width:44ch;margin:.85rem 0 0;color:#dde3d9;
  font-size:clamp(1rem,.96rem + .34vw,1.14rem);line-height:1.46}
.hero__cta{display:flex;flex-wrap:wrap;gap:.55rem;margin-top:1.25rem}

/* --------------------------------------------------------- the hero lockup */
/* HIS MARK, MATTED, ON THE PHOTOGRAPH. The house standard, and the thing he
   pointed at. No plate, no box, no mount, no rounded card, no drop shadow doing
   a border's job: the photograph shows through the counter of the C and through
   the gaps in the wordmark, which is the whole point of matting it rather than
   sitting it on a chip.
   27rem is a ceiling, not a size. On a phone the mark takes the full text
   measure (358px inside the wrap at 390) and that is 1074 device pixels at DPR3,
   under the 1217 the matte actually has. It is never scaled up. */
.hero__mark{width:min(100%,27rem);margin:0 0 clamp(.9rem,3vw,1.3rem)}
.hero__mark img{width:100%;height:auto}
/* Under the mark the headline is the second voice, not a competing first one.
   The mark now says who; the headline only has to say what. */
.hero--brand h1{max-width:15ch;font-size:clamp(1.95rem,1.3rem + 2.9vw,3.1rem)}
.hero--brand .hero__lede{max-width:40ch;margin-top:.7rem}
.hero__alt{margin:.75rem 0 0;font-size:.9rem;color:#c8d0c4}
.hero__alt a{text-decoration:underline;text-underline-offset:.22em;
  text-decoration-color:rgba(255,255,255,.45)}
.hero__alt a:hover{text-decoration-color:var(--green-hi)}
.hero__meta{display:flex;flex-wrap:wrap;gap:.3rem 1.1rem;margin-top:1.2rem;padding-top:.9rem;
  border-top:1px solid rgba(255,255,255,.22);font-size:.83rem;color:#c8d0c4;
  list-style:none;padding-left:0}
.hero__meta li{display:flex;align-items:center;gap:.4rem}
.hero__meta li::before{content:"";width:.34rem;height:.34rem;background:var(--green-hi);
  flex:0 0 auto}
@media(min-width:64rem){
  .hero__in{grid-template-columns:minmax(0,1fr) 24.5rem;gap:2.6rem;
    padding-block:clamp(2.4rem,4vw,3.6rem)}
  .hero{min-height:33rem}
  /* the lockup takes the top of the headline column; the diagonal scrim already
     runs at .86 or better across the whole width that column can occupy */
  .hero--brand .hero__mark{margin-bottom:1.5rem}
  /* a town page has no tariff docked into it, so it stays one column and shorter */
  .hero--town .hero__in{grid-template-columns:minmax(0,44rem)}
  .hero--town{min-height:24rem}
}
.hero--town{min-height:17rem}
.hero--town .hero__img img{object-position:50% 50%}

/* ---------------------------------------------------------------- tariff */
/* His price list as a real table, in tabular numerals, on a white panel. The
   fill bar restates the word in the row name ("half load" = two of four) and is
   marked aria-hidden: it is not a volume claim and there are no cubic yards,
   no tonnages and no bag counts anywhere on this site. */
.tariff{background:var(--surface);border:1px solid var(--rule-2);color:var(--ink)}
.hero .tariff{box-shadow:0 26px 60px -26px rgba(0,0,0,.85);align-self:end}
.tariff__hd{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;
  padding:.75rem .95rem;background:var(--dark);color:var(--on-dark);flex-wrap:wrap}
.tariff__hd h2,.tariff__hd .dsp{font-size:1.02rem;letter-spacing:-.012em;color:#fff}
.tariff__hd span{font-size:.755rem;letter-spacing:.085em;text-transform:uppercase;
  color:var(--green-hi);font-weight:700}
table.tar{width:100%;border-collapse:collapse;font-size:.92rem}
table.tar caption{text-align:left;padding:.6rem .95rem 0;font-size:.8rem;color:var(--ink-muted)}
table.tar th,table.tar td{text-align:left;padding:.5rem .95rem;
  border-bottom:1px solid var(--rule);vertical-align:middle}
table.tar thead th{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:700;
  font-size:.7rem;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-muted);
  padding-block:.5rem;border-bottom:1px solid var(--rule-2);background:var(--ground-2)}
table.tar tbody th{font-weight:600}
table.tar tbody tr:last-child th,table.tar tbody tr:last-child td{border-bottom:0}
table.tar tbody tr:hover{background:var(--ground)}
/* ⚠ `table.tar td` is 0-1-2 and quietly beat this class's 0-1-0, so the load
   prices have been left-aligned in their column since 27 Aug. Type-qualified. */
.tar__p,table.tar td.tar__p,table.tar th.tar__p{text-align:right}
.tar__p{white-space:nowrap;font-family:Anybody,AnybodyFallback,sans-serif;
  font-weight:770;letter-spacing:-.02em;color:var(--green);
  font-size:clamp(1.06rem,1rem + .42vw,1.3rem)}
.tar__k{color:var(--ink-muted);font-size:.83rem;white-space:nowrap}
.tar__row{display:flex;align-items:center;gap:.6rem}
.fill{display:grid;grid-template-columns:repeat(4,.32rem);gap:2px;flex:0 0 auto}
.fill i{display:block;height:1.05rem;background:var(--rule);border-radius:1px}
.fill i.on{background:var(--green)}
.fill--none i{background:repeating-linear-gradient(45deg,var(--rule) 0 2px,transparent 2px 4px)}
/* The footer under the load prices. It was a flex row holding one button; since
   30 Aug it carries the calculator route as the primary action, because a man who
   has just read a number should not have to go looking for the thing that turns it
   into his number. Grid, not flex, so the three parts stack in a fixed order at
   every width instead of reflowing into a different reading order on a phone. */
.tariff__ft{padding:.75rem .95rem;border-top:1px solid var(--rule-2);background:var(--ground-2);
  display:grid;gap:.5rem;justify-items:start}
.tariff__ft p{margin:0;font-size:.82rem;color:var(--ink-muted);max-width:38ch}
/* p.tariff__go, not .tariff__go: `.tariff__ft p` above is (0,1,1) and was beating
   a bare (0,1,0) class, so max-width:38ch still applied and wrapped the two
   buttons onto separate lines. */
.tariff__ft p.tariff__go{display:flex;flex-wrap:wrap;gap:.45rem;max-width:none}
/* The honesty line, tied to the button above it. Smaller than the note but not
   small enough to read as a disclaimer nobody is meant to see. */
.tariff__cn{font-size:.775rem;line-height:1.5;max-width:46ch}
@media(max-width:29.99rem){
  table.tar th,table.tar td{padding-inline:.6rem}
  .tar__k{display:none}
  table.tar thead th:nth-child(2){display:none}
}

/* --------------------------------------------------------------- evidence */
/* NOT a badge row. Four statements a customer can check on this site inside a
   minute. There is no accreditation logo, no trust-platform mark, no star, no
   count-up statistic, because not one of those is evidenced for this client. */
.evid{display:grid;border:1px solid var(--rule-dark);border-bottom:0}
.evid>div{padding:.85rem 1rem;border-bottom:1px solid var(--rule-dark)}
.evid b{display:block;font-family:Anybody,AnybodyFallback,sans-serif;font-weight:730;
  font-size:.97rem;letter-spacing:-.012em;color:var(--green-hi);margin-bottom:.16rem}
.evid p{margin:0;font-size:.855rem;color:var(--on-dark-muted);max-width:34ch}
.evid--light{border-color:var(--rule);background:var(--surface)}
.evid--light>div{border-bottom-color:var(--rule)}
.evid--light b{color:var(--green)}
.evid--light p{color:var(--ink-muted)}
.evid--light a{color:var(--ink);text-decoration:underline;text-underline-offset:2px}
.evid--light a:hover{color:var(--green)}
@media(min-width:38rem){.evid--light>div:nth-child(odd){border-right-color:var(--rule)}}
@media(min-width:66rem){.evid--light>div{border-right-color:var(--rule)}}
@media(min-width:38rem){.evid{grid-template-columns:1fr 1fr}
  .evid>div:nth-child(odd){border-right:1px solid var(--rule-dark)}}
@media(min-width:66rem){.evid{grid-template-columns:repeat(4,1fr)}
  .evid>div{border-right:1px solid var(--rule-dark)}
  .evid>div:last-child{border-right:0}}

/* --------------------------------------------------------- section header */
/* Heading left, the section's own action right, one rule under both. A document
   heading, not a tracked-caps eyebrow: there is no kicker above any section on
   this site. */
.shead{display:flex;flex-wrap:wrap;gap:.5rem 1.5rem;align-items:baseline;
  justify-content:space-between;border-bottom:2px solid var(--rule-2);
  padding-bottom:.55rem;margin-bottom:var(--gap-s)}
.band--dark .shead{border-bottom-color:var(--rule-dark)}
.shead p{margin:0;font-size:.9rem;color:var(--ink-muted);max-width:52ch}
.band--dark .shead p{color:var(--on-dark-muted)}
.shead a{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:700;font-size:.87rem;
  color:var(--green);text-decoration:none;border-bottom:1px solid currentColor;
  padding-bottom:1px;white-space:nowrap}
.band--dark .shead a{color:var(--green-hi)}
.shead a:hover{color:var(--ink)}
.band--dark .shead a:hover{color:#fff}
.shead__t{display:grid;gap:.3rem}

/* ------------------------------------------------------------------ buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.45rem;
  min-height:48px;padding:.72rem 1.25rem;border-radius:2px;text-decoration:none;
  font-family:Anybody,AnybodyFallback,sans-serif;font-weight:730;font-size:.96rem;
  letter-spacing:-.012em;border:1px solid transparent;cursor:pointer;
  transition:background .2s var(--ease),border-color .2s var(--ease),color .2s var(--ease)}
.btn--primary{background:var(--green);color:#fff}      /* 7.05:1 */
.btn--primary:hover{background:var(--green-lift)}
.btn--onDark{background:var(--green-hi);color:#0d120c}  /* 5.77:1 */
.btn--onDark:hover{background:#6fb92a}
.btn--ghost{border-color:var(--rule-2);color:var(--ink);background:var(--surface)}
.btn--ghost:hover{border-color:var(--green);color:var(--green)}
.btn--ghostDark{border-color:rgba(255,255,255,.4);color:#fff;background:rgba(12,17,11,.35)}
.btn--ghostDark:hover{border-color:var(--green-hi);background:rgba(12,17,11,.6)}
.btn--wa{background:var(--surface);border-color:var(--rule-2);color:var(--ink)}
.btn--wa:hover{border-color:var(--green);color:var(--green)}
.btn--sm{min-height:42px;padding:.5rem .95rem;font-size:.88rem}
.btn--block{width:100%}

/* ------------------------------------------------------ the "cleared" record */
/* One large AFTER frame with the BEFORE inset in its corner. Two <img> tags and a
   caption: nothing to degrade with JS off, nothing to operate by keyboard.
   Packed three across on a wide screen rather than one enormous frame per
   scroll, which is where the first build lost the room. */
.records{display:grid;gap:0;border-top:1px solid var(--rule);border-left:1px solid var(--rule);
  list-style:none;margin:0;padding:0}
@media(min-width:44rem){.records{grid-template-columns:1fr 1fr}}
@media(min-width:70rem){.records--3{grid-template-columns:repeat(3,1fr)}}
.record{background:var(--surface);display:flex;flex-direction:column;
  border-right:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.band--dark .records,.band--dark .record{border-color:var(--rule-dark)}
.band--dark .record{background:var(--dark-2);color:var(--on-dark)}
.record__frame{position:relative;background:var(--ground-2);overflow:hidden}
.band--dark .record__frame{background:var(--dark-3)}
.record__after img{width:100%;aspect-ratio:4/3;object-fit:cover}
.record__before{position:absolute;right:0;bottom:0;width:38%;max-width:12.5rem;
  border-left:2px solid var(--surface);border-top:2px solid var(--surface);
  background:var(--surface)}
.band--dark .record__before{border-color:var(--dark-2);background:var(--dark-2)}
.record__before img{width:100%;aspect-ratio:4/3;object-fit:cover}
.record__tag{position:absolute;right:0;bottom:0;font-size:.63rem;letter-spacing:.11em;
  text-transform:uppercase;font-weight:700;background:var(--surface);color:var(--ink-muted);
  padding:.2rem .45rem;font-family:Anybody,AnybodyFallback,sans-serif;
  border-left:1px solid var(--rule);border-top:1px solid var(--rule)}
.band--dark .record__tag{background:var(--dark-2);color:var(--on-dark-muted);
  border-color:var(--rule-dark)}
.record__cap{padding:.8rem .95rem 1rem;display:grid;gap:.45rem;flex:1}
.record__svc{font-family:Anybody,AnybodyFallback,sans-serif;font-size:.7rem;
  letter-spacing:.1em;text-transform:uppercase;font-weight:700;color:var(--green);margin:0}
.band--dark .record__svc{color:var(--green-hi)}
.record__cap h3,.record__cap h2{font-size:1.04rem;letter-spacing:-.014em}
.record__dl{margin:0;display:grid;grid-template-columns:auto 1fr;gap:.22rem .7rem;
  font-size:.85rem;border-top:1px solid var(--rule);padding-top:.55rem;margin-top:.15rem}
.band--dark .record__dl{border-top-color:var(--rule-dark)}
.record__dl dt{font-weight:640;color:var(--ink-muted);white-space:nowrap}
.band--dark .record__dl dt{color:var(--on-dark-muted)}
.record__dl dd{margin:0;color:var(--ink-muted);max-width:46ch}
.band--dark .record__dl dd{color:var(--on-dark-muted)}

/* ---------------------------------------------------------------- steps */
/* A real four-step sequence, numbered because the order is the information the
   reader needs. It is the only numbered list on the site and it is an <ol>. */
.steps{list-style:none;counter-reset:s;margin:0;padding:0;display:grid;
  border-top:1px solid var(--rule)}
.steps li{counter-increment:s;display:grid;grid-template-columns:2.3rem 1fr;
  gap:.2rem .95rem;padding:.95rem 0;border-bottom:1px solid var(--rule)}
.band--dark .steps,.band--dark .steps li{border-color:var(--rule-dark)}
.steps li::before{content:counter(s,decimal-leading-zero);grid-row:1 / span 2;
  font-family:Anybody,AnybodyFallback,sans-serif;font-weight:760;font-size:1.02rem;
  color:var(--green);border:1px solid var(--rule-2);width:2.3rem;height:2.3rem;
  display:grid;place-items:center;font-variant-numeric:tabular-nums}
.band--dark .steps li::before{color:var(--green-hi);border-color:var(--rule-dark)}
.steps h3{font-size:1rem}
.steps p{margin:.18rem 0 0;font-size:.885rem;color:var(--ink-muted);max-width:56ch}
.band--dark .steps p{color:var(--on-dark-muted)}
@media(min-width:60rem){
  .steps{grid-template-columns:repeat(4,1fr);border-top:0;
    border-left:1px solid var(--rule)}
  .band--dark .steps{border-left-color:var(--rule-dark)}
  .steps li{border-bottom:0;border-right:1px solid var(--rule);padding:1.1rem 1.1rem 1.3rem;
    grid-template-columns:1fr;gap:.55rem}
  .band--dark .steps li{border-right-color:var(--rule-dark)}
  .steps li::before{grid-row:auto}
}

/* ------------------------------------------------------------ situations */
/* Split by what the customer turned up to, not by the trade's own categories.
   Every row is here because at least one of the twelve photographed job pairs
   carries that tag, so each one is backed by two frames of it. */
.sit{width:100%;border-collapse:collapse;font-size:.93rem;
  border:1px solid var(--rule);background:var(--surface)}
.sit caption{text-align:left;padding:0 0 .55rem;font-size:.86rem;color:var(--ink-muted)}
.sit th,.sit td{text-align:left;padding:.7rem .9rem;border-bottom:1px solid var(--rule);
  vertical-align:top}
.sit thead th{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:700;font-size:.7rem;
  letter-spacing:.09em;text-transform:uppercase;color:var(--ink-muted);
  background:var(--ground-2);border-bottom:1px solid var(--rule-2);padding-block:.5rem}
.sit tbody th{font-weight:660;white-space:nowrap;font-size:.95rem}
.sit tbody tr:last-child th,.sit tbody tr:last-child td{border-bottom:0}
.sit td{color:var(--ink-muted)}
.sit a{color:var(--green);white-space:nowrap;font-weight:600}

/* --- the photograph on every row ------------------------------------------
   The caption over this table promises a photograph of one of his own jobs on
   every line. Until 30 Aug the row answered that with the words "See it". The
   frame now sits in the cell that used to hold only the link, so the "Shown"
   column shows something and the whole cell is one target.
   The column is sized to the image rather than the other way round: 132 CSS px
   on the table, 104 on a phone, both declared in the <picture> `sizes` so the
   browser fetches a 200/280/400 rendition and never the 640. */
/* The photograph makes the row about 150px tall. With the cells still top-aligned
   that left roughly 90px of empty space under a one-line description on every row,
   which is the white space this build is supposed to be removing rather than
   adding. Centring the words against the frame turns eight ragged rows into eight
   bands. `top` stays on the header row so the column labels sit on the rule. */
.sit tbody th,.sit tbody td{vertical-align:middle}
.sit__shot{width:1%;padding-left:.7rem;padding-block:.55rem}
.sit__a{display:block;width:132px;text-decoration:none}
.sit__f{position:relative;display:block;border:1px solid var(--rule);
  background:var(--ground-2);overflow:hidden}
/* aspect-ratio, not the intrinsic height, so eight portrait phone photographs
   make one straight column instead of eight different heights. The width and
   height attributes are still on the <img> for the browser's own ratio guess,
   so nothing shifts if the stylesheet is slow. */
.sit__img{display:block;width:100%;height:auto;aspect-ratio:4/3;object-fit:cover}
/* Same chip as the one on the before/after records, so the site reads as one
   thing. aria-hidden in the markup: the alt text already says "After". */
.sit__tag{position:absolute;right:0;bottom:0;font-size:.63rem;letter-spacing:.09em;
  text-transform:uppercase;font-weight:700;background:var(--surface);color:var(--ink-muted);
  padding:.12rem .32rem;font-family:Anybody,AnybodyFallback,sans-serif;
  border-left:1px solid var(--rule);border-top:1px solid var(--rule)}
.sit__see{display:block;margin-top:.34rem;font-size:.85rem;font-weight:600;
  color:var(--green);text-decoration:underline;text-underline-offset:2px}
.sit__a:hover .sit__see{text-decoration-thickness:2px}
.sit__a:hover .sit__f{border-color:var(--green)}
@media(max-width:39.99rem){
  /* caption MUST be in this list. A <caption> keeps display:table-caption when
     its table is switched to block and collapses to min-content: on a phone it
     rendered one word per line. */
  .sit,.sit caption,.sit tbody,.sit tr,.sit th,.sit td{display:block;width:100%}
  .sit thead{display:none}
  .sit tbody tr{border-bottom:1px solid var(--rule);padding:.7rem .9rem}
  .sit tbody tr:last-child{border-bottom:0}
  .sit th,.sit td{border:0;padding:0}
  .sit tbody th{margin-bottom:.15rem}
  /* The row becomes a two-track grid rather than a stack: the photograph sits
     beside the words instead of under them. Stacking eight full-width frames
     would add roughly 1800px of scroll to the homepage for no extra
     information. Explicit placement, so the photograph leads the row visually
     while the DOM order stays name, description, photograph. */
  .sit tbody tr{display:grid;grid-template-columns:104px 1fr;
    column-gap:.8rem;row-gap:.2rem;align-items:start}
  .sit tbody th{grid-column:2;grid-row:1;width:auto;white-space:normal}
  .sit tbody td{grid-column:2;grid-row:2;width:auto}
  .sit tbody td.sit__shot{grid-column:1;grid-row:1/span 2;width:auto;padding-left:0}
  .sit__a{width:104px}
  .sit__see{white-space:nowrap}
}

/* ------------------------------------------------------------------- FAQ */
/* Native <details>. Opens with JavaScript off and it is keyboard-native.
   There is no "are you licensed" and no "are you insured" question here, and
   that absence is deliberate: see the note in _build/data.py. */
.faq{border:1px solid var(--rule);background:var(--surface);max-width:56rem}
.faq details{border-bottom:1px solid var(--rule)}
.faq details:last-child{border-bottom:0}
.faq summary{display:flex;align-items:flex-start;gap:.8rem;padding:.85rem .95rem;
  cursor:pointer;list-style:none;font-family:Anybody,AnybodyFallback,sans-serif;
  font-weight:700;font-size:.99rem;letter-spacing:-.012em;min-height:48px;
  transition:background .16s var(--ease)}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{background:var(--ground)}
.faq summary::after{content:"";margin-left:auto;flex:0 0 auto;width:.65rem;height:.65rem;
  border-right:2px solid var(--green);border-bottom:2px solid var(--green);
  transform:rotate(45deg);margin-top:.42rem;transition:transform .22s var(--ease)}
.faq details[open]>summary{background:var(--ground-2)}
.faq details[open]>summary::after{transform:rotate(-135deg);margin-top:.62rem}
.faq .faq__a{padding:0 .95rem 1rem;animation:faqin .22s var(--ease) both}
.faq .faq__a p{margin:0;font-size:.92rem;color:var(--ink-muted);max-width:64ch}
@keyframes faqin{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}

/* --------------------------------------------------------------- the form */
/* The card is FIRST in the DOM and therefore first in the grid, so visual order,
   document order and focus order are the same thing. There is no `order`
   property anywhere in this stylesheet. */
.quote{background:var(--dark);color:var(--on-dark);border-block:1px solid var(--rule-dark)}
.quote__grid{display:grid;gap:clamp(1.5rem,3.4vw,2.6rem)}
@media(min-width:58rem){.quote__grid{grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr)}}
.card{background:var(--surface);color:var(--ink);border:1px solid var(--rule-2);
  padding:clamp(1.1rem,3.2vw,1.75rem)}
.card h2{font-size:clamp(1.35rem,1.15rem + .8vw,1.85rem)}
.card>p{color:var(--ink-muted);font-size:.93rem}
.field{display:grid;gap:.28rem;margin-bottom:.8rem}
.field label{font-weight:620;font-size:.865rem;color:var(--ink)}
.field .req{color:var(--green);font-weight:700}
.field input,.field textarea{
  font:inherit;font-size:1rem;padding:.7rem .8rem;min-height:48px;
  border:1px solid var(--rule-2);border-radius:2px;background:#fff;color:var(--ink);
  width:100%;transition:border-color .18s var(--ease),box-shadow .18s var(--ease)}
.field textarea{min-height:96px;resize:vertical}
.field input::placeholder,.field textarea::placeholder{color:#5b6157}
.field input:focus,.field textarea:focus{border-color:var(--green);
  box-shadow:0 0 0 3px rgba(0,104,0,.2);outline:none}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.form__note{font-size:.83rem;color:var(--ink-muted);margin:.7rem 0 0;max-width:none}
.quote__aside h2{font-size:clamp(1.2rem,1.1rem + .55vw,1.5rem);margin-bottom:.7rem;color:#fff}
.quote__aside ul{list-style:none;padding:0;margin:0 0 1.1rem;display:grid;gap:0;
  border-top:1px solid var(--rule-dark)}
.quote__aside li{padding:.6rem 0;border-bottom:1px solid var(--rule-dark);
  color:var(--on-dark-muted);font-size:.9rem;max-width:46ch}
.quote__ct{display:grid;gap:.5rem}
@media(min-width:26rem){.quote__ct{grid-template-columns:1fr 1fr}}

/* ---------------------------------------------------------------- pieces */
.cols{display:grid;gap:clamp(1.4rem,3.2vw,2.4rem)}
@media(min-width:52rem){.cols--2{grid-template-columns:1fr 1fr}
  .cols--side{grid-template-columns:minmax(0,1.35fr) minmax(0,1fr)}}
.rule{border:0;border-top:1px solid var(--rule);margin:var(--gap-s) 0}
.band--dark .rule{border-top-color:var(--rule-dark)}

.svc{border-top:1px solid var(--rule);padding-top:1rem;margin-top:1rem}
.svc:first-of-type{border-top:0;margin-top:0;padding-top:0}
.svc ul,.ticks{margin:.7rem 0 0;padding:0;list-style:none;display:grid;gap:.34rem}
.ticks li{position:relative;padding-left:1.05rem;color:var(--ink-muted);font-size:.92rem}
.ticks li::before{content:"";position:absolute;left:0;top:.55em;width:.4rem;height:.4rem;
  background:var(--green)}
.band--dark .ticks li{color:var(--on-dark-muted)}
.band--dark .ticks li::before{background:var(--green-hi)}

/* Two up on a phone. That is denser, which is the brief, and it also stops ten
   town photographs being fetched at 1280px for a card 359px wide: /where-we-work
   was pulling 1.6 MB of them. */
.towns{display:grid;gap:0;border-top:1px solid var(--rule);border-left:1px solid var(--rule);
  grid-template-columns:repeat(auto-fit,minmax(9.5rem,1fr));list-style:none;padding:0;margin:0}
@media(min-width:40rem){.towns{grid-template-columns:repeat(auto-fit,minmax(13rem,1fr))}}
.town{background:var(--surface);border-right:1px solid var(--rule);
  border-bottom:1px solid var(--rule)}
.town a{display:grid;text-decoration:none;height:100%;
  transition:background .2s var(--ease)}
.town a:hover{background:var(--ground)}
.town img{width:100%;aspect-ratio:16/9;object-fit:cover}
.town__b{padding:.6rem .7rem .75rem;display:grid;gap:.08rem}
@media(min-width:40rem){.town__b{padding:.7rem .85rem .85rem}}
.town__b span{font-size:.65rem;letter-spacing:.07em;text-transform:uppercase;
  color:var(--green);font-weight:700;font-family:Anybody,AnybodyFallback,sans-serif}
.town__b strong{font-family:Anybody,AnybodyFallback,sans-serif;font-size:1rem;
  font-weight:740;letter-spacing:-.02em;line-height:1.1}
@media(min-width:40rem){.town__b strong{font-size:1.1rem}}
.town__b em{font-style:normal;font-size:.8rem;color:var(--ink-muted)}

.linkcols{list-style:none;padding:0;margin:0;display:grid;gap:0;
  border-top:1px solid var(--rule);border-left:1px solid var(--rule);
  grid-template-columns:repeat(auto-fit,minmax(13.5rem,1fr))}
.linkcols li{background:var(--surface);border-right:1px solid var(--rule);
  border-bottom:1px solid var(--rule)}
.linkcols a{display:flex;align-items:center;min-height:46px;padding:.55rem .8rem;
  text-decoration:none;font-size:.9rem;transition:background .18s var(--ease)}
.linkcols a:hover{background:var(--ground);color:var(--green)}

.figure img{width:100%;border:1px solid var(--rule)}
.figure figcaption,.credit{font-size:.75rem;color:var(--ink-muted);margin:.45rem 0 0;
  line-height:1.42;max-width:60ch}
.band--dark .credit{color:var(--on-dark-muted)}
.credit a{color:inherit}
.ledger{font-size:.78rem;color:var(--ink-muted);line-height:1.5;padding-left:1.1rem}
.ledger li{margin-bottom:.35rem}
.prose,.narrow{max-width:56rem}
.prose h2{margin-top:1.6rem}
.prose h2:first-child{margin-top:0}
.prose .lede,.prose p{max-width:64ch}

/* ------------------------------------------------------------ mobile bar */
.callbar{position:fixed;left:0;right:0;bottom:0;z-index:var(--z-bar);display:flex;
  gap:1px;background:var(--rule-dark);border-top:1px solid var(--rule-dark)}
.callbar a{flex:1;display:flex;align-items:center;justify-content:center;gap:.4rem;
  min-height:54px;text-decoration:none;font-family:Anybody,AnybodyFallback,sans-serif;
  font-weight:730;font-size:.96rem;background:var(--dark);color:var(--on-dark)}
.callbar a.is-call{background:var(--green-hi);color:#0d120c}
@media(min-width:58rem){.callbar{display:none}}
@media(max-width:57.99rem){body{padding-bottom:55px}}

/* ----------------------------------------------------------------- footer */
/* Four columns, the standing detail, and a legal line. The company's registered
   number and registered-office address are deliberately NOT here — see the
   handback. */
.ftr{background:var(--dark);color:var(--on-dark-muted);border-top:3px solid var(--green-hi);
  padding-block:clamp(2rem,4.5vw,3rem);font-size:.885rem}
.ftr__grid{display:grid;gap:1.7rem}
@media(min-width:44rem){.ftr__grid{grid-template-columns:1fr 1fr}}
@media(min-width:66rem){.ftr__grid{grid-template-columns:1.5fr 1fr 1fr 1.15fr}}
.ftr h2{font-size:.78rem;letter-spacing:.1em;text-transform:uppercase;color:var(--on-dark);
  font-family:Anybody,AnybodyFallback,sans-serif;font-weight:730;margin-bottom:.65rem;
  padding-bottom:.45rem;border-bottom:1px solid var(--rule-dark)}
.ftr ul{list-style:none;padding:0;margin:0;display:grid;gap:.32rem}
.ftr a{color:var(--on-dark-muted);text-decoration:none}
.ftr a:hover{color:var(--on-dark);text-decoration:underline}
.ftr img{height:40px;width:auto;margin-bottom:.8rem}
.ftr__blurb{max-width:34ch;margin-bottom:.9rem;font-size:.86rem}
.ftr__tel{display:block;font-family:Anybody,AnybodyFallback,sans-serif;font-weight:760;
  font-size:1.3rem;letter-spacing:-.02em;color:var(--green-hi);text-decoration:none;
  margin-bottom:.3rem}
.ftr__legal{border-top:1px solid var(--rule-dark);margin-top:1.8rem;padding-top:1rem;
  font-size:.775rem;display:flex;flex-wrap:wrap;gap:.4rem 1.3rem;align-items:center}

/* ----------------------------------------------------------------- motion */
/* One deliberate entrance, on the hero, staggered across the three things it
   reveals. Nothing on this site is gated behind a scroll observer: a reveal that
   needs a failsafe is a band that can ship blank, and on the first build it did
   exactly that under an instant-jump capture. Everything below the fold is
   simply visible. The rest of the motion is interaction feedback — the nav
   panel, the FAQ answer, hovers — which only ever runs on a user action. */
.hero__mark,.hero h1,.hero__lede,.hero__cta,.hero__meta,.hero__alt{animation:rise .7s var(--ease) both}
.hero h1{animation-delay:.07s}
.hero__lede{animation-delay:.13s}
.hero__cta{animation-delay:.19s}
.hero__meta,.hero__alt{animation-delay:.25s}
@keyframes rise{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-delay:0ms!important;
    animation-iteration-count:1!important;transition-duration:.001ms!important}
  .hero__mark,.hero h1,.hero__lede,.hero__cta,.hero__meta,.hero__alt{animation:none;opacity:1;transform:none}
}

/* ==========================================================================
   THE BOOKING TOOL  (/book)
   Same lane as the rest of the site: the works docket. Ruled rows, tabular
   figures, a numbered sequence, real borders. Nothing here introduces a second
   visual system — every colour, rule and radius is a token already defined
   above, and there is not a single new font size that is not on the same scale.

   Built for a thumb at 390px first. The item rows are 48px targets, the
   stepper buttons are 44px, and the running total is welded to the bottom of
   the screen where the thumb already is.
   ========================================================================== */

/* --- the two doors ------------------------------------------------------- */
.doors__g{display:grid;gap:1px;background:var(--rule-2);border:1px solid var(--rule-2)}
@media(min-width:46rem){.doors__g{grid-template-columns:1fr 1fr}}
.door{background:var(--surface);padding:1.15rem 1.1rem 1.25rem}
.door--b{background:var(--ground-2)}
.door__k{font-family:Anybody,AnybodyFallback,sans-serif;font-size:.7rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink-muted);font-weight:700;margin:0 0 .3rem}
.door h3{font-size:clamp(1.12rem,1.02rem + .5vw,1.34rem);margin:0 0 .4rem}
.door p{margin:0 0 .85rem;font-size:.92rem;color:var(--ink-muted);max-width:44ch}
.door__n{font-size:.85rem;margin:.6rem 0 0}

/* --- the picker ---------------------------------------------------------- */
.pick__find{margin:0 0 1.1rem;max-width:26rem}
.pick__find label{display:block;font-weight:620;font-size:.865rem;margin-bottom:.28rem}
.pick__find input{font:inherit;font-size:1rem;padding:.7rem .8rem;min-height:48px;width:100%;
  border:1px solid var(--rule-2);border-radius:2px;background:#fff;color:var(--ink)}
.pick__find input:focus{border-color:var(--green);box-shadow:0 0 0 3px rgba(0,104,0,.2);
  outline:none}
.pick__fn{font-size:.82rem;color:var(--ink-muted);margin:.35rem 0 0}

.pick__cols{display:grid;gap:1px;background:var(--rule);border:1px solid var(--rule-2)}
@media(min-width:52rem){.pick__cols{grid-template-columns:1fr 1fr}}
@media(min-width:74rem){.pick__cols{grid-template-columns:1fr 1fr 1fr}}
.pick__g{background:var(--surface);padding:.9rem 0 .3rem}
.pick__gh{font-size:.78rem;letter-spacing:.085em;text-transform:uppercase;font-weight:700;
  color:var(--ink);margin:0 .95rem .15rem;font-family:Anybody,AnybodyFallback,sans-serif}
.pick__h{margin:0 .95rem .5rem;font-size:.82rem;color:var(--ink-muted);max-width:40ch}
.pick__l{list-style:none;margin:.45rem 0 0;padding:0}
.pick__row{display:flex;align-items:center;justify-content:space-between;gap:.7rem;
  padding:.3rem .95rem;min-height:48px;border-top:1px solid var(--rule)}
.pick__row:has(.pick__q:focus-visible){background:var(--ground)}
.pick__lb{font-size:.92rem;line-height:1.3;flex:1 1 auto;cursor:pointer}
.pick__st{display:flex;align-items:center;gap:.2rem;flex:0 0 auto}
.pick__b{width:38px;height:38px;flex:0 0 auto;border:1px solid var(--rule-2);background:#fff;
  color:var(--ink);font:inherit;font-size:1.15rem;line-height:1;border-radius:2px;
  cursor:pointer;display:grid;place-items:center;
  transition:border-color .15s var(--ease),color .15s var(--ease)}
.pick__b:hover{border-color:var(--green);color:var(--green)}
.pick__q{width:3.1rem;height:38px;text-align:center;font:inherit;font-size:1rem;
  font-variant-numeric:tabular-nums;border:1px solid var(--rule-2);border-radius:2px;
  background:#fff;color:var(--ink);-moz-appearance:textfield}
.pick__q::-webkit-outer-spin-button,.pick__q::-webkit-inner-spin-button{
  -webkit-appearance:none;margin:0}
.pick__q:focus{border-color:var(--green);box-shadow:0 0 0 3px rgba(0,104,0,.2);outline:none}
/* A row with something in it is marked, so a long list can be scanned back. */
.pick__row:has(.pick__q:not([value="0"])){background:var(--ground)}

/* --- the answer ---------------------------------------------------------- */
.ans__grid{display:grid;gap:var(--gap-s)}
@media(min-width:56rem){.ans__grid{grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  align-items:start}}
.ans__box{background:var(--surface);border:1px solid var(--rule-2)}
.ans__hd{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;
  padding:.75rem .95rem;background:var(--dark);color:var(--on-dark);flex-wrap:wrap}
.ans__hd h2{font-size:1.02rem;letter-spacing:-.012em;color:#fff;margin:0}
.ans__hd span{font-size:.755rem;letter-spacing:.085em;text-transform:uppercase;
  color:var(--green-hi);font-weight:700}
.ans__body{padding:1rem .95rem}
.ans__empty{margin:0;color:var(--ink-muted);font-size:.92rem;max-width:46ch}
.ans__size{margin:0;font-family:Anybody,AnybodyFallback,sans-serif;font-weight:700;
  font-size:clamp(1.3rem,1.1rem + 1vw,1.7rem);letter-spacing:-.02em;line-height:1.1}
.ans__price{margin:.1rem 0 0;font-family:Anybody,AnybodyFallback,sans-serif;font-weight:800;
  letter-spacing:-.025em;color:var(--green);font-variant-numeric:tabular-nums;
  font-size:clamp(2rem,1.5rem + 2.4vw,2.9rem);line-height:1}
.ans__alt{margin:.7rem 0 0;padding:.7rem 0 0;font-size:.87rem;color:var(--ink-muted);
  max-width:52ch;border-top:1px solid var(--rule)}
.ans__list{list-style:none;margin:.9rem 0 0;padding:.7rem 0 0;border-top:1px solid var(--rule)}
.ans__list li{display:flex;justify-content:space-between;gap:1rem;padding:.28rem 0;
  font-size:.88rem;border-bottom:1px solid var(--rule)}
.ans__list li:last-child{border-bottom:0}
.ans__list b{font-variant-numeric:tabular-nums;color:var(--ink-muted)}
.ans__ft{padding:.7rem .95rem;border-top:1px solid var(--rule-2);background:var(--ground-2)}
.ans__ft p{margin:0;font-size:.83rem;color:var(--ink-muted)}
.ans__side h3{font-size:.78rem;letter-spacing:.085em;text-transform:uppercase;
  font-family:Anybody,AnybodyFallback,sans-serif;margin:0 0 .5rem;
  padding-bottom:.4rem;border-bottom:1px solid var(--rule-2)}
.ans__side h3+ul{margin:0 0 1.3rem}
.ans__cav{list-style:none;margin:0;padding:0}
.ans__cav li{font-size:.87rem;color:var(--ink-muted);padding:.42rem 0 .42rem .95rem;
  border-bottom:1px solid var(--rule);position:relative;max-width:52ch}
.ans__cav li:last-child{border-bottom:0}
.ans__cav li::before{content:"";position:absolute;left:0;top:.95em;width:.42rem;height:1px;
  background:var(--green)}

/* --- day and window ------------------------------------------------------ */
.when__grid{display:grid;gap:var(--gap-s)}
/* ⚠ A grid item is min-width:auto by default, so the horizontally scrolling day
   strip below would stretch its own column and push the whole PAGE sideways
   instead of scrolling inside itself. Caught at 390 and 768 by the overflow
   gate. Every grid on this page gets the same treatment. */
.when__grid>*,.ans__grid>*,.who__grid>*,.doors__g>*{min-width:0}
@media(min-width:56rem){.when__grid{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}}
.when__lb{font-family:Anybody,AnybodyFallback,sans-serif;font-size:.78rem;letter-spacing:.085em;
  text-transform:uppercase;font-weight:700;margin:0 0 .5rem;padding-bottom:.4rem;
  border-bottom:1px solid var(--rule-2)}
.when__days{display:flex;gap:.4rem;overflow-x:auto;max-width:100%;padding-bottom:.5rem;
  scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch}
.when__days:empty{display:none}
.day{flex:0 0 auto;width:4.1rem;min-height:68px;scroll-snap-align:start;
  border:1px solid var(--rule-2);background:var(--surface);color:var(--ink);
  border-radius:2px;cursor:pointer;font:inherit;padding:.45rem .2rem;display:grid;
  gap:.05rem;place-items:center;transition:border-color .15s var(--ease)}
.day em{font-style:normal;font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-muted)}
.day strong{font-family:Anybody,AnybodyFallback,sans-serif;font-size:1.25rem;line-height:1;
  font-variant-numeric:tabular-nums}
.day span{font-size:.72rem;color:var(--ink-muted)}
.day:hover{border-color:var(--green)}
.day.is-on{background:var(--dark);border-color:var(--dark);color:var(--on-dark)}
.day.is-on em,.day.is-on span{color:var(--green-hi)}
.when__fallback label{display:block;font-weight:620;font-size:.865rem;margin-bottom:.28rem}
.when__fallback input{font:inherit;font-size:1rem;padding:.7rem .8rem;min-height:48px;
  border:1px solid var(--rule-2);border-radius:2px;background:#fff;color:var(--ink);
  width:100%;max-width:16rem}
.when__fallback input:focus{border-color:var(--green);box-shadow:0 0 0 3px rgba(0,104,0,.2);
  outline:none}
.when__n{font-size:.83rem;color:var(--ink-muted);margin:.6rem 0 0;max-width:46ch}
.wins{display:grid;gap:.4rem}
.win{display:block;border:1px solid var(--rule-2);background:var(--surface);border-radius:2px;
  cursor:pointer;transition:border-color .15s var(--ease)}
.win span{display:grid;gap:.1rem;padding:.7rem .85rem;min-height:56px;align-content:center}
.win strong{font-size:.96rem}
.win em{font-style:normal;font-size:.83rem;color:var(--ink-muted)}
.win input{position:absolute;opacity:0;width:1px;height:1px}
.win:hover{border-color:var(--green)}
.win:has(input:checked){border-color:var(--green);box-shadow:inset 3px 0 0 var(--green)}
.win:has(input:focus-visible){box-shadow:0 0 0 3px rgba(0,104,0,.2)}
.win.is-gone{opacity:.55;cursor:not-allowed}
.win__gone{display:block;font-size:.78rem;color:var(--ink-muted);letter-spacing:.06em;
  text-transform:uppercase;font-weight:700}

/* --- the details, on the dark band --------------------------------------- */
.who__grid{display:grid;gap:var(--gap-s)}
@media(min-width:56rem){.who__grid{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr)}}
.band--dark .field label,.band--dark .field legend{color:var(--on-dark)}
.band--dark .field .req{color:var(--green-hi)}
.band--dark .field input,.band--dark .field textarea{background:var(--dark-2);
  border-color:var(--dark-3);color:var(--on-dark)}
.band--dark .field input::placeholder,.band--dark .field textarea::placeholder{
  color:var(--on-dark-muted)}
.band--dark .field input:focus,.band--dark .field textarea:focus{border-color:var(--green-hi);
  box-shadow:0 0 0 3px rgba(94,162,27,.28)}
.field--set{border:0;padding:0;margin:0 0 .8rem;min-width:0}
.field--set legend{font-weight:620;font-size:.865rem;padding:0;margin-bottom:.4rem}
.accs{display:grid;gap:.35rem}
@media(min-width:34rem){.accs{grid-template-columns:1fr 1fr}}
.acc{display:flex;align-items:center;gap:.55rem;min-height:44px;padding:.35rem .7rem;
  border:1px solid var(--dark-3);background:var(--dark-2);border-radius:2px;cursor:pointer;
  font-size:.88rem}
.acc input{width:20px;height:20px;flex:0 0 auto;accent-color:var(--green-hi)}
.acc:has(input:checked){border-color:var(--green-hi)}
.acc:has(input:focus-visible){box-shadow:0 0 0 3px rgba(94,162,27,.28)}
.who__a h3{font-size:.78rem;letter-spacing:.085em;text-transform:uppercase;
  font-family:Anybody,AnybodyFallback,sans-serif;margin:0 0 .6rem;padding-bottom:.4rem;
  border-bottom:1px solid var(--rule-dark)}
.who__ol{margin:0 0 1rem;padding-left:1.1rem}
.who__ol li{margin-bottom:.4rem;color:var(--on-dark-muted);font-size:.92rem}
.who__p{font-size:.88rem;color:var(--on-dark-muted);max-width:44ch}

/* --- confirm and send ---------------------------------------------------- */
.sum{border:1px solid var(--rule-2);background:var(--surface);margin-bottom:1rem}
table.sum__t{width:100%;border-collapse:collapse;font-size:.92rem}
table.sum__t th,table.sum__t td{text-align:left;padding:.55rem .85rem;
  border-bottom:1px solid var(--rule);vertical-align:top}
table.sum__t th{font-weight:620;color:var(--ink-muted);width:9.5rem}
table.sum__t tr:last-child th,table.sum__t tr:last-child td{border-bottom:0}
.sum__ns{font-size:.9rem;color:var(--ink-muted);margin:0 0 1rem}
.sendfail{margin-top:1rem;border:1px solid var(--rule-2);border-left:3px solid var(--green);
  background:var(--surface);padding:.85rem .95rem}
.sendfail p{margin:0 0 .5rem;font-size:.9rem}
.sendfail p:last-child{margin-bottom:0}
.done{background:var(--ground-2);border-top:1px solid var(--rule-2)}
.done h2{margin:0 0 .3rem}
.done:focus{outline:none}
.done__ref{font-family:Anybody,AnybodyFallback,sans-serif;font-size:1.05rem;margin:0 0 1rem;
  color:var(--ink-muted)}
.done .btn{margin-right:.5rem;margin-top:.5rem}

/* --- the running total, welded to the thumb ------------------------------ */
.bkbar{position:sticky;bottom:0;z-index:var(--z-bar);background:var(--dark);
  border-top:1px solid var(--dark-3);color:var(--on-dark)}
.bkbar__in{width:min(80rem,100% - var(--pad)*2);margin-inline:auto;display:flex;
  align-items:center;justify-content:space-between;gap:.8rem;padding:.55rem 0;min-height:56px}
.bkbar__t{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:700;font-size:1rem;
  letter-spacing:-.015em;font-variant-numeric:tabular-nums}
/* The site's own call bar is fixed to the bottom below 58rem and is 55px tall,
   so the running total stacks on top of it rather than fighting it for the same
   strip. The breakpoint MUST match .callbar's or they overlap. */
@media(max-width:57.99rem){.bkbar{bottom:55px}}

/* This hero carries no photograph, so it needs none of the top padding the
   photo heroes use to clear their scrim. Density is the brief. */
.hero--book{min-height:0;background:var(--dark);color:var(--on-dark)}
.hero--book .hero__in{padding-block:clamp(1.5rem,5vw,2.4rem) clamp(1.3rem,3.4vw,2rem)}
.hero--book::after{display:none}
.hero--book h1{color:#fff}
.hero--book .hero__lede{color:var(--on-dark-muted);max-width:56ch}

@media(prefers-reduced-motion:reduce){
  .day,.win,.pick__b,.field input,.field textarea{transition:none}
}

/* Focus, said out loud. The site's text fields signal focus with a border
   change plus a soft ring; the booking tool's own controls (day chips, window
   cards, steppers, search) get a hard 2px offset outline as well, because a
   ring alone at 20% alpha is not enough to find your place in a 56-row list
   with a keyboard. Never `outline:none` without something louder in its place. */
.day:focus-visible,.pick__b:focus-visible,.pick__q:focus-visible,
.win:has(input:focus-visible),#pick-find:focus-visible,.acc:has(input:focus-visible),
.bkbar .btn:focus-visible,.door .btn:focus-visible{
  outline:2px solid var(--green);outline-offset:2px}
.band--dark .acc:has(input:focus-visible),.bkbar .btn:focus-visible{
  outline-color:var(--green-hi)}

/* ===========================================================================
   HIS COLLECTION TARIFF — 30 Aug 2026
   33 real, odd, specific figures. What reads as an established contractor in
   this trade is DENSITY: a published tariff you can scan, not three rounded
   numbers with air around them. So this is deliberately tight, in ruled
   columns, and it holds at 390 without a horizontal scroll because the tables
   are one label plus one figure and nothing else.
   =========================================================================== */
.itar{background:var(--surface);border:1px solid var(--rule-2);color:var(--ink)}
.itar__hd{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;
  padding:.75rem .95rem;background:var(--dark);color:var(--on-dark);flex-wrap:wrap}
.itar__hd h2{font-size:1.02rem;letter-spacing:-.012em;color:#fff;margin:0}
.itar__hd span{font-size:.755rem;letter-spacing:.085em;text-transform:uppercase;
  color:var(--green-hi);font-weight:700}
/* His printed caveat. Directly under the heading, on its own ground, never a
   footnote: it is the line that stops somebody reading a £100 sofa as the price
   of emptying a house. */
.itar__cav{margin:0;padding:.6rem .95rem;background:var(--ground-2);max-width:none;
  border-bottom:1px solid var(--rule-2);font-size:.85rem;color:var(--ink);font-weight:560}
.itar__cav>span{display:block;max-width:74ch}
.itar__g{display:grid;gap:1px;background:var(--rule)}
@media(min-width:34rem){.itar__g{grid-template-columns:1fr 1fr}}
@media(min-width:62rem){.itar__g{grid-template-columns:1fr 1fr 1fr}}
.itar__c{background:var(--surface);padding:.85rem 0 .5rem;min-width:0}
.itar__h{font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;font-weight:700;
  font-family:Anybody,AnybodyFallback,sans-serif;color:var(--ink-muted);
  margin:0 .95rem .35rem}
table.itar__t{width:100%;border-collapse:collapse;font-size:.9rem;table-layout:fixed}
table.itar__t th,table.itar__t td{text-align:left;padding:.34rem .95rem;
  border-bottom:1px solid var(--rule);vertical-align:baseline}
table.itar__t tbody th{font-weight:500;overflow-wrap:anywhere}
table.itar__t tbody tr:last-child th,table.itar__t tbody tr:last-child td{border-bottom:0}
table.itar__t tbody tr:hover{background:var(--ground)}
.itar__p,table.itar__t td.itar__p{text-align:right}
.itar__p{white-space:nowrap;width:5.6rem;
  font-family:Anybody,AnybodyFallback,sans-serif;font-weight:770;letter-spacing:-.02em;
  color:var(--green);font-size:1.02rem}
.itar__p em{display:block;font-style:normal;font-weight:500;font-size:.66rem;
  letter-spacing:.02em;color:var(--ink-muted);font-family:inherit}
/* The extras get their own block with a rule above it, so nobody reads the
   call-out as the price of a footstool. */
.itar__x{border-top:1px solid var(--rule-2);background:var(--ground-2);padding:.85rem 0 .6rem}
.xt{list-style:none;margin:0;padding:0}
.xt li{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding:.45rem .95rem;border-bottom:1px solid var(--rule)}
.xt li:last-child{border-bottom:0}
.xt__n{font-size:.9rem;font-weight:560;min-width:0}
.xt__n em{display:block;font-style:normal;font-weight:400;font-size:.8rem;
  color:var(--ink-muted);margin-top:.1rem}
.xt__p{white-space:nowrap;font-family:Anybody,AnybodyFallback,sans-serif;font-weight:770;
  letter-spacing:-.02em;color:var(--green);font-size:1.02rem}
.xt__p em{display:block;font-style:normal;font-weight:500;font-size:.66rem;
  color:var(--ink-muted);font-family:inherit}
.itar__ft{padding:.75rem .95rem;border-top:1px solid var(--rule-2);background:var(--surface);
  display:grid;gap:.6rem}
.itar__ft p{margin:0;font-size:.83rem;color:var(--ink-muted);max-width:74ch}
.itar__ft p:last-child{display:flex;flex-wrap:wrap;gap:.5rem;max-width:none}
@media(max-width:24.99rem){
  table.itar__t th,table.itar__t td{padding-inline:.65rem}
  .xt li{padding-inline:.65rem}
  .itar__h{margin-inline:.65rem}
  .itar__cav{padding-inline:.65rem}
  .itar__p{width:4.9rem}
}

/* ---------------------------------------------- his prices inside the picker */
.pick__lb{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem}
.pick__p{flex:0 0 auto;font-family:Anybody,AnybodyFallback,sans-serif;font-weight:750;
  letter-spacing:-.015em;color:var(--green);font-size:.9rem;font-variant-numeric:tabular-nums}
.pick__p em{font-style:normal;font-weight:500;font-size:.66rem;color:var(--ink-muted);
  font-family:inherit}
/* An item John has never named carries no figure and says why. A silent blank
   reads as an oversight; an invented number is worse than either. */
.pick__p--load{font-family:inherit;font-weight:400;font-size:.72rem;color:var(--ink-muted);
  letter-spacing:.01em}
.pick__cav{margin:0 0 1rem;padding:.6rem .8rem;background:var(--ground-2);
  border:1px solid var(--rule-2);font-size:.85rem;max-width:64ch}

/* --------------------------------------------------- the house clearance ask */
.clr{margin:0 0 1rem;border:1px solid var(--rule-2);background:var(--ground-2)}
.clr__lb{display:flex;align-items:flex-start;gap:.6rem;padding:.7rem .8rem;cursor:pointer;
  min-height:44px}
.clr__lb input{flex:0 0 auto;width:20px;height:20px;margin-top:.12rem;accent-color:var(--green)}
.clr__lb span{font-size:.88rem;line-height:1.4}
.clr__lb em{display:block;font-style:normal;font-size:.8rem;color:var(--ink-muted);
  margin-top:.15rem}
.clr:has(input:checked){border-color:var(--green);background:var(--surface)}
.clr:has(input:focus-visible){box-shadow:0 0 0 3px rgba(0,104,0,.2)}
.ans__noprice{margin:.1rem 0 0;font-family:Anybody,AnybodyFallback,sans-serif;font-weight:800;
  letter-spacing:-.022em;color:var(--green);font-size:clamp(1.5rem,1.2rem + 1.6vw,2rem);
  line-height:1.05}

/* ------------------------------------------------------------- the extras */
/* John's own ask, 28 Aug, sending the Clearabee flow: "Click on the loads then
   extra charges come up." So they appear here, beside the price, as the job is
   built. Nothing is added for the customer: the ULEZ line is a question about
   their own address and the dismantling is a count they choose. */
.xtra{margin:1rem 0 0;padding:.8rem 0 0;border-top:1px solid var(--rule-2)}
.xtra__h{font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;font-weight:700;
  font-family:Anybody,AnybodyFallback,sans-serif;color:var(--ink-muted);margin:0 0 .4rem}
.xtra__l{list-style:none;margin:0;padding:0}
.xtra__r{display:flex;align-items:flex-start;justify-content:space-between;gap:.8rem;
  padding:.5rem 0;border-bottom:1px solid var(--rule)}
.xtra__r:last-child{border-bottom:0}
.xtra__n{display:flex;align-items:flex-start;gap:.55rem;font-size:.87rem;min-width:0;
  line-height:1.35}
label.xtra__n{cursor:pointer;min-height:44px;align-items:center}
.xtra__n input{flex:0 0 auto;width:20px;height:20px;accent-color:var(--green)}
.xtra__n em{display:block;font-style:normal;font-size:.78rem;color:var(--ink-muted);
  margin-top:.12rem}
.xtra__p{flex:0 0 auto;white-space:nowrap;font-family:Anybody,AnybodyFallback,sans-serif;
  font-weight:750;letter-spacing:-.015em;color:var(--green);font-size:.94rem}
.xtra__p em{font-style:normal;font-weight:500;font-size:.66rem;color:var(--ink-muted);
  font-family:inherit}
.xtra__q{display:flex;align-items:center;gap:.45rem;flex:0 0 auto}
.xtra__r:has(input:checked),.xtra__r:has(.pick__q:not([value="0"])){background:var(--ground)}
/* The second line under the price. A charge somebody only meets at the end is
   the thing this tool exists to stop, so it is on the same screen as the price
   and it is always a "from", because his call-out is a floor. */
.ans__from{margin:.85rem 0 0;padding:.6rem .7rem;background:var(--ground-2);
  border:1px solid var(--rule-2);font-size:.87rem;line-height:1.45}
.ans__from strong{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:800;
  letter-spacing:-.015em;color:var(--green);font-size:1.02rem}
.ans__cavl{margin:.7rem 0 0;font-size:.82rem;color:var(--ink-muted);max-width:52ch}

/* ==========================================================================
   THE TOOL'S OWN SURFACE — 30 August 2026
   ==========================================================================
   Cameron's note: "it is all the same colour as well, we want it to stand out,
   i know it is meant to match the theme but still, we need to outline it, it is
   a serious tool". Both halves of that are true and they do not conflict.

   So this introduces a LEVEL, not a palette. Every colour below is already a
   token: --dark for the rail, --surface for the plate, --ground-2 for the ground
   it sits on, --green for state. What is new is the STACK — a dark rail over a
   white plate with a hard 2px edge, sitting on the inset ground, with the page
   ground outside that again. Four planes, so a person can see where the
   instrument starts and stops.

   ⛔ No gradient, no glow, no drop shadow doing a border's job, no card grid of
   identical tiles, no eyebrow label. Definition here is edge, weight and space.
   -------------------------------------------------------------------------- */
.tool{padding-block:var(--gap-s)}
.tool__plate{background:var(--surface);border:2px solid var(--ink);
  /* The one shadow in the file, and it is a hard offset rather than a blur:
     it reads as a plate resting on the ground, not as a floating card. */
  box-shadow:4px 4px 0 var(--rule-2)}

/* The rail. The instrument's nameplate and its contents list. */
.tool__rail{background:var(--dark);color:var(--on-dark);padding:.7rem var(--pad) .55rem;
  border-bottom:2px solid var(--ink)}
.tool__ttl{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:750;font-size:.95rem;
  letter-spacing:-.01em;margin:0 0 .5rem;color:#fff}
.tool__nav{list-style:none;display:flex;flex-wrap:wrap;gap:.2rem .35rem;margin:0;padding:0;
  counter-reset:none}
.tool__nav a{display:inline-flex;align-items:center;gap:.4rem;padding:.42rem .6rem;
  min-height:38px;color:var(--on-dark-muted);text-decoration:none;font-size:.83rem;
  border:1px solid transparent;transition:color .18s var(--ease),border-color .18s var(--ease)}
.tool__nav a:hover{color:#fff;border-color:var(--dark-3)}
.tool__rn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;
  flex:0 0 auto;border:1px solid var(--on-dark-muted);font-family:Anybody,AnybodyFallback,sans-serif;
  font-weight:700;font-size:.72rem;line-height:1}
.tool__nav a:hover .tool__rn{border-color:var(--green-hi);color:var(--green-hi)}

/* A step. Ruled off from the one above it, numbered, on the plate. */
.tstep{border-top:1px solid var(--rule-2)}
.tstep:first-of-type{border-top:0}
.tstep__hd{display:flex;align-items:flex-start;gap:.75rem;padding:1rem var(--pad) .7rem;
  border-bottom:1px solid var(--rule)}
.tstep__n{flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  width:30px;height:30px;border:2px solid var(--ink);background:var(--ground-2);
  font-family:Anybody,AnybodyFallback,sans-serif;font-weight:800;font-size:.98rem;
  line-height:1;color:var(--ink)}
.tstep__t{flex:1 1 auto;min-width:0}
.tstep__t h2{font-size:clamp(1.04rem,.98rem + .4vw,1.22rem);letter-spacing:-.014em;margin:0;
  padding-top:.14rem}
.tstep__b{margin:.35rem 0 0;font-size:.88rem;color:var(--ink-muted);max-width:60ch}
.tstep__chip{flex:0 0 auto;align-self:flex-start;margin-top:.2rem;
  font-size:.7rem;letter-spacing:.085em;text-transform:uppercase;font-weight:700;
  font-family:Anybody,AnybodyFallback,sans-serif;color:var(--ink-muted);
  border:1px solid var(--rule-2);padding:.24rem .45rem;background:var(--ground-2)}
.tstep__body{padding:1rem var(--pad) 1.15rem}
.tstep--ans{background:var(--ground-2)}
.tstep--send .tstep__body{max-width:44rem}

/* -------------------------------------------------------- the picked state
   ⭐ SELECTION IS CARRIED BY FOUR SIGNALS, never by a faint tint alone: a hard
   2px outline round the whole row, the label going bold, the icon going green,
   and the count showing as a filled badge. `data-on` is kept in sync by the
   script; the stylesheet used to test the input's `value` ATTRIBUTE, which the
   steppers never wrote, so nothing ever highlighted at all. */
.pick__row[data-on]:not([data-on="0"]){background:#fff;
  outline:2px solid var(--green);outline-offset:-2px;position:relative;z-index:1}
.pick__row[data-on]:not([data-on="0"]) .pick__nm{font-weight:700}
.pick__row[data-on]:not([data-on="0"]) .ico{color:var(--green)}
.pick__row[data-on]:not([data-on="0"]) .pick__q{border-color:var(--green);
  background:var(--green);color:#fff;font-weight:700}

/* -------------------------------------------------------------- the icons */
.ico{flex:0 0 auto;width:26px;height:26px;color:var(--ink-muted);
  stroke:currentColor;fill:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;
  transition:color .18s var(--ease)}
.pick__row:hover .ico{color:var(--ink)}
.pick__nm{flex:1 1 auto;min-width:0}
/* The label was a baseline flex row of two children. It is three now, and the
   icon has to sit centred against the name rather than on its baseline. */
.pick__lb{align-items:center;gap:.65rem}
.itar__t .ico{width:22px;height:22px;margin-right:.5rem;vertical-align:-.42rem}

/* ------------------------------------------------ the running answer, docked
   It was a mobile-only strip carrying a load name. It is the running answer
   now, at every width, because if somebody has to scroll to find out what they
   are being quoted the tool has failed at the only job it has. */
.dock{position:sticky;bottom:0;z-index:var(--z-bar);background:var(--dark);
  border-top:2px solid var(--green-hi);color:var(--on-dark)}
.dock__in{width:min(80rem,100% - var(--pad)*2);margin-inline:auto;display:flex;
  align-items:center;gap:.7rem;padding:.5rem 0;min-height:58px}
.dock__c{flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  min-width:28px;height:28px;padding:0 .35rem;background:var(--green-hi);color:#0d120c;
  font-family:Anybody,AnybodyFallback,sans-serif;font-weight:800;font-size:.9rem;
  font-variant-numeric:tabular-nums}
.dock__c:empty{display:none}
.dock__t{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;line-height:1.2}
.dock__t em{font-style:normal;font-size:.78rem;color:var(--on-dark-muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dock__t strong{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:800;
  font-size:1.08rem;letter-spacing:-.018em;color:#fff;font-variant-numeric:tabular-nums}
.dock__t strong:empty{display:none}
.dock .btn{flex:0 0 auto}
/* The site's own call bar is fixed to the bottom below 58rem and is 55px tall,
   so the dock stacks on top of it rather than fighting it for the same strip.
   The breakpoint MUST match .callbar's or they overlap. */
@media(max-width:57.99rem){.dock{bottom:55px}}
.dock .btn:focus-visible{outline:2px solid var(--green-hi);outline-offset:2px}

/* --------------------------------------------------------- plate at width */
@media(min-width:58rem){
  .tool__rail{display:flex;align-items:center;justify-content:space-between;gap:1rem;
    padding-block:.5rem}
  .tool__ttl{margin:0}
  .tstep--ans .tstep__body.ans__grid{grid-template-columns:1.35fr .85fr;gap:1.6rem}
}
@media(max-width:33rem){
  .tool__plate{box-shadow:3px 3px 0 var(--rule-2)}
  .tstep__hd{padding-inline:.85rem}.tstep__body{padding-inline:.85rem}
  .tool__rail{padding-inline:.85rem}
}

/* -------------------------------------------------- the picked row, at width
   The row was a baseline flex of name and price fighting the steppers for a
   390px line, so "Cardboard boxes (about ten)" wrapped to four lines. It is a
   grid now: the icon spans both rows on the left, the name sits over the price
   on the right. That is the shape of John's own tiles, and it gives the name
   the whole column back. */
.pick__lb{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;
  column-gap:.6rem;row-gap:.05rem;justify-content:start}
.pick__lb .ico{grid-row:1 / span 2;grid-column:1}
.pick__nm{grid-column:2;grid-row:1;font-weight:500}
.pick__p{grid-column:2;grid-row:2;text-align:left}
.pick__p--load{font-size:.7rem;color:var(--ink-muted);letter-spacing:.005em}
.pick__row{gap:.5rem;padding-inline:.85rem}
/* Give the name back the width the steppers were taking. 44px stays the touch
   floor on the buttons; only the number field narrows. */
.pick__st{gap:.15rem}
.pick__b{width:36px;height:44px}
.pick__q{width:2.5rem;height:44px}

/* -------------------------------------------------- the route into the tool
   ⚠ THE PHONE IS NOT TOUCHED by any of this. It keeps first position in the
   sticky bar and it keeps the loud green. What is new here is a THIRD cell, so
   the tool is reachable from any page without hunting for it. */
.callbar a.is-call{flex:1.25}
@media(max-width:22rem){.callbar a{font-size:.82rem;padding-inline:.3rem}}

/* The tool's own block in the enquiry aside. It was the third ghost button
   under a photo pitch, which is the footnote treatment this run exists to undo.
   Bounded and on the accent edge, so it reads as its own offer rather than as
   one more link in a stack. */
/* ⚠ This was `rgba(94,162,27,.09)` over --dark. It LOOKED right and it measured
   at 1.63:1, because a translucent ground cannot be computed from declared
   values: the contrast pass reads the first non-transparent background it
   finds, which is the raw green, not the composite. A colour whose real ratio
   cannot be computed has no business on a page this file governs, so it is a
   solid token. --on-dark-muted on --dark-2 is 8.42:1 and is written down in the
   token block at the top of this file. */
.quote__tool{border:1px solid var(--green-hi);background:var(--dark-2);
  padding:.9rem 1rem 1rem;margin:0 0 1.4rem}
.quote__tool h2{margin:0 0 .45rem;font-size:clamp(1.06rem,1rem + .4vw,1.24rem)}
.quote__tool p{margin:0 0 .9rem;font-size:.9rem;color:var(--on-dark-muted);max-width:46ch}
.quote__tool .btn{margin:0}
/* A two-line item name wrapped back under its own icon. The row header is a
   flex line now, so the name indents against the icon like every other list
   on the site. */
.itar__t th{display:flex;align-items:flex-start;gap:.5rem}
.itar__t .ico{width:22px;height:22px;margin:0;vertical-align:baseline;
  position:relative;top:.05rem}
.itar__t th>span{flex:1 1 auto;min-width:0}

/* ------------------------------------------------- step 4, relit for the plate
   ⚠ REAL REGRESSION, caught by axe and fixed rather than excused. "Your details"
   used to be a `band--dark` section of its own; on the plate it is a light step,
   so the access-note chips were still painting a dark-2 ground under inherited
   --ink text. Ten serious colour-contrast violations, all of them here.

   The "what happens next" aside stays dark ON PURPOSE. It is the one inset panel
   inside the plate and it gives the instrument an interior rhythm rather than
   five identical white steps stacked up. --on-dark-muted is correct against it,
   which is why those rules are left alone. */
.acc{border-color:var(--rule-2);background:var(--ground-2);color:var(--ink)}
.acc input{accent-color:var(--green)}
.acc:has(input:checked){border-color:var(--green);background:#fff}
.acc:has(input:focus-visible){box-shadow:0 0 0 3px rgba(0,104,0,.22)}
.tstep .acc:has(input:focus-visible){outline:2px solid var(--green);outline-offset:2px}

.who__a{background:var(--dark);color:var(--on-dark);padding:1rem 1.05rem 1.1rem;
  border:1px solid var(--rule-dark);align-self:start}
.who__a h3{color:#fff}
.who__a a{color:var(--green-hi)}
.who__a a:hover{color:#fff}

/* ------------------------------------------------- the time window, restated
   Two problems, both real.

   1. Selection was a border colour plus `inset 3px 0 0` — a left side-stripe,
      which is on the banned list in WEB-STANDARDS §9 and is exactly the "faint
      tint alone" this run exists to stop. It is a full 2px outline, a white
      ground and a weight change now: three signals, same as the picker rows, so
      the tool has ONE selected state rather than two.
   2. The unavailable window hid behind `opacity:.55`, which drags the "gone"
      text to about 2.7:1. Disabled text is exempt from 1.4.3, but this text is
      the thing telling you WHY you cannot have that window, so it is given a
      real ground and a real colour instead of being faded out. */
.win:has(input:checked){border-color:var(--green);box-shadow:none;
  outline:2px solid var(--green);outline-offset:-2px;background:#fff}
.win:has(input:checked) strong{font-weight:750}
.win.is-gone{opacity:1;background:var(--ground-2);border-color:var(--rule);
  cursor:not-allowed}
.win.is-gone strong,.win.is-gone em,.win.is-gone .win__gone{color:var(--ink-muted)}

/* ==========================================================================
   GOOGLE REVIEWS  ·  #google-reviews / .grw
   --------------------------------------------------------------------------
   28 reviews, all five star, and none of them were on his site. This is the
   strongest single fact on the page, so it gets an instrument of its own
   rather than a row of quote cards.

   THE REGISTER. Same furniture as the booking tool, one plane shallower:
     page ground     --ground     #e9ece5
     the band        --ground-2   #dfe3d9    the panel sits in an inset
     the plate       --surface    #f8f9f6    2px --ink edge + hard 4px offset
     the entries     #fff                    1px ruled, white, like a docket
   Three planes, so it reads as something set into the page rather than as
   another section of it. The only shadow is a hard offset, same as .tool__plate.

   ⛔ No gradient, no glow, no shadow doing a border's job, no grid of identical
   tiles (it is a track that moves, not a wall), no eyebrow label. Definition is
   edge, weight and space.

   ⭐ It ships HIDDEN. /api/reviews reveals it and nothing else does, so a missing
   key, a listing that is not his, an API failure, an empty feed or scripting
   turned off all leave the page exactly as it was.
   ========================================================================== */
#google-reviews[hidden]{display:none !important}

.grw{background:var(--surface);border:2px solid var(--ink);
  box-shadow:4px 4px 0 var(--rule-2);
  padding:clamp(1rem,2.4vw,1.6rem)}

/* ------------------------------------------------------------------- head */
.grw__head{display:flex;align-items:center;gap:.75rem 1rem;flex-wrap:wrap;
  border-bottom:2px solid var(--ink);padding-bottom:.9rem;margin-bottom:1.1rem}
/* square box, so the official mark can never be stretched by the flex row */
.grw__g{width:40px;height:40px;flex:0 0 40px}

.grw__agg{display:flex;align-items:center;gap:.7rem;margin:0;
  font-size:inherit;line-height:1}
.grw__agg b{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:750;
  font-size:clamp(2rem,1.6rem + 1.4vw,2.6rem);line-height:.9;letter-spacing:-.02em;
  color:var(--ink)}
.grw__meta{display:block}
/* Google's own star gold is #FBBC04 and it measures 1.71:1 on white, which is
   nowhere near the AA floor. #a85f00 is the same warm gold two stops down and
   measures 4.88:1 on #fff and 4.62:1 on --surface, so it passes as TEXT and no
   "it is only decorative" argument has to be made for it. */
.grw__stars{display:block;color:#a85f00;font-size:1.02rem;line-height:1.1;
  letter-spacing:.13em}
/* the headline half of "5.0 from 28 Google reviews": ink, not a muted caption */
.grw__count{display:block;margin-top:.22rem;color:var(--ink);font-weight:600;
  font-size:.93rem;letter-spacing:-.005em}

.grw__act{margin-left:auto;display:flex;align-items:center;gap:.45rem}
/* ⚠ display:grid below beats the UA's [hidden]{display:none}, so without this
   rule an arrow that JS has hidden still occupies a 44px box. MEASURED: it did.
   This is what stops the one-review case rendering a dead control. */
.grw__arrow[hidden]{display:none}
.grw__arrow{width:44px;height:44px;flex:0 0 44px;background:#fff;color:var(--ink);
  border:1px solid var(--rule-2);display:grid;place-items:center;cursor:pointer;
  padding:0;transition:border-color .18s var(--ease),background .18s var(--ease)}
.grw__arrow:hover{border-color:var(--ink);background:var(--ground)}
.grw__arrow[disabled]{opacity:.38;cursor:default}
.grw__arrow[disabled]:hover{border-color:var(--rule-2);background:#fff}
.grw__arrow svg{width:18px;height:18px}
.grw__cta{font-family:Anybody,AnybodyFallback,sans-serif;font-weight:700;
  font-size:.85rem;background:var(--green);color:#fff;text-decoration:none;
  padding:.6rem 1rem;min-height:44px;display:inline-flex;align-items:center;
  white-space:nowrap;border:1px solid var(--green);
  transition:background .18s var(--ease)}
.grw__cta:hover{background:var(--green-lift);border-color:var(--green-lift)}

/* ------------------------------------------------------------------ track */
.grw__track{display:flex;gap:.7rem;overflow-x:auto;scroll-snap-type:x mandatory;
  padding:2px 2px .4rem;scrollbar-width:none;align-items:stretch}
.grw__track::-webkit-scrollbar{display:none}
/* one lone review must not read as a narrow orphan on a wide plate */
.grw__track.is-still{overflow-x:visible}
.grev:only-child{flex:0 0 min(34rem,100%)}

/* ---------------------------------------------------------------- entries */
.grev{scroll-snap-align:start;flex:0 0 19rem;max-width:84vw;background:#fff;
  border:1px solid var(--rule-2);padding:1rem;display:flex;flex-direction:column}
.grev__top{display:flex;align-items:center;gap:.6rem;margin-bottom:.6rem}
.grev__ava{width:40px;height:40px;flex:0 0 40px;border-radius:50%;object-fit:cover;
  background:var(--ground-2)}
/* flat green tile, no gradient: initials for a reviewer with no Google photo */
.grev__ava--f{background:var(--green);color:#fff;display:grid;place-items:center;
  font-family:Anybody,AnybodyFallback,sans-serif;font-weight:750;font-size:1.05rem}
.grev__who{min-width:0}
.grev__who b{display:block;font-family:Anybody,AnybodyFallback,sans-serif;
  font-weight:700;font-size:.92rem;color:var(--ink);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.grev__who span{display:block;font-size:.78rem;color:var(--ink-muted)}
.grev__g{margin-left:auto;width:20px;height:20px;flex:0 0 20px}
.grev .grw__stars{margin-bottom:.5rem;font-size:.95rem}
/* verbatim, and NOT clamped. The longest review on the profile is 248
   characters, so every one of them fits whole. white-space:pre-line keeps the
   reviewer's own line breaks. */
.grev p{margin:0;font-size:.92rem;line-height:1.6;color:var(--ink);
  white-space:pre-line}

.grw__note{margin:.9rem 0 0;font-size:.8rem;color:var(--ink-muted);max-width:64ch}
.grw__note a{color:var(--green);text-decoration:underline;
  text-underline-offset:.18em}
.grw__note a:hover{color:var(--ink)}

@media (max-width:44rem){
  .grw__act{margin-left:0;width:100%}
  .grw__cta{margin-left:auto}
}
/* No prefers-reduced-motion block here on purpose: the site already kills every
   transition globally with transition-duration:.001ms!important, and !important
   beats anything scoped that could be written here. The motion this component
   adds on top of that is the smooth scroll, and THAT is switched off in JS
   (behavior:'auto' when the query matches). */
