
/* BEGIN GENERATED cases section CSS — tools/build-cases.py — do not edit */

      /* Layout-stable tab strip + panel stage (2026-09-10, owner brief). Measured defect: inactive panels were
         display:none, so the wrapper was as tall as the ACTIVE panel and the section below moved on every switch;
         the active tab gained font-weight, so the strip reflowed by a pixel; the swap keyframe translated the panel.
         Fix: every panel occupies the same grid cell (the stage is always the tallest panel at the current
         viewport — pure layout, re-evaluated on resize, font load and media load); inactive panels stay in layout
         as visibility:hidden (not painted, not focusable, not in the accessibility tree); every tab keeps one
         weight, one padding and a reserved 2px underline in every state; the strip's hairline is an inset shadow
         so no negative margin is needed; no animation, no transform, no measured heights. */
      .cases-tabs { margin-bottom: 28px; border-bottom: 0; box-shadow: inset 0 -1px 0 var(--line-soft); }
      .cases-tab { margin: 0; border-bottom: 2px solid transparent; font-weight: 500; }
      .cases-tab:hover, .cases-tab:focus-visible { color: var(--muted); }
      .cases-tab[aria-selected="true"] { color: var(--text); border-bottom-color: var(--mineral); font-weight: 500; }
      .cases-tab:focus-visible { outline: 2px solid var(--focus-ring, var(--mineral)); outline-offset: -3px; border-radius: 6px; }
      .cases-panels { display: grid; grid-template-columns: minmax(0, 1fr); }
      .cases-panel { display: block; grid-area: 1 / 1; min-width: 0; visibility: hidden; }
      .cases-panel[data-active="true"] { display: block; visibility: visible; animation: none; }
      /* Selected-scenario heading (2026-09-10, owner brief): one type step below the section heading, medium weight,
         softer ink, compact measure; the title and its context sentence read as one unit, then a larger gap. */
      .cases-panel-head { max-width: 62em; margin-bottom: 32px; }
      .cases-panel-head h3 { font-size: clamp(19px,1.7vw,24px); line-height:1.25; letter-spacing:-.012em; font-weight:500; color:var(--text-mute, var(--text)); margin:0 0 8px; max-width: 36ch; }
      .cases-panel-head p { margin: 0; }
      .cases-card-quiet { background:transparent; border-color:rgba(230,224,210,.055); }
      /* Milestone path (2026-09-08, owner brief): the timeline was a two-column table with a
         horizontal rule above every row. It is now a vertical dot-and-rail path. The pages still
         carry the legacy .cases-tl rules in their own head styles; this region is written last, so
         these override them — the two-column grid and every border-top are explicitly reset here
         rather than left to chance. No nth-child, no !important, no negative margins. */
      .cases-tl { list-style:none; margin:0; padding:0; display:grid; gap:0; }
      .cases-tl li { position:relative; display:grid; grid-template-columns:24px minmax(0,1fr); column-gap:14px; align-items:start; padding:0 0 22px; border-top:0; }
      .cases-tl li:last-child { padding-bottom:0; }
      .cases-tl-mark { position:relative; z-index:1; width:24px; height:24px; border:1px solid var(--line-strong); border-radius:999px; background:var(--surface); display:grid; place-items:center; }
      .cases-tl-mark::before { content:""; width:7px; height:7px; border-radius:50%; background:var(--mineral); }
      .cases-tl li:not(:last-child) .cases-tl-mark::after { content:""; position:absolute; top:24px; left:50%; transform:translateX(-50%); width:1px; height:calc(100% + 22px); background:var(--line); }
      .cases-tl b { display:block; margin:3px 0 5px; font-family:var(--mono,'JetBrains Mono',monospace); font-size:10.5px; letter-spacing:.13em; text-transform:uppercase; font-weight:500; color:var(--muted); }
      .cases-tl span { display:block; font-size:14px; line-height:1.5; color:var(--text); }
      /* RouteTimelineMediaPanel (2026-09-08, owner brief). NB the panel element is a DIV, not a
         sectioning element: many regions in this repo are matched by a non-greedy regex that ends at
         the first closing sectioning tag, and nesting one here made build-referral-panel.py silently
         truncate four of the five panels on ae/setup-estimate.html. This comment deliberately spells
         out no tag names — an earlier version of it did, and the literal text was counted as real
         markup by the very balance checks it was describing.
         The timeline sits INSIDE a contained
         panel over a route-specific photograph, not bare on the page ground. One <img> (never a CSS
         background), one veil, then the rail above both. Focal points and the image come from
         cases.json media[<route id>] — no nth-child, no per-page mapping, no path in CSS. */
      .cases-media { position:relative; isolation:isolate; overflow:hidden; min-height:360px; border:1px solid var(--line); border-radius:16px; background:var(--surface-tinted); display:flex; }
      .cases-media-img { position:absolute; inset:0; z-index:0; width:100%; height:100%; object-fit:cover; object-position:var(--cases-media-pos, center center); }
      .cases-media-veil { position:absolute; inset:0; z-index:1; background:linear-gradient(90deg, rgba(18,20,19,.86) 0%, rgba(18,20,19,.72) 52%, rgba(18,20,19,.34) 100%); }
      .cases-media .cases-tl { position:relative; z-index:2; width:100%; align-content:center; padding:28px 30px; }
      .cases-media .cases-tl-mark { border-color:rgba(255,255,255,.62); background:rgba(18,20,19,.55); }
      .cases-media .cases-tl-mark::before { background:#F5F2EA; }
      .cases-media .cases-tl li:not(:last-child) .cases-tl-mark::after { background:rgba(255,255,255,.42); }
      .cases-media .cases-tl b { color:rgba(255,255,255,.76); }
      .cases-media .cases-tl span { color:#FFFFFF; }
      @media (max-width: 900px) { .cases-media { min-height:300px; } .cases-media-img { object-position:var(--cases-media-pos-mobile, var(--cases-media-pos, center center)); } }
      .cases-card-quiet .cases-tl span { color:var(--muted); }
      /* Text-led timeline card — the DEFAULT (2026-09-09, owner rule). In factual route-selection,
         comparison, eligibility, cost and operational contexts the photograph competed with the
         milestone timeline, so pages[page].timelineMedia "none" renders the rail inside the same
         .cases-card shell as the route-fact card on the left: same border, radius, surface and
         padding, dark text, no image, no veil, no minimum height — the panel is as tall as its
         milestones. The image panel above stays available as the opt-in "image" variant. The pair
         top-aligns so neither card is stretched to the other's height. */
      .cases-panel-grid { align-items:start; }
      .cases-card--timeline .cases-tl span { color:var(--text); }
/* END GENERATED cases section CSS */
      