/* Refined Barber Lounge & Cafe — Variant A, "The Crest"
   Built from the only brand asset they own: the gold heraldic crest on black.
   Palette is measured, not invented (data/recon-photos.json > brand.colors).
   Zero external requests: system font stacks only, no CDN, no web fonts. */

:root {
  /* Ground — their logo ground is effectively pure black; lifted a hair so the
     gold hairlines have something to sit on. */
  --ink: #080807;
  --ink-2: #100F0D;
  --ink-3: #191713;

  /* Measured brand gold. Nothing brighter than #D4AF37 — it reads cheap beside
     the crest foil. */
  --gold: #bfa769;
  --gold-lift: #e8d9a8;
  --gold-deep: #675b43;

  /* Warm white sampled off the shop wall. */
  --cream: #e4e2d8;
  --cream-dim: #aba79a;

  --line: rgba(191, 167, 105, 0.3);
  --line-soft: rgba(191, 167, 105, 0.16);

  --display: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
    Georgia, "Times New Roman", serif;
  --body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;

  /* 1.25 modular scale, fluid at the display end. */
  --t--1: 0.875rem;
  --t-0: 1.0625rem;
  --t-1: 1.3rem;
  --t-2: 1.6rem;
  --t-3: clamp(1.75rem, 1.45rem + 1.3vw, 2.35rem);
  --t-h1: clamp(1.85rem, 1.15rem + 3vw, 3.25rem);

  --s-1: 0.5rem;
  --s-2: 1rem;
  --s-3: 1.75rem;
  --s-4: clamp(2.5rem, 5vw, 4rem);
  --s-5: clamp(4rem, 9vw, 7.5rem);

  --wrap: 66rem;
  --measure: 58ch;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  /* Semantic z-scale. */
  --z-sticky: 20;
  --z-skip: 40;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--cream);
  font: var(--t-0) / 1.7 var(--body);
  text-rendering: optimizeLegibility;
  padding-bottom: env(safe-area-inset-bottom);
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: var(--gold-lift);
  text-underline-offset: 0.22em;
  text-decoration-thickness: from-font;
}

a:hover {
  color: var(--cream);
}

:focus-visible {
  outline: 2px solid var(--gold-lift);
  outline-offset: 3px;
  border-radius: 2px;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: clamp(1.15rem, 4vw, 2.5rem);
}

.skip {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -120%);
  z-index: var(--z-skip);
  background: var(--gold);
  color: #0a0a0a;
  padding: 0.6rem 1.1rem;
  font: 600 var(--t--1) / 1 var(--body);
  text-decoration: none;
}

.skip:focus {
  transform: translate(-50%, 0);
}

/* ---------- Type ---------- */

h1,
h2,
h3 {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: -0.012em;
  line-height: 1.14;
  text-wrap: balance;
  margin: 0;
}

h1 {
  font-size: var(--t-h1);
  line-height: 1.06;
}

h2 {
  font-size: var(--t-3);
}

h3 {
  font-size: var(--t-1);
  line-height: 1.25;
}

p {
  margin: 0 0 var(--s-2);
  text-wrap: pretty;
}

p:last-child {
  margin-bottom: 0;
}

.lede {
  font-size: var(--t-1);
  line-height: 1.55;
  color: var(--cream);
}

.dim {
  color: var(--cream-dim);
}

.small {
  font-size: var(--t--1);
  line-height: 1.6;
}

/* The one label style in the system — used for the crest sub-line and table
   captions only, never as a per-section eyebrow. */
.gold {
  color: var(--gold);
}

/* Unresolved facts render visibly. This is the point: he can see exactly what
   is still owed before anything goes live. */
.tbd {
  background: rgba(191, 167, 105, 0.14);
  color: var(--gold-lift);
  border: 1px dashed var(--line);
  border-radius: 2px;
  padding: 0.05em 0.4em;
  font-family: var(--body);
  font-size: 0.9em;
  font-style: normal;
  white-space: nowrap;
}

/* ---------- The crest motifs ---------- */

/* Dot-and-circle border lifted off the roundel edge of their logo. */
.rule {
  height: 7px;
  margin: var(--s-4) auto;
  max-width: 22rem;
  background-image: radial-gradient(
    circle at center,
    var(--gold) 0 1.6px,
    transparent 1.7px
  );
  background-size: 13px 7px;
  background-repeat: repeat-x;
  background-position: center;
  opacity: 0.75;
}

.rule--tight {
  margin: var(--s-3) auto;
  max-width: 12rem;
}

