/* =========================================================
   NEXT - Concrete Coatings
   Warm cream · charcoal · the logo's burnt orange
   ========================================================= */

/* ---------- fonts ----------

   Both faces are local, so there is no network round-trip on the
   critical path and nothing to block the first paint. WOFF2 first -
   it is a third of the TTF - with the TTF kept only as a fallback for
   anything that cannot read it.
*/

@font-face {
  font-family: "AlteHaasGrotesk";
  src: url("assets/fonts/AlteHaasGroteskRegular.woff2") format("woff2"),
    url("assets/fonts/AlteHaasGroteskRegular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "AlteHaasGrotesk";
  src: url("assets/fonts/AlteHaasGroteskBold.woff2") format("woff2"),
    url("assets/fonts/AlteHaasGroteskBold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/*
  Neue Montreal, for the headings. Licensed from Pangram Pangram, so the
  files are deliberately not committed. To switch it on:

    1. Put NeueMontreal-Bold.woff2 in assets/fonts/ (a .woff2 - convert
       the .otf with `woff2_compress`, which is already installed).
    2. That is all. The stack below picks it up and every h1/h2/h3, the
       form's questions, the estimate figure and the footer number
       follow it.

  font-display: swap means a missing file costs nothing: the fallback
  renders immediately and the page never blocks on it.

  Note the free "PP Neue Montreal" download is personal-use only. A
  commercial site needs the paid licence.
*/
@font-face {
  font-family: "NeueMontreal";
  src: url("assets/fonts/NeueMontreal-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- tokens ---------- */

:root {
  /* the palette is pulled straight off the logo */
  --cream: #eeeae1;
  --cream-rgb: 238, 234, 225;
  --ink: #1a1512;
  --ink-rgb: 26, 21, 18;
  --rust: #b4451c;
  --rust-rgb: 180, 69, 28;
  --amber: #e08a2e;

  --bg: var(--cream);
  --fg: var(--ink);
  --muted: #6d6358;
  --rule: rgba(26, 21, 18, 0.14);

  --body: "AlteHaasGrotesk", "Helvetica Neue", Arial, sans-serif;
  /*
    Headings want Neue Montreal Bold. It is a licensed face, so the files
    are not in the repo - see the @font-face block above for what to drop
    in. Until they are there the stack falls straight through to the
    platform's own UI face, which is what the site shipped with and is a
    near enough neo-grotesque that nothing looks broken in the meantime.
  */
  --display: "NeueMontreal", "SF Pro Display", -apple-system,
    BlinkMacSystemFont, "Segoe UI", system-ui, "Helvetica Neue", sans-serif;
  --hero-face: var(--display);

  --measure: 76rem;
  --gutter: clamp(1.25rem, 5vw, 3.5rem);
  --radius: 14px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  --nav-h: 6.25rem;
  --nav-pill-h: 4.4rem;
  /* how far clear of the top edge the pill floats once stuck */
  --nav-float: 0.4in;
}

/* ---------- base ---------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-pill-h) + var(--nav-float) + 1.5rem);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--body);
  font-size: clamp(0.95rem, 0.9rem + 0.2vw, 1.03rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img,
video {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
}

/*
  Light rather than bold, and tracked open rather than pulled in. A
  heading this size does not need weight to carry - it has the size
  already - and the air between the letters is what makes it read as
  set rather than typed.
*/
h1,
h2,
h3 {
  margin: 0;
  font-family: var(--display);
  font-weight: 350;
  line-height: 1.15;
  letter-spacing: 0.015em;
  text-transform: none;
}

/*
  For text that exists for search engines and screen readers but has no
  place in the layout - the home page's hero is a video with no copy on
  it, so its h1 lives here.
*/
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.75rem 1rem;
  background: var(--ink);
  color: var(--cream);
}

.skip:focus {
  left: 0.5rem;
  top: 0.5rem;
}

:focus-visible {
  outline: 2px solid var(--rust);
  outline-offset: 3px;
}

/* ---------- shared ---------- */

.wrap {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.eyebrow {
  margin: 0 0 0.9rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
}

.eyebrow--light {
  color: rgba(var(--cream-rgb), 0.72);
}

.sec {
  padding-block: clamp(3.5rem, 9vh, 6rem);
}

/*
  Below the fold nothing needs laying out until it is scrolled near; the
  reserved height keeps the scrollbar honest while it is skipped.
*/
.sec--defer {
  content-visibility: auto;
  contain-intrinsic-size: auto 600px;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.5rem;
  border: 0;
  border-radius: 999px;
  background: var(--rust);
  color: var(--cream);
  font-family: var(--body);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.25s ease, transform 0.25s var(--ease);
}

.btn:hover,
.btn:focus-visible {
  background: #c9501f;
  transform: translateY(-1px);
}

.btn--ghost {
  background: transparent;
  color: var(--cream);
  box-shadow: inset 0 0 0 1px rgba(var(--cream-rgb), 0.5);
}

.btn--ghost:hover,
.btn--ghost:focus-visible {
  background: rgba(var(--cream-rgb), 0.12);
}

.btn--ink {
  background: var(--ink);
}

.btn--ink:hover,
.btn--ink:focus-visible {
  background: #2d2521;
}

.btn__arw {
  transition: transform 0.25s var(--ease);
}

.btn:hover .btn__arw,
.link:hover .btn__arw {
  transform: translateX(3px);
}

/* ---------- nav ----------

   In normal flow directly under the hero, so it lands on the bottom
   edge of the first screen. sticky pins it to the top the moment you
   scroll past it, and it stays there for the rest of the page.
*/

.topnav {
  position: sticky;
  /*
    Clear of the top edge once stuck. This lives on the sticky offset,
    not as a margin on the bar - a margin there collapses through this
    and just moves the whole element, leaving the bar flush to the top.
  */
  top: var(--nav-float);
  z-index: 30;
  /*
    Flat height, not min-. It has to stay put when the bar inside it
    collapses, or that shrink would reach the document, move everything
    below it, and shove the sentinel back across the trigger it fired.
  */
  block-size: var(--nav-h);
  /*
    Once stuck, the bottom of that reserved strip is empty and invisible
    but still sits above the page. It must not eat clicks meant for the
    content underneath.
  */
  pointer-events: none;
}

.topnav__bar {
  pointer-events: auto;
}

/* zero-height marker for the docked → floating switch */
.nav-sentinel {
  display: block;
  height: 0;
}

/*
  Two states, and the gap between them is the point. Docked: a deep
  full-width band lying across the bottom of the video. Stuck: it
  collapses to roughly half that depth and two thirds the width, and
  lifts off the page as a pill. The transition runs on the bar, not the
  sticky wrapper, so sticky positioning is never animated.
*/
.topnav__bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(0.85rem, 3vw, 2.25rem);
  width: 100%;
  margin-inline: auto;
  /* height is the thing that collapses, so it is set rather than left
     to the padding to imply */
  block-size: var(--nav-h);
  padding: 0 clamp(1rem, 4vw, 4rem);
  /* the page background exactly - docked, it should read as part of the
     page rather than a panel sitting on it */
  background: var(--bg);
  border: 1px solid transparent;
  border-bottom-color: var(--rule);
  border-radius: 0;
  transition: width 1.15s var(--ease), block-size 1.15s var(--ease),
    padding 1.15s var(--ease), border-radius 1.15s var(--ease),
    border-color 0.7s ease, box-shadow 1s ease, background 0.7s ease;
}

.topnav.is-stuck .topnav__bar {
  width: min(66.667%, 62rem);
  block-size: var(--nav-pill-h);
  padding-inline: clamp(1rem, 2.5vw, 2rem);
  background: rgba(var(--cream-rgb), 0.86);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  border-color: var(--rule);
  /* a floating bar, not a lozenge - the softer the corner, the more it
     reads as a component someone dropped in rather than designed */
  border-radius: 8px;
  /* a tight contact shadow plus a soft cast - lifted, not flat */
  box-shadow: 0 1px 2px rgba(var(--ink-rgb), 0.05),
    0 10px 28px rgba(var(--ink-rgb), 0.12),
    0 28px 56px rgba(var(--ink-rgb), 0.07);
}

.topnav__group {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.6vw, 2.15rem);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
}

.topnav__group--end {
  justify-content: flex-end;
}

.topnav__group a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.18s ease;
}

.topnav__group a:hover,
.topnav__group a:focus-visible {
  color: var(--rust);
}

.topnav__group a[aria-current="page"] {
  color: var(--fg);
}

/* same fill-fade as the page buttons */
.topnav__cta {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: 0.7rem 1.3rem;
  background: var(--ink);
  color: var(--cream) !important;
  border-radius: 6px;
}

.topnav__cta::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  background: var(--rust);
  opacity: 0;
  transition: opacity 0.4s ease;
}

.topnav__cta:hover::before,
.topnav__cta:focus-visible::before {
  opacity: 1;
}

/*
  The logo carries the size difference between the two states. Scale
  rather than width, so the collapse is a transform the compositor can
  run instead of a reflow on every frame of it.
*/
.topnav__logo {
  display: block;
  line-height: 0;
  text-decoration: none;
  scale: 1.18;
  transition: scale 1.15s var(--ease);
}

.topnav.is-stuck .topnav__logo {
  scale: 1;
}

/*
  The logo sits in the bar's `auto` track, and a grid track is allowed to
  shrink below its content when the two 1fr columns beside it want the
  room - which, with `img { max-width: 100% }` in the base, let the mark
  scale down to nothing once the bar collapsed to a pill. min-width on
  the link holds the track open and max-width:none stops the image
  giving way inside it.
*/
.topnav__logo {
  min-width: max-content;
}

.topnav__logo img {
  width: clamp(112px, 12.5vw, 146px);
  max-width: none;
  height: auto;
}

/* ---------- mobile menu ---------- */

.topnav__menu {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--fg);
  cursor: pointer;
}

