/* ==========================================================================
   Tupelo Curbing and Landscape
   Implemented from the Claude Design hand-off "Tupelo Curbing".

   Plain CSS, no build step. Fonts are self-hosted from assets/fonts so the
   page has no third-party dependency at runtime; the unicode-range splits
   mean a visitor only downloads the subsets their content actually needs.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Typefaces - both families are variable, one file per unicode subset
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 100%;
  font-display: swap;
  src: url('../fonts/bricolage-grotesque-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 100%;
  font-display: swap;
  src: url('../fonts/bricolage-grotesque-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 100%;
  font-display: swap;
  src: url('../fonts/bricolage-grotesque-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

@font-face {
  font-family: 'Karla';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/karla-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Karla';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/karla-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   Design tokens - lifted verbatim from the design hand-off
   -------------------------------------------------------------------------- */

:root {
  --cream: #FBF7EF;      /* page background */
  --ink: #22301F;        /* body text, footer background */
  --forest: #1F4426;     /* hero, primary button, CTA band */
  --leaf: #2F7B3E;       /* link hover, current-page nav */
  --sprout: #A8CE7E;     /* light green accent on dark */
  --bone: #F2F0E4;       /* text on dark green */
  --sage: #4B5B43;       /* secondary body copy */
  --sand: #F1EADB;       /* warm feature panel */
  --mist: #E7EADF;       /* image placeholder while loading */
  --swatch: #F4F1E8;     /* stamp sample backdrop */
  --bark: #7A5C3E;       /* the "screens lie a little" caveat */
  --card: #fff;
  --hairline: rgba(34, 48, 31, .09);

  --display: 'Bricolage Grotesque', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --body: Karla, system-ui, -apple-system, 'Segoe UI', sans-serif;

  --shell: 1180px;
  --gutter: clamp(18px, 4vw, 40px);

  /* Height of the sticky header, tracked so scroll-padding can clear it. It
     changes with the logo size at the two narrow breakpoints below. */
  --header-h: 75px;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

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

/* Any author `display` beats the browser's [hidden] rule, so a component with
   `display: flex` stays on screen even when JavaScript marks it hidden. Both
   the chat prompt and the review score block hit exactly that. This makes the
   attribute mean what it says, everywhere. */
[hidden] { display: none !important; }

html {
  scroll-behavior: smooth;
  /* Without this the sticky header paints over whatever the browser just
     scrolled to - an anchor target, or a control that Tab or the tablist's
     arrow keys moved focus to. Every focusable thing on this page is shorter
     than the header, so the focus ring would land completely hidden.
     WCAG 2.2 SC 2.4.11 Focus Not Obscured (Minimum), AA. */
  scroll-padding-top: calc(var(--header-h) + 8px);
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 700;
  text-wrap: balance;
}

p { text-wrap: pretty; }

a {
  color: var(--forest);
  text-decoration: none;
}

a:hover { color: var(--leaf); }

img {
  max-width: 100%;
  display: block;
}

:focus-visible {
  outline: 3px solid var(--leaf);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Dark surfaces need the lighter ring to stay visible. */
.hero :focus-visible,
.cta :focus-visible,
.curbing-band :focus-visible,
.leadform__head :focus-visible,
.chat__head :focus-visible,
.footer :focus-visible { outline-color: var(--sprout); }

.shell {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 100;
  background: var(--forest);
  color: var(--bone);
  padding: 12px 18px;
  border-radius: 0 0 12px 12px;
  font-weight: 600;
  transition: top .16s ease;
}

.skip-link:focus {
  top: 0;
  color: var(--bone);
}

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

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

.header {
  position: sticky;
  top: 0;
  z-index: 60;
  padding: 11px 0;
  background: rgba(251, 247, 239, .94);
  border-bottom: 1px solid var(--hairline);
}

@supports (backdrop-filter: blur(10px)) or (-webkit-backdrop-filter: blur(10px)) {
  .header {
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
  }
}

.header__inner {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: clamp(14px, 4vw, 40px);
  display: flex;
  align-items: center;
  gap: clamp(10px, 2vw, 26px);
  flex-wrap: nowrap;
}

.header__logo {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
}

.header__logo img {
  height: 52px;
  width: auto;
}

.nav {
  display: flex;
  gap: clamp(10px, 1.6vw, 20px);
  align-items: center;
  font-size: 14.5px;
  font-weight: 500;
  flex-wrap: nowrap;
  flex: 1 1 auto;
  min-width: 0;
  justify-content: flex-end;
  white-space: nowrap;
}

/* Padding rather than height, so the row keeps the design's 52px logo rhythm
   while every link clears the 24px minimum target size. */
.nav a { padding-block: 6px; }

.nav a[aria-current='page'] {
  color: var(--leaf);
  font-weight: 700;
}

.header__actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: none;
}

/* Calling is the main thing a phone visitor does here, so the number gets a
   full 44px target even though the design draws it as plain text. The header
   row is already 52px tall, so nothing moves. */
.header__phone {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 16px;
  white-space: nowrap;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  border-radius: 999px;
  font-weight: 600;
  white-space: nowrap;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}

.btn--primary {
  background: var(--forest);
  color: var(--cream);
  padding: 11px 18px;
  font-size: 14.5px;
}

.btn--primary:hover,
.btn--primary:focus-visible {
  background: var(--leaf);
  color: var(--cream);
}

.btn--sprout {
  background: var(--sprout);
  color: #16301B;
  padding: 14px 22px;
  font-weight: 700;
  font-size: 15.5px;
}

.btn--sprout:hover,
.btn--sprout:focus-visible {
  background: #BEDD98;
  color: #16301B;
}

.btn--ghost {
  border: 1.5px solid rgba(242, 240, 228, .35);
  color: var(--bone);
  padding: 14px 22px;
  font-size: 15.5px;
}

.btn--ghost:hover,
.btn--ghost:focus-visible {
  border-color: var(--bone);
  color: var(--bone);
  background: rgba(242, 240, 228, .08);
}

/* The header row is nowrap by design, so the labels have to give way before
   the row does. Below 600px the phone keeps its number but loses the padding,
   and the quote button switches to its short label. */
.btn__label--short { display: none; }

@media (max-width: 1020px) {
  .nav { display: none; }
}

@media (max-width: 600px) {
  :root { --header-h: 67px; }
  .header__logo img { height: 44px; }
  .header__actions { gap: 10px; }
  .header__phone { font-size: 15px; }
  .btn--primary { padding: 11px 14px; font-size: 13.5px; }
  .btn__label--full { display: none; }
  .btn__label--short { display: inline; }
}

@media (max-width: 380px) {
  :root { --header-h: 63px; }
  .header__phone { font-size: 14px; }
  .header__logo img { height: 40px; }
}

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

.hero {
  background: var(--forest);
  color: var(--bone);
  padding: clamp(34px, 5vw, 64px) 0 0;
}

.hero a { color: var(--sprout); }
.hero a:hover { color: #C6E4A6; }

.hero__back {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 14px;
  font-weight: 600;
  /* Negative margin cancels the padding visually - the link sits where the
     design puts it, but it is comfortably tappable. */
  padding: 10px 12px 10px 0;
  margin: -10px 0;
}

.hero__back svg {
  width: 15px;
  height: 15px;
  flex: none;
  transition: transform .18s ease;
}

.hero__back:hover svg { transform: translateX(-3px); }

.hero__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(22px, 4vw, 48px);
  align-items: end;
  margin-top: 18px;
}

.eyebrow {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--sprout);
}

