/* ============================================================================
   Noma Construction LLC

   DESIGN NOTE — "the gap"
   Everything this company builds is parallel elements separated by a consistent
   gap: deck boards, fence pickets, pergola rafters, screen frames. So that is
   the page's structural language. Photography runs edge to edge across the full
   viewport, separated by exactly --gap of warm white, and nothing has a rounded
   corner, because nothing they build is round.

   Palette is anchored on the exact navy from the logo (#22376D). Cedar is its
   warm counterpoint — every photo is amber-toned wood, and warm against cool
   navy is what makes that wood read rich rather than muddy.

   Type is the system stack, set Swiss: heavy weights, tight negative tracking
   on display sizes, wide tracking on the small uppercase labels. The site loads
   nothing from a third-party host, so a custom face would have to be
   self-hosted — that needs Dave's sign-off on adding font files.

   MOTION — one idea, applied consistently: things wipe in from their bottom
   edge, staggered along a row, like boards being laid. Fully disabled under
   prefers-reduced-motion.
   ========================================================================= */

:root {
  --navy:        #22376D;
  --navy-deep:   #141E3A;
  --navy-tint:   #E9EDF6;
  --cedar:       #A4622A;
  --cedar-dark:  #7E4A1F;
  --cedar-light: #C8853F;

  --warm-white:  #FAF8F5;
  --ink:         #16181C;
  --ink-soft:    #4A4F58;
  --hairline:    #DFDAD2;

  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;

  /* The gap. One value, used everywhere two surfaces meet. */
  --gap: 6px;

  /* Type scale — fluid all the way up, so a 27" monitor gets a bigger page,
     not the same page with more empty space beside it. */
  --step--2: clamp(0.72rem, 0.68rem + 0.15vw, 0.86rem);
  --step--1: clamp(0.85rem, 0.8rem + 0.2vw, 1rem);
  --step-0:  clamp(1rem, 0.93rem + 0.32vw, 1.25rem);
  --step-1:  clamp(1.3rem, 1.1rem + 0.9vw, 2rem);
  --step-2:  clamp(1.9rem, 1.35rem + 2.4vw, 4rem);
  --step-3:  clamp(2.6rem, 1.4rem + 5.6vw, 8.5rem);

  /* Page margin scales with the viewport instead of pinning to a container. */
  --edge: clamp(1.25rem, 4vw, 5rem);
  --section-gap: clamp(4rem, 8vw, 10rem);

  --header-h: clamp(64px, 5.5vw, 92px);
  --measure: 68ch;

  --ease: cubic-bezier(.22, .68, .3, 1);
}

/* --- Reset -------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
body, h1, h2, h3, h4, p, figure, blockquote, ul, ol, figcaption { margin: 0; padding: 0; }
img, picture, video { display: block; max-width: 100%; height: auto; }
button, input, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }

html { scroll-behavior: smooth; scroll-padding-top: var(--header-h); }

body {
  background: var(--warm-white);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3 { line-height: 1; font-weight: 800; letter-spacing: -0.035em; text-wrap: balance; }
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
h3 { font-size: var(--step-1); letter-spacing: -0.02em; }
p { text-wrap: pretty; }

a { color: var(--cedar); text-underline-offset: 0.2em; }
a:hover { color: var(--cedar-dark); }

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

/* Full-bleed by default. Prose gets a measure so lines stay readable no matter
   how wide the monitor is — full-width layout, not full-width sentences. */
