/*
  SkilledMob shared design system.
  Extracted from the approved index.html homepage. Do not add new colors or fonts —
  every generated page (hub, service, guide, state, city, combo) includes this one file.
*/
:root{
  /* Brand */
  --purple:#2B124C;
  /* Header-only, deliberately darker than --purple (2026-08-13) — fixes the
     header/inner-hero blend on service+state, combo, and future state/city
     hub pages. Scoped to .site-header's background only; every other purple
     surface (hero sections, footer, buttons) stays on --purple. */
  --purple-header:#22103F;
  --purple-light:#3D1E68;
  --orange:#FF6A21;
  --orange-hover:#E85A15;
  --teal:#17B890;
  --white:#FFFFFF;
  /* Neutrals */
  --bg-section:#F7F7F9;
  --border:#E5E7EB;
  --gray-secondary:#6B7280;
  --gray-disabled:#9CA3AF;
  --danger:#D93B3B;
  --text-dark:#25252B;
  --radius:12px;
  --max-w:1280px;
}
*{margin:0;padding:0;box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{
  font-family:'Inter',sans-serif;
  color:var(--text-dark);
  background:var(--white);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,.font-display{font-family:'Sora',sans-serif;}
a{text-decoration:none;color:inherit;}
img{max-width:100%;display:block;}
ul{list-style:none;}
button{font-family:inherit;cursor:pointer;}
.wrap{max-width:var(--max-w);margin:0 auto;padding:0 24px;}
:focus-visible{outline:3px solid var(--teal);outline-offset:2px;}

/* ===== BACK TO TOP (2026-08-14) =====
   Global, fixed, hidden until JS adds .is-visible (see fragments/
   backToTop.js — scroll past 300px). Square with a shared card-radius
   corner (var(--radius), same language as the site's cards), not circular
   and not sharp. 48x48 floor matches the .btn min-height accessibility
   target elsewhere. Orange hover is a DELIBERATE, CONFIRMED exception to
   orange-is-call-actions-only (same category as the state-chip tint
   exception) — do not flag or revert. bottom:100px (2026-08-14, was 200px)
   keeps clear of the .lower-cta-wrap CTA strip that ends most pages;
   z-index:90 stays below the sticky header's 100 (defensive — they never
   actually overlap spatially, since one pins to the top and this pins near
   the bottom). */
.back-to-top{
  position:fixed;right:24px;bottom:100px;z-index:90;
  width:48px;height:48px;border-radius:var(--radius);
  background:var(--teal);border:none;
  display:flex;align-items:center;justify-content:center;
  cursor:pointer;box-shadow:0 4px 14px rgba(0,0,0,.18);
  opacity:0;visibility:hidden;transform:translateY(8px);
  transition:opacity .2s,transform .2s,background .15s;
}
.back-to-top.is-visible{opacity:1;visibility:visible;transform:translateY(0);}
.back-to-top:hover{background:var(--orange);}
.back-to-top svg{width:22px;height:22px;}

/* ===== BUTTONS ===== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:14px 26px;border-radius:var(--radius);font-weight:700;font-size:15px;
  border:none;min-height:48px;transition:background .15s,transform .1s;
}
.btn svg{width:18px;height:18px;flex-shrink:0;}
.btn-call{background:var(--orange);color:#fff;}
.btn-call:hover{background:var(--orange-hover);}
.btn-call:active{transform:scale(.98);}
.btn-outline-purple{background:#fff;color:var(--purple);border:1.5px solid var(--purple);}
.btn-outline-purple:hover{background:var(--purple);color:#fff;}
/* Bottom CTA's call button (2026-08-14) — same default look as
   .btn-outline-purple, but scoped so ONLY this button hovers to orange
   instead of purple (every other .btn-outline-purple on the site keeps its
   purple hover). Icon uses stroke="currentColor" (see renderCallCta's
   'outline' variant), so it follows `color` automatically — no separate
   icon rule needed. */
.btn-outline-purple.lower-cta-call-btn:hover{background:var(--orange);border-color:var(--orange);color:#fff;}
.btn-purple{background:var(--purple);color:#fff;border:1.5px solid var(--purple);transition:background .15s,border-color .15s,transform .1s;}
.btn-purple:hover{background:var(--orange);border-color:var(--orange);}
.btn-purple:active{transform:scale(.98);}
.btn-disabled{
  background:var(--bg-section);color:var(--gray-disabled);width:100%;
  display:inline-flex;align-items:center;justify-content:center;padding:14px 26px;
  border-radius:var(--radius);font-weight:700;font-size:14px;border:1px solid var(--border);
  cursor:default;
}

/* ===== HEADER ===== */
/* Hairline divider (2026-08-13) — subtle light border, not orange (orange
   stays reserved for call actions only). Solid 1px, matching the site's
   existing thin-solid-border language. Part of the shared header component,
   so it renders consistently on every page — purple .inner-hero pages
   (fixes the header/hero blend) and white .category-hero pages alike. */
.site-header{background:var(--purple-header);border-bottom:1px solid rgba(255,255,255,.12);position:sticky;top:0;z-index:100;height:78px;}
.header-inner{
  max-width:var(--max-w);margin:0 auto;padding:0 24px;height:78px;
  display:flex;align-items:center;justify-content:space-between;gap:24px;
}
.logo{display:flex;align-items:center;font-family:'Sora',sans-serif;font-weight:700;font-size:22px;color:#fff;gap:1px;}
.logo .pin{width:16px;height:16px;margin:0 1px;}
.main-nav{display:flex;align-items:center;gap:30px;}
.main-nav a{color:#EDE7F5;font-size:14.5px;font-weight:500;display:flex;align-items:center;gap:5px;transition:color .15s;}
.main-nav a:hover{color:#fff;}
.header-actions{display:flex;align-items:center;gap:16px;}
.hamburger{display:none;background:none;border:none;padding:8px;}
.hamburger svg{width:24px;height:24px;stroke:#fff;}

/* ===== NAV DROPDOWN (2026-08-15) =====
   Targeted nav update — 3 of the 4 top-level items are dropdowns (Home
   stays a plain link, no chevron). Trigger is a real <button> (not an <a
   href="#">), so it's keyboard-focusable/activatable by default with no
   extra ARIA plumbing beyond aria-expanded/aria-haspopup. Opens on hover
   (desktop, via :hover/:focus-within) AND on click (.is-open, toggled by
   fragments/callScript.js's renderNavDropdownScript — also the only way it
   opens on mobile, see the 860px breakpoint below). The ::after pseudo-
   element bridges the visual gap between trigger and menu so hover doesn't
   drop when the cursor crosses it. */
.nav-dropdown{position:relative;}
.nav-dropdown::after{content:'';position:absolute;top:100%;left:0;right:0;height:14px;}
.nav-dropdown-trigger{
  background:none;border:none;padding:0;cursor:pointer;font-family:inherit;
  color:#EDE7F5;font-size:14.5px;font-weight:500;display:flex;align-items:center;gap:5px;
  transition:color .15s;
}
.nav-dropdown-trigger:hover{color:#fff;}
.nav-dropdown-trigger svg{transition:transform .15s;}
.nav-dropdown-trigger[aria-expanded="true"] svg{transform:rotate(180deg);}
/* Mega-menu (2026-08-15) — 2x2 icon-tile grid instead of a plain stacked
   list (each of the 3 dropdowns already has exactly 4 items, so a fixed
   2-col grid always fills evenly). display is "grid" when open, not
   "block" — see the open-state rule below. */
.nav-dropdown-menu{
  display:none;position:absolute;top:calc(100% + 14px);left:50%;transform:translateX(-50%);width:360px;
  grid-template-columns:repeat(2,1fr);gap:8px;
  background:#fff;border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:0 12px 28px rgba(0,0,0,.16);padding:10px;z-index:110;
}
.nav-dropdown:hover .nav-dropdown-menu,
.nav-dropdown:focus-within .nav-dropdown-menu,
.nav-dropdown-menu.is-open{display:grid;}
/* Live and coming-soon items look identical (same Deep Purple text/icon,
   same card treatment) — non-interactivity alone communicates status, no
   dimming, no badge, per explicit direction. Only the hover feedback
   differs: a real link gets the light-gray hover, an inert item gets none,
   since hovering something that does nothing shouldn't look interactive.
   Card language (border + radius) matches the site's existing tile/card
   components (.tile-link, .service-type-card), not a one-off style. */
.nav-dropdown-item{
  display:flex;align-items:center;gap:9px;
  border:1px solid var(--border);border-radius:var(--radius);
  padding:11px 10px;font-size:13px;font-weight:700;color:var(--purple);
  transition:background .15s,border-color .15s;
}
.nav-dropdown-item svg{width:19px;height:19px;stroke:var(--purple);flex-shrink:0;}
/* Fix (2026-08-15): the real <a> tile (Dumpster Rental) was nearly
   invisible — .main-nav a{color:#EDE7F5} (pale lavender, meant for links
   directly on the dark header) has higher specificity (element+class) than
   the plain .nav-dropdown-item class rule above, so it was winning for the
   one item that's an <a> instead of a <span>. This matches it in
   specificity (element+class) so Deep Purple wins instead. */
a.nav-dropdown-item{color:var(--purple);}
/* Hover redesign (2026-08-15) — orange bg, white text/icon, per explicit
   direction. Deliberate, confirmed exception to orange-is-call-actions-only
   (same category as the state-chip tint and back-to-top hover) — do not
   flag or revert. Scoped to real links only (a.nav-dropdown-item); inert
   items still get zero hover change, per the standing "don't make
   non-interactive things look interactive" rule for this menu. */
a.nav-dropdown-item:hover{background:var(--orange);border-color:var(--orange);color:#fff;}
a.nav-dropdown-item:hover svg{stroke:#fff;}
.nav-dropdown-item.is-inert{cursor:default;}

/* ===== HERO ===== */
.hero{background:var(--white);padding:64px 0 0;overflow:hidden;}
.hero-grid{display:grid;grid-template-columns:1.05fr 1fr;gap:40px;align-items:center;}
.hero-copy h1{font-size:clamp(34px,4.6vw,52px);line-height:1.08;font-weight:800;margin-bottom:18px;}
.hero-copy h1 .c-purple{color:var(--purple);}
.hero-copy h1 .c-orange{color:var(--orange);}
.hero-copy p.lead{font-size:16px;color:var(--gray-secondary);max-width:460px;margin-bottom:26px;}
.hero-benefits{display:flex;gap:26px;flex-wrap:wrap;margin-bottom:32px;}
.hero-benefit{display:flex;align-items:center;gap:10px;}
.hero-benefit .icon-circle{width:38px;height:38px;background:#F1EAFA;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.hero-benefit .icon-circle svg{width:18px;height:18px;stroke:var(--purple);}
.hero-benefit b{display:block;font-size:13.5px;color:var(--text-dark);}
.hero-benefit span{font-size:12px;color:var(--gray-secondary);}
.hero-visual{position:relative;}
.hero-img-wrap{
  position:relative;border-radius:24px;overflow:hidden;aspect-ratio:4/3.1;
  background:linear-gradient(135deg,#3D1E68,#2B124C);
}
.hero-img-wrap img{width:100%;height:100%;object-fit:cover;}
.hero-img-wrap::before{
  content:'';position:absolute;left:-30px;top:10%;bottom:10%;width:70px;
  background:var(--purple);border-radius:40px;z-index:0;
}
.hero-card{
  position:absolute;left:-24px;bottom:-24px;background:var(--purple);color:#fff;
  border-radius:16px;padding:18px 22px;display:flex;gap:14px;align-items:flex-start;
  max-width:300px;box-shadow:0 12px 30px rgba(43,18,76,.28);
}
.hero-card .icon-circle{width:36px;height:36px;background:rgba(255,255,255,.14);border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.hero-card .icon-circle svg{width:16px;height:16px;stroke:#fff;}
.hero-card b{display:block;font-size:14px;margin-bottom:3px;}
.hero-card span{font-size:12.5px;color:#D8CDEB;line-height:1.5;}

/* ===== INNER HERO (every page type EXCEPT the top-level vertical hub) =====
   Confirmed 2026-08-12: purple hero is the general pattern for every non-hub
   page — service, guide, state hub, city hub, and combo.
   Only /{vertical}/ itself (.category-hero) keeps the white/photo treatment.
   Renamed from .service-hero once this was confirmed as general, not
   service-page-specific — use THIS class for any new non-hub page type.
   Use renderBreadcrumbs() as-is here; the base .breadcrumbs rules below are
   already styled for a purple background, no scoped override needed.

   UNIVERSAL FIXED STANDARD (2026-08-16) — replaces the 2026-08-13 graduated
   3-tier density system (baseline/tier2/tier3), which was retired entirely.
   Every inner page now gets ONE hero size, no modifier class needed —
   values below are what used to be "tier3" (the combo page's density),
   promoted to be the only size, since a single consistent hero height
   across every inner page type read better than three different depths.
   Deliberate consequence: the service page (previously 100% baseline) and
   the state hub (previously reverted back to full baseline after being
   flagged as "too much empty") both shrink to this same smaller size now —
   both are intentional under this standard, not a regression.
   .is-tier2/.is-tier3 modifier classes and their markup usage
   (templates/serviceStateHubPage.js, templates/comboPage.js) were removed
   — every inner-page template now renders plain `<section class="inner-hero">`
   with no modifier.
   No literal height:Xpx here on purpose — a fixed pixel height risks
   clipping dynamically-generated H1/description text that runs longer than
   expected (e.g. "Concrete / Heavy Debris in Texas"). Visual height instead
   comes from these fixed padding/gap/font values alone, with line-clamp:2 +
   ellipsis on the description below as a safety net so a longer description
   is truncated cleanly (whole words, "…") rather than ever wrapping to a
   3rd line and growing the hero.

   min-height (2026-08-16) — Playwright measurement (getBoundingClientRect,
   not code inspection) showed real, expected variance depending on content:
   223.8px for a 1-line description, 248.59375px for a 2-line description,
   186px for the guide page's hero (no description paragraph at all — every
   other field on this page has real content, so this is a MINIMUM, not a
   fixed height: nothing here can push a hero taller than 248.59375px given
   the H1 clamp + description line-clamp above, so min-height floors every
   shorter case up to the tallest real one instead of capping/clipping
   anything. Confirmed via the same Playwright method afterward: all 8
   sampled inner-page types render exactly 248.59375px. */
.inner-hero{background:var(--purple);padding:26px 0 24px;min-height:248.59px;}
.inner-hero .wrap{color:#fff;}
.inner-hero .breadcrumbs{margin-bottom:9px;}
.inner-hero h1{font-size:clamp(20px,2.7vw,30px);font-weight:800;margin-bottom:7px;}
.inner-hero p{
  font-size:15.5px;color:#D8CDEB;max-width:640px;margin-bottom:13px;
  display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;text-overflow:ellipsis;
}

/* "Available In" location pills — kept for potential reuse elsewhere, no
   longer used on the service page as of 2026-08-13 (see .state-chip below,
   which replaced it there). */
.location-pills{display:flex;flex-wrap:wrap;gap:16px;}
.location-pill{display:inline-flex;align-items:center;gap:7px;font-size:13.5px;font-weight:600;color:var(--purple);background:#fff;border:1.5px solid var(--border);border-radius:100px;padding:10px 18px;transition:background .15s,border-color .15s;}
.location-pill svg{width:15px;height:15px;stroke:var(--purple);flex-shrink:0;}
.location-pill:hover{background:#F1EAFA;border-color:rgba(43,18,76,.25);}

/* State chips — service page's "Available In" section (2026-08-13). Wide,
   short boxes (more horizontal than the square service-grid cards), 5-color
   rotating tint cycling in DOM order via :nth-child, deep-purple text/icon
   on every variant regardless of tint. #FFF1E8 (tint 2) is a confirmed,
   deliberate exception to "orange stays reserved for call actions" — this
   is a light background tint, not the call-action orange itself, and the
   exception is scoped to exactly this component. Not a status system (no
   live/soon meaning) — purely visual variety across genuinely-available
   states, unlike the hub's .cat-badge live/soon treatment. */
.state-chip-grid{display:flex;flex-wrap:wrap;gap:12px;}
.state-chip{
  display:inline-flex;align-items:center;gap:8px;
  padding:14px 22px;border-radius:var(--radius);
  font-size:14px;font-weight:700;color:var(--purple);
  transition:transform .15s,box-shadow .15s;
}
.state-chip svg{width:15px;height:15px;stroke:var(--purple);flex-shrink:0;}
.state-chip:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(43,18,76,.08);}
.state-chip:nth-child(5n+1){background:#F1EAFA;}
.state-chip:nth-child(5n+2){background:#FFF1E8;}
.state-chip:nth-child(5n+3){background:#E4F8F2;}
.state-chip:nth-child(5n+4){background:#FFFFFF;border:1px solid var(--border);}
.state-chip:nth-child(5n+5){background:#F7F7F9;}

/* Tile grid — horizontal icon+title+chevron cards, used for "Other Services"
   and "Helpful Guides" on the full-width service page layout. */
.tile-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;}
.tile-link{display:flex;align-items:center;gap:14px;background:#fff;border:1px solid var(--border);border-radius:var(--radius);padding:18px 20px;transition:transform .15s,box-shadow .15s;}
.tile-link:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(43,18,76,.08);}

/* Tinted tile grid (2026-08-15) — state hub's "Browse Services" grid only
   (templates/stateHubPage.js), base for every state page since it's the
   shared template. First 3 tints match .state-chip's established rotation
   (light purple/orange/teal) above. Tint 4 is a new light-blue addition
   (2026-08-15) — the white slot from .state-chip's rotation read as a "gap"
   once every card in this grid needed real color, so it's replaced here
   with a soft blue that rounds out the purple/orange/teal triad rather than
   reusing white. Tint 5 stays the same light neutral gray. Deep-purple
   icon/text on every variant, same as .state-chip. Scoped under
   .tile-grid-tinted so the service page's plain white "Helpful
   Guides"/"Other Services" tile grids stay untouched. */
.tile-grid-tinted .tile-link{border:none;}
.tile-grid-tinted .tile-link:nth-child(5n+1){background:#F1EAFA;}
.tile-grid-tinted .tile-link:nth-child(5n+2){background:#FFF1E8;}
.tile-grid-tinted .tile-link:nth-child(5n+3){background:#E4F8F2;}
.tile-grid-tinted .tile-link:nth-child(5n+4){background:#E8F0FE;}
.tile-grid-tinted .tile-link:nth-child(5n+5){background:#F7F7F9;}
.tile-icon{flex-shrink:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;}
.tile-icon svg{width:26px;height:26px;stroke:var(--purple);stroke-width:1.6;}
.tile-link.is-guide .tile-icon svg{stroke:var(--teal);}
.tile-title{flex:1;font-size:14.5px;font-weight:700;color:var(--text-dark);line-height:1.3;}
.tile-link .chevron{flex-shrink:0;stroke:var(--gray-disabled);}

/* ===== OTHER SERVICES GRID (2026-08-15, tightened twice same day) =====
   Redesign of the service page's "Other {vertical} Services" section only
   — .tile-grid/.tile-link above stays exactly as it was for "Helpful
   Guides", untouched, this is a separate component. 3x2 grid: one card per
   sibling service (real title/description reused from the manifest's
   existing hubTitle/hubBlurb — same fields the vertical hub's category
   grid already uses, not new copy) plus a purple call-out card filling the
   last grid slot. Icons reused from icons.SERVICE_ICONS, same set already
   used elsewhere for these exact services.

   Icon+title now sit side by side in .other-service-head (was icon-above-
   title, stacked) with a smaller icon — removes a full row of vertical
   space per card. .other-service-card and .other-service-cta share the
   same min-height so all 6 boxes match regardless of row (CSS grid only
   equalizes height WITHIN a row by default, not across the two rows here,
   since each row's auto height is independent) — .other-service-cta gets
   `flex:1` on its <p> so its button still anchors to the bottom instead of
   leaving a gap when its content is shorter than the shared min-height. */
/* grid-auto-rows:1fr (not just min-height on the cards) is what actually
   forces the two rows to match — min-height alone is only a floor, so a
   shorter row still ends up shorter than a row whose tallest item (usually
   the CTA card) needs more than that floor. 1fr rows on an auto-height grid
   equalize every row to the tallest content across all of them. */
.other-services-grid{display:grid;grid-template-columns:repeat(3,1fr);grid-auto-rows:1fr;gap:20px;}
.other-service-card,.other-service-cta{
  display:flex;flex-direction:column;min-height:150px;
  border-radius:16px;padding:20px;
}
.other-service-card{background:#fff;border:1px solid var(--border);transition:transform .15s,box-shadow .15s,border-color .15s;}
.other-service-card:hover{transform:translateY(-3px);box-shadow:0 10px 24px rgba(43,18,76,.1);border-color:rgba(43,18,76,.15);}
.other-service-head{display:flex;align-items:center;gap:12px;margin-bottom:10px;}
.other-service-icon{
  width:40px;height:40px;border-radius:50%;background:#F1EAFA;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
}
.other-service-icon svg{width:20px;height:20px;stroke:var(--purple);stroke-width:1.8;}
.other-service-card h3{font-size:16px;font-weight:800;color:var(--purple);margin:0;line-height:1.25;}
.other-service-card p{font-size:13.5px;color:var(--gray-secondary);line-height:1.5;}
/* Call-out card — fills the grid's last slot, real call button (same
   renderCallCta/data-call-cta mechanism as every other call action on the
   site, not a static button). */
.other-service-cta{background:var(--purple);color:#fff;}
.other-service-cta .other-service-icon{background:transparent;border:1.5px solid rgba(255,255,255,.4);}
.other-service-cta .other-service-icon svg{stroke:#fff;width:18px;height:18px;}
.other-service-cta h3{font-size:16px;font-weight:800;margin:0;line-height:1.25;}
.other-service-cta p{font-size:13px;color:#D8CDEB;line-height:1.5;margin-bottom:14px;flex:1;}
.other-service-cta .btn{align-self:flex-start;}

/* State grid — full 50-state listing on the vertical hub's "Browse by
   State" in-page section. Reuses .cat-badge/.cat-badge.live/.cat-badge.soon
   as-is (already generic) for the live/coming-soon distinction, matching
   the homepage category grid. (The standalone /{vertical}/locations/
   directory page that also used to reuse this component was removed
   2026-08-15 — this section is now the only place it's used.) */
.state-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:14px;}
.state-card{
  background:#fff;border:1px solid var(--border);border-radius:var(--radius);
  padding:16px 14px;text-align:center;transition:transform .15s,box-shadow .15s;
}
.state-card.is-live{border-color:rgba(23,184,144,.35);}
.state-card.is-live:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(43,18,76,.08);}
.state-card.is-soon{background:var(--bg-section);}
.state-card .cat-badge{margin-bottom:8px;}
.state-card h3{font-size:13.5px;font-weight:700;color:var(--text-dark);}
.state-card.is-soon h3{color:var(--gray-secondary);}
/* Not-available state (2026-08-14) — e.g. Alaska: no page generated (service
   isn't offered there), so this renders as a plain non-interactive div, not
   an <a> — no hover lift, no link to a page that doesn't exist. */
.state-card.is-unavailable{background:var(--bg-section);border-color:rgba(217,59,59,.25);cursor:default;}
.state-card.is-unavailable h3{color:var(--gray-secondary);}

/* ===== BREADCRUMBS ===== */
.breadcrumbs{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font-size:12.5px;color:#D8CDEB;margin-bottom:16px;}
.breadcrumbs a{color:#D8CDEB;}
.breadcrumbs a:hover{color:#fff;text-decoration:underline;}
.breadcrumbs .sep{color:#8B6FAE;}
.breadcrumbs .current{color:#fff;font-weight:600;}

/* ===== CATEGORIES ===== */
.categories{padding:80px 0 60px;}
.section-title{text-align:center;font-size:clamp(24px,3vw,32px);font-weight:700;color:var(--purple);margin-bottom:40px;}
.cat-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:16px;}
.cat-card{
  background:#fff;border:1px solid var(--border);border-radius:var(--radius);
  padding:22px 16px;text-align:center;transition:transform .15s,box-shadow .15s;
}
.cat-card.is-live{border-color:rgba(23,184,144,.35);}
.cat-card.is-live:hover{transform:translateY(-3px);box-shadow:0 10px 24px rgba(43,18,76,.1);}
.cat-card.is-soon{background:var(--bg-section);}
.cat-badge{
  display:inline-block;font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  padding:3px 9px;border-radius:100px;margin-bottom:12px;
}
.cat-badge.live{background:#E4F8F2;color:var(--teal);}
.cat-badge.soon{background:#EEEFF1;color:var(--gray-disabled);}
.cat-badge.unavailable{background:#FBEAEA;color:var(--danger);}
.cat-icon{width:52px;height:52px;border-radius:12px;margin:0 auto 12px;display:flex;align-items:center;justify-content:center;}
.cat-card.is-live .cat-icon{background:#F1EAFA;}
.cat-card.is-live .cat-icon svg{stroke:var(--purple);}
.cat-card.is-soon .cat-icon{background:#E9EAEC;}
.cat-card.is-soon .cat-icon svg{stroke:var(--gray-disabled);}
.cat-icon svg{width:24px;height:24px;}
.cat-card h3{font-size:14.5px;font-weight:700;color:var(--text-dark);margin-bottom:3px;}
.cat-card.is-soon h3{color:var(--gray-secondary);}
.cat-card p{font-size:11.5px;color:var(--gray-secondary);}
.cat-legend{display:flex;justify-content:center;gap:26px;margin-top:26px;font-size:13px;color:var(--gray-secondary);}
.cat-legend span{display:flex;align-items:center;gap:7px;}
.dot{width:9px;height:9px;border-radius:50%;}
.dot.teal{background:var(--teal);}
.dot.gray{background:var(--gray-disabled);}

/* ===== HOW IT WORKS ===== */
.how{padding:70px 0 0;}
.how-steps{display:flex;align-items:flex-start;justify-content:center;gap:0;margin-bottom:52px;}
.how-step{display:flex;gap:14px;max-width:230px;}
.step-num-icon{position:relative;flex-shrink:0;}
.step-circle{
  width:56px;height:56px;border-radius:50%;background:#F1EAFA;
  display:flex;align-items:center;justify-content:center;
}
.step-circle svg{width:22px;height:22px;stroke:var(--purple);}
.step-badge{
  position:absolute;top:-4px;right:-4px;width:22px;height:22px;border-radius:50%;
  background:var(--purple);color:#fff;font-size:11px;font-weight:700;
  display:flex;align-items:center;justify-content:center;
}
.how-step h3{font-size:15.5px;margin:2px 0 4px;color:var(--text-dark);}
.how-step p{font-size:13px;color:var(--gray-secondary);}
.how-arrow{display:flex;align-items:center;padding:0 18px;margin-top:26px;}
.how-arrow svg{width:44px;height:14px;stroke:var(--border);}

/* ===== TRUST STRIP ===== */
.trust-strip{background:var(--purple);border-radius:20px;padding:30px;display:grid;grid-template-columns:repeat(4,1fr);gap:20px;margin-bottom:80px;}
.trust-item{display:flex;gap:13px;align-items:flex-start;color:#fff;}
.trust-item .icon-circle{width:38px;height:38px;background:rgba(255,255,255,.12);border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.trust-item .icon-circle svg{width:17px;height:17px;stroke:#fff;}
.trust-item.teal-icon .icon-circle svg{stroke:var(--teal);}
.trust-item b{display:block;font-size:14px;margin-bottom:3px;}
.trust-item span{font-size:12px;color:#D8CDEB;line-height:1.5;}

/* ===== FEATURED ===== */
.featured{padding:0 0 80px;}
.feat-grid{display:grid;grid-template-columns:1fr 1fr;gap:22px;}
.feat-card{background:#fff;border:1px solid var(--border);border-radius:16px;overflow:hidden;}
.feat-body{padding:26px;}
.feat-pill{
  display:inline-block;background:var(--purple);color:#fff;font-size:10.5px;font-weight:700;
  letter-spacing:.5px;text-transform:uppercase;padding:4px 11px;border-radius:100px;margin-bottom:14px;
}
.feat-content{display:grid;grid-template-columns:1fr 1fr;}
.feat-text h3{font-size:19px;margin-bottom:8px;}
.feat-text p.desc{font-size:13.5px;color:var(--gray-secondary);margin-bottom:14px;}
.feat-list{display:flex;flex-direction:column;gap:7px;margin-bottom:0;}
.feat-list li{font-size:13px;color:var(--text-dark);display:flex;gap:8px;align-items:flex-start;}
.feat-list li svg{width:14px;height:14px;stroke:var(--teal);flex-shrink:0;margin-top:2px;}
.feat-img{position:relative;border-radius:10px;overflow:hidden;min-height:150px;background:var(--bg-section);}
.feat-img img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0;}
.feat-cta{padding:16px 26px;}
.feat-cta .btn{width:100%;}

/* ===== LOWER CTA ===== */
.lower-cta-wrap{padding:0 0 80px;}
.lower-cta{
  background:var(--purple);border-radius:20px;padding:28px 34px;
  display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;color:#fff;
}
.lower-cta-left{display:flex;align-items:center;gap:18px;}
.lower-cta-icon{
  width:54px;height:54px;border-radius:50%;background:var(--orange);
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
}
.lower-cta-icon svg{width:24px;height:24px;stroke:#fff;}
.lower-cta-left b{font-size:17px;display:block;margin-bottom:3px;}
.lower-cta-left span{font-size:13px;color:#D8CDEB;}

/* ===== FOOTER (2026-08-15 rebuild) =====
   5 columns: Brand, Property & Exterior, Home Repair & Systems, Moving &
   Specialty, Hours — same 3 category groupings as the header nav's
   mega-menu, so the site uses one consistent taxonomy everywhere. No
   "(Live)"/"Coming Soon" labels — plain links only, same rule as the nav;
   Dumpster Rental is a real link, everything else (including HVAC) is a
   plain non-interactive <span>, no href, same "coming soon" pattern used
   sitewide. Company column dropped entirely (confirmed, not needed right
   now). Legal column (Privacy/Terms/Disclaimer links) removed outright
   (2026-08-15) — bottom bar is just "© 2026 SkilledMob" (white, centered,
   see .foot-legal-line) followed by the disclaimer paragraph, no links. */
.site-footer{background:var(--purple);color:#D8CDEB;padding:56px 0 0;}
.foot-grid{display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr 1fr;gap:28px;padding-bottom:40px;}
.foot-col h4{color:#fff;font-size:13.5px;margin-bottom:15px;}
.foot-col li{margin-bottom:9px;font-size:13px;}
.foot-col a:hover{color:#fff;}
.foot-brand .logo{color:#fff;margin-bottom:12px;}
.foot-brand p{font-size:13px;line-height:1.6;max-width:230px;}
.foot-talk{display:flex;align-items:center;gap:8px;margin-top:14px;font-size:13px;color:#fff;font-weight:600;}
.foot-talk svg{width:15px;height:15px;stroke:var(--orange);}
.foot-bottom{border-top:1px solid rgba(255,255,255,.12);padding:20px 0;text-align:center;}
.foot-legal-line{font-size:12px;color:#fff;font-weight:600;margin-bottom:10px;}
.foot-bottom p{font-size:11.5px;color:#B9A9D1;max-width:820px;margin:0 auto;line-height:1.6;}

/* ===== INTERIOR / CONTENT PAGES (service, guide, state, city, combo) =====
   New components built for Batch 1. Reuse existing tokens only — no new colors/fonts. */

.content-section{padding:56px 0;}
.content-section + .content-section{padding-top:0;}
.two-col{display:grid;grid-template-columns:2.1fr 1fr;gap:40px;align-items:start;}

/* Prose (guide articles, intro copy) */
.prose h2{font-size:22px;color:var(--purple);margin:34px 0 14px;}
.prose h2:first-child{margin-top:0;}
.prose h3{font-size:17px;margin:22px 0 10px;}
.prose p{font-size:15px;color:var(--text-dark);margin-bottom:14px;max-width:70ch;}
.prose ul,.prose ol{list-style:disc;padding-left:22px;margin-bottom:14px;}
.prose ol{list-style:decimal;}
.prose li{font-size:15px;margin-bottom:6px;}
.prose a{color:var(--purple);text-decoration:underline;text-underline-offset:2px;}
/* Inline clickable phone number within body copy — orange (call-action
   color), distinct from the purple used for regular prose links. Selector
   is deliberately ".prose a.inline-phone-link" (not just ".inline-phone-link")
   so it out-specifies the ".prose a" rule above, which would otherwise win
   and force it purple. */
.prose a.inline-phone-link{color:var(--orange);font-weight:700;text-decoration:none;}
.prose a.inline-phone-link:hover{color:var(--orange-hover);text-decoration:underline;}
/* Bug fix 2026-08-16: same specificity collision as .prose a.inline-phone-link
   above — the combo page's fact-box CTA button (.btn-purple, a real <a>) sits
   inside .prose, so ".prose a" (element+class) was beating ".btn-purple"
   (single class), turning the white button label into purple-on-purple
   (invisible) with an underline, only becoming legible on hover once
   .btn-purple:hover's orange background gave the purple text contrast. Same
   out-specify fix: ".prose a.btn-purple" wins over ".prose a". */
.prose a.btn-purple{color:#fff;text-decoration:none;}
.prose table{width:100%;border-collapse:collapse;margin:14px 0 20px;font-size:14px;}
.prose th,.prose td{border:1px solid var(--border);padding:10px 12px;text-align:left;}
.prose th{background:var(--bg-section);font-weight:700;}

/* Sidebar card (used on guide/service/combo pages) */
.side-card{background:var(--bg-section);border:1px solid var(--border);border-radius:var(--radius);padding:22px;margin-bottom:20px;}
.side-card h4{font-size:14px;color:var(--purple);margin-bottom:12px;}
.side-card ul{display:flex;flex-direction:column;gap:9px;}
.side-card li a{font-size:13.5px;color:var(--text-dark);display:flex;gap:8px;align-items:flex-start;}
.side-card li a:hover{color:var(--purple);text-decoration:underline;}
/* Bug fix 2026-08-12: this svg had no width/height anywhere (attribute or
   CSS). An unsized inline <svg> falls back to the browser's replaced-element
   default (~300x150px), which was inflating every <li> to that height —
   the "huge broken gaps" were actually each icon rendering enormous, not
   real spacing. Same icons.check() call is used with no size issue elsewhere
   (e.g. .feat-list, .coverage-highlights) only because those already had
   an explicit svg rule; this component never did. */
.side-card li a svg{width:14px;height:14px;stroke:var(--teal);flex-shrink:0;margin-top:2px;}
.side-card .btn{width:100%;margin-top:6px;}

/* Link grid (state hub -> city hubs, city hub -> combo pages, nearby cities).
   Gap and card padding matched to the service page's density (2026-08-13):
   16px grid gap standard, padding matched to .service-type-card's weight. */
.link-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;}
.link-card{
  background:#fff;border:1px solid var(--border);border-radius:var(--radius);
  padding:24px 20px;transition:transform .15s,box-shadow .15s,border-color .15s;
}
.link-card:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(43,18,76,.08);border-color:rgba(43,18,76,.25);}
.link-card b{display:block;font-size:15px;color:var(--text-dark);margin-bottom:4px;}
.link-card span{font-size:12.5px;color:var(--gray-secondary);}

/* Tinted link grid (2026-08-16) — city hub's "Browse Services" grid only
   (templates/cityHubPage.js). Same 5-color light-tint rotation as
   .tile-grid-tinted above (purple/orange/teal/blue/gray) — reused for
   consistency rather than a new palette. Scoped under .link-grid-tinted so
   the state hub's plain white "Cities We Cover" .link-grid stays untouched. */
.link-grid-tinted .link-card{border:none;}
.link-grid-tinted .link-card:nth-child(5n+1){background:#F1EAFA;}
.link-grid-tinted .link-card:nth-child(5n+2){background:#FFF1E8;}
.link-grid-tinted .link-card:nth-child(5n+3){background:#E4F8F2;}
.link-grid-tinted .link-card:nth-child(5n+4){background:#E8F0FE;}
.link-grid-tinted .link-card:nth-child(5n+5){background:#F7F7F9;}

/* ===== VERTICAL HUB ONLY =====
   Everything below is used exclusively by templates/verticalHubPage.js.
   Photo hero is intentionally reserved for hub pages — every other interior
   template (service/guide/state/city/combo/service-state) uses the purple
   .inner-hero above instead. */

/* Photo hero — independent grid/copy/visual classes (not the homepage's
   .hero-grid/.hero-copy) so the locked homepage hero is never entangled with
   hub-page changes. .hero-benefits/.hero-benefit are reused as-is since
   they're a generic sub-component already, not core hero identity. */
.category-hero{background:var(--white);padding:40px 0 0;overflow:hidden;}
.category-hero .breadcrumbs{color:var(--gray-secondary);margin-bottom:18px;}
.category-hero .breadcrumbs a{color:var(--gray-secondary);}
.category-hero .breadcrumbs a:hover{color:var(--purple);}
.category-hero .breadcrumbs .sep{color:var(--border);}
.category-hero .breadcrumbs .current{color:var(--text-dark);}
.category-hero-grid{display:grid;grid-template-columns:1.05fr 1fr;gap:40px;align-items:center;padding-bottom:8px;}
.category-hero-copy h1{font-size:clamp(34px,4.6vw,52px);font-weight:800;color:var(--purple);line-height:1.08;margin-bottom:14px;}
.category-hero-copy p.lead{font-size:16px;color:var(--gray-secondary);max-width:480px;margin-bottom:26px;}
.category-hero-copy .hero-benefits{margin-bottom:30px;}
/* Value-prop icons scoped to the hub hero only — bumped up from the base
   .hero-benefit 38px/18px sizing (locked, shared with the homepage) to
   ~58px/26px per the approved hub mockup. Does not touch .hero-copy, so the
   homepage is unaffected. */
.category-hero-copy .hero-benefits .icon-circle{width:58px;height:58px;}
.category-hero-copy .hero-benefits .icon-circle svg{width:26px;height:26px;stroke-width:2;}
.category-hero-visual{position:relative;}
.category-hero-img-wrap{position:relative;border-radius:24px;overflow:hidden;aspect-ratio:4/3.1;background:var(--bg-section);}
.category-hero-img-wrap img{width:100%;height:100%;object-fit:cover;}

/* Intro + call-cta card, two columns below the hero */
.category-intro{padding:44px 0 56px;}
.category-intro-grid{display:grid;grid-template-columns:2fr 1fr;gap:40px;align-items:start;}
.category-intro-grid h2{font-size:23px;color:var(--purple);margin-bottom:14px;}
.category-intro-grid .prose p{max-width:none;font-size:15.5px;}

.call-cta{background:var(--bg-section);border:1px solid var(--border);border-radius:16px;overflow:hidden;}
.call-cta-top{background:var(--purple);color:#fff;padding:22px;display:flex;gap:14px;align-items:flex-start;}
.call-cta-top .icon-circle{width:42px;height:42px;background:rgba(255,255,255,.18);border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.call-cta-top .icon-circle svg{width:20px;height:20px;stroke:#fff;stroke-width:2;}
.call-cta-top b{display:block;font-size:16px;margin-bottom:3px;}
.call-cta-top span{font-size:13px;color:rgba(255,255,255,.9);line-height:1.5;}
.call-cta-status{display:flex;align-items:center;gap:7px;padding:14px 22px;font-size:13px;color:var(--teal);font-weight:600;}

/* 6-card service-type grid */
.service-type-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;}
.service-type-card{background:#fff;border:1px solid var(--border);border-radius:var(--radius);padding:24px 20px;text-align:center;transition:transform .15s,box-shadow .15s;}
.service-type-card:hover{transform:translateY(-3px);box-shadow:0 10px 24px rgba(43,18,76,.1);}
.service-type-card .cat-icon{width:58px;height:58px;border-radius:50%;background:#F1EAFA;}
.service-type-card .cat-icon svg{width:26px;height:26px;stroke:var(--purple);stroke-width:2;}
.service-type-card h3{font-size:15.5px;font-weight:700;margin-bottom:6px;}
.service-type-card p{font-size:13px;color:var(--gray-secondary);}

/* FAQ grid (2026-08-14) — always-visible, no accordion. Same border/
   padding/radius language as .service-type-card above, left-aligned since
   this is read text rather than an icon-first nav card. Hub page: 3x2 (6
   FAQs), default below. .faq-grid-2col modifier: 2x2 (4 FAQs) — service page
   and other deeper page types, per the standing per-page-type FAQ count. */
.faq-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;}
.faq-grid.faq-grid-2col{grid-template-columns:repeat(2,1fr);}
.faq-card{background:#fff;border:1px solid var(--border);border-radius:var(--radius);padding:24px 20px;}
.faq-card h3{font-size:15px;font-weight:700;color:var(--purple);margin-bottom:8px;line-height:1.35;}
.faq-card p{font-size:13.5px;color:var(--gray-secondary);line-height:1.55;}

/* Coverage + guides combined panel */
.coverage-panel{background:var(--bg-section);border:1px solid var(--border);border-radius:16px;padding:0;display:grid;grid-template-columns:1.4fr 1fr 1fr;}
.coverage-panel > div{padding:28px 26px;}
.coverage-panel > div + div{border-left:1px solid var(--border);}
.coverage-panel-info{display:flex;gap:14px;align-items:flex-start;}
.coverage-panel-info .icon-circle{width:48px;height:48px;background:#F1EAFA;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.coverage-panel-info .icon-circle svg{width:22px;height:22px;stroke:var(--purple);stroke-width:2;}
.coverage-panel-info h4{font-size:15px;margin-bottom:6px;}
.coverage-panel-info p{font-size:13px;color:var(--gray-secondary);}
.coverage-highlights{display:flex;flex-direction:column;gap:9px;margin-top:14px;}
.coverage-highlights li{display:flex;gap:9px;align-items:flex-start;font-size:13px;color:var(--text-dark);}
.coverage-highlights li svg{width:14px;height:14px;stroke:var(--teal);flex-shrink:0;margin-top:2px;}
.coverage-panel-expand p{font-size:13px;color:var(--gray-secondary);margin-bottom:14px;}

.guide-list h4{font-size:14.5px;color:var(--purple);margin-bottom:14px;}
.guide-list{display:flex;flex-direction:column;gap:2px;}
.guide-link{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 0;font-size:13.5px;color:var(--text-dark);border-bottom:1px solid var(--border);}
.guide-link:last-child{border-bottom:none;}
.guide-link:hover{color:var(--purple);}
.guide-link svg:last-child{stroke:var(--gray-disabled);flex-shrink:0;}

/* FAQ */
.faq-item{border-bottom:1px solid var(--border);padding:18px 0;}
.faq-item:first-child{padding-top:0;}
.faq-item h3{font-size:15.5px;margin-bottom:8px;color:var(--text-dark);}
.faq-item p{font-size:14px;color:var(--gray-secondary);}

/* Nearby cities / related links strip */
.related-strip{display:flex;flex-wrap:wrap;gap:10px;margin-top:8px;}
.related-strip a{
  font-size:12.5px;color:var(--purple);background:var(--bg-section);border:1px solid var(--border);
  border-radius:100px;padding:7px 14px;
}
.related-strip a:hover{background:#F1EAFA;}

/* Local facts callout — flex row (2026-08-16) so a CTA button can sit on
   the right of the text instead of stacked below it; the text itself stays
   in .fact-box-text so it remains one flex item, not two. */
.fact-box{background:#F1EAFA;border-radius:var(--radius);padding:18px 20px;margin:20px 0;display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap;}
.fact-box-text b{display:block;color:var(--purple);font-size:13px;margin-bottom:4px;}
.fact-box-text p{font-size:13.5px;color:var(--text-dark);margin:0;}
.fact-box .btn{flex-shrink:0;}

/* ===== RESPONSIVE ===== */
@media(max-width:1024px){
  .cat-grid{grid-template-columns:repeat(4,1fr);}
  .state-grid{grid-template-columns:repeat(4,1fr);}
  .foot-grid{grid-template-columns:1fr 1fr;}
  .trust-strip{grid-template-columns:1fr 1fr;}
  .two-col{grid-template-columns:1fr;}
  .link-grid{grid-template-columns:repeat(2,1fr);}
  .service-type-grid{grid-template-columns:repeat(2,1fr);}
  .tile-grid{grid-template-columns:repeat(2,1fr);}
  .other-services-grid{grid-template-columns:repeat(2,1fr);}
  .faq-grid{grid-template-columns:repeat(2,1fr);}
  .coverage-panel{grid-template-columns:1fr;}
  .coverage-panel > div + div{border-left:none;border-top:1px solid var(--border);}
}
@media(max-width:860px){
  .main-nav{
    display:none;flex-direction:column;align-items:stretch;gap:2px;
    position:absolute;top:78px;left:0;right:0;background:var(--purple-header);
    padding:14px 24px 20px;border-bottom:1px solid rgba(255,255,255,.12);
    max-height:calc(100vh - 78px);overflow-y:auto;
  }
  .hamburger{display:block;}
  /* Mobile nav (2026-08-15) — same 4 items, same link/inert data, just
     restructured as a stacked accordion instead of a horizontal hover bar
     (hover doesn't really exist on touch). Click/tap is the only way to
     open a group here — the desktop :hover rule still matches technically
     but nothing on a touchscreen triggers it, so .is-open (JS) does all the
     work at this width. */
  .main-nav > a,.nav-dropdown-trigger{width:100%;padding:12px 4px;font-size:15px;}
  .nav-dropdown-trigger{justify-content:space-between;}
  /* Same 2x2 icon-tile grid as desktop, just static-positioned (part of the
     accordion flow) instead of floating, and recolored for the dark
     accordion panel instead of the white desktop dropdown. */
  .nav-dropdown-menu{
    position:static;left:auto;transform:none;display:none;width:auto;background:transparent;border:none;
    box-shadow:none;padding:4px 0;margin:2px 0 4px;
  }
  .nav-dropdown-menu.is-open{display:grid;}
  .nav-dropdown-item{color:#fff;border-color:rgba(255,255,255,.16);padding:10px;}
  .nav-dropdown-item svg{stroke:#fff;}
  a.nav-dropdown-item{color:#fff;}
  a.nav-dropdown-item:hover{background:var(--orange);border-color:var(--orange);color:#fff;}
  a.nav-dropdown-item:hover svg{stroke:#fff;}
  .hero-grid{grid-template-columns:1fr;}
  .hero-visual{order:-1;}
  .hero-card{position:static;margin-top:16px;max-width:none;}
  .hero-img-wrap::before{display:none;}
  .feat-grid{grid-template-columns:1fr;}
  .feat-content{grid-template-columns:1fr;}
  .feat-img{order:-1;}
  .how-steps{flex-direction:column;gap:22px;}
  .how-arrow{display:none;}
}
@media(max-width:600px){
  .cat-grid{grid-template-columns:repeat(2,1fr);}
  .state-grid{grid-template-columns:repeat(2,1fr);}
  .trust-strip{grid-template-columns:1fr;}
  .header-inner{padding:0 16px;}
  .wrap{padding:0 16px;}
  .lower-cta{flex-direction:column;align-items:flex-start;}
  .lower-cta .btn{width:100%;}
  .fact-box{flex-direction:column;align-items:flex-start;}
  .fact-box .btn{width:100%;}
  .link-grid{grid-template-columns:1fr;}
  .service-type-grid{grid-template-columns:1fr;}
  .tile-grid{grid-template-columns:1fr;}
  /* auto, not 1fr, at single-column mobile — with only one card per "row"
     there's no sibling to match height to, so forcing 1fr here would just
     stretch every short card to match the CTA card's height for no reason,
     leaving a lot of dead space in a stacked single-column list. */
  .other-services-grid{grid-template-columns:1fr;grid-auto-rows:auto;}
  .faq-grid{grid-template-columns:1fr;}
  .faq-grid.faq-grid-2col{grid-template-columns:1fr;}
  .category-intro-grid{grid-template-columns:1fr;}
  .location-pills{gap:10px;}
  .back-to-top{right:16px;}
}
