/* Outlaw Guide Service — design system.
   Tokens and rules come from ART_DIRECTION.md. Palette is sampled from the client's own
   business card and hand painted sign; do not swap a value here without updating that file. */

:root {
  /* --- palette: three colours, per ART_DIRECTION --- */
  --ink: #171310;            /* warm near black, never #000 */
  --ink-1: #1f1a15;
  --ink-2: #2a231c;
  --ink-3: #3a3128;
  --bone: #e9e3d6;           /* the real business card stock */
  --bone-dim: #b3aa99;
  --ochre: #e0a828;          /* the yellow on their own sign */
  --ochre-deep: #b8851a;

  --measure: 62ch;
  --wrap: 1200px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);

  /* major third, 1.25 */
  --t-xs: 0.875rem;
  --t-s: 1rem;
  --t-m: clamp(1.05rem, 0.98rem + 0.35vw, 1.25rem);
  --t-l: clamp(1.35rem, 1.15rem + 0.9vw, 1.95rem);
  --t-xl: clamp(1.85rem, 1.4rem + 2vw, 3.05rem);
  --t-2xl: clamp(2.4rem, 1.5rem + 4.2vw, 4.75rem);

  --ease: cubic-bezier(0.16, 0.84, 0.44, 1);
  --dur: 400ms;

  --edge: 1px solid rgb(233 227 214 / 0.14);
}

*, *::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(--ink);
  color: var(--bone);
  font-family: "Public Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  font-size: 1.125rem;
  font-size: var(--t-m);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img, video { max-width: 100%; height: auto; display: block; }

h1, h2, h3, .display {
  font-family: Bitter, ui-serif, Georgia, "Times New Roman", serif;
  font-weight: 900;
  line-height: 1.02;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: 2.75rem; font-size: var(--t-2xl); }
h2 { font-size: 2rem; font-size: var(--t-xl); }
h3 { font-size: 1.5rem; font-size: var(--t-l); letter-spacing: 0.01em; }
p { margin: 0 0 1.1em; max-width: var(--measure); text-wrap: pretty; }

a { color: var(--ochre); text-underline-offset: 0.22em; }
a:focus-visible, button:focus-visible, summary:focus-visible {
  outline: 3px solid var(--ochre);
  outline-offset: 3px;
  border-radius: 2px;
}

.wrap { width: min(var(--wrap), 100% - (var(--gutter) * 2)); margin-inline: auto; }
.section { padding-block: 4.5rem; padding-block: clamp(3.5rem, 9vw, 7rem); }
.section--tight { padding-block: 3rem; padding-block: clamp(2.5rem, 6vw, 4.5rem); }
.stack > * + * { margin-top: 1.15rem; }
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ochre); color: var(--ink); padding: 0.75rem 1.1rem; font-weight: 700;
}
.skip:focus { left: 0; }

.eyebrow {
  font-size: var(--t-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ochre);
  font-weight: 700;
  margin: 0 0 0.9rem;
}
.lede { font-size: 1.5rem; font-size: var(--t-l); line-height: 1.35; font-weight: 300; color: var(--bone); }
.muted { color: var(--bone-dim); }
.small { font-size: var(--t-xs); line-height: 1.55; }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem;
  font-family: Bitter, serif; font-weight: 900; text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: clamp(1.05rem, 0.9rem + 0.7vw, 1.4rem);
  padding: 0.85em 1.4em;
  background: var(--ochre); color: var(--ink);
  border: 2px solid var(--ochre); border-radius: 2px;
  text-decoration: none; white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn:hover { background: var(--ochre-deep); border-color: var(--ochre-deep); }
/* The secondary action must not compete with the phone number. Smaller, lighter, quieter. */
.btn--ghost {
  background: transparent; color: var(--bone); border-color: rgb(233 227 214 / 0.4);
  font-size: clamp(0.9rem, 0.82rem + 0.35vw, 1.05rem); padding: 0.8em 1.2em;
}
.btn--ghost:hover { background: rgb(233 227 214 / 0.08); border-color: var(--bone); color: var(--bone); }
.btn--wide { width: 100%; }
@media (min-width: 40rem) { .btn--wide { width: auto; } }