/* three rules drawn with one element: the bar itself plus its two
   pseudos, so the X is a transform rather than a second icon */
.topnav__burger {
  position: relative;
}

.topnav__burger,
.topnav__burger::before,
.topnav__burger::after {
  display: block;
  width: 1.35rem;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.3s var(--ease), opacity 0.2s ease;
}

.topnav__burger::before,
.topnav__burger::after {
  content: "";
  position: absolute;
}

.topnav__burger::before {
  transform: translateY(-0.42rem);
}

.topnav__burger::after {
  transform: translateY(0.42rem);
}

.topnav__menu[aria-expanded="true"] .topnav__burger {
  background: transparent;
}

.topnav__menu[aria-expanded="true"] .topnav__burger::before {
  transform: rotate(45deg);
}

.topnav__menu[aria-expanded="true"] .topnav__burger::after {
  transform: rotate(-45deg);
}

/*
  A full sheet rather than a dropdown: the bar spends half its life
  docked at the foot of the screen, and a panel hanging below it would
  open straight off the bottom.
*/
.topnav__panel {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: auto;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 1.5rem;
  padding: var(--gutter);
  background: var(--cream);
  font-size: 1.5rem;
  font-weight: 700;
  /*
    No fill-mode on purpose. With `both` the panel is pinned at the
    keyframe's opacity:0 until the animation actually starts, so any
    situation where it does not start leaves an invisible menu. Without
    it the element's own paint applies outside the active window and the
    animation is pure decoration on top.
  */
  animation: panel-in 0.3s var(--ease);
}

