/* ═══════════════════════════════════════════════════════════════════════
   QUICKS — the shell.

   Everything shared by every page: tokens, the masthead, the footer, type,
   buttons, tables, the paper panel. The homepage additionally carries its
   own stylesheet inline (the chair, the intro, the razor); this file is
   loaded first there so those rules win on ties and the approved homepage
   design is untouched.

   Palette rule that is doing real work: black and bone only, with pole red
   as the single saturated colour. Red appears on section ornaments, today's
   opening hours and the star rating — nowhere else. Scarcity is what makes
   it magnetic. CTAs are bone on black (17.7:1, AAA) rather than red on
   black (3.8:1, which fails AA).
   ═══════════════════════════════════════════════════════════════════════ */

:root{
  --night:#0C0A08; --room:#16120E; --deep:#070504;
  --bone:#F5F2ED; --smoke:#8E8A84; --faint:#7C7872;
  --red:#C7392C; --red-lite:#DC4A3E; --steel:#9AA3A8;
  --paper:#F2EDE3; --ink:#151210; --ink-mut:#5B5751;
  --sign:"Oswald",Impact,sans-serif;
  --body:"Inter",system-ui,-apple-system,sans-serif;
  --board:"Anonymous Pro",ui-monospace,Menlo,monospace;
  --g:clamp(20px,5vw,72px);
  color-scheme:dark;
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--night);color:var(--bone);font-family:var(--body);
  font-size:17px;line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden}
img,picture,svg{max-width:100%}
picture{display:block}
picture img{display:block;width:100%;height:auto}
a{color:inherit}

/* grain, so no field is ever a flat digital black */
body::after{content:"";position:fixed;inset:0;z-index:60;pointer-events:none;
  opacity:.48;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.4'/%3E%3C/svg%3E")}
@media print{body::after{display:none}}

.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:-9999px;top:0;z-index:100;background:var(--bone);
  color:#0A0A0A;padding:12px 18px;font-family:var(--board);font-size:12px;
  letter-spacing:.18em;text-transform:uppercase;text-decoration:none}
.skip:focus{left:8px;top:8px}
:focus-visible{outline:2px solid var(--red-lite);outline-offset:3px}

/* ── type ─────────────────────────────────────────────────────────── */
.sign{font-family:var(--sign);font-weight:500;text-transform:uppercase;
  letter-spacing:.03em;line-height:1;margin:0;text-wrap:balance}
.plate{font-family:var(--board);font-size:11px;letter-spacing:.24em;
  text-transform:uppercase;color:var(--smoke);margin:0}
.lead{font-size:clamp(1.05rem,1.9vw,1.24rem);color:var(--smoke);max-width:60ch;
  line-height:1.62}
.wrap{max-width:1180px;margin:0 auto;padding:0 var(--g)}
.wrap--n{max-width:760px}

/* letterpress ornament — rule, dot, rule. Turns an <h2> into a title page. */
.orn{--oc:var(--red);display:flex;align-items:center;gap:9px;margin:0 0 16px}
.orn::before,.orn::after{content:"";height:1px;flex:0 0 clamp(30px,6vw,74px)}
.orn::before{background:linear-gradient(90deg,transparent,var(--oc))}
.orn::after{background:linear-gradient(90deg,var(--oc),transparent)}
.orn i{flex:0 0 auto;width:4px;height:4px;border-radius:50%;background:var(--oc);
  box-shadow:0 0 0 3px rgba(199,57,44,.15)}
.orn--c{justify-content:center}

/* ── buttons ──────────────────────────────────────────────────────── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--board);font-size:12.5px;letter-spacing:.2em;text-transform:uppercase;
  padding:17px 30px;background:var(--bone);color:#0A0A0A;text-decoration:none;border:0;
  cursor:pointer;transition:background .2s,transform .2s;min-height:44px}
.btn:hover{background:#fff;transform:translateY(-1px)}
.btn--ghost{background:transparent;color:var(--bone);box-shadow:inset 0 0 0 1px rgba(245,242,237,.3)}
.btn--ghost:hover{background:transparent;box-shadow:inset 0 0 0 1px var(--bone)}
.btn--sm{padding:11px 18px;font-size:11px;letter-spacing:.18em}
.out{display:inline-flex;align-items:center;gap:6px}
.ext{width:12px;height:12px;flex:0 0 auto;opacity:.75;margin-bottom:1px}
.out:hover .ext{opacity:1}

/* ── masthead ─────────────────────────────────────────────────────── */
/* The scrim used to reach .72 alpha by 62% of its height and zero by the
   bottom -- and the nav text sits at y 20-52 of a 72px header, i.e. right in
   the part that had faded. Over the shop photos the links measured 2.9:1 at
   rest and 3.0:1 scrolled, against the 4.5:1 they need. The fade is now spent
   entirely BELOW the text: solid to 74%, gone by 100%, so the soft edge into
   the page is kept and nothing legible sits on it. */
