/* ═══════════════════════════════════════════════════════════════════════════
   ALIGN HAIR STUDIO — shared design system
   ---------------------------------------------------------------------------
   Palette sampled directly from the studio's logo: a metallic gold that runs
   bronze -> gold -> champagne, platinum for the wordmark, on near-black. Gold
   is never a flat fill here for the same reason it is not flat in the logo —
   a single #D4AF37 reads as mustard. It is always a gradient with a highlight.

   No build step (house convention): this file is shared by every page and the
   header/footer markup is duplicated per page.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  /* ground */
  --black:    #050505;
  --black-2:  #0A0A09;
  --black-3:  #121110;
  --black-4:  #1A1815;
  --hair:     #241F18;   /* hairline rules */
  --hair-2:   #352D20;

  /* metal */
  --bronze:   #584028;
  --gold-d:   #8A6A22;
  --gold:     #C9A227;
  --gold-l:   #F3DFA6;
  --champ:    #FFF6E0;
  --platinum: #E8E8E8;

  --gold-grad: linear-gradient(135deg,#8A6A22 0%,#C9A227 22%,#F3DFA6 48%,#FFF6E0 58%,#C9A227 78%,#7A5A2A 100%);
  --silver-grad: linear-gradient(160deg,#FFFFFF 0%,#E8E8E8 32%,#A9A9A9 58%,#F2F2F2 82%,#C4C4C4 100%);

  /* type */
  --ink:      #EDE8DF;
  --ink-2:    #B7AF9F;
  --mute:     #8B8375;

  --display: 'Cinzel', 'Trajan Pro', ui-serif, Georgia, serif;
  --sans:    'Jost', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --wrap: 1200px;
  --nav-h: 84px;
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  background:var(--black);color:var(--ink);
  font-family:var(--sans);font-size:16.5px;line-height:1.7;font-weight:300;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
::selection{background:var(--gold);color:#000}
:focus-visible{outline:2px solid var(--gold);outline-offset:3px}

.wrap{max-width:var(--wrap);margin:0 auto;padding:0 28px}
.narrow{max-width:820px}

/* ── metallic type ─────────────────────────────────────────────────────── */
.gold{
  background:var(--gold-grad);-webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:var(--gold);
}
.silver{
  background:var(--silver-grad);-webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:var(--platinum);
}

h1,h2,h3,h4{font-family:var(--display);font-weight:400;line-height:1.08;letter-spacing:.01em}
h1{font-size:clamp(2.6rem,6vw,5rem);text-transform:uppercase;letter-spacing:.04em}
h2{font-size:clamp(2rem,4vw,3.2rem);text-transform:uppercase;letter-spacing:.06em}
h3{font-size:1.5rem;text-transform:uppercase;letter-spacing:.06em}

/* the wide-tracked caps line from the logo ("CUT • SHAVE • TRIM • STYLE • COLOR") */
.eyebrow{
  font-family:var(--sans);font-size:.7rem;font-weight:400;
  letter-spacing:.42em;text-transform:uppercase;color:var(--gold);
  display:block;margin-bottom:18px;
}
.eyebrow.dim{color:var(--mute)}
.lede{color:var(--ink-2);font-size:1.08rem;font-weight:300;max-width:62ch}
.small{font-size:.9rem;color:var(--mute)}

/* gold hairline with a diamond, echoing the logo's dividers */
.divider{display:flex;align-items:center;gap:14px;margin:26px 0}
.divider::before,.divider::after{content:"";height:1px;flex:1;background:linear-gradient(90deg,transparent,var(--gold-d),transparent)}
.divider i{width:5px;height:5px;background:var(--gold);transform:rotate(45deg);flex:none}
.divider.left::before{display:none}
/* the centred rule under a page-head title (was an inline style on two pages;
   it has to be a class so the mobile pass can tighten it) */
.pdiv{max-width:340px;margin:26px auto}

/* ── buttons ───────────────────────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--sans);font-size:.78rem;font-weight:500;
  letter-spacing:.22em;text-transform:uppercase;
  padding:16px 34px;border:0;cursor:pointer;position:relative;
  transition:transform .2s cubic-bezier(.2,.8,.3,1),box-shadow .25s,color .2s,background .25s;
  white-space:nowrap;
}
.btn-gold{background:var(--gold-grad);color:#120E05;font-weight:600;box-shadow:0 4px 22px rgba(201,162,39,.18)}
.btn-gold:hover{transform:translateY(-2px);box-shadow:0 8px 30px rgba(201,162,39,.34)}
.btn-ghost{color:var(--ink);border:1px solid var(--hair-2);background:transparent}
.btn-ghost:hover{border-color:var(--gold);color:var(--champ);background:rgba(201,162,39,.06)}
.btn-sm{padding:12px 22px;font-size:.7rem;letter-spacing:.18em}
.btn:disabled{opacity:.35;cursor:not-allowed;transform:none;box-shadow:none}

/* ── header ────────────────────────────────────────────────────────────── */
header{
  position:sticky;top:0;z-index:200;
  background:rgba(5,5,5,.82);backdrop-filter:blur(16px) saturate(140%);
  border-bottom:1px solid var(--hair);
}
nav{display:flex;align-items:center;justify-content:space-between;height:var(--nav-h);gap:26px}
.brand{display:flex;align-items:center;gap:13px;flex:none}
/* The mark is the shears-and-triangle from their capes and window decal, not a badge:
   no disc, no ring, no shadow. It is taller than it is wide, so height drives the size
   and width follows — a square box would letterbox it and shrink the shears. */
.brand img{width:auto;height:50px;border-radius:0;box-shadow:none}
.brand .bt{line-height:1}
.brand .bn{font-family:var(--display);font-size:1.18rem;letter-spacing:.16em;text-transform:uppercase;display:block}
.brand .bs{font-family:var(--sans);font-size:.54rem;letter-spacing:.36em;text-transform:uppercase;color:var(--gold);margin-top:5px;display:block}
.navlinks{display:flex;gap:36px;align-items:center}
.navlinks a{
  font-size:.72rem;letter-spacing:.2em;text-transform:uppercase;color:var(--ink-2);
  position:relative;padding:6px 0;transition:color .2s;
}
.navlinks a:hover,.navlinks a[aria-current="page"]{color:var(--champ)}
.navlinks a::after{
  content:"";position:absolute;left:0;bottom:0;height:1px;width:0;
  background:var(--gold-grad);transition:width .28s cubic-bezier(.2,.8,.3,1);
}
.navlinks a:hover::after,.navlinks a[aria-current="page"]::after{width:100%}
.navtoggle{display:none;background:none;border:1px solid var(--hair-2);color:var(--ink);
  width:44px;height:44px;cursor:pointer;font-size:1.1rem;align-items:center;justify-content:center}
@media(max-width:1000px){
  .navlinks{
    position:absolute;inset:100% 0 auto 0;background:var(--black-2);
    flex-direction:column;gap:0;padding:12px 0 26px;border-bottom:1px solid var(--hair);
    transform:translateY(-120%);visibility:hidden;pointer-events:none;
    transition:transform .34s cubic-bezier(.2,.8,.3,1);
    max-height:calc(100dvh - var(--nav-h) - env(safe-area-inset-top));overflow-y:auto;overscroll-behavior:contain;
  }
  .navlinks.open{transform:translateY(0);visibility:visible;pointer-events:auto}
  .navlinks a{padding:16px 28px;width:100%;font-size:.8rem}
  .navlinks a::after{display:none}
  .navtoggle{display:inline-flex}
  header .btn{display:none}
}

/* ── sections ──────────────────────────────────────────────────────────── */
section{padding:clamp(72px,10vw,130px) 0;position:relative}
.sec-head{margin-bottom:56px;max-width:70ch}
.sec-head.split{display:flex;justify-content:space-between;align-items:flex-end;gap:40px;max-width:none;flex-wrap:wrap}
.alt{background:var(--black-2)}

/* marble veining, echoing the logo's stone. Pure CSS so there is no asset to
   ship, no request to make, and nothing to go stale. */
.veined{position:relative;overflow:hidden}
.veined::before{
  content:"";position:absolute;inset:0;pointer-events:none;opacity:.5;
  background:
    radial-gradient(ellipse 60% 40% at 88% 12%, rgba(201,162,39,.10), transparent 60%),
    radial-gradient(ellipse 50% 60% at 4% 88%, rgba(201,162,39,.07), transparent 62%);
}

/* ── hero ──────────────────────────────────────────────────────────────── */
.hero{
  min-height:calc(100svh - var(--nav-h));display:grid;place-items:center;
  text-align:center;padding:clamp(50px,8vw,90px) 0;position:relative;overflow:hidden;
}
.hero::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(ellipse 70% 55% at 50% 42%, rgba(201,162,39,.13), transparent 68%),
    radial-gradient(ellipse 40% 30% at 12% 88%, rgba(201,162,39,.06), transparent 70%);
}
.hero .wrap{position:relative;z-index:1}
/* Their real shears-and-triangle mark, from the capes and the window decal — not a
   badge, so no disc and no ring. Deliberately the MARK and not the full lockup: the
   lockup carries "CUT · SHAVE · TRIM · STYLE · COLOR" and "ALIGN HAIR STUDIO", both of
   which sit directly beneath it as live text, and printing each twice read as a
   mistake. The glow stays — it ties the mark to the gold wash behind the hero.
   aria-hidden for the same reason: the h1 already says the name. */
.hero-mark{
  width:clamp(96px,13vw,152px);height:auto;margin:0 auto 30px;
  filter:drop-shadow(0 0 42px rgba(201,162,39,.22));
  animation:markIn 1.1s cubic-bezier(.2,.8,.3,1) both;
}
@keyframes markIn{from{opacity:0;transform:translateY(22px) scale(.94)}to{opacity:1;transform:none}}
.hero h1{margin-bottom:8px}
.hero .tagline{
  font-family:var(--display);font-size:clamp(.95rem,1.7vw,1.25rem);
  letter-spacing:.5em;text-transform:uppercase;color:var(--gold);margin:22px 0 0;
}
.hero .lede{margin:28px auto 0;text-align:center}
.hero-cta{display:flex;gap:16px;justify-content:center;flex-wrap:wrap;margin-top:40px}
.scrollcue{
  position:absolute;bottom:28px;left:50%;transform:translateX(-50%);
  font-size:.6rem;letter-spacing:.3em;text-transform:uppercase;color:var(--mute);
  display:flex;flex-direction:column;align-items:center;gap:10px;
}
.scrollcue::after{content:"";width:1px;height:38px;background:linear-gradient(180deg,var(--gold-d),transparent);animation:cue 2.2s ease-in-out infinite}
@keyframes cue{0%,100%{opacity:.3;transform:scaleY(.6);transform-origin:top}50%{opacity:1;transform:scaleY(1)}}
@media(max-width:700px){.scrollcue{display:none}}

/* the logo's service line, reused as a marquee strip */
.strip{
  border-top:1px solid var(--hair);border-bottom:1px solid var(--hair);
  background:var(--black-2);padding:20px 0;overflow:hidden;
}
.strip .row{display:flex;gap:0;justify-content:center;flex-wrap:wrap;
  font-size:.7rem;letter-spacing:.4em;text-transform:uppercase;color:var(--ink-2)}
.strip .row span{padding:0 26px;position:relative}
.strip .row span+span::before{content:"";position:absolute;left:0;top:50%;width:4px;height:4px;
  background:var(--gold);transform:translateY(-50%) rotate(45deg)}

/* ── cards ─────────────────────────────────────────────────────────────── */
.grid{display:grid;gap:26px}
.g2{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}
.g3{grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr))}
.card{
  background:var(--black-3);border:1px solid var(--hair);padding:34px 30px;
  position:relative;transition:border-color .28s,transform .28s,background .28s;
}
.card:hover{border-color:var(--hair-2);transform:translateY(-3px)}
.card .num{font-family:var(--display);font-size:.9rem;letter-spacing:.2em;color:var(--gold-d);display:block;margin-bottom:14px}

