/* ==========================================================================
   Fortified Asset Solutions — main.css  (V3)
   Evolves 02_Assets/site_v1_baseline/assets/css/site.css — same token system,
   same palette (sand paper / rust / navy), same type stack. Nothing replaced.
   Added in V3: "work-order ticket" component layer — mono section indices,
   hairline rules, dotted-leader spec rows, numbered process ladder, placeholder
   chips, marked review slot, breadcrumbs, package + service index components.
   Vanilla CSS. No framework, no build step. Painting-order rules honored.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@700;800&family=Public+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@500;600&display=swap');

/* ---------- Design tokens (carried forward from V1, extended) ---------- */
:root {
  /* Palette — OKLCH per brand-pack.md */
  --color-bg-primary:     oklch(97.5% 0.012 85);
  --color-bg-secondary:   oklch(93% 0.02 75);
  --color-text-primary:   oklch(24% 0.03 250);
  --color-text-secondary: oklch(42% 0.025 250);
  --color-accent:         oklch(48% 0.13 45);
  --color-accent-soft:    oklch(88% 0.05 50);
  --color-ink:            oklch(20% 0.035 250);

  /* Fallback sRGB (older browser safety net) */
  --paper:     #F7F2E9;
  --paper-2:   #EDE2CE;
  --paper-3:   #FBF8F1;
  --ink:       #23272F;
  --ink-soft:  #4B5563;
  --rust:      #B5501E;
  --rust-deep: #8E3D14;
  --rust-soft: #F0D2B8;
  --navy:      #1B2333;
  --navy-2:    #2A3346;

  /* V3 additions */
  --hair:      rgba(27, 35, 51, 0.14);
  --hair-2:    rgba(27, 35, 51, 0.08);
  --hair-band: rgba(255, 255, 255, 0.16);
  --band-text: #F1EEE6;
  --band-soft: #C7CBD6;

  --font-display: "Manrope", system-ui, sans-serif;
  --font-body: "Public Sans", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  --radius: 6px;
  --radius-lg: 14px;
  --shadow-card: 0 4px 14px rgba(27, 35, 51, 0.10), 0 1px 3px rgba(27, 35, 51, 0.08);
  --shadow-lift: 0 14px 34px rgba(27, 35, 51, 0.14);

  --ease: cubic-bezier(.2,.8,.2,1);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
img, picture, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }
ul, ol { list-style: none; }

/* ---------- Painting order: html carries bg + decoration, body transparent ---------- */
html {
  background-color: var(--paper);
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

html::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(90deg, rgba(181, 80, 30, 0.30) 1px, transparent 1px),
    linear-gradient(0deg, rgba(181, 80, 30, 0.30) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(ellipse 70% 55% at 50% 0%, black 40%, transparent 78%);
  mask-image: radial-gradient(ellipse 70% 55% at 50% 0%, black 40%, transparent 78%);
}

body {
  background: transparent;
  font-family: var(--font-body);
  color: var(--ink);
  line-height: 1.6;
  font-size: 17px;
  -webkit-font-smoothing: antialiased;
}

main { position: relative; z-index: 1; }
header.site-header, footer.site-footer { position: relative; z-index: 1; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.1;
  color: var(--ink);
  letter-spacing: -0.01em;
  text-wrap: balance;
}
h1 { font-size: clamp(2.1rem, 4.2vw + 1rem, 3.4rem); }
h2 { font-size: clamp(1.6rem, 2.1vw + 1rem, 2.25rem); }
h3 { font-size: 1.2rem; font-weight: 700; }
h4 { font-size: 1rem; font-weight: 700; }

p { color: var(--ink-soft); max-width: 64ch; }
p + p { margin-top: 14px; }
.mono { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.01em; }
.lede { font-size: 1.13rem; color: var(--ink-soft); }
a.inline-link { color: var(--rust); text-decoration: underline; text-underline-offset: 3px; font-weight: 600; }
a.inline-link:hover { color: var(--rust-deep); }

/* ---------- Layout helpers ---------- */
.wrap { max-width: 1140px; margin: 0 auto; padding: 0 24px; }
.wrap--narrow { max-width: 780px; }
.wrap--mid { max-width: 900px; }
.section { padding: 84px 0; background: transparent; }
.section--tight { padding: 52px 0; }
.section--band { background: var(--navy); color: var(--band-text); }
.section--band h1, .section--band h2, .section--band h3, .section--band h4 { color: var(--band-text); }
.section--band p { color: var(--band-soft); }
.section--band .eyebrow { background: rgba(255,255,255,0.10); color: #F4C7A6; }
.section--soft { background: var(--paper-2); }
.section--edge { border-top: 1px solid var(--hair); }

@media (max-width: 768px) {
  .section { padding: 56px 0; }
  .section--tight { padding: 40px 0; }
}

/* ---------- Skip link + focus ---------- */
.skip-link { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.skip-link:focus {
  position: fixed; top: 12px; left: 12px; width: auto; height: auto; padding: 10px 16px;
  background: var(--rust); color: #fff; border-radius: 999px; z-index: 1000; font-weight: 700;
}
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--rust); outline-offset: 2px; border-radius: 3px; }

/* ---------- Header / nav ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(247, 242, 233, 0.93);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--hair);
}
.nav-row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 24px; max-width: 1140px; margin: 0 auto;
}
.brand-wordmark {
  font-family: var(--font-display); font-weight: 800; font-size: 1.12rem;
  color: var(--ink); display: flex; flex-direction: column; line-height: 1;
}
.brand-wordmark .b1 { letter-spacing: -0.015em; }
.brand-wordmark .b2 {
  font-size: 0.6rem; font-weight: 600; letter-spacing: 0.16em; color: var(--rust);
  text-transform: uppercase; margin-top: 4px;
}
.nav-links { display: flex; gap: 24px; align-items: center; }
.nav-links a { font-weight: 600; font-size: 0.92rem; color: var(--ink-soft); transition: color 180ms var(--ease); }
.nav-links a:hover, .nav-links a:focus-visible { color: var(--rust); }
.nav-phone {
  font-family: var(--font-mono); font-weight: 600; font-size: 0.9rem; color: var(--ink) !important;
  border-left: 1px solid var(--hair); padding-left: 24px;
}
.nav-cta {
  background: var(--rust); color: #fff !important; padding: 10px 18px; border-radius: 999px;
  font-weight: 700; font-size: 0.88rem;
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease);
}
.nav-cta:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(181,80,30,0.35); }

.nav-mobile { display: none; }
@media (max-width: 980px) {
  .nav-links.desktop-only { display: none; }
  .nav-mobile { display: block; }
  .nav-mobile summary {
    list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; border-radius: var(--radius);
  }
  .nav-mobile summary::-webkit-details-marker { display: none; }
  .nav-mobile summary::marker { content: ''; }
  .nav-mobile .bars { display: flex; flex-direction: column; gap: 4px; }
  .nav-mobile .bars span { width: 22px; height: 2px; background: var(--ink); display: block; }
  .nav-mobile[open] .mobile-panel {
    position: fixed; inset: 0; top: 62px; background: var(--paper); padding: 24px;
    display: flex; flex-direction: column; gap: 18px; z-index: 60; overflow-y: auto;
  }
  .nav-mobile .mobile-panel a { font-size: 1.1rem; font-weight: 700; }
  .nav-mobile .mobile-panel .nav-phone { border-left: none; padding-left: 0; }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 14px 26px; border-radius: 999px; font-weight: 700; font-size: 1rem; min-height: 44px;
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease), background 160ms var(--ease), color 160ms var(--ease);
  border: 2px solid transparent; text-align: center;
}
.btn-primary { background: var(--rust); color: #fff; }
.btn-primary:hover, .btn-primary:focus-visible { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(181,80,30,0.32); }
.btn-outline { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn-outline:hover, .btn-outline:focus-visible { background: var(--ink); color: #fff; }
.btn-band-outline { background: transparent; color: var(--band-text); border-color: var(--band-text); }
.btn-band-outline:hover, .btn-band-outline:focus-visible { background: var(--band-text); color: var(--navy); }
.btn-sm { padding: 10px 18px; font-size: 0.9rem; min-height: 40px; }

/* ---------- Eyebrow + section index rules (work-order motif) ---------- */
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--rust); background: var(--rust-soft); padding: 6px 12px; border-radius: 999px;
  margin-bottom: 18px; font-weight: 600;
}
.rule-head { display: flex; align-items: center; gap: 16px; margin-bottom: 26px; }
.rule-head .idx {
  font-family: var(--font-mono); font-size: 0.75rem; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--rust); white-space: nowrap;
}
.rule-head .line { flex: 1; height: 1px; background: var(--hair); }
.section--band .rule-head .line { background: var(--hair-band); }
.section--band .rule-head .idx { color: #F4C7A6; }
.section-head { max-width: 660px; margin-bottom: 44px; }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }
.section-head h2 { margin-bottom: 14px; }