.topnav__panel[hidden] {
  display: none;
}

.topnav__panel a:not(.btn) {
  color: var(--fg);
  text-decoration: none;
}

.topnav__panel a:not(.btn):hover {
  color: var(--rust);
}

@keyframes panel-in {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }
}

/*
  Between the phone layout and a roomy desktop the pill is the tightest
  it ever gets: two links, the mark and a filled CTA inside two thirds
  of the viewport. Widen the pill and tighten the type rather than let
  anything get squeezed.
*/
@media (min-width: 54.0625rem) and (max-width: 78rem) {
  .topnav.is-stuck .topnav__bar {
    width: min(92%, 62rem);
  }

  .topnav__group {
    gap: clamp(0.7rem, 1.8vw, 1.25rem);
    font-size: 0.68rem;
    letter-spacing: 0.1em;
  }

  .topnav__cta {
    padding: 0.6rem 0.95rem;
  }

  .topnav__bar {
    gap: 0.85rem;
  }
}

@media (max-width: 54rem) {
  .topnav.is-stuck .topnav__bar {
    width: calc(100% - 1.5rem);
  }

  /* logo hard left, menu hard right, and nothing in between */
  .topnav__bar {
    grid-template-columns: auto 1fr auto;
    padding-inline: clamp(1rem, 5vw, 1.75rem);
  }

  .topnav__group {
    display: none;
  }

  .topnav__logo {
    order: -1;
    justify-self: start;
    scale: 1;
  }

  .topnav.is-stuck .topnav__logo {
    scale: 1;
  }

  .topnav__menu {
    display: inline-flex;
    grid-column: 3;
    justify-self: end;
  }
}

@media (min-width: 54.0625rem) {
  .topnav__panel {
    display: none;
  }
}

/* ---------- hero ----------

   A spot for a video, and nothing else. The nav sits under it rather
   than on it, so the two together are exactly one screenful and the
   collapse never leaves the pill floating on bare footage.
*/

.hero {
  position: relative;
  height: calc(100svh - var(--nav-h));
  min-height: 24rem;
  overflow: hidden;
  background: #241c17;
}

/*
  The poster is a real <img>, not a CSS background, so the preload
  scanner can start it before the stylesheet has finished parsing. The
  video - when there is one - fades in over the top once it can play.
*/
.hero__media,
.hero__media img,
.hero__media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.hero__media img,
.hero__media video {
  object-fit: cover;
  object-position: center 45%;
}

.hero__video {
  opacity: 0;
  transition: opacity 0.7s ease;
}

.hero__video.is-ready {
  opacity: 1;
}

/*
  The inner pages do carry copy over their hero, so they get the scrim
  and the copy column the home page's bare video spot has no use for.
*/
.hero--page {
  height: auto;
  min-height: clamp(26rem, 68svh, 38rem);
  display: flex;
  align-items: center;
  color: var(--cream);
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
      100deg,
      rgba(16, 12, 10, 0.92) 0%,
      rgba(16, 12, 10, 0.78) 28%,
      rgba(16, 12, 10, 0.28) 62%,
      rgba(16, 12, 10, 0.1) 100%
    ),
    linear-gradient(to top, rgba(16, 12, 10, 0.55), transparent 40%);
}

