/* Lawn landing page — page-specific styles.
   Tokens, reset, footer base and .rl-btn live in /shared/tokens.css
   Layout mirrors the Figma "Simple Design System – Optik" 2120px frame;
   every fixed size from that frame is expressed here as a clamp() that
   lands on the Figma value at the top of its range. */

.lawn-page-width {
  width: 100%;
  max-width: 1804px;
  margin-inline: auto;
}

/* Page-level side inset for the desktop hero and features section.
   10vw lands on 128px at a 1280 window; floor and cap keep it sane on small
   laptops and ultrawides. */
:root {
  --lawn-inset: clamp(64px, 10vw, 200px);
  /* Stacked-layout counterpart to --lawn-inset: the edge every text block on
     the page lines up on below 768. Derived from the value cards — the cards
     grid's 16px padding plus the card's own inset — since that block of copy
     sets the measure the rest of the page reads against. Lands on 40px at 375.
     --lawn-inset-card is the matching edge for card *boxes* (the grid padding
     alone), so the two card sections share an outer edge. */
  --lawn-inset-sm: calc(16px + clamp(24px, 5vw, 48px));
  --lawn-inset-card: 16px;
  /* Shared headline size — hero, promise band and Early Access all set at the
     same scale. Stacked, it's driven by the hero line: "Run the Route." holds
     one line at every width, and at that weight and tracking the line measures
     7.01x its font size, so dividing the content box (viewport minus the two
     equal insets) by 7.1 sizes it to end just inside the right inset. Capped at
     the comp's 48px. Re-measure the divisor if the hero's weight, tracking or
     wording changes, or the line will wrap. */
  --lawn-title-size: min(3rem, calc((100vw - 2 * var(--lawn-inset-sm)) / 7.1));
  /* check glyph for the plan feature lists — used as a mask, so the fill comes
     from background-color and the stroke colour here is irrelevant */
  --lawn-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2.75 8.5l3.5 3.5 7-8' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* announcement bar + nav — subtracted from the hero so the whole hero,
     not hero-plus-overflow, is what fills the screen on load. script.js
     replaces this with the measured height; the values here are the
     no-JS fallback. */
  --lawn-header: 88px;
}
@media (min-width: 1024px) {
  :root {
    --lawn-header: 105px;
  }
}

/* ── Announcement bar ────────────────────────────────────────────────────── */

.lawn-announce {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: var(--rl-lime);
  padding: clamp(14px, 2vw, 21px) clamp(16px, 3vw, 33px);
}
.lawn-announce p {
  margin: 0;
  color: #000;
  font-weight: 400;
  font-size: clamp(0.8125rem, 1.1vw, 1rem);
  line-height: 1.4;
}

/* ── Nav ─────────────────────────────────────────────────────────────────── */

.lawn-nav {
  position: sticky;
  top: 0;
  z-index: 6;
  background: var(--rl-bg-translucent);
  display: flex;
  justify-content: center;
  padding: clamp(10px, 1.6vw, 17px) 12px;
  backdrop-filter: blur(4px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease;
}
.lawn-nav.is-scrolled {
  border-bottom-color: var(--rl-border);
}
.lawn-nav__brand {
  display: flex;
  align-items: center;
  gap: 5px;
  text-decoration: none;
  color: var(--rl-ink);
}
/* logo-mark.svg is exported with preserveAspectRatio="none" and no intrinsic
   size, so the box has to carry the ratio or the mark stretches */
.lawn-nav__brand img {
  width: clamp(30px, 3vw, 39.6px);
  aspect-ratio: 39.6007 / 23.1884;
  height: auto;
}
.lawn-nav__brand span {
  font-weight: 700;
  font-size: clamp(1.0625rem, 2.2vw, 1.5rem);
  line-height: 1.2;
}
.lawn-nav__brand-green {
  color: var(--rl-green);
}

/* Desktop trims the top of the page: the brand lockup drops to 75% and the
   announcement bar to 60% of its height (padding carries the reduction, so
   the copy stays at 16px). */
@media (min-width: 1024px) {
  .lawn-announce {
    padding-block: 8px;
  }
  .lawn-nav__brand img {
    width: clamp(22.5px, 2.25vw, 29.7px);
  }
  .lawn-nav__brand span {
    font-size: clamp(0.8rem, 1.65vw, 1.125rem);
  }
}

/* ── Hero ────────────────────────────────────────────────────────────────── */

.lawn-hero {
  position: relative;
  overflow: hidden;
  display: flex;
  /* stacked (comp 4215:5944): phone first, copy beneath it, flush left at 48px */
  align-items: flex-start;
  justify-content: center;
  /* fills the viewport on load. svh is the "small" viewport — the height with
     mobile browser chrome showing — so the hero can't be cut off at load and
     won't resize as the address bar collapses. vh first for older browsers. */
  min-height: calc(100vh - var(--lawn-header));
  min-height: calc(100svh - var(--lawn-header));
  padding: 20px var(--lawn-inset-sm) 40px;
}
.lawn-hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  /* portrait crop for stacked layouts; the wide crop takes over at 1024 */
  background: url('assets/hero_bg_skyline_mobile.jpg') center / cover no-repeat;
}
/* Mobile comp washes top-down: near-white behind the phone, then a grey-green
   midtone, deepening to olive at the base so the white copy holds. */