.hair {
  border: 0;
  border-top: 1px solid var(--line-soft);
  margin: var(--s-4) 0;
}

.crest {
  display: block;
  width: clamp(40px, 3.6vw + 20px, 76px);
  height: auto;
  grid-row: 1 / 3;
  align-self: center;
}

/* ---------- Header ---------- */

/* The masthead paint is deliberately translucent: body::before already lays the
   crest damask across the whole page, and the old opaque gradient was covering it
   up, leaving the header as the one band on the site with no material in it.
   The radial is a pool of light behind the crest, not a texture of its own. */
.masthead {
  border-bottom: 1px solid var(--line-soft);
  background:
    radial-gradient(120% 150% at 50% 0%, rgba(191, 167, 105, 0.06), rgba(191, 167, 105, 0) 62%),
    linear-gradient(180deg, rgba(1, 1, 1, 0.92), rgba(8, 8, 7, 0.86));
  padding-block: clamp(0.85rem, 2.2vw, 1.5rem) 0;
  text-align: center;
}

.brand {
  display: inline-grid;
  grid-template-columns: auto auto;
  align-items: center;
  column-gap: clamp(0.7rem, 1.5vw, 1.15rem);
  text-align: left;
  text-decoration: none;
  color: inherit;
}

.brand__name {
  display: block;
  margin: 0 -0.1em 0 0;      /* trailing letter-space compensation */
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.35rem, 0.95rem + 1.55vw, 2.35rem);
  line-height: 1.04;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold);
}

.brand__sub {
  display: block;
  margin: 0.42em -0.28em 0 0; /* tracking tuned so this line matches .brand__name's width */
  font-size: clamp(0.6rem, 0.42rem + 0.4vw, 0.78rem);
  line-height: 1.15;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--cream-dim);
}

/* The hairline is the ornament, and it earns its place: it is the only element
   that spans the full wrap, so it converts the dead horizontal band into
   structure and separates identity from navigation. No extra DOM. */
.nav {
  margin-top: clamp(0.85rem, 2vw, 1.35rem);
  border-top: 1px solid var(--line-soft);
}

.nav ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 clamp(1.5rem, 5vw, 3.25rem);
  margin: 0;
  padding: 0;
}

.nav a {
  display: inline-flex;
  align-items: center;
  min-height: 46px;
  padding: 0.4rem 0.15rem;
  color: var(--cream);
  text-decoration: none;
  font-size: clamp(0.76rem, 0.62rem + 0.35vw, 0.85rem);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  border-bottom: 1px solid transparent;
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease);
}

.nav a:hover {
  color: var(--gold-lift);
  border-bottom-color: var(--line);
}

.nav a[aria-current="page"] {
  color: var(--gold);
  border-bottom-color: var(--gold);
}

/* The QR code lands on a phone with 812px of screen. The stacked crest lockup
   ate 209px of that and pushed the hero's Call CTA under the sticky action
   bar, where it was 100% invisible. On phones only, lay the masthead out as a
   row so the address, hours and both CTAs clear the bar without scrolling.
   Desktop runs the same horizontal lockup, scaled up and centred. */
@media (max-width: 47.99rem) {
  .masthead {
    padding-block: 0.55rem 0;
    text-align: left;
  }

  .masthead > .wrap {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-2);
  }

  .crest {
    width: 40px;
  }

  /* At 40px on a 1dppx screen the 2-unit dots land on 1.25 device px and the
     rings go mushy. Thicken the strokes here so the markup stays identical on
     all five pages. */
  .crest__dots {
    stroke-width: 3;
    stroke-dasharray: 0.01 7.54;
  }

  .crest__edge,
  .crest__ring {
    stroke-width: 1.3;
  }

  .brand {
    column-gap: 0.62rem;
  }

  .brand__name {
    font-size: 1.16rem;
    line-height: 1.1;
    letter-spacing: 0.11em;
    margin-right: -0.11em;
  }

  .brand__sub {
    font-size: 0.58rem;
    letter-spacing: 0.2em;
    margin-right: -0.2em;
    margin-top: 0.34em;
  }

  .nav {
    margin-top: 0;
    border-top: 0;
  }

  .nav ul {
    gap: 0 clamp(0.75rem, 3vw, 2.1rem);
  }

  .nav a {
    min-height: 44px;
    font-size: 0.8rem;
    letter-spacing: 0.14em;
  }

  .hero {
    padding-block: var(--s-3) var(--s-4);
  }
}

/* ---------- Sections ---------- */

