/* ============================================================
   barburs on the web — foundations

   /app is the iOS app. Everything else is this: a dark, hairline-ruled
   site in the Vercel idiom — near-black ground, 1px borders doing the
   work shadows used to, one accent, and Geist, which is the typeface
   that idiom is written in and is open-licensed, so it can simply be
   served.

   Three files, in cascade order:
     base.css    tokens, reset, type, nav, footer, buttons, imagery
     site.css    the marketing pages
     browse.css  the directory, the feed, a shop's page
   ============================================================ */

:root {
  /* ---- ground and rules ----
     Vercel's dark scale almost exactly. #000 is the page; the cards sit
     one step up from it, which is the whole reason a border is enough. */
  --bg: #000;
  --bg-1: #0a0a0a;
  --bg-2: #111;
  --bg-3: #161616;
  --line: #1f1f1f;
  --line-2: #2a2a2a;
  --line-3: #3a3a3a;

  /* ---- ink ---- */
  --fg: #ededed;
  --fg-2: #a1a1a1;
  --fg-3: #7d7d7d;
  --fg-4: #545454;

  /* ---- the one colour that is barburs's and not the idiom's ----
     bone, the app's button and badge colour. Everything else here is
     greyscale, so this is the only place the eye is told to go. */
  --bone: #ede4d3;
  --bone-dim: #b9b0a0;

  /* ---- metrics ---- */
  --r: 8px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-xl: 20px;
  --nav-h: 64px;
  --page: 1200px;
  --gut: 24px;

  --sans: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* ---- liquid glass ----
     Copied value for value out of the app, so a control on the web and
     the same control in the app are made of the same material. The
     sheen is what separates liquid from merely frosted: a bright top
     edge and a highlight falling away from it, over the blur. */
  --glass-bg: rgba(16, 16, 16, .92);
  --glass-blur: blur(34px) saturate(180%);
  --glass-line: rgba(255, 255, 255, .13);
  --glass-inset:
    inset 0 1px 0 rgba(255, 255, 255, .26),
    inset 0 -1px 0 rgba(0, 0, 0, .34),
    inset 0 -10px 20px -12px rgba(0, 0, 0, .5);
  --glass-drop: 0 2px 8px rgba(0, 0, 0, .40), 0 16px 44px rgba(0, 0, 0, .55);
  --sheen:
    linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, .02) 38%, rgba(255, 255, 255, 0) 62%),
    radial-gradient(120% 70% at 50% -20%, rgba(255, 255, 255, .10), transparent 60%);
  --sheen-lit: linear-gradient(180deg, rgba(255, 255, 255, .5), rgba(255, 255, 255, 0) 46%, rgba(0, 0, 0, .07));
  --sheet-bg: rgba(14, 14, 14, .95);

  color-scheme: dark;
}

@media (max-width: 640px) { :root { --gut: 18px; } }

/* ============================================================
   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(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* the one rule that makes a 390px phone behave: nothing may be wider
     than the window, however long a word or wide a grid child */
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
h1, h2, h3, h4, p, figure, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, select { font: inherit; color: inherit; }
a { color: inherit; }

:focus-visible { outline: 2px solid var(--bone); outline-offset: 2px; border-radius: 4px; }

::selection { background: rgba(237, 228, 211, .22); }

/* ============================================================
   Type

   Two scales. Display is tight and heavy and only ever appears at the
   top of a page or a section; body is Geist at its normal weight. The
   mono face is reserved for labels, prices, codes and counts — things
   that are data rather than prose.
   ============================================================ */

.h1, h1 {
  font-size: clamp(38px, 6.2vw, 76px);
  line-height: 1.02;
  letter-spacing: -.04em;
  font-weight: 600;
}
.h2, h2 {
  font-size: clamp(28px, 4vw, 46px);
  line-height: 1.08;
  letter-spacing: -.035em;
  font-weight: 600;
}
.h3, h3 {
  font-size: clamp(19px, 1.6vw, 22px);
  line-height: 1.25;
  letter-spacing: -.02em;
  font-weight: 600;
}

