/* reset.css: a small modern reset (the la-rosa and service-station base), loaded first by aurochs-ssg. */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { min-height: 100vh; line-height: 1.5; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; }
img, picture, video, canvas, svg { display: block; max-width: 100%; }
img { height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul[role="list"], ol[role="list"] { list-style: none; padding: 0; }
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
h1, h2, h3, h4, h5, h6 { font-weight: inherit; font-size: inherit; }
fieldset { border: 0; padding: 0; min-width: 0; }
legend { padding: 0; }
:target { scroll-margin-top: 24px; }

/* GENERATED by scripts/gen_tokens.py; edit the script or styles/tokens-*.json, never this file. */

:root {
  /* colour (the Figma "Color" collection) */
  --paper: #ffffff;
  --ink: #101010;
  --band: #000000;
  --on-band: #ffffff;
  --rule: rgba(16, 16, 16, 0.141);
  --dim: #5a5a5a;
  --note: #f4f4f2;

  /* type (comps-ref text styles; Nunito Sans and Fraunces stand in for Avenir Next, plan D-B5) */
  --font-sans: "Nunito Sans", "Nunito Sans Fallback", "Avenir Next", Avenir, "Segoe UI", Arial, sans-serif;
  --font-story: "Fraunces", "Fraunces Fallback", Georgia, "Times New Roman", serif;
  --lh-story-name: 1.05;  --ls-story-name: -0.01em;
  --lh-display: 1.18;
  --lh-h2: 1.25;
  --lh-h3: 1.3;
  --lh-body: 1.6;
  --lh-small: 1.5;
  --lh-label: 1.3;  --ls-label: 0.12em;
  --fs-nav: 15px;  --lh-nav: 1.2;  --ls-nav: 0.04em;
  --fs-button: 15px;  --lh-button: 1.2;  --ls-button: 0.06em;

  /* motion (plan section 5; the house standard: service-station comp-reveal.css, la-rosa tokens.css) */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-standard: cubic-bezier(0.2, 0.7, 0.2, 1);
  --duration-press: 100ms;
  --duration-fast: 140ms;
  --duration-base: 200ms;
  --duration-menu: 280ms;
  --duration-image: 400ms;
  --duration-reveal: 600ms;
  --duration-hover-image: 600ms;
  --reveal-shift: 24px;
  --reveal-stagger: 70ms;

  /* width-dependent values, held below 390 */
  --margin: 16px;
  --gutter: 8px;
  --collage-w: 358px;
  --tile-l-w: 175px;
  --tile-l-h: 267px;
  --tile-s-w: 103px;
  --tile-s-h: 145px;
  --radius: 8px;
  --section-gap: 64px;
  --block-gap: 24px;
  --gap: 12px;
  --header-h: 96px;
  --logo-w: 150px;
  --logo-h: 68px;
  --measure: 358px;
  --fs-story-name: 40px;
  --fs-display: 28px;
  --fs-h2: 22px;
  --fs-h3: 18px;
  --fs-body: 16px;
  --fs-small: 13px;
  --fs-label: 11px;
  --home-hero-h: 360px;
  --home-hero-x: 100%;
  --home-hero-y: 50%;
  --home-door-h: 440px;
  --home-line-w: 358px;
  --bb-title-photo-h: 300px;
  --bb-modeling-photo-h: 280px;
  --bb-homage-photo-w: 240px;
  --about-bio-gap: 32px;
  --about-press-gap: 12px;
  --bk-step-w: 89.5px;
  --sb-spread-h: 150px;
}

@media (min-width: 390px) {
  :root {
    --margin: calc(16px + 24 * (100vw - 390px) / 378);
    --gutter: calc(8px + 4 * (100vw - 390px) / 378);
    --collage-w: calc(358px + 330 * (100vw - 390px) / 378);
    --tile-l-w: calc(175px + 163 * (100vw - 390px) / 378);
    --tile-l-h: calc(267px + 249 * (100vw - 390px) / 378);
    --tile-s-w: calc(103px + 95 * (100vw - 390px) / 378);
    --tile-s-h: calc(145px + 134 * (100vw - 390px) / 378);
    --radius: calc(8px + 4 * (100vw - 390px) / 378);
    --section-gap: calc(64px + 32 * (100vw - 390px) / 378);
    --block-gap: calc(24px + 8 * (100vw - 390px) / 378);
    --gap: calc(12px + 4 * (100vw - 390px) / 378);
    --header-h: calc(96px + 24 * (100vw - 390px) / 378);
    --logo-w: calc(150px + 26 * (100vw - 390px) / 378);
    --logo-h: calc(68px + 12 * (100vw - 390px) / 378);
    --measure: calc(358px + 202 * (100vw - 390px) / 378);
    --fs-story-name: calc(40px + 16 * (100vw - 390px) / 378);
    --fs-display: calc(28px + 8 * (100vw - 390px) / 378);
    --fs-h2: calc(22px + 4 * (100vw - 390px) / 378);
    --fs-h3: 18px;
    --fs-body: 16px;
    --fs-small: 13px;
    --fs-label: calc(11px + 1 * (100vw - 390px) / 378);
    --home-hero-h: calc(360px + 200 * (100vw - 390px) / 378);
    --home-hero-x: 100%;
    --home-hero-y: 50%;
    --home-door-h: calc(440px + -140 * (100vw - 390px) / 378);
    --home-line-w: calc(358px + 330 * (100vw - 390px) / 378);
    --bb-title-photo-h: calc(300px + 120 * (100vw - 390px) / 378);
    --bb-modeling-photo-h: calc(280px + 120 * (100vw - 390px) / 378);
    --bb-homage-photo-w: calc(240px + 30 * (100vw - 390px) / 378);
    --about-bio-gap: 32px;
    --about-press-gap: 12px;
    --bk-step-w: calc(89.5px + 23.5 * (100vw - 390px) / 378);
    --sb-spread-h: calc(150px + 11 * (100vw - 390px) / 378);
  }
}

@media (min-width: 768px) {
  :root {
    --margin: calc(40px + 24 * (100vw - 768px) / 672);
    --gutter: calc(12px + 5 * (100vw - 768px) / 672);
    --collage-w: calc(688px + 379 * (100vw - 768px) / 672);
    --tile-l-w: calc(338px + 187 * (100vw - 768px) / 672);
    --tile-l-h: calc(516px + 285 * (100vw - 768px) / 672);
    --tile-s-w: calc(198px + 109 * (100vw - 768px) / 672);
    --tile-s-h: calc(279px + 154 * (100vw - 768px) / 672);
    --radius: calc(12px + 5 * (100vw - 768px) / 672);
    --section-gap: calc(96px + 32 * (100vw - 768px) / 672);
    --block-gap: calc(32px + 8 * (100vw - 768px) / 672);
    --gap: calc(16px + 4 * (100vw - 768px) / 672);
    --header-h: calc(120px + 76 * (100vw - 768px) / 672);
    --logo-w: calc(176px + 88 * (100vw - 768px) / 672);
    --logo-h: calc(80px + 40 * (100vw - 768px) / 672);
    --measure: calc(560px + 60 * (100vw - 768px) / 672);
    --fs-story-name: calc(56px + 19 * (100vw - 768px) / 672);
    --fs-display: calc(36px + 8 * (100vw - 768px) / 672);
    --fs-h2: calc(26px + 4 * (100vw - 768px) / 672);
    --fs-h3: calc(18px + 2 * (100vw - 768px) / 672);
    --fs-body: calc(16px + 1 * (100vw - 768px) / 672);
    --fs-small: calc(13px + 1 * (100vw - 768px) / 672);
    --fs-label: 12px;
    --home-hero-h: calc(560px + -100 * (100vw - 768px) / 672);
    --home-hero-x: 50%;
    --home-hero-y: 50%;
    --home-door-h: calc(300px + 220 * (100vw - 768px) / 672);
    --home-line-w: calc(688px + 72 * (100vw - 768px) / 672);
    --bb-title-photo-h: calc(420px + 220 * (100vw - 768px) / 672);
    --bb-modeling-photo-h: calc(400px + 200 * (100vw - 768px) / 672);
    --bb-homage-photo-w: calc(270px + 37 * (100vw - 768px) / 672);
    --about-bio-gap: calc(32px + 8 * (100vw - 768px) / 672);
    --about-press-gap: calc(12px + 5 * (100vw - 768px) / 672);
    --bk-step-w: calc(113px + 42 * (100vw - 768px) / 672);
    --sb-spread-h: calc(161px + 19 * (100vw - 768px) / 672);
  }
}

@media (min-width: 1440px) {
  :root {
    --margin: calc(64px + 32 * (100vw - 1440px) / 480);
    --gutter: calc(17px + 3 * (100vw - 1440px) / 480);
    --collage-w: calc(1067px + 213 * (100vw - 1440px) / 480);
    --tile-l-w: calc(525px + 105 * (100vw - 1440px) / 480);
    --tile-l-h: calc(801px + 161 * (100vw - 1440px) / 480);
    --tile-s-w: calc(307px + 62 * (100vw - 1440px) / 480);
    --tile-s-h: calc(433px + 87 * (100vw - 1440px) / 480);
    --radius: calc(17px + 3 * (100vw - 1440px) / 480);
    --section-gap: calc(128px + 32 * (100vw - 1440px) / 480);
    --block-gap: calc(40px + 8 * (100vw - 1440px) / 480);
    --gap: calc(20px + 4 * (100vw - 1440px) / 480);
    --header-h: calc(196px + 24 * (100vw - 1440px) / 480);
    --logo-w: calc(264px + 36 * (100vw - 1440px) / 480);
    --logo-h: calc(120px + 16 * (100vw - 1440px) / 480);
    --measure: calc(620px + 60 * (100vw - 1440px) / 480);
    --fs-story-name: calc(75px + 21 * (100vw - 1440px) / 480);
    --fs-display: calc(44px + 12 * (100vw - 1440px) / 480);
    --fs-h2: calc(30px + 6 * (100vw - 1440px) / 480);
    --fs-h3: calc(20px + 2 * (100vw - 1440px) / 480);
    --fs-body: calc(17px + 1 * (100vw - 1440px) / 480);
    --fs-small: 14px;
    --fs-label: calc(12px + 1 * (100vw - 1440px) / 480);
    --home-hero-h: calc(460px + 100 * (100vw - 1440px) / 480);
    --home-hero-x: 50%;
    --home-hero-y: 38.71%;
    --home-door-h: calc(520px + 160 * (100vw - 1440px) / 480);
    --home-line-w: calc(760px + 220 * (100vw - 1440px) / 480);
    --bb-title-photo-h: calc(640px + 160 * (100vw - 1440px) / 480);
    --bb-modeling-photo-h: calc(600px + 150 * (100vw - 1440px) / 480);
    --bb-homage-photo-w: calc(307px + 33 * (100vw - 1440px) / 480);
    --about-bio-gap: calc(40px + 8 * (100vw - 1440px) / 480);
    --about-press-gap: calc(17px + 3 * (100vw - 1440px) / 480);
    --bk-step-w: calc(155px + 30 * (100vw - 1440px) / 480);
    --sb-spread-h: calc(180px + 14 * (100vw - 1440px) / 480);
  }
}

@media (min-width: 1920px) {
  :root {
    --margin: 96px;
    --gutter: 20px;
    --collage-w: 1280px;
    --tile-l-w: 630px;
    --tile-l-h: 962px;
    --tile-s-w: 369px;
    --tile-s-h: 520px;
    --radius: 20px;
    --section-gap: 160px;
    --block-gap: 48px;
    --gap: 24px;
    --header-h: 220px;
    --logo-w: 300px;
    --logo-h: 136px;
    --measure: 680px;
    --fs-story-name: 96px;
    --fs-display: 56px;
    --fs-h2: 36px;
    --fs-h3: 22px;
    --fs-body: 18px;
    --fs-small: 14px;
    --fs-label: 13px;
    --home-hero-h: 560px;
    --home-hero-x: 50%;
    --home-hero-y: 40.34%;
    --home-door-h: 680px;
    --home-line-w: 980px;
    --bb-title-photo-h: 800px;
    --bb-modeling-photo-h: 750px;
    --bb-homage-photo-w: 340px;
    --about-bio-gap: 48px;
    --about-press-gap: 20px;
    --bk-step-w: 185px;
    --sb-spread-h: 194px;
  }
}

/* Reduced motion: every duration is zero, so each transition that reads a token collapses to an
   instant change (the la-rosa and midnight-petal idiom); the scripts also return before hiding anything. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-press: 0ms;
    --duration-fast: 0ms;
    --duration-base: 0ms;
    --duration-menu: 0ms;
    --duration-image: 0ms;
    --duration-reveal: 0ms;
    --duration-hover-image: 0ms;
    --reveal-shift: 0px;
    --reveal-stagger: 0ms;
  }
}

/* global.css: type roles, layout primitives, buttons, labels, the prototype notice and the reveal states.
   Every value reads a token (styles/tokens.css, generated). Plan section 3; the comps' text styles. */

@font-face {
  font-family: "Nunito Sans";
  font-style: normal;
  font-display: swap;
  font-weight: 200 1000;
  src: url("/fonts/nunito-sans-var-latin.woff2") format("woff2-variations"), url("/fonts/nunito-sans-var-latin.woff2") format("woff2");
}
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("/fonts/fraunces-var-latin.woff2") format("woff2-variations"), url("/fonts/fraunces-var-latin.woff2") format("woff2");
}
/* metric-matched fallbacks so the swap does not shift the page (CLS) */
@font-face { font-family: "Nunito Sans Fallback"; src: local("Arial"); size-adjust: 101%; ascent-override: 101%; descent-override: 35%; line-gap-override: 0%; }
@font-face { font-family: "Fraunces Fallback"; src: local("Georgia"); size-adjust: 105%; ascent-override: 92%; descent-override: 24%; line-gap-override: 0%; }

