/* Service areas section (spec 2026-09-09-suburbs-and-process-image.md):
   suburbs ticker + "Where we work" region groups. Served from public/
   like onsite-quote.css and process-layout.css, so it never touches the
   Vite-merged bundle (the main bundle's 99B headroom stays untouched).
   Pattern adapted from projects/flowthroughhi-website's own ticker
   (index.html ~L203-209, css/styles.css .ticker ~L336-344) -- structure
   only, restyled with this site's own tokens (--border/--paper/--accent-
   dark/--text-muted etc.) rather than FTHI's visual values. */

/* Round 1d (2026-09-09, Codex design review, fix 1 "ribbon gap"): the
   global `section { padding: 120px 0 }` (styles.css) sat its top
   padding ABOVE the ticker, leaving 0px of breathing room BELOW it
   before the heading -- "too close to the ribbon". Zeroing the
   section's own top padding and moving the same amount onto
   `.container` instead puts the gap where it reads correctly (ticker
   flush to the section top, breathing room above the H2). Bottom
   padding is untouched -- still inherited from the global section rule.
   Round 2 (codex desktop alignment unification) keeps this exactly as
   is -- the spec's unified system explicitly calls out that the 120px
   top space stays on the container BELOW the ticker for this section,
   matching this round-1d behaviour. */
#service-areas { padding-top: 0; }
#service-areas > .container { padding-top: 120px; }
@media (max-width: 768px) {
  #service-areas > .container { padding-top: 80px; }
}

/* Round 1d, fix 6 "quiet ticker": vertical padding and weight both
   toned down (1.75rem->1rem, 600->500) -- the original read as too
   loud/pill-like next to the rest of the page. Animation, per-item
   margin spacing (round 1b's seamless-loop fix) and the reduced-motion
   override below are all untouched. */
.ticker { overflow: hidden; padding: 1rem 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); background: var(--paper); }
/* round 1b fix: spacing is a trailing margin on EVERY span (not a flex
   `gap` on the container) so all 36 spans -- both the visible and the
   aria-hidden duplicate set -- carry the same number of spacer units.
   With `gap`, 36 items produce only 35 gaps, so the duplicate set sits
   half a gap short of exactly half the track's total width -- a real,
   if small (20px), seam mismatch the -50% keyframe can't perfectly
   close. Per-item margin gives 36 equal spacer units, so the duplicate
   set lands at EXACTLY 50% of the track width and the loop is
   pixel-seamless (verified: 0px drift, see spec Records round 1b). */
.ticker__track { display: flex; width: max-content; animation: service-ticker 40s linear infinite; }
.ticker:hover .ticker__track { animation-play-state: paused; }
.ticker__track span { font-weight: 500; font-size: 1rem; color: var(--text-dim); white-space: nowrap; margin-right: 2.5rem; }
@keyframes service-ticker { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .ticker { overflow-x: auto; }
  .ticker__track { animation: none; }
}

/* Round 1c base (mobile/unconditional): plain block stack of group
   cards. Round 2 leaves this untouched -- below 900px nothing here
   changes. */
.service-area-groups { display: grid; grid-template-columns: 1fr; gap: 2rem; margin-top: 2.5rem; }

/* Round 4 (2026-09-09, Adelaide service-area map): UNCONDITIONAL --
   applies at every width, not just >=900px. The inline SVG root carries
   explicit width="560" height="660" attributes (added for CLS safety;
   the coordinator-supplied geometry itself is untouched) -- without a
   width override here, an SVG with explicit width/height attributes
   renders at THAT PIXEL SIZE regardless of viewport, which caused a
   real, measured 580px scrollWidth at a 390px viewport (190px of
   horizontal overflow) before this rule existed, caught by this
   round's own 390 screenshot pass. width:100% + aspect-ratio (not the
   attributes) is what actually governs the rendered size at every
   width; the attributes only matter as the pre-CSS-load intrinsic-size
   hint that prevents CLS. margin-top gives the map its own gap below
   the directory on mobile (where the two stack in one column, per the
   coordinator's "map renders BELOW the directory" instruction) --
   overridden to 0 at >=900px below, where the outer grid's own
   column-gap does that job instead. */