.hero__in {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding: clamp(3rem, 9vh, 5rem) var(--gutter);
}

.hero__copy {
  max-width: 34rem;
}

.hero__h {
  font-weight: 350;
  font-size: clamp(2.4rem, 6vw, 4.2rem);
  line-height: 1.12;
  letter-spacing: 0.01em;
  margin-bottom: 1.35rem;
}

.hero__p {
  margin: 0 0 1.9rem;
  max-width: 30rem;
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.12rem);
  color: rgba(var(--cream-rgb), 0.88);
}

.hero__acts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
}

/* ---------- services ---------- */

.svc__head {
  display: grid;
  gap: clamp(1.25rem, 4vw, 3rem);
  grid-template-columns: 1fr;
  align-items: start;
  margin-bottom: clamp(2rem, 5vh, 3rem);
}

@media (min-width: 60rem) {
  .svc__head {
    grid-template-columns: 1.15fr 1fr auto;
  }

  /* a head with nothing but the heading in it should not reserve the
     two columns the blurb and the link used to sit in */
  .svc__head:not(:has(.svc__blurb)) {
    grid-template-columns: 1fr;
  }
}

.sec__h {
  font-size: clamp(2rem, 4.6vw, 3.25rem);
}

.svc__blurb {
  margin: 0;
  color: var(--muted);
  max-width: 34ch;
}

.link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--rust);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
  white-space: nowrap;
}

/*
  Three shared rows - shot, title, benefits - and every card spans all
  three via subgrid. That is what makes the rule above the bullets land
  on the same line across the row: the cards are measured together
  rather than each one stacking to its own content height.
*/
.svc__grid {
  display: grid;
  /* column-gap only. `gap` would apply between the subgrid's rows too,
     stacking a full gutter on top of the title's own margin and pushing
     the rule away from the heading it belongs to. */
  column-gap: clamp(1.25rem, 2.5vw, 1.75rem);
  row-gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  grid-template-rows: auto auto auto;
}

.card {
  grid-row: span 3;
  display: grid;
  grid-template-rows: subgrid;
}

.svc__grid--three {
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}

.card {
  text-decoration: none;
  color: inherit;
}

.card__shot {
  position: relative;
  /* square, as the layout asks - reserved up front so nothing shifts
     when the image lands */
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--radius);
  background: #c9c1b1;
}

.card__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--ease);
}

.card:hover .card__shot img {
  transform: scale(1.04);
}

.card__t {
  /* still more air above than below, so the title binds to the rule and
     the bullets under it rather than to the photo above */
  margin: 0.8rem 0 0.45rem;
  font-size: 1.05rem;
  font-weight: 500;
  letter-spacing: 0.01em;
}

.card__p {
  margin: 0 0 0.9rem;
  font-size: 0.88rem;
  color: var(--muted);
}

/*
  Two benefits at the foot of every card, and the rule above them is
  what makes them read as the card's bottom line rather than more prose.
  margin-top:auto pins them to the base, so a longer description on one
  card never leaves its neighbours' bullets floating at different
  heights.
*/
.card__wins {
  margin: 0;
  align-self: start;
  /* the browser's default list indent is what was pushing these off the
     card's left edge while the title sat flush to it */
  padding: 0.7rem 0 0;
  border-top: 1px solid var(--rule);
  list-style: none;
  display: grid;
  gap: 0.4rem;
  font-size: 0.82rem;
}

.card__wins li {
  display: grid;
  grid-template-columns: 0.95rem 1fr;
  gap: 0.5rem;
  align-items: start;
}

/* a tick rather than a bullet - these are claims, not an inventory */
.card__wins li::before {
  content: "";
  width: 0.5rem;
  height: 0.28rem;
  margin-top: 0.42rem;
  border-left: 1.6px solid var(--rust);
  border-bottom: 1.6px solid var(--rust);
  transform: rotate(-45deg);
}

