/* ==========================================================================
   site.css — Franklin's Lawn Care. Per-site layout & components, built FROM
   tokens (house-tech-spec §3). No raw hex, no px/rem size literal, no
   font-name literal in this file — tokens only, except the house breakpoints
   (48em/64em) and this brief's own 40em nav breakpoint (brief §5.3 step 1),
   both inside @media conditions, the documented escape hatch.
   ========================================================================== */

/* --- 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);
}

/* Every strong/b emphasis switches to the display face rather than a bold
   Barlow — Barlow ships only 400/400-italic on this site (brief §2.2), so a
   heavier body weight does not exist to fall back on. This is the same role
   the brief's own type table (§2.6) assigns "footer meta labels." */
strong, b {
  font-family: var(--font-display);
  font-weight: var(--font-weight-display-strong);
}

/* --- Header & navigation ----------------------------------------------------
   Brief §5.3 step 1: wordmark + tel: CTA on one line to 320px; no anchor nav
   below 640px, four links at >=640px. No toggle: the mobile header has no
   room for a third control once wordmark+CTA fill 320px, so the collapse is
   pure CSS, and the noscript override in @shared:head-boilerplate shows the
   links when JS cannot offer another way to reach them (spec §1). Fixed
   height <=56px + 1px border at every width. */

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

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

.site-header__brand {
  font-family: var(--font-display);
  font-size: var(--text-small);
  font-weight: var(--font-weight-display-strong);
  color: var(--color-ink);
  text-decoration: none;
  letter-spacing: var(--tracking-tight);
  white-space: nowrap;
}

.site-nav {
  display: none;
}

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

.site-nav__link {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: var(--font-weight-display-strong);
  font-size: var(--text-small);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  line-height: var(--leading-caps);
  color: var(--color-ink);
  text-decoration: none;
  white-space: nowrap;
}

.site-nav__link:hover,
.site-nav__link:focus-visible {
  color: var(--color-accent);
}

/* Brief's own value, 640px — distinct from the house 48em/64em breakpoints
   used elsewhere on this site (field height, gutter). Literal is the
   documented escape hatch inside a media-query condition. */
@media (min-width: 40em) {
  .site-nav {
    display: block;
  }
}

/* --- Buttons ----------------------------------------------------------------
   Brief §2.6: buttons carry the display face at weight 600, uppercase,
   tracking-caps — the same treatment as the eyebrow and hero tag labels.
   Flat corners everywhere (--radius-none, brief §3). */

.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-none);
  font-family: var(--font-display);
  font-weight: var(--font-weight-display-strong);
  font-size: var(--text-button);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  line-height: var(--leading-caps);
  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--primary:hover,
.btn--primary:focus-visible {
  /* R3: darkening the fill can only raise contrast against the fixed white
     label — never a trade against AA. */
  background-color: var(--color-accent-hover);
}

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

/* Narrower than a standard .btn so wordmark + CTA fit 320px (brief §5.3.1). */
.site-header__cta {
  flex: 0 0 auto;
  padding-inline: var(--space-2xs);
  font-size: var(--text-small);
  white-space: nowrap;
}

/* --- Hero — asymmetric-collage (brief §5, §7) -------------------------------
   Single-column flow at every width (brief §7.1/§7.2 both stack the same
   order); only the field height and hero padding-block-start step up at
   >=768. Dark radial-gradient ground; no scrim needed (brief §4.4 — 0% of
   the hero text block falls below AA at either gradient stop). */

.hero {
  position: relative;
  /* background-color set separately from the gradient image, to its
     lightest stop (the worst-case point for the text on it, brief §4.4) —
     a `background` shorthand leaves background-color at its transparent
     initial value, which is invisible to any tool that reads
     background-color and would otherwise report contrast against whatever
     sits behind the hero instead of the hero itself. */
  background-color: var(--hero-dark-2);
  background-image: radial-gradient(140% 100% at 30% 0%, var(--hero-dark-2) 0%, var(--hero-dark) 65%);
  color: var(--color-bg);
  padding-block-start: var(--space-sm);
  padding-block-end: var(--section-gap);
}

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

.hero__inner {
  display: flex;
  flex-direction: column;
}

.hero__eyebrow {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--font-weight-display-strong);
  font-size: var(--text-eyebrow);
  line-height: var(--leading-caps);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--color-tag-eyebrow);
}

/* thanks.html reuses the eyebrow treatment on the light page ground, where
   --color-tag-eyebrow (tuned for the hero's dark ground) fails AA — swap to
   the page's own accent-ink role, already validated at 5.28:1 (brief §4.3
   row 7). */
.hero__eyebrow--onlight {
  color: var(--color-accent-text);
}

.hero__title {
  margin: var(--space-xs) 0 0 0;
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-h1);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-transform: uppercase;
  color: var(--color-bg);
}

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

.hero__field {
  position: relative;
  z-index: var(--z-field);
  block-size: var(--field-height);
  margin: var(--space-md) 0 0 0;
  overflow: visible;
}

