/* ==========================================================================
   site.css — J&R Sanchez Painting, San Angelo TX.
   family: quiet-premium · archetype: split-hero
   Source: runs/j-r-sanchez-painting-san-angelo-tx/brief.md (APPROVED, C3
   2026-09-18). Tokens only — no raw hex, px/rem literal or font name below
   except inside a media-query condition (house-tech-spec §3).
   ========================================================================== */

/* base.css's skip-link defaults to --color-accent/--color-accent-ink, which
   the brief restricts to large-text/icon use only (§2.3) — 3.97:1, below the
   16px/700 AA floor a skip link needs. Swapped to --color-cta-fill/
   --color-cta-text, the brief's own primary-button pairing at 15.44:1 (§2.3)
   — not a new colour decision, the same reuse pattern as other quiet-premium
   builds in this ledger (e.g. pro-landscapers-fargo-nd). */
.skip-link {
  background-color: var(--color-cta-fill);
  color: var(--color-cta-text);
}

/* --- Layout primitives (house shell, unchanged from skeleton) ------------- */

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

/* --- Header & navigation (house shell, unchanged from skeleton) -----------
   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;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}

.site-header__brand {
  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);
  /* The nav-toggle's only shape is this hairline, so it is a CONTROL boundary
     (WCAG 1.4.11, >= 3:1), not a decorative one — use --color-border-strong. */
  border: var(--border-hairline) var(--border-style) var(--color-border-strong);
  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);
}

.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 (house shell, unchanged from skeleton) ------------------------
   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-cta-fill);
  color: var(--color-cta-text);
}

.btn--quiet {
  /* Outline button: the border is the whole control, so it takes the 3:1
     control-boundary token, not the decorative hairline (WCAG 1.4.11). */
  border-color: var(--color-border-strong);
  color: var(--color-ink);
}

/* --- Form (house shell, unchanged from skeleton) ---------------------------
   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);
  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);
}

.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 (house shell, unchanged from skeleton) -------------------------- */

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

/* --- Header brand — inherits the house .site-header__brand rule above
   (font-size var(--text-h3), Marcellus), nothing further to add here. ------ */

/* --- Hero — "the seam holds light" (brief §3.2, §3.3, §5). House order:
   eyebrow -> h1 -> primary CTA -> field -> lead -> facts. Single column
   below 64em; the archetype's asymmetric two-column split from 64em up
   (design-rules §7's split-hero). The hero is never reveal-gated (spec §7);
   nothing here carries [data-reveal]. -------------------------------------- */

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

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

.hero__eyebrow {
  margin: 0;
  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);
}

.hero__title {
  margin: 0;
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
}

.hero__cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm) var(--space-md);
  margin: 0;
}

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

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

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

/* --- The hero field — the anchor image plus its CSS atmosphere (brief §3.2,
   §5). The picture is the LCP element: fetchpriority="high" in the HTML, no
   lazy loading, no [data-reveal]. The sweep/motes are aria-hidden, pure CSS,
   ambient on load, and touch no scroll/zoom/keyboard behaviour (spec §8). */

.hero__field {
  position: relative;
  height: var(--hero-field-height);
  overflow: hidden;
}

.hero__field-picture,
.hero__field-img {
  display: block;
  width: 100%;
  height: 100%;
}

.hero__field-img {
  object-fit: cover;
  object-position: center;
}

/* The static cut-in-line ornament + its travelling highlight, composited
   over the image at the seam's actual measured position (--hero-seam-inset,
   tuned to the generated asset, brief §3.2). Both sit on the brass side of
   the seam, per brief §5 — the sweep highlight overlaps the line itself
   (centred on it), never crossing into the bone field. */
.hero__field-seam {
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--hero-seam-inset);
  width: var(--hero-seam-width);
  /* The glow re-uses --color-bg (warm bone) rather than a new invented hue —
     a highlight is the field's own light tone travelling the seam, not a
     third colour introduced for the effect. transparent is a CSS keyword,
     not a literal (spec §3). */
  background: linear-gradient(
    180deg,
    transparent 0%,
    var(--color-bg) 50%,
    transparent 100%
  );
  opacity: 0.35;
  pointer-events: none;
}

.hero__field-sweep {
  position: absolute;
  top: 0;
  inset-inline-start: var(--hero-seam-inset);
  width: var(--hero-sweep-glow-width);
  height: 45%;
  background: radial-gradient(ellipse at center, var(--color-bg) 0%, transparent 70%);
  animation: hero-sweep var(--duration-sweep) var(--ease-in-out) infinite;
  pointer-events: none;
}

/* transform-only, never `top` — animating a layout property here reads as a
   continuous, unbounded Cumulative Layout Shift even though nothing visible
   reflows (the element is absolutely positioned and overflow:hidden clips
   it). translateY is expressed in the element's OWN box-height units (this
   box is 45% of --hero-field's height, fixed at every breakpoint), scaled so
   the travel distance still spans the full field: -20% and 95% of the
   field's height, converted to -44.44% and 211.11% of the sweep's own 45%
   height. -50%/-.. handles the existing horizontal centring in the same
   transform (perf/cls). */
@keyframes hero-sweep {
  0%   { transform: translate(-50%, -44.44%); opacity: 0; }
  18%  { opacity: 0.85; }
  82%  { opacity: 0.85; }
  100% { transform: translate(-50%, 211.11%); opacity: 0; }
}

.hero__mote {
  position: absolute;
  width: var(--mote-size);
  height: var(--mote-size);
  border-radius: var(--radius-pill);
  background: radial-gradient(circle, var(--color-bg) 0%, transparent 75%);
  opacity: 0.9;
  pointer-events: none;
  animation: hero-mote-drift var(--duration-mote-1) var(--ease-in-out) infinite;
}

