@font-face{font-family:'Newsreader';src:url('../fonts/heading-newsreader.woff2') format('woff2');font-style:normal;font-weight:100 900;font-display:swap}
@font-face{font-family:'Manrope';src:url('../fonts/body-manrope.woff2') format('woff2');font-style:normal;font-weight:100 900;font-display:swap}
/* ==========================================================================
   Cinematic Chapters — Vestry Rose Weddings
   DS-02. Static CSS. No framework, no library, no CDN, no preprocessor.

   The static state IS the product. Every rule below renders the finished
   composition with no script running and with all motion removed. The one
   TypeScript module that touches presentation (chapters.ts) only adds the
   class `js-reveal` to <html> and `is-on` to chapters, and every selector
   that depends on those two classes is an enhancement of a state that is
   already correct without them.

   Order of this file:
     1  tokens
     2  reset and base
     3  typography
     4  shell, letterbox and chapter primitives
     5  header overlay bar and the bottom-sheet navigation
     6  hero chapter
     7  interior chapter variants
     8  components (actions, rails, cards, quotes, forms)
     9  gallery reel
    10  staff portraits
    11  subscribe band and footer
    12  responsive contract, width by width
    13  reduced motion, forced colours, print
   ========================================================================== */

/* -------------------------------------------------------------------------
   1  TOKENS — the single block. No page-specific near-duplicates.
   ------------------------------------------------------------------------- */
:root {
  /* colour */
  --bg: #f8f1f2;
  --bg-lift: #ecdcda;
  --bg-sheet: #f2e3e4;
  --text: #251819;
  --muted: #5a4445;
  --action: #254b0c;
  --accent: #6d1d21;
  --hl: #b2f0c7;
  /* The highlight where the sheet spends it as INK. Section 9 names the
     highlight as a ground with a text colour on it; this sheet uses it
     for labels and quiet links instead, which a light system cannot do
     with a tint. Same role, a tone that reads. */
  --hl-ink: #125e2c;
  --rule: rgba(108, 55, 58, 0.28);
  --rule-soft: rgba(37, 24, 25, 0.14);
  --focus: #254b0c;
  /* The colour section 9 names for text ON the action colour. Three of
     the four DS-02 systems are light, where the page ground and the
     action label are no longer the same near-black. */
  --on-action: #ffffff;

  /*
     Section 17 names three values outright: a field, a chapter mark and a 1px rule.
          This unit's are #ECDCDA, #6D1D21 and rgba(37,24,25,.18). They sit beside the
          palette rather than replacing it -- #F8F1F2 stays the page ground, and the
          field is the slightly lifted plane the chapter furniture is drawn on. The mark
          is the accent, not a gold: on paper the ceremonial red is what reads as a mark.
  */
  --field: #ecdcda;
  --mark-gold: #6d1d21;
  --hair: rgba(37, 24, 25, 0.18);

  /* spacing scale — 4 8 12 16 24 32 48 64 96 128 */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;
  --s9: 96px;
  --s10: 128px;

  /* geometry */
  --maxw: 1240px;
  --measure: 68ch;
  --measure-review: 52ch;
  --radius: 24px;
  --header-h: 56px;
  --gutter: 16px;
  --section: 72px;
  --letterbox: 16px;
  --control: 44px;

  /* motion */
  --t-std: 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
  --t-long: 600ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Material catalogue correction: four cinematic acts. Supporting sections
   share a scene instead of forming a generic vertical preview stack. */
@media (min-width: 1100px) {
  .home-page main.page--hero {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "hero hero"
      "services approach"
      "gallery staff"
      "reviews faq"
      "closing closing";
    background: #381e20;
  }
  .home-page main > .hero { grid-area: hero; min-height: 100svh; }
  .home-page main > .filmband { grid-column: 1 / -1; grid-row: 1; align-self: end; z-index: 4; }
  .home-page main > [aria-labelledby="svc-h"] { grid-area: services; min-height: 100svh; }
  .home-page main > [aria-labelledby="how-h"] { grid-area: approach; min-height: 100svh; }
  .home-page main > [aria-labelledby="gal-h"] { grid-area: gallery; min-height: 100svh; }
  .home-page main > [aria-labelledby="ppl-h"] { grid-area: staff; min-height: 100svh; }
  .home-page main > [aria-labelledby="rev-h"] { grid-area: reviews; min-height: 100svh; }
  .home-page main > [aria-labelledby="faq-h"] { grid-area: faq; min-height: 100svh; }
  .home-page main > .atmos { grid-area: closing; min-height: 100svh; }
  .home-page main > .cta { grid-area: closing; align-self: end; z-index: 3; background: linear-gradient(transparent, #381e20 40%); }
  .home-page main > [aria-labelledby="svc-h"],
  .home-page main > [aria-labelledby="ppl-h"],
  .home-page main > [aria-labelledby="rev-h"] { border-right: 1px solid rgba(108,55,58,.25); }
}

/* -------------------------------------------------------------------------
   2  RESET AND BASE
   ------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
  scroll-behavior: auto;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family:var(--catalog-font-body);
  font-size: 1rem;
  line-height: 1.6;
  font-synthesis-weight: none;
  overflow-x: hidden;
}

/*
   height: auto is load-bearing, not tidiness. Every <img> here carries width
   and height attributes so the box is reserved before the bytes arrive, and
   HTML maps those attributes to presentational width and height declarations.
   max-width: 100% then shrinks the width while the height declaration stands,
   so the hero poster rendered 320 x 1080 instead of 320 x 180: the correct
   width against the full attribute height. height: auto lets the derived
   aspect ratio govern, which is what keeps the reserved box honest and CLS
   at zero.
*/
img,
svg,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: var(--action);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}

a:hover {
  color: var(--text);
}

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Browsers without :focus-visible still show a ring. */
:focus {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
}

:focus:not(:focus-visible) {
  outline: none;
}

.skip {
  position: absolute;
  left: var(--s4);
  top: var(--s2);
  z-index: 200;
  transform: translateY(-160%);
  background: var(--action);
  color: var(--on-action);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 12px 20px;
  border-radius: var(--radius);
  text-decoration: none;
  transition: transform var(--t-std);
}

.skip:focus {
  transform: translateY(0);
  color: var(--on-action);
}

.vh {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* -------------------------------------------------------------------------
   3  TYPOGRAPHY — two self-hosted variable files, nothing else.
   ------------------------------------------------------------------------- */




h1,
h2,
h3,
.mark,
.quote__text,
.num {
  font-family:var(--catalog-font-heading);
  font-weight: 400;
  margin: 0;
}

h1 {
  font-size: clamp(2.25rem, 11vw, 3.75rem);
  line-height: 0.98;
  letter-spacing: -0.03em;
}

h2 {
  font-size: clamp(2rem, 4vw, 4rem);
  line-height: 1.02;
  letter-spacing: -0.028em;
}

h3 {
  font-size: clamp(1.25rem, 2vw, 1.75rem);
  line-height: 1.15;
  letter-spacing: -0.018em;
}

p {
  margin: 0;
}

.lede {
  font-size: 1.0625rem;
  line-height: 1.55;
  color: var(--text);
  max-width: var(--measure);
}

.body {
  color: var(--muted);
  max-width: var(--measure);
}

.label {
  font-size: 0.875rem;
  line-height: 1.35;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--hl-ink);
  margin: 0;
}

.meta {
  font-size: 0.8125rem;
  line-height: 1.45;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin: 0;
}

.num {
  font-size: 0.9375rem;
  letter-spacing: 0.2em;
  color: var(--action);
}

/* -------------------------------------------------------------------------
   4  SHELL, LETTERBOX AND CHAPTER PRIMITIVES
   ------------------------------------------------------------------------- */
.shell {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding-inline: var(--gutter);
}

/*
   A chapter is the unit of this design. It is a viewport layer: an absolutely
   positioned media plane, a scrim plane above it, and a content plane above
   that. The two black bands drawn by ::before and ::after are the cinematic
   letterbox mask; they clip the media inside the frame at every width, which
   is what stops a full-bleed photograph reading as a hero banner.
*/
.chapter {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--bg);
  padding-block: var(--section);
}

.chapter::before,
.chapter::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: var(--letterbox);
  background: var(--bg);
  z-index: 4;
  pointer-events: none;
}

.chapter::before {
  top: 0;
  box-shadow: 0 1px 0 0 var(--rule);
}

.chapter::after {
  bottom: 0;
  box-shadow: 0 -1px 0 0 var(--rule);
}