.top{position:fixed;top:0;left:0;right:0;z-index:40;display:flex;align-items:center;
  justify-content:space-between;gap:16px;padding:14px var(--g);
  background:linear-gradient(180deg,rgba(12,10,8,.97) 0%,rgba(12,10,8,.95) 74%,
    rgba(12,10,8,.5) 88%,rgba(12,10,8,0) 100%)}
.top .mk{display:block;overflow:hidden}
.top .mk img{height:32px;width:auto;display:block}
.top .mk picture{width:auto}
.mk-a{text-decoration:none;flex:0 0 auto}
.top a{text-decoration:none}
.top__r{display:flex;align-items:center;gap:clamp(10px,2vw,22px)}
.nav{display:flex;gap:clamp(14px,2.2vw,30px);font-family:var(--board);font-size:11.5px;
  letter-spacing:.2em;text-transform:uppercase;color:var(--smoke)}
.nav a{padding:6px 0;transition:color .18s;border-bottom:1px solid transparent}
.nav a:hover{color:var(--bone)}
.nav a[aria-current="page"]{color:var(--bone);border-bottom-color:var(--red)}
@media (max-width:900px){.nav{display:none}.hide-s{display:none}}

/* ══ mobile navigation ════════════════════════════════════════════════
   .nav goes to display:none below 900px and nothing replaced it, so a phone
   had a masthead of a logo and a Book button and no way to reach Haircuts,
   Barbers, Shop or Visit except the footer. */
.burger{display:none;appearance:none;background:none;border:0;cursor:pointer;
  width:44px;height:44px;padding:11px 10px;flex-direction:column;
  justify-content:space-between;align-items:stretch}
.burger span{display:block;height:2px;background:var(--bone);border-radius:2px;
  transition:transform .28s cubic-bezier(.2,.8,.2,1),opacity .18s}
.burger[aria-expanded="true"] span:nth-child(1){transform:translateY(9px) rotate(45deg)}
.burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-9px) rotate(-45deg)}
.mnav{display:none}
/* opaque while the panel is open -- see the note in shell.js */
/* No .paper variants here: the masthead sits OUTSIDE main, so `.paper .top`
   never matches -- the header is dark on every page, light theme or not. */
.top.nav-open{background:var(--night)}
@media (max-width:900px){
  .burger{display:flex}
  .top{flex-wrap:wrap}
  /* A dark panel on a dark page is not a panel, it is just more page -- the
     first version blended straight into whatever was under it. It is now a
     bone SHEET: the one surface on this site that is unmistakably a layer on
     top, and the same colour the Book button already uses. */
  /* flex-basis has to carry the extra width, not just the margin: at 100% the
     panel keeps the CONTENT box width and the negative right margin only
     shifts it, leaving a strip of page showing down the right-hand side. */
  .mnav{display:block;order:3;
    flex-basis:calc(100% + var(--g) * 2);
    margin:14px calc(var(--g) * -1) calc(var(--g) * -1);
    background:var(--bone);padding:6px var(--g) 10px;
    box-shadow:0 18px 40px rgba(0,0,0,.55)}
  .mnav[hidden]{display:none}
  .mnav a{display:block;padding:16px 2px;text-decoration:none;color:#141210;
    font-family:var(--sign);font-weight:500;font-size:1.45rem;letter-spacing:.02em;
    text-transform:uppercase;line-height:1.1;min-height:24px;
    border-bottom:1px solid rgba(21,18,16,.12)}
  .mnav a:last-child{border-bottom:0}
  .mnav a[aria-current]{color:var(--red)}
  .mnav a[aria-current]::after{content:"";display:inline-block;width:8px;height:8px;
    border-radius:50%;background:var(--red);margin-left:10px;vertical-align:middle}
}

/* the cart, in the corner where people look for it */
.cartbtn{display:none;appearance:none;background:none;border:0;cursor:pointer;
  color:var(--bone);position:relative;width:44px;height:44px;padding:10px;
  align-items:center;justify-content:center}
.cartbtn[hidden]{display:none!important}
.cartbtn:not([hidden]){display:inline-flex}
.cartbtn svg{width:22px;height:22px;display:block}
.cartbtn b{position:absolute;top:3px;right:2px;min-width:17px;height:17px;
  border-radius:9px;background:var(--red-lite);color:#fff;font-family:var(--board);
  font-size:10px;font-weight:400;line-height:17px;text-align:center;padding:0 4px}

/* ── breadcrumb ───────────────────────────────────────────────────── */
.crumb{font-family:var(--board);font-size:11px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--faint);margin:0 0 clamp(22px,4vw,38px);
  display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.crumb a{text-decoration:none}