.hero__mote--1 {
  inset-inline-start: 58%;
  inset-block-start: 32%;
}

.hero__mote--2 {
  inset-inline-start: 78%;
  inset-block-start: 62%;
  animation-duration: var(--duration-mote-2);
  animation-delay: calc(var(--mote-2-delay) * -1);
}

@keyframes hero-mote-drift {
  0%   { transform: translate(0, 0); }
  33%  { transform: translate(var(--mote-drift-x), calc(var(--mote-drift-y) * -1)); }
  66%  { transform: translate(calc(var(--mote-drift-x) * -0.6), var(--mote-drift-y)); }
  100% { transform: translate(0, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .hero__field-sweep {
    animation: none;
    /* Static rest position near the seam's midpoint (brief §5's reduced-
       motion statement) — -50% recentres horizontally (no longer supplied by
       the animation, per the transform-only fix above), 88.89% is the same
       own-height-relative conversion as the keyframes (40% of the field's
       height / 45% own height * 100). */
    transform: translate(-50%, 88.89%);
    opacity: 0.35;
  }

  .hero__mote {
    animation: none;
  }
}

@media (min-width: 64em) {
  .hero__inner {
    grid-template-columns: 1fr var(--hero-field-inline-size);
    align-items: stretch;
    column-gap: var(--space-xl);
  }

  .hero__eyebrow,
  .hero__title,
  .hero__cta-row {
    grid-column: 1;
  }

  .hero__field {
    grid-column: 2;
    grid-row: 1 / 5;
    height: 100%;
    min-height: var(--hero-field-height-lg);
  }

  .hero__lead,
  .hero__facts {
    grid-column: 1;
  }
}

/* --- Services — a plain rule-divided list, category headers only, no
   numerals (brief §3.1 row 2; kept deliberately distinct from the Index of
   Care's counted system). Two lines (Cabinet, Exterior) carry a small
   contextual thumbnail; the other five stay plain text — never a per-item
   icon set (design-rules §4's ban). ---------------------------------------- */

.services__intro {
  max-width: var(--layout-measure);
  font-size: var(--text-lead);
  color: var(--color-ink-muted);
}

.services__group + .services__group {
  margin-block-start: var(--space-xl);
}

.services__group-heading {
  font-size: var(--text-h3);
  margin-block-end: var(--space-sm);
}

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

.services__list {
  margin: 0;
  padding: 0;
}

.services__row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding-block: var(--space-sm);
  border-top: var(--border-hairline) var(--border-style) var(--color-border);
}

.services__row:last-child {
  border-bottom: var(--border-hairline) var(--border-style) var(--color-border);
}

.services__row-label {
  flex: 1 1 auto;
  font-weight: var(--font-weight-body-strong);
}

.services__row-media {
  flex: 0 0 auto;
  width: var(--service-img-size);
  height: var(--service-img-size);
  overflow: hidden;
  border-radius: var(--radius-sm);
}

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

.services__tag {
  flex: 0 0 auto;
  padding: var(--space-3xs) var(--space-xs);
  background-color: var(--color-accent-wash);
  color: var(--color-ink);
  font-size: var(--text-small);
  font-weight: var(--font-weight-body-strong);
  border-radius: var(--radius-sm);
}

/* --- The Index of Care (brief §3.1 row 3) — the page's only counted
   sequence (design-rules §5's nested-counters rule). Numeral column: 56px at
   >=48em beside the row heading; below that width the row collapses to a
   single column and the numeral sits above its heading (brief §2.5's
   repeated-ornament minimum). ------------------------------------------- */

.care-list {
  margin: 0;
  padding: 0;
}

.care-list__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2xs) var(--space-md);
  padding-block: var(--space-lg);
  border-top: var(--border-hairline) var(--border-style) var(--color-border);
}

.care-list__row:last-child {
  border-bottom: var(--border-hairline) var(--border-style) var(--color-border);
}

.care-list__num {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-index-num);
  font-weight: var(--font-weight-display);
  color: var(--color-accent);
  line-height: 1;
}

.care-list__heading {
  margin: 0;
  font-size: var(--text-h3);
}

.care-list__body {
  margin: 0;
  max-width: var(--layout-measure);
  color: var(--color-ink-muted);
  grid-column: 1 / -1;
}

@media (min-width: 48em) {
  .care-list__row {
    grid-template-columns: var(--index-num-col) 1fr;
    align-items: baseline;
  }

  .care-list__num {
    grid-row: 1 / 3;
  }

  .care-list__heading {
    grid-column: 2;
  }

  .care-list__body {
    grid-column: 2;
  }
}

/* --- Review — one quiet, softened quote, no numeral, no star rating (brief
   §3.1 row 4). Mulish's own true drawn italic, never a synthesized slant. */

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

.review__attrib {
  margin-block-start: var(--space-sm);
  font-size: var(--text-small);
  font-style: normal;
  color: var(--color-ink-muted);
}

/* --- Contact section framing (the form itself is the house .form/.field
   components, unchanged from base + skeleton site.css). ------------------ */

.contact__intro {
  max-width: var(--layout-measure);
  font-size: var(--text-lead);
  color: var(--color-ink-muted);
}

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

/* --- Footer email line — a fourth contact channel, never a CTA (brief
   §3.4's channel argument: phone is the demonstrated primary). ------------ */

.site-footer__email {
  display: inline-block;
  margin-block-start: var(--space-2xs);
}