/* ── barber cards ──────────────────────────────────────────────────────── */
.barber{
  background:var(--black-3);border:1px solid var(--hair);
  display:flex;flex-direction:column;transition:border-color .3s,transform .3s;
}
.barber:hover{border-color:var(--gold-d);transform:translateY(-4px)}
/* 4:5 is right for a real headshot. Until the studio supplies photos the same box
   is 60% empty space with a monogram floating in it, so the no-photo state gets its
   own shorter ratio — set by JS via .no-photo — rather than eight tall voids. */
.barber .photo{
  aspect-ratio:4/3;background:linear-gradient(165deg,var(--black-4),var(--black-2));
  display:grid;place-items:center;position:relative;overflow:hidden;border-bottom:1px solid var(--hair);
  /* ONE definition of the disc, used by the image, the ring and the glow so they can
     never disagree. Sized off WIDTH (a definite length here) — a percentage HEIGHT on
     a centered grid item has no definite basis to resolve against, which is exactly
     what broke: `height:86%` produced a 311px image inside a 272px-tall box, so the
     photo overflowed and was clipped while the ring sat correctly at 86% (232px).
     Two different circles, visibly offset. */
  --disc:min(70%,208px);
}
/* The disc. clip-path crops INSIDE the image rather than border-radius + scale():
   scaling up to hide the source's faint white ring pushed the circle past the box
   and overflow:hidden sliced the bottom off every face. circle(47%) removes the
   ring and stays inside the frame. The ring/glow moves to a sibling ::after, since
   a box-shadow on a clipped element is clipped away with it. */
.barber .photo img{
  width:var(--disc);height:auto;aspect-ratio:1;object-fit:cover;
  clip-path:circle(50% at 50% 50%);
  position:relative;z-index:1;              /* above the glow, below the ring */
}
/* GLOW — behind the photo (z-index 0). It used to live on the same element as the
   ring at z-index 2, which meant a 40px gold haze painted over the face; the photos
   looked like they were sitting UNDER the gold circle rather than inside it. */
.barber .photo::before{
  content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:var(--disc);aspect-ratio:1;border-radius:50%;pointer-events:none;z-index:0;
  box-shadow:0 0 44px 6px rgba(201,162,39,.16);
}
.barber .photo.no-photo::before{display:none}
.barber .photo.no-photo{aspect-ratio:4/3}
.barber .photo .mono{
  font-family:var(--display);font-size:clamp(2.4rem,5vw,3.4rem);letter-spacing:.14em;
  position:relative;z-index:1;
}
/* a thin gold ring makes the monogram read as a deliberate mark, not a missing image */
.barber .photo.no-photo .mono::after{
  content:"";position:absolute;left:50%;top:50%;width:2.9em;height:2.9em;
  transform:translate(-50%,-50%);border:1px solid rgba(201,162,39,.28);border-radius:50%;
}
/* RING — a hairline in FRONT of the photo, with no blur so it cannot wash the face.
   (This element previously held a gold radial tint across the whole photo area,
   which was the second thing greying the faces out.) */