.hero h1 {
  font-size: clamp(32px, 4.4vw, 54px);
  line-height: 1.03;
  letter-spacing: -.03em;
  margin: 14px 0 0;
}

.hero__lead {
  font-size: clamp(16px, 1.6vw, 18.5px);
  line-height: 1.6;
  color: rgba(242, 240, 228, .86);
  max-width: 50ch;
  margin: 16px 0 0;
}

.stats {
  display: flex;
  flex-wrap: wrap;
  gap: 22px 34px;
  padding-bottom: 6px;
  margin: 0;
}

.stats div { margin: 0; }

.stats dt {
  font-family: var(--display);
  font-weight: 800;
  font-size: 34px;
  line-height: 1;
}

.stats dd {
  margin: 6px 0 0;
  font-size: 13.5px;
  line-height: 1.4;
  color: rgba(242, 240, 228, .8);
  max-width: 16ch;
}

/* --------------------------------------------------------------------------
   Tabs
   -------------------------------------------------------------------------- */

.tabs {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: clamp(26px, 4vw, 44px);
}

.tab {
  font-family: var(--body);
  font-size: 15px;
  font-weight: 600;
  padding: 13px 20px;
  border: 0;
  cursor: pointer;
  min-height: 46px;
  border-radius: 14px 14px 0 0;
  background: rgba(242, 240, 228, .14);
  color: rgba(242, 240, 228, .86);
  transition: background-color .18s ease, color .18s ease;
}

/* The label has to go fully opaque as the surface lightens: at 86% over the
   .24 surface it computes to 3.94:1, under the 4.5:1 minimum. Full bone on the
   same surface is 5.00:1. */
.tab:hover {
  background: rgba(242, 240, 228, .24);
  color: var(--bone);
}

.tab.is-selected {
  background: var(--cream);
  color: var(--forest);
}

/* Narrow screens wrap the strip onto two rows, where a folder-tab shape reads
   as a cream chip floating in the green rather than a tab joined to its panel.
   Rounding all four corners turns them into filter chips, which is what a
   wrapped row actually is, and lifting them off the edge finishes the idea. */
@media (max-width: 600px) {
  .tab {
    padding: 12px 15px;
    font-size: 14px;
    border-radius: 12px;
  }

  .hero { padding-bottom: 18px; }
}

/* Without JavaScript every panel stays on the page, so the tabs are dead
   weight - hide them and let the headings do the navigating. */
.tabs { display: none; }
.js .tabs { display: flex; }

.js .tabpanel { display: none; }
.js .tabpanel.is-active { display: block; }

/* --------------------------------------------------------------------------
   Panels
   -------------------------------------------------------------------------- */

.panel { padding: clamp(30px, 5vw, 56px) 0; }

.panel__intro { max-width: 760px; }

.panel__intro h2 {
  font-size: clamp(26px, 3.2vw, 38px);
  letter-spacing: -.025em;
  margin: 0;
}

.panel__intro p {
  font-size: 17px;
  line-height: 1.6;
  color: var(--sage);
  margin: 14px 0 0;
}

.subhead {
  font-size: clamp(20px, 2.2vw, 26px);
  letter-spacing: -.02em;
  margin: 38px 0 0;
}

.note {
  margin: 18px 0 0;
  font-size: 14px;
  color: var(--bark);
  font-style: italic;
}

/* --- CurbColor swatches --------------------------------------------------- */

.swatches {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(12px, 1.8vw, 20px);
  margin-top: 30px;
  padding: 0;
  list-style: none;
}

/* 16 finishes over 6 columns leaves 4 in the last row. Starting that row in
   column 2 centres it, so the block tapers - one empty cell at each end -
   instead of hanging left. The reset below matters as much as the offset:
   at 4 and 2 columns 16 divides evenly and any nudge would break the grid. */