/* A full-viewport chapter. Used for the hero and for every priced service. */
.chapter--full {
  min-height: 100vh;
  display: grid;
  align-content: center;
}

@supports (min-height: 100svh) {
  .chapter--full {
    min-height: 100svh;
  }
}

/*
   R2 allows one featured review a 70vh stage rather than the full viewport.
   align-content: end is not decoration: it drops the caption plate to the
   bottom of the frame, which is where .chapter__scrim is between .92 and .96
   opaque, so the overlay text keeps its contrast on the brightest still.
*/
.chapter--lead {
  min-height: 70vh;
  align-content: end;
}

@supports (min-height: 100svh) {
  .chapter--lead {
    min-height: 70svh;
  }
}

.chapter__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.chapter__media img,
.chapter__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/*
   The scrim is what makes overlay text legible on the brightest frame of a
   photograph. It is opaque at the bottom, where the text sits, and clears
   toward the top so the image is still visible as an image.
*/
.chapter__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    to top,
    rgba(10, 12, 14, 0.96) 0%,
    rgba(10, 12, 14, 0.92) 34%,
    rgba(10, 12, 14, 0.66) 62%,
    rgba(10, 12, 14, 0.3) 100%
  );
}

.chapter__body {
  position: relative;
  z-index: 3;
}

/*
   The scene's right-hand anchor: the chapter counter, a hairline and the
   timestamp. Below 1024px .shell is not a grid, so this stacks under the
   caption plate as a closing credit; the 1024px block turns it into the
   4fr column and flushes it right.
*/
.chapter__aside {
  display: grid;
  gap: var(--s3);
  align-content: end;
}

.chapter__aside .rule {
  display: block;
  width: 96px;
  height: 1px;
  background: var(--rule);
}

.chapter__inner {
  display: grid;
  /*
     Stated explicitly for the same reason .hero states it. An implicit auto
     column is sized from its items' max-content contribution, and .lede and
     .body carry max-width: var(--measure) (68ch). Inside .chapter--open,
     where this box is capped at 40ch/46ch, that made the track 623px wide in
     a 493px box and the prose painted outside its own column at 1600px.
     minmax(0, 1fr) pins the track to the box, so the narrower cap governs
     and the 68ch measure is simply an upper bound that never binds here.
  */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s5);
  max-width: var(--measure);
}

/* The chapter marker: an index number, a hairline and a category label. */
.chapter__mark {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.chapter__mark .rule {
  flex: 1 1 auto;
  height: 1px;
  background: var(--rule);
  max-width: 96px;
}

/* -------------------------------------------------------------------------
   5  HEADER OVERLAY BAR + BOTTOM-SHEET NAVIGATION
   ------------------------------------------------------------------------- */
.bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 80;
  height: var(--header-h);
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding-inline: var(--gutter);
  background: linear-gradient(to bottom, rgba(10, 12, 14, 0.9) 0%, rgba(10, 12, 14, 0.55) 62%, rgba(10, 12, 14, 0) 100%);
}

.bar::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--rule-soft);
}

.mark {
  font-size: 0.9375rem;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  margin-right: auto;
}

.mark:hover {
  color: var(--action);
}

.mark em {
  font-style: italic;
  color: var(--action);
}

/*
   The Book destination stays IN THE BAR at every width, 320px included. It is
   not hidden below 768px and promoted into the sheet instead, for two reasons.
   A Book action that exists only behind a disclosure is one extra tap away on
   exactly the devices most visitors arrive on. And a control removed with
   `display: none` cannot accept a focus ring, so a keyboard visitor tabbing
   across the header would reach nothing at all where the primary action is.
   Room is made by shortening two things rather than deleting one: the wordmark
   drops its trailing word below 414px and the button takes compact padding
   below 768px. At 320px that is 94px of wordmark, 58px of Book and 86px of
   disclosure with two 16px gaps — 270px inside 288px of available width.
*/
.mark__tail {
  display: none;
}

.bar .btn--book {
  padding: 0 var(--s3);
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
}

/* Desktop overlay links. Hidden below 1024px, where the sheet takes over. */
.bar__nav {
  display: none;
}

.bar__nav ul {
  display: flex;
  align-items: center;
  gap: 14px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.bar__nav a {
  display: block;
  font-size: 0.8125rem;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text);
  text-decoration: none;
  padding: 14px 2px;
  white-space: nowrap;
  transition: color var(--t-std);
}

.bar__nav a:hover {
  color: var(--action);
}

.bar__nav a[aria-current="page"] {
  color: var(--action);
  box-shadow: inset 0 -1px 0 0 var(--action);
}

/* The disclosure. A native <details>, so it works with no script at all. */
.drawer {
  margin-left: auto;
}

.drawer > summary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-width: var(--control);
  min-height: var(--control);
  padding: 0 var(--s3);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: rgba(10, 12, 14, 0.6);
  color: var(--text);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  list-style: none;
}

.drawer > summary::-webkit-details-marker {
  display: none;
}

.drawer > summary::after {
  content: "";
  width: 14px;
  height: 9px;
  background: currentColor;
  clip-path: polygon(0 0, 100% 0, 100% 1px, 0 1px, 0 4px, 100% 4px, 100% 5px, 0 5px, 0 8px, 100% 8px, 100% 9px, 0 9px);
}

.drawer[open] > summary::after {
  clip-path: polygon(0 4px, 100% 4px, 100% 5px, 0 5px);
}

.drawer > summary:hover {
  border-color: var(--action);
  color: var(--action);
}

/*
   The panel is a bottom sheet: it enters from the foot of the viewport, which
   is where a thumb already is. It is a fixed layer, not a dropdown, so a long
   link list never pushes the page or falls off the top of the screen.
*/
.drawer__panel {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  max-height: 82vh;
  overflow-y: auto;
  padding: var(--s5) var(--gutter) var(--s6);
  background: var(--bg-sheet);
  border-top: 1px solid var(--rule);
  box-shadow: 0 -24px 64px rgba(0, 0, 0, 0.6);
}

.drawer__panel ul {
  list-style: none;
  margin: 0 0 var(--s4);
  padding: 0;
  display: grid;
}

.drawer__panel li + li {
  border-top: 1px solid var(--rule-soft);
}

.drawer__panel a {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: var(--control);
  padding: 10px 2px;
  font-size: 1.0625rem;
  color: var(--text);
  text-decoration: none;
}

.drawer__panel a:hover {
  color: var(--action);
}

.drawer__panel a[aria-current="page"] {
  color: var(--action);
}

.drawer__panel a .num {
  font-size: 0.8125rem;
  min-width: 2.4em;
}

.drawer__book {
  display: block;
}

.sheet__foot {
  display: grid;
  gap: var(--s2);
  border-top: 1px solid var(--rule-soft);
  padding-top: var(--s4);
}

/* Keep the page clear of the fixed bar. */
.page {
  padding-top: var(--header-h);
}

.page--hero {
  padding-top: 0;
}

/* -------------------------------------------------------------------------
   6  HERO CHAPTER
   ------------------------------------------------------------------------- */
/*
   Below 768px the hero is two stacked planes: a media band with a fixed
   aspect ratio, then the text. That is what gives the 4:5 crop the responsive
   contract asks for at 320px while the chapter as a whole still fills the
   viewport. From 768px the media becomes the background plane of the chapter
   and the text sits over it.

   The media box reserves its ratio in CSS and the <img> carries width and
   height, so the poster cannot shift the page — and a real <video> dropped
   into the same box with the same intrinsic size changes nothing about
   layout or CLS.
*/
.hero {
  padding-block: 0;
  min-height: 100vh;
  display: grid;
  /*
     The column is stated explicitly, and minmax(0, 1fr) is load-bearing.
     An implicit `auto` column is sized from its items' max-content
     contribution, and .hero__media carries aspect-ratio: 4 / 5 over a
     1920x1080 poster: the ratio transfers the 1080px height into an 864px
     width contribution, so the track became 864px inside a 320px viewport.
     The measured box was 864 x 1080 and body { overflow-x: hidden } hid it.
     minmax(0, 1fr) removes the automatic minimum and pins the track to the
     container, which is what makes the 4:5 crop resolve to 320 x 400.
  */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr;
}

@supports (min-height: 100svh) {
  .hero {
    min-height: 100svh;
  }
}

