/* R&R Services LLC. Built from .moa/CREATIVE_SPEC.json, revision 2.
   Mobile first: phone to 699px, tablet from 700px, desktop from 1024px. */

@font-face {
  font-family: "Manrope";
  src: url("../assets/fonts/manrope.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "DM Sans";
  src: url("../assets/fonts/dm-sans.woff2") format("woff2");
  font-weight: 100 1000;
  font-style: normal;
  font-display: swap;
}

:root {
  --charcoal: #111411;
  --green: #76bb40;
  --ivory: #f3f2ec;
  --white: #ffffff;
  --logo-black: #000000;
  --ink-soft: #4b514b;
  --ivory-soft: #b8bbb1;

  --display: "Manrope", "Segoe UI", system-ui, sans-serif;
  --body: "DM Sans", "Segoe UI", system-ui, sans-serif;

  --size-display-xl: clamp(2.75rem, 7.5vw, 7rem);
  --size-display-l: clamp(2.125rem, 5.2vw, 4.75rem);
  --size-numeral: clamp(3rem, 8vw, 7.5rem);
  --size-heading: clamp(1.75rem, 3.2vw, 2.75rem);
  --size-title: clamp(1.25rem, 1.7vw, 1.625rem);
  --size-body-l: clamp(1.0625rem, 1.3vw, 1.25rem);
  --size-body: 1.0625rem;
  --size-label: 0.8125rem;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* Grid: 4 columns on phones, 8 on tablets, 12 on desktop. */
  --max: 1440px;
  --cols: 4;
  --margin: 20px;
  --gutter: 16px;
  --col: calc((min(100%, var(--max)) - 2 * var(--margin) - (var(--cols) - 1) * var(--gutter)) / var(--cols));

  /* Section spacing alternates between these two so sections do not land on an even beat. */
  --space-a: 72px;
  --space-b: 112px;
  --header-h: 68px;
}

@media (min-width: 700px) {
  :root {
    --cols: 8;
    --margin: 32px;
    --gutter: 24px;
  }
}

@media (min-width: 1024px) {
  :root {
    --cols: 12;
    --margin: 48px;
    --space-a: 112px;
    --space-b: 160px;
    --header-h: 80px;
  }
}

/* ---------- base ---------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-padding-top: var(--header-h);
  -webkit-text-size-adjust: 100%;
}

html:has(dialog[open]) {
  overflow: hidden;
}

body {
  margin: 0;
  font-family: var(--body);
  font-size: var(--size-body);
  line-height: 1.6;
  color: var(--charcoal);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
p,
ul,
ol,
figure,
blockquote {
  margin: 0;
}

ul[role="list"],
ol[role="list"] {
  padding: 0;
  list-style: none;
}

img,
picture {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

a {
  color: inherit;
}

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
}

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: var(--margin);
  top: 8px;
  z-index: 100;
  padding: 12px 16px;
  background: var(--green);
  color: var(--charcoal);
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: none;
}

/* The page grid. Side tracks let a child run to the viewport edge with `full-start` or `full-end`;
   everything else sits on the numbered `col` lines. */
.grid {
  display: grid;
  column-gap: var(--gutter);
  grid-template-columns:
    [full-start] minmax(calc(var(--margin) - var(--gutter)), 1fr)
    [content-start] repeat(var(--cols), [col] minmax(0, var(--col)))
    [content-end] minmax(calc(var(--margin) - var(--gutter)), 1fr)
    [full-end];
}

.grid > * {
  grid-column: content-start / content-end;
}

.label,
.work__label,
.review__by,
.after-dark__caption span {
  font-size: var(--size-label);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.section-title {
  font-family: var(--display);
  font-size: var(--size-heading);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

/* ---------- buttons ---------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 0 24px;
  border: 0;
  font-size: var(--size-label);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  transition: background-color 200ms ease-out, box-shadow 200ms ease-out, transform 120ms ease-out;
}

.button:active {
  transform: scale(0.98);
}

.button--primary {
  background: var(--green);
  color: var(--charcoal);
}

.button--primary:focus-visible {
  outline-color: var(--ivory);
}

.button--dark {
  background: var(--charcoal);
  color: var(--ivory);
}

.button--dark:focus-visible {
  outline-color: var(--charcoal);
}

@media (hover: hover) {
  .button--primary:hover {
    background: var(--ivory);
  }

  .button--dark:hover {
    box-shadow: inset 0 -3px 0 var(--green);
  }
}

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--logo-black);
  color: var(--white);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  max-width: var(--max);
  min-height: var(--header-h);
  margin-inline: auto;
  padding-inline: var(--margin);
  transition: min-height 200ms ease-out;
}

.site-header.is-scrolled .site-header__inner {
  min-height: calc(var(--header-h) - 16px);
}

.brand {
  display: flex;
  align-items: center;
  min-height: 48px;
}

.brand img {
  width: auto;
  height: 40px;
}

/* Without scripting the five links stay in the header as a wrapped row. */
.site-nav {
  order: 5;
  width: 100%;
}

.js .site-nav {
  display: none;
}

.site-nav__list {
  display: flex;
  flex-wrap: wrap;
  gap: 0 24px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav a,
.site-header__call,
.menu-button,
.menu__close {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  font-size: var(--size-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
}

.site-nav a {
  position: relative;
}

.site-nav a[aria-current="true"]::after {
  content: "";
  position: absolute;
  inset: auto 0 10px;
  height: 2px;
  background: var(--green);
}

.site-header__call {
  margin-left: auto;
  padding-inline: 8px;
}

.site-header__cta {
  display: none;
}

.menu-button {
  display: none;
  padding-inline: 16px;
  border: 1px solid var(--ivory-soft);
  background: none;
}

.js .menu-button {
  display: inline-flex;
}

@media (min-width: 1024px) {
  .site-header__inner {
    flex-wrap: nowrap;
    gap: 40px;
  }

  .site-nav,
  .js .site-nav {
    display: block;
    order: 0;
    width: auto;
    margin-left: auto;
  }

  .site-nav__list {
    gap: 32px;
  }

  .site-header__call,
  .js .menu-button {
    display: none;
  }

  .site-header__cta {
    display: inline-flex;
  }

  .site-header.is-scrolled .site-header__cta {
    min-height: 48px;
  }
}

/* ---------- phone and tablet menu ---------- */

.menu {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0 var(--margin) 32px;
  border: 0;
  background: var(--charcoal);
  color: var(--ivory);
}

.menu[open] {
  display: flex;
  flex-direction: column;
}

.menu::backdrop {
  background: var(--charcoal);
}

.menu__bar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  min-height: var(--header-h);
}

.menu__close {
  padding-inline: 16px;
  border: 1px solid var(--ivory-soft);
  background: none;
}

.menu__list {
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.menu__list a {
  display: flex;
  align-items: center;
  min-height: 64px;
  border-bottom: 1px solid var(--ink-soft);
  font-family: var(--display);
  font-size: var(--size-heading);
  font-weight: 700;
  letter-spacing: -0.02em;
  text-decoration: none;
}

.menu__actions {
  display: grid;
  gap: 8px;
  margin-top: auto;
  padding-top: 32px;
}

.menu__phone {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  color: var(--green);
  font-weight: 500;
  text-decoration: none;
}

/* ---------- hero ---------- */

.hero {
  background: var(--charcoal);
  color: var(--ivory);
}

.hero__photo {
  grid-column: full-start / full-end;
}

.hero__photo img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

.hero__panel {
  padding: 32px 0 56px;
}

.hero__title {
  font-family: var(--display);
  font-size: var(--size-display-xl);
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: -0.03em;
}

.hero__line {
  display: block;
}

.hero__statement {
  max-width: 34ch;
  margin-top: 20px;
  font-size: var(--size-body-l);
  line-height: 1.5;
  color: var(--ivory-soft);
}

.hero__actions {
  display: grid;
  gap: 4px;
  margin-top: 28px;
}

.hero__call {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  font-weight: 500;
  text-underline-offset: 4px;
}

/* Spanish is spoken: said once, quietly, below the actions. Information, not a control. */
.hero__badge {
  display: inline-flex;
  margin-top: 16px;
  padding: 6px 14px;
  border: 1px solid var(--green);
  font-size: var(--size-label);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.04em;
  color: var(--ivory);
}

@media (min-width: 700px) {
  .hero__photo img {
    aspect-ratio: 3 / 2;
  }

  .hero__panel {
    padding: 48px 0 72px;
  }

  .hero__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 28px;
  }
}

@media (min-width: 1024px) {
  /* The photograph holds the right eight columns and runs off the right edge. The text panel
     is charcoal and overlaps the photograph by one column, so no text sits on the photograph. */
  .hero__photo {
    position: relative;
    grid-column: col 5 / full-end;
    grid-row: 1;
  }

  /* Holds the 4:3 shape. The photograph itself stretches with the row, so it always reaches
     the bottom of the section, even where the panel is taller. */
  .hero__photo::before {
    content: "";
    display: block;
    aspect-ratio: 4 / 3;
    max-height: calc(100svh - var(--header-h));
  }

  .hero__photo img {
    position: absolute;
    inset: 0;
    height: 100%;
    aspect-ratio: auto;
  }

  .hero__panel {
    grid-column: content-start / col 6;
    grid-row: 1;
    align-self: end;
    z-index: 1;
    padding: 24px 24px 32px 0;
    background: var(--charcoal);
  }
}

@media (min-width: 1280px) {
  .hero__panel {
    padding: 40px 32px 56px 0;
  }
}

/* ---------- credibility ---------- */

.credibility {
  padding-block: var(--space-a) var(--space-b);
  background: var(--ivory);
}

.credibility__lines {
  row-gap: 20px;
}

.credibility__line {
  display: flex;
  align-items: center;
  gap: 12px;
  grid-column: full-start / content-end;
  font-family: var(--display);
  font-size: var(--size-display-l);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.025em;
}

/* A hairline from the left page edge to the start of each line. */
.credibility__line::before {
  content: "";
  flex: 0 0 calc(var(--margin) + var(--indent, 0px) - 12px);
  height: 1px;
  background: var(--ink-soft);
}

.credibility__line:nth-child(2) {
  --indent: 20px;
}

.credibility__line:nth-child(3) {
  --indent: 40px;
}

.credibility__sentence {
  max-width: 30ch;
  margin-top: 40px;
}

@media (min-width: 700px) {
  .credibility__lines {
    row-gap: 28px;
  }

  .credibility__line {
    display: grid;
    grid-template-columns: subgrid;
    grid-column: full-start / full-end;
    --start: col 1;
  }

  .credibility__line::before {
    grid-column: full-start / var(--start);
  }

  .credibility__line span {
    grid-column: var(--start) / content-end;
  }

  .credibility__line:nth-child(2) {
    --start: col 2;
  }

  .credibility__line:nth-child(3) {
    --start: col 3;
  }
}

@media (min-width: 1024px) {
  .credibility__line:nth-child(2) {
    --start: col 3;
  }

  .credibility__line:nth-child(3) {
    --start: col 5;
  }

  .credibility__sentence {
    grid-column: col 9 / content-end;
    margin-top: 64px;
  }
}

/* ---------- services ---------- */

.services {
  padding-block: var(--space-b) var(--space-a);
  background: var(--white);
}

.services__title {
  margin-bottom: 48px;
}

.services__frame {
  display: none;
}

.services__list {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: full-start / full-end;
  --inset-from: col 2;
  --inset-to: col 4;
}

/* Phone and tablet: every block opens with a hairline, the number and the name on the left
   margin. The image then changes shape, side and spacing from block to block. */
.service {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: full-start / full-end;
  margin-bottom: 72px;
}

.service:last-child {
  margin-bottom: 0;
}

.service > * {
  grid-column: content-start / content-end;
}

.service__head {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--ink-soft);
}

.service__number,
.step__number {
  font-family: var(--display);
  font-size: var(--size-numeral);
  font-weight: 500;
  line-height: 0.9;
  letter-spacing: -0.04em;
}

.service__name,
.step__name {
  font-family: var(--display);
  font-size: var(--size-title);
  font-weight: 700;
  line-height: 1.2;
}

.service__media {
  margin-top: 20px;
}

.service__media img {
  width: 100%;
  object-fit: cover;
}

.service--edge > .service__media,
.service--band > .service__media {
  grid-column: full-start / full-end;
}

.service--edge .service__media img {
  aspect-ratio: 3 / 2;
}

.service--wide .service__media img {
  aspect-ratio: 16 / 9;
}

.service--inset-left,
.service--inset-right {
  margin-bottom: 48px;
}

.service--inset-left > .service__media {
  grid-column: var(--inset-from) / full-end;
}

.service--inset-right > .service__media {
  grid-column: full-start / var(--inset-to);
}

.service--inset-left .service__media img,
.service--inset-right .service__media img {
  aspect-ratio: 4 / 5;
}

/* Irrigation: a short band, edge to edge. */
.service--band .service__media img {
  aspect-ratio: 2 / 1;
}

/* Two irrigation photographs in one place. The second lies over the first and fades in and out
   (the script decides when); the first never fades, so the dark ground cannot show between them.
   Without scripting, or with reduced motion, the first stays. The second has an empty alt, so
   the pair has one description, the first photograph's, and nothing is announced as they change. */
.service__media.crossfade {
  position: relative;
}

.crossfade__image {
  display: block;
  height: 100%;
}

.crossfade__image + .crossfade__image {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 700ms ease-in-out;
}

.crossfade.is-alternate .crossfade__image + .crossfade__image {
  opacity: 1;
}

.service__text {
  max-width: 34ch;
  margin-top: 16px;
}

@media (min-width: 700px) {
  .services__list {
    --inset-from: col 3;
    --inset-to: col 7;
  }
}

@media (min-width: 1024px) {
  .services__list {
    display: block;
    grid-column: content-start / content-end;
  }

  /* Without scripting each row shows its own photograph beside it. */
  .service {
    position: relative;
    grid-template-columns: minmax(0, 2fr) minmax(0, 5fr) minmax(0, 4fr);
    grid-template-rows: auto 1fr;
    column-gap: var(--gutter);
    align-items: start;
    margin: 0;
    padding: 40px 0;
    border-top: 1px solid var(--ink-soft);
  }

  .service:last-child {
    border-bottom: 1px solid var(--ink-soft);
  }

  .service > * {
    grid-column: auto;
  }

  .service__head {
    display: contents;
  }

  .service__number {
    grid-column: 1;
    grid-row: 1 / span 2;
  }

  .service > .service__head > .service__name,
  .service > .service__text {
    grid-column: 2;
  }

  .service > .service__media {
    grid-column: 3;
    grid-row: 1 / span 2;
    margin-top: 0;
  }

  .service .service__media img {
    aspect-ratio: 3 / 2;
  }

  .service__text {
    margin-top: 12px;
  }

  /* With scripting: one fixed frame on the left shows the active service. */
  .js .services__frame {
    display: block;
    position: sticky;
    top: calc(var(--header-h) + 32px);
    grid-column: col 1 / span 4;
    grid-row: 2;
    align-self: start;
    aspect-ratio: 4 / 5;
    overflow: hidden;
    background: var(--charcoal);
  }

  .services__slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    transform: scale(1.03);
    transition: opacity 450ms var(--ease), transform 450ms var(--ease);
  }

  .services__slide.is-active {
    opacity: 1;
    transform: none;
  }

  .services__slide img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .js .services__list {
    grid-column: col 6 / content-end;
    grid-row: 2;
  }

  .js .service {
    grid-template-columns: minmax(0, 2fr) minmax(0, 5fr);
  }

  .js .service > .service__media {
    display: none;
  }

  .js .service::before {
    content: "";
    position: absolute;
    inset: -1px 0 auto;
    height: 2px;
    background: var(--green);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 220ms ease-out;
  }

  .js .service.is-active::before {
    transform: scaleX(1);
  }

  .js .service__name {
    transition: transform 220ms ease-out;
  }

  .js .service.is-active .service__name {
    transform: translateX(8px);
  }
}

/* ---------- selected work ---------- */

.work {
  padding-block: var(--space-a) var(--space-b);
  background: var(--ivory);
}

.work__title {
  margin-bottom: 40px;
}

/* One row of photographs, every one in the same 5:4 frame. Without scripting it is a row the
   visitor scrolls. With scripting (.is-carousel) it moves slowly to the right and loops; the
   script copies the photographs once for the loop and hides the copies from assistive technology. */
.work__carousel {
  --item: min(78vw, 360px);
}

.work__viewport {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.work__track {
  display: flex;
  gap: var(--gutter);
  width: max-content;
  margin: 0;
  padding: 0 var(--margin);
  list-style: none;
}

.work__item {
  flex: 0 0 var(--item);
}

.work__figure {
  margin: 0;
}

.work__open {
  display: block;
  aspect-ratio: 5 / 4;
  overflow: hidden;
}

.work__open:focus-visible {
  outline-color: var(--charcoal);
  outline-offset: -2px;
}

.work__open picture {
  display: block;
  height: 100%;
}

.work__open img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
  transition: transform 600ms ease-out;
}

/* Where each portrait keeps its subject inside the 5:4 frame. */
.work__figure--2 {
  --focus: 50% 45%;
}

.work__figure--3 {
  --focus: 50% 62%;
}

.work__figure--6 {
  --focus: 50% 62%;
}

@media (hover: hover) {
  .work__open:hover img {
    transform: scale(1.02);
  }
}

.work__label {
  margin-top: 12px;
  color: var(--ink-soft);
}

.is-carousel .work__viewport {
  overflow: hidden;
  touch-action: pan-y;
  user-select: none;
}

.is-carousel .work__track {
  padding: 0;
  will-change: transform;
}

.is-carousel .work__open,
.is-carousel .work__open img {
  -webkit-user-drag: none;
}

.work__controls {
  margin-top: 24px;
}

.work__toggle {
  grid-column: content-start / content-end;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--charcoal);
  background: transparent;
  color: var(--charcoal);
  font: inherit;
  font-size: var(--size-label);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: box-shadow 200ms ease-out;
}

.work__toggle[hidden] {
  display: none;
}

/* Two bars while moving (press to pause), a triangle while paused (press to play). */
.work__toggle::before {
  content: "";
  width: 10px;
  height: 12px;
  border-inline: 3px solid currentColor;
  box-sizing: border-box;
}

.work__toggle[data-paused]::before {
  width: 0;
  height: 0;
  border-block: 6px solid transparent;
  border-inline: 10px solid currentColor;
  border-inline-end: 0;
}

.work__toggle:focus-visible {
  outline-color: var(--charcoal);
}

@media (hover: hover) {
  .work__toggle:hover {
    box-shadow: inset 0 -3px 0 var(--green);
  }
}

@media (min-width: 700px) {
  .work__carousel {
    --item: min(44vw, 420px);
  }
}

@media (min-width: 1024px) {
  .work__title {
    margin-bottom: 64px;
  }

  .work__carousel {
    --item: clamp(320px, 30vw, 460px);
  }

  .work__controls {
    margin-top: 32px;
  }
}

/* ---------- after dark ---------- */

.after-dark {
  padding-block: 72px;
  background: var(--charcoal);
  color: var(--ivory);
}

.after-dark__figure img {
  width: 100%;
}

.after-dark__caption {
  margin-top: 16px;
  color: var(--ivory-soft);
}

@media (min-width: 1024px) {
  .after-dark {
    padding-block: 112px;
  }
}

/* ---------- process ---------- */

.process {
  padding-block: var(--space-b) var(--space-a);
  background: var(--white);
}

/* Phone: one vertical line down the left edge with the numerals on it. */
.process__steps {
  margin-top: 40px;
  border-left: 1px solid var(--ink-soft);
}

.step {
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr);
  margin-left: -1px;
  padding: 0 0 40px 20px;
  border-left: 2px solid transparent;
}

