/* ============================================================
   IFFY CUTZ — v4 "THE FADE"
   Concept: the page is a taper. Noir → bone → noir.
   Sections are numbered like clipper guards (#0…#4).
   Type: Big Shoulders Display (signage) · Hanken Grotesk (body)
         · Spline Sans Mono (ticket/price-board voice)
   ============================================================ */

:root {
  /* absolutes */
  --noir:#0A0B0A; --noir-2:#101210; --noir-3:#171A17;
  --bone:#EDE7D9; --bone-2:#E2DACA; --bone-3:#D4CAB6;
  /* sampled straight out of assets/logo.png — the real brand green and gold */
  --green:#0FC96F; --green-deep:#0A7A42; --green-ink:#04240F;
  --gold:#D8C572; --gold-lift:#EDE0A4;
  --red:#D2402E;
  --tex-op:0.055;   /* barber-tool texture strength */

  /* semantic — flipped inside .zone-bone */
  --bg:var(--noir); --surface:var(--noir-2); --surface-2:var(--noir-3);
  --fg:#F2EFE6; --muted:#8E958C; --faint:#7A8078;
  --line:rgba(242,239,230,0.12); --line-2:rgba(242,239,230,0.22);
  --accent:var(--green);

  --font-display:"Big Shoulders Display","Arial Narrow",sans-serif;
  --font-body:"Hanken Grotesk",system-ui,sans-serif;
  --font-mono:"Spline Sans Mono",ui-monospace,monospace;
  /* used in exactly one place — the signature line. One soft edge in a
     page of hard ones, which is why it reads as deliberate. */
  --font-serif:"Instrument Serif",Georgia,serif;

  /* the header overlays the full-bleed hero, so its height has to be a
     token the hero can offset itself against */
  --nav-h:92px;
  --maxw:1280px;
  --gutter:clamp(20px,4vw,44px);
  /* Trimmed from clamp(88px,10vw,150px). Section padding is paid twice at
     every boundary — top of one plus bottom of the last — so 150px read as a
     300px dead band between blocks. This is the one knob for spacing on every
     page, so tightening it here tightens the whole site consistently. */
  --sect:clamp(62px,7vw,104px);
  --ease:cubic-bezier(0.22,1,0.36,1);
  --snap:cubic-bezier(0.16,1,0.3,1);
}

/* the light band inverts every semantic token — components follow automatically */
.zone-bone {
  --bg:var(--bone); --surface:var(--bone-2); --surface-2:var(--bone-3);
  --fg:#0A0B0A; --muted:#5C5F58; --faint:#666A61;
  --line:rgba(10,11,10,0.16); --line-2:rgba(10,11,10,0.3);
  --accent:var(--green-deep);
  background:var(--bg); color:var(--fg);
}

* { margin:0; padding:0; box-sizing:border-box; }
html { scroll-behavior:auto; }
html.lenis, html.lenis body { height:auto; }
.lenis.lenis-smooth { scroll-behavior:auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior:contain; }
.lenis.lenis-stopped { overflow:clip; }
.lenis.lenis-smooth iframe { pointer-events:none; }

body {
  background:var(--noir); color:var(--fg);
  font-family:var(--font-body); font-size:17px; line-height:1.6;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}
/* The original wallpaper, restored: ONE fixed layer over the whole page —
   two soft metal glows plus the barber tools, tiled, sitting still while the
   content scrolls past. Fixed rather than per-section is what made the old
   background feel like a room the site stands in. */
body::before {
  content:""; position:fixed; inset:0; pointer-events:none; z-index:1;
  background-image:
    url("assets/pattern.svg");
  background-repeat:repeat;
  background-size:300px 300px;
  background-position:center;
}
/* The cream band needs ink strokes instead of white ones. background-attachment
   keeps them locked to the viewport like the layer above, but clipped to the
   band — so the wallpaper reads as continuous straight through the fade. */
.zone-bone {
  background-image:url("assets/pattern-ink.svg");
  background-attachment:fixed;
  background-size:300px 300px;
  background-position:center;
  background-repeat:repeat;
  /* lift above the fixed wallpaper, or its white strokes and green glow
     would wash straight over the cream band */
  position:relative; z-index:2;
}

body::after {
  content:""; position:fixed; inset:0; pointer-events:none; z-index:3; opacity:0.035;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

img { max-width:100%; display:block; }
a { color:inherit; text-decoration:none; }
::selection { background:var(--green); color:var(--green-ink); }
:focus-visible { outline:2px solid var(--green); outline-offset:3px; }

.skip-link {
  position:fixed; top:10px; left:10px; z-index:200;
  transform:translateY(-160%); transition:transform 0.25s var(--snap);
  background:var(--green); color:var(--green-ink);
  font-family:var(--font-mono); font-size:0.7rem; font-weight:600;
  letter-spacing:0.16em; text-transform:uppercase; padding:13px 18px; border-radius:3px;
  box-shadow:0 10px 26px -8px rgba(0,0,0,0.8);
}
.skip-link:focus { transform:none; outline:2px solid var(--gold); outline-offset:3px; }

.wrap {
  width:100%; max-width:var(--maxw); margin:0 auto;
  padding-left:max(var(--gutter), env(safe-area-inset-left));
  padding-right:max(var(--gutter), env(safe-area-inset-right));
  position:relative; z-index:2;
}

/* ============================================================
   TYPE — display is condensed signage, set tight and huge
   ============================================================ */
h1,h2,h3,h4 {
  font-family:var(--font-display); font-weight:800;
  line-height:0.88; letter-spacing:-0.005em; text-transform:uppercase;
}
.display-xl { font-size:clamp(4.2rem, 15vw, 13.5rem); }
.display-lg { font-size:clamp(3rem, 9vw, 7.5rem); }
.display-md { font-size:clamp(2.4rem, 5.5vw, 4.4rem); }

/* the tag: mono, ticket-like, used for every label on the site */
.tag {
  font-family:var(--font-mono); font-size:0.69rem; font-weight:500;
  letter-spacing:0.24em; text-transform:uppercase; color:var(--accent);
  display:inline-flex; align-items:center; gap:10px;
}
.tag.muted { color:var(--muted); }

/* guard number — the structural device. It is a scale, so it earns its place. */
.guard {
  font-family:var(--font-mono); font-weight:600; font-size:0.72rem;
  letter-spacing:0.12em; color:var(--accent);
  display:inline-flex; align-items:center; gap:12px; white-space:nowrap;
}
.guard::after { content:""; width:clamp(28px,6vw,84px); height:1px; background:currentColor; opacity:0.5; }

/* ============================================================
   BUTTONS — hard-edged, no rounding, weight in the type
   ============================================================ */
/* ---- BUTTONS ------------------------------------------------------------
   Pressable objects, not flat rectangles: a top-lit bevel, a hard bottom
   edge that reads as thickness, ambient shadow, and a real travel on press.
   The trailing letter-space is cancelled so labels sit optically centred. */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:11px;
  font-family:var(--font-mono); font-weight:600; font-size:0.76rem;
  letter-spacing:0.18em; text-transform:uppercase; text-indent:0.18em;
  padding:18px 32px; border:1px solid transparent; border-radius:3px;
  position:relative; overflow:hidden; cursor:pointer;
  background-image:linear-gradient(180deg, rgba(255,255,255,0.18), rgba(0,0,0,0.10) 55%, rgba(0,0,0,0.20));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.38),
    inset 0 -1px 0 rgba(0,0,0,0.30),
    0 2px 0 rgba(0,0,0,0.42),
    0 9px 20px -9px rgba(0,0,0,0.65);
  transition:color 0.35s var(--ease), border-color 0.35s var(--ease),
             transform 0.18s var(--snap), box-shadow 0.18s var(--snap), filter 0.3s var(--ease);
}
.btn > * { position:relative; z-index:1; }
/* each variant names its own hover fill so the brand colour is never wiped */
.btn { --btn-fill:var(--fg); --btn-fill-ink:var(--bg); }
.btn::after {
  content:""; position:absolute; inset:0; z-index:0; background-color:var(--btn-fill);
  background-image:linear-gradient(180deg, rgba(255,255,255,0.18), rgba(0,0,0,0.10) 55%, rgba(0,0,0,0.20));
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.32), inset 0 -1px 0 rgba(0,0,0,0.26);
  transform:translateY(100%); transition:transform 0.45s var(--snap);
}
.btn:hover::after { transform:translateY(0); }
.btn:hover {
  filter:brightness(1.04);
  color:var(--btn-fill-ink);
  border-color:var(--btn-fill);   /* kills the 1px halo the transparent border left */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.42),
    inset 0 -1px 0 rgba(0,0,0,0.30),
    0 4px 0 rgba(0,0,0,0.42),
    0 16px 28px -12px rgba(0,0,0,0.7);
}
/* pressed: the button travels down onto its own shadow */
.btn:active {
  box-shadow:
    inset 0 2px 4px rgba(0,0,0,0.42),
    inset 0 1px 0 rgba(0,0,0,0.22),
    0 0 0 rgba(0,0,0,0.42);
  filter:brightness(0.97);
}
.btn:focus-visible { outline:2px solid var(--gold); outline-offset:3px; }
.btn:disabled, .btn[aria-disabled="true"] {
  filter:grayscale(0.55) brightness(0.75); cursor:not-allowed;
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.12), 0 1px 0 rgba(0,0,0,0.3);
}
.btn:disabled::after { transform:translateY(100%); }
/* trailing icons lead the eye forward; a leading icon leans back instead */
.btn > svg { width:15px; height:15px; margin-top:-1px; transition:transform 0.4s var(--snap); }
.btn:hover > svg:last-child { transform:translateX(5px); }
.btn:hover > svg:first-child { transform:translateX(-2px); }

/* primary inverts into the brand ink and keeps the green — it never goes bone */
.btn-primary {
  background-color:var(--green); color:var(--green-ink);
  --btn-fill:var(--green-ink); --btn-fill-ink:var(--green);
}
.btn-ghost {
  background-color:transparent; background-image:linear-gradient(180deg, rgba(255,255,255,0.07), rgba(0,0,0,0.06));
  border-color:var(--line-2); color:var(--fg);
  --btn-fill:var(--fg); --btn-fill-ink:var(--bg);
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.10), 0 2px 0 rgba(0,0,0,0.22), 0 8px 18px -10px rgba(0,0,0,0.55);
}
.wa-btn {
  background-color:#25D366; color:#06301A; border-color:#1FB457;
  --btn-fill:#06301A; --btn-fill-ink:#25D366;
}

/* ============================================================
   PRELOADER + PROGRESS — a taper that fills
   ============================================================ */
.preloader {
  position:fixed; inset:0; z-index:999; background:var(--noir);
  display:flex; align-items:center; justify-content:center; flex-direction:column; gap:24px;
  transition:opacity 0.6s var(--ease), visibility 0.6s;
}
.preloader.done { opacity:0; visibility:hidden; }
.preloader img { height:64px; width:auto; }
.preloader .bar { width:180px; height:3px; background:rgba(242,239,230,0.14); overflow:hidden; }
.preloader .bar span {
  display:block; height:100%; width:100%; transform-origin:0 50%; transform:scaleX(0);
  background:linear-gradient(90deg, var(--green), var(--gold));
  animation:load 1.15s var(--ease) infinite;
}
@keyframes load { 0%{transform:scaleX(0)} 60%{transform:scaleX(1)} 100%{transform:scaleX(1); opacity:0} }

.scroll-progress {
  position:fixed; top:0; left:0; height:3px; width:0%; z-index:60;
  background:var(--green);
  transition:width 0.12s linear;
}

/* ============================================================
   HEADER — thin, mono, no card. Sits on the poster.
   ============================================================ */
/* ============================================================
   THE INTRO — the shop opening up.
   The wordmark sets, a blade draws across it, and the screen
   is cut in two and pulled apart to reveal the page. Plays once
   per session (the <head> flag hides it instantly otherwise, so
   there is never a flash of it on the next page).
   ============================================================ */
.intro { position:fixed; inset:0; z-index:1000; pointer-events:none; }
html.intro-done .intro { display:none; }
html.intro-playing, html.intro-playing body { overflow:hidden; }

.intro-half {
  position:absolute; left:0; right:0; height:50.2%;
  background:var(--noir); overflow:hidden;
  transition:transform 1.05s cubic-bezier(0.76,0,0.24,1);
  will-change:transform;
}
.intro-half.top { top:0; }
.intro-half.bot { bottom:0; }
/* the tool texture continues across the intro so it feels like the same surface */
.intro-half::before {
  content:""; position:absolute; inset:0; opacity:0.05; background:#F2EFE6;
  -webkit-mask-image:url("assets/pattern-mask.svg"); mask-image:url("assets/pattern-mask.svg");
  -webkit-mask-size:300px 300px; mask-size:300px 300px;
  -webkit-mask-repeat:repeat; mask-repeat:repeat;
}
.intro.cut .intro-half.top { transform:translateY(-100%); }
.intro.cut .intro-half.bot { transform:translateY(100%); }

/* the wordmark is split across the two halves so the cut runs through it */
.intro-word {
  position:absolute; left:0; right:0; text-align:center;
  font-family:var(--font-display); font-weight:800; text-transform:uppercase;
  font-size:clamp(3rem,13vw,10rem); line-height:1; letter-spacing:-0.01em;
  color:#F2EFE6; white-space:nowrap;
}
.intro-half.top .intro-word { top:0; transform:translateY(0); height:200%; }
.intro-half.bot .intro-word { bottom:0; transform:translateY(0); height:200%; line-height:1; }
.intro-half.top .intro-word { display:flex; align-items:center; justify-content:center; }
.intro-half.bot .intro-word { display:flex; align-items:center; justify-content:center; top:-100%; }
.intro-word em { font-style:normal; color:var(--green); }

/* the word rises into place */
.intro-word span { display:inline-block; transform:translateY(0.42em); opacity:0; transition:transform 0.85s var(--snap), opacity 0.5s var(--ease); }
.intro.set .intro-word span { transform:none; opacity:1; }

/* ---- the cut ------------------------------------------------------------
   The scissors runs left to right and the line is the cut it leaves behind,
   so the two have to move as one. Both use --cut-t and --cut-e, and the maths
   is set up so the line's leading edge and the blade tips share an x at every
   frame: the line scales 0 → 1 from its left edge across the viewport, and the
   scissors translates -100% → calc(100vw - 100%), which puts its right edge at
   100vw × progress — the same place. Change the duration or the easing in one
   place and they stay locked. */
.intro { --cut-t:1.19s; --cut-e:cubic-bezier(0.45,0.05,0.35,1); }