.lawn-hero__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0) 28.76%,
    rgba(151, 165, 158, 0.0) 60.53%,
    rgba(61, 90, 22, 0.54) 90%
  );
}
.lawn-hero__inner {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 38px;
  width: 100%;
  /* same measure the features grid and footer use, so the hero copy shares
     their left edge at every width */
  max-width: 1804px;
}
.lawn-hero__text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  gap: 20px;
}
.lawn-hero__title {
  margin: 0;
  color: var(--rl-text-on-brand);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  font-size: var(--lawn-title-size);
}
.lawn-hero__title em {
  font-style: italic;
}
.lawn-hero__subtitle {
  margin: 0;
  max-width: 100%;
  color: var(--rl-text-on-brand);
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.4;
  font-size: clamp(1rem, 4.53vw, 1.0625rem);
}
.lawn-hero__subtitle em {
  font-style: italic;
}
/* comp's mobile CTA is 143 wide against the shared 175 default */
.lawn-hero__text .rl-btn--cta {
  min-width: 143px;
}
.lawn-hero__device {
  /* grows to whatever the fold allows: viewport minus header, hero padding,
     the 45px gap and the copy block, converted to width by the 0.847 aspect —
     with a 250px floor so short phones scroll instead of shrinking the device */
  width: min(310px, 96%, max(250px, calc((100svh - var(--lawn-header) - 20px - 40px - 38px - 319px) * 0.847)));
  align-self: center;
  order: -1; /* comp puts the phone above the copy when stacked */
  /* nudged right and down — transform so it doesn't reflow the copy below */
  transform: translate(18px, 47px);
}
.lawn-hero__device img {
  width: 100%;
  filter: drop-shadow(8.87px 31.47px 20.21px rgba(0, 0, 0, 0.13));
}

