/* ==========================================================================
   site.css — Yard Master Services, Logan UT. clean-clinical / clay /
   full-bleed-immersive, built from the approved brief.

   HARD RULE (house-tech-spec §3): no raw hex, no px/rem size literal, no
   font-name literal here. Tokens only. The two escape hatches are the house
   breakpoints (48em / 64em) and an explicit `@allow-literal: reason`.

   THE GREPPABLE RULES THIS FILE IS WRITTEN AGAINST (brief §4.5): R1 accent is
   never text or focus on the band · R2 no string on the field or atmosphere ·
   R3 paint order field -> atmosphere -> plate · R4 no plate is translucent ·
   R5 the rule token is decorative only · R6 focus geometry is base.css's ·
   R7 no font-variation-settings · R8 no !important · R9 no literals.
   ========================================================================== */

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

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

/* design-rules §7.1's ONE inter-section token, at its two permitted call sites:
   .section's padding-block and .hero's padding-block-END (brief §5.6). */
.section {
  padding-block: var(--section-gap);
}

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

/* The sticky header would otherwise cover the top of an anchored section. */
section[id] {
  scroll-margin-block-start: calc(var(--layout-header-height) + var(--border-hairline));
}

/* --- Type roles (brief §2.7). Weight is font-weight and nothing else (R7). */

h1,
.band__display {
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

h2 {
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-h2);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

h3,
.faq__q {
  font-family: var(--font-display-mid);
  font-weight: var(--font-weight-display-mid);
  font-size: var(--text-h3);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-normal);
}

/* The caps role. Every such string is authored in natural case in the HTML and
   uppercased at this one place (house-tech-spec §8). */
.hero__eyebrow,
.section-head__label,
.thanks__eyebrow {
  font-family: var(--font-body-strong);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-eyebrow);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}

/* One clay accent word per heading, and at most one. */
.accent-word {
  color: var(--color-accent);
}

/* R1: inside the band the accent word takes the on-dark sibling. */
.band .accent-word {
  color: var(--color-accent-onband);
}

/* --- Header. Wordmark left, tel: right, at every width. The tap floor plus
   --space-xs is the min-height, plus a 1px rule = 57.0px of chrome (brief §6).
   The wordmark sets two lines below 48rem and one above; intended. It never
   shrinks, takes nowrap, truncates or gets a variant. */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-header);
  background-color: var(--color-bg);
  border-block-end: var(--border-hairline) var(--border-style) var(--color-ink);
  padding-block: 0;
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  min-height: var(--layout-header-height);
}

.site-header__brand {
  font-family: var(--font-display-mid);
  font-weight: var(--font-weight-display-mid);
  font-size: var(--text-h3);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-decoration: none;
}

/* A number that breaks mid-string is undiallable. */
.site-header__tel {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  min-height: var(--layout-tap-min);
  font-family: var(--font-body-strong);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-small);
  white-space: nowrap;
  text-decoration: none;
  color: var(--color-accent);
}

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

/* --- Buttons. One control shape, no rounded corner, and --radius-pill does not
   exist as a token — design-rules §4's "two pill buttons" is unreachable. .btn's
   block padding is the small step, holding the preview bar's Buy chip on the tap
   floor and the sticky stack at 101.0px; the page's control opts up to 56. */

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

/* N1: the control's boundary IS its fill, at 6.23:1 on the page ground, so
   colour is never the sole indicator. */
.btn--primary {
  padding-block: var(--space-sm);
  background-color: var(--color-accent);
  color: var(--color-accent-ink);
}

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

/* --- §I hero — full-bleed-immersive (brief §5.3, §5.4). The field is out of
   flow: it displaces nothing and nothing displaces it. The hero has NO
   padding-block-start — the plate's margin does that, and the field starts at
   the hero's true top edge. */

.hero {
  position: relative;
  padding-block-end: var(--section-gap);
  isolation: isolate;
}

.hero__field {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  block-size: var(--field-height);
  overflow: clip;
  z-index: var(--z-field);
}

.hero__field picture,
.hero__field img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
}

/* One 3:2 source at every width. object-position keeps the recipe's low-detail
   upper band — the ground the plates sit over — in every crop. */
.hero__field img {
  object-fit: cover;
  object-position: center top;
}

/* design-rules §0 requires atmosphere, not a flat ground. Two stacked radials,
   painted BELOW every plate and ABOVE the field (R3). No text sits on this
   layer (R2), so §6's gradient clause has nothing to measure. */