.card__go {
  margin-top: auto;
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  border: 1px solid var(--rule);
  color: var(--fg);
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

.card:hover .card__go {
  background: var(--rust);
  border-color: var(--rust);
  color: var(--cream);
}

/* ---------- process ---------- */

.proc {
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  background: #e6e1d4;
}

.proc__in {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: center;
}

@media (min-width: 62rem) {
  .proc__in {
    grid-template-columns: minmax(16rem, 1fr) 2fr;
  }
}

.proc__steps {
  display: grid;
  gap: 1.5rem 1rem;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

.proc__step {
  position: relative;
  text-align: center;
}

/* the connecting rule lives on the step, so it can never outrun the row
   it belongs to when the grid wraps */
.proc__step::after {
  content: "";
  position: absolute;
  top: 1.3rem;
  left: calc(50% + 1.9rem);
  right: calc(-50% + 1.9rem);
  height: 1px;
  background: var(--rule);
}

.proc__step:last-child::after {
  display: none;
}

.proc__n {
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  margin: 0 auto 0.7rem;
  border-radius: 50%;
  background: #d9cdb7;
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 700;
}

.proc__t {
  display: block;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: 0.35rem;
}

.proc__s {
  margin: 0;
  font-size: 0.82rem;
  color: var(--muted);
}

/* ---------- gallery ---------- */

/*
  One column. The two-column version was built around a paragraph that
  is no longer there, and a two-line headline this size cannot sit in a
  15rem track without spilling out of it.
*/
.work__in {
  display: grid;
  gap: clamp(1.75rem, 4vw, 2.75rem);
}

/* ---------- carousel ---------- */

/*
  The browser owns the scrolling, the snapping and the momentum. The
  buttons only nudge the track by one card, so a trackpad, a touch drag
  and the keyboard all work before any JavaScript has loaded - and if
  the script never runs, it is still a perfectly good scroller.
*/
.carousel {
  position: relative;
}

.carousel__track {
  display: flex;
  gap: clamp(0.6rem, 1.4vw, 1rem);
  margin: 0;
  padding: 0 0 0.5rem;
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  overscroll-behavior-x: contain;
  /* the arrows are the affordance; a scrollbar under the photos is not */
  scrollbar-width: none;
}

.carousel__track::-webkit-scrollbar {
  display: none;
}

.carousel__item {
  flex: 0 0 80%;
  scroll-snap-align: start;
  overflow: hidden;
  border-radius: var(--radius);
  background: #c9c1b1;
  /* every photo is a true square, so the row can never go ragged */
  aspect-ratio: 1;
}

@media (min-width: 40rem) {
  .carousel__item {
    flex-basis: calc((100% - 1rem) / 2);
  }
}

@media (min-width: 62rem) {
  .carousel__item {
    flex-basis: calc((100% - 2rem) / 3);
  }
}

.carousel__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.carousel__btn {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2.9rem;
  height: 2.9rem;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 50%;
  background: rgba(var(--cream-rgb), 0.92);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--fg);
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(var(--ink-rgb), 0.08),
    0 10px 26px rgba(var(--ink-rgb), 0.12);
  transition: background 0.25s ease, color 0.25s ease, opacity 0.25s ease;
}

.carousel__btn:hover {
  background: var(--rust);
  border-color: var(--rust);
  color: var(--cream);
}

/* at either end the button has nothing to do, so it stops asking */
.carousel__btn[disabled] {
  opacity: 0;
  pointer-events: none;
}

.carousel__btn--prev {
  left: clamp(-1.1rem, -1vw, 0.5rem);
}

.carousel__btn--next {
  right: clamp(-1.1rem, -1vw, 0.5rem);
}

.carousel__btn svg {
  width: 1.2rem;
  height: 1.2rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- cta band ---------- */

.band {
  position: relative;
  overflow: hidden;
  background: #2a1d14;
  color: var(--cream);
  isolation: isolate;
}

.band__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 60%;
}

.band::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    95deg,
    rgba(20, 14, 10, 0.88) 0%,
    rgba(20, 14, 10, 0.6) 40%,
    rgba(20, 14, 10, 0.12) 78%,
    rgba(20, 14, 10, 0.05) 100%
  );
}

.band__in {
  display: grid;
  gap: 2rem;
  align-items: center;
  padding-block: clamp(3.5rem, 11vh, 6.5rem);
}

.band__in > div {
  max-width: 34rem;
}

@media (min-width: 56rem) {
  .band__in {
    grid-template-columns: 1fr auto;
  }
}

.band__h {
  font-size: clamp(2rem, 5vw, 3.4rem);
  margin-bottom: 1.5rem;
}

.band__logo {
  width: clamp(150px, 22vw, 260px);
  height: auto;
  justify-self: start;
  opacity: 0.95;
}

/* ---------- the form ---------- */

.build {
  border-top: 1px solid var(--rule);
}

.build__head {
  text-align: center;
  margin-bottom: clamp(2rem, 5vh, 3rem);
}

.build__p {
  margin: 0.75rem 0 0;
  color: var(--muted);
}

.cfg {
  position: relative;
  max-width: 44rem;
  margin-inline: auto;
  padding: clamp(1.5rem, 4vw, 2.5rem);
  background: #f6f2e9;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 1px 2px rgba(var(--ink-rgb), 0.04),
    0 18px 44px rgba(var(--ink-rgb), 0.06);
}

.cfg__rail {
  display: flex;
  gap: 0.4rem;
  margin-bottom: 1.75rem;
}

.cfg__tick {
  height: 3px;
  flex: 1;
  border-radius: 2px;
  background: var(--rule);
  transition: background 0.4s ease;
}

.cfg__tick.is-on {
  background: var(--rust);
}

.cfg__step {
  margin: 0;
  padding: 0;
  border: 0;
  display: none;
}