.hero__media {
  position: relative;
  inset: auto;
  aspect-ratio: 4 / 5;
  width: 100%;
  /*
     min-height: 0 is load-bearing for the same reason the column is stated
     explicitly. This box is a grid item, so its min-height: auto resolves to
     a content-based minimum, and the poster inside contributes its own
     1080px intrinsic height. That minimum beat the 400px the 4:5 ratio
     computes from a 320px width, so the media band measured 320 x 1080.
     Removing the automatic minimum is what lets aspect-ratio decide the
     height, which is the whole basis of the no-CLS claim: a real <video>
     dropped into this box gets the same 320 x 400 band.
  */
  min-height: 0;
  z-index: 0;
}

/*
   The poster fills the band and is cropped by it, so the 16:9 photograph can
   sit in a 4:5 opening at 320px and a full-bleed plane at 1600px from one
   master file. <picture> is an inline wrapper with no height of its own, so
   it has to become a block that fills the band before height: 100% on the
   image can resolve against anything. This is the contract a real <video>
   inherits unchanged: same box, same object-fit, same reserved ratio.
*/
.hero__media picture {
  display: block;
  height: 100%;
}

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to top, rgba(10, 12, 14, 0.95) 0%, rgba(10, 12, 14, 0.35) 55%, rgba(10, 12, 14, 0.5) 100%);
}

.hero__body {
  position: relative;
  z-index: 3;
  display: grid;
  align-content: end;
  gap: var(--s5);
  padding-block: var(--s7) var(--s8);
}

.hero__body > * {
  max-width: 22ch;
}

.hero__body .lede,
.hero__body .film {
  max-width: 46ch;
}

.hero h1 {
  text-wrap: balance;
}

.hero__actions {
  display: grid;
  gap: var(--s3);
  max-width: none;
}

/*
   The film. It is a moving layer laid OVER the poster photograph, not a
   replacement for it. The <picture> underneath is what the browser paints
   first and what LCP measures; this element is transparent until the browser
   reports it is actually playing frames, so a slow connection, a refused
   play(), a decode failure or a visitor who has asked for reduced motion all
   resolve to the same designed still. It inherits the band unchanged --
   same box, same object-fit, same reserved ratio -- so there is nothing for
   it to shift.

   `pointer-events: none` because it carries no control and no meaning the
   photograph beneath does not already carry, which is the same reason the
   element is aria-hidden and out of the tab order.
*/
.hero__film {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  opacity: 0;
  transition: opacity 700ms ease;
}

.hero__film[data-playing] {
  opacity: 1;
}

/* The credit line under the opening, where the film's source is named. */
.film {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  flex-wrap: wrap;
  font-size: 0.8125rem;
  letter-spacing: 0.05em;
  color: var(--muted);
}

.film a {
  color: var(--hl-ink);
}

.film a:hover {
  color: var(--action);
}

/*
   Section 17 limits the first viewport to the headline, the proposition and
   two actions, so the film credit sits in a thin band directly beneath the
   opening card rather than inside it. It is a rule and a line of metadata,
   not a section.
*/
.filmband {
  border-bottom: 1px solid var(--hair);
  background: var(--field);
}

.filmband .shell {
  padding-block: var(--s4);
}

/* -------------------------------------------------------------------------
   7  INTERIOR CHAPTER VARIANTS
   ------------------------------------------------------------------------- */
/* A titled chapter with no photograph: used for openings and for text pages. */
.chapter--open {
  padding-block: calc(var(--section) + var(--s5)) var(--section);
}

.chapter--open .chapter__inner {
  max-width: 40ch;
}

/*
   A page heading sits in a 40ch/46ch column measured in the BODY font while
   the heading itself renders at up to 112px, so one long word can be wider
   than the whole column: "photographs" measures 623px at 112px against a
   493px column, and painted outside it at 1600px. The document declares
   lang="en", so automatic hyphenation breaks that word correctly rather than
   chopping it mid-glyph. It applies to page headings only — the hero H1 sits
   in a much wider column and is never hyphenated.
*/
.chapter--open h1 {
  hyphens: auto;
}

/*
   .body and .lede already carry max-width: var(--measure) at their own rules,
   so an override repeating it here changed nothing while reading as intent.
   Inside an open chapter the 40ch/46ch cap on .chapter__inner is what governs.
*/

/* A panel: simpler than a full chapter, still letterboxed. Text pages. */
.chapter--panel {
  padding-block: var(--section);
}

.chapter--panel .shell > * + * {
  margin-top: var(--s5);
}

/* Two-plane chapter: text beside a still. Activates at 768px. */
.chapter--split .split {
  display: grid;
  gap: var(--s6);
}

.chapter--split .still {
  position: relative;
  border: 1px solid var(--rule-soft);
  background: var(--bg-lift);
}

/* The contact call to action that closes every page. */
.cta {
  background: var(--bg-lift);
}

.cta .shell {
  display: grid;
  gap: var(--s5);
}

.cta__row {
  display: grid;
  gap: var(--s3);
}

/* The three-step contact explanation and the operating principles. */
.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--s5);
  counter-reset: step;
}

.steps > li {
  display: grid;
  gap: var(--s2);
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
}

.steps > li::before {
  counter-increment: step;
  content: "0" counter(step);
  font-family:var(--catalog-font-body);
  font-size: 0.9375rem;
  letter-spacing: 0.2em;
  color: var(--action);
}

/* -------------------------------------------------------------------------
   8  COMPONENTS
   ------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control);
  padding: 0 24px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--t-std), color var(--t-std), border-color var(--t-std);
}

.btn--book {
  background: var(--action);
  color: var(--on-action);
  border-color: var(--action);
}

.btn--book:hover,
.btn--book:active {
  background: #2d5e0d;
  border-color: #2d5e0d;
  color: var(--on-action);
}

.btn--ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--rule);
}

.btn--ghost:hover,
.btn--ghost:active {
  border-color: var(--action);
  color: var(--action);
}

.btn[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
}

/* A quiet in-text link with a gold underline that thickens on hover. */
.link {
  color: var(--hl-ink);
  text-decoration-color: var(--rule);
}

.link:hover {
  color: var(--action);
  text-decoration-color: var(--action);
  text-decoration-thickness: 2px;
}

/* The price line on a service chapter. */
.price {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  font-family:var(--catalog-font-heading);
  font-size: 1.75rem;
  line-height: 1.1;
  color: var(--action);
}

.price small {
  font-family:var(--catalog-font-heading);
  font-size: 0.8125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.cue {
  display: grid;
  gap: var(--s1);
  padding-left: var(--s4);
  border-left: 2px solid var(--accent);
}

/* Review subtitles. Deliberately not a three-card grid. */
.quotes {
  display: grid;
  gap: var(--s8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.quote {
  display: grid;
  gap: var(--s4);
  max-width: var(--measure-review);
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}

.quote__text {
  font-size: clamp(1.25rem, 2vw, 1.75rem);
  line-height: 1.25;
  letter-spacing: -0.012em;
  color: var(--text);
}

.quote__by {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s2) var(--s4);
  font-size: 0.8125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--hl-ink);
}

.quote__by .who {
  color: var(--text);
}

.escape {
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--bg-lift);
  display: grid;
  gap: var(--s3);
}

/* Forms. The pending, success and error region is a real live region. */
.form {
  display: grid;
  gap: var(--s5);
  max-width: 52ch;
}

.field {
  display: grid;
  gap: var(--s2);
}

.field > label {
  font-size: 0.875rem;
  line-height: 1.35;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--hl-ink);
}

.field .hint {
  font-size: 0.8125rem;
  color: var(--muted);
}

input,
select,
textarea {
  width: 100%;
  min-height: var(--control);
  padding: 10px 12px;
  border: 1px solid var(--rule-soft);
  border-radius: var(--radius);
  background: #fdfcfc;
  color: var(--text);
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.4;
}

textarea {
  min-height: 160px;
  resize: vertical;
}

input:hover,
select:hover,
textarea:hover {
  border-color: var(--rule);
}

input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: #8c2f26;
}

.err {
  font-size: 0.8125rem;
  color: #7a2a22;
  min-height: 1.2em;
}

.status {
  font-size: 0.875rem;
  line-height: 1.5;
  padding: var(--s3) var(--s4);
  border-left: 3px solid var(--rule-soft);
  color: var(--muted);
}

.status[data-state="pending"] {
  border-left-color: var(--hl-ink);
  color: var(--text);
}

.status[data-state="ok"] {
  border-left-color: var(--action);
  color: var(--text);
}

.status[data-state="error"] {
  border-left-color: #8c2f26;
  color: var(--text);
}

.status:empty {
  display: none;
}