.step:first-child {
  border-left-color: var(--green);
}

.step:last-child {
  padding-bottom: 0;
}

.step__number {
  color: var(--ink-soft);
}

.step__body p {
  max-width: 30ch;
  margin-top: 8px;
}

@media (min-width: 700px) {
  /* One horizontal rule with a numeral above each step. */
  .process__steps {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    margin-top: 56px;
    border-left: 0;
  }

  .step {
    display: block;
    margin: 0;
    padding: 0;
    border-left: 0;
  }

  .step__number {
    display: block;
    padding-bottom: 20px;
  }

  .step__body {
    height: 100%;
    padding: 20px 24px 0 0;
    border-top: 1px solid var(--ink-soft);
  }

  .step:first-child .step__body {
    margin-top: -1px;
    border-top: 2px solid var(--green);
  }
}

@media (min-width: 1024px) {
  .process__title {
    grid-column: col 1 / col 5;
  }

  .process__steps {
    grid-column: col 5 / content-end;
    margin-top: 0;
  }
}

/* ---------- reviews ---------- */

.reviews {
  padding-block: var(--space-a) var(--space-b);
  background: var(--ivory);
}

.reviews__title {
  margin-bottom: 32px;
  color: var(--ink-soft);
}

.review blockquote p + p {
  margin-top: 1em;
}

