/* ==========================================================================
   GROOMED UP & CO. — theme.css  (v39, the studio redesign)
   --------------------------------------------------------------------------
   THE PALETTE IS SAMPLED, NOT PICKED. Every colour below comes from a k-means
   pass over the client's three pinned Instagram posts (assets/img/pin-1..3.jpg
   — colour studio portraits on a warm seamless backdrop):
     · --studio  #6A6257  the seamless-paper backdrop itself (medians #6C6258,
                          #736C62, #87796C across the three frames)
     · --ground  #F1EEE8  the same hue family lifted to a page-light value —
                          the skill's design-system run warns off pure white
     · --ink     #1D1A17  the charcoal cape (sampled #1D1B1E)
     · --accent  #4E4F47  the sage cape in pin-2 (sampled #4F4F49) — spent on
                          exactly one element, the floating Book It, the same
                          one-accent discipline the gold used to carry. It is
                          ONE variable; recolour the bubble by changing it.
   The taupe appears at full strength only twice — the hero and the closing
   Book It band — because that is how the cards use it: a field behind a white
   condensed wordmark. Everything between is greige ground and white cards.

   SURFACES (Apple-style): greige page, white cards with soft layered shadows,
   frosted header, no grain overlay (the old body::after noise was the most
   expensive paint on the page and is gone with the dark theme it textured).

   TYPE: Oswald is the condensed face of the wordmark baked into his cards;
   everything else is the system stack (-apple-system → SF on Apple devices),
   which is the Apple ask made literal. The old mono eyebrows became tracked
   system-sans labels — the sub-line on his cards is a tracked light sans, not
   a monospace.

   BUTTONS: every press is sprung. The press itself is fast (90ms in), the
   release is a spring curve (--spring, 320ms out) — that asymmetry is the
   whole "special to press" feel. Hovers lift; presses compress; both live
   only where they belong (@media (hover:hover) for hover, :active for touch).

   SHOPIFY PORTING NOTE
   Every custom property in :root maps to a theme setting in
   config/settings_schema.json. Every `.gu-<name>` block below corresponds to
   one section file in sections/<name>.liquid. Nothing is scoped to a page, so
   sections can be reordered freely in the Shopify theme editor.
   ========================================================================== */

/* ---------- tokens ---------- */
:root {
  --ground:   #0F0D0B;   /* page — BLACK since 2026-09-12 (client). The
                            bands and cards stay light; the page around them
                            is now the dark of his B&W brand. */
  --line-l:      rgba(255,255,255,0.16);  /* hairlines ON the black ground */
  --line-l-soft: rgba(255,255,255,0.09);
  --paper:    #FFFFFF;   /* cards and the white bands */
  --studio:   #6A6257;   /* the seamless backdrop, at strength */
  --studio-2: #7E7568;   /* its lit centre, for the radial field */
  --ink:      #1D1A17;   /* charcoal cape */
  --ink-2:    #575048;   /* secondary body text — 6:1 on ground */
  --ink-3:    #635C52;   /* labels and meta — darkened a step (client: the
                            light-taupe tier read "washed"); ~5.2:1 on ground */
  --line:      rgba(29,26,23,0.14);
  --line-soft: rgba(29,26,23,0.07);

  /* THE SAGE — lighter and greener since 2026-09-12 (client). Lives on the
     top bar; the Book It bubble is white now. White type holds ~4.7:1 on it. */
  --accent:      #7A8876;   /* the client's swatch, 2026-09-12 */
  --accent-deep: #66735F;

  --font-display: 'Oswald', 'Arial Narrow', 'Helvetica Neue', sans-serif;
  --font-body: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI',
               Roboto, 'Helvetica Neue', Arial, sans-serif;

  --space-1: 8px;   --space-2: 16px;  --space-3: 24px;
  --space-4: 40px;  --space-5: 64px;  --space-6: 96px;  --space-7: 140px;

  --wrap: 1280px;
  --gutter: clamp(20px, 5vw, 64px);

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  /* The overshoot curve. Only ever on transform/shadow — an overshooting
     colour looks like a rendering error. */
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --dur: 220ms;

  /* One radius token drives every pill; one drives every card. */
  --radius-pill: 999px;
  --radius-card: 20px;
  /* Block scale for the banded sections. NOT --radius-pill: 999px on a
     700px-tall section clamps to half its height and swallows the corners of
     the content inside it. */
  --radius-block: clamp(28px, 3.6vw, 56px);

  /* Soft layered elevation — one tight contact shadow + one wide ambient.
     A single blurred shadow reads as a sticker. */
  --shadow-card: 0 1px 2px rgba(29,26,23,0.05), 0 10px 30px rgba(29,26,23,0.07);
  --shadow-card-up: 0 2px 4px rgba(29,26,23,0.06), 0 18px 44px rgba(29,26,23,0.12);
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ground);
  color: #EFECE6;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }

::selection { background: #F1EEE8; color: #1D1A17; }

/* currentColor, so the ring is ink on light bands and white on the studio
   bands without a per-surface override. */
:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* ---------- typography primitives ---------- */
/* The tracked label — the sub-line of his cards ("PICTURE PERFECT CUTS"),
   generalised. System sans, wide tracking, never mono. */
.u-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.65);
}
.section--invert .u-label { color: var(--ink-3); }

/* Oswald 500, not 700: the wordmark baked into his cards is a medium-weight
   condensed with air in it, not a black. The slight positive tracking is
   also the cards'. */
.u-display {
  font-family: var(--font-display);
  font-weight: 500;
  text-transform: uppercase;
  line-height: 0.95;
  letter-spacing: 0.02em;
  margin: 0;
}

h2.u-display { font-size: clamp(42px, 7.4vw, 96px); }
h3.u-display { font-size: clamp(26px, 3.6vw, 42px); }

.u-body {
  color: rgba(255,255,255,0.72);
  font-size: clamp(15px, 1.4vw, 17px);
  line-height: 1.65;
  max-width: 56ch;
}

.u-rule { height: 1px; background: var(--line-l); border: 0; margin: 0; }

/* ---------- layout ---------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: clamp(72px, 11vw, 150px); position: relative; }
.section--tight { padding-block: clamp(52px, 7vw, 92px); }

/* THE WHITE BAND — a card at section scale. On the greige ground a white
   block with a soft shadow reads as a lifted surface, which is the whole
   Apple layering language in one move. Held off the page edges with the
   block radius so it reads as an object sitting ON the ground rather than a
   stripe painted across it.
   `overflow: hidden` is load-bearing: anything inside that bleeds to the
   block's edge would square off the corner it sits in. */
.section--invert {
  background: var(--paper); color: var(--ink);
  border-radius: var(--radius-block);
  margin-inline: var(--gutter);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}

/* THE STUDIO BAND — the backdrop taupe at full strength, white type on it:
   the pinned card as a section surface. Spent twice on the site (hero and
   the closing Book It), like the cards spend it. */