.consent {
  font-size: 0.8125rem;
  color: var(--muted);
}

/* The contact facts block. */
.facts {
  display: grid;
  gap: var(--s5);
  margin: 0;
}

.facts div {
  display: grid;
  gap: var(--s1);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule-soft);
}

.facts dt {
  font-size: 0.8125rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--hl-ink);
}

.facts dd {
  margin: 0;
  color: var(--text);
}

/* -------------------------------------------------------------------------
   9  GALLERY REEL — eight media, four ratios, deliberately uneven.
   ------------------------------------------------------------------------- */
.reel {
  display: grid;
  gap: var(--s5);
  margin: 0;
  padding: 0;
  list-style: none;
}

.plate {
  display: grid;
  gap: var(--s3);
}

.plate__frame {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--rule-soft);
  background: var(--bg-lift);
}

.plate__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(10, 12, 14, 0.5);
}

.plate img {
  width: 100%;
  height: auto;
}

.plate figcaption {
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--muted);
}

.plate figcaption b {
  display: block;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--hl-ink);
  font-size: 0.75rem;
}

/* The three-image home preview keeps the reel language, not a card grid. */
.strip {
  display: grid;
  gap: var(--s4);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* -------------------------------------------------------------------------
   10  STAFF — photographs of the work, never of a nameable person.
   ------------------------------------------------------------------------- */
.people {
  display: grid;
  gap: var(--s8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.person {
  display: grid;
  gap: var(--s4);
  max-width: 46ch;
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}

/*
   Section 17 asked for four portraits in 4:5 frames. The media direction
   then replaced the drawn emblems with photographs of the work each role
   does, framed so no face is in shot, so the frame carries a hairline and a
   solid field behind it rather than a colour edge drawn inside an SVG. The
   solid background matters twice: it is what the contrast sweep walks up to
   find, and it is what shows while a lazy photograph is still arriving.

   <picture> is inline by default, which would leave the image sized against
   the wrong box inside the .person grid, so the wrapper is made a block.
*/
.portrait-wrap {
  display: block;
}

.portrait {
  display: block;
  width: 100%;
  max-width: 240px;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border: 1px solid var(--hair);
  background: var(--field);
}

.portrait--sm {
  max-width: 112px;
}

.person__focus {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* -------------------------------------------------------------------------
   11  SUBSCRIBE BAND AND FOOTER
   ------------------------------------------------------------------------- */
.sub-form {
  display: grid;
  gap: var(--s3);
  max-width: 46ch;
}

.sub-form .row {
  display: grid;
  gap: var(--s3);
}

/*
   THE CREDITS CARD -- footer.

   Section 17 asks for four content zones and for a footer that "must feel
   designed, not like a dark rectangle added after the page", and forbids
   reusing one footer treatment across DS-01 to DS-09. The device carried down
   here is this design's own and no other's: the closing title card of a film.
   A centred END OF CHAPTER rule in Bodoni with two hairlines running out to
   the page edges opens the footer, the four zones read as a credit roll
   beneath it, and the fine print closes on a single line. Nothing about it
   transfers to a barbershop journal or a modular accounting grid.
*/
.credits {
  background: var(--field);
  border-top: 1px solid var(--hair);
  padding-block: 48px;
}

.credits .shell {
  display: grid;
  gap: var(--s6);
}

/* The signature: a credits-card divider, not a border. */
.credits__sig {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin: 0;
  font-family:var(--catalog-font-body);
  font-size: 0.8125rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--mark-gold);
}

.credits__sig::before,
.credits__sig::after {
  content: "";
  flex: 1 1 0;
  height: 1px;
  background: var(--hair);
}

.credits__grid {
  display: grid;
  gap: var(--s5);
}

.credits__zone {
  display: grid;
  gap: var(--s4);
  align-content: start;
}

/* 13px labels against 16px useful text -- the hierarchy section 17 asks for. */
.credits__lbl {
  margin: 0;
  font-family:var(--catalog-font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mark-gold);
}

.credits__mark {
  font-family:var(--catalog-font-body);
  font-size: 1.25rem;
  line-height: 1.1;
  letter-spacing: 0.02em;
  color: var(--text);
}

.credits__mark em {
  font-style: italic;
  color: var(--mark-gold);
}

.credits__sum {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--text);
  max-width: 34ch;
}

.credits__note {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--muted);
  max-width: 34ch;
}

/* Two compact navigation columns on mobile; one per zone from 1024px. */
.credits__zone nav ul,
.credits__zone > ul {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--s4);
  list-style: none;
  margin: 0;
  padding: 0;
}

.credits nav a {
  display: inline-block;
  padding: 6px 0;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text);
  text-decoration: none;
}

.credits nav a:hover,
.credits nav a[aria-current="page"] {
  color: var(--mark-gold);
}

.credits nav .is-book a {
  color: var(--action);
}

.credits .meta {
  font-size: 1rem;
  line-height: 1.7;
  color: var(--text);
}

.credits .meta a {
  color: var(--hl-ink);
}

.credits .facts {
  gap: var(--s3);
}

.credits .facts dd {
  font-size: 1rem;
}

.credits__rule {
  height: 1px;
  background: var(--hair);
}

.credits__fine {
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--muted);
}

.credits__fine a {
  color: var(--hl-ink);
}

@media (min-width: 768px) {
  .credits {
    padding-block: 80px;
  }

  .credits__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s6) 32px;
  }
}

@media (min-width: 1024px) {
  .credits__grid {
    grid-template-columns:
      minmax(0, 4fr) minmax(0, 3fr)
      minmax(0, 3fr) minmax(0, 4fr);
    gap: 32px;
  }

  .credits__zone nav ul,
  .credits__zone > ul {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* -------------------------------------------------------------------------
   12  RESPONSIVE CONTRACT
   Each block below is one line of section 7 of the specification.
   ------------------------------------------------------------------------- */

/* 360px — 18px gutters. Overlap of visual layers stays under 12px. */
@media (min-width: 360px) {
  :root {
    --gutter: 18px;
  }
}

/* 375px — 20px gutters. Two actions share a row only when each clears 148px. */
@media (min-width: 375px) {
  :root {
    --gutter: 20px;
  }

  .hero__actions,
  .cta__row,
  .sub-form .row {
    grid-template-columns: repeat(auto-fit, minmax(148px, auto));
    justify-content: start;
    gap: var(--s3);
  }
}

/* 390px — the hero crop may widen to 3:4. */
@media (min-width: 390px) {
  .hero__media {
    aspect-ratio: 3 / 4;
  }
}

/* 414px — two compact metadata columns allowed; body copy stays one column. */
@media (min-width: 414px) {
  :root {
    --gutter: 24px;
  }

  /* The wordmark can carry its third word again. */
  .mark__tail {
    display: inline;
  }
}

/* 768px — desktop identity begins. Media becomes the chapter's ground plane. */
@media (min-width: 768px) {
  .bar .btn--book {
    padding: 0 20px;
    font-size: 0.9375rem;
    letter-spacing: 0.06em;
  }

  :root {
    --gutter: 36px;
    --header-h: 64px;
    --section: 112px;
    --letterbox: 20px;
  }

  body {
    font-size: 1.0625rem;
  }

  h1 {
    font-size: clamp(3.25rem, 7vw, 7rem);
    line-height: 0.94;
    letter-spacing: -0.035em;
  }

  /*
     The hours list goes two-up here and not at 414px, where it used to.
     Every .facts on this site sits inside .credits__grid, and that grid
     splits in two at 414px. Splitting both at once left each hours row a
     70px track for "8:00 AM to 8:00 PM", whose min-content width is 85px,
     so the times painted 15px outside their own column. At 768px the
     surrounding column is wide enough for the split to hold.
  */
  .facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s5) var(--s6);
  }

  .hero {
    grid-template-rows: 1fr;
  }

  .hero__media {
    position: absolute;
    inset: 0;
    aspect-ratio: auto;
    height: 100%;
  }

  .hero__body {
    padding-block: var(--s10) var(--s9);
    align-content: end;
  }

  /*
     From 768px up the opening card stops being stacked under the media and
     starts sitting ON it, and that is where the only real contrast problem in
     this hero lives. The vertical scrim was tuned for the bottom of the frame;
     the chapter label sits high in the text column, where that scrim is near
     its thinnest, and a bright area of the photograph directly behind it took
     the label to 1.9:1 -- measured behind the glyphs themselves, not over the
     element box. It is not the film's doing: the poster alone measures 1.8:1
     in the same place, and it went unseen because a contrast sweep reads
     declared colours and cannot see the picture underneath.

     The remedy is horizontal rather than vertical, so the photograph keeps
     the openness it was composed for. The text column is the left third; the
     wash is heaviest there and is gone by the middle of the frame, which
     leaves the subject of the film and the right two thirds of the room
     untouched.
  */
  .hero__scrim::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to right, rgba(10, 12, 14, 0.78) 0%, rgba(10, 12, 14, 0.5) 34%, rgba(10, 12, 14, 0) 60%);
  }

  .hero__body > * {
    max-width: 18ch;
  }

  .hero__body .lede,
  .hero__body .film {
    max-width: 42ch;
  }

  .chapter--split .split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--s8);
  }

  .reel {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s6);
  }

  .strip {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s6);
  }

  /*
     A steps list nested inside a split column has roughly a third of the
     measure to work with, not the whole of it. Three-up there gave each step
     an 84px track for headings whose min-content width is 101px, so the text
     painted outside its own column. A nested list stays one column.
  */
  .split .steps {
    grid-template-columns: minmax(0, 1fr);
  }

  .people {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s8) var(--s7);
  }

  /* Offsetting the second column stops four records reading as a card grid. */
  .people > li:nth-child(even) {
    transform: translateY(var(--s7));
  }

  .quotes {
    gap: var(--s9);
  }

  .quote:nth-child(even) {
    margin-left: auto;
  }

  .credits .shell {
    gap: var(--s7);
  }
}

