/* ===========================================================================
   HOOME. DIRECT MAIL LANDING PAGE
   ---------------------------------------------------------------------------
   Structure of this file
     1.  Tokens
     2.  Reset & base
     3.  Typographic scale
     4.  Document rail
     5.  Reveal motion system
     6.  Section 01. The reveal
     7.  Section 01b. Introduction
     8.  Section 02. Recognition
     9.  Section 03. Closing the loop
    10.  Section 04. Proof
    11.  Section 05. The invitation
    12.  Reduced motion

   Design rules this file holds to, deliberately:
     • Two colours do the work. Ivory paper, black envelope. Green and tan
       appear a handful of times each, and nowhere else.
     • No gradients, no shadows, no border-radius above 0. The only soft
       edge on the page is the mask over the photograph.
     • Nothing is in a card. Hierarchy comes from size, weight, and space.
     • Mobile-first: every size below is written for a phone, then widened.
   =========================================================================== */


/* 1. TOKENS ---------------------------------------------------------------
   Colours are taken verbatim from the Hoome Brand Guidelines (p.14–15).
   Do not add to this list without a guideline reference.                    */

:root {
  /* Brand */
  --ivory:  #F6F5F2;   /* Primary White  */
  --black:  #151515;   /* Primary Black  */
  --green:  #334737;   /* Primary Green  */
  --blue:   #193741;   /* Accent Blue    */
  --tan:    #C1A26C;   /* Accent Tan     */
  --brown:  #7C5C3C;   /* Accent Brown   */

  /* Neutrals */
  --n100: #DAD6CE;
  --n300: #BEB9B3;
  --n400: #8F8C89;
  --n500: #555555;

  /* Contextual: reassigned inside dark panels */
  --paper: var(--ivory);
  --ink:   var(--black);
  --quiet: var(--n400);
  --rule:  rgba(21, 21, 21, .15);

  /* Rhythm. One scale, used everywhere. */
  --gutter:  clamp(1.5rem, 6vw, 6rem);
  --section: clamp(6rem, 16vw, 13rem);
  --measure: 34em;

  /* Motion */
  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* Dark panels swap the contextual tokens rather than overriding every rule. */
.panel--dark {
  --paper: var(--black);
  --ink:   var(--ivory);
  --quiet: rgba(246, 245, 242, .52);
  --rule:  rgba(246, 245, 242, .18);
  background: var(--paper);
  color: var(--ink);
}


/* 2. RESET & BASE --------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ivory);
  color: var(--black);
  font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, p, figure, blockquote, ol, ul { margin: 0; padding: 0; }
ol, ul { list-style: none; }
img, svg { display: block; max-width: 100%; }
em { font-style: normal; color: var(--green); }

a { color: inherit; }

::selection { background: var(--green); color: var(--ivory); }

:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 4px;
}
.panel--dark :focus-visible { outline-color: var(--tan); }

/* Every section is a full-width band; `.wrap` holds the measure inside it. */
.wrap {
  width: 100%;
  max-width: 76rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Paper grain. Printed matter, not a screen. Dark panels only, barely there. */
.panel--dark::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .05;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
}
.panel--dark { position: relative; }


/* 3. TYPOGRAPHIC SCALE ----------------------------------------------------
   Four sizes and one eyebrow. The Brand Guidelines set headlines at
   80px/80px, line-height equal to font-size, so the display sizes below
   all sit at or just under 1.                                              */

.display-xl {
  font-size: clamp(2.6rem, 10.5vw, 7rem);
  line-height: .94;
  font-weight: 700;
  letter-spacing: -.035em;
  text-wrap: balance;
}

.display-l {
  font-size: clamp(2rem, 7vw, 4.25rem);
  line-height: 1;
  font-weight: 700;
  letter-spacing: -.03em;
  text-wrap: balance;
}

.display-m {
  font-size: clamp(1.5rem, 4.4vw, 2.6rem);
  line-height: 1.12;
  font-weight: 600;
  letter-spacing: -.02em;
  text-wrap: balance;
}

.lede {
  font-size: clamp(1.02rem, 1.9vw, 1.25rem);
  line-height: 1.55;
  font-weight: 400;
  color: var(--n500);
  max-width: var(--measure);
}
.panel--dark .lede { color: var(--quiet); }

.eyebrow {
  font-size: .6875rem;             /* 11px */
  line-height: 1.4;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--quiet);
}