.section--studio {
  background: radial-gradient(120% 100% at 50% 20%,
    var(--studio-2) 0%, var(--studio) 55%, #5D564C 100%);
  color: #fff;
  border-radius: var(--radius-block);
  margin-inline: var(--gutter);
  overflow: hidden;
}

/* Rounded blocks need air around them or the corners have nothing to read
   against and the whole effect collapses back into a band. */
:is(.section--invert, .section--studio) + .section,
.section + :is(.section--invert, .section--studio),
:is(.section--invert, .section--studio) + :is(.section--invert, .section--studio) {
  margin-top: clamp(8px, 1.6vw, 26px);
}

@media (max-width: 560px) {
  /* At phone width the inset costs more than it buys. Keep the corners,
     drop most of the inset. */
  .section--invert, .section--studio { margin-inline: 10px; border-radius: 22px; }
}

.section--invert .u-label { color: var(--ink-3); }
.section--invert .u-body  { color: var(--ink-2); }
.section--invert .u-rule  { background: var(--line); }

.section--studio .u-label { color: rgba(255,255,255,0.78); }
.section--studio .u-body  { color: rgba(255,255,255,0.92); }
.section--studio .u-rule  { background: rgba(255,255,255,0.28); }

.section__head {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.section__head > div { min-width: 0; }
.section__num {
  font-family: var(--font-body); font-size: 11px; font-weight: 600;
  letter-spacing: 0.26em; text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.section--invert .section__num { color: var(--ink-3); }

/* ---------- buttons ----------
   THE PRESS SYSTEM. Two timings, deliberately asymmetric:
     · :active is near-instant (90ms, plain ease) — the button must move the
       moment the finger lands or the press reads as lag
     · the release inherits the base 320ms --spring, so it pops back with a
       small overshoot — that rebound is what makes it feel physical
   Hover (pointer devices only) lifts the button toward the light and grows
   the ambient shadow; the press compresses and tightens the shadow to a
   contact line. Transform and shadow only — layout never animates. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 50px; padding: 0 32px;
  font-family: var(--font-display);
  font-size: 15px; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
  border: 0;
  border-radius: var(--radius-pill);
  background: #fff; color: var(--ink);
  box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 8px 22px rgba(0,0,0,0.28);
  transition: transform 320ms var(--spring), box-shadow 320ms var(--spring),
              background var(--dur) var(--ease), color var(--dur) var(--ease);
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) {
  .btn:hover {
    transform: translateY(-2px);
    background: #F3F0EA;
    box-shadow: 0 2px 4px rgba(0,0,0,0.26), 0 14px 34px rgba(0,0,0,0.4);
  }
}
.section--invert .btn { background: var(--ink); color: #fff;
  box-shadow: 0 1px 2px rgba(29,26,23,0.18), 0 8px 22px rgba(29,26,23,0.16); }
@media (hover: hover) {
  .section--invert .btn:hover { background: #2C2823;
    box-shadow: 0 2px 4px rgba(29,26,23,0.16), 0 14px 34px rgba(29,26,23,0.24); }
}
.btn:active {
  transform: scale(0.96);
  box-shadow: 0 1px 2px rgba(29,26,23,0.22);
  transition-duration: 90ms, 90ms, var(--dur), var(--dur);
  transition-timing-function: ease, ease, var(--ease), var(--ease);
}

.btn--ghost {
  background: transparent; color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.35);
}
.section--invert .btn--ghost { color: var(--ink);
  box-shadow: inset 0 0 0 1px rgba(29,26,23,0.30); }
@media (hover: hover) {
  .btn--ghost:hover {
    background: var(--paper); color: var(--ink);
    box-shadow: inset 0 0 0 1px rgba(29,26,23,0.30),
                0 2px 4px rgba(29,26,23,0.08), 0 12px 28px rgba(29,26,23,0.12);
  }
}
.btn--ghost:active {
  box-shadow: inset 0 0 0 1px rgba(29,26,23,0.36);
}

/* On the studio bands the roles flip: solid buttons are white, ghosts are
   white-outlined. The hero uses the same pair. */
:is(.section--studio, .gu-herocard) .btn {
  background: #fff; color: var(--ink);
  box-shadow: 0 1px 2px rgba(0,0,0,0.18), 0 10px 26px rgba(0,0,0,0.22);
}
@media (hover: hover) {
  :is(.section--studio, .gu-herocard) .btn:hover {
    background: #fff; color: var(--ink);
    transform: translateY(-2px);
    box-shadow: 0 2px 4px rgba(0,0,0,0.16), 0 16px 38px rgba(0,0,0,0.30);
  }
}
/* On the studio fields the ghost is FROSTED GLASS, not a bare outline — a
   translucent white fill with a backdrop blur, the material Apple builds
   controls from. The blur has real pixels to work on here (the field's own
   gradient), and it degrades to the tint alone where unsupported. */
:is(.section--studio, .gu-herocard) .btn--ghost {
  background: rgba(255,255,255,0.13); color: #fff;
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  /* the machined edge (grafted from the panel's "card" variant): a 1px
     specular catch on the top lip and a dark lip rolling away below, so the
     one interactive element on the studio fields reads milled, not printed */
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.32),
              inset 0 1px 0 rgba(255,255,255,0.34),
              inset 0 -1px 0 rgba(29,26,23,0.20),
              0 4px 14px rgba(0,0,0,0.10),
              0 14px 34px rgba(29,26,23,0.20);
}
@media (hover: hover) {
  :is(.section--studio, .gu-herocard) .btn--ghost:hover {
    background: #fff; color: var(--ink);
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.55),
                0 2px 4px rgba(0,0,0,0.14), 0 12px 30px rgba(0,0,0,0.24);
  }
}

/* The closing Book It band's button is SAGE (client) — band-agnostic so it
   survived the band going white (client again: "the brown background should
   be white and the info inside black"). 18px bold white on the swatch sage
   clears AA large-text. */
.gu-book .btn,
#services .btn {
  background: var(--accent); color: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,0.18), 0 10px 26px rgba(29,26,23,0.2);
}
@media (hover: hover) {
  .gu-book .btn:hover,
  #services .btn:hover {
    background: var(--accent-deep); color: #fff;
    transform: translateY(-2px);
  }
}

.btn--lg { min-height: 62px; padding: 0 48px; font-size: 18px; }
.btn--sm { min-height: 40px; padding: 0 22px; font-size: 13px; }

/* the Book It arrow */
.btn__arrow { transition: transform var(--dur) var(--ease); }
.btn:hover .btn__arrow { transform: translateX(4px); }

/* ==========================================================================
   HEADER  →  sections/header.liquid
   Transparent over the taupe hero (white type reads fine on a flat studio
   field — the old photographic scrim is gone with the photograph), frosted
   greige once the page starts. The colour flip runs through two custom
   properties so every child follows one switch.
   ========================================================================== */
/* Three columns, not space-between: `1fr auto 1fr` pins the nav to the true
   centre of the viewport regardless of what flanks it. */
.gu-header {
  --hd: #FFFFFF;
  --hd-soft: rgba(255,255,255,0.75);
  position: fixed; top: 0; left: 0; right: 0; z-index: 900;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: var(--space-3);
  padding: 14px var(--gutter);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
  border-bottom: 1px solid transparent;
}
.gu-header--solid {
  /* the swatch sage is LIGHT, so the bar wears ink type and the dark mark —
     white on it fails contrast for 12px nav caps */
  --hd: var(--ink);
  --hd-soft: rgba(29,26,23,0.72);
  background: rgba(122,136,118,0.9);
  backdrop-filter: blur(20px) saturate(1.6);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  border-bottom-color: rgba(29,26,23,0.18);
}
.gu-header--solid .gu-header__mark { filter: invert(1); }

.gu-header__brand { display: flex; align-items: center; gap: 12px; justify-self: start; }
/* The real Groomed Up mark — white-on-transparent PNG lifted from the shop's
   own logo file, not a redraw. White artwork, so on the light solid header it
   inverts to ink. */
.gu-header__mark {
  width: 34px; height: 34px; flex: none; object-fit: contain;
  transition: filter var(--dur) var(--ease);
}
.gu-header__name {
  font-family: var(--font-display); font-weight: 500; text-transform: uppercase;
  font-size: 19px; letter-spacing: 0.06em; line-height: 1;
  color: var(--hd);
}
.gu-header__name span { color: var(--hd-soft); }

.gu-header__nav { display: flex; align-items: center; gap: 30px; justify-self: center; }
.gu-header__nav a {
  font-family: var(--font-body); font-size: 12px; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--hd-soft);
  transition: color var(--dur) var(--ease);
}
.gu-header__nav a:hover, .gu-header__nav a[aria-current='page'] { color: var(--hd); }