.swatches > li:nth-child(13) { grid-column-start: 2; }

.swatch__chip {
  display: block;
  aspect-ratio: 4 / 3;
  border-radius: 14px;
  /* A hairline keeps the palest chips from vanishing into the page. */
  box-shadow: inset 0 0 0 1px var(--hairline);
}

.swatch__name {
  display: block;
  margin-top: 10px;
  font-size: 15px;
  font-weight: 600;
}

/* --- Generic cards -------------------------------------------------------- */

.notes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(14px, 2vw, 20px);
  margin-top: 34px;
}

.note-card {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 18px;
  padding: 20px;
}

.note-card h3 {
  font-size: 18.5px;
  margin: 0 0 7px;
  letter-spacing: -.01em;
}

.note-card p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--sage);
}

/* --- Moroccan stone style cards ------------------------------------------- */

.styles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(14px, 2vw, 20px);
  margin-top: 30px;
  padding: 0;
  list-style: none;
}

.style-card {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 20px;
  overflow: hidden;
}

.style-card__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--mist);
}

.style-card__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.style-card__body { padding: 16px 18px 20px; }

.style-card__body h3 {
  font-size: 19px;
  margin: 0;
  letter-spacing: -.01em;
}

.style-card__body p {
  margin: 6px 0 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--sage);
}

/* --- Finished job grids --------------------------------------------------- */

.jobs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(10px, 1.4vw, 16px);
  margin-top: 16px;
  padding: 0;
  list-style: none;
}

.job {
  position: relative;
  aspect-ratio: 1;
  border-radius: 16px;
  overflow: hidden;
  background: var(--mist);
  margin: 0;
}

.job img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.job figcaption {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 12px;
  /* .78 rather than the design's .74: at .74 a very bright photo behind the
     tile drops this label to 4.44:1, just under AA. The client will be
     swapping in their own job photos, so the overlay carries the margin. */
  background: rgba(31, 68, 38, .78);
  color: var(--bone);
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(15px, 1.5vw, 20px);
  letter-spacing: -.01em;
  opacity: 0;
  transition: opacity .22s ease;
}

.job:hover figcaption,
.job:focus-within figcaption { opacity: 1; }

/* Touch devices never hover, so the style name would simply be unreachable.
   Show it as a quiet bar along the bottom instead of a full-tile wash. */
@media (hover: none) {
  .job figcaption {
    opacity: 1;
    inset: auto 0 0 0;
    padding: 22px 12px 10px;
    align-items: flex-end;
    font-size: 14px;
    /* The scrim needs a plateau, not a plain ramp. A bare `to top` gradient
       reaches .82 only at the very bottom of the box - which is padding - so
       the glyphs ended up sitting in the transparent end at roughly .3 alpha
       and dropped to 2.4:1 over the brighter photos. Holding .82 up to 72%
       puts the full scrim behind the text and keeps the soft top edge. */
    background: linear-gradient(to top,
      rgba(22, 48, 27, .82) 0,
      rgba(22, 48, 27, .82) 72%,
      rgba(22, 48, 27, 0) 100%);
  }
}

/* --- Stone feature cards (address stamping, rain drains) ------------------ */

.features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: clamp(14px, 2vw, 20px);
  margin-top: 26px;
}

.feature {
  background: var(--sand);
  border-radius: 18px;
  padding: 20px;
  display: grid;
  gap: 14px;
  align-content: start;
}

.feature img {
  width: 100%;
  height: auto;
  border-radius: 12px;
}

.feature h3 {
  font-size: 18.5px;
  margin: 0;
  letter-spacing: -.01em;
}

.feature p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--sage);
}

/* --- Stamp pattern samples ------------------------------------------------ */

.samples {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(10px, 1.2vw, 14px);
  margin-top: 30px;
  padding: 0;
  list-style: none;
}

.sample {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  padding: 11px 11px 14px;
}

.sample img {
  width: 100%;
  aspect-ratio: 4 / 3;
  height: auto;
  object-fit: contain;
  background: var(--swatch);
  border-radius: 7px;
}

.sample h3 {
  font-size: 14.5px;
  margin: 9px 0 4px;
  letter-spacing: -.01em;
  /* "Basketweave" renders 93px and these cards get narrow. Without this the
     word simply paints out over the neighbouring card. */
  overflow-wrap: break-word;
  hyphens: auto;
}

.sample p {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--sage);
  overflow-wrap: break-word;
}

/* --------------------------------------------------------------------------
   Closing CTA
   -------------------------------------------------------------------------- */

.cta { margin: clamp(20px, 3vw, 34px) 0 clamp(52px, 8vw, 88px); }

.cta__inner {
  background: var(--forest);
  color: var(--bone);
  border-radius: 24px;
  padding: clamp(24px, 4vw, 40px);
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
  align-items: center;
  justify-content: space-between;
}

.cta h2 {
  font-size: clamp(22px, 2.6vw, 30px);
  letter-spacing: -.02em;
  margin: 0;
}

.cta p {
  margin: 9px 0 0;
  font-size: 16px;
  line-height: 1.55;
  color: rgba(242, 240, 228, .85);
  max-width: 46ch;
}

.cta__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

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

.footer {
  background: var(--ink);
  color: rgba(242, 240, 228, .72);
  padding: clamp(30px, 5vw, 52px) 0;
}

.footer__inner {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  justify-content: space-between;
  align-items: flex-start;
}

.footer__brand {
  display: flex;
  align-items: center;
  gap: 13px;
}