.review--featured blockquote {
  font-family: var(--display);
  font-size: var(--size-heading);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.review--second,
.review--third {
  margin-top: 48px;
  font-size: var(--size-body-l);
  line-height: 1.5;
}

.review__by {
  margin-top: 24px;
  padding-top: 12px;
  border-top: 1px solid var(--ink-soft);
}

/* The way to every review: R&R's own Google listing, in a new tab. A text link, not a button. */
.reviews__more {
  margin-top: 48px;
}

.reviews__more a {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  font-weight: 500;
  text-underline-offset: 4px;
}

@media (min-width: 700px) {
  .review--second {
    grid-column: col 1 / col 5;
  }

  .review--third {
    grid-column: col 5 / content-end;
  }

  .review--second,
  .review--third,
  .reviews__more {
    margin-top: 72px;
  }
}

@media (min-width: 1024px) {
  /* The two supporting reviews start at column 5, so the block steps to the right. */
  .review--featured {
    grid-column: col 1 / col 9;
  }

  .review--second {
    grid-column: col 5 / col 9;
  }

  .review--third {
    grid-column: col 9 / content-end;
  }

  .reviews__more {
    grid-column: col 5 / content-end;
  }
}

/* ---------- contact ---------- */

.contact {
  background: var(--charcoal);
  color: var(--ivory);
}

.contact__inner {
  align-content: space-between;
  row-gap: 56px;
  min-height: 80svh;
  padding-block: var(--space-b) var(--space-a);
}

.contact__intro p {
  max-width: 30ch;
  margin-top: 16px;
  font-size: var(--size-body-l);
  line-height: 1.5;
  color: var(--ivory-soft);
}

.contact__details {
  padding-top: 32px;
  border-top: 1px solid var(--ivory-soft);
  font-style: normal;
}

.contact__phone,
.contact__email {
  display: flex;
  align-items: center;
  width: fit-content;
  min-height: 48px;
  text-decoration: none;
}

.contact__phone {
  color: var(--green);
  font-family: var(--display);
  font-size: var(--size-display-l);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.025em;
  white-space: nowrap;
}

.contact__email {
  margin-top: 12px;
  font-family: var(--display);
  font-size: var(--size-title);
  font-weight: 700;
  line-height: 1.2;
}

.contact__phone:focus-visible,
.contact__email:focus-visible {
  outline-color: var(--ivory);
  outline-offset: 4px;
}

@media (hover: hover) {
  .contact__phone:hover,
  .contact__email:hover {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 6px;
  }
}

.contact__city {
  margin-top: 8px;
  color: var(--ivory-soft);
}

/* Estimate form. It needs scripting for the spam check, so without it the page shows the
   call-or-email note instead. Square corners and existing tokens only. */
.estimate {
  display: none;
  color-scheme: dark;
}

.js .estimate {
  display: block;
}

.js .estimate-nojs {
  display: none;
}

.estimate-nojs {
  max-width: 40ch;
  color: var(--ivory-soft);
}

.estimate__form {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px var(--gutter);
}

/* After a successful send the confirmation replaces the form. */
.estimate__form[hidden] {
  display: none;
}

.estimate__hint,
.estimate__note {
  color: var(--ivory-soft);
  font-size: 0.9375rem;
  line-height: 1.5;
}

.estimate__note a {
  color: var(--ivory);
  text-underline-offset: 3px;
}

/* Spam trap: never shown. People leave it empty; many bots fill it in. */
.estimate__trap {
  display: none;
}

.field {
  display: grid;
  gap: 8px;
  align-content: start;
}

.field__label {
  font-size: var(--size-label);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ivory);
}