.gu-header__actions { display: flex; align-items: center; gap: 14px; justify-self: end; }

.gu-burger {
  display: none; width: 44px; height: 44px; padding: 0;
  background: none; border: 1px solid var(--hd-soft); color: var(--hd);
  border-radius: 50%;
  align-items: center; justify-content: center;
  transition: transform 320ms var(--spring), background var(--dur) var(--ease),
              color var(--dur) var(--ease), border-color var(--dur) var(--ease);
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) {
  .gu-burger:hover { background: var(--hd); color: var(--ground); border-color: var(--hd); }
}
.gu-burger:active { transform: scale(0.9); transition-duration: 90ms; }

@media (max-width: 900px) {
  /* The nav collapses into the drawer, so the centre column has nothing in
     it. Drop to two columns or the burger floats a third of the way in. */
  .gu-header { grid-template-columns: 1fr auto; }
  .gu-header__nav { display: none; }
  .gu-burger { display: inline-flex; }
  .gu-header__name { font-size: 16px; }
}

@media (max-width: 460px) {
  .gu-header { padding-inline: 16px; gap: 10px; }
  .gu-header__name { font-size: 14px; white-space: nowrap; letter-spacing: 0.04em; }
  .gu-header__name span { display: none; }   /* drop the "& Co." tail */
  .gu-header__mark { width: 26px; height: 26px; }
  .gu-header__actions { gap: 8px; }
}

/* mobile drawer — now a light surface.
   Three things here are load-bearing on a LANDSCAPE phone, where the content
   is taller than the 375–430px of available height:

   `overflow-y: auto` — without it the box simply overflows and the Book It
   link renders past the bottom edge with no gesture that can reach it (body
   scroll is locked while the drawer is open). That link is the Squire booking
   link and the drawer is the ONLY navigation below 900px.

   `overflow: hidden` in the closed state — the drawer is only moved out of
   frame with translateY(-100%), so anything overflowing its BOTTOM gets
   translated back into the viewport, full-bleed, at z-index 950 over the
   header's 900 — an invisible slab eating the tap that opens the menu.

   `justify-content: safe center` — plain centred flex pushes overflow out of
   BOTH ends; `safe` degrades to flex-start when it overflows. */
.gu-drawer {
  position: fixed; inset: 0; z-index: 950;
  background: var(--ground);
  color: #fff;
  display: flex; flex-direction: column; justify-content: safe center;
  padding: var(--gutter);
  padding-top: max(var(--gutter), calc(env(safe-area-inset-top) + 64px));
  padding-bottom: max(var(--gutter), env(safe-area-inset-bottom));
  transform: translateY(-100%);
  transition: transform 420ms var(--ease);
  overflow: hidden;                       /* closed: nothing may escape the box */
}
.gu-drawer[data-open='true'] {
  transform: translateY(0);
  overflow-y: auto;                       /* open: let tall content be reached */
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;           /* don't chain the fling to the page */
}
.gu-drawer a {
  font-family: var(--font-display); text-transform: uppercase;
  /* Sized against the SHORT axis too — 12vw alone is ~101px on a landscape
     iPhone, which is what made the list overflow in the first place. */
  font-size: clamp(28px, min(12vw, 11vh), 64px); font-weight: 500;
  letter-spacing: 0.02em; line-height: 1.06;
  border-bottom: 1px solid var(--line-l-soft); padding: 14px 0;
  flex: none;                             /* never let flex squash the links */
}
.gu-drawer__close {
  position: absolute; top: 14px; right: var(--gutter);
  width: 44px; height: 44px; background: none; border: 1px solid var(--line-l);
  color: #fff; display: grid; place-items: center; border-radius: 50%;
  transition: transform 320ms var(--spring);
  -webkit-tap-highlight-color: transparent;
}
.gu-drawer__close:active { transform: scale(0.9); transition-duration: 90ms; }
.gu-drawer__book { margin-top: var(--space-4); }

/* ==========================================================================
   HERO  ->  sections/hero.liquid   (v10 — THE HAND, DEALT)
   --------------------------------------------------------------------------
   Round-two design panel (variants in film/retired/hero-lab-v9/): "fan2" won
   the first-impression lens and the tiebreak — it doubles down on the one
   thing the client explicitly liked (his three posts, dealt) and kills the
   thing he flagged ("Groomed Up & Co. is a bit everywhere"):

   - The photos are SUBJECT-ONLY crops (pin-*-face.jpg) — the captions baked
     into the full cards were the wordmark echo, so they are cropped off.
   - EXACTLY ONE brand instance in the hero: the h1, deliberately small and
     wide-tracked above the display line. "PICTURE PERFECT CUTS" carries the
     display scale — his own slogan in his own condensed voice. The border
     is gone entirely (client order).

   DEPTH LAYERS: the real studio-paper plate, a tonal hold-back (calm dark
   top for the header, open middle, settling under the lockup), a warm lift
   at the base so the plate's dark drift stays umber (never black), a pooled
   studio light the fan sits inside, a blurred grounding shadow beneath the
   deal, and triple-layered card shadows. Grafted from the losing variants:
   the centre card rides slightly brighter and highest in the stack
   (triptych's lifted anchor), and the phone reorders to spread's stack —
   type block on top, the fan whole beneath it, nothing reduced to slivers.

   THE DEAL: cards rise from a tighter, lower under-throw into the fan on a
   one-shot ease-out. Keyframes define only `from` and fill is BACKWARDS, so
   every element lands on its BASE styles — a forwards fill would pin the
   animated transform and dead-arm the hover lift forever. Outer faces gaze
   inward (object-position per crop); flip nothing.

   After the deal, nothing moves. Two heroes died for perpetual motion.
   ========================================================================== */
.gu-herocard {
  position: relative;
  /* a bubble like the rest of the page (client, 2026-09-11): inset on the
     ground with the block radius. The top margin clears the fixed header,
     which is now frosted-solid from y=0 — a transparent header over the
     greige gap around the bubble would be white type on near-white. */
  margin: calc(64px + clamp(10px, 1.6vw, 22px)) var(--gutter) 0;
  border-radius: var(--radius-block);
  box-shadow: var(--shadow-card);
  min-height: calc(100svh - 64px - clamp(10px, 1.6vw, 22px) - clamp(8px, 1.6vw, 26px));
  display: flex; flex-direction: column; align-items: center;
  padding: clamp(56px, 8vh, 84px) 24px 40px;
  background: var(--studio) url("img/hero-backdrop.jpg?v=74") center 40% / cover no-repeat;
  color: #fff;
  overflow: hidden;
  text-align: center;
}
/* tonal hold-back — the top band also carries the fixed header */
.gu-herocard::before {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg,
    rgba(29,26,23,0.18) 0%, rgba(29,26,23,0.08) 22%, rgba(29,26,23,0.04) 44%,
    rgba(29,26,23,0.14) 74%, rgba(29,26,23,0.34) 100%);
  pointer-events: none;
}
/* pooled studio light the fan sat inside — off while the film carries the
   light itself (restore with the fan) */
.gu-herocard::after {
  content: none; position: absolute;
  left: 50%; top: 37%;
  width: min(1040px, 130vw); height: min(680px, 86vw);
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse at center,
    rgba(241,238,232,0.22) 0%, rgba(241,238,232,0.09) 38%, rgba(241,238,232,0) 70%);
  pointer-events: none;
}
/* warm lift at the base: the plate's dark drift stays umber, never black */
.gu-herocard__warm {
  position: absolute; left: 50%; bottom: -12%;
  width: 120%; height: 56%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center,
    rgba(126,117,104,0.26) 0%, rgba(126,117,104,0.10) 46%, rgba(126,117,104,0) 72%);
  pointer-events: none;
}