.hero__band {
  position: absolute;
  inset: 0;
  z-index: var(--z-field);
  overflow: hidden;
}

.hero__band img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Anchors the crop to the band's clay base edge so the turf/clay transition
     stays in frame at every field height (brief §4.5, §6.1). */
  object-position: center bottom;
}

.hero__lead {
  margin: var(--space-sm) 0 0 0;
  font-size: var(--text-lead);
  line-height: var(--leading-body);
  color: var(--color-bg);
}

.hero__facts {
  margin: var(--space-xs) 0 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs);
  font-family: var(--font-display);
  font-weight: var(--font-weight-display-strong);
  font-size: var(--text-small);
  letter-spacing: var(--tracking-caps);
  color: var(--color-bg);
}

.hero__facts-sep {
  color: var(--color-tag-eyebrow);
}

/* --- The collage tags (brief §5.1, §7.3, §7.4) ------------------------------
   Reading order 1-2-3 left to right, positions proportional to the field's
   own box (percentages carried from the approved tile's composition,
   tiles/tile-b.html, so they scale across the two field-height steps without
   separate per-breakpoint coordinates). */

.tag-slot {
  position: absolute;
  z-index: var(--z-tag);
  transform: translate(-50%, -50%);
}

.tag-slot--1 { inset-inline-start: 24%; inset-block-start: 24%; }
.tag-slot--2 { inset-inline-start: 51%; inset-block-start: 19%; }
.tag-slot--3 { inset-inline-start: 77%; inset-block-start: 26%; }

.tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--tag-min-w);
  block-size: var(--tag-h);
  padding-inline: var(--space-xs);
  background-color: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-display);
  font-weight: var(--font-weight-display-strong);
  font-size: var(--text-eyebrow);
  line-height: var(--leading-caps);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  white-space: nowrap;
  animation-duration: var(--duration-settle);
  animation-timing-function: var(--ease-out);
  animation-fill-mode: both;
}

/* The signature move: each tag settles once on load, then holds — no
   continuous loop (brief §7.4, §8). Carried unchanged from the approved
   tile (tiles/tile-b.html lines 58-67): all three arrive on the same shape
   of motion, offset only by delay and by their own rest angle. */
.tag--1 { animation-name: tag-settle-1; animation-delay: var(--tag-delay-1); }
.tag--2 { animation-name: tag-settle-2; animation-delay: var(--tag-delay-2); }
.tag--3 { animation-name: tag-settle-3; animation-delay: var(--tag-delay-3); }

@keyframes tag-settle-1 {
  from { transform: translateY(var(--settle-offset-y)) rotate(-14deg); opacity: 0; }
  to   { transform: translateY(0) rotate(-6deg); opacity: 1; }
}
@keyframes tag-settle-2 {
  from { transform: translateY(var(--settle-offset-y)) rotate(10deg); opacity: 0; }
  to   { transform: translateY(0) rotate(3deg); opacity: 1; }
}
@keyframes tag-settle-3 {
  from { transform: translateY(var(--settle-offset-y)) rotate(-4deg); opacity: 0; }
  to   { transform: translateY(0) rotate(9deg); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  /* Renders each tag immediately at its settled rest position and rotation
     (brief §7.4, §8) rather than hidden — the collage reads identically,
     just without the arrival. No !important: wins purely on source order
     and equal specificity against the rules above. */
  .tag--1 { animation: none; transform: rotate(-6deg); opacity: 1; }
  .tag--2 { animation: none; transform: rotate(3deg); opacity: 1; }
  .tag--3 { animation: none; transform: rotate(9deg); opacity: 1; }
}

/* --- Section head-mark (brief §5.1, §8): the settled tag silhouette, shrunk
   and static, as every section's head-mark below the hero. Flat corners
   everywhere (brief §3) — the "fold" is clip-path, never border-radius. */

.section__title {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-h2);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  text-transform: uppercase;
  color: var(--color-ink);
}

.section__mark {
  flex: 0 0 auto;
  inline-size: var(--space-md);
  block-size: var(--space-sm);
  background-color: var(--color-accent);
  clip-path: polygon(0 0, 70% 0, 100% 45%, 100% 100%, 0 100%);
}

.section__lead {
  margin: var(--space-sm) 0 0 0;
  font-size: var(--text-lead);
  line-height: var(--leading-body);
  color: var(--color-ink-muted);
}

/* A dark section (services) inverts the mark and title colours to the
   panel's own light-on-dark pair. */
.section--dark .section__title,
.section--dark .section__lead {
  color: var(--color-bg);
}
.section--dark .section__mark {
  background-color: var(--color-tag-eyebrow);
}

/* --- Services — [LOAD-BEARING], dark panel (brief §5.3 step 3, §5.6) -------- */

.section--dark {
  background-color: var(--color-panel-dark);
}

.service-list {
  margin: var(--space-lg) 0 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-sm);
}

.service-list__row {
  padding: var(--space-md);
  background-color: var(--color-panel-dark-card);
  border-block-start: var(--border-thick) var(--border-style) var(--color-accent);
}