.field__label span {
  color: var(--ivory-soft);
  text-transform: none;
  letter-spacing: 0;
}

.field__input {
  width: 100%;
  min-height: 52px;
  padding: 12px 14px;
  border: 1px solid var(--ivory-soft);
  border-radius: 0;
  background: transparent;
  color: var(--ivory);
  font: inherit;
  font-size: var(--size-body);
  line-height: 1.4;
}

.field__input--area {
  min-height: 140px;
  resize: vertical;
}

/* The open list of a select is drawn by the browser, often on a light ground whatever the
   field looks like, and the options would inherit the field's ivory text. They get charcoal
   on ivory everywhere; "Choose a service" is the softer ink. The closed field keeps the form's
   own colours. Phones use their native picker, which keeps its own readable colours. */
.field__input option {
  background-color: var(--ivory);
  color: var(--charcoal);
}

.field__input option[value=""] {
  color: var(--ink-soft);
}

.field__input:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
  border-color: var(--ivory);
}

.field__input[aria-invalid="true"] {
  border: 2px solid var(--ivory);
}

.field__error,
.estimate__failure {
  color: var(--ivory);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.4;
}

.field__error::before,
.estimate__failure::before {
  content: "\2014\00a0";
  color: var(--green);
}

.estimate__failure a,
.estimate__done a {
  color: var(--ivory);
  text-underline-offset: 3px;
}