.muted { color: var(--quiet); }


/* 4. DOCUMENT RAIL --------------------------------------------------------
   Behaves like the running head of a printed report. `.rail--light` is
   applied by script.js whenever a dark section is under it.                */

.rail {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.15rem var(--gutter);
  color: var(--black);
  transition: color .45s var(--ease), transform .45s var(--ease);
  pointer-events: none;                /* only the mark is clickable */
}
.rail--light { color: var(--ivory); }

/* The rail has no background. It sits directly on the page like a running
   head, so it has to get out of the way while the reader is moving forward.
   It lifts on scroll down and returns the moment they scroll back. */
.rail--away { transform: translate3d(0, -110%, 0); }

.rail__mark { pointer-events: auto; display: block; }
.rail__mark img {
  width: 78px;
  height: auto;
  /* The wordmark is a currentColor SVG; as an <img> it renders black, so we
     invert it rather than swap files. Replace with an <object> or inline SVG
     if you would rather keep it as true currentColor. */
  filter: none;
  transition: filter .45s var(--ease);
}
.rail--light .rail__mark img { filter: invert(1) brightness(1.12); }

.rail__for {
  text-align: right;
  /* Long builder names wrap to a second line rather than crowding the mark.
     Two lines of 10px still sit inside the rail's height. */
  max-width: 58%;
  font-size: .625rem;                  /* 10px, intentionally quiet */
  line-height: 1.35;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.rail__for-label { display: block; opacity: .5; }
.rail__for-name  { display: block; font-weight: 600; }


/* 5. REVEAL MOTION SYSTEM -------------------------------------------------
   One transition, used for everything that reveals on scroll: 12px up and
   a fade. Nothing scales, nothing slides sideways, nothing bounces.
   Rules are scoped to `.js` so content is never hidden if the script fails. */

.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 12px, 0);
  transition: opacity .8s var(--ease), transform .8s var(--ease);
}
.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
}
.js [data-reveal-delay="1"] { transition-delay: .10s; }
.js [data-reveal-delay="2"] { transition-delay: .20s; }


/* 6. SECTION 01. THE REVEAL ---------------------------------------------
   The card that was in the envelope, at the size it was in the envelope,
   opening out into the page.                                              */

.reveal {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 7rem var(--gutter) 5rem;
  overflow: hidden;
}

/* The A6 frame. 30 × 42 in a 100 × 100 box is the proportion of the card. */
.reveal__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: var(--ivory);
  opacity: .5;
}
.js .reveal__frame rect {
  animation: card-open 1200ms 250ms var(--ease) forwards;
}

@keyframes card-open {
  from { x: 35; y: 29; width: 30; height: 42; opacity: .55; }
  to   { x: 0;  y: 0;  width: 100; height: 100; opacity: 0; }
}

/* No max-width here. `ch` on a wrapper resolves against the wrapper's own
   16px font, not the 112px headline inside it, which throttles the headline
   to a fraction of the width it should have. Measure is set on the type. */
.reveal__inner {
  position: relative;
  z-index: 1;
}

.reveal__eyebrow { margin-bottom: 1.6rem; color: var(--tan); }

/* The line breaks in this headline are art direction, not accident, so the
   balancer is switched off here and the <br>s are left to do their job. */
.reveal__line    { margin-bottom: 2.4rem; text-wrap: wrap; }
.reveal__beat    { font-weight: 400; color: var(--quiet); }

/* The opening is timed, not scrolled. They have just scanned a code and are
   holding the phone. Each line arrives, then a beat, then the last line. */