@media (min-width: 768px) {
  /* side-by-side: copy left, phone right, and back to a vertically centred
     row with symmetric top/bottom padding so the phone sits mid-hero */
  .lawn-hero {
    align-items: center;
    padding: clamp(40px, 5.4vw, 78px) var(--lawn-inset);
  }
  /* wide crop of the same scene once there's room for it */
  .lawn-hero__bg {
    background-image: url('assets/hero_bg_skyline.jpg');
  }
  /* wash flips to left-to-right so the copy column sits on a light field for
     the dark type, leaving the phone side clear */
  .lawn-hero__bg::after {
    background:
      linear-gradient(135deg, rgba(248, 248, 248, 0.95) 0%, rgba(247, 252, 255, 0.8) 46%, rgba(255, 255, 255, 0) 90%),
      linear-gradient(180deg, rgba(58, 103, 119, 0.1) 0%, rgba(94, 171, 125, 0.2) 100%);
  }
  /* side by side, the hero line is bound by the copy column's share of the row
     (~0.376 of the window) rather than the full content box */
  :root {
    --lawn-title-size: clamp(2.125rem, 4.9vw, 6.75rem);
  }
  .lawn-hero__inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: clamp(32px, 3.6vw, 56px);
  }
  .lawn-hero__text {
    gap: clamp(16px, 2.2vw, 25px);
    /* copy sits a touch above the row's centre line — transform so the lift
       doesn't change the hero's height or the phone's placement */
    transform: translateY(calc(-1 * clamp(16px, 2.2vw, 40px)));
  }
  .lawn-hero__text .rl-btn--cta {
    min-width: 175px;
  }
  /* desktop type is dark on the lightened left of the photo; only the mobile
     comp uses white copy */
  .lawn-hero__title {
    color: var(--rl-ink);
    /* "Run the Route." stays on one line from 768 up, so the size is tied to
       the copy column's share of the row (~0.376 of the window) divided by the
       line's ~8.0x width-to-font-size ratio, with margin to spare */
    white-space: nowrap;
  }
  .lawn-hero__subtitle {
    color: var(--rl-ink);
    max-width: 500px;
    font-weight: 400;
    letter-spacing: -0.02em;
    line-height: 1.36;
    font-size: clamp(1rem, 1.45vw, 1.25rem);
  }
  .lawn-hero__device {
    /* third term caps the phone by available height (its aspect is 0.847) so it
       tends to fit the fold on short laptop windows — but max() floors that at
       360px, so a short window scrolls a little rather than shrinking the phone
       to a thumbnail. The 48% share keeps it large as the window narrows while
       still leaving the copy column room for the one-line title. */
    width: min(640px, 48%, max(420px, calc((100svh - var(--lawn-header) - 2 * clamp(60px, 5.4vw, 78px)) * 0.9)));
    flex-shrink: 0;
    align-self: center;
    order: 0;
    /* nudged below centre — transform so it doesn't reflow the text column */
    transform: translateY(28px);
  }
  /* tilted render casts its shadow down-right, matching the angle */
  .lawn-hero__device img {
    filter: drop-shadow(21.6px 76.68px 49.25px rgba(0, 0, 0, 0.13));
  }
}

/* ── Special cards ───────────────────────────────────────────────────────── */

.lawn-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  padding: var(--lawn-inset-card);
}
.lawn-card {
  background: var(--rl-card-gradient);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(20px, 3vw, 32px);
  padding: clamp(40px, 7vw, 56px) clamp(24px, 5vw, 48px);
  min-height: clamp(420px, 52vw, 550px);
}
.lawn-card__device {
  width: clamp(160px, 42vw, 225px);
  flex-shrink: 0;
}
.lawn-card__device img {
  width: 100%;
}
.lawn-card__text {
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2.6vw, 32px);
  max-width: 314px;
  color: var(--rl-ink);
}
.lawn-card__title {
  margin: 0;
  font-weight: 800;
  letter-spacing: -0.02em;
  /*text-transform: uppercase;*/
  line-height: 1;
  font-size: clamp(2rem, 4.2vw, 2.4rem);
}
.lawn-card__title em {
  font-style: italic;
}
.lawn-card__body {
  margin: 0;
  font-weight: 400;
  line-height: 1.2;
  font-size: clamp(0.9375rem, 1.5vw, 1.25rem);
}

/* side-by-side once there's room for the phone and the copy column */
@media (min-width: 640px) {
  .lawn-card {
    flex-direction: row;
    justify-content: center;
    padding-left: clamp(32px, 6vw, 78px);
  }
  /* Comp pins the copy column to the full card height and drops the title in
     at a fixed 123px from the top, so description length can't shift it. The
     card's own top padding covers ~56px of that; this adds the rest. */
  .lawn-card__text {
    align-self: stretch;
    justify-content: flex-start;
    padding-top: clamp(16px, 5vw, 67px);
  }
}

@media (min-width: 1024px) {
  .lawn-cards {
    grid-template-columns: 1fr 1fr;
  }
  /* Grid items default to min-width:auto, so a card whose min-content width
     (inset + phone + gap + copy) exceeds its column pushes past it and scrolls
     the page. Pin the card to its column and let the copy reflow instead. */
  .lawn-card {
    min-width: 0;
    /* the 6vw inset is sized for a full-width card; halve it once two share
       the row, so the phone and copy keep their measure */
    padding-left: clamp(32px, 4vw, 78px);
  }
  .lawn-card__text {
    min-width: 0;
  }
  /* two-up, the phone gets roughly half the row — size it off that share, not
     the whole viewport, so the pair always fits */
  .lawn-card__device {
    width: clamp(150px, 15.6vw, 225px);
  }
}

/* ── "Try it for 30 days" promise band ───────────────────────────────────── */

