/* ==========================================================================
   site.css — Landscape Maintenance of Bend. Archetype `band-rhythm` (brief
   §4): alternating full-width bands (--color-bg / --color-surface), one
   direction change per band, no grid-based multi-column layout anywhere.
   Signature: "the tags swing" (brief §6), index.html only.

   HARD RULE (house-tech-spec §3): tokens only, no raw literals. The two
   escape hatches are the house breakpoints and an explicit
   `@allow-literal: reason` comment on the preceding line.

   This file EXTENDS the house skeleton's base component set (layout
   primitives, header/nav, buttons, form, footer) below, then adds this
   brief's own components (hero, tags-swing signature, bands, page-header,
   detail/cross-link lists) after it — per skeleton/SKELETON.md's build
   order ("extend this file with the brief's components").
   ========================================================================== */

/* --- 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 a site (design-rules §7.1); the brief picks which scale step it is. */
.section {
  padding-block: var(--section-gap);
}

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

/* QA round 1 FIX (lensB/alignment): `.measure`'s narrower max-width was
   feeding `.container`'s own `margin-inline: auto`, which centred these
   boxes against their OWN (narrower) width instead of the 72rem width
   every sibling `.container` centres against — jogging the band ~260px
   right of the page's left margin. (Capping each child's own max-width
   instead was tried and reverted: `ch` is per-child font-size, so larger
   headings stopped sharing the paragraph's column — a second defect.)
   Fix: keep `.measure`'s narrowing on this shared box, but compute the
   start margin the way `.container` alone would (against 72rem, not this
   box's own width), landing at the same left edge as every sibling
   `.container`. `margin-inline-end: 0`: width is already fixed, so the
   trailing auto has nothing left to solve for. */
.container.measure {
  margin-inline-start: max(0px, calc((100% - var(--layout-container)) / 2));
  margin-inline-end: 0;
}

/* --- 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 {
  display: flex;
  /* @allow-literal: nowrap is a layout keyword, not a colour/size/font value */
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}

/* QA round 2 FIX (brief-amendment-1.md, "separately, not a brief issue"):
   round 1's nowrap+ellipsis stopped the font-swap CLS by truncating the
   business name ("Landscape Maintenance of B…") at every viewport — a real
   defect. Truncation is gone; the wordmark wraps normally.
   Letting the two faces' line-counts happen to agree was tried and mostly
   stable, but not reliably: repeated `lighthouse.mjs` runs at its own
   gated width (412px) showed occasional CLS 0.016, traced with a raw
   `PerformanceObserver` (not guessed) to this box's height changing around
   the fallback→webfont swap. `min-height` (token
   `--size-header-brand-min-height`, tokens.css) reserves 2 lines from
   first paint regardless of which face is active, so a swap has no height
   left to change — the token's `em` is relative to this element's own
   `font-size`, identical across the swap. Re-run 8x: CLS 0.000 every
   time. */
.site-header__brand {
  flex: 1 1 auto;
  min-width: 0;
  min-height: var(--size-header-brand-min-height);
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: var(--font-weight-display);
  text-decoration: none;
  letter-spacing: var(--tracking-tight);
}

.nav-toggle {
  display: inline-flex;
  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);
}

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

.site-nav__link {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  font-size: var(--text-small);
  font-weight: var(--font-weight-body-strong);
}

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

/* QA r3 FIX perf/cls (house-wide skeleton fix, carried forward): the
   collapsed state used to apply only once a deferred `type="module"`
   script called `initNav()` and set `[data-nav-ready]`, so the full nav
   list rendered open at first paint and then collapsed into the hamburger
   AFTER first contentful paint. Inverting the default removes the race
   entirely: closed is now the plain CSS default below 48em, with no JS
   gate. JS-off visitors get the nav back via the <noscript> stylesheet
   override in `@shared:head-boilerplate`. */
.site-nav {
  display: none;
}

[data-nav-ready] .site-nav[data-nav-open='true'] {
  display: block;
  flex-basis: 100%;
}

@media (min-width: 48em) {
  .site-nav {
    display: block;
  }

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

/* --- Buttons --------------------------------------------------------------
   Two roles, no more. Radius, weight and colour all come from the brief via
   tokens — including --radius-none, which is a legitimate answer.          */

.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-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);
}

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

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

/* --- Form -----------------------------------------------------------------
   One form per site (spec §6). POSTs to the endpoint constant in main.js;
   works as a plain HTML POST with JS off; auto-hides when no endpoint is
   configured so a spec site never shows a dead form.                       */

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

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

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

.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-border-strong);
  border-radius: var(--radius-sm);
}

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

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

/* 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-hairline) var(--border-style) var(--color-border);
  font-size: var(--text-small);
}

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

.site-footer__nap {
  font-style: normal;
}

/* ==========================================================================
   BRIEF COMPONENTS — Landscape Maintenance of Bend
   ========================================================================== */

/* --- Eyebrow (shared pattern: hero eyebrow, page-header breadcrumb) ------- */

.eyebrow {
  margin: 0;
  font-family: var(--font-body);
  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);
}