/* ---------- Breadcrumb ---------- */
.crumbs {
  font-family: var(--font-mono); font-size: 0.76rem; letter-spacing: 0.04em;
  color: var(--ink-soft); padding: 18px 0 0; display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
}
.crumbs a { color: var(--ink-soft); }
.crumbs a:hover { color: var(--rust); }
.crumbs .sep { color: var(--rust); }
.crumbs .here { color: var(--ink); font-weight: 600; }

/* ---------- Placeholder chips (client-input markers, intentionally visible) ---------- */
.ph {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-mono); font-size: 0.74rem; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--rust-deep);
  background: repeating-linear-gradient(45deg, rgba(181,80,30,0.07) 0 8px, transparent 8px 16px);
  border: 1px dashed var(--rust); border-radius: 4px; padding: 5px 10px; white-space: nowrap;
}
.ph--price { font-size: 0.9rem; padding: 8px 14px; }
/* .ph is nowrap by default because most chips are two words. The V3.1b chips
   ([WARRANTY — Connor decision pending], [PAYMENT METHODS — Connor]) are long
   enough to force a horizontal scroll at 320px if they can't break, so they opt
   out. Verified in the 320px sweep. */
.ph--long { white-space: normal; text-align: left; }
.section--band .ph { color: #F6C9A9; border-color: #C97A48; }
.slot {
  border: 1px dashed var(--rust); border-radius: var(--radius-lg); padding: 26px;
  background: repeating-linear-gradient(45deg, rgba(181,80,30,0.05) 0 10px, transparent 10px 20px);
}
.slot h3 { margin-bottom: 8px; }
.slot p { font-size: 0.95rem; }

/* ---------- Hero ---------- */
.hero { background: transparent; padding: 64px 0 56px; position: relative; }
.hero--home { padding: 72px 0 64px; }
.hero-grid { display: grid; grid-template-columns: 1.12fr 0.88fr; gap: 52px; align-items: center; }
@media (max-width: 940px) { .hero-grid { grid-template-columns: 1fr; gap: 36px; } }
.hero h1 { margin-bottom: 18px; }
.hero .lede { margin-bottom: 28px; max-width: 56ch; }
.hero-ctas { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 24px; }
.hero-trust-line {
  font-size: 0.88rem; color: var(--ink-soft); display: flex; align-items: center; gap: 14px;
  flex-wrap: wrap; font-family: var(--font-mono); font-weight: 500;
}
.hero-trust-line span.item { display: inline-flex; align-items: center; gap: 7px; }
.hero-trust-line .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--rust); display: inline-block; }

/* Hero visual panel — CSS-only (no client photos yet) */
.hero-visual {
  background: var(--navy); border-radius: var(--radius-lg); aspect-ratio: 4/5;
  position: relative; overflow: hidden; box-shadow: var(--shadow-card);
}
.hero-visual--square { aspect-ratio: 1/1; }
.hero-visual::before {
  content: ''; position: absolute; inset: 0;
  background-image:
    linear-gradient(90deg, rgba(255,255,255,0.075) 1px, transparent 1px),
    linear-gradient(0deg, rgba(255,255,255,0.075) 1px, transparent 1px);
  background-size: 34px 34px;
}
.hero-visual::after {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 70% 55% at 25% 15%, rgba(181,80,30,0.55), transparent 60%),
    radial-gradient(ellipse 60% 50% at 80% 85%, rgba(181,80,30,0.26), transparent 60%);
}
/* PHOTO SLOT — fail-open, sitewide (V3.1b). Every .hero-visual panel is emitted
   by common.photo_panel() and accepts an <img class="hero-visual-img"
   data-photo-slot> as its FIRST child. The img sits above the grid/wash
   decoration and below the content, so the trade tag and the name stay readable.
   initPhotoSlots() in main.js removes the img if it fails to load and the panel
   falls back to this treatment — no broken-image glyph anywhere on the site. */
.hero-visual-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 1;
}
/* Scrim only exists while a real photo does. If initPhotoSlots() removes a
   failed image, :has() re-evaluates and the scrim disappears with it — the
   fail-open path needs no second code path. */
.hero-visual:has(.hero-visual-img) .hero-visual-content {
  background: linear-gradient(180deg, rgba(18,23,36,0.62) 0%, rgba(18,23,36,0.18) 42%, rgba(18,23,36,0.80) 100%);
}
.hero-visual-content {
  position: relative; z-index: 2; height: 100%;
  display: flex; flex-direction: column; justify-content: space-between; padding: 26px; color: var(--band-text);
}
.hero-visual-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.hero-visual-tag {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: #F4C7A6; border: 1px solid rgba(244,199,166,0.4); padding: 5px 9px; border-radius: 4px;
}
.hero-visual-content .initials {
  width: 62px; height: 62px; border-radius: 50%; background: var(--rust); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: 800; font-size: 1.3rem; margin-bottom: 14px;
}
.hero-visual-content .name { font-family: var(--font-display); font-weight: 800; font-size: 1.1rem; }
.hero-visual-content .role { font-size: 0.84rem; color: var(--band-soft); margin-top: 2px; }

/* ---------- Cards ---------- */
.grid { display: grid; gap: 22px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 960px) { .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 860px) { .grid--3, .grid--2 { grid-template-columns: 1fr; } }
@media (max-width: 560px) { .grid--4 { grid-template-columns: 1fr; } }

.card {
  background: var(--paper-3); border: 1px solid var(--hair-2); border-radius: var(--radius-lg);
  padding: 26px; box-shadow: var(--shadow-card); position: relative;
}
.card h3 { margin-bottom: 10px; }
.card p { font-size: 0.97rem; }
.card .icon-chip {
  width: 42px; height: 42px; border-radius: 10px; background: var(--rust-soft); color: var(--rust);
  display: flex; align-items: center; justify-content: center; margin-bottom: 14px;
  font-family: var(--font-mono); font-weight: 600; font-size: 0.9rem;
}
.card--ticket { padding-top: 30px; }
.card--ticket::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--rust); border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.card--ticket .tick-idx {
  position: absolute; top: 10px; right: 16px;
  font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.1em; color: var(--rust);
}

/* ---------- Service index (hub): full-width numbered rows ---------- */
.svc-index { border-top: 1px solid var(--hair); margin-top: 8px; }
.svc-row {
  display: grid; grid-template-columns: 68px 1fr auto; gap: 20px; align-items: center;
  padding: 24px 8px; border-bottom: 1px solid var(--hair);
  transition: background 180ms var(--ease), padding-left 180ms var(--ease);
}
.svc-row:hover, .svc-row:focus-visible { background: rgba(181,80,30,0.055); padding-left: 16px; }
.svc-row .num {
  font-family: var(--font-mono); font-weight: 600; font-size: 1.5rem; color: var(--rust); line-height: 1;
}
.svc-row h3 { margin-bottom: 5px; }
.svc-row p { font-size: 0.95rem; margin: 0; max-width: 60ch; }
.svc-row .go {
  font-family: var(--font-mono); font-size: 0.78rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--rust); white-space: nowrap; display: inline-flex; align-items: center; gap: 6px;
}
.svc-row:hover .go { color: var(--rust-deep); }
@media (max-width: 700px) {
  .svc-row { grid-template-columns: 44px 1fr; gap: 14px; padding: 20px 4px; }
  .svc-row .num { font-size: 1.15rem; }
  .svc-row .go { grid-column: 2; }
}

