/* ==========================================================================
   site.css — per-site components, built FROM tokens; tokens only, no raw
   literals (§3). ARCHETYPE poster-hero (brief §5): one column, full width, at
   every width — no rail, nothing overlapping, one reading order top to bottom
   (ref-011's refused clause). BREAKPOINTS: 48em and 64em only (§5.1 rule 5).
   ONE GRADIENT, the hero atmosphere (R2).
   ========================================================================== */

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

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

/* The ONE inter-section value and its two call sites (brief §5.6). No section
   sets its own vertical rhythm. */
.section {
  padding-block: var(--section-gap);
}

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

/* --- Type roles (brief §2.7). Weight is font-weight and nothing else;
   no variable-axis declaration appears anywhere (brief R11). --- */

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

h3 {
  font-size: var(--text-h3);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-normal);
}

/* The page's only section mark, in place of numerals (brief §6.6). Authored
   in natural case, uppercased here (house-tech-spec §8). */
.eyebrow {
  margin-block-end: var(--space-2xs);
  color: var(--color-accent);
  font-family: var(--font-body-strong);
  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;
}

/* Section head → content, every section (brief §5.6). */
.section > .container > h2 {
  margin-block-end: var(--space-md);
}

/* --- Header. 56px + a 1px border = the 57px half of §5.5's measured 101px
   sticky stack. The sticky rule lives in preview.css. --- */

.site-header {
  z-index: var(--z-header);
  border-block-end: var(--border-hairline) var(--border-style) var(--color-border);
  background-color: var(--color-bg);
}

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

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

.site-header__nav {
  display: flex;
  align-items: center;
}

/* The phone never disappears (playbook §5). One line at every width. */
.site-header__tel {
  padding-block: var(--space-3xs);
  white-space: nowrap;
}

/* --- Buttons. One control shape (§6.2 §I): accent fill, accent-ink label,
   --radius-sm, full-width below 768, 52px then 56px. Nothing else on the site
   is rounded and nothing casts a shadow. --- */

.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-sm);
  box-shadow: var(--shadow-none);
  font-family: var(--font-body-strong);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-body);
  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 {
  min-height: var(--control-height);
  background-color: var(--color-accent);
  color: var(--color-accent-ink);
}

@media (min-width: 48em) {
  .btn--primary {
    min-height: var(--control-height-lg);
  }
}

/* --- §I hero-quote, house DOM order (brief §5.2): eyebrow → h1 → CTA → field
   → lead → trust line. The field is a picture the poster stands on. --- */

.hero {
  padding-block-start: var(--space-md);
  padding-block-end: var(--section-gap);
  background: radial-gradient(120% 82% at 24% 6%,
    var(--color-atmos-1) 0%, var(--color-atmos-2) 54%, var(--color-atmos-3) 100%);
}

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

/* Slot ① — the width-bounded eyebrow (§5.4). Two block children, normal
   wrapping, no hyphenation, no text-wrap: balance, so the line count stays
   verifiable. */
.hero__eyebrow {
  max-inline-size: min(100%, var(--eyebrow-max));
  margin-block-end: var(--space-xs);
  color: var(--color-ink-muted);
  font-family: var(--font-body-strong);
  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;
  text-wrap: normal;
}

.hero__trade,
.hero__place {
  display: block;
  overflow-wrap: normal;
  hyphens: none;
}

/* The poster. --text-hero runs 40.32px at 320 to 88px at 1440; nothing else
   is set above --text-h2. */
.poster {
  margin-block-end: var(--space-sm);
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: normal;
}

.poster .ln {
  display: block;
}

/* --- The signature, "below grade" (brief §5.3).

   THE CLIP IS EXPRESSED FROM THE BOTTOM, never as a percentage from the top. A
   top-anchored inset() cuts the middle of the FIRST line the moment the line
   wraps; a bottom-anchored one always cuts the LAST rendered line at the same
   depth, whatever the line count. The soil rectangle is anchored to the same
   edge by the same token, so the two edges are one number and cannot drift.

   .grade__below must NOT carry white-space: nowrap — it wraps identically to
   .grade__above or the two strings desynchronise. Its ground is --color-soil,
   which is what is behind it: chalk on soil, 11.46:1. --- */