.footer__mark {
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: var(--cream);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.footer__mark img { width: 48px; height: auto; }

.footer__name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 19px;
  color: var(--bone);
  line-height: 1.2;
}

.footer__meta {
  margin: 8px 0 0;
  font-size: 14px;
  line-height: 1.6;
}

.footer__links {
  display: flex;
  gap: 28px;
  font-size: 14px;
  flex-wrap: wrap;
}

.footer__links a { padding-block: 5px; }

.footer a { color: rgba(242, 240, 228, .72); }
.footer a:hover { color: var(--bone); }

.footer a.footer__phone {
  /* Same story as .h2-sm: `.footer a` outranks a bare class, which dropped
     the phone number's green accent. */
  color: var(--sprout);
  font-weight: 600;
}

.footer a.footer__phone:hover { color: #C6E4A6; }

.footer__legal {
  max-width: var(--shell);
  margin: 22px auto 0;
  padding: 18px var(--gutter) 0;
  border-top: 1px solid rgba(242, 240, 228, .14);
  font-size: 13px;
  color: rgba(242, 240, 228, .6);
}

/* --------------------------------------------------------------------------
   Responsive grid steps - these mirror the design's own breakpoints
   -------------------------------------------------------------------------- */

@media (max-width: 860px) {
  .swatches { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .swatches > li:nth-child(13) { grid-column-start: auto; }
  .samples { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* The design holds the stamp samples at 4 columns all the way down, but the
   pattern names do not fit: at 430px a 4-column cell gives the heading 67px
   for a 93px word. These two steps give every name room on its own line. */

@media (max-width: 600px) {
  .jobs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .styles { grid-template-columns: 1fr; }
  .swatches { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .swatches > li:nth-child(16) { grid-column-start: 2; }
  .samples { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 420px) {
  /* Only the samples drop to 2 here - the swatches stay at 3, so the
     centred last swatch from the 600px block carries through. */
  .samples { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
   Scroll reveal

   Confirmed design direction in the README: "subtle scroll-triggered image
   enlarge... a little goes a long way, don't apply it to everything." So it
   lands on the photo grids and nothing else.

   This is a CSS scroll-driven animation rather than an IntersectionObserver
   on purpose. An observer has to hide the element first and then be trusted
   to un-hide it, and it does not reliably fire for content that was
   display:none behind a closed tab - which would leave a whole panel blank.
   Here the hidden state only exists inside @supports, so a browser without
   scroll-driven animations simply shows the photos, and a missed frame can
   never cost the client a section of the page.

   To drop the effect entirely, delete this block - the .reveal classes in the
   markup then do nothing.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .reveal {
      animation: reveal-in linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 70%;
    }

    @keyframes reveal-in {
      from {
        opacity: 0;
        transform: scale(.965) translateY(10px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }
  }
}

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

@media print {
  .header, .tabs, .cta, .skip-link { display: none !important; }
  .js .tabpanel { display: block !important; }
  body { background: #fff; }
}

/* ==========================================================================
   HOMEPAGE, REVIEWS PAGE AND SHARED FORM / CHAT UI

   The tokens, header, footer and buttons above are shared with the curbing
   page - nothing there is duplicated here.
   ========================================================================== */

:root {
  --grass: #6FA83C;   /* the bright accent rule over each "why" card */
  --star: #C2683F;    /* review stars */
  --prose: #3C4B36;   /* long-form body copy in the About section */
}

/* --- shared section rhythm ------------------------------------------------ */

.section { margin-top: clamp(52px, 8vw, 96px); }
.section--last { margin-bottom: clamp(52px, 8vw, 90px); }

.section__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 20px;
  flex-wrap: wrap;
}

.section h2 {
  font-size: clamp(28px, 3.4vw, 42px);
  letter-spacing: -.025em;
  margin: 0;
}

.section h2.h2-sm,
.h2-sm {
  /* `.section h2` outranks a bare class, so the small variant has to match
     that specificity or the two smaller headings render at the large size. */
  font-size: clamp(24px, 2.8vw, 34px);
  letter-spacing: -.02em;
  margin: 0;
}

.section__lead {
  margin: 8px 0 0;
  font-size: 16px;
  color: var(--sage);
  max-width: 46ch;
}

.eyebrow--bark { color: var(--bark); }

.stamp-note {
  font: 11.5px ui-monospace, Menlo, monospace;
  color: var(--bark);
}

/* These four are standalone calls to action rather than links inside a
   sentence, so the inline exception to WCAG 2.2 target size does not cover
   them. Padding, not height, so nothing shifts visually. */
.arrow-link {
  font-weight: 600;
  font-size: 14.5px;
  display: inline-block;
  padding-block: 5px;
}

.underline-link {
  color: var(--bone);
  font-weight: 600;
  font-size: 15px;
  border-bottom: 1.5px solid rgba(168, 206, 126, .7);
  display: inline-block;
  padding: 6px 0 3px;
}

.underline-link:hover { color: var(--sprout); }

.stars { color: var(--star); letter-spacing: 2px; }

/* --- extra buttons -------------------------------------------------------- */

.btn--leaf {
  background: var(--leaf);
  color: #fff;
  padding: 15px 24px;
  font-weight: 700;
  font-size: 16px;
}

.btn--leaf:hover, .btn--leaf:focus-visible { background: var(--forest); color: #fff; }

.btn--outline {
  border: 1.5px solid rgba(34, 48, 31, .22);
  padding: 15px 24px;
  font-size: 16px;
  color: var(--ink);
}

.btn--outline:hover, .btn--outline:focus-visible {
  border-color: var(--forest);
  color: var(--forest);
  background: rgba(31, 68, 38, .05);
}

.btn--ink {
  background: var(--ink);
  color: var(--cream);
  padding: 13px 20px;
  font-size: 14.5px;
}

.btn--ink:hover, .btn--ink:focus-visible { background: var(--forest); color: var(--cream); }

/* --- hero ----------------------------------------------------------------- */

.hero-home { padding: clamp(28px, 5vw, 54px) 0 0; }

.hero-home__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(20px, 4vw, 44px);
  align-items: center;
}

.pill-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--bark);
  background: var(--sand);
  padding: 7px 13px;
  border-radius: 999px;
}

.hero-home__title {
  font-size: clamp(38px, 5.6vw, 66px);
  line-height: 1.02;
  letter-spacing: -.03em;
  margin: 18px 0 0;
  text-wrap: pretty;
}

.hero-home__lead {
  font-size: clamp(16px, 1.6vw, 19px);
  line-height: 1.55;
  color: var(--sage);
  max-width: 44ch;
  margin: 18px 0 0;
}

.hero-home__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 26px;
}

.rating-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
  font-size: 14px;
  color: var(--sage);
  padding-block: 6px;
}

.rating-link:hover { color: var(--forest); }

.hero-home__media { position: relative; min-width: 0; }

.hero-home__frame {
  position: relative;
  overflow: hidden;
  border-radius: 24px;
  aspect-ratio: 4 / 3.4;
  background: var(--mist);
}

.hero-home__frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.owner-card {
  position: absolute;
  left: -14px;
  bottom: 34px;
  background: var(--cream);
  border: 1px solid rgba(34, 48, 31, .1);
  box-shadow: 0 12px 30px rgba(34, 48, 31, .13);
  border-radius: 16px;
  padding: 13px 16px;
  display: flex;
  align-items: center;
  gap: 11px;
  max-width: 250px;
  font-size: 13px;
  line-height: 1.35;
  color: var(--sage);
}

.owner-card img {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  object-fit: cover;
  object-position: 42% 34%;
  flex: none;
}

.owner-card strong { color: var(--ink); }

@media (max-width: 620px) {
  /* At this width the card would hang off the screen edge. */
  .owner-card { left: 8px; right: 8px; bottom: 10px; max-width: none; }
}

/* --- why folks call us back ---------------------------------------------- */

.reasons {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: clamp(14px, 2vw, 22px);
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.reasons li { border-top: 2px solid var(--grass); padding-top: 16px; }

.reasons__num {
  font-family: var(--display);
  font-size: 13px;
  font-weight: 700;
  color: var(--bark);
}

.reasons h3 {
  font-size: 18.5px;
  margin: 6px 0;
  letter-spacing: -.01em;
}

.reasons p { margin: 0; font-size: 14.5px; line-height: 1.5; color: var(--sage); }

/* --- services ------------------------------------------------------------- */

.services {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr));
  gap: clamp(14px, 2vw, 22px);
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
}

.svc-card {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 20px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.svc-card__media {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--mist);
}

.svc-card__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.svc-card__body { padding: 18px 20px 22px; }

.svc-card__body h3 { font-size: 20px; margin: 0; letter-spacing: -.01em; }

.svc-card__body p,
.svc-card--ask p {
  margin: 7px 0 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--sage);
}

.svc-card--ask {
  background: var(--sand);
  border: 1px dashed rgba(122, 92, 62, .4);
  padding: 22px;
  justify-content: center;
  gap: 10px;
}

.svc-card--ask h3 { font-size: 19px; margin: 0; letter-spacing: -.01em; }
.svc-card--ask p { margin: 0; }

/* --- about ---------------------------------------------------------------- */

.about {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(24px, 4vw, 52px);
  align-items: center;
}

.about__portrait {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}

.about__photo {
  position: relative;
  width: min(78%, 320px);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--mist);
}

.about__photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.about__card { text-align: center; }

.about__name {
  display: block;
  font-family: var(--display);
  font-weight: 700;
  font-size: 24px;
  letter-spacing: -.02em;
}

.about__role { display: block; font-size: 14px; color: var(--sage); margin-top: 4px; }

.about__contact {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 12px;
  font-size: 15px;
}

.about__contact a { padding-block: 4px; }

.about__title {
  font-size: clamp(26px, 3.2vw, 40px);
  letter-spacing: -.025em;
  line-height: 1.06;
  margin: 14px 0 0;
  text-wrap: pretty;
}

.about__prose { display: grid; gap: 14px; margin-top: 18px; max-width: 52ch; }
.about__prose p { margin: 0; font-size: 16.5px; line-height: 1.62; color: var(--prose); }

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

.chips li {
  background: var(--sand);
  border-radius: 999px;
  padding: 9px 15px;
  font-size: 14px;
  font-weight: 600;
}

.chips--white li { background: #fff; font-size: 14.5px; }

/* --- gallery -------------------------------------------------------------- */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(14px, 2vw, 22px);
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}

.shot {
  position: relative;
  overflow: hidden;
  border-radius: 20px;
  aspect-ratio: 5 / 4;
  background: var(--mist);
  margin: 0;
}

.shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.shot__tag {
  position: absolute;
  left: 14px;
  top: 14px;
  font: 11px ui-monospace, Menlo, monospace;
  padding: 5px 10px;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.shot__tag--before { background: var(--ink); color: var(--cream); }
.shot__tag--after { background: var(--leaf); color: #fff; }
.shot__tag--detail { background: rgba(251, 247, 239, .92); color: var(--ink); }

.shot__caption { margin: 10px 2px 0; font-size: 14px; color: var(--sage); }

.gallery__wide {
  position: relative;
  overflow: hidden;
  border-radius: 24px;
  aspect-ratio: 21 / 8;
  background: var(--mist);
  margin-top: clamp(14px, 2vw, 22px);
}

.gallery__wide img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* --- curbing teaser band -------------------------------------------------- */

.curbing-band {
  background: var(--forest);
  color: var(--bone);
  margin-top: clamp(52px, 8vw, 96px);
  padding: clamp(44px, 7vw, 86px) 0;
}

/* Links in this dark band go sprout green - but NOT the buttons, whose own
   label colours must win. `.curbing-band a` outranks `.btn--sprout` on
   specificity, which painted the button's text the same green as its fill. */
.curbing-band a:not(.btn) { color: var(--sprout); }

.curbing-band__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(24px, 4vw, 52px);
  align-items: center;
}

.curbing-band__title {
  font-size: clamp(28px, 3.6vw, 44px);
  letter-spacing: -.025em;
  line-height: 1.05;
  margin: 14px 0 0;
}

.curbing-band__lead {
  font-size: 16.5px;
  line-height: 1.6;
  color: rgba(242, 240, 228, .85);
  max-width: 48ch;
  margin: 16px 0 0;
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.tag-row li {
  border: 1px solid rgba(242, 240, 228, .28);
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 13.5px;
}

.palette {
  margin-top: 28px;
  background: rgba(242, 240, 228, .07);
  border: 1px solid rgba(242, 240, 228, .16);
  border-radius: 20px;
  padding: 20px 20px 22px;
}

.palette__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}

.palette__title { font-family: var(--display); font-weight: 700; font-size: 16.5px; }
.palette__note { font-size: 12.5px; color: rgba(242, 240, 228, .7); }

.palette__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(64px, 1fr));
  gap: 10px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}