.barber .photo::after{
  content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:var(--disc);aspect-ratio:1;border-radius:50%;pointer-events:none;z-index:2;
  border:1px solid rgba(201,162,39,.42);
}
/* the monogram fallback keeps a soft backdrop — there is no face to protect there */
.barber .photo.no-photo{background:
  radial-gradient(ellipse 60% 55% at 50% 42%, rgba(201,162,39,.10), transparent 70%),
  linear-gradient(165deg,var(--black-4),var(--black-2))}
.barber .body{padding:26px 26px 28px;display:flex;flex-direction:column;gap:11px;flex:1}
.barber h3{font-size:1.45rem;margin:0}
/* The barber profile page uses an h1 for the name (it is that page's real
   heading). The global h1 is a clamp() up to 5rem for hero use, so it is reset
   here to sit in the card at the same size the h3 did. */
.barber .barber-name{font-size:1.9rem;margin:0;text-transform:uppercase;letter-spacing:.04em}
.barber .role{font-size:.64rem;letter-spacing:.28em;text-transform:uppercase;color:var(--gold)}
.barber .bio{font-size:.93rem;color:var(--ink-2);flex:1}
.barber .meta{font-size:.8rem;color:var(--mute);padding-top:14px;border-top:1px solid var(--hair)}
.barber .meta b{color:var(--ink);font-weight:400}
/* the category list was a bare text node after a <br>; it is a span now (so the
   phone layout can drop it) and has to keep its own line here */
.barber .meta .cats{display:block}
.barber .acts{display:flex;gap:14px;align-items:center;margin-top:6px}

/* ── service menu ──────────────────────────────────────────────────────── */
.menu-cat{margin-bottom:52px}
.menu-cat h3{color:var(--gold);font-size:.76rem;letter-spacing:.34em;margin-bottom:22px;
  font-family:var(--sans);font-weight:400}
/* wrap explicitly: a two-word service name ("Cut & Beard") was wrapping the NAME
   and pushing the description inline beside the price instead of onto its own row */
.menu-row{display:flex;flex-wrap:wrap;gap:6px 18px;align-items:baseline;padding:18px 0;border-bottom:1px solid var(--hair)}
.menu-row .nm{flex:0 1 auto;min-width:0}
.menu-row .nm{font-family:var(--display);font-size:1.28rem;letter-spacing:.03em;text-transform:uppercase}
.menu-row .fill{flex:1;border-bottom:1px dotted var(--hair-2);transform:translateY(-5px);min-width:20px}
.menu-row .pr{font-family:var(--display);font-size:1.2rem;color:var(--gold-l);white-space:nowrap;text-align:right}
.menu-row .by{display:block;font-family:var(--sans);font-size:.72rem;letter-spacing:.1em;color:var(--mute);text-transform:uppercase;margin-top:3px}
.menu-row .desc{flex-basis:100%;font-size:.88rem;color:var(--mute);margin-top:-4px}

/* ── footer ────────────────────────────────────────────────────────────── */
footer{background:var(--black-2);border-top:1px solid var(--hair);padding:70px 0 34px;font-size:.9rem;color:var(--ink-2)}
/* five columns: Hours and Follow used to share one cell, which on a 2-up phone
   layout left a 157px hole beside them. */
.foot-grid{display:grid;grid-template-columns:1.6fr 1fr 1.1fr 1fr .8fr;gap:44px}
@media(max-width:900px){.foot-grid{grid-template-columns:1fr 1fr;gap:34px}}
footer h4{font-size:.68rem;letter-spacing:.3em;color:var(--gold);margin-bottom:18px;font-family:var(--sans);font-weight:400}
footer a:hover{color:var(--champ)}
footer ul{list-style:none;display:flex;flex-direction:column;gap:10px}
.foot-bottom{margin-top:52px;padding-top:24px;border-top:1px solid var(--hair);
  display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;font-size:.76rem;color:var(--mute)}

/* ── hours ─────────────────────────────────────────────────────────────── */
.hours-row{display:flex;justify-content:space-between;gap:16px;padding:13px 0;border-bottom:1px solid var(--hair);font-size:.94rem}
.hours-row .d{color:var(--mute);letter-spacing:.05em}
.hours-row.today{color:var(--champ)}
.hours-row.today .d{color:var(--gold)}

/* ── reveal on scroll ──────────────────────────────────────────────────── */
.reveal{opacity:0;transform:translateY(24px);transition:opacity .8s cubic-bezier(.2,.8,.3,1),transform .8s cubic-bezier(.2,.8,.3,1)}
.reveal.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){
  .reveal{opacity:1;transform:none;transition:none}
  .hero-mark{animation:none}
  .scrollcue::after{animation:none}
  html{scroll-behavior:auto}
}

/* ── page header (inner pages) ─────────────────────────────────────────── */
.pagehead{padding:clamp(64px,9vw,120px) 0 clamp(40px,5vw,64px);text-align:center;position:relative;overflow:hidden}
.pagehead::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(ellipse 60% 70% at 50% 0%, rgba(201,162,39,.10), transparent 70%)}
.pagehead .wrap{position:relative;z-index:1}
.crumb{font-size:.66rem;letter-spacing:.24em;text-transform:uppercase;color:var(--mute);margin-bottom:20px}
.crumb a:hover{color:var(--gold)}

/* ── review proof ─────────────────────────────────────────────────────────
   Deliberately visible content only, never schema aggregateRating: Google's
   structured-data policy forbids a business marking up its own aggregate
   rating pulled from a third party, and doing it risks a manual action. The
   stars still do their job where it counts — on the page. */
.rating{display:flex;align-items:center;justify-content:center;gap:12px;margin-top:26px;
  font-size:.86rem;color:var(--ink-2);flex-wrap:wrap}
.rating .stars{color:var(--gold);letter-spacing:.18em;font-size:.95rem}
.rating b{color:var(--champ);font-weight:500}

/* ── work photo ───────────────────────────────────────────────────────── */
.workgrid{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center}
@media(max-width:860px){.workgrid{grid-template-columns:1fr;gap:34px}}
.workshot{position:relative;border:1px solid var(--hair);overflow:hidden}
.workshot img{width:100%;height:auto;display:block;filter:saturate(.9) contrast(1.03)}
.workshot::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(5,5,5,.18),transparent 40%,rgba(5,5,5,.28));
}

/* ═══════════════════════════════════════════════════════════════════════════
   POLISH PASS
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── grain ────────────────────────────────────────────────────────────────
   Flat #050505 across a whole page reads as "unfinished dark theme". A very
   low-opacity noise layer gives the black a surface, the way the logo's stone
   has one. Inline SVG turbulence: no asset, no request, ~200 bytes. */
body::after{
  content:"";position:fixed;inset:0;z-index:9999;pointer-events:none;opacity:.035;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode:overlay;
}

/* ── the wordmark catches the light once, on load ─────────────────────────── */
.hero h1 .gold, .hero h1 .silver{background-size:220% 100%;animation:sheen 2.4s cubic-bezier(.3,.7,.3,1) .35s both}
@keyframes sheen{from{background-position:120% 0}to{background-position:0 0}}

/* ── social proof band ────────────────────────────────────────────────────── */
.proof{border-bottom:1px solid var(--hair);background:var(--black)}
.proofrow{display:grid;grid-template-columns:repeat(4,1fr);gap:2px;text-align:center}
.proofrow > div{padding:34px 14px;position:relative}
.proofrow > div + div::before{content:"";position:absolute;left:0;top:26%;height:48%;width:1px;
  background:linear-gradient(180deg,transparent,var(--hair-2),transparent)}