/* ---------- Process ladder (Ace "Our Process" block, our voice) ---------- */
.ladder { margin-top: 8px; border-left: 2px solid var(--rust-soft); padding-left: 0; }
.ladder-step { position: relative; padding: 0 0 30px 34px; }
.ladder-step:last-child { padding-bottom: 0; }
.ladder-step::before {
  content: attr(data-step); position: absolute; left: -13px; top: 0;
  width: 24px; height: 24px; border-radius: 50%; background: var(--rust); color: #fff;
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
.ladder-step h3 { margin-bottom: 6px; }
.ladder-step p { font-size: 0.97rem; }

/* ---------- Spec rows (dotted-leader "what you get" lists) ---------- */
.specs { border-top: 1px solid var(--hair); }
.spec {
  display: flex; align-items: baseline; gap: 10px; padding: 13px 0; border-bottom: 1px solid var(--hair);
}
.spec .k { font-weight: 600; color: var(--ink); font-size: 0.97rem; }
.spec .lead { flex: 1; border-bottom: 1px dotted rgba(27,35,51,0.28); transform: translateY(-4px); min-width: 18px; }
.spec .v { font-family: var(--font-mono); font-size: 0.88rem; color: var(--ink-soft); text-align: right; }
.section--band .spec { border-color: var(--hair-band); }
.section--band .spec .k { color: var(--band-text); }
.section--band .spec .v { color: var(--band-soft); }
.section--band .spec .lead { border-color: rgba(255,255,255,0.28); }

.checklist { display: grid; gap: 11px; margin-top: 6px; }
.checklist li {
  position: relative; padding-left: 26px; color: var(--ink-soft); font-size: 0.97rem;
}
.checklist li::before {
  content: ''; position: absolute; left: 0; top: 8px; width: 12px; height: 7px;
  border-left: 2px solid var(--rust); border-bottom: 2px solid var(--rust); transform: rotate(-45deg);
}
.section--band .checklist li { color: var(--band-soft); }

/* ---------- Package cards ---------- */
.pkg {
  background: var(--paper-3); border: 1px solid var(--hair); border-radius: var(--radius-lg);
  padding: 0; overflow: hidden; display: flex; flex-direction: column; box-shadow: var(--shadow-card);
}
.pkg-head { padding: 24px 26px 18px; border-bottom: 1px solid var(--hair); background: rgba(181,80,30,0.045); }
.pkg-head .kicker {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--rust); display: block; margin-bottom: 8px;
}
.pkg-head h3 { font-size: 1.35rem; margin-bottom: 6px; }
.pkg-time { font-family: var(--font-mono); font-size: 0.85rem; color: var(--ink-soft); }
.pkg-body { padding: 22px 26px; flex: 1; }
.pkg-foot { padding: 18px 26px 24px; border-top: 1px solid var(--hair); display: flex; flex-direction: column; gap: 12px; }
.pkg-foot .price-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.pkg-foot .price-label {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-soft);
}