/* THE FILM — fills the bubble, his mark centred on the plate's 46% light
   line. The section's own background-image is the SAME plate the film was
   grown from, so the loading state and the first frame are one scene. */
.gu-herocard__film {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 46%;
  /* the ORIGINAL film, big sign — the client's pick over the recomposed
     small-sign v3 ("the logo was bigger before"). The lift keeps the sign
     high enough that the lockup clears its body at most viewport shapes;
     where they meet, that overlap is the accepted look. */
  transform: translateY(-5%) scale(1.06);
}

.gu-herocard__inner {
  /* static ON PURPOSE: the address inside is absolute-anchored to the
     SECTION's bottom edge, and a positioned inner would capture it 114px
     high. Flex items honour z-index without being positioned. */
  z-index: 2;
  flex: 1;
  display: flex; flex-direction: column; align-items: center;
  width: 100%;
}

/* ---- the fan ---- */
.gu-herofan {
  --fan-w: clamp(200px, 22.5vw, 334px);
  position: relative;
  width: min(900px, 96vw);
  height: calc(var(--fan-w) * 1.25 + 34px);
}
.gu-herofan__ground {
  position: absolute; left: 50%; bottom: -14px;
  width: 78%; height: 60px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center,
    rgba(29,26,23,0.40) 0%, rgba(29,26,23,0.16) 48%, rgba(29,26,23,0) 72%);
  filter: blur(7px);
  pointer-events: none;
}
.gu-herofan__card {
  position: absolute; left: 50%; top: 0;
  width: var(--fan-w); aspect-ratio: 4 / 5;
  border-radius: 12px; overflow: hidden;
  display: block;
  transform: translateX(calc(-50% + var(--x))) translateY(var(--y)) rotate(var(--r));
  transform-origin: 50% 92%;
  box-shadow:
    0 1px 2px rgba(29,26,23,0.24),
    0 10px 22px rgba(29,26,23,0.24),
    0 34px 68px rgba(29,26,23,0.36);
  transition: transform 420ms cubic-bezier(0.22,0.61,0.21,1),
              box-shadow 420ms cubic-bezier(0.22,0.61,0.21,1);
  -webkit-tap-highlight-color: transparent;
}
.gu-herofan__card img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* studio light catching the top of each print, settling at its foot */
.gu-herofan__card::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(180deg,
    rgba(255,255,255,0.10) 0%, rgba(255,255,255,0) 24%,
    rgba(29,26,23,0) 76%, rgba(29,26,23,0.16) 100%);
  pointer-events: none;
}
/* the deal — outer faces look inward; centre is the lifted anchor */
.gu-herofan__card--l { --x: calc(var(--fan-w) * -0.78); --y: 30px; --r: -10deg;  z-index: 1; }
.gu-herofan__card--r { --x: calc(var(--fan-w) *  0.78); --y: 30px; --r: 10deg;   z-index: 2; }
.gu-herofan__card--m { --x: 0px;                        --y: 0px;  --r: -1.4deg; z-index: 3; }
.gu-herofan__card--l img { object-position: 74% 45%; }  /* copper quiff, faces right */
.gu-herofan__card--r img { object-position: 30% 40%; }  /* platinum crop, faces left */
.gu-herofan__card--m img { object-position: 40% 38%; filter: brightness(1.05); }

@media (hover: hover) {
  .gu-herofan__card:hover {
    transform: translateX(calc(-50% + var(--x))) translateY(calc(var(--y) - 10px)) rotate(var(--r));
    box-shadow:
      0 1px 2px rgba(29,26,23,0.24),
      0 16px 30px rgba(29,26,23,0.26),
      0 46px 88px rgba(29,26,23,0.42);
  }
}
.gu-herofan__card:active {
  transform: translateX(calc(-50% + var(--x))) translateY(var(--y)) rotate(var(--r)) scale(0.97);
  transition-duration: 90ms;
}

/* ---- the lockup — the v43 wording the client asked back: address
   eyebrow, the wordmark AT DISPLAY SCALE, hairline rule, tracked sub-line.
   The repetition complaint died with the cards' baked captions, so the big
   brand line returns without echo. ---- */
.gu-herocard__eyebrow {
  margin: auto 0 0;                 /* pushes the lockup to the bottom band */
  font-family: var(--font-body); font-size: 11px; font-weight: 500;
  letter-spacing: 0.3em; text-indent: 0.3em; text-transform: uppercase;
  /* white again: the sign is INK now (client: "should we make the logo
     black?" — yes), so white type reads over the sign and the paper both */
  color: rgba(255,255,255,0.85);
  text-shadow: 0 1px 10px rgba(29,26,23,0.4);
  white-space: nowrap;
}
.gu-herocard__display {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(34px, 4.9vw, 68px);
  letter-spacing: 0.06em; text-indent: 0.06em;
  text-transform: uppercase; line-height: 1.05;
  color: #fff;
  white-space: nowrap;
  margin: 10px 0 0;
}
.gu-herocard__rule {
  width: 64px; height: 1px;
  background: rgba(255,255,255,0.45);
  margin: clamp(14px, 2vh, 20px) auto 0;
}
.gu-herocard__tag {
  margin: clamp(12px, 1.8vh, 18px) 0 0;
  font-family: var(--font-body); font-size: 12px; font-weight: 500;
  letter-spacing: 0.36em; text-indent: 0.36em; text-transform: uppercase;
  color: rgba(255,255,255,0.9);
}
.gu-herocard__cta {
  margin-top: clamp(18px, 2.6vh, 26px);
  margin-bottom: clamp(2px, 1vh, 10px);
}

/* the cycle's incoming layer — see theme.js heroCycle */
.gu-herofan__card .gu-herofan__fade {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0;
  transition: opacity 900ms ease;
}
.gu-herofan__card .gu-herofan__fade.is-in { opacity: 1; }

/* ---- one-shot load-in ---- */
.gu-herofan__card { animation: guDealFan 0.95s cubic-bezier(0.16,0.68,0.22,1) var(--d) backwards; }
@keyframes guDealFan {
  from {
    opacity: 0;
    transform: translateX(calc(-50% + var(--x) * 0.45))
               translateY(calc(var(--y) + 72px))
               rotate(calc(var(--r) * 0.3));
  }
}
.gu-herofan__ground { animation: guPool 0.9s ease-out 0.58s backwards; }
@keyframes guPool { from { opacity: 0; transform: translateX(-50%) scaleX(0.82); } }
.gu-rise { animation: guRise 0.8s cubic-bezier(0.22,0.61,0.21,1) var(--d) backwards; }
@keyframes guRise  { from { opacity: 0; transform: translateY(22px); } }
@media (prefers-reduced-motion: reduce) {
  .gu-herofan__card, .gu-herofan__ground, .gu-rise { animation: none !important; }
}

/* ---- phone: spread's stack, grafted — type block on top, the fan whole
   beneath it ---- */
@media (max-width: 600px) {
  .gu-herocard { margin: 74px 10px 0; border-radius: 22px; min-height: calc(100svh - 84px); padding: 44px 16px 40px; }
  .gu-herocard__inner { justify-content: flex-end; }
  .gu-herocard__eyebrow { font-size: 9.5px; letter-spacing: 0.22em; text-indent: 0.22em; }
  .gu-herocard__display { font-size: clamp(28px, 8.2vw, 36px); }
  .gu-herocard__tag     { font-size: 11px; letter-spacing: 0.3em; text-indent: 0.3em; }
  .gu-herofan {
    order: 6;
    --fan-w: 46vw;   /* whole faces inside the bubble's 10px inset */
    margin-top: clamp(24px, 4vh, 40px);
    height: calc(var(--fan-w) * 1.25 + 30px);
  }
  .gu-herofan__card { border-radius: 10px; }
  .gu-herofan__card--l { --x: -19vw; --y: 18px; --r: -9deg; }
  .gu-herofan__card--r { --x:  19vw; --y: 18px; --r: 9deg; }
}