.cfg__step.is-on {
  display: block;
  animation: step-in 0.45s var(--ease) both;
}

@keyframes step-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

.cfg__q {
  padding: 0;
  margin-bottom: 1.1rem;
  font-family: var(--display);
  font-size: clamp(1.3rem, 2.8vw, 1.75rem);
  font-weight: 350;
  letter-spacing: 0.015em;
  line-height: 1.2;
}

.cfg__q--sm {
  font-size: 1.15rem;
}

.cfg__sub {
  margin: -0.6rem 0 1.1rem;
  font-size: 0.85rem;
  color: var(--muted);
}

.opts {
  display: grid;
  gap: 0.7rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}

.opt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  padding: 1rem;
  background: var(--cream);
  border: 1px solid var(--rule);
  border-radius: 10px;
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.25s ease, background 0.25s ease,
    transform 0.25s var(--ease);
}

.opt:hover,
.opt:focus-visible {
  border-color: var(--rust);
  transform: translateY(-2px);
}

.opt.is-picked {
  border-color: var(--rust);
  background: rgba(var(--rust-rgb), 0.07);
}

.opt__ic {
  width: 2rem;
  height: 2rem;
  margin-bottom: 0.5rem;
  color: var(--rust);
}

.opt__ic--bay {
  width: 3.4rem;
  height: 2.2rem;
}

.opt__t {
  font-weight: 700;
  font-size: 0.95rem;
}

.opt__s {
  font-size: 0.8rem;
  color: var(--muted);
}

.row {
  display: grid;
  gap: 0.9rem;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
}

.field {
  margin: 0 0 0.9rem;
  display: grid;
  gap: 0.35rem;
}

.field label,
.field__label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.field input {
  padding: 0.75rem 0.9rem;
  background: var(--cream);
  border: 1px solid var(--rule);
  border-radius: 8px;
  font: inherit;
  color: inherit;
}

.field input:focus-visible {
  border-color: var(--rust);
  outline: none;
}

.note {
  margin: 0.6rem 0;
  font-size: 0.82rem;
  color: var(--muted);
  min-height: 1.2em;
}

.note--bad {
  color: var(--rust);
}

.quote {
  padding: 1.25rem;
  margin-bottom: 1.5rem;
  background: var(--ink);
  color: var(--cream);
  border-radius: 10px;
}

.label {
  margin: 0;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.66;
}

.quote__n {
  margin: 0.3rem 0 0;
  font-family: var(--display);
  font-size: clamp(1.9rem, 5vw, 2.7rem);
  font-weight: 350;
  letter-spacing: 0.015em;
  line-height: 1.1;
}

.quote__n--text {
  font-family: var(--body);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.3;
}

.quote__note {
  margin: 0.5rem 0 0;
  font-size: 0.82rem;
  opacity: 0.72;
}

.sheet {
  margin: 1rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid rgba(var(--cream-rgb), 0.18);
  display: grid;
  gap: 0.3rem;
  font-size: 0.84rem;
}

/* render() wraps each pair in a div, so the two columns live there */
.sheet > div {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1rem;
}

.sheet dt {
  opacity: 0.6;
}

.sheet dd {
  margin: 0;
  text-align: right;
}

.fine {
  margin: 1rem 0 0;
  font-size: 0.76rem;
  color: var(--muted);
}

.cfg__back {
  margin-top: 1.25rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 0.82rem;
  cursor: pointer;
}

.cfg__back:hover {
  color: var(--rust);
}

.done {
  text-align: center;
  padding: clamp(1rem, 4vh, 2.5rem) 0;
  animation: step-in 0.5s var(--ease) both;
}

.done__mark {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  margin: 0 auto 1.1rem;
  border-radius: 50%;
  background: var(--rust);
  color: var(--cream);
  font-weight: 700;
}

.done__h {
  margin: 0.4rem 0 0.5rem;
  font-size: clamp(1.3rem, 3.4vw, 1.8rem);
}

.done__who {
  margin: 0;
  color: var(--muted);
}

.extras {
  margin-top: 1.75rem;
  text-align: left;
  border-top: 1px solid var(--rule);
  padding-top: 1.25rem;
}

.extras summary {
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--rust);
}

.extras[open] summary {
  margin-bottom: 1rem;
}

.drop {
  position: relative;
  display: grid;
  place-items: center;
  gap: 0.2rem;
  padding: 1.5rem 1rem;
  border: 1px dashed var(--rule);
  border-radius: 10px;
  text-align: center;
  cursor: pointer;
}

.drop.is-over {
  border-color: var(--rust);
  background: rgba(var(--rust-rgb), 0.05);
}

.drop input {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

.drop__t {
  font-weight: 700;
  font-size: 0.9rem;
}

.drop__s {
  font-size: 0.8rem;
  color: var(--muted);
}

.files {
  margin: 0.75rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.4rem;
  font-size: 0.82rem;
}

.files li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  color: var(--muted);
}