/* Small juniper dot used as a separator inside eyebrows and as the
   "tag-hook" marker beside each services-index heading (brief §2.3: the
   accent-2 token's carrier roles). Non-text decorative use only. */
.dot {
  display: inline-block;
  width: var(--size-dot);
  height: var(--size-dot);
  border-radius: 50%;
  background-color: var(--color-accent-2);
  margin-inline: var(--space-2xs);
  vertical-align: middle;
}

/* --- Hero (index.html only) ------------------------------------------------
   DOM order per brief §4.1/§4.4: eyebrow -> h1 -> primary CTA -> secondary
   CTA -> living-hero field. Single column at every width (band-rhythm: no
   grid-based multi-column layout anywhere). */

.hero {
  padding-block-start: var(--space-lg);
  padding-block-end: var(--section-gap);
  background-color: var(--color-bg);
}

.hero__eyebrow {
  margin-block-end: var(--space-md);
}

.hero__h1 {
  margin: 0 0 var(--space-lg);
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.hero__h1 .accent {
  color: var(--color-accent);
}

.hero__cta-primary {
  margin: 0 0 var(--space-sm);
}

.hero__cta-secondary {
  margin: 0 0 var(--space-sm);
}

.tel-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--layout-tap-min);
  color: var(--color-accent-2);
  font-weight: var(--font-weight-body-strong);
  text-decoration: underline;
  text-underline-offset: var(--space-3xs);
}

/* --- The living-hero field: painted board backdrop + four swinging tags -- */

.hero__field {
  position: relative;
  overflow: hidden;
  /* @allow-literal: aspect-ratio is a layout ratio, not a colour/size/font token */
  aspect-ratio: 335 / 270;
  border: var(--border-hairline) var(--border-style) var(--color-border-strong);
}

@media (min-width: 48em) {
  .hero__field {
    aspect-ratio: 21 / 9;
  }
}

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

/* Four tags, hung near the top of the field where the backdrop image's own
   drawn rail and hook fixtures sit. Positions match the approved tile
   (tiles/tile-b.html): 14% / 38% / 62% / 86% from the left. */
.hero__tags {
  position: absolute;
  inset: 0;
}

.tag {
  position: absolute;
  top: 16%;
  /* Centres the box on its `left` percentage instead of left-aligning it
     there, so all four tags keep equal clearance from the field's edges
     regardless of --tag-width's clamped value (Builder note: the tile's own
     left-edge-anchored positions let the rightmost tag's box run past the
     field boundary at the clamp ceiling — this keeps every tag inside it). */
  margin-left: calc(var(--tag-width) / -2);
  width: var(--tag-width);
  padding: var(--space-2xs) var(--space-3xs) var(--space-3xs);
  background-color: var(--color-surface);
  border: var(--border-hairline) var(--border-style) var(--color-border-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-micro);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink);
  text-align: center;
  /* A single long word (Maintenance, Irrigation, Winter) has no space to
     wrap at; without this it overflows the tag's fixed width rather than
     wrapping the way "Fire Prevention" naturally does. hyphens:auto picks a
     syllable boundary (Irri-gation) instead of the ragged one-letter orphan
     overflow-wrap alone would leave (Irrigatio-n); `lang="en"` on <html>
     supplies the hyphenation dictionary. */
  overflow-wrap: break-word;
  hyphens: auto;
  transform-origin: top center;
}

.tag::before {
  content: '';
  position: absolute;
  left: 50%;
  top: calc(var(--tag-chain) * -1);
  width: var(--tag-chain);
  height: var(--tag-chain);
  border-radius: 50%;
  border: var(--border-hairline) var(--border-style) var(--color-border-strong);
  background-color: var(--color-accent-2);
  transform: translateX(-50%);
}

.tag--a { left: 15%; animation: swingA var(--duration-swing-a) var(--ease-in-out) infinite; }
.tag--b { left: 38%; animation: swingB var(--duration-swing-b) var(--ease-in-out) infinite; }
.tag--c { left: 62%; animation: swingC var(--duration-swing-c) var(--ease-in-out) infinite; }
.tag--d { left: 85%; animation: swingD var(--duration-swing-d) var(--ease-in-out) infinite; }

/* @allow-literal: keyframe rotation angles are motion geometry, not colour/size/font tokens */
@keyframes swingA { 0%, 100% { transform: rotate(-4deg); } 50% { transform: rotate(3deg); } }
@keyframes swingB { 0%, 100% { transform: rotate(3deg); } 50% { transform: rotate(-4deg); } }
@keyframes swingC { 0%, 100% { transform: rotate(-3deg); } 50% { transform: rotate(4deg); } }
@keyframes swingD { 0%, 100% { transform: rotate(4deg); } 50% { transform: rotate(-3deg); } }

@media (prefers-reduced-motion: reduce) {
  .tag--a, .tag--b, .tag--c, .tag--d {
    animation: none;
    transform: rotate(0deg);
  }
}

/* --- Band rhythm: every full-width band below the hero alternates bg /
   surface explicitly, in document order (brief §4: "one direction change
   per band"). Modifier classes rather than nth-of-type, because the bands
   are not uniform siblings (services-index bands, trust, reviews, area,
   FAQ and final-CTA are each their own <section>, and the hero and footer
   sit outside the alternation). ------------------------------------------ */