.js .reveal__eyebrow,
.js .reveal__line,
.js .reveal__beat,
.js .reveal__cue {
  opacity: 0;
  animation: rise 900ms var(--ease) forwards;
}
.js .reveal__eyebrow { animation-delay: 800ms; }
.js .reveal__line    { animation-delay: 1050ms; }
.js .reveal__beat    { animation-delay: 1950ms; }
.js .reveal__cue     { animation-delay: 2700ms; }

@keyframes rise {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

.reveal__cue {
  position: relative;
  z-index: 1;
  margin-top: auto;
  padding-top: 4rem;
  font-size: .625rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--quiet);
}
.reveal__cue::after {
  content: "";
  display: block;
  width: 1px;
  height: 2.5rem;
  margin-top: .75rem;
  background: currentColor;
  transform-origin: top;
  animation: drop 2.6s var(--ease) infinite;
}
@keyframes drop {
  0%, 100% { transform: scaleY(.25); opacity: .35; }
  45%      { transform: scaleY(1);   opacity: .9; }
}


/* 7. SECTION 01b. INTRODUCTION ------------------------------------------ */

.intro {
  padding: var(--section) 0;
}
.intro__note { margin-top: 2.5rem; }

@media (min-width: 60em) {
  .intro .display-l { max-width: 17ch; }
}


/* 8. SECTION 02. RECOGNITION --------------------------------------------
   An index of problems. Hairlines and numbers, no containers.             */

.recognition { padding: var(--section) 0; }

.recognition__head { margin-top: 1.5rem; }

/* The per builder observation. Body scale, never headline scale, and indented
   to the same column as the numbered list below it from 48em up. It is hidden
   in the markup and only revealed when script.js has copy for this builder,
   so an empty insight leaves no trace. */
.insight {
  margin-top: clamp(2rem, 5vw, 2.75rem);
  max-width: 54ch;
  font-size: clamp(1.02rem, 1.9vw, 1.15rem);
  line-height: 1.62;
  color: var(--n500);
}
.insight[hidden] { display: none; }

.pressures { margin-top: clamp(3rem, 8vw, 5.5rem); }

.pressure {
  display: grid;
  grid-template-columns: 2.75rem 1fr;
  gap: .5rem;
  padding: 1.5rem 0;
  border-top: 1px solid var(--rule);
}
.pressure:last-child { border-bottom: 1px solid var(--rule); }

.pressure__num {
  font-size: .625rem;
  letter-spacing: .14em;
  color: var(--n300);
  padding-top: .65em;
  font-variant-numeric: tabular-nums;
}

.pressure__text {
  font-size: clamp(1.2rem, 4.4vw, 1.9rem);
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: -.02em;
  max-width: 26ch;
}

/* The pivot of the whole page: the problem is named, then answered. It is
   allowed to be the largest type in this section. */
.verdict { margin-top: clamp(4rem, 11vw, 8rem); }
.verdict .display-m { font-size: clamp(1.55rem, 4.6vw, 3.3rem); }
.verdict__turn {
  margin-top: .6em;
  color: var(--green);
}

@media (min-width: 48em) {
  .pressure { grid-template-columns: 5rem 1fr; padding: 2rem 0; }
  .verdict  { padding-left: 5rem; }
  .insight  { padding-left: 5rem; }
}


/* 9. SECTION 03. CLOSING THE LOOP ---------------------------------------
   The diagram is the brandmark's geometry at scale. Four arcs are the loop
   that already exists in the business; the fifth is drawn in green because
   the fifth is what Hoome sells.                                          */

.loop {
  padding: var(--section) 0;
  border-top: 1px solid var(--rule);
}

.loop__head { margin: 1.25rem 0 2rem; max-width: 18ch; }
.loop__copy .lede + .lede { margin-top: 1.25rem; }

/* On a phone the diagram is the hero of this section, so it is allowed to
   break out of the gutter and use the full width of the screen. */
.loop__figure {
  margin-top: clamp(3.5rem, 10vw, 5rem);
  margin-inline: calc(var(--gutter) * -.75);
}

.loop__svg { width: 100%; height: auto; }