.files button {
  border: 0;
  background: none;
  color: var(--rust);
  font: inherit;
  cursor: pointer;
}

/* ---------- faq ---------- */

.faq__list {
  max-width: 48rem;
  margin-inline: auto;
}

.qa {
  border-bottom: 1px solid var(--rule);
}

.qa summary {
  padding: 1.1rem 2.5rem 1.1rem 0;
  position: relative;
  cursor: pointer;
  font-weight: 700;
  list-style: none;
}

.qa summary::-webkit-details-marker {
  display: none;
}

.qa summary::after {
  content: "";
  position: absolute;
  right: 0.5rem;
  top: 1.55rem;
  width: 0.55rem;
  height: 0.55rem;
  border-right: 1.5px solid var(--rust);
  border-bottom: 1.5px solid var(--rust);
  transform: rotate(45deg);
  transition: transform 0.25s ease;
}

.qa[open] summary::after {
  transform: rotate(-135deg);
}

.qa p {
  margin: 0 0 1.2rem;
  color: var(--muted);
  max-width: 62ch;
}

/* ---------- contact page ---------- */

/*
  No hero and no form: the page is three answers and nothing else, so it
  centres itself in whatever height it is given rather than stacking from
  the top of a mostly empty screen.
*/
.reach {
  display: grid;
  align-items: center;
  min-height: calc(100svh - var(--nav-h));
  padding-block: clamp(3rem, 10vh, 6rem);
}

.reach__in {
  text-align: center;
}

.reach__h {
  font-size: clamp(2.2rem, 5.6vw, 3.6rem);
  margin-bottom: 1rem;
}

.reach__p {
  margin: 0 auto clamp(2.5rem, 6vh, 3.5rem);
  max-width: 34ch;
  color: var(--muted);
}

.reach__grid {
  display: grid;
  gap: clamp(0.85rem, 2vw, 1.25rem);
  grid-template-columns: 1fr;
  max-width: 58rem;
  margin-inline: auto;
}

@media (min-width: 48rem) {
  .reach__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* the whole card is the tap target, which on a phone is the point */
.reach__card {
  display: grid;
  justify-items: center;
  gap: 0.3rem;
  padding: clamp(1.75rem, 4vw, 2.5rem) 1.25rem;
  background: #f6f2e9;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.25s ease, transform 0.3s var(--ease),
    box-shadow 0.3s ease;
}

.reach__card:hover,
.reach__card:focus-visible {
  border-color: var(--rust);
  transform: translateY(-3px);
  box-shadow: 0 1px 2px rgba(var(--ink-rgb), 0.05),
    0 14px 34px rgba(var(--ink-rgb), 0.09);
}

.reach__ic {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  margin-bottom: 0.9rem;
  border-radius: 50%;
  background: rgba(var(--rust-rgb), 0.1);
  color: var(--rust);
  transition: background 0.25s ease, color 0.25s ease;
}

.reach__card:hover .reach__ic {
  background: var(--rust);
  color: var(--cream);
}

.reach__ic svg {
  width: 1.5rem;
  height: 1.5rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.reach__k {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}

.reach__v {
  font-size: clamp(1.02rem, 2.2vw, 1.2rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  /* an email address must never push the card wider than its column */
  overflow-wrap: anywhere;
}

.reach__s {
  font-size: 0.84rem;
  color: var(--muted);
}

.reach__foot {
  margin: clamp(2rem, 5vh, 3rem) auto 0;
  max-width: 44ch;
  font-size: 0.9rem;
  color: var(--muted);
}

.reach__foot a {
  color: var(--rust);
  text-underline-offset: 0.2em;
}

/* ---------- footer ---------- */

.foot {
  border-top: 1px solid var(--rule);
  background: #e6e1d4;
}

.foot__in {
  display: grid;
  gap: 2rem;
  padding-block: clamp(2.5rem, 6vh, 3.5rem);
}

@media (min-width: 52rem) {
  .foot__in {
    grid-template-columns: 1.2fr 1fr;
  }
}

.foot__logo {
  width: 130px;
  height: auto;
  margin-bottom: 1rem;
}

.foot__p {
  margin: 0;
  color: var(--muted);
  max-width: 34ch;
}

.foot__label {
  margin: 0 0 0.3rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--rust);
}

.foot__tel {
  display: inline-block;
  font-family: var(--display);
  font-size: clamp(1.7rem, 4vw, 2.3rem);
  font-weight: 350;
  letter-spacing: 0.015em;
  line-height: 1.1;
  text-decoration: none;
  transition: color 0.25s ease;
}

.foot__tel:hover {
  color: var(--rust);
}

.foot__mail {
  display: inline-block;
  margin-top: 0.5rem;
  font-size: 0.9rem;
  color: var(--fg);
  text-underline-offset: 0.2em;
}

.foot__mail:hover {
  color: var(--rust);
}

.foot__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.5rem;
  margin-top: 1.5rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.foot__nav a {
  color: var(--muted);
  text-decoration: none;
}

.foot__nav a:hover {
  color: var(--rust);
}

.foot__areas {
  margin: 1.5rem 0 0;
  font-size: 0.8rem;
  color: var(--muted);
  max-width: 60ch;
}

/* ---------- contact bar ----------

   Kept from the previous site, behaviour unchanged: it rises once the
   hero is behind you and drops away over the form, which asks for the
   same thing in more detail.
*/

.hail {
  position: fixed;
  z-index: 50;
  right: clamp(0.75rem, 2.5vw, 1.75rem);
  bottom: clamp(0.75rem, 2.5vw, 1.75rem);
  opacity: 0;
  visibility: hidden;
  transform: translateY(140%);
  transition: opacity 0.35s ease, transform 0.5s var(--ease),
    visibility 0s linear 0.5s;
}

.hail.is-up {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 0.35s ease, transform 0.5s var(--ease), visibility 0s;
}

.hail__bar {
  position: relative;
  display: flex;
  align-items: stretch;
  background: linear-gradient(
      to bottom,
      rgba(var(--cream-rgb), 0.14),
      rgba(var(--cream-rgb), 0.02) 42%,
      rgba(var(--ink-rgb), 0.06)
    ),
    rgba(var(--ink-rgb), 0.58);
  /* brightness pulls the plate down under the glass, so the cream labels
     hold their contrast over the bright photos as well as over the page */
  -webkit-backdrop-filter: blur(26px) saturate(1.7) brightness(0.62);
  backdrop-filter: blur(26px) saturate(1.7) brightness(0.62);
  border: 1px solid rgba(var(--cream-rgb), 0.2);
  /* the same softened rectangle as the nav bar, so the two floating
     objects on the page read as one family */
  border-radius: 8px;
  overflow: hidden;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22),
    inset 0 -1px 0 rgba(var(--ink-rgb), 0.35),
    0 12px 32px rgba(var(--ink-rgb), 0.2),
    0 30px 60px rgba(var(--ink-rgb), 0.12),
    0 8px 26px rgba(var(--rust-rgb), 0.22);
}

/*
  A halo that beats three times as the bar arrives, then never again. An
  animation that never stops stops being seen.
*/
.hail.is-up .hail__bar::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  border-radius: inherit;
  animation: hail-halo 2.1s ease-out 0.45s 3;
}