.hero__atmosphere {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  block-size: var(--field-height);
  z-index: var(--z-atmosphere);
  pointer-events: none;
  background-image:
    radial-gradient(ellipse 70% 46% at 50% 8%, var(--color-halo-cool), transparent 72%),
    radial-gradient(ellipse 96% 40% at 50% 100%, var(--color-halo-clay), transparent 78%);
}

/* flow-root: the plate's margin-block-start must stay INSIDE the hero. It is the
   40px of bare field across the top of the first screen (brief §5.4.1), and a
   collapsed margin deletes it. */
.hero__inner {
  position: relative;
  z-index: var(--z-plate);
  display: flow-root;
  width: 100%;
  max-width: var(--layout-container);
  margin-inline: auto;
}

/* THE PLATE (brief §4.4, §5.4.1). Opaque, always — a translucent plate turns
   every flat pair in §4.1 into an unmeasured gradient pair (R4). padding-block
   is 0 as a positive decision: the plate's top and bottom edges ARE its clay
   rules, and a rule marking an edge cannot be inset from it. Internal breathing
   is the children's margins, on the space scale. */
.hero__plate {
  background-color: var(--color-bg);
  opacity: 1;
  border-block: var(--border-hairline) var(--border-style) var(--color-accent);
  border-inline: 0;
  padding-block: 0;
  padding-inline: var(--space-sm);
  margin-block-start: var(--space-lg);
}

.hero__plate > * {
  margin-block: var(--space-xs);
}

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

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

.hero__lead {
  font-size: var(--text-lead);
  color: var(--color-ink-muted);
}

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

.hero__facts-figure {
  font-family: var(--font-body-strong);
  font-weight: var(--font-weight-body-strong);
  color: var(--color-ink);
}

/* Ornament, in clay, beside the figure. It does not animate, count up or tick —
   a rating that counts up is a rating a reader distrusts. */
.stars {
  display: inline-block;
  vertical-align: text-bottom;
  inline-size: var(--space-3xl);
  fill: var(--color-accent);
}

.stars svg {
  display: block;
  inline-size: 100%;
  block-size: auto;
}

/* --- The dew catches — the signature move (brief §8). Inside the field, and
   only there. Sizes and positions are percentages of the field, so the
   composition is identical at every width; the fall is absolute, because one
   that scaled down would vanish on a phone. Nothing yields; the field clips. */

.catch {
  position: absolute;
  display: block;
  aspect-ratio: 1;
  min-inline-size: var(--bead-floor);
  border-radius: var(--radius-round);
  background-color: var(--color-halo-cool);
  pointer-events: none;
}

.catch--a {
  inline-size: 1.87%;
  inset-inline-start: 11.7%;
  inset-block-end: 10.8%;
  animation: ym-catch var(--loop-catch-a) var(--ease-in-out) infinite;
}

.catch--b {
  inline-size: 1.33%;
  inset-inline-start: 52.3%;
  inset-block-end: 20%;
  animation: ym-catch var(--loop-catch-b) var(--ease-in-out) infinite;
}

.catch--c {
  inline-size: 1.6%;
  inset-inline-start: 82.1%;
  inset-block-end: 7.9%;
  animation: ym-catch var(--loop-catch-c) var(--ease-in-out) infinite;
}

/* The bead — the object every section marker is drawn from. It swells, falls
   twice and resets off-frame. Its rest-frame extreme never leaves the field: at
   320 its bottom is 27.5% of 480 = 132px against a 64px fall. */
.catch--bead {
  inline-size: 2.4%;
  inset-inline-start: 69.9%;
  inset-block-end: 27.5%;
  background-color: var(--color-accent);
  animation: ym-bead var(--loop-bead) var(--ease-in-out) infinite;
}

@keyframes ym-catch {
  0%, 100% { opacity: 0.18; }
  46%      { opacity: 0.96; }
  72%      { opacity: 0.32; }
}

@keyframes ym-bead {
  0%   { transform: translateY(0) scale(0.7);  opacity: 0; }
  14%  { transform: translateY(0) scale(1.15); opacity: 0.75; }
  38%  { transform: translateY(0) scale(1.15); opacity: 0.9; }
  58%  { transform: translateY(var(--bead-fall-1)) scale(1); opacity: 0.9; }
  84%  { transform: translateY(var(--bead-fall-2)) scale(0.9); opacity: 0.55; }
  92%, 100% { transform: translateY(var(--bead-fall-2)) scale(0.9); opacity: 0; }
}

/* --- Section head — bead + caps label (brief §6.7). N7: the bead is NEVER a
   section's sole mark — every head carries bead AND label, so structure never
   rests on a 10px dot. align-self keeps it on the label's FIRST line; it never
   shrinks, wraps away or re-centres. */