/* 1024px — chapters take the whole viewport, overlay links replace the sheet. */
@media (min-width: 1024px) {
  :root {
    --gutter: 48px;
    --section: 144px;
    --letterbox: 24px;
  }

  .bar {
    padding-inline: 24px;
    gap: 20px;
  }

  .bar__nav {
    display: block;
  }

  .drawer {
    display: none;
  }

  .mark {
    font-size: 1.0625rem;
  }

  /*
     The chapter must not become an ordinary centered container here. The
     content column is pinned to the left of a 1240px measure, the media
     plane runs full bleed behind it, and the index marker sits in the right
     third. That asymmetry is the composition.
  */
  .chapter--full .chapter__body .shell {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    gap: var(--s8);
    align-items: end;
  }

  .chapter--full .chapter__aside {
    align-self: end;
    display: grid;
    gap: var(--s3);
    justify-items: end;
    text-align: right;
  }

  .chapter--full .chapter__aside .rule {
    width: 100%;
    height: 1px;
    background: var(--rule);
  }

  .chapter--open .chapter__inner {
    max-width: 46ch;
  }

  .hero__body > * {
    max-width: 16ch;
  }

  .reel {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: var(--s7) var(--s6);
    align-items: start;
  }

  /*
     Spans are authored per position, not derived from the ratio, because the
     eight spans have to total 24 — four exact rows of six. A span set derived
     from the ratio alone comes to 22 and leaves a hole in the second row.
  */
  .plate--s2 {
    grid-column: span 2;
  }

  .plate--s4 {
    grid-column: span 4;
  }

  .people {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s9) var(--s8);
  }
}

/* 1600px — content centres at 1240px; full-bleed media may reach 1600px. */
@media (min-width: 1600px) {
  .chapter__media {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(100vw, 1600px);
  }

  .hero__media {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(100vw, 1600px);
  }

  .chapter__scrim,
  .hero__scrim {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(100vw, 1600px);
  }

  .bar {
    padding-inline: max(48px, calc((100vw - var(--maxw)) / 2));
  }
}

/* -------------------------------------------------------------------------
   13  THE SIGNATURE EFFECT — chapter crossfade.
   Every rule here is additive and is applied only when chapters.ts has
   confirmed that an IntersectionObserver exists and that the visitor has not
   asked for reduced motion. Without the `js-reveal` class on <html> the
   chapters are simply visible, which is the designed static composition.
   ------------------------------------------------------------------------- */
.js-reveal .chapter__body,
.js-reveal .plate,
.js-reveal .quote,
.js-reveal .person {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--t-long), transform var(--t-long);
}

.js-reveal .chapter.is-on .chapter__body,
.js-reveal .plate.is-on,
.js-reveal .quote.is-on,
.js-reveal .person.is-on {
  opacity: 1;
  transform: none;
}

/* The hero never waits for anything. It is the first paint. */
.js-reveal .hero .hero__body {
  opacity: 1;
  transform: none;
}

/* The media plane settles rather than moves: a 600ms crossfade, no parallax. */
.js-reveal .chapter--full .chapter__media {
  opacity: 0.55;
  transition: opacity var(--t-long);
}

.js-reveal .chapter--full.is-on .chapter__media {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  /* The designed static composition, restored in full. */
  .js-reveal .chapter__body,
  .js-reveal .plate,
  .js-reveal .quote,
  .js-reveal .person,
  .js-reveal .chapter--full .chapter__media {
    opacity: 1;
    transform: none;
  }

  .people > li:nth-child(even) {
    transform: translateY(var(--s7));
  }

  /*
     The film is never started under this preference -- `autoplay` is absent
     and film.ts gates play() on the same query. This is the second half of
     that promise: if the preference is switched on while the film is already
     running, the poster comes back at once instead of fading back.
  */
  .hero__film,
  .hero__film[data-playing] {
    opacity: 0;
  }
}

@media (forced-colors: active) {
  .chapter__scrim,
  .hero__scrim {
    display: none;
  }

  .btn {
    border: 1px solid currentColor;
  }
}

@media print {
  .bar,
  .drawer,
  .chapter__media,
  .chapter__scrim,
  .hero__media {
    display: none !important;
  }

  body {
    background: #fff;
    color: #000;
  }

  .chapter--full {
    min-height: 0;
  }
}

/* -------------------------------------------------------------------------
   14  THE SECTION 17 SIGNATURE SYSTEM

   One chapter number, one 6px progress marker and one 21:9 cinematic still
   on every page, drawn on #101010 fields with #E0A458 marks and 1px
   rgba(255,255,255,.18) rules. Every rule here is part of the static
   composition; the only motion is the 600ms crossfade already declared in
   section 13, and it is never required to read the page.
   ------------------------------------------------------------------------- */

/* 14.1  The progress marker -- ten segments, one lit, exactly 6px tall.
   It rides under the fixed bar so the visitor's position in the sequence is
   legible from the first paint of every page, not only after a scroll. */
.prog {
  position: fixed;
  top: var(--header-h);
  left: 0;
  right: 0;
  z-index: 79;
  display: flex;
  gap: 2px;
  height: 6px;
  padding-inline: var(--gutter);
  background: var(--field);
}

.prog span {
  flex: 1 1 0;
  background: rgba(37, 24, 25, 0.12);
}

.prog span.is-here {
  background: var(--mark-gold);
}

/* 14.2  The 21:9 cinematic still. */
.atmos {
  background: var(--field);
  border-block: 1px solid var(--hair);
  padding-block: var(--section);
}

.atmos .shell {
  display: grid;
  gap: var(--s4);
}

.atmos__frame {
  position: relative;
  overflow: hidden;
  aspect-ratio: 21 / 9;
  background: var(--bg-lift);
  border: 1px solid var(--hair);
}

.atmos__frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.atmos__note {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  align-items: baseline;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--muted);
}

.atmos__note b {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mark-gold);
}

/* 14.3  Service scene cards: 40 per cent image, 60 per cent copy, alternating,
   all six on one shared 3:2 crop. Six identical dark rectangles is the thing
   section 17 names as the defect, so the silhouette flips every card. */
.scenes {
  display: grid;
  gap: var(--s8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.scene {
  display: grid;
  gap: var(--s5);
}

.scene__media {
  position: relative;
  overflow: hidden;
  aspect-ratio: 3 / 2;
  background: var(--bg-lift);
}

.scene__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.scene__media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px var(--hair);
}

.scene__num {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;
  padding: var(--s2) var(--s3);
  background: var(--field);
  color: var(--mark-gold);
  font-family:var(--catalog-font-heading);
  font-size: 0.9375rem;
  letter-spacing: 0.2em;
}

.scene__body {
  display: grid;
  gap: var(--s3);
  align-content: start;
  max-width: var(--measure);
}

.scene__price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s2) var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--hair);
}

.scene__price b {
  font-family:var(--catalog-font-heading);
  font-size: 1.375rem;
  font-weight: 400;
  color: var(--text);
}

.scene__price span {
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mark-gold);
}