.service-list__name {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-lead);
  line-height: var(--leading-snug);
  color: var(--color-bg);
}

.service-list__desc {
  margin: var(--space-2xs) 0 0 0;
  font-size: var(--text-small);
  color: var(--color-tag-muted);
}

@media (min-width: 48em) {
  .service-list {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* --- Season strip (brief §5.3 step 4) ---------------------------------------
   Four unnumbered cards, shared turf-blade texture behind each, tinted per
   card so the one asset reads consistently under all four (brief §6). */

.season-grid {
  margin: var(--space-lg) 0 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-sm);
}

@media (min-width: 48em) {
  .season-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 64em) {
  .season-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* R1 fix (design/contrast, §6): text now sits on its own solid
   --color-surface panel below; the texture only frames the card. */
.season-card {
  padding: var(--space-xs);
  background-color: var(--color-surface);
  background-image: url('/assets/img/season-turf-texture.webp');
  background-size: cover;
  background-position: center;
  background-blend-mode: multiply;
}

/* Brief §6's "tinted per-card" names no four tint values, and inventing
   colours here would be a fabricated decision. Varying blend mode against
   the same --color-surface and asset differs each card, no new literal. */
.season-card--2 { background-blend-mode: soft-light; }
.season-card--3 { background-blend-mode: luminosity; }
.season-card--4 { background-blend-mode: darken; }

.season-card__panel {
  padding: var(--space-sm);
  background-color: var(--color-surface);
}

.season-card__label {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-body);
  line-height: var(--leading-snug);
  color: var(--color-ink);
}

.season-card__body {
  margin: var(--space-2xs) 0 0 0;
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

/* --- Trust strip (brief §5.3 step 5, §5.6 point 4) --------------------------
   Honest-absence framing; the honesty statement is set in Barlow italic
   (brief §2.6). */

.trust-strip__inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

@media (min-width: 48em) {
  .trust-strip__inner {
    flex-direction: row;
    align-items: center;
  }
  .trust-strip__copy {
    flex: 1 1 auto;
  }
  .trust-strip__image {
    flex: 0 0 auto;
    inline-size: 40%;
  }
}

.trust-strip__notice {
  margin: var(--space-sm) 0 0 0;
  font-style: italic;
  font-size: var(--text-body);
  color: var(--color-ink);
}

.trust-strip__notice em {
  font-style: italic;
}

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

.trust-strip__image {
  overflow: hidden;
}

.trust-strip__image img {
  width: 100%;
  height: auto;
}

/* --- Process (brief §5.3 step 7) --------------------------------------------
   The site's one numbered list — a different face/colour role from the
   hero tags and the section head-mark, so no two counters share a costume. */

.process-list {
  margin: var(--space-lg) 0 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-sm);
}

.process-list__row {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
}

.process-list__num {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-weight: var(--font-weight-body);
  font-size: var(--text-lead);
  color: var(--color-accent);
}

.process-list__body {
  font-size: var(--text-body);
  color: var(--color-ink);
}

/* --- Service area (brief §5.3 step 8) ---------------------------------------
   Low-opacity wide band behind the section, carrying the anchor's "earth
   and sky" register a second time (brief §6). */

.service-area {
  position: relative;
  overflow: hidden;
}

.service-area__band {
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
  opacity: 0.35;
}

.service-area__band img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.service-area__inner {
  position: relative;
  z-index: 1;
}

/* --- FAQ (brief §5.3 step 9) -------------------------------------------------
   Native details/summary; the disclosure marker is the sub-list's own
   ornament, so it carries no additional counter (brief §2.6). */

.faq-list {
  margin: var(--space-lg) 0 0 0;
  display: grid;
  gap: var(--space-xs);
}

.faq-list__row {
  padding: var(--space-md);
  background-color: var(--color-surface);
}

.faq-list__q {
  font-family: var(--font-display);
  font-weight: var(--font-weight-display-strong);
  font-size: var(--text-body);
  color: var(--color-ink);
  cursor: pointer;
}

.faq-list__a {
  margin: var(--space-sm) 0 0 0;
  font-size: var(--text-body);
  color: var(--color-ink-muted);
}

/* --- Form -------------------------------------------------------------------
   House form primitives (spec §6), labels set in the display face per
   brief §2.6's button/label role. */

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

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

.field__label {
  font-family: var(--font-display);
  font-weight: var(--font-weight-display-strong);
  font-size: var(--text-small);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  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);
  font-family: var(--font-body);
  border: var(--border-hairline) var(--border-style) var(--color-border-strong);
  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-display-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: inherit;
  text-underline-offset: var(--space-3xs);
}

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

/* --- Dark-band-safe focus ring (house-tech-spec §3 default pattern) --------
   The hero and the dark services panel both sit on grounds --color-focus was
   never validated against; scope the ring to those bands only. */

.hero :focus-visible,
.section--dark :focus-visible {
  outline-color: var(--color-focus-on-band);
}