.crumb a:hover{color:var(--bone)}
/* 24px is the WCAG 2.2 floor and three links had slipped under it: the
   breadcrumb, the footer phone number and the hero's "every price" line. */
.crumb a,.crumb span{display:inline-flex;align-items:center;min-height:24px}
.crumb>*+*::before{content:"/";margin-right:8px;color:#4A463F}
.crumb span{color:var(--smoke)}

/* ── interior page head ───────────────────────────────────────────── */
.ph{padding:calc(88px + clamp(38px,7vw,88px)) 0 clamp(34px,5vw,56px)}
.ph h1{font-family:var(--sign);font-weight:500;text-transform:uppercase;
  letter-spacing:.02em;line-height:1.02;margin:0 0 18px;
  font-size:clamp(2.1rem,5.2vw,3.9rem);text-wrap:balance}
.ph .lead{margin:0}
.sec{padding:clamp(40px,6vw,74px) 0;border-top:1px solid rgba(245,242,237,.08)}
.sec>h2,.sec>.wrap>h2{font-family:var(--sign);font-weight:500;text-transform:uppercase;
  letter-spacing:.03em;font-size:clamp(1.4rem,3vw,2.1rem);margin:0 0 20px;line-height:1.08}
.sec h3{font-family:var(--sign);font-weight:400;text-transform:uppercase;
  letter-spacing:.09em;font-size:1rem;margin:0 0 8px}
.sec p{color:var(--smoke);max-width:66ch}
.sec p b,.sec p strong{color:var(--bone);font-weight:500}

/* ── paper panel — the light room ─────────────────────────────────── */
.paper{background:var(--paper);color:var(--ink);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='pf'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.55' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23pf)' opacity='.05'/%3E%3C/svg%3E")}
.paper p,.paper .lead{color:#4A4844}
.paper .btn{background:#141210;color:var(--paper)}
.paper .btn:hover{background:#000}
.paper .orn{--oc:var(--red)}
.paper .sec{border-top-color:rgba(21,18,16,.12)}
.paper .prices th,.paper .prices td{border-color:rgba(21,18,16,.13)}
.paper .prices tbody th{color:var(--ink)}
.paper .prices td span{color:var(--ink-mut)}

/* ── cards ────────────────────────────────────────────────────────── */
.cards{display:grid;gap:clamp(14px,2vw,22px);
  grid-template-columns:repeat(auto-fit,minmax(min(250px,100%),1fr))}
.card{padding:clamp(20px,3vw,30px);box-shadow:inset 0 0 0 1px rgba(245,242,237,.1)}
.card h3{margin-bottom:10px}
.card p{margin:0;font-size:15.5px}
.paper .card{box-shadow:inset 0 0 0 1px rgba(21,18,16,.14)}
/* the second product image: the real jar, under the rendering */
.good__alt{display:block;margin-top:12px}
.good__alt img{width:100%;height:auto;display:block}

/* Three cards in an auto-fit grid orphan one the moment it lands on TWO
   columns -- hours and address share a row and "call the shop" sits alone
   underneath. The band where that happens is roughly 620-900px. Fix is to
   skip two columns entirely: one across, then three. There is no width left
   at which a card can be stranded.
   The alternative considered and rejected was adding a fourth card to make a
   2x2 -- that just moves the orphan to the three-column layout, and it would
   put the rating on this page for the third time. */
.cards--3{grid-template-columns:1fr}
@media(min-width:900px){.cards--3{grid-template-columns:repeat(3,1fr)}}


/* ── price table ──────────────────────────────────────────────────── */
.tw{overflow-x:auto;-webkit-overflow-scrolling:touch}
.prices{width:100%;border-collapse:collapse;min-width:520px}
.prices th,.prices td{text-align:left;padding:15px 16px;
  border-bottom:1px solid rgba(245,242,237,.11);vertical-align:top}
.prices thead th{font-family:var(--board);font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--red-lite);border-bottom-width:1px}
.prices tbody th{font-weight:400;color:var(--bone);font-size:15.5px;white-space:nowrap}
.prices td b{font-family:var(--sign);font-size:1.28rem;font-weight:500;display:block;
  letter-spacing:.01em}
.prices td span{display:block;font-family:var(--board);font-size:11px;
  letter-spacing:.14em;color:var(--smoke);margin-top:3px}
.prices .na{font-size:15px;color:var(--faint)}

/* Restack the price table on a phone rather than side-scrolling it. */
@media (max-width:680px){
  .tw{overflow:visible}
  .prices{min-width:0}
  .prices thead{display:none}
  .prices,.prices tbody,.prices tr,.prices tbody th,.prices td{display:block}
  .prices tr{padding:16px 0;border-bottom:1px solid rgba(245,242,237,.11)}
  .prices tr:last-child{border-bottom:0}
  .prices tbody th{padding:0 0 10px;border:0;font-family:var(--sign);
    text-transform:uppercase;letter-spacing:.06em;font-size:1rem;white-space:normal}
  .prices td{display:flex;align-items:baseline;gap:8px;padding:6px 0;border:0}
  .prices td::before{content:attr(data-label);font-family:var(--board);font-size:11px;
    letter-spacing:.18em;text-transform:uppercase;color:var(--smoke)}
  .prices td b{margin-left:auto;font-size:1.06rem}
  .prices td span{margin-top:0}
  .paper .prices tr{border-bottom-color:rgba(21,18,16,.13)}
  .paper .prices td::before{color:var(--ink-mut)}
}

/* ── hours ────────────────────────────────────────────────────────── */
.hrs{font-family:var(--board);font-size:13.5px;max-width:210px}
.hrs>div{display:flex;justify-content:space-between;gap:16px;padding:5px 0;
  border-bottom:1px solid rgba(245,242,237,.09)}
.hrs>div:last-child{border-bottom:0}
.hrs .today{color:var(--red-lite);font-weight:700}
.paper .hrs>div{border-bottom-color:rgba(21,18,16,.12)}
.paper .hrs .today{color:var(--red)}

/* ── Q&A — written to be quotable by an answer engine ─────────────── */
.qa{display:grid;gap:clamp(18px,2.4vw,26px);
  grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr))}
.qa__i{padding-left:16px;border-left:2px solid var(--red)}
.qa__i h3{font-family:var(--body);font-size:16px;font-weight:600;text-transform:none;
  letter-spacing:0;margin:0 0 7px;color:var(--bone)}
.paper .qa__i h3{color:var(--ink)}
.qa__i p{margin:0;font-size:15.5px;max-width:52ch}

/* ── product + roster ─────────────────────────────────────────────── */
.goods{display:grid;gap:clamp(14px,2vw,26px);
  grid-template-columns:repeat(auto-fit,minmax(min(148px,100%),1fr))}
.good{text-decoration:none;display:block}
/* a sellable card is a div wrapping a link plus its own button -- a button
   cannot live inside an anchor, and the whole tile being one link is what
   forced the extra hop in the first place */
/* The work gallery. Nine real cuts, so the grid is deliberately dense --
   the persuasion is the SPREAD (hair types, ages, fades vs scissor work),
   and a spread only reads when you can see it all at once. No lightbox: a
   modal on a phone is a tax on the thing people actually came to look at. */
.work{display:grid;gap:8px;margin:0 0 clamp(30px,5vw,52px);
  grid-template-columns:repeat(2,1fr)}
/* Nine photos, so the grid is pinned to 3 across rather than auto-fit --
   auto-fit gave six then a ragged three, and a gallery that does not close
   its own rectangle reads as unfinished no matter how good the pictures. */
@media(min-width:700px){.work{grid-template-columns:repeat(3,1fr);gap:10px}}
.work__i{overflow:hidden;background:var(--deep);aspect-ratio:4/5}
.work__i img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .7s cubic-bezier(.2,.7,.3,1)}
.work__i:hover img{transform:scale(1.04)}
@media(prefers-reduced-motion:reduce){.work__i img{transition:none}
  .work__i:hover img{transform:none}}

.good__go{text-decoration:none;display:block;color:inherit}
.good__buy{width:100%;margin-top:10px}
.good__img{background:#F5F2ED;aspect-ratio:1;overflow:hidden;margin-bottom:12px}
.good__img img{width:100%;height:100%;object-fit:cover}
.good h3{font-family:var(--sign);font-weight:400;text-transform:uppercase;
  letter-spacing:.07em;font-size:.94rem;margin:0 0 3px}
.good p{margin:0;font-family:var(--board);font-size:12px;letter-spacing:.12em;
  color:var(--smoke)}
.good:hover h3{color:var(--red-lite)}
.paper .good p{color:var(--ink-mut)}

.who{display:grid;gap:clamp(26px,4vw,48px);margin-top:10px}
.who__i{display:grid;gap:clamp(18px,3vw,36px);align-items:start;
  grid-template-columns:minmax(0,1fr)}
@media (min-width:760px){.who__i{grid-template-columns:minmax(230px,320px) minmax(0,1fr)}}
.who__i+.who__i{padding-top:clamp(26px,4vw,48px);
  border-top:1px solid rgba(245,242,237,.09)}
/* ⚠ Mike's photo is portrait (1100x1275) and Jay's and Gaby's are
   landscape (1000x750), so his card ran 131px taller and the roster read
   ragged. These three are peers on this page. One frame, photo fills it,
   biased upward because that is where faces are. */
.who__i > div:first-child img{aspect-ratio:1/1;object-fit:cover;
  object-position:50% 28%;width:100%;height:auto;display:block}
.who h2{font-family:var(--sign);font-weight:500;text-transform:uppercase;
  font-size:clamp(1.5rem,3.4vw,2.2rem);margin:0 0 4px;letter-spacing:.03em}
.who .role{font-family:var(--board);font-size:11px;letter-spacing:.22em;
  text-transform:uppercase;color:var(--red-lite);margin:0 0 16px}
.svc{list-style:none;padding:0;margin:0 0 22px;display:grid;gap:9px}
.svc li{display:flex;justify-content:space-between;gap:18px;align-items:baseline;
  padding-bottom:9px;border-bottom:1px solid rgba(245,242,237,.09);max-width:460px}
/* A list of buttons is not a price list: the li rule ran the full width
   of the container while the button beside it was 170px, leaving a line
   hanging off into space on /book/. */
.svc--plain{list-style:none}
.svc--plain li{display:block;border:0;padding:0}
.svc .n{color:var(--bone)}
.svc .p{font-family:var(--sign);font-size:1.16rem;white-space:nowrap}
.svc .t{font-family:var(--board);font-size:11px;letter-spacing:.13em;
  color:var(--smoke);margin-left:10px}

/* ── the storefront band — the one image that does a job ──────────── */
.front{position:relative;margin:clamp(40px,6vw,76px) 0 0}
.front picture{height:clamp(240px,42vw,460px);overflow:hidden}
.front img{width:100%;height:100%;object-fit:cover;object-position:50% 38%}
.front figcaption{position:absolute;left:0;right:0;bottom:0;padding:26px var(--g) 20px;
  background:linear-gradient(180deg,transparent,rgba(7,5,4,.86));
  font-family:var(--board);font-size:11.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--bone)}

/* ── footer ───────────────────────────────────────────────────────── */
.foot{padding:clamp(56px,8vw,100px) var(--g) 36px;display:grid;gap:36px;
  grid-template-columns:repeat(auto-fit,minmax(min(230px,100%),1fr));
  border-top:1px solid rgba(245,242,237,.08)}
.foot__mk img{height:44px;width:auto;margin-bottom:14px}
.foot__mk{width:auto}
.foot h3{font-family:var(--sign);font-weight:400;text-transform:uppercase;letter-spacing:.16em;
  font-size:11px;color:var(--red-lite);margin:0 0 12px}
.foot p,.foot li{color:var(--smoke);font-size:15px;margin:0 0 7px}
.foot ul{list-style:none;padding:0;margin:0}
.foot a{text-decoration:none}
/* Same 24px floor. The footer phone number was 20px tall. */
.foot__c a,.foot .stars a{display:inline-flex;align-items:center;min-height:24px}
.foot a:hover{color:var(--bone)}
/* WCAG 2.2 target size: footer and masthead links were 11-18px tall. */
.foot li a,.foot p a,.mini a{display:inline-flex;align-items:center;min-height:24px}
/* Scoped to wide viewports on purpose: unscoped, .top .plate (0,2,0) beats
   .hide-s (0,1,0) and the plates reappear on a phone, pushing the Book
   button off the edge of a masthead that clips rather than scrolls. */
@media (min-width:901px){
  .top .plate{display:inline-flex;align-items:center;min-height:24px}
}
/* The 4.9 is the strongest asset this shop has, and until now the star
   only appeared in the footer — the masthead, which is on every screen,
   carried none. Red here is earned: outside the pole and the live dot it
   is the only decoration it is spent on. */
.foot .stars a{color:var(--bone)}
.foot .stars .stars__s{color:var(--red-lite);letter-spacing:.06em}
.plate__star{color:var(--red-lite);font-size:12px;line-height:1}
.mini{display:flex;flex-wrap:wrap;gap:14px;margin-top:18px!important}
.mini li{font-family:var(--board);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;margin:0}
.social{display:flex;gap:10px;flex-wrap:wrap}
.social__a{display:inline-flex;align-items:center;gap:9px;padding:9px 13px 9px 11px;
  color:var(--smoke);text-decoration:none;min-height:44px;
  box-shadow:inset 0 0 0 1px rgba(245,242,237,.16);
  transition:color .2s,box-shadow .2s,transform .2s}
.social__a svg{width:19px;height:19px;display:block;flex:0 0 auto}
.social__a span{font-family:var(--board);font-size:11.5px;letter-spacing:.14em}
.social__a:hover{color:var(--bone);box-shadow:inset 0 0 0 1px var(--bone);transform:translateY(-1px)}
.fine{padding:0 var(--g) 42px;display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap}

/* ── long-form (policies) ─────────────────────────────────────────── */
.doc h2{font-family:var(--sign);font-weight:500;text-transform:uppercase;
  letter-spacing:.05em;font-size:1.12rem;margin:36px 0 12px;color:var(--bone)}
.doc p,.doc li{color:var(--smoke);font-size:16px;max-width:72ch}
.doc ul{padding-left:20px}
.doc a{color:var(--red-lite)}

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

/* ══ the cart ══════════════════════════════════════════════════════════
   Bone on black like every other CTA (17.7:1) -- no new colour, the red
   stays scarce. The pill is hidden until there is something in the order,
   so an empty shop never shows an empty basket.

   z-index: the grain overlay sits at 60 and is pointer-events:none, so the
   drawer goes above it at 70 and the pill below it at 45, over the
   masthead's 40. */
.cartpill{position:fixed;right:clamp(14px,4vw,28px);bottom:clamp(14px,4vw,28px);
  z-index:45;border:0;cursor:pointer;min-height:48px;padding:14px 22px;
  background:var(--bone);color:#0A0A0A;font-family:var(--board);
  font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;
  box-shadow:0 12px 34px rgba(0,0,0,.55)}
.cartpill:hover{background:#fff}
.cart[hidden],.cartpill[hidden]{display:none}
.cart{position:fixed;inset:0;z-index:70;display:flex;justify-content:flex-end}
.cart__veil{position:absolute;inset:0;background:rgba(5,4,3,.72)}
.cart__box{position:relative;width:min(430px,100%);background:var(--room);
  color:var(--bone);padding:clamp(20px,4vw,30px);overflow-y:auto;
  display:flex;flex-direction:column;gap:16px;
  box-shadow:-20px 0 60px rgba(0,0,0,.6)}
.cart__top{display:flex;align-items:baseline;justify-content:space-between;gap:16px}
.cart__top h2{font-family:var(--sign);font-weight:500;text-transform:uppercase;
  letter-spacing:.04em;font-size:1.5rem;margin:0}
.cart__x{background:none;border:0;color:var(--smoke);cursor:pointer;
  font-family:var(--board);font-size:11px;letter-spacing:.16em;
  text-transform:uppercase;min-height:44px;padding:0 4px}
.cart__x:hover{color:var(--bone)}
.cart__list{list-style:none;margin:0;padding:0;display:grid;gap:14px}
.cart__list li{display:grid;grid-template-columns:1fr auto auto;gap:12px;
  align-items:center;padding-bottom:14px;
  border-bottom:1px solid rgba(245,242,237,.1)}
.cart__n{font-size:15px;line-height:1.3}
.cart__q{display:inline-flex;align-items:center;gap:2px}
.cart__q button{width:36px;height:44px;background:none;cursor:pointer;
  border:1px solid rgba(245,242,237,.22);color:var(--bone);font-size:16px;
  line-height:1}
.cart__q button:hover{border-color:var(--bone)}
.cart__q b{min-width:34px;text-align:center;font-family:var(--board);
  font-weight:400;font-size:14px}
.cart__p{font-family:var(--sign);font-size:1.1rem;min-width:70px;text-align:right}
.cart__sum{margin:0;font-family:var(--sign);font-size:1.35rem;
  text-transform:uppercase;letter-spacing:.03em}
.cart__ful{display:grid;gap:10px}
.cart__ful label{display:flex;align-items:center;gap:10px;font-size:14.5px;
  min-height:44px;cursor:pointer}
.cart__ful input{accent-color:var(--bone);width:17px;height:17px}
.cart__go{width:100%}
.cart__go[disabled]{opacity:.45;cursor:not-allowed}
/* THE CHAIR PRICE. Red is the pole, the 4.9 and the live dot -- the palette
   rule is that it is never spent on decoration. An offer that changes what
   someone pays is the one other thing that earns it, and it earns it as a
   3px rule on the edge rather than as a field of colour. */
.deal{margin:22px 0 0;padding:14px 0 14px 16px;border-left:3px solid var(--red);
  font-size:15px;line-height:1.55;color:var(--smoke);max-width:60ch}
.deal b{color:var(--bone);font-weight:500}
.deal i{font-style:normal;color:var(--bone)}
/* The block is a <p>, so an inline-block button flowed INTO the sentence
   — "Good for 30 days. [BOOK A CUT]" mid-paragraph. flex gives it a
   block-level box so it drops to its own line, and fit-content stops it
   stretching the full column. */
.deal .btn{display:flex;width:fit-content;margin-top:14px}
.cart__deal{margin:0;font-size:13.5px;line-height:1.5;color:var(--smoke);
  padding-left:12px;border-left:2px solid rgba(199,57,44,.55)}
.cart__deal.is-on{color:var(--bone);border-left-color:var(--red)}
.cart__deal[hidden]{display:none}
.cart__say{margin:0;font-size:13.5px;color:var(--smoke);min-height:1.2em}
.cart__say a{color:var(--bone)}
@media(max-width:560px){
  .cart__box{width:100%}
  .cartpill{left:clamp(14px,4vw,28px);right:clamp(14px,4vw,28px)}
}
@media(prefers-reduced-motion:no-preference){
  .cart__box{animation:cartin .28s cubic-bezier(.2,.7,.3,1)}
  @keyframes cartin{from{transform:translateX(26px);opacity:.4}}
}
/* The drawer takes focus when it opens, and the UA default ring is red --
   which breaks the palette rule that red means ornament, today's hours and
   the rating, and nothing else. Same visibility, bone instead. */
.cart :focus-visible{outline:2px solid var(--bone);outline-offset:2px}

/* the add button sits under a price on a paper panel, so it needs the
   inverse of the dark-page treatment */
.paper .add{background:#141210;color:var(--paper)}
.cart__note{margin:0 0 8px;font-size:12px;line-height:1.45;color:var(--red-lite)}
.paper .add:hover{background:#2a2521}

/* the post-visit page: two answers, both of which reach the review link */
.fb{border-top:1px solid rgba(21,18,16,.14);padding:22px 0}
.fb summary{font-family:var(--sign);font-weight:500;text-transform:uppercase;
  letter-spacing:.04em;font-size:clamp(1.15rem,2.6vw,1.5rem);cursor:pointer;
  min-height:44px;display:flex;align-items:center}
.fb summary::marker{color:var(--red-lite)}
.fb p{max-width:60ch}
.paper .fb{border-color:rgba(21,18,16,.14)}

/* ── THE ASK-FOR-IT BOARD ──────────────────────────────────────────
   A phrasebook, not a configurator. Three rows, one sentence, one button.
   No price goes anywhere near it: prices here are per barber, and a number
   sitting next to a spec reads as a quote. */
.ask{margin-top:26px}
.ask__panel{display:grid;gap:26px;align-items:start;
  grid-template-columns:minmax(0,1fr)}
/* The head belongs BESIDE the choices, not stranded under them. Explicit
   placement: the picker and the sentence stack in column one, the drawing
   holds column two across both. Left to auto-placement it landed in the
   second row of column one and opened a dead gap the width of the page. */
@media(min-width:800px){
  .ask__panel{grid-template-columns:minmax(0,1fr) 232px;column-gap:34px}
  .ask__pick,.ask__out{grid-column:1}
  .ask__rig{grid-column:2;grid-row:1 / span 2;align-self:start}
}
.ask__pick{display:grid;gap:18px;margin:0;border:0;padding:0}
.ask__pick fieldset{border:0;margin:0;padding:0}
.ask__pick legend{font-family:var(--board);font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--smoke);padding:0;margin-bottom:9px}
.chips{display:flex;flex-wrap:wrap;gap:8px}
/* 13 guards. Tighter padding keeps the row two lines deep on a phone
   without going under the 44px tap target, which stays non-negotiable. */
.chips--many span{padding:0 12px;letter-spacing:.1em}
/* The input stays in the flow and focusable — it is only made invisible, so
   the ring lands on the chip and arrow keys still move through the group. */
.chip{position:relative;display:inline-flex}
.chip input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer}
.chip span{display:inline-flex;align-items:center;min-height:44px;padding:0 16px;
  font-family:var(--board);font-size:12px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--smoke);
  box-shadow:inset 0 0 0 1px rgba(245,242,237,.26)}
.chip input:checked+span{color:#0A0A0A;background:var(--bone);
  box-shadow:inset 0 0 0 1px var(--bone)}
.chip input:focus-visible+span{outline:2px solid var(--red-lite);outline-offset:3px}
.chip:hover input:not(:checked)+span{color:var(--bone);
  box-shadow:inset 0 0 0 1px rgba(245,242,237,.55)}

.ask__out{margin-top:4px}
.ask__say{font-family:var(--sign);font-size:clamp(1.25rem,3.4vw,1.75rem);
  line-height:1.25;color:var(--bone);margin:8px 0 18px;max-width:22ch}
.ask__say .say[hidden]{display:none}
.ask__copy{vertical-align:middle}
.ask__done{font-family:var(--board);font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--red-lite);margin-left:12px}
.ask__neck{font-size:14.5px;line-height:1.6;color:var(--smoke);margin:18px 0 0;
  max-width:52ch}