.proofrow b{display:block;font-family:var(--display);font-size:clamp(1.7rem,3vw,2.5rem);line-height:1}
.proofrow span{display:block;margin-top:9px;font-size:.63rem;letter-spacing:.22em;
  text-transform:uppercase;color:var(--mute)}
@media(max-width:760px){.proofrow{grid-template-columns:1fr 1fr}
  .proofrow > div:nth-child(3)::before{display:none}}

/* ── the service finder ───────────────────────────────────────────────────── */
.svcfilter{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:48px;justify-content:center}
.fchip{background:transparent;border:1px solid var(--hair-2);color:var(--ink-2);
  padding:11px 20px;font-family:var(--sans);font-size:.68rem;letter-spacing:.2em;
  text-transform:uppercase;cursor:pointer;transition:all .2s}
.fchip:hover{border-color:var(--gold-d);color:var(--champ)}
.fchip.on{background:var(--gold-grad);border-color:transparent;color:#120E05;font-weight:600}

.svccat{font-family:var(--sans);font-size:.68rem;letter-spacing:.34em;text-transform:uppercase;
  color:var(--gold);font-weight:400;margin:0 0 22px;display:flex;align-items:center;gap:16px}
.svccat::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,var(--hair-2),transparent)}
.svcblock{margin-bottom:56px}
.svcblock[hidden]{display:none}

.svcitem{border:1px solid var(--hair);background:var(--black-3);padding:28px 28px 24px;margin-bottom:16px;
  transition:border-color .26s}
.svcitem:hover{border-color:var(--hair-2)}
.svchead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;flex-wrap:wrap}
.svcitem h3{font-size:1.6rem;margin:0}
.svcfrom{font-size:.74rem;letter-spacing:.16em;text-transform:uppercase;color:var(--mute);white-space:nowrap}
.svcfrom b{font-family:var(--display);font-size:1.15rem;color:var(--gold-l);letter-spacing:0}
.svcdesc{color:var(--ink-2);font-size:.95rem;margin-top:10px;max-width:64ch}
.svcwho{font-size:.63rem;letter-spacing:.22em;text-transform:uppercase;color:var(--mute);
  margin:20px 0 12px}

/* one row per barber who does it — their face, their price, a direct booking link */
.offers{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:10px}
.offer{display:flex;align-items:center;gap:13px;padding:11px 15px;
  border:1px solid var(--hair-2);background:var(--black-2);transition:all .2s}
.offer:hover{border-color:var(--gold);background:var(--black-4);transform:translateY(-2px)}
.offer .oav{width:38px;height:38px;border-radius:50%;overflow:hidden;flex:none;
  background:linear-gradient(150deg,var(--black-4),var(--black-2));
  display:grid;place-items:center;font-family:var(--display);font-size:.85rem;
  box-shadow:0 0 0 1px var(--hair-2)}