.estimate__failure a[href^="tel:"],
.estimate__done a[href^="tel:"] {
  white-space: nowrap;
}

.estimate__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 24px;
}

.estimate__actions .button[aria-busy="true"] {
  cursor: progress;
  opacity: 0.75;
}

.estimate__done {
  padding-top: 24px;
  border-top: 1px solid var(--green);
  font-size: var(--size-body-l);
  line-height: 1.5;
  color: var(--ivory-soft);
}

.estimate__done:focus {
  outline: none;
}

.estimate__done-title {
  margin-bottom: 8px;
  font-family: var(--display);
  font-size: var(--size-title);
  font-weight: 700;
  color: var(--ivory);
}

@media (min-width: 700px) {
  .estimate__form {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .field--full {
    grid-column: 1 / -1;
  }

  .estimate__hint {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1024px) {
  .contact__intro {
    grid-column: col 1 / col 6;
  }

  .estimate,
  .estimate-nojs {
    grid-column: col 7 / content-end;
    grid-row: 1;
  }

  .contact__details {
    display: grid;
    grid-template-columns: subgrid;
  }

  .contact__details > * {
    grid-column: 6 / -1;
  }
}

/* ---------- footer ---------- */

.site-footer {
  padding-block: 48px 32px;
  background: var(--logo-black);
  color: var(--white);
}

.site-footer__inner {
  row-gap: 24px;
}

.site-footer__logo img {
  width: auto;
  height: 96px;
}

.site-footer__links a {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  font-size: var(--size-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
}

@media (hover: hover) {
  .site-footer__links a:hover {
    text-decoration: underline;
    text-underline-offset: 4px;
  }
}

.site-footer__line {
  font-size: var(--size-label);
  color: var(--ivory-soft);
}

/* The studio credit: the last line of every page, centred under a hairline. */
.site-footer__credit {
  padding-top: 12px;
  border-top: 1px solid var(--ink-soft);
  font-size: var(--size-label);
  color: var(--ivory-soft);
  text-align: center;
}

.site-footer__credit a {
  display: inline-block;
  padding-block: 12px;
  color: var(--ivory);
  text-underline-offset: 3px;
}

.site-footer__credit a:focus-visible {
  outline-color: var(--ivory);
}

@media (min-width: 1024px) {
  .site-footer__inner {
    align-items: center;
  }

  .site-footer__logo {
    grid-column: col 1 / col 5;
  }

  .site-footer__links {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0 32px;
    grid-column: col 5 / content-end;
    grid-row: 1;
  }
}

/* ---------- phone and tablet estimate bar ---------- */

/* Below 1024px the header has no estimate button, so a bar fixed to the bottom of the screen
   carries one. It needs scripting, which hides it while the hero's own button or the contact
   section is on screen: it never doubles that button and never sits over the form. */
.sticky-cta {
  display: none;
}

@media (max-width: 1023px) {
  :root {
    --cta-space: calc(76px + env(safe-area-inset-bottom, 0px));
  }

  .js .sticky-cta {
    display: block;
    position: fixed;
    inset: auto 0 0;
    z-index: 40;
    padding: 12px max(var(--margin), env(safe-area-inset-right, 0px)) max(12px, env(safe-area-inset-bottom, 0px)) max(var(--margin), env(safe-area-inset-left, 0px));
    border-top: 1px solid var(--ink-soft);
    background: var(--logo-black);
    transition: transform 240ms var(--ease), visibility 240ms;
  }

  .js .sticky-cta.is-hidden {
    transform: translateY(100%);
    visibility: hidden;
  }

  .sticky-cta__button {
    display: flex;
    width: 100%;
    max-width: 560px;
    margin-inline: auto;
  }

  /* The page ends above the bar, and keyboard focus scrolls controls clear of it. */
  .js .site-footer {
    padding-bottom: calc(32px + var(--cta-space));
  }

  .js {
    scroll-padding-bottom: var(--cta-space);
  }
}

/* ---------- enlarged view for Selected Work ---------- */

.lightbox {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 16px;
  border: 0;
  background: var(--charcoal);
  color: var(--ivory);
}

.lightbox[open] {
  display: grid;
  grid-template:
    "close close" auto
    "image image" minmax(0, 1fr)
    "caption caption" auto
    "previous next" auto / 1fr 1fr;
  gap: 12px;
}

.lightbox::backdrop {
  background: var(--charcoal);
}

.lightbox__close,
.lightbox__step {
  min-width: 48px;
  min-height: 48px;
  padding: 0 16px;
  border: 1px solid var(--ivory-soft);
  background: none;
  font-size: var(--size-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.lightbox__close {
  grid-area: close;
  justify-self: end;
}

.lightbox__image {
  grid-area: image;
  place-self: center;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 100%;
  min-height: 0;
  object-fit: contain;
  transition: opacity 200ms ease-out;
}

.lightbox__image.is-changing {
  opacity: 0;
}

.lightbox__caption {
  grid-area: caption;
  text-align: center;
  font-size: var(--size-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.lightbox__step[data-lightbox-previous] {
  grid-area: previous;
  justify-self: start;
}

.lightbox__step[data-lightbox-next] {
  grid-area: next;
  justify-self: end;
}

@media (min-width: 1024px) {
  .lightbox {
    padding: 24px;
  }

  .lightbox[open] {
    grid-template:
      ". . close" auto
      "previous image next" minmax(0, 1fr)
      ". caption ." auto / auto minmax(0, 1fr) auto;
    column-gap: 24px;
  }

  .lightbox__step {
    align-self: center;
  }
}

/* ---------- legal pages ---------- */

.legal {
  padding-block: var(--space-a);
}

.legal__body {
  max-width: 62ch;
}

.legal__body h1 {
  font-family: var(--display);
  font-size: var(--size-heading);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.legal__body h2 {
  margin-top: 32px;
  font-family: var(--display);
  font-size: var(--size-title);
  font-weight: 700;
  line-height: 1.2;
}

.legal__body p,
.legal__body ul {
  margin-top: 12px;
}

.legal__body ul {
  padding-left: 1.25em;
}

.legal__body li + li {
  margin-top: 6px;
}

.legal__body .legal__effective {
  margin-top: 16px;
}

.legal__body .button {
  margin-top: 40px;
}

.legal__body a:not(.button) {
  text-underline-offset: 4px;
}

/* ---------- motion ---------- */

@keyframes line-rise {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
}

@keyframes settle {
  from {
    transform: scale(0.98);
  }
}

@keyframes link-rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }

  .hero__line {
    animation: line-rise 700ms var(--ease) backwards;
  }

  .hero__line:nth-child(2) {
    animation-delay: 80ms;
  }

  .hero__line:nth-child(3) {
    animation-delay: 160ms;
  }

  /* Hidden only when scripting has confirmed it can reveal: see the script in the page head. */
  .reveal [data-reveal] {
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 600ms var(--ease), transform 600ms var(--ease);
  }

  .reveal [data-reveal].is-visible {
    opacity: 1;
    transform: none;
  }

  .menu[open] {
    animation: fade-in 280ms ease-out;
  }

  .menu[open] .menu__list a {
    animation: link-rise 280ms ease-out backwards;
  }

  .lightbox[open] {
    animation: fade-in 240ms ease-out;
  }

  .lightbox[open] .lightbox__image {
    animation: settle 240ms ease-out;
  }
}

@media (prefers-reduced-motion: no-preference) and (min-width: 700px) {
  .reveal [data-reveal] {
    transform: translateY(12px);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }

  .button:active,
  .work__open:hover img,
  .services__slide {
    transform: none;
  }
}