.palette__grid li {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 10.5px;
  color: rgba(242, 240, 228, .82);
  text-align: center;
}

.palette__grid span {
  height: 44px;
  border-radius: 10px;
  display: block;
  box-shadow: inset 0 0 0 1px rgba(242, 240, 228, .14);
}

.curbing-band__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  margin-top: 26px;
}

.curbing-band__photos {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  min-width: 0;
}

.curbing-band__tall,
.curbing-band__small {
  position: relative;
  overflow: hidden;
  border-radius: 20px;
  background: #2A5330;
}

.curbing-band__tall { aspect-ratio: 3 / 4; grid-row: span 2; height: 100%; }
.curbing-band__small { aspect-ratio: 4 / 3; }

.curbing-band__photos img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --- reviews -------------------------------------------------------------- */

.reviews__head {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(20px, 3vw, 40px);
  align-items: flex-end;
  justify-content: space-between;
}

.reviews__score { display: flex; align-items: baseline; gap: 12px; margin-top: 16px; }

.reviews__big {
  font-family: var(--display);
  font-weight: 800;
  font-size: 56px;
  line-height: 1;
  letter-spacing: -.03em;
}

.reviews__meta { font-size: 14.5px; color: var(--sage); line-height: 1.4; }

.reviews__actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 22px; }