.loop__arc {
  fill: none;
  stroke: rgba(21, 21, 21, .22);
  stroke-width: 1.25;
}
.loop__return {
  fill: none;
  stroke: var(--green);
  stroke-width: 4;
  stroke-linecap: round;
}

.loop__node {
  fill: var(--ivory);
  stroke: var(--black);
  stroke-width: 1.75;
}

.loop__labels text {
  font-size: 18px;
  font-weight: 500;
  letter-spacing: -.005em;
  fill: var(--black);
}

.loop__return-label {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  fill: var(--green);
}

.loop__travel { fill: var(--green); }

/* Draw-on. Each 72° segment is 2πr/5 = 175.9 units long. */
.js .loop__arc,
.js .loop__return { stroke-dasharray: 176; stroke-dashoffset: 176; }
.js .loop__nodes circle,
.js .loop__labels text,
.js .loop__return-label,
.js .loop__travel { opacity: 0; }

.js [data-loop].is-drawn .loop__arc {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset .55s var(--ease);
}
.js [data-loop].is-drawn .loop__arc:nth-child(1) { transition-delay: .05s; }
.js [data-loop].is-drawn .loop__arc:nth-child(2) { transition-delay: .35s; }
.js [data-loop].is-drawn .loop__arc:nth-child(3) { transition-delay: .65s; }
.js [data-loop].is-drawn .loop__arc:nth-child(4) { transition-delay: .95s; }

/* The return arc arrives last, and slower. It's the point of the whole thing. */
.js [data-loop].is-drawn .loop__return {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1.1s var(--ease) 1.45s;
}
.js [data-loop].is-drawn .loop__nodes circle,
.js [data-loop].is-drawn .loop__labels text {
  opacity: 1;
  transition: opacity .6s var(--ease);
}
.js [data-loop].is-drawn .loop__nodes circle:nth-child(1),
.js [data-loop].is-drawn .loop__labels text:nth-child(1) { transition-delay: .35s; }
.js [data-loop].is-drawn .loop__nodes circle:nth-child(2),
.js [data-loop].is-drawn .loop__labels text:nth-child(2) { transition-delay: .60s; }
.js [data-loop].is-drawn .loop__nodes circle:nth-child(3),
.js [data-loop].is-drawn .loop__labels text:nth-child(3) { transition-delay: .85s; }
.js [data-loop].is-drawn .loop__nodes circle:nth-child(4),
.js [data-loop].is-drawn .loop__labels text:nth-child(4) { transition-delay: 1.10s; }
.js [data-loop].is-drawn .loop__nodes circle:nth-child(5),
.js [data-loop].is-drawn .loop__labels text:nth-child(5) { transition-delay: 1.35s; }
.js [data-loop].is-drawn .loop__return-label {
  opacity: 1;
  transition: opacity .7s var(--ease) 2s;
}
.js [data-loop].is-drawn .loop__travel {
  opacity: 1;
  transition: opacity 1.2s var(--ease) 2.4s;
}

.loop__caption {
  margin-top: 1.5rem;
  font-size: .8125rem;
  line-height: 1.5;
  letter-spacing: .01em;
  color: var(--n400);
  max-width: 26ch;
}

.loop__key {
  margin-top: clamp(4rem, 10vw, 7rem);
  padding-top: 2rem;
  font-size: clamp(1.55rem, 4.2vw, 3.1rem);
  max-width: 22ch;
  border-top: 2px solid var(--green);
  display: inline-block;
}

@media (min-width: 60em) {
  .loop__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: clamp(3rem, 7vw, 7rem);
    align-items: center;
  }
  .loop__figure { margin-top: 0; margin-inline: 0; }
  .loop__caption { margin-left: 12%; }
}


/* 10. SECTION 04. PROOF -------------------------------------------------
   One dominant figure. The supporting proof sits around it at a different
   size and off the same baseline, so the eye ranks them without being told. */

.proof {
  padding: var(--section) 0;
  border-top: 1px solid var(--rule);
}

.proof__head { margin-top: 1.25rem; }