/* ---------- Related content module ---------- */
.related { border-top: 1px solid var(--hair); padding-top: 34px; }
.related-links { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
.related-links a {
  display: inline-flex; align-items: center; gap: 7px; padding: 9px 15px;
  border: 1px solid var(--hair); border-radius: 999px; background: var(--paper-3);
  font-size: 0.9rem; font-weight: 600; color: var(--ink);
  transition: border-color 160ms var(--ease), color 160ms var(--ease), transform 160ms var(--ease);
}
.related-links a:hover { border-color: var(--rust); color: var(--rust); transform: translateY(-1px); }
.related-links a .arw { font-family: var(--font-mono); color: var(--rust); font-size: 0.8rem; }

/* ---------- Area list ---------- */
.area-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.area-list li {
  font-family: var(--font-mono); font-size: 0.82rem; color: var(--ink-soft);
  border: 1px solid var(--hair); border-radius: 4px; padding: 6px 11px; background: var(--paper-3);
}
.section--band .area-list li { color: var(--band-soft); border-color: var(--hair-band); background: rgba(255,255,255,0.04); }

/* ---------- FAQ accordion ---------- */
.faq-item { border-bottom: 1px solid var(--hair); }
.faq-item:first-child { border-top: 1px solid var(--hair); }
.faq-q {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: none; border: none; text-align: left; padding: 21px 4px;
  font-family: var(--font-display); font-weight: 700; font-size: 1.03rem; color: var(--ink);
}
.faq-q:hover { color: var(--rust); }
.faq-chevron { transition: transform 220ms var(--ease); flex-shrink: 0; }
.faq-q[aria-expanded="true"] .faq-chevron { transform: rotate(180deg); }
.faq-a { padding: 0 4px 21px; }
.faq-a[hidden] { display: none; }

/* ---------- Forms ---------- */
.form-card {
  background: var(--paper-3); border: 1px solid var(--hair); border-radius: var(--radius-lg);
  padding: 30px; box-shadow: var(--shadow-card);
}
@media (max-width: 560px) { .form-card { padding: 22px 18px; } }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 640px) { .form-row { grid-template-columns: 1fr; gap: 0; } }
.form-field { margin-bottom: 18px; }
.form-field label { display: block; font-weight: 700; font-size: 0.88rem; margin-bottom: 7px; color: var(--ink); }
.form-field label .req { color: var(--rust); font-family: var(--font-mono); }
.form-field .hint { font-size: 0.81rem; color: var(--ink-soft); margin-top: 6px; }
.form-field input, .form-field textarea, .form-field select {
  width: 100%; padding: 13px 14px; border: 1.5px solid rgba(27,35,51,0.18); border-radius: var(--radius);
  background: #fff; font: inherit; color: var(--ink);
  transition: border-color 150ms var(--ease), box-shadow 150ms var(--ease);
}
.form-field input:focus-visible, .form-field textarea:focus-visible, .form-field select:focus-visible {
  border-color: var(--rust); box-shadow: 0 0 0 3px rgba(181,80,30,0.14); outline: none;
}
.form-field.has-error input, .form-field.has-error textarea, .form-field.has-error select { border-color: #B3261E; }
.field-error { display: none; color: #B3261E; font-size: 0.82rem; font-weight: 600; margin-top: 6px; }
.form-field.has-error .field-error { display: block; }
.form-check { display: flex; align-items: flex-start; gap: 11px; margin-bottom: 16px; }
.form-check input[type="checkbox"] { width: 20px; height: 20px; margin-top: 2px; flex-shrink: 0; accent-color: var(--rust); }
.form-check label { font-weight: 400; font-size: 0.86rem; color: var(--ink-soft); line-height: 1.55; }
.consent-block { border-top: 1px solid var(--hair); margin-top: 24px; padding-top: 22px; }
.consent-block .consent-title {
  font-family: var(--font-mono); font-size: 0.74rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--rust); margin-bottom: 14px; display: block; font-weight: 600;
}
/* Server-decided states. .form-alert is the banner /api/lead bounces a rejected
   submission back into (?error=missing / ?error=send); .heldup-note is the
   honest line on the thank-you page when the CRM write failed (?heldup=1).
   Both ship hidden and are unhidden by initServerFormState() in main.js. */
.form-alert {
  margin: 0 0 22px; padding: 13px 15px; border-radius: var(--radius);
  border: 1.5px solid #B3261E; border-left-width: 4px; background: rgba(179,38,30,0.06);
  color: #8E1D17; font-weight: 600; font-size: 0.9rem; line-height: 1.5;
}
.form-alert[hidden] { display: none; }
.heldup-note {
  margin-top: 18px; padding: 13px 15px; border-radius: var(--radius);
  border: 1.5px solid var(--rust); border-left-width: 4px; background: rgba(181,80,30,0.07);
  color: var(--rust-deep); font-weight: 600; font-size: 0.92rem; line-height: 1.55;
}
.heldup-note[hidden] { display: none; }
.form-status { margin-top: 14px; font-weight: 600; font-size: 0.94rem; min-height: 1.2em; }
.form-status.is-error { color: #B3261E; }
.form-status.is-ok { color: var(--rust-deep); }
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ---------- Sticky mobile CTA bar ---------- */
.sticky-cta { display: none; }
@media (max-width: 760px) {
  .sticky-cta {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 80;
    background: var(--navy); padding: 10px 14px calc(10px + env(safe-area-inset-bottom)); gap: 10px;
  }
  .sticky-cta a { flex: 1; text-align: center; }
  body { padding-bottom: 74px; }
}

/* ---------- Footer ---------- */
.site-footer { background: var(--navy); color: var(--band-soft); padding: 54px 0 26px; }
.footer-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1.2fr; gap: 30px; margin-bottom: 34px; }
@media (max-width: 900px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .footer-grid { grid-template-columns: 1fr; } }
.site-footer h4 { color: var(--band-text); font-size: 0.92rem; margin-bottom: 13px; }
.site-footer a { color: var(--band-soft); font-size: 0.9rem; }
.site-footer a:hover, .site-footer a:focus-visible { color: #fff; }
.site-footer p { color: var(--band-soft); font-size: 0.9rem; }
.footer-links { display: flex; flex-direction: column; gap: 9px; }
.footer-addr { font-style: normal; font-size: 0.9rem; line-height: 1.7; color: var(--band-soft); }
.footer-bottom {
  border-top: 1px solid var(--hair-band); padding-top: 20px;
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px;
  font-size: 0.8rem; color: #8E96A8;
}
.footer-bottom a { color: #8E96A8; font-size: 0.8rem; }

/* ---------- Legal pages ---------- */
.legal-content h2 { margin-top: 38px; margin-bottom: 13px; font-size: 1.28rem; }
.legal-content h2:first-child { margin-top: 0; }
.legal-content p, .legal-content li { margin-bottom: 13px; color: var(--ink-soft); }
.legal-content ul, .legal-content ol { padding-left: 22px; margin-bottom: 13px; }
.legal-content ul li, .legal-content ol li { list-style: revert; }
.legal-content strong { color: var(--ink); }
.legal-content a { color: var(--rust); text-decoration: underline; text-underline-offset: 3px; }
.legal-updated {
  font-family: var(--font-mono); font-size: 0.84rem; color: var(--rust);
  margin-bottom: 30px; display: inline-block;
}

/* ---------- Reveal-on-scroll (quiet baseline) ---------- */
.reveal { opacity: 0; transform: translateY(12px); transition: opacity 350ms var(--ease), transform 350ms var(--ease); }
.reveal.is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; transition: none; } }

/* ---------- Utility ---------- */
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.mt-sm { margin-top: 14px; }
.mt-md { margin-top: 26px; }
.mt-lg { margin-top: 40px; }
.mb-sm { margin-bottom: 14px; }
.mb-md { margin-bottom: 26px; }
.mb-lg { margin-bottom: 40px; }
.note {
  font-size: 0.9rem; color: var(--ink-soft); border-left: 3px solid var(--rust-soft);
  padding-left: 14px; max-width: 66ch;
}
.stack-sm > * + * { margin-top: 10px; }
.flex-ctas { display: flex; gap: 14px; flex-wrap: wrap; }


/* ==========================================================================
   V3.1 LAYER — brand emblem, Ace-mirror hero, service picker, opening intro
   Added 2026-08-02. Everything below is additive: no V3 rule above this line
   was edited, so reverting V3.1 is a matter of deleting from here down plus
   the four initXxx() calls in main.js.
   ========================================================================== */

/* ---------- EMBLEM + LOCKUP -----------------------------------------------
   ONE custom property (--em, the emblem width) drives the entire lockup; every
   other dimension is a fixed ratio of it. That is what makes it a true logo —
   it scales as one rigid unit, and it is why the opening animation can land its
   big centred lockup on the hero lockup with a MEASURED scale factor rather
   than an eyeballed guess. Do not hard-code px inside this block.
   The shield plate is inline SVG with no glyphs; "FAS" is real HTML text layered
   over it, so the monogram renders with the same font everywhere.
   -------------------------------------------------------------------------- */
.emblem { position: relative; width: var(--em, 180px); aspect-ratio: 120 / 140; flex: 0 0 auto; }
.emblem svg { width: 100%; height: 100%; }
.emblem-fas {
  position: absolute; left: 0; right: 0; top: 61%;
  font-family: var(--font-display); font-weight: 800; letter-spacing: 0.01em;
  text-align: center; color: var(--navy); line-height: 1;
  font-size: calc(var(--em, 180px) * 0.285);
  transform: translateY(-50%); pointer-events: none;
}
.emblem-fas i { font-style: normal; display: inline-block; }

/* HORIZONTAL BUILD — owner-revised 2026-08-02 (V3.1a), refined V3.1c.
   Shield left; one left-aligned stack to its right: FORTIFIED, the rust chalk
   line directly beneath it, HANDYMAN SERVICES beneath the line. One tier, one
   tight unit. This is the header lockup's arrangement at hero scale.

   ---- V3.1c VERTICAL ALIGNMENT (--cap-fix) --------------------------------
   The cap-height top of the "F" in FORTIFIED is aligned with the TOP OF THE
   LIGHT HORIZONTAL STRIPE inside the shield — the sand band between the rust
   gable and the rust hairline. In the variant-B plate that stripe's top edge is
   the roof triangle's base, at viewBox y=36 of a 0 0 120 140 box. The SVG fills
   the emblem box exactly (aspect-ratio 120/140, no letterboxing), so:

       stripe top, from the emblem box top =  36/120 * --em  =  0.30 * --em

   Inside the word's own box the cap top sits below the box top by
   half-leading + fontAscent - capHeight. That distance is MEASURED OFF PIXELS,
   not taken from canvas metrics: Chrome's measureText('F').actualBoundingBoxAscent
   reports 0.735 of the font-size for Manrope 800, but the raster's cap height is
   0.71995 — trusting the canvas number puts the word ~0.9px low at 1280. So the
   figure below comes from an 8-sample sweep of the real element blown up to
   --em 500-920px, reading the F's flat top arm at the 50%-coverage row:

       cap top below the word's box top = 0.0914 of the font-size
       the word is 0.52 * --em          = 0.0914 * 0.52 = 0.047528 * --em

       --cap-fix = 0.30 - 0.047528 = 0.252472   (rounded to 0.2525)

   Cross-check, analytic: line-height 0.86 with Manrope 800's own ascent 1.066
   and descent 0.300 puts the baseline 0.813 below the box top; minus the 0.71995
   raster cap height gives 0.09305 — 0.0016 off the measured mean, i.e. inside
   the baseline's device-pixel snapping. Both routes agree; the pixel sweep wins
   because it is what the visitor actually sees.

   V3.1a aligned to the shield's OUTER TOP EDGE and therefore pulled the stack
   UP (margin-top was negative). V3.1c aligns to the stripe and pushes it DOWN,
   so the sign flipped. FORTIFIED's SIZE is unchanged at 0.52 * --em.
   The lockup's total height is still set by the emblem (1.1667 * --em), not by
   the stack (which now bottoms out at ~1.04 * --em), so nothing below the
   lockup moved: the hero's vertical rhythm is untouched.
   -------------------------------------------------------------------------- */
.lockup {
  --cap-fix: 0.2525;
  display: flex; align-items: flex-start;
  gap: calc(var(--em, 180px) * 0.125);
}
.lockup-stack {
  display: flex; flex-direction: column; align-items: flex-start;
  margin-top: calc(var(--em, 180px) * var(--cap-fix));
}
.lockup-word {
  font-family: var(--font-display); font-weight: 800; letter-spacing: -0.025em;
  line-height: 0.86; color: var(--paper); font-size: calc(var(--em, 180px) * 0.52);
  white-space: nowrap;
}
/* the chalk line spans the stack, whose width is set by FORTIFIED (the widest
   child), so the rule ends exactly where the word ends */
.lockup-rule {
  position: relative; align-self: stretch;
  height: max(2px, calc(var(--em, 180px) * 0.017)); background: var(--rust);
  margin-top: calc(var(--em, 180px) * 0.062);
}
/* ---- V3.1c SUB-LINE: width-matched to FORTIFIED, tucked up under the rule ----
   The sub-line is a flex row with justify-content:space-between and
   align-self:stretch, so it fills the stack — and the stack's width is set by
   FORTIFIED. "Sub-line width == FORTIFIED width" is therefore a PROPERTY OF THE
   LAYOUT, exact at every --em, not a number to re-tune when the font or the
   string changes. There is no letter-spacing on this element any more: the
   distributed gaps ARE the tracking.
   Font-size is chosen so those gaps read as deliberate tracking rather than as
   a scattered line. IBM Plex Mono advances 0.6em/char; 17 chars gives a natural
   width of 10.2 * font-size, and FORTIFIED measures 2.4781 * --em. At
   0.175 * --em the natural width is 1.785 * --em, leaving 0.693 * --em spread
   over 16 gaps = 0.0433 * --em each = 0.247 of the sub's own font-size — i.e.
   an effective ~0.25em tracking.
   HARD CONSTRAINT: keep font-size below 0.2429 * --em. Above that the sub's
   max-content exceeds FORTIFIED's width, the sub starts defining the stack
   width instead, and the chalk line stops matching the word. */
.lockup-sub {
  display: flex; align-self: stretch; justify-content: space-between;
  font-family: var(--font-mono); font-weight: 500; text-transform: uppercase;
  letter-spacing: 0; text-indent: 0;
  color: var(--rust-soft); font-size: calc(var(--em, 180px) * 0.175);
  line-height: 1.1;
  margin-top: calc(var(--em, 180px) * 0.026);
  white-space: nowrap;
}
.lockup-sub i { font-style: normal; display: inline-block; }

/* ---------- Compact lockup: header + footer ---------- */
.brand-lockup { display: flex; align-items: center; gap: 11px; color: var(--ink); }
.brand-lockup .emblem--nav { --em: 36px; }
.brand-lockup .bl-text { display: flex; flex-direction: column; line-height: 1; }
.brand-lockup .bl1 {
  font-family: var(--font-display); font-weight: 800; font-size: 1.06rem; letter-spacing: -0.015em;
}
.brand-lockup .bl2 {
  font-family: var(--font-mono); font-size: 0.58rem; font-weight: 600; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--rust); margin-top: 4px;
}
.brand-lockup--dark { color: var(--band-text); }
.brand-lockup--dark .bl2 { color: var(--rust-soft); }
@media (max-width: 420px) {
  .brand-lockup .emblem--nav { --em: 30px; }
  .brand-lockup .bl1 { font-size: 0.95rem; }
  .brand-lockup .bl2 { font-size: 0.52rem; letter-spacing: 0.14em; }
}