.grade {
  position: relative;
  isolation: isolate;
  display: block;
}

.grade__above {
  position: relative;
  color: var(--color-ink);
}

.grade__soil {
  position: absolute;
  z-index: -1;
  inset-inline: calc(-1 * var(--layout-gutter));
  inset-block-start: auto;
  inset-block-end: calc(-1 * var(--space-2xs));
  block-size: calc(var(--grade-knockout) + var(--space-2xs));
  background-color: var(--color-soil);
}

.grade__below {
  position: absolute;
  inset: 0;
  background-color: var(--color-soil);
  color: var(--color-accent-ink);
  clip-path: inset(calc(100% - var(--grade-knockout)) 0 0 0);
}

.hero__ask .btn {
  display: flex;
  width: 100%;
}

@media (min-width: 48em) {
  .hero__ask .btn {
    display: inline-flex;
    width: auto;
  }
}

/* The living field — full-bleed at 16:10 at every width. A direct child of
   .hero, not of .container, which is how it breaks the container without a
   viewport-width literal. */
.field {
  position: relative;
  margin-block-start: var(--space-md);
  aspect-ratio: var(--field-ratio);
  overflow: hidden;
}

@media (min-width: 64em) {
  .field {
    margin-block-start: var(--space-lg);
  }
}

.field__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Ambient satellite motion (brief §8.3) — three seed motes and one light
   sweep, aria-hidden, carrying no text, meaning or control (brief R3).
   Nothing else on the site moves. */

.field__mote,
.field__sweep {
  position: absolute;
  pointer-events: none;
  background-color: var(--color-atmos-1);
  /* §8.3 calls the sweep radial and the three motes seed motes, which is more
     specific than §3.3's summary of which page COMPONENTS carry a radius —
     these are aria-hidden atmosphere, not components. */
  border-radius: 50%;
}

.field__sweep {
  inset-block-start: 0;
  inset-inline-start: 10%;
  inline-size: var(--sweep-size);
  aspect-ratio: 1;
  /* A soft edge without a second gradient — brief R2 allows exactly one on
     this site and it is the hero ground. */
  filter: blur(var(--sweep-blur));
  opacity: var(--sweep-opacity-min);
  animation: sweep-breathe var(--sweep-period) var(--ease-in-out) infinite;
}

.field__mote {
  inline-size: var(--mote-size);
  block-size: var(--mote-size);
  opacity: var(--sweep-opacity-max);
  animation-name: mote-drift;
  animation-timing-function: var(--ease-in-out);
  animation-iteration-count: infinite;
}

.field__mote--1 {
  inset-block-start: 22%;
  inset-inline-start: 18%;
  animation-duration: var(--float-period-1);
}

.field__mote--2 {
  inset-block-start: 34%;
  inset-inline-start: 57%;
  animation-duration: var(--float-period-2);
  animation-delay: var(--float-phase-2);
}

.field__mote--3 {
  inset-block-start: 15%;
  inset-inline-start: 79%;
  animation-duration: var(--float-period-3);
  animation-delay: var(--float-phase-3);
}

@keyframes mote-drift {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(var(--mote-x1), var(--mote-y1)); }
  55%  { transform: translate(var(--mote-x2), var(--mote-y2)); }
  80%  { transform: translate(var(--mote-x3), var(--mote-y3)); }
  100% { transform: translate(0, 0); }
}

@keyframes sweep-breathe {
  0%   { opacity: var(--sweep-opacity-min); }
  50%  { opacity: var(--sweep-opacity-max); }
  100% { opacity: var(--sweep-opacity-min); }
}

.hero__lead {
  margin-block-start: var(--space-md);
  font-size: var(--text-lead);
  line-height: var(--leading-body);
}

/* Three items, one rule above. Never a counter row (design-rules §4). */
.hero__trust {
  margin-block-start: var(--space-md);
  padding-block-start: var(--space-xs);
  border-block-start: var(--border-hairline) var(--border-style) var(--color-border);
  color: var(--color-ink-muted);
  font-size: var(--text-small);
  line-height: var(--leading-body);
}

