/* ===========================================================================
   Traveling Man Painting Co.
   Palette sampled from the logo artwork. The look is modern and soft-surfaced,
   but the brushed-gold texture is kept deliberately in three places — the hero
   band, the section rules, and the swatches — so it still reads as a trade
   brand rather than a tech product.
   =========================================================================== */
:root{
  /* Palette. Same brand, light ground. Paper white is the same warm family as
     the cream in the highlight boxes, just lighter, so nothing new enters the
     palette. */
  --ink:#FAF8F4;                 /* the page */
  --on-gold:#150F05;             /* text that sits ON gold, stays dark */

  /* Gold has two jobs now. #C5A45D is the accent, unchanged, for rules,
     borders, buttons and the brushed texture. It measures 2.24:1 on paper
     white, so it cannot carry text. --gold-text is one notch off --gold-lo,
     already in this palette, and clears 4.5:1 on paper, on the band and on
     card white. */
  --gold:#C5A45D; --gold-hi:#EDDB9D; --gold-lo:#8A6F3E; --gold-deep:#4D3D1B;
  --gold-text:#816639;

  /* Surfaces that were literals in the light build. Tokenised so the dark
     theme can move them without touching a component rule. */
  --field-bg:#FFFFFF;
  --ghost-bg:#FFFFFF;
  --map-bg:#EFEAE1;
  --map-label-bg:rgba(255,255,255,.92);
  --attr-bg:rgba(255,255,255,.93);
  --county-fill:#EFEAE1;
  --county-stroke:rgba(20,16,10,.14);
  /* The brushed ramp on large display type. Deep on paper, bright on ink. */
  --leaf-ramp:linear-gradient(96deg,#6D562D 0%,#816639 18%,#8F7140 34%,
    #7A6034 50%,#8A6C3B 66%,#6F5830 84%,#7C6236 100%);

  --chalk:#0F0E0C;               /* primary text, near-black and warm */
  --muted:#5F594F;               /* secondary text, 6.5:1 on paper */

  /* Translucent BLACK over paper, where it used to be translucent white over
     ink. Same idea inverted, so surfaces still lift off the page. */
  --lift-1:rgba(20,16,10,.028);
  --lift-2:rgba(20,16,10,.05);
  --lift-3:rgba(20,16,10,.08);

  /* The warm gray band. This is what keeps sections reading as separate now
     that the page is one light sheet. */
  --char-band:#F0EDE7;
  --card-top:#FFFFFF; --card-bot:#FBF9F5;
  --card-top-hi:#FFFFFF; --card-bot-hi:#F6F1E8;
  --line:rgba(20,16,10,.11);
  --line-soft:rgba(20,16,10,.07);
  --hair:rgba(197,164,93,.55);

  /* radii */
  --r-sm:12px; --r-md:20px; --r-lg:28px; --r-xl:44px; --r-pill:999px;

  /* Shadows drop hard on a light ground. These are barely-there lifts, not
     the deep wells the dark build needed. */
  --e1:0 1px 2px rgba(20,16,10,.05);
  --e2:0 6px 18px -10px rgba(20,16,10,.16);
  --e3:0 18px 40px -22px rgba(20,16,10,.22);
  /* The inset white top edge did the work on dark cards. On near-white cards
     it is invisible, so it is a no-op rather than fourteen edits. */
  --glint:0 0 0 0 transparent;

  /* motion */
  --ease:cubic-bezier(.32,.72,.28,1);
  --out:cubic-bezier(.16,1,.3,1);

  --display:"Archivo",system-ui,sans-serif;
  --body:"Source Serif 4",Georgia,serif;
  --pad:clamp(1.25rem,5vw,5rem);
  /* More air between sections. The content was fine, it needed room. */
  --gap:clamp(6.5rem,14vw,13rem);
}

/* ---------------------------------------------------------------------------
   Dark theme. Light is the default and stays the default, including for people
   whose OS is set to dark. This only applies when someone asks for it with the
   toggle, which is what data-theme="dark" means here.

   These are the original values from the dark build, restored token for token,
   so the old look comes back exactly rather than approximately.
   --------------------------------------------------------------------------- */
:root[data-theme="dark"]{
  --ink:#0A0A0A;
  --chalk:#F2F0EA; --muted:#9A958A;
  --gold-text:#C5A45D;              /* on ink the bright gold reads at 8.4:1 */

  --lift-1:rgba(255,255,255,.035);
  --lift-2:rgba(255,255,255,.055);
  --lift-3:rgba(255,255,255,.085);

  --char-band:#141210;
  --card-top:#201D19; --card-bot:#191614;
  --card-top-hi:#282420; --card-bot-hi:#1F1B18;
  --line:rgba(255,255,255,.08);
  --line-soft:rgba(255,255,255,.055);
  --hair:rgba(197,164,93,.20);

  --e1:0 2px 8px -3px rgba(0,0,0,.6);
  --e2:0 10px 30px -14px rgba(0,0,0,.75);
  --e3:0 26px 60px -24px rgba(0,0,0,.85);
  --glint:inset 0 1px 0 rgba(255,255,255,.07);

  --field-bg:rgba(0,0,0,.35);
  --ghost-bg:var(--lift-1);
  --map-bg:#12100E;
  --map-label-bg:rgba(10,10,10,.82);
  --attr-bg:rgba(10,10,10,.86);
  --county-fill:#2A2621;
  --county-stroke:rgba(255,255,255,.10);
  --leaf-ramp:linear-gradient(96deg,var(--gold-lo) 0%,var(--gold) 15%,
    var(--gold-hi) 30%,var(--gold) 42%,#9A7F49 54%,var(--gold-hi) 70%,
    var(--gold) 85%,var(--gold-lo) 100%);
}
/* The bar was already dark in the light theme, so in dark it only needs its
   translucency back. */
:root[data-theme="dark"] header{background:rgba(10,10,10,.5)}
:root[data-theme="dark"] header.scrolled{background:rgba(10,10,10,.85)}
/* Hovers that were pushed to near-black for legibility on paper go back to the
   pale gold, which is what reads on ink. */
:root[data-theme="dark"] .who-card:hover .svc-more,
:root[data-theme="dark"] .leaflet-control-zoom a:hover,
:root[data-theme="dark"] .attr-toggle:hover{color:var(--gold-hi)}
:root[data-theme="dark"] .stars{color:var(--gold)}
/* Form controls specifically. Inheriting the value through a custom property
   works on first paint but did not restyle these when the attribute flipped
   live, so the fields stayed white in dark mode. Matching the attribute in the
   selector itself forces the restyle. */
:root[data-theme="dark"] .field input,
:root[data-theme="dark"] .field select,
:root[data-theme="dark"] .field textarea,
:root[data-theme="dark"] .field input:focus,
:root[data-theme="dark"] .field select:focus,
:root[data-theme="dark"] .field textarea:focus{background-color:rgba(0,0,0,.35)}
:root[data-theme="dark"] .field select option{background-color:#141412}
:root[data-theme="dark"] .btn-ghost{background:rgba(255,255,255,.035)}  /* shorthand, see .btn-ghost */

/* --- theme toggle -------------------------------------------------------- */
/* Floats bottom-left rather than sitting in the bar. In the nav it pushed the
   wordmark and links onto a second line on narrow screens. Bottom-LEFT because
   the map parks its own credits control bottom-right. */
.theme-toggle{position:fixed;left:clamp(.85rem,2vw,1.5rem);bottom:clamp(.85rem,2vw,1.5rem);
  z-index:80;width:44px;height:44px;display:grid;place-items:center;padding:0;
  border-radius:var(--r-pill);border:1px solid var(--line);
  background:var(--card-top);color:var(--gold-text);
  box-shadow:var(--e2);cursor:pointer;
  transition:transform .25s var(--out),border-color .25s var(--ease),color .25s var(--ease)}
@media (hover:hover){.theme-toggle:hover{transform:translateY(-2px);border-color:var(--hair)}}
.theme-toggle:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.theme-toggle svg{display:block}
/* One button, two glyphs. The moon offers dark, the sun offers the way back. */
.theme-toggle .moon{display:block}
.theme-toggle .sun{display:none}
:root[data-theme="dark"] .theme-toggle .moon{display:none}
:root[data-theme="dark"] .theme-toggle .sun{display:block}
/* Out of the way while a photo is open full screen. */
body.lb-open .theme-toggle{display:none}

/* --- cross-document view transitions ------------------------------------ */
/* Navigating between pages cross-fades instead of flashing white. This is the
   whole opt-in. No JavaScript, no library, and browsers without support just
   navigate the old way, so there is no fallback to maintain.

   Same-origin only, which every link on this site is. */
@view-transition{navigation:auto}

/* The bar and the floating toggle are identical on every page, so they are
   lifted out of the page fade and hold still while the content changes
   underneath. Left in the root snapshot they would fade out and back in on
   every click, which reads as a flicker.

   Each name has to be unique in the document. header, footer and the toggle
   are single instances on all six pages, so these are safe. The footer is
   deliberately NOT named: pages differ in length, so a named footer would
   slide up or down between them instead of staying put. */
header{view-transition-name:site-bar}
.theme-toggle{view-transition-name:theme-toggle}

/* Short and on the site's own easing curve. Long page fades feel broken
   rather than smooth, because nothing is interactive while they run. */
::view-transition-old(root),
::view-transition-new(root){
  animation-duration:.26s;
  animation-timing-function:var(--ease)}
::view-transition-group(site-bar),
::view-transition-group(theme-toggle){animation-duration:.26s}

/* Motion sensitivity wins over polish. This kills the animation but keeps the
   navigation itself working. */
@media (prefers-reduced-motion:reduce){
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*){animation:none!important}
}

*,*::before,*::after{box-sizing:border-box}
/* `clip`, not `hidden`: overflow-x:hidden on body turns it into a scroll
   container and breaks the sticky header. clip contains stray overflow
   without that side effect. */
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;overflow-x:clip}
body{margin:0;background:var(--ink);color:var(--chalk);font-family:var(--body);
  font-size:clamp(1.02rem,.99rem + .18vw,1.1rem);line-height:1.7;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:clip}
