/* ---------------------------------------------------------------
   R2 Landscape — deviations from the source design.
   Everything we change together lives here, so assets/styles.css
   stays a clean copy of the original and diffs stay readable.
   --------------------------------------------------------------- */

/* Hero — the source stacks eyebrow / headline / intro into two
   half-width columns, which forces the 150px headline to wrap to
   four ragged lines on wide screens. Give it the full width so it
   breaks where the markup intends: two lines, on its own <br>. */
/* Source pins the hero to a full 100vh with a 400px minimum on the
   photo row. Trimmed so the next section starts pulling into view. */
.hero {
  min-height: 82vh;
  grid-template-rows: auto minmax(300px, 0.72fr);
}

.hero-copy {
  grid-template-columns: 1fr;
  align-items: start;
  padding: 3vw 0 2vw;
}

.hero-copy .eyebrow { margin-bottom: 28px; }

/* Eyebrow, headline and intro all share the same left edge. */
.hero-intro { justify-self: start; text-align: left; margin-top: 2.2vw; }

/* Closing CTA — source runs 72vh tall with a 165px headline, which
   overshoots its own <br> and wraps to three lines. Tightened so it
   reads as two lines and stops eating a full screen. */
.contact {
  min-height: 48vh;
  padding: 5vw 3.3vw;
}

.contact h2 {
  font-size: clamp(52px, 7.2vw, 108px);
  margin: 30px 0 40px;
}

/* Project photos — shorter than the source's 16/8.5 so the copy
   carries more of the section and the grid scans faster. */
.project-image { aspect-ratio: 16 / 6.5; }

/* Matches the source's own mobile breakpoint. */
@media (max-width: 800px) {
  .project-image { aspect-ratio: 4 / 3.4; }
}

/* ---------------------------------------------------------------
   Portfolio — projects.html index and the per-project detail pages.
   The .project / .project-image / .project-details classes are the
   source design's; these only add what the portfolio needs on top:
   category filtering, a clickable card, and prev/next navigation.
   --------------------------------------------------------------- */

.project-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 42px;
}

.filter-pill {
  border: 1px solid currentColor;
  background: none;
  color: inherit;
  cursor: pointer;
  border-radius: 999px;
  padding: 10px 22px;
  font: 500 12px var(--font-barlow-condensed, inherit);
  letter-spacing: .1em;
  text-transform: uppercase;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}

.filter-pill { opacity: .55; }
.filter-pill:hover { opacity: 1; }