.reviews__all { margin: 10px 0 0; font-size: 14.5px; }
.reviews__all a { display: inline-block; padding-block: 5px; }

.reviews__status {
  margin: 22px 0 0;
  font: 12.5px ui-monospace, Menlo, monospace;
  color: var(--bark);
}

.marquee { overflow: hidden; margin-top: 18px; padding: 4px 0; }

.marquee__track { display: flex; gap: 14px; width: max-content; }

.marquee--running .marquee__track { animation: tp-marquee var(--marquee-duration, 70s) linear infinite; }
.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track { animation-play-state: paused; }

@keyframes tp-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  /* No crawl. The row becomes an ordinary horizontal scroller instead. */
  .marquee--running .marquee__track { animation: none; }
  .marquee { overflow-x: auto; }
}

.rv {
  flex: none;
  width: min(84vw, 320px);
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 18px;
  padding: 20px;
}

.rv__stars { font-size: 14px; }

.rv__text {
  margin: 10px 0 14px;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--ink);
}

.rv__text--bare { color: var(--sage); font-style: italic; }

.rv__who { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--sage); }
.rv__who strong { color: var(--ink); }

.rv__avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #E3D7C0;
  flex: none;
  object-fit: cover;
}

/* Attribution links. Google's Places policy requires crediting the review's
   author with their profile link and giving readers a way to reach the
   original review on Maps, so these are a condition of showing the content
   rather than a flourish. Kept quiet so they do not compete with the quote. */
.rv__author { color: inherit; text-decoration: none; }
.rv__author:hover strong,
.rv__author:focus-visible strong { text-decoration: underline; }

.rv__source { color: var(--sage); text-decoration: underline; text-underline-offset: 2px; }
.rv__source:hover,
.rv__source:focus-visible { color: var(--forest); }

/* The line under the marquee, which carries the Google Maps credit and the
   note about how the reviews are ordered. */
.reviews__attribution {
  font-size: 13px;
  line-height: 1.5;
  color: var(--sage);
  max-width: 60ch;
}

/* --- service area --------------------------------------------------------- */