img{max-width:100%;display:block}
a{color:inherit}

/* --- type ---------------------------------------------------------------- */
.display{font-family:var(--display);font-variation-settings:"wdth" 112,"wght" 800;
  text-transform:uppercase;line-height:.94;letter-spacing:-.015em;margin:0}
/* Section headings are written as sentences — uppercasing them fights the copy
   and reads dated. Sentence case with tight tracking is the modern move. */
.sec-head h1,.sec-head h2,.vac h2{text-transform:none;letter-spacing:-.038em;line-height:1.05;
  font-variation-settings:"wdth" 100,"wght" 650;
  font-size:clamp(2.35rem,1.4rem + 4.4vw,4.6rem)}
.label{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 600;
  text-transform:uppercase;font-size:.7rem;letter-spacing:.2em;color:var(--gold-text)}
/* Deep golds only. The bright ramp measured about 2.2:1 on paper white, which
   is unreadable at any size. This ramp stays above 4.5:1 across its whole
   length and still reads as brushed metal. */
.leaf{background-image:var(--leaf-ramp);
  -webkit-background-clip:text;background-clip:text;color:transparent}

.wrap{max-width:1180px;margin-inline:auto;padding-inline:var(--pad)}
section{padding-block:var(--gap)}
.eyebrow{display:flex;align-items:center;gap:1rem;margin-bottom:1.25rem}
.eyebrow::after{content:"";flex:1;height:1px;
  background:linear-gradient(90deg,var(--hair),transparent)}
/* Measure is set per-element, not on the wrapper — a single wrapper width
   computed in body ems throttles the much larger headline into four lines. */
.sec-head{margin-bottom:clamp(2.75rem,5.5vw,4.5rem);text-align:center}
.sec-head .eyebrow{max-width:none;justify-content:center}
/* The flex rule that draws a line after the eyebrow has to go when centred,
   otherwise it pushes the label off to one side. */
.sec-head .eyebrow::after{display:none}
.sec-head h1,.sec-head h2{max-width:22ch;margin-inline:auto}
.sec-head p{color:var(--muted);margin:1.5rem auto 0;max-width:56ch}
.sec-head .brushed{margin-inline:auto}
/* Two-column sections keep their left alignment. */
.vac-copy{text-align:left}
.eyebrow{max-width:34rem}