/* ---------------------------------------------------------------- header */

.site-header {
  position: fixed; inset: 0 0 auto; z-index: 100;
  display: flex; align-items: center; gap: 1rem;
  padding: 0.7rem var(--gutter);
  background: transparent;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
  border-bottom: 1px solid transparent;
}
.site-header.is-stuck {
  background: rgb(23 19 16 / 0.97);
  border-bottom-color: rgb(233 227 214 / 0.14);
  backdrop-filter: blur(10px) saturate(1.2);
}
.brand { display: flex; flex-direction: column; text-decoration: none; color: var(--bone); line-height: 0.92; }
.brand b {
  font-family: Bitter, serif; font-weight: 900; text-transform: uppercase;
  font-size: 1.4rem; letter-spacing: 0.01em;
}
.brand span {
  font-size: 0.72rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ochre); font-weight: 700;
}
.nav-toggle {
  margin-left: auto; background: none; border: var(--edge); color: var(--bone);
  font: inherit; font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.12em;
  padding: 0.55rem 0.85rem; border-radius: 2px; cursor: pointer;
}
.nav {
  position: fixed; inset: 3.6rem 0 auto; display: none;
  flex-direction: column; gap: 0.2rem;
  background: var(--ink); border-bottom: var(--edge);
  padding: 0.5rem var(--gutter) 1.25rem;
}
.nav--open { display: flex; }
.nav a {
  color: var(--bone); text-decoration: none; padding: 0.75rem 0;
  border-bottom: 1px solid rgb(233 227 214 / 0.08);
  font-size: var(--t-xs); letter-spacing: 0.14em; text-transform: uppercase; font-weight: 600;
}
.nav a[aria-current="page"] { color: var(--ochre); }
.nav__call {
  margin-top: 0.9rem; text-align: center;
  background: var(--ochre); color: var(--ink) !important;
  font-family: Bitter, serif; font-weight: 900; letter-spacing: 0.02em;
  padding: 0.85rem 1rem !important; border-radius: 2px;
  text-decoration: none; border: 0 !important; font-size: 1.05rem !important;
  text-transform: none !important;
}
.header-call { display: none; }

@media (min-width: 56rem) {
  .nav-toggle { display: none; }
  .nav {
    position: static; display: flex; flex-direction: row; align-items: center; gap: 1.75rem;
    background: none; border: 0; padding: 0; margin-left: auto;
  }
  .nav a { border: 0; padding: 0; }
  .nav__call { display: none; }  /* .header-call covers desktop */
  .nav a:hover { color: var(--ochre); }
  .header-call {
    display: inline-flex; align-items: center; gap: 0.45rem;
    margin-left: 1.75rem; color: var(--bone); text-decoration: none;
    font-family: Bitter, serif; font-weight: 900; font-size: 1.05rem; letter-spacing: 0.01em;
  }
  .header-call:hover { color: var(--ochre); }
  .header-call svg { width: 1em; height: 1em; fill: var(--ochre); }
}

/* ---------------------------------------------- hero + the lamp (signature) */

