/* ==========================================================================
   site.css — per-site layout & components, built FROM tokens.

   HARD RULE (house-tech-spec §3): tokens only, no raw hex/px/font literal.
   Escape hatches: house breakpoints, `@allow-literal: reason` comments.

   Brief: runs/eagle-landscaping-grand-junction-co/brief.md — editorial-modern
   / asymmetric-collage — signature "the field notes settle" (§4.3, §7)
   ========================================================================== */

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

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

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

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

/* --- Heading emphasis (brief §2.6) -----------------------------------------
   The italic accent word inside an h1/h2 — explicitly 500 italic, never
   inherited from the 600 upright parent (brief §2.1's own correction of the
   tile's stale rule). Scope is closed: H1's accent word, each h2's accent
   word — never body prose, card copy or FAQ text (brief §2.6). */
h1 em,
h2 em {
  font-style: italic;
  font-weight: var(--font-weight-emphasis);
  color: var(--color-accent-strong);
}

/* base.css's h1-h4 rule reads --tracking-tight for letter-spacing, but the
   brief (§2.7) scopes that token's VALUE to footer meta only and states no
   heading tracking at all — so headings reset to normal rather than
   silently inheriting a value the brief never assigned to that role. */
h1, h2, h3 {
  letter-spacing: normal;
}

h2, h3 {
  line-height: var(--leading-h2);
}

/* --- Header (brief §4.4 step 1) --------------------------------------------
   Fixed 56px height + 1px border-bottom at every breakpoint. Wordmark, then
   the tel: link (persistent, visible at 375 without opening the menu), then
   the collapsible Services/Contact nav. Sticky, stacked under the sticky
   preview expiry bar (css/preview.css; brief §5's 101px sticky-chrome term). */

.site-header {
  position: relative;
  z-index: var(--z-header);
  block-size: var(--layout-header-height);
  border-bottom: var(--border-hairline) var(--border-style) var(--color-border);
  background-color: var(--color-bg);
}

.site-header__inner {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--space-sm);
  block-size: 100%;
}

.site-header__brand {
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: var(--font-weight-display);
  font-style: normal;
  color: var(--color-ink);
  text-decoration: none;
  white-space: nowrap;
}

.site-header__phone {
  font-family: var(--font-body);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-small);
  color: var(--color-accent);
  text-decoration: none;
  white-space: nowrap;
  margin-inline-start: auto;
}

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

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

.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);
  color: var(--color-ink);
}

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

.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 ---------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  padding-inline: var(--space-md);
  border: var(--border-hairline) var(--border-style) transparent;
  border-radius: var(--radius-none);
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-style: normal;
  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 {
  block-size: var(--cta-height);
  background-color: var(--color-accent-strong);
  color: var(--color-accent-ink);
}

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

/* --- Form -------------------------------------------------------------------
   Shape 1 (brief §4.5): name / phone / message, no email field. A form
   field's border is a real control boundary, not decoration — --color-border
   is restricted to decorative hairlines only (R5), so fields and buttons use
   --color-ink-muted instead (5.80:1 vs bg, 5.17:1 vs surface, brief §3.3). */

.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-body);
  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-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  border: var(--border-hairline) var(--border-style) var(--color-ink-muted);
  border-radius: var(--radius-none);
}

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

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

.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);
  color: var(--color-ink-muted);
}

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

.site-footer__nap {
  font-style: normal;
  color: var(--color-ink);
}

.site-footer p {
  margin-block-start: var(--space-sm);
  /* brief §2.7: footer meta carries the site's own --tracking-tight value */
  letter-spacing: var(--tracking-tight);
}

/* ============================================================================
   BRIEF COMPONENTS — runs/eagle-landscaping-grand-junction-co/brief.md
   ============================================================================ */

/* --- Section head, the page's spine (brief §4.1 rule 4) --------------------
   Every section head is the same three-part object: caps eyebrow (accent),
   h2 with one italic accent word (accent-strong), and — Field Notes/FAQ
   only — a small decorative accent image beside it. */

