/* RankForge -- shared structural CSS, linked by EVERY template's page.html
   BEFORE its own style.css (see renderer.py's asset copy, which copies this
   file into every build as /base.css, and each page.html's <link> order).
   Holds the ~80-line-per-skin duplication (box-sizing reset, .cta-button /
   .mobile-call / .quote-form skeletons) plus the NEW shared components this
   redesign introduces (fluid type scale, section rhythm, content-block
   image variants, .cta-band, .why-us-strip, a real FAQ affordance) in ONE
   place instead of copy-pasted eight times.

   Every skin's style.css loads AFTER this file, so any selector a skin
   redeclares wins by normal CSS source-order cascade (same specificity) --
   a skin keeps full control of its own colors/radius/fonts/spacing, this
   file only ever supplies STRUCTURE/BEHAVIOR (layout, transitions) or the
   shared --* contrast vars (renderer.py's _resolve_palette), never a
   hardcoded text/background color -- so a palette swap can't break
   contrast (see the parametrized contrast test in tests/test_renderer.py).

   --radius: every skin declares its own value in :root (modern: 1rem,
   bold: 0 for square corners, etc.) -- the new content-block variants /
   .cta-band below read it via var(--radius, 0.75rem) so the corner
   treatment stays on-brand per skin without each one re-declaring the same
   selector list just to override one property.
*/

*, *::before, *::after { box-sizing: border-box; }
/* overflow-x on the SCROLL ROOT, because the full-bleed breakout below
   (.stats-band/.cta-band/body.hero-bg .hero) sizes itself with 100vw, and
   100vw counts the vertical scrollbar while the content box does not -- so
   every banded page sat ~8-15px wider than its own viewport and scrolled
   sideways by exactly the scrollbar width. Several skins already set
   `overflow-x: hidden` on BODY, which does nothing here: the scroll
   container is <html>, not <body>. `clip` rather than `hidden` on purpose --
   `hidden` would turn <html> into a scroll container and break the
   position:sticky headers every skin relies on; `clip` just clips. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: clip; }
img { max-width: 100%; height: auto; display: block; }

/* Fluid type scale -- every skin's h1/h2/h3 rides this clamp() curve unless
   it sets its own font-size (most do, for their own look -- this is the
   floor every skin that DOESN'T override still gets, and the shared curve
   shape keeps h1/h2/h3 proportional to each other across skins). */
h1 { font-size: clamp(2rem, 1.1rem + 3.6vw, 3.4rem); margin: 0 0 0.6rem; }
h2 { font-size: clamp(1.5rem, 1.15rem + 1.2vw, 2.1rem); margin: 0 0 0.85rem; }
h3 { font-size: clamp(1.05rem, 0.92rem + 0.5vw, 1.3rem); margin: 0 0 0.5rem; }
p { max-width: 68ch; }

/* Vertical rhythm -- every top-level section gets the same breathing room
   by default, so the page doesn't read as one undifferentiated slab (the
   diagnosed problem: six identical content-block sections back to back). */
.trust-badges, .services-grid, .content-sections, .faq, .team-photo,
.reviews, .map, .quote-form, .related-links, .why-us-strip, .cta-band {
  margin: clamp(1.5rem, 3vw, 2.5rem) 0;
}

/* CTA buttons -- shared layout/behavior skeleton only; every skin still
   owns background/color/radius/font/text-transform. */
.cta-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  text-decoration: none;
  white-space: nowrap;
  border: 0;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.cta-button:hover { transform: translateY(-1px); }
.cta-button:active { transform: translateY(0); }

/* Hero full-bleed background photo + overlay skeleton -- opt-in via
   body.hero-bg (renderer.TEMPLATE_FLAGS' hero_bg flag, set on <body> by
   _shared/page.html) rather than applied to every skin unconditionally:
   editorial/minimal render this exact same hero markup but keep a normal
   small inline <img> instead, and an unscoped absolutely-positioned
   .hero::after would sit on top of their hero text/CTAs as an invisible
   click-blocking overlay. Each opted-in skin (modern/bold/callpro/trades)
   still owns its own .hero background color, .hero::after gradient tint,
   and .hero-inner padding/max-width -- only position/sizing lives here. */
body.hero-bg .hero { position: relative; overflow: hidden; }
body.hero-bg .hero-image { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; margin: 0; z-index: 0; }
body.hero-bg .hero::after { content: ""; position: absolute; inset: 0; z-index: 1; }
body.hero-bg .hero:not(:has(.hero-image))::after { display: none; }
body.hero-bg .hero-inner { position: relative; z-index: 2; }