html { background: var(--paper); color: var(--ink); font-family: var(--font-sans); }
body { font-size: var(--fs-body); line-height: var(--lh-body); font-weight: 400; background: var(--paper); }
::selection { background: var(--ink); color: var(--paper); }

/* ---- type roles (one class per comps text style) ---- */
.t-story-name { font-family: var(--font-story); font-weight: 700; font-size: var(--fs-story-name); line-height: var(--lh-story-name); letter-spacing: var(--ls-story-name); font-optical-sizing: auto; }
.t-display { font-weight: 300; font-size: var(--fs-display); line-height: var(--lh-display); }
.t-h2 { font-weight: 500; font-size: var(--fs-h2); line-height: var(--lh-h2); }
.t-h3 { font-weight: 600; font-size: var(--fs-h3); line-height: var(--lh-h3); }
.t-body { font-weight: 400; font-size: var(--fs-body); line-height: var(--lh-body); }
.t-small { font-weight: 400; font-size: var(--fs-small); line-height: var(--lh-small); }
.t-label { font-weight: 600; font-size: var(--fs-label); line-height: var(--lh-label); letter-spacing: var(--ls-label); text-transform: uppercase; }
.t-nav { font-weight: 500; font-size: var(--fs-nav); line-height: var(--lh-nav); letter-spacing: var(--ls-nav); }
.t-dim { color: var(--dim); }
.t-bracket { color: var(--dim); }   /* words he still has to write, or values not yet set */

/* ---- layout primitives ---- */
.page { display: flex; flex-direction: column; align-items: center; }
.wrap { width: var(--collage-w); max-width: calc(100% - 2 * var(--margin)); margin-inline: auto; }
.band { width: 100%; }
.section { width: var(--collage-w); max-width: calc(100% - 2 * var(--margin)); margin-inline: auto; display: flex; flex-direction: column; gap: var(--block-gap); padding-bottom: var(--section-gap); }
.measure { width: var(--measure); max-width: 100%; }
.stack { display: flex; flex-direction: column; gap: var(--gap); }
.cluster { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---- links ---- */
.link { background-image: linear-gradient(currentColor, currentColor); background-size: 0% 1px; background-position: 0 100%; background-repeat: no-repeat; transition: background-size var(--duration-base) var(--ease-out); }
.link:hover, .link:focus-visible, .link[aria-current="page"] { background-size: 100% 1px; }
.link-u { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }

/* ---- buttons (the Button component: Primary, Secondary, Text) ---- */
/* the border is drawn inside the comps' box (a Figma stroke takes no room), so the padding gives it back:
   126 x 46 for "Book Now", as drawn */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 46px; padding: calc(14px - 1.5px) calc(24px - 1.5px); font-weight: 600; font-size: var(--fs-button); line-height: var(--lh-button); letter-spacing: var(--ls-button); border: 1.5px solid var(--ink); white-space: nowrap; transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out), transform var(--duration-press) var(--ease-out); cursor: pointer; }
.btn--primary { background: var(--ink); color: var(--paper); }
.btn--secondary { background: transparent; color: var(--ink); }
.btn--text { border: 0; padding: 4px 0; min-height: 26px; background: none; color: var(--ink); }
.btn--on-band.btn--secondary { border-color: var(--on-band); color: var(--on-band); }
@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover { background: #2b2b2b; }
  .btn--secondary:hover { background: var(--ink); color: var(--paper); }
  .btn--text:hover { text-decoration: underline; text-underline-offset: 4px; }
}
.btn:active { transform: scale(0.98); }
.btn[aria-disabled="true"], .btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* ---- focus: visible, never removed ---- */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.band--dark :focus-visible, .site-footer :focus-visible { outline-color: var(--on-band); }
.skip-link { position: absolute; left: 8px; top: -60px; z-index: 100; padding: 10px 16px; background: var(--ink); color: var(--paper); font-weight: 600; transition: top var(--duration-fast) var(--ease-out); }
.skip-link:focus { top: 8px; }