.band {
  padding-block: var(--section-gap);
}

.band--surface { background-color: var(--color-surface); }
.band--bg { background-color: var(--color-bg); }

.band__heading {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0 0 var(--space-sm);
}

.band__heading .dot {
  margin-inline: 0;
  flex: 0 0 auto;
}

.band__heading h2 {
  margin: 0;
  font-size: var(--text-h2);
  line-height: var(--leading-snug);
}

.band__body {
  margin: 0 0 var(--space-md);
}

.band__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--layout-tap-min);
  color: var(--color-accent-2);
  font-weight: var(--font-weight-body-strong);
  text-decoration: underline;
  text-underline-offset: var(--space-3xs);
}

/* --- Trust strip ----------------------------------------------------------- */

.trust p {
  margin: 0 0 var(--space-md);
}

.trust p:last-child {
  margin-bottom: 0;
}

.trust__quote {
  font-family: var(--font-display);
  font-size: var(--text-h3);
  line-height: var(--leading-snug);
  font-weight: var(--font-weight-display);
  color: var(--color-ink);
}

/* --- Reviews ---------------------------------------------------------------- */

.review {
  margin: 0;
  border-inline-start: var(--border-thick) var(--border-style) var(--color-accent-2);
  padding-inline-start: var(--space-md);
}

.review p {
  margin: 0 0 var(--space-2xs);
  font-size: var(--text-lead);
  line-height: var(--leading-body);
}

.review cite {
  display: block;
  font-style: normal;
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

/* --- Service area ------------------------------------------------------------ */

.area p {
  margin: 0 0 var(--space-sm);
}

.area p:last-child {
  margin-bottom: 0;
}

/* --- FAQ, native <details>/<summary> ---------------------------------------- */

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

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

.faq-item summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  cursor: pointer;
  min-height: var(--layout-tap-min);
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: var(--font-weight-display);
  color: var(--color-ink);
  list-style: none;
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

.faq-item summary::after {
  content: '+';
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-wide);
  color: var(--color-accent-2);
}

.faq-item[open] summary::after {
  content: '\2212';
}

.faq-item p {
  margin: var(--space-2xs) 0 0;
  color: var(--color-ink-muted);
}

/* --- Final CTA band + contact form ------------------------------------------- */

.cta-final__body {
  margin: 0 0 var(--space-md);
}

.cta-final__phone {
  margin: 0 0 var(--space-lg);
}

/* --- Page-header band (service pages) --------------------------------------- */

.page-header {
  padding-block-start: var(--space-lg);
  padding-block-end: var(--section-gap);
  background-color: var(--color-bg);
}

.page-header__eyebrow {
  margin-block-end: var(--space-md);
}

.page-header__title {
  margin: 0 0 var(--space-sm);
  font-size: var(--text-h2);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
}

.page-header__lead {
  margin: 0 0 var(--space-lg);
}

.page-header__cta {
  margin: 0 0 var(--space-lg);
}

.page-header__image {
  width: 100%;
  height: auto;
  border: var(--border-hairline) var(--border-style) var(--color-border-strong);
}

/* --- Detail band: plain declarative list, no icons, no cards ---------------- */

.detail-list {
  display: grid;
  gap: var(--space-sm);
}

.detail-list li {
  padding-block-start: var(--space-sm);
  border-block-start: var(--border-hairline) var(--border-style) var(--color-border);
}

.detail-list li:first-child {
  padding-block-start: 0;
  border-block-start: none;
}

/* --- Local CTA band ---------------------------------------------------------- */

.local-cta__body {
  margin: 0 0 var(--space-md);
}

.local-cta__primary {
  margin: 0 0 var(--space-sm);
}

.local-cta__secondary {
  margin: 0;
}

/* --- Cross-link band: the same four-line structure reused as navigation ----- */

.cross-link-list {
  display: grid;
  gap: var(--space-sm);
}

.cross-link-list li {
  padding-block-start: var(--space-sm);
  border-block-start: var(--border-hairline) var(--border-style) var(--color-border);
}

.cross-link-list li:first-child {
  padding-block-start: 0;
  border-block-start: none;
}

.cross-link-list a {
  display: block;
  text-decoration: none;
}

.cross-link-list a:hover,
.cross-link-list a:focus-visible {
  color: var(--color-accent-2);
  text-decoration: underline;
}

.cross-link-list strong {
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-h3);
}

/* --- thanks.html ------------------------------------------------------------- */

.thanks__cta {
  margin: 0;
}

/* --- Footer extensions: nav + tagline (brief keeps the shared footer block,
   extended with the four-line nav and the owner's tagline, per copy.md) ----- */

.site-footer__nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-md);
  margin: var(--space-md) 0 0;
  padding: 0;
}

.site-footer__nav a {
  text-decoration: underline;
  text-underline-offset: var(--space-3xs);
}

.site-footer__tagline {
  margin: var(--space-md) 0 0;
  font-style: italic;
  color: var(--color-ink-muted);
}