/* Hero height -- was purely content-driven (padding + h1 + slogan + CTAs),
   landing around 510px on a 1080p screen: shallow, doesn't read as a real
   hero banner. min-height (not height) so a longer h1/slogan can still grow
   it; grid + align-items: center (NOT flexbox) so .hero-inner keeps
   stretching to the container's full width -- CSS Grid's default
   justify-items is stretch, flexbox's isn't -- while its own content
   vertically centers within the taller box. */
body.hero-bg .hero { min-height: clamp(420px, 64vh, 760px); display: grid; align-items: center; }

/* A taller hero reads better with a slightly bigger headline. Overridden
   here (not in each skin's style.css) at higher specificity than every
   skin's own ".hero h1" rule -- (body.hero-bg .hero h1) beats (.hero h1) on
   selector count regardless of source order, so this raises the ceiling
   uniformly for every hero_bg skin without touching skin files. */
body.hero-bg .hero h1 { font-size: clamp(2.1rem, 5.2vw, 3.8rem); }

/* Quote form -- shared grid/reset skeleton, skin owns background/border/radius/color. */
.quote-form form { display: grid; gap: 0.8rem; max-width: 480px; }
.quote-form label { display: grid; gap: 0.3rem; font-size: 0.85rem; font-weight: 700; }
.quote-form input, .quote-form textarea { width: 100%; font: inherit; }
.quote-form button { justify-self: start; cursor: pointer; font: inherit; }

/* FAQ -- a real open/close affordance instead of the bare browser triangle;
   skin owns border/background/radius/color. */
.faq summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  flex: none;
  font-size: 1.3rem;
  line-height: 1;
  transition: transform 0.15s ease;
}
.faq details[open] summary::after { transform: rotate(45deg); }

/* Service cards -- shared hover affordance + a fixed aspect ratio (instead
   of each skin's own hardcoded pixel height) so the grid stays even
   regardless of the source photo's proportions. */
.service-card { transition: transform 0.15s ease, box-shadow 0.15s ease; }
.service-card img { aspect-ratio: 4 / 3; width: 100%; height: auto; object-fit: cover; }

/* Content-block variants -- see renderer._content_flow. "v-plain" needs no
   extra rules (identical to the old undecorated content-block). */
.content-block.v-panel, .content-block.v-accent-band {
  background: var(--surface);
  color: var(--text-on-surface);
  border-radius: var(--radius, 0.75rem);
  padding: clamp(1.75rem, 4vw, 2.75rem);
}
.content-block.v-accent-band { border-left: 0.35rem solid var(--accent); }
.content-block.v-image-left, .content-block.v-image-right {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem 2rem;
  align-items: center;
}
.content-block .section-media img {
  width: 100%;
  height: 100%;
  max-height: 22rem;
  object-fit: cover;
  border-radius: var(--radius, 0.75rem);
}
@media (min-width: 760px) {
  .content-block.v-image-left, .content-block.v-image-right { grid-template-columns: 1fr 1fr; }
  .content-block.v-image-right .section-media { order: 2; }
}

/* CTA band -- interleaved between content sections (renderer._content_flow,
   after roughly the 2nd section). Uses the accent color as its own block so
   it visually breaks up the page instead of blending into the surrounding
   text sections. */
.cta-band {
  text-align: center;
  background: var(--accent);
  color: var(--text-on-accent);
  border-radius: var(--radius, 0.75rem);
  padding: clamp(2rem, 5vw, 3rem) clamp(1.5rem, 4vw, 2.5rem);
}
.cta-band h2 { color: inherit; }
.cta-band .cta-ctas { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.85rem; margin-top: 1rem; }
.cta-band .cta-button:not(.secondary) { background: var(--base); color: var(--text); }
.cta-band .cta-button.secondary { border: 2px solid var(--text-on-accent); color: var(--text-on-accent); }

/* Why-us strip -- interleaved after roughly the 4th section (renderer.
   _content_flow): trust_claims when configured, or renderer._why_us_items'
   honest city/areas/service-count fallback when not -- never an empty gap. */
.why-us-strip { text-align: center; }
.why-us-strip ul {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem 2rem;
}
.why-us-strip li { font-weight: 700; }

/* Sticky call band -- opt-in via template_flags.sticky_call_band (see
   renderer.TEMPLATE_FLAGS / _shared/page.html), rendered once right under
   the header. Shared position skeleton only; the opting-in skin owns
   colors/padding. */
.sticky-call-band {
  position: sticky;
  top: 0;
  z-index: 19;
  text-align: center;
}

/* Mobile call bar -- shared skeleton, skin owns colors. */
.mobile-call { display: none; }
@media (max-width: 640px) {
  .mobile-call {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1rem;
    text-decoration: none;
    font-weight: 700;
  }
}