/* White at the top fading to grey at the baseline. The single most
   recognisable thing about this idiom, and it costs three lines. */
.grad {
  background: linear-gradient(180deg, #fff 28%, #8f8f8f);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  /* a descender clipped by the text box is the usual cost of this trick */
  padding-bottom: .08em;
}

.lede {
  font-size: clamp(16px, 1.35vw, 18.5px);
  line-height: 1.6;
  color: var(--fg-2);
  max-width: 58ch;
}

.fine { font-size: 13.5px; line-height: 1.5; color: var(--fg-3); }

/* the mono label above a heading */
.eyebrow {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--fg-3);
}

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ============================================================
   Layout
   ============================================================ */

.wrap { max-width: var(--page); margin-inline: auto; padding-inline: var(--gut); }
.wrap-narrow { max-width: 760px; margin-inline: auto; padding-inline: var(--gut); }

/* Every section is ruled off from the one above it. That hairline is
   the page's only structure — there are no boxes around sections and no
   alternating backgrounds, because at this contrast one line is louder
   than either. */
.sec { padding-block: clamp(56px, 8vw, 104px); border-top: 1px solid var(--line); }
.sec:first-of-type { border-top: 0; }
.sec-head { max-width: 680px; }
.sec-head .eyebrow + h2 { margin-top: 14px; }
.sec-head h2 + .lede { margin-top: 16px; }

/* ============================================================
   Buttons

   Three: a bone primary, an outlined secondary, and a quiet one. All the
   same height, all 8px, none with a shadow.
   ============================================================ */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding-inline: 20px;
  border-radius: var(--r);
  font-size: 15px; font-weight: 500; letter-spacing: -.01em;
  text-decoration: none; white-space: nowrap;
  border: 1px solid transparent;
  transition: background .15s, border-color .15s, color .15s, opacity .15s;
}
.btn svg { width: 16px; height: 16px; }

/* White, not bone. Bone is kept for the things that quote the app —
   the verified badge, the rating star, the drawn slot grid — and
   anything you actually press is white, which on a black page is the
   loudest a control can be. */
.btn-primary { background: #fff; color: #0a0a0a; font-weight: 600; }
.btn-primary:hover { background: #d9d9d9; }

.btn-ghost { border-color: var(--line-2); color: var(--fg); background: var(--bg); }
.btn-ghost:hover { border-color: var(--line-3); background: var(--bg-2); }

.btn-quiet { color: var(--fg-2); padding-inline: 12px; }
.btn-quiet:hover { color: var(--fg); background: var(--bg-2); }

.btn-sm { height: 36px; padding-inline: 14px; font-size: 14px; border-radius: var(--r); }
.btn-lg { height: 50px; padding-inline: 26px; font-size: 16px; }

.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }

/* A grid used to carry its own padding-block, and the button under it
   lived in that air. The browse screens needed that padding gone, so
   on the homepage every "Browse the directory" ended up sitting
   directly on the cards above it. The space belongs to whichever of
   the two is underneath. */
.dir-grid + .btn-row,
.clip-grid + .btn-row,
.bento + .btn-row,
.facts + .btn-row,
.steps + .btn-row { margin-top: clamp(28px, 3.4vw, 42px); }

/* an inline link that announces itself as one */
.link {
  color: var(--fg); text-decoration: none;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 15px; font-weight: 500;
}
.link svg { width: 14px; height: 14px; transition: transform .15s; }
.link:hover { color: #fff; }
.link:hover svg { transform: translateX(2px); }

/* ============================================================
   Small pieces
   ============================================================ */

/* the pill above a hero — a mono label in a bordered capsule */
.pill {
  display: inline-flex; align-items: center; gap: 8px;
  height: 30px; padding-inline: 12px;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--bg-1);
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--fg-2); text-decoration: none;
}
.pill b { color: var(--fg); font-weight: 500; }