.ask__neck b{color:var(--bone);font-weight:500}

.ask__rig{width:100%;max-width:232px;height:auto;display:block;
  justify-self:center}
/* The face and the neck. The SKULL is deliberately not stroked — the outer
   edge of the hair is the head's outline, and drawing the skull under it is
   what made an earlier version read as a head wearing a cap. */
.ask__ln,.ask__line2{fill:none;stroke:var(--bone);stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;opacity:.92}
/* Flat bone; the MASK does the fading, because only a mask can follow a
   drop fade's dive behind the ear or a burst's arc around it. */
.ask__mass{fill:var(--bone)}
/* Hair tips, stroked with the SAME gradient as the mass, so the texture
   thins out exactly where the fade does. One source of truth for the fade. */
.ask__tips path{fill:none;stroke:var(--bone);stroke-width:1;stroke-linecap:round;opacity:.9}
.ask__ln--thin{stroke-width:1.3;opacity:.7}
/* No hatching: the mass carries tone, the mask carries the fade, the
   outline carries the form. See ASK_TEXTURE in build.py. */
.ask__mass{opacity:.42}
.ask__hair[hidden]{display:none}
/* The ear punches through the hair in the page's own colour — on a fade the
   ear is exposed, and hair drawn over it is the tell that nobody looked at
   a real head. */