/* ==========================================================================
   MARQUEE  →  sections/marquee.liquid
   ========================================================================== */
.gu-marquee {
  border-block: 1px solid var(--line-l-soft);
  padding-block: 20px; overflow: hidden; white-space: nowrap;
}
.gu-marquee__track { display: inline-flex; gap: 48px; animation: slide 42s linear infinite; }
.gu-marquee span {
  font-family: var(--font-display); text-transform: uppercase;
  font-size: clamp(18px, 2.4vw, 30px); font-weight: 500;
  /* was #C9C1B5 — the client called it washed; the band should read, not
     whisper. The diamond stays a shade lighter so it stays punctuation. */
  letter-spacing: 0.06em; color: var(--ink-3);
  display: inline-flex; align-items: center; gap: 48px;
}
.gu-marquee span::after { content: '✦'; font-size: 0.5em; color: #A79C8D; }
@keyframes slide { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .gu-marquee__track { animation: none; } }

/* ==========================================================================
   SIGNATURE  →  sections/signature.liquid   (The Groomed Up)
   ========================================================================== */
.gu-signature { display: grid; grid-template-columns: 1.05fr 1fr; gap: clamp(32px, 6vw, 88px); align-items: center; }
.gu-signature__media {
  position: relative; aspect-ratio: 4/5; overflow: hidden;
  background: #E5E0D7;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
.gu-signature__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 700ms var(--ease), filter 700ms var(--ease);
}

/* THE SHARED IMAGE HOVER — every photograph pushes in slightly and lifts.
   The other copies live beside .gu-barber, .gu-pin and .gu-gram.

   Each copy lives NEXT TO the element it styles, never in one shared block:
   a shared block already died with its host section once and took this hover
   with it silently.

   INSIDE @media (hover: hover), ALWAYS — opt IN, never opt out. A tap leaves
   :hover stuck on touch, and an opt-out guard once forgot three of five
   declarations and served white-on-white to every iPhone.

   700ms and 1.05: fast-and-large reads as a stock widget; slow-and-small
   reads as the picture leaning toward you. */
@media (hover: hover) {
  .gu-signature__media:hover img {
    transform: scale(1.05);
    filter: brightness(1.06) contrast(1.02);
  }
}
.gu-signature__list { list-style: none; margin: var(--space-4) 0 0; padding: 0; }
.gu-signature__list li {
  display: flex; align-items: center; gap: 14px;
  padding: 13px 0; border-bottom: 1px solid var(--line-soft);
  font-size: 15px; color: var(--ink-2);
}
.gu-signature__list li::before {
  content: ''; width: 6px; height: 6px; flex: none;
  background: var(--ink); transform: rotate(45deg);
}
@media (max-width: 860px) { .gu-signature { grid-template-columns: 1fr; } }

/* ==========================================================================
   SERVICES  →  sections/services.liquid
   ========================================================================== */
.gu-services { border-top: 1px solid var(--line); }
.gu-service {
  /* TWO columns — the price column was removed with the prices (client,
     2026-08-12): Squire shows the real figure at the moment of booking. */
  display: grid; grid-template-columns: 1fr auto;
  gap: clamp(16px, 3vw, 40px); align-items: center;
  padding: clamp(20px, 2.6vw, 30px) 0;
  border-bottom: 1px solid var(--line-soft);
  position: relative;
  transition: padding-left var(--dur) var(--ease);
  -webkit-tap-highlight-color: transparent;
}

/* The fill is a sibling of the content in paint order, so the row's own
   children have to be lifted above it or the wipe covers the text. */
.gu-service > * { position: relative; z-index: 1; }

/* ⚠ THE WHOLE HOVER MECHANISM LIVES INSIDE @media (hover: hover), and must.
   iOS applies :hover on tap and holds it — these rows open Squire in a NEW
   TAB, so the page never navigates and the state stays stuck. Opt IN on
   pointers that can actually hover, and there is nothing to undo.

   The row highlight is a rounded ink slab that wipes in from the left —
   left, because the eye is already travelling that way along the row. It
   bleeds 20px past the text on both sides: flush against the type it reads
   as a rendering glitch; the bleed is what makes it a highlight. */
.gu-service::before {
  content: ''; position: absolute;
}
@media (hover: hover) {
  .gu-service::before {
    inset: 0 -20px;
    background: var(--ink);
    border-radius: 14px;
    transform: scaleX(0); transform-origin: left;
    transition: transform 380ms var(--ease);
  }
  .gu-service:hover::before { transform: scaleX(1); }
  .gu-service:hover { color: #fff; padding-left: 14px; }
  .gu-service:hover .gu-service__desc,
  .gu-service:hover .gu-service__meta { color: rgba(255,255,255,0.7); }
}

.gu-service__name {
  font-family: var(--font-display); font-weight: 500; text-transform: uppercase;
  font-size: clamp(21px, 2.6vw, 32px); letter-spacing: 0.02em; line-height: 1.05;
}
.gu-service__desc { font-size: 14px; color: var(--ink-3); margin-top: 5px; max-width: 46ch; }
.gu-service__meta {
  font-family: var(--font-body); font-size: 11px; font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--ink-3); text-transform: uppercase; white-space: nowrap;
}
@media (max-width: 720px) {
  /* Name and description in column 1, duration pinned right and centred. */
  .gu-service { row-gap: 6px; }
  .gu-service__meta { grid-column: 2; align-self: center; text-align: right; }
}

/* ==========================================================================
   PRODUCTS  →  sections/featured-products.liquid
   On Shopify this iterates `collections.all.products` instead of products.json.
   White cards, soft elevation, sprung hover lift.
   ========================================================================== */
.gu-products {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: clamp(12px, 1.6vw, 20px);
}
.gu-product {
  background: var(--paper); color: var(--ink);
  position: relative; display: flex; flex-direction: column;
  border-radius: var(--radius-card); overflow: hidden;
  border: 1px solid var(--line-soft);   /* holds the edge on the white bands */
  box-shadow: var(--shadow-card);
  transition: transform 320ms var(--spring), box-shadow 320ms var(--spring);
}
@media (hover: hover) {
  .gu-product:hover { transform: translateY(-4px); box-shadow: var(--shadow-card-up); }
  .gu-product:hover .gu-product__media img { transform: scale(1.045); }
}
.gu-product:active { transform: scale(0.985); transition-duration: 90ms; }
.gu-product__media { aspect-ratio: 3/4; overflow: hidden; background: #EDE9E2; }
.gu-product__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 620ms var(--ease);
}
.gu-product__body { padding: 20px; display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.gu-product__title {
  font-family: var(--font-display); font-weight: 500; text-transform: uppercase;
  font-size: 18px; letter-spacing: 0.03em; line-height: 1.1;
}
.gu-product__desc { font-size: 13px; color: var(--ink-3); margin-top: 6px; }
.gu-product__price { font-family: var(--font-display); font-weight: 500; font-size: 20px; }
@media (max-width: 1000px) { .gu-products { grid-template-columns: repeat(2, 1fr); } }

/* ---- mobile: swipe, don't stack ----
   Six stacked cards meant ~4 viewport-heights just to pass the shop. As a
   snapping rail you take them in with a thumb flick. `overflow-x` lives on
   the rail, never on the page — the body must never scroll sideways. */
@media (max-width: 760px) {
  .gu-products {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 72%;
    grid-template-columns: none;
    gap: 12px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* bleed to the screen edges so the rail reads as scrollable, while the
       first card still lines up with the text above it */
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    padding-block: 4px 12px;   /* room for the card shadows to paint */
  }
  .gu-products::-webkit-scrollbar { display: none; }
  .gu-product { scroll-snap-align: start; }
  .gu-product__media { aspect-ratio: 4/5; }
}
@media (max-width: 420px) {
  .gu-products { grid-auto-columns: 80%; }
}

/* soon badge for the preview build */
.gu-product__tag {
  position: absolute; top: 12px; left: 12px; z-index: 2;
  font-family: var(--font-body); font-size: 9px; font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase; background: var(--ink); color: #fff;
  padding: 6px 13px; border-radius: var(--radius-pill);
}

/* ==========================================================================
   TEAM  →  sections/team.liquid
   White cards; the body keeps the pinned-card lockup — name centred in
   condensed caps, role tracked wide beneath, exactly his cards' composition.
   ========================================================================== */
.gu-team {
  /* three chairs since 2026-09-11 (Angel removed — not a barber there) */
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(12px, 1.6vw, 20px);
}
.gu-barber {
  background: var(--paper); color: var(--ink);
  display: flex; flex-direction: column;
  border-radius: var(--radius-card); overflow: hidden;
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-card);
  transition: transform 320ms var(--spring), box-shadow 320ms var(--spring);
  -webkit-tap-highlight-color: transparent;
}
.gu-barber:not(.gu-barber--photo) { padding: clamp(24px, 3vw, 40px); min-height: 210px; }

/* Portrait from the barber's own Squire profile — the same face the client
   sees when they pick a barber at booking. */
.gu-barber__media { aspect-ratio: 1; overflow: hidden; background: #EDE9E2; }
.gu-barber__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 700ms var(--ease), filter 700ms var(--ease);
}

.gu-barber__body {
  padding: 20px clamp(18px, 2vw, 26px) clamp(22px, 2.4vw, 30px);
  display: flex; flex-direction: column; gap: 14px; flex: 1;
  align-items: center; text-align: center;
}
.gu-barber__idx { align-self: flex-start; }
.gu-barber:not(.gu-barber--photo) .gu-barber__body { padding: 0; justify-content: space-between; }
.gu-barber__idx {
  font-family: var(--font-body); font-size: 10px; font-weight: 600;
  letter-spacing: 0.3em; color: var(--ink-3);
}
.gu-barber__name {
  font-family: var(--font-display); font-weight: 500; text-transform: uppercase;
  font-size: clamp(22px, 2.4vw, 30px); letter-spacing: 0.03em;
  line-height: 0.95; margin-top: auto;
}
.gu-barber__role {
  font-family: var(--font-body); font-size: 10px; font-weight: 600;
  letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--ink-3); margin-top: 8px;
}