/* the verified tick, in the app's cream — matched to it on purpose, so
   the badge a shop sees on the web is the badge it has in the app */
/* The hero's search. Same furniture as the directory's bar, because
   it is the same search -- it just happens one page earlier. */
.herofind {
  display: flex; align-items: center; gap: 12px;
  width: min(620px, 100%); margin: 30px auto 0;
  padding: 7px 7px 7px 20px; border-radius: 999px;
  background: var(--bg-2); border: 1px solid var(--line-2);
  transition: border-color .15s, box-shadow .15s;
}
/* the focus ring belongs to the bar, not the input inside it */
.herofind:focus-within {
  border-color: var(--line-3);
  box-shadow: 0 0 0 4px rgba(237, 228, 211, .07);
}
.herofind svg { width: 19px; height: 19px; flex: none; color: var(--fg-3); }
.herofind input {
  flex: 1 1 auto; min-width: 0; border: 0; background: none; outline: none;
  color: var(--fg-1); font: inherit; font-size: 16.5px;
  padding-block: 13px; text-align: left;
}
.herofind input::placeholder { color: var(--fg-3); }
.herofind input::-webkit-search-cancel-button { -webkit-appearance: none; }
.herofind .btn { flex: none; height: 46px; padding-inline: 24px; font-size: 15px; }
.herofind-or { margin-top: 16px; font-size: 14px; }
.herofind-or a { color: var(--fg-3); text-underline-offset: 4px; }
.herofind-or a:hover { color: var(--fg-1); }
/* the cities sit under the search, where "where?" belongs */
.hero-in .cityrail {
  margin: 18px auto 0; justify-content: safe center;
  padding-inline: 2px;
}

.verified {
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px; padding-inline: 8px; border-radius: 999px;
  background: linear-gradient(180deg, #f6efe2, #ddd0b8);
  color: #0a0a0a; font-size: 11.5px; font-weight: 600; letter-spacing: -.005em;
}
.verified svg { width: 13px; height: 13px; }

/* the same tick on its own, for the places that name a shop in passing
   rather than giving it a badge — a barber's card, a barber's page */
.tick { display: inline-flex; align-items: center; color: #ddd0b8; }
.tick svg { width: 13px; height: 13px; }

/* "Owner at Smithdown Cuts", with the shop's tick on it and a link to
   the shop. A role and a destination, where a credential used to be. */
.tag-at { gap: 6px; text-decoration: none; }
.tag-at:hover { border-color: var(--line-1); color: var(--fg); }

.tag {
  display: inline-flex; align-items: center; height: 24px; padding-inline: 9px;
  border: 1px solid var(--line-2); border-radius: 6px;
  font-size: 12px; color: var(--fg-2); white-space: nowrap;
}

.card {
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}

/* ---- the glass surface, as the app builds it ----
   The ::after is the whole trick: the blur alone reads as frosted, and
   it is the specular over the top that makes it read as liquid. */
.glass {
  position: relative;
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-line);
  box-shadow: var(--glass-inset), var(--glass-drop);
}
.glass::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; background: var(--sheen);
}
/* without backdrop blur the tint alone has to carry it */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root { --glass-bg: rgba(16, 16, 20, .94); }
}

/* a filled control gets the specular keyed for a light surface */
.btn-primary { position: relative; overflow: hidden; }
.btn-primary::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; background: var(--sheen-lit);
}
.btn-ghost { position: relative; overflow: hidden; }
.btn-ghost::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; background: var(--sheen);
}

/* ============================================================
   Backdrops

   Two, both decorative, both pointer-events:none. The grid is the one
   that makes a black page read as a surface rather than as nothing.
   ============================================================ */