.lawn-promise {
  background: var(--rl-slate-gradient);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: clamp(16px, 2.4vw, 27px);
  min-height: clamp(460px, 44vw, 800px);
  padding: clamp(80px, 10vw, 140px) clamp(20px, 5vw, 158px);
  color: var(--rl-text-on-brand);
}
.lawn-promise__title {
  margin: 0;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
  font-size: var(--lawn-title-size);
}
.lawn-promise__body {
  margin: 0;
  max-width: 456px;
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.36;
  font-size: clamp(1rem, 1.8vw, 1.5rem);
  /* the section already carries its own inset — add only the difference so the
     copy lands on the shared stacked-layout edge */
  padding-inline: calc(var(--lawn-inset-sm) - clamp(20px, 5vw, 158px));
}
@media (min-width: 768px) {
  /* the title fits on one line from here up, and the copy is measure-limited
     rather than inset-limited */
  .promise-br-sm {
    display: none;
  }
  .lawn-promise__body {
    padding-inline: 0;
  }
}

/* ── Subscription Plans ──────────────────────────────────────────────────── */

/* Comp 4318:7417: three 400x433 cards, 20px apart, centred under a 48px title.
   Fixed card height there is what keeps the three footers on one line; here the
   grid rows do that job so long copy can't clip. */
.lawn-plans {
  /* same field as Early Access below it; the cards stay white so they lift off it */
  background: var(--rl-surface-muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(36px, 4.4vw, 61px);
  /* stacked, the plan cards are boxes like the value cards — same outer edge */
  padding: clamp(64px, 8vw, 110px) var(--lawn-inset-card);
}
@media (min-width: 900px) {
  .lawn-plans {
    padding-inline: clamp(20px, 5vw, 158px);
  }
}
.lawn-plans__title {
  margin: 0;
  color: var(--rl-ink);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
  text-align: center;
  font-size: clamp(1.75rem, 4vw, 3rem);
}
.lawn-plans__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
  width: 100%;
  max-width: 1240px;
}
@media (min-width: 900px) {
  .lawn-plans__grid {
    grid-template-columns: repeat(3, minmax(240px, 400px));
    justify-content: center;
    /* rows share a height so the three cards line up whatever the copy runs to.
       Stacked they sit one per row, where an equal height would just pad the
       shorter cards out — so each hugs its own content instead. */
    grid-auto-rows: 1fr;
  }
  .lawn-plan {
    /* the comp's fixed card height, restored once the three sit side by side */
    min-height: 433px;
    padding: 32px;
  }
}
.lawn-plan {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: var(--rl-space-400);
  /* comp's 32px inset would put the copy 8px inside the value cards' text edge
     when stacked; the full inset returns once the cards sit side by side */
  padding: 24px;
  border: 1px solid var(--rl-border);
  border-radius: 16px;
  background: #fff;
}
.lawn-plan__top {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--rl-space-400);
  width: 100%;
}
.lawn-plan__name {
  margin: 0;
  color: var(--rl-ink);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  font-size: 2rem;
}
.lawn-plan__price {
  margin: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  color: var(--rl-ink);
  white-space: nowrap;
}
.lawn-plan__currency {
  align-self: flex-start;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  font-size: 1.5rem;
}
.lawn-plan__amount {
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  font-size: 3rem;
}
.lawn-plan__period {
  font-weight: 400;
  line-height: 1.8;
  font-size: 0.875rem;
}
/* annual alternative, tucked under the monthly price — the negative margin
   pulls it inside the 16px stack gap so it reads as part of the price block */
.lawn-plan__annual {
  margin: -10px 0 0;
  color: #757575;
  text-align: center;
  line-height: 1.4;
  font-size: 0.875rem;
}
.lawn-plan__annual span {
  color: #00875f;
  font-weight: 600;
}
/* the comp centres the bullet block itself, but left-aligns the items inside it */
.lawn-plan__list {
  margin: 0;
  padding: 0;
  /* the marker is drawn on each item instead, so the browser's own is dropped */
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
  color: #757575;
  line-height: 1.4;
  font-size: var(--rl-body-size);
}
.lawn-plan__list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
/* Green check in place of the disc. Drawn as a mask rather than a background
   image so the colour stays a token, and as a mask rather than a ✓ character
   because Google's latin subset doesn't carry U+2713 — that would fall back to
   a system font and change shape per platform. The box is one line tall so the
   check centres on the item's first line however many lines it wraps to. */