/* Barber hover — the shared image language plus the card lift. Opt-IN. */
@media (hover: hover) {
  .gu-barber:hover { transform: translateY(-4px); box-shadow: var(--shadow-card-up); }
  .gu-barber:hover .gu-barber__media img {
    transform: scale(1.05);
    filter: brightness(1.06) contrast(1.02);
  }
}

@media (max-width: 900px) { .gu-team { grid-template-columns: repeat(2, 1fr); } }

/* ==========================================================================
   INSTAGRAM  →  sections/instagram.liquid
   ========================================================================== */
.gu-gram { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; }
.gu-gram a {
  position: relative; aspect-ratio: 1; overflow: hidden; background: #E5E0D7;
  display: block; border-radius: 12px;
  -webkit-tap-highlight-color: transparent;
}
.gu-gram img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 600ms var(--ease), filter var(--dur) var(--ease);
}
@media (hover: hover) {
  .gu-gram a:hover img { transform: scale(1.06); filter: contrast(1.04) brightness(1.04); }
}
@media (max-width: 900px) { .gu-gram { grid-template-columns: repeat(3, 1fr); } }

/* THE PINS — restored (client, 2026-09-11 evening): the hero is the ink
   logo film now, so the three pinned cards came home to open The Feed. */
.gu-pins {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(14px, 2.2vw, 32px);
  margin-bottom: clamp(28px, 4vw, 54px);
}
.gu-pin {
  margin: 0; overflow: hidden; background: #E5E0D7;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  transition: transform 320ms var(--spring), box-shadow 320ms var(--spring);
}
.gu-pin img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 5; object-fit: cover;   /* IG portrait, as posted */
  transition: transform 700ms var(--ease), filter 700ms var(--ease);
}
@media (hover: hover) {
  .gu-pin:hover { transform: translateY(-4px); box-shadow: var(--shadow-card-up); }
  .gu-pin:hover img { transform: scale(1.05); filter: brightness(1.05) contrast(1.02); }
}
@media (max-width: 700px) {
  .gu-pins { grid-template-columns: 1fr; gap: 16px; }
}

/* ==========================================================================
   REVIEWS  →  sections/reviews.liquid
   One white card: the sourced aggregate beside the one quote we could source
   accurately. Add entries to reviews.json and it becomes a grid on its own.
   ========================================================================== */
.gu-reviews {
  display: grid; grid-template-columns: auto 1fr;
  gap: clamp(28px, 5vw, 72px); align-items: center;
  border: 1px solid var(--line-soft); border-radius: 28px;
  padding: clamp(28px, 4vw, 52px);
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--shadow-card);
}

.gu-reviews__score { text-align: center; }
.gu-reviews__num {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(56px, 8vw, 96px); line-height: 0.9; letter-spacing: 0;
}
.gu-reviews__stars {
  display: flex; gap: 4px; justify-content: center; margin-top: 10px;
  color: var(--ink);
}
.gu-reviews__stars svg { width: 18px; height: 18px; }
.gu-reviews__count {
  font-family: var(--font-body); font-size: 10px; font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-3); margin-top: 14px;
  display: inline-flex; align-items: center; min-height: 44px;
}
/* 0.2em tracking eats the trailing space before the link — give the link its
   own left margin rather than fighting it with an &nbsp;. */
.gu-reviews__count a { color: var(--ink-2); border-bottom: 1px solid var(--line); margin-left: 6px; }
.gu-reviews__count a:hover { color: var(--ink); border-bottom-color: var(--ink); }

.gu-reviews__quotes { display: grid; gap: clamp(18px, 2.5vw, 28px); }
.gu-reviews blockquote {
  margin: 0;
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(21px, 2.6vw, 34px); line-height: 1.24;
  letter-spacing: 0.005em; color: var(--ink);
}
.gu-reviews blockquote::before { content: '\201C'; }
.gu-reviews blockquote::after  { content: '\201D'; }
.gu-reviews figcaption {
  font-family: var(--font-body); font-size: 10px; font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-3); margin-top: 12px;
}
.gu-reviews__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; }

/* Two or more quotes: side by side at reading size. */
.gu-reviews__quotes--multi { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.gu-reviews__quotes--multi blockquote { font-size: clamp(16px, 1.5vw, 19px); line-height: 1.45; }

@media (max-width: 780px) {
  .gu-reviews { grid-template-columns: 1fr; text-align: center; }
  .gu-reviews__quotes { text-align: left; }
  .gu-reviews__actions { justify-content: center; }
  .gu-reviews__count { min-height: 40px; }
}

/* ==========================================================================
   VISIT  →  sections/visit.liquid
   ========================================================================== */
.gu-visit { display: grid; grid-template-columns: 1fr 1.15fr; gap: clamp(32px, 5vw, 80px); }
.gu-visit__rows { list-style: none; margin: 0; padding: 0; }
.gu-visit__rows li {
  display: flex; justify-content: space-between; gap: 20px;
  padding: 15px 0; border-bottom: 1px solid var(--line-l-soft);
  font-size: 15px; color: rgba(255,255,255,0.82);
}
.gu-visit__rows li span:first-child {
  font-family: var(--font-body); font-size: 11px; font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase; color: rgba(255,255,255,0.55);
}
.gu-visit__map {
  min-height: 380px;
  border-radius: var(--radius-card); overflow: hidden;
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-card);
}
.gu-visit__map iframe { width: 100%; height: 100%; min-height: 380px; border: 0; display: block; }
@media (max-width: 900px) { .gu-visit { grid-template-columns: 1fr; } }