/* ---- photographs ---- */
.ph { display: block; overflow: hidden; background: var(--note); }
.ph img { width: 100%; height: 100%; object-fit: cover; }
/* arrival fade, never on the first image in view (it is the LCP), and only once the script runs */
html[data-js] .ph img[data-fade] { opacity: 0; transition: opacity var(--duration-image) var(--ease-out); }
html[data-js] .ph img[data-fade].is-loaded { opacity: 1; }
/* hover on a photograph that is a link (collage tiles, doors, covers; plan section 5): the anchor carries .zoom and
   the photograph scales to 1.03 inside its .ph frame (overflow hidden, so the frame and its corners hold still),
   under a fine pointer only; every page uses this one rule, none writes its own */
.zoom .ph img { transition: transform var(--duration-hover-image) var(--ease-out); }
html[data-js] .zoom .ph img[data-fade] { transition: opacity var(--duration-image) var(--ease-out), transform var(--duration-hover-image) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .zoom:hover .ph img, .zoom:focus-visible .ph img { transform: scale(1.03); }
}

/* ---- reveal: the hidden state exists only under html[data-reveal-ready], which site.js sets,
   so no JavaScript, a script error, print and non-scrolling captures all show every element ---- */
html[data-reveal-ready] [data-reveal]:not(.is-in) { opacity: 0; transform: translateY(var(--reveal-shift)); }
html[data-reveal-ready] [data-reveal] { transition: opacity var(--duration-reveal) var(--ease-out), transform var(--duration-reveal) var(--ease-out); transition-delay: calc(var(--reveal-i, 0) * var(--reveal-stagger)); }
@media print { html[data-reveal-ready] [data-reveal] { opacity: 1 !important; transform: none !important; } }

/* ---- the prototype notice (plan row 9) ---- */
.proto-notice { display: flex; gap: 10px; align-items: flex-start; padding: 12px 16px; background: var(--note); border-left: 2px solid var(--ink); font-size: var(--fs-small); line-height: var(--lh-small); color: var(--ink); }
.proto-notice strong { font-weight: 600; }
/* the prototype bar (base_layout.ProtoBar): fixed to the foot of the viewport on the prototype routes, over the
   page's own layout; the body gives its height back so the footer's last line is never under it, and the scroll
   padding keeps a focused control above it (WCAG 2.4.11) */
.proto-notice--bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 40; margin: 0; justify-content: center; padding: 12px var(--margin); border-left: 0; border-top: 1px solid var(--rule); text-align: center; }
body.has-proto-bar { padding-bottom: calc(var(--fs-small) * var(--lh-small) + 25px); }
html:has(body.has-proto-bar) { scroll-padding-bottom: calc(var(--fs-small) * var(--lh-small) + 41px); }
.form-notice { margin-top: 12px; }
.form-notice[hidden] { display: none; }

/* ---- page transitions: a cross-document View Transition, the main region crossfades,
   the header and footer hold still (one shared name each, never a per-tile name) ---- */
@view-transition { navigation: auto; }
.site-header { view-transition-name: site-header; }
.site-footer { view-transition-name: site-footer; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 240ms; animation-timing-function: var(--ease-out); }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