.grid-bg {
  position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, .055) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, .055) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(120% 86% at 50% 0%, #000 12%, transparent 72%);
  mask-image: radial-gradient(120% 86% at 50% 0%, #000 12%, transparent 72%);
}

.glow {
  position: absolute; pointer-events: none; z-index: 0;
  border-radius: 50%; filter: blur(90px); opacity: .5;
}

/* ============================================================
   Nav
   ============================================================ */

.nav {
  position: sticky; top: 0; z-index: 50;
  height: var(--nav-h);
  background: rgba(0, 0, 0, .72);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--line);
}
.nav-in {
  max-width: var(--page); height: 100%; margin-inline: auto;
  padding-inline: var(--gut);
  display: flex; align-items: center; gap: 8px;
}
.nav-logo {
  display: flex; align-items: center; gap: 9px;
  text-decoration: none; margin-right: 18px; flex: none;
}
.nav-logo b {
  font-size: 17px; font-weight: 600; letter-spacing: -.035em;
}
.nav-links { display: flex; align-items: center; gap: 2px; margin-right: auto; }
.nav-links a {
  padding: 7px 11px; border-radius: 6px;
  font-size: 14px; font-weight: 400; color: var(--fg-2); text-decoration: none;
  transition: color .15s, background .15s;
}
.nav-links a:hover { color: var(--fg); background: var(--bg-2); }
.nav-links a[aria-current="page"] { color: var(--fg); }

/* The links are a horizontal scroller under 760px rather than a menu
   behind a button. Four links do not earn a drawer, and a drawer needs
   script that this site otherwise does not need at all. */