.lawn-plan__list li::before {
  content: '';
  flex-shrink: 0;
  width: 1.05em;
  height: 1.4em;
  background-color: var(--rl-green);
  -webkit-mask: var(--lawn-check) center / 1.05em 1.05em no-repeat;
  mask: var(--lawn-check) center / 1.05em 1.05em no-repeat;
}
.lawn-plan__note {
  margin: 10px 0;
  max-width: 290px;
  color: #757575;
  text-align: center;
  line-height: 1.4;
  font-size: var(--rl-body-size);
}
.lawn-plan__foot {
  /* breathing room under the feature list. Adds to the card's 16px gap when the
     card hugs its content; where the card runs to a fixed height and
     space-between already parks this at the bottom, it changes nothing. */
  margin: 12px 0 0;
  color: var(--rl-text);
  text-align: center;
  line-height: 1;
  font-size: var(--rl-body-size);
}
.lawn-plan__foot a {
  color: inherit;
  text-decoration: none;
}
.lawn-plan__foot a:hover {
  text-decoration: underline;
}

/* ── Early Access ────────────────────────────────────────────────────────── */

.lawn-early {
  background: var(--rl-surface-muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: clamp(16px, 2.4vw, 27px);
  /* stacked, the section's copy is short enough that the desktop band height
     leaves a lot of dead field around it — trimmed here, restored at 768 */
  min-height: 440px;
  padding: 64px var(--lawn-inset-sm);
}
@media (min-width: 768px) {
  .lawn-early {
    min-height: clamp(540px, 44vw, 800px);
    padding: clamp(80px, 10vw, 140px) clamp(20px, 5vw, 158px);
  }
}
.lawn-early__title {
  margin: 0;
  color: var(--rl-ink);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
  font-size: var(--lawn-title-size);
}
.lawn-early__body {
  margin: 0;
  color: var(--rl-ink-muted);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.36;
  font-size: clamp(1rem, 1.8vw, 1.5rem);
}
.lawn-early__form {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(16px, 2.4vw, 27px);
  width: 100%;
}
/* one visible step at a time: email, then phone, then the confirmation */
.lawn-early__step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(16px, 2.4vw, 27px);
  width: 100%;
}
.lawn-early__step[hidden] {
  display: none;
}
/* spam trap — offscreen rather than display:none so bots still fill it */
.lawn-waitlist__honeypot {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
/* Confirmation check. A darkened --rl-green: the brand value is too light to
   read as a stroked icon on --rl-surface-muted. */
.lawn-early__check {
  color: #00875f;
  flex-shrink: 0;
}
/* The static state above is the fully drawn check; the entrance is layered on
   only when motion is welcome, so a stalled or unsupported animation can never
   leave the confirmation invisible. */
@media (prefers-reduced-motion: no-preference) {
  .lawn-early__check {
    animation: lawn-check-pop 0.32s cubic-bezier(0.34, 1.56, 0.64, 1) both;
  }
  /* mark draws itself in after the circle lands */
  .lawn-early__check-mark {
    stroke-dasharray: 18;
    stroke-dashoffset: 18;
    animation: lawn-check-draw 0.28s ease-out 0.16s forwards;
  }
}
@keyframes lawn-check-pop {
  from {
    opacity: 0;
    transform: scale(0.7);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@keyframes lawn-check-draw {
  to {
    stroke-dashoffset: 0;
  }
}
.lawn-early__success {
  margin: 0;
  max-width: 340px;
  color: var(--rl-ink);
  font-weight: 600;
  line-height: 1.4;
}
/* visible label would duplicate the placeholder in the comp — keep it for AT only */
.lawn-early__label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.lawn-early__input {
  width: min(322px, 100%);
  height: 40px;
  padding: var(--rl-space-300) var(--rl-space-400);
  border: 1px solid #383838;
  border-radius: 33px;
  background: transparent;
  color: var(--rl-ink);
  font-family: inherit;
  font-size: var(--rl-body-size);
  line-height: 1;
}
.lawn-early__input::placeholder {
  color: var(--rl-ink);
  opacity: 1;
}
.lawn-early__input:focus-visible {
  outline: 2px solid var(--rl-ink);
  outline-offset: 1px;
}
.lawn-early__input.is-invalid {
  border-color: #c0392b;
}
.lawn-early__error {
  margin: calc(-1 * clamp(16px, 2.4vw, 27px) + 6px) 0 0;
  max-width: 322px;
  color: #c0392b;
  font-size: 0.875rem;
  line-height: 1.3;
}
.lawn-early__error[hidden] {
  display: none;
}
/* ── Packed with features ────────────────────────────────────────────────── */

.lawn-features {
  background: var(--rl-bg);
  padding: clamp(56px, 8vw, 150px) var(--lawn-inset-sm) clamp(64px, 9vw, 185px);
}
@media (min-width: 768px) {
  .lawn-features {
    padding-inline: clamp(20px, 5vw, 158px);
  }
}
@media (min-width: 1024px) {
  .lawn-features {
    padding-inline: var(--lawn-inset);
  }
}
.lawn-features__head {
  text-align: center;
  margin: 0 auto clamp(40px, 6vw, 78px);
  max-width: 900px;
}
.lawn-features__title {
  margin: 0 0 clamp(10px, 1.4vw, 16px);
  color: var(--rl-ink);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.05;
  font-size: clamp(1.5rem, 4vw, 3rem);
}
.lawn-features__body {
  margin: 0;
  color: var(--rl-ink-muted);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.36;
  font-size: clamp(1rem, 1.8vw, 1.5rem);
}
.lawn-features__grid {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(32px, 4.5vw, 86px) clamp(24px, 4.5vw, 86px);
  max-width: 1804px;
}
.lawn-feature h3 {
  /* Comp uses a fixed 118px title box at 32px type (3.6875em) with the text
     bottom-aligned inside it. Fixed height — not min-height — is what makes
     every title in a row sit on the same baseline no matter how many lines it
     runs, and it keeps the body copy starting on a common line too. */
  display: flex;
  align-items: flex-end;
  height: 3.6875em;
  margin: 0 0 10px;
  color: var(--rl-ink-muted);
  font-weight: 700;
  line-height: 1.1;
  font-size: clamp(1.0625rem, 1.5vw, 1.5rem);
}
.lawn-feature p {
  margin: 0;
  color: var(--rl-ink-muted);
  font-weight: 400;
  line-height: 1.5;
  font-size: clamp(0.8125rem, 1vw, 1rem);
}

@media (min-width: 768px) {
  .lawn-features__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@media (min-width: 1200px) {
  .lawn-features__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
@media (min-width: 1500px) {
  .lawn-features__grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* ── Footer ──────────────────────────────────────────────────────────────── */

.lawn-footer {
  background: var(--rl-footer-gradient);
  border-top: 1px solid var(--rl-border);
  /* side inset matches the features section above it, so the footer's brand,
     links and copyright start on the same left edge as the rest of the page */
  padding: clamp(56px, 7vw, 117px) var(--lawn-inset-sm) clamp(32px, 4vw, 48px);
  color: var(--rl-text-on-brand);
}
@media (min-width: 768px) {
  .lawn-footer {
    padding-inline: clamp(20px, 5vw, 158px);
  }
}
@media (min-width: 1024px) {
  .lawn-footer {
    padding-inline: var(--lawn-inset);
  }
}
.lawn-footer__inner {
  width: 100%;
  max-width: 1804px;
  margin-inline: auto;
}
.lawn-footer__brand {
  display: flex;
  align-items: center;
  gap: 6px;
}
.lawn-footer__logo {
  width: clamp(40px, 4vw, 52.41px);
  aspect-ratio: 39.6007 / 23.1884;
  height: auto;
  filter: brightness(0) invert(1);
}
.lawn-footer__name {
  font-weight: 700;
  line-height: 1.2;
  font-size: clamp(1.5rem, 3vw, 2rem);
}
.lawn-footer__links {
  display: flex;
  flex-direction: column;
  gap: 19px;
  margin-top: clamp(32px, 4vw, 63px);
}
.lawn-footer__links a {
  color: var(--rl-text-on-brand);
  text-decoration: none;
  line-height: 1.4;
  font-size: var(--rl-body-size);
  width: fit-content;
}
.lawn-footer__links a:hover {
  text-decoration: underline;
}
.lawn-footer__copy {
  margin: clamp(48px, 8vw, 120px) 0 0;
  color: rgba(243, 243, 243, 0.45);
  font-size: 0.75rem;
}