/* 14.4  Reviews: one lead testimony, then compact frames with 64px marks. */
.quote__mark {
  display: block;
  font-family:var(--catalog-font-body);
  font-size: 64px;
  line-height: 0.62;
  height: 40px;
  color: var(--mark-gold);
}

.quote--lead {
  max-width: var(--measure);
  border-top: 0;
  padding-top: 0;
  /* it is a <blockquote>, and the UA gives that 40px of side margin */
  margin: 0;
}

.quote--lead .quote__text {
  font-size: clamp(1.5rem, 3vw, 2.5rem);
}

.quote__id {
  display: flex;
  align-items: center;
  gap: var(--s4);
}

.quote__avatar {
  flex: 0 0 auto;
  width: 64px;
  height: 64px;
  background: var(--field);
  border: 1px solid var(--hair);
}

.quote__avatar img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.quote__tag {
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mark-gold);
}

.quote__when {
  font-size: 0.8125rem;
  color: var(--muted);
}

.quote__count {
  font-family:var(--catalog-font-body);
  font-size: 0.8125rem;
  letter-spacing: 0.2em;
  color: var(--hl-ink);
}

/* 14.5  FAQ: a chapter index over native details on a film-strip field.
   No text on this field drops below full opacity; section 17 sets a floor of
   .82 and the simplest way to honour it is not to reduce opacity at all. */
.filmstrip {
  background-color: var(--field);
  background-image:
    repeating-linear-gradient(to bottom, rgba(37, 24, 25, 0.06) 0 12px, transparent 12px 36px),
    repeating-linear-gradient(to bottom, rgba(37, 24, 25, 0.06) 0 12px, transparent 12px 36px);
  background-size: 8px 36px, 8px 36px;
  background-position: left 10px top, right 10px top;
  background-repeat: repeat-y, repeat-y;
}

.idx {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s5);
  margin: 0;
  padding: 0;
  list-style: none;
}

.idx a {
  display: inline-block;
  padding: 6px 0;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--hl-ink);
}

.idx a:hover {
  color: var(--mark-gold);
}

.faqs {
  display: grid;
  gap: var(--s3);
  max-width: min(100%, 64rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.faq {
  background: var(--field);
  border: 1px solid var(--hair);
}

.faq > summary {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  min-height: var(--control);
  padding: var(--s4);
  cursor: pointer;
  list-style: none;
  color: var(--text);
}

.faq > summary::-webkit-details-marker {
  display: none;
}

.faq > summary:hover {
  color: var(--mark-gold);
}

.faq__idx {
  flex: 0 0 auto;
  font-family:var(--catalog-font-body);
  font-size: 0.8125rem;
  letter-spacing: 0.2em;
  color: var(--mark-gold);
}

.faq__q {
  margin: 0;
  font-family:var(--catalog-font-body);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: 0;
  text-transform: none;
}

.faq__a {
  padding: 0 var(--s4) var(--s4) var(--s4);
  color: var(--muted);
  max-width: 68ch;
}

/* 14.6  Contact: the split closing scene. */
.close-scene {
  background: var(--field);
  border-top: 1px solid var(--hair);
  padding-block: var(--section);
}

.close-scene .shell {
  display: grid;
  gap: var(--s6);
  align-items: start;
}

.close-scene__still {
  position: relative;
  overflow: hidden;
  aspect-ratio: 3 / 2;
  background: var(--bg-lift);
  border: 1px solid var(--hair);
}

.close-scene__still img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.close-scene__facts {
  display: grid;
  gap: var(--s5);
  margin-top: var(--s5);
}

/* Headings in this design carry no margin of their own, and each half of the
   scene stacks a heading over its own block. */
.close-scene .shell > div > h2 {
  margin-bottom: var(--s5);
}

/* A near-black solid field for the form, distinct from the textured still. */
.close-scene__form {
  background: #fdfcfc;
  border: 1px solid var(--hair);
  padding: var(--s5);
}

/* 50px fields and a 2px focus outline, both named by section 17. */
.close-scene__form input,
.close-scene__form select,
.close-scene__form textarea {
  min-height: 50px;
  padding: 13px 14px;
  background: var(--field);
}

.close-scene__form textarea {
  min-height: 150px;
}

.close-scene__form :focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/*
   The response region is reserved, not conjured. .status:empty hides every
   other status on the site, which is right for a subscribe row inside a
   footer column; here the height has to be held so the form does not jump
   when the demonstration endpoint answers.
*/
.status--held {
  display: flex;
  align-items: center;
  min-height: 56px;
  border-left-color: var(--hair);
}

.status--held:empty {
  display: flex;
}

/* 14.7  About: three acts against a chapter rail. */
.railed {
  display: grid;
  gap: var(--s6);
}

.rail {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3) var(--s5);
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail li {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.rail b {
  font-weight: 600;
  color: var(--mark-gold);
}

.acts {
  display: grid;
  gap: var(--s7);
  margin: 0;
  padding: 0;
  list-style: none;
}

.act {
  display: grid;
  gap: var(--s3);
  padding-top: var(--s4);
  border-top: 1px solid var(--hair);
  max-width: var(--measure);
}

.act__num {
  font-family:var(--catalog-font-heading);
  font-size: 0.8125rem;
  letter-spacing: 0.2em;
  color: var(--mark-gold);
}

/* 14.8  Privacy: a solid field and a narrow contents rail, no video plane. */
.policy {
  background: var(--field);
  padding-block: var(--section);
}

.policy .shell {
  display: grid;
  gap: var(--s6);
  align-items: start;
}

.policy__body {
  display: grid;
  gap: var(--s6);
  max-width: 68ch;
}

.toc {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s5);
  margin: 0;
  padding-top: var(--s3);
  border-top: 1px solid var(--hair);
  list-style: none;
}

.toc a {
  display: inline-block;
  padding: 6px 0;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  color: var(--hl-ink);
}

.toc a:hover {
  color: var(--mark-gold);
}

/* Each part of the notice is a chapter number, a gold rule, a title and the
   text -- four stacked blocks, and headings in this design carry no margin. */
.policy__body > section {
  display: grid;
  gap: var(--s3);
}

.policy__body > h2 {
  margin-bottom: var(--s3);
}

/* The credits chapter sits under the notice on the same page and shares its
   ground, so it needs a hairline of its own to read as a separate chapter
   rather than an eleventh part of the notice. Everything else it inherits from
   `.policy`, including the contents rail -- which is why it carries a `.toc` of
   its own rather than a reset grid: a single child in that two-column layout
   would have left the body flush against the rail column with the measure
   empty beside it. */
.credits-page {
  border-top: 1px solid var(--hair);
}

.cred {
  display: grid;
  gap: var(--s5);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Each entry is three lines: the work, who made it and under what licence,
   and what this website did to it. CC BY asks for the first two and the third
   together, so they are kept as one block that cannot be split up. */
.cred__item {
  display: grid;
  gap: var(--s1);
  padding-top: var(--s3);
  border-top: 1px solid var(--hair);
}

.cred__work {
  font-family:var(--catalog-font-body);
  font-size: 1.0625rem;
  line-height: 1.35;
  color: var(--text);
  margin: 0;
}

.cred__who,
.cred__what {
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--hl-ink);
  margin: 0;
}

.cred__what {
  color: var(--muted);
}

/* 14.9  404: the end card. */
.endcard {
  background: var(--field);
  border: 1px solid var(--hair);
  display: grid;
  gap: var(--s5);
  padding: var(--s5);
}

.endcard__still {
  position: relative;
  overflow: hidden;
  aspect-ratio: 21 / 9;
  background: var(--bg-lift);
}

.endcard__still img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The copy half of the card: a mark, a heading, a sentence, the routes and the
   Book action, evenly spaced and centred against the still beside it. */
.endcard__copy {
  display: grid;
  gap: var(--s4);
  align-content: center;
}

.endcard__routes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
}

/* 14.10  Responsive behaviour for the section 17 components. */
@media (min-width: 768px) {
  .scene {
    grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
    gap: var(--s6);
    align-items: start;
  }

  .scene--flip .scene__media {
    order: 2;
  }

  .close-scene .shell {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--s7);
  }

  .endcard {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--s6);
    padding: var(--s6);
  }
}