main {
  display: block;
}

section {
  padding-block: var(--s-5);
}

section + section {
  padding-top: 0;
}

.center {
  text-align: center;
}

.prose {
  max-width: var(--measure);
  margin-inline: auto;
}

.prose--wide {
  max-width: 72ch;
}

.stack > * + * {
  margin-top: var(--s-2);
}

/* ---------- Hero ---------- */

.hero {
  padding-block: clamp(2.75rem, 7vw, 5.5rem) var(--s-4);
  text-align: center;
}

.hero__grid {
  display: grid;
  gap: var(--s-4);
  align-items: center;
}

@media (min-width: 62rem) {
  .hero__grid {
    grid-template-columns: 1.05fr 0.95fr;
    text-align: left;
    gap: clamp(2.5rem, 5vw, 4.5rem);
  }

  .hero .rule {
    margin-inline: 0;
  }
}

.hero h1 {
  margin-bottom: var(--s-2);
}

.hero__where {
  font-family: var(--display);
  font-size: var(--t-1);
  color: var(--gold);
  margin-bottom: 0.35rem;
}

.hero__when {
  color: var(--cream-dim);
  margin-bottom: var(--s-3);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  justify-content: center;
}

@media (min-width: 62rem) {
  .actions {
    justify-content: flex-start;
  }

  /* ponytail: a centred wrap centres its buttons. Above 62rem the rule above
     left-aligns every .actions row, which is right for the two-column heroes
     (copy beside a photo) and wrong for the centred ones — the buttons pinned
     61px left of the heading. Fixing it here retires seven inline
     justify-content patches that were papering over this one rule. */
  .center .actions {
    justify-content: center;
  }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0.75rem 1.6rem;
  border: 1px solid var(--gold);
  background: var(--gold);
  color: #0a0a0a;
  font: 600 var(--t--1) / 1 var(--body);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease),
    transform 0.25s var(--ease);
}

.btn:hover {
  background: var(--gold-lift);
  border-color: var(--gold-lift);
  color: #0a0a0a;
  transform: translateY(-2px);
}

.btn:active {
  transform: translateY(0);
}

.btn .tbd {
  margin-left: 0.5em;
  letter-spacing: 0;
  text-transform: none;
}

.btn--ghost {
  background: transparent;
  color: var(--gold);
}

.btn--ghost:hover {
  background: rgba(191, 167, 105, 0.12);
  color: var(--gold-lift);
}

/* ---------- Framed photography ---------- */

.frame {
  position: relative;
  margin: 0;
  border: 1px solid var(--line);
  padding: 8px;
  background: var(--ink-2);
}

.frame::after {
  content: "";
  position: absolute;
  inset: 3px;
  border: 1px solid var(--line-soft);
  pointer-events: none;
}

.frame img {
  width: 100%;
  filter: saturate(0.94) contrast(1.03);
  transition: filter 0.4s var(--ease);
}

.frame:hover img {
  filter: saturate(1) contrast(1.06);
}

.frame figcaption {
  padding: 0.7rem 0.2rem 0.1rem;
  font-size: var(--t--1);
  line-height: 1.5;
  color: var(--cream-dim);
  text-align: center;
}

.frame--tall img {
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

.gallery {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(0.9rem, 2.5vw, 1.6rem);
}

/* ponytail: fixed 2 columns, not auto-fit. The one gallery on the site holds
   four photos; auto-fit packed three across and orphaned the fourth on its
   own row. Two columns gives a clean 2x2. */
@media (min-width: 34rem) {
  .gallery {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ---------- Pull quote ---------- */

.quote {
  max-width: 46ch;
  margin-inline: auto;
  text-align: center;
}

.quote blockquote {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.35rem, 1rem + 1.7vw, 2.1rem);
  line-height: 1.34;
  color: var(--cream);
  text-wrap: balance;
}

.quote cite {
  display: block;
  margin-top: var(--s-2);
  font-style: normal;
  font-size: var(--t--1);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
}

/* ---------- Tables: hours and menus ---------- */

.panel {
  border: 1px solid var(--line-soft);
  background: var(--ink-2);
  padding: clamp(1.25rem, 3.5vw, 2.25rem);
}

.table-scroll {
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t--1);
}

caption {
  caption-side: top;
  text-align: left;
  padding-bottom: 0.75rem;
  color: var(--cream-dim);
  font-size: var(--t--1);
}

th,
td {
  padding: 0.62rem 0.75rem;
  text-align: left;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}

thead th {
  color: var(--gold);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 0.76rem;
  white-space: nowrap;
}

tbody tr:last-child th,
tbody tr:last-child td {
  border-bottom: 0;
}

tbody th {
  font-weight: 400;
  color: var(--cream);
}

td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--gold-lift);
}