/* ---------------------------------------------------------------------------
   Section eyebrow, stats band and areas grid -- ported from the proven
   alcoholrehabhouston.com design (seo-directory-builder/web-brand). Structure
   only: every colour resolves through the contrast vars so these stay
   readable on ANY brand palette, and each skin overrides look via its own
   style.css (fonts, --radius, letter-spacing) without redeclaring layout.
   --------------------------------------------------------------------------- */

/* The small uppercase label above each section heading. This single element
   does most of the work breaking a run of prose sections into distinct
   "chapters" rather than one wall of text. */
.side-label {
  text-transform: uppercase;
  letter-spacing: 0.28em;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--accent-ink, var(--accent));
  margin: 0 0 0.2rem;
}
.side-label + h2 { margin-top: 0; }

/* Stats band -- full-bleed strip of counted figures (services/areas/pages). */
.stats-band {
  background: var(--surface);
  color: var(--text-on-surface);
  border-radius: var(--radius, 0.75rem);
  padding: 1.6rem 1.4rem;
  margin: 2.5rem 0;
}
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1.4rem;
}
.stat {
  display: flex;
  flex-direction: column;
  border-left: 4px solid var(--accent);
  padding-left: 0.9rem;
}
.stat-n {
  font-size: clamp(1.6rem, 3.6vw, 2.4rem);
  font-weight: 800;
  line-height: 1.05;
  color: var(--accent-ink-on-surface, var(--accent));
}
.stat-l {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top: 0.35rem;
  color: var(--text-muted-on-surface);
}

/* Areas we serve -- card grid built from the Keywords step's adjacent towns
   + neighborhoods (previously only a footer comma-string). */
.areas-grid { padding: 2.5rem 0 1rem; }
.areas {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 0.7rem;
  margin-top: 1.1rem;
}
.area-card {
  display: block;
  background: var(--surface);
  color: var(--text-on-surface);
  border: 1px solid var(--border-on-surface);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius, 0.75rem);
  padding: 0.7rem 0.9rem;
  font-weight: 600;
  font-size: 0.92rem;
}

/* ---------------------------------------------------------------------------
   Typed sections -- benefits list + numbered process steps (see
   renderer._typed_content_flow / backend/templates/_shared/_sections/ and
   docs/SECTION_SYSTEM.md). Structure only, contrast vars only (same rule as
   every other component in this file) -- every skin's own h2/h3/font/accent
   cascades in automatically; a skin only needs its own override here if it
   wants a genuinely different LOOK for these two components (e.g. bold's
   uppercase h3 styling already applies to .step-copy h3 with zero extra
   CSS, because it cascades from bold's existing h-element rule).
   --------------------------------------------------------------------------- */

.sec-benefits .benefits-list {
  list-style: none;
  margin: 1.25rem 0 0;
  padding: 0;
  display: grid;
  gap: 1rem;
}
.sec-benefits .benefits-list li {
  padding-left: 1.4rem;
  border-left: 3px solid var(--accent);
}
.sec-benefits .benefits-list strong { color: var(--accent-ink, var(--accent)); }

.sec-process .process-steps {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: grid;
  gap: 1.1rem;
}
.sec-process .process-steps li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1rem;
  align-items: start;
  padding: 1rem 0;
  border-bottom: 1px solid var(--border);
}
.sec-process .process-steps li:last-child { border-bottom: 0; }
.sec-process .step-n {
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  font-weight: 800;
  line-height: 1;
  color: var(--accent-ink, var(--accent));
  font-variant-numeric: tabular-nums;
}
.sec-process .step-copy h3 { margin: 0 0 0.3rem; }
.sec-process .step-copy p { margin: 0; }

/* ---------------------------------------------------------------------------
   Layout corrections (found by actually looking at the rendered page).
   --------------------------------------------------------------------------- */

/* Full-bleed hero. The hero markup sits INSIDE <main>, which every skin
   caps (max-width) for readable line lengths -- so without this the hero
   renders as a narrow floating box with the page background showing down
   both sides, which reads as broken rather than designed. The negative-
   margin breakout lets it span the viewport while <main> keeps constraining
   the prose. Scoped to hero_bg templates (see TEMPLATE_FLAGS): editorial/
   minimal deliberately keep a small inline hero image, which stretching to
   100vw would blow out. */