.bleed { width: 100%; padding-inline: var(--edge); }
.measure { max-width: var(--measure); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.skip-link {
  position: absolute; left: 0; top: -100%;
  z-index: 300; padding: 0.75rem 1.25rem;
  background: var(--navy); color: #fff; text-decoration: none;
}
.skip-link:focus { top: 0; color: #fff; }

/* --- Motion ------------------------------------------------------------- */

/* The one motion idea: a wipe up from the bottom edge, like a board being laid.
   --i staggers items along a row so they land in sequence.

   The hidden state is opacity ONLY — deliberately. clip-path: inset(100%) also
   works visually, but it clips the element's area to zero, and
   IntersectionObserver measures visible area. An element hidden that way
   reports as permanently off-screen and never gets revealed: it hides itself
   so well the observer can never find it. So the clip lives in the keyframes,
   which don't run until after the observer has already fired. */
/* Gated on .js — set by an inline script in the head. Without JavaScript
   nothing would ever add .is-in, so ungated this would leave the entire page
   permanently invisible. */
.js .reveal { opacity: 0; }
.reveal.is-in {
  animation: layIn 1s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 90ms);
}
@keyframes layIn {
  from { clip-path: inset(100% 0 0 0); transform: translateY(24px); opacity: 0; }
  to   { clip-path: inset(0 0 0 0);    transform: none;             opacity: 1; }
}

@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;
  }
  .reveal, .js .reveal, .reveal.is-in { clip-path: none; transform: none; opacity: 1; animation: none !important; }
  .hero__media img { animation: none !important; }
  .hero h1 .line > span { transform: none; animation: none !important; }
  .hero__rule { transform: scaleX(1); animation: none !important; }
  .hero__lead, .hero__actions, .hero__logo { opacity: 1; animation: none !important; }
}

/* --- Buttons ------------------------------------------------------------ */

.btn {
  position: relative; display: inline-block; overflow: hidden;
  padding: 1em 2.2em;
  font-weight: 700; font-size: var(--step--1);
  letter-spacing: 0.08em; text-transform: uppercase; text-decoration: none;
  border-radius: 0;
  transition: color .35s var(--ease);
}
/* The fill wipes up from the bottom — same gesture as the page reveals. */
.btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  transform: scaleY(0); transform-origin: bottom;
  transition: transform .4s var(--ease);
}
.btn:hover::before { transform: scaleY(1); }