/* --- §II and §VII — ref-011's index list: name left in the display face,
   qualifier right in small caps, one hairline per row. The qualifier moves
   under the name at its own size when the row cannot hold both (§6.6) —
   flex-wrap, not a breakpoint — and is never dropped. --- */

.group {
  margin-block-start: var(--space-lg);
  margin-block-end: var(--space-2xs);
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
}

.index {
  border-block-start: var(--border-hairline) var(--border-style) var(--color-border);
}

.index__row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2xs);
  padding-block: var(--row-pad-top) var(--row-pad-bottom);
  border-block-end: var(--border-hairline) var(--border-style) var(--color-border);
}

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

.index__qual {
  color: var(--color-ink-muted);
  font-family: var(--font-body-strong);
  font-weight: var(--font-weight-body-strong);
  font-size: var(--text-small);
  line-height: var(--leading-caps);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

/* Inline plates — type sits beneath, never over (brief R3). */
.section-figure {
  margin-block-start: var(--space-md);
}

.section-figure img {
  width: 100%;
  height: auto;
}

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

.section__ask .btn {
  display: flex;
  width: 100%;
}

@media (min-width: 48em) {
  .section__ask .btn {
    display: inline-flex;
    width: auto;
  }
}

/* --- §III process. The tick carries sequence without a numeral (brief R5,
   §6.6): a 12x2px accent rule indented one step per row. --- */

.process {
  border-block-start: var(--border-hairline) var(--border-style) var(--color-border);
}

.process__row {
  padding-block: var(--row-pad-top) var(--row-pad-bottom);
  border-block-end: var(--border-hairline) var(--border-style) var(--color-border);
}

.process__tick {
  display: block;
  inline-size: var(--tick-length);
  block-size: var(--border-thick);
  margin-block-end: var(--space-2xs);
  background-color: var(--color-accent);
}

.process__row--2 .process__tick { margin-inline-start: var(--tick-step); }
.process__row--3 .process__tick { margin-inline-start: calc(2 * var(--tick-step)); }
.process__row--4 .process__tick { margin-inline-start: calc(3 * var(--tick-step)); }
.process__row--5 .process__tick { margin-inline-start: calc(4 * var(--tick-step)); }
.process__row--6 .process__tick { margin-inline-start: calc(5 * var(--tick-step)); }

.process__name {
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
}

.process__text {
  max-width: var(--layout-measure);
  line-height: var(--leading-body);
}

/* --- §IV the soil band — THE ONE DARK GROUND (brief R4). Slot 4 is its top
   edge and carries no text. --color-focus-on-band is scoped here only. --- */

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

.band :focus-visible {
  outline-color: var(--color-focus-on-band);
}

.band__edge {
  display: block;
  aspect-ratio: var(--band-edge-ratio);
  overflow: hidden;
}

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

/* --section-gap keeps its two call sites (brief §5.6); this is the same step
   on the house scale, named directly. */
.band__body {
  padding-block: var(--space-xl);
}

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

/* --- §V trust-strip — method and fact, never credential ------------------- */

.trust {
  border-block-start: var(--border-hairline) var(--border-style) var(--color-border);
}

.trust__item {
  padding-block: var(--row-pad-top) var(--row-pad-bottom);
  border-block-end: var(--border-hairline) var(--border-style) var(--color-border);
}

.trust__name {
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
}

.trust__text {
  max-width: var(--layout-measure);
  line-height: var(--leading-body);
}

/* --- §VI and §VIII, the reserved frames: rendered, never filled, never
   deleted (c1-gate condition 8). No shape mimics content that does not
   exist. --- */

.reserved {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-2xs);
  min-block-size: var(--reserved-min);
  padding: var(--space-md);
  border: var(--border-hairline) dashed var(--color-border);
}

.reserved__label {
  color: var(--color-ink-muted);
  font-family: var(--font-body-strong);
  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;
}

.reserved__line {
  max-width: var(--layout-measure);
  color: var(--color-ink-muted);
  font-size: var(--text-small);
  line-height: var(--leading-body);
}

/* --- §IX faq — native <details>/<summary>, no JS, no ARIA widget. The
   disclosure marker is the row's ornament, so no counter (design-rules §5). */

.faq {
  border-block-start: var(--border-hairline) var(--border-style) var(--color-border);
}