td.dur {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--cream-dim);
}

/* ---------- Two-up ---------- */

.duo {
  display: grid;
  gap: clamp(1.25rem, 3.5vw, 2.5rem);
}

@media (min-width: 48rem) {
  .duo {
    grid-template-columns: 1fr 1fr;
  }
}

.duo--photo {
  align-items: start;
}

/* ---------- Service list ---------- */

.services {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--line-soft);
}

.service {
  border-bottom: 1px solid var(--line-soft);
  padding-block: var(--s-3);
  display: grid;
  gap: 0.35rem 1.5rem;
}

@media (min-width: 48rem) {
  .service {
    grid-template-columns: 15rem 1fr;
    align-items: baseline;
  }
}

.service h3 {
  font-size: var(--t-1);
  color: var(--gold-lift);
  margin: 0;
}

.service p {
  margin: 0;
  color: var(--cream-dim);
  max-width: 62ch;
}

/* ---------- Barber sections ---------- */

.barber {
  padding-top: var(--s-4);
}

.barber__head {
  text-align: center;
}

.barber__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem 1.4rem;
  margin: var(--s-2) 0 var(--s-3);
  padding: 0;
  list-style: none;
  font-size: var(--t--1);
  color: var(--cream-dim);
}

.barber__meta b {
  color: var(--cream);
  font-weight: 600;
}

/* ---------- Booking routes ---------- */

/* Flex column so the two cards align structurally: the description is the only
   child that grows, the button is pushed to a shared bottom baseline, and the
   note rides with it. Works for any description length -- no matched heights.
   align-self: stretch is part of the fix, not decoration: shrink-to-fit made the
   two gold blocks 241px and 338px wide, which reads as misaligned on its own. */
.route {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  border: 1px solid var(--line-soft);
  background: var(--ink-2);
  padding: clamp(1.4rem, 4vw, 2.4rem);
  text-align: center;
}

.route > * {
  margin: 0;
}

.route > p:not(.route__note) {
  flex: 1 1 auto;
}

.route .btn {
  margin-top: auto;
  align-self: stretch;
}

.route__note {
  font-size: var(--t--1);
  color: var(--cream-dim);
}

/* Subgrid puts both buttons in one shared row track, so they also match in
   height across the 768-955px band where Darienne's longer label wraps. The
   flex rules above are the fallback and already share the bottom baseline.
   Scoped to the two sections that actually hold .route cards so it cannot
   touch .duo on the barbers, contact, services or cafe blocks.
   Row counts differ: book.html's cards carry a .route__note (4 rows), the
   home page's do not (3 rows). Without the matching count the shared button
   track is lost and the wrapped label lifts one button by 6px. */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 48rem) {
    #routes .duo { grid-template-rows: auto 1fr auto auto; }
    #routes .route { display: grid; grid-row: span 4; grid-template-rows: subgrid; }

    #barbers .duo { grid-template-rows: auto 1fr auto; }
    #barbers .route { display: grid; grid-row: span 3; grid-template-rows: subgrid; }

    #routes .route .btn,
    #barbers .route .btn { margin-top: 0; }
  }
}

/* ---------- Footer ---------- */

.foot {
  border-top: 1px solid var(--line-soft);
  background: #010101;
  padding-block: var(--s-4);
  text-align: center;
  margin-top: var(--s-5);
}

.foot__grid {
  display: grid;
  gap: var(--s-3);
  justify-items: center;
}

@media (min-width: 48rem) {
  .foot__grid {
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    align-items: start;
  }
}

.foot .foot__label {
  font-size: var(--t--1);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
  font-family: var(--body);
  font-weight: 600;
  line-height: 1.2;
  margin: 0 0 0.75rem;
}

.foot address {
  font-style: normal;
  line-height: 1.75;
}

.foot address a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.foot ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.foot li a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.foot a {
  color: var(--cream);
  text-decoration: none;
  border-bottom: 1px solid var(--line-soft);
}

.foot a:hover {
  color: var(--gold-lift);
  border-bottom-color: var(--gold);
}

.colophon {
  margin-top: var(--s-4);
  font-size: 0.78rem;
  color: #918c80;
}

/* ---------- Mobile action bar ----------
   A barbershop is a phone-first business. Two actions, always in reach. */