/* ---- forms (the Field component) ---- */
/* every form in the comps sets its fields and its button 20 px apart (8 px from a label to its input) */
.form { display: flex; flex-direction: column; gap: 20px; align-items: flex-start; }
.form > .field { align-self: stretch; }
.field { display: flex; flex-direction: column; gap: 8px; }
.field__label { color: var(--ink); }
.field__input { width: 100%; min-height: 48px; padding: 0 14px; border: 1px solid var(--ink); border-radius: 0; background: var(--paper); font-size: var(--fs-body); line-height: var(--lh-body); color: var(--ink); transition: box-shadow var(--duration-fast) var(--ease-out); }
.field--multi .field__input { min-height: 140px; padding: 14px; resize: vertical; }
select.field__input { appearance: none; padding-right: 40px; background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%), linear-gradient(135deg, var(--ink) 50%, transparent 50%); background-position: calc(100% - 20px) 50%, calc(100% - 15px) 50%; background-size: 5px 5px; background-repeat: no-repeat; }
.field__input::placeholder { color: var(--dim); opacity: 1; }
.field__input:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--ink); }
.field__input:user-invalid { border-color: #9b1c1c; }
/* no margin of its own: every comp draws the submit button on its form's own gap (agent A, Contact, 10-19) */
.form__submit { margin-top: 0; }

/* ---- client words (shared by Home and Book) ---- */
.client-words__inner { display: flex; flex-direction: column; gap: 16px; }
.client-words__quote p { margin: 0; }
.lb-link { display: block; cursor: zoom-in; }

/* comp-footer.css: the Footer component (comps-ref 02-home-1440 / 02-home-390). The black band. */
.site-footer { width: 100%; background: var(--band); color: var(--on-band); }
.site-footer ul { margin: 0; padding: 0; list-style: none; }
/* a flex item, so the li carries no body-height line strut: the link's own line height sets the pitch (the comp's
   18 px link on a 14 px gap; 32 px apart, clear of the 24 px target spacing of WCAG 2.5.8) */
.site-footer li { display: flex; }
.site-footer__inner { padding: 48px var(--margin) 40px; display: flex; flex-direction: column; align-items: center; gap: 32px; text-align: center; }
.site-footer__links ul { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.site-footer__socials { display: flex; gap: 12px; }
.social { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: 1px solid var(--on-band); border-radius: 50%; color: var(--on-band); transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out); }
.social .icon--platform { width: 15px; height: 15px; }
.site-footer__rule { display: none; width: 100%; height: 1px; margin: 0; border: 0; background: rgba(255, 255, 255, 0.18); }
.site-footer__base { display: flex; flex-direction: column; align-items: center; gap: 32px; }
.site-footer__legal ul { display: flex; gap: 20px; justify-content: center; }
.site-footer__email { color: var(--on-band); }
.site-footer__copy { color: var(--on-band); }
@media (hover: hover) and (pointer: fine) {
  .social:hover { background: var(--on-band); color: var(--band); }
}

@media (min-width: 1024px) {
  .site-footer__inner { padding: 72px var(--margin) 56px; display: grid; grid-template-columns: 1fr auto; grid-template-areas: "links socials" "rule rule" "base base"; row-gap: 48px; align-items: center; text-align: left; }
  .site-footer__links { grid-area: links; }
  .site-footer__links ul { flex-direction: row; gap: 28px; }
  .site-footer__socials { grid-area: socials; justify-self: end; }
  .site-footer__rule { grid-area: rule; display: block; }
  .site-footer__base { grid-area: base; flex-direction: row; justify-content: space-between; gap: 24px; }
  .site-footer__copy { order: -1; }
  .site-footer__legal ul { gap: 24px; }
}

/* comp-header.css: the Header component and the phone menu (comps-ref 02-home-1440 / 02-home-390). */
.site-header { position: relative; z-index: 10; background: var(--paper); }
.site-header__inner { height: var(--header-h); padding-inline: var(--margin); display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
.site-header__left { display: flex; align-items: center; min-width: 0; }
.site-header__right { display: flex; align-items: center; justify-content: flex-end; gap: 28px; min-width: 0; }
.site-header__logo { display: block; line-height: 0; }
.site-header__logo .logo, .menu-sheet__logo .logo { width: var(--logo-w); height: auto; }
.site-nav__list { display: flex; gap: 28px; align-items: center; margin: 0; padding: 0; list-style: none; }
.site-nav .link, .site-nav .ext { padding-block: 6px; }
.ext { display: inline-flex; align-items: center; gap: 5px; }
.ext .icon--out { width: 8px; height: 8px; stroke-width: 2.4; flex: none; }
/* the button's 1.5 px border sits inside the comps' box (see .btn in global.css) */
.site-header__cta { min-height: 46px; padding: calc(14px - 1.5px) calc(24px - 1.5px); }

/* the menu button: three 26 x 2 bars, 6 apart (the Phone header's Menu frame) */
.menu-btn { display: none; width: 44px; height: 44px; margin-left: -9px; align-items: center; justify-content: center; }
.menu-btn__bars { display: flex; flex-direction: column; gap: 6px; width: 26px; }
.menu-btn__bars span { display: block; height: 2px; background: var(--ink); }

@media (max-width: 1023.98px) {
  .site-nav { display: none; }
  .menu-btn { display: inline-flex; }
  .site-header__cta { min-height: 40px; padding: calc(11px - 1.5px) calc(12px - 1.5px); }
}

/* the phone menu: a native modal dialog, full screen, fading and settling 12 px into place */
.menu-sheet { width: 100%; max-width: none; height: 100%; max-height: none; margin: 0; padding: 0 var(--margin) 40px; border: 0; background: var(--paper); color: var(--ink); opacity: 0; transform: translateY(-12px); transition: opacity var(--duration-menu) var(--ease-out), transform var(--duration-menu) var(--ease-out), overlay var(--duration-menu) allow-discrete, display var(--duration-menu) allow-discrete; }
.menu-sheet[open] { display: flex; flex-direction: column; opacity: 1; transform: none; }
@starting-style { .menu-sheet[open] { opacity: 0; transform: translateY(-12px); } }
.menu-sheet::backdrop { background: transparent; }
.menu-sheet__top { height: var(--header-h); display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
.menu-sheet__logo { grid-column: 2; line-height: 0; }
.menu-sheet__close { grid-column: 3; justify-self: end; width: 44px; height: 44px; margin-right: -9px; display: inline-flex; align-items: center; justify-content: center; }
.menu-sheet__nav ul { display: flex; flex-direction: column; gap: 4px; margin: 24px 0 40px; padding: 0; list-style: none; }
.menu-sheet__link { display: inline-flex; align-items: center; gap: 8px; min-height: 48px; font-size: var(--fs-h2); line-height: var(--lh-h2); font-weight: 500; }
.menu-sheet__link .icon--out { width: 12px; height: 12px; stroke-width: 2; }
.menu-sheet__cta { align-self: flex-start; }
body.is-locked { overflow: hidden; }

/* comp-lightbox.css: the lightbox (plan D-B10): a photograph full screen on the paper ground, the count, previous,
   next and close. Opens by fading in; each photograph fades in once decoded. Reduced motion: instant. */
.lightbox { width: 100%; max-width: none; height: 100%; max-height: none; margin: 0; padding: 0; border: 0; background: rgba(255, 255, 255, 0.98); color: var(--ink); opacity: 0; transition: opacity var(--duration-base) var(--ease-out), overlay var(--duration-base) allow-discrete, display var(--duration-base) allow-discrete; }
.lightbox[open] { display: grid; place-items: center; opacity: 1; }
@starting-style { .lightbox[open] { opacity: 0; } }
.lightbox::backdrop { background: transparent; }
.lightbox__figure { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 64px var(--margin) 24px; max-width: 100%; max-height: 100%; touch-action: pinch-zoom; }
.lightbox__img { max-width: min(100%, 1600px); max-height: calc(100vh - 140px); width: auto; height: auto; object-fit: contain; border-radius: var(--radius); opacity: 0; transform: scale(0.985); transition: opacity var(--duration-image) var(--ease-out), transform var(--duration-image) var(--ease-out); }
.lightbox.is-shown .lightbox__img { opacity: 1; transform: none; }
.lightbox__count { color: var(--dim); min-height: 1.5em; }
.lightbox__btn { position: fixed; display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; color: var(--ink); background: rgba(255, 255, 255, 0.9); border-radius: 50%; transition: background-color var(--duration-fast) var(--ease-out); }
.lightbox__close { top: 12px; right: 12px; }
.lightbox__prev { left: 12px; top: 50%; transform: translateY(-50%); }
.lightbox__next { right: 12px; top: 50%; transform: translateY(-50%); }
.lightbox.is-single .lightbox__prev, .lightbox.is-single .lightbox__next { display: none; }
@media (hover: hover) and (pointer: fine) { .lightbox__btn:hover { background: var(--note); } }
@media (max-width: 767.98px) { .lightbox__prev, .lightbox__next { top: auto; bottom: 16px; transform: none; } }

/* pages-home.css: Home (comps 02-home, V2). Values from tokens.css and tokens-home.json. */
.page--home { display: block; }

/* the photograph: full bleed, its height and crop per width (the V2 h and cropT rules) */
.home-hero { width: 100%; height: var(--home-hero-h); }
.home-hero img { object-position: var(--home-hero-x) var(--home-hero-y); }

/* the first view line: his line slot and the two doors; a row from 1024, stacked below (comps stackAt 768) */
.home-first { display: flex; flex-direction: column; gap: 24px; padding: 40px var(--margin); }
.home-first__line { max-width: var(--home-line-w); }
.home-first__doors { display: flex; gap: 16px; flex-wrap: wrap; }
@media (min-width: 1024px) {
  .home-first { flex-direction: row; align-items: center; justify-content: space-between; gap: 40px; }
  .home-first__line { flex: 1 1 auto; }
  .home-first__doors { flex: none; flex-wrap: nowrap; }
}

/* the three doors: three columns from 768 (comps stackAt 390), one column below */
.home-doors { display: grid; grid-template-columns: 1fr; gap: 48px; padding: var(--section-gap) var(--margin) 0; }
@media (min-width: 768px) { .home-doors { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); } }
.door { display: flex; flex-direction: column; align-items: flex-start; gap: 16px; }
.door__photo { display: block; width: 100%; overflow: hidden; }
.door__ph { width: 100%; height: var(--home-door-h); }
.door__ph img { transition: transform var(--duration-hover-image) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .door:hover .door__ph img { transform: scale(1.03); }
}

/* his client's words: centred on the measure */
.client-words { display: flex; justify-content: center; padding: var(--section-gap) var(--margin); }

/* pages-offers.css: Book, Bear Book, Collaborations (comps 05-book, 06-bear-book, 08h-collaboration, V2).
   Agent C. Values come from tokens.css and tokens-offers.json. Selector prefixes: .book-, .bb-, .collab-
   only; a rule shared by two pages' own classes is written as a combined selector of those classes.
   No hairline rules: the comps-ref export carries no stroke data (checked, zero "stroke" keys in the
   export), so a divider is drawn only where a comp frame holds a RECT for one; none of these do. */

/* ---- fixed (non-fluid) eyebrow pairings: the comps draw these at one gap regardless of width ---- */
.bb-eyebrow-12 { display: flex; flex-direction: column; gap: 12px; }
.bb-modeling-intro { display: flex; flex-direction: column; gap: 16px; }
.bb-closing { display: flex; flex-direction: column; gap: 16px; }

/* ---- the first section on each page: the comps give it extra top padding (parity, seen RED 10-19:
   "Book a session"/"Bear magazine book"/"Collaborate" sat 40 px (1440) / 24 px (390) above the comp) ---- */
.book-lede, .bb-title, .collab-lede { padding-top: var(--block-gap); }

/* the Section title shape, under our own class: components.ui.SectionTitle's shared .section-title class
   carries no gap (parity, seen RED 10-19: "Select your city" sat 12 to 13 px above the comp); never fixed
   there (a shared class), fixed here instead */
.book-section-title { display: flex; flex-direction: column; gap: 12px; }

/* ---- the numbered step (Book's Process, Bear Book's Interested in modeling?): one grid, var(--gutter)
   matches the comps at both 390 (8) and 1440 (17) exactly, so no mobile override is needed ---- */
.book-steps, .bb-steps { display: grid; grid-template-columns: 1fr; gap: var(--gutter); }
@media (min-width: 768px) { .book-steps { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 768px) { .bb-steps { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.book-step, .bb-step { display: flex; flex-direction: column; gap: 10px; padding-top: 20px; }
.book-step__title, .bb-step__title { margin: 0; }

/* ---- Book: the three city cards ---- */
.book-cities { display: flex; flex-direction: column; gap: 40px; }
@media (min-width: 768px) { .book-cities { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); } }
.book-city { display: flex; flex-direction: column; }
.book-city__ph { width: 100%; height: 420px; }
.book-city__body { display: flex; flex-direction: column; gap: 14px; align-items: flex-start; padding: 28px; flex: 1 1 auto; }
/* the cards end level, their buttons on one line (comps-record, Deviations: "Equal heights are a one-line CSS
   detail in the build"; the independent review, 10-19, found it not done) */
.book-city__body .btn { margin-top: auto; }
.book-city__name { margin: 0; }

/* ---- Book: the session terms list ---- */
.book-terms { display: flex; flex-direction: column; }
.book-term { display: flex; flex-direction: row; align-items: baseline; gap: 0; padding: 16px 0; }
.book-term__label { flex: 0 0 220px; margin: 0; }
.book-term__value { flex: 1 1 auto; margin: 0; }
@media (max-width: 767px) { .book-term { flex-direction: column; gap: 4px; } .book-term__label { flex-basis: auto; } }
/* the pricing CTA: a direct child of .section (align-items: stretch) would otherwise fill its full width */
.book-pricing-cta { align-self: flex-start; }

/* ---- Book: his client's words, on a full-bleed note band (the comps' own band here; Home's is not) ---- */
.book-words-band { width: 100%; display: flex; justify-content: center; background: var(--note); padding: var(--section-gap) var(--margin); }

/* ---- Book: the travel request (a PreviewForm) beside the door to Collaborations ---- */
.book-travel { padding-top: var(--section-gap); }
.book-travel-row { display: flex; flex-direction: column; gap: 32px; }
.book-travel-text { display: flex; flex-direction: column; gap: 16px; }
@media (min-width: 1024px) {
  .book-travel-row { flex-direction: row; gap: var(--block-gap); align-items: flex-start; }
  .book-travel-text, .book-travel-form { flex: 1 1 0; }
}
.book-collab-door { display: flex; flex-direction: column; gap: 16px; align-items: flex-start; padding-top: var(--block-gap); }

/* ---- Bear Book: the title photograph and the modeling photograph (full bleed, fixed height per width) ---- */
.bb-title-ph { width: 100%; height: var(--bb-title-photo-h); }
.bb-modeling-ph { width: 100%; height: var(--bb-modeling-photo-h); }

/* ---- Bear Book: the three themes ---- */
.bb-themes { display: flex; flex-direction: column; gap: 32px; }
@media (min-width: 768px) { .bb-themes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--block-gap); } }
.bb-theme { display: flex; flex-direction: column; gap: 12px; padding-top: 20px; }

/* ---- Bear Book: homage to Bear Magazine (two paragraphs and the cover, row above 1024) ---- */
.bb-homage-row { display: flex; flex-direction: column; gap: var(--block-gap); }
@media (min-width: 1024px) { .bb-homage-row { flex-direction: row; align-items: flex-start; } }
.bb-homage-text { flex: 1 1 0; margin: 0; }
.bb-homage-photo { flex: none; width: var(--bb-homage-photo-w); aspect-ratio: 3 / 4; align-self: flex-start; }

/* ---- Bear Book: should you participate (a full-bleed note band, two columns above 1024) ---- */
.bb-participate-band { width: 100%; background: var(--note); padding: var(--section-gap) 0; }
.bb-participate-row { display: flex; flex-direction: column; gap: 16px; }
@media (min-width: 1024px) { .bb-participate-row { flex-direction: row; gap: var(--block-gap); align-items: flex-start; } }
.bb-participate-row > * { flex: 1 1 0; margin: 0; }

/* Interested in modeling: like Book's travel section, it follows a full-bleed band and the comp gives it
   back the same top padding (parity, seen RED 10-19: the section sat 145 px short of the comp) */
.bb-modeling-section { padding-top: var(--section-gap); }

/* ---- Bear Book: connect here (a PreviewForm beside its text, row above 1024) ---- */
.bb-connect-row { display: flex; flex-direction: column; gap: 32px; }
.bb-connect-text { display: flex; flex-direction: column; gap: 16px; }
@media (min-width: 1024px) {
  .bb-connect-row { flex-direction: row; gap: var(--block-gap); align-items: flex-start; }
  .bb-connect-text, .bb-connect-form { flex: 1 1 0; }
}

/* ---- Collaborations: the application (text beside its form, row above 1024); the heading sits inside
   the text column, as the comp draws it (Collaboration row, both columns starting level) ---- */
.collab-row { display: flex; flex-direction: column; gap: 32px; }
.collab-text { display: flex; flex-direction: column; gap: 16px; }
@media (min-width: 1024px) {
  .collab-row { flex-direction: row; gap: var(--block-gap); align-items: flex-start; }
  .collab-text, .collab-form { flex: 1 1 0; }
}

/* the three PreviewForms: the comps' own "Form" frames all give 20 px between fields (Book's Travel
   Request, Bear Book's Connect Here, this page), not the shared .form's 16 px; a higher-specificity rule
   under our own classes, .form itself stays untouched */
.form.book-travel-form, .form.bb-connect-form, .form.collab-form { gap: 20px; }

/* ---- Collaborations: the Preferred month control: native radios styled as the drawn pills, so the
   pressed state (:checked) needs no script and survives with JavaScript off ---- */
/* block, not flex: a <legend> is not a normal flex item in every engine (it did not pick up the fieldset's
   own gap, parity seen RED 10-19), so each child's own margin-bottom carries the comps' uniform 20 px */
.collab-months-field { border: 0; margin: 0; padding: 0; }
.collab-months-field > legend { padding: 0; margin-bottom: 20px; }
.collab-months-field > .collab-months { margin-bottom: 20px; }
.collab-months { display: flex; flex-wrap: wrap; gap: 8px; }
.collab-month { position: relative; display: inline-flex; }
.collab-month__label { cursor: pointer; }
.collab-month__input:checked + .collab-month__label { background: var(--ink); color: var(--paper); }
.collab-month__input:focus-visible + .collab-month__label { outline: 2px solid var(--ink); outline-offset: 3px; }

/* pages-public.css: About, Contact, the legal template, Not found (comps 07-about, 07-contact, 07-legal,
   07-not-found, V2). Values from the shared tokens.css and this page group's own tokens-public.json
   (the few gaps that change with width and are not a drawn width of any shared token). Selector
   prefixes: .about-, .contact-, .legal-, .nf-. */

.page--about,
.page--contact,
.page--legal,
.page--not-found {
  display: block;
}

/* ---- About (07-about): his photograph beside his bio, stacked on phones; Press (bracketed); the door ---- */
.about-bio { padding-top: var(--block-gap); }
/* the Bio row's own gap (390 to 1440: 32, 32, 40; tokens-public.json) */
.about-bio__row { display: flex; flex-direction: column; gap: var(--about-bio-gap); }
.about-bio__photo { width: 100%; aspect-ratio: 3 / 4; }
.about-bio__text { display: flex; flex-direction: column; gap: 20px; }
@media (min-width: 768px) {
  /* 525fr 502fr: the comp's Bio row is 1067 wide with a 525 photo and a 502 text column (gap 40);
     fr tracks share the row's width (minus the gap) in that ratio, so this renders 525 and 502
     exactly at 1440 and keeps the same proportion at every other width */
  .about-bio__row { display: grid; grid-template-columns: 525fr 502fr; align-items: start; }
  .about-bio__photo { width: auto; }
}

.about-press {
  /* the comp's Press frame carries its own top padding (the section gap), on top of Bio's own
     bottom padding below: the gap between them is two section-gaps, not one (plan parity fix) */
  padding-top: var(--section-gap);
}
.about-press__heading { display: flex; flex-direction: column; gap: 8px; }
/* the Press list's own gap (390 to 1440: 12, 12, 17; tokens-public.json) */
.about-press__list { display: grid; grid-template-columns: 1fr; gap: var(--about-press-gap); }
.about-press__item { display: flex; flex-direction: column; gap: 8px; padding-top: 16px; }
@media (min-width: 600px) { .about-press__list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .about-press__list { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.about-door { display: flex; flex-direction: column; align-items: flex-start; }

/* ---- Contact (07-contact): his line and email beside the PreviewForm, stacked on phones ---- */
.contact-connect { padding-top: var(--block-gap); }
.contact-row { display: flex; flex-direction: column; gap: 40px; }
.contact-text { display: flex; flex-direction: column; gap: 20px; }
@media (min-width: 768px) {
  .contact-row { flex-direction: row; align-items: flex-start; }
  .contact-text, .contact-row .contact-form { flex: 1 1 0; }
}
/* the Field component's own gap is 16px (global.css .form); this comp draws a uniform 20px between
   every child including the submit button, so the shared .form__submit's own 8px top margin
   (global.css) is cancelled here: flagged as a shared change requested (every PreviewForm carries it) */
.contact-row .contact-form { gap: 20px; }
.contact-row .contact-form .form__submit { margin-top: 0; }

/* ---- Legal template (07-legal): Privacy Policy and Accessibility Statement, one template ---- */
.legal-body { padding-top: var(--block-gap); }
.legal-title { display: flex; flex-direction: column; gap: 8px; }
.legal-blocks { display: flex; flex-direction: column; gap: 32px; }
.legal-block { display: flex; flex-direction: column; gap: 12px; }

/* ---- Not found (07-not-found): copied to the root 404.html ---- */
.nf-body { padding-top: var(--section-gap); }
.nf-text { display: flex; flex-direction: column; gap: 16px; }
.nf-ways { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
@media (min-width: 768px) {
  .nf-ways { flex-direction: row; flex-wrap: wrap; align-items: center; }
}

/* pages-studio.css: Booking 1-4, Client gallery 1-3, Story builder (comps 08a-08g, 09a-09b, V2).
   Agent D. Selector prefixes: .bk- (booking), .gal- (client gallery), .sb- (story builder). Values from
   tokens.css; two custom properties added here for the studio motion spec (plan section 5, "Studio"
   row) that the shared tokens do not carry. */

:root {
  --studio-pop: 220ms;
}
@media (prefers-reduced-motion: reduce) {
  :root { --studio-pop: 0ms; }
}

/* ============================== shared across booking / gallery / builder ============================== */

.bk-page, .gal-picks, .gal-prints { padding-top: var(--block-gap); }
.gal-signin { padding-top: var(--section-gap); }

/* the four-step progress bar (comps "Progress"): a fixed width per step, not stretched to the section.
   No divider or bottom padding of its own (that was this build's invention, not comps-ref: its own
   height is exactly the steps' content, so the normal block-gap after it matches the comp's spacing) */
.bk-progress { display: flex; width: fit-content; max-width: 100%; list-style: none; gap: 0; padding: 0; margin: 0; }
/* no white-space:nowrap: "4  Confirmed" wraps to 2 lines at 390 in the comp, and every step stretches
   (flex's own default) to match that tallest step, exactly as comps-ref draws it */
.bk-progress__step { flex: none; width: var(--bk-step-w); min-width: 0; padding-top: 12px; }

.bk-session { display: flex; flex-direction: column; gap: 8px; }
/* a lone Continue/Pay button sitting directly in the shared .section (flex column, align-items:stretch by
   default) would otherwise stretch full width and centre its label; keep it at the comp's own width */
.bk-page > .btn, .gal-prints > .btn { align-self: flex-start; }

/* a custom radio/checkbox: appearance:none + a ::before dot, matching the comps' plain ellipse/rect
   marks (no browser default UI drawn over his monochrome system) */
.bk-radio__input, .gal-size__input, .bk-agree__input {
  appearance: none; -webkit-appearance: none; flex: none; width: 18px; height: 18px; margin: 2px 0 0;
  border: 1.5px solid var(--ink); background: var(--paper); display: grid; place-content: center; cursor: pointer;
}
.bk-radio__input, .gal-size__input { border-radius: 50%; }
.bk-radio__input::before, .gal-size__input::before {
  content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--ink);
  transform: scale(0); transition: transform var(--duration-fast) var(--ease-out);
}
.bk-agree__input::before {
  content: ""; width: 10px; height: 10px; background: var(--ink);
  transform: scale(0); transition: transform var(--duration-fast) var(--ease-out);
}
.bk-radio__input:checked::before, .gal-size__input:checked::before, .bk-agree__input:checked::before { transform: scale(1); }

/* ====================================== booking (.bk-) ====================================== */

.bk-datetime { display: flex; flex-direction: column; gap: var(--section-gap); }
.bk-calendar, .bk-times { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
@media (min-width: 1024px) {
  /* a grid, not weighted flex-grow: flex-basis:0 plus border-box padding does not split in the declared
     ratio when the two columns' padding differs (667:360 measured as 684:343 until this changed) */
  .bk-datetime { display: grid; grid-template-columns: 520fr 507fr; gap: var(--block-gap); align-items: start; }
}
/* a direct-child button would otherwise stretch to the column's width and centre its label (align-items:
   stretch is flex's default); every lone primary action here keeps its own, comp-drawn width instead */
.bk-times > .btn { align-self: flex-start; }

.bk-calendar__head { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.bk-calendar__nav { display: flex; gap: 4px; }
.bk-calendar__arrow {
  background: none; border: 0; padding: 4px 2px; font-weight: 600; font-size: var(--fs-h3); line-height: var(--lh-h3);
  color: var(--ink); cursor: pointer;
}
.bk-calendar__arrow:disabled { color: var(--dim); cursor: not-allowed; }

.bk-calendar__weekdays, .bk-calendar__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.bk-calendar__wd { text-align: center; padding: 8px 0; }
.bk-day {
  appearance: none; background: none; border: 0; border-radius: var(--radius);
  min-height: 48px; color: var(--ink); cursor: pointer; transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.bk-day--blank { cursor: default; }
.bk-day:disabled { color: var(--dim); cursor: not-allowed; }
.bk-day[data-day-available]:not(:disabled):hover { background: var(--note); }
.bk-day.is-selected { background: var(--ink); color: var(--paper); }

.bk-slots { display: flex; flex-wrap: wrap; gap: 12px; }
.bk-slot { min-width: 108px; }

.bk-selection { font-weight: 600; }

.bk-details-row { display: flex; flex-direction: column; gap: var(--section-gap); }
.bk-details-col { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
@media (min-width: 1024px) {
  .bk-details-row { flex-direction: row; gap: var(--block-gap); }
  .bk-details-col { flex: 1 1 0; }
}
.bk-location { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 12px; }
.bk-location legend { padding: 0 0 4px; }
.bk-radio {
  display: flex; gap: 14px; padding: 16px; border: 1px solid var(--rule); border-radius: var(--radius); cursor: pointer;
}
.bk-radio.is-selected { border-color: var(--ink); }
.bk-radio__text { display: flex; flex-direction: column; gap: 4px; }

.bk-deposit-row { display: flex; flex-direction: column; gap: var(--section-gap); }
.bk-summary, .bk-payment { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.bk-summary { background: var(--note); padding: 28px; border-radius: var(--radius); }
.bk-payment > .btn { align-self: flex-start; }
@media (min-width: 1024px) {
  /* a grid, not weighted flex-grow: see .bk-datetime above for why */
  .bk-deposit-row { display: grid; grid-template-columns: 541.5fr 485.5fr; gap: var(--block-gap); align-items: start; }
}
.bk-summary__due { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding-top: 16px; border-top: 1px solid var(--rule); }
.bk-card-entry { background: var(--note); border-radius: var(--radius); padding: 40px 24px; text-align: center; }
.bk-agree { display: flex; gap: 12px; cursor: pointer; }

/* comps-ref constrains this text to the measure (620 px at 1440), not the full booking column (1067): its
   own line count, and the page height below it, depend on that narrower wrap */
.bk-confirmed, .bk-next { max-width: var(--measure); }
.bk-confirmed { display: flex; flex-direction: column; gap: 12px; }
.bk-next { display: flex; flex-direction: column; gap: 12px; padding-top: 24px; border-top: 1px solid var(--rule); }
.bk-confirmed__actions { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
@media (min-width: 1024px) {
  .bk-confirmed__actions { flex-direction: row; align-items: center; }
}

/* ====================================== client gallery (.gal-) ====================================== */

/* the section itself keeps the shared .section width/position; only its content is measure-capped, so it
   stays left-aligned at the section's own margin instead of being re-centred in a narrower box */
.gal-signin { display: flex; flex-direction: column; gap: 20px; }
.gal-signin > * { max-width: var(--measure); }
.gal-signin__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 20px; }

.gal-picks { display: flex; flex-direction: column; gap: var(--block-gap); }
.gal-picks__head { display: flex; flex-direction: column; gap: 24px; }
@media (min-width: 1024px) {
  /* the comp's own split (736:291 of the 1067 px row at 1440); the two columns are bottom-aligned, not
     top: Title (91 px tall) sits 26 px lower than Picks (117 px tall) because both share the same foot */
  .gal-picks__head { display: grid; grid-template-columns: 736fr 291fr; align-items: end; gap: var(--block-gap); }
}
.gal-picks__title, .gal-picks__counter-block { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.gal-picks__counter-row { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }
.gal-picks__intro { max-width: var(--measure); }
.gal-limit[hidden] { display: none; }
.gal-limit { color: #9b1c1c; }

.gal-filters { display: flex; gap: 24px; padding: 0; margin: 0; }
.gal-filter {
  appearance: none; background: none; border: 0; border-bottom: 2px solid transparent; padding: 0 0 6px;
  font-family: inherit; font-size: var(--fs-nav); line-height: var(--lh-nav); font-weight: 500; letter-spacing: var(--ls-nav);
  color: var(--dim); cursor: pointer;
}
.gal-filter.is-active { color: var(--ink); border-bottom-color: var(--ink); }

.gal-grid { list-style: none; display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gutter); padding: 0; margin: 0; }
@media (min-width: 768px) { .gal-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1440px) { .gal-grid { grid-template-columns: repeat(4, 1fr); } }
.gal-tile { position: relative; }
.gal-tile[hidden] { display: none; }
.gal-tile__ph { aspect-ratio: 4 / 5; border: 3px solid transparent; transition: border-color var(--duration-fast) var(--ease-out); }
/* a picked photograph carries a thick ink border around the whole tile, as drawn */
.gal-tile[data-picked="true"] .gal-tile__ph { border-color: var(--ink); }
/* a scrim behind the controls: his photographs run from near-black to brightly lit at the exact spot the
   heart and pick sit, and the gal-ctrl circle alone was not reliably readable against a light photograph
   (found by looking at the capture of book/book-01, 2026-10-19) */
.gal-tile__controls {
  position: absolute; inset-inline: 0; bottom: 0; display: flex; justify-content: space-between; padding: 10px 12px;
  background: linear-gradient(to top, rgba(16, 16, 16, 0.38), rgba(16, 16, 16, 0) 100%);
}
.gal-ctrl { border: 0; background: none; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
/* the heart (comps-ref "Frame" 22x20): the icon alone, white outline when not favourited, solid white when
   favourited; no circle behind it */
.gal-ctrl--heart { width: 22px; height: 20px; color: var(--paper); }
.gal-ctrl--heart .icon { fill: none; stroke: currentColor; transition: fill var(--duration-fast) var(--ease-out); }
.gal-ctrl--heart[aria-pressed="true"] .icon { fill: currentColor; }
/* the pick (comps-ref "Frame" 24x24): an outlined circle; picked fills it white with a dark check */
.gal-ctrl--pick {
  width: 24px; height: 24px; border: 1.5px solid var(--paper); border-radius: 50%; color: var(--ink);
  transition: background var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
}
.gal-ctrl--pick .icon { opacity: 0; transition: opacity var(--duration-fast) var(--ease-out); }
.gal-ctrl--pick[aria-pressed="true"] { background: var(--paper); border-color: var(--paper); }
.gal-ctrl--pick[aria-pressed="true"] .icon { opacity: 1; }
.gal-ctrl.is-popping { animation: studio-pop var(--studio-pop) var(--ease-out); }
.gal-ctrl:disabled { opacity: 0.4; cursor: not-allowed; }
@keyframes studio-pop { 0% { transform: scale(1); } 50% { transform: scale(1.12); } 100% { transform: scale(1); } }

.gal-picks__next { display: flex; justify-content: flex-start; }

.gal-prints { display: flex; flex-direction: column; gap: var(--block-gap); align-items: flex-start; }
.gal-prints__title { display: flex; flex-direction: column; gap: 8px; }
.gal-prints__row { display: flex; flex-direction: column; gap: var(--block-gap); width: 100%; }
.gal-prints__ph { width: 100%; aspect-ratio: 4 / 5; }
.gal-prints__options { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.gal-prints__options > .btn { align-self: flex-start; }
@media (min-width: 1024px) {
  /* the comp's own split (520:507 of the 1067 px row at 1440); a grid, not weighted flex-grow (see
     .bk-datetime above for why) */
  .gal-prints__row { display: grid; grid-template-columns: 520fr 507fr; align-items: start; }
}
.gal-sizes { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 12px; }
.gal-sizes legend { padding: 0 0 4px; }
.gal-size { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border: 1px solid var(--rule); border-radius: var(--radius); cursor: pointer; }
.gal-size.is-selected { border-color: var(--ink); }
.gal-size__label { flex: 1 1 auto; }

.gal-order { display: flex; flex-direction: column; gap: 12px; background: var(--note); border-radius: var(--radius); padding: 28px; width: 100%; }
.gal-order > .btn { align-self: flex-start; }
.gal-order__line { display: flex; justify-content: space-between; gap: 12px; }

/* ====================================== story builder (.sb-) ====================================== */

.page--builder { background: var(--note); }

/* width:100% counters .page's align-items:center (the shared rule that centres, shrink-to-fit, any child
   with no width of its own): the admin bar is full-bleed, unlike the centred, measure-width .section content */
.sb-admin { width: 100%; background: var(--paper); border-bottom: 1px solid var(--rule); }
.sb-admin__inner {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px var(--margin);
}
.sb-admin__crumb { display: flex; gap: 10px; flex-wrap: wrap; }
.sb-admin__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }

.sb-page { padding-top: var(--block-gap); padding-bottom: var(--section-gap); }

.sb-editor-row, .sb-reorder-row { display: flex; flex-direction: column; gap: var(--block-gap); align-items: flex-start; }
@media (min-width: 1024px) {
  /* a grid, not weighted flex-grow: see .bk-datetime above for why. The comp's own split (667:360 of the
     1067 px row at 1440); the reorder row splits its two panels evenly (513.5:513.5), a plain 1fr 1fr. */
  .sb-editor-row { display: grid; grid-template-columns: 667fr 360fr; gap: var(--block-gap); align-items: start; }
  .sb-reorder-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--block-gap); align-items: start; }
}
.sb-fields, .sb-side { min-width: 0; }
.sb-side { display: flex; flex-direction: column; gap: 20px; width: 100%; }
/* comps-ref draws every studio panel and card with square corners: no radius anywhere below */
.sb-panel { background: var(--paper); padding: 24px; display: flex; flex-direction: column; gap: 16px; width: 100%; box-sizing: border-box; }
/* comps-ref draws the Story fields panel at 28 px padding, the only panel that differs from the 24 px the
   rest share (Spread layouts, Publishing, Photographs, Spread preview) */
.sb-fields.sb-panel { padding: 28px; }
/* the narrative shows its whole text, not a scrolling box (comps-ref: it grows to content, about 368 px at
   1440, 668 at 390): field-sizing:content does this natively in Chromium; studio.js autosizes it (height =
   scrollHeight) for engines that do not support that property yet */
.sb-narrative { min-height: 140px; font-family: inherit; field-sizing: content; resize: none; overflow: hidden; }

.sb-layout { display: flex; align-items: center; gap: 14px; padding: 12px; border: 1px solid var(--rule); }
.sb-layout__text { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.sb-diagram { flex: none; width: 72px; height: 48px; display: flex; gap: 4px; padding: 4px; background: var(--note); }
.sb-diagram__ph { flex: 1 1 0; background: var(--dim); }
.sb-diagram__credits { flex: 1 1 0; background: rgba(16, 16, 16, 0.14); }

.sb-photographs { width: 100%; }
/* comps-ref: rows are 16px apart at 1440 on the edit screen (117 between starts, 101 own height), 12px on
   the reorder screen (113 between starts); .sb-rows--tight is added on that one page only */
.sb-rows { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 16px; }
.sb-rows--tight { gap: 12px; }
.sb-row {
  display: flex; align-items: center; gap: 16px; padding: 10px 0;
  background: var(--paper); touch-action: manipulation;
}
.sb-row.is-dragging {
  border: 1px solid var(--rule); padding: 10px 12px; box-shadow: 0 8px 24px rgba(16, 16, 16, 0.18);
  position: relative; z-index: 2;
}
.sb-row:not(.is-dragging) { transition: transform var(--duration-base) var(--ease-out); }
/* the grip is the comp's own "⠇⠇" text (plan section 4): no fixed width, so it is exactly as wide as that
   glyph renders at each breakpoint's type scale (29 px at 1440, 26 at 390), never a size I chose */
.sb-row__grip { flex: none; height: 26px; display: flex; align-items: center; justify-content: center; color: var(--dim); cursor: grab; touch-action: none; }
.sb-row.is-dragging .sb-row__grip { cursor: grabbing; }
.sb-row__move { flex: none; display: flex; flex-direction: column; gap: 4px; }
.sb-row__move-btn {
  width: 32px; height: 32px; border: 1px solid var(--ink); background: var(--paper); color: var(--ink);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
/* the comp does not draw a disabled state (its rows are not at an edge); the bordered style stays and only
   dims, since a first row with no Move up and a last with no Move down is this build's own addition */
.sb-row__move-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.sb-row__photo { flex: none; width: 64px; height: 80px; }
.sb-row__text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.sb-upload { border: 1px dashed var(--rule); padding: 28px; text-align: center; }

.sb-spread-preview { display: flex; flex-direction: column; gap: 16px; }
.sb-spread { display: flex; flex-direction: column; gap: 8px; }
/* comps-ref: every spread photograph is a fixed height (--sb-spread-h), never an aspect-ratio box; width is
   flexible and the image crops to fill it (global .ph img { object-fit: cover }) */
.sb-spread__pair { display: flex; gap: 8px; height: var(--sb-spread-h); }
.sb-spread__ph { flex: 1 1 0; min-width: 0; height: 100%; }
.sb-spread__credits { flex: 1 1 0; min-width: 0; height: 100%; box-sizing: border-box; background: var(--note); padding: 12px; display: flex; flex-direction: column; gap: 4px; }
/* the last spread's photograph and its credits are not an even split (comps-ref: about 217:241 at 1440,
   139:163 at 390, both close to 9:10); a grid, not weighted flex-grow (see .bk-datetime above for why:
   the credits block's own padding skewed a flex-basis:0 split the same way) */
.sb-spread__pair--credits { display: grid; grid-template-columns: 139fr 163fr; }
/* each drawn width's own split (orchestrator, 10-19: 9:10 put the credits 4 px right at 390) */
@media (min-width: 768px) { .sb-spread__pair--credits { grid-template-columns: 216.8fr 240.8fr; } }
.sb-spread__pair--credits .sb-spread__ph, .sb-spread__pair--credits .sb-spread__credits { height: 100%; }

/* pages-work.css: Collections index, the collection template and the story template (comps 03-collections-index,
   03-collection-i, 04-story, V2). Values come from tokens.css; every value below either reuses an existing
   token (checked against the comp's own measurements at 1440 and 390) or is a static ratio/plain px for a
   discrete breakpoint switch the comps do not draw at 768 or 1920 (the same idiom as pages-home.css's
   .home-first/.home-doors). Selectors: .colls- (index), .coll- (the collection template), .story- (stories). */

.page--collections, .page--collection, .page--story { display: block; }

/* ============ Collections index (.colls-) ============ */
/* The index spans margin to margin at every width (comps-record.md: "open for review"), not the collage-w
   content column the other pages keep: built as measured, not second-guessed. */
.colls-title { width: 100%; max-width: calc(100% - 2 * var(--margin)); margin-inline: auto; padding-block: var(--block-gap); text-align: center; }
.colls-covers { display: flex; flex-direction: column; gap: 40px; width: 100%; max-width: calc(100% - 2 * var(--margin)); margin-inline: auto; padding-bottom: var(--section-gap); }
.colls-cover { display: flex; flex-direction: column; gap: 14px; }
.colls-cover__photo { display: block; }
.colls-cover__ph { width: 100%; aspect-ratio: 358 / 460; border-radius: var(--radius); }
.colls-cover__title { margin: 0; }
.colls-cover__link { align-self: flex-start; }
@media (min-width: 768px) {
  .colls-covers { flex-direction: row; gap: var(--gutter); }
  .colls-cover { flex: 1 1 0; }
  .colls-cover__ph { aspect-ratio: 426 / 620; }
}

/* ============ The collection template (.coll-) ============ */
.coll-title { width: var(--collage-w); max-width: calc(100% - 2 * var(--margin)); margin-inline: auto; padding-block: var(--block-gap); display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; }
.coll-title__heading { margin: 0; }
.coll-tabs { display: flex; gap: 24px; flex-wrap: wrap; justify-content: center; }
.coll-tabs__link { color: var(--dim); }
.coll-tabs__link[aria-current="page"] { color: var(--ink); }

/* the collage: a size container at the collage-w column; each tile sits at its measured x, y, w, h (percent
   of that column, i.e. cqw) via custom properties in its own style attribute (plan 2b); two columns at every
   width, including phones, falls out of those percentages for free (D-B4's one-column option is not built). */
/* height is computed from the token width, never from this element's own cqw: a container-query length unit
   used on a property of the query container ITSELF falls back to the viewport (not the container), by spec,
   to avoid circularity (seen RED: at 1440 the collage rendered 23401 px tall instead of 17340). A percentage
   cannot stand in for it either: height% resolves against the containing block's height, which is indefinite
   here, so it is treated as 0 inside the calc() (seen RED: height collapsed to 0). var(--collage-w) is the
   plain width token the four drawn widths already hold exactly, so multiplying by it needs no percentage. */
.coll-collage { position: relative; container-type: inline-size; width: var(--collage-w); max-width: calc(100% - 2 * var(--margin)); margin-inline: auto; height: calc(var(--coll-h, 0) / 100 * var(--collage-w)); }
.coll-tile { position: absolute; left: calc(var(--tx) * 1cqw); top: calc(var(--ty) * 1cqw); width: calc(var(--tw) * 1cqw); height: calc(var(--th) * 1cqw); }
.coll-tile__ph, .coll-tile__fill { display: block; width: 100%; height: 100%; }
.coll-tile__ph { border-radius: var(--radius); }   /* D-B8: rounded everywhere, one system */

.coll-back-top { display: flex; justify-content: center; padding-top: var(--block-gap); }
.coll-end { display: flex; flex-direction: column; gap: var(--block-gap); padding: var(--section-gap) var(--margin); }
.coll-end__next { display: flex; flex-direction: column; gap: 8px; }
.coll-end__next-title { margin: 0; }
.coll-end__doors { display: flex; gap: 16px; flex-wrap: wrap; }
@media (min-width: 768px) {
  .coll-end { flex-direction: row; align-items: center; justify-content: space-between; }
}

/* ============ The story template (.story-) ============ */
/* every block sits in the same collage-w content column as the collage on the other pages (the comp's Story
   head, spreads and Story end all measure from this column, centered margin to margin). */
.story-col { width: var(--collage-w); max-width: calc(100% - 2 * var(--margin)); margin-inline: auto; }

/* name + title, beside the narrative on the native story: the same row/column switch as Home's first view
   (pages-home.css .home-first), at the same 1024 breakpoint, since no 768 comp exists for this page. */
.story-head { display: flex; flex-direction: column; gap: 24px; padding-block: var(--block-gap); }
.story-head__names { display: flex; flex-direction: column; gap: 12px; }
.story-head__name, .story-head__title { margin: 0; }
.story-narrative { display: flex; flex-direction: column; gap: 16px; }
.story-narrative p { margin: 0; }
@media (min-width: 1024px) {
  .story-head { flex-direction: row; gap: 40px; }
  .story-head__names { flex: 0 1 360px; }
  .story-narrative { flex: 1 1 667px; flex-direction: row; gap: 40px; }
  .story-narrative p { flex: 1 1 0; }
}

/* the native story's four spreads (Kylie, "Haunting of Point Reyes"): square corners, as the comp draws them
   (no radius on its Photograph rects, unlike the collage's tiles). */
/* each spread in the comp carries the gutter as its own bottom padding, so the last one keeps it before the story's end
   (a flex gap stops at the last item: 17 px short at 1440, orchestrator 10-19) */
.story-native { display: flex; flex-direction: column; gap: var(--gutter); padding-bottom: var(--gutter); }
.story-native__photo { display: block; width: 100%; }
.story-native__photo img { border-radius: 0; }
/* the photograph fills its lightbox link, which carries the slot's size (orchestrator, 10-19) */
.story-native__photo > .story-native__fill { display: block; width: 100%; height: 100%; }
.story-native__single .story-native__photo { aspect-ratio: 3 / 2; }
.story-native__duo { display: flex; flex-direction: column; gap: var(--gap); }
.story-native__duo .story-native__photo { aspect-ratio: 2 / 3; }
.story-native__credits-row { display: flex; flex-direction: column; gap: var(--gap); }
.story-native__credits-row .story-native__photo { aspect-ratio: 2 / 3; }
/* the credits text sits at the bottom of its column, not the top (measured: 113 px of empty space above it
   at 390, where the column's own height exceeds its content); below 768 nothing stretches it to the photo's
   height (they stack), so it takes the comp's own measured height directly. */
.story-native__credits { display: flex; flex-direction: column; justify-content: flex-end; gap: 14px; padding: 0 32px 32px 32px; min-height: 260px; }
@media (min-width: 768px) {
  .story-native__duo { flex-direction: row; gap: var(--gutter); }
  .story-native__duo .story-native__photo { flex: 1 1 0; }
  .story-native__credits-row { display: grid; grid-template-columns: 493fr 557fr; gap: var(--gutter); align-items: stretch; }
  .story-native__credits-row .story-native__photo { aspect-ratio: 493 / 788; }
}
.story-credits__row { display: flex; align-items: baseline; gap: 8px; }
.story-credits__label, .story-credits__value { flex: 0 0 auto; margin: 0; }
.story-credits__leader { flex: 1 1 auto; border-bottom: 1px dotted var(--dim); margin-bottom: 5px; height: 0; }

/* the other 52 stories: his flattened spreads, full width, in a lightbox group per story (D-B10, B16) */
.story-plain { display: flex; flex-direction: column; gap: var(--gutter); padding-bottom: var(--gutter); }
.story-plain__link { display: block; }
.story-plain__ph { display: block; width: 100%; }
.story-plain__ph img { border-radius: 0; }

.story-end { display: flex; flex-direction: column; gap: var(--block-gap); padding-block: var(--section-gap); }
/* the comp's Next story block: the label and the title 8 px apart (orchestrator, 10-19: parity measured the label and
   title touching; the collection pages' .coll-end__next had the same fix) */
.story-end__next { display: flex; flex-direction: column; gap: 8px; }
.story-end__next-title { margin: 0; }
.story-end__doors { display: flex; gap: 16px; flex-wrap: wrap; }
@media (min-width: 768px) {
  .story-end { flex-direction: row; align-items: center; }
  .story-end__doors { margin-left: auto; }
}