.btn--accent { background: var(--cedar); color: #fff; isolation: isolate; }
.btn--accent::before { background: var(--navy-deep); }
.btn--accent:hover { color: #fff; }

.btn--ghost { border: 2px solid rgba(255,255,255,.7); color: #fff; isolation: isolate; }
.btn--ghost::before { background: #fff; }
.btn--ghost:hover { color: var(--navy-deep); }

.btn--block { width: 100%; text-align: center; }

/* --- Header ------------------------------------------------------------- */

.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 200;
  height: var(--header-h);
  background: transparent;
  transition: background-color .4s var(--ease), height .4s var(--ease);
}
.site-header.is-stuck { background: var(--navy-deep); }

/* Scroll progress, drawn as a chalk line across the very top. */
.site-header::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  height: 2px; width: 100%;
  background: var(--cedar);
  transform: scaleX(var(--progress, 0)); transform-origin: left;
}

.site-header__inner {
  height: 100%; padding-inline: var(--edge);
  display: flex; align-items: center; gap: clamp(1rem, 3vw, 3rem);
}

.site-header__brand { flex: 0 0 auto; display: flex; align-items: center; }
/* Sized by HEIGHT — the logo is taller than it is wide once "CONSTRUCTION, LLC"
   is included, so a width would overflow the bar and clip that line off. */
.site-header__brand img { height: clamp(38px, 3.4vw, 56px); width: auto; }

/* At the top of the page the brand mark belongs in the hero, not the bar — so
   the header logo waits, then drops in once you scroll past the hero. Gated on
   .js because without JavaScript nothing ever adds .is-stuck, and the logo
   would never appear at all. */
.js .site-header__brand {
  opacity: 0;
  transform: translateY(-0.6rem);
  pointer-events: none;
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
.js .site-header.is-stuck .site-header__brand {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.site-nav { display: flex; gap: clamp(1rem, 2.2vw, 2.5rem); margin-left: auto; }
.site-nav a {
  position: relative; color: #fff; text-decoration: none;
  font-weight: 600; font-size: var(--step--2);
  letter-spacing: 0.16em; text-transform: uppercase;
  padding: 0.6rem 0;
}
/* Underline draws in from the left, at the width of the gap motif. */
.site-nav a::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 100%; height: 2px; background: var(--cedar-light);
  transform: scaleX(0); transform-origin: left;
  transition: transform .35s var(--ease);
}
.site-nav a:hover::after, .site-nav a:focus-visible::after { transform: scaleX(1); }

.site-header__actions { display: flex; align-items: center; gap: clamp(1rem, 2vw, 2rem); }

.phone-link {
  color: #fff; text-decoration: none; font-weight: 700;
  font-size: var(--step--1); letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.phone-link:hover { color: var(--cedar-light); }

.nav-toggle { display: none; width: 44px; height: 44px; padding: 10px; margin-left: auto; }
.nav-toggle__bar { display: block; height: 2px; background: #fff; margin: 5px 0; transition: transform .3s var(--ease), opacity .2s; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(4) { transform: translateY(-7px) rotate(-45deg); }

.site-nav-mobile { display: none; }

@media (max-width: 1000px) {
  .site-nav, .site-header__actions { display: none; }
  .nav-toggle { display: block; }
  .site-nav-mobile { display: block; background: var(--navy-deep); padding: 0.5rem var(--edge) 1.5rem; }
  .site-nav-mobile[hidden] { display: none; }
  .site-nav-mobile a {
    display: block; padding: 0.9rem 0; color: #fff;
    text-decoration: none; font-weight: 700;
    letter-spacing: 0.1em; text-transform: uppercase; font-size: var(--step--1);
    border-bottom: 1px solid rgba(255,255,255,.14);
  }
}

/* --- Hero --------------------------------------------------------------- */

.hero {
  position: relative; isolation: isolate; overflow: hidden;
  min-height: 100svh;
  display: grid; align-items: end;
}
.hero__media, .hero__media img {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%; object-fit: cover;
}
/* Very slow drift. Long enough that you notice depth, not movement. */
.hero__media img { animation: drift 28s ease-in-out infinite alternate; }
@keyframes drift {
  from { transform: scale(1.06) translate3d(0, 0, 0); }
  to   { transform: scale(1.16) translate3d(-1.5%, -1%, 0); }
}

.hero__veil {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom,
    rgba(20,30,58,.62) 0%, rgba(20,30,58,.12) 34%,
    rgba(20,30,58,.55) 72%, rgba(20,30,58,.88) 100%);
}

.hero__body { padding: 0 var(--edge) clamp(4rem, 9vh, 8rem); color: #fff; }

/* The brand mark, at the size it deserves. Sized by width here — unlike the
   header, there is nothing beside it to overflow. */
.hero__logo {
  width: clamp(120px, 11vw, 230px);
  height: auto;
  margin-bottom: clamp(1.25rem, 2.5vw, 2.25rem);
  opacity: 0;
  animation: fade .9s ease .1s forwards;
  /* The hero veil is at its thinnest in the middle of the image, which is
     where the logo sits — without this the fine "CONSTRUCTION, LLC" line
     disappears against bright sky. Same reason the h1 carries a shadow. */
  filter: drop-shadow(0 2px 18px rgba(20, 30, 58, .55));
}
.hero h1 { color: #fff; text-transform: uppercase; letter-spacing: -0.04em; }
.hero h1 .line { display: block; overflow: hidden; }
.hero h1 .line > span {
  display: block;
  transform: translateY(105%);
  animation: rise 1.1s var(--ease) forwards;
  animation-delay: calc(.2s + var(--i, 0) * .12s);
}
@keyframes rise { to { transform: translateY(0); } }

/* A cedar rule between the headline and the lead — the gap motif at
   architectural scale. */
.hero__rule {
  width: clamp(80px, 12vw, 220px); height: 3px; background: var(--cedar);
  margin: clamp(1.5rem, 3vw, 2.5rem) 0;
  transform: scaleX(0); transform-origin: left;
  animation: draw 1s var(--ease) .7s forwards;
}
@keyframes draw { to { transform: scaleX(1); } }

.hero__lead {
  max-width: 52ch; font-size: var(--step-1); line-height: 1.35;
  color: rgba(255,255,255,.94); font-weight: 400;
  opacity: 0; animation: fade .9s ease .85s forwards;
}
.hero__actions {
  display: flex; flex-wrap: wrap; gap: var(--gap);
  margin-top: clamp(2rem, 4vw, 3rem);
  opacity: 0; animation: fade .9s ease 1s forwards;
}
@keyframes fade { to { opacity: 1; } }

.hero__scroll {
  position: absolute; left: 50%; bottom: 1.75rem; z-index: 2;
  width: 26px; height: 26px; margin-left: -13px;
  border-right: 2px solid rgba(255,255,255,.8);
  border-bottom: 2px solid rgba(255,255,255,.8);
  transform: rotate(45deg);
  animation: nudge 2.6s var(--ease) infinite;
}
@keyframes nudge {
  0%, 100% { transform: rotate(45deg) translate(0,0); opacity: .55; }
  50%      { transform: rotate(45deg) translate(6px,6px); opacity: 1; }
}

/* --- Sections ----------------------------------------------------------- */

.section { padding-block: var(--section-gap); }
.section--flush { padding-block: 0; }
.section--tint { background: var(--navy-tint); }
.section--dark { background: var(--navy-deep); color: rgba(255,255,255,.85); }
.section--dark h2, .section--dark h3 { color: #fff; }

.section__head { padding-inline: var(--edge); margin-bottom: clamp(2.5rem, 5vw, 5rem); }
.section__head h2 { margin-bottom: 1.25rem; text-transform: uppercase; }
.section__lead { font-size: var(--step-1); line-height: 1.4; color: var(--ink-soft); max-width: var(--measure); }
.section--dark .section__lead { color: rgba(255,255,255,.72); }

.eyebrow {
  display: flex; align-items: center; gap: 0.75rem;
  font-size: var(--step--2); font-weight: 700; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--cedar); margin-bottom: 1.25rem;
}
.eyebrow::before { content: ""; width: clamp(24px, 3vw, 56px); height: 2px; background: currentColor; }
.eyebrow--light { color: var(--cedar-light); }

/* --- Service tiles ------------------------------------------------------ */
/* Edge to edge, separated by the gap. No container, no radius. */

.tiles {
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}
.tile { position: relative; overflow: hidden; background: var(--navy-deep); }
.tile__media { aspect-ratio: 3 / 4; }
.tile__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s var(--ease); }
.tile:hover .tile__media img { transform: scale(1.06); }

.tile__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(20,30,58,.92) 0%, rgba(20,30,58,.35) 45%, rgba(20,30,58,0) 75%);
}
.tile__body {
  position: absolute; inset: auto 0 0 0;
  padding: clamp(1.25rem, 2vw, 2rem);
  color: #fff;
}
.tile__body h3 { text-transform: uppercase; letter-spacing: 0.02em; margin-bottom: 0.6rem; }
.tile__body p { font-size: var(--step--1); line-height: 1.5; color: rgba(255,255,255,.82); }
/* Cedar rule draws across the full tile width on hover. */
.tile__rule {
  display: block; height: 3px; width: 100%; background: var(--cedar);
  margin-bottom: 1rem;
  transform: scaleX(0); transform-origin: left;
  transition: transform .5s var(--ease);
}
.tile:hover .tile__rule, .tile:focus-within .tile__rule { transform: scaleX(1); }

/* --- Split (built / repaired) ------------------------------------------- */

.split {
  display: grid; gap: clamp(2rem, 5vw, 5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  padding-inline: var(--edge);
}
.split__col h3 { text-transform: uppercase; margin-bottom: 1rem; }
.split__col p { color: var(--ink-soft); max-width: var(--measure); }
.section--dark .split__col p { color: rgba(255,255,255,.78); }

.duo {
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
  margin-top: clamp(2.5rem, 5vw, 5rem);
}
/* --- Carousel ----------------------------------------------------------- */
/* Native horizontal scroll with snap points. The arrows and dots drive
   scrollTo, so with no JavaScript it is still a swipeable, scrollable strip
   showing every photo — not a stack with two hidden. */

.carousel { position: relative; overflow: hidden; }

.carousel__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;            /* Firefox */
  -ms-overflow-style: none;
}
.carousel__track::-webkit-scrollbar { display: none; }

.carousel__slide {
  position: relative;
  flex: 0 0 100%;
  scroll-snap-align: start;
}
.carousel__slide img {
  width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
}
.carousel__slide figcaption {
  position: absolute; inset: auto 0 0 0;
  padding: clamp(1rem, 2vw, 1.75rem) clamp(3.5rem, 6vw, 5rem)
           clamp(2.75rem, 4vw, 3.5rem) clamp(1rem, 2vw, 1.75rem);
  background: linear-gradient(to top, rgba(20,30,58,.92), rgba(20,30,58,0));
  color: #fff; font-size: var(--step--1); line-height: 1.4;
}

.carousel__arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 48px; height: 48px;
  font-size: 2.2rem; line-height: 1; color: #fff;
  background: rgba(20,30,58,.55);
  transition: background-color .3s var(--ease), transform .3s var(--ease), opacity .3s;
}
.carousel__arrow:hover { background: var(--cedar); }
.carousel__arrow--prev { left: 0; }
.carousel__arrow--next { right: 0; }
.carousel__arrow--prev:hover { transform: translateY(-50%) translateX(-2px); }
.carousel__arrow--next:hover { transform: translateY(-50%) translateX(2px); }
.carousel__arrow[disabled] { opacity: .25; pointer-events: none; }

.carousel__dots {
  position: absolute; left: 0; right: 0; bottom: clamp(0.9rem, 1.5vw, 1.25rem);
  z-index: 3; display: flex; justify-content: center; gap: var(--gap);
}
.carousel__dot {
  width: 30px; height: 4px; background: rgba(255,255,255,.45);
  transition: background-color .3s var(--ease);
}
.carousel__dot:hover { background: rgba(255,255,255,.8); }
.carousel__dot.is-active { background: var(--cedar); }

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

/* --- Filters ------------------------------------------------------------ */

.filters {
  display: flex; flex-wrap: wrap; gap: var(--gap);
  padding-inline: var(--edge); margin-bottom: clamp(2rem, 4vw, 3.5rem);
}
.filter {
  position: relative; overflow: hidden; isolation: isolate;
  padding: 0.7em 1.6em; border: 1px solid var(--hairline); background: transparent;
  font-size: var(--step--2); font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-soft);
  transition: color .3s var(--ease), border-color .3s var(--ease);
}
.filter::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--navy); transform: scaleY(0); transform-origin: bottom;
  transition: transform .35s var(--ease);
}
.filter:hover { color: #fff; border-color: var(--navy); }
.filter:hover::before { transform: scaleY(1); }
.filter.is-active { color: #fff; border-color: var(--navy); }
.filter.is-active::before { transform: scaleY(1); }

/* --- Gallery ------------------------------------------------------------ */
/* The signature: full-viewport mosaic, hairline gaps, square corners. */

.gallery {
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr));
}
.gallery__item {
  position: relative; overflow: hidden; padding: 0; display: block;
  background: var(--navy-tint); aspect-ratio: 4 / 3;
}
.gallery__item img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.1s var(--ease); }
.gallery__item:hover img, .gallery__item:focus-visible img { transform: scale(1.07); }