.offer .oav img{width:100%;height:100%;object-fit:cover;transform:scale(1.06)}
.offer .oinfo{flex:1;min-width:0;line-height:1.25}
.offer .onm{display:block;font-size:.94rem}
.offer .odur{display:block;font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
.offer .opr{font-family:var(--display);font-size:1.12rem;color:var(--gold-l);flex:none}

/* ── skeletons ────────────────────────────────────────────────────────────
   "Loading the team…" is a status message; a skeleton is the shape of the thing
   arriving. On a slow phone the difference is most of the perceived speed. */
.skel{border:1px solid var(--hair);background:var(--black-3)}
.skel .sk{background:linear-gradient(90deg,var(--black-4) 25%,#221F1A 37%,var(--black-4) 63%);
  background-size:400% 100%;animation:shimmer 1.5s ease-in-out infinite}
.skel .sk-photo{aspect-ratio:4/3}
.skel .sk-body{padding:26px}
.skel .sk-line{height:12px;margin-bottom:11px}
.skel .sk-line.w60{width:60%}.skel .sk-line.w40{width:40%}.skel .sk-line.w85{width:85%}
@keyframes shimmer{from{background-position:100% 0}to{background-position:-100% 0}}
@media(prefers-reduced-motion:reduce){.skel .sk{animation:none}.hero h1 .gold,.hero h1 .silver{animation:none}}

/* Mobile booking dock. Safari owns its browser chrome; the site only paints
   its own safe area, never an oversized block beyond the viewport. */
.mobile-book-bar{display:none}
@media(max-width:1000px){
  .mobile-book-bar{
    display:block;position:fixed;inset:auto 0 0;z-index:300;
    padding:10px max(20px,env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) max(20px,env(safe-area-inset-left));
    background:var(--black);border-top:1px solid var(--hair-2);
    visibility:hidden;opacity:0;pointer-events:none;
    transform:translateY(100%);
    transition:transform .2s ease,opacity .2s ease;
  }
  .mobile-book-bar.is-up{visibility:visible;opacity:1;pointer-events:auto;transform:none}
  .mbook{
    display:flex;align-items:center;justify-content:center;min-height:48px;
    padding:12px 16px;border-radius:4px;background:var(--gold-grad);color:#120E05;
    text-align:center;font-size:.78rem;font-weight:600;letter-spacing:.22em;text-transform:uppercase;
  }
  /* The video belongs in the corner until the booking dock needs that space.
     Inherited properties also reach the video widget's shadow root. */
  body{--arcbay-bubble-bottom-mobile:calc(14px + env(safe-area-inset-bottom))}
  body:not([data-page="book"]):has(.mobile-book-bar.is-up){
    --arcbay-bubble-bottom-mobile:calc(83px + env(safe-area-inset-bottom));
  }
  body{padding-bottom:calc(88px + env(safe-area-inset-bottom))}
  body[data-page="book"] .mobile-book-bar{display:none}
  body[data-page="book"]{padding-bottom:0}
}
@media(prefers-reduced-motion:reduce){
  .mobile-book-bar{transition:none}
}

/* ── photo warms on hover ─────────────────────────────────────────────────── */
/* no desaturation at rest: it was compensating for the gold overlay that is now gone */
.barber .photo img{transition:transform .6s cubic-bezier(.2,.8,.3,1)}
.barber:hover .photo img{transform:scale(1.04)}

/* ── cross-page transitions where supported (progressive, no JS) ──────────── */
@media(prefers-reduced-motion:no-preference){
  @view-transition{navigation:auto}
}

/* ═══════════════════════════════════════════════════════════════════════════
   PHOTOGRAPHY
   The site launched with a single image on the whole home page, so it read as a
   dark template rather than as this shop. These two blocks carry the pictures.
   ═══════════════════════════════════════════════════════════════════════════ */

/* --- split hero -----------------------------------------------------------
   The image sits in a PANEL rather than behind the text. Behind the text it had
   to cover ~1440px from a ~400px source and went soft exactly where the page
   makes its first impression; in a panel it is downscaled and stays sharp.
   Text left, photo right on desktop; photo first on a phone, where a picture of
   the shop is the fastest way to say what this is.                         */
.hero{text-align:left}                     /* was centred for the old stacked hero */
.hero-split{
  display:grid;grid-template-columns:1.05fr .95fr;
  gap:clamp(32px,5vw,72px);align-items:center;width:100%;
}
.hero-copy{max-width:34rem;text-align:left}
/* Everything in here was built for a centred stacked hero, so each piece
   auto-centres itself. Undo that explicitly rather than relying on inheritance. */
.hero-copy .hero-mark{margin-left:0}
.hero-copy .lede{margin-left:0;text-align:left}
.hero-copy .tagline,
.hero-copy .eyebrow{text-align:left}
.hero-copy .hero-cta{justify-content:flex-start}
.hero-copy .rating{justify-content:flex-start}
/* the wordmark broke to three lines beside a photo; it has half the width now */
.hero-copy h1{font-size:clamp(2.2rem,3.6vw,3.6rem)}

/* Text first, photo second — the name and the reason to book should be read
   before the picture, and the picture is the thing you look at while deciding. */
.hero-shot{order:2}

.hero-shot{
  margin:0;position:relative;border-radius:2px;overflow:hidden;
  box-shadow:0 30px 90px rgba(0,0,0,.75),0 0 0 1px var(--hair-2);
}
.hero-shot img{
  display:block;width:100%;height:auto;
  aspect-ratio:4/5;object-fit:cover;object-position:50% 32%;
  filter:saturate(.92) contrast(1.05);
}
/* a gold edge-light so the photo belongs to the palette instead of sitting on it */
.hero-shot::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(200deg,rgba(201,162,39,.16),transparent 42%),
    linear-gradient(0deg,rgba(5,5,5,.55),transparent 55%);
}

@media (max-width:900px){
  .hero-split{grid-template-columns:1fr;gap:30px}
  /* photo first: on a phone a picture of the room says what this is faster than
     any heading can, and it earns the scroll for everything below it */
  .hero-shot{order:-1;max-width:none}
  .hero-shot img{aspect-ratio:16/11}       /* a band, not a tower, above the fold */
  .hero-copy{max-width:none}
  /* Stays LEFT-aligned, not centred. Centred body copy is harder to read at
     phone measure, and a ragged-left column under a full-width photo is the
     stronger composition. (An earlier version centred these and the unconditional
     desktop rule silently overrode it — the CSS claimed one thing and did another.) */
  .hero-copy .eyebrow{letter-spacing:.3em}  /* .42em wrapped "COLOR" onto its own line */
}

/* --- the work marquee -----------------------------------------------------
   A continuously moving strip, after itsdote.com's .marquee (src/styles/global.css).

   This began as a static 8-column grid, then as a carousel that advanced a tile
   at a time and showed progress dots. Both were wrong for what this is. The grid
   moved not at all on a wide screen — every tile fitted, so there was nothing to
   scroll and the dots hid themselves — and dots are meaningless for a strip that
   is supposed to drift past on its own: nobody wants to jump to photo 6 of 8, they
   want to watch the work go by. It also has to keep working as photographs are
   added, which a fixed 8-column grid does not.

   ONE row, sliding left forever. The photographs are listed twice inside it and
   the animation stops at -50%: the frame where the second copy sits exactly where
   the first began, so it wraps with no gap and no jump. Duration is set from the
   tile count in home.js, so adding photos makes the strip longer, not faster.  */
.workrail{
  margin-top:clamp(46px,6vw,88px);
  display:flex;gap:2px;overflow:hidden;user-select:none;
  border-top:1px solid var(--hair);border-bottom:1px solid var(--hair);
  background:var(--hair);
  /* the strip fades out at both edges instead of being chopped, so it reads as
     something passing through rather than a row that has been cut off */
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.workrow{
  display:flex;gap:2px;flex:0 0 auto;
  animation:workslide var(--marq-dur,48s) linear infinite;
  will-change:transform;
}
/* -1px trims the half-gap that -50% of an even-numbered row leaves over */
@keyframes workslide{to{transform:translateX(calc(-50% - 1px))}}
/* Pause so a photo can actually be tapped — a target sliding out from under the
   thumb is not a target. Hover for a mouse, :active + a JS class for touch. */
.workrail:hover .workrow,
.workrail.paused .workrow,
.workrail:focus-within .workrow{animation-play-state:paused}

.workrail figure{
  margin:0;position:relative;overflow:hidden;background:var(--black-3);
  flex:0 0 auto;width:clamp(150px,20vw,230px);cursor:pointer;
}
.workrail img{
  display:block;width:100%;height:100%;object-fit:cover;aspect-ratio:9/16;
  filter:saturate(.88) contrast(1.04);transition:filter .4s ease;
}
/* a hint of the brand gold over the photos so the strip belongs to this page */
.workrail figure::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,transparent 55%,rgba(8,8,9,.55) 100%),
             radial-gradient(ellipse 80% 60% at 50% 100%, rgba(201,162,39,.10), transparent 70%);
}
.workrail figure:hover img{filter:saturate(1) contrast(1.04)}
.workrail figure:focus-visible{outline:2px solid var(--gold);outline-offset:-4px}

@media (prefers-reduced-motion:reduce){
  /* Someone who asked for less motion gets a strip they scroll themselves,
     rather than a frozen crop of the first three photographs. */
  .workrow{animation:none}
  .workrail{overflow-x:auto;scroll-snap-type:x mandatory}
  .workrail figure{scroll-snap-align:center}
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE PASS
   Measured at 390x844 / DPR 3 / touch. Most of this traffic is a phone inside
   Instagram's in-app browser, so these are not edge cases — they are the norm.
   Findings this fixes, with the numbers they were measured at:
     · hero was 1066px = 126% of the viewport, so screen one held only branding
     · the logo appeared TWICE above the fold (nav mark + 132px hero mark)
     · 15 tap targets under Apple's 44px minimum, incl. the barber name links (32px)
     · content text at 10.1px ("5 barbers · pick who you want")
     · 5 barber cards = 2554px = 3 screens
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width:760px){

  /* ── hero: copy first, photo as a band under it ───────────────────────────
     The photo led, at 4:5 and full width. With the 85px nav that consumed the
     whole viewport and pushed the wordmark AND the book button off screen one.
     Whatever a picture of the room is worth, it is not worth spending the only
     screen everyone sees. */
  .hero{min-height:0;padding:26px 0 40px}
  .hero-split{grid-template-columns:1fr;gap:26px}
  .hero-shot{order:2;max-width:none;margin-top:4px}
  .hero-shot img{aspect-ratio:3/2;object-position:50% 34%}

  /* The nav bar already shows the logo AND the name, 60px above this. A second
     132px copy of the same mark is the single biggest waste of the fold. */
  .hero-copy .hero-mark{display:none}
  .hero-copy h1{font-size:clamp(2.1rem,10.5vw,3rem)}
  .hero-copy .lede{margin-top:16px;font-size:1rem}
  .hero-copy .hero-cta{margin-top:20px}
  .hero .scrollcue{display:none}          /* nothing to cue: the fold now ends mid-content */

  /* ── tap targets: 44px minimum ────────────────────────────────────────────
     A 32px-tall barber name is the one link that matters most on this site and
     was the easiest to mis-tap. Padding rather than font-size, so nothing about
     the type changes. */
  .barber h3 a,
  .navlinks a,
  footer a{display:inline-block;min-height:44px;line-height:44px}
  .crumb{font-size:.72rem}
  .crumb a{display:inline-block;min-height:36px;line-height:36px;padding-right:4px}
  .fchip{min-height:44px;padding-top:0;padding-bottom:0}
  .btn-sm{padding:14px 22px}              /* the card Book/Menu buttons were 43px */

  /* ── text that was too small to read ──────────────────────────────────────
     These are content, not decoration: "5 barbers · pick who you want" is the
     line that tells someone they get to choose. 10.1px is not a size, it is a
     rounding error. */
  .svcwho{font-size:.78rem;letter-spacing:.14em}
  .proofrow span{font-size:.72rem;letter-spacing:.14em}
  .proofrow > div{padding:26px 12px}
  footer .small,.copy{font-size:.82rem}

  /* Barber cards stay STACKED on mobile.
     They were briefly rebuilt as horizontal cards (photo left, details right) to
     get five barbers from three screens down to under two. It backfired twice:
     grid items default to min-width:auto, so the 1fr column would not shrink and
     the whole page grew to 469px wide on a 390px viewport; and once that was
     fixed with minmax(0,1fr) the 120px photo column left the portrait too small
     to recognise a face, with the Book button colliding with it. A taller page is
     a smaller problem than an unrecognisable barber and a sideways scroll.
     Only the bio is dropped — nobody has written one, so it rendered as an empty
     gap that pushed the price and the Book button further down. */
  .barber .bio{display:none}

}

