/* Tom Williamson Plumbing & Heating, Dereham. A 3-scene 3D film mock-up (Tier 2C,
   ~/studio/assets/3d-playbook.md). One lead effect: a cut-away house on a cold night
   warms up room by room as the boiler lights. Then the house goes see-through so the
   glowing pipes show, stop by stop, and the camera dives into a phone screen that
   becomes the "send a photo" form. Navy, white and his flame orange and water blue.
   Mobile first. */

@font-face {
  font-family: "Archivo Expanded";
  src: url("assets/fonts/archivo-expanded-800.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light dark;

  --navy: #0c1a2b;
  --flame: #ff7a1f;
  --flame-hover: #ff9142;
  --flame-deep: #b84a00;
  --on-flame: #0c1a2b;
  --blue: #1f5fbf;

  --paper: #ffffff;
  --ink: #0c1a2b;
  --ink-soft: #46566a;
  --line: #cdd6e0;
  --sheet-alt: #eef3f8;
  --wash: rgb(255 255 255 / 0.985);
  --focus: #0c1a2b;
  --focus-gap: #ffffff;
  --error: #b42318;
  --good: #1c6b3c;
  --mark: rgb(255 122 31 / 0.24);

  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --font-display: "Archivo Expanded", "Arial Black", "Segoe UI", system-ui, sans-serif;

  --gutter: clamp(1rem, 4vw, 3rem);
  --header-h: 3.75rem;
  --step--1: clamp(0.875rem, 0.85rem + 0.1vw, 0.95rem);
  --step-0: clamp(1rem, 0.98rem + 0.15vw, 1.1rem);
  --step-1: clamp(1.15rem, 1.05rem + 0.5vw, 1.45rem);
  --radius: 0.55rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --flame: #ff9a4d;
    --flame-hover: #ffb27a;
    --flame-deep: #c75a0c;
    --blue: #8cc3f5;
    --paper: #08121f;
    --ink: #eef3f8;
    --ink-soft: #b3c1d0;
    --line: #2a3a4e;
    --sheet-alt: #0f1d2f;
    --wash: rgb(8 18 31 / 0.985);
    --focus: #ffb27a;
    --focus-gap: #08121f;
    --error: #ff9c8f;
    --good: #8fdbab;
    --mark: rgb(255 154 77 / 0.26);
  }
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; overflow-x: clip; scroll-padding-top: calc(var(--header-h) + 0.75rem); }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: 1.55;
  overflow-x: clip;
}
img { display: block; max-width: 100%; height: auto; }
h1, h2, h3, p, ul, ol, figure, fieldset, blockquote { margin: 0; padding: 0; }
h1, h2, h3 { font-family: var(--font-display); font-weight: 800; line-height: 1.04; letter-spacing: -0.03em; color: var(--ink); }
h2 { font-size: clamp(1.9rem, 1.1rem + 4vw, 4rem); }
ul, ol { list-style: none; }
a { color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--focus-gap);
  border-radius: 2px;
}

.wrap { width: min(100% - 2 * var(--gutter), 76rem); margin-inline: auto; }
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.small { font-size: var(--step--1); color: var(--ink-soft); }
.nowrap { white-space: nowrap; }

.skip-link {
  position: fixed; left: 0.75rem; top: -4rem; z-index: 60;
  padding: 0.75rem 1rem; background: var(--paper); color: var(--ink); font-weight: 700;
}
.skip-link:focus { top: 0.75rem; }