.gallery__item::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(20,30,58,.78) 0%, rgba(20,30,58,.1) 55%, rgba(20,30,58,0) 100%);
  opacity: 0; transition: opacity .4s var(--ease);
}
.gallery__item:hover::after, .gallery__item:focus-visible::after { opacity: 1; }

.gallery__meta {
  position: absolute; inset: auto 0 0 0; z-index: 2;
  padding: clamp(1rem, 1.6vw, 1.6rem);
  transform: translateY(0.75rem); opacity: 0;
  transition: transform .4s var(--ease), opacity .4s var(--ease);
}
.gallery__item:hover .gallery__meta, .gallery__item:focus-visible .gallery__meta {
  transform: translateY(0); opacity: 1;
}
.gallery__rule {
  display: block; height: 3px; background: var(--cedar); margin-bottom: 0.75rem;
  transform: scaleX(0); transform-origin: left;
  transition: transform .55s var(--ease) .05s;
}
.gallery__item:hover .gallery__rule, .gallery__item:focus-visible .gallery__rule { transform: scaleX(1); }
.gallery__tag {
  display: block; color: #fff;
  font-size: var(--step--2); font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
}

.gallery__item[hidden] { display: none; }
.gallery__empty { text-align: center; color: var(--ink-soft); padding: 3rem var(--edge); }