@keyframes hail-halo {
  0% {
    box-shadow: 0 0 0 0 rgba(var(--rust-rgb), 0.55);
  }
  45%,
  100% {
    box-shadow: 0 0 0 14px rgba(var(--rust-rgb), 0);
  }
}

.hail__act {
  animation: hail-flash 0.85s ease-out 3;
}

.hail__act {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1rem clamp(1.1rem, 2.6vw, 1.6rem);
  color: var(--cream);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.3s ease;
}

.hail__act::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  background: var(--rust);
  opacity: 0;
  transition: opacity 0.35s ease;
}

.hail__act:hover::before,
.hail__act:focus-visible::before {
  opacity: 1;
}

.hail__icon {
  width: 1.15rem;
  height: 1.15rem;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.hail__sep {
  width: 1px;
  margin-block: 0.6rem;
  background: rgba(var(--cream-rgb), 0.18);
  box-shadow: 1px 0 0 rgba(255, 255, 255, 0.06);
}

/* revealed only when a mailto: click went nowhere */
.hail__fall {
  position: absolute;
  right: 0;
  bottom: calc(100% + 0.6rem);
  width: max-content;
  max-width: min(20rem, calc(100vw - 2rem));
  padding: 0.9rem 1rem;
  background: var(--ink);
  color: var(--cream);
  border-radius: var(--radius);
  box-shadow: 0 10px 28px rgba(var(--ink-rgb), 0.22);
}

.hail__fall[hidden] {
  display: none;
}

.hail__fall-note {
  margin: 0 0 0.5rem;
  font-size: 0.72rem;
  opacity: 0.62;
}

.hail__copy {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 0.86rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}

.hail__copy:hover {
  text-decoration: underline;
  text-underline-offset: 0.22em;
}

/* on a phone it stops being a corner object and becomes the bottom bar */
@media (max-width: 30rem) {
  .hail {
    left: clamp(0.75rem, 2.5vw, 1.75rem);
  }

  .hail__bar {
    justify-content: center;
  }

  .hail__act {
    flex: 1;
    justify-content: center;
    padding-inline: 0.5rem;
    font-size: 0.74rem;
    letter-spacing: 0.1em;
  }
}

/* ---------- reveal ---------- */

[data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.6s ease var(--d, 0ms),
    transform 0.6s var(--ease) var(--d, 0ms);
}

[data-reveal].is-in {
  opacity: 1;
  transform: none;
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  [data-reveal] {
    opacity: 1;
    transform: none;
  }
}