/* ==========================================================================
   ACE-MIRROR HERO  (homepage only)
   Full-bleed dark field, photo panel left-weighted, emblem + one headline +
   one action centre-right. The H1 is deliberately set at body-copy scale — the
   emblem is the hero. It is still a real <h1> with the full headline.
   ========================================================================== */
.hero-ace {
  position: relative; display: flex;
  /* The mockup's hero was full-viewport with a transparent overlay header. The
     production site keeps its sticky sand header on all 23 pages for consistency,
     so the hero subtracts the header band — otherwise the trust strip sits a full
     header-height below the fold at every viewport. --hdr is the measured height
     of .nav-row (14px + 44px + 14px) plus its 1px border. */
  --hdr: 73px;
  min-height: min(880px, calc(100svh - var(--hdr)));
  background: var(--navy); overflow: hidden; isolation: isolate;
  margin-top: -1px;
}

/* PHOTO PANEL — graceful degradation (locked decision #4).
   No <img> ships, so this IS the panel: textured navy, work-hatch, crop marks.
   An <img data-photo-slot> dropped in later paints over it; if that image fails
   to load main.js removes it and the visitor lands back on this treatment
   rather than a broken-image glyph. */
.hero-photo {
  position: absolute; inset: 0 auto 0 0; width: clamp(300px, 46vw, 760px); z-index: 0;
  background: linear-gradient(160deg, #26314A 0%, #1C2436 55%, #151B29 100%);
  overflow: hidden;
}
.hero-photo::before {
  content: ''; position: absolute; inset: 0;
  background-image: repeating-linear-gradient(-38deg, rgba(247,242,233,0.085) 0 2px, transparent 2px 13px);
}
.hero-photo::after {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 62% 48% at 34% 26%, rgba(181,80,30,0.42), transparent 66%),
    radial-gradient(ellipse 70% 60% at 74% 92%, rgba(181,80,30,0.16), transparent 64%),
    linear-gradient(90deg, transparent 52%, var(--navy) 99%);
}
.hero-photo-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 1;
}
.photo-marks { position: absolute; inset: 22px; z-index: 2; pointer-events: none; }
.photo-marks i { position: absolute; width: 26px; height: 26px; border: 2px solid rgba(247,242,233,0.30); }
.photo-marks i:nth-child(1) { top: 0; left: 0; border-right: 0; border-bottom: 0; }
.photo-marks i:nth-child(2) { top: 0; right: 0; border-left: 0; border-bottom: 0; }
.photo-marks i:nth-child(3) { bottom: 0; left: 0; border-right: 0; border-top: 0; }
.photo-marks i:nth-child(4) { bottom: 0; right: 0; border-left: 0; border-top: 0; }
.photo-label {
  position: absolute; z-index: 3;
  left: clamp(20px, 3.4vw, 46px); bottom: clamp(20px, 3.4vw, 46px);
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.10em; color: var(--paper);
  background: rgba(18,23,36,0.72); border: 1px dashed rgba(247,242,233,0.42);
  padding: 9px 14px; border-radius: var(--radius);
  max-width: min(84%, 340px); line-height: 1.4;
}
.photo-label .ph { color: #F6C9A9; border-color: #C97A48; background: none; }
.photo-label b {
  display: block; color: var(--rust-soft); font-weight: 500; font-size: 0.64rem;
  letter-spacing: 0.16em; margin-top: 5px;
}

.hero-ace-inner {
  position: relative; z-index: 2; margin-left: auto;
  width: min(100%, 72ch); flex: 0 1 auto;
  padding: clamp(56px, 8vh, 110px) clamp(20px, 5vw, 64px) clamp(48px, 7vh, 80px);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; color: var(--paper);
}
/* The centre-right column is 58% of the hero — but NOT below 640px of it. At
   exactly 1000px the old flat `width:58%` was NARROWER (580px) than the 72ch the
   rule replaced (~640px), so the column pinched inward at the breakpoint; with
   the V3.1c H1 two steps larger that pinch wrapped "Handyman" onto a second line
   between 1000 and 1070px. max() removes the discontinuity: 640px wins until
   1104px, 58% wins above it, and the two meet exactly. */
@media (min-width: 1000px) {
  .hero-ace-inner { width: max(58%, 640px); margin-right: clamp(0px, 3vw, 60px); }
}

/* THE EMBLEM IS THE HERO — one variable sizes the whole lockup.
   Measured, not estimated: the horizontal build is 3.6028 x --em wide
   (1 emblem + 0.125 gap + FORTIFIED at 2.4778 x --em) and 1.1667 x --em tall
   (the emblem sets the height; even after the V3.1c cap-fix push the stack
   bottoms out at 0.997 x --em, 1.023 on the mobile ratio, so it never reaches
   the emblem and the lockup's box did NOT grow). Against ~3.48x for
   the old stacked build, so the clamp came down to keep the unit inside the hero
   content box at every viewport from 320px to 2560px. */
.hero-lockup { --em: clamp(88px, 10.4vw, 168px); }

/* The H1 still sits BELOW the emblem in the visual hierarchy — the emblem is the
   hero — but V3.1c takes it off body-copy scale, where the owner read it as
   undersized against the enlarged lockup. It is a real <h1> carrying the full
   headline, so this is a visual-weight decision, not a markup one.

   ---- V3.1c TYPE BUMP -----------------------------------------------------
   H1 up TWO steps on a 1.125 modular scale (x1.2656):
       min  1.08rem -> 1.37rem   (x1.2685)
       max  1.74rem -> 2.20rem   (x1.2644)
       mid  1.28vw + 0.6rem -> 1.62vw + 0.76rem  (both terms x1.266)
   The sub-line goes up ONE step (x1.125) — half the H1's move — so the gap
   between them WIDENS and the sub stays clearly subordinate.
   max-width 34ch -> 42ch because at the new size 34ch clipped the line short of
   its natural width and wrapped "Handyman" onto its own line.
   Swept in 20px steps from 320px to 2560px: ONE LINE from 440px up, everywhere.
   At 420px and below text-wrap:balance splits it evenly onto two, on purpose. */
.hero-ace h1 {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.37rem, 1.62vw + 0.76rem, 2.2rem);
  line-height: 1.22; letter-spacing: -0.012em; color: var(--paper);
  max-width: 42ch; margin: clamp(24px, 3.2vh, 38px) auto 0; text-wrap: balance;
}
.hero-ace-sub {
  font-size: clamp(1.04rem, 0.56vw + 0.88rem, 1.19rem);
  color: #BFC5D2; max-width: 46ch; margin: 13px auto 0;
}

