/* ==========================================================================
   site.css — By Design Landscapes, Logan UT, built FROM tokens.
   HARD RULE (house-tech-spec §3): no raw hex, no px/rem literal, no
   font-name literal in this file — tokens only, the Critic greps for it.
   The shell (header/nav, section rhythm, buttons, form, footer) is the
   skeleton's; every component below it is written per brief.md's
   editorial-modern / band-rhythm archetype (design-rules §7).
   ========================================================================== */

/* --- Layout primitives ---------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--layout-container);
  margin-inline: auto;
  padding-inline: var(--layout-gutter);
}

/* Vertical rhythm hook. --section-gap is the only inter-section spacing value
   on this site (design-rules §7.1); it is also the hero's own
   padding-block-end, so the hero-to-band boundary is the same measure as
   every band-to-band boundary. */
.section {
  padding-block: var(--section-gap);
}

.measure {
  max-width: var(--layout-measure);
}

/* --- Header & navigation --------------------------------------------------
   Progressive enhancement: with JS off the nav list is a plain, always-visible
   list of links and the toggle stays [hidden] (it ships hidden in the HTML;
   main.js reveals it). With JS on, narrow viewports collapse the list behind
   the toggle. Nothing about navigation depends on JavaScript.              */

.site-header {
  position: relative;
  z-index: var(--z-header);
  padding-block: var(--space-sm);
  border-bottom: var(--border-hairline) var(--border-style) var(--color-border);
  background-color: var(--color-bg);
}

.site-header__inner {
  position: relative;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--space-sm);
}

/* The wordmark yields first at narrow widths, never the phone or the
   toggle (brief §2). It yields by WRAPPING, not truncating: a single-line
   ellipsis floor sized for an 18-char name (anderson-landscape-green-bay-wi)
   cuts this business's 21-char name off mid-word ("By Desig…") at
   320–412px. */
.site-header__brand {
  min-width: 0;
  flex-shrink: 1;
  font-family: var(--font-display);
  /* --text-body, not --text-h2: at 375px the name + phone + toggle don't
     fit at display scale on one line, so the wordmark yields (design-rules
     §7.2 keeps phone/toggle un-shrinkable). */
  font-size: var(--text-body);
  font-weight: var(--font-weight-display);
  line-height: var(--leading-tight);
  text-decoration: none;
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

/* Below ~480px, wrapping alone isn't enough: phone+toggle are un-shrinkable
   and what's left for the wordmark (28px@320, 83px@375 measured) is
   narrower than its own longest word alone ("Landscapes," ~90px) — a
   wrapped word still gets cut. Below this width the wordmark takes its own
   full row above phone+toggle instead, clearing every word to 320px without
   shrinking either. Cutover at 32em, above the ~30em edge, for margin. */
@media (max-width: 31.9375em) {
  .site-header__inner {
    flex-wrap: wrap;
  }

  .site-header__brand {
    flex-basis: 100%;
  }
}

/* Sits outside the collapsible nav so it never disappears behind the toggle
   (brief §2). Clusters with the toggle at the row's trailing edge. Plain
   link, not a bordered button — the row has to fit the wordmark, the phone
   and the toggle on one line at 375px, and a button's own padding is the
   difference between fitting and not. */
.site-header__phone {
  flex-shrink: 0;
  margin-inline-start: auto;
  white-space: nowrap;
  font-size: var(--text-small);
  font-weight: var(--font-weight-body-strong);
  color: var(--color-accent);
  text-decoration: none;
}

.site-header__phone:hover,
.site-header__phone:focus-visible {
  text-decoration: underline;
  text-underline-offset: var(--space-3xs);
}

.nav-toggle {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--space-2xs);
  padding: var(--space-2xs) var(--space-xs);
  border: var(--border-hairline) var(--border-style) var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-small);
  font-weight: var(--font-weight-body-strong);
}