@media (min-width: 1024px) {
  .atmos .shell {
    gap: var(--s5);
  }

  .close-scene .shell {
    gap: var(--s8);
  }

  .railed {
    grid-template-columns: minmax(0, 3fr) minmax(0, 9fr);
    gap: var(--s8);
  }

  .policy .shell {
    grid-template-columns: minmax(0, 3fr) minmax(0, 9fr);
    gap: var(--s8);
  }

  /* The rail turns vertical and holds position beside the acts. */
  .rail {
    position: sticky;
    top: calc(var(--header-h) + var(--s5));
    display: grid;
    gap: var(--s4);
  }

  .rail li {
    display: grid;
    gap: var(--s1);
    padding-top: var(--s3);
    border-top: 1px solid var(--hair);
  }

  .toc {
    position: sticky;
    top: calc(var(--header-h) + var(--s5));
    display: grid;
    gap: var(--s2);
  }
}

/* The progress marker is furniture, not content: it does not print. */
/* =========================================================================
   15  GALLERY BREAKS
   Section 17 asks the gallery for "two full-bleed 21:9 breaks". The closing
   still on the other pages is a framed plate inside the measure; a break is
   the same still with the frame taken away, running edge to edge so the reel
   is interrupted by the room itself rather than by another bordered box. The
   note keeps the gutter so the 13px caption line still sits on the measure.
   ========================================================================= */
.atmos--bleed {
  border-block: 0;
  padding-block: 0;
}

.atmos--bleed .shell {
  max-width: none;
  padding-inline: 0;
  gap: 0;
}

.atmos--bleed .atmos__frame {
  border-inline: 0;
}

.atmos--bleed .atmos__note {
  padding: var(--s4) var(--gutter);
  border-bottom: 1px solid var(--hair);
}

@media print {
  .prog {
    display: none !important;
  }
}

/* ============================== the emblem ==============================

   A lantern drawn as a strip of film: cap, body, base, three sprocket
   perforations down each side, and the flame carried as the gold chapter
   mark.  The body is `currentColor` so the lantern inverts correctly
   wherever it sits; only the flame is a literal, because the gold is the
   one colour that has to stay gold in a browser tab.

   Fixed boxes, so the header bar and the credits zone reserve their space
   before the stylesheet lands.                                          */

.emb { display: block; flex: 0 0 auto; width: 22px; height: 22px; }

.mark { display: inline-flex; align-items: center; gap: 10px; }

.credits__mark { display: flex; align-items: center; gap: 12px; }
.credits__mark .emb { width: 30px; height: 30px; }

/* ============================ the social row ============================

   Five platform links in the "Find the room" zone of the credits, added by
   `_build-tools/clone/ds02-restaurant-cafe/add_social.py` after the hours
   list.  The marks are inline SVG on the same 0 0 24 24 box as `.emb`, so
   they sit at the lantern size and inherit `currentColor`.

   The child combinator is not decoration.  `.credits__zone > ul` above sets
   every direct list child of a credits zone to a two-column link grid, and
   this row is a direct list child of a credits zone.  A bare `.foot__social`
   would be the LESS specific of the two and would lose, leaving five 44px
   buttons stacked two-up down the column.  Matching the same combinator with
   a class instead of the element name wins on specificity without an
   !important and without editing the nav rule the ten page footers rely on.

   44px is the `--control` tap target section 7 asks for, and the row is
   measured to survive the 320px floor: five of them plus four 8px gaps is
   252px against the 288px a 320px viewport leaves inside a 16px gutter.  It
   wraps rather than overflows if a sixth ever arrives.

   Muted at rest so the row reads as a quiet aside under the opening hours,
   gold on hover and on keyboard focus so it answers the same way the rest of
   the footer does.  The transition is the shared `--t-std` and is already
   covered by the reduced-motion block in section 2.                       */

.credits__zone > .foot__social {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin: var(--s2) 0 0;
  padding: 0;
  list-style: none;
}

.foot__social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control);
  height: var(--control);
  color: var(--muted);
  border: 1px solid var(--rule-soft);
  border-radius: var(--radius);
  transition: color var(--t-std), border-color var(--t-std);
}

.foot__social a:hover,
.foot__social a:focus-visible {
  color: var(--mark-gold);
  border-color: var(--mark-gold);
}

.soc {
  display: block;
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
}

/* >>> fix_contexts.py */
/* Overlay bar: one solid light plane under dark ink (a translucent gradient
   let the >=1100px letterbox show through as a grey band). */