.eyebrow {
  margin-block-end: var(--space-xs);
  font-family: var(--font-body);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-eyebrow);
  line-height: var(--leading-caps);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--color-accent);
}

.section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-md);
  margin-block-end: var(--space-lg);
}

.section__head-text {
  flex: 1 1 auto;
  min-width: 0;
}

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

.section__head-accent {
  flex: 0 0 auto;
  /* the brief names no explicit accent-image size; --space-xl (96px) is the
     nearest house-scale step to the tile's own small decorative-icon
     register, reused rather than a new raw literal. */
  inline-size: var(--space-xl);
  overflow: hidden;
  border: var(--border-hairline) var(--border-style) var(--color-border);
}

.section__head-accent img {
  display: block;
  width: 100%;
  height: auto;
}

/* --- Hero (brief §4.1, §4.2, §4.3, §5) --------------------------------------
   DOM order fixed at every width: eyebrow -> H1 -> primary CTA -> field ->
   secondary CTA (rule 1). At >=48rem: two unequal columns (46/54), field
   offset 24px lower than the text column's own top (rule 2). Ground is the
   two-stop atmosphere gradient (brief §3.4), computed against its darkest
   stop, #EDE4D2. */

.hero {
  position: relative;
  padding-block-start: var(--space-sm);
  padding-block-end: var(--section-gap);
  background: linear-gradient(160deg, var(--color-atmos-hi) 0%, var(--color-atmos-lo) 100%);
  color: var(--color-ink);
}

@media (min-width: 48em) {
  .hero {
    padding-block-start: var(--space-2xl);
  }
}

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

.hero__title {
  margin-block-end: var(--space-md);
  font-size: var(--text-h1);
  line-height: var(--leading-tight);
}

@media (min-width: 48em) {
  .hero__eyebrow {
    margin-block-end: var(--space-sm);
  }

  .hero__title {
    margin-block-end: var(--space-lg);
  }
}

.hero__cta-row {
  margin: 0;
}

.hero__cta-secondary-row {
  margin-block-start: var(--space-sm);
}

.hero__cta-secondary {
  display: inline-block;
  font-size: var(--text-small);
  color: var(--color-ink-muted);
  text-decoration: underline;
  text-underline-offset: var(--space-3xs);
}

/* --- The signature device: "the field notes settle" (brief §4.3, §7) -------
   viewBox 0 0 375 220, unchanged from the C2-verified tile
   (tiles/tile-b.html): card-1 spans x:[14,142], card-2 spans x:[180,308] —
   a proportional, never-closing gap at any width (§4.3). Two abstract note
   cards (line-and-rule only, no simulated text) + a marker pin + a sprig.
   aspect-ratio keeps the 375:220 field ratio at both breakpoints (§5). This
   base rule MUST precede the ">=48rem" override below: an unconditional
   rule after a media-query rule of equal specificity wins regardless of
   width (found in self-check — desktop's `position: absolute` was being
   silently discarded when this sat later in the file). */

.hero__field-wrap {
  position: relative;
  aspect-ratio: 375 / 220;
  overflow: hidden;
  background-color: var(--color-field-bg);
  border: var(--border-hairline) var(--border-style) var(--color-field-border);
}

/* Two unequal columns at >=48rem, 46%/54% with the gap fairly divided
   (brief §4.1 rule 2, §4.2; README flags the table's own pixel cells as
   internally inconsistent). NOT CSS Grid: two earlier drafts let Grid's
   track-sizing distribute the field's own height onto whichever row(s)
   it shared with shorter text, inflating the gap around it (self-check).
   The field is out of flow instead (absolute, relative to .hero__inner),
   so its height never sizes anything the text stack shares. */
