/* =========================================================================
   CACTUS CONTAINERS — Design System  v1
   Evolve brand: steel + desert sand + sage + corten-rust accent
   Type: Satoshi (display) / General Sans (body)
   ========================================================================= */

:root{
  /* --- brand palette: Graphite & Cactus Sage ---
     Anchored on the Cactus Containers logo color #7A8B79 (hue 117°).
     The logo tint itself is too light for text (3.62:1 on white), so UI text/CTAs use
     deeper shades of the SAME hue that pass WCAG AA. --brand-logo is the exact
     logo color, reserved for decorative fills where contrast doesn't apply. */
  --brand-logo:#7a8b79;  /* EXACT logo sage — decorative use only */
  --ink:#14171a;         /* charcoal steel */
  --ink-2:#1d2227;
  --steel:#2c343b;
  --sage-900:#223621;    /* deepest sage — icon fills / bands */
  --sage-700:#577656;    /* primary accent / CTA — 5.08:1 on white */
  --sage-600:#436241;    /* hover / text on light — 6.86:1 on white, 6.04:1 on --sand */
  --sage-400:#8da68c;    /* light sage on dark */
  --sage-200:#cbd8cb;
  --blue:#3b6ea5;        /* steel blue — secondary */
  --blue-600:#2f5a86;
  --sand:#eef1f2;        /* cool light page background */
  --sand-2:#e4e9ec;
  --sand-3:#d7dee2;
  --line:#dde3e6;        /* hairline border */
  --line-2:#ccd4d8;
  --rust:#577656;        /* accent = primary CTA (teal) */
  --rust-600:#436241;
  --amber:#e6b13c;
  --paper:#ffffff;
  --text:#161a1e;
  --muted:#586067;
  /* --muted-2 was #828a90 — 3.51:1 on white, 2.87:1 on --sand-2. It is used for
     real fine print (.qr-fine, .qr-line small, .fcount, group labels, doc-meta),
     so it has to clear 4.5:1 on the lightest surface it lands on. #60686e is the
     lightest value that does: 5.67 white / 5.00 sand / 4.64 sand-2. */
  --muted-2:#60686e;
  /* --star was #e6b13c — 1.96:1 on white, failing 1.4.11 for the rating stars.
     Deepened to keep the gold read while clearing 3:1 (3.63 white / 3.20 sand).
     --amber above is untouched: it is a background, not a foreground. */
  --star:#b07d12;

  /* --- type --- */
  --font-display:"Satoshi","General Sans",system-ui,sans-serif;
  --font-body:"General Sans","Satoshi",system-ui,-apple-system,sans-serif;

  /* --- structure --- */
  --maxw:1240px;
  --radius:14px;
  --radius-sm:9px;
  --radius-lg:22px;
  --shadow-sm:0 1px 2px rgba(20,24,26,.06),0 2px 6px rgba(20,24,26,.05);
  --shadow:0 8px 24px -8px rgba(20,24,26,.14),0 3px 8px -4px rgba(20,24,26,.08);
  --shadow-lg:0 30px 60px -24px rgba(20,24,26,.30),0 12px 24px -12px rgba(20,24,26,.14);
  --ease:cubic-bezier(.22,.61,.36,1);
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  margin:0;font-family:var(--font-body);color:var(--text);
  background:var(--sand);line-height:1.6;font-size:17px;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font-family:inherit}
h1,h2,h3,h4{font-family:var(--font-display);font-weight:700;line-height:1.05;margin:0;letter-spacing:-.02em;color:var(--text)}
p{margin:0}

/* --- layout helpers --- */
.container{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:24px}
.section{padding-block:clamp(56px,7vw,104px)}
.section-tight{padding-block:clamp(40px,5vw,64px)}
.center{text-align:center}
.eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  font-size:12.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  /* sage-700 is 5.08:1 on pure white but only 4.48:1 on --sand, and the eyebrow
     sits on --sand more often than not. sage-600 is the token meant for text on
     light surfaces (6.04:1 on sand) and is the same brand hue. */
  color:var(--sage-600);
}
.eyebrow::before{content:"";width:22px;height:2px;background:var(--rust);border-radius:2px}
.eyebrow.on-dark{color:var(--sage-200)}
h2.h-xl{font-size:clamp(30px,4.4vw,52px)}
.lead{font-size:clamp(17px,1.6vw,20px);color:var(--muted);max-width:60ch}
.section-head{max-width:64ch}
.section-head.center{margin-inline:auto}

/* --- buttons --- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-weight:600;font-size:15.5px;letter-spacing:.01em;
  padding:14px 24px;border-radius:10px;border:1.5px solid transparent;
  cursor:pointer;transition:all .25s var(--ease);white-space:nowrap;
}
.btn svg{width:18px;height:18px}
.btn-primary{background:var(--rust);color:#fff;box-shadow:0 6px 18px -6px rgba(87, 118, 86,.6)}
.btn-primary:hover{background:var(--rust-600);transform:translateY(-2px);box-shadow:0 12px 26px -8px rgba(87, 118, 86,.65)}
.btn-dark{background:var(--ink);color:#fff}
.btn-dark:hover{background:var(--ink-2);transform:translateY(-2px)}
.btn-ghost{background:transparent;color:var(--text);border-color:var(--line-2)}
.btn-ghost:hover{border-color:var(--ink);background:var(--paper)}
.btn-ghost.on-dark{color:#fff;border-color:rgba(255,255,255,.28)}
.btn-ghost.on-dark:hover{border-color:#fff;background:rgba(255,255,255,.08)}
.btn-lg{padding:17px 30px;font-size:16.5px}
.btn-block{width:100%}

/* --- badges / chips / specs --- */
.chip{
  display:inline-flex;align-items:center;gap:6px;
  /* sage-700 on its own 10% tint is 4.47:1 — just under AA for this 12.5px text.
     sage-600 on the same tint is 6.03:1. */
  font-size:12.5px;font-weight:600;color:var(--sage-600);
  background:rgba(87, 118, 86,.10);border:1px solid rgba(87, 118, 86,.18);
  padding:5px 11px;border-radius:100px;letter-spacing:.01em;
}
.chip.rust{color:var(--rust-600);background:rgba(87, 118, 86,.09);border-color:rgba(87, 118, 86,.20)}
.chip.ink{color:#e7ebed;background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.14)}
.spec{display:inline-flex;align-items:center;gap:6px;font-size:13.5px;color:var(--muted);font-weight:500}
.spec svg{width:15px;height:15px;color:var(--sage-600)}

/* --- generic card --- */
.card{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-sm);transition:transform .3s var(--ease),box-shadow .3s var(--ease),border-color .3s}
.card:hover{transform:translateY(-4px);box-shadow:var(--shadow);border-color:var(--line-2)}