body.hero-bg .hero {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

/* Banded sections read as bands only when they span the page. Same breakout,
   with the inner content re-constrained so the text still lines up with the
   column above it. */
.stats-band, .cta-band {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  border-radius: 0;
  padding-left: max(1.25rem, calc(50vw - var(--content-max, 1140px) / 2));
  padding-right: max(1.25rem, calc(50vw - var(--content-max, 1140px) / 2));
}

/* 5 services in an auto-fit grid landed as 4 + 1 orphan, so the track count
   is capped at 3 below and the last row is never a lone card.
   `display: grid` belongs HERE too, with the columns it governs. Only
   classic and darkpro declared it in their own style.css; minimal and modern
   set grid-template-columns without it, so their service cards laid out as
   plain stacked blocks and every column rule -- theirs and this file's --
   was silently inert. Measured on minimal: five 852x639 images stacked 31px
   apart, ~3200px of near-contiguous photo in a 13400px page, which is what
   "too many big images close together" was. The other four skins ship their
   own _services_grid.html with different markup and are unaffected. */
body .services-grid .grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.25rem;
}
@media (min-width: 900px) {
  body .services-grid .grid { grid-template-columns: repeat(3, 1fr); }
}

/* Footer nav -- an even, aligned column grid instead of flex-wrap. Every
   skin declares `.footer-links { display: flex; flex-wrap: wrap }`, which
   packs 15 links of wildly different widths into ragged rows (measured 4
   rows of 3/4/5/3). A grid puts them on a shared baseline and in aligned
   columns, so the footer reads as a site map rather than a run-on list.
   `body footer` (element + element + class) deliberately outspecifies each
   skin's own `.footer-links` -- base.css loads FIRST, so an equal-
   specificity rule here would lose the cascade to every skin. Colors,
   font-size and max-width all stay with the skins. */
body footer .footer-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 0.55rem 1.5rem;
  align-items: start;
  justify-content: start;
}
body footer .footer-links a { line-height: 1.45; }

/* Image sections: give the media real presence instead of a small inset
   picture beside a narrow ragged text column. */
@media (min-width: 900px) {
  body .content-block.v-image-left, body .content-block.v-image-right {
    grid-template-columns: 1.05fr 1fr;
    gap: 2.5rem;
    align-items: center;
  }
}
/* aspect-ratio, NOT height:100% -- inside the align-items:center grid the
   media cell has no resolved height, so height:100% collapsed the image to
   0px (caught by measuring the live page, not by reading the CSS). */
body .content-block .section-media img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  max-height: 420px;
  object-fit: cover;
}

/* Header: brand + nav + CTA were wrapping onto three cramped left-aligned
   rows while most of the bar sat empty, because service names make for long
   nav labels. Widen the bar to the content width, let the nav take the
   middle and the CTA sit hard right, and tighten nav type so a typical
   5-6 item nav fits one row on desktop. */
body .header-inner {
  max-width: var(--content-max, 1140px);
  flex-wrap: wrap;
  row-gap: 0.4rem;
}
.site-header nav { margin-left: auto; }
.site-header nav a { white-space: nowrap; }
@media (min-width: 1000px) {
  .site-header nav { font-size: 0.78rem; letter-spacing: 0.04em; }
  .header-inner > .cta-button { margin-left: 0.75rem; }
}

/* Heading-profile variation (see the per-skin _sections/*.html overrides).
   Some skins promote a benefits lead to a real h3, others render a process
   step title as a plain label -- these two rules make both read at the
   right visual weight, so a markup change never becomes a design change.
   .step-title matches the h3 the shared process partial uses; .benefit-item
   h3 sits at body scale rather than the h3 clamp, since it labels one
   bullet, not a section. */
.step-title {
  display: block;
  font-weight: 700;
  font-size: 1.02rem;
  line-height: 1.3;
  margin: 0 0 0.3rem;
}
.benefit-item h3 {
  font-size: 1rem;
  margin: 0 0 0.2rem;
  line-height: 1.35;
}
.benefit-item p { margin: 0; }
.benefits-headed { display: grid; gap: 1rem; margin-top: 1.25rem; }
@media (min-width: 700px) {
  .benefits-headed { grid-template-columns: repeat(2, 1fr); gap: 1.1rem 2rem; }
}

/* Brand lockup in the header -- the generated monogram mark (mark.svg, see
   backend/logo.py) beside the brand name. Structure only: every skin already
   styles `.brand` for its own font/size/color and that still applies to the
   text, which is why the wordmark is real HTML rather than baked into the
   SVG (an <img>-loaded SVG is its own document and cannot inherit the
   header's color -- it would be black on the dark-header skins).
   The mark is sized off the text it sits next to, so it scales with each
   skin's own .brand font-size instead of needing eight overrides. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
}
.brand-mark {
  flex: none;
  width: 1.9em;
  height: 1.9em;
  display: block;
}
.brand-text { display: inline-block; }