/* ---------- THE ONE ACTION: service picker ---------- */
.hero-action { width: min(100%, 600px); margin: clamp(26px, 3.6vh, 44px) auto 0; }
.action-label {
  display: block; font-family: var(--font-display); font-weight: 700;
  font-size: 1.02rem; color: var(--paper); margin-bottom: 11px;
}
.action-form { display: flex; gap: 10px; align-items: stretch; }
.combo { position: relative; flex: 1 1 auto; min-width: 0; }
#svcInput {
  width: 100%; height: 60px; padding: 0 16px; border-radius: var(--radius);
  border: 2px solid rgba(247,242,233,0.24); background: var(--paper-3);
  color: var(--ink); font-size: 1.02rem; font-family: var(--font-body);
}
#svcInput::placeholder { color: #8A9099; }
#svcInput:focus { border-color: var(--rust); box-shadow: 0 0 0 4px rgba(181,80,30,0.25); outline: none; }
.btn-go {
  height: 60px; flex: 0 0 auto; padding: 0 clamp(20px, 2.6vw, 34px);
  background: var(--rust); color: #fff; border: 0; border-radius: var(--radius);
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(0.94rem, 0.9vw + 0.5rem, 1.1rem); white-space: nowrap; cursor: pointer;
  transition: background 160ms var(--ease), transform 160ms var(--ease), box-shadow 160ms var(--ease);
}
.btn-go:hover { background: #C75C24; transform: translateY(-2px); box-shadow: 0 12px 26px rgba(181,80,30,0.38); }
.btn-go:active { transform: translateY(0); }

.sugg {
  position: absolute; top: calc(100% + 8px); left: 0; right: 0; z-index: 40;
  background: var(--paper-3); border: 1px solid rgba(27,35,51,0.16); border-radius: var(--radius);
  box-shadow: 0 20px 44px rgba(9,12,20,0.48);
  max-height: 322px; overflow-y: auto; text-align: left; padding: 5px; list-style: none;
}
.sugg[hidden] { display: none; }
.sugg li {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 11px 12px; border-radius: 4px; color: var(--ink); cursor: pointer;
  font-size: 0.98rem; line-height: 1.3;
}
.sugg li .cat {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-soft); flex: 0 0 auto;
}
.sugg li mark { background: var(--rust-soft); color: var(--ink); border-radius: 2px; padding: 0 1px; }
.sugg li[aria-selected="true"], .sugg li:hover { background: var(--rust); color: #fff; }
.sugg li[aria-selected="true"] .cat, .sugg li:hover .cat { color: rgba(255,255,255,0.72); }
.sugg li[aria-selected="true"] mark, .sugg li:hover mark { background: rgba(255,255,255,0.26); color: #fff; }
.sugg .empty { padding: 13px 12px; color: var(--ink-soft); font-size: 0.92rem; cursor: default; }
.sugg .empty:hover { background: transparent; color: var(--ink-soft); }

.action-note {
  margin-top: 12px; font-family: var(--font-mono);
  font-size: 0.7rem; letter-spacing: 0.09em; text-transform: uppercase; color: #9AA3B5;
}
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (max-width: 640px) {
  .action-form { flex-direction: column; }
  .btn-go { width: 100%; }
}
/* Mobile: the lockup STAYS horizontal — it is one unit and breaking it into two
   tiers on a phone is exactly the thing this revision removed. It just gets
   smaller and centres. The photo panel becomes a full-width background wash
   behind the content rather than a left column. */
@media (max-width: 640px) {
  .hero-lockup { --em: clamp(58px, 18vw, 104px); }
  .lockup { gap: calc(var(--em, 180px) * 0.11); }
  /* smaller --em means fewer real pixels per glyph, so the sub takes a slightly
     larger ratio to stay legible. Still well under the 0.2429 ceiling that would
     make the sub, not FORTIFIED, define the stack width. */
  .lockup-sub { font-size: calc(var(--em, 180px) * 0.195); margin-top: calc(var(--em, 180px) * 0.03); }
  .hero-photo { width: 100%; opacity: 0.45; }
  .hero-photo::after { background:
    radial-gradient(ellipse 74% 46% at 40% 24%, rgba(181,80,30,0.40), transparent 68%),
    radial-gradient(ellipse 80% 60% at 70% 92%, rgba(181,80,30,0.14), transparent 66%); }
}

/* ---------- Trust strip: natural end of the hero ---------- */
.trust-strip {
  background: var(--navy-2); border-top: 1px solid rgba(247,242,233,0.10);
  padding: 20px clamp(18px, 4vw, 48px);
}
.trust-inner {
  max-width: 1140px; margin: 0 auto;
  display: flex; align-items: center; justify-content: center;
  gap: clamp(12px, 2.6vw, 34px); flex-wrap: wrap;
  font-family: var(--font-mono); font-size: 0.74rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: #AEB5C4;
}
.trust-inner .sep { color: var(--rust); opacity: 0.9; }
.trust-inner a { color: var(--paper); }
.trust-inner a:hover { color: var(--rust-soft); }

/* TRUST PROMISES — second row of the strip (V3.1b, ACE_GAP_CHECK §2).
   Row 1 is credential chips; this row is the two trust SENTENCES. The on-my-way
   promise is live copy; the warranty line is a reserved, visibly-empty position.
   Both are sentence-case body type, not mono chips, because a promise that reads
   like a badge reads like decoration. */
.trust-promises {
  max-width: 1140px; margin: 16px auto 0; padding-top: 15px;
  border-top: 1px solid rgba(247,242,233,0.10);
  display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center;
}
.trust-promises .promise {
  display: inline-flex; align-items: center; gap: 10px;
  color: var(--paper); font-size: clamp(0.95rem, 1.4vw, 1.06rem); font-weight: 700;
  letter-spacing: -0.005em; margin: 0;
}
.trust-promises .promise .dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--rust); flex: none;
}
.warranty-slot {
  display: flex; align-items: center; justify-content: center; gap: 11px; flex-wrap: wrap;
  margin: 0; max-width: 74ch;
  font-size: 0.88rem; line-height: 1.45; color: #AEB5C4;
}
.warranty-slot .ph { color: #F6C9A9; border-color: #C97A48; background: none; }
@media (max-width: 560px) {
  .trust-promises { gap: 12px; }
  .warranty-slot { font-size: 0.83rem; gap: 9px; }
}

/* ---------- Coordinated-work row (the 13th row that is not a service) ---------- */
.svc-row--coord {
  border-top: 1px dashed var(--rust);
  background: repeating-linear-gradient(45deg, rgba(181,80,30,0.045) 0 10px, transparent 10px 20px);
}
.svc-row--coord .num { color: var(--rust); }

/* ---------- "From $[PRICE — Connor]" anchor (locked decision #3) ---------- */
.price-anchor {
  display: inline-flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
  font-family: var(--font-display); font-weight: 700; font-size: 0.92rem; color: var(--ink-soft);
}
.section--band .price-anchor { color: var(--band-soft); }

/* ---------- Estimate page: "Asking about:" confirmation receipt ---------- */
.req-summary {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 22px; padding: 14px 18px;
  border: 1px solid var(--rust); border-left: 4px solid var(--rust);
  border-radius: var(--radius); background: rgba(181,80,30,0.07);
}
.req-summary[hidden] { display: none; }
.req-summary-label {
  font-size: 0.68rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--rust-deep);
}
.req-summary-value { font-family: var(--font-display); font-weight: 800; font-size: 1.06rem; color: var(--ink); }
.req-summary-note { font-size: 0.86rem; color: var(--ink-soft); flex-basis: 100%; }