.bar {
  position: sticky;
  bottom: 0;
  z-index: var(--z-sticky);
  display: flex;
  gap: 1px;
  background: var(--line-soft);
  border-top: 1px solid var(--gold-deep);
  padding-bottom: env(safe-area-inset-bottom);
}

.bar a {
  flex: 1;
  min-height: 54px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0d0c0a;
  color: var(--gold);
  text-decoration: none;
  font: 600 var(--t--1) / 1 var(--body);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.bar a + a {
  background: var(--gold);
  color: #0a0a0a;
}

@media (min-width: 48rem) {
  .bar {
    display: none;
  }
}

/* ---------- Motion ----------
   One page-load reveal on the hero. Everything else is already visible; the
   animation only softens the arrival. */

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
}

.hero__copy > *,
.hero__art {
  animation: rise 0.7s var(--ease) both;
}

.hero__copy > *:nth-child(2) {
  animation-delay: 0.06s;
}

.hero__copy > *:nth-child(3) {
  animation-delay: 0.12s;
}

.hero__copy > *:nth-child(4) {
  animation-delay: 0.18s;
}

.hero__art {
  animation-delay: 0.1s;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0.001ms !important;
  }

  .btn:hover {
    transform: none;
  }
}

@media print {
  .bar,
  .nav,
  .skip {
    display: none;
  }

  body {
    background: #fff;
    color: #000;
  }
}

/* ---------- Generated atmosphere (site-assets/generated, gemini-3-pro-image) ----------
   Backgrounds, textures and light only. Nothing here depicts a person or a cut —
   every photo of the craft on this site is their own work. */

body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("assets/generated/a-tex-crest-border.jpg");
  background-size: 460px;
  opacity: .085;
}

.hero {
  background-image:
    linear-gradient(rgba(8, 8, 7, .88), rgba(8, 8, 7, .94)),
    url("assets/generated/a-bg-crest-vignette.jpg");
  background-size: cover;
  background-position: 50% 40%;
}

.foot {
  background-image:
    linear-gradient(rgba(1, 1, 1, .90), rgba(1, 1, 1, .95)),
    url("assets/generated/a-atm-gold-haze.jpg");
  background-size: cover;
  background-position: 50% 50%;
}

/* Service icons (src/icons.py). Inline SVG, currentColor. */
.svc-icon { display: block; width: 24px; height: 24px; color: var(--gold); margin: 0 0 .6rem; }

/* ---------- Textured bands ----------
   Rhythm between blocks. Generated atmosphere sits under a near-black wash so
   it reads as texture; it is never a photograph of this shop. Bands that carry
   no image are pure CSS — the gold-haze gradient is the fallback where the
   asset library came up short. */

.band {
  border-block: 1px solid var(--line-soft);
  background-color: var(--ink-2);
  background-size: cover;
  background-position: 50% 50%;
  background-repeat: no-repeat;
}

/* section + section zeroes top padding; a band needs its own box back. */
section + section.band,
section.band + section {
  padding-top: var(--s-5);
}

.band--lounge {
  background-image: linear-gradient(rgba(4, 4, 3, 0.955), rgba(4, 4, 3, 0.975)),
    url("assets/generated/a-int-waiting-area.jpg");
}

.band--chair {
  background-image: linear-gradient(rgba(4, 4, 3, 0.95), rgba(4, 4, 3, 0.975)),
    url("assets/generated/a-int-empty-chair.jpg");
}

.band--mirror {
  background-image: linear-gradient(rgba(4, 4, 3, 0.945), rgba(4, 4, 3, 0.97)),
    url("assets/generated/a-int-mirror-counter.jpg");
}

.band--tools {
  background-image: linear-gradient(rgba(4, 4, 3, 0.93), rgba(4, 4, 3, 0.965)),
    url("assets/generated/a-tool-brushes-combs.jpg");
}

.band--haze {
  background-image: linear-gradient(rgba(3, 3, 3, 0.9), rgba(3, 3, 3, 0.95)),
    url("assets/generated/a-atm-gold-haze.jpg");
}

/* ponytail: no asset behind this one — layered gradients only. Same rhythm,
   zero bytes. Used where the generated library ran out. */