.section-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2xs);
  border-block-start: var(--border-hairline) var(--border-style) var(--color-accent);
  padding-block-start: var(--space-xs);
  margin-block-end: var(--space-lg);
}

.bead {
  flex: 0 0 var(--bead-size);
  inline-size: var(--bead-size);
  block-size: var(--bead-size);
  align-self: flex-start;
  margin-block-start: var(--bead-offset);
  border-radius: var(--radius-round);
  background-color: var(--color-accent);
}

.band .bead {
  background-color: var(--color-accent-onband);
}

.band .section-head {
  border-block-start-color: var(--color-accent-onband);
}

.band .section-head__label {
  color: var(--color-band-ink-muted);
}

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

.section__lead {
  max-width: var(--layout-measure);
  font-size: var(--text-lead);
  color: var(--color-ink-muted);
  margin-block-end: var(--space-lg);
}

/* --- §II services — a ruled index. No cards, no icons. */

.index {
  margin: 0;
  padding: 0;
  list-style: none;
}

.index__row {
  display: grid;
  gap: var(--space-2xs);
  padding-block: var(--space-md);
}

/* R5: a decorative separator, never the sole indicator of anything. */
.index__row + .index__row {
  border-block-start: var(--border-hairline) var(--border-style) var(--color-rule);
}

.index__desc {
  max-width: var(--layout-measure);
  color: var(--color-ink-muted);
}

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

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

/* In the section foot the CTA is a grid child: the grid's gap carries it. */
.section-foot .section-foot__cta {
  margin-block-start: 0;
}

/* Drawn STUDIES, not an icon set: one specimen each, never repeated, tinted,
   mirrored or set in a row, and the three never share a screen (brief §6.6). */
.plate-figure {
  margin: 0;
  max-width: var(--layout-measure);
}

.plate-figure img {
  inline-size: 100%;
  block-size: auto;
}

/* --- §III season strip --- */

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

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

.season__desc {
  max-width: var(--layout-measure);
  color: var(--color-ink-muted);
  margin-block-start: var(--space-2xs);
}

/* --- §IV the one deep soil band. A FLAT fill: no image, texture or gradient
   (brief §4.3 clause 4), nothing in it moves, used once. */

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

/* R6: only the colour changes. Ring geometry stays base.css's. Kept live
   although §IV carries no focusable element: a guard with nothing to report and
   a guard that does not exist look identical from outside. */
.band :focus-visible {
  outline-color: var(--color-focus-on-band);
}

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

.band__support {
  color: var(--color-band-ink-muted);
  margin-block-start: var(--space-md);
}

/* Plain type, one fact per line. Never a counter row, never animated, never a
   stat grid. SLOT L would be a fifth line here and ships absent. */
.band__stack {
  margin: 0;
  padding: 0;
  list-style: none;
  margin-block-start: var(--space-lg);
  display: grid;
  gap: var(--space-2xs);
}

/* --- §V reviews — a ruled stack. No cards, avatars, quotation-mark ornament,
   per-review star run, truncation or carousel. */

.reviews {
  margin: 0;
  padding: 0;
  list-style: none;
}

.review {
  padding-block: var(--space-lg);
}

.review + .review {
  border-block-start: var(--border-hairline) var(--border-style) var(--color-rule);
}

/* Our label. The reviewer's name is inside .review__name and takes no transform
   at any breakpoint — it ships as publicly displayed. */
.review__meta {
  font-family: var(--font-body-strong);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-small);
  color: var(--color-ink-muted);
  margin-block-end: var(--space-2xs);
}

.review__quote {
  margin: 0;
  max-width: var(--layout-measure);
  font-family: var(--font-body);
  font-weight: var(--font-weight-body);
  font-size: var(--text-lead);
  line-height: var(--leading-body);
}

/* --- §VI process ---------------------------------------------------------
   The digit column never collapses and the digits never right-align into the
   text. The description wraps. Four rows is this device's maximum here. */

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

.step {
  display: grid;
  grid-template-columns: var(--layout-digit-col) 1fr;
  gap: var(--space-xs);
  align-items: start;
}

/* The one enumerated sub-list on the site. Against the section mark it changes
   numeral system, mark class and colour role — three of §5's floor of two, and
   no row carries both a bead and a digit. */
.step__digit {
  font-family: var(--font-body-strong);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-body);
  line-height: var(--leading-snug);
  color: var(--color-ink-muted);
}

.step__desc {
  max-width: var(--layout-measure);
  color: var(--color-ink-muted);
  margin-block-start: var(--space-2xs);
}

.plate-figure--step {
  margin-block-start: var(--space-md);
}