/* =======================  TOP BAR + HEADER  ======================= */
.topbar{background:var(--ink);color:#c4cace;font-size:13px}
.topbar .container{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:40px}
.topbar a{color:#c4cace;transition:color .2s}
.topbar a:hover{color:#fff}
.topbar .tb-left{display:flex;gap:22px;align-items:center}
.topbar .tb-item{display:inline-flex;gap:7px;align-items:center}
.topbar .tb-item svg{width:14px;height:14px;color:var(--sage-400)}
.topbar .tb-right{display:flex;gap:16px;align-items:center}
.topbar .tb-social{display:flex;gap:12px}
.topbar .tb-social svg{width:15px;height:15px}

header.site{position:sticky;top:0;z-index:50;background:rgba(238,241,242,.86);backdrop-filter:blur(14px);border-bottom:1px solid var(--line)}
.nav{display:flex;align-items:center;gap:28px;min-height:82px}
.nav .logo{display:flex;align-items:center;gap:11px;flex-shrink:0}
.nav .logo img{height:54px;width:auto}
.nav .logo b{font-family:var(--font-display);font-size:19px;letter-spacing:-.01em;line-height:1}
.nav .logo span{display:block;font-size:10px;letter-spacing:.28em;color:var(--sage-600);font-weight:600}
.nav ul{display:flex;gap:4px;list-style:none;margin:0;padding:0;margin-left:8px}
.nav ul a{padding:9px 15px;border-radius:8px;font-weight:500;font-size:15.5px;color:var(--text);transition:all .2s;position:relative}
.nav ul a:hover{background:rgba(87, 118, 86,.10);color:var(--sage-600)}
.nav ul a.active{color:var(--sage-600)}
.nav ul a.active::after{content:"";position:absolute;left:15px;right:15px;bottom:2px;height:2px;background:var(--rust);border-radius:2px}
.nav .nav-right{margin-left:auto;display:flex;align-items:center;gap:14px}
.nav .icon-btn{width:42px;height:42px;display:grid;place-items:center;border-radius:10px;border:1px solid var(--line);background:var(--paper);color:var(--text);transition:all .2s;position:relative}
.nav .icon-btn:hover{border-color:var(--ink);transform:translateY(-1px)}
.nav .icon-btn svg{width:19px;height:19px}
.nav .phone-cta{display:flex;flex-direction:column;line-height:1.1}
.nav .phone-cta small{font-size:11px;color:var(--muted);font-weight:500}
.nav .phone-cta b{font-family:var(--font-display);font-size:17px;color:var(--text)}
/* Multi-word nav items ("Rent-to-Own", "Custom Builds", "Self Storage",
   "Tack Rooms") must never break onto two lines. The nav now carries up to 10
   items, so it tightens in two stages on mid-size laptops — and drops the
   phone-cta block before the links themselves — to stay on one row instead of
   overflowing the container. */
.nav ul a{white-space:nowrap}
@media(max-width:1460px){
  .nav{gap:14px}
  .nav ul{margin-left:0;gap:0}
  .nav ul a{padding-left:9px;padding-right:9px;font-size:14.7px}
  .nav .nav-right{gap:10px}
}
@media(max-width:1220px){
  .nav{gap:10px}
  .nav ul a{padding-left:6px;padding-right:6px;font-size:13.8px}
  .nav .phone-cta{display:none}
}

/* =======================  HERO  ======================= */
.hero{position:relative;background:var(--ink);color:#fff;overflow:hidden}
.hero-media{position:absolute;inset:0}
.hero-media img{width:100%;height:100%;object-fit:cover;opacity:.55}
.hero-media::after{content:"";position:absolute;inset:0;
  background:linear-gradient(100deg,rgba(15,20,22,.94) 0%,rgba(15,20,22,.72) 42%,rgba(15,20,22,.25) 100%);}
.hero .container{position:relative;z-index:2;padding-block:clamp(72px,11vw,132px)}
.hero-inner{max-width:680px}
.hero h1{font-size:clamp(38px,6vw,68px);font-weight:900;color:#fff;letter-spacing:-.03em}
.hero h1 em{font-style:normal;color:var(--sage-400)}
.hero .lead{color:rgba(255,255,255,.82);margin-top:20px;font-size:clamp(17px,1.7vw,20px);max-width:52ch}
.hero .hero-cta{display:flex;flex-wrap:wrap;gap:14px;margin-top:32px}
.hero-trust{display:flex;flex-wrap:wrap;gap:26px;margin-top:44px;padding-top:28px;border-top:1px solid rgba(255,255,255,.14)}
.hero-trust .ht{display:flex;flex-direction:column;gap:2px}
.hero-trust .ht b{font-family:var(--font-display);font-size:26px;color:#fff;line-height:1}
.hero-trust .ht span{font-size:13px;color:rgba(255,255,255,.62)}

/* ZIP quote widget floating on hero */
.zip-card{position:relative;z-index:2;background:var(--paper);border-radius:var(--radius);box-shadow:var(--shadow-lg);
  padding:22px;max-width:var(--maxw);margin:-46px auto 0;display:grid;grid-template-columns:1.3fr 1fr 1fr auto;gap:16px;align-items:end}
.zip-card .field{display:flex;flex-direction:column;gap:6px}
.zip-card label{font-size:12px;font-weight:600;color:var(--muted);letter-spacing:.03em;text-transform:uppercase}
.zip-card input,.zip-card select{padding:12px 14px;border:1.5px solid var(--line-2);border-radius:9px;font-size:15px;font-family:inherit;background:var(--sand);color:var(--text)}
/* Keep the border tint as the hover/typing affordance, but never suppress the
   focus ring for keyboard users — see the :focus-visible block at the bottom. */
.zip-card input:focus,.zip-card select:focus{border-color:var(--sage-600);background:#fff}
.zip-card optgroup{font-family:inherit}

/* ---- ZIP quote result panel (rendered by the delivery pricing engine) ---- */
.quote-result{display:none;max-width:var(--maxw);margin:14px auto 0;background:var(--paper);
  border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);
  padding:clamp(18px,2.2vw,26px)}
.quote-result.show{display:block;animation:qrIn .35s var(--ease)}
@keyframes qrIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.quote-result.is-warn{background:var(--sand-2);border-color:var(--line-2);box-shadow:var(--shadow-sm)}
.qr-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 14px;padding-bottom:14px;
  border-bottom:1px solid var(--line)}
.qr-where{font-family:var(--font-display);font-size:clamp(18px,2vw,21px);font-weight:700;color:var(--text);line-height:1.25}
.qr-meta{font-size:14px;color:var(--muted)}
.qr-meta b{color:var(--sage-600);font-weight:600}
.qr-line{display:flex;justify-content:space-between;align-items:baseline;gap:14px;
  padding:11px 0;border-bottom:1px solid var(--line);font-size:15px}
.qr-line>span{color:var(--muted);min-width:0}
.qr-line>b{font-variant-numeric:tabular-nums;font-weight:600;color:var(--text);white-space:nowrap}
.qr-line small{display:block;font-size:12.5px;color:var(--muted-2);margin-top:1px}
.qr-line.qr-total{border-bottom:0;padding-top:16px}
.qr-line.qr-total>span{color:var(--text);font-weight:600;font-size:15.5px}
.qr-line.qr-total>b{font-family:var(--font-display);font-size:clamp(23px,3vw,30px);color:var(--sage-700);line-height:1.1}
.qr-beat{display:flex;gap:9px;align-items:flex-start;margin-top:14px;padding:11px 13px;
  border-radius:var(--radius-sm);background:rgba(87,118,86,.09);border:1px solid rgba(87,118,86,.20);
  font-size:14px;line-height:1.5;color:var(--sage-600)}
.qr-beat svg{width:16px;height:16px;flex-shrink:0;margin-top:3px}
.qr-msg{margin:0;font-size:15.5px;line-height:1.6;color:var(--text)}
.qr-head+.qr-msg{margin-top:14px}
.qr-fine{margin:14px 0 0;font-size:13px;color:var(--muted-2)}
.quote-result a:not(.btn){color:var(--sage-600);font-weight:600;text-decoration:underline;text-underline-offset:2px}
.qr-cta{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px}
.qr-cta .btn{white-space:normal;text-align:center}
@media(max-width:520px){.qr-cta .btn{width:100%}}

/* =======================  STAT / LOGO STRIP  ======================= */
.marquee{background:var(--ink-2);color:#c5cbcf;overflow:hidden}
.marquee .container{display:flex;gap:44px;align-items:center;justify-content:center;flex-wrap:wrap;padding-block:20px;font-size:14px}
.marquee .mi{display:inline-flex;gap:9px;align-items:center;white-space:nowrap}
.marquee .mi svg{width:17px;height:17px;color:var(--sage-400)}

/* =======================  CATEGORY GRID  ======================= */
.cat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;margin-top:44px}
.cat{position:relative;border-radius:var(--radius);overflow:hidden;min-height:270px;display:flex;align-items:flex-end;
  color:#fff;background:var(--steel);box-shadow:var(--shadow-sm);transition:transform .35s var(--ease),box-shadow .35s}
.cat img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .6s var(--ease)}
.cat::after{content:"";position:absolute;inset:0;background:linear-gradient(to top,rgba(13,18,20,.92),rgba(13,18,20,.15) 62%,transparent)}
.cat:hover{transform:translateY(-5px);box-shadow:var(--shadow-lg)}
.cat:hover img{transform:scale(1.07)}
.cat .cat-body{position:relative;z-index:2;padding:22px}
.cat .cat-body h3{color:#fff;font-size:20px}
.cat .cat-body p{font-size:13.5px;color:rgba(255,255,255,.74);margin-top:4px}
.cat .cat-arrow{display:inline-flex;align-items:center;gap:6px;margin-top:12px;font-weight:600;font-size:14px;color:var(--sage-200)}
.cat.tall{grid-row:span 2;min-height:100%}

/* =======================  PRODUCT CARDS  ======================= */
.prod-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:22px;margin-top:44px}
.prod{display:flex;flex-direction:column;overflow:hidden}
.prod .prod-media{position:relative;aspect-ratio:4/3;background:var(--sand-2);overflow:hidden}
.prod .prod-media img{width:100%;height:100%;object-fit:cover;transition:transform .5s var(--ease)}
.prod:hover .prod-media img{transform:scale(1.05)}
.prod .prod-tag{position:absolute;top:12px;left:12px;z-index:2}
.prod .prod-fav{position:absolute;top:12px;right:12px;z-index:2;width:34px;height:34px;border-radius:100px;background:rgba(255,255,255,.92);display:grid;place-items:center;color:var(--muted);border:none;cursor:pointer;transition:all .2s}
.prod .prod-fav:hover{color:var(--rust);transform:scale(1.08)}
.prod .prod-body{padding:18px 18px 20px;display:flex;flex-direction:column;flex:1}
.prod .prod-cat{font-size:12px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--sage-600)}
.prod h3{font-size:18px;margin-top:6px;line-height:1.15}
.prod .prod-specs{display:flex;flex-wrap:wrap;gap:14px;margin-top:12px;padding-top:12px;border-top:1px dashed var(--line)}
.prod .prod-foot{display:flex;align-items:center;justify-content:space-between;margin-top:auto;padding-top:16px;gap:12px}
.prod .price{font-family:var(--font-display);font-size:22px;font-weight:700;color:var(--text)}
.prod .price small{font-size:12.5px;font-weight:500;color:var(--muted);display:block;letter-spacing:0}
.prod .price.quote{font-size:16px;color:var(--sage-700)}

/* =======================  HOW IT WORKS  ======================= */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:22px;margin-top:48px;position:relative}
.step{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);padding:28px 24px;position:relative;transition:all .3s var(--ease)}
.step:hover{border-color:var(--sage-400);box-shadow:var(--shadow)}
.step .step-num{font-family:var(--font-display);font-size:14px;font-weight:700;color:var(--rust);letter-spacing:.06em}
.step .step-ico{width:56px;height:56px;border-radius:14px;background:var(--sage-900);color:var(--sage-200);display:grid;place-items:center;margin:14px 0 18px}
.step .step-ico svg{width:27px;height:27px}
.step h3{font-size:18px}
.step p{margin-top:8px;font-size:14.5px;color:var(--muted)}

/* =======================  CUSTOM BUILD BAND  ======================= */
.band{position:relative;background:var(--sage-900);color:#fff;border-radius:var(--radius-lg);overflow:hidden}
.band-media{position:absolute;inset:0}
.band-media img{width:100%;height:100%;object-fit:cover;opacity:.22}
.band-media::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,var(--sage-900) 30%,rgba(55,67,46,.5))}
.band .band-inner{position:relative;z-index:2;padding:clamp(40px,6vw,72px);display:grid;grid-template-columns:1.2fr .9fr;gap:40px;align-items:center}
.band h2{color:#fff;font-size:clamp(28px,3.6vw,42px)}
.band p{color:rgba(255,255,255,.82);margin-top:14px;max-width:46ch}
.band .band-list{display:flex;flex-direction:column;gap:12px;margin-top:24px}
.band .band-list .bl{display:flex;gap:11px;align-items:flex-start;font-size:15.5px;color:rgba(255,255,255,.9)}
.band .band-list .bl svg{width:20px;height:20px;color:var(--sage-400);flex-shrink:0;margin-top:2px}
.quote-box{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.16);border-radius:var(--radius);padding:26px;backdrop-filter:blur(6px)}
.quote-box h3{color:#fff;font-size:20px}
.quote-box .qf{display:flex;flex-direction:column;gap:12px;margin-top:16px}
.quote-box input,.quote-box select,.quote-box textarea{width:100%;padding:12px 14px;border-radius:9px;border:1px solid rgba(255,255,255,.2);background:rgba(255,255,255,.07);color:#fff;font-family:inherit;font-size:15px}
/* Placeholder text is text: 50% white on this panel was 3.97:1, 62% is 5.18:1. */
.quote-box input::placeholder,.quote-box textarea::placeholder{color:rgba(255,255,255,.62)}
/* outline:none removed — this rule out-specifies the :focus-visible baseline at
   the foot of this file, so leaving it here would have silently kept the focus
   ring suppressed on the quote form. Border tint stays as the typing cue. */
.quote-box input:focus,.quote-box select:focus,.quote-box textarea:focus{border-color:var(--sage-400)}

/* =======================  WHY / FEATURES  ======================= */
.feat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:44px}
.feat{padding:28px;background:var(--paper);border:1px solid var(--line);border-radius:var(--radius)}
.feat .feat-ico{width:50px;height:50px;border-radius:12px;background:rgba(87, 118, 86,.10);color:var(--rust);display:grid;place-items:center;margin-bottom:16px}
.feat .feat-ico svg{width:24px;height:24px}
.feat h3{font-size:18px}
.feat p{margin-top:8px;font-size:14.5px;color:var(--muted)}

/* =======================  COVERAGE  ======================= */
.coverage{display:grid;grid-template-columns:1fr 1fr;gap:40px;align-items:center}
.coverage .cov-map{background:var(--ink);border-radius:var(--radius);overflow:hidden;position:relative;min-height:340px;display:grid;place-items:center;color:#fff}
.loc-list{display:flex;flex-direction:column;gap:16px;margin-top:26px}
.loc{display:flex;gap:16px;padding:20px;border:1px solid var(--line);border-radius:var(--radius);background:var(--paper);transition:all .25s}
.loc:hover{border-color:var(--sage-400);box-shadow:var(--shadow-sm)}
.loc .loc-ico{width:46px;height:46px;border-radius:12px;background:var(--sage-900);color:var(--sage-200);display:grid;place-items:center;flex-shrink:0}
.loc h3{font-size:17px}
.loc p{font-size:14px;color:var(--muted);margin-top:3px}

/* =======================  TESTIMONIALS  ======================= */
.tst-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:44px}
.tst{padding:28px;background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);display:flex;flex-direction:column}
.tst .stars{display:flex;gap:3px;color:var(--star);margin-bottom:14px}
.tst .stars svg{width:17px;height:17px}
.tst blockquote{margin:0;font-size:16px;color:var(--text);line-height:1.6;flex:1}
.tst .tst-by{display:flex;align-items:center;gap:12px;margin-top:20px;padding-top:18px;border-top:1px solid var(--line)}
.tst .avatar{width:44px;height:44px;border-radius:100px;background:var(--sage-700);color:#fff;display:grid;place-items:center;font-family:var(--font-display);font-weight:700}
.tst .tst-by b{font-size:15px}
.tst .tst-by span{font-size:13px;color:var(--muted)}

/* =======================  FAQ  ======================= */
.faq{max-width:820px;margin:44px auto 0}
.faq details{border-bottom:1px solid var(--line);padding:6px 0}
.faq summary{cursor:pointer;list-style:none;padding:18px 4px;font-family:var(--font-display);font-weight:600;font-size:18px;display:flex;justify-content:space-between;align-items:center;gap:16px}
.faq summary::-webkit-details-marker{display:none}
.faq summary .q-ico{flex-shrink:0;width:28px;height:28px;border-radius:8px;background:var(--sand-2);display:grid;place-items:center;transition:all .3s;color:var(--sage-700)}
.faq details[open] summary .q-ico{background:var(--sage-700);color:#fff;transform:rotate(45deg)}
.faq .faq-a{padding:0 4px 20px;color:var(--muted);font-size:15.5px;max-width:70ch}

/* =======================  CTA  ======================= */
.cta{position:relative;background:var(--rust);color:#fff;border-radius:var(--radius-lg);overflow:hidden;text-align:center;padding:clamp(44px,6vw,76px) 24px}
.cta::before{content:"";position:absolute;inset:0;background:radial-gradient(circle at 20% 0%,rgba(255,255,255,.14),transparent 55%)}
.cta h2{position:relative;color:#fff;font-size:clamp(28px,4vw,46px)}
/* 90% white on the sage CTA panel measured 4.47:1. 94% clears AA at 4.72:1. */
.cta p{position:relative;color:rgba(255,255,255,.94);margin:14px auto 0;max-width:52ch}
.cta .cta-btns{position:relative;display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-top:30px}
.cta .btn-primary{background:#fff;color:var(--rust);box-shadow:none}
.cta .btn-primary:hover{background:var(--sand)}

/* =======================  FOOTER  ======================= */
footer.site{background:var(--ink);color:#b3b9bd;padding-top:64px;font-size:14.5px}
footer.site .f-top{display:grid;grid-template-columns:1.5fr 1fr 1fr 1.4fr;gap:36px;padding-bottom:44px;border-bottom:1px solid rgba(255,255,255,.1)}
footer.site .logo b{color:#fff;font-family:var(--font-display);font-size:19px}
footer.site .logo span{color:var(--sage-400);font-size:10px;letter-spacing:.28em;font-weight:600}
footer.site p{margin-top:14px;max-width:34ch;color:#969ca1;line-height:1.65}
/* The footer column headings were <h4> sitting directly under the page's <h2>
   sections, which skips h3. They are now <h2> (siblings of the main sections,
   which is what they are); the h4 selector is kept so nothing regresses if a
   stray one comes back. Appearance is unchanged. */
footer.site h2,
footer.site h4{color:#fff;font-size:13px;letter-spacing:.12em;text-transform:uppercase;margin-bottom:16px;font-family:var(--font-body);font-weight:600}
footer.site ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:11px}
footer.site ul a:hover{color:#fff}
footer.site .f-contact div{display:flex;gap:10px;align-items:flex-start;margin-bottom:14px}
footer.site .f-contact svg{width:17px;height:17px;color:var(--sage-400);flex-shrink:0;margin-top:3px}
footer.site .f-news{display:flex;gap:8px;margin-top:14px}
footer.site .f-news input{flex:1;padding:11px 13px;border-radius:9px;border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.06);color:#fff;font-family:inherit}
footer.site .f-social{display:flex;gap:10px;margin-top:18px}
footer.site .f-social a{width:38px;height:38px;border-radius:10px;border:1px solid rgba(255,255,255,.14);display:grid;place-items:center;transition:all .2s}
footer.site .f-social a:hover{background:var(--sage-700);border-color:var(--sage-700);color:#fff}
footer.site .f-bot{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;padding:24px 0;color:#7f858a;font-size:13.5px}
footer.site .f-bot img{height:22px;opacity:.85}
/* legal link row — privacy / terms / accessibility, on every page */
footer.site .f-legal{display:flex;flex-wrap:wrap;gap:6px 12px;align-items:center}
footer.site .f-legal a{color:#9aa1a6;transition:color .2s}
footer.site .f-legal a:hover{color:#fff;text-decoration:underline}
/* aria-hidden in the markup, but it is still rendered text, so give it the same
   4.5:1 floor as the links either side of it (#5c6266 was 2.91:1). */
footer.site .f-legal .sep{color:#8b9297;user-select:none}

/* =======================  RESPONSIVE  ======================= */
@media(max-width:1024px){
  .cat-grid,.prod-grid,.steps,.feat-grid,.tst-grid{grid-template-columns:repeat(2,1fr)}
  .zip-card{grid-template-columns:1fr 1fr}
  .band .band-inner,.coverage{grid-template-columns:1fr}
  footer.site .f-top{grid-template-columns:1fr 1fr}
}
@media(max-width:820px){
  .nav ul,.topbar .tb-left,.nav .phone-cta{display:none}
  .nav-toggle{display:grid!important}
}
@media(max-width:640px){
  body{font-size:16px}
  .cat-grid,.prod-grid,.steps,.feat-grid,.tst-grid,.zip-card,footer.site .f-top{grid-template-columns:1fr}
  /* A 1fr track still floors at the item's min-content width, and the product
     <select> carries long option labels — without min-width:0 the single
     column blew out to 436px and scrolled the page sideways at 375px. */
  .zip-card .field{min-width:0}
  .zip-card input,.zip-card select{min-width:0;max-width:100%}
  .hero-trust{gap:18px}
  .hero-trust .ht b{font-size:22px}
}
.nav-toggle{display:none;width:42px;height:42px;place-items:center;border:1px solid var(--line);border-radius:10px;background:var(--paper)}

/* reveal on scroll */
.reveal{opacity:0;transform:translateY(22px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.reveal.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}.reveal{opacity:1;transform:none}}

/* ---- Header phone block: never let the number wrap ------------------------
   The nav carries 10 items plus search, phone and a CTA. Below ~1250px the
   phone block is what breaks first, so it collapses to an icon button and
   then hides entirely — the number is always still in the topbar and footer. */
.nav .phone-cta{white-space:nowrap;line-height:1.15}
.nav .phone-cta small{white-space:nowrap;font-size:10.5px;letter-spacing:.01em}
.nav .phone-cta b{white-space:nowrap;font-size:16px;font-variant-numeric:tabular-nums}
.nav ul a{padding-inline:12px}
.nav{gap:18px}

@media(max-width:1350px){
  .nav ul a{padding-inline:9px;font-size:14.5px}
  .nav .phone-cta b{font-size:15px}
}
@media(max-width:1180px){
  /* drop the text phone block; keep a compact call icon instead */
  .nav .phone-cta{display:none}
  .nav .call-icon{display:grid}
}
.nav .call-icon{display:none;width:42px;height:42px;place-items:center;border-radius:10px;
  border:1px solid var(--line);background:var(--paper);color:var(--sage-700);transition:all .2s}
.nav .call-icon:hover{border-color:var(--sage-700);transform:translateY(-1px)}
.nav .call-icon svg{width:19px;height:19px}

/* ---- Nav dropdowns --------------------------------------------------------
   10 flat items overflowed the bar (needed 1401px in a 1240px container and
   pushed the CTA off-screen). Grouped into 6, two of which open on hover and
   on keyboard focus so the menu stays reachable without a pointer. */
.nav ul{align-items:center}
.nav li{position:relative}
.nav .caret{width:13px;height:13px;margin-left:3px;opacity:.6;transition:transform .2s}
.nav .has-sub:hover > a .caret,
.nav .has-sub:focus-within > a .caret{transform:rotate(180deg)}

.nav ul.sub{
  position:absolute;top:calc(100% - 2px);left:0;min-width:212px;flex-direction:column;
  background:var(--paper);border:1px solid var(--line);border-radius:12px;
  box-shadow:var(--shadow);padding:7px;gap:1px;z-index:60;
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .18s var(--ease),transform .18s var(--ease),visibility .18s;
}
.nav .has-sub:hover > ul.sub,
.nav .has-sub:focus-within > ul.sub{opacity:1;visibility:visible;transform:none}
.nav ul.sub li{width:100%}
.nav ul.sub a{display:block;width:100%;padding:9px 13px;font-size:14.5px;border-radius:8px;white-space:nowrap}
.nav ul.sub a::after{display:none}

/* keep the whole bar on one line */
.nav ul > li > a{white-space:nowrap}

/* ---- Custom work showcase (3 photos inside the custom-builds band) -------- */
.work-gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:26px}
.work-shot{margin:0;position:relative;border-radius:12px;overflow:hidden;
  border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.05)}
.work-shot img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;
  transition:transform .5s var(--ease)}
.work-shot:hover img{transform:scale(1.06)}
/* The old gradient faded to transparent across the caption box, so where the
   text actually sits the scrim was only ~52% — white on a light photo measured
   3.91:1. Holding .82 solid behind the text and only fading above it puts the
   worst case (a blown-out white photo) at 11.7:1 regardless of the image. */
.work-shot figcaption{position:absolute;left:0;right:0;bottom:0;padding:16px 12px 9px;
  font-size:12.5px;font-weight:600;color:#fff;letter-spacing:.01em;
  background:linear-gradient(to top,rgba(9,14,16,.90) 0%,rgba(9,14,16,.82) 62%,rgba(9,14,16,0) 100%)}
@media(max-width:640px){
  .work-gallery{grid-template-columns:1fr 1fr;gap:9px}
  .work-shot:last-child{grid-column:1/-1}
}

/* ---- Header "Call" menu ---------------------------------------------------
   One compact trigger listing all three yards, so no single location gets the
   default. Keeps the nav narrow (a single number, or three, overflowed the bar)
   and keeps each number tied to its own city for local SEO. */
.call-menu{position:relative}
.call-trigger{display:inline-flex;align-items:center;gap:7px;cursor:pointer;
  font-family:inherit;font-weight:600;font-size:15px;color:var(--text);
  background:transparent;border:1.5px solid var(--line-2);border-radius:10px;
  padding:11px 14px;transition:all .2s var(--ease);white-space:nowrap}
.call-trigger:hover{border-color:var(--sage-700);color:var(--sage-600)}
.call-trigger svg{width:17px;height:17px}
.call-trigger .caret{width:13px;height:13px;opacity:.6;transition:transform .2s}
.call-menu:hover .caret,.call-menu:focus-within .caret,
.call-trigger[aria-expanded="true"] .caret{transform:rotate(180deg)}

.call-sub{position:absolute;top:calc(100% + 6px);right:0;min-width:238px;
  list-style:none;margin:0;padding:7px;display:flex;flex-direction:column;gap:1px;
  background:var(--paper);border:1px solid var(--line);border-radius:12px;
  box-shadow:var(--shadow);z-index:70;
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .18s var(--ease),transform .18s var(--ease),visibility .18s}
.call-menu:hover .call-sub,.call-menu:focus-within .call-sub,
.call-trigger[aria-expanded="true"] + .call-sub{opacity:1;visibility:visible;transform:none}
/* Dismissal escape hatch (WCAG 2.4.7 / 4.1.2). `:focus-within` above is what
   makes this menu keyboard-reachable with scripting off, but it also means the
   menu cannot be closed while the trigger still holds focus — pressing Escape,
   or clicking the trigger a second time, left the panel on screen while
   aria-expanded had already flipped to "false", so the announced state was the
   exact opposite of the visible one. cinematic.js sets .is-closed on those two
   paths and clears it on re-open. Equal specificity to the rule above (0,3,0),
   so it must stay AFTER it in source order to win. */
.call-menu.is-closed .call-sub{opacity:0;visibility:hidden;transform:translateY(-6px)}
.call-menu.is-closed .caret{transform:none}
.call-sub .call-head{padding:8px 12px 6px;font-size:11px;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--muted-2)}
.call-sub a{display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  padding:10px 12px;border-radius:8px;transition:background .18s}
.call-sub a:hover{background:rgba(87,118,86,.10)}
.call-sub a b{font-family:var(--font-display);font-size:15px;color:var(--text)}
/* sage-600, not sage-700: these rows get a 10% sage hover tint behind them,
   where sage-700 drops to 4.47:1. */
.call-sub a span{font-size:14px;color:var(--sage-600);font-weight:600;
  font-variant-numeric:tabular-nums;white-space:nowrap}

@media(max-width:1180px){
  .call-trigger span{display:none}       /* icon-only when space is tight */
  .call-trigger{padding:11px}
}

/* ---- Header on small phones ----------------------------------------------
   These rules used to live only in catalog.css, so the three pages that don't
   load it (index, accessories, rent-to-own) kept a full-width CTA plus the
   search button in the bar and scrolled sideways at 375px. The header is
   global markup, so its responsive rules belong in the global sheet.
   Duplicating them in catalog.css is harmless — identical declarations. */
@media(max-width:560px){
  header.site .nav{gap:14px}
  header.site .nav-right{gap:10px}
  header.site .nav-right .btn-primary{display:none}  /* CTA lives in-page + topbar phone */
  header.site .nav .logo img{height:38px}
}
@media(max-width:400px){
  header.site .nav-right .icon-btn[aria-label="Search"]{display:none}
}

/* ---- Mobile navigation drawer --------------------------------------------
   Built at runtime from the desktop nav (see assets/js/mobile-nav.js), so the
   markup lives in exactly one place. */
.mnav{position:fixed;inset:0;z-index:200;background:rgba(9,14,16,.55);
  backdrop-filter:blur(3px);opacity:0;transition:opacity .24s var(--ease)}
.mnav.is-open{opacity:1}
.mnav-panel{position:absolute;top:0;right:0;bottom:0;width:min(88vw,380px);
  background:var(--paper);display:flex;flex-direction:column;
  box-shadow:-18px 0 48px -20px rgba(9,14,16,.5);
  transform:translateX(100%);transition:transform .26s var(--ease);
  overflow-y:auto;-webkit-overflow-scrolling:touch}
.mnav.is-open .mnav-panel{transform:none}

.mnav-head{display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:16px 18px;border-bottom:1px solid var(--line);position:sticky;top:0;
  background:var(--paper);z-index:2}
.mnav-head .logo img{height:42px;width:auto}
.mnav-close{width:42px;height:42px;display:grid;place-items:center;flex-shrink:0;
  border:1px solid var(--line);border-radius:10px;background:var(--paper);
  color:var(--text);cursor:pointer;transition:all .2s}
.mnav-close:hover{border-color:var(--ink)}
.mnav-close svg{width:20px;height:20px}

.mnav-links{padding:12px 12px 4px;display:flex;flex-direction:column;gap:2px}
.mnav-link{display:block;padding:13px 14px;border-radius:10px;font-weight:600;
  font-size:16.5px;color:var(--text);transition:background .18s}
.mnav-link:hover,.mnav-link.is-active{background:rgba(87,118,86,.10);color:var(--sage-600)}

.mnav-group{padding:14px 12px 4px;display:flex;flex-direction:column;gap:2px}
.mnav-grouplabel{padding:0 14px 7px;font-size:11px;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted-2)}
.mnav-sublink{display:block;padding:12px 14px;border-radius:10px;font-size:15.5px;
  color:var(--text);transition:background .18s}
.mnav-sublink:hover{background:rgba(87,118,86,.10);color:var(--sage-600)}

.mnav-calls{border-top:1px solid var(--line);margin-top:10px;padding-top:16px}
.mnav-call{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  padding:12px 14px;border-radius:10px;transition:background .18s}
.mnav-call:hover{background:rgba(87,118,86,.10)}
.mnav-call b{font-family:var(--font-display);font-size:15.5px;color:var(--text)}
.mnav-call span{font-size:14.5px;font-weight:600;color:var(--sage-600);
  font-variant-numeric:tabular-nums;white-space:nowrap}

.mnav-foot{margin-top:auto;padding:16px 18px calc(18px + env(safe-area-inset-bottom));
  border-top:1px solid var(--line);position:sticky;bottom:0;background:var(--paper)}

@media(prefers-reduced-motion:reduce){
  .mnav,.mnav-panel{transition:none}
}

/* ---- Photo gallery for product pages --------------------------------------
   Light-background variant of .work-gallery. Drop real photos into
   assets/img/ and swap the three src paths in each page's <section id="gallery">. */
.photo-gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:36px}
.photo-shot{margin:0;position:relative;border-radius:var(--radius);overflow:hidden;
  border:1px solid var(--line);background:var(--sand-2);box-shadow:var(--shadow-sm);
  transition:transform .3s var(--ease),box-shadow .3s var(--ease)}
.photo-shot:hover{transform:translateY(-4px);box-shadow:var(--shadow)}
.photo-shot img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;
  transition:transform .5s var(--ease)}
.photo-shot:hover img{transform:scale(1.05)}
/* Same fix as .work-shot: the caption used to sit on a ~51% scrim, which put
   white text at 3.81:1 over a light photo. Now floored at .82 behind the text. */
.photo-shot figcaption{position:absolute;left:0;right:0;bottom:0;padding:18px 14px 11px;
  font-size:13px;font-weight:600;color:#fff;
  background:linear-gradient(to top,rgba(9,14,16,.90) 0%,rgba(9,14,16,.82) 62%,rgba(9,14,16,0) 100%)}
@media(max-width:900px){
  .photo-gallery{grid-template-columns:1fr 1fr;gap:12px}
  .photo-shot:last-child{grid-column:1/-1}
}
@media(max-width:560px){
  .photo-gallery{grid-template-columns:1fr}
  .photo-shot:last-child{grid-column:auto}
}

/* =========================================================================
   ACCESSIBILITY LAYER  (WCAG 2.1 AA)
   Added by the accessibility audit. Everything below is additive — it does not
   restyle any component, it only makes existing components operable and
   perceivable. Lives in styles.css because this is the only sheet all pages
   load (catalog.css / local.css / legal.css are page-specific).
   ========================================================================= */

/* ---- Visually-hidden text -------------------------------------------------
   Was defined only in catalog.css, which index.html, accessories.html and
   rent-to-own.html do not load — so an .sr-only label on those pages rendered
   as visible text. Defined here so it works everywhere. The catalog.css copy is
   left in place; the declarations are identical, so the duplicate is harmless. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* ---- Skip link (WCAG 2.4.1 Bypass Blocks) --------------------------------
   Every page opens with a topbar, a 10-item nav and a hero before the content
   starts. This lets a keyboard user jump straight to <main>. */
.skip-link{position:absolute;left:8px;top:-60px;z-index:300;
  padding:12px 18px;border-radius:0 0 10px 10px;
  background:var(--ink);color:#fff;font-weight:600;font-size:15px;
  text-decoration:none;transition:top .18s var(--ease)}
.skip-link:focus{top:0}
/* main is a scroll target for the skip link; don't ring it when it takes focus */
main:focus{outline:none}

/* ---- Visible focus indicator (WCAG 2.4.7 Focus Visible) -------------------
   Four rules in this codebase set `outline:none` on :focus and replaced it with
   a border-colour change only, which is not a reliable focus indicator. The
   baseline below applies to anything focusable by keyboard; :focus-visible
   means mouse users still never see a ring.
   Two rings are drawn — a dark outline plus a white box-shadow halo — so the
   indicator stays visible on the sand page, on white cards AND on the dark
   header/hero/locbar without needing a per-surface rule. */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:3px solid var(--sage-600);
  outline-offset:2px;
  border-radius:4px;
}
/* on dark surfaces the sage ring alone is low-contrast against near-black —
   add a light halo so the indicator reads on both */
.topbar :focus-visible,
header.site :focus-visible,
.hero :focus-visible,
.page-hero :focus-visible,
.band :focus-visible,
.cinema :focus-visible,
.locbar :focus-visible,
.cta :focus-visible,
footer.site :focus-visible,
.yard-cross :focus-visible{
  outline-color:#fff;
  box-shadow:0 0 0 6px rgba(9,14,16,.55);
}
/* the FAQ rows hide the native marker and are the main keyboard target on most
   pages — give the ring a little breathing room so it isn't clipped */
.faq summary:focus-visible{outline-offset:-2px;border-radius:8px}

/* Forms that previously killed the ring outright. Keeping the border tint as a
   secondary cue, but the ring above now always draws. */
.quote-box input:focus-visible,
.quote-box select:focus-visible,
.quote-box textarea:focus-visible{outline-color:#fff}

/* ---- Don't let a reveal strand its content --------------------------------
   .reveal / .stagger start at opacity:0 and only become visible when
   cinematic.js adds .in, so with scripting off the page renders large blank
   bands. The counterpart to this is the <noscript> block in each page's
   <head>, which force-shows them.

   Why <noscript> and not an html.js class: cinematic.js is loaded at the end of
   <body>, so a class it sets would arrive after first paint — content would
   flash in, snap out, then fade back. And an inline <head> script is off the
   table because this codebase is deliberately keeping `script-src 'self'`
   viable with no 'unsafe-inline' (see the note above the zip-quote scripts).
   <noscript> needs no script execution at all and cannot flash.

   The rules themselves live in that <noscript><style> block rather than here,
   because <noscript> in <head> can only carry <style>/<link>/<meta> — it cannot
   set a class for a selector here to hook. Keep the two in sync:

     .reveal,.reveal-scale,.reveal-left,.reveal-right,.stagger>*
       { opacity:1!important; transform:none!important; filter:none!important; }

   cinematic.js additionally force-shows everything when the browser has no
   IntersectionObserver, which covers the other way this could strand. */

/* ---- Rating stars ---------------------------------------------------------
   The five star glyphs are decorative once the rating is also given in text
   (see the .sr-only span added next to each set in the markup). */
.stars svg{flex-shrink:0}


/* ---- No-JavaScript notices --------------------------------------------------
   Shown only from inside <noscript>, where the interactive control they replace
   has been hidden. Styled as an ordinary notice rather than an error: scripting
   being off is a legitimate way to browse, not a fault of the visitor's. */
.nojs-note{
  margin:18px 0;padding:16px 18px;
  border:1px solid var(--line);border-left:4px solid var(--sage-600);
  border-radius:10px;background:var(--paper);
  font-size:15px;line-height:1.65;color:var(--ink)
}
/* sage-600 (6.86:1 on white), not sage-700 (5.08:1) — this notice carries the
   phone numbers a no-JS visitor needs, so it gets the stronger of the two. */
.nojs-note a{color:var(--sage-600);font-weight:600}

/* Fallback shown in place of the GoHighLevel iframe when scripting is off. It
   sits inside .quote-box, which is a dark translucent panel, so it needs light
   text rather than the .nojs-note treatment used on light backgrounds. */
.nojs-quote{
  margin:0;padding:14px 16px;border-radius:10px;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.18);
  color:rgba(255,255,255,.92);font-size:14.5px;line-height:1.6
}
.nojs-quote a{color:#fff;font-weight:600}