.faq__row {
  border-block-end: var(--border-hairline) var(--border-style) var(--color-border);
}

.faq__row[open] {
  background-color: var(--color-surface);
}

.faq__q {
  display: flex;
  align-items: center;
  padding-block: var(--row-pad-top) var(--row-pad-bottom);
  padding-inline: var(--space-2xs);
  font-family: var(--font-display);
  font-weight: var(--font-weight-display);
  font-size: var(--text-h3);
  line-height: var(--leading-snug);
  cursor: pointer;
}

.faq__a {
  max-width: var(--layout-measure);
  padding-inline: var(--space-2xs);
  padding-block-end: var(--space-md);
  line-height: var(--leading-body);
}

/* --- §X contact — the quote block ---------------------------------------- */

.quote__lead {
  margin-block-end: var(--space-md);
  font-size: var(--text-lead);
  line-height: var(--leading-body);
}

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

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

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

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

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

/* Honeypot: in the DOM for bots, unreachable otherwise. 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 {
  color: var(--color-ink-muted);
  font-size: var(--text-small);
}

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

.quote__secondary {
  margin-block-start: var(--space-md);
  max-width: var(--layout-measure);
  line-height: var(--leading-body);
}

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

/* --- Footer — SIX blocks (§6.2, C4 amendment 1). A block-level stack, never a
   grid. No street address: dossier C3. No top border — §6.6 lists every
   hairline and a footer edge is not one; its one internal rule sits between
   blocks 4 and 5. --section-gap keeps its two call sites. --- */

.site-footer {
  padding-block: var(--space-xl);
  font-size: var(--text-small);
}

.site-footer > .container > * + * {
  margin-block-start: var(--space-sm);
}

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

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

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

/* The tel: keeps the header's ≥44px target. */
.site-footer__nap a[href^='tel'] {
  display: inline-flex;
  align-items: center;
  min-height: var(--layout-tap-min);
}

.site-footer__hours {
  color: var(--color-ink-muted);
  line-height: var(--leading-body);
}

/* Blocks 4 and 5 share a treatment: the same kind of object, an owner-published
   enumeration. The RULE between them is the distinction, so block 5 adds no
   ornament, colour pair or token. */
.site-footer__list-label {
  margin-block-end: var(--space-2xs);
  color: var(--color-ink-muted);
  font-family: var(--font-body-strong);
  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;
}

.site-footer__list-run {
  color: var(--color-ink-muted);
  font-size: var(--text-small);
  line-height: var(--leading-body);
}

.site-footer__list--services {
  padding-block-start: var(--space-sm);
  border-block-start: var(--border-hairline) var(--border-style) var(--color-border);
}

.site-footer__legal {
  color: var(--color-ink-muted);
}

/* --- thanks.html (§5.5): no field, no atmosphere, no grade split, flat
   --color-bg. h1 at --text-h2; the primary action is the phone. --- */

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

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

.thanks__lead {
  font-size: var(--text-lead);
  line-height: var(--leading-body);
}

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

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

/* --- Reveals (brief §8.1). base.css owns the states; this re-points the
   duration at --duration-reveal. The reduced-motion block below keeps that
   override from outranking base.css's kill switch on source order. --- */

[data-reveal-ready] [data-reveal] {
  transition:
    opacity var(--duration-reveal) var(--ease-out),
    transform var(--duration-reveal) var(--ease-out);
}

/* --- Reduced motion — the still frame IS the composed picture (brief §8.4).
   All four loops stop; the sweep holds at --rm-sweep-opacity and the motes at
   composed offsets. The grade split never moved. No section opts out. --- */

@media (prefers-reduced-motion: reduce) {
  :root {
    /* @allow-literal: a duration token must resolve to a real time value */
    --duration-reveal: 0.01ms;
  }

  [data-reveal-ready] [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0s;
  }

  .field__sweep {
    animation: none;
    opacity: var(--rm-sweep-opacity);
  }

  .field__mote {
    animation: none;
  }

  .field__mote--1 { transform: translate(var(--mote-x1), var(--mote-y1)); }
  .field__mote--2 { transform: translate(var(--mote-x2), var(--mote-y2)); }
  .field__mote--3 { transform: translate(var(--mote-x3), var(--mote-y3)); }
}