.area {
  background: var(--sand);
  border-radius: 24px;
  padding: clamp(22px, 4vw, 40px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(20px, 3vw, 40px);
  align-items: center;
}

.area__lead { margin: 10px 0 0; font-size: 15.5px; line-height: 1.55; color: var(--sage); max-width: 40ch; }

.area__map {
  border-radius: 18px;
  overflow: hidden;
  background: #E2EAD6;
  border: 1px solid rgba(34, 48, 31, .1);
  min-width: 0;
}

.area__map svg { display: block; width: 100%; height: auto; }

.map-town circle { fill: var(--leaf); }
.map-town text { font-family: var(--body); font-size: 30px; font-weight: 600; fill: var(--ink); }
.map-town--home circle { fill: var(--forest); }
.map-town--home text { font-weight: 700; font-size: 36px; }
.map-ref { font-size: 26px; font-weight: 500; fill: rgba(34, 48, 31, .62); }
.map-state {
  font-family: var(--body);
  font-size: 21px;
  font-weight: 700;
  letter-spacing: .14em;
  fill: rgba(34, 48, 31, .5);
}

/* --- quote form ----------------------------------------------------------- */

.quote {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(20px, 3vw, 44px);
  align-items: start;
}

.quote__lead { margin: 12px 0 0; font-size: 16.5px; line-height: 1.6; color: var(--sage); max-width: 40ch; }

.quote__call {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 24px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  padding: 14px 16px;
  max-width: 330px;
  font-size: 14px;
  line-height: 1.4;
  color: var(--sage);
}

.quote__call img { width: 46px; height: 46px; border-radius: 50%; object-fit: cover; flex: none; }

.quote__phone {
  font-family: var(--display);
  font-weight: 700;
  font-size: 17px;
  display: inline-block;
  padding-block: 3px;
}

.leadform {
  background: var(--card);
  border: 1px solid rgba(34, 48, 31, .1);
  border-radius: 24px;
  box-shadow: 0 18px 40px rgba(34, 48, 31, .07);
  overflow: hidden;
}

.leadform__head {
  background: var(--leaf);
  padding: 16px 20px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.leadform__avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--cream);
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.leadform__avatar img { width: 30px; height: auto; }

.leadform__who { color: #fff; font-size: 14.5px; line-height: 1.35; }
.leadform__who span { opacity: .85; }

.leadform__body { padding: 20px; }

.leadform__bubble {
  margin: 0 0 18px;
  background: var(--sand);
  border-radius: 16px 16px 16px 4px;
  padding: 13px 16px;
  font-size: 15px;
  line-height: 1.5;
  max-width: 34ch;
}

/* Two columns only while there is room for two. The card sits in a grid that
   splits at roughly 620px of shell, so between there and about 1000px each
   field was being squeezed to ~123px - narrower than on a 320px phone. Sizing
   off the field rather than the viewport fixes every width at once. */
.leadform__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--sage);
}

.field--wide { grid-column: 1 / -1; }

.field input,
.field select,
.field textarea {
  border: 1px solid rgba(34, 48, 31, .55);
  border-radius: 11px;
  padding: 12px 13px;
  font-size: 15px;
  font-family: inherit;
  font-weight: 400;
  color: var(--ink);
  background: #FDFBF6;
  min-height: 44px;
  box-sizing: border-box;
  width: 100%;
}

.field textarea { resize: vertical; }
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible { outline-offset: 1px; }

.field input[aria-invalid='true'],
.field select[aria-invalid='true'],
.field textarea[aria-invalid='true'] { border-color: #B4432B; background: #FFF6F3; }

/* Honeypot: off-screen for people, still in the DOM for bots. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.leadform__submit {
  margin-top: 16px;
  width: 100%;
  background: var(--leaf);
  color: #fff;
  border: 0;
  border-radius: 999px;
  padding: 15px;
  font-family: inherit;
  font-weight: 700;
  font-size: 16px;
  cursor: pointer;
  min-height: 48px;
  transition: background-color .18s ease;
}

.leadform__submit:hover:not(:disabled) { background: var(--forest); }
.leadform__submit:disabled { opacity: .65; cursor: progress; }

.leadform__fine {
  margin: 12px 0 0;
  font-size: 12.5px;
  color: var(--bark);
  text-align: center;
}

.formstatus { margin: 12px 0 0; font-size: 14px; line-height: 1.5; text-align: center; }
.formstatus:empty { display: none; }
.formstatus--ok { color: var(--forest); font-weight: 600; }
.formstatus--bad { color: #B4432B; }

/* --- chat prompt ---------------------------------------------------------- */

.chat {
  position: fixed;
  right: clamp(14px, 3vw, 26px);
  bottom: clamp(14px, 3vw, 26px);
  z-index: 80;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 12px;
}

.chat__panel {
  width: min(92vw, 356px);
  /* A ceiling, not a target. The panel is sized to fit its content and in
     normal use never reaches this - it is the safety valve for large text
     settings and short landscape viewports, where clipping the submit button
     would be much worse than a scrollbar.

     dvh rather than vh: iOS counts the collapsing URL bar inside vh, so 78vh
     could be taller than the screen was actually showing. The vh line stays
     first as the fallback for browsers that do not know dvh. */
  max-height: min(76vh, 620px);
  max-height: min(calc(100dvh - 96px), 620px);
  overflow-y: auto;
  /* No overscroll-behavior here, deliberately. `overflow-y: auto` makes this a
     scroll container by style whether or not it has anything to scroll, and
     `overscroll-behavior: contain` breaks the scroll chain at any such box -
     so on the normal, non-overflowing panel it silently swallowed page scroll
     over the bottom third of a phone screen, exactly where a thumb rests and
     exactly where this thing auto-opens. Measured: a wheel gesture over the
     panel moved the page 0px, the same gesture beside it moved 600px. */
  background: var(--card);
  border: 1px solid rgba(34, 48, 31, .12);
  border-radius: 20px;
  box-shadow: 0 20px 46px rgba(34, 48, 31, .2);
}

@media (prefers-reduced-motion: no-preference) {
  .chat__panel { animation: tp-pop .22s ease-out; }
  @keyframes tp-pop {
    from { opacity: 0; transform: translateY(10px) scale(.97); }
    to { opacity: 1; transform: none; }
  }
}

.chat__head {
  background: var(--leaf);
  padding: 11px 16px;
  display: flex;
  align-items: center;
  gap: 10px;
  position: sticky;
  top: 0;
}

.chat__avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--cream);
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.chat__avatar img { width: 27px; height: auto; }

