/* ============================================
   custom.css — BPS Fiber
   Project-specific styles. Do NOT edit template CSS directly.
   Load order: template libs -> mainstyle.css -> brand.css -> custom.css

   The block below is the design comps' own global stylesheet, lifted verbatim
   from BPS Fiber Homepage.dc.html <style> (lines 18-52). It carries the grid
   helpers the lifted markup depends on (.r2 .r3 .r4 .rfoot .cmp .ticket), the
   Leaflet skin, the bpsPulse keyframe, and the responsive breakpoints.

   NOTE: the h1/h2/h3 !important rules at the bottom override brand.css's
   mobile type scale by design — the comps' inline font sizes are the visual
   source of truth, brand.css tokens govern anything we author from scratch.
   ============================================ */

/* ---------- lifted verbatim from the design comps ---------- */
*{box-sizing:border-box;}
body{margin:0;font-family:Poppins,system-ui,sans-serif;color:#222222;background:#ffffff;-webkit-font-smoothing:antialiased;}
html{scroll-padding-top:80px;}
a{color:inherit;}
input::placeholder{color:#9aa3ad;}
.bps-tip{background:#003268;color:#fff;border:none;border-radius:7px;font:600 12px Poppins,sans-serif;padding:3px 9px;box-shadow:0 3px 8px rgba(0,0,0,.28);}
.bps-tip.leaflet-tooltip-top:before{border-top-color:#003268;}
.bps-divicon{background:transparent !important;border:0 !important;}
.leaflet-container{font-family:Poppins,sans-serif;background:#eef2f6;}
@keyframes bpsPulse{0%{transform:scale(1);opacity:.55;}70%{transform:scale(2.6);opacity:0;}100%{opacity:0;}}
/* ---------- responsive ---------- */
.hdr-burger{display:none;}
@media (min-width:861px){.hdr-menu{display:none !important;}}
@media (max-width:980px){
  .r4{grid-template-columns:repeat(2,1fr) !important;}
}
@media (max-width:860px){
  .hdr-nav,.hdr-phone{display:none !important;}
  .hdr-burger{display:flex !important;}
  .hdr-cta{margin-left:auto !important;}
}
@media (max-width:760px){
  .r2,.r3{grid-template-columns:1fr !important;}
  .rfoot{grid-template-columns:repeat(2,1fr) !important;}
}
@media (max-width:560px){
  .r4,.rfoot{grid-template-columns:1fr !important;}
  .cmp{overflow-x:auto !important;-webkit-overflow-scrolling:touch;}
  .cmp>div{min-width:520px;}
  .ticket{flex-direction:column !important;}
  .ticket>div[style*="width:2px"]{display:none !important;}
  h1{font-size:32px !important;}
  h2{font-size:25px !important;}
  h3{font-size:23px !important;}
}

/* ============================================
   PAGE-SCOPED RESPONSIVE — Batch B pages (ARN Task 04)

   Each design comp carries its own <style> block. The universal parts
   (*, body, html, a, ::placeholder) are already above — lifted from the
   homepage comp and identical across all of them. What was NOT above are
   the per-page grid-collapse rules, keyed to page-specific class names.
   Without these the two-column bands never collapse and the pages are
   broken on phones, so they are lifted here verbatim.

   Class names are unique per page (rh-/ri-/rp-/bh-/bi-/bp-), so there is
   zero collision risk in one shared file.
   ============================================ */

/* Residential.dc.html */
@media (max-width:900px){.rh-hero{grid-template-columns:1fr !important;}.rh-two{grid-template-columns:1fr !important;}}
/* Residential Internet.dc.html */
/* P03 customer note (2) - Clay 2026-08-11: the plan grid is 3-col or 1-col ONLY. Three
   cards in two columns always orphan one, so the 2-col step is RETIRED and the single-
   column breakpoint moves UP to 1040px, covering the 900-1040 band the old rule existed
   to protect. On collapse the featured (dark) card sorts first via order:-1.
   DESKTOP ORDER IS UNCHANGED - Clay ruled explicitly: no desktop reorder.
   NOTE: rev-2 DOES ship this 1040px 2-col rule (residential-internet.html:30), so
   retiring it is a DELIBERATE deviation on Clay's instruction, not drift. Do not
   'restore' it from a later comp diff. */
@media (max-width:1040px){.ri-plans{grid-template-columns:1fr !important;}.ri-plans .ri-card.is-feat{order:-1;}}
@media (max-width:900px){.ri-hero{grid-template-columns:1fr !important;}.ri-plans{grid-template-columns:1fr !important;}.ri-shield{grid-template-columns:1fr !important;}.ri-serve{grid-template-columns:1fr !important;}}
/* Residential Phone.dc.html */
@media (max-width:900px){.rp-hero{grid-template-columns:1fr !important;}.rp-two{grid-template-columns:1fr !important;}}
/* Business.dc.html */
@media (max-width:900px){.bh-hero{grid-template-columns:1fr !important;}.bh-two{grid-template-columns:1fr !important;}}
/* Business Internet.dc.html */
@media (max-width:900px){.bi-hero{grid-template-columns:1fr !important;}.bi-two{grid-template-columns:1fr !important;}.bi-use{grid-template-columns:repeat(2,1fr) !important;}}
@media (max-width:520px){.bi-use{grid-template-columns:1fr !important;}}
/* Business Phone.dc.html */
@media (max-width:900px){.bp-hero{grid-template-columns:1fr !important;}.bp-two{grid-template-columns:1fr !important;}}

/* Heading step-down. The comps fire this at 620px; the block already above
   fires at 560px. Both are kept — 620 catches the tablet-to-phone gap.
   HARMONIZED, not lifted: the six comps disagree by 1px (h1 31-32, h2 24-26).
   Taking the homepage values (32/25) so headings are consistent sitewide. */
@media (max-width:620px){
  h1{font-size:32px !important;}
  h2{font-size:25px !important;}
}

/* Residential Internet's comp adds textarea to the placeholder rule. */
textarea::placeholder{color:#9aa3ad;}

/* ============================================
   PAGE-SCOPED RESPONSIVE — Batch C pages (ARN Task 04)
   Same rationale as the Batch B block above: lifted verbatim from each comp's
   own <style>. Class names are unique per page, so no collision.
   ============================================ */

/* For Subscribers.dc.html */
@media (max-width:900px){.fs-three{grid-template-columns:1fr !important;}}
/* Your Account.dc.html */
@media (max-width:900px){.ya-app{grid-template-columns:1fr !important;}.ya-two{grid-template-columns:1fr !important;}}
/* Technical Support.dc.html */
@media (max-width:900px){.ts-contact{grid-template-columns:1fr !important;}.ts-two{grid-template-columns:1fr !important;}}
/* About Us.dc.html */
@media (max-width:900px){.ab-hero{grid-template-columns:1fr !important;}.ab-two{grid-template-columns:1fr !important;}.ab-links{grid-template-columns:1fr !important;}}
/* Contact Us.dc.html */
@media (max-width:900px){.ct-grid{grid-template-columns:1fr !important;}}
/* Our History.dc.html */
@media (max-width:900px){.oh-hero{grid-template-columns:1fr !important;}.oh-time{grid-template-columns:1fr !important;}}
/* News.dc.html */
@media (max-width:900px){.nw-feature{grid-template-columns:1fr !important;}.nw-cards{grid-template-columns:1fr !important;}}
@media (max-width:900px){.tw-two{grid-template-columns:1fr !important;}}

/* Legal trio (AUP / Privacy / Terms) — SCOPED, not global.
   Those three comps override the base a{color:inherit} with real link colours,
   because their bodies are dense prose where links must be visible. Applying
   that rule as written would recolour every link sitewide, so the lift is
   scoped to <main class="legal-page"> instead.
   DEVIATION from verbatim (ARN Task 20A-F, 2026-07-29 - WCAG 1.4.1 Use of Color):
   the comps ship text-decoration:none. Measured, #0275d8 is 4.63:1 on white (AA
   pass) but only 2.10:1 against the surrounding #444 prose - under the 3:1 that
   would let colour serve as the sole cue - so links in dense legal prose were
   distinguishable by colour alone. Underline is now the default, and
   :focus-visible is styled because the comps offered :hover only, which is
   unreachable by keyboard. Colour VALUES are unchanged. */
.legal-page a{color:#0275d8;text-decoration:underline;text-underline-offset:2px;}
.legal-page a:hover{color:#003268;text-decoration:underline;}
.legal-page a:focus-visible{color:#003268;text-decoration:underline;outline:2px solid #0275d8;outline-offset:2px;}

/* NOTE on the 620px heading step-down (block above, set in Batch B):
   Batch C comps ask for h2 22-23px where the sitewide harmonized value is 25px.
   Keeping 25px so headings stay consistent across all 18 pages — a deliberate
   2-3px deviation from those comps, documented rather than silent. */


/* ============================================
   SITE HEADER — lifted verbatim from Site Header.dc.html <style> (lines 15-38).
   The header markup depends on these: .sh-item hover dropdowns, the gold
   underline sweep, the ribbon link colours, and the 960px nav/burger swap.
   ARN Task 05.
   ============================================ */
.sh-item{position:relative;}
.sh-item>a{position:relative;}
.sh-item>a::after{content:"";position:absolute;left:12px;right:12px;bottom:3px;height:2px;background:#FFCC16;border-radius:2px;transform:scaleX(0);transform-origin:left;transition:transform .18s;}
.sh-item:hover>a::after{transform:scaleX(1);}
.sh-drop a{position:relative;}
.sh-drop a::after{content:"";position:absolute;left:14px;right:14px;bottom:6px;height:2px;background:#FFCC16;border-radius:2px;transform:scaleX(0);transform-origin:left;transition:transform .18s;}
.sh-drop a:hover::after{transform:scaleX(1);}
.sh-item>.sh-drop{display:none;position:absolute;top:100%;left:-14px;padding-top:14px;z-index:70;}
.sh-item:hover>.sh-drop{display:block;}
.sh-item:hover>a .sh-car{transform:rotate(180deg);}
.sh-burger{display:none;}
.sh-rib-a{color:#cdd9e8;text-decoration:none;}
.sh-rib-a:hover{color:#FFCC16;}
.sh-rib-sales{color:#ffffff;}
.sh-rib-sales:hover{color:#FFCC16;}
@media (min-width:961px){.sh-mobile{display:none !important;}}
@media (max-width:960px){
  .sh-nav{display:none !important;}
  .sh-burger{display:flex !important;}
  .sh-cta{margin-left:auto !important;}
}
@media (max-width:760px){.sh-rib-locale{display:none !important;}}
@media (max-width:540px){.sh-rib-inner{justify-content:center !important;}.sh-rib-row{margin-left:0 !important;gap:12px !important;}}
/* Overrides the 80px value set in the comps' global block above: the real
   sticky header (ribbon + bar) is taller, so anchor targets need more offset.
   Verbatim from the header comp, which carries the !important itself. */
html{scroll-padding-top:104px !important;}
/* 3R-5-f5 (2026-08-08): breakpoint-matched to the MEASURED header height.
   The header is position:sticky (3R-5-f4), so an anchor jump must clear its
   real height -- and that height is NOT monotonic in viewport width, because
   the 540px ribbon rule above re-centers the row and shaves 8px off it.
   Measured live, same-origin iframe harness, wrap points pinned to the pixel
   and identical on /, /about/, /support/, /fiber-internet-plans/, /contact/:
       >=838px  header 102 -> 104  (unchanged, 2px clear)
     581-837px  header 138 -> 140
     541-580px  header 174 -> 176  <- WORST CASE, taller than at 375px
     337-540px  header 166 -> 168
       <=336px  header 186 -> 188
   Convention is header height + 2px, matching the desktop value already here.
   WARNING: these wrap points are a function of the RIBBON CONTENT. If the
   phone number, hours or utility links change length, RE-MEASURE -- do not
   assume these numbers survive a copy edit. */
@media (max-width:837px){html{scroll-padding-top:140px !important;}}
@media (max-width:580px){html{scroll-padding-top:176px !important;}}
@media (max-width:540px){html{scroll-padding-top:168px !important;}}
@media (max-width:336px){html{scroll-padding-top:188px !important;}}

/* Keyboard/touch parity for the hover dropdowns: :hover alone leaves them
   unreachable by keyboard. Same display rule, driven by focus-within. */
.sh-item:focus-within>.sh-drop{display:block;}
.sh-item:focus-within>a .sh-car{transform:rotate(180deg);}

/* ============================================
   Testimonials mobile -- NO RULE IS NEEDED HERE, and that is the point.

   History, so that nobody re-adds a fix: 07F (2026-07-28) neutralised the lead
   card span; 3R-5-f1 (2026-08-10) proved the rev-2 comp renders that span
   deliberately and restored it with two explicit tracks. Clay then re-specified
   the band at 3R-5-f7 (2026-08-10): SIX equal cards, two rows of three, with no
   full-width lead card and no span at all. With no span there is no implicit
   column, so the sitewide max-width:760px rule collapses the band to one column
   unaided, exactly like every other .r3 on the site.
   DO NOT re-introduce a #testimonials grid override without re-measuring first.
   ============================================ */


/* ── Task 07G — dark-band heading inheritance ──────────────────────────────
   brand.css sets `h1..h6 { color: var(--brand-primary) }` (navy). That is a
   DIRECT rule on the heading, so it beats the `color:#fff` that a navy
   <section> passes down by INHERITANCE — inherited values lose to any
   matching rule regardless of the ancestor's specificity. Result: navy
   headings on navy bands, i.e. invisible. Every interior page hero is
   `<section style="background:#003268;color:#fff;">` with an <h1> carrying
   no color of its own, so all 17 were affected.
   `color:inherit` hands control back to the band. Scoped to sections that
   explicitly declare a light text colour, so light-background bands keep
   brand.css's navy. Matches `color:#fff` and `color:#ffffff` (substring),
   with and without a space after the colon. */
section[style*="color:#fff"]  :is(h1,h2,h3,h4,h5,h6),
section[style*="color: #fff"] :is(h1,h2,h3,h4,h5,h6) { color: inherit; }


/* -- Task 07H (2026-07-28) -- service-area map painting over the sticky header.
   header.php is position:sticky with z-index:60 (it was position:fixed with a
   hardcoded spacer div until ARN 3R-5-f4, 2026-08-07; the switch to sticky removed
   the spacer and this stacking reasoning is UNCHANGED by it - a sticky element with
   a z-index still creates a stacking context, and 60 still beats #map's 0). The map wrapper in index.php is
   position:relative with NO z-index, so it never creates a stacking context and
   Leaflet's own z-indexes compete directly with the header in the root context:
   .leaflet-pane 400, controls 800, .leaflet-top/.leaflet-bottom 1000 -- all > 60.
   Giving the band `position:relative;z-index:0` creates a stacking context, so every
   Leaflet layer is confined inside it and the whole band sits under the header.
   Scoped to #map only, so the Task 31 iframe swap stays a single block and no
   lifted markup is touched. */
#map { position: relative; z-index: 0; }

/* ...and the SAME containment on the map ELEMENT, not just the homepage's band
   (Clay 2026-08-11: the Leaflet map drew over the sticky nav on scroll).
   WHY IT CAME BACK: the fix above is keyed to #map, which is the HOMEPAGE band's id.
   #bps-leaflet is what actually travels - fiber-internet-plans.php now hosts the same
   map in a section with no id, so Leaflet's control z-indexes (1000) competed with the
   header's 60 in the ROOT stacking context and won. Containing #bps-leaflet itself
   fixes every page that ever hosts the map, including any future one, and is harmless
   on the homepage where it nests inside an already-contained band.
   Per the rule above: do NOT raise a z-index to win. */
#bps-leaflet { position: relative; z-index: 0; }
/* == ARN 3R-Z (2026-08-06) == THE STACKING INVARIANT: nothing renders above the
   sticky header, anywhere on this site. Clay, 2026-08-06: "nothing should go over
   the sticky menu it should always be on top."

   THE RESERVED SCALE -- measured across every stylesheet and every page file, not
   assumed. These are the ONLY stacking values on the site:

     0      #map, and any band hosting third-party UI (see THE RULE below)
     <= 9   ordinary page content. mainstyle.css .cc-media is the only user.
     60     the sticky header itself. NOTE: declared INLINE at header.php:107, not
            here, so a CSS-only reader cannot see it -- which is why it is written
            down in this block.
     70     .sh-item > .sh-drop, the header's own dropdown (custom.css:150). This is
            ABOVE 60 and is CORRECT: it is a descendant INSIDE the header's own
            stacking context, so it never competes with the header in the root
            context. Do not "fix" it -- lowering it would break the dropdown.

   THE RULE FOR ALL NEW WORK -- do NOT raise a z-index to win. You cannot win that
   race: a third party can always pick a bigger number, and Leaflet ships 400 / 800
   / 1000. Instead give the HOST BAND its own stacking context with
   `position:relative; z-index:0`. Every descendant is then confined beneath the
   header no matter what values it declares. That is exactly what the #map rule
   above does, and it is why the Leaflet panes stopped painting over the menu.

   CHECK THIS BEFORE SHIPPING any absolutely- or fixed-positioned overlay:
     - Task 31's OpenStreetMap embed (contact page)
     - Task 31's bill-pay iframe (pay-your-bill)
     - the customer's service-area iframe -- swaps into #map, so it INHERITS the
       clamp above and needs nothing extra
     - any modal, lightbox, drawer, toast or sticky CTA added later
   A regression here surfaces in the 3R-5 visual sweep, where it reads as a design
   defect rather than a stacking one -- which is what makes it expensive to find. */