/* KEPT: the brushed rule. Hand-made texture against all the soft geometry. */
.brushed{width:92px;height:7px;margin-top:1.4rem;
  background:linear-gradient(90deg,var(--gold-lo),var(--gold) 25%,var(--gold-hi) 55%,var(--gold) 80%,var(--gold-lo));
  -webkit-mask-image:repeating-linear-gradient(0deg,#000 0 2px,rgba(0,0,0,.45) 2px 3px,#000 3px 5px,rgba(0,0,0,.25) 5px 6px);
  mask-image:repeating-linear-gradient(0deg,#000 0 2px,rgba(0,0,0,.45) 2px 3px,#000 3px 5px,rgba(0,0,0,.25) 5px 6px);
  clip-path:polygon(0 12%,96% 0,100% 46%,97% 100%,2% 88%)}

/* --- header (glass) ------------------------------------------------------ */
header{position:sticky;top:0;z-index:60;
  background:rgba(10,10,10,.9);
  -webkit-backdrop-filter:saturate(180%) blur(22px);
  backdrop-filter:saturate(180%) blur(22px);
  border-bottom:1px solid transparent;
  transition:background .4s var(--ease),border-color .4s var(--ease)}
header.scrolled{background:rgba(10,10,10,.92);border-bottom-color:rgba(255,255,255,.1)}
.bar{display:flex;align-items:center;gap:1.25rem;min-height:66px}
.mark{display:flex;align-items:center;gap:.75rem;text-decoration:none;flex:none;
  border-radius:var(--r-sm);transition:opacity .25s var(--ease)}
.mark:hover{opacity:.82}
.mark img{height:44px;width:auto}
.mark b{font-family:var(--display);font-variation-settings:"wdth" 108,"wght" 800;
  text-transform:uppercase;font-size:.88rem;letter-spacing:.03em;line-height:1.05;display:block}
/* Was an <s>, which is the strikethrough element. The rule below cancelled the
   line, but <s> also means "no longer accurate", which is the wrong thing to
   say about a company name. <i> here is styled upright, so the look is
   identical and the markup no longer lies. */
.mark i{display:block;font-style:normal;font-family:var(--display);font-size:.56rem;
  letter-spacing:.22em;color:var(--muted);font-variation-settings:"wdth" 95,"wght" 500}
nav{margin-left:auto;display:flex;align-items:center;gap:clamp(.75rem,2.2vw,2rem)}
.nav-links{display:flex;gap:clamp(.4rem,1.4vw,.7rem)}
.nav-links a{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 550;
  text-transform:none;font-size:.82rem;letter-spacing:-.006em;text-decoration:none;
  color:var(--muted);padding:.5rem .8rem;border-radius:var(--r-pill);
  transition:color .25s var(--ease),background .25s var(--ease)}
.nav-links a:hover{color:var(--chalk);background:var(--lift-2)}

/* The bar is the one dark surface left on the site, so it carries its own
   light text set. This has to sit AFTER the rules above, which set the
   page-level muted colour and would otherwise win on source order and drop
   the wordmark to 2.3:1 against the dark bar. */
header{color:#F2F0EA}
.mark b{color:#F2F0EA}
.mark i{color:rgba(242,240,234,.72)}
.nav-links a{color:rgba(242,240,234,.8)}
.nav-links a:hover{color:#F2F0EA;background:rgba(255,255,255,.1)}
.nav-links a.current{color:var(--gold)}

/* --- buttons ------------------------------------------------------------- */
/* min-height 44px is a floor, not a size. The header button trims its padding
   on narrow screens to fit beside the logo, which took the tap target down to
   35px on a 320px phone. The floor keeps every button hittable without
   touching the padding that shapes them. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;min-height:44px;
  font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 700;
  text-transform:uppercase;font-size:.74rem;letter-spacing:.12em;
  padding:1em 1.75em;border-radius:var(--r-pill);
  text-decoration:none;border:1px solid transparent;color:#150F05;cursor:pointer;
  background:linear-gradient(160deg,var(--gold-hi),var(--gold) 44%,var(--gold-lo));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.45),0 6px 16px -10px rgba(197,164,93,.75);
  transition:transform .3s var(--out),box-shadow .3s var(--out),filter .3s var(--ease)}
.btn:hover{filter:brightness(1.07);transform:translateY(-2px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.55),0 12px 26px -12px rgba(197,164,93,.85)}
.btn:active{transform:translateY(0) scale(.985)}
/* background, not background-color. .btn above sets the gold gradient with
   the background shorthand, and a gradient is a background-IMAGE. Overriding
   only background-color swaps the layer underneath it and leaves the gradient
   painting straight over the top, so the ghost button was never a ghost. It
   was a gold button wearing gold text.

   In dark mode --gold-text is #C5A45D and the gradient's 44% stop is also
   #C5A45D. Same hex, so the middle of every Call and Text button measured
   1.00:1 against its own background and the words simply were not there.
   Light mode ran 1.14:1 to 3.91:1, bad but dark-on-gold, which is why it read
   as merely low contrast rather than blank.

   The tell was that hovering fixed it. .btn-ghost:hover uses the shorthand,
   so the gradient cleared on hover and the text reappeared.

   With the image cleared it is 8.34:1 on ink and 5.39:1 on white. */
.btn-ghost{background:var(--ghost-bg);color:var(--gold-text);border-color:rgba(197,164,93,.3);
  box-shadow:none}
.btn-ghost:hover{background:rgba(197,164,93,.1);border-color:rgba(197,164,93,.55);
  box-shadow:none;filter:none}

/* --- hero ---------------------------------------------------------------- */
.hero{padding-block:clamp(3.5rem,9vh,7rem) clamp(3rem,7vw,5.5rem);position:relative}
/* Ambient light behind the logo — depth without a hard edge. Insets stay at or
   inside 0 on the horizontal axis: a negative right inset pushes past the
   viewport, and Safari before 16 ignores overflow-x:clip and shows a scrollbar. */
.hero::before{content:"";position:absolute;inset:-20% 0 0 0;pointer-events:none;
  background:radial-gradient(46% 42% at 50% 26%,rgba(197,164,93,.14),transparent 72%);
  filter:blur(10px)}
/* One centre line. The mark on top, then the eyebrow, headline, sentence and
   buttons stacked beneath it, every one of them centred on the same axis. */
.hero-grid{display:grid;grid-template-columns:1fr;gap:clamp(1.5rem,4vw,2.5rem);
  justify-items:center;text-align:center;position:relative}
.hero-copy{max-width:62rem}
.hero h1{font-size:clamp(2.7rem,1rem + 7.4vw,6rem)}
.hero h1 span{display:block}

/* KEPT — the signature. A loaded brush lays gold across the black and the word
   is knocked out of it, the way a sign painter letters a truck door. */
/* nowrap is load-bearing: if "next day" wraps, the band stretches to the full
   block and becomes a slab instead of a single brush stroke. */
.band{position:relative;display:inline-block;white-space:nowrap;
  padding:.06em .26em .1em;color:var(--on-gold);isolation:isolate}
.band::before{content:"";position:absolute;inset:-.02em -.02em .01em;z-index:-1;
  background:linear-gradient(94deg,var(--gold-lo),var(--gold) 18%,var(--gold-hi) 38%,
    var(--gold) 55%,#A8873F 70%,var(--gold-hi) 86%,var(--gold) 100%);
  -webkit-mask-image:repeating-linear-gradient(0deg,#000 0 6px,rgba(0,0,0,.6) 6px 8px,#000 8px 15px,rgba(0,0,0,.38) 15px 17px);
  mask-image:repeating-linear-gradient(0deg,#000 0 6px,rgba(0,0,0,.6) 6px 8px,#000 8px 15px,rgba(0,0,0,.38) 15px 17px);
  clip-path:polygon(0 4%,99.2% 0,100% 51%,99% 97%,.6% 100%);
  transform:scaleX(0);transform-origin:left center;
  animation:brushpass 1.05s cubic-bezier(.32,.72,.28,1) .3s forwards}
@keyframes brushpass{to{transform:scaleX(1)}}

.hero-sub{font-size:clamp(1.08rem,.98rem + .62vw,1.38rem);color:var(--muted);
  max-width:54ch;margin:2.1rem auto 0;line-height:1.62}
.hero-sub strong{color:var(--chalk);font-weight:600}
/* Same reason the section heads kill it. The flex line after the label pushes
   the label off the centre line it is supposed to sit on. */
.hero .eyebrow{justify-content:center;max-width:none}
.hero .eyebrow::after{display:none}
.cta-row{display:flex;flex-wrap:wrap;gap:.85rem;margin-top:2.4rem;justify-content:center}
.hero-logo{opacity:0;animation:fadein 1.1s var(--out) .8s forwards;
  width:clamp(230px,30vw,430px);height:auto;display:block;
  filter:drop-shadow(0 24px 48px rgba(0,0,0,.45))}
@keyframes fadein{to{opacity:1}}

/* --- trust strip --------------------------------------------------------- */
/* Charcoal bands give the page rhythm. At ~12,000px tall it is otherwise one
   uninterrupted run of near-black and the sections stop reading as separate. */
.tint{background:var(--char-band)}
.strip{background:var(--char-band);border-block:1px solid var(--line-soft)}
.strip ul{list-style:none;margin:0;padding:1.6rem 0;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:1rem 2rem}
.strip li{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 500;
  text-transform:uppercase;font-size:.72rem;letter-spacing:.14em;color:var(--muted);
  line-height:1.5;display:flex;align-items:flex-start;gap:.7rem}
/* pinned to the first line, so a two-line marker keeps its dot beside the
   text rather than floating in the middle of the block */
/* One marker, two placements. The trust strip and the About creed drew the
   same gold square at 6px and 8px from two separate blocks, so they drifted.
   The look is defined once here and each list only sets its own position. */
.strip li::before,.creed li::before{content:"";width:7px;height:7px;border-radius:2px;
  background:linear-gradient(140deg,var(--gold-hi),var(--gold-lo));
  box-shadow:0 0 12px rgba(197,164,93,.5)}
.strip li::before{flex:none;margin-top:.42em}

/* --- vacancy calculator -------------------------------------------------- */
.vac{background:var(--char-band);position:relative}
.vac-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2rem,5vw,4.5rem);align-items:center}
.vac-copy p{color:var(--muted);margin-top:1.5rem;max-width:46ch}
.vac-panel{background:linear-gradient(180deg,var(--card-top-hi),var(--card-bot-hi));
  border:1px solid var(--line);border-radius:var(--r-xl);
  box-shadow:var(--glint),var(--e3);
  padding:clamp(1.6rem,3.2vw,2.6rem)}
.vac-panel label{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 600;
  text-transform:uppercase;font-size:.68rem;letter-spacing:.16em;color:var(--gold-text);
  display:block;margin-bottom:.7rem}
.money-in{display:flex;align-items:center;border:1px solid var(--line);
  background:rgba(0,0,0,.35);border-radius:var(--r-sm);
  transition:border-color .25s var(--ease),box-shadow .25s var(--ease)}
.money-in:focus-within{border-color:rgba(197,164,93,.6);
  box-shadow:0 0 0 4px rgba(197,164,93,.14)}
.money-in span{padding:0 .15rem 0 1rem;color:var(--muted);font-size:1.2rem}
.money-in input{flex:1;background:none;border:0;color:var(--chalk);font-family:var(--body);
  font-size:1.2rem;padding:.9rem 1rem;width:100%}
.money-in input:focus{outline:none}
.readout{margin-top:2rem;padding-top:1.7rem;border-top:1px solid var(--line-soft)}
.readout .big{font-family:var(--display);font-variation-settings:"wdth" 118,"wght" 800;
  font-size:clamp(2.6rem,1.6rem + 4.2vw,4.2rem);line-height:1;display:block;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.readout small{display:block;font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 500;
  text-transform:uppercase;font-size:.68rem;letter-spacing:.16em;color:var(--muted);margin-top:.8rem}
.readout .line{margin:1.5rem 0 0;color:var(--muted);font-size:.96rem}
.readout .line b{color:var(--chalk);font-weight:600}

/* --- included: floating cards -------------------------------------------- */
/* Two by two, not auto-fit. Four cards across a 1180px page gave three on the
   top row and one stranded underneath. Every grid that uses this holds exactly
   four, so a fixed pair of columns squares them off. */
.chips{display:grid;grid-template-columns:1fr;gap:clamp(.9rem,1.6vw,1.25rem)}
@media (min-width:760px){.chips{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* Three cards in a two-column grid strand the last one on its own row. Where a
   section has exactly three, they go three across on a wide screen instead.
   The four-card sections keep their 2x2, which is what they were built for. */
@media (min-width:1000px){
  .chips:has(> .chip:nth-child(3):last-child){grid-template-columns:repeat(3,minmax(0,1fr))}
}
.chip{background:linear-gradient(180deg,var(--card-top),var(--card-bot));
  border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--glint),var(--e1);
  padding:clamp(1.9rem,3vw,2.6rem);
  transition:transform .4s var(--out),box-shadow .4s var(--out),
             border-color .4s var(--ease),background .4s var(--ease)}
.chip:hover{transform:translateY(-4px);border-color:rgba(197,164,93,.28);
  background:linear-gradient(180deg,var(--card-top-hi),var(--card-bot-hi));
  box-shadow:var(--glint),var(--e3)}
/* KEPT: the paint swatches, softened into rounded chips */
.swatch{width:48px;height:48px;border-radius:14px;margin-bottom:1.4rem;
  background:linear-gradient(150deg,var(--gold-hi),var(--gold) 48%,var(--gold-lo));
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.22),0 12px 26px -12px rgba(197,164,93,.85)}
.chip:nth-child(2) .swatch{background:linear-gradient(150deg,var(--gold),#7A6231 60%,var(--gold-deep))}
.chip:nth-child(3) .swatch{background:linear-gradient(150deg,#FBF1D2,var(--gold-hi) 50%,var(--gold))}
.chip:nth-child(4) .swatch{background:linear-gradient(150deg,#6E6A60,#33302A 60%,#191817)}
.chip:nth-child(5) .swatch{background:linear-gradient(150deg,var(--gold-hi),#9A7F49 55%,#5C4A1C)}
.chip:nth-child(6) .swatch{background:linear-gradient(150deg,#DCD6C6,#8E887A 55%,#4A463E)}
.chip h3{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 700;
  font-size:1.12rem;letter-spacing:-.01em;margin:0 0 .7rem;text-transform:none}
.chip p{margin:0;color:var(--muted);font-size:.97rem;line-height:1.62}

/* --- who I work with ----------------------------------------------------- */
/* Two-up, not four. Four cards across 1036px left about 160px of text width
   once the larger tile padding went on, which reads as cramped columns rather
   than tiles. Two big tiles is also closer to how Apple lays out a feature
   grid, and it never orphans a card the way auto-fit did. */
/* Two columns held the four customer cards as a square. There are six
   services now, so three across reads as a block rather than a list that
   happens to stop. Two columns in between, one on a phone. */
.who{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(1rem,1.8vw,1.4rem)}
@media (min-width:1000px){.who{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:700px){.who{grid-template-columns:minmax(0,1fr)}}
.who-card h3{font-size:1.32rem}
.who-card .tag{margin-bottom:1.1rem}
/* The card is an anchor now that it carries the service link, so it has to
   shed the default link styling and lay its children out in a column. */
.who-card{display:flex;flex-direction:column;text-decoration:none;
  background:linear-gradient(180deg,var(--card-top),var(--card-bot));
  border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--glint),var(--e1);padding:clamp(1.5rem,2.6vw,2rem);
  transition:transform .4s var(--out),border-color .4s var(--ease)}
.who-card:hover{transform:translateY(-3px);border-color:rgba(197,164,93,.26)}
.who-card h3{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 700;
  font-size:1.08rem;letter-spacing:-.012em;margin:0 0 .3rem;text-transform:none}
.who-card .tag{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 600;
  text-transform:uppercase;font-size:.62rem;letter-spacing:.16em;color:var(--gold-text);
  display:block;margin-bottom:.9rem}
.who-card p{margin:0 0 1.4rem;color:var(--muted);font-size:.95rem;line-height:1.62}
@media (hover:hover){.who-card:hover .svc-more{color:var(--chalk)}}

/* --- faq ----------------------------------------------------------------- */
/* The groups collapse too. Thirty-three questions sitting open as rows made
   this section a wall of bars, and nobody reads a wall. Six lines you can scan,
   with the count so you know what is behind each one before you open it. */
/* h3 sits inside the summary now, so the old direct-child selector no longer
   matched it and the group labels would have lost their gold entirely. */

.faq{display:grid;gap:.6rem}
.faq details{background:linear-gradient(180deg,var(--card-top),var(--card-bot));
  border:1px solid var(--line);border-radius:var(--r-md);
  transition:border-color .3s var(--ease),background .3s var(--ease)}
.faq details:hover{border-color:rgba(197,164,93,.24)}
.faq details[open]{background:linear-gradient(180deg,var(--card-top-hi),var(--card-bot-hi))}
.faq summary{list-style:none;cursor:pointer;display:block;position:relative;
  padding:1.05rem 3.2rem 1.05rem 1.35rem;
  font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 600;
  font-size:.98rem;letter-spacing:-.006em;color:var(--chalk)}
.faq summary::-webkit-details-marker{display:none}
.faq summary::marker{content:""}
.faq summary::after{content:"";position:absolute;right:1.45rem;top:1.45rem;
  width:8px;height:8px;border-right:2px solid var(--gold);border-bottom:2px solid var(--gold);
  transform:rotate(45deg);transition:transform .3s var(--ease)}
.faq details[open] summary::after{transform:rotate(225deg);top:1.6rem}
.faq .a{padding:0 1.6rem 1.25rem 1.35rem;color:var(--muted);font-size:.96rem;
  line-height:1.65;max-width:74ch}
.faq .a p{margin:0 0 .7rem}
.faq .a p:last-child{margin:0}

/* --- pricing ------------------------------------------------------------- */
.rate-title{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 700;
  font-size:1.15rem;letter-spacing:-.015em;color:var(--chalk);margin:0 0 .7rem}
.rate-note{color:var(--muted);font-size:.98rem;margin:0 0 1.4rem;max-width:72ch}

.unit-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));
  gap:clamp(.9rem,1.6vw,1.25rem);margin-bottom:.5rem}
.unit-card,.price-card{background:linear-gradient(180deg,var(--card-top),var(--card-bot));
  border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--glint),var(--e1);
  padding:clamp(1.5rem,2.6vw,2rem);
  transition:transform .4s var(--out),border-color .4s var(--ease)}
.unit-card:hover,.price-card:hover{transform:translateY(-3px);border-color:rgba(197,164,93,.24)}
.unit-card h3,.price-card h3{font-family:var(--display);
  font-variation-settings:"wdth" 100,"wght" 600;
  text-transform:uppercase;font-size:.7rem;letter-spacing:.16em;color:var(--gold-text);
  margin:0 0 1.1rem}
.unit-card .scope{margin:0;color:var(--muted);font-size:.96rem;line-height:1.62}
.price-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(270px,1fr));
  gap:clamp(.9rem,1.6vw,1.25rem);margin-top:.5rem}
.price-card ul{margin:0;padding:0;list-style:none}
/* All three cards are plain lists now. The old flex row existed to hang a
   bold value on the right, but two of the three had nothing meaningful to put
   there ("quoted" four times over) and one was splitting a single phrase
   across the columns. */
.price-card li{color:var(--muted);font-size:.97rem;padding:.62rem 0;
  border-bottom:1px solid var(--line-soft);line-height:1.5}
.price-card li:last-child{border-bottom:0;padding-bottom:0}

/* Backup & overflow. Lifted out of the standard-turn grid, where it sat among
   things a turn includes while actually being a fifth kind of customer. It
   borrows the rate-sheet card's shape so it reads as an aside to Who I work
   with rather than a new section. */
.overflow-strip{display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:1.5rem;
  padding:clamp(1.4rem,2.6vw,2rem) clamp(1.5rem,3vw,2.25rem);
  border:1px solid var(--hair);border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--card-top-hi),var(--card-bot-hi));
  box-shadow:var(--glint),var(--e2)}
.overflow-strip>div{flex:1 1 26rem;min-width:0}
.overflow-strip h3{font-family:var(--display);
  font-variation-settings:"wdth" 100,"wght" 600;
  text-transform:uppercase;font-size:.7rem;letter-spacing:.16em;color:var(--gold-text);
  margin:0 0 .6rem}
.overflow-strip p{margin:0;color:var(--muted);font-size:.97rem;line-height:1.6;max-width:62ch}
.overflow-strip .btn{flex:none}
@media (max-width:640px){.overflow-strip .btn{width:100%}}

/* rate-sheet call to action */
.sheet-cta{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:1.75rem;margin-top:2rem;padding:clamp(1.6rem,3vw,2.25rem);
  border:1px solid rgba(197,164,93,.24);border-radius:var(--r-xl);
  background:linear-gradient(135deg,rgba(197,164,93,.14),var(--card-top) 55%,var(--card-bot));
  box-shadow:var(--glint),var(--e2)}
.sheet-cta .btn{flex:none}

/* --- process ------------------------------------------------------------- */
.steps{counter-reset:s;margin-top:-.5rem}
.step{counter-increment:s;display:grid;grid-template-columns:auto 1fr;
  gap:clamp(1.25rem,3.5vw,3rem);padding-block:clamp(1.6rem,3vw,2.4rem);
  border-top:1px solid var(--line-soft);align-items:start}
.step:last-child{border-bottom:1px solid var(--line-soft)}
/* Roman numerals. Each .step is its own grid, so an auto column would size to
   that row's own numeral and the headings would start at five different left
   edges, I being narrow and III being wide. min-width holds one shared column,
   and the tighter tracking that suited 01 opens back up because I I I needs the
   air between the strokes. */
.step::before{content:counter(s,upper-roman);
  font-family:var(--display);font-variation-settings:"wdth" 118,"wght" 800;
  font-size:clamp(1.7rem,1rem + 2.1vw,2.7rem);line-height:1;
  min-width:2.1em;letter-spacing:.01em;color:var(--gold-text);opacity:.5;
  transition:opacity .45s var(--ease)}
.step:hover::before{opacity:1}
.step h3{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 700;
  font-size:1.15rem;letter-spacing:-.015em;margin:0 0 .55rem;text-transform:none}
.step p{margin:0;color:var(--muted);max-width:64ch}

.svc-more{margin-top:auto;font-family:var(--display);
  font-variation-settings:"wdth" 100,"wght" 650;text-transform:uppercase;
  font-size:.66rem;letter-spacing:.14em;color:var(--gold-text);
  transition:color .25s var(--ease)}
.svc-more::after{content:" \2192"}

/* Closing CTA on the service pages. The buttons centre because the heading
   above them does, and a left-aligned pair under a centred heading reads as a
   mistake rather than a choice. */
.closing-cta .cta-row{justify-content:center;margin-top:0}

/* --- service page cross-links -------------------------------------------- */
/* Pills rather than a list, so the three siblings read as a choice instead of
   leftover navigation at the bottom of the page. */
.svc-links{display:flex;flex-wrap:wrap;gap:.6rem;justify-content:center}
.svc-links a{display:inline-flex;align-items:center;min-height:44px;
  padding:.6rem 1.15rem;border-radius:var(--r-pill);
  border:1px solid var(--line);background:var(--lift-1);color:var(--chalk);
  text-decoration:none;font-family:var(--display);
  font-variation-settings:"wdth" 100,"wght" 550;font-size:.85rem;
  transition:color .25s var(--ease),background .25s var(--ease),border-color .25s var(--ease)}
.svc-links a:hover{color:var(--gold-text);border-color:var(--hair);background:var(--lift-2)}

/* --- reviews ------------------------------------------------------------- */
/* Same card surface as everything else, so the quotes read as part of the site
   rather than a bolted-on widget. Auto-fit means two reviews or four both look
   deliberate. */
/* Columns rather than a grid. Reviews are wildly different lengths, and a
   grid stretches every card in a row to match the tallest one, so a one-line
   review sat in a card sized for a five-line one and the section filled with
   dead space. Columns let each card size to its own text and close the gaps.
   It also removes the orphan row a grid leaves when the count does not divide
   evenly. */
.review-grid{columns:1;column-gap:clamp(.9rem,1.6vw,1.25rem)}
@media (min-width:700px){.review-grid{columns:2}}
@media (min-width:1150px){.review-grid{columns:3}}
.review{break-inside:avoid;-webkit-column-break-inside:avoid;
  margin:0 0 clamp(.9rem,1.6vw,1.25rem);display:flex;flex-direction:column;
  background:linear-gradient(180deg,var(--card-top),var(--card-bot));
  border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--glint),var(--e2);padding:clamp(1.5rem,2.6vw,1.9rem)}
.stars{display:inline-flex;gap:.18rem;color:var(--gold-lo);margin-bottom:1rem}
.review blockquote{margin:0 0 1.2rem;color:var(--chalk);font-size:1rem;line-height:1.65}
/* The attribution is what makes a quote believable, so it takes the display
   face and sits apart from the words it belongs to. margin-top:auto pins it to
   the bottom, keeping the three cards aligned when the quotes differ in
   length. */
.review figcaption{margin-top:auto;font-family:var(--display);
  font-variation-settings:"wdth" 100,"wght" 650;font-size:.86rem;color:var(--chalk)}
.review figcaption span{display:block;font-variation-settings:"wdth" 100,"wght" 500;
  text-transform:uppercase;font-size:.62rem;letter-spacing:.16em;
  color:var(--muted);margin-top:.4rem}

/* --- finished work gallery ----------------------------------------------- */
/* Square tiles on a fluid grid. The photos come off a phone in both portrait
   and landscape, and a mixed-ratio grid leaves ragged gaps down the right
   edge, so the tile is a fixed square and the photo is cropped to fill it.
   The full frame, uncropped, is one tap away in the viewer.

   Column counts are fixed rather than auto-fill, because auto-fill cannot
   give two columns on a phone and four on a desktop from one minimum. These
   three steps are also exactly what the sizes attribute on every img claims,
   so the browser downloads the file it actually needs. */
.gallery{display:grid;gap:clamp(.6rem,1.2vw,1rem);
  grid-template-columns:repeat(2,1fr);
  /* dense, because a hero tile spanning two columns leaves a hole behind it
     otherwise. Dense backfills that hole with the next tile that fits, so the
     grid stays solid however the shuffle deals them out. */
  grid-auto-flow:dense}
@media (min-width:700px){.gallery{grid-template-columns:repeat(3,1fr)}}
@media (min-width:1100px){.gallery{grid-template-columns:repeat(4,1fr)}}

/* The best photographs get four times the area. A wall of identical squares
   says every shot is equally good, which drags the strong ones down to the
   average. On a phone a hero spans the full width, which is the right place
   for the one image worth stopping on. */
.shot--hero{grid-column:span 2;grid-row:span 2}

/* Same gold frame as the rest of the site, held at the deep end of the ramp.
   Full strength gold competes with the photograph it is meant to hold. */
.shot{position:relative;display:block;width:100%;padding:0;margin:0;
  aspect-ratio:1;overflow:hidden;cursor:zoom-in;
  border:2px solid var(--gold-lo);border-radius:var(--r-lg);
  box-shadow:var(--glint),var(--e2),0 0 0 1px rgba(197,164,93,.14);
  background:var(--card-bot);color:var(--chalk);
  -webkit-appearance:none;appearance:none;
  transition:border-color .25s var(--ease)}
.shot picture{display:block;width:100%;height:100%}
.shot img{width:100%;height:100%;display:block;object-fit:cover;
  transition:transform .45s var(--ease)}
.shot:focus-visible{outline:2px solid var(--gold-hi);outline-offset:3px}

.shot-zoom{position:absolute;right:.5rem;bottom:.5rem;display:grid;
  place-items:center;width:32px;height:32px;border-radius:var(--r-pill);
  color:var(--gold-hi);background:rgba(10,10,10,.7);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  opacity:0;transition:opacity .25s var(--ease),background .25s var(--ease),
    color .25s var(--ease);pointer-events:none}

@media (hover:hover){
  .shot:hover{border-color:var(--gold)}
  .shot:hover img{transform:scale(1.045)}
  .shot:hover .shot-zoom{opacity:1;background:var(--gold);color:#14110A}
}
/* No hover on a touch screen, so the badge is the only thing telling anyone
   the photo opens. It stays put there. */
@media (hover:none){.shot-zoom{opacity:1}}
.shot:focus-visible .shot-zoom{opacity:1}

@media (prefers-reduced-motion:reduce){
  .shot img{transition:none}
  .shot:hover img{transform:none}
}

/* --- photo viewer -------------------------------------------------------- */
/* [hidden] loses to any author display rule, so it has to be restated here or
   the viewer sits open over the whole page from first paint. */
.lb[hidden]{display:none}
.lb{position:fixed;inset:0;z-index:200;display:grid;place-items:center;
  padding:clamp(1rem,4vw,3rem);background:rgba(6,6,6,.94);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.lb figure{margin:0;max-width:min(1600px,100%)}
.lb img{max-width:100%;max-height:78vh;width:auto;height:auto;display:block;
  margin-inline:auto;border-radius:var(--r-md);border:2px solid var(--gold-lo)}
.lb-btn{position:absolute;display:grid;place-items:center;width:46px;height:46px;
  border-radius:var(--r-pill);border:1px solid var(--line);cursor:pointer;
  background:rgba(20,18,16,.9);color:var(--chalk);font-size:1.5rem;line-height:1;
  transition:background .2s var(--ease),color .2s var(--ease),border-color .2s var(--ease)}
.lb-btn:hover{background:var(--gold);color:#14110A;border-color:var(--gold)}
.lb-btn:focus-visible{outline:2px solid var(--gold-hi);outline-offset:3px}
.lb-close{top:clamp(.75rem,2.5vw,1.5rem);right:clamp(.75rem,2.5vw,1.5rem);font-size:1.05rem}
.lb-prev{left:clamp(.5rem,2vw,1.5rem);top:50%;transform:translateY(-50%)}
.lb-next{right:clamp(.5rem,2vw,1.5rem);top:50%;transform:translateY(-50%)}
/* Scroll is locked while this is open, so the page cannot drift behind it. */
body.lb-open{overflow:hidden}

/* Spacing that used to live in inline style attributes. Inline values cannot
   be overridden by a media query and drift every time the markup is touched,
   so the rhythm here is set once and reused. */
.rate-note strong{color:var(--chalk)}
.rate-note-lead{margin-top:1.5rem}
.rate-title-spaced{margin-top:3rem}
.rate-note-spaced{margin-top:2rem}
.sheet-cta .rate-title{margin:0 0 .5rem}
.sheet-cta .rate-note{margin:0 0 1rem;max-width:58ch}
.sheet-cta .rate-note:last-child{margin:0}
/* Links inside body copy take the gold, matching every other link on the site. */
.link-gold{color:var(--gold-text)}
/* The About intro sits directly under the header, so it does not need the full
   between-sections gap above it. */
.about-intro{padding-block:clamp(3rem,7vh,5.5rem) clamp(2rem,4vw,3rem)}

/* --- estimate form ------------------------------------------------------- */
.estimate{background:var(--char-band)}
.form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:1.15rem}
.field{display:flex;flex-direction:column;gap:.5rem}
/* An author `display` rule beats the browser's own [hidden]{display:none},
   so the conditional unit-count field would stay on screen without this. */
.field[hidden]{display:none}
.field.full{grid-column:1/-1}
.field label{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 600;
  text-transform:uppercase;font-size:.66rem;letter-spacing:.16em;color:var(--gold-text)}
.field input,.field select,.field textarea{
  background-color:var(--field-bg);border:1px solid var(--line);
  color:var(--chalk);font-family:var(--body);font-size:1rem;
  padding:.95rem 1.05rem;border-radius:var(--r-sm);
  transition:border-color .25s var(--ease),box-shadow .25s var(--ease),background .25s var(--ease)}
.field select{appearance:none;-webkit-appearance:none;cursor:pointer;
  padding-right:2.6rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%235F594F' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 1.05rem center;background-size:12px}
.field select option{background-color:var(--field-bg);color:var(--chalk)}
.field textarea{min-height:140px;resize:vertical;line-height:1.6}
.field input::placeholder,.field textarea::placeholder{color:rgba(95,89,79,.6)}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;
  border-color:var(--gold);background-color:var(--field-bg);
  box-shadow:0 0 0 4px rgba(197,164,93,.14)}
/* Required fields carry a gold dot rather than an asterisk, which reads as a
   footnote marker and makes people hunt for a footnote that is not there. */
.field:has(input[required]) label::after{content:"•";color:var(--gold-text);margin-left:.35em}

/* Chip toggles. A property manager standing in a parking lot will not type a
   paragraph, but they will tap. Radios and checkboxes are hidden behind their
   own pills, so the control stays native and keyboard-navigable. */
.opt-label{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 600;
  text-transform:uppercase;font-size:.66rem;letter-spacing:.16em;color:var(--gold-text)}
.opt-set{display:flex;flex-wrap:wrap;gap:.5rem}
.opt{position:relative;display:inline-flex}
.opt input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
/* min-height 44px, not padding alone. These get tapped one-handed on a phone
   and 44 is the smallest target that reliably hits on the first try. */
.opt span{display:flex;align-items:center;min-height:44px;
  padding:.5rem 1.05rem;border-radius:var(--r-pill);
  border:1px solid var(--line);background:var(--lift-1);color:var(--chalk);
  font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 500;
  font-size:.86rem;line-height:1.2;cursor:pointer;
  transition:background .22s var(--ease),border-color .22s var(--ease),color .22s var(--ease)}
@media (hover:hover){.opt:hover span{border-color:var(--hair);background:var(--lift-2)}}
.opt input:checked ~ span{background:var(--gold);border-color:var(--gold);
  color:#14110A;font-variation-settings:"wdth" 100,"wght" 650}
.opt input:focus-visible ~ span{outline:2px solid var(--gold-hi);outline-offset:2px}

.form-note{color:var(--muted);font-size:.9rem;margin:1.3rem 0 0}

/* --- footer -------------------------------------------------------------- */
footer{border-top:1px solid var(--line-soft);padding-block:clamp(3rem,5.5vw,4.5rem) 2rem}
.foot-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:2.5rem;margin-bottom:2.75rem}
/* Uneven columns above tablet so the contact column is wide enough to hold the
   email address on one line. Equal shares gave it less than the 244px the
   address needs, which is what forced it to wrap. */
@media (min-width:1000px){
  .foot-grid{grid-template-columns:1.15fr 1.5fr .9fr}
}
.foot-grid .foot-h{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 600;
  text-transform:uppercase;font-size:.68rem;letter-spacing:.18em;color:var(--gold-text);margin:0 0 1.1rem}
/* The email is one unbreakable 244px string in a ~225px column, so without
   break-word it spills across the gutter into Hours. Chromium happens to
   leave a few px of clearance; Safari and any zoom level do not. */
.foot-grid p,.foot-grid a{color:var(--muted);text-decoration:none;font-size:.95rem;
  margin:0 0 .45rem;display:block;line-height:1.55;overflow-wrap:break-word;
  transition:color .25s var(--ease)}
/* A link inside a heading must not pick up the link font-size. Both selectors
   have the same specificity and this one comes later, so without it Stephen's
   name rendered at .95rem while the other three column headings sat at .68rem. */
.foot-grid .foot-h a{font-size:inherit;letter-spacing:inherit;text-transform:inherit;
  font-variation-settings:inherit;margin:0;display:inline}
/* The address is a single unit. Let it size down rather than break. */
.foot-grid a[href^="mailto"]{overflow-wrap:normal;white-space:nowrap;
  font-size:clamp(.78rem,.62rem + .42vw,.95rem)}
.foot-grid a:hover{color:var(--gold-text)}

/* The phone is the one line in here anybody actually taps, so it stops looking
   like the email's twin. */
.foot-grid a[href^="tel:"]{color:var(--chalk);font-size:1.05rem;letter-spacing:-.01em;
  margin-bottom:.55rem}
.foot-grid a[href^="tel:"]:hover{color:var(--gold-text)}

/* Stacked on a phone, the three groups had the same space between them as
   inside them, so they read as one long list and Hours looked like part of the
   contact block. A hairline does the grouping that columns do on a wide
   screen, and the inside of each group tightens up to match. */
@media (max-width:639px){
  /* Forced to one column, because auto-fit was giving two from about 480px up
     and a divider drawn above a block that sits beside another block reads as
     a mistake. The rule only makes sense when the groups are stacked. */
  .foot-grid{grid-template-columns:1fr;gap:0}
  .foot-grid>div+div{margin-top:1.7rem;padding-top:1.7rem;
    border-top:1px solid var(--line-soft)}
  .foot-grid .foot-h{margin-bottom:.7rem}
  .foot-grid p,.foot-grid a{margin-bottom:.3rem}
  .foot-grid a[href^="tel:"]{margin-bottom:.4rem}
}

/* Social row. Mark plus label in a pill, so the destination is readable
   without hovering. 44px floor stays, these get tapped on a phone. */
.foot-social{display:flex;flex-wrap:wrap;gap:.6rem;margin-bottom:2.5rem}
/* Icon only. The aria-label carries the name, so a screen reader still hears
   which service each one is while the footer stays a row of marks rather than
   a row of words. Square rather than pill now there is no text to sit beside. */
.foot-social a{display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;padding:0;
  border-radius:var(--r-pill);border:1px solid var(--line);background:var(--lift-1);
  color:var(--muted);text-decoration:none;
  font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 550;
  font-size:.8rem;letter-spacing:.01em;
  transition:color .25s var(--ease),background .25s var(--ease),border-color .25s var(--ease)}
.foot-social svg{flex:none}
.foot-social a:hover{color:var(--gold-text);border-color:var(--hair);background:var(--lift-2)}
.foot-social a:focus-visible{outline:2px solid var(--gold-hi);outline-offset:2px}
/* One full-width line rather than two spans pushed to opposite ends. Split
   across a wide footer they read as two unrelated notes; chained with the
   same interpunct the rest of the site uses, they read as one. */
.colophon{border-top:1px solid var(--line-soft);padding-top:1.6rem;margin:0;
  font-size:.8rem;line-height:1.7;color:var(--muted)}

/* --- focus + motion ------------------------------------------------------ */
:focus-visible{outline:2px solid var(--gold-hi);outline-offset:3px;border-radius:4px}

.reveal{opacity:0;transform:translateY(18px);
  transition:opacity .85s var(--out),transform .85s var(--out)}
.reveal.in{opacity:1;transform:none}

/* children stagger in behind their section — the small delay is what makes it
   feel composed rather than everything arriving at once */
.chips>*,.unit-cols>*,.price-cols>*,.step{
  opacity:0;transform:translateY(14px);
  transition:opacity .7s var(--out),transform .7s var(--out)}
.reveal.in .chips>*,.reveal.in .unit-cols>*,.reveal.in .price-cols>*,
.reveal.in .step{opacity:1;transform:none}
.reveal.in .chips>*:nth-child(1),.reveal.in .unit-cols>*:nth-child(1),
.reveal.in .price-cols>*:nth-child(1),.reveal.in .step:nth-child(1){transition-delay:.06s}
.reveal.in .chips>*:nth-child(2),.reveal.in .unit-cols>*:nth-child(2),
.reveal.in .price-cols>*:nth-child(2),.reveal.in .step:nth-child(2){transition-delay:.12s}
.reveal.in .chips>*:nth-child(3),.reveal.in .unit-cols>*:nth-child(3),
.reveal.in .price-cols>*:nth-child(3),.reveal.in .step:nth-child(3){transition-delay:.18s}
.reveal.in .chips>*:nth-child(4),.reveal.in .step:nth-child(4){transition-delay:.24s}
.reveal.in .chips>*:nth-child(5),.reveal.in .step:nth-child(5){transition-delay:.3s}
.reveal.in .chips>*:nth-child(6){transition-delay:.36s}

/* --- responsive ---------------------------------------------------------- */
@media (max-width:900px){
  /* The mark leads on a phone too. It is sized off the viewport so it stays
     big without pushing the estimate button off the first screen, which is
     what happened the last time this was tuned. */
  /* Tighter on a phone. The mark on top costs vertical space the old
     side-by-side layout did not, and the estimate button was landing well
     below the fold. The header is sticky and carries the phone number, so
     there is always a live action on screen, but the first screen should
     still get close to one. */
  .hero{padding-block:1.75rem 2.5rem}
  .hero-grid{gap:1rem}
  .hero-sub{margin-top:1.35rem}
  .cta-row{margin-top:1.5rem}
  .hero-logo{width:clamp(150px,42vw,215px);margin-top:0;
    /* Desktop's shadow is tuned for a much larger mark. That blur radius at
       this size just greys the artwork out. */
    filter:drop-shadow(0 8px 18px rgba(0,0,0,.35))}
  .hero::before{inset:-10% 0 40% 0}
  .vac-grid{grid-template-columns:1fr}
  .sheet-cta{flex-direction:column;align-items:flex-start}
  .sheet-cta .btn{width:100%}
}
@media (max-width:760px){
  /* Only the same-page anchors go. Those sections are all reachable by
     scrolling, so hiding them costs nothing. About is a separate page, and
     hiding it left a phone with no route to that page at all once the
     Sections column came out of the footer. */
  .nav-links a[href^="/#"],.nav-links a[href^="#"]{display:none}
  .nav-links a{padding:.5rem .6rem}
  .step{grid-template-columns:1fr;gap:.5rem}
  .mark i{display:none}
  .cta-row .btn{flex:1 1 100%}
  /* Logo + wordmark + phone button overrun a 390px viewport at full size,
     which widens the document and cuts text off mid-word everywhere below.
     Shrink all three so the bar fits. */
  .bar{gap:.7rem;min-height:66px}
  .mark img{height:36px}
  .mark b{font-size:.76rem;letter-spacing:.01em}
  nav .btn{padding:.8em 1.1em;font-size:.68rem;letter-spacing:.06em}
}
@media (max-width:380px){
  .mark b{font-size:.7rem}
  nav .btn{padding:.75em .9em;font-size:.64rem;letter-spacing:.03em}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important;
    transition-delay:0ms!important}
  .band::before{transform:scaleX(1)}
  .reveal,.hero-logo,.chips>*,.unit-cols>*,.price-cols>*,.step{
    opacity:1;transform:none}
}

/* --- service area map ----------------------------------------------------- */
/* The county NAME is the control, which is what was asked for. Buttons are
   natively focusable, so hover, tap and keyboard all drive the same state —
   a hover-only map is invisible to every phone user, and they are most of
   this audience. */
.map-grid{display:grid;grid-template-columns:.85fr 1.15fr;
  gap:clamp(2rem,5vw,3.5rem);align-items:start}
.county-list{display:flex;flex-wrap:wrap;gap:.6rem;margin:0 0 1.6rem;padding:0;list-style:none}
.county-btn{font:inherit;cursor:pointer;padding:.7rem 1.25rem;border-radius:var(--r-pill);
  border:1px solid var(--line);background:var(--card-top);color:var(--muted);
  font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 600;
  text-transform:uppercase;font-size:.75rem;letter-spacing:.11em;
  transition:color .3s var(--ease),border-color .3s var(--ease),
             background .3s var(--ease),transform .3s var(--out)}
.county-btn:hover{color:var(--chalk);border-color:rgba(197,164,93,.45);transform:translateY(-2px)}
.county-btn[aria-pressed="true"]{color:#150F05;border-color:transparent;
  background:linear-gradient(160deg,var(--gold-hi),var(--gold) 44%,var(--gold-lo));
  box-shadow:0 8px 20px -12px rgba(197,164,93,.85)}

.county-detail{min-height:8.5rem}
.county-detail h3{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 700;
  font-size:1.3rem;letter-spacing:-.018em;margin:0 0 .5rem;text-transform:none;color:var(--chalk)}
.county-detail p{margin:0;color:var(--muted);max-width:46ch}
.county-detail .towns{margin-top:.9rem;color:var(--gold-text);font-size:.93rem}

.map{background:var(--card-top);border:1px solid var(--line);
  border-radius:var(--r-xl);box-shadow:var(--glint),var(--e2);
  padding:clamp(.75rem,1.6vw,1.1rem)}
/* Scoped to the fallback map by id. As `.map svg` it also matched the tiny
   flag SVG inside Leaflet's attribution control and stretched it to the
   full width of the card. */
#svgmap{width:100%;height:auto;display:block;overflow:visible}
/* An id selector beats the UA stylesheet's [hidden]{display:none}, so without
   this the fallback map keeps rendering underneath the live one. */
#svgmap[hidden]{display:none}
.leaflet-control-attribution svg{width:auto;height:auto;display:inline}
.county rect{fill:var(--county-fill);stroke:var(--county-stroke);stroke-width:1.5;
  transition:fill .35s var(--ease),stroke .35s var(--ease)}
.county .cname{fill:var(--muted);font-family:var(--display);font-size:15px;
  font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  transition:fill .35s var(--ease)}
.county.on rect{fill:var(--gold);stroke:var(--gold-hi)}
.county.on .cname{fill:#150F05}
.map .pin{fill:var(--gold-hi)}
.map .pin-label{fill:var(--muted);font-family:var(--display);font-size:11px;letter-spacing:.04em}
.county.on .pin{fill:#150F05}
.county.on .pin-label{fill:#2A1F08}
.map .home{fill:var(--gold-hi);stroke:var(--ink);stroke-width:1.5}
.map .home-label{fill:var(--gold-hi);font-family:var(--display);font-size:11.5px;
  font-weight:700;letter-spacing:.06em}
.county.on .home{fill:var(--ink);stroke:var(--gold-hi)}
.county.on .home-label{fill:#150F05}
.map-note{margin:1rem 0 0;font-size:.82rem;color:var(--muted);text-align:center}

@media (max-width:820px){
  .map-grid{grid-template-columns:1fr}
  .county-detail{min-height:0;margin-bottom:1.75rem}
}

/* --- about page ----------------------------------------------------------- */
/* One column. The portrait is a round mark above the writing now, not a panel
   beside it, so there is no second column left to balance. */
.about-grid{display:grid;grid-template-columns:1fr;justify-items:center}
.about-grid .about-body{max-width:66ch}
/* A round portrait sitting on its own centre line, directly under the heading,
   with the bio underneath it. The gold ring is the same one the gallery tiles
   carry, held at the deep end of the ramp so it frames the photograph rather
   than competing with it.
   The image is already cropped square, so the circle never distorts him. */
.portrait{margin:0 auto 2.5rem;width:clamp(210px,52vw,260px);
  display:flex;flex-direction:column;align-items:center;gap:.9rem}
.portrait picture{display:block;width:100%;aspect-ratio:1;border-radius:50%;
  overflow:hidden;border:2px solid var(--gold-lo);background:var(--card-top);
  box-shadow:var(--glint),var(--e2),0 0 0 1px rgba(197,164,93,.14)}
.portrait img{width:100%;height:100%;display:block;object-fit:cover}
.portrait figcaption{padding:0;color:var(--muted);font-size:.86rem;
  text-align:center;border:0}
/* .about-body p is (0,1,1) and would otherwise beat a bare .lede (0,1,0),
   dropping the opening line back to muted body colour. */
.about-body .lede{font-size:clamp(1.1rem,1rem + .5vw,1.3rem);color:var(--chalk);
  max-width:54ch;margin:0 0 1.5rem;line-height:1.6}
.about-body p{color:var(--muted);max-width:62ch;margin:0 0 1.15rem}
.about-body p:last-child{margin-bottom:0}
.creed{list-style:none;margin:0;padding:0;display:grid;gap:.85rem}
.creed li{position:relative;padding-left:1.85rem;color:var(--muted)}
.creed li::before{position:absolute;left:0;top:.6em}
.creed li b{color:var(--chalk);font-weight:600}
.perks{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
  gap:clamp(.9rem,1.6vw,1.25rem)}
.perk{background:linear-gradient(135deg,rgba(197,164,93,.1),var(--card-top) 55%,var(--card-bot));
  border:1px solid rgba(197,164,93,.24);border-radius:var(--r-lg);
  box-shadow:var(--glint),var(--e2);padding:clamp(1.5rem,2.6vw,2rem)}
.perk h3{font-family:var(--display);font-variation-settings:"wdth" 100,"wght" 700;
  font-size:1.08rem;letter-spacing:-.012em;margin:0 0 .55rem;text-transform:none}
.perk p{margin:0;color:var(--muted);font-size:.95rem;line-height:1.62}
.nav-links a.current{color:var(--gold)}
@media (max-width:820px){
  .about-grid{grid-template-columns:1fr}
  .portrait{max-width:460px}
}

/* --- leaflet map ---------------------------------------------------------- */
/* Real tiles, dark basemap. The SVG below it stays in the markup as a fallback
   and is only hidden once Leaflet has actually loaded, so a blocked CDN or a
   dead connection still leaves a usable map of the service area. */
#leafmap{height:clamp(340px,46vw,470px);border-radius:var(--r-lg);
  background:var(--map-bg);z-index:1}
#leafmap.ready{outline:1px solid var(--line)}
.leaflet-container{background:var(--map-bg);font-family:var(--body)}
.leaflet-control-zoom a{background:var(--card-top);color:var(--gold-text);
  border-color:var(--line)}
.leaflet-control-zoom a:hover{background:var(--card-top-hi);color:var(--chalk)}
.leaflet-bar{border:1px solid var(--line);box-shadow:var(--e2)}
/* Credits collapse behind the "i" button. Row layout so the panel opens to the
   left of the button rather than stacking above it. */
/* row-reverse: the toggle is first in the DOM, so reversing keeps it pinned to
   the right edge and lets the panel expand leftward instead of shoving the
   button sideways every time it opens. */
.leaflet-bottom.leaflet-right{max-width:100%;display:flex;flex-direction:row-reverse;
  align-items:flex-end}
.leaflet-control-attribution{display:none;background:var(--attr-bg)!important;
  color:var(--muted)!important;font-size:10px;line-height:1.45;
  padding:4px 8px!important;border-radius:var(--r-sm);
  max-width:min(66vw,290px);white-space:normal;
  border:1px solid var(--line)}
.leaflet-control-attribution.open{display:block}
.attr-toggle{flex:none;width:24px;height:24px;border-radius:50%;padding:0;
  margin:0 6px 6px 6px;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  background:rgba(10,10,10,.86);color:var(--gold);
  border:1px solid var(--line);
  font-family:var(--display);font-size:12px;font-weight:800;line-height:1;
  font-style:italic;
  transition:color .25s var(--ease),border-color .25s var(--ease),
             background .25s var(--ease)}
.attr-toggle:hover{color:var(--chalk);border-color:rgba(197,164,93,.75);
  background:rgba(10,10,10,.95)}
.leaflet-control-attribution a{color:var(--gold-text)!important}
.city-label{background:var(--map-label-bg);border:1px solid var(--line);
  border-radius:var(--r-pill);color:var(--chalk);
  font-family:var(--display);font-size:10.5px;font-weight:600;
  letter-spacing:.05em;text-transform:uppercase;
  padding:2px 8px;box-shadow:none;white-space:nowrap}
.city-label::before{display:none}
.home-label-tip{background:linear-gradient(160deg,var(--gold-hi),var(--gold) 45%,var(--gold-lo));
  border:0;color:#150F05;font-weight:800}
.leaflet-popup-content-wrapper{background:var(--card-top-hi);color:var(--chalk);
  border:1px solid var(--line);border-radius:var(--r-md)}
.leaflet-popup-tip{background:var(--card-top-hi);border:1px solid var(--line)}
.leaflet-popup-content{font-family:var(--body);margin:.7rem .95rem}
.leaflet-popup-content b{font-family:var(--display);color:var(--gold-text)}