.chat__who { color: #fff; font-size: 13.5px; line-height: 1.3; flex: 1; }
.chat__who span { opacity: .85; }

.chat__close {
  background: rgba(255, 255, 255, .18);
  border: 0;
  color: #fff;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 17px;
  line-height: 1;
  flex: none;
}

.chat__close:hover { background: rgba(255, 255, 255, .3); }

.chat__body { padding: 12px 14px 14px; }
.chat__body .leadform__bubble { font-size: 14px; margin: 0; max-width: none; }

/* --- step one: the greeting on its own --- */

.chat__start {
  display: block;
  width: 100%;
  margin-top: 14px;
  background: var(--leaf);
  color: #fff;
  border: 0;
  border-radius: 999px;
  padding: 13px;
  font-family: inherit;
  font-weight: 700;
  font-size: 15.5px;
  line-height: 1.2;
  cursor: pointer;
  min-height: 48px;
  transition: background-color .18s ease;
}

.chat__start:hover { background: var(--forest); }

/* --- step two: the form, sized to fit a phone screen whole ---

   The shared .leadform__grid sizes its columns off a 170px minimum, which
   inside a 356px panel collapses to one column: seven stacked rows, roughly
   600px, guaranteed to scroll. Here the fields are paired two-up on purpose,
   which brings the whole panel to about 440px including the header, the
   submit button and the call link.

   That number is the budget. An iPhone SE shows about 555px of dvh with the
   URL bar expanded, and the panel reserves 96px of that for the pill below
   it, leaving roughly 460px to work with. Check the arithmetic before adding
   a field, and do not trust this comment over a real measurement.

   One trap, already fallen into once: min-height does not size a textarea.
   The rows attribute does, and min-height is only a floor beneath it. A
   rows="2" notes box renders at about 58px whatever min-height claims, which
   is why the chat copy uses rows="1" where the main form uses rows="3". */

.chat__body .leadform__grid {
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.chat__body .field { font-size: 11.5px; gap: 4px; }

.chat__body .field input,
.chat__body .field select,
.chat__body .field textarea {
  padding: 9px 10px;
  border-radius: 9px;
  min-height: 40px;
  /* Must not go below 16px. iOS Safari zooms the whole page in when a focused
     input is smaller than that, which would undo the entire point of making
     this fit without scrolling. */
  font-size: 16px;
}

.chat__body .field textarea { min-height: 44px; }

.chat__body .leadform__submit {
  margin-top: 10px;
  padding: 12px;
  font-size: 15px;
}

.chat__call {
  display: block;
  text-align: center;
  margin-top: 8px;
  font-size: 12.5px;
  color: var(--bark);
  /* 6px, not less: at 12.5px that is a ~28px tap target, and WCAG 2.2
     SC 2.5.8 asks for 24px minimum. Trimming it to 2px to save height
     took it under. */
  padding-block: 6px;
}

.chat__pill {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--ink);
  color: var(--cream);
  border: 0;
  border-radius: 999px;
  padding: 13px 19px;
  font-family: inherit;
  font-weight: 600;
  font-size: 14.5px;
  box-shadow: 0 12px 28px rgba(34, 48, 31, .28);
  cursor: pointer;
  min-height: 48px;
}

@media (prefers-reduced-motion: no-preference) {
  .chat__pill { animation: tp-float 4.5s ease-in-out infinite; }
  @keyframes tp-float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-6px); }
  }
}

.chat__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--sprout); display: block; flex: none; }

/* --- scroll zoom ---------------------------------------------------------- */

[data-zoom] { transform-origin: center 60%; }
.js [data-zoom] { will-change: transform; }

/* --- reviews page --------------------------------------------------------- */

.rv-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  gap: clamp(14px, 2vw, 20px);
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}

.rv-list .rv { width: auto; }

.rv-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px; }

.rv-filter {
  border: 1px solid rgba(34, 48, 31, .55);
  background: transparent;
  border-radius: 999px;
  padding: 9px 16px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--sage);
  cursor: pointer;
  min-height: 40px;
}

.rv-filter[aria-pressed='true'] { background: var(--forest); border-color: var(--forest); color: var(--cream); }

/* --- long-form pages (privacy, thank you) -------------------------------- */

.prose { max-width: 68ch; }
.prose h2 { font-size: clamp(20px, 2.2vw, 26px); letter-spacing: -.02em; margin: 34px 0 0; }
.prose p, .prose li { font-size: 16.5px; line-height: 1.65; color: var(--prose); }
.prose p { margin: 12px 0 0; }
.prose ul { margin: 12px 0 0; padding-left: 20px; }
.prose li { margin-top: 6px; }

.page-head { padding: clamp(28px, 5vw, 52px) 0 0; }

/* The back link is inline-flex, so anything after it would sit on the same
   line. The eyebrow starts its own. */
.page-head .eyebrow { display: block; margin-top: 20px; }

.page-head h1 {
  font-size: clamp(32px, 4.4vw, 52px);
  letter-spacing: -.03em;
  line-height: 1.04;
  margin: 14px 0 0;
}

.page-head__lead {
  font-size: clamp(16px, 1.6vw, 18.5px);
  line-height: 1.6;
  color: var(--sage);
  max-width: 52ch;
  margin: 16px 0 0;
}