/* CREDENTIALS
   A credit line, not a stats bar. Nothing here is larger than body copy, so
   the eye still lands on +145% first. Stacked hairline rows on a phone, one
   row divided by vertical hairlines from 48em up. */

.creds {
  margin-top: clamp(2.5rem, 7vw, 4rem);
  border-top: 1px solid var(--rule);
}

.creds__item {
  padding: .95rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: .75rem;
  line-height: 1.5;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--n400);
}

.creds__figure {
  font-weight: 600;
  color: var(--black);
}

@media (min-width: 48em) {
  .creds {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    border-bottom: 1px solid var(--rule);
  }
  .creds__item {
    padding: 1.1rem clamp(.9rem, 2vw, 1.5rem);
    border-bottom: 0;
    border-left: 1px solid var(--rule);
  }
  .creds__item:first-child { padding-left: 0; border-left: 0; }
}

.proof__grid { margin-top: clamp(3.5rem, 9vw, 6rem); }

.result__figure {
  font-weight: 700;
  letter-spacing: -.04em;
  line-height: .92;
}
.result__caption {
  margin-top: 1rem;
  font-size: .8125rem;
  line-height: 1.45;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--n400);
  max-width: 22ch;
}

/* The primary proof statistic. It has to read as unarguably the biggest thing
   in the section on a phone as well as on a desktop. */
.result--hero .result__figure {
  font-size: clamp(3.4rem, 17vw, 7.5rem);
  color: var(--tan);
}
.result--hero .result__caption {
  font-size: .875rem;
  color: var(--black);
}

.result--sub {
  margin-top: clamp(2.5rem, 7vw, 4rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--rule);
}
.result--sub .result__figure {
  font-size: clamp(1.6rem, 5.5vw, 2.6rem);
  color: var(--green);
}

/* THE CASE STUDY
   The figures are the claim, this is the payoff, so the two belong to one
   section. The photograph is substantial but no longer a full-bleed slab
   between them. Mobile stacks image, label, headline, story. */

.case { margin-top: clamp(4rem, 11vw, 8rem); }

/* The only photograph on the page. Warm monochrome so it reads as art
   direction rather than as a stock image dropped into a slot. */
.case__image { width: 100%; }

/* `height: auto` is load bearing. The <img> carries width and height
   attributes so the browser can reserve space before the file arrives, and
   those map to a presentational height that beats aspect-ratio. Without this
   the image renders at its intrinsic 1500px on a phone, which is nearly twice
   the viewport, and the photograph swallows the case study.

   Capped so the recipient meets the image and the start of the Plunkett copy
   in one natural scroll. Lands at 56 to 58svh across common handsets: a pause,
   not a takeover. object-fit crops the difference on short viewports. */
.case__image img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  max-height: 58vh;
  max-height: 58svh;
  object-fit: cover;
  object-position: center 40%;
  filter: grayscale(.72) contrast(1.06) brightness(.94) sepia(.14);
}

.case__copy { margin-top: clamp(1.75rem, 5vw, 3.5rem); }

.case__label {
  font-size: .6875rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--n400);
}

/* A genuine headline, at the same scale as the section headings above it. */
.case__head {
  margin: 1.25rem 0 2rem;
  font-size: clamp(1.5rem, 4.4vw, 2.6rem);
  line-height: 1.12;
  font-weight: 600;
  letter-spacing: -.02em;
}

.case__body {
  font-size: clamp(1.02rem, 1.9vw, 1.15rem);
  line-height: 1.62;
  color: var(--n500);
  max-width: 42ch;
}
.case__body + .case__body { margin-top: 1.35rem; }

/* THE CLOSING PROOF POINT
   Runs wider than the case study copy, under a full-width hairline, so it
   reads as the end of the argument rather than another module. */
.quote {
  margin-top: clamp(4.5rem, 11vw, 8rem);
  padding-top: clamp(2.5rem, 6vw, 4rem);
  border-top: 1px solid var(--rule);
}
.quote__text {
  font-size: clamp(1.55rem, 5.2vw, 3rem);
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: -.025em;
  max-width: 24ch;                     /* measured on this element's own type */
}
.quote__by {
  margin-top: clamp(2rem, 5vw, 3rem);
  font-size: .75rem;
  line-height: 1.6;
  letter-spacing: .12em;
  text-transform: uppercase;
}