@media (min-width: 48em) {
  .hero__inner {
    position: relative;
  }

  .hero__text {
    max-inline-size: calc(46% - (var(--space-lg) / 2));
  }

  .hero__field-wrap {
    position: absolute;
    inset-inline-end: 0;
    /* the field's own stated 24px downward offset from the text column's
       top (rule 2) — .hero__inner IS that top, since .hero__text carries
       no padding-block-start of its own. */
    inset-block-start: var(--space-md);
    inline-size: calc(54% - (var(--space-lg) / 2));
  }
}

.hero__field {
  display: block;
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  z-index: var(--z-field-svg);
}

/* Position lives on an un-animated ancestor <g>; rotation/opacity animate on
   the inner <g> — a CSS transform animation replaces an attribute transform
   outright on the same element (df-landscapes sibling finding), so the two
   are split across ancestor/child instead. */
.card-1,
.card-2 {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  opacity: 0;
  /* base = SETTLED end-state so a reduced-motion visitor (no animation
     applied at all) sees the finished composition immediately. */
  opacity: 1;
  transform: rotate(-3.5deg);
}

.card-2 {
  transform: rotate(2.5deg);
}

.pin-sway {
  transform-box: fill-box;
  transform-origin: 50% 0%;
}

.sprig-group {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  /* base = fully open, at rest — the reduced-motion still frame */
  opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
  .card-1 {
    opacity: 0;
    animation: cardSettle1 var(--duration-card-1) var(--ease-settle) forwards;
  }

  .card-2 {
    opacity: 0;
    animation: cardSettle2 var(--duration-card-2) var(--ease-settle) var(--delay-card-2) forwards;
  }

  .pin-sway {
    animation: pinSway var(--duration-pin-sway) ease-in-out infinite var(--delay-pin-sway);
  }

  /* One-shot unfurl + independent sway, combined into one comma-separated
     `animation` declaration — two shorthands on the same element in two
     rules would not compose (df-landscapes sibling finding). */
  .sprig-group {
    opacity: 0;
    animation:
      sprigOpen var(--duration-sprig-open) var(--ease-out) forwards,
      sprigSway var(--duration-sprig-sway) ease-in-out infinite var(--delay-sprig-sway);
  }
}

@keyframes cardSettle1 {
  0%   { transform: translate(var(--card-1-drift-x), var(--card-1-drift-y)) rotate(-11deg); opacity: 0; }
  100% { transform: translate(0, 0) rotate(-3.5deg); opacity: 1; }
}

@keyframes cardSettle2 {
  0%   { transform: translate(var(--card-2-drift-x), var(--card-2-drift-y)) rotate(9deg); opacity: 0; }
  100% { transform: translate(0, 0) rotate(2.5deg); opacity: 1; }
}

@keyframes pinSway {
  0%, 100% { transform: rotate(-2.2deg); }
  50%      { transform: rotate(2.2deg); }
}

@keyframes sprigOpen {
  0%   { transform: rotate(-70deg) scale(0.5); opacity: 0; }
  100% { transform: rotate(0deg) scale(1); opacity: 1; }
}

@keyframes sprigSway {
  0%, 100% { transform: rotate(-3deg); }
  50%      { transform: rotate(3deg); }
}

/* --- Field Notes (#field-notes, brief §4.3, §4.4 step 3) --------------------
   Two real HTML cards, computed non-overlap: card_width 260px fixed >=768,
   48px gap (n2.left = 260+48 = 308), n2 offset 64px lower than n1. Below
   768: normal document flow, stacked, 24px gap, reduced rotation — overlap
   is structurally impossible in flow layout regardless of rotation. */

.notes-grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* data-reveal (opacity + translateY, base.css) sits on this wrapper, never
   on .note-card itself — base.css sets `transform` directly on [data-reveal],
   which would replace rather than compose with the card's own permanent
   rotation (and force it to `none` under reduced motion). Split onto
   parent/child so the two transforms stay independent. */