.intro-blade {
  position:absolute; top:50%; left:0; right:0; height:2px; margin-top:-1px; z-index:3;
  /* brightest at the leading edge, where the blades are — it reads as heat
     off the cut rather than a lit rod with two dim ends */
  background:linear-gradient(90deg,
    rgba(15,201,111,0) 0%, rgba(15,201,111,0.55) 14%, var(--green) 55%, #FFFFFF 100%);
  transform:scaleX(0); transform-origin:0 50%;
  box-shadow:0 0 22px 2px rgba(15,201,111,0.5);
  transition:transform var(--cut-t) var(--cut-e), opacity 0.4s var(--ease);
  will-change:transform;
}
.intro.slice .intro-blade { transform:scaleX(1); }
.intro.cut .intro-blade { opacity:0; }

/* the shears themselves — the logo's mark, turned to lead the cut */
.intro-scissors {
  position:absolute; top:50%; left:0; z-index:5;
  width:clamp(62px,9.5vw,104px); line-height:0;
  /* the lifted gold, not the flat one — at this size on black the base tone
     greys out and the mark stops reading as the logo's shears */
  color:var(--gold-lift);
  transform:translate3d(-100%,0,0);
  transition:transform var(--cut-t) var(--cut-e), opacity 0.3s var(--ease);
  will-change:transform;
}
.intro-scissors svg {
  display:block; width:100%; height:auto;
  /* the pivot is the vertical middle of the viewBox, so lifting the svg by
     half its own height drops the pivot onto the cut line at any clamp value.
     A percentage margin would resolve against the parent's WIDTH, not height,
     and land it well above the line — translate is measured against the svg. */
  transform:translateY(-50%);
  filter:drop-shadow(0 0 14px rgba(216,197,114,0.55));
}
.intro-scissors .sc-pin { fill:currentColor; stroke:none; }
.intro.slice .intro-scissors { transform:translate3d(calc(100vw - 100%),0,0); }
.intro.cut .intro-scissors { opacity:0; }

/* the blades snip on the way across, each turning about the pivot at 24,16 */
.intro-scissors .sc-a, .intro-scissors .sc-b { transform-box:view-box; transform-origin:23px 17px; }
.intro.slice .intro-scissors .sc-a { animation:sc-snip-a 0.298s ease-in-out 4 both; }
.intro.slice .intro-scissors .sc-b { animation:sc-snip-b 0.298s ease-in-out 4 both; }
@keyframes sc-snip-a { 50% { transform:rotate(-8deg); } }
@keyframes sc-snip-b { 50% { transform:rotate(8deg); } }

/* The line above the wordmark.
   It used to sit at left:50% with a translate pull-back. An absolutely
   positioned box only offset from the left shrink-to-fits into what's
   left of the line — half the viewport — so on a phone the mark needed
   ~240px, got ~195px, and wrapped: two ragged-left lines sitting on top
   of the wordmark. Spanning the full width and centring the text means
   the available width is never the constraint. */
.intro-mark {
  position:absolute; left:0; right:0;
  /* tracks the wordmark's own clamp so the clearance below it stays even
     — a fixed offset left ~30px of air on a phone but only ~20px under a
     160px wordmark on a desktop, where the line read as an afterthought */
  top:calc(50% - clamp(72px, 6.5vw + 46px, 150px));
  z-index:4; opacity:0; transform:translateY(7px);
  transition:opacity 0.5s var(--ease), transform 0.75s var(--snap);
  font-family:var(--font-mono);
  font-size:clamp(0.64rem, 0.55rem + 0.35vw, 0.88rem); letter-spacing:0.34em;
  /* tracking is added after the final letter as well, which drags a
     centred line half a step right — indent by one step to cancel it */
  text-indent:0.34em;
  text-transform:uppercase; color:var(--gold);
  text-align:center; white-space:nowrap;
}
/* rises with the wordmark rather than only fading, so the two read as one move */
.intro.set .intro-mark { opacity:1; transform:none; }
.intro.cut .intro-mark { opacity:0; }

/* very narrow phones: tighten the tracking instead of letting it wrap again */
@media (max-width:360px){
  .intro-mark { font-size:0.64rem; letter-spacing:0.22em; text-indent:0.22em; }
}

@media (prefers-reduced-motion: reduce){
  .intro-half { transition:opacity 0.35s linear; }
  .intro.cut .intro-half.top, .intro.cut .intro-half.bot { transform:none; opacity:0; }
  .intro-word span { transition:none; transform:none; opacity:1; }
  .intro-mark { transition:none; transform:none; }
  .intro-blade, .intro-scissors { display:none; }
}

/* ---- HEADER -------------------------------------------------------------
   A glass instrument panel: frosted, edge-lit, with a light that sweeps the
   top rail and a marker that slides under whichever link you're on. */
.site-header {
  position:sticky; top:0; z-index:50; padding-top:env(safe-area-inset-top);
  background:transparent; border-bottom:1px solid transparent;
  transition:background 0.5s var(--ease), border-color 0.5s var(--ease),
             backdrop-filter 0.5s var(--ease), box-shadow 0.5s var(--ease);
}
.site-header.scrolled {
  /* One flat translucent plane. The old vertical gradient faded out downwards,
     which over the cream band read as a black smear bleeding into the page
     rather than as a bar. A single surface, a hairline and a soft shadow. */
  background:rgba(10,11,10,0.66);
  border-bottom-color:rgba(242,239,230,0.09);
  -webkit-backdrop-filter:blur(20px) saturate(150%); backdrop-filter:blur(20px) saturate(150%);
  box-shadow:0 8px 30px -18px rgba(0,0,0,0.75);
}
/* the header keeps a plain hairline — the travelling green light read as a
   loading bar and competed with the real scroll-progress indicator */
.site-header::after {
  content:""; position:absolute; left:0; right:0; bottom:-1px; height:1px;
  pointer-events:none; opacity:0; background:var(--line);
  transition:opacity 0.5s var(--ease);
}
.site-header.scrolled::after { opacity:1; }

.nav { display:flex; align-items:center; gap:clamp(14px,2vw,28px); height:var(--nav-h); transition:height 0.5s var(--ease); }
.site-header.scrolled .nav { height:70px; }
.nav-spacer { flex:1; }

/* live shop state, read straight off the clock */
.hdr-status {
  display:inline-flex; align-items:center; gap:7px; flex-shrink:0;
  font-family:var(--font-mono); font-size:0.69rem; font-weight:500;
  letter-spacing:0.18em; text-transform:uppercase; color:var(--muted);
  padding:6px 11px; border:1px solid var(--line); border-radius:100px;
  background:rgba(242,239,230,0.03);
}
.hdr-status i { width:6px; height:6px; border-radius:50%; background:var(--muted-2, #6f7a71); font-style:normal; }
.hdr-status.is-open { color:var(--green); border-color:rgba(15,201,111,0.35); background:rgba(15,201,111,0.07); }
.hdr-status.is-open i { background:var(--green); box-shadow:0 0 0 0 rgba(15,201,111,0.6); animation:sb-pulse 2.4s infinite; }
.hdr-status.is-shut { color:var(--red); border-color:rgba(210,64,46,0.32); }
.hdr-status.is-shut i { background:var(--red); }
@media (max-width:1180px){ .hdr-status { display:none; } }

.brand { display:flex; align-items:center; gap:14px; }
.brand img { height:52px; width:auto; transition:height 0.5s var(--ease); }
.site-header.scrolled .brand img { height:40px; }
.brand-text { display:flex; flex-direction:column; line-height:0.9; }
.brand-text b { font-family:var(--font-display); font-weight:800; font-size:1.5rem; letter-spacing:0.02em; color:#F2EFE6; text-transform:uppercase; }
.brand-text span { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.3em; color:var(--gold); text-transform:uppercase; margin-top:5px; }

/* nav sits in its own rail with a marker that slides between items */
.nav-links {
  position:relative; display:flex; align-items:center; gap:4px;
  padding:5px; border:0; border-radius:100px; background:none;
}
.nav-links a {
  position:relative; z-index:2;
  font-family:var(--font-mono); font-size:0.69rem; font-weight:500;
  letter-spacing:0.16em; text-transform:uppercase; color:#8E958C;
  padding:9px 14px; border-radius:100px; white-space:nowrap;
  transition:color 0.3s var(--ease);
}
.nav-links a:hover { color:#F2EFE6; }
/* Readable by default; the dark on-pill ink is applied only while the pill is
   genuinely behind this label — script.js sets .ind-on-active when it lands. */
.nav-links a.active { color:#F2EFE6; }
.nav-links.ind-on-active a.active { color:var(--green-ink); }
/* the marker — positioned by script, so it tracks the real element box */
.nav-ind {
  position:absolute; z-index:1; top:5px; bottom:5px; left:0; width:0;
  border-radius:100px; background:var(--green);
  box-shadow:0 0 18px -4px rgba(15,201,111,0.7), inset 0 1px 0 rgba(255,255,255,0.35);
  opacity:0; transform-origin:50% 50%;
  transition:transform 0.45s var(--snap), width 0.45s var(--snap), opacity 0.3s var(--ease), background 0.3s;
}
.nav-ind.ready { opacity:1; }
.nav-links:hover .nav-ind { background:var(--green); }
.nav-cta { padding:13px 24px; flex-shrink:0; }
@media (max-width:1080px){
  .nav-links a { padding:9px 10px; font-size:0.69rem; letter-spacing:0.12em; }
}

.burger { display:none; flex-direction:column; gap:6px; background:none; border:none; cursor:pointer; padding:10px; z-index:51; }
.burger span { width:26px; height:2px; background:#F2EFE6; transition:transform 0.4s var(--snap), opacity 0.3s; }
.burger.open span:nth-child(1) { transform:translateY(8px) rotate(45deg); }
.burger.open span:nth-child(2) { opacity:0; }
.burger.open span:nth-child(3) { transform:translateY(-8px) rotate(-45deg); }

/* ---- mobile menu -------------------------------------------------------
   A contents page, not one flat stack of shouty links. A hand-set label
   opens each group, the page links carry the weight, and the things people
   actually open a menu to find — directions, hours, the phone number —
   get their own heading instead of being left to the footer.

   The old version centred five 4rem links between two rules and offered
   nothing else. Dropping the type to a readable size is what buys the room
   for everything underneath it. */
.mobile-menu {
  position:fixed; inset:0; z-index:49;
  background:rgba(10,11,10,0.97);
  -webkit-backdrop-filter:blur(18px); backdrop-filter:blur(18px);
  display:block; overflow-y:auto; overscroll-behavior:contain;
  padding:calc(var(--nav-h) + env(safe-area-inset-top) + 20px) var(--gutter)
          calc(46px + env(safe-area-inset-bottom));
  /* visibility, not display, so the panel keeps a layer and the open/close
     never costs a re-layout — the whole move is opacity + transform */
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity 0.42s var(--ease), visibility 0.42s;
  will-change:opacity;
}
.mobile-menu.open { opacity:1; visibility:visible; pointer-events:auto; }
/* one soft light off the top left, so flat black gets some depth behind the list */
.mobile-menu::before {
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(130% 62% at 10% 18%, rgba(15,201,111,0.12), transparent 62%);
}
.mm-inner { position:relative; max-width:34rem; }

.mm-group { margin-bottom:clamp(30px,5.5vh,44px); }
.mm-group:last-child { margin-bottom:0; }

/* ---- the open ----------------------------------------------------------
   Each line lifts into place a beat behind the one above it. Only opacity
   and transform move, so the whole sequence is composited — no layout, no
   repaint, nothing for a phone to choke on. Held down while closed and
   released by .open, so the cascade replays on every open, not just the first.
   Selectors target the real elements rather than a marker class, so the
   markup stays plain and nothing can fall out of sync with it. */
.mm-group, .mm-nav a {
  opacity:0; transform:translateY(15px);
  transition:opacity 0.44s var(--ease), transform 0.52s var(--snap);
}
.mobile-menu.open .mm-group, .mobile-menu.open .mm-nav a { opacity:1; transform:none; }
.mobile-menu.open .mm-group:nth-child(1) { transition-delay:0.04s; }
.mobile-menu.open .mm-group:nth-child(2) { transition-delay:0.20s; }
.mobile-menu.open .mm-group:nth-child(3) { transition-delay:0.26s; }
/* the page links ride on top of their group's own delay */
.mobile-menu.open .mm-nav a:nth-child(1) { transition-delay:0.09s; }
.mobile-menu.open .mm-nav a:nth-child(2) { transition-delay:0.13s; }
.mobile-menu.open .mm-nav a:nth-child(3) { transition-delay:0.17s; }
.mobile-menu.open .mm-nav a:nth-child(4) { transition-delay:0.21s; }
.mobile-menu.open .mm-nav a:nth-child(5) { transition-delay:0.25s; }
/* hover has its own transform, so it must not inherit the entrance delay */
.mobile-menu.open .mm-nav a:hover { transition-delay:0s; }
/* closing goes straight back with no queue — a stagger on the way out
   reads as lag rather than polish */
.mobile-menu:not(.open) .mm-group,
.mobile-menu:not(.open) .mm-nav a { transition-delay:0s; transition-duration:0.18s; }

/* the group headings — mono, the voice this site already uses for annotation */
.mm-label {
  display:block; margin-bottom:14px;
  font-family:var(--font-mono); font-weight:500; font-style:normal;
  font-size:0.7rem; letter-spacing:0.18em; text-transform:uppercase;
  line-height:1.2; color:rgba(242,239,230,0.42);
}
.mm-label::before { content:"/ "; color:var(--green); }

/* The page list. Set in the body face at a medium weight with tight negative
   tracking — sentence case, not the condensed uppercase the headings use.
   Five words shouting in a stack is a poster; this is a menu. */
.mm-nav a {
  display:block; font-family:var(--font-body); font-weight:600;
  text-transform:none; letter-spacing:-0.03em;
  font-size:clamp(2rem,8.6vw,2.45rem); line-height:1.26; color:#F2EFE6;
  padding:5px 0;
  transition:color 0.3s var(--ease), transform 0.4s var(--snap);
}
.mm-nav a:hover { color:var(--green); transform:translateX(7px); }
/* the current page is marked by colour alone — nudging it too would read as
   a hover that will not go away */
.mm-nav a.active { color:var(--green); }

/* While the menu is open the header is only the frame the close button sits
   in. It stays above the panel so the button keeps working, so its plate and
   its wordmark have to get out of the way or they print over the list. */
.site-header:has(.burger.open) {
  background:transparent; border-bottom-color:transparent; box-shadow:none;
  -webkit-backdrop-filter:none; backdrop-filter:none;
}
.site-header:has(.burger.open) .brand { opacity:0; pointer-events:none; }
/* the floating launchers and the book bar sit above everything by default —
   over a full-screen menu they are just clutter you cannot dismiss */
.mobile-menu.open ~ .book-bar, .mobile-menu.open ~ .dock { display:none; }

/* The CTA stays a button — the fixed book bar is hidden while this is open.
   Its box sits flush on the same left edge as every label and link above it,
   so the whole column reads off one margin instead of stepping in and out. */
.mobile-menu .mm-cta {
  display:inline-flex; width:auto; align-self:flex-start;
  margin:22px 0 0; font-size:0.72rem; padding:15px 26px; text-indent:0.18em;
}

/* second group: quieter, set in the body face so it cannot be mistaken
   for another page link */
.mobile-menu .mm-sub {
  display:block; font-family:var(--font-body); font-weight:500;
  font-size:1.05rem; line-height:1.5; color:rgba(242,239,230,0.74);
  padding:7px 0; transition:color 0.3s var(--ease);
}
.mobile-menu .mm-sub:hover { color:var(--green); }

/* third group: the details, in the mono the rest of the site uses for facts */
.mobile-menu .mm-direct {
  display:block; font-family:var(--font-mono); font-weight:500;
  font-size:0.95rem; letter-spacing:0.02em; color:#F2EFE6;
  padding:6px 0; transition:color 0.3s var(--ease);
}
.mobile-menu .mm-direct:hover { color:var(--green); }
.mm-place {
  display:block; margin-top:8px;
  font-family:var(--font-mono); font-size:0.76rem; letter-spacing:0.07em;
  line-height:1.7; color:var(--faint);
}
.mm-social { display:flex; flex-wrap:wrap; gap:8px 22px; margin-top:20px; }
.mobile-menu .mm-social a {
  font-family:var(--font-mono); font-weight:500; text-transform:uppercase;
  font-size:0.71rem; letter-spacing:0.16em; color:rgba(242,239,230,0.6);
  transition:color 0.3s var(--ease);
}
.mobile-menu .mm-social a:hover { color:var(--green); }

/* mobile book bar
   Two controls, nothing to read. It used to stack a live status line over
   a big brand line — the brand is already in the masthead and the status
   already runs across the top of the page, so both were reprints. That
   copy was most of the bar's 68px; without it the row is 55px. */
.book-bar {
  position:fixed; bottom:0; left:0; right:0; z-index:48; display:none;
  background:rgba(10,11,10,0.95); -webkit-backdrop-filter:blur(16px); backdrop-filter:blur(16px);
  border-top:1px solid var(--line); padding:6px 14px;
  padding-bottom:calc(6px + env(safe-area-inset-bottom));
  align-items:center; gap:10px;
}
/* booking takes the row; the call button keeps its square */
.book-bar .btn { flex:1; padding:0 18px; min-height:44px; font-size:0.68rem; white-space:nowrap; }

/* live status strip */
/* One line, always. The bar used to wrap to two on a phone, which made a
   utility strip look like a paragraph. Colour is carried by the dot and a
   single word — everything else stays quiet. */
.status-bar { background:var(--noir-2); border-bottom:1px solid var(--line); }
.status-bar .wrap {
  display:flex; align-items:center; justify-content:center; gap:9px;
  padding:9px var(--gutter);
  white-space:nowrap; overflow:hidden;
}
.status-bar .sb-dot {
  width:6px; height:6px; border-radius:50%; background:var(--green);
  animation:sb-pulse 2.4s infinite; flex-shrink:0;
}
.status-bar.closed .sb-dot { background:var(--red); }
.status-bar .sb-text {
  font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.1em;
  text-transform:uppercase; color:#8E958C;
  min-width:0; overflow:hidden; text-overflow:ellipsis;
}
/* the one coloured word — the state itself */
.status-bar .sb-text b { font-weight:600; color:#F2EFE6; }
.status-bar.open .sb-text b { color:var(--green); }
.status-bar.closed .sb-text b { color:var(--red); }
/* separators, dimmed so they read as punctuation rather than content */
.status-bar .sb-text i { font-style:normal; color:var(--faint); margin:0 0.5em; }

/* narrow phones: drop the Wednesday note rather than wrap the bar */
@media (max-width:560px){
  .status-bar .wrap { gap:8px; padding:8px var(--gutter); }
  .status-bar .sb-text { letter-spacing:0.06em; }
  .status-bar .sb-extra { display:none; }
}
@keyframes sb-pulse { 0%{box-shadow:0 0 0 0 currentColor;opacity:1} 70%{box-shadow:0 0 0 7px transparent;opacity:.65} 100%{box-shadow:0 0 0 0 transparent;opacity:1} }

/* ============================================================
   HERO — a poster. Masthead type first, everything else under it.
   ============================================================ */
.hero { position:relative; padding:clamp(36px,5vw,64px) 0 clamp(56px,7vw,88px); overflow:hidden; }


/* masthead */
.masthead { padding:clamp(24px,4vw,44px) 0 clamp(28px,4vw,48px); }
.masthead h1 { margin:0; }
/* Big Shoulders' content area is ~1.19em, so at line-height 0.8 the cap tops —
   and especially the overshoot on round caps like S and C — sit ABOVE the line
   box and get guillotined by the mask. Headroom is scaled off the same clamp
   the type uses, so the clearance holds at every viewport. */
.mast-line {
  display:block; overflow:hidden;
  padding-top:calc(clamp(4.2rem, 20vw, 17rem) * 0.035);
  margin-top:calc(clamp(4.2rem, 20vw, 17rem) * -0.035);
  padding-bottom:0.22em; margin-bottom:-0.22em;
}
.mast-line > span { display:block; transform:translateY(135%); animation:mast-rise 1.05s var(--snap) forwards; }
.mast-line:nth-child(2) > span { animation-delay:0.1s; }
@keyframes mast-rise { to { transform:none; } }

.mast-outline {
  font-size:clamp(2.5rem,10.4vw,8.8rem); line-height:0.92; color:transparent;
  -webkit-text-stroke:1.5px rgba(242,239,230,0.45); letter-spacing:0.005em;
}
.mast-solid { font-size:clamp(4.2rem,20vw,17rem); line-height:0.8; letter-spacing:-0.022em; }
.mast-solid .green { color:var(--green); }
.mast-rule { height:1px; background:var(--line); margin-top:clamp(20px,3vw,32px); }

/* the row beneath the masthead */
.hero-body { display:grid; grid-template-columns:1fr 0.82fr; gap:clamp(32px,5vw,64px); align-items:start; padding-top:clamp(28px,4vw,44px); }
.hero-copy { opacity:0; animation:fade-up 0.9s var(--ease) 0.45s forwards; }
.hero-copy .lead { color:var(--muted); font-size:clamp(1rem,1.2vw,1.16rem); max-width:44ch; margin:18px 0 32px; }
.hero-cta { display:flex; gap:14px; flex-wrap:wrap; }
@keyframes fade-up { from{opacity:0;transform:translateY(24px)} to{opacity:1;transform:none} }

.hero-visual { position:relative; aspect-ratio:4/5; opacity:0; animation:fade-up 1s var(--ease) 0.55s forwards; }
.hero-img-clip { position:absolute; inset:0; overflow:hidden; background:var(--noir-2); }
.hero-img-clip::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg,transparent 45%,rgba(10,11,10,0.75)); }
.hero-img-clip img { width:100%; height:100%; object-fit:cover; will-change:transform; }
.hero-badge {
  position:absolute; left:0; bottom:0; z-index:2; display:flex; align-items:baseline; gap:12px;
  background:var(--green); color:var(--green-ink); padding:14px 20px;
}
.hero-badge b { font-family:var(--font-display); font-weight:800; font-size:2.1rem; line-height:1; font-variant-numeric:tabular-nums; }
.hero-badge span { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.14em; text-transform:uppercase; line-height:1.5; }

/* hanging OPEN/CLOSED sign */
.hang-sign { position:absolute; top:-6px; right:16px; z-index:4; width:142px; transform-origin:50% -6px; animation:sway 6.5s ease-in-out infinite; }
@keyframes sway { 0%,100%{transform:rotate(-2deg)} 50%{transform:rotate(2deg)} }
.hang-rope { position:absolute; top:-2px; left:50%; width:76px; height:30px; transform:translateX(-50%); }
.hang-rope::before, .hang-rope::after { content:""; position:absolute; top:0; width:1.5px; height:34px; background:linear-gradient(var(--gold),rgba(201,162,39,0.3)); }
.hang-rope::before { left:8px; transform:rotate(20deg); transform-origin:top; }
.hang-rope::after { right:8px; transform:rotate(-20deg); transform-origin:top; }
.hang-plate {
  position:relative; margin-top:26px; text-align:center; padding:15px 12px 13px;
  background:var(--green-deep); color:#fff; border:2px solid rgba(255,255,255,0.9);
  box-shadow:0 20px 34px -16px rgba(0,0,0,0.8);
}
.hang-sign.closed .hang-plate { background:var(--red); }
.hang-scissors { width:22px; height:22px; margin:0 auto 6px; display:block; color:rgba(255,255,255,0.9); }
.hang-status { display:block; font-family:var(--font-display); font-weight:800; font-size:1.75rem; line-height:1; letter-spacing:0.04em; }
.hang-sub { display:block; font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.08em; margin-top:6px; opacity:0.9; }


/* ============================================================
   FULL-BLEED HERO — the photograph is the poster

   The masthead is set into the empty side the photograph already
   has, so the type and the subject share one frame instead of
   sitting in two boxes. The section carries .zone-bone, so every
   component inside it — buttons, meta, rules, the accent — flips
   to dark ink through the existing tokens rather than being
   restyled by hand.
   ============================================================ */
.hero-full {
  position:relative; overflow:hidden;
  min-height:100svh; display:flex;
  /* Centred, not floor-pinned. Pinned to the floor it left a growing dead band
     above the masthead on tall windows and crowded the fold on short ones. */
  flex-direction:column; justify-content:center; align-items:stretch;
  /* the sticky header sits above this in the flow; reclaim its band so the
     photo starts at the top of the page, then pad it back so nothing hides */
  margin-top:calc(-1 * var(--nav-h));
  /* Content is bottom-anchored, so the floor padding only lifts it while the
     hero is still being sized by min-height. Once content + padding overflows
     100svh the hero just grows and the lift stops working — which is why the
     ceiling is what actually moves this block up. */
  /* The content is centred in the box inside these paddings, so a deeper
     floor lifts it. It needed lifting because the sticky header eats the top
     92px of the hero: measured from the header's bottom edge rather than the
     section's, the block was sitting low with a band of empty cream above it. */
  padding:calc(clamp(20px,3vh,48px) + var(--nav-h)) 0 clamp(130px,20vh,270px);
}
.hero-full .hero-photo { position:absolute; inset:0; z-index:0; background:var(--bone-2); }
.hero-full .hero-photo img {
  width:100%; height:100%; object-fit:cover;
  /* the subject sits right of centre, so hold him there and leave the
     empty third of the frame free for the masthead */
  object-position:center;
}

/* A scrim, not a tint. The reference sets pale type on a pale backdrop and
   loses its own title; this keeps the copy legible whatever photo is dropped
   in, and fades out before it reaches the subject. */
.hero-full .hero-photo::after {
  content:""; position:absolute; inset:0;
  background:linear-gradient(96deg,
    rgba(237,231,217,0.92) 0%,
    rgba(237,231,217,0.86) 32%,
    rgba(237,231,217,0.52) 42%,
    rgba(237,231,217,0.12) 49%,
    rgba(237,231,217,0) 54%);
}

.hero-full .hero-inner { position:relative; z-index:1; width:100%; }
/* poster scale is too tall once the type shares a viewport with a subject
   and a paragraph — this keeps the whole composition on one screen */
.hero-full .mast-outline { font-size:clamp(1.7rem,5.4vw,4.3rem); }
.hero-full .mast-solid { font-size:clamp(3rem,11vw,9.4rem); }
/* 81px sat between the masthead and the lead — the rule's own margin, the
   masthead's floor padding and the paragraph's top margin all stacking. */
.hero-full .masthead { padding:clamp(16px,2.5vw,30px) 0 clamp(8px,1.1vw,14px); }
.hero-full .mast-rule { background:rgba(10,11,10,0.18); margin-top:clamp(12px,1.6vw,18px); }
.hero-full .hero-copy { max-width:44ch; opacity:0; animation:fade-up 0.9s var(--ease) 0.45s forwards; }
/* The block is pinned to the floor, so tightening the space ABOVE the lead only
   drags the masthead down. Opening the space BELOW it is what actually lifts
   the paragraph — the buttons and badge stay where they are. */
.hero-full .hero-copy .lead { color:var(--muted); font-size:clamp(1rem,1.2vw,1.14rem); margin:10px 0 44px; }

/* the outline face is stroked in the light ink — over a pale photograph that
   is invisible, so it takes the zone's own foreground instead */
.hero-full .mast-outline { -webkit-text-stroke-color:rgba(10,11,10,0.42); }
/* electric green on bone fails contrast; --accent is the deep cut */
.hero-full .mast-solid .green { color:var(--accent); }

 /* three things wanted the bottom-right corner: the rating badge, the hanging
    sign and the fixed chat launcher. The sign hangs — so it belongs at the top,
    off the header — and the badge clears the launcher. */
.hero-full .hero-badge {
  position:static; display:inline-flex; align-items:center;
  margin:clamp(24px,3vw,34px) 0 0; padding:16px 22px;
}
/* the red hanging sign said CLOSED a third time, over the photograph */
.hero-full .hang-sign { display:none; }

/* ---- header over the pale hero -------------------------------------------
   .scrolled fires at 40px, which on a 100svh hero means "not scrolled" is
   exactly "still over the photograph" — so the inversion needs no JS. */
.home-hero .site-header:not(.scrolled) .brand-text b,
.home-hero .site-header:not(.scrolled) .nav-links a { color:#0A0B0A; }
.home-hero .site-header:not(.scrolled) .nav-links a:hover { color:var(--green-deep); }
.home-hero .site-header:not(.scrolled) .brand-text span { color:#7A6410; }
.home-hero .site-header:not(.scrolled) .hdr-status { color:#3C403A; border-color:rgba(10,11,10,0.2); }
.home-hero .site-header:not(.scrolled) .burger span { background:#0A0B0A; }

/* The bar sits over both bands, so it matches whichever is under it — script.js
   sets .on-bone. A dark bar hard-cut over cream is what made it look heavy. */
.site-header.scrolled.on-bone {
  background:rgba(237,231,217,0.72);
  border-bottom-color:rgba(10,11,10,0.10);
  box-shadow:0 8px 30px -20px rgba(10,11,10,0.35);
}
.site-header.scrolled.on-bone .brand img { content:url("assets/logo-ink.png"); }
.site-header.scrolled.on-bone .nav-links a { color:#4A4F49; }
.site-header.scrolled.on-bone .nav-links a:hover { color:#0A0B0A; }
.site-header.scrolled.on-bone .hdr-status { color:#3C403A; border-color:rgba(10,11,10,0.18); }
.site-header.scrolled.on-bone .burger span { background:#0A0B0A; }

/* The burger goes dark ink over the cream hero and the cream header. But the
   open menu is a full-screen noir overlay, so the moment it opens that same
   dark X is drawn on near-black — 1:1 contrast, completely invisible. Once the
   menu is open the overlay is what is behind it, so it is always light.
   Both selectors repeat the parent chain to outrank the inversions above. */
.home-hero .site-header:not(.scrolled) .burger.open span,
.site-header.scrolled.on-bone .burger.open span,
.burger.open span { background:#F2EFE6; }
/* the mark is drawn for black; over the pale hero it needs the ink cut */
.home-hero .site-header:not(.scrolled) .brand img { content:url("assets/logo-ink.png"); }
/* same guard over the light hero: dark ink until the pill is really there */
.home-hero .site-header:not(.scrolled) .nav-links a.active { color:#0A0B0A; }
.home-hero .site-header:not(.scrolled) .nav-links.ind-on-active a.active { color:var(--green-ink); }

/* Short viewports — a laptop with browser chrome. The masthead is sized for a
   tall window; here it has to shrink so the buttons and the rating still land
   above the fold instead of being padded off the bottom. */
@media (min-width:941px) and (max-height:860px){
  .hero-full { padding:calc(clamp(14px,2vh,32px) + var(--nav-h)) 0 clamp(88px,14vh,150px); }
  .hero-full .mast-solid   { font-size:clamp(2.6rem,7.6vw,6.2rem); }
  .hero-full .mast-outline { font-size:clamp(1.4rem,3.8vw,3rem); }
  .hero-full .masthead     { padding:clamp(8px,1.4vw,16px) 0 clamp(6px,0.9vw,10px); }
  .hero-full .mast-rule    { margin-top:clamp(8px,1.2vw,14px); }
  .hero-full .hero-copy .lead { margin:8px 0 24px; font-size:1rem; }
  .hero-full .hero-badge   { margin-top:clamp(14px,2vw,20px); }
}

@media (max-width:940px){
  /* A 2.3:1 frame inside a portrait viewport crops to a fifth of its width —
     a meaningless slice of cheek, with the copy veiled on top of it. So on a
     phone the photo stops being a backdrop and becomes its own band: full
     width across the top, copy underneath on flat bone. Nothing is washed. */
  .hero-full { min-height:auto; padding:0 0 clamp(40px,7vh,72px); }

  .hero-full .hero-photo {
    position:relative; inset:auto; width:100%;
    height:calc(clamp(230px,42svh,360px) + var(--nav-h));
  }
  .hero-full .hero-photo img { object-position:60% center; }
  /* light at the very top so the inverted header still reads over the hair,
     and a fade into the page colour at the foot so the band has no hard edge */
  .hero-full .hero-photo::after {
    background:linear-gradient(180deg,
      rgba(237,231,217,0.62) 0%,
      rgba(237,231,217,0.10) 26%,
      rgba(237,231,217,0) 60%,
      var(--bone) 100%);
  }

  .hero-full .hero-inner { padding-top:clamp(22px,4vh,38px); }
  .hero-full .hang-sign { display:none; }

  /* 11vw bottoms out well under the old poster floor on a phone */
  .hero-full .mast-solid { font-size:clamp(4rem,15vw,9.4rem); }
  .hero-full .mast-outline { font-size:clamp(2rem,7.4vw,4.3rem); }
}

/* Landscape phone. 42svh of a 390px-tall screen still hits the 230px floor, so
   the photo band took ~60% of the viewport before a word of copy appeared.
   Height-based, not width-based, so a small tablet in portrait is unaffected. */
@media (max-width:940px) and (max-height:520px) and (orientation:landscape){
  .hero-full .hero-photo { height:calc(clamp(140px,40svh,210px) + var(--nav-h)); }
  .hero-full .mast-solid   { font-size:clamp(2.4rem,8.5vw,4.6rem); }
  .hero-full .mast-outline { font-size:clamp(1.2rem,4.2vw,2.2rem); }
  .hero-full .hero-copy .lead { margin:6px 0 18px; }
  .hero-full { padding-bottom:clamp(28px,5vh,48px); }
}

/* ============================================================
   MARQUEE — the shop window strip, hard-edged
   ============================================================ */
.marquee { position:relative; overflow:hidden; padding:18px 0; background:var(--green); color:var(--green-ink); }
.marquee-track { position:relative; z-index:2; display:flex; white-space:nowrap; width:max-content; animation:scroll-x 38s linear infinite; }
.marquee:hover .marquee-track { animation-play-state:paused; }
.marquee-track > span {
  display:inline-flex; align-items:center; gap:34px; padding-right:34px;
  font-family:var(--font-display); font-weight:700; text-transform:uppercase;
  font-size:clamp(1.1rem,2vw,1.6rem); letter-spacing:0.03em;
}
.marquee .dot { width:6px; height:6px; min-width:6px; background:currentColor; transform:rotate(45deg); }
@keyframes scroll-x { to { transform:translateX(-50%); } }

/* ============================================================
   SECTIONS — guard-numbered, with the fade between zones
   ============================================================ */
.section { padding:var(--sect) 0; position:relative; }
/* two stacked sections were paying a full --sect each, leaving a dead band
   between them roughly twice as tall as intended */
.section + .section { padding-top:0; }
.section:last-child { padding-bottom:calc(var(--sect) * 0.6); }
.zone-bone { position:relative; }

/* the marquee is a solid green band — texture reads as ink pressed into it */
.marquee::before {
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none; opacity:0.09;
  background:var(--green-ink);
  -webkit-mask-image:url("assets/pattern-mask.svg"); mask-image:url("assets/pattern-mask.svg");
  -webkit-mask-size:300px 300px; mask-size:300px 300px;
  -webkit-mask-repeat:repeat; mask-repeat:repeat;
}
/* ---- THE TAPER ----------------------------------------------------------
   A straight two-stop black→cream ramp interpolates through muddy grey and,
   over 60px, reads as a dirty smear with hard edges at both ends. This is a
   long, eased ramp that holds in the dark and opens up late — the way a real
   fade actually blends — with grain over the top to kill 8-bit banding. */
.fade-in-bone, .fade-out-bone {
  position:relative; overflow:hidden;
  /* A longer ramp reads softer, but this element is pure empty scroll —
     at the old clamp it was up to 460px of nothing, and with the next
     section's own top padding stacked on it that ran past half a screen.
     21 smootherstep stops stay band-free over a much shorter run, so the
     blend survives the trim. On the home page there is no spacer at all
     now: see .portfolio-band, which runs the same ramp behind the grid. */
  height:clamp(150px, 17vw, 260px);
}
/* 21 stops sampled in OKLab along a smootherstep curve (6t⁵−15t⁴+10t³).
   Both the first and second derivative reach zero at each end, so the ramp
   leaves the solid colour and arrives at it with no slope change — that is
   what removes the Mach band, which is what reads as a "harsh" edge.
   A short two- or four-stop gradient always kinks; this one cannot. */
.fade-in-bone {
  background-image:linear-gradient(180deg,
    #0A0B0A 0%, #0A0B0A 5%, #0B0C0B 10%, #0F0F0E 15%,
    #141513 20%, #1C1D1B 25%, #282825 30%, #363632 35%,
    #474742 40%, #5B5A54 45%, #706E67 50%, #86837B 55%,
    #9C988F 60%, #B0ACA2 65%, #C2BEB2 70%, #D2CDC0 75%,
    #DED8CB 80%, #E6E0D3 85%, #EBE5D7 90%, #EDE7D9 95%,
    #EDE7D9 100%);
}
.fade-out-bone {
  background-image:linear-gradient(180deg,
    #EDE7D9 0%, #EDE7D9 5%, #EBE5D7 10%, #E6E0D3 15%,
    #DED8CB 20%, #D2CDC0 25%, #C2BEB2 30%, #B0ACA2 35%,
    #9C988F 40%, #86837B 45%, #706E67 50%, #5B5A54 55%,
    #474742 60%, #363632 65%, #282825 70%, #1C1D1B 75%,
    #141513 80%, #0F0F0E 85%, #0B0C0B 90%, #0A0B0A 95%,
    #0A0B0A 100%);
}
/* dither: breaks up the banding a flat gradient always shows on large areas */
.fade-in-bone::after, .fade-out-bone::after {
  content:""; position:absolute; inset:0; pointer-events:none; opacity:0.5;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
  mix-blend-mode:overlay;
}
/* the barber tools carry on across the seam so it reads as one surface */
.fade-in-bone::before, .fade-out-bone::before,
.portfolio-band::before {
  content:""; position:absolute; inset:0; pointer-events:none; opacity:0.05;
  -webkit-mask-image:url("assets/pattern-mask.svg"); mask-image:url("assets/pattern-mask.svg");
  -webkit-mask-size:300px 300px; mask-size:300px 300px;
  -webkit-mask-repeat:repeat; mask-repeat:repeat;
  background:#8C8A78;
}

/* ============================================================
   THE WORK — the portfolio band
   This replaces a spacer that was up to 460px of pure empty ramp.
   The bone→noir blend still happens over the same distance, but it
   now runs BEHIND the last rows of the grid instead of behind
   nothing — so the transition costs no height at all, and the space
   it used to waste carries the most persuasive thing on the site.
   ============================================================ */
.portfolio-band { position:relative; z-index:2; overflow:hidden; }
.portfolio-band > .wrap { position:relative; z-index:3; }
/* the ramp is pinned to the foot of the section, so the head and the
   filters stay on solid bone and keep their dark-on-light contrast */
.portfolio-band::after {
  content:""; position:absolute; left:0; right:0; bottom:0; z-index:1;
  height:clamp(320px, 38vw, 560px); pointer-events:none;
  background-image:linear-gradient(180deg,
    rgba(237,231,217,0) 0%, rgba(232,226,212,0.28) 8%, rgba(224,218,205,0.52) 15%,
    #D8D2C5 22%, #C8C3B7 28%, #B4B0A6 34%, #9E9A92 40%,
    #86837B 46%, #706E67 52%, #5B5A54 58%, #474742 64%,
    #363632 70%, #282825 76%, #1C1D1B 82%, #141513 87%,
    #0F0F0E 91%, #0B0C0B 96%, #0A0B0A 100%);
}
/* the tool wallpaper rides over the ramp, same as it does across the old seam */
.portfolio-band::before { z-index:2; }

/* the grid tiles sit on the ramp, so their own plate has to disappear */
.portfolio-band .gal-item { background:rgba(10,11,10,0.18); }
.portfolio-band .gal-item picture { display:block; width:100%; height:100%; }
/* filters read on bone, so they keep the light-zone treatment */
.portfolio-band .gal-empty { color:var(--muted); }

@media (max-width:900px){ .portfolio-band::after { height:clamp(260px,46vw,420px); } }

/* ============================================================
   INSTAGRAM — the feed strip and the credentials off the profile
   A snapshot, not a live embed: Instagram's CDN signs its image URLs
   with an expiry, so anything hot-linked would break within days.
   These are copies, and they go stale when the shop posts again —
   the "See all N posts" link is what stays current.
   ============================================================ */
.ig-head { display:flex; flex-wrap:wrap; align-items:flex-end; gap:18px 30px; margin-bottom:26px; }
.ig-handle {
  font-family:var(--font-display); font-weight:800; text-transform:uppercase;
  font-size:clamp(1.6rem,3.4vw,2.3rem); line-height:1; color:var(--fg);
}
.ig-handle span { color:var(--accent); }
.ig-stats { display:flex; gap:22px; margin-left:auto; }
.ig-stat { font-family:var(--font-mono); font-size:0.72rem; letter-spacing:0.12em; text-transform:uppercase; color:var(--faint); }
.ig-stat b { display:block; font-family:var(--font-display); font-weight:800; font-size:1.5rem; letter-spacing:0; color:var(--fg); }

/* the two claims that were only ever on the Instagram bio */
.ig-creds { display:grid; grid-template-columns:repeat(2,1fr); gap:14px; margin-bottom:30px; }
.ig-cred {
  border:1px solid var(--line); padding:18px 20px;
  font-family:var(--font-body); font-size:0.98rem; line-height:1.5; color:var(--muted);
}
.ig-cred b { display:block; font-family:var(--font-mono); font-weight:600; font-size:0.7rem;
  letter-spacing:0.16em; text-transform:uppercase; color:var(--accent); margin-bottom:8px; }

.ig-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:10px; }
.ig-item { position:relative; display:block; aspect-ratio:1/1; overflow:hidden; background:var(--surface); }
.ig-item img { width:100%; height:100%; object-fit:cover; transition:transform 0.9s var(--ease); }
.ig-item:hover img { transform:scale(1.06); }
.ig-item::after {
  content:""; position:absolute; inset:0; background:linear-gradient(180deg,transparent 55%,rgba(10,11,10,0.8));
  opacity:0; transition:opacity 0.4s;
}
.ig-item:hover::after { opacity:1; }
/* reels get a marker so the strip does not pretend every tile is a photo */
.ig-item .ig-play {
  position:absolute; top:9px; right:9px; z-index:2; width:19px; height:19px;
  color:#F2EFE6; filter:drop-shadow(0 1px 3px rgba(0,0,0,0.6));
}
.ig-foot { display:flex; flex-wrap:wrap; align-items:center; gap:16px; margin-top:26px; }

@media (max-width:900px){
  .ig-grid { grid-template-columns:repeat(3,1fr); }
  .ig-creds { grid-template-columns:1fr; }
  .ig-stats { margin-left:0; }
}
@media (max-width:560px){ .ig-grid { grid-template-columns:repeat(2,1fr); } }

.section-head { margin-bottom:clamp(40px,5vw,66px); }
.section-head .guard { margin-bottom:22px; }
.section-head h2 { max-width:16ch; }
.section-head p { color:var(--muted); margin-top:22px; max-width:56ch; font-size:1.02rem; }
.section-head.center { text-align:center; }
.section-head.center h2, .section-head.center p { margin-left:auto; margin-right:auto; }
.section-head.center .guard { justify-content:center; }
.section-head.center .guard::after { display:none; }

/* ============================================================
   PRICE BOARD — the wall menu. The centrepiece of the bone band.
   ============================================================ */
.board { border-top:1px solid var(--line-2); }
.board-row {
  display:grid; grid-template-columns:auto 1fr auto auto; align-items:baseline;
  gap:clamp(14px,3vw,30px); padding:clamp(18px,2.4vw,26px) 0;
  border-bottom:1px solid var(--line); position:relative;
  transition:padding-left 0.45s var(--snap), color 0.35s var(--ease);
}
/* The slide-in plate is for the about page's values list only. On the price
   board it turned the whole row black under the cursor, which buried the price
   you were reading — the row already moves and the Book tag already lights up,
   so the plate was doing nothing except getting in the way. */
.board-row:not(a)::before {
  content:""; position:absolute; left:0; top:0; bottom:0; width:0; z-index:-1;
  background:var(--fg); transition:width 0.5s var(--snap);
}
.board-row:hover { padding-left:clamp(12px,2vw,26px); }
.board-row:not(a):hover::before { width:100%; }
.board-row:not(a):hover, .board-row:not(a):hover .b-price { color:var(--bg); }
.board-row:not(a):hover .b-guard { color:var(--green); }
.board-row:not(a):hover .b-desc { color:rgba(237,231,217,0.62); }
.zone-bone .board-row:not(a):hover .b-desc { color:rgba(237,231,217,0.7); }

.b-guard { font-family:var(--font-mono); font-size:0.7rem; font-weight:600; letter-spacing:0.1em; color:var(--accent); min-width:3.4ch; font-variant-numeric:tabular-nums; transition:color 0.35s; }
.b-main { min-width:0; }
.b-name { font-family:var(--font-display); font-weight:700; text-transform:uppercase; font-size:clamp(1.5rem,3.2vw,2.5rem); line-height:1; letter-spacing:0.005em; }
/* the after-8pm rate, on the service it belongs to. It used to be three
   duplicate rows in a separate "After 8 PM" section — the same three services
   listed twice, so you had to scroll to another block to find out what your
   cut cost in the evening. One line under the description says it in place. */
.b-late {
  display:inline-flex; align-items:center; margin-top:10px;
  font-family:var(--font-mono); font-weight:500; font-size:0.68rem;
  letter-spacing:0.1em; color:var(--accent);
  border:1px solid var(--line-2); border-radius:999px; padding:5px 12px;
  transition:color 0.35s, border-color 0.35s;
}
/* the pill just firms up rather than inverting */
a.board-row:hover .b-late { border-color:var(--accent); }

.b-desc { display:block; font-family:var(--font-body); font-size:0.86rem; color:var(--muted); margin-top:8px; line-height:1.5; transition:color 0.35s; }
.b-price {
  font-family:var(--font-display); font-weight:800; font-size:clamp(1.5rem,3.2vw,2.5rem);
  line-height:1; white-space:nowrap; font-variant-numeric:tabular-nums; transition:color 0.35s;
}
.b-price small { font-family:var(--font-mono); font-weight:500; font-size:0.69rem; letter-spacing:0.12em; display:block; text-align:right; margin-bottom:6px; color:var(--faint); }
/* the duration sits under the price rather than trailing the description —
   the generic `.b-price small` rule above is the "from" label and pushes
   space BELOW itself, so this one has to undo that and push space above */
.b-price .b-mins {
  margin-bottom:0; margin-top:9px;
  font-size:0.68rem; letter-spacing:0.14em; text-transform:uppercase;
}
.board-row:not(a):hover .b-mins { color:rgba(237,231,217,0.6); }
/* the Book tag on each price row */
.b-book {
  display:inline-flex; align-items:center; gap:8px; align-self:center;
  font-family:var(--font-mono); font-weight:600; font-size:0.66rem;
  letter-spacing:0.16em; text-transform:uppercase; white-space:nowrap;
  padding:11px 16px; border:1px solid var(--line-2); border-radius:3px;
  color:inherit;
  transition:background 0.35s var(--ease), border-color 0.35s var(--ease), color 0.35s var(--ease);
}
.b-book svg { width:13px; height:13px; transition:transform 0.4s var(--snap); }
/* the row inverts on hover, so the tag has to go somewhere the inverted
   plate cannot swallow it — the accent, which reads on both plates */
.board-row:hover .b-book {
  background:var(--accent); border-color:var(--accent); color:var(--green-ink);
}
.board-row:hover .b-book svg { transform:translateX(3px); }

.board-note { margin-top:30px; font-family:var(--font-mono); font-size:0.7rem; letter-spacing:0.06em; color:var(--faint); line-height:1.9; }

/* group heading inside a board */
.board-group { margin-bottom:clamp(44px,6vw,72px); }
.board-group > h3 {
  font-size:clamp(1.1rem,2vw,1.5rem); letter-spacing:0.04em; color:var(--accent);
  display:flex; align-items:center; gap:16px; margin-bottom:6px;
}
.board-group > h3::after { content:""; flex:1; height:1px; background:var(--line); }
.board-group .group-note { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.06em; color:var(--faint); margin:10px 0 4px; }
/* keep the sweep behind the row's own content, not behind the zone */
.board-row:not(a)::before { z-index:0; }
.board-row > * { position:relative; z-index:1; }

/* ============================================================
   STATS — three big facts, no boxes
   ============================================================ */
.stats { display:grid; grid-template-columns:repeat(3,1fr); border-top:1px solid var(--line); }
.stat { padding:clamp(28px,3.5vw,46px) 0; border-bottom:1px solid var(--line); }
.stat + .stat { border-left:1px solid var(--line); padding-left:clamp(20px,3vw,40px); }
.stat b { display:block; font-family:var(--font-display); font-weight:800; font-size:clamp(3.4rem,8vw,6.4rem); line-height:0.85; color:var(--accent); font-variant-numeric:tabular-nums; }
.stat span { display:block; margin-top:14px; font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.2em; text-transform:uppercase; color:var(--muted); }

/* ============================================================
   PROCESS — a real sequence, so it is numbered
   ============================================================ */
.steps { display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--line); border:1px solid var(--line); }
.step { position:relative; padding:clamp(28px,3.5vw,44px); background:var(--bg); transition:background 0.4s var(--ease); }
.step:hover { background:var(--surface); }
.step .step-no { font-family:var(--font-display); font-weight:800; font-size:clamp(2.6rem,5vw,4rem); line-height:0.8; color:var(--line-2); font-variant-numeric:tabular-nums; }
.step h3 { font-size:clamp(1.3rem,2.2vw,1.7rem); margin:18px 0 12px; }
.step p { color:var(--muted); font-size:0.94rem; }
.step .step-ic { position:absolute; top:clamp(28px,3.5vw,44px); right:clamp(28px,3.5vw,44px); color:var(--accent); }
.step .step-ic svg { width:22px; height:22px; }

/* ============================================================
   WHERE TO NEXT — the three routes off the homepage
   ============================================================ */
/* auto-fit, not a hardcoded 3. The grid used to be fixed at three columns;
   when the Work card was removed the third column stayed behind as an empty
   grey panel. This now matches however many cards are actually present. */
.next-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:1px; background:var(--line); border:1px solid var(--line); margin-top:clamp(40px,5vw,64px); }
.next-card {
  display:flex; flex-direction:column; gap:8px; padding:clamp(26px,3.2vw,38px);
  background:var(--bg); transition:background 0.4s var(--ease), transform 0.4s var(--snap);
}
.next-card:hover { background:var(--surface); }
.nc-guard { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.22em; text-transform:uppercase; color:var(--accent); }
.next-card h3 { font-size:clamp(1.3rem,2.2vw,1.75rem); margin-top:4px; }
.next-card p { color:var(--muted); font-size:0.92rem; flex:1; }
.nc-go {
  display:inline-flex; align-items:center; gap:9px; margin-top:14px;
  font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.16em; text-transform:uppercase; color:var(--fg);
}
.nc-go svg { width:14px; height:14px; transition:transform 0.4s var(--snap); }
.next-card:hover .nc-go { color:var(--accent); }
.next-card:hover .nc-go svg { transform:translateX(5px); }
@media (max-width:860px){ .next-grid { grid-template-columns:1fr; } }

/* ============================================================
   REVIEWS — pull quotes, not cards
   ============================================================ */
/* ============================================================
   THE REVIEW WALL — every review off Google and Booksy
   A CSS column masonry rather than a grid: the cards are wildly
   different lengths, and a grid would leave a ragged gap under every
   short one. Columns let each card be exactly as tall as its words.
   ============================================================ */
.rev-sources { display:flex; flex-wrap:wrap; gap:12px; margin-bottom:clamp(26px,3vw,40px); }
.rev-source {
  display:inline-flex; align-items:center; gap:12px;
  border:1px solid var(--line); background:var(--surface);
  padding:12px 18px; border-radius:999px; text-decoration:none; color:inherit;
  transition:border-color 0.3s var(--ease), transform 0.3s var(--snap);
}
.rev-source:hover { border-color:var(--accent); transform:translateY(-2px); }
.rev-source b { font-family:var(--font-display); font-weight:800; font-size:1.3rem; line-height:1; }
.rev-source span {
  font-family:var(--font-mono); font-size:0.68rem; letter-spacing:0.13em;
  text-transform:uppercase; color:var(--faint); line-height:1.5;
}
.rev-source .rs-stars { color:var(--gold); letter-spacing:2px; font-size:0.75rem; }

.rev-wall { columns:3; column-gap:clamp(14px,1.6vw,20px); }
.rev-card {
  break-inside:avoid; -webkit-column-break-inside:avoid;
  display:inline-block; width:100%;
  margin:0 0 clamp(14px,1.6vw,20px);
  background:var(--surface); border:1px solid var(--line);
  border-radius:14px; padding:clamp(18px,2vw,24px);
}
.rev-card .rc-stars { color:var(--gold); letter-spacing:3px; font-size:0.82rem; margin-bottom:12px; }
.rev-card p {
  font-family:var(--font-body); font-size:1rem; line-height:1.55; color:var(--fg);
  margin:0 0 16px;
}
.rev-who { display:flex; align-items:center; gap:11px; }
.rev-av {
  width:34px; height:34px; flex-shrink:0; border-radius:50%;
  background:var(--accent); color:var(--green-ink);
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-weight:800; font-size:0.95rem;
}
.rev-who b { display:block; font-family:var(--font-body); font-weight:600; font-size:0.88rem; }
.rev-who span {
  display:block; font-family:var(--font-mono); font-size:0.64rem;
  letter-spacing:0.11em; text-transform:uppercase; color:var(--faint); margin-top:2px;
}
.rev-card.hide { display:none; }
.rev-more { display:flex; justify-content:center; margin-top:30px; }
.rev-more.done { display:none; }

@media (max-width:980px){ .rev-wall { columns:2; } }
@media (max-width:620px){ .rev-wall { columns:1; } }

.reviews { display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(24px,3vw,44px); }
.review { display:flex; flex-direction:column; gap:18px; padding-top:26px; border-top:2px solid var(--accent); }
.review .stars { font-family:var(--font-mono); color:var(--gold); letter-spacing:4px; font-size:0.9rem; }
.review p { font-family:var(--font-display); font-weight:600; text-transform:none; font-size:clamp(1.25rem,2.1vw,1.6rem); line-height:1.16; letter-spacing:0.005em; }
.review .who { display:flex; align-items:center; gap:12px; margin-top:auto; }
.review .who .av {
  width:38px; height:38px; flex-shrink:0; display:flex; align-items:center; justify-content:center;
  border:1px solid var(--line-2); font-family:var(--font-display); font-weight:700; font-size:1rem; color:var(--accent);
}
.review .who b { display:block; font-family:var(--font-body); font-size:0.9rem; }
.review .who span { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.12em; text-transform:uppercase; color:var(--faint); }

/* ============================================================
   SPLIT — portrait + statement
   ============================================================ */
.split { display:grid; grid-template-columns:1fr 1fr; gap:clamp(32px,5vw,72px); align-items:center; }
.split.reverse .split-media { order:2; }
.split-media { position:relative; aspect-ratio:4/5; overflow:hidden; background:var(--surface); }
.split-media img { width:100%; height:100%; object-fit:cover; transition:transform 1.2s var(--ease); }
.split-media:hover img { transform:scale(1.04); }
.split h2 { margin:20px 0 24px; }
.split p { color:var(--muted); margin-bottom:16px; }
/* The one soft edge. Everything else on this page is uppercase condensed
   with a hard corner; this line is a lowercase italic serif, used here and
   nowhere else, so it reads as the human moment rather than another heading. */
/* The pull quote. It used to be Instrument Serif italic — the one serif in
   the whole site, sitting on its own with nothing to answer it, which read
   as a stray font rather than a deliberate one. Now it is the body face at
   a medium weight with the same tight negative tracking the mobile menu
   uses, so the line still stands apart by size and rule without importing
   a voice the rest of the page never speaks in. */
.split .signature {
  font-family:var(--font-body); font-style:normal; font-weight:500;
  text-transform:none; letter-spacing:-0.025em;
  font-size:clamp(1.5rem,2.9vw,2.2rem); line-height:1.25; color:var(--fg);
  border-left:2px solid var(--accent); padding-left:24px; margin:32px 0;
}

/* ============================================================
   INFO — hours + find us, as a ledger
   ============================================================ */
.info-grid { display:grid; grid-template-columns:1fr 1fr; gap:clamp(24px,3vw,44px); }
.info-card { border-top:1px solid var(--line-2); padding-top:26px; }
.info-card h3 { font-size:clamp(1.3rem,2.2vw,1.7rem); }
.hours-head { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:22px; flex-wrap:wrap; }
.hours-status { display:inline-flex; align-items:center; gap:8px; font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.16em; text-transform:uppercase; padding:7px 12px; border:1px solid var(--line-2); }
.hours-status .hs-dot { width:7px; height:7px; min-width:7px; border-radius:50%; background:var(--faint); }
.hours-status.open { border-color:var(--accent); color:var(--accent); }
.hours-status.open .hs-dot { background:var(--accent); }
.hours-status.closed { border-color:var(--red); color:var(--red); }
.hours-status.closed .hs-dot { background:var(--red); }
.hours-row { display:flex; justify-content:space-between; align-items:center; gap:16px; padding:13px 0; border-bottom:1px solid var(--line); }
.hours-row > span:first-child { display:inline-flex; align-items:center; gap:12px; white-space:nowrap; font-family:var(--font-mono); font-size:0.74rem; letter-spacing:0.1em; text-transform:uppercase; color:var(--muted); }
.hours-row > span:last-child { font-family:var(--font-mono); font-size:0.78rem; color:var(--fg); font-variant-numeric:tabular-nums; }
.day-dot { width:6px; height:6px; min-width:6px; background:var(--line-2); transform:rotate(45deg); }
.hours-row.is-open .day-dot { background:var(--accent); }
.hours-row.today > span:first-child { color:var(--fg); font-weight:600; }
.today-pill { display:none; }
.hours-row.today .today-pill { display:inline-flex; font-size:0.69rem; letter-spacing:0.14em; color:var(--green-ink); background:var(--green); padding:3px 8px; }
.info-line { display:flex; gap:16px; padding:16px 0; border-bottom:1px solid var(--line); align-items:flex-start; }
.info-line:last-child { border-bottom:none; }
.info-line svg { width:17px; height:17px; color:var(--accent); flex-shrink:0; margin-top:4px; }
.info-line .lbl { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.2em; text-transform:uppercase; color:var(--faint); margin-bottom:4px; }
/* phone and email are the two things people tap on a contact page */
.info-line .val { color:var(--fg); }
.info-line a.val { display:inline-flex; align-items:center; min-height:44px; }
.info-line a.val:hover { color:var(--accent); }
.map-embed { border:1px solid var(--line); height:clamp(280px,38vw,420px); overflow:hidden; }
.map-embed iframe { width:100%; height:100%; display:block; border:0; }

/* trust ledger + gift card */
.extras-grid { display:grid; grid-template-columns:1fr 1fr; gap:clamp(24px,3vw,44px); }
.trust-row { display:flex; gap:16px; padding:15px 0; border-bottom:1px solid var(--line); align-items:center; }
.trust-row:last-child { border-bottom:none; }
.trust-ic { width:34px; height:34px; min-width:34px; display:flex; align-items:center; justify-content:center; border:1px solid var(--line-2); color:var(--accent); }
.trust-ic svg { width:16px; height:16px; }
.trust-row b { display:block; font-family:var(--font-mono); font-size:0.7rem; letter-spacing:0.12em; text-transform:uppercase; }
.trust-row span { font-size:0.86rem; color:var(--muted); }
.giftcard { display:flex; flex-direction:column; justify-content:center; }
.giftcard h3 { font-size:clamp(1.8rem,3.4vw,2.8rem); margin:14px 0 14px; }
.giftcard h3 em { font-style:normal; color:var(--accent); }
.giftcard p { color:var(--muted); margin-bottom:26px; max-width:40ch; }
.giftcard .btn { align-self:flex-start; }

/* ============================================================
   QUIZ — a ticket you fill in
   ============================================================ */
.quiz-card { position:relative; max-width:760px; margin:0 auto; border:1px solid var(--line-2); background:var(--surface); padding:clamp(28px,4vw,48px); }
.quiz-progress { position:absolute; top:0; left:0; right:0; height:3px; background:var(--line); }
.quiz-progress span { display:block; height:100%; width:20%; background:var(--accent); transition:width 0.5s var(--snap); }
.quiz-step { display:none; }
.quiz-step.active { display:block; animation:fade-up 0.45s var(--ease); }
.quiz-q-num { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.22em; text-transform:uppercase; color:var(--accent); }
.quiz-q { font-size:clamp(1.6rem,3.2vw,2.4rem); margin:14px 0 28px; }
.quiz-options { display:grid; grid-template-columns:1fr 1fr; gap:12px; }
.quiz-opt {
  position:relative; text-align:left; padding:20px 22px; border:1px solid var(--line-2);
  background:transparent; color:var(--fg); font-family:var(--font-mono); font-size:0.78rem;
  letter-spacing:0.08em; text-transform:uppercase; cursor:pointer; overflow:hidden;
  transition:color 0.35s var(--ease), border-color 0.35s var(--ease);
}
.quiz-opt::after { content:""; position:absolute; inset:0; z-index:0; background:var(--accent); transform:translateY(101%); transition:transform 0.4s var(--snap); }
.quiz-opt > * , .quiz-opt { position:relative; }
.quiz-opt span { position:relative; z-index:1; }
.quiz-opt:hover { border-color:var(--accent); color:var(--green-ink); }
.quiz-opt:hover::after { transform:translateY(0); }
.quiz-back { margin-top:26px; background:none; border:none; color:var(--muted); font-family:var(--font-mono); font-size:0.7rem; letter-spacing:0.12em; text-transform:uppercase; cursor:pointer; transition:color 0.3s; }
.quiz-back:hover { color:var(--fg); }
.quiz-result { text-align:center; }
.quiz-rec-title { font-size:clamp(1.8rem,4vw,3rem); color:var(--accent); margin:16px 0 14px; }
.quiz-rec-desc { color:var(--muted); max-width:48ch; margin:0 auto 30px; }
.quiz-cta { display:flex; gap:14px; justify-content:center; flex-wrap:wrap; }

/* ============================================================
   FAQ — a ledger of questions
   ============================================================ */
.faq { max-width:900px; margin:0 auto; border-top:1px solid var(--line-2); }
.faq-item { border-bottom:1px solid var(--line); }
.faq-q {
  width:100%; background:none; border:none; color:var(--fg); cursor:pointer;
  font-family:var(--font-display); font-weight:700; text-transform:uppercase;
  font-size:clamp(1.15rem,2.2vw,1.7rem); line-height:1.1; letter-spacing:0.01em;
  text-align:left; padding:26px 0; display:flex; justify-content:space-between; align-items:center; gap:24px;
  transition:color 0.3s, padding-left 0.4s var(--snap);
}
.faq-q:hover { color:var(--accent); padding-left:8px; }
.faq-q .ic { flex-shrink:0; width:22px; height:22px; position:relative; }
.faq-q .ic::before, .faq-q .ic::after { content:""; position:absolute; background:var(--accent); top:50%; left:50%; transform:translate(-50%,-50%); }
.faq-q .ic::before { width:14px; height:2px; }
.faq-q .ic::after { width:2px; height:14px; transition:transform 0.4s var(--snap); }
.faq-item.open .faq-q .ic::after { transform:translate(-50%,-50%) scaleY(0); }
/* visibility (not just max-height) so a screen reader skips a closed panel;
   the 0s delay lets the collapse finish playing before it disappears. */
.faq-a { max-height:0; overflow:hidden; visibility:hidden; transition:max-height 0.55s var(--ease), visibility 0s linear 0.55s; }
.faq-item.open .faq-a { visibility:visible; transition:max-height 0.55s var(--ease), visibility 0s linear 0s; }
.faq-a p { color:var(--muted); padding-bottom:28px; max-width:70ch; }

/* ============================================================
   FOLLOW + CTA
   ============================================================ */
.follow-row { display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--line); border:1px solid var(--line); }
.follow-btn { display:flex; align-items:center; gap:16px; padding:26px 28px; background:var(--bg); transition:background 0.4s var(--ease), color 0.4s; }
.follow-btn:hover { background:var(--accent); color:var(--green-ink); }
.follow-btn .fi { width:38px; height:38px; flex-shrink:0; display:flex; align-items:center; justify-content:center; border:1px solid currentColor; }
.follow-btn .fi svg { width:19px; height:19px; }
.follow-btn .ft b { display:block; font-family:var(--font-display); font-weight:700; text-transform:uppercase; font-size:1.2rem; line-height:1; }
.follow-btn .ft span { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.1em; color:var(--muted); }
.follow-btn:hover .ft span { color:var(--green-ink); opacity:0.75; }

.cta-band {
  /* was clamp(90px,12vw,170px) — deeper than a normal section on both sides,
     and the section above it still pays its own floor, so the seam ran to ~270px */
  position:relative; text-align:center; padding:clamp(66px,8vw,116px) 0; overflow:hidden;
  /* flat — the green wash made the band look like it was lit from off-screen */
}
/* The eyebrow carries a trailing rule, which is inside the box being centred —
   so the label itself landed 48px left of everything below it. Same fix the
   centred section heads already use. */
.cta-band .guard { justify-content:center; }
.cta-band .guard::after { display:none; }
.cta-band h2 { font-size:clamp(3rem,11vw,9rem); }
.cta-band h2 em { font-style:normal; color:var(--green); }
.cta-band p { color:var(--muted); margin:24px auto 40px; max-width:48ch; }

/* ============================================================
   PAGE HERO · PROSE · FORM
   ============================================================ */
.page-hero { position:relative; padding:clamp(52px,7vw,96px) 0 clamp(40px,5vw,64px); border-bottom:1px solid var(--line); overflow:hidden; }
/* nothing may draw a hairline where the taper starts — it reads as a hard ledge */
.page-hero:has(+ .fade-in-bone) { border-bottom:0; }
.page-hero h1 { margin-top:22px; }
/* the motion module injects <span class="anim-word"> wrappers into headings, so
   this must only colour the author's own accent span, not every word */
.page-hero h1 span:not(.anim-word):not(.anim-line) { color:var(--green); }
.page-hero p { color:var(--muted); margin-top:22px; max-width:54ch; }

.prose { max-width:760px; }
.prose h2 { font-size:clamp(1.4rem,2.4vw,1.9rem); color:var(--accent); margin:44px 0 16px; }
.prose p { color:var(--muted); margin-bottom:16px; }
.prose a { color:var(--gold); border-bottom:1px solid currentColor; }
.prose .updated { font-family:var(--font-mono); font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase; color:var(--faint); margin-top:44px; }

.contact-grid { display:grid; grid-template-columns:1fr 1fr; gap:clamp(32px,5vw,68px); align-items:start; }
.form-field { margin-bottom:22px; }
.form-field label { display:block; font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.2em; text-transform:uppercase; color:var(--muted); margin-bottom:10px; }
.form-field input, .form-field textarea {
  width:100%; background:var(--surface); border:1px solid var(--line-2); color:var(--fg);
  padding:16px; border-radius:0; font-family:var(--font-body); font-size:1rem;
  transition:border-color 0.3s, background 0.3s;
}
.form-field input::placeholder, .form-field textarea::placeholder { color:var(--faint); }
.form-field input:focus, .form-field textarea:focus { outline:none; border-color:var(--accent); background:var(--bg); }
.form-field textarea { min-height:150px; resize:vertical; }
.consent { display:flex; gap:12px; align-items:flex-start; margin-bottom:24px; }
/* a 13px checkbox is not tappable; the label is also a target, so the pair
   gives a comfortable hit area either way */
.consent input { width:22px; height:22px; min-width:22px; margin-top:2px; accent-color:var(--green); cursor:pointer; }
.consent label { cursor:pointer; padding:10px 0; }
.consent label { font-size:0.84rem; color:var(--muted); }
.form-msg { margin-top:18px; font-family:var(--font-mono); font-size:0.76rem; letter-spacing:0.06em; display:none; }
.form-msg.ok { display:block; color:var(--accent); }
.form-msg.err { display:block; color:var(--red); }

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer { position:relative; background:var(--noir); padding:clamp(64px,8vw,100px) 0 36px; border-top:1px solid var(--line); }
.footer-mast { font-family:var(--font-display); font-weight:800; text-transform:uppercase; font-size:clamp(3.4rem,15vw,13rem); line-height:0.82; letter-spacing:-0.02em; color:transparent; -webkit-text-stroke:1px rgba(242,239,230,0.22); margin-bottom:clamp(40px,6vw,72px); }
.footer-grid { display:grid; grid-template-columns:1.6fr 1fr 1fr 1fr; gap:clamp(28px,4vw,48px); margin-bottom:56px; }
.footer-brand img { height:52px; margin-bottom:20px; }
.footer-brand p { color:var(--muted); font-size:0.9rem; max-width:32ch; }
.footer-col h4 { font-family:var(--font-mono); font-weight:500; font-size:0.69rem; letter-spacing:0.24em; color:var(--gold); margin-bottom:22px; }
.footer-col a, .footer-col p { display:block; color:var(--muted); font-size:0.9rem; margin-bottom:12px; transition:color 0.3s, padding-left 0.3s var(--snap); }
.footer-col a:hover { color:var(--fg); padding-left:5px; }
.socials { display:flex; gap:10px; }
.socials a { width:40px; height:40px; border:1px solid var(--line-2); display:flex; align-items:center; justify-content:center; transition:0.3s; }
.socials a:hover { background:var(--green); border-color:var(--green); color:var(--green-ink); }
.socials svg { width:17px; height:17px; }
.footer-bottom { display:flex; justify-content:space-between; align-items:center; gap:14px; flex-wrap:wrap; padding-top:28px; border-top:1px solid var(--line); font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.12em; text-transform:uppercase; color:var(--faint); }

/* the studio credit — inherits the footer's mono voice, lifts to the accent on
   hover so it reads as a link without shouting over the shop's own footer */
.footer-bottom .credit a {
  color:var(--muted); border-bottom:1px solid var(--line-2);
  padding-bottom:1px; transition:color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.footer-bottom .credit a:hover { color:var(--accent); border-bottom-color:var(--accent); }

/* ============================================================
   TOUCH TARGETS — 44px is the floor a finger can hit reliably.
   Applied as min-height plus centring so nothing shifts visually;
   the extra area is padding, not a bigger-looking control.
   ============================================================ */
.brand { min-height:44px; }
.burger { min-width:44px; min-height:44px; }
.chair-launch, .desk-launch { min-height:44px; }
.footer-col a, .mobile-menu a {
  min-height:44px; display:flex; align-items:center;
}
.footer-bottom .credit a { display:inline-flex; align-items:center; min-height:44px; }
.nav-links a { min-height:40px; display:inline-flex; align-items:center; }
.socials a { min-width:44px; min-height:44px; display:inline-flex; align-items:center; justify-content:center; }

/* Coarse pointers get the full treatment — a mouse can hit a 34px target,
   a thumb on a moving bus cannot. */
@media (pointer:coarse){
  .nav-links a, .gal-filter, .quiz-opt, .faq-q, .b-price small,
  .fx-seg button, .chair-tab { min-height:44px; }
  .fx-range, .quiz-back { min-height:44px; }
  input, select, textarea { min-height:44px; font-size:16px; }  /* 16px stops iOS zooming on focus */
}

/* ============================================================
   BOTTOM FURNITURE — steps aside while you scroll

   The book bar and the launcher dock sit over the content. While the page is
   moving they drop out of the way in either direction and come back once it
   settles, so nothing is ever reading underneath them. Transform only, so it
   composites on the GPU and costs nothing per frame.
   ============================================================ */
.book-bar, .dock {
  transition:transform 0.34s var(--ease), opacity 0.34s var(--ease);
  will-change:transform;
}
html.scrolling .book-bar { transform:translateY(115%); }
html.scrolling .dock     { transform:translateY(calc(100% + var(--gutter) + 12px)); opacity:0; }

/* an open panel keeps its launcher anchored — nothing should slide out from
   under a thing the visitor is currently using */
html.scrolling .dock:has(.is-open) { transform:none; opacity:1; }

@media (prefers-reduced-motion: reduce){
  .book-bar, .dock { transition:none; }
  html.scrolling .book-bar, html.scrolling .dock { transform:none; opacity:1; }
}

/* ============================================================
   REVEAL
   ============================================================ */
.reveal { opacity:0; transform:translateY(26px); transition:opacity 0.9s var(--ease), transform 0.9s var(--ease); }
.reveal.in { opacity:1; transform:none; }
.reveal.d1 { transition-delay:0.08s; } .reveal.d2 { transition-delay:0.16s; } .reveal.d3 { transition-delay:0.24s; }

/* ============================================================
   WORK — the cut gallery
   ============================================================ */
.gal-filters { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:26px; }
.gal-filter {
  font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.16em; text-transform:uppercase;
  padding:10px 15px; background:transparent; border:1px solid var(--line-2); color:var(--muted);
  cursor:pointer; transition:color 0.3s, background 0.3s, border-color 0.3s;
}
.gal-filter:hover { color:var(--fg); border-color:var(--fg); }
.gal-filter[aria-pressed="true"] { background:var(--accent); border-color:var(--accent); color:var(--green-ink); }

/* the work, split under its own headings.
   The mount point is itself a .gallery, so once groups are put inside it the
   four-column grid would treat each GROUP as a cell and stand the three
   categories side by side at a quarter width. script.js flags it .gal-grouped
   so it stops being a grid; the real grids are the ones inside the groups. */
.gallery.gal-grouped { display:block; }
.gal-group { margin-bottom:clamp(34px,4.5vw,56px); }
.gal-group:last-child { margin-bottom:0; }
.gal-group.hide { display:none; }
.gal-cat {
  font-family:var(--font-mono); font-weight:600; font-size:0.72rem;
  letter-spacing:0.2em; text-transform:uppercase; color:var(--accent);
  margin-bottom:16px; display:flex; align-items:center; gap:14px;
}
.gal-cat::after { content:""; flex:1; height:1px; background:var(--line); }

.gallery { display:grid; grid-template-columns:repeat(4,1fr); gap:10px; }
.gal-item {
  position:relative; aspect-ratio:3/4; overflow:hidden; border:0; padding:0; margin:0;
  background:var(--surface); cursor:pointer; display:block;
  transition:opacity 0.45s var(--ease), transform 0.45s var(--snap);
}
.gal-item.tall { grid-row:span 2; aspect-ratio:3/8; }
.gal-item.hide { display:none; }
.gal-item img { width:100%; height:100%; object-fit:cover; transition:transform 0.9s var(--ease); }
.gal-item::after { content:""; position:absolute; inset:0; background:linear-gradient(180deg,transparent 45%,rgba(10,11,10,0.85)); opacity:0; transition:opacity 0.45s; }
.gal-item:hover img { transform:scale(1.06); }
.gal-item:hover::after { opacity:1; }
.gal-tag {
  position:absolute; left:14px; bottom:13px; z-index:2; text-align:left;
  font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.14em; text-transform:uppercase;
  color:#F2EFE6; opacity:0; transform:translateY(8px); transition:0.45s var(--snap);
}
.gal-item:hover .gal-tag { opacity:1; transform:none; }
.gal-empty { font-family:var(--font-mono); font-size:0.72rem; letter-spacing:0.08em; color:var(--faint); padding:30px 0; }

/* lightbox */
.lightbox {
  position:fixed; inset:0; z-index:80; background:rgba(6,7,6,0.94);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  display:flex; align-items:center; justify-content:center; padding:var(--gutter);
  opacity:0; visibility:hidden; transition:opacity 0.35s var(--ease), visibility 0.35s;
}
.lightbox.open { opacity:1; visibility:visible; }
.lightbox img { max-width:100%; max-height:82vh; object-fit:contain; }
.lb-cap { position:absolute; left:0; right:0; bottom:calc(var(--gutter) + 4px); text-align:center; font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.16em; text-transform:uppercase; color:#8E958C; }
.lb-btn {
  position:absolute; background:transparent; border:1px solid rgba(242,239,230,0.25); color:#F2EFE6;
  width:46px; height:46px; cursor:pointer; display:flex; align-items:center; justify-content:center; transition:0.3s;
}
.lb-btn:hover { background:var(--green); border-color:var(--green); color:var(--green-ink); }
.lb-btn svg { width:16px; height:16px; }
.lb-close { top:var(--gutter); right:var(--gutter); }
.lb-prev { left:var(--gutter); top:50%; transform:translateY(-50%); }
.lb-next { right:var(--gutter); top:50%; transform:translateY(-50%); }

/* ============================================================
   BEFORE / AFTER — the fade, made literal
   ============================================================ */
/* capped so it never eats the viewport on a wide monitor */
.ba {
  position:relative; width:100%; max-width:920px; margin:0 auto;
  aspect-ratio:3/2; max-height:min(70vh, 620px);
  overflow:hidden; background:var(--surface);
  border:1px solid var(--line-2);
  user-select:none; touch-action:pan-y;
}
.ba img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; pointer-events:none; }
.ba .ba-after { clip-path:inset(0 0 0 var(--pos, 50%)); }
.ba-line { position:absolute; top:0; bottom:0; left:var(--pos, 50%); width:2px; background:var(--green); pointer-events:none; }
.ba-grip {
  position:absolute; top:50%; left:var(--pos, 50%); transform:translate(-50%,-50%);
  width:46px; height:46px; background:var(--green); color:var(--green-ink);
  display:flex; align-items:center; justify-content:center; pointer-events:none;
}
.ba-grip svg { width:20px; height:20px; }
.ba-label {
  position:absolute; top:14px; font-family:var(--font-mono); font-size:0.69rem;
  letter-spacing:0.16em; text-transform:uppercase; color:#F2EFE6;
  background:rgba(10,11,10,0.7); padding:6px 11px; pointer-events:none;
}
.ba-label.is-before { left:14px; }
.ba-label.is-after { right:14px; }
.ba-range { position:absolute; inset:0; width:100%; height:100%; opacity:0; cursor:ew-resize; margin:0; }
.ba-range:focus-visible + .ba-line { box-shadow:0 0 0 3px rgba(0,224,107,0.4); }

/* ============================================================
   BARBERS
   ============================================================ */
.crew { display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(20px,3vw,34px); }
/* until the other chairs are filled in, one profile shouldn't stretch the row */
.crew[data-count="1"] { grid-template-columns:minmax(0,380px); }
.crew[data-count="2"] { grid-template-columns:repeat(2,minmax(0,380px)); }
.barber { display:flex; flex-direction:column; }
.barber-shot { position:relative; aspect-ratio:3/4; overflow:hidden; background:var(--surface); margin-bottom:18px; }
.barber-shot img { width:100%; height:100%; object-fit:cover; transition:transform 1s var(--ease); }
.barber:hover .barber-shot img { transform:scale(1.04); }
.barber-shot .b-role { position:absolute; left:0; bottom:0; background:var(--green); color:var(--green-ink); font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.16em; text-transform:uppercase; padding:7px 12px; }
.barber h3 { font-size:clamp(1.4rem,2.4vw,1.9rem); }
.barber p { color:var(--muted); font-size:0.92rem; margin:10px 0 14px; }
.barber-skills { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:16px; }
.barber-skills span { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.1em; text-transform:uppercase; border:1px solid var(--line-2); padding:5px 10px; color:var(--muted); }
.barber .btn { align-self:flex-start; margin-top:auto; }

/* ============================================================
   RETURNING CLIENT — "book your usual"
   ============================================================ */
.usual {
  display:none; align-items:center; gap:16px; flex-wrap:wrap;
  border:1px solid var(--accent); padding:16px 20px; margin-top:26px;
  background:rgba(0,224,107,0.06);
}
.usual.show { display:flex; }
.usual .u-txt { flex:1; min-width:200px; }
.usual .u-lbl { display:block; font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.2em; text-transform:uppercase; color:var(--accent); margin-bottom:5px; }
.usual .u-name { font-family:var(--font-display); font-weight:700; text-transform:uppercase; font-size:1.4rem; line-height:1; }
.usual .u-dismiss { background:none; border:none; color:var(--faint); font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.14em; text-transform:uppercase; cursor:pointer; }
.usual .u-dismiss:hover { color:var(--fg); }

/* ============================================================
   WHATSAPP + review CTA
   ============================================================ */
.wa-btn { background:#25D366; color:#06301A; border-color:#25D366; }
.wa-btn::after { background:var(--fg); }
.wa-btn:hover { color:var(--bg); }
.review-cta { display:flex; align-items:center; justify-content:center; gap:18px; flex-wrap:wrap; margin-top:38px; padding-top:30px; border-top:1px solid var(--line); }
.review-cta p { font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.1em; text-transform:uppercase; color:var(--muted); }

/* form states */
.form-msg.sending { display:block; color:var(--muted); }

@media (max-width:1040px){
  .gallery { grid-template-columns:repeat(3,1fr); }
  .crew { grid-template-columns:repeat(2,1fr); }
}
@media (max-width:760px){
  .gallery { grid-template-columns:repeat(2,1fr); }
  .gal-item.tall { grid-row:span 1; aspect-ratio:3/4; }
  .crew { grid-template-columns:1fr; }
  .ba { aspect-ratio:1; }
  .lb-prev { left:6px; } .lb-next { right:6px; }
  .lb-btn { width:40px; height:40px; }
}

@media (prefers-reduced-motion: reduce){
  .gal-item img, .barber-shot img, .lightbox, .gal-item { transition:none; }
}

/* ============================================================
   THE FRONT DESK — chat assistant
   ============================================================ */
.desk-launch {
  position:fixed; right:var(--gutter); bottom:var(--gutter); z-index:70;
  display:inline-flex; align-items:center; gap:11px; padding:14px 20px;
  background:var(--green); color:var(--green-ink); border:none; cursor:pointer;
  font-family:var(--font-mono); font-weight:600; font-size:0.7rem;
  letter-spacing:0.18em; text-transform:uppercase;
  box-shadow:0 18px 40px -16px rgba(0,0,0,0.85);
  transition:transform 0.4s var(--snap), background 0.3s, opacity 0.3s var(--ease), visibility 0.3s;
}
.desk-launch:hover { transform:translateY(-3px); }
.desk-launch svg { width:17px; height:17px; }
.desk-launch .dl-dot { width:7px; height:7px; border-radius:50%; background:var(--green-ink); opacity:0.45; }
.desk-launch.is-open { opacity:0; visibility:hidden; transform:scale(0.9); }

.desk {
  position:fixed; right:var(--gutter); bottom:var(--gutter); z-index:71;
  width:min(390px, calc(100vw - var(--gutter) * 2));
  height:min(580px, calc(100vh - var(--gutter) * 2 - 20px));
  display:flex; flex-direction:column;
  background:var(--noir-2); border:1px solid var(--line-2);
  box-shadow:0 40px 90px -30px rgba(0,0,0,0.9);
  opacity:0; visibility:hidden; transform:translateY(18px) scale(0.98);
  transform-origin:100% 100%;
  transition:opacity 0.4s var(--ease), transform 0.45s var(--snap), visibility 0.4s;
}
.desk.open { opacity:1; visibility:visible; transform:none; }

.desk-head { display:flex; align-items:center; gap:12px; padding:16px 18px; border-bottom:1px solid var(--line); flex-shrink:0; }
.desk-head .dh-mark { width:34px; height:34px; flex-shrink:0; display:flex; align-items:center; justify-content:center; background:var(--green); color:var(--green-ink); }
.desk-head .dh-mark svg { width:17px; height:17px; }
.desk-head .dh-txt { flex:1; min-width:0; }
.desk-head b { display:block; font-family:var(--font-display); font-weight:800; text-transform:uppercase; font-size:1.15rem; line-height:1; color:#F2EFE6; }
.desk-head .dh-state { display:flex; align-items:center; gap:6px; font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.14em; text-transform:uppercase; color:var(--muted); margin-top:4px; }
.desk-head .dh-state i { width:6px; height:6px; border-radius:50%; background:var(--green); font-style:normal; }
.desk-head .dh-state.shut i { background:var(--red); }
.desk-close { background:none; border:1px solid var(--line-2); color:var(--muted); width:32px; height:32px; flex-shrink:0; cursor:pointer; display:flex; align-items:center; justify-content:center; transition:0.3s; }
.desk-close:hover { color:#F2EFE6; border-color:#F2EFE6; }
.desk-close svg { width:13px; height:13px; }

.desk-log { flex:1; overflow-y:auto; overscroll-behavior:contain; padding:20px 18px; display:flex; flex-direction:column; gap:14px; scrollbar-width:thin; }
.desk-log::-webkit-scrollbar { width:5px; }
.desk-log::-webkit-scrollbar-thumb { background:var(--line-2); }

.msg { max-width:88%; font-size:0.9rem; line-height:1.55; animation:msg-in 0.45s var(--snap); }
@keyframes msg-in { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:none; } }
.msg .who { display:block; font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.18em; text-transform:uppercase; color:var(--faint); margin-bottom:6px; }
.msg .bubble { padding:12px 15px; background:var(--noir-3); border:1px solid var(--line); color:#E8E5DA; }
.msg .bubble a { color:var(--green); border-bottom:1px solid currentColor; }
.msg .bubble strong { color:#F2EFE6; font-weight:600; }
.msg.me { align-self:flex-end; text-align:right; }
.msg.me .bubble { background:var(--green); border-color:var(--green); color:var(--green-ink); text-align:left; }
.msg.me .who { color:var(--muted); }

.desk-typing { display:inline-flex; gap:5px; padding:14px 15px; background:var(--noir-3); border:1px solid var(--line); }
.desk-typing i { width:6px; height:6px; border-radius:50%; background:var(--muted); animation:blip 1.15s ease-in-out infinite; }
.desk-typing i:nth-child(2) { animation-delay:0.16s; }
.desk-typing i:nth-child(3) { animation-delay:0.32s; }
@keyframes blip { 0%,60%,100% { opacity:0.28; transform:translateY(0); } 30% { opacity:1; transform:translateY(-3px); } }

.desk-chips { display:flex; flex-wrap:wrap; gap:7px; padding:0 18px 14px; flex-shrink:0; }
.desk-chip {
  font-family:var(--font-mono); font-size:0.69rem; letter-spacing:0.1em; text-transform:uppercase;
  padding:8px 12px; background:transparent; border:1px solid var(--line-2); color:var(--muted);
  cursor:pointer; transition:color 0.25s, border-color 0.25s, background 0.25s;
}
.desk-chip:hover { color:var(--green-ink); background:var(--green); border-color:var(--green); }

.desk-form { display:flex; gap:0; border-top:1px solid var(--line); flex-shrink:0; }
.desk-form input {
  flex:1; min-width:0; background:transparent; border:none; color:#F2EFE6;
  padding:16px 18px; font-family:var(--font-body); font-size:0.9rem;
}
.desk-form input::placeholder { color:var(--faint); }
.desk-form input:focus { outline:none; background:rgba(242,239,230,0.03); }
.desk-send { background:var(--green); color:var(--green-ink); border:none; width:56px; flex-shrink:0; cursor:pointer; display:flex; align-items:center; justify-content:center; transition:background 0.3s; }
.desk-send:hover { background:#F2EFE6; }
.desk-send svg { width:17px; height:17px; }

/* lift clear of the mobile booking bar */
@media (max-width:940px){
  .desk-launch { bottom:calc(84px + env(safe-area-inset-bottom)); }
  .desk { bottom:calc(84px + env(safe-area-inset-bottom)); height:min(70vh, calc(100vh - 190px)); }
}
@media (max-width:560px){
  .desk-launch { padding:13px 16px; font-size:0.69rem; }
  .desk { right:12px; left:12px; width:auto; }
}

/* ============================================================
   GUARD RAIL — the taper, made legible

   The guard numbers were doing nothing but decorating section
   headings: a visitor read "Guard 3" and had no way to know it
   was a position on a scale. This is that scale, drawn. Fixed to
   the left edge, it lights the guard you are currently inside, so
   the numbering finally behaves like the thing it borrows from.

   It sits outside .zone-bone, so it cannot inherit the band flip —
   script.js toggles .on-bone and these two lines do the inverting.
   ============================================================ */
.guard-rail {
  --gr-dim:rgba(242,239,230,0.34);
  --gr-lit:var(--green);
  --gr-veil:rgba(10,11,10,0.86);
  position:fixed; left:clamp(14px,1.8vw,30px); top:50%; transform:translateY(-50%);
  z-index:40; display:none; flex-direction:column; gap:3px;
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity 0.5s var(--ease), visibility 0.5s;
}
.guard-rail.on-bone {
  --gr-dim:rgba(10,11,10,0.42); --gr-lit:var(--green-deep);
  --gr-veil:rgba(237,231,217,0.88);
}

/* the names only appear on hover, and they cross into the column when they do —
   the masthead runs the full bleed, so they need something to sit on */
.guard-rail::before {
  content:""; position:absolute; inset:-16px -18px; z-index:-1;
  background:var(--gr-veil); opacity:0;
  transition:opacity 0.3s var(--ease);
}
.guard-rail:hover::before { opacity:1; }
.guard-rail.on { opacity:1; visibility:visible; pointer-events:auto; }

/* desktop only — below this there is no gutter to live in */
@media (min-width:1180px){ .guard-rail { display:flex; } }

.gr-item {
  display:flex; align-items:center; gap:11px; height:27px;
  font-family:var(--font-mono); font-weight:600; font-size:0.69rem;
  letter-spacing:0.1em; color:var(--gr-dim);
  font-variant-numeric:tabular-nums;
  transition:color 0.35s var(--ease);
}
.gr-item:hover, .gr-item:focus-visible { color:var(--gr-lit); }

.gr-tick {
  display:block; width:13px; height:1px; background:currentColor;
  transition:width 0.4s var(--snap);
}
.gr-n { width:1ch; }

/* Collapsed to zero width, not just zero opacity. Left in the flow it made the
   rail a 110px-wide invisible column down the left of the page, and the anchors
   in it swallowed clicks meant for the masthead behind. */
.gr-l {
  font-weight:500; font-size:0.69rem; letter-spacing:0.16em; text-transform:uppercase;
  white-space:nowrap; max-width:0; overflow:hidden; opacity:0;
  transition:max-width 0.35s var(--ease), opacity 0.3s var(--ease);
}
.guard-rail:hover .gr-l { max-width:170px; opacity:0.7; }

.gr-item.is-on { color:var(--gr-lit); }
.gr-item.is-on .gr-tick { width:31px; }
.guard-rail:hover .gr-item.is-on .gr-l { opacity:1; }

/* ============================================================
   MOTION SYSTEM — word-level reveals, driven by the fade
   ============================================================ */
/* Display type is set at line-height 0.8–0.88, so the glyph ink sits OUTSIDE
   the content box. Clipping at the box edge sliced the bottom off large
   headings (the footer wordmark most visibly). Pad the clip box out, pull it
   back with negative margin so layout is unchanged, and push the hidden start
   position further down so nothing peeks into the new padding. */
.anim-line {
  display:block; overflow:hidden;
  padding-top:0.16em; margin-top:-0.16em;
  padding-bottom:0.24em; margin-bottom:-0.24em;
}
.anim-word { display:inline-block; will-change:transform; transform:translateY(145%) rotate(2deg); transform-origin:0 100%; }
.in .anim-word, .anim-run .anim-word {
  transform:none;
  transition:transform 0.95s var(--snap);
  transition-delay:calc(var(--i, 0) * 42ms);
}

/* line-draw rules that grow as they enter */
.rule-draw { transform:scaleX(0); transform-origin:0 50%; transition:transform 1.1s var(--snap); }
.in .rule-draw, .anim-run .rule-draw { transform:scaleX(1); }

/* board rows deal in one at a time */
.board-row { opacity:0; transform:translateX(-14px); transition:opacity 0.7s var(--ease), transform 0.7s var(--snap), padding-left 0.45s var(--snap), color 0.35s var(--ease); }
.board.in .board-row { opacity:1; transform:none; transition-delay:calc(var(--i, 0) * 70ms); }
.board.in .board-row:hover { transition-delay:0s; }

/* hero image wipes open on load */
.hero-img-clip { clip-path:inset(0 0 100% 0); animation:wipe-open 1.15s var(--snap) 0.5s forwards; }
@keyframes wipe-open { to { clip-path:inset(0 0 0 0); } }

/* Magnetic buttons (desktop) — offsets set by script.
   Every state keeps --my in the transform. Hard-coding the pressed Y made the
   button jump UP whenever the cursor sat low in it; a press must always travel
   down, by the same amount, from wherever the magnet has pulled it. */
.btn { transform:translate(var(--mx, 0px), var(--my, 0px)); }
.btn:hover { transform:translate(var(--mx, 0px), calc(var(--my, 0px) - 2px)); }
.btn:active { transform:translate(var(--mx, 0px), calc(var(--my, 0px) + 3px)); }

/* marquee reacts to scroll velocity */
.marquee-track { transform:skewX(var(--skew, 0deg)); transition:transform 0.5s var(--ease); }

@media (prefers-reduced-motion: reduce){
  .anim-word { transform:none !important; }
  .rule-draw { transform:scaleX(1) !important; }
  .board-row { opacity:1 !important; transform:none !important; }
  .hero-img-clip { animation:none; clip-path:none; }
  .marquee-track { transform:none !important; }
  .msg { animation:none; }
  .desk, .desk-launch { transition-duration:0.01ms; }
  .desk-typing i { animation:none; }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width:1040px){
  .footer-grid { grid-template-columns:1fr 1fr; }
  .steps, .reviews { grid-template-columns:1fr 1fr; }
  .follow-row { grid-template-columns:1fr; }
}
@media (max-width:940px){
  .nav-links, .nav-cta { display:none; }
  /* The trigger is a disc, and it stays one when it turns into the close
     button — same slot, same shape, so the X reads as the same control
     rather than something new appearing over the menu. */
  .burger {
    display:flex; align-items:center; justify-content:center;
    width:46px; height:46px; padding:0; border-radius:50%;
    border:1px solid rgba(242,239,230,0.2);
    background:rgba(22,24,22,0.5);
    -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
    transition:background 0.3s var(--ease), border-color 0.3s var(--ease);
  }
  .burger span { width:20px; }
  /* over the cream hero and the cream header the disc has to invert too,
     but only until it opens — after that the noir overlay is what is behind it */
  .home-hero .site-header:not(.scrolled) .burger,
  .site-header.scrolled.on-bone .burger {
    border-color:rgba(10,11,10,0.22); background:rgba(255,255,255,0.34);
  }
  .home-hero .site-header:not(.scrolled) .burger.open,
  .site-header.scrolled.on-bone .burger.open,
  .burger.open { border-color:rgba(242,239,230,0.3); background:rgba(242,239,230,0.07); }
  .book-bar { display:flex; }
  body { padding-bottom:80px; }
  .hero-body, .split, .info-grid, .contact-grid, .extras-grid { grid-template-columns:1fr; }
  .split.reverse .split-media { order:0; }
  .steps, .reviews { grid-template-columns:1fr; }
  .hero-visual { aspect-ratio:16/11; max-width:560px; }
  .hang-sign { width:120px; }
  .hang-status { font-size:1.4rem; }
  .quiz-options { grid-template-columns:1fr; }
}
@media (max-width:640px){
  body { font-size:16px; }
  :root { --nav-h:70px; }
  .brand img { height:38px; }
  .brand-text b { font-size:1.2rem; }
  .brand-text span { font-size:0.69rem; letter-spacing:0.24em; }

  /* Bottom only. This used to set all three sides, and because it sits far
     below the max-width:940px block at equal specificity its 24px top won —
     re-opening a band of bare page above the hero photo on every phone, the
     exact gap the 940 rule had zeroed so the photo could start at the top. */
  .hero { padding-bottom:44px; }
  .masthead { padding:22px 0 26px; }
  .mast-outline { -webkit-text-stroke-width:1px; }
  .hero-copy .lead { margin:16px 0 26px; }
  .hero-cta { gap:10px; }
  .hero-cta .btn { width:100%; }
  .hero-visual { aspect-ratio:4/3; }
  .hang-sign { width:96px; right:8px; }
  .hang-plate { margin-top:20px; padding:11px 9px 10px; }
  .hang-scissors { width:17px; height:17px; }
  .hang-status { font-size:1.15rem; }
  .hang-sub { font-size:0.69rem; }
  .hero-badge { padding:11px 15px; }
  .hero-badge b { font-size:1.6rem; }

  .stats { grid-template-columns:1fr; }
  .stat + .stat { border-left:none; padding-left:0; }
  .stat b { font-size:3.6rem; }

  /* price board: price drops to its own line, right-aligned */
  .board-row:hover { padding-left:10px; }
  /* the tag shares the last row with the price rather than adding a fourth
     line to every service — grid-column on both keeps them on one baseline */
  .board-row { grid-template-columns:auto 1fr; row-gap:12px; }
  .b-price { grid-column:1; text-align:left; }
  .b-price .b-mins { display:block; text-align:left; margin-top:6px; }
  .b-book { grid-column:2; justify-self:end; padding:10px 14px; }
  .b-price small { display:inline; margin:0 8px 0 0; }

  .section-head h2 { max-width:none; }
  .faq-q { padding:22px 0; gap:16px; }
  .quiz-card { padding:26px 20px; }
  .quiz-cta { flex-direction:column; }
  .quiz-cta .btn { width:100%; }
  .follow-btn { padding:20px; }
  .footer-grid { grid-template-columns:1fr; gap:30px; }
  .footer-bottom { flex-direction:column; align-items:flex-start; gap:10px; }
  .cta-band .btn { width:100%; }
}

/* tap targets */
@media (pointer:coarse){
  .btn, .burger, .faq-q, .quiz-opt, .follow-btn, .socials a, .book-bar .btn { min-height:44px; }
  .nav-links a, .footer-col a, .mobile-menu a { padding-top:6px; padding-bottom:6px; }
}

/* ============================================================
   REDUCED MOTION — everything arrives, nothing travels
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  .mast-line > span, .hero-copy, .hero-visual { animation:none !important; opacity:1 !important; transform:none !important; }
  .marquee-track, .hang-sign, .status-bar .sb-dot, .preloader .bar span { animation:none !important; }
  .preloader .bar span { transform:scaleX(1); }
  .reveal { opacity:1; transform:none; transition:none; }
  .board-row, .btn, .quiz-opt, .step, .follow-btn, .faq-q, .socials a, .footer-col a { transition-duration:0.01ms; }
  .split-media img, .hero-img-clip img { transition:none; }
  .guard-rail, .gr-item, .gr-tick, .gr-l { transition-duration:0.01ms !important; }
  .gr-l { opacity:0.7; transform:none; }
}

/* ============================================================
   SECONDARY CONTROLS — same plate model as .btn, at 2px scale.
   Shadow-only so the centred lightbox arrows keep their transform.
   ============================================================ */
.gal-filter, .quiz-opt, .desk-chip, .lb-btn, .desk-launch, .desk-send, .desk-close, .quiz-back {
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.07), 0 2px 0 rgba(0,0,0,0.26);
  transition:color 0.25s var(--ease), background 0.25s var(--ease),
             border-color 0.25s var(--ease), box-shadow 0.14s var(--snap), transform 0.14s var(--snap);
}
.gal-filter:active, .quiz-opt:active, .desk-chip:active,
.lb-btn:active, .desk-send:active, .desk-close:active, .quiz-back:active {
  box-shadow:inset 0 2px 4px rgba(0,0,0,0.34), 0 0 0 rgba(0,0,0,0.26);
}
.zone-bone .gal-filter, .zone-bone .quiz-opt { box-shadow:inset 0 1px 0 rgba(255,255,255,0.5), 0 2px 0 rgba(10,11,10,0.16); }
.zone-bone .gal-filter:active, .zone-bone .quiz-opt:active { box-shadow:inset 0 2px 4px rgba(10,11,10,0.22); }

/* the chat launcher is a real key: lit top, hard bottom edge, travels on press */
.desk-launch {
  background-image:linear-gradient(180deg, rgba(255,255,255,0.20), rgba(0,0,0,0.12) 55%, rgba(0,0,0,0.20));
  border-radius:3px;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.42), inset 0 -1px 0 rgba(0,0,0,0.28),
    0 3px 0 rgba(0,0,0,0.45), 0 14px 26px -10px rgba(0,0,0,0.75);
}
.desk-launch:active {
  transform:translateY(3px);
  box-shadow:inset 0 2px 5px rgba(0,0,0,0.4), 0 0 0 rgba(0,0,0,0.45);
}
.desk-send {
  background-image:linear-gradient(180deg, rgba(255,255,255,0.20), rgba(0,0,0,0.14));
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.38), inset 1px 0 0 rgba(0,0,0,0.2);
}
.desk-send:active { box-shadow:inset 0 2px 5px rgba(0,0,0,0.4); }
.gal-filter:focus-visible, .quiz-opt:focus-visible, .desk-chip:focus-visible,
.lb-btn:focus-visible, .desk-launch:focus-visible, .desk-send:focus-visible {
  outline:2px solid var(--gold); outline-offset:2px;
}

@media (prefers-reduced-motion: reduce){
  .gal-filter, .quiz-opt, .desk-chip, .lb-btn, .desk-launch, .desk-send { transition-duration:0.01ms; }
}

/* ============================================================
   SCISSOR CURSOR — desktop only
   ============================================================ */
@media (hover:hover) and (pointer:fine){
  body, .wrap, section, div, p, span, h1, h2, h3, h4, img, footer, header {
    cursor:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%2732%27%20height%3D%2732%27%20viewBox%3D%270%200%2032%2032%27%3E%3Cg%20fill%3D%27none%27%20stroke%3D%27%230A0B0A%27%20stroke-width%3D%275%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20opacity%3D%27.85%27%3E%3Ccircle%20cx%3D%277%27%20cy%3D%277%27%20r%3D%273.2%27%2F%3E%3Ccircle%20cx%3D%277%27%20cy%3D%2719%27%20r%3D%273.2%27%2F%3E%3Cpath%20d%3D%27M9.6%205%20L27%2022%20M9.6%2021%20L27%204%20M14%2013%20L20%2013%27%2F%3E%3C%2Fg%3E%3Cg%20fill%3D%27%230A0B0A%27%20stroke%3D%27%23D8C572%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%277%27%20cy%3D%277%27%20r%3D%273.2%27%2F%3E%3Ccircle%20cx%3D%277%27%20cy%3D%2719%27%20r%3D%273.2%27%2F%3E%3Cpath%20d%3D%27M9.6%205%20L27%2022%20M9.6%2021%20L27%204%20M14%2013%20L20%2013%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") 7 7, auto;
  }
  a, button, .btn, .quiz-opt, .faq-q, .follow-btn, .socials a, .nav-links a, label, .burger, .board-row, [role="button"] {
    cursor:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%2732%27%20height%3D%2732%27%20viewBox%3D%270%200%2032%2032%27%3E%3Cg%20fill%3D%27none%27%20stroke%3D%27%230A0B0A%27%20stroke-width%3D%275%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20opacity%3D%27.85%27%3E%3Ccircle%20cx%3D%278%27%20cy%3D%278%27%20r%3D%273.2%27%2F%3E%3Ccircle%20cx%3D%278%27%20cy%3D%2718%27%20r%3D%273.2%27%2F%3E%3Cpath%20d%3D%27M10.4%206.4%20L27%2017%20M10.4%2019.6%20L27%209%20M14%2013%20L19%2013%27%2F%3E%3C%2Fg%3E%3Cg%20fill%3D%27%230A0B0A%27%20stroke%3D%27%230FC96F%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%278%27%20cy%3D%278%27%20r%3D%273.2%27%2F%3E%3Ccircle%20cx%3D%278%27%20cy%3D%2718%27%20r%3D%273.2%27%2F%3E%3Cpath%20d%3D%27M10.4%206.4%20L27%2017%20M10.4%2019.6%20L27%209%20M14%2013%20L19%2013%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") 8 8, pointer;
  }
  input, textarea { cursor:text; }
  body.snipping, body.snipping * {
    cursor:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%2732%27%20height%3D%2732%27%20viewBox%3D%270%200%2032%2032%27%3E%3Cg%20fill%3D%27none%27%20stroke%3D%27%230A0B0A%27%20stroke-width%3D%275%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%20opacity%3D%27.85%27%3E%3Ccircle%20cx%3D%279%27%20cy%3D%279%27%20r%3D%273.2%27%2F%3E%3Ccircle%20cx%3D%279%27%20cy%3D%2715%27%20r%3D%273.2%27%2F%3E%3Cpath%20d%3D%27M11.4%2010.2%20L28%2012%20M11.4%2013.8%20L28%2012%20M13%2012%20L19%2012%27%2F%3E%3C%2Fg%3E%3Cg%20fill%3D%27%230A0B0A%27%20stroke%3D%27%230FC96F%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%279%27%20cy%3D%279%27%20r%3D%273.2%27%2F%3E%3Ccircle%20cx%3D%279%27%20cy%3D%2715%27%20r%3D%273.2%27%2F%3E%3Cpath%20d%3D%27M11.4%2010.2%20L28%2012%20M11.4%2013.8%20L28%2012%20M13%2012%20L19%2012%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") 9 12, auto !important;
  }
}

/* ============================================================
   BOOKSY WIDGET
   The widget script appends its own trigger to <body>. The real buttons
   are the ones already on the page, so that trigger is taken out of the
   layout but left in the DOM and focusable-free — script.js clicks it
   programmatically, which works regardless of pointer-events.
   ============================================================ */
.booksy-widget-button {
  position:absolute !important; width:1px; height:1px;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%);
  pointer-events:none; opacity:0;
}

/* The widget positions its dialog absolutely, near the top of the DOCUMENT,
   and relies on scroll messages to keep it with you. Opened from halfway down
   a long page — which is where most Book buttons are — it lands above the
   viewport and looks like nothing happened. Pinning it to the viewport makes
   it a real modal, and letting it scroll internally handles the fact that the
   booking flow grows to a couple of thousand pixels tall. */
html body .booksy-widget-dialog {
  position:fixed !important;
  top:50% !important; left:50% !important; right:auto !important; bottom:auto !important;
  transform:translate(-50%,-50%) !important;
  width:min(770px, calc(100vw - 24px)) !important;
  max-height:min(900px, calc(100dvh - 32px));
  overflow-y:auto; overscroll-behavior:contain;
  border-radius:14px;
  box-shadow:0 40px 90px -30px rgba(0,0,0,0.6);
}
html body .booksy-widget-dialog iframe { width:100% !important; display:block; border:0; }