@media (min-width: 60em) {
  .proof__grid {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    align-items: start;
  }
  .result--hero { grid-column: 1 / 8; }
  .result--sub  { grid-column: 9 / 13; margin-top: 0; }
  .result--a    { grid-row: 1; padding-top: 1.5rem; }
  .result--b    { grid-row: 1; margin-top: 14rem; }   /* deliberately off-baseline */

  /* Image just under three fifths, copy in the remainder, optically centred
     against it rather than hung from the top. */
  .case {
    display: grid;
    grid-template-columns: 57fr 43fr;
    gap: clamp(3rem, 6vw, 6rem);
    align-items: center;
  }
  .case__copy { margin-top: 0; }
  .case__head { margin-bottom: 2.25rem; }

  /* Held to a fixed height rather than a portrait ratio. At this column width
     4:5 would run taller than the viewport, which is the full-bleed slab this
     composition replaced. Substantial, not overwhelming. */
  .case__image img {
    aspect-ratio: auto;
    height: clamp(28rem, 44vw, 38rem);
    max-height: none;                  /* the mobile svh cap must not bind here */
    object-position: center 38%;
  }
}


/* 11. SECTION 05. THE INVITATION ---------------------------------------- */

.invitation {
  padding: var(--section) 0 3.5rem;
}

.invitation__line {
  margin-top: 2rem;
  font-size: clamp(2.1rem, 6.6vw, 4.4rem);
  line-height: 1.02;
  font-weight: 700;
  letter-spacing: -.035em;
  max-width: 16ch;
  text-wrap: balance;
}

.invitation__turn {
  margin-top: 2rem;
  font-weight: 400;
  color: var(--quiet);
  max-width: 24ch;
}

.invitation__ask {
  margin-top: clamp(3.5rem, 9vw, 6rem);
  max-width: 20ch;
}

.invitation__note {
  margin-top: 1.75rem;
  max-width: 34ch;
}


/* THE ENQUIRY FORM
   Built from labels, rules, and space. No panel, no boxed inputs, no filled
   button. Inputs are 17px so iOS does not zoom the page when one is focused. */

.enquiry {
  margin-top: clamp(3.5rem, 9vw, 5.5rem);
  max-width: 30rem;
}

.field + .field { margin-top: clamp(2.25rem, 6vw, 3rem); }

/* From 60em the four short fields pair up two by two, so five fields do not
   turn the close of the page into a long column of rules. The textarea and the
   submit still run the full width of the form. */
@media (min-width: 60em) {
  .enquiry {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: clamp(2rem, 4vw, 3.5rem);
    row-gap: clamp(2.25rem, 3.5vw, 3rem);
    align-items: start;
    max-width: 46rem;
  }
  .field + .field { margin-top: 0; }
  .field--wide,
  .cta--submit,
  .form-note { grid-column: 1 / -1; }
}

.field__label {
  display: block;
  margin-bottom: .85rem;
  font-size: .6875rem;
  line-height: 1.5;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--quiet);
}
/* Its own line, so it never wraps into a hanging indent under a long label. */
.field__optional {
  display: block;
  margin-top: .3rem;
  opacity: .55;
  letter-spacing: .12em;
}

.field__input {
  display: block;
  width: 100%;
  margin: 0;
  padding: .35rem 0 .75rem;
  border: 0;
  border-bottom: 1px solid rgba(246, 245, 242, .3);
  border-radius: 0;
  background: none;
  color: var(--ivory);
  font-family: inherit;
  font-size: 1.0625rem;                /* 17px, keeps iOS from zooming in */
  line-height: 1.5;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color .3s var(--ease);
}
.field__input:focus {
  outline: none;
  border-bottom-color: var(--tan);
  border-bottom-width: 2px;
  padding-bottom: calc(.75rem - 1px);  /* hold the baseline as the rule thickens */
}
.field__input--area {
  resize: vertical;
  min-height: 5.5rem;
}
.field__input:-webkit-autofill {
  -webkit-text-fill-color: var(--ivory);
  transition: background-color 9999s;  /* suppress the browser's yellow fill */
}