.demo-banner {
  position: relative; z-index: 11;
  padding: 0.4rem var(--gutter);
  background: var(--navy);
  color: #ffffff;
  font-size: var(--step--1);
  line-height: 1.35;
  text-align: center;
}
@media (prefers-color-scheme: dark) { .demo-banner { background: #02070d; } }

/* --- Header: the call button is always here -------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.header-inner {
  min-height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.logo {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  min-height: 44px;
  text-decoration: none;
  min-width: 0;
}
.logo-mark { flex: none; width: 1.3rem; height: auto; }
@media (prefers-color-scheme: dark) { .logo-mark .drop { fill: #4f86e8; } }
.logo-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.86rem;
  line-height: 1;
  letter-spacing: -0.03em;
}
.logo-name { white-space: nowrap; }
.logo-trade { display: none; margin-top: 0.15rem; font-family: var(--font-sans); font-weight: 650; font-size: 0.74rem; letter-spacing: 0; color: var(--ink-soft); }
nav { display: none; }
.header-actions { display: flex; align-items: center; gap: 0.4rem; flex: none; }
.label-long { display: none; }
.nav-list { display: flex; align-items: center; gap: 0.1rem; }
.nav-list a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 0.6rem;
  font-size: var(--step--1);
  font-weight: 650;
  text-decoration: none;
  text-underline-offset: 0.3em;
}
.nav-list a:hover, .nav-list a:focus-visible { text-decoration: underline; text-decoration-thickness: 2px; text-decoration-color: var(--flame); }

/* Phones: the logo and Call. The hero's own photo button sits just below. */
@media (max-width: 25.99rem) {
  .header-actions .header-photo { display: none; }
}
@media (max-width: 19.9rem) {
  .logo-name { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}
@media (min-width: 30rem) { .logo-name { font-size: 1rem; } .logo-trade { display: block; } }
@media (min-width: 40rem) {
  .label-long { display: inline; }
  .label-short { display: none; }
}
@media (min-width: 64rem) { nav { display: block; } }

/* --- Buttons --------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0.6rem 1.3rem;
  border: 2px solid transparent;
  border-radius: 0.6rem;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 160ms ease, transform 120ms ease, box-shadow 160ms ease, border-color 160ms ease;
  -webkit-tap-highlight-color: transparent;
}
.btn svg { fill: currentColor; flex: none; }
.btn-primary { background: var(--flame); color: var(--on-flame); box-shadow: 0 4px 0 var(--flame-deep); }
.btn-primary:hover { background: var(--flame-hover); }
.btn-primary:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--flame-deep); }
.btn-big { min-height: 56px; padding: 0.75rem 1.5rem; font-size: 1.1rem; }
.btn-outline { background: var(--paper); color: var(--ink); border-color: var(--ink); }
.btn-outline:hover { background: var(--mark); }
.btn-outline:active { transform: translateY(1px) scale(0.98); }
.btn-call { background: var(--navy); color: #ffffff; }
.btn-call:hover { background: #1d3150; }
.btn-call:active { transform: scale(0.96); }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { border-color: var(--ink); }
.btn-ghost:active { transform: scale(0.96); }
.btn-small { min-height: 44px; padding: 0.4rem 0.8rem; font-size: var(--step--1); }
@media (prefers-color-scheme: dark) {
  .btn-call { background: #eef3f8; color: #0c1a2b; }
  .btn-call:hover { background: #ffffff; }
}

/* --- The film ----------------------------------------------------------------
   One 3D world behind the whole page (film.js). The words never live in it:
   each section is a solid sheet that scrolls over the film, and each scene gets
   a "stage" where the film is the picture and a huge title slides across.
   Without the film (reduced motion, Save-Data, weak devices, no JavaScript)
   each stage shows a still frame rendered from the film itself. */
.film {
  position: fixed;
  inset: 0;
  z-index: -1;
  display: none;
  pointer-events: none;
  overflow: hidden;
  background: #0b1626;
}
html.film-on .film { display: block; }
.film canvas { display: block; width: 100%; height: 100%; opacity: 0; transition: opacity 700ms ease; }
html.film-ready .film canvas { opacity: 1; }
.film::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 45%, transparent 62%, rgb(4 10 20 / 0.28) 100%);
}

/* Labels pinned to the 3D: white pills with navy text pass in every frame.
   Decorative copies of the real list in the stage. */
.film-labels { position: fixed; inset: 0; z-index: 5; pointer-events: none; }
.film-label {
  position: absolute;
  left: 0;
  top: 0;
  padding: 0.35rem 0.85rem 0.4rem;
  background: rgb(255 255 255 / 0.97);
  color: #0c1a2b;
  border-radius: 0.45rem;
  box-shadow: 0 6px 18px -8px rgb(4 10 20 / 0.6);
  font-size: var(--step--1);
  font-weight: 800;
  line-height: 1.25;
  white-space: nowrap;
  opacity: 0;
  will-change: transform, opacity;
}
.film-label b { display: block; font-size: 0.72rem; font-weight: 700; color: #8a3a00; letter-spacing: 0; }
.film-lead {
  position: absolute;
  left: 0;
  top: 0;
  height: 2px;
  background: #ffffff;
  transform-origin: 0 50%;
  opacity: 0;
  box-shadow: 0 0 2px rgb(4 10 20 / 0.8);
}
.film-lead::after {
  content: "";
  position: absolute;
  right: -5px;
  top: -4px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #ff7a1f;
  box-shadow: 0 0 0 2px #0c1a2b;
}
@media (min-width: 48rem) { .film-label { font-size: var(--step-0); padding: 0.45rem 1.05rem 0.5rem; } }

/* --- Hero: a cold house warms up ------------------------------------------- */
.hero {
  position: relative;
  isolation: isolate;
  overflow: clip;
  display: flex;
  flex-direction: column;
  background: #0b1626;
}
html.film-on .hero { background: transparent; }
.hero-window { height: 40svh; flex: none; }

.hero-poster { position: absolute; inset: 0 0 auto 0; height: 100svh; z-index: -2; overflow: hidden; }
.hero-poster img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
/* Without the film the still starts where the screen starts (behind the banner
   and header), so it frames the house exactly as the film does. */
html:not(.film-on) .hero-poster { top: -6.4rem; }
html.film-on .hero-poster { position: fixed; inset: 0; height: auto; }
html.film-ready .hero-poster { opacity: 0; transition: opacity 700ms ease, visibility 0s linear 700ms; visibility: hidden; }

/* The cold veil: a deep night blue over the warm still, with a hole at the
   boiler that grows until the whole house is warm (transform and opacity only,
   so it costs the main thread nothing). Only where the film runs, and only
   until the 3D takes over. Its geometry is set per screen shape below. */
.chill { display: none; position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; --bx: 30.2%; --by: 32.4%; }
/* Where the boiler sits in each still (measured from the film, film.js). */
@media (min-aspect-ratio: 1/1) { .chill { --bx: 63.1%; --by: 61%; } }
html.film-on .chill { display: block; }
html.film-ready .chill { display: none; }
.chill i {
  position: absolute;
  left: var(--bx, 50%);
  top: var(--by, 30%);
  width: 360vmax;
  height: 360vmax;
  margin: -180vmax 0 0 -180vmax;
  border-radius: 50%;
  background: radial-gradient(circle, transparent 0 1.2%, rgb(6 16 34 / 0.55) 2.6%, rgb(6 16 34 / 0.86) 5%);
  opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
  html.film-on .chill i { animation: warm-up 3.1s cubic-bezier(.45, 0, .3, 1) 0.15s both; }
  html.film-on .hero-poster img { animation: settle 4.5s cubic-bezier(.2, .6, .2, 1) both; transform-origin: 50% 35%; }
  .hero-panel h1 { animation: land 900ms cubic-bezier(.2, .7, .2, 1) both; }
}
.hero.is-paused .chill i, .hero.is-paused .hero-poster img { animation-play-state: paused; }
@keyframes warm-up {
  0% { opacity: 1; transform: scale(0.35); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: scale(9); }
}
@keyframes settle { from { transform: scale(1.08) translateY(1.5%); } to { transform: none; } }
@keyframes land { from { transform: translateY(0.25em); } to { transform: none; } }

/* Words on phones: a solid block under the house, in thumb reach, with the
   title above it. Nothing that moves can land on the buttons. */
.hero-panel {
  position: relative;
  z-index: 2;
  padding: 1.1rem var(--gutter) 2rem;
  background: var(--paper);
}
.hero-where { font-size: var(--step--1); font-weight: 700; color: var(--ink-soft); }
.hero-panel h1 { margin-top: 0.45rem; font-size: clamp(1.65rem, 1rem + 3.4vw, 3.4rem); line-height: 1.02; }
.hero-actions { margin-top: 1.1rem; display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; }
/* Phones: the second button wraps under the call button on the left, clear of
   the fixed pause button in the bottom-right corner. */
@media (max-width: 47.99rem) {
  .hero-actions { padding-right: 6.4rem; }
  .hero-actions .btn { width: 100%; }
  .hero-actions .btn-outline { font-size: 0.94rem; padding-inline: 0.8rem; }
  .scene-title--house, .scene-title--photo { font-size: 13vw; }
}
.hero-quote { margin-top: 1.4rem; padding-left: 1rem; border-left: 4px solid var(--flame); max-width: 40rem; }
.hero-quote p { font-size: var(--step--1); line-height: 1.5; color: var(--ink-soft); }
.hero-quote mark, .review mark { background: var(--mark); color: var(--ink); font-weight: 700; padding: 0 0.1em; }
.hero-quote figcaption { margin-top: 0.4rem; font-size: var(--step--1); font-weight: 700; }
.hero-rating { margin-top: 0.6rem; font-size: var(--step--1); color: var(--ink-soft); }
.hero-rating strong { color: var(--ink); }
.stars { color: #8f4a00; letter-spacing: 0.08em; margin-left: 0.3rem; }
@media (prefers-color-scheme: dark) { .stars { color: #ffc35c; } }

/* --- Scene titles ------------------------------------------------------------ */
.scene-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(3.6rem, 16vw, 11rem);
  line-height: 0.9;
  letter-spacing: -0.05em;
  color: #ffffff;
  white-space: nowrap;
  paint-order: stroke fill;
  -webkit-text-stroke: 0.07em #0c1a2b;
  pointer-events: none;
  user-select: none;
}
@media (prefers-reduced-motion: no-preference) {
  .scene-title { transform: translateX(calc((0.5 - var(--p, 0.5)) * 40vw)); will-change: transform; }
}
.scene-title--hero {
  position: relative;
  z-index: 1;
  padding: 0 var(--gutter) 0.08em;
  font-size: clamp(1.6rem, 7.8vw, 10rem);
}

/* --- Stages ------------------------------------------------------------------ */
.stage { position: relative; overflow-x: clip; }
.stage-inner { position: relative; }
html.film-on .stage { height: 200svh; }
html.film-on .stage--house { height: 380svh; }
html.film-on .stage--photo { height: 210svh; }
html.film-on .stage-inner {
  position: sticky;
  top: var(--header-h);
  height: calc(100svh - var(--header-h));
  overflow: clip;
}
html.film-on .stage-still { position: absolute; inset: 0; z-index: -1; }
html.film-on .stage-still img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
html.film-ready .stage-still { display: none; }

html:not(.film-on) .stage-inner { overflow: clip; }
.stage-still img { width: 100%; max-height: 88svh; object-fit: cover; object-position: 50% 0; background: #0b1626; }

.scene-title--house, .scene-title--photo {
  position: absolute;
  left: var(--gutter);
  top: 0.75rem;
}
.scene-title--photo { font-size: clamp(3rem, 13vw, 9rem); }

/* The see-through house: the real words sit low on the scene, on their own
   white card. With the film running, the labels live in the 3D and the card
   becomes a slim caption so the camera's view stays clear. */
.house-words, .photo-words {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: 5rem;
  max-width: 34rem;
  padding: 0.9rem 1.1rem 1rem;
  background: rgb(255 255 255 / 0.97);
  color: #0c1a2b;
  border-radius: var(--radius);
  box-shadow: 0 18px 40px -22px rgb(4 10 20 / 0.7);
}
html:not(.film-on) .house-words, html:not(.film-on) .photo-words { position: relative; left: auto; right: auto; bottom: auto; margin: -3rem var(--gutter) 2.5rem; }
.house-words h2, .photo-words h2 { font-size: clamp(1.3rem, 1.05rem + 1.2vw, 2rem); color: #0c1a2b; }
.house-sub { display: block; margin-top: 0.3rem; font-family: var(--font-sans); font-size: var(--step--1); font-weight: 600; letter-spacing: 0; color: #46566a; }
.photo-words p { margin-top: 0.35rem; font-size: var(--step--1); font-weight: 600; color: #46566a; }
.house-stops { margin-top: 0.7rem; display: grid; gap: 0.35rem; font-size: var(--step--1); counter-reset: stop; }
.house-stops li { counter-increment: stop; padding-left: 1.9rem; position: relative; line-height: 1.35; }
.house-stops li::before { content: counter(stop); position: absolute; left: 0; top: 0.05rem; width: 1.35rem; height: 1.35rem; border-radius: 50%; background: #ff7a1f; color: #0c1a2b; font-weight: 800; font-size: 0.75rem; display: grid; place-items: center; }
.house-stops strong { display: block; }
html.film-ready .house-stops { position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
html.film-ready .house-words { bottom: 4.6rem; max-width: 26rem; }

/* --- Pause button ------------------------------------------------------------ */
.motion-toggle {
  position: fixed;
  right: max(var(--gutter), env(safe-area-inset-right));
  bottom: max(0.9rem, env(safe-area-inset-bottom));
  z-index: 20;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.5rem 0.95rem;
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: 999px;
  font-size: var(--step--1);
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 6px 16px -8px rgb(4 10 20 / 0.5);
  transition: transform 140ms ease;
}
.motion-toggle[hidden], html:not(.film-on) .motion-toggle { display: none; }
.motion-toggle:hover { transform: translateY(-1px); }
.motion-toggle:active { transform: scale(0.96); }
.motion-toggle svg { fill: currentColor; }
.ml-long { display: none; }
@media (min-width: 40rem) { .ml-long { display: inline; } }
.motion-toggle .icon-play { display: none; }
body:has(.hero.is-paused) .motion-toggle .icon-play { display: inline; }
body:has(.hero.is-paused) .motion-toggle .icon-pause { display: none; }
@media (prefers-reduced-motion: reduce) { .motion-toggle { display: none; } }

/* --- Sections: solid sheets that slide over the film ------------------------ */
.section { position: relative; z-index: 1; padding-block: clamp(3.5rem, 8vw, 7rem); background: var(--paper); }
/* Below the fold: skip their layout until they come near the screen. */
.section-work, .section-reviews, .section-contact { content-visibility: auto; contain-intrinsic-size: auto 1100px; }

/* His own work: his photos, big, in an uneven mosaic (not a card grid). */
.work-head { display: grid; gap: 0.9rem; max-width: 46rem; }
.work-lede { font-size: var(--step-1); line-height: 1.4; }
.work-grid { margin-top: clamp(1.75rem, 4vw, 3rem); display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.work-grid li:first-child { grid-column: 1 / -1; }
.work-grid figure { position: relative; height: 100%; overflow: hidden; border-radius: var(--radius); background: var(--sheet-alt); }
.work-grid img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 1; }
.work-grid li:first-child img { aspect-ratio: 4 / 3; }
.work-grid figcaption {
  position: absolute;
  left: 0.5rem;
  bottom: 0.5rem;
  max-width: calc(100% - 1rem);
  padding: 0.2rem 0.55rem 0.25rem;
  background: rgb(255 255 255 / 0.96);
  color: #0c1a2b;
  border-radius: 0.35rem;
  font-size: 0.8rem;
  font-weight: 800;
  line-height: 1.25;
}
@media (min-width: 48rem) {
  .work-grid { grid-template-columns: repeat(6, 1fr); grid-auto-rows: 11rem; gap: 0.75rem; }
  .work-grid li:first-child { grid-column: 1 / 4; grid-row: span 2; }
  .work-b { grid-column: 4 / 6; grid-row: span 2; }
  .work-c { grid-column: 6 / 7; grid-row: span 2; }
  .work-d { grid-column: 1 / 3; grid-row: span 2; }
  .work-e { grid-column: 3 / 7; grid-row: span 2; }
  .work-grid img, .work-grid li:first-child img { aspect-ratio: auto; }
  .work-grid figcaption { font-size: var(--step--1); }
}

/* Reviews: an editorial run, not cards. */
.section-reviews { background: var(--sheet-alt); }
.reviews-layout { display: grid; gap: clamp(2rem, 5vw, 4rem); }
.reviews-lede { margin-top: 1rem; font-size: var(--step-1); line-height: 1.35; font-weight: 600; }
.rating { margin-top: 0.4rem; font-size: var(--step--1); color: var(--ink-soft); }
.rating strong { color: var(--ink); }
.reviews-actions { margin-top: 1.25rem; }
.reviews-list { display: grid; gap: clamp(1.75rem, 3.5vw, 2.75rem); }
.review blockquote p {
  font-size: clamp(1.1rem, 1rem + 0.55vw, 1.4rem);
  line-height: 1.4;
  font-weight: 500;
  color: var(--ink);
}
.review figcaption { margin-top: 0.55rem; font-size: var(--step--1); font-weight: 700; color: var(--ink-soft); padding-left: 1.6rem; position: relative; }
.review figcaption::before { content: ""; position: absolute; left: 0; top: 0.65em; width: 1rem; height: 3px; border-radius: 2px; background: var(--flame); }
@media (min-width: 62rem) {
  .reviews-layout { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.3fr); align-items: start; }
  .reviews-head { position: sticky; top: calc(var(--header-h) + 2rem); }
}

/* The photo scene's words. */
.photo-words { max-width: 26rem; }

/* The form: the white the camera flew into. */
.section-quote { background: var(--paper); }
.quote-layout { display: grid; gap: clamp(1.75rem, 4vw, 3rem); }
.quote-lede { margin-top: 1rem; font-size: var(--step-1); line-height: 1.4; max-width: 32ch; }
.review--steven { margin-top: 1.5rem; padding-left: 1rem; border-left: 4px solid var(--flame); }
.review--steven blockquote p { font-size: var(--step-0); }
.quote-call { margin-top: 1.4rem; display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 0.9rem; font-weight: 700; }
.quote-form { display: grid; gap: 0.95rem; padding: clamp(1.1rem, 3vw, 2rem); border: 2px solid var(--line); border-radius: 0.9rem; background: var(--paper); }
.field { min-width: 0; border: 0; }
.field-row { display: grid; gap: 0.95rem; }
.quote-form label { display: block; font-weight: 800; font-size: var(--step--1); margin-bottom: 0.3rem; }
.optional { font-weight: 400; color: var(--ink-soft); }
input[type="text"], input[type="tel"], textarea {
  display: block;
  width: 100%;
  min-height: 48px;
  padding: 0.55rem 0.75rem;
  background: var(--paper);
  border: 2px solid var(--ink-soft);
  border-radius: var(--radius);
  transition: border-color 140ms ease, box-shadow 140ms ease;
}
textarea { resize: vertical; }
::placeholder { color: var(--ink-soft); opacity: 1; }
input:hover, textarea:hover { border-color: var(--ink); }
input[type="text"]:focus-visible, input[type="tel"]:focus-visible, textarea:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; box-shadow: none; }
.field.is-valid input, .field.is-valid textarea { border-color: var(--good); }
.field.is-invalid input, .field.is-invalid textarea { border-color: var(--error); }
.field-msg { min-height: 1.3em; margin-top: 0.2rem; font-size: var(--step--1); color: var(--error); }
input[type="file"] {
  display: block;
  width: 100%;
  min-height: 48px;
  padding: 0.6rem;
  border: 2px dashed var(--ink-soft);
  border-radius: var(--radius);
  background: var(--sheet-alt);
  font-size: var(--step--1);
  cursor: pointer;
  transition: border-color 140ms ease, background-color 140ms ease;
}
input[type="file"]:hover { border-color: var(--ink); }
input[type="file"]::file-selector-button {
  margin-right: 0.75rem;
  min-height: 40px;
  padding: 0.35rem 0.9rem;
  border: 0;
  border-radius: 0.45rem;
  background: var(--navy);
  color: #ffffff;
  font-weight: 800;
  cursor: pointer;
}
@media (prefers-color-scheme: dark) { input[type="file"]::file-selector-button { background: #eef3f8; color: #0c1a2b; } }
.photo-preview { margin-top: 0.6rem; display: flex; align-items: center; gap: 0.75rem; font-size: var(--step--1); font-weight: 700; overflow-wrap: anywhere; }
.photo-preview[hidden] { display: none; }
.photo-preview img { width: 4.5rem; height: 4.5rem; object-fit: cover; border-radius: 0.4rem; border: 2px solid var(--flame); }
.quote-form .btn { justify-self: start; }
.form-note { margin-top: -0.3rem; }
.form-done { padding: 0.9rem 1rem; border-left: 4px solid var(--flame); background: var(--sheet-alt); }
.form-done[hidden] { display: none; }
.form-done p + p { margin-top: 0.3rem; }
@media (min-width: 40rem) { .field-row { grid-template-columns: 1fr 1fr; } }
@media (min-width: 62rem) {
  .quote-layout { grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.15fr); align-items: start; }
}

/* Contact strip: his van, big. */
.section-contact { background: var(--sheet-alt); }
.contact-layout { display: grid; gap: clamp(1.75rem, 5vw, 4rem); align-items: center; }
.van img { width: 100%; border-radius: var(--radius); box-shadow: 0 30px 50px -30px rgb(4 10 20 / 0.6); }
.contact-list { margin-top: 1.1rem; display: grid; gap: 0; }
.contact-list li { display: grid; grid-template-columns: 6.5rem 1fr; gap: 0.75rem; padding: 0.65rem 0; border-bottom: 1px solid var(--line); font-size: var(--step-0); font-weight: 600; }
.contact-list a { font-weight: 800; text-underline-offset: 0.25em; text-decoration-color: var(--flame); text-decoration-thickness: 2px; overflow-wrap: anywhere; display: inline-block; padding-block: 0.35rem; margin-block: -0.35rem; }
.contact-k { color: var(--ink-soft); font-weight: 600; }
.contact-words .small { margin-top: 0.75rem; }
@media (min-width: 62rem) {
  .contact-layout { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr); }
}

.site-footer { position: relative; z-index: 1; padding-block: 1.5rem 5.5rem; background: var(--navy); color: #ffffff; font-size: var(--step--1); }
.site-footer a { color: inherit; text-underline-offset: 0.2em; overflow-wrap: anywhere; }
.site-footer .small { color: #d3dde8; margin-top: 0.4rem; }
@media (prefers-color-scheme: dark) { .site-footer { background: #02070d; } }

/* Scroll scenes. Visible in the HTML; only once script.js has set them up do
   they wait to arrive. Each reveal suits its content: his photos open out
   like the camera opening up the house, reviews rise one by one, the van
   pulls in from the side. */
html.scenes-on [data-scene="photos"] figure { clip-path: inset(18% 18% 18% 18% round var(--radius)); transition: clip-path 720ms cubic-bezier(.2,.7,.2,1); }
html.scenes-on [data-scene="photos"] li:nth-child(2) figure { transition-delay: 90ms; }
html.scenes-on [data-scene="photos"] li:nth-child(3) figure { transition-delay: 180ms; }
html.scenes-on [data-scene="photos"] li:nth-child(4) figure { transition-delay: 270ms; }
html.scenes-on [data-scene="photos"] li:nth-child(5) figure { transition-delay: 360ms; }
html.scenes-on [data-scene="photos"].is-in figure { clip-path: inset(0 0 0 0 round var(--radius)); }
html.scenes-on [data-scene="quote"] { transform: translateY(1.5rem); opacity: 0; transition: transform 560ms cubic-bezier(.2,.7,.2,1), opacity 420ms ease; }
html.scenes-on [data-scene="quote"].is-in { transform: none; opacity: 1; }
html.scenes-on [data-scene="open"] img { transform: translateX(-12%); opacity: 0; transition: transform 800ms cubic-bezier(.2,.7,.2,1), opacity 500ms ease; }
html.scenes-on [data-scene="open"].is-in img { transform: none; opacity: 1; }

/* Wide screens: the white wash, solid enough to read at every frame. The house
   sits to the right of it and never reaches the words or the buttons. */
@media (min-width: 48rem) and (min-aspect-ratio: 1/1) {
  .hero { flex-direction: row; justify-content: flex-start; align-items: stretch; min-height: calc(100svh - var(--header-h) - 2.2rem); }
  .hero-window { display: none; }
  .hero-poster { height: auto; inset: 0; }
  .hero-panel {
    width: min(38rem, 44vw);
    flex: none;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: clamp(2rem, 4vw, 4rem) clamp(1.5rem, 3.5vw, 4rem);
    background: var(--wash);
  }
  .hero-panel h1 { font-size: clamp(2rem, 0.9rem + 2.6vw, 3.5rem); }
  .scene-title--hero {
    position: absolute;
    z-index: -1;
    right: var(--gutter);
    bottom: 4.6rem;
    padding: 0;
    text-align: right;
    font-size: clamp(2.6rem, 5.4vw, 6.5rem);
  }
  .house-words, .photo-words { right: auto; bottom: 2rem; }
  html.film-ready .house-words { bottom: 2rem; }
}
@media (min-aspect-ratio: 1/1) and (max-height: 34rem) {
  .hero-panel { padding-block: 1rem; }
  .hero-panel h1 { font-size: clamp(1.5rem, 1rem + 2.2vw, 2.2rem); }
  .hero-quote { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
}

@media print {
  .site-header, .film, .film-labels, .stage-still, .hero-poster, .scene-title, .motion-toggle, .chill { display: none !important; }
}

/* Still-frame capture (film.js ?still=J): only the film shows. */
html.film-capture body > :not(.film) { visibility: hidden; }
html.film-capture .film { z-index: 1; }
html.film-capture .film::after { display: none; }
html.film-capture .film canvas { transition: none; }
html.film-washed .film::after { opacity: 0; transition: opacity 300ms ease; }
html.film-capture { scrollbar-width: none; }
html.film-capture::-webkit-scrollbar { display: none; }