/* --- §VII service area --- */

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

/* The quiet blocks: F2 and F4 pairs, 13.00:1 and 6.16:1. */
.towns__group {
  background-color: var(--color-surface);
  padding: var(--space-md);
}

.towns__list {
  margin-block-start: var(--space-2xs);
  color: var(--color-ink-muted);
}

.towns__base {
  margin-block-start: var(--space-lg);
  max-width: var(--layout-measure);
  color: var(--color-ink-muted);
}

/* --- §VIII faq — native disclosure, works with JS off. The summary carries a
   marker and NO counter (design-rules §5 limit 2). */

.faq__item {
  padding-block: var(--space-md);
}

.faq__item + .faq__item {
  border-block-start: var(--border-hairline) var(--border-style) var(--color-rule);
}

.faq__q {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
}

.faq__a {
  max-width: var(--layout-measure);
  color: var(--color-ink-muted);
  margin-block-start: var(--space-2xs);
}

/* --- §IX contact --- */

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

.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-strong);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-small);
}

/* N8: fields never use --color-rule. Their border is --color-ink-muted at
   7.07:1 — a control boundary is never a 1.45:1 hairline. */
.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);
  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);
}

/* In the DOM for bots, unreachable for humans and AT. Not display:none. */
.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-family: var(--font-body-strong);
  font-weight: var(--font-weight-body-strong);
}

.contact__aside {
  display: grid;
  gap: var(--space-md);
  align-content: start;
}

.contact__call {
  font-family: var(--font-body-strong);
  font-weight: var(--font-weight-body-strong);
}

.contact__nap {
  font-style: normal;
  color: var(--color-ink-muted);
}

/* --- Footer --- */

.site-footer {
  padding-block: var(--space-xl);
  border-block-start: var(--border-hairline) var(--border-style) var(--color-accent);
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

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

.site-footer__hours,
.site-footer__services {
  margin-block-start: var(--space-md);
  max-width: var(--layout-measure);
}

.site-footer p:last-child {
  margin-block-start: var(--space-md);
}

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

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

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

.thanks__body {
  margin-block-start: var(--space-md);
  font-size: var(--text-lead);
  color: var(--color-ink-muted);
}

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

/* --- buy.html --- */

.buy__body,
.buy__next {
  margin-block-start: var(--space-md);
  font-size: var(--text-lead);
  color: var(--color-ink-muted);
}

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

/* 48rem — the plate becomes an inset panel and the field grows (brief §5.2). */

@media (min-width: 48em) {
  .hero__field,
  .hero__atmosphere {
    block-size: var(--field-height-md);
  }

  .hero__inner {
    padding-inline: var(--layout-gutter);
  }

  .hero__plate {
    inline-size: var(--layout-plate);
    padding-inline: var(--space-lg);
    margin-block-start: var(--space-xl);
  }

  .hero__plate > * {
    margin-block: var(--space-md);
  }

  .hero__cta {
    margin-inline: 0;
  }

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

  .section-foot {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }

  .season {
    grid-template-columns: 2fr 1fr;
    align-items: start;
  }

  .towns {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }

  .contact {
    grid-template-columns: 3fr 2fr;
    align-items: start;
    gap: var(--space-xl);
  }

  /* brief §5.6 rank 2: review and process row gaps step up to 64px here — the
     largest intra-section gap on the site, one third of 2 x --section-gap. */
  .review {
    padding-block: var(--space-xl);
  }

  .process__list {
    gap: var(--space-xl);
  }
}

/* 64rem — one value changes, and it is declared because §5 requires every
   breakpoint to be computed rather than assumed constant. */

@media (min-width: 64em) {
  .hero__field,
  .hero__atmosphere {
    block-size: var(--field-height-lg);
  }
}

/* ==========================================================================
   Reduced motion — brief §8, no exceptions.

   base.css collapses the duration tokens at :root, stopping every transition at
   the source. The ambient loops are animations, so they are stopped explicitly
   and held at the brief's hand-set rest frame: three separate opacities, and
   the bead mid-form, elongated, at the moment before release. No !important
   (R8) — these selectors match the earlier ones and win on source order.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .catch--a,
  .catch--b,
  .catch--c,
  .catch--bead {
    animation: none;
  }

  .catch--a { opacity: var(--rest-catch-a); }
  .catch--b { opacity: var(--rest-catch-b); }
  .catch--c { opacity: var(--rest-catch-c); }

  .catch--bead {
    transform: var(--rest-bead-transform);
    opacity: var(--rest-bead-opacity);
  }

  .btn {
    transition: none;
  }
}