/* Round 4b (2026-09-09): Robin supplied his own branded map artwork,
   replacing the round-4 generated/inlined SVG -- now a plain raster
   <img> (poc/public/adelaide-service-map.webp, 1145x1374, coordinator-
   verified: all 18 suburbs + ADELAIDE + GULF ST VINCENT + ADELAIDE
   HILLS fringe + compass present via OCR, correct geography, no
   foreign/third-party branding). aspect-ratio matches the asset's own
   intrinsic 1145:1374 (was 560:660 for the generated SVG) -- width/
   height attrs on the <img> itself (1145/1374) already reserve the box
   before this rule loads, so there is zero CLS either way, same
   convention as `.process-dashboard`'s image in round 2. No SVG-
   specific mechanism survives this round: a raster image can't
   selectively hide individual labels the way the old inline SVG's
   `text[font-size="11"]` rule could -- the round-4 mobile label-hide
   media query is REMOVED entirely (not left inert), and sub-600px
   suburb-label legibility is now baked into the artwork itself,
   whatever Robin's source PNG rendered at that size. Not independently
   re-verified as a "legible at 390" claim this round -- the coordinator
   verified the CONTENT (OCR, geography, branding) at full asset
   resolution, not per-breakpoint rendered legibility; flagged as a
   known gap, not silently assumed fine. */
.service-map-img { display: block; width: 100%; height: auto; aspect-ratio: 1145 / 1374; margin-top: 2rem; border-radius: var(--radius-lg); box-shadow: var(--shadow); }
.service-area-group h3 { font-size: 1rem; line-height: 1.3; margin-bottom: 0.75rem; color: var(--accent-dark); }
/* Round 1d, fix 2 "kill the pills": suburb names are a plain text list
   (no background/border/radius/padding) -- the pill treatment read as
   "tacky" against the rest of the page's typography. ul/li semantics
   and all 19 entries (18 ticker suburbs + the Adelaide Hills fringe)
   are unchanged, copy untouched. Mobile keeps the flex-wrap row order
   (fix 4's single-column list is >=900px only); the gap here is fix
   6's requested 0.5rem row / 1rem column spacing for that wrapped
   layout. */
.suburb-chips { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; align-content: flex-start; }
.suburb-chips li { font-size: 0.94rem; line-height: 1.65; color: var(--text-muted); }
/* Round 1d, fix 5: extra breathing room between the lede and whatever
   follows it in the intro column. This is the MOBILE/unconditional
   value (24px) -- round 2's >=900px block below overrides it to the
   system's 16px for desktop only, per spec ("lede top margin 24px ->
   16px (system says 16)"), leaving mobile exactly as it was. */
.service-areas-intro .lede { margin-top: 1.5rem; }
.service-area-note { color: var(--text-muted); font-size: 0.92rem; margin-top: 2rem; }
.service-area-note a { color: var(--accent-dark); font-weight: 600; }

/* Round 4c (2026-09-09, small): mobile-only reorder -- Robin wants the
   map BEFORE the suburbs directory below 900px (intro, then map, then
   region groups + note); desktop (>=900px) stays exactly as round
   4/4b left it, directory left / map right, unchanged.

   Implemented as a flex reorder, scoped ENTIRELY to max-width:899px so
   it has zero interaction with the >=900px grid block below.
   `.service-areas-content` becomes a column flex container only in
   this range (plain block by default below 900px otherwise, and grid
   at >=900px via the existing rule, both completely untouched);
   `.service-areas-map` gets `order: -1` (visually first) while
   `.service-areas-directory` keeps its default `order: 0` (visually
   second). DOM order itself is NOT changed -- directory still precedes
   map in the markup -- so the existing >=900px grid's auto-placement
   (which relies on order-modified DOM order for its implicit column
   1/column 2 placement) is unaffected: neither element has an `order`
   value outside this mobile-only block, so both are tied at order:0
   at desktop and DOM order (directory first) breaks the tie exactly as
   before. Confirmed by re-running the existing desktop geometry probes
   unmodified -- see spec Records round 4c. No copy/schema changes;
   `.reveal` scroll-in animations are IntersectionObserver-driven per
   element's own actual viewport position, so they follow the new
   visual order automatically, no JS changes needed either. */
@media (max-width: 899px) {
  .service-areas-content { display: flex; flex-direction: column; }
  .service-areas-map { order: -1; }
}