/* Second mobile pass — what the first one missed, from re-measuring.        */
@media (max-width:760px){
  /* 36px was still under the 44px minimum. */
  .crumb a{min-height:44px;line-height:44px}

  /* The phone number was a 110x24 target — on the Visit page, for a shop whose
     Instagram bio literally says "Or call (619)884-1247", that is the single most
     likely tap on the site. */
  a[href^="tel:"],a[href^="mailto:"]{
    display:inline-block;min-height:44px;line-height:44px;
  }

  /* Remaining sub-14px CONTENT. The .eyebrow is left at 11.2px on purpose: it is
     a letterspaced graphic rule lifted from the logo, not something anyone reads
     as a sentence, and enlarging it wraps it onto two lines. Everything below is
     an actual sentence someone is expected to read. */
  .barber .meta{font-size:.86rem}                 /* "4 services · from $50" */
  .svcwho{font-size:.84rem}
  .booknote,.bookform .small,.slotnote{font-size:.88rem}
  footer .small{font-size:.88rem}
  .copy,footer .copy{font-size:.82rem}
}

@media (max-width:760px){
  /* The two remaining sub-14px lines that are genuinely read, by their real
     selectors (my first guesses at the class names did not match anything). */
  .proofrow span{font-size:.82rem}   /* "Booked online, no deposit" was 11.5px */
  .note{font-size:.88rem}            /* book.html's "No deposit is taken online…" */
}

/* ═══════════════════════════════════════════════════════════════════════════
   CAROUSELS + LIGHTBOX
   ═══════════════════════════════════════════════════════════════════════════ */

/* the marquee itself lives in the PHOTOGRAPHY section above; the progress dots
   that used to sit here are gone — see the note on .workrail for why a drifting
   strip has nothing for a dot to point at. */

/* ── lightbox ───────────────────────────────────────────────────────────── */
.lbx{
  position:fixed;inset:0;z-index:400;display:none;
  background:rgba(4,4,5,.94);
  align-items:center;justify-content:center;
  padding:max(16px,env(safe-area-inset-top)) 16px max(16px,env(safe-area-inset-bottom));
}
.lbx[open],.lbx.on{display:flex}
.lbx img{
  max-width:min(100%,900px);max-height:100%;width:auto;height:auto;
  box-shadow:0 40px 120px rgba(0,0,0,.9);
  border:1px solid var(--hair-2);
}
.lbx .lbxbtn{
  position:absolute;background:rgba(10,10,9,.72);border:1px solid var(--hair-2);
  color:var(--ink);width:52px;height:52px;font-size:1.4rem;line-height:1;cursor:pointer;
  display:grid;place-items:center;border-radius:50%;backdrop-filter:blur(6px);
}
.lbx .lbxbtn:hover{border-color:var(--gold);color:var(--champ)}
.lbx .lbxclose{top:max(14px,env(safe-area-inset-top));right:14px}
.lbx .lbxprev{left:10px;top:50%;transform:translateY(-50%)}
.lbx .lbxnext{right:10px;top:50%;transform:translateY(-50%)}
.lbx .lbxcount{
  position:absolute;bottom:max(16px,env(safe-area-inset-bottom));left:0;right:0;text-align:center;
  font-size:.72rem;letter-spacing:.24em;text-transform:uppercase;color:var(--mute);
}
body.lbx-open{overflow:hidden}

/* ── the team preview as a swipeable carousel on a phone ─────────────────── */
@media (max-width:760px){
  /* Five stacked cards were three full screens. A rail keeps ALL FIVE — nobody
     gets cut for being fifth, which is the whole point — inside one screen. */
  #teamPreview.grid{
    display:grid;grid-auto-flow:column;grid-auto-columns:80vw;gap:14px;
    overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;
    /* bleed to the screen edges so the next card peeks and reads as swipeable */
    margin-inline:calc(-1 * var(--gut,28px));
    padding-inline:var(--gut,28px);
    scrollbar-width:none;
  }
  #teamPreview.grid::-webkit-scrollbar{display:none}
  #teamPreview .barber{scroll-snap-align:center}
  #teamPreview .barber .photo{--disc:min(58%,150px)}
}

@media(max-width:1000px){
  /* the cloned Book entry at the foot of the open menu — see initNav() */
  .navlinks .navbook{
    margin:10px 28px 4px;padding:16px;text-align:center;width:auto;
    background-image:linear-gradient(180deg,var(--gold-l) 0%,var(--gold) 42%,var(--gold-d) 100%);
    color:#120E05;font-weight:600;letter-spacing:.22em;text-transform:uppercase;font-size:.78rem;
    min-height:0;line-height:1.2;
  }
  .navlinks .navbook::after{display:none}
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE HEADER — reworked after itsdote.com's (src/components/Nav.astro)
   ---------------------------------------------------------------------------
   What was wrong with the old one:
     · the toggle was the text character ☰ swapped for ✕ by JS. A glyph that
       teleports gives no sense that one control became the other, and a bordered
       44px square around a text character reads as a form field.
     · the header was rgba(5,5,5,.82) + backdrop-filter. Dote hit this on iOS and
       documented it: at that alpha the page reads THROUGH the bar, so content
       appears to sit inside it. Opaque here.
     · --nav-h is 84px, which is a desktop measurement. On a 714px iOS viewport
       that is 12% of the screen spent on a logo, before anything is said.
     · the open panel's links were floating text with no separators, so five
       destinations read as one block of words.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width:1000px){
  :root{--nav-h:64px}
  /* opaque: see above. The blur was buying nothing over a near-black page. */
  header{position:fixed;inset:0 0 auto;background:var(--black);backdrop-filter:none;z-index:400;padding-top:env(safe-area-inset-top)}
  body{padding-top:calc(var(--nav-h) + env(safe-area-inset-top))}
  .brand img{width:42px;height:42px}
  .brand .bn{font-size:1.05rem}
  .brand .bs{font-size:.5rem;margin-top:4px}

  /* ── the burger, drawn ─────────────────────────────────────────────────
     Three rules from one element plus its two pseudo-elements: one box to
     centre, and the lines cannot drift apart. 19px of glyph inside a 44px
     target — the target belongs to the finger, the glyph to the eye, and they
     are not the same measurement. */
  .navtoggle{
    display:inline-flex;align-items:center;justify-content:center;position:relative;
    width:44px;height:44px;padding:0;background:none;border:0;border-radius:10px;
    color:var(--ink-2);cursor:pointer;-webkit-tap-highlight-color:transparent;
  }
  .navtoggle:hover,.navtoggle[aria-expanded="true"]{color:var(--champ)}
  .burger,.burger::before,.burger::after{
    content:"";position:absolute;left:50%;width:19px;height:1.6px;margin-left:-9.5px;
    border-radius:2px;background:currentColor;
    transition:transform .28s cubic-bezier(.2,.8,.3,1),top .28s cubic-bezier(.2,.8,.3,1),background .2s;
  }
  .burger{top:50%;margin-top:-.8px}
  .burger::before{left:0;margin-left:0;top:-6px}
  .burger::after{left:0;margin-left:0;top:6px}
  /* open: the middle line goes, the outer two cross. The button that opened it
     is the button that closes it, and it has to look like it. */
  .navtoggle[aria-expanded="true"] .burger{background:transparent}
  .navtoggle[aria-expanded="true"] .burger::before{top:0;transform:rotate(45deg)}
  .navtoggle[aria-expanded="true"] .burger::after{top:0;transform:rotate(-45deg)}

  /* ── the panel: a list, below the bar ──────────────────────────────────
     Five destinations separated by hairlines at 48px each, not a wall of
     floating words. Deliberately not a full-screen overlay: five links behind a
     modal is something you have to get out of. */
  .navlinks{
    inset:100% 0 auto 0;background:var(--black-2);
    padding:0 0 10px;box-shadow:0 26px 40px rgba(0,0,0,.6);
  }
  .navlinks a{
    display:flex;align-items:center;min-height:48px;line-height:1.2;
    padding:0 24px;width:100%;font-size:.82rem;letter-spacing:.18em;
    border-top:1px solid var(--hair);color:var(--ink);
  }
  .navlinks a:first-child{border-top:0}
  .navlinks a[aria-current="page"]{color:var(--gold-l)}
  /* the cloned Book row — a control among destinations, so it looks like one */
  .navlinks .navbook{
    border-top:1px solid var(--hair-2);margin:8px 24px 2px;padding:15px;
    justify-content:center;width:auto;min-height:0;letter-spacing:.22em;
  }
}
@media (prefers-reduced-motion:reduce){
  .burger,.burger::before,.burger::after{transition:none}
}