/* ==========================================================================
   BOOK CTA  →  sections/book-cta.liquid   (a .section--studio band)
   The closing bookend: the same studio field as the hero, white type, white
   pill — the site ends on the card it opened on.
   ========================================================================== */
.gu-book { text-align: center; }
.gu-book__title {
  font-family: var(--font-display); font-weight: 500; text-transform: uppercase;
  font-size: clamp(52px, 12vw, 170px); line-height: 0.9; letter-spacing: 0.02em;
  margin: 0 0 var(--space-4);
}
.gu-book__sub { margin: 0 auto var(--space-4); }

.gu-book__proof {
  margin-top: 18px;
  font-family: var(--font-body); font-size: 11px; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink-3);
}
.gu-book__proof a { border-bottom: 1px solid rgba(29,26,23,0.25); padding-bottom: 2px; }
@media (hover: hover) {
  .gu-book__proof a:hover { color: var(--ink); border-bottom-color: var(--ink); }
}

/* ==========================================================================
   FOOTER  →  sections/footer.liquid
   ========================================================================== */
.gu-footer { border-top: 1px solid var(--line-l-soft); padding-block: var(--space-5) var(--space-4); }
/* the footer wordmark reuses .gu-header__name, which reads its colour from
   the header's --hd custom property — restate ink here where there is no
   header to inherit from */
.gu-footer .gu-header__name { color: #fff; }
.gu-footer .gu-header__name span { color: rgba(255,255,255,0.55); }
.gu-footer__grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1.2fr; gap: var(--space-4); }
.gu-footer h4 {
  font-family: var(--font-body); font-size: 10px; font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase; color: rgba(255,255,255,0.55); margin: 0 0 16px;
}
.gu-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.gu-footer li a { color: rgba(255,255,255,0.72); font-size: 14px; transition: color var(--dur) var(--ease); }
.gu-footer a:hover { color: #fff; }
.gu-footer__bottom {
  display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between;
  margin-top: var(--space-5); padding-top: 22px; border-top: 1px solid var(--line-l-soft);
  font-family: var(--font-body); font-size: 10px; font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase; color: rgba(255,255,255,0.55);
}
@media (max-width: 860px) { .gu-footer__grid { grid-template-columns: 1fr 1fr; } }

/* legacy sticky book bar — retired in favour of the bubble on every
   breakpoint; the element stays in the markup for the Shopify port to decide */
.gu-bookbar { display: none !important; }

/* ==========================================================================
   FLOATING BOOK IT  →  snippets/book-float.liquid
   THE booking control — the only persistent one on the site, on screen from
   the first paint. The accent colour is spent here and nowhere else (see the
   token note): the sage of the cape in pin-2, as a soft-elevated pill. The
   press is the springiest on the site because it is the button that matters.
   ========================================================================== */
.gu-float {
  position: fixed;
  right: clamp(20px, 3vw, 44px);
  bottom: clamp(20px, 3vw, 44px);
  z-index: 890;
  display: inline-flex; align-items: center; gap: 12px;
  min-height: 58px; padding: 0 34px;
  font-family: var(--font-display); font-weight: 500; font-size: 16px;
  letter-spacing: 0.14em; text-transform: uppercase;
  border-radius: var(--radius-pill);
  /* WHITE with black writing (client, 2026-09-12). The hairline inset ring
     keeps its edge when it floats over the white bands. */
  color: var(--ink);
  background: linear-gradient(180deg, #FFFFFF 0%, #F4F1EB 100%);
  box-shadow:
    inset 0 0 0 1px rgba(29,26,23,0.12),
    inset 0 1px 0 rgba(255,255,255,0.9),
    0 2px 6px rgba(0,0,0,0.3),
    0 14px 34px rgba(0,0,0,0.34);
  opacity: 0; transform: translateY(22px) scale(0.94);
  pointer-events: none;
  transition: opacity 320ms var(--ease),
              transform 380ms var(--spring),
              box-shadow 380ms var(--spring);
  -webkit-tap-highlight-color: transparent;
}
.gu-float[data-show='true'] {
  opacity: 1; transform: none; pointer-events: auto;
}
@media (hover: hover) {
  .gu-float[data-show='true']:hover {
    transform: translateY(-2px);
    box-shadow:
      inset 0 0 0 1px rgba(29,26,23,0.12),
      inset 0 1px 0 rgba(255,255,255,0.9),
      0 4px 10px rgba(0,0,0,0.28),
      0 22px 48px rgba(0,0,0,0.4);
  }
  .gu-float:hover .btn__arrow { transform: translateX(4px); }
}
.gu-float[data-show='true']:active {
  transform: scale(0.94);
  box-shadow:
    inset 0 0 0 1px rgba(29,26,23,0.16),
    inset 0 2px 5px rgba(29,26,23,0.18),
    0 1px 3px rgba(0,0,0,0.3);
  transition-duration: 90ms;
}
/* theme.js toggles .gu-float--on-light from a position probe; the sage pill
   reads on every surface of the light theme, so the class currently carries
   no styles — the hook stays for the day a surface disagrees. */
@media (prefers-reduced-motion: reduce) {
  .gu-float { transition: opacity 1ms linear; }
}

/* Phones: bottom-right, inside the safe area, comfortably over 44px. */
@media (max-width: 900px) {
  .gu-float {
    right: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom));
    min-height: 54px; padding: 0 26px;
    font-size: 15px; gap: 10px;
  }
}
@media (max-width: 380px) {
  .gu-float { min-height: 50px; padding: 0 22px; font-size: 14px; letter-spacing: 0.1em; }
}

/* ==========================================================================
   MOBILE
   --------------------------------------------------------------------------
   Finger-sized targets, and press states — :hover never fires on touch, so
   every interactive surface needs an :active that shows the press.
   ========================================================================== */