@media (max-width: 760px) {
  :root { --nav-h: 56px; }
  .nav-in { gap: 6px; padding-inline: 12px; }
  .nav-logo { margin-right: 8px; margin-left: 6px; }
  .nav-links {
    overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
    -webkit-mask-image: linear-gradient(90deg, #000 86%, transparent);
    mask-image: linear-gradient(90deg, #000 86%, transparent);
  }
  .nav-links::-webkit-scrollbar { display: none; }
  .nav-links a { padding: 7px 9px; font-size: 13.5px; white-space: nowrap; }
  .nav .btn { flex: none; }
}
@media (max-width: 420px) {
  .nav-logo b { font-size: 16px; }
  .nav .btn-sm { padding-inline: 11px; font-size: 13px; }
}

/* ============================================================
   Footer
   ============================================================ */

/* One footer on every page, a browse screen included — those had
   nothing under the grid at all. A box inside the gutter rather than a
   full-width band: it closes the page off without reading as another
   piece of chrome, and it sits the same on a screen and on a document. */
.foot { padding-block: clamp(40px, 5vw, 72px) clamp(28px, 3vw, 44px); }
/* the app's material, at the end of the page — the sheen as a
   background layer rather than an ::after, so nothing inside has to be
   raised above an overlay */
.footbox {
  border-radius: var(--r-xl);
  border: 1px solid var(--glass-line);
  background: var(--sheen), var(--glass-bg);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-inset), var(--glass-drop);
  padding: clamp(22px, 2.8vw, 30px);
}
.footbox-end { border-top-color: var(--glass-line); }
.footbox-top {
  display: flex; align-items: flex-start; gap: 24px 32px; flex-wrap: wrap;
}
.footbox-brand b {
  display: block; font-size: 16px; font-weight: 600; letter-spacing: -.03em;
}
.footbox-brand span {
  display: block; margin-top: 6px; font-size: 13.5px; color: var(--fg-3); max-width: 34ch;
}
.footbox-links {
  display: flex; flex-wrap: wrap; gap: 8px 22px; margin-left: auto; padding-top: 2px;
}
.footbox-links a { font-size: 14px; color: var(--fg-2); text-decoration: none; }
.footbox-links a:hover { color: var(--fg); }

.footbox-end {
  margin-top: clamp(20px, 2.4vw, 26px); padding-top: 18px;
  border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 20px;
  font-size: 13px; color: var(--fg-4);
}
.footbox-legal { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-left: auto; }
.footbox-legal a { font-size: 13px; color: var(--fg-4); text-decoration: none; }
.footbox-legal a:hover { color: var(--fg-2); }

@media (max-width: 640px) {
  .footbox-links { margin-left: 0; }
  .footbox-legal { margin-left: 0; }
}

/* on a phone the tab bar is under this, so the box needs to clear it */
body.app .foot { padding-bottom: clamp(28px, 3vw, 44px); }

/* ============================================================
   Product imagery

   The app has no photographs. Every "photo" in it is four CSS layers
   over a three-colour scene: a key light behind the head, a fill from
   the lower left, a wall wash, and grain over the top.

   The same markup is used here, which matters more than it sounds. A
   page selling "see the cut before you book it" that shows no cuts is
   arguing with itself. These are not screenshots of the product — they
   are the product's own markup, drawn the way the product draws it.
   ============================================================ */

.clip {
  position: relative; overflow: hidden; background: #07070a;
  --c1: #2a2118; --c2: #0d0c12; --c3: #6b5536;
  isolation: isolate;
}
.clip-bg {
  position: absolute; inset: -14%;
  animation-delay: calc(var(--d, 0s) * -19);
  background:
    radial-gradient(54% 37% at var(--lx, 20%) var(--ly, 24%), rgba(255, 255, 255, .42), transparent 76%),
    radial-gradient(98% 64% at 14% 96%, var(--c1), transparent 84%),
    radial-gradient(135% 42% at 50% -4%, var(--c3), transparent 76%),
    linear-gradient(176deg, var(--c1) 0%, var(--c2) 54%, var(--c1) 100%);
  transform: scale(1.06);
  animation: drift 19s ease-in-out infinite alternate;
}
@keyframes drift {
  0%   { transform: scale(1.06) translate3d(0, 0, 0); }
  100% { transform: scale(1.14) translate3d(-2.4%, -1.8%, 0); }
}
.clip-sweep {
  position: absolute; inset: 0;
  background: linear-gradient(104deg, transparent 34%, rgba(255, 255, 255, .17) 50%, transparent 66%);
  animation: sweep 7.5s ease-in-out infinite;
}
@keyframes sweep {
  0%        { transform: translateX(-62%); }
  55%, 100% { transform: translateX(62%); }
}
/* The shop's own photograph, over the drawn scene rather than
   instead of it: if the reference has expired or the Worker has no
   key, the img fails and the nameplate underneath is what shows --
   which is what the card looked like before photographs existed. */
.clip-photo {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; object-fit: cover;
}

.clip-grain {
  position: absolute; inset: 0; opacity: .28; mix-blend-mode: overlay; pointer-events: none;
  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' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}
.clip-vig {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(112% 76% at 50% 42%, transparent 52%, rgba(0, 0, 0, .62));
}

/* The scenes, lifted from the app's own palette -- which is grey
   now. A scene carries a weight, not a hue: how dark this shop's
   frontage is and nothing more. */
.sc-tungsten  { --c1:hsl(30 3% 14%); --c2:hsl(30 3% 5%); --c3:hsl(30 4% 27%); }
.sc-ember     { --c1:hsl(30 3% 15%); --c2:hsl(30 3% 5%); --c3:hsl(30 4% 29%); }
.sc-steel     { --c1:hsl(30 3% 12%); --c2:hsl(30 3% 4%); --c3:hsl(30 4% 23%); }
.sc-chrome    { --c1:hsl(30 3% 16%); --c2:hsl(30 3% 5%); --c3:hsl(30 4% 30%); }
.sc-slate     { --c1:hsl(30 3% 11%); --c2:hsl(30 3% 4%); --c3:hsl(30 4% 21%); }
.sc-indigo    { --c1:hsl(30 3% 11%); --c2:hsl(30 3% 3%); --c3:hsl(30 4% 20%); }
.sc-plum      { --c1:hsl(30 3% 14%); --c2:hsl(30 3% 5%); --c3:hsl(30 4% 26%); }
.sc-champagne { --c1:hsl(30 3% 17%); --c2:hsl(30 3% 6%); --c3:hsl(30 4% 32%); }
.sc-moss      { --c1:hsl(30 3% 12%); --c2:hsl(30 3% 4%); --c3:hsl(30 4% 24%); }
.sc-rose      { --c1:hsl(30 3% 15%); --c2:hsl(30 3% 5%); --c3:hsl(30 4% 28%); }
.sc-mint      { --c1:hsl(30 3% 13%); --c2:hsl(30 3% 4%); --c3:hsl(30 4% 22%); }

/* ---- the nameplate on a shop's first frame ----

   No shop has a photograph yet, so a directory of them was a grid of
   anonymous gradients. The lead frame carries the shop's name instead,
   which makes it a cover rather than a missing image.

   It is sized in cqw, not vw: the same plate is drawn at 340px in a
   card, at 700px as a gallery's lead, and the type has to hold its
   proportion to the frame it is in rather than to the window. */
.clip { container-type: inline-size; }

.plate {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  /* the name sits on the floor of the picture, not across its middle */
  display: grid; align-content: end; justify-items: start; gap: 2.5cqw;
  padding: 7cqw; text-align: left;
  /* black where the words are, clear where the shop is */
  background: linear-gradient(to top,
    rgba(0, 0, 0, .82) 0%,
    rgba(0, 0, 0, .55) 28%,
    rgba(0, 0, 0, .12) 58%,
    transparent 82%);
}
/* A photograph of a shop front in daylight will swallow white text
   whatever the gradient does, so one with a picture under it gets a
   heavier floor than one with a drawn scene. */
.clip:has(.clip-photo) .plate {
  background: linear-gradient(to top,
    rgba(0, 0, 0, .92) 0%,
    rgba(0, 0, 0, .7) 30%,
    rgba(0, 0, 0, .22) 60%,
    transparent 84%);
}
.clip:has(.clip-photo) .plate b { text-shadow: 0 1px 14px rgba(0, 0, 0, .7); }
.plate b {
  font-size: clamp(13px, 7.4cqw, 34px);
  font-weight: 600; letter-spacing: -.035em; line-height: 1.05;
  text-wrap: balance; max-width: 16ch;
  color: #fff; text-shadow: 0 1px 14px rgba(0, 0, 0, .5);
}
/* the rule, drawn on the span so the plate stays two elements */
.plate span {
  position: relative; padding-top: 0;
  font-family: var(--mono); font-size: clamp(8px, 3cqw, 12px);
  letter-spacing: .14em; text-transform: uppercase;
  color: rgba(255, 255, 255, .72);
}
/* The rule was a centred hairline over a centred name. The name is
   ranged left on the floor now, so the rule has nothing to sit over
   and the gradient does the separating. */

/* Without container queries the plate would size itself off the window
   and come out enormous in a card and tiny in a gallery, so it falls
   back to fixed type instead. */
@supports not (container-type: inline-size) {
  .plate { gap: 6px; padding: 18px; }
  .plate b { font-size: 24px; }
  .plate span { padding-top: 14px; font-size: 10.5px; }
  .plate span::before { width: 30px; }
}

/* a monogram, used wherever a shop or barber has no picture — which is
   everywhere, because none of them has one */
.mono-av {
  display: grid; place-items: center; flex: none;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--bg-3); border: 1px solid var(--line-2);
  font-size: 12.5px; font-weight: 600; letter-spacing: -.01em; color: var(--fg-2);
}

@media (prefers-reduced-motion: reduce) {
  .clip-bg, .clip-sweep { animation: none; }
}

/* ============================================================
   Utilities
   ============================================================ */

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
[hidden] { display: none !important; }