.filter-pill.is-active {
  opacity: 1;
  background: var(--ink, #0a0a0a);
  border-color: var(--ink, #0a0a0a);
  color: var(--paper, #efede7);
}

/* The whole card is the link — image and caption together. */
.project-link { display: block; text-decoration: none; color: inherit; }

.project-link .project-image {
  transition: transform .5s ease, filter .5s ease;
  will-change: transform;
}

.project-link:hover .project-image { transform: scale(1.02); filter: brightness(1.04); }
.project-link:focus-visible { outline: 2px solid currentColor; outline-offset: 6px; }

.project[hidden] { display: none; }
.project-empty[hidden] { display: none; }
.project-empty { color: inherit; opacity: .6; }

/* Prev / all / next at the foot of a project page. */
.project-pager {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 18px;
  border-top: 1px solid rgba(10, 10, 10, .16);
  padding-top: 26px;
}

.project-pager a {
  font: 500 13px var(--font-barlow-condensed, inherit);
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
}

.project-pager a:hover { text-decoration: underline; text-underline-offset: 4px; }

@media (max-width: 700px) {
  .project-pager { flex-direction: column; align-items: flex-start; }
}

/* Project gallery — real photos pulled from the r2_project posts. */
.project-gallery-section { padding: 6vw 3.3vw; }

.project-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
  margin-top: 26px;
}

.gallery-tile {
  aspect-ratio: 4 / 3;
  background-size: cover;
  background-position: center;
}

.project-gallery .gallery-tile:first-child {
  grid-column: 1 / -1;
  aspect-ratio: 16 / 7;
}

@media (max-width: 700px) {
  .project-gallery { grid-template-columns: 1fr; }
  .project-gallery .gallery-tile:first-child { aspect-ratio: 4 / 3; }
}

/* ---------------------------------------------------------------
   Journal — blog.html index and the per-post article pages.
   --------------------------------------------------------------- */

.post-list-section { padding-top: 2vw; }

.post-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
  gap: 46px 34px;
}

.post-card .project-image { aspect-ratio: 16 / 10; }
.post-card-body { padding-top: 20px; }

.post-meta {
  font: 500 11px var(--font-barlow-condensed, inherit);
  letter-spacing: .14em;
  text-transform: uppercase;
  opacity: .6;
  margin: 0 0 12px;
}

.post-card-body h3 {
  font: 500 clamp(22px, 2.1vw, 31px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  line-height: 1.04;
  margin: 0 0 14px;
}

.post-card-excerpt { max-width: 46ch; margin: 0 0 16px; opacity: .78; }

.post-more {
  font: 500 12px var(--font-barlow-condensed, inherit);
  letter-spacing: .12em;
  text-transform: uppercase;
}

.post-card .project-link:hover .post-more { text-decoration: underline; text-underline-offset: 5px; }

/* ---- the article itself ---- */

.post-body {
  max-width: 44rem;
  margin: 0 auto;
  padding: 7vw 3.3vw 2vw;
  font-size: clamp(17px, 1.35vw, 20px);
  line-height: 1.62;
}

.post-body > h2 {
  font: 500 clamp(28px, 3.1vw, 44px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  line-height: 1.04;
  margin: 52px 0 20px;
}

.post-body > h2:first-child { margin-top: 0; }

.post-body > h3 {
  font: 500 clamp(19px, 1.9vw, 25px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  margin: 34px 0 10px;
}

.post-body p { margin: 0 0 20px; }
.post-body ul { margin: 0 0 24px; padding-left: 1.1em; }
.post-body li { margin-bottom: 9px; }
.post-body a { text-decoration: underline; text-underline-offset: 3px; }
.post-lead-soft { font-weight: 400; text-transform: none; }

.post-byline {
  border-top: 1px solid rgba(10, 10, 10, .16);
  margin-top: 44px;
  padding-top: 20px;
  font: 500 12px var(--font-barlow-condensed, inherit);
  letter-spacing: .12em;
  text-transform: uppercase;
}

.post-byline p { margin: 0 0 8px; }
.post-tags { opacity: .55; letter-spacing: .08em; }

@media (max-width: 700px) {
  .post-list { grid-template-columns: 1fr; }
}

/* The source's .projects section carries no padding of its own — on the
   homepage its children supply it. Our generated portfolio and journal
   sections need it explicitly, or the cards bleed to the viewport edge. */
.architecture-page .projects { padding: 0 3.3vw; }
.architecture-page .post-list-section { padding: 3vw clamp(24px, 5vw, 90px) 6vw; }
.architecture-page .project-gallery-section { padding: 6vw 3.3vw; }

/* Mobile menu — mirrors the desktop nav's grouping (Services and About
   are dropdowns there; here they are labelled groups with indented
   children, since nested dropdowns inside <details> are awkward on a
   phone). */
.mobile-menu-group {
  font: 500 10px var(--font-barlow-condensed, inherit);
  letter-spacing: .18em;
  text-transform: uppercase;
  opacity: .45;
  margin: 18px 0 6px;
}

.mobile-menu-panel .mobile-menu-sub { padding-left: 14px; }

/* ---------------------------------------------------------------
   Contact page — direct-contact cards and the project inquiry form.
   --------------------------------------------------------------- */

.contact-direct {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1px;
  background: rgba(10, 10, 10, .16);
  border-top: 1px solid rgba(10, 10, 10, .16);
  border-bottom: 1px solid rgba(10, 10, 10, .16);
}

/* The source stylesheet lays anchors out as flex rows, which put the
   label, heading and note side by side. Force a vertical stack. */
.contact-card {
  display: flex !important;
  flex-direction: column !important;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 0;
  background: var(--paper, #efede7);
  padding: 38px clamp(24px, 3.3vw, 60px);
  text-decoration: none;
  color: inherit;
  transition: background .2s ease;
}

.contact-card > * { width: 100%; }
.contact-card .section-label { margin: 0; }

.contact-card:hover { background: var(--sand, #d8d4ca); }

.contact-card h3 {
  font: 500 clamp(21px, 2vw, 29px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  margin: 12px 0 8px;
}

.contact-card p:last-child { opacity: .65; margin: 0; }

.contact-form-section { padding: 7vw clamp(24px, 5vw, 90px); }

.contact-form {
  max-width: 46rem;
  margin-top: 34px;
}

.form-row { display: flex; flex-direction: column; margin-bottom: 22px; }

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0 22px;
}

.contact-form label {
  font: 500 11px var(--font-barlow-condensed, inherit);
  letter-spacing: .14em;
  text-transform: uppercase;
  opacity: .7;
  margin-bottom: 8px;
}

.contact-form input,
.contact-form select,
.contact-form textarea {
  font-family: inherit;
  font-size: 16px; /* 16px minimum keeps iOS from zooming on focus */
  color: inherit;
  background: transparent;
  border: 1px solid rgba(10, 10, 10, .22);
  border-radius: 0;
  padding: 13px 14px;
  width: 100%;
  transition: border-color .18s ease;
}

.contact-form textarea { resize: vertical; line-height: 1.5; }

.contact-form input:focus,
.contact-form select:focus,
.contact-form textarea:focus {
  outline: none;
  border-color: currentColor;
}

.contact-form ::placeholder { opacity: .45; }

.form-submit {
  border: 0;
  cursor: pointer;
  font-family: inherit;
  margin-top: 10px;
}

.form-note { margin-top: 20px; opacity: .7; max-width: 44ch; }
.form-note a { text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 700px) {
  .form-grid { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------
   Homepage additions — the residential/commercial fork, clickable
   project cards and phase rows, and the "see all" text links.
   --------------------------------------------------------------- */

.home-fork .contact-card h3 {
  font: 500 clamp(23px, 2.4vw, 34px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  margin: 12px 0 10px;
}

.home-fork .contact-card p:last-child { max-width: 42ch; }

/* The source renders .phase as a grid row; keep that when it becomes a link. */
a.phase { text-decoration: none; color: inherit; }
a.phase .phase-arrow { transition: transform .25s ease; display: inline-block; }
a.phase:hover .phase-arrow { transform: translate(3px, -3px); }

.home-more {
  display: inline-block;
  margin: 38px 3.3vw 0;
}

/* Honeypot — off-screen, not display:none (some bots skip hidden fields). */
.form-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* The fork sits between two dark sections on the homepage, so the cards
   inherited white text onto a paper background — unreadable. Pin the
   colours explicitly and put the body copy back to sentence case. */
.home-fork .contact-card,
.home-fork .contact-card h3 { color: #0a0a0a; }

.home-fork .contact-card .section-label { color: #0a0a0a; opacity: .55; }

.home-fork .contact-card p:last-child {
  color: #2b2b2b;
  opacity: 1;
  text-transform: none;
  letter-spacing: normal;
  font: 400 clamp(15px, 1.15vw, 17px)/1.55 var(--font-barlow, "Barlow", Helvetica, Arial, sans-serif);
  margin-top: 4px;
}

/* Header logo. The source design sets 64px (52px on its own narrow
   breakpoint), which sits small in a 92px header bar. Bumped, with the
   mark's 2.2:1 ratio leaving it about 42px tall - still clear of the
   header's edges. */
.brand img { width: 92px; }

@media (max-width: 800px) {
  .brand img { width: 72px; }
}

/* Homepage project grid. The source runs one full-bleed project per row,
   which at desktop widths makes each photo ~770px tall - it dominates the
   page and pushes everything below it off screen. Two per row halves the
   size of each without cropping them into letterboxes. Scoped to the
   homepage; the portfolio index keeps its own grid. */
main:not(.architecture-page) .project-list {
  grid-template-columns: repeat(2, 1fr);
}

main:not(.architecture-page) .project { padding: 2vw; }

main:not(.architecture-page) .project-image { aspect-ratio: 16 / 10; }

/* The third card would sit alone on a two-up grid, so let it run full
   width and stay shorter than the source's full-bleed row. */
main:not(.architecture-page) .project:last-child { grid-column: 1 / -1; }
main:not(.architecture-page) .project:last-child .project-image { aspect-ratio: 16 / 5; }

@media (max-width: 800px) {
  main:not(.architecture-page) .project-list { grid-template-columns: 1fr; }
  main:not(.architecture-page) .project-image,
  main:not(.architecture-page) .project:last-child .project-image { aspect-ratio: 4 / 3; }
  main:not(.architecture-page) .project { padding: 5vw; }
}

/* Homepage projects, take two. Two-up at 16/10 was still ~570px tall on a
   desktop, and that ratio crops a 4:3 photo top and bottom - which is why
   the projects looked cut off. Three across at 4/3 matches the source
   photos exactly, so the full frame shows and each card is roughly a third
   of the original size. Mobile keeps the single-column 4/3 that already
   looked right. */
@media (min-width: 801px) {
  main:not(.architecture-page) .project-list { grid-template-columns: repeat(3, 1fr); }
  main:not(.architecture-page) .project { padding: 1.6vw; }
  main:not(.architecture-page) .project-image,
  main:not(.architecture-page) .project:last-child .project-image { aspect-ratio: 4 / 3; }
  main:not(.architecture-page) .project:last-child { grid-column: auto; }
  main:not(.architecture-page) .project-details { grid-template-columns: 34px 1fr; gap: 12px; padding-top: 14px; }
  main:not(.architecture-page) .project-details h3 { font-size: clamp(17px, 1.5vw, 23px); }
}

/* Hero alignment. The source splits the inner-page hero into two columns -
   eyebrow and headline on the left, intro paragraph pushed into a right
   column and bottom-aligned. The homepage hero was already overridden to a
   single left column; this matches every other page to it: everything
   stacked, sharing one left edge, with the intro on a readable measure. */
.architecture-hero-copy {
  grid-template-columns: 1fr;
  align-items: start;
  gap: 0;
}

.architecture-hero-copy .eyebrow { margin-bottom: 26px; }

.architecture-hero-copy h1 { margin: 0; }

.architecture-hero-copy > p {
  justify-self: start;
  text-align: left;
  max-width: 62ch;
  margin-top: 2.2vw;
}

/* ---------------------------------------------------------------
   Project grid - one definition for the homepage and the portfolio
   index, so the two can't drift apart again. Supersedes the earlier
   homepage-only blocks above.
   --------------------------------------------------------------- */
@media (min-width: 801px) {
  main .project-list { grid-template-columns: repeat(3, 1fr); }
  main .project { padding: 1.6vw; }
  main .project-image,
  main .project:last-child .project-image { aspect-ratio: 4 / 3; }
  main .project:last-child { grid-column: auto; }
}

/* The caption was a 3-column grid, which squeezed the location/type/year
   line into a narrow column and wrapped it four lines deep. Number and
   title share a row; the meta gets its own full-width row underneath. */
main .project-details {
  grid-template-columns: 26px 1fr;
  align-items: baseline;
  gap: 6px 12px;
  padding-top: 16px;
}

main .project-details h3 { font-size: clamp(17px, 1.5vw, 23px); }

main .project-details p {
  grid-column: 2 / -1;
  font-size: 11px;
  letter-spacing: .08em;
  opacity: .62;
  line-height: 1.5;
  max-width: none;
}

@media (max-width: 800px) {
  main .project-list { grid-template-columns: 1fr; }
  main .project-image,
  main .project:last-child .project-image { aspect-ratio: 4 / 3; }
  main .project { padding: 5vw; }
}

/* One-line project description under the caption. The meta line says what
   and where; this says why anyone should click. Sits in the title column
   so it lines up under the project name, not the number. */
main .project-blurb {
  grid-column: 2 / -1;
  font-size: clamp(13px, 1vw, 15px);
  line-height: 1.5;
  letter-spacing: normal;
  text-transform: none;
  opacity: .82;
  max-width: 44ch;
  margin-top: 2px;
}

/* Project cards sit on a black background, but .architecture-page sets a
   near-black ink colour for the page - so on the portfolio index the entire
   caption (number, title, meta, description) was rendering black on black
   and looked like empty space. The homepage escaped it because that section
   is already white-on-black. Pin the colour to the card, not the page. */
main .project,
main .project-details,
main .project-details h3,
main .project-details a { color: var(--white, #fff); }

main .project-details p { color: var(--white, #fff); opacity: .6; }
main .project-blurb { color: var(--white, #fff); opacity: .8; }
main .project-details span { color: var(--white, #fff); opacity: .5; }

/* Sticky header. The source positions it absolutely, so it scrolls away with
   the hero and the nav is gone for the rest of the page. Fixed rather than
   sticky, because absolute already takes it out of the flow - the heroes
   pad 92px (74px mobile) to clear it, so switching to fixed adds no layout
   shift and nothing jumps. */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 60;
}

/* Anchor targets need to clear the bar they now scroll underneath. */
[id] { scroll-margin-top: 110px; }

@media (max-width: 800px) {
  [id] { scroll-margin-top: 90px; }
}

/* The five build phases nested under Residential Construction. Indented
   inside the existing panel rather than a second flyout - a sideways
   sub-panel means hovering along a diagonal without falling off it, which
   is miserable on a trackpad.

   Collapsed by default and expanded on hover, so the panel opens at six
   items instead of eleven. The whole list is still one click away on the
   Residential Construction page itself, so nothing is buried. */
.services-dropdown .dropdown-sub {
  padding-left: 30px;
  font-size: 11px;
  opacity: .62;
  position: relative;

  /* The base rule sets min-height:48px and a bottom rule on every dropdown
     anchor. min-height beats max-height, so both have to be unset here or
     the row refuses to collapse. Animated rather than display:none so it
     slides open instead of snapping. */
  min-height: 0;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  border-bottom-width: 0;
  transition: min-height .26s ease, max-height .26s ease,
              opacity .18s ease, border-bottom-width .26s ease;
}

.services-dropdown .dropdown-sub::before {
  content: "";
  position: absolute;
  left: 16px;
  top: 50%;
  width: 7px;
  height: 1px;
  background: currentColor;
  opacity: .6;
}

/* Open while the parent row is hovered or keyboard-focused, and stay open
   while the cursor is down among the children themselves.

   The .18s opening delay is deliberate: without it, a cursor travelling
   past Residential Construction on its way to Pools expands five rows and
   shoves the target out from under the pointer. The delay means a pass-
   through does not trigger it, but an intentional hover does. Closing has
   no delay - retracting under the cursor is not a hazard. */
.services-dropdown:hover .dropdown-parent:hover ~ .dropdown-sub,
.services-dropdown:focus-within .dropdown-parent:focus ~ .dropdown-sub,
.services-dropdown .dropdown-sub:hover,
.services-dropdown .dropdown-sub:hover ~ .dropdown-sub,
.services-dropdown .dropdown-sub:focus,
.services-dropdown .dropdown-sub:focus ~ .dropdown-sub {
  min-height: 40px;
  max-height: 40px;
  opacity: .62;
  border-bottom-width: 1px;
  transition-delay: .18s;
}

/* Sibling combinators only reach forward, so hovering the third child
   cannot re-open the first two on its own. :has() closes the gap - one
   rule, no JavaScript, and it degrades to the rules above where it is
   unsupported. */
.services-dropdown:has(.dropdown-sub:hover) .dropdown-sub,
.services-dropdown:has(.dropdown-sub:focus) .dropdown-sub {
  min-height: 40px;
  max-height: 40px;
  opacity: .62;
  border-bottom-width: 1px;
  transition-delay: 0s;
}

.services-dropdown .dropdown-sub:hover { opacity: 1; }

/* The parent row earns a chevron so the collapsed state reads as
   collapsible rather than as the end of the list. */
.services-dropdown .dropdown-parent { position: relative; }

.services-dropdown .dropdown-caret {
  position: absolute;
  right: 18px;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -4px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  opacity: .45;
  transform: rotate(45deg);
  transform-origin: 60% 60%;
  transition: transform .26s ease, opacity .18s ease;
}

.services-dropdown .dropdown-parent:hover .dropdown-caret,
.services-dropdown .dropdown-parent:focus .dropdown-caret { opacity: .9; }

.services-dropdown:hover .dropdown-parent:hover .dropdown-caret,
.services-dropdown:has(.dropdown-sub:hover) .dropdown-caret,
.services-dropdown:has(.dropdown-sub:focus) .dropdown-caret {
  transform: rotate(225deg);
  opacity: .9;
}

/* Touch has no hover state, so a tap on the parent would follow the link
   and the five phases would never be reachable from the dropdown. The
   mobile menu below carries them expanded instead, and this panel is not
   used at that width - but pin it open anyway for anything in between. */
@media (hover: none) {
  .services-dropdown .dropdown-sub {
    min-height: 40px;
    max-height: 40px;
    opacity: .62;
    border-bottom-width: 1px;
  }
  .services-dropdown .dropdown-caret { display: none; }
}

/* Mobile: one level deeper than the existing indent. */
.mobile-menu-panel .mobile-menu-sub2 {
  padding-left: 30px;
  font-size: 15px;
  opacity: .68;
}

/* Mobile menu height. The source gives every row a 58px minimum, which was
   fine for 11 rows and overflows the screen now there are 24 - and because
   the panel sits inside a fixed header, the overflow was simply cut off with
   no way to reach it. Cap the panel to the viewport, let it scroll, and
   tighten the rows so most phones don't need to. */
.mobile-menu-panel {
  max-height: calc(100dvh - 74px);
  max-height: calc(100vh - 74px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.mobile-menu-panel a {
  min-height: 46px;
  font-size: 16px;
}

.mobile-menu-panel .mobile-menu-sub { font-size: 15px; }
.mobile-menu-panel .mobile-menu-sub2 { font-size: 14px; min-height: 40px; }
.mobile-menu-group { margin: 12px 0 4px; }

/* ---------------------------------------------------------------
   Bottom sticky bar - section jumper on the left, CTA on the right.
   Black and white, using the site's existing condensed type. Appears
   once the hero is behind you so it never fights the headline.
   --------------------------------------------------------------- */
.sticky-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 70;
  display: grid;
  grid-template-columns: 1fr auto;
  transform: translateY(110%);
  transition: transform .32s cubic-bezier(.4, 0, .2, 1);
  font: 500 12px var(--font-barlow-condensed, "Barlow Semi Condensed", Helvetica, Arial, sans-serif);
  letter-spacing: .1em;
  text-transform: uppercase;
}

.sticky-bar.is-visible { transform: translateY(0); }

.sticky-nav { position: relative; background: #0a0a0a; color: #fff; }

.sticky-current {
  width: 100%;
  height: 100%;
  min-height: 56px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 20px;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
  text-align: left;
}

.sticky-num { opacity: .45; }
.sticky-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sticky-chev { opacity: .55; transition: transform .25s ease; font-size: 15px; line-height: 1; }
.sticky-bar.is-open .sticky-chev { transform: rotate(180deg); }

.sticky-list {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  background: #0a0a0a;
  border-top: 1px solid rgba(255, 255, 255, .16);
  max-height: 54vh;
  overflow-y: auto;
}

.sticky-list button {
  display: flex;
  gap: 14px;
  width: 100%;
  padding: 14px 20px;
  background: none;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, .1);
  color: #fff;
  opacity: .62;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  text-align: left;
  cursor: pointer;
}

.sticky-list button span { opacity: .5; min-width: 22px; }
.sticky-list button:hover { opacity: 1; }
.sticky-list button.is-active { opacity: 1; }

.sticky-cta {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 34px;
  min-height: 56px;
  background: #fff;
  color: #0a0a0a;
  text-decoration: none;
  white-space: nowrap;
  font-weight: 700;
  transition: background .2s ease;
}

.sticky-cta::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #0a0a0a;
}

.sticky-cta:hover { background: var(--sand, #d8d4ca); }

/* Phones: the CTA is the point, so it takes the full width underneath. */
@media (max-width: 700px) {
  .sticky-bar { grid-template-columns: 1fr; }
  .sticky-current { min-height: 50px; font-size: 11px; }
  .sticky-cta { min-height: 52px; justify-content: center; padding: 0 20px; }
}

/* Keep the last section clear of the bar. */
.architecture-cta, .contact { padding-bottom: 120px; }

/* ---------------------------------------------------------------
   Careers - the apply form now sits directly under the hero, which
   means it lands on the dark stock rather than mid-page. Give it the
   treatment that position needs: inverted fields, a readable lede,
   and the form itself in a panel so it reads as the thing to do.
   --------------------------------------------------------------- */
.architecture-page .contact-form-section:first-of-type {
  background: var(--ink, #0a0a0a);
  color: #fff;
  padding: 6vw clamp(24px, 5vw, 90px) 7vw;
}

.architecture-page .contact-form-section:first-of-type .section-label,
.architecture-page .contact-form-section:first-of-type h2 { color: #fff; }
.architecture-page .contact-form-section:first-of-type .section-label { opacity: .55; }

.form-lede {
  max-width: 52ch;
  margin: 22px 0 0;
  font-size: clamp(15px, 1.15vw, 17px);
  line-height: 1.6;
  opacity: .8;
}

.form-lede a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }

/* Fields on dark stock: hairline boxes, white text, white focus. */
.architecture-page .contact-form-section:first-of-type .contact-form label { color: #fff; opacity: .7; }

.architecture-page .contact-form-section:first-of-type .contact-form input,
.architecture-page .contact-form-section:first-of-type .contact-form select,
.architecture-page .contact-form-section:first-of-type .contact-form textarea {
  color: #fff;
  border-color: rgba(255, 255, 255, .3);
  background: rgba(255, 255, 255, .04);
}

.architecture-page .contact-form-section:first-of-type .contact-form input:focus,
.architecture-page .contact-form-section:first-of-type .contact-form select:focus,
.architecture-page .contact-form-section:first-of-type .contact-form textarea:focus {
  border-color: #fff;
  background: rgba(255, 255, 255, .07);
}

.architecture-page .contact-form-section:first-of-type .contact-form ::placeholder { color: rgba(255,255,255,.42); }
.architecture-page .contact-form-section:first-of-type .contact-form option { color: #0a0a0a; }

.architecture-page .contact-form-section:first-of-type .form-submit {
  background: #fff;
  color: #0a0a0a;
}

.architecture-page .contact-form-section:first-of-type .form-note { color: #fff; opacity: .65; }
.architecture-page .contact-form-section:first-of-type .form-note a { color: #fff; }

/* Address in the footer contact column. Two lines, so it needs a little
   room above the phone number and its own line-height. */
.footer-address {
  display: block;
  line-height: 1.5;
  margin-bottom: 6px;
}

/* ---------------------------------------------------------------
   Credential strip - four facts, directly under the hero. Only
   things R2 can prove; the Parade of Homes line is the one that
   does real work.
   --------------------------------------------------------------- */
.cred-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: rgba(255, 255, 255, .14);
  border-bottom: 1px solid rgba(255, 255, 255, .14);
}

.cred-strip > div {
  background: var(--ink, #0a0a0a);
  color: #fff;
  padding: 22px clamp(16px, 2vw, 34px);
}

.cred-strip b {
  display: block;
  font: 500 clamp(17px, 1.7vw, 25px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  letter-spacing: .02em;
}

.cred-strip span {
  display: block;
  margin-top: 5px;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  opacity: .55;
}

@media (max-width: 800px) {
  .cred-strip { grid-template-columns: repeat(2, 1fr); }
}

/* Lead project. Scaled down 30% PROPORTIONALLY on 2026-08-12 - the whole card
   is 70% width and centred, with the original 16/7.5 ratio kept, so the photo
   shrinks in both dimensions and no longer spans the screen.
   First attempt cropped the ratio to 16/5 instead, which made it shorter but
   still full-bleed. That was the wrong reading of "reduce by 30%".
   The card is constrained rather than just the image so the title and meta
   stay aligned to the photo's left edge instead of hanging off it. */
@media (min-width: 801px) {
  main .project-list .project-feature { grid-column: 1 / -1; }
  /* Constrain the LINK, not the card. .project-list paints itself with --line
     and shows it through the 1px grid gaps; shrinking the card let that grey
     show as two slabs either side of the photo. The card still fills its cell
     and stays black - only its contents are 70% and centred. */
  main .project-list .project-feature .project-link {
    max-width: 70%;
    margin-inline: auto;
  }
  main .project-list .project-feature .project-image { aspect-ratio: 16 / 7.5; }
  main .project-list .project-feature .project-details h3 { font-size: clamp(24px, 2.4vw, 36px); }
}

/* Photo band - three complete properties, edge to edge. */
.photo-band { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--ink, #0a0a0a); }

.photo-band-item {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  background-size: cover;
  background-position: center;
  text-decoration: none;
  transition: filter .4s ease;
}

.photo-band-item:hover { filter: brightness(1.08); }

.photo-band-item span {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 14px 18px;
  background: linear-gradient(transparent, rgba(0, 0, 0, .75));
  color: #fff;
  font: 500 11px var(--font-barlow-condensed, inherit);
  letter-spacing: .1em;
  text-transform: uppercase;
}

@media (max-width: 800px) {
  .photo-band { grid-template-columns: 1fr; }
}

/* Homepage hero: close the gap. The source reserves a tall second row for a
   hero photo (82vh tall, 300px minimum). That row was the empty black space
   under the intro copy. Drop the row and the hero ends where the copy ends,
   so the credential strip sits directly beneath it. */
main:not(.architecture-page) .hero {
  min-height: 0;
  grid-template-rows: auto;
  padding-bottom: 3vw;
}

main:not(.architecture-page) .hero-image { display: none; }

/* Image band between the credentials and the fork. Shows the whole frame -
   an <img> at its natural ratio rather than a background crop, because the
   point of this photo is that you can see the entire property at once. */
/* Inset rather than edge to edge - the same 3.3vw gutter the rest of the
   page uses, so the photo lines up with the copy above and below it. */
/* Work strip between the credentials and the audience fork.
   History: this was one full-width 2048x1364 aerial, which on a wide monitor
   rendered over 1100px tall - taller than the viewport, so you scrolled
   through a photograph rather than past one. Ben asked to halve it
   (2026-08-12), then to make it a gallery of 3-4 instead.
   Four across at the page's own 3.3vw gutter. Each cell is forced to 3:2 with
   object-fit so the row keeps one clean baseline - Sage_Manor-4 is natively
   4:3 and would otherwise break the line. Cropping is acceptable here in a way
   it was not for the single hero: these are sized as a set of glimpses, not as
   one photo you are meant to read every corner of. */
.hero-band {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  background: var(--ink, #0a0a0a);
  font-size: 0;
  padding: 2.6vw 3.3vw;
}

.hero-band img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  height: auto;
}

/* Two-up before the cells get too narrow to read, one-up on a phone. 900px
   matches the source design's own mobile breakpoint used elsewhere in here. */
@media (max-width: 1100px) {
  .hero-band { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
  .hero-band { grid-template-columns: 1fr; }
}

/* Portfolio index: no hero photo. The page is wall-to-wall project
   photography already, so a hero image competes with the work rather than
   introducing it. Drop the image row; the hero ends at the copy. */
.page-projects .architecture-hero {
  min-height: 0;
  grid-template-rows: auto;
  padding-bottom: 4vw;
}

.page-projects .architecture-hero-image { display: none; }

/* Homepage: close the gap between "The R2 standard" and "Three phases".
   Both .intro and .services carry padding:11vw vertical, so where they sit
   next to each other the two pads stack into 22vw - roughly 410px of empty
   black on a desktop viewport, which reads as a broken page rather than as
   breathing room. Halved to ~11vw combined. Scoped to the adjacent pair so
   the section rhythm everywhere else is untouched. */
.intro:has(+ .services) { padding-bottom: 2.5vw; }
.intro + .services { padding-top: 3.5vw; }

@media (width <= 800px) {
  /* Mobile stacks 24vw + 24vw = 48vw. Same fix, same proportion. */
  .intro:has(+ .services) { padding-bottom: 6vw; }
  .intro + .services { padding-top: 8vw; }
}

/* The name, in the hero. The header carries the abstract R2 mark, which does
   not tell a first-time visitor who the company is - so the wordmark leads the
   hero above the eyebrow. Alt text carries the name for search and screen
   readers, since the mark itself is an image. */
.hero-wordmark {
  display: block;
  width: min(330px, 46vw);
  height: auto;
  margin-bottom: 26px;
}

@media (max-width: 800px) {
  .hero-wordmark { width: min(260px, 62vw); margin-bottom: 20px; }
}

/* Homepage fork: half the vertical padding. The source gives .contact-direct
   7vw top / 10vw bottom - about 130px and 186px on a wide monitor - which on
   the contact page is right, because the cards are the whole point of that
   screen. On the home page the fork is a signpost between the work strip and
   the rest of the page, and that much air made it read as an isolated island.
   Ben, 2026-08-12. Scoped to .home-fork so the contact page keeps the
   original spacing. Mobile halves the source's 20vw to match. */
/* Padding moved from .home-fork to the wrapper 2026-08-12 - the grid is now
   nested inside .home-fork-section, and leaving the padding on the grid would
   have indented the cards away from the divider rather than spacing the block. */
.home-fork-section {
  padding-top: 3.5vw;
  padding-bottom: 5vw;
}

@media (max-width: 800px) {
  .home-fork-section {
    padding-top: 10vw;
    padding-bottom: 10vw;
  }
}

/* ---------------------------------------------------------------
   "Three phases" section — inverted to white with black lettering.
   Ben, 2026-08-12. Only index.html and index-v2.html carry .services,
   so this is effectively homepage-scoped without a page class.
   Three things have to move together or the invert half-lands:
     - --line is #ffffff3d, a white hairline that vanishes on white, so
       the rules between phases need a dark one
     - .phase p is hardcoded #bdbdbd, which is 1.6:1 on white - unreadable
     - everything else inherits colour, so the section colour carries it
   --------------------------------------------------------------- */
.services {
  background: var(--white, #fff);
  color: var(--ink, #0a0a0a);
}

.services .phase {
  border-top-color: rgba(10, 10, 10, .16);
}

.services .phase p {
  color: #4a4a4a;
}

/* Air above "Projects". The source gives .projects no padding of its own and
   .section-heading only bottom padding, so on the homepage the heading started
   hard against the top edge of the black band - and once the section above it
   went white (2026-08-12) that edge became a hard colour boundary the heading
   was sitting right on top of. Ben, 2026-08-12: more padding above projects.
   clamp so it does not collapse to nothing on a phone.
   Scoped away from .architecture-page, which sets its own .projects padding. */
main:not(.architecture-page) .projects {
  padding-top: clamp(40px, 6vw, 120px);
  /* And a little below "See all projects". .home-more is margin: 38px 3.3vw 0
     - no bottom - and .projects has no bottom padding either, so the link sat
     flush on the black/white boundary. Smaller than the top value on purpose:
     the heading needs room to breathe, the link just needs to not touch the
     edge. Ben, 2026-08-12. */
  padding-bottom: clamp(28px, 3vw, 56px);
}

/* ---------------------------------------------------------------
   "A clear path forward" process section — inverted to white/black,
   matching the "Three phases" treatment above. Ben, 2026-08-12.
   Only index.html and index-v2.html carry .process.
   Same three traps as that invert: --line is a white hairline that
   disappears on white (here it draws the grid box AND the cell
   dividers), .process-grid p is hardcoded #bdbdbd (1.6:1 on white),
   and the step numbers are #888 (3.5:1 - legal but weak at 12px).
   --------------------------------------------------------------- */
.process {
  background: var(--white, #fff);
  color: var(--ink, #0a0a0a);
}

/* Vertical padding halved, 2026-08-12. Source is 7vw top / 11vw bottom
   (about 130px / 204px on a wide monitor) - a lot of white now that the
   section actually is white. Horizontal stays at the source's 3.3vw so the
   grid keeps the same left edge as every other section on the page. */
.process {
  padding-top: 3.5vw;
  padding-bottom: 5.5vw;
}

/* Source mobile is 10vw top / 24vw bottom. */
@media (max-width: 800px) {
  .process {
    padding-top: 5vw;
    padding-bottom: 12vw;
  }
}

.process .process-grid,
.process .process-grid article {
  border-color: rgba(10, 10, 10, .16);
}

.process .process-grid span { color: #6a6a6a; }
.process .process-grid p { color: #4a4a4a; }

/* Process section, Ben's rewrite 2026-08-12: headline + intro + four steps
   with a lead line each + a closing CTA. Source styling assumed one short
   paragraph per card, so several of its rules have to be undone:
     - .process-grid h3 is `margin: auto 0 14px`, which pushed the title to the
       BOTTOM of the card. With three blocks of content per step the title has
       to sit at the top.
     - articles were min-height:280px to stop short cards collapsing; the new
       copy fills them, so the floor just adds dead space. */
.process h2 {
  font: 500 clamp(34px, 4.6vw, 68px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  line-height: .94;
  letter-spacing: -.02em;
  margin: 14px 0 26px;
  max-width: 20ch;
}

.process .process-lead {
  max-width: 62ch;
  margin: 0 0 34px;
  color: #4a4a4a;
  font-size: clamp(16px, 1.25vw, 19px);
  line-height: 1.55;
}

.process .process-grid article { min-height: 0; }

.process .process-grid h3 {
  margin: 0 0 12px;
  font-size: clamp(24px, 2.1vw, 32px);
  display: flex;
  align-items: baseline;
  gap: 9px;
}

/* The number reads as "01 — Discover" without hard-coding the dash in copy. */
.process .process-grid h3 span {
  font-size: 13px;
  letter-spacing: .1em;
  color: #6a6a6a;
}

.process .process-grid h3 span::after { content: "—"; margin-left: 9px; }

.process .process-grid .step-lead {
  color: var(--ink, #0a0a0a);
  font-weight: 500;
  margin: 0 0 10px;
  line-height: 1.35;
}

/* Solid pill rather than the header's outlined one - this is the page's
   conversion point, and an outline on white reads as a secondary link. */
.process-cta {
  display: inline-block;
  margin: 34px 3.3vw 0;
  padding: 15px 30px;
  border-radius: 99px;
  background: var(--ink, #0a0a0a);
  color: var(--white, #fff);
  font: 500 13px var(--font-barlow-condensed, inherit);
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  transition: opacity .2s ease;
}

.process-cta:hover { opacity: .78; }

@media (max-width: 800px) {
  .process .process-grid h3 { font-size: 26px; }
  .process-cta { margin-left: 5vw; margin-right: 5vw; }
}

/* ---------------------------------------------------------------
   The fork — "How can we help?" 2026-08-12.
   Two whole-card links that invert on hover. Reuses .contact-direct
   for the grid and 1px divider and .contact-card for the cream
   plate; everything below is the decision-point treatment on top.
   --------------------------------------------------------------- */

.fork-head { padding: 0 3.3vw 26px; }

.fork-head h2 {
  font: 500 clamp(30px, 3.4vw, 52px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  line-height: .96;
  letter-spacing: -.02em;
  margin: 0 0 12px;
}

.fork-head p {
  margin: 0;
  color: #bdbdbd;
  font-size: clamp(15px, 1.15vw, 18px);
}

/* Tighter than the source's 38px - the cards carry four short blocks now,
   and the extra air read as unfinished rather than generous. */
/* Tighter than the source's 38px - the cards carry four short blocks now,
   and the extra air read as unfinished rather than generous. (Briefly cut to
   12/11px on 2026-08-12; reverted - the space Ben wanted gone was OUTSIDE the
   cards, see the .home-fork rule below.) */
.home-fork .contact-card {
  padding: 30px clamp(24px, 3.3vw, 60px) 28px;
  cursor: pointer;
  transition: background .28s ease, color .28s ease;
}

/* Padding ABOVE and BELOW the cards.
   REGRESSION FIX: the source sets .contact-direct to `padding: 7vw 3.3vw 10vw`
   - 128px top / 183px bottom on a wide monitor. An earlier override killed
   that, but when the fork was rebuilt on 2026-08-12 the override moved to the
   new .home-fork-section wrapper, which let the source rule come back on the
   grid. Zeroed here: the wrapper already supplies the outer spacing, and
   .fork-head's 26px is the gap between the supporting line and the cards.
   Horizontal 3.3vw is left alone so the cards stay inset on the page grid. */
.home-fork {
  padding-top: 0;
  padding-bottom: 0;
}

.home-fork .contact-card h3 { margin: 10px 0 12px; }

.home-fork .contact-card .fork-lead {
  color: #0a0a0a;
  font: 500 clamp(16px, 1.3vw, 19px)/1.4 var(--font-barlow, "Barlow", Helvetica, Arial, sans-serif);
  text-transform: none;
  letter-spacing: normal;
  margin: 0 0 8px;
  max-width: 34ch;
}

.home-fork .contact-card .fork-body {
  color: #2b2b2b;
  opacity: 1;
  text-transform: none;
  letter-spacing: normal;
  font: 400 clamp(15px, 1.15vw, 17px)/1.55 var(--font-barlow, "Barlow", Helvetica, Arial, sans-serif);
  margin: 0;
  max-width: 42ch;
}

.home-fork .contact-card .fork-cta {
  display: inline-block;
  margin-top: 22px;
  font: 500 12px var(--font-barlow-condensed, inherit);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #0a0a0a;
}

.fork-arrow {
  display: inline-block;
  margin-left: 6px;
  transition: transform .25s ease;
}

/* ---- inverted state: cream plate -> black, on hover AND keyboard focus ---- */
.home-fork .contact-card:hover,
.home-fork .contact-card:focus-visible { background: var(--ink, #0a0a0a); }

.home-fork .contact-card:hover,
.home-fork .contact-card:hover h3,
.home-fork .contact-card:hover .fork-lead,
.home-fork .contact-card:hover .fork-cta,
.home-fork .contact-card:focus-visible,
.home-fork .contact-card:focus-visible h3,
.home-fork .contact-card:focus-visible .fork-lead,
.home-fork .contact-card:focus-visible .fork-cta { color: var(--paper, #f1f0ec); }

.home-fork .contact-card:hover .section-label,
.home-fork .contact-card:focus-visible .section-label {
  color: var(--paper, #f1f0ec);
  opacity: .6;
}

.home-fork .contact-card:hover .fork-body,
.home-fork .contact-card:focus-visible .fork-body { color: #d9d6ce; }

.home-fork .contact-card:hover .fork-arrow,
.home-fork .contact-card:focus-visible .fork-arrow { transform: translateX(5px); }

/* Keyboard users get the invert plus a visible ring; mouse users just the
   invert. outline-offset -3px keeps the ring inside the 1px grid divider. */
.home-fork .contact-card:focus-visible {
  outline: 2px solid var(--paper, #f1f0ec);
  outline-offset: -3px;
}

/* Respect reduced-motion: keep the colour change, drop the arrow travel. */
@media (prefers-reduced-motion: reduce) {
  .home-fork .contact-card,
  .fork-arrow { transition: none; }
  .home-fork .contact-card:hover .fork-arrow,
  .home-fork .contact-card:focus-visible .fork-arrow { transform: none; }
}

@media (max-width: 800px) {
  .fork-head { padding: 0 5vw 22px; }
  .home-fork .contact-card { padding: 26px 5vw 24px; }
  /* Source mobile is `padding: 20vw 5vw` on .contact-direct - same regression
     as desktop, same fix. */
  .home-fork { padding-top: 0; padding-bottom: 0; }
}

/* ---------------------------------------------------------------
   Hero background video (added 2026-08-12). Shared by the homepage
   and the contact page - the selectors below are deliberately not tied
   to .hero, so any section can opt in with .has-hero-video.
   The hero used to be copy on flat black. The video sits behind it
   as a full-bleed layer with the poster frame underneath, so there
   is never a bare black flash and never a moment where the white
   headline sits on unpredictable footage: a black scrim carries the
   contrast, not the video.
   --------------------------------------------------------------- */
.has-hero-video {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background-image: url(/site-assets/img/hero-video-poster.jpg);
  background-size: cover;
  background-position: center;
}

.has-hero-video .hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
  opacity: 0;
  transition: opacity 900ms ease;
  pointer-events: none;
}

/* Only revealed once the browser says it can actually play - otherwise
   the poster stays and the swap is never visible as a stutter. */
.has-hero-video .hero-video.is-playing { opacity: 1; }

/* The scrim. Heavier at the top where the wordmark and eyebrow sit and
   the fixed header overlaps, easing off toward the bottom so the footage
   is still legible as footage. */
.has-hero-video::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.78) 0%,
    rgba(0, 0, 0, 0.62) 45%,
    rgba(0, 0, 0, 0.5) 100%
  );
  pointer-events: none;
}

/* The homepage hero override above collapses the hero to the height of
   its copy. With footage behind it that reads as a letterbox strip, so
   give it real height back - but not a full screen. */
main:not(.architecture-page) .hero.has-hero-video {
  min-height: 78vh;
  padding-bottom: 5vw;
}

@media (max-width: 900px) {
  /* Taller on a phone than the 62vh it started at: the footage is landscape
     and the viewport is portrait, so object-fit crops hard from the sides.
     Height is what keeps enough of the frame on screen to read as a place
     rather than as an abstract moving texture. */
  main:not(.architecture-page) .hero.has-hero-video {
    min-height: 72vh;
  }
}

@media (prefers-reduced-motion: reduce) {
  .has-hero-video .hero-video { display: none; }
}

/* ---------------------------------------------------------------
   Work-strip captions (added 2026-08-12). The strip's cells are now
   <figure>, so the grid items are the figures rather than the images.
   Type deliberately mirrors .cred-strip directly above it: a condensed
   uppercase label over a small muted line. The two sections are one
   argument - the strip says it in words, the photos say it in pictures -
   so they should not look like two different systems.
   --------------------------------------------------------------- */
.hero-band figure {
  margin: 0;
  display: flex;
  flex-direction: column;
}

.hero-band figcaption {
  /* .hero-band sets font-size: 0 to kill inline whitespace between the
     cells; the caption has to put a real size back. */
  font-size: 11px;
  color: #fff;
  padding: 14px 2px 0;
}

.hero-band figcaption b {
  display: block;
  font: 500 clamp(13px, 1.05vw, 16px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  letter-spacing: .04em;
}

.hero-band figcaption span {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  line-height: 1.45;
  letter-spacing: .05em;
  text-transform: uppercase;
  opacity: .55;
}

@media (max-width: 1100px) {
  /* Two-up: the cells are wide enough that the caption can breathe. */
  .hero-band figcaption { padding-top: 16px; }
}

@media (max-width: 560px) {
  .hero-band figcaption { padding-bottom: 10px; }
}

/* Work-strip header. Spans every column so it introduces the set rather than
   sitting in it, at any breakpoint. Type mirrors .fork-head but a step down:
   the fork is the page's decision point and the Projects section below is a
   top-level destination, so this header has to read as supporting both, not
   as a third thing shouting at the same volume. */
.hero-band .band-head {
  grid-column: 1 / -1;
  font-size: 1rem;          /* .hero-band zeroes font-size for the grid */
  padding: 0 0 clamp(20px, 1.9vw, 30px);
  max-width: 62ch;
}

.hero-band .band-head .section-label {
  margin-bottom: 14px;
  opacity: .55;
}

.hero-band .band-head h2 {
  font: 500 clamp(26px, 2.7vw, 40px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  line-height: .98;
  letter-spacing: -.015em;
  margin: 0 0 12px;
  color: #fff;
}

.hero-band .band-head .band-lead {
  margin: 0;
  color: #bdbdbd;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.5;
}

@media (max-width: 560px) {
  .hero-band .band-head { padding-bottom: 22px; }
}

/* Section heading: headline left, label right (2026-08-12, Ben).
   The source ran the eyebrow left and the display headline hard right.
   Reversing the row puts PROJECTS on the left edge, where it lines up with
   every other left-aligned headline on the page and with the photo below it,
   instead of floating off to the right on its own.

   Scoped to >800px on purpose: at 800px and under the source stacks this to
   a column, and overrides.css loads after styles.css, so an unscoped
   flex-direction here would beat that media query and un-stack the heading
   on phones. */
@media (min-width: 801px) {
  .section-heading { flex-direction: row-reverse; }
}

/* .intro sections: content left, label right (2026-08-12, Ben) — the same
   flip just applied to .section-heading, so the two read as one decision.

   The source runs a 1fr / 2fr grid with the eyebrow in the narrow left
   column. Widths swap to 2fr / 1fr and the two children are placed
   explicitly into the same row, so the copy takes the wide left column and
   the label the narrow right one. The label is right-aligned so it hugs the
   page edge, mirroring how it hugged the left edge before — otherwise it
   just floats next to the paragraph with no edge to hold it.

   Scoped to >800px for the same reason as .section-heading: at 800px and
   under the source collapses this to a single column, and this file loads
   last, so an unscoped grid-template-columns would override that. */
@media (min-width: 801px) {
  .intro { grid-template-columns: 2fr 1fr; }

  .intro > div { grid-column: 1; grid-row: 1; }

  .intro > .section-label {
    grid-column: 2;
    grid-row: 1;
    text-align: right;
  }
}

/* Contact page video hero. The source runs .architecture-hero as two rows -
   copy, then a tall still-image panel - and overrides.css already collapses
   it to just the copy row on inner pages. With footage behind it that
   collapsed height reads as a letterbox strip, so give it real height back,
   the same way the homepage hero does. */
.page-contact .architecture-hero.has-hero-video {
  min-height: 72vh;
  grid-template-rows: auto;
  align-content: center;
}

@media (max-width: 900px) {
  /* Landscape footage in a portrait viewport crops hard from the sides;
     height is what keeps enough of the frame on screen to read as a place. */
  .page-contact .architecture-hero.has-hero-video { min-height: 66vh; }
}

/* ---------------------------------------------------------------
   Service hero photo - one image across every service page.
   Ben's call 2026-08-13. The nine architecture-hero pages carry it
   as an inline style; the design page keeps its image in the source
   stylesheet, so it is matched here instead.
   --------------------------------------------------------------- */
.design-hero-image {
  background-image: url(https://r2landscape.com/wp-content/uploads/2026/07/DSC06612.jpg);
  background-position: 50% 60%;
}

/* ===============================================================
   CONVERSION LAYER — 2026-08-13.
   Added after a homepage conversion review found the page asked for
   nothing in the hero, showed no phone number above the footer, had
   no on-page form, and offered only one CTA ("Start Your Project")
   with no lower-commitment alternative.
   Everything below reuses the existing type scale, the ink/sand
   palette and the pill idiom already in the page — no new visual
   language, so the additions read as part of the original design.
   =============================================================== */

/* --- Header phone -------------------------------------------------
   Sits left of the outlined project CTA. Deliberately quieter than the
   CTA: it is a second option, not a competing one. */
.header-phone {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-right: clamp(10px, 1.2vw, 22px);
  color: #fff;
  font: 500 13px var(--font-barlow-condensed, inherit);
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  opacity: .82;
  transition: opacity .2s ease;
}

.header-phone:hover { opacity: 1; }
.header-phone-icon { font-size: 15px; line-height: 1; }

/* The header is tight on tablet; the number is the first thing to go,
   because the mobile menu and the hero both carry it. */
@media (max-width: 1100px) {
  .header-phone span:last-child { display: none; }
  .header-phone { margin-right: 12px; }
  .header-phone-icon { font-size: 18px; }
}

@media (max-width: 800px) {
  .header-phone { display: none; }
}

/* --- Hero actions -------------------------------------------------
   The hero previously ended at .hero-intro with nothing clickable.
   Two asks side by side, then a transitional link underneath. */
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(14px, 1.6vw, 26px);
  margin-top: clamp(26px, 2.6vw, 42px);
}

/* Solid pill. Same treatment as .process-cta — this is a conversion
   point, and an outline over photography loses to the background. */
.hero-cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 16px 32px;
  border-radius: 99px;
  background: var(--white, #fff);
  color: var(--ink, #0a0a0a);
  font: 500 13px var(--font-barlow-condensed, inherit);
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background .22s ease, color .22s ease;
}

.hero-cta:hover { background: var(--sand, #d8d4ca); }

/* Call: outlined, so it reads as the secondary of the two without
   disappearing. Two-line so the number carries a reason next to it. */
.hero-call {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 12px 26px 12px 22px;
  border: 1px solid rgba(255, 255, 255, .42);
  border-radius: 99px;
  color: #fff;
  text-decoration: none;
  transition: border-color .22s ease, background .22s ease;
}

.hero-call:hover { border-color: #fff; background: rgba(255, 255, 255, .08); }
.hero-call-icon { font-size: 21px; line-height: 1; opacity: .9; }

.hero-call b {
  display: block;
  font: 500 16px var(--font-barlow-condensed, inherit);
  letter-spacing: .04em;
}

.hero-call em {
  display: block;
  margin-top: 2px;
  font-style: normal;
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  opacity: .6;
}

/* The transitional CTA. Every other ask on this page is a commitment;
   this is the one for the visitor who is still deciding. */
.hero-transitional {
  display: inline-block;
  margin-top: clamp(16px, 1.6vw, 24px);
  color: #fff;
  font-size: 13px;
  letter-spacing: .04em;
  text-decoration: none;
  opacity: .6;
  border-bottom: 1px solid rgba(255, 255, 255, .3);
  padding-bottom: 3px;
  transition: opacity .2s ease, border-color .2s ease;
}

.hero-transitional:hover { opacity: .95; border-bottom-color: rgba(255, 255, 255, .8); }

@media (max-width: 800px) {
  .hero-actions { gap: 12px; margin-top: 24px; }
  .hero-cta,
  .hero-call { width: 100%; justify-content: center; }
  .hero-cta { padding: 15px 24px; }
}

/* --- Proof / testimonials ----------------------------------------
   Styled and ready; the markup in index.html is commented out until
   Ben supplies real client quotes. See the note above it. */
.proof { padding: 6vw 3.3vw; background: var(--paper, #efede7); }
.proof-head { max-width: 46rem; margin-bottom: 3vw; }

.proof-head h2 {
  font: 500 clamp(30px, 3.4vw, 52px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  line-height: .96;
  letter-spacing: -.02em;
  margin: 12px 0 0;
}

.proof-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.4rem;
}

.proof-card {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  margin: 0;
  padding: 2rem 1.9rem;
  background: #fff;
  border: 1px solid rgba(10, 10, 10, .12);
}

.proof-quote {
  flex: 1;
  margin: 0;
  font-size: 1.02rem;
  line-height: 1.55;
}

.proof-quote::before { content: "\201C"; }
.proof-quote::after  { content: "\201D"; }

.proof-attrib b {
  display: block;
  font: 500 15px var(--font-barlow-condensed, inherit);
  letter-spacing: .06em;
  text-transform: uppercase;
}

.proof-attrib span {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  opacity: .55;
}

/* --- FAQ ----------------------------------------------------------
   Native <details> so it works with JS disabled and stays accessible
   without a custom accordion. */
.faq {
  display: grid;
  grid-template-columns: minmax(0, .8fr) minmax(0, 1.6fr);
  gap: clamp(30px, 4vw, 80px);
  padding: 6vw 3.3vw;
  align-items: start;
}

.faq-head h2 {
  font: 500 clamp(30px, 3.4vw, 52px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  line-height: .96;
  letter-spacing: -.02em;
  margin: 12px 0 0;
}

.faq-list { border-top: 1px solid rgba(10, 10, 10, .16); }
.faq-item { border-bottom: 1px solid rgba(10, 10, 10, .16); }

.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 20px 0;
  cursor: pointer;
  list-style: none;
  font: 500 clamp(17px, 1.5vw, 21px) var(--font-barlow-condensed, inherit);
  letter-spacing: .01em;
  text-transform: uppercase;
}

.faq-item summary::-webkit-details-marker { display: none; }

/* Plus that becomes a minus. Drawn rather than typed so it lines up
   optically with the text baseline at every clamp size. */
.faq-mark {
  position: relative;
  flex: 0 0 14px;
  width: 14px;
  height: 14px;
}

.faq-mark::before,
.faq-mark::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 1.5px;
  background: var(--ink, #0a0a0a);
  transition: transform .25s ease;
}

.faq-mark::after { transform: rotate(90deg); }
.faq-item[open] .faq-mark::after { transform: rotate(0deg); }

.faq-item > p {
  margin: 0;
  padding: 0 0 24px;
  max-width: 62ch;
  line-height: 1.62;
  opacity: .78;
}

.faq-item > p a { text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 900px) {
  .faq { grid-template-columns: 1fr; padding: 12vw 5vw; }
}

/* --- Homepage inquiry form ---------------------------------------
   Copy left, form right. Reuses .contact-form wholesale so the inputs,
   focus states and submit button match the contact page exactly. */
.home-form-section {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: clamp(30px, 4.5vw, 90px);
  padding: 6vw 3.3vw;
  background: var(--paper, #efede7);
  align-items: start;
}

.home-form-copy h2 {
  font: 500 clamp(34px, 4vw, 62px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  line-height: .95;
  letter-spacing: -.02em;
  margin: 12px 0 22px;
}

.home-form-lead {
  max-width: 34ch;
  font-size: clamp(15px, 1.15vw, 18px);
  line-height: 1.6;
  opacity: .78;
}

.home-form-alt {
  margin-top: 26px;
  font-size: 14px;
  line-height: 1.75;
  opacity: .62;
}

.home-form-alt a { text-decoration: underline; text-underline-offset: 3px; }

/* .contact-form caps itself for the contact page's single column; here
   it is already inside a grid track, so let it fill. */
.home-form { max-width: none; width: 100%; }

@media (max-width: 900px) {
  .home-form-section { grid-template-columns: 1fr; padding: 12vw 5vw; }
}

/* --- Sticky bar: tap-to-call ---------------------------------------
   2026-08-13. The bar was 1fr auto (section jumper + CTA); it is now
   1fr auto auto so the call button sits between them. On phones the
   bar stacks to a single column, so call and CTA share one row —
   call narrower, because the project CTA is still the primary ask. */
.sticky-bar { grid-template-columns: 1fr auto auto; }

.sticky-call {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 22px;
  min-height: 56px;
  background: var(--sand, #d8d4ca);
  color: #0a0a0a;
  text-decoration: none;
  white-space: nowrap;
  font-weight: 700;
  border-right: 1px solid rgba(10, 10, 10, .16);
  transition: background .2s ease;
}

.sticky-call span[aria-hidden] { font-size: 17px; line-height: 1; }
.sticky-call:hover { background: #c9c4b8; }

@media (max-width: 700px) {
  /* Row 1 = section jumper, row 2 = call + CTA side by side. The CTA keeps
     the larger share; the call button only needs to be thumb-sized. */
  .sticky-bar {
    grid-template-columns: 0.8fr 1.2fr;
    grid-template-areas:
      "nav  nav"
      "call cta";
  }
  .sticky-nav  { grid-area: nav; }
  .sticky-call { grid-area: call; justify-content: center; min-height: 52px; padding: 0 14px; border-right: 0; border-top: 1px solid rgba(10, 10, 10, .16); }
  .sticky-cta  { grid-area: cta; }
}

/* ---------------------------------------------------------------
   CONTRAST FIX — 2026-08-13, same day as the conversion layer.

   body is `background: var(--black); color: var(--white)` — the whole
   site is dark by default and every section inherits white text. Two
   of the new sections got that wrong in opposite directions:

     .proof and .home-form-section were given a LIGHT (--paper)
     background but no text colour, so every heading, label, quote and
     button inherited white and rendered white-on-cream — invisible.

     .faq was left on the DARK body, but its rules were written for a
     light background: hairline borders at rgba(10,10,10,.16) and a
     +/- mark filled with --ink, i.e. black on black — also invisible.

   Fixed by stating the colour explicitly on both, rather than relying
   on inheritance. The base .contact-form styling already assumes a
   light background (its borders are rgba(10,10,10,.22)), which is why
   the form's field boxes were the only thing visible in the light
   section — so the light background stays and the text colour comes
   to meet it.
   --------------------------------------------------------------- */

/* --- Light sections: state the ink colour --------------------- */
.proof,
.home-form-section {
  color: var(--ink, #0a0a0a);
}

/* .section-label and the headings carry no colour of their own, so the
   line above covers them. These two do need saying: the submit button
   is a bordered pill that draws from currentColor, and links inside
   the light block must not fall back to the dark theme's white. */
.proof a,
.home-form-section a { color: inherit; }

.home-form-section .pill-button,
.home-form-section .form-submit {
  color: var(--ink, #0a0a0a);
  background: transparent;
}

.home-form-section .form-submit:hover {
  background: var(--ink, #0a0a0a);
  color: var(--white, #fff);
}

/* --- FAQ: it sits on the dark body, so invert its hairlines ---- */
.faq-list { border-top-color: rgba(255, 255, 255, .18); }
.faq-item { border-bottom-color: rgba(255, 255, 255, .18); }

.faq-mark::before,
.faq-mark::after { background: #fff; }

/* Answer copy at .78 on black is thin; lift it slightly so it reads. */
.faq-item > p { opacity: .72; }

/* ---------------------------------------------------------------
   HEADER RIGHT CLUSTER — 2026-08-13 (fix).

   .site-header is `grid-template-columns: 1fr auto 1fr` — brand, nav,
   and a third column the CTA sits in with justify-self:end. Adding
   .header-phone as a fourth direct child created an implicit fourth
   column: the phone took the CTA's slot against the nav, and "Start
   Your Project" was pushed into a column outside the header's padding.

   Both now live in one wrapper that occupies column three, so the grid
   keeps the exact shape every other page uses.

   At <=800px the header collapses to `1fr auto` (brand + burger) and
   hides nav and CTA — so the wrapper has to go too, or it would take
   the burger's cell and break the mobile header the same way. The
   number is still reachable there: it is in the mobile menu, the hero,
   the sticky bar and the footer.
   --------------------------------------------------------------- */
.header-actions {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.4vw, 26px);
}

/* The CTA set its own justify-self for when it was a direct grid child;
   inside a flex row that does nothing, and the wrapper handles it. */
.header-actions .header-cta { justify-self: auto; }

/* .header-phone kept its own right margin from the first pass, when it
   was a sibling of the CTA rather than a flex item beside it. The gap
   above owns the spacing now. */
.header-actions .header-phone { margin-right: 0; }

@media (max-width: 800px) {
  .header-actions { display: none; }
}

/* ---------------------------------------------------------------
   PROOF GRID — 2026-08-13, revised for a fourth review.

   The first pass used `repeat(auto-fit, minmax(280px, 1fr))`, which is
   right for three cards and wrong for four: between roughly 900px and
   1250px it resolves to three columns and strands the fourth card
   alone on a second row. Explicit breakpoints instead, so the count is
   always a factor of four — 4 across, then 2x2, then stacked. No
   orphan row at any width.
   --------------------------------------------------------------- */
.proof-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1250px) {
  .proof-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .proof-grid { grid-template-columns: minmax(0, 1fr); }
}

/* Four narrower cards need slightly tighter setting than three wide ones,
   and the quotes vary a lot in length — Emily's is one line where
   Jonathan's is six. flex:1 on the quote already pins every attribution
   to the same baseline; this just stops the long ones running loose. */
.proof-quote { font-size: 1rem; line-height: 1.5; }

@media (min-width: 1251px) {
  .proof-card { padding: 1.8rem 1.6rem; }
}

/* ===============================================================
   SERVICE PAGE SEO PASS — 2026-08-13.

   The ten service pages carried no <img> at all; every photograph was
   a CSS background-image, which meant no alt text and no presence in
   Google Images on a business that sells with pictures. The photos are
   now real <img> elements inside the same containers, positioned to
   render identically to the backgrounds they replace.
   =============================================================== */

/* --- Photographs -------------------------------------------------
   Absolutely positioned inside the existing container so the layout
   is byte-for-byte what the background-image produced. The containers
   keep their background declaration as a fallback for the moment
   between paint and decode. */
.architecture-hero-image,
.design-hero-image,
.design-feature-image { position: relative; overflow: hidden; }

.architecture-hero-image-photo,
.design-hero-image-photo,
.design-feature-image-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The hero photo on .design-hero-image was focused at 50% 55% as a
   background; object-position carries that across. */
.design-hero-image-photo { object-position: 50% 55%; }

/* The hero container is a flex row with the R2 / Built With Purpose
   captions pinned to the bottom. They have to sit above the photo. */
.architecture-hero-image > span,
.design-image-label { position: relative; z-index: 1; }

/* --- Keyword subhead under the H1 --------------------------------
   The H1 headlines are the best writing on the site and were left
   alone; this is the line that carries the search terms they don't.
   Sized between the H1 and the body paragraph so it reads as part of
   the headline block rather than as a first paragraph. */
.hero-subhead {
  max-width: 44ch;
  margin: 18px 0 0;
  font: 500 clamp(15px, 1.35vw, 19px) var(--font-barlow-condensed, inherit);
  letter-spacing: .01em;
  line-height: 1.4;
  opacity: .72;
}

/* --- Service page link block -------------------------------------
   Every service page was close to a dead end - commercial.html had
   zero in-body outbound links. This sends equity to the city pages
   that were already linking in, and to sibling services. */
.service-links {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(30px, 4vw, 80px);
  padding: 5vw 3.3vw 6vw;
  border-top: 1px solid rgba(255, 255, 255, .14);
}

.service-links-col p:not(.section-label) {
  margin: 0 0 20px;
  line-height: 2;
  opacity: .78;
}

.service-links-col a {
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}

.service-links-col .text-link {
  text-decoration: none;
  opacity: .9;
}

@media (max-width: 800px) {
  .service-links { grid-template-columns: 1fr; padding: 12vw 5vw; }
}

/* --- FAQ on the service pages ------------------------------------
   .faq was written for the homepage, which sits on the same dark
   stock, so the existing rules carry over unchanged. Only the outer
   spacing needs to match the service-page rhythm. */
.architecture-page .faq { padding: 6vw 3.3vw 5vw; }

@media (max-width: 900px) {
  .architecture-page .faq { padding: 12vw 5vw 8vw; }
}

/* ---------------------------------------------------------------
   SERVICE GALLERY — 2026-08-13.

   Three photographs of the actual service, on every service page.
   Ben's note: "the retaining wall page doesn't have retaining wall
   pictures." It had a hero and one stock feature image, and nothing
   showing the work itself.

   Deliberately real <img> rather than the CSS background-image
   treatment used by .photo-band and .hero-band: the whole point of
   this block is that the photographs are indexable and carry alt
   text. Captions echo the credential-strip idiom (bold label over a
   muted line) so the block reads as part of the existing design.
   --------------------------------------------------------------- */
.service-gallery {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 1.4vw, 24px);
  padding: 5vw 3.3vw 6vw;
  border-top: 1px solid rgba(255, 255, 255, .14);
}

/* The heading spans the row so it does not become a fourth cell. */
.gallery-head { grid-column: 1 / -1; margin-bottom: clamp(10px, 1.4vw, 22px); }

.gallery-head h2 {
  font: 500 clamp(30px, 3.4vw, 52px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  line-height: .96;
  letter-spacing: -.02em;
  margin: 12px 0 0;
}

.service-gallery figure { margin: 0; }

.service-gallery img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: rgba(255, 255, 255, .06);
}

.service-gallery figcaption { padding-top: 14px; }

.service-gallery figcaption b {
  display: block;
  font: 500 clamp(14px, 1.25vw, 17px) var(--font-barlow-condensed, inherit);
  text-transform: uppercase;
  letter-spacing: .04em;
}

.service-gallery figcaption span {
  display: block;
  margin-top: 5px;
  font-size: 12.5px;
  line-height: 1.5;
  opacity: .58;
}

@media (max-width: 900px) {
  .service-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); padding: 12vw 5vw; }
  /* Three photos in a two-column grid strands the third. Let the first
     one run full width instead, so the row is always complete. */
  .service-gallery figure:first-of-type { grid-column: 1 / -1; }
  .service-gallery figure:first-of-type img { aspect-ratio: 16 / 9; }
}

@media (max-width: 560px) {
  .service-gallery { grid-template-columns: 1fr; }
  .service-gallery figure:first-of-type img { aspect-ratio: 3 / 2; }
}