/* ==========================================================================
   OPENING ANIMATION — "COLLAPSE TO SHIELD" v2  (homepage only)
   transform / opacity ONLY. contain:strict isolates it from page layout, so it
   can never reflow the hero underneath it and can never become the LCP element.
   ========================================================================== */
/* FAIL-OPEN DEFAULT. The overlay is display:none until the inline controller on
   the homepage decides to play it and adds .armed. If that script is blocked,
   throws, or never runs, the visitor sees the hero — never a navy field stuck
   over the site. This is the single most important rule in this block. */
#fas-intro { display: none; position: fixed; inset: 0; z-index: 900; overflow: hidden; contain: strict; pointer-events: none; }
#fas-intro.armed { display: block; }
#fas-intro.done { display: none !important; }

.ov-field {
  position: absolute; inset: -1px 0;
  background: radial-gradient(125% 82% at 50% 48%, #232C3E 0%, var(--navy) 46%, #121724 100%);
  transform: translate3d(0,0,0);
}
.ov-field::after {
  content: ''; position: absolute; inset: 0; opacity: 0.5;
  background-image: linear-gradient(90deg, rgba(181,80,30,0.16) 1px, transparent 1px),
                    linear-gradient(0deg, rgba(181,80,30,0.16) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(ellipse 68% 58% at 50% 50%, #000 28%, transparent 76%);
          mask-image: radial-gradient(ellipse 68% 58% at 50% 50%, #000 28%, transparent 76%);
}

/* Two nested jolt layers. They MUST be separate elements: two animations on one
   element both targeting `transform` with fill-mode:both would have the later
   one's backwards-fill silently override the earlier one for the whole timeline. */
.ov-stage { position: absolute; inset: 0; will-change: transform; }
.ov-jolt  { position: absolute; inset: 0; will-change: transform; }

.ov-words {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  text-align: center; white-space: nowrap;
}
.ov-words .w {
  display: block; font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.1rem, 9.2vw, 6.4rem); line-height: 0.94; letter-spacing: -0.03em;
  color: var(--paper); opacity: 0;
}
.ov-words .w:nth-child(2) { color: #E3DED2; }
.ov-words .w:nth-child(3) { color: #D2CDC2; }
.ov-words .w b { font-weight: 800; display: inline-block; will-change: transform, opacity; }

.ov-settle { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); will-change: transform; }
.ov-lockup {
  /* deliberately larger than the hero lockup so the final glide scales DOWN into
     place (~0.67x at 1280). Capped for the ~4.0x-wide horizontal build so the
     whole unit — including FORTIFIED, which is invisible but already occupying
     layout width during the collapse — stays inside the viewport at every size. */
  --em: clamp(120px, 15.5vw, 230px);
  transform: translate(var(--sx, 0px), var(--sy, 0px));
  will-change: transform;
}
@media (max-width: 640px) { .ov-lockup { --em: clamp(74px, 23vw, 132px); } }

.ov-lockup .emblem { opacity: 0; transform: scale(0.55); will-change: transform, opacity; }
.ov-lockup .emblem-fas i { opacity: 0; }
/* FORTIFIED reveals rightward out of the shield, so its origin is its own left
   edge — the edge that sits against the emblem in the horizontal build. */
.ov-lockup .lockup-word {
  opacity: 0; transform: translateX(calc(var(--em, 180px) * -0.17)) scale(0.84);
  transform-origin: left center; will-change: transform, opacity;
}
.ov-lockup .lockup-sub i { opacity: 0; transform: translateY(calc(var(--em, 180px) * 0.026)); }
.ov-lockup .lockup-rule { opacity: 0; transform: scaleX(0); transform-origin: left center; }

/* impact ring is a SIBLING of the emblem, not a child, so the stamp's own
   scale-overshoot doesn't multiply into the ring's expansion */
.emblem-wrap { position: relative; display: flex; flex: 0 0 auto; }
.ov-ring {
  position: absolute; left: 50%; top: 50%; width: var(--em); aspect-ratio: 120 / 140;
  transform: translate(-50%, -50%) scale(0.6); opacity: 0; pointer-events: none;
}
.ov-ring svg { width: 100%; height: 100%; }

.snap-fx { position: absolute; left: 0; right: 0; bottom: 0; height: 0; pointer-events: none; }
.snap-flash {
  position: absolute; left: 0; right: 0; top: -4px; height: 9px;
  background: linear-gradient(90deg, transparent, #FFF8EA 18%, #FFF8EA 82%, transparent);
  opacity: 0; transform: scaleY(0.3);
}
.snap-dust { position: absolute; left: 0; right: 0; top: 0; height: 0; }
.snap-dust i {
  position: absolute; top: 0; left: var(--x); width: 4px; height: 4px; border-radius: 50%;
  background: var(--rust-soft); opacity: 0;
}
.snap-dust i.d2 { background: #FFF3E0; width: 3px; height: 3px; }
.snap-dust i.d3 { background: var(--rust); width: 5px; height: 5px; }

.skip-hint {
  position: absolute; left: 0; right: 0; bottom: clamp(22px, 5vh, 50px);
  text-align: center; font-family: var(--font-mono); font-size: 0.66rem;
  letter-spacing: 0.2em; text-transform: uppercase; color: rgba(247,242,233,0.42); opacity: 0;
}

@keyframes ov-wordin { from { opacity: 0; transform: translateY(26px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes ov-flykey { 0% { opacity: 1; transform: translate(0,0) scale(1); } 72% { opacity: 1; } 100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(var(--s)); } }
@keyframes ov-flydead { 0% { opacity: 1; transform: translate(0,0) scale(1); } 55% { opacity: 0.55; } 100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(0.14); } }
@keyframes ov-wordfade { from { opacity: 1; } to { opacity: 0; } }
@keyframes ov-stamp { 0% { opacity: 0; transform: scale(0.52); } 45% { opacity: 1; transform: scale(1.07); } 72% { transform: scale(0.985); } 100% { opacity: 1; transform: scale(1); } }
@keyframes ov-ringout { 0% { opacity: 0; transform: translate(-50%,-50%) scale(0.72); } 14% { opacity: 0.85; } 100% { opacity: 0; transform: translate(-50%,-50%) scale(1.62); } }
@keyframes ov-fasin { from { opacity: 0; } to { opacity: 1; } }
@keyframes ov-jolt { 0%,100% { transform: translate3d(0,0,0); } 14% { transform: translate3d(0,4px,0); } 32% { transform: translate3d(-3px,-2px,0); } 52% { transform: translate3d(2px,2px,0); } 76% { transform: translate3d(-1px,-1px,0); } }
@keyframes ov-jolt2 { 0%,100% { transform: translate3d(0,0,0); } 18% { transform: translate3d(0,3px,0); } 44% { transform: translate3d(2px,-2px,0); } 72% { transform: translate3d(-1px,1px,0); } }
@keyframes ov-recenter { from { transform: translate(var(--sx,0px), var(--sy,0px)); } to { transform: translate(0px, 0px); } }
@keyframes ov-wordsettle { 0% { opacity: 0; transform: translateX(calc(var(--em, 180px) * -0.17)) scale(0.84); } 62% { opacity: 1; } 100% { opacity: 1; transform: translateX(0) scale(1); } }
@keyframes ov-subletter { from { opacity: 0; transform: translateY(calc(var(--em, 180px) * 0.026)); } to { opacity: 1; transform: translateY(0); } }
@keyframes ov-chalksnap { 0% { opacity: 0; transform: scaleX(0) translateY(0); } 26% { opacity: 1; transform: scaleX(1) translateY(0); } 44% { transform: scaleX(1) translateY(-10px); } 60% { transform: scaleX(1) translateY(6px); } 78% { transform: scaleX(1) translateY(-2px); } 100% { opacity: 1; transform: scaleX(1) translateY(0); } }
@keyframes ov-flashout { 0% { opacity: 0; transform: scaleY(0.3); } 22% { opacity: 1; transform: scaleY(1); } 100% { opacity: 0; transform: scaleY(0.4); } }
@keyframes ov-dustout { 0% { opacity: 0; transform: translate(0,0) scale(1); } 16% { opacity: 0.95; } 100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(var(--s)); } }
@keyframes ov-hintin { from { opacity: 0; } to { opacity: 1; } }
@keyframes ov-settleout { from { transform: translate(-50%,-50%) translate(0,0) scale(1); } to { transform: translate(-50%,-50%) translate(var(--fx), var(--fy)) scale(var(--fs)); } }
@keyframes ov-fieldout { from { opacity: 1; } to { opacity: 0; } }
@keyframes ov-lockfade { from { opacity: 1; } to { opacity: 0; } }

/* ==========================================================================
   TIMELINE — 2.98s total.  REVISED 2026-08-02 (V3.1a) for the horizontal lockup.
   The concept is unchanged (three words collapse, FAS lands in the shield); what
   changed is the ASSEMBLY ORDER, which now builds the horizontal unit left to
   right and snaps the chalk line BEFORE the sub-line resolves under it — the
   owner's requested reading order.

     0.06 - 0.67   FORTIFIED / ASSET / SOLUTIONS rise in, stacked, 90ms stagger
     0.78 - 1.25   COLLAPSE — every letter flies to the dead centre of the
                   viewport; F, A and S survive and land as the monogram, the
                   other twenty implode and fade
     1.15 - 1.50   Shield STAMPS in around them, DEAD CENTRE (overshoot 1.07 +
                   expanding impact ring + 300ms jolt through the stage)
     1.45 - 1.84   FORTIFIED reveals to the RIGHT of the shield and the lockup
                   re-centres around the finished horizontal unit
     1.80 - 2.12   CHALK LINE SNAP directly under FORTIFIED — taut, pulled 10px,
                   snapped 6px past level, settles. Flash + 16 dust particles +
                   a second jolt. Still the best 300ms in the sequence.
     2.04 - 2.50   HANDYMAN SERVICES resolves under the line, letter by letter
                   (15ms stagger, opacity+translate only — never letter-spacing)
     2.48 - 2.88   The whole formed lockup GLIDES from centre to its final hero
                   position, centre-right. Measured landing, not eyeballed.
     2.84 - 2.98   Navy field cross-fades ONLY after the lockup has landed —
                   fading earlier double-images the two lockups for ~250ms
   ========================================================================== */
#fas-intro.run .ov-words .w { animation: ov-wordin 0.43s cubic-bezier(.16,.85,.3,1) both; animation-delay: calc(0.06s + var(--w) * 0.09s); }
#fas-intro.run .ov-words .w b.key  { animation: ov-flykey 0.47s cubic-bezier(.62,.02,.3,1) 0.78s both; }
#fas-intro.run .ov-words .w b.dead { animation: ov-flydead 0.47s cubic-bezier(.62,.02,.3,1) both; animation-delay: calc(0.78s + var(--j) * 0.012s); }
#fas-intro.run .ov-words { animation: ov-wordfade 0.10s linear 1.24s both; }
#fas-intro.run .ov-lockup .emblem { animation: ov-stamp 0.35s cubic-bezier(.22,.9,.28,1.05) 1.15s both; }
#fas-intro.run .ov-ring { animation: ov-ringout 0.42s cubic-bezier(.2,.7,.3,1) 1.15s both; }
#fas-intro.run .ov-lockup .emblem-fas i { animation: ov-fasin 0.09s linear 1.19s both; }
#fas-intro.run .ov-stage { animation: ov-jolt 0.30s cubic-bezier(.3,.7,.4,1) 1.16s both; }
#fas-intro.run .ov-lockup { animation: ov-recenter 0.39s cubic-bezier(.2,.8,.2,1) 1.45s both; }
#fas-intro.run .ov-lockup .lockup-word { animation: ov-wordsettle 0.39s cubic-bezier(.2,.85,.25,1.02) 1.45s both; }
#fas-intro.run .ov-lockup .lockup-rule { animation: ov-chalksnap 0.32s cubic-bezier(.3,.72,.36,1) 1.80s both; }
#fas-intro.run .ov-jolt  { animation: ov-jolt2 0.20s cubic-bezier(.3,.7,.4,1) 1.96s both; }
#fas-intro.run .snap-flash { animation: ov-flashout 0.30s ease-out 1.94s both; }
#fas-intro.run .snap-dust i { animation: ov-dustout 0.54s cubic-bezier(.2,.7,.3,1) both; animation-delay: calc(1.96s + var(--d)); }
#fas-intro.run .ov-lockup .lockup-sub i { animation: ov-subletter 0.22s var(--ease) both; animation-delay: calc(2.04s + var(--k) * 0.015s); }
#fas-intro.run .skip-hint { animation: ov-hintin 0.34s ease-out 1s both; }

/* Settle onto the hero's own lockup. Both animations live on .ov-settle because
   they target DIFFERENT properties (transform vs opacity) so they compose. The
   fade must NOT go on .ov-lockup: that element still holds the `recenter`
   transform via fill-mode, and a second animation there drops it back to its
   pre-recenter offset — a visible jump on the last beat. */
/* The GLIDE. Both animations live on .ov-settle because they target DIFFERENT
   properties (transform vs opacity) so they compose instead of clobbering. The
   fade must NOT go on .ov-lockup: that element is still holding the `recenter`
   transform via fill-mode, and a second animation there would drop it back to
   its pre-recenter offset — a visible jump on the last beat. */
#fas-intro.out .ov-settle {
  animation: ov-settleout 0.40s cubic-bezier(.5,.03,.2,1) both,
             ov-lockfade 0.12s linear 0.38s both;
}
#fas-intro.out .ov-field { animation: ov-fieldout 0.14s linear 0.36s both; }
#fas-intro.out .skip-hint { opacity: 0; }
#fas-intro.out .snap-fx { opacity: 0; }

/* Reduced motion: never render, never auto-play. Straight to the hero. */
@media (prefers-reduced-motion: reduce) {
  #fas-intro { display: none !important; }
}

/* ---------- V3.1 narrow-viewport corrections ------------------------------
   Two defects found in the 320px sweep during the V3.1 pass. Both predate this
   build; fixed here because the pass added a wider element to one of them.
   1. Grid children default to min-width:auto, so a long dotted-leader spec row
      could push its track past the container and force a 2px horizontal scroll
      on the homepage pricing band. min-width:0 lets the track shrink.
   2. The estimate page's two-column form/sidebar split was set with an INLINE
      grid-template-columns, which outranks the 860px collapse rule — so it
      stayed two columns all the way down. It is now a class.
   -------------------------------------------------------------------------- */
.grid > * { min-width: 0; }
.grid--form { grid-template-columns: 1.25fr 0.75fr; }
@media (max-width: 860px) { .grid--form { grid-template-columns: 1fr; } }
@media (max-width: 560px) {
  .spec { flex-wrap: wrap; }
  .spec .lead { min-width: 8px; }
  .price-anchor { font-size: 0.86rem; }
  .price-anchor .ph--price { font-size: 0.8rem; padding: 6px 9px; }
}
@media (max-width: 380px) {
  /* mono section indices are wide by design; let the longest ones wrap rather
     than force a horizontal scroll on a 320px phone */
  .rule-head { flex-wrap: wrap; }
  .rule-head .idx { white-space: normal; }
}