/* --- Custom work -------------------------------------------------------- */

/* No gap between the two halves — deliberately, unlike the photo grids.
   A gap shows whatever is behind it, and behind this row it is the dark
   section background while behind the contact row below it is the warm white
   page. Same 6px in both, but the eye reads the seam on opposite sides of it,
   so the two rows look misaligned by 6px even though they measure identical.
   Colour fields meet edge to edge; only photographs get the gap. */
.custom {
  display: grid; align-items: stretch; gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
}
.custom__text { padding: clamp(3rem, 6vw, 7rem) var(--edge); align-self: center; }
.custom__text h2 { text-transform: uppercase; margin-bottom: 1.25rem; }
.custom__text p { max-width: var(--measure); margin-bottom: 2rem; }
.custom__media { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap); }
.custom__media picture { overflow: hidden; }
.custom__media img { width: 100%; height: 100%; min-height: 320px; object-fit: cover; transition: transform 1.2s var(--ease); }
.custom__media picture:hover img { transform: scale(1.05); }

/* --- Contact ------------------------------------------------------------ */

/* gap: 0 for the same reason as .custom above — these two rows sit directly on
   top of each other, so their seams have to land on the same pixel. */
.contact {
  display: grid; gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
}
.contact__intro { background: var(--navy); color: rgba(255,255,255,.85); padding: clamp(2.5rem, 5vw, 6rem) var(--edge); }
.contact__intro h2 { color: #fff; text-transform: uppercase; margin-bottom: 1.25rem; }
.contact__intro p { max-width: var(--measure); }
.contact__phone { margin-top: clamp(2rem, 3vw, 3rem); }
.contact__phone a {
  font-size: var(--step-2); font-weight: 800; color: #fff; text-decoration: none;
  font-variant-numeric: tabular-nums; letter-spacing: -0.03em;
  transition: color .3s var(--ease);
}
.contact__phone a:hover { color: var(--cedar-light); }
.contact__crew { margin-top: clamp(2rem, 3vw, 3rem); overflow: hidden; }
/* Flipped back — this is a front-camera selfie, so the NOMA logo on the shirt
   and the lettering behind them read backwards until it's reversed. */
.contact__crew img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; transform: scaleX(-1); }