@media (max-width:1000px){
  /* 42px — two short of the minimum, and it is the link back to the home page. */
  .brand{min-height:44px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE ROSTER ON A PHONE — 2-up, composed like /book's step 1
   ---------------------------------------------------------------------------
   Measured before: five stacked cards = 2685px, and the page 5.7 screens. Almost
   all of that was frame, not content. Each card carried a FULL-WIDTH 4:3 photo
   band (332x249) whose actual content is a 208px CIRCLE — 124px of empty gutter
   either side of every face, five times over, plus a "Menu & hours" button
   duplicating the link the photo and the name already are.

   /book already solved this: a round avatar centred over the name, two per row,
   so four people are on screen at once and choosing is a comparison instead of a
   scroll. Same composition here, at a larger avatar because THIS page is about
   the faces. The frame becomes the circle rather than a box around it.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width:560px){
  #teamGrid.grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  /* minmax(0,…) not 1fr: grid items default to min-width:auto, which is what
     previously pushed this page 79px wider than the phone. */
  #teamGrid .barber{
    position:relative;padding:18px 10px 14px;align-items:center;text-align:center;
  }
  #teamGrid .barber:hover{transform:none}      /* no hover on a touch screen */

  /* the photo frame IS the disc now — no band, no bottom rule, no 4:3 void */
  #teamGrid .barber .photo,
  #teamGrid .barber .photo.no-photo{
    width:96px;aspect-ratio:1;border-radius:50%;border-bottom:0;
    margin:0 auto 12px;--disc:100%;
    /* the whole card is the link (see the ::after below), so this anchor must not
       also take the tap — two overlapping links on the same destination is how you
       get a card that sometimes navigates and sometimes doesn't. */
    pointer-events:none;
  }
  /* a 44px-blur glow inside a 96px circle that clips it is just a smudge */
  #teamGrid .barber .photo::before{display:none}
  #teamGrid .barber .photo .mono{font-size:1.85rem}

  #teamGrid .barber .body{padding:0;gap:4px;align-items:center;width:100%;flex:1}
  #teamGrid .barber h3{font-size:1.06rem;line-height:1.15}
  /* the 44px tap target moves from the name to the entire card, so the name goes
     back to being type rather than a 44px-tall band of empty line-height */
  #teamGrid .barber h3 a{min-height:0;line-height:1.15;display:inline}
  #teamGrid .barber .role{font-size:.56rem;letter-spacing:.16em}
  /* 12.5px was under the readable floor for a line someone is meant to read.
     At .84rem it wraps to two lines in 140px — 21px a card, which is the right
     place to spend the 1833px this layout gave back. */
  #teamGrid .barber .meta{width:100%;font-size:.84rem;padding-top:9px;margin-top:2px;line-height:1.4}
  /* "Cuts · Beard · Extensions" wraps to three lines in 141px and buries the
     price. It is on the barber's own page, one tap away, in full. */
  #teamGrid .barber .meta .cats{display:none}

  #teamGrid .barber .acts{width:100%;margin-top:11px;gap:8px}
  /* the ghost button was a third link to the profile the card already opens */
  #teamGrid .barber .acts .btn-ghost{display:none}
  #teamGrid .barber .acts .btn-gold{
    flex:1;padding:13px 8px;font-size:.68rem;letter-spacing:.16em;
    position:relative;z-index:2;               /* above the card-wide link */
  }

  /* Tap the card → that barber's menu and hours. Tap the gold button → straight
     into booking them. Standard card behaviour, and it buys back the 49px the
     second button cost per card. */
  #teamGrid .barber h3 a::after{content:"";position:absolute;inset:0;z-index:1}

  /* An odd roster leaves the last barber alone beside an empty 162px cell — the
     exact hole this whole layout was meant to close. The orphan spans the row and
     recomposes sideways instead. (A horizontal card failed on this page before, at
     full width with a 120px rectangular photo column that made the face
     unrecognisable. It works here because the avatar is a circle at its own fixed
     size and the text simply sits beside it.) */
  #teamGrid .barber:last-child:nth-child(odd){
    grid-column:1/-1;flex-direction:row;align-items:center;text-align:left;
    padding:14px;gap:16px;
  }
  /* the avatar stays 96px here too: the monogram's gold ring is 2.9em of the mono
     font, which at 84px is wider than the frame and gets clipped away — Aaron
     turned into a dark blob in exactly the card that has no photograph. */
  #teamGrid .barber:last-child:nth-child(odd) .photo{margin:0;flex:none}
  #teamGrid .barber:last-child:nth-child(odd) .body{align-items:flex-start;min-width:0}
  #teamGrid .barber:last-child:nth-child(odd) .meta{border-top:0;padding-top:0;margin-top:0}
  #teamGrid .barber:last-child:nth-child(odd) .acts{margin-top:9px;width:auto}
  #teamGrid .barber:last-child:nth-child(odd) .acts .btn-gold{flex:none;padding:13px 34px}
}

/* ── page heads: 424px before the first barber ───────────────────────────────
   clamp(64px,9vw,120px) bottoms out at 64px on a phone, which is a lot of black
   above a crumb, an eyebrow, an h1, a rule and a lede — half the viewport spent
   on a title. */
@media (max-width:760px){
  .pagehead{padding:30px 0 24px}
  .pagehead h1{font-size:clamp(2rem,10.5vw,2.9rem)}
  .pagehead .pdiv{margin:14px auto;max-width:190px}
  .pagehead .lede{font-size:1rem}
}