/* Before main.js marks the page ready (and permanently with JS off),
   .site-nav sits in the header's nowrap row. Left free to wrap, its link
   list grows to two lines at narrow widths — header height then depends on
   how long main.js takes to arm the collapsed state, and a height tied to
   JS timing is a layout shift (measured: header 60px taller pre-JS than
   post). Horizontal scroll pins the row height at every width/timing. */
.site-nav {
  min-width: 0;
}

.site-nav__list {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  align-items: center;
  gap: var(--space-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav__list li {
  flex-shrink: 0;
}

/* white-space: nowrap keeps each link at its natural width instead of
   wrapping its own text — that internal wrap is what left the row's height
   still tied to JS timing even after the list stopped wrapping. */
.site-nav__link {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  text-decoration: none;
  font-size: var(--text-small);
  font-weight: var(--font-weight-body-strong);
  color: var(--color-ink);
}

.site-nav__link:hover,
.site-nav__link:focus-visible {
  text-decoration: underline;
  text-underline-offset: var(--space-3xs);
}

/* Collapsed state exists only once JS has armed it. The header row itself is
   nowrap (below) so the wordmark shrinks instead of the row wrapping — the
   open nav is therefore a dropdown panel, not a wrapped-to-its-own-line
   sibling, which is what a wrap-based approach would need. */
[data-nav-ready] .site-nav[data-nav-open='false'] {
  display: none;
}

[data-nav-ready] .site-nav[data-nav-open='true'] {
  position: absolute;
  inset-inline: 0;
  top: 100%;
  padding: var(--space-sm) var(--layout-gutter);
  background-color: var(--color-bg);
  border-bottom: var(--border-hairline) var(--border-style) var(--color-hairline);
}

@media (min-width: 48em) {
  [data-nav-ready] .site-nav[data-nav-open='false'] {
    display: block;
  }

  [data-nav-ready] .site-nav[data-nav-open='true'] {
    position: static;
    padding: 0;
    border-bottom: 0;
    background-color: transparent;
  }

  [data-nav-ready] .nav-toggle {
    display: none;
  }
}

/* --- Buttons --------------------------------------------------------------
   Two roles. Radius/colour come from tokens — --radius-sm is the house
   neutral default; nothing in the brief argues a different shape. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  padding: var(--space-xs) var(--space-md);
  border: var(--border-hairline) var(--border-style) transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-chrome);
  font-weight: var(--font-weight-body-strong);
  line-height: var(--leading-snug);
  text-align: center;
  text-decoration: none;
  transition: background-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
}

.btn--primary {
  background-color: var(--color-accent-deep);
  color: var(--color-accent-ink);
}

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

.btn--quiet {
  border-color: var(--color-hairline);
  color: var(--color-ink);
}

.btn--quiet:hover,
.btn--quiet:focus-visible {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

/* --- Form -----------------------------------------------------------------
   One form per site (spec §6). POSTs to the endpoint constant in main.js;
   works as a plain HTML POST with JS off.                                  */

.form {
  display: grid;
  gap: var(--space-md);
  max-width: var(--layout-measure);
}

.field {
  display: grid;
  gap: var(--space-3xs);
}

.field__label {
  font-family: var(--font-chrome);
  font-size: var(--text-small);
  font-weight: var(--font-weight-body-strong);
  color: var(--color-ink);
}

.field__control {
  width: 100%;
  min-height: var(--layout-tap-min);
  padding: var(--space-2xs) var(--space-xs);
  background-color: var(--color-surface);
  color: var(--color-ink);
  border: var(--border-hairline) var(--border-style) var(--color-hairline);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
}

textarea.field__control {
  min-height: var(--space-3xl);
  resize: vertical;
}

.field__hint {
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

/* Service-interest checkboxes (brief §5.6). The fieldset carries no new copy
   — its accessible name is borrowed from the section's own h2 via
   aria-labelledby (house-tech-spec §12: the Builder writes no copy); each
   checkbox's own visible label reuses the four service names verbatim from
   §services above, not new text. */
.field--checks {
  border: 0;
  padding: 0;
  margin: 0;
}

.field__check {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: var(--layout-tap-min);
  font-family: var(--font-chrome);
  font-size: var(--text-body);
  font-weight: var(--font-weight-body);
  color: var(--color-ink);
}

.field__check input {
  width: var(--layout-tap-min);
  height: var(--layout-tap-min);
  accent-color: var(--color-accent-deep);
}

/* Honeypot: present in the DOM for bots, unreachable for humans and assistive
   tech. Not display:none — some bots skip those. */
.form__trap {
  position: absolute;
  /* @allow-literal: off-canvas parking position, not a design value */
  left: -9999px;
  opacity: 0;
  pointer-events: none;
}

.form__status {
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

.form__status[data-state='error'] {
  color: var(--color-ink);
  font-weight: var(--font-weight-body-strong);
}

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

.site-footer {
  padding-block: var(--space-xl);
  border-top: var(--border-thick) var(--border-style) var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-small);
  color: var(--color-ink);
}

.site-footer a {
  color: var(--color-accent);
  text-underline-offset: var(--space-3xs);
}

.site-footer__nap {
  font-style: normal;
  line-height: var(--leading-body);
}

/* Footer meta text (the copyright/rights line) — brief §4.4's chrome list. */
.site-footer small {
  font-family: var(--font-chrome);
}

/* ==========================================================================
   BRIEF COMPONENTS — brief.md (C3 PASS), family editorial-modern, archetype
   band-rhythm. Built FROM tokens (spec §3).
   ========================================================================== */

/* --- Eyebrow — chrome-only face (brief §4.4), every section head -------- */

.eyebrow {
  display: block;
  margin-block-end: var(--space-2xs);
  font-family: var(--font-chrome);
  font-size: var(--text-eyebrow);
  font-weight: var(--font-weight-body-strong);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}

h2 {
  font-size: var(--text-h2);
  color: var(--color-ink);
}

/* --- HERO — "the index draws" (brief §5.1, §7.3) --------------------------
   Single column at every width (band-rhythm has no split-hero state). The
   atmosphere is two radial washes fading to transparent over --color-bg,
   positioned exactly per brief §3.3's contrast-table rows 10–13. */

.hero {
  position: relative;
  border-top: var(--border-thick) var(--border-style) var(--color-ink);
  padding-block-start: var(--hero-pad-top);
  padding-block-end: var(--section-gap);
  background-image:
    radial-gradient(ellipse at 92% -12%, var(--color-atmo-1), transparent 60%),
    radial-gradient(ellipse at -12% 112%, var(--color-atmo-2), transparent 60%);
  background-color: var(--color-bg);
}

.hero__h1 {
  margin-block-start: var(--space-sm);
  font-size: var(--text-h1);
  color: var(--color-ink);
}

.hero__cta {
  margin-block-start: var(--space-md);
}

/* thanks.html's H1 — brief §8's plank-1 table: "2 line-boxes at --text-h2
   scale (confirmation + trade reference)", deliberately smaller than the
   homepage h1 since this page carries no living-hero field. */
.thanks__h1 {
  margin-block-start: var(--space-sm);
  font-size: var(--text-h2);
  color: var(--color-ink);
}

.hero__lead {
  max-width: var(--hero-lead-measure);
  margin-block-start: var(--space-md);
  color: var(--color-ink-muted);
}

/* --- The living-hero field — brief §6 slot 1 + §7.3 signature move --------
   The plate is the LCP element: real alt text, fetchpriority high, never
   lazy, explicit dimensions, AVIF+WebP (index.html). Two purely decorative
   motion layers on top realise "the index draws" exactly as C2-DECISION
   verified the tile's own working CSS (brief §7.4): a rule that draws once
   via a left-to-right wipe (rest state: fully revealed, opacity 0.7 — the
   verified tile value), and four small satellite marks at rest opacity 0.85,
   landing on the plate's own four evenly-spaced vignettes rather than
   reproducing their artwork a second time (design-rules §0: "adapt the
   physics, never the subject"). */

.hero__field {
  position: relative;
  overflow: clip;
  width: 100%;
  margin-block-start: var(--space-md);
  /* Brief §8's plank-1 table: 120px @375, 220px @1440 — a fluid height, not
     a fixed aspect-ratio (the field visibly widens more than it deepens at
     desktop, "the generous-desktop-hero allowance", design-rules §5). */
  height: var(--hero-field-height);
}

/* <picture> has no intrinsic size of its own, so the img's height:100%
   below needs an explicit height on this wrapper to resolve against —
   without it the img falls back to its natural aspect ratio and overflows
   the field's own fixed height. */
.hero__field picture {
  display: block;
  width: 100%;
  height: 100%;
}

.hero__plate {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The rule: a single horizontal line, vertically centred on the field,
   drawn once via stroke-dashoffset. Rest state (also the reduced-motion
   state, brief §7.4) is fully drawn at opacity 0.7 — the value C2-DECISION
   verified on the tile. viewBox is 100 units wide × 1 unit tall so
   pathLength-free dasharray math stays in round numbers regardless of the
   field's rendered size. */
.hero__rule {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.hero__rule-line {
  stroke: var(--color-ink);
  /* @allow-literal: viewBox-local stroke geometry, not a design size — the
     viewBox is deliberately non-square (1000×100) so a horizontal rule stays
     a hairline at every field height without vector-effect, which is what
     was mis-scaling stroke-dasharray into screen pixels and rendering a
     dashed line instead of a solid one. */
  stroke-width: 1.2;
  opacity: 0.7;
  stroke-dasharray: 1000;
  stroke-dashoffset: 0;
}

.hero__marks {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.hero__mark {
  position: absolute;
  top: 50%;
  /* @allow-literal: fixed satellite-mark diameter — a decorative dot, not a
     type or space value; scaled from --space-2xs so it still derives from
     the house scale rather than a bare literal */
  width: calc(var(--space-2xs) * 0.7);
  height: calc(var(--space-2xs) * 0.7);
  border-radius: var(--radius-pill);
  transform: translate(-50%, -50%) translateY(0);
  opacity: 0.85;
}

.hero__mark--1 { left: 12.5%; background-color: var(--color-accent); }
.hero__mark--2 { left: 37.5%; background-color: var(--color-accent-2); }
.hero__mark--3 { left: 62.5%; background-color: var(--color-accent); }
.hero__mark--4 { left: 87.5%; background-color: var(--color-accent-2); }

@media (prefers-reduced-motion: no-preference) {
  .hero__rule-line {
    stroke-dashoffset: 1000;
    animation: rule-draw var(--duration-rule-draw) var(--ease-signature) forwards;
  }

  .hero__mark {
    animation: settle-bob var(--duration-settle-1) var(--ease-settle) infinite alternate;
    animation-delay: calc(var(--duration-rule-draw) + var(--settle-stagger-1));
  }

  .hero__mark--2 {
    animation-duration: var(--duration-settle-2);
    animation-delay: calc(var(--duration-rule-draw) + var(--settle-stagger-2));
  }

  .hero__mark--3 {
    animation-duration: var(--duration-settle-3);
    animation-delay: calc(var(--duration-rule-draw) + var(--settle-stagger-3));
  }

  .hero__mark--4 {
    animation-duration: var(--duration-settle-4);
    animation-delay: calc(var(--duration-rule-draw) + var(--settle-stagger-4));
  }
}

@keyframes rule-draw {
  from { stroke-dashoffset: 1000; }
  to   { stroke-dashoffset: 0; }
}

@keyframes settle-bob {
  from { transform: translate(-50%, -50%) translateY(0); opacity: 0.85; }
  to   { transform: translate(-50%, -50%) translateY(calc(var(--settle-travel) * -1)); opacity: 1; }
}

/* --- Band-rhythm bands (brief §5.1) ----------------------------------------
   Alternating top-rule colour is the archetype's whole direction-change
   device: odd bands ink, even bands earth. */

.band--odd {
  border-top: var(--border-thick) var(--border-style) var(--color-ink);
}

.band--even {
  border-top: var(--border-thick) var(--border-style) var(--color-accent-2);
}

.band__cta {
  margin-block-start: var(--space-lg);
}

/* --- WHAT WE DO — pure typographic index (brief §5.3) ---------------------
   Digit numerals (01–04), fixed 1.5rem regardless of the surrounding
   heading's fluid size (brief §3.5 — the WCAG large-text floor this size
   guarantees for accent-2's 4.49:1 contrast). Single column below 60rem;
   4-column row at and above it (brief §5.1). */

.index-list {
  display: grid;
  gap: var(--space-lg);
  margin-block-start: var(--space-lg);
}

.index-row__heading {
  font-size: var(--text-h2);
}

.index-row__mark {
  font-size: var(--text-index-mark);
  line-height: 1;
}

.index-row__mark--accent { color: var(--color-accent); }
.index-row__mark--accent-2 { color: var(--color-accent-2); }

.index-row__desc {
  margin-block-start: var(--space-2xs);
  font-family: var(--font-body);
  color: var(--color-ink-muted);
}

/* @allow-literal: 60rem is the brief's own declared layout breakpoint
   (§5.1) — distinct from the house's two structural breakpoints (base.css),
   which govern chrome, not this archetype's content grid. */
@media (min-width: 60rem) {
  .index-list {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* --- WHO DOES THE WORK — letter-indexed (brief §5.4) -----------------------
   Distinct numeral system (letters, not digits) AND distinct colour role
   (neutral ink, not an accent hue) from §services — design-rules §5's
   two-axis nested-counter rule. Single column below 60rem; the band's own
   grid becomes 2 columns at and above it (brief §5.1): the who-list (both
   rows) in column 1, the image in column 2, aligned beside row B. */

.who-grid {
  display: grid;
  gap: var(--space-lg);
  margin-block-start: var(--space-lg);
}

.who-list {
  display: grid;
  gap: var(--space-lg);
}

.who-row__heading {
  font-size: var(--text-h2);
}

.who-row__mark {
  font-size: var(--text-index-mark);
  line-height: 1;
  color: var(--color-ink);
}

.who-row__desc {
  margin-block-start: var(--space-2xs);
  font-family: var(--font-body);
  color: var(--color-ink-muted);
}

.who-image picture,
.who-image img {
  display: block;
  width: 100%;
  height: auto;
}

/* @allow-literal: 60rem, the brief's declared layout breakpoint (§5.1) */
@media (min-width: 60rem) {
  .who-grid {
    grid-template-columns: repeat(2, 1fr);
    align-items: center;
  }
}

/* --- FAQ (brief §5.5) — native <details>/<summary>, zero JS --------------- */

.faq-list {
  display: grid;
  gap: var(--space-sm);
  margin-block-start: var(--space-lg);
}

.faq-item {
  padding-block-end: var(--space-sm);
  border-bottom: var(--border-hairline) var(--border-style) var(--color-hairline);
}

.faq-item:last-child {
  border-bottom: 0;
  padding-block-end: 0;
}

.faq-item summary {
  cursor: pointer;
  padding-block: var(--space-xs);
}

.faq-item summary::-webkit-details-marker {
  color: var(--color-accent);
}

.faq-item__q {
  display: inline;
  font-size: var(--text-h2);
}

.faq-item p {
  margin-block-start: var(--space-2xs);
  max-width: var(--layout-measure);
  font-family: var(--font-body);
  color: var(--color-ink-muted);
}

/* --- QUOTE FORM band (brief §5.6) ------------------------------------------ */

.quote-area {
  margin-block-start: var(--space-2xs);
  font-family: var(--font-body);
  color: var(--color-ink-muted);
}

.quote-image {
  margin-block: var(--space-lg);
  overflow: clip;
}

.quote-image picture,
.quote-image img {
  display: block;
  width: 100%;
  height: auto;
}

.form {
  margin-block-start: var(--space-lg);
}