.bar {
  background: #f8f1f2;
}
.drawer > summary { background: #fdfcfc; }

/* Below 768px the scrim covers the media band only, not the text under it. */
@media (max-width: 767.98px) {
  .hero__scrim { grid-row: 1 / 2; grid-column: 1 / 2; }
}
/* "Book a consultation" is longer than the reference label: stack the two
   actions at their own width instead of wrapping them inside 148px tracks. */
@media (min-width: 375px) {
  .hero__actions,
  .cta__row { grid-template-columns: max-content; }
}
@media (min-width: 768px) {
  .hero__body > .hero__actions,
  .hero__body > .chapter__mark { max-width: none; }
  .hero__actions .btn { white-space: nowrap; }
  /* Ground under the scrim is dark too, so computed contrast matches what paints. */
  .hero { background-color: #1a1112; }
.hero__body {
  --text: #ffffff;
  --muted: #eadcdd;
  --hl-ink: #b2f0c7;
  --mark-gold: #f2c4c7;
  --rule: rgba(255, 255, 255, 0.34);
  --rule-soft: rgba(255, 255, 255, 0.2);
  --hair: rgba(255, 255, 255, 0.22);
  --focus: #b2f0c7;
  color: var(--text);
}
.hero__body a:not(.btn):hover,
.hero__body .link:hover { color: #ffffff; text-decoration-color: currentColor; }
.hero__body .num { color: var(--mark-gold); }
.hero__body .btn--book { border-color: var(--hl-ink); }
.hero__body .btn--ghost:hover { border-color: var(--hl-ink); color: var(--hl-ink); }
.hero__body input,
.hero__body select,
.hero__body textarea { color: #251819; }
}

/* Photograph chapters (reviews lead): the chapter scrim stays dark at every width. */
.chapter:has(> .chapter__scrim) { background-color: #1a1112; }
.chapter__scrim ~ .chapter__body {
  --text: #ffffff;
  --muted: #eadcdd;
  --hl-ink: #b2f0c7;
  --mark-gold: #f2c4c7;
  --rule: rgba(255, 255, 255, 0.34);
  --rule-soft: rgba(255, 255, 255, 0.2);
  --hair: rgba(255, 255, 255, 0.22);
  --focus: #b2f0c7;
  color: var(--text);
}
.chapter__scrim ~ .chapter__body a:not(.btn):hover,
.chapter__scrim ~ .chapter__body .link:hover { color: #ffffff; text-decoration-color: currentColor; }
.chapter__scrim ~ .chapter__body .num { color: var(--mark-gold); }
.chapter__scrim ~ .chapter__body .btn--book { border-color: var(--hl-ink); }
.chapter__scrim ~ .chapter__body .btn--ghost:hover { border-color: var(--hl-ink); color: var(--hl-ink); }
.chapter__scrim ~ .chapter__body input,
.chapter__scrim ~ .chapter__body select,
.chapter__scrim ~ .chapter__body textarea { color: #251819; }

/* Wedding headings are short words: no soft breaks ("wed-dings", "ques-tions"). */
.chapter--open h1 { hyphens: manual; }

/* fix2-1: an email address never splits inside a word. */
.mail-seg { white-space: nowrap; }
/* The menu sheet link is a flex row with a gap: that spread the pieces apart and
   stopped them wrapping. No gap, and wrap only at the piece seams. */
a[href^="mailto:"] { flex-wrap: wrap; column-gap: 0; }

/* fix2-2: the closing contact buttons sit side by side from 1100px. */
@media (min-width: 1100px) {
  .cta__row { grid-template-columns: repeat(2, max-content); }
}

/* fix3-1: home service cards. The UA figure margin (40px a side) shrank each
   thumbnail to ~90-220px. Fill the card column at an even 4:5, like the gallery. */
@media (min-width: 1024px) {
  .home-page [aria-labelledby="svc-h"] .strip { gap: var(--s4); align-items: start; }
  .home-page [aria-labelledby="svc-h"] .plate { margin: 0; }
  .home-page [aria-labelledby="svc-h"] .plate__frame { aspect-ratio: 4 / 5; }
  .home-page [aria-labelledby="svc-h"] .plate__frame picture { display: block; height: 100%; }
  .home-page [aria-labelledby="svc-h"] .plate__frame img { width: 100%; height: 100%; object-fit: cover; }
  /* fix3-2: the Approach still was a 160-350px stamp for the same reason. */
  .home-page [aria-labelledby="how-h"] .still { margin: 0; width: 100%; }
  .home-page [aria-labelledby="how-h"] .still img { display: block; width: 100%; height: auto; }
}
/* From 1100 the chapter sits in a half-width cell: put the still full width under the text. */
@media (min-width: 1100px) {
  .home-page [aria-labelledby="how-h"] .split { grid-template-columns: minmax(0, 1fr); align-items: start; gap: var(--s6); }
}
/* fix2-3: home gallery and staff strips, >=1024px. Each figure kept the UA
   40px side margins, which shrank the plates to slivers inside the
   half-width scene, and mixed photo ratios made the row uneven. Frames are
   one 4:5 ratio, cropped with object-fit; staff portraits share it. */
@media (min-width: 1024px) {
  .home-page [aria-labelledby="gal-h"] .strip { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); align-items: start; }
  .home-page [aria-labelledby="gal-h"] .plate { margin: 0; }
  .home-page [aria-labelledby="gal-h"] .plate__frame { aspect-ratio: 4 / 5; }
  .home-page [aria-labelledby="gal-h"] .plate__frame picture { display: block; height: 100%; }
  .home-page [aria-labelledby="gal-h"] .plate__frame img { width: 100%; height: 100%; object-fit: cover; }
  .home-page [aria-labelledby="ppl-h"] .people { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
  .home-page [aria-labelledby="ppl-h"] .people > li:nth-child(even) { transform: none; }
  .home-page [aria-labelledby="ppl-h"] .portrait--sm { width: 100%; max-width: 224px; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
}

/* Bar below 414px: the full wordmark on one line. Smaller type and emblem,
   8px bar gap, compact Book, and an icon-only disclosure (its aria-label
   "All pages" stays the accessible name). */
@media (max-width: 413.98px) {
  .mark__tail { display: inline; }
  .bar { gap: var(--s2); }
  .mark { font-size: 12px; letter-spacing: 0; gap: 6px; }
  .mark .emb { width: 18px; height: 18px; }
  .bar .btn--book { padding: 0 10px; }
  .drawer > summary { font-size: 0; letter-spacing: 0; padding: 0; }
}
@media (min-width: 360px) and (max-width: 413.98px) {
  .mark { font-size: 13px; }
}

/* .scene__num is absolute with no positioned ancestor, so the six service
   numbers stacked on one spot; it flows as a chip above the heading instead.
   The 404 route list is a flex row that still painted list markers. */
.scene__num { position: static; justify-self: start; }
.endcard__routes { list-style: none; margin: 0; padding: 0; }

/* Section 9 footer: #381E20 ground, #FFFFFF text. */
.credits { background: #381e20; border-top-color: #381e20; }
.credits nav .is-book a { color: var(--hl-ink); }
.credits .emb circle { fill: #f2c4c7; }
.credits {
  --text: #ffffff;
  --muted: #eadcdd;
  --hl-ink: #b2f0c7;
  --mark-gold: #f2c4c7;
  --rule: rgba(255, 255, 255, 0.34);
  --rule-soft: rgba(255, 255, 255, 0.2);
  --hair: rgba(255, 255, 255, 0.22);
  --focus: #b2f0c7;
  color: var(--text);
}
.credits a:not(.btn):hover,
.credits .link:hover { color: #ffffff; text-decoration-color: currentColor; }
.credits .num { color: var(--mark-gold); }
.credits .btn--book { border-color: var(--hl-ink); }
.credits .btn--ghost:hover { border-color: var(--hl-ink); color: var(--hl-ink); }
.credits input,
.credits select,
.credits textarea { color: #251819; }

@media (min-width: 1100px) {
  /* The closing contact section sat in the same grid cell as the closing
     still and painted its gradient over the photograph. Give it its own row. */
  .home-page main > .atmos { min-height: 0; }
  .home-page main > .cta {
    grid-area: auto;
    grid-column: 1 / -1;
    grid-row: 6;
    align-self: stretch;
    background: #381e20;
  }
  .home-page main > .cta::before,
  .home-page main > .cta::after { background: transparent; box-shadow: none; }
.home-page main > .cta {
  --text: #ffffff;
  --muted: #eadcdd;
  --hl-ink: #b2f0c7;
  --mark-gold: #f2c4c7;
  --rule: rgba(255, 255, 255, 0.34);
  --rule-soft: rgba(255, 255, 255, 0.2);
  --hair: rgba(255, 255, 255, 0.22);
  --focus: #b2f0c7;
  color: var(--text);
}
.home-page main > .cta a:not(.btn):hover,
.home-page main > .cta .link:hover { color: #ffffff; text-decoration-color: currentColor; }
.home-page main > .cta .num { color: var(--mark-gold); }
.home-page main > .cta .btn--book { border-color: var(--hl-ink); }
.home-page main > .cta .btn--ghost:hover { border-color: var(--hl-ink); color: var(--hl-ink); }
.home-page main > .cta input,
.home-page main > .cta select,
.home-page main > .cta textarea { color: #251819; }
}
/* <<< fix_contexts.py */

/* fix4-1: gallery Act 03 paired a 278px landscape with a 670px portrait.
   The two plates share the row evenly at one 4:5 frame. */
@media (min-width: 1024px) {
  [aria-labelledby="act-c-h"] .reel > li { grid-column: span 3; }
  [aria-labelledby="act-c-h"] .plate__frame { aspect-ratio: 4 / 5; }
  [aria-labelledby="act-c-h"] .plate__frame picture { display: block; height: 100%; }
  [aria-labelledby="act-c-h"] .plate__frame img { width: 100%; height: 100%; object-fit: cover; }
}

/* fix4-2: the home page now carries all six services and all four people.
   Half-width, those two panels ran twice the height of their neighbours and
   left empty panels beside them, so each takes a full-width row and the
   Approach and Gallery scenes share one. */
@media (min-width: 1100px) {
  .home-page main.page--hero {
    grid-template-areas:
      "hero hero"
      "services services"
      "approach gallery"
      "staff staff"
      "reviews faq"
      "closing closing";
  }
  .home-page main > [aria-labelledby="svc-h"],
  .home-page main > [aria-labelledby="ppl-h"] { border-right: 0; min-height: 0; }
  .home-page main > [aria-labelledby="how-h"] { border-right: 1px solid rgba(108,55,58,.25); }
  .home-page [aria-labelledby="ppl-h"] .people { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .home-page main > .cta { grid-row: 7; }
}

/* fix4-3: below 1024px the home service and gallery figures kept the UA 40px
   figure margins, which left 768px thumbnails at ~80px and 390px images
   inset. Same even frames as the desktop rule. */
.home-page [aria-labelledby="svc-h"] .plate,
.home-page [aria-labelledby="gal-h"] .plate,
.home-page [aria-labelledby="how-h"] .still { margin: 0; }
@media (min-width: 768px) and (max-width: 1023.98px) {
  .home-page [aria-labelledby="svc-h"] .strip,
  .home-page [aria-labelledby="gal-h"] .strip { gap: var(--s4); align-items: start; }
  .home-page [aria-labelledby="svc-h"] .plate__frame,
  .home-page [aria-labelledby="gal-h"] .plate__frame { aspect-ratio: 4 / 5; }
  .home-page [aria-labelledby="svc-h"] .plate__frame picture,
  .home-page [aria-labelledby="gal-h"] .plate__frame picture { display: block; height: 100%; }
  .home-page [aria-labelledby="svc-h"] .plate__frame img,
  .home-page [aria-labelledby="gal-h"] .plate__frame img { width: 100%; height: 100%; object-fit: cover; }
  .home-page [aria-labelledby="how-h"] .still img { display: block; width: 100%; height: auto; }
}
/* Catalogue typography identity — headings and reading text. */
:root{--catalog-font-heading:'Newsreader', Georgia, 'Times New Roman', serif;--catalog-font-body:'Manrope', system-ui, -apple-system, 'Segoe UI', Arial, sans-serif}
html body,input,select,textarea,button{font-family:var(--catalog-font-body)}
h1,h2,h3,h4,h5,h6,.display,.disp,.brand,.logo{font-family:var(--catalog-font-heading)}

/* aajwebz-mailto-nowrap — an address is one token, never split across lines */
a[href^="mailto:"] {
  overflow-wrap: normal;
  word-break: normal;
  white-space: nowrap;
  display: inline-block;
  max-width: 100%;
}
@media (max-width: 380px) {
  a[href^="mailto:"] { font-size: 0.88em; }
}