.field__error {
  margin-top: .65rem;
  font-size: .75rem;
  letter-spacing: .04em;
  color: var(--tan);
}
.field--invalid .field__input { border-bottom-color: var(--tan); }

.form-note {
  margin-top: 2rem;
  max-width: 34ch;
  font-size: .8125rem;
  line-height: 1.6;
  color: var(--quiet);
}


/* THE CTA
   A line of type over a rule, whether it is a link or the form's submit. */

.cta {
  display: inline-block;
  position: relative;
  padding-bottom: .5rem;
  font-size: clamp(1.5rem, 5.5vw, 2.4rem);
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ivory);
}
.cta::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2px;
  background: var(--tan);
  transform: scaleX(1);
  transform-origin: left;
  transition: transform .5s var(--ease);
}
@media (hover: hover) {
  .cta::after { transform: scaleX(.28); }
  .cta:hover::after,
  .cta:focus-visible::after { transform: scaleX(1); }
}

/* The submit is the same object as the link CTA, with the button chrome
   removed and a tap target tall enough for a thumb. */
.cta--submit {
  margin-top: clamp(3rem, 8vw, 4rem);
  padding-top: .35rem;
  border: 0;
  background: none;
  font-family: inherit;
  cursor: pointer;
  text-align: left;
}
.cta__arrow {
  display: inline-block;
  margin-left: .35em;
  transition: transform .4s var(--ease);
}
@media (hover: hover) {
  .cta--submit:hover .cta__arrow,
  .cta--submit:focus-visible .cta__arrow { transform: translateX(.25em); }
}

/* SUCCESS STATE. Shown only when a real submission succeeds. */
.thanks { margin-top: clamp(3.5rem, 9vw, 5.5rem); max-width: 30rem; }
/* It takes focus so assistive tech lands on it, but it is not interactive, so
   it must not draw a focus ring. A ring here reads as a card. */
.thanks:focus,
.thanks:focus-visible { outline: none; }
.thanks__line { max-width: 18ch; }
.thanks__note { margin-top: 1.5rem; }

.colophon {
  position: relative;
  z-index: 1;
  margin-top: var(--section);
  padding: 2.5rem var(--gutter) 0;
  border-top: 1px solid var(--rule);
  max-width: 76rem;
  margin-inline: auto;
}
.colophon__mark {
  width: 92px;
  height: auto;
  filter: invert(1) brightness(1.12);
}
.colophon__promise {
  margin-top: 1.25rem;
  font-size: .6875rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--quiet);
}
.colophon__link {
  margin-top: .5rem;
  font-size: .6875rem;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.colophon__link a { text-decoration: none; border-bottom: 1px solid var(--rule); padding-bottom: 2px; }

@media (min-width: 48em) {
  .colophon {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 2rem;
  }
  .colophon__promise { margin-top: 0; flex: 1; text-align: right; }
  .colophon__link { margin-top: 0; }
}


/* 12. REDUCED MOTION -----------------------------------------------------
   Everything arrives already in place. The loop is drawn, the card frame is
   gone, the traveller is removed by script.js. Nothing animates.          */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }

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

  /* The rail's auto-hide is switched off above, so instead of sitting fixed
     over the type it simply scrolls away with the opening. */
  .rail { position: absolute; }
  .rail--away { transform: none; }

  .js .reveal__eyebrow,
  .js .reveal__line,
  .js .reveal__beat,
  .js .reveal__cue { opacity: 1; animation: none; }

  .reveal__frame { display: none; }
  .reveal__cue::after { animation: none; transform: scaleY(1); }

  .js .loop__arc,
  .js .loop__return { stroke-dashoffset: 0; }
  .js .loop__nodes circle,
  .js .loop__labels text,
  .js .loop__return-label { opacity: 1; }
}