@media (max-width: 900px) {

  /* --- tap targets. Everything actionable clears 44px. ------------------- */
  .gu-header__brand { min-height: 44px; }
  .btn--sm { min-height: 44px; padding-inline: 20px; }
  .gu-reviews__count a { display: inline-flex; align-items: center; min-height: 44px; }

  .gu-footer li a,
  .gu-visit__rows li a {
    display: inline-flex; align-items: center;
    min-height: 44px;
  }
  .gu-footer ul { gap: 2px; }
  .gu-footer__grid { gap: var(--space-3) var(--space-4); }

  /* Service rows are the main booking path on a phone.
     The press state is a FULL inversion — background AND text together. A
     background-only change once left ink text on an ink row (1.04:1) at the
     exact moment the reader was confirming which service they were tapping. */
  .gu-service { padding-block: 20px; }
  .gu-service:active { background: var(--ink); color: #fff; border-radius: 14px; }
  .gu-service:active .gu-service__desc,
  .gu-service:active .gu-service__meta { color: rgba(255,255,255,0.7); }
  .gu-barber:active { transform: scale(0.985); }
  .btn:active { transform: scale(0.96); }

  /* --- legibility --------------------------------------------------------- */
  .gu-product__tag { font-size: 10px; padding: 6px 12px; }
  .gu-service__meta { font-size: 10px; letter-spacing: 0.14em; }

  /* The bubble floats over the footer's bottom-right corner. */
  .gu-footer { padding-bottom: calc(84px + env(safe-area-inset-bottom)); }
}

/* Very small phones (SE and down): the header is the tightest row. */
@media (max-width: 380px) {
  .gu-header { padding-inline: 14px; }
  .gu-header__name { font-size: 13px; }
}

/* ---------- scroll reveals ---------- */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity 560ms var(--ease), transform 560ms var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ---------- shop page ---------- */
.gu-pagehead { padding-top: clamp(120px, 16vh, 190px); }
.gu-pagehead h1 {
  font-family: var(--font-display); font-weight: 500; text-transform: uppercase;
  font-size: clamp(52px, 12vw, 150px); line-height: 0.9; letter-spacing: 0.02em; margin: 0;
}
.gu-note {
  border: 1px solid var(--line-soft); border-radius: var(--radius-card);
  background: var(--paper);
  box-shadow: var(--shadow-card);
  padding: 20px 22px;
  display: flex; gap: 16px; align-items: flex-start;
  font-size: 14px; color: var(--ink-2);
}
.gu-note strong { color: var(--ink); font-weight: 600; }


/* ==========================================================================
   SCROLL-FILM IN THE BUBBLE  →  sections/film-hero.liquid
   --------------------------------------------------------------------------
   The v6 film is back at the client's word, re-cut to three legs (the
   interior "middle picture" is gone — storefront, door, mark). The vendored
   engine (assets/scroll-film.js) is UNTOUCHED; everything bubble-shaped
   happens here:

   - The engine pins position:fixed full-viewport layers. Instead of fighting
     that, .sw-stage and .sw-copylayer are CLIPPED to the site's inset block
     radius — a fixed layer wearing a rounded inset clip IS a pinned bubble.
   - The engine's own backdrop (.sw-sky) is hidden entirely, so the greige
     page ground shows around the clipped film — the same surface every other
     bubble sits on.
   - Engine chrome we replace or don't want (topbar, hint, particles, route
     rail, progress bar) is display:none.
   - The engine injects its stylesheet inside @layer sw at mount time; these
     UNLAYERED rules beat it regardless of order. Tokens are re-declared ON
     .sw-root because custom properties on the element beat inherited ones.

   .film-over (toggled by film-config.js) retires the fixed layers once the
   film scrolls past — without it the mark and copy sit fixed on top of the
   services band below. Reversible by scrolling back up.
   ========================================================================== */
.sw-root {
  --sw-bg:        #1D1A17;
  --sw-ink:       #FFFFFF;
  --sw-ink-soft:  rgba(255,255,255,0.6);
  --sw-accent:    #FFFFFF;
  --sw-font-display: 'Oswald', 'Arial Narrow', sans-serif;
  --sw-font-body: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;
}

/* THE BUBBLE IS THE STAGE'S OWN BOX, not a clip over a full-viewport one.
   A clip-path windowed the full-screen video and CROPPED THE FRAME'S TOP —
   the client's sign board vanished under the header inset. Insetting the
   fixed stage itself makes object-fit:cover compose the film INSIDE the
   bubble, so the whole frame shows (the 16:9 loses a sliver of the sides,
   never the sign). The copylayer wears the same box so copy and scrims are
   bubble-relative. */
.sw-root .sw-stage,
.sw-root .sw-copylayer {
  inset: calc(64px + clamp(10px, 1.6vw, 22px))
         var(--gutter)
         clamp(8px, 1.6vw, 26px);
  border-radius: var(--radius-block);
  overflow: hidden;
}
@media (max-width: 560px) {
  .sw-root .sw-stage,
  .sw-root .sw-copylayer {
    inset: 74px 10px 10px;
    border-radius: 22px;
  }
}
/* the film is dark; the stage behind the video crop should be too, so the
   bubble never flashes greige between poster and first frame */
.sw-root .sw-stage { background: var(--sw-bg); }

/* chrome the site replaces or the bubble has no room for */
.sw-root .sw-topbar,
.sw-root .sw-hint,
.sw-root .sw-particles,
.sw-root .sw-sky,
.sw-root .sw-route,
.sw-root .sw-scrollbar { display: none !important; }

/* retire the fixed layers once the film has scrolled past */
.sw-root .sw-stage,
.sw-root .sw-copylayer {
  transition: opacity 220ms var(--ease), visibility 0s linear 0s;
}
.sw-root.film-over .sw-stage,
.sw-root.film-over .sw-copylayer {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 220ms var(--ease), visibility 0s linear 220ms;
}

/* the first scene is the title card — suppress the orphaned "01 / 03" */
.sw-root .sw-copy:first-of-type .sw-copy__num { display: none; }

/* Copy legibility over the film: the dusk grade does most of it, but white
   type still wants a left scrim on desktop and a bottom scrim on phones. */
.sw-root .sw-copylayer::before {
  width: min(70vw, 900px);
  background: linear-gradient(90deg,
    rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.78) 30%,
    rgba(0,0,0,0.42) 58%, rgba(0,0,0,0) 100%);
}
@media (max-width: 860px) {
  .sw-root .sw-copylayer::before {
    width: 100%; height: 68%; top: auto; bottom: 0;
    background: linear-gradient(0deg,
      rgba(0,0,0,0.94) 6%, rgba(0,0,0,0.72) 38%,
      rgba(0,0,0,0.28) 66%, rgba(0,0,0,0) 100%);
  }
}

/* The copy anchors to the bubble's BOTTOM, not its centre. Centred, the
   tall title-card block overflowed short bubbles and the overflow:hidden
   radius clipped "CUTS." at the waist (client screenshot). The engine only
   writes inline opacity + a small translateY drift, never top/bottom, so a
   bottom anchor coexists with its animation. The title also scales by
   HEIGHT so three stacked words + eyebrow + CTA always fit. */
.sw-root .sw-copy {
  top: auto;
  bottom: clamp(28px, 6vh, 64px);
}
.sw-root .sw-copy__num {
  font-family: var(--sw-font-body); font-size: 10px; font-weight: 600;
  letter-spacing: 0.26em; color: rgba(255,255,255,0.34);
}
.sw-root .sw-copy__eyebrow {
  font-family: var(--sw-font-body); font-weight: 600; font-size: 10px;
  letter-spacing: 0.3em; color: rgba(255,255,255,0.66); margin-top: 16px;
}
.sw-root .sw-copy__title {
  font-family: var(--sw-font-display); font-weight: 500; text-transform: uppercase;
  font-size: clamp(1.9rem, min(5.2vw, 6.5vh), 4.4rem); line-height: 0.95; letter-spacing: 0.02em;
  margin-top: 14px; text-shadow: 0 6px 40px rgba(0,0,0,0.6);
}
.sw-root .sw-copy__body {
  color: rgba(255,255,255,0.74);
  text-shadow: 0 2px 20px rgba(0,0,0,0.7);
}

.sw-root .sw-btn {
  border-radius: var(--radius-pill); font-family: var(--sw-font-display);
  font-weight: 500; font-size: 15px; letter-spacing: 0.14em; text-transform: uppercase;
  min-height: 52px; padding: 0 34px;
  display: inline-flex; align-items: center;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              transform 320ms var(--spring), box-shadow 320ms var(--spring);
  -webkit-tap-highlight-color: transparent;
}
.sw-root .sw-btn--primary { background: #fff; color: var(--ink); }
.sw-root .sw-btn--ghost {
  background: rgba(255,255,255,0.13); color: #fff;
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.32),
              inset 0 1px 0 rgba(255,255,255,0.34),
              inset 0 -1px 0 rgba(29,26,23,0.2);
  border: 0;
}
@media (hover: hover) {
  .sw-root .sw-btn--ghost:hover { transform: translateY(-2px); background: #fff; color: var(--ink); }
  .sw-root .sw-btn--primary:hover { transform: translateY(-2px); }
}
.sw-root .sw-btn:active { transform: scale(0.96); transition-duration: 90ms; }

/* visually-hidden utility — the film's headings are the engine's h2s, so the
   page's h1 rides along unseen for structure and search */
.gu-vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