.ask__earfill{fill:var(--night)}
/* Stroked, not filled — see ASK_SCALP in build.py for why that is load-bearing. */

/* The one red thing here, and it earns it: it marks WHERE the fade starts,
   which is the single fact the whole feature exists to explain. */
.ask__cut{stroke:var(--red);stroke-width:1.5;stroke-dasharray:4 5;opacity:.85}

.ask__defs{margin-top:30px;padding-top:22px;
  border-top:1px solid rgba(245,242,237,.14)}
/* The chart, not thirteen paragraphs. Scrolls rather than squeezing on a
   phone, and the wrapper is focusable so it can be reached by keyboard. */
.ask__tablewrap{margin-top:14px;overflow-x:auto}
.ask__tbl{border-collapse:collapse;width:100%;min-width:280px;font-size:14.5px}
.ask__tbl th,.ask__tbl td{text-align:left;padding:9px 14px 9px 0;
  border-bottom:1px solid rgba(245,242,237,.1)}
.ask__tbl thead th{font-family:var(--board);font-size:10.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--smoke);font-weight:400}
.ask__tbl tbody th{font-family:var(--sign);font-size:1.02rem;font-weight:500;
  color:var(--bone);white-space:nowrap}
.ask__tbl td{color:var(--smoke)}
.ask__note{margin:16px 0 0;font-size:14.5px;line-height:1.6;color:var(--smoke);
  max-width:60ch}