.band--plain {
  background-image:
    radial-gradient(120% 80% at 50% 0%, rgba(191, 167, 105, 0.09), transparent 62%),
    linear-gradient(180deg, #050504, var(--ink-2) 55%, #050504);
}

/* ---------- Lookbook ----------
   Their own cuts, nothing else. A real grid at a uniform square crop: six of the
   eight photos are within 13% of square already, so 1:1 is near-lossless for most
   of the set and reduces the crop decision to the two 4:5 portraits, which get an
   explicit vertical anchor below. 4:5 was rejected -- it would take ~20% off the
   width of six photos, and one of them is a side-by-side before/after where that
   cuts through both heads. */
.lookbook {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(0.65rem, 1.9vw, 1.15rem);
}

@media (min-width: 34rem) {
  .lookbook {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 60rem) {
  .lookbook {
    grid-template-columns: repeat(4, 1fr);
  }
}

.lookbook .frame {
  padding: 5px;
}

.lookbook img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  object-position: 50% 50%;
}

/* Four photos whose subject is not at the geometric centre. See
   docs/visual-fix-spec.md section C.2 for the reasoning and the tested
   alternatives. Portrait sources crop vertically, so the percentage is the
   share of the excess taken off the TOP -- keep it low enough that the crown
   of the head stays in frame. */
.lookbook img[src$="ig-DTgzfnOjevf.jpg"] {
  object-position: 50% 0%;
}

.lookbook img[src$="ig-DS1TBEsjSCg.jpg"] {
  object-position: 50% 20%;
}

.lookbook img[src$="ig-DSu-vsNk8QL-crop.jpg"] {
  object-position: 50% 15%;
}

/* Landscape source: the square crop takes 144px off the width. Anchor left so
   the man-bun the alt text names survives; the wall on the right is what goes. */
.lookbook img[src$="ig-DSvAOLpkxG1-crop.jpg"] {
  object-position: 0% 50%;
}

/* Reserve two caption lines so the frames in a row are identical rectangles
   rather than ragged ones. 2.9em = 2 x the 1.45 line-height declared below, plus
   the 0.7rem of vertical padding, because box-sizing is border-box site-wide --
   a bare 2.9em reserves only 1.4 lines and the second one still pushes a row. */
.lookbook figcaption {
  min-height: calc(2.9em + 0.7rem);
  padding: 0.55rem 0.2rem 0.15rem;
  font-size: 0.78rem;
  line-height: 1.45;
  text-align: left;
}

/* ---------- Still-life plates (generated assets) ----------
   Deliberately narrower and cooler than .frame so a still life never reads as
   documentary. Every plate carries a caption saying what it is. */

.plate {
  background: #060605;
}

.plate img {
  aspect-ratio: 16 / 9;
  object-fit: cover;
  filter: saturate(0.88) contrast(1.04) brightness(0.97);
}

.plate figcaption {
  font-size: 0.78rem;
  letter-spacing: 0.03em;
  color: #8b8578;
}

.plate--wide img {
  aspect-ratio: 21 / 9;
}

/* A row of decorative stills. Purely a divider — no captions, no claims. */
.strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3px;
  margin-block: var(--s-4);
  border: 1px solid var(--line-soft);
  padding: 3px;
  background: var(--ink-2);
}

.strip__note {
  margin-top: calc(var(--s-4) * -1 + 0.5rem);
  margin-bottom: var(--s-4);
  text-align: center;
  font-size: var(--t--1);
}

.strip img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  filter: saturate(0.7) contrast(1.02) brightness(0.72);
}

/* ---------- Status pill ----------
   The cafe is not open. Say so where the eye lands first. */

.soon {
  display: inline-block;
  margin-left: 0.45em;
  padding: 0.2em 0.75em;
  border: 1px solid var(--gold);
  border-radius: 999px;
  color: var(--gold);
  font: 600 0.7rem / 1.6 var(--body);
  letter-spacing: 0.17em;
  text-transform: uppercase;
  vertical-align: middle;
}

/* ---------- Stacked figures ----------
   Two photos in one column of a .duo, for the barber pages. */

.pair {
  display: grid;
  gap: clamp(0.6rem, 2vw, 1rem);
}

/* ---------- Service icons: keep the row aligned once every card has one ----
   Three children per service (icon, h3, p) so one row per service on desktop.
   On phones the icon sits beside the name and the description spans the row. */

.service {
  grid-template-columns: 1.75rem 1fr;
  align-items: center;
}

.service p {
  grid-column: 1 / -1;
  margin-top: 0.35rem;
}

@media (min-width: 48rem) {
  .service {
    grid-template-columns: 1.75rem 13.25rem 1fr;
    align-items: baseline;
  }

  .service p {
    grid-column: auto;
    margin-top: 0;
  }
}

.service .svc-icon {
  margin: 0;
}