/* ── section rhythm on a phone ───────────────────────────────────────────────
   clamp(72px,10vw,130px) bottoms out at 72px, so every section boundary is 72+72
   of black and the last card sits 142px above the footer's first word (70px of
   its own padding on top of that). Vertical air that reads as generous on a
   1440px canvas reads as an empty screen on a 390px one — you scroll past
   nothing to get to the next thing. */
@media (max-width:760px){
  section{padding:44px 0}
  footer{padding:46px 0 28px}
}

/* ── the footer on a phone ───────────────────────────────────────────────────
   1030px — 1.2 screens, on every one of the six pages. It is a four-column
   desktop footer stacked into one column, where every link is a 44px tap row with
   another 10px of gap on top of it, the opening hours are seven near-identical
   lines, and there is 52px of air before the copyright.

   Nobody scrolls a barbershop site to read the footer twice. Two columns, the gap
   folded into the 44px rows that already separate the links, and the hours
   collapsed into runs by renderHours({compact:true}). */
@media (max-width:560px){
  .foot-grid{grid-template-columns:1fr 1fr;gap:22px 20px}
  /* the brand blurb spans the row: at 155px it wraps "independent" every line.
     Everything after it pairs up cleanly — Studio | Visit, Hours | Follow. */
  .foot-grid > :first-child{grid-column:1/-1}
  footer h4{margin-bottom:6px}
  /* The 44px tap rows were rendering 88px apart. `footer a` is an inline-block with
     line-height:44px, so each <li> also carries a line box of its own around it —
     the classic inline-block descender gap, doubled here because the line-height is
     44px. Making the row itself the flex line removes the second box; the 44px
     minimum is untouched. */
  footer ul{gap:0}
  footer li{display:flex}
  /* `display:flex` beats the [hidden] attribute's display:none, which un-hid the
     email row that applyBusiness() hides when the shop has no email on file — a
     dangling em-dash in the Visit column, which is the exact thing that code exists
     to prevent. */
  footer li[hidden]{display:none}
  footer ul a{display:flex;align-items:center;line-height:1.25;width:100%}

  /* "Mon – Sat" and "11am – 7pm" do not fit on one 157px line, and wrapping them
     produced a four-line block reading "Mon – / Sat / 11am – / 7pm". Stacked, the
     day is a label above its hours. */
  .hours-row{flex-direction:column;align-items:flex-start;gap:1px;padding:8px 0}
  .foot-bottom{margin-top:24px;padding-top:16px}
  .hours-row{padding:9px 0;font-size:.88rem}
}

/* ── the service finder on a phone ───────────────────────────────────────────
   8.4 screens for sixteen services. Nothing here is empty — it is dense, correct
   information — but it is dressed at desktop scale: 28px of padding on every one
   of sixteen cards, 56px between category blocks, a 1.6rem heading, and 60px-tall
   offer rows for a 38px avatar. Tightening the frame (not the content) is worth
   about a screen and a half, and the offer row keeps its 44px tap height with room
   to spare. Everything on the page is still on the page. */
@media (max-width:760px){
  /* 56px under every section heading, on a page with five of them */
  .sec-head{margin-bottom:28px}

  .svcfilter{margin-bottom:22px;gap:8px}
  .fchip{padding:11px 15px}
  .svcblock{margin-bottom:28px}
  .svccat{margin-bottom:14px;gap:12px}
  .svcitem{padding:15px 14px 14px;margin-bottom:10px}
  .svcitem h3{font-size:1.24rem}
  .svchead{gap:6px 14px}
  .svcdesc{font-size:.9rem;margin-top:6px}
  .svcwho{margin:12px 0 8px}
  .offers{gap:8px}
  .offer{padding:8px 12px;gap:11px}
  .offer .oav{width:36px;height:36px}
}

/* Owner pull-quote (About). One real, attributable review rather than a carousel of
   five — a single line a visitor could go and verify reads as true; a wall of them
   reads as marketing. Left rule instead of quote marks so it sits inside the prose
   column without breaking the page's vertical rhythm. */
.ownerquote{margin:38px 0 0;padding:24px 30px;border-left:2px solid var(--gold-d);
  background:rgba(255,255,255,.02);max-width:62ch}
.ownerquote blockquote{margin:0;font-family:var(--display);font-size:1.2rem;font-weight:300;
  color:var(--ink);line-height:1.55}
.ownerquote figcaption{margin-top:14px;font-size:.76rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--mute)}

/* Owner header (About) — portrait beside the heading rather than above it, so the
   name and the face land in the same glance. Stacks on phones: at 140px the portrait
   plus a two-line display heading does not fit a 360px column without the heading
   collapsing to one word per line. */
.ownerhead{display:flex;align-items:center;gap:26px;flex-wrap:wrap}
.ownerhead img{width:140px;height:140px;flex:none;object-fit:cover;border-radius:50%;
  border:1px solid var(--hair-2);box-shadow:0 10px 30px rgba(0,0,0,.5)}
/* min-width:0 is load-bearing: without it the display heading's min-content width
   (one very long word at 3rem) keeps the text column wider than the row, and the
   whole thing wraps the portrait onto its own line at every viewport. */
.ownerhead>div{flex:1 1 340px;min-width:0}
.ownerhead h2{margin-top:6px}
.ownerbody p+p{margin-top:18px}
@media(max-width:560px){
  .ownerhead{gap:18px}
  .ownerhead img{width:96px;height:96px}
}

/* Phone layouts: keep content inside the viewport and the next action in reach. */
#biography{scroll-margin-top:calc(var(--nav-h) + 20px)}
@media(max-width:760px){
  .grid > *{min-width:0}
  .hero-cta .btn{max-width:100%;white-space:normal;text-align:center}
  #teamPreview .barber .bio{
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;
    overflow:hidden;font-size:.95rem;line-height:1.6;
  }
  .barber .role{font-size:.75rem;letter-spacing:.12em;line-height:1.5}
  .profile-sidebar{display:contents}
  .profile-sidebar > .barber{order:0}
  .profile-menu{order:1}
  .profile-hours{order:2}
  #barberPage .profile-layout{gap:32px!important}
  #barberPage .barber{display:grid;grid-template-columns:88px minmax(0,1fr);align-items:center;padding:18px;gap:16px}
  #barberPage .barber .photo{width:88px;height:88px;aspect-ratio:1;--disc:88px;border-radius:50%}
  #barberPage .barber .body{padding:0;min-width:0}
  #barberPage .barber-name{font-size:1.4rem;overflow-wrap:anywhere}
  #barberPage .barber .acts{flex-wrap:wrap}
  #barberPage .barber .acts .btn{padding:12px;letter-spacing:.1em;white-space:normal;min-height:44px}
  #barberPage .barber .acts .small{display:inline-flex;align-items:center;min-height:44px;overflow-wrap:anywhere}
  .profile-hours{margin-top:0!important}
}
@media(max-width:560px){
  :root{--gut:20px}
  .wrap{padding-inline:var(--gut)}
  #teamGrid .barber .role{font-size:.7rem;letter-spacing:.08em;line-height:1.45}
  .ownerhead h2{font-size:clamp(1.7rem,8vw,2.3rem);letter-spacing:.03em}
}
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .navlinks{transition:none}
}

/* Landscape notches must not cover the logo, menu, or page content. */
@media(max-width:1000px){
  .wrap{padding-left:max(var(--gut,28px),env(safe-area-inset-left));padding-right:max(var(--gut,28px),env(safe-area-inset-right))}
}