.ask__note b{color:var(--bone);font-weight:500}
.ask__defgrid{display:grid;gap:18px;margin-top:14px;
  grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr))}
.ask__def b{display:block;font-family:var(--sign);font-size:1.05rem;
  font-weight:500;color:var(--bone);margin-bottom:5px}
.ask__def p{margin:0;font-size:14.5px;line-height:1.6;color:var(--smoke)}

/* ⚠ THE PAPER ROOM ("there's some white on white", 2026-09-26).
   ⚠ THIS BLOCK LIVES LAST ON PURPOSE. `.paper .role` and `.who .role` are
   both (0,2,0), so specificity does not separate them and SOURCE ORDER
   decides — the component rule was winning and the override did nothing.
   Theme overrides go at the end of the file.
   This site has two rooms — night and paper — and every component needs a
   rule for both. These four were written for the dark room and then shown
   on /shop/ and the product page, where bone-on-paper measures a contrast
   ratio of 1.04: literally invisible. The product's own spec labels
   (Hold / Finish / Base / Size) could not be read at all.
   --ink is 13.9:1 on paper and --ink-mut is 6.1:1; both clear AA. */
.paper .crumb a,.paper .crumb span{color:var(--ink-mut)}
.paper .crumb a:hover{color:var(--ink)}
.paper .deal{color:var(--ink-mut)}
.paper .deal b,.paper .deal i{color:var(--ink)}
.paper .svc .n{color:var(--ink)}
.paper .svc .t{color:var(--ink-mut)}
/* red-lite is only 3.5:1 on paper — the darker red already used by the
   shelf ornament measures 6.0:1. */
.paper .role{color:#A82A1B}

/* review quotes (home "In their words", /barbers/ cards) */
.rv{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr));margin-top:26px}
.rv--one{grid-template-columns:1fr;gap:12px;margin-top:12px}
.rv__q{margin:0;padding:20px 20px 16px;border:1px solid rgba(245,242,237,.1);border-radius:4px;background:rgba(245,242,237,.03)}
.rv__q blockquote{margin:0}
.rv__q blockquote p{margin:0;font-size:1rem;line-height:1.55;color:var(--bone)}
.rv__q figcaption{margin-top:12px;font-size:.8rem;color:var(--smoke);letter-spacing:.03em}
.rv__s{color:var(--red);letter-spacing:3px;font-size:.78rem;margin-bottom:10px}
.rv--one .rv__q{padding:14px 16px 12px}
.rv--one .rv__q blockquote p{font-size:.93rem}
.rv__h{margin:26px 0 0;font-family:var(--sign);text-transform:uppercase;letter-spacing:.06em;font-size:.9rem;color:var(--smoke)}
.rv__all{margin-top:24px}