.hero { position: relative; min-height: 100svh; display: grid; align-items: end; isolation: isolate; }
.lamp { position: absolute; inset: 0; overflow: hidden; background: var(--ink); }
.lamp__base, .lamp__lit { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.lamp__base { filter: saturate(1.03) contrast(1.02); }

/* THE LAMP, INVERTED (2026-09-11, when the night photographs were replaced by daylight ones).
   It used to work by ADDING light: a second, brighter copy of the same photograph was layered
   on top and revealed through a radial hole in a mask, so the pool read as a headlamp lifting
   a dark night frame. That is the wrong machine for a daylight photograph, twice over.

   1. It would have blown out. The night hero had a median luma of 63 and a `brightness(1.85)`
      pool landed it around 117. The daylight hero's median is 108, so the same filter drives it
      to 200 with the top percentile clipped flat to white: the pool would have been a bright
      smear with no detail, in the exact place a visitor is looking.
   2. It cost a second full-size DECODE and a second composited layer of the hero image on every
      frame the pool moved. (Not a second download: the lit layer pointed at the same URL as the
      <img>, so the file itself was already cached. The earlier note here that it "doubled the
      LCP payload" was about an older revision that pointed the lit layer at the 1400px file.)

   So the layer now SUBTRACTS light instead: it is a flat sheet of --ink, opaque everywhere and
   transparent inside the pool. The photograph underneath is shown at its true exposure where
   the light falls and dimmed everywhere else. Identical interaction, no second image, and the
   dark surround is what keeps the headline's measured contrast where the 2026-09-02 pass put it.
   The mask stops is simply the old one reversed. --shade is the knob; it was set by measuring,
   not by eye, so re measure with _audit/hero_contrast.py before changing it. */
.lamp__lit {
  background: var(--ink);
  opacity: var(--shade, 0.62);
  --lx: 50%; --ly: 40%; --lr: 34vmin;
  -webkit-mask-image: radial-gradient(circle var(--lr) at var(--lx) var(--ly),
    transparent 0%, rgb(0 0 0 / 0.14) 38%, rgb(0 0 0 / 0.65) 64%, #000 78%);
  mask-image: radial-gradient(circle var(--lr) at var(--lx) var(--ly),
    transparent 0%, rgb(0 0 0 / 0.14) 38%, rgb(0 0 0 / 0.65) 64%, #000 78%);
}
/* scrim ramps LATE, and is tinted with --ink so the photograph's own warmth survives */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(180deg, rgb(23 19 16 / 0.55) 0%, rgb(23 19 16 / 0) 26%, rgb(23 19 16 / 0) 52%, rgb(23 19 16 / 0.86) 88%, var(--ink) 100%);
}
@media (max-width: 61.99rem) {
  /* The header is ~65px, sticky, and paints ABOVE the hero (z-index 100 against 2). When the
     hero content is taller than the viewport the grid row grows, `align-items: end` stops
     holding the body below the fold, and the brand lockup and Menu button print straight
     through the headline. Reproduced at 320x568, 320x658 and 360x640 after the headline grew.
     Reserving the header height here costs nothing when the content already fits, because the
     body stays bottom aligned. */
  .hero { padding-top: 5rem; }
  .hero::after {
    /* WHY THIS IS AS DARK AS IT IS. The headline is a sentence, so it is tall, and on any
       viewport shorter than the hero content it rides UP into the flash lit face and fur.
       Measured against the real rendered background, the ochre name hit 1.00:1 and the
       lead-in 1.98:1 against a 3.0 requirement. An earlier attempt gated the darker scrim on
       `max-width: 22.5rem`, which fixed 320 and 360 and left 375x667 (iPhone SE 2/3 and
       6/7/8) and every phone in landscape still failing, because the driver is viewport
       HEIGHT, not width. Do not re key this to width. Re measure with the per pixel sampler
       if you touch it. */
    /* REBALANCED 2026-09-11 against the daylight photograph. The stops above were tuned
       when the hero image was a dark night frame and the lit layer ADDED light; there was
       no shade layer to share the work with. Carrying those stops over on top of the new
       inverted lamp double-darkened the phone hero until the photograph was invisible,
       which defeats the point of replacing it. The scrim is now lighter across the top
       third, where no type sits, and the .lamp__lit shade carries the rest. Re measured
       across all 14 viewports with _audit/hero_contrast.py after every change. */
    background: linear-gradient(180deg,
      rgb(23 19 16 / 0.50) 0%, rgb(23 19 16 / 0.24) 11%, rgb(23 19 16 / 0.34) 27%,
      rgb(23 19 16 / 0.74) 43%, rgb(23 19 16 / 0.93) 64%, var(--ink) 86%);
  }
  /* lift the subject out from behind the type */
  .lamp__base { object-position: center 26%; }
  /* the phone hero carries the headline over the photograph, so it needs more shade than
     the desktop split, where the type sits on its own dark ground. Measured, see the note
     on --shade above. */
  /* On a phone the box is far taller than the photograph's 0.8 aspect, so cover matches the
     HEIGHT and crops the sides. The whole frame is on screen but the sign and the bear sit
     mid frame, which is exactly where the type is, and no object-position can move them
     because the overflow is horizontal. So the phone hero treats the photograph as ground
     rather than as subject, and the pool lights the one band that carries no type, the top.

     An attempt to aim the pool at the bear's head instead (--lx 72%, --ly 33%) was measured
     and REJECTED: it lit the animal only slightly, because the right edge crops its head,
     and it cut the worst-case contrast from 5.47:1 to 3.19:1 against a 3.0 floor. Trading
     three quarters of the safety margin for a barely visible bear is a bad trade, and this
     is the hero that has already failed contrast twice. The photograph gets its proper
     showing in the split desktop hero above 62rem. */
  .lamp__lit { --shade: 0.38; --ly: 21%; --lr: 29vmin; }
}

/* SHORT VIEWPORTS. This is the same root cause the 2026-09-02 pass wrote up: when the
   viewport is short the hero content rides UP out of the dark foot of the scrim and into
   the bright photograph, and the headline is a full sentence so it is tall. The driver is
   viewport HEIGHT, never width, which is why this query is on max-height and why the
   earlier max-width attempt left 375x667 failing.

   On a tall phone the top third of the hero is free of type and the photograph should be
   seen there. On a short or landscape phone there is no such band, so the photograph gives
   way and the type wins. Measured: with the light scrim alone, 932x430 put the h1 lead at
   1.86:1 and 844x390 at 1.88:1 against a 3.0 requirement. */
/* TWO bands, not one. A single max-height: 48rem threshold was too coarse: it lumped 640 to
   667px portrait phones in with 568px phones and with landscape, and on an iPhone SE 2/3 or
   6/7/8 (375x667), one of the most common small phones in the US, 84.5% of the hero came out
   within 8 luma of flat ink. The daylight photograph simply did not land there, which defeats
   the point of putting it on the hero at all.

   A 640 to 667px phone still has a usable type-free band at the top; a 568px phone or a phone
   in landscape does not. So the middle band shows the photograph and the bottom band does not.
   📕 Do NOT collapse these back into one query, and do NOT lighten the bottom one: fully
   reverting it measures 1.86 to 1.97 and even a moderate lightening measures 2.41 at 320x568,
   against a 3.0 floor. Worst-pixel contrast here is dominated by one bright highlight and
   collapses non-linearly, so there is no slack to spend. */
@media (max-width: 61.99rem) and (max-height: 48rem) and (min-height: 38rem) {
  .hero::after {
    background: linear-gradient(180deg,
      rgb(23 19 16 / 0.66) 0%, rgb(23 19 16 / 0.47) 10%, rgb(23 19 16 / 0.62) 25%,
      rgb(23 19 16 / 0.86) 42%, rgb(23 19 16 / 0.95) 63%, var(--ink) 88%);
  }
  .lamp__lit { --shade: 0.54; --ly: 15%; }
}
@media (max-width: 61.99rem) and (max-height: 37.99rem) {
  .hero::after {
    background: linear-gradient(180deg,
      rgb(23 19 16 / 0.72) 0%, rgb(23 19 16 / 0.60) 8%, rgb(23 19 16 / 0.78) 22%,
      rgb(23 19 16 / 0.90) 40%, rgb(23 19 16 / 0.96) 62%, var(--ink) 90%);
  }
  .lamp__lit { --shade: 0.62; --ly: 13%; }
}


.hero__body { position: relative; z-index: 2; padding-block: clamp(2rem, 6vw, 4.5rem) clamp(2.5rem, 7vw, 5rem); }
.hero h1 { max-width: 16ch; }
/* The headline is a full sentence (owner supplied 2026-09-02), so the h1 carries a smaller
   lead-in and the ochre display weight lands on the name. Sizes stay on the existing scale.
   Do NOT widen the max-width on .hero h1: it is in `ch` of the 76px display size, and raising
   it runs the type under the photograph in the split desktop hero. */
.hero h1 .lead {
  display: block;
  font-size: var(--t-l);
  font-weight: 700;
  /* NOT uppercase, and NOT the 1.02 display leading. This is 66 characters running three
     lines, which is a paragraph wearing a headline, and all caps at that length costs real
     legibility. Same call the blockquote cite got. It also buys the ochre name below it a
     much stronger case contrast to land against. */
  text-transform: none;
  line-height: 1.3;
  letter-spacing: -0.005em;
  margin-bottom: 0.5em;
}
.hero h1 em { font-style: normal; color: var(--ochre); display: block; }
.hero__sub { font-size: var(--t-l); font-weight: 300; max-width: 34ch; margin: 1.1rem 0 1.9rem; }
.hero__cta { display: flex; flex-direction: column; gap: 0.75rem; align-items: stretch; }
.hero__note { font-size: var(--t-xs); color: var(--bone-dim); margin: 0.35rem 0 0; }
@media (min-width: 40rem) {
  .hero__cta { flex-direction: row; align-items: center; gap: 1rem; }
}

/* DESKTOP HERO, split.
   The only good photograph we have is portrait (1400x1750, aspect 0.8). Cover cropping it
   into a 1440x900 landscape hero threw away the bear's head and the hand painted sign and
   left a meaningless close up of fur. So from 62rem up the photo takes the right half of
   the hero, where the box is 720x900 and the aspect is 0.8 exactly: it lands essentially
   uncropped. The type gets a clean dark ground instead of fighting a scrim for contrast. */
@media (min-width: 62rem) {
  .hero { align-items: center; min-height: 94svh; }
  .lamp { left: 46%; }
  .lamp__lit { --lr: 22vmin; }
  .hero::after {
    background:
      linear-gradient(90deg, var(--ink) 0%, var(--ink) 30%, rgb(23 19 16 / 0.72) 48%,
        rgb(23 19 16 / 0) 68%),
      linear-gradient(180deg, rgb(23 19 16 / 0.5) 0%, rgb(23 19 16 / 0) 22%,
        rgb(23 19 16 / 0) 74%, rgb(23 19 16 / 0.72) 100%);
  }
  .hero h1 { max-width: 11ch; }
  .hero__sub { max-width: 27ch; }
  .hero__cta { max-width: none; }
  .hero__note { max-width: 30rem; }
}

@media (prefers-reduced-motion: reduce) { .lamp__lit { transition: none !important; } }

/* ---------------------------------------------------------------- facts bar */

.facts { border-block: var(--edge); margin: 0; }
.facts__inner { display: grid; gap: 1px; background: rgb(233 227 214 / 0.14); }
@media (min-width: 40rem) { .facts__inner { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .facts__inner { grid-template-columns: repeat(4, 1fr); } }
.fact { background: var(--ink); padding: 1.75rem 1.5rem; }
.fact dt {
  font-family: Bitter, serif; font-weight: 900; text-transform: uppercase;
  font-size: 1.5rem; color: var(--ochre); line-height: 1.1;
}
.fact dd { margin: 0.35rem 0 0; font-size: var(--t-s); color: var(--bone-dim); max-width: 34ch; }

/* ---------------------------------------------------------------- layout bits */

.split { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; }
@media (min-width: 52rem) {
  .split { grid-template-columns: 1fr 1fr; }
  .split--wide-left { grid-template-columns: 1.15fr 0.85fr; }
}
.figure { position: relative; }
.figure img, .figure video { width: 100%; border-radius: 2px; }
/* kill the rectangle: the image bottom dissolves into the page ground */
.figure--dissolve::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 38%; pointer-events: none;
  background: linear-gradient(180deg, rgb(23 19 16 / 0) 0%, var(--ink) 96%);
}
figcaption { font-size: var(--t-xs); color: var(--bone-dim); margin-top: 0.7rem; }

.rule { border: 0; border-top: var(--edge); margin: 0; }

/* Wide content scrolls inside its own box; the page body must never scroll sideways. */
.table-scroll {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  /* A cut off column with no cue reads as broken. This fade only appears while there is
     actually more to scroll to, because the mask is pinned to the scrollport edge. */
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 96%, rgb(0 0 0 / 0.55) 100%);
  mask-image: linear-gradient(90deg, #000 0, #000 96%, rgb(0 0 0 / 0.55) 100%);
}
.table-scroll:focus-visible { outline: 3px solid var(--ochre); outline-offset: 3px; }
/* The caption is page copy, not table content. Leaving it inside the scrollport meant it was
   cut mid word on a phone and could only be read by scrolling the table sideways. */
.table-note { font-size: var(--t-xs); line-height: 1.55; color: var(--bone-dim); margin: 0 0 0.9rem; max-width: 60ch; }
.table-scroll .seasons { min-width: 34rem; }
@media (min-width: 44rem) {
  .table-scroll { -webkit-mask-image: none; mask-image: none; }
  .table-scroll .seasons { min-width: 0; }
}

/* seasons — a real table, not a grid of cards */
.seasons { width: 100%; border-collapse: collapse; font-size: var(--t-s); }
.seasons caption { text-align: left; color: var(--bone-dim); font-size: var(--t-xs); padding-bottom: 0.9rem; }
.seasons th, .seasons td { text-align: left; padding: 0.95rem 0.8rem 0.95rem 0; border-bottom: 1px solid rgb(233 227 214 / 0.1); vertical-align: baseline; }
.seasons th {
  font-family: Bitter, serif; font-weight: 900; text-transform: uppercase;
  letter-spacing: 0.02em; font-size: var(--t-s); white-space: nowrap;
}
.seasons thead th { color: var(--ochre); font-size: var(--t-xs); letter-spacing: 0.16em; border-bottom-color: rgb(224 168 40 / 0.4); }
.seasons td:last-child { color: var(--bone-dim); }

/* included / not included */
.checks { list-style: none; padding: 0; margin: 0; }
.checks li { padding: 0.6rem 0 0.6rem 1.75rem; position: relative; border-bottom: 1px solid rgb(233 227 214 / 0.08); }
.checks li::before {
  content: ""; position: absolute; left: 0; top: 1.15em;
  width: 0.65rem; height: 0.65rem; background: var(--ochre); border-radius: 50%;
}
.checks--open li::before { background: none; border: 2px solid rgb(233 227 214 / 0.35); }

/* gallery */
.grid-photos { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 44rem) { .grid-photos { grid-template-columns: repeat(2, 1fr); gap: 1.25rem; } }
/* align-self:start, because the photographs are no longer all the same shape. The daylight
   set mixes one 700x875 portrait with two 900x800 landscapes, and a stretched grid row sized
   itself to the portrait and left ~213px of dead ground under the landscape beside it, which
   read as a hole in the middle of the gallery. Each figure now hugs its own image. */
.grid-photos figure { margin: 0; align-self: start; }
.grid-photos img, .grid-photos video { width: 100%; border-radius: 2px; }

/* the archive strip — their real printed material, shown as what it is */
.archive { background: var(--ink-1); padding-inline: 1.5rem; }
.archive__items { display: grid; gap: 1.5rem; }
@media (min-width: 48rem) { .archive__items { grid-template-columns: 1fr 1fr; gap: 2rem; } }
.archive__items img { width: 100%; border-radius: 2px; border: var(--edge); }

blockquote {
  margin: 0; padding-left: 1.25rem; border-left: 3px solid var(--ochre);
  font-family: Bitter, serif; font-weight: 400; font-style: italic;
  font-size: var(--t-l); line-height: 1.32; color: var(--bone);
}
blockquote cite { display: block; font-family: "Public Sans", sans-serif; font-style: normal; font-size: 0.875rem; font-size: var(--t-xs); letter-spacing: 0.04em; color: var(--bone-dim); margin-top: 0.9rem; }

/* ---------------------------------------------------------------- call band */

.band { background: var(--ochre); color: var(--ink); text-align: center; padding-inline: 1.5rem; }
/* The global focus ring is ochre, which is invisible on this band. Flip it to ink here or a
   keyboard user gets no visible focus at all on the primary phone CTA. */
.band a:focus-visible, .band .btn:focus-visible {
  outline: 3px solid var(--ink); outline-offset: 4px;
}
.band h2 { color: var(--ink); }
.band p { margin-inline: auto; color: rgb(23 19 16 / 0.82); }
.band .btn { background: var(--ink); color: var(--ochre); border-color: var(--ink); }
.band .btn:hover { background: var(--ink-2); border-color: var(--ink-2); }
.band .phone {
  display: inline-block; font-family: Bitter, serif; font-weight: 900;
  font-size: clamp(2rem, 1.2rem + 4vw, 3.75rem); color: var(--ink);
  text-decoration: none; letter-spacing: -0.01em; margin: 0.6rem 0 0.3rem;
}
.band .phone:hover { text-decoration: underline; }

/* ---------------------------------------------------------------- form */

.form { display: grid; gap: 1rem; max-width: 34rem; }
.field { display: grid; gap: 0.4rem; }
.field label { font-size: var(--t-xs); letter-spacing: 0.12em; text-transform: uppercase; font-weight: 700; color: var(--bone-dim); }
.field input, .field select, .field textarea {
  font: inherit; font-size: var(--t-s); color: var(--bone);
  background: var(--ink-1); border: 1px solid rgb(233 227 214 / 0.46); border-radius: 2px;
  padding: 0.75rem 0.85rem;
  width: 100%; max-width: 100%; min-width: 0;
}
.field input:focus, .field select:focus, .field textarea:focus { outline: 3px solid var(--ochre); outline-offset: 1px; border-color: transparent; }
.field textarea { min-height: 7rem; resize: vertical; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-note { font-size: var(--t-xs); color: var(--bone-dim); max-width: 34rem; }
/* No accent stripe here on purpose: a status message wearing a coloured left bar is the
   templated-alert tell. The status earns attention from weight and colour instead. */
.form-status { font-size: var(--t-s); font-weight: 700; color: var(--ochre); margin: 0; }
.form-status:empty { display: none; }

/* ---------------------------------------------------------------- footer */

.site-footer { background: var(--ink-1); border-top: var(--edge); padding-block: clamp(2.5rem, 6vw, 4rem); }
.footer-grid { display: grid; gap: 2rem; }
@media (min-width: 48rem) { .footer-grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.site-footer h3 { font-size: var(--t-s); letter-spacing: 0.16em; color: var(--ochre); }
.site-footer ul { list-style: none; padding: 0; margin: 0.8rem 0 0; }
.site-footer li { padding: 0.28rem 0; }
.site-footer a { color: var(--bone); text-decoration: none; font-size: var(--t-s); }
.site-footer a:hover { color: var(--ochre); text-decoration: underline; }
.colophon { margin-top: 2.5rem; padding-top: 1.5rem; border-top: var(--edge); font-size: var(--t-xs); color: var(--bone-dim); }
.colophon p { max-width: none; margin: 0; }

/* ---------------------------------------------------------------- reveal */

.js [data-reveal] { opacity: 0; transform: translateY(14px); transition: opacity 600ms var(--ease), transform 600ms var(--ease); }
.js [data-reveal].is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