.note-card-reveal {
  max-width: var(--note-card-max-width);
}

.note-card {
  padding: var(--space-md);
  background-color: var(--color-bg);
  border: var(--border-hairline) var(--border-style) var(--color-border);
  box-shadow: var(--shadow-card);
  transform: rotate(-2deg);
}

.note-card--n2 {
  transform: rotate(1.5deg);
}

.note-card__tag {
  display: block;
  margin-block-end: var(--space-2xs);
  font-family: var(--font-body);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-eyebrow);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--color-accent-strong);
}

.note-card__body {
  margin: 0;
  font-size: var(--text-body);
  color: var(--color-ink);
}

@media (min-width: 48em) {
  .notes-grid {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--field-note-gap);
  }

  .note-card-reveal {
    flex: 0 0 var(--field-note-card-width);
    max-width: none;
  }

  .note-card-reveal--n2 {
    margin-block-start: var(--space-xl);
  }

  .note-card {
    transform: rotate(-3.5deg);
  }

  .note-card--n2 {
    transform: rotate(2.5deg);
  }
}

/* --- Trust-strip (#trust, brief §4.4 step 4) --------------------------------
   The three V-tier facts this dossier supports, each with a sage
   leaf-glyph icon (icon-fill only, R6 — sage never carries text). The
   local-character band image sits behind the section as a low-opacity CSS
   background (brief §6 slot 3) — no text sits directly on it above
   --color-ink-muted's own already-validated pairing against --color-bg. */

.trust {
  position: relative;
  overflow: hidden;
}

.trust__band {
  position: absolute;
  inset: 0;
  z-index: var(--z-atmosphere);
  background-image: url('../assets/img/high-desert-valley-band.webp');
  background-image: image-set(
    url('../assets/img/high-desert-valley-band.avif') type('image/avif'),
    url('../assets/img/high-desert-valley-band.webp') type('image/webp')
  );
  background-size: cover;
  background-position: center;
  /* @allow-literal: opacity is a unitless ratio, not a size/colour/font value */
  opacity: 0.32;
}

.trust .container {
  position: relative;
  z-index: 2;
}

.trust-list {
  display: grid;
  gap: var(--space-md);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 48em) {
  .trust-list {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-lg);
  }
}

.trust-list__item {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.trust-list__icon {
  flex: 0 0 auto;
  inline-size: var(--space-lg);
  block-size: var(--space-lg);
  fill: var(--color-accent-2);
}

.trust-list__label {
  font-size: var(--text-body);
  font-weight: var(--font-weight-body-strong);
  color: var(--color-ink);
}

/* --- FAQ (#faq, brief §4.4 step 5) ------------------------------------------
   Native <details>/<summary>, no JS, no icon rotation state beyond what the
   browser gives for free. */

.faq-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}

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

.faq-item summary {
  padding-block: var(--space-xs);
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-body);
  color: var(--color-ink);
  cursor: pointer;
}

.faq-item summary:hover,
.faq-item summary:focus-visible {
  color: var(--color-accent);
}

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

/* --- Final CTA / contact block (#contact, brief §4.4 step 6) ---------------- */

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

.contact__cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
  margin-block-end: var(--space-lg);
}

.contact__phone {
  font-size: var(--text-small);
  font-weight: var(--font-weight-body-strong);
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: var(--space-3xs);
}

/* --- thanks.html (brief §4.7) -----------------------------------------------
   A thin confirmation page, no second living-hero (§0 permits exactly one
   spectacular moment per site). Reuses the hero's own tighter rhythm
   tokens at the same breakpoints (brief §5's mirrored gap table). */

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

.thanks__eyebrow {
  margin-block-end: var(--space-xs);
}

.thanks__title {
  margin-block-end: var(--space-sm);
  font-size: var(--text-h2);
}

@media (min-width: 48em) {
  .thanks__eyebrow {
    margin-block-end: var(--space-sm);
  }

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

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

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