/* Round 2 (2026-09-09, codex desktop alignment unification, spec
   2026-09-09-suburbs-and-process-image.md Round 2): replaces round 1c/
   1d's side-by-side intro-left/content-right split (which itself
   replaced a ragged auto-fit grid) with the shared system all three
   sections now use -- a FULL-WIDTH intro above a 528/64/528 content
   grid below it. `.service-areas-layout` goes back to plain block flow
   (intro full width, content full width below it, margin-top:48px
   doing the intro-to-content gap).

   Round 4 (2026-09-09, Adelaide service-area map): the 528/64/528
   content grid moves DOWN one level -- it now belongs to
   `.service-areas-content` itself (LEFT column = `.service-areas-
   directory`, the region-groups stack + note; RIGHT column =
   `.service-areas-map`, the map graphic -- an inline SVG in round 4,
   swapped for Robin's own raster artwork in round 4b, see that round's
   own note below `.service-map-img`), not to `.service-area-groups`.
   `.service-area-groups` goes back to a SINGLE column (matching its own
   mobile/unconditional shape below -- the old 2-col column-major split,
   3-left/2-right, is gone: with the map now claiming the right half,
   there is no second column left for a second group column to sit in).
   The old header min-height reservation (2.6em at 900-1099px, reset at
   >=1100px) existed only to align PAIRED headers across two group
   columns -- with a single column there is no neighbour to align
   against, so both rules are removed rather than left inert. */
@media (min-width: 900px) {
  .service-areas-layout { display: block; }
  .service-areas-intro .eyebrow { margin: 0 0 16px; }
  .service-areas-intro h2 { width: 100%; max-width: 760px; margin: 0; }
  .service-areas-intro .lede { max-width: 640px; margin: 16px 0 0; }
  /* The system's content grid: 528/64/528 columns, x=160/752 at 1440.
     `.service-areas-directory` (groups+note) and `.service-areas-map`
     are the only two direct children -- CSS Grid's default row-major
     auto-placement puts the first into column 1 and the second into
     column 2 with no explicit grid-column needed on either, since DOM
     order already matches the desired left/right split. */
  .service-areas-content { margin-top: 48px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 64px; align-items: start; }
  /* Single column now (was the 2-col column-major split pre-round-4) --
     row-gap between the 5 stacked groups, tuned for the narrower 528px
     column this now occupies alone. margin-top:0 -- the outer grid's
     own margin-top:48px above already does the intro-to-content gap. */
  .service-area-groups { grid-template-columns: 1fr; row-gap: 1.5rem; margin-top: 0; }
  /* Round 1d, fix 4 "text edges": each suburb list becomes a single
     left-aligned column (was a wrapped flex row) so every name lines up
     under its own region heading instead of ragging out at different
     widths per line. */
  .suburb-chips { display: grid; grid-template-columns: 1fr; gap: 0.25rem; }

  /* Map column: the raster fills its 528px column at its own intrinsic
     aspect ratio (1145:1374, round 4b -- Robin's own artwork, was
     560:660 for round 4's generated SVG) -- width:100% + aspect-ratio
     (not a hardcoded height) means it also scales correctly at the
     fluid 900-1199px widths, not just the 1200px-capped 528px column
     (matches the same fluid-column pattern #process/#onsite-quote/
     #quiz all already use). At the capped 528px column this renders
     ~634px tall (528 * 1374/1145), inside the ~620-660px band originally
     asked for, with zero extra CSS needed to enforce it. Visual call
     (unchanged from round 4, still applies to the raster): radius +
     shadow, no visible border, no padding -- SAME treatment as
     `.onsite-quote-frame` and `.process-dashboard` (this site's
     existing pattern for framed illustrative content), not the
     white-card-with-padding treatment `#quizBox`/`.pack` use for
     interactive elements. The artwork has its own light background per
     the coordinator, so a second white card behind it would double-
     frame; borderless-but-shadowed reads as one cohesive graphic
     instead. margin-top:0 -- the mobile-only gap-below-directory margin
     (unconditional rule above) is replaced by the grid's own
     column-gap once the map sits beside the directory instead of below
     it. */
  .service-map-img { margin-top: 0; }
}