.form { padding: clamp(2.5rem, 5vw, 6rem) var(--edge); }
.form__grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.field--wide { grid-column: 1 / -1; }
.field label {
  display: block; font-weight: 700; font-size: var(--step--2);
  letter-spacing: 0.14em; text-transform: uppercase; margin-bottom: 0.6rem;
}
.field__hint { font-weight: 500; letter-spacing: 0.06em; color: var(--ink-soft); }
.field input, .field textarea {
  width: 100%; padding: 0.9em 0; border: 0; border-bottom: 2px solid var(--hairline);
  background: transparent; border-radius: 0;
  transition: border-color .3s var(--ease);
}
.field input:focus, .field textarea:focus { outline: none; border-bottom-color: var(--cedar); }
.field input:focus-visible, .field textarea:focus-visible { outline: 3px solid var(--cedar); outline-offset: 4px; }
.field textarea { resize: vertical; min-height: 7rem; }

.hp { position: absolute !important; left: -9999px !important; opacity: 0 !important; }

.form__submit { margin-top: 2.5rem; }
.form__status { margin-top: 1.25rem; font-size: var(--step--1); font-weight: 700; }
.form__status.is-ok { color: #1B6B3A; }
.form__status.is-error { color: #A32020; }

/* --- Lightbox ----------------------------------------------------------- */

.lightbox {
  position: fixed; inset: 0; z-index: 400;
  background: rgba(10,14,26,.96);
  display: grid; place-items: center; padding: clamp(1rem, 4vw, 4rem);
  animation: fade .25s ease forwards;
}
.lightbox[hidden] { display: none; }
.lightbox__figure { max-width: min(100%, 1800px); text-align: center; }
.lightbox__figure img { max-height: 80vh; width: auto; margin-inline: auto; }
.lightbox__figure figcaption {
  margin-top: 1.25rem; color: rgba(255,255,255,.75);
  font-size: var(--step--1); max-width: 70ch; margin-inline: auto;
}
.lightbox__close { position: absolute; top: 1rem; right: 1.5rem; width: 52px; height: 52px; font-size: 2.6rem; line-height: 1; color: #fff; }
.lightbox__nav { position: absolute; top: 50%; transform: translateY(-50%); width: 60px; height: 60px; font-size: 3.2rem; line-height: 1; color: #fff; transition: color .25s, transform .25s var(--ease); }
.lightbox__nav--prev { left: 0.5rem; }
.lightbox__nav--next { right: 0.5rem; }
.lightbox__nav--prev:hover { transform: translateY(-50%) translateX(-4px); color: var(--cedar-light); }
.lightbox__nav--next:hover { transform: translateY(-50%) translateX(4px); color: var(--cedar-light); }
.lightbox__close:hover { color: var(--cedar-light); }

/* ==========================================================================
   ABOUT PAGE
   ========================================================================== */

/* A shorter hero than the home page — this page is here to be read, so the
   opening should not take up a whole screen before the words start. */
/* Tall enough that the logo, eyebrow and headline clear the header bar with
   air to spare — at the old height they filled the hero and the logo ended up
   almost touching the top edge. */
.hero--short { min-height: clamp(560px, 76svh, 820px); }
.hero--short .hero__body { padding-bottom: clamp(2.5rem, 6vh, 5rem); }

/* --- The letter --------------------------------------------------------- */

.letter { padding-inline: var(--edge); }
.letter__grid {
  display: grid; gap: clamp(2.5rem, 5vw, 5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));
  align-items: start;
}
/* Set slightly larger and looser than body copy. It is a person talking, and
   it should feel like a letter rather than a block of website text. */
.letter__body p {
  max-width: var(--measure);
  font-size: var(--step-1);
  line-height: 1.55;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.letter__body p + p { margin-top: 1.5em; }

/* The opening line carries a cedar rule, the same mark used in the hero. */
.letter__open { position: relative; padding-top: 2rem; }
.letter__open::before {
  content: ""; position: absolute; top: 0; left: 0;
  width: clamp(60px, 8vw, 140px); height: 3px; background: var(--cedar);
}

/* Martin's headshot. Sticky, so his face stays with the reader while the
   letter scrolls past — the whole reason the photo is there is that people
   want to see who they are letting into their garden. */
.portrait { overflow: hidden; position: sticky; top: calc(var(--header-h) + 2rem); }
.portrait img {
  width: 100%;
  /* Matches the source, so nothing is cropped off the top of his head. */
  aspect-ratio: 4 / 5;
  object-fit: cover; object-position: 50% 20%;
}

@media (max-width: 800px) {
  .portrait { position: static; }
}

/* --- The name — the signature moment ------------------------------------ */

.namesake {
  background: var(--navy-deep);
  color: rgba(255,255,255,.85);
  padding-inline: var(--edge);
}
.namesake__head { margin-bottom: clamp(3rem, 6vw, 5rem); }
.namesake__head h2 { color: #fff; text-transform: uppercase; }

/* Four letters, four names. The whole point of the page, so it is allowed to
   be the biggest thing on it. */
/* Four across on any screen wide enough, two-by-two on a phone. Never one per
   row: stacked in a single column they stop spelling anything, and the letters
   spelling NOMA is the entire point of the section. */
.initials {
  list-style: none; margin: 0 0 clamp(3rem, 6vw, 5rem); padding: 0;
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(2, 1fr);
  border-top: 1px solid rgba(255,255,255,.16);
}
@media (min-width: 700px) {
  .initials { grid-template-columns: repeat(4, 1fr); }
}
.initials__item {
  padding: clamp(1.5rem, 3vw, 2.5rem) 0;
  border-bottom: 1px solid rgba(255,255,255,.16);
  text-align: center;
}
/* OPTICAL CENTRING — letter-spacing is why these looked off.
   A centred line box includes the space AFTER the last character, so tracking
   drags the visible ink sideways by half its value. Here the letters had
   negative tracking (ink pushed right) and the names positive (ink pushed
   left), and the two errors compounded into a ~7px stagger.

   Tracking does nothing on a single glyph except create that phantom space,
   so the letter simply doesn't have it. */
.initials__letter {
  display: block;
  font-size: clamp(4.5rem, 11vw, 11rem);
  font-weight: 800; line-height: 0.85; letter-spacing: normal;
  color: var(--cedar-light);
}
/* The name keeps its wide tracking, so it needs the trailing space cancelled:
   a text-indent equal to the letter-spacing puts the ink back on centre. */
.initials__name {
  display: block; margin-top: clamp(0.75rem, 1.5vw, 1.25rem);
  font-size: var(--step--1); font-weight: 700;
  letter-spacing: 0.18em; text-indent: 0.18em;
  text-transform: uppercase; color: #fff;
  /* "ALEXANDER" is the long one — it must not wrap or overflow its cell. */
  overflow-wrap: anywhere;
}
@media (min-width: 700px) {
  .initials__name {
    font-size: var(--step-0);
    letter-spacing: 0.24em; text-indent: 0.24em;
  }
}

.namesake__note p {
  max-width: var(--measure);
  font-size: var(--step-1); line-height: 1.55;
  color: rgba(255,255,255,.8);
}

/* --- Values ------------------------------------------------------------- */

.values { padding-inline: var(--edge); background: var(--navy-tint); }
.values__inner { max-width: 68rem; }
.values__quote {
  margin: 0; border: 0; padding: 0;
  border-left: 3px solid var(--cedar);
  padding-left: clamp(1.25rem, 3vw, 2.5rem);
}
.values__quote p {
  max-width: var(--measure);
  font-size: var(--step-1); line-height: 1.5; color: var(--ink);
}

.signature { margin-top: clamp(2.5rem, 5vw, 4rem); }
.signature__name {
  display: block; font-size: var(--step-1); font-weight: 800;
  letter-spacing: -0.02em; color: var(--navy);
}
.signature__role {
  display: block; margin-top: 0.35rem;
  font-size: var(--step--2); font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-soft);
}

/* --- Closing call to action --------------------------------------------- */

.cta { background: var(--navy); color: rgba(255,255,255,.85); }
.cta__inner { padding: clamp(3.5rem, 8vw, 7rem) var(--edge); }
.cta__inner h2 { color: #fff; text-transform: uppercase; margin-bottom: 1.25rem; }
.cta__inner p { max-width: var(--measure); }
.cta__actions { display: flex; flex-wrap: wrap; gap: var(--gap); margin-top: clamp(2rem, 4vw, 3rem); }

/* --- Footer ------------------------------------------------------------- */

.site-footer { background: var(--navy-deep); color: rgba(255,255,255,.72); padding: clamp(3rem, 6vw, 6rem) var(--edge); }
.site-footer__inner {
  display: grid; gap: clamp(2rem, 4vw, 4rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  align-items: start;
}
.site-footer__logo { width: clamp(110px, 9vw, 170px); height: auto; }
.site-footer__name { color: #fff; font-weight: 800; font-size: var(--step-1); text-transform: uppercase; letter-spacing: -0.02em; margin-bottom: 0.75rem; }
.site-footer__services { font-size: var(--step--1); letter-spacing: 0.1em; text-transform: uppercase; }
.site-footer a { color: #fff; text-decoration: none; }
.site-footer a:hover { color: var(--cedar-light); }
.site-footer__legal { font-size: var(--step--2); color: rgba(255,255,255,.5); letter-spacing: 0.06em; }
