/* ==========================================================================
   CORINTH GAS & WATER — COMPONENTS
   Loaded LAST, so it wins over Bootstrap and the legacy rules in style.css.

   Everything here targets markup that is ALREADY on the pages — list-group,
   breadcrumb, card, btn, link-darkblue — so all 35 pages pick up the new look
   without a single HTML edit. Colours come from tokens.css only.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0a. WATER SURFACE — header & footer background
   --------------------------------------------------------------------------
   Replaces underwater_classic_1150w.jpg entirely. No photo, no request, no
   "which shade of teal is this JPEG" problem ever again — every tone comes
   from the same brand tokens as the rest of the site, so a palette change
   updates this automatically instead of needing a re-export.

   Built from the water photo's own logic, not a flat fill:
     - a bright "sunlight" highlight, off-centre near the top — the thing a
       real photo of shallow water has that a plain gradient doesn't
     - two soft caustic blooms — the dappled light patterns water throws
     - a diagonal depth ombre underneath, light corner to dark corner
     - a very faint repeating ripple texture, animated on a slow drift

   Header reads as sunlit, near-surface water (bright + mid tones — the same
   role "background-position: top" played on the old photo). Footer reads as
   deep water (primary + deep + ink — the role "background-position: bottom"
   played): same recipe, shifted down the brand ramp, so the two still read
   as one continuous body of water rather than two unrelated panels.
   -------------------------------------------------------------------------- */
#nav-container,
#footer-container {
  position: relative;
  isolation: isolate;
  background-color: var(--brand-deep);
}

/* #footer-container has nothing below it that needs to escape its box, so it
   clips its own water effect directly. #nav-container can't do the same —
   the nav dropdowns (ABOUT US, CUSTOMER SERVICE, FAQS) are descendants of
   #nav-container and must be able to extend below the header. So the water
   effect for the header lives on its own .nav-water-bg layer, which clips
   itself, while #nav-container stays unclipped. See z-index note below for
   the other half of this fix. */
#footer-container {
  overflow: hidden;
}

.nav-water-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: -1;
  pointer-events: none;
}

/* #page-content > .container (below) also gets position:relative on every
   interior page, and with both boxes at the implicit z-index:auto layer,
   plain DOM order would decide the winner — #page-content comes second in
   the markup and would paint over the header, burying open dropdown menus
   behind the page content instead of on top of it. An explicit z-index here
   moves the whole header (and anything inside it) to a higher paint layer
   regardless of source order. */
#nav-container {
  z-index: 2;
}

.nav-water-bg::before,
#footer-container::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
}

.nav-water-bg::before {
  background:
    radial-gradient(60% 130% at 18% -20%, color-mix(in srgb, var(--brand-bright) 65%, white) 0%, transparent 58%),
    radial-gradient(42% 70% at 82% 115%, var(--brand-mid) 0%, transparent 62%),
    radial-gradient(30% 55% at 55% 40%, color-mix(in srgb, var(--brand-bright) 40%, transparent) 0%, transparent 70%),
    linear-gradient(128deg, var(--brand-mid) 0%, var(--brand-primary) 48%, var(--brand-deep) 100%);
}

#footer-container::before {
  background:
    radial-gradient(50% 90% at 80% -25%, color-mix(in srgb, var(--brand-mid) 55%, transparent) 0%, transparent 60%),
    radial-gradient(38% 60% at 15% 120%, color-mix(in srgb, var(--brand-primary) 45%, transparent) 0%, transparent 62%),
    linear-gradient(150deg, var(--brand-primary) 0%, var(--brand-deep) 55%, var(--brand-ink) 100%);
}

/* Ripple texture: a repeating diagonal band pair, low opacity, drifting very
   slowly. Reads as light refracting through moving water rather than a
   static pattern — the one place motion earns its keep here. */
.nav-water-bg::after,
#footer-container::after {
  content: "";
  position: absolute;
  inset: -20% -10%;
  z-index: -1;
  background-image: repeating-linear-gradient(115deg,
    rgba(255, 255, 255, 0.10) 0px,
    rgba(255, 255, 255, 0.10) 2px,
    transparent 2px,
    transparent 34px,
    rgba(255, 255, 255, 0.05) 34px,
    rgba(255, 255, 255, 0.05) 36px,
    transparent 36px,
    transparent 74px);
  opacity: 0.55;
  animation: cgw-water-drift 26s linear infinite;
}

#footer-container::after { opacity: 0.32; animation-duration: 34s; animation-direction: reverse; }

@keyframes cgw-water-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-74px, 30px, 0); }
}

/* A hairline of "surface light" along the very top of the header — the water
   line, brighter than anything below it. */
#nav-container {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35);
}

/* --------------------------------------------------------------------------
   0c. SILVER STRIPE — sitewide chrome signature
   --------------------------------------------------------------------------
   A brushed-metal band between the dark info bar and the main nav row, on
   every page. Three thin passes of light at different angles (not one flat
   highlight) is what reads as "brushed metal" rather than "a stripe" — a
   single gradient line looks painted, three overlapping ones look machined.
   -------------------------------------------------------------------------- */
#nav-container > .bg-nav-darker {
  position: relative;
}
#nav-container > .bg-nav-darker::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 3px;
  background:
    linear-gradient(90deg, transparent 0%, var(--metal-light) 18%, transparent 32%),
    linear-gradient(90deg, transparent 45%, #fff 58%, transparent 66%),
    linear-gradient(90deg, transparent 78%, var(--metal-light) 90%, transparent 100%),
    linear-gradient(90deg, var(--metal-dark), var(--metal), var(--metal-dark));
  opacity: 0.9;
}

@media (prefers-reduced-motion: reduce) {
  .nav-water-bg::after,
  #footer-container::after { animation: none; }
}

/* --------------------------------------------------------------------------
   0b. FACEBOOK BADGE — chrome sphere
   --------------------------------------------------------------------------
   A flat disc reads as a coloured circle no matter how good the bevel is —
   a sphere needs to shade RADIALLY in every direction from one light source,
   not diagonally like a flat panel. That's the whole difference from the
   first pass: the base fill is now a radial gradient centred near the light,
   plus a tight specular hotspot (the "glint" a photographed ball has), plus
   a dim bounce-light near the bottom edge (ambient light reflecting back up
   off whatever surface the sphere is sitting on). Three cues most flat-metal
   CSS skips, and together they're what actually sells "3D" over "shiny".

   The glyph is embossed rather than just drop-shadowed: filter: drop-shadow
   traces the mask's own alpha shape, so a light offset one way and a dark
   offset the other reads as the glyph stamped INTO the metal, not floating
   on top of it.

   Hover adds real 3D rotation via perspective() in the transform itself — no
   parent perspective context needed for a single flat plane — so the badge
   genuinely turns in space rather than just lifting and glowing.

   Base is Facebook's own blue, so the badge stays instantly recognisable
   rather than being recoloured into the site palette and losing its job.
   -------------------------------------------------------------------------- */
.fb-badge {
  --btn-base: #1877F2;
  --btn-lit: color-mix(in srgb, var(--btn-base) 45%, #FFFFFF);
  --btn-shade: color-mix(in srgb, var(--btn-base) 40%, #000000);
  --btn-deep: color-mix(in srgb, var(--btn-base) 62%, #000000);

  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;

  width: 40px;
  height: 40px;
  border-radius: 50%;
  line-height: 0;
  text-decoration: none;

  border: 1px solid rgba(255, 255, 255, 0.22);

  /* Painter's order, top to bottom: tight specular glint, broad hemisphere
     light, dim ambient bounce near the bottom rim, then the sphere's own
     radial base-to-shade fill. */
  background:
    radial-gradient(circle at 32% 24%, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.55) 5%, transparent 17%),
    radial-gradient(120% 130% at 28% 8%, var(--btn-lit) 0%, transparent 52%),
    radial-gradient(85% 55% at 68% 108%, color-mix(in srgb, var(--btn-lit) 55%, transparent) 0%, transparent 60%),
    radial-gradient(130% 130% at 34% 28%, var(--btn-base) 0%, var(--btn-shade) 72%, var(--btn-deep) 100%);

  box-shadow:
    inset 0 2px 2px rgba(255, 255, 255, 0.50),
    inset 0 -4px 6px rgba(0, 0, 0, 0.50),
    inset 0 0 0 1px rgba(255, 255, 255, 0.16),
    0 2px 3px rgba(4, 22, 50, 0.45),
    0 10px 20px rgba(4, 22, 50, 0.38);

  transform-style: preserve-3d;
  transition: transform 420ms var(--ease-spring),
              box-shadow var(--dur) var(--ease-out);
}

/* Position for the desktop top bar, which places it absolutely at the left. */
.fb-badge.topbar-fb {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
}

.fb-badge__glyph {
  width: 20px;
  height: 20px;
  background-color: #FFFFFF;
  -webkit-mask: var(--icon-facebook) center / contain no-repeat;
  mask: var(--icon-facebook) center / contain no-repeat;

  /* Emboss: a light rim on the side facing the light source, a dark rim on
     the opposite side. Both trace the glyph's own silhouette because
     drop-shadow follows alpha, not the element's box. */
  filter:
    drop-shadow(-0.5px -0.5px 0.4px rgba(255, 255, 255, 0.85))
    drop-shadow(1px 1.5px 1px rgba(0, 0, 0, 0.55));

  transition: transform 420ms var(--ease-spring);
}

/* Specular sweep, same as the buttons. */
.fb-badge::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(105deg,
    transparent 30%,
    rgba(255, 255, 255, 0.25) 45%,
    rgba(255, 255, 255, 0.48) 50%,
    rgba(255, 255, 255, 0.25) 55%,
    transparent 70%);
  transform: translateX(-125%);
  transition: transform 700ms var(--ease-out);
  pointer-events: none;
}

/* Real 3D tilt: perspective() lives inside the transform itself, so this
   single flat layer can rotate in space without needing a `perspective`
   property on its parent. Fixed angles rather than pointer-tracked — cheap,
   dependable, and it still reads as the sphere catching the light as it
   turns, which is the effect that was asked for. */
.fb-badge:hover,
.fb-badge:focus-visible {
  transform: perspective(400px) translateY(-3px) rotateX(-14deg) rotateY(16deg) scale(1.08);
  box-shadow:
    inset 0 2px 2px rgba(255, 255, 255, 0.62),
    inset 0 -4px 6px rgba(0, 0, 0, 0.46),
    inset 0 0 0 1px rgba(255, 255, 255, 0.24),
    0 6px 10px rgba(4, 22, 50, 0.48),
    0 18px 32px rgba(4, 22, 50, 0.44);
}

/* The top-bar copy is already translated on Y to centre it, so its hover has
   to keep that translate or the badge jumps out of alignment. */
.fb-badge.topbar-fb:hover,
.fb-badge.topbar-fb:focus-visible {
  transform: perspective(400px) translateY(calc(-50% - 3px)) rotateX(-14deg) rotateY(16deg) scale(1.1);
}

.fb-badge:hover::after,
.fb-badge:focus-visible::after { transform: translateX(125%); }

/* The glyph counter-rotates a little less than the disc, so it stays legible
   face-on while the metal around it visibly turns — the same trick a coin
   embossment uses to stay readable as the coin tilts. */
.fb-badge:hover .fb-badge__glyph {
  transform: translateZ(6px) scale(1.05);
}

.fb-badge:active {
  transform: perspective(400px) translateY(0) rotateX(-4deg) scale(0.96);
}
.fb-badge.topbar-fb:active {
  transform: perspective(400px) translateY(-50%) rotateX(-4deg) scale(0.96);
}

.fb-badge:focus-visible { outline: 3px solid #FFFFFF; outline-offset: 3px; }

@media (max-width: 991.98px) {
  .fb-badge { width: 38px; height: 38px; }
  .fb-badge__glyph { width: 19px; height: 19px; }
}

@media (prefers-reduced-motion: reduce) {
  .fb-badge::after { display: none; }
  .fb-badge:hover,
  .fb-badge:focus-visible { transform: none; }
  .fb-badge.topbar-fb:hover,
  .fb-badge.topbar-fb:focus-visible { transform: translateY(-50%); }
  .fb-badge:hover .fb-badge__glyph { transform: none; }
}

/* --------------------------------------------------------------------------
   1. PAGE SURFACE
   -------------------------------------------------------------------------- */

/* The old design ran a flat white band edge to edge. Now the page sits on a
   soft tinted ground with the content lifted onto its own surface, which is
   what gives interior pages any sense of depth at all. */
#page-content.bg-white,
#page-content {
  background: var(--page-bg) !important;
  padding-top: var(--space-l) !important;
  padding-bottom: var(--space-2xl) !important;
}

/* The content card. :has() excludes the homepage, which already has its own
   glass panel — without it the two would nest and double the padding. */
#page-content > .container:not(:has(.home-glass-panel)) {
  background: var(--ombre-soft);
  border: 1px solid var(--edge);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-m);
  padding: var(--space-xl) var(--space-l);
  position: relative;
  overflow: hidden;
}

/* Brushed-metal hairline along the top edge — the metallic accent, used once
   per surface so it reads as a finish rather than decoration. */
#page-content > .container:not(:has(.home-glass-panel))::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--ombre-metal);
  opacity: 0.85;
}

#page-content h1, #page-content h2, #page-content h3,
#page-content h4, #page-content h5, #page-content h6 {
  color: var(--heading);
}

#page-content { color: var(--text); }
#page-content p, #page-content li, #page-content dd { color: var(--text-soft); }

/* --------------------------------------------------------------------------
   1b. ARTICLE BODY — long-form paragraph rhythm
   --------------------------------------------------------------------------
   Every plain-text page (About Us, History, FAQs...) was a wall of identical
   paragraphs — same size, same weight, same colour, no entry point, no
   rhythm. Two changes, both CSS-only so they apply to all 23 pages with a
   single edit:

   1. More generous line-height and paragraph spacing — readable prose runs
      1.7-1.8, not the 1.65 used for compact UI text elsewhere on the site.
   2. A "lede" treatment on the first paragraph of the main column — larger,
      darker, slightly heavier. Newspapers and magazines use this to give a
      page an entry point instead of starting flat; it costs one CSS rule and
      needs no markup change since :first-of-type finds it automatically,
      including on pages like About Us where a <blockquote> now comes first.
   -------------------------------------------------------------------------- */
#page-content > .container > .row > div:first-child > p {
  line-height: 1.78;
  margin-bottom: var(--space-l);
}

#page-content > .container > .row > div:first-child > p:first-of-type {
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: 1.5;
  font-weight: 600;
  color: var(--heading);
  letter-spacing: -.005em;
}

/* --------------------------------------------------------------------------
   2. BREADCRUMB
   -------------------------------------------------------------------------- */
#page-content .breadcrumb {
  background: transparent !important;
  border: 0 !important;
  border-bottom: 1px solid var(--edge) !important;
  border-radius: 0 !important;
  padding: 0 0 var(--space-s) 0;
  margin-bottom: var(--space-l);
  font-size: var(--step--1);
  letter-spacing: 0.02em;
}

#page-content .breadcrumb-item a {
  color: var(--link);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}

#page-content .breadcrumb-item a:hover,
#page-content .breadcrumb-item a:focus-visible {
  color: var(--link-hover);
  border-bottom-color: var(--accent-dark);
}

#page-content .breadcrumb-item.active { color: var(--text-mute); }

/* --------------------------------------------------------------------------
   3. LIST GROUPS — the document and link lists (89 of them site-wide)
   --------------------------------------------------------------------------
   These were flat stacked rows. Now each is a card with a hover lift, a
   sliding accent rail, and a chevron that steps forward — so the whole page
   reads as a set of things you can act on, not a wall of blue text. */
#page-content .list-group { gap: var(--space-2xs); display: flex; }

#page-content .list-group-item {
  background: var(--surface);
  border: 1px solid var(--edge) !important;
  border-radius: var(--radius-m) !important;
  box-shadow: var(--shadow-xs);
  padding: var(--space-m) var(--space-m) var(--space-m) calc(var(--space-m) + 6px);
  position: relative;
  overflow: hidden;
  transition: transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out);
}

/* Accent rail, collapsed until hover. */
#page-content .list-group-item::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--ombre-brand);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform var(--dur) var(--ease-out);
}

#page-content .list-group-item-action:hover,
#page-content .list-group-item-action:focus-visible {
  transform: translateY(-2px);
  box-shadow: var(--shadow-m);
  border-color: var(--edge-strong) !important;
  background: var(--surface);
  z-index: 1;
}

#page-content .list-group-item-action:hover::before,
#page-content .list-group-item-action:focus-visible::before {
  transform: scaleY(1);
}

/* Chevron affordance — added in CSS, so no markup changes and it can never
   fall out of sync with the list. */
#page-content .list-group-item-action::after {
  content: "";
  position: absolute;
  right: var(--space-m);
  top: 50%;
  width: 8px; height: 8px;
  border-right: 2px solid var(--brand-mid);
  border-bottom: 2px solid var(--brand-mid);
  transform: translateY(-50%) rotate(-45deg);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out), right var(--dur) var(--ease-out);
}

#page-content .list-group-item-action:hover::after,
#page-content .list-group-item-action:focus-visible::after {
  opacity: 1;
  right: calc(var(--space-m) - 4px);
}

/* --------------------------------------------------------------------------
   4. LINKS
   -------------------------------------------------------------------------- */
#page-content a.link-darkblue,
#page-content .link-darkblue,
#page-content p a:not(.btn):not(.list-group-item):not([href^="tel:"]) {
  color: var(--link) !important;
  font-weight: 500;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, var(--link) 40%, transparent);
  transition: color var(--dur) var(--ease-out), text-decoration-color var(--dur) var(--ease-out);
}

#page-content a.link-darkblue:hover,
#page-content .link-darkblue:hover,
#page-content p a:not(.btn):not(.list-group-item):not([href^="tel:"]):hover {
  color: var(--link-hover) !important;
  text-decoration-color: var(--accent-dark);
}

/* --------------------------------------------------------------------------
   4b. PHONE & FAX
   --------------------------------------------------------------------------
   Every callable number looks the same everywhere on the site: a small phone
   mark, medium weight, brand link colour, and NO underline at rest. The
   underline only appears on hover and keyboard focus.

   Dropping the resting underline means colour can no longer be the only thing
   marking these as links (WCAG 1.4.1). The phone mark is what replaces it — a
   non-colour indicator that reads at a glance and survives greyscale, which an
   underline was doing far more crudely.

   The mark is a mask, not an <img> or a coloured SVG, so it takes its colour
   from currentColor — one rule covers the dark top bar, the light page body
   and the dark footer without a separate override for each.
   -------------------------------------------------------------------------- */
a[href^="tel:"] {
  color: var(--link);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;              /* never split "(662) 286-2263" across lines */
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}

a[href^="tel:"]::before {
  content: "";
  display: inline-block;
  width: 0.82em;
  height: 0.82em;
  margin-right: 0.34em;
  vertical-align: -0.06em;
  background-color: currentColor;
  -webkit-mask: var(--icon-phone) center / contain no-repeat;
  mask: var(--icon-phone) center / contain no-repeat;
}

a[href^="tel:"]:hover,
a[href^="tel:"]:focus-visible {
  color: var(--accent-dark);
  border-bottom-color: currentColor;
}

/* On dark surfaces — the top info bar, the footer — inherit the light text
   colour instead of the dark brand blue, and hover to the bright accent. */
.bg-nav-darker a[href^="tel:"],
.bg-nav a[href^="tel:"],
#footer-container a[href^="tel:"],
.tile-cap-phone[href^="tel:"] {
  color: inherit;
}

.bg-nav-darker a[href^="tel:"]:hover,
.bg-nav-darker a[href^="tel:"]:focus-visible,
.bg-nav a[href^="tel:"]:hover,
.bg-nav a[href^="tel:"]:focus-visible,
#footer-container a[href^="tel:"]:hover,
#footer-container a[href^="tel:"]:focus-visible {
  color: var(--accent);
}

/* E-mail addresses get the same treatment as phones, so the contact block
   reads as one consistent set rather than three different styles.
   The selector is written to outrank `#page-content a.link-darkblue`, which
   many of these carry and which would otherwise put the underline back. */
a[href^="mailto:"],
#page-content a[href^="mailto:"].link-darkblue {
  text-decoration: none;
  font-weight: 500;
  border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}

a[href^="mailto:"]::before {
  content: "";
  display: inline-block;
  width: 0.86em;
  height: 0.86em;
  margin-right: 0.34em;
  vertical-align: -0.08em;
  background-color: currentColor;
  -webkit-mask: var(--icon-mail) center / contain no-repeat;
  mask: var(--icon-mail) center / contain no-repeat;
}

a[href^="mailto:"]:hover,
a[href^="mailto:"]:focus-visible,
#page-content a[href^="mailto:"].link-darkblue:hover,
#page-content a[href^="mailto:"].link-darkblue:focus-visible {
  color: var(--accent-dark) !important;
  text-decoration: none;
  border-bottom-color: currentColor;
}

/* Addresses open turn-by-turn directions from wherever the visitor is
   standing (Google's dir/?api=1 with no origin makes the device supply it),
   so they get the same pin, weight and hover language as phone and e-mail.
   PO boxes are deliberately left as plain text — they aren't destinations. */
.address-link,
#page-content a.address-link,
#page-content a.address-link.link-darkblue {
  color: var(--link);
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}

.address-link::before {
  content: "";
  display: inline-block;
  width: 0.86em;
  height: 0.86em;
  margin-right: 0.32em;
  vertical-align: -0.1em;
  background-color: currentColor;
  -webkit-mask: var(--icon-pin) center / contain no-repeat;
  mask: var(--icon-pin) center / contain no-repeat;
}

.address-link:hover,
.address-link:focus-visible,
#page-content a.address-link:hover,
#page-content a.address-link:focus-visible {
  color: var(--accent-dark) !important;
  border-bottom-color: currentColor;
}

/* In the dark top bar the address inherits the bar's own light colour. */
.bg-nav-darker .address-link,
#footer-container .address-link { color: inherit; }

.bg-nav-darker .address-link:hover,
.bg-nav-darker .address-link:focus-visible,
#footer-container .address-link:hover,
#footer-container .address-link:focus-visible { color: var(--accent) !important; }

/* --------------------------------------------------------------------------
   4c-1. APP CALLOUT — mobile-app panel, shared by home + Pay Bill
   --------------------------------------------------------------------------
   Was defined once, inline, on the homepage only — Pay Bill's version of the
   same pitch ("get the app") was two bare <img> store badges with no frame,
   no hover, no shadow, at the mercy of whatever DPI the source PNG happened
   to be. Same component now, usable anywhere.
   -------------------------------------------------------------------------- */
/* Base is deep-to-ink only (13.8:1 and 16.6:1 against white — both pass AA
   with heavy margin, not a bare pass). No "mid" or "bright" stop anywhere
   text can sit on: the previous version put the LIGHTEST part of the
   gradient exactly where the icon and title render, and translucent text on
   top of that measured 3.9:1 for the eyebrow — a real AA failure, not just a
   look. The bright accent glow here is confined to the far bottom-right
   corner via the radial's size and position, well clear of the content
   column, so it adds shine without ever sitting under a letter. */
.app-callout {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: flex;
  align-items: center;
  gap: 24px;
  text-align: left;
  background:
    radial-gradient(55% 85% at 108% 115%, color-mix(in srgb, var(--brand-bright) 55%, transparent) 0%, transparent 62%),
    linear-gradient(165deg, var(--brand-deep) 0%, var(--brand-ink) 100%);
  border-radius: 16px;
  padding: 32px 34px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), var(--shadow-l);
}
.app-callout::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, transparent, var(--metal-light), var(--brand-bright), var(--metal-light), transparent);
}
/* Gloss sweep confined to the same far corner as the glow, behind the icon
   and text column rather than across the whole panel — decoration should
   never cross the content it would fog. */
.app-callout::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 55%, rgba(255, 255, 255, 0.12) 68%, transparent 82%);
  pointer-events: none;
}
.app-callout__icon {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  width: 68px;
  height: 68px;
  border-radius: 18px;
  background: linear-gradient(160deg, color-mix(in srgb, var(--brand-bright) 30%, transparent), rgba(255, 255, 255, 0.08));
  border: 1px solid rgba(255, 255, 255, 0.32);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), inset 0 -2px 4px rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
}
.app-callout__icon svg { width: 36px; height: 36px; color: #ffffff; }
.app-callout__content { position: relative; z-index: 1; min-width: 0; }

/* Every text tier is SOLID white — hierarchy comes from size, weight and
   letter-spacing, never from opacity, so nothing can quietly slip below AA
   the way a translucent tier did before.

   #page-content-prefixed: these are <p> tags, and the generic
   "#page-content p { color: var(--text-soft) }" rule from the page-surface
   section is an ID selector — it outranks a plain class selector regardless
   of source order, which was silently forcing dark grey-blue text onto a
   dark navy panel (i.e. this bug shipped invisible-on-screenshot the first
   time; only caught because the rendered page was actually inspected). This
   prefix matches that ID's specificity so white wins for real. */
#page-content .app-callout__eyebrow {
  color: #ffffff;
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: .72rem;
  font-weight: 700;
  margin: 0 0 6px;
}
#page-content .app-callout__title {
  font-family: var(--font-display);
  color: #ffffff;
  font-weight: 800;
  font-size: var(--step-1);
  letter-spacing: -.01em;
  line-height: 1.15;
  margin: 0 0 6px;
  text-wrap: balance;
  max-width: none;
}
#page-content .app-callout__text {
  color: #ffffff;
  font-size: var(--step--1);
  margin: 0 0 16px;
  max-width: 46ch;
  text-wrap: pretty;
}

/* Store badges: normal, consistent sizing (44px tall — the source PNGs are
   at wildly different native resolutions, so height-only sizing is what
   keeps them proportional to each other) plus a hover lift and shadow. */
.app-badges { display: flex; flex-wrap: wrap; gap: 12px; }
.app-badge {
  display: inline-block;
  border-radius: 9px;
  overflow: hidden;
  line-height: 0;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
.app-badge img { display: block; height: 44px; width: auto; }
.app-badge:hover, .app-badge:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.38);
}
.app-badge:focus-visible { outline: 2px solid #ffffff; outline-offset: 2px; }

@media (max-width: 575px) {
  .app-callout { flex-direction: column; text-align: center; padding: 28px 22px; }
  .app-callout__text { margin-left: auto; margin-right: auto; }
  .app-badges { justify-content: center; }
}

/* --------------------------------------------------------------------------
   4c-2. NOTICE CALLOUT — amber info panel
   --------------------------------------------------------------------------
   Same metal-panel family as .emergency-callout (radial glint + linear
   ombre + bevel + chrome hairline), base swapped to the accent colour. Red
   means "act now, something's wrong"; amber means "worth knowing" — same
   material, different urgency, so the two read as one system instead of two
   unrelated designs.
   -------------------------------------------------------------------------- */
.notice-callout {
  --btn-base: var(--accent);
  --btn-lit: color-mix(in srgb, var(--btn-base) 55%, #FFFFFF);
  /* Kept to 80% base / 20% black — darker mixes here (as used on the red
     signal panels) look great but fall below AA against the dark text this
     panel needs: #F59E1F only pairs safely with dark text within roughly
     75-100% of itself before a black-mixed "shade" swings through a muddy
     mid-brown that's simultaneously too dark for white text and too close in
     luminance to #2B1A00 for dark text. Verified: this exact mix holds
     5.07:1, comfortably above the 4.5:1 floor, at the darkest point in the
     gradient — not just at its lighter average. */
  --btn-shade: color-mix(in srgb, var(--btn-base) 80%, #000000);

  display: flex;
  align-items: center;
  gap: 16px;
  position: relative;
  overflow: hidden;
  isolation: isolate;

  background:
    radial-gradient(125% 150% at 16% -35%, var(--btn-lit) 0%, transparent 60%),
    linear-gradient(158deg, var(--btn-base) 0%, var(--btn-shade) 100%);
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: var(--radius-m);
  padding: var(--space-m) var(--space-l);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.46),
    inset 0 -1px 0 rgba(0, 0, 0, 0.22),
    0 2px 4px color-mix(in srgb, var(--btn-shade) 35%, transparent),
    0 10px 24px color-mix(in srgb, var(--btn-shade) 30%, transparent);
}
.notice-callout::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--metal-light), transparent);
}
.notice-callout__icon {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.20);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
  color: #2B1A00;
}
.notice-callout__icon svg { width: 22px; height: 22px; }
/* #page-content-prefixed: same specificity trap as .app-callout__* above —
   this is a <p>, and "#page-content p { color: var(--text-soft) }" (an ID
   selector) would otherwise win over a plain class regardless of source
   order or the opacity/colour set here. */
#page-content .notice-callout__eyebrow {
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: var(--step--1);
  font-weight: 700;
  color: #2B1A00;
  margin: 0 0 2px;
  opacity: .82;
}
#page-content .notice-callout__link {
  font-weight: 700;
  font-size: var(--step-0);
  color: #2B1A00;
  text-decoration: underline;
  text-decoration-color: rgba(43, 26, 0, 0.4);
  text-underline-offset: 3px;
}
.notice-callout__link:hover,
.notice-callout__link:focus-visible {
  text-decoration-color: #2B1A00;
}
@media (max-width: 575px) {
  .notice-callout { flex-direction: column; text-align: center; }
}

/* --------------------------------------------------------------------------
   4d. EMERGENCY CALLOUT
   --------------------------------------------------------------------------
   A 24-hour emergency number is the single most important thing on a utility
   site and it was set as a plain centred heading floating between the contact
   list and the map — no weight, no boundary, easy to skim past. It now gets
   its own panel: red ground, a pulsing ring on the icon, and the number as a
   large tap target.

   Red is used here and on gas-emergency elements only, never decoratively, so
   it keeps its meaning. The label carries the word "Emergency" as well as the
   colour, since colour alone can't convey it (WCAG 1.4.1).
   -------------------------------------------------------------------------- */
.emergency-callout {
  display: flex;
  align-items: center;
  gap: var(--space-l);
  flex-wrap: wrap;
  color: #FFFFFF;
  border-radius: var(--radius-l);
  padding: var(--space-l);
  margin: var(--space-l) 0;
  position: relative;
  overflow: hidden;
  isolation: isolate;

  /* Same recipe as the buttons, base swapped to the emergency red. Because
     every tone is derived from --btn-base, the panel and the buttons are
     provably the same material rather than two hand-tuned lookalikes that
     drift apart the next time either is touched. */
  --btn-base: var(--signal);
  --btn-lit: color-mix(in srgb, var(--btn-base) 62%, #FFFFFF);
  --btn-shade: color-mix(in srgb, var(--btn-base) 52%, #000000);

  background:
    radial-gradient(125% 150% at 16% -35%, var(--btn-lit) 0%, transparent 60%),
    linear-gradient(158deg, var(--btn-base) 0%, var(--btn-shade) 100%);

  border: 1px solid rgba(255, 255, 255, 0.24);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.42),
    inset 0 -1px 0 rgba(0, 0, 0, 0.28),
    0 2px 4px color-mix(in srgb, var(--btn-shade) 42%, transparent),
    0 14px 34px color-mix(in srgb, var(--btn-shade) 38%, transparent);

  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}

/* Specular sweep. Parked off to the left at rest and travels across on hover,
   which is what sells the surface as polished rather than painted. */
.emergency-callout::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(105deg,
    transparent 30%,
    rgba(255, 255, 255, 0.16) 44%,
    rgba(255, 255, 255, 0.30) 50%,
    rgba(255, 255, 255, 0.16) 56%,
    transparent 70%);
  transform: translateX(-115%);
  transition: transform 900ms var(--ease-out);
  pointer-events: none;
}

.emergency-callout:hover,
.emergency-callout:focus-within {
  transform: translateY(-3px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    inset 0 -1px 0 rgba(0, 0, 0, 0.28),
    0 4px 8px color-mix(in srgb, var(--btn-shade) 46%, transparent),
    0 22px 52px color-mix(in srgb, var(--btn-shade) 46%, transparent);
}

.emergency-callout:hover::after,
.emergency-callout:focus-within::after {
  transform: translateX(115%);
}

/* Chrome hairline along the top edge, tying it to the metallic language used
   on the page surfaces rather than letting it read as a stray warning box. */
.emergency-callout::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg,
    transparent, rgba(255, 255, 255, 0.35) 20%,
    var(--metal-light) 50%,
    rgba(255, 255, 255, 0.35) 80%, transparent);
  z-index: 1;
}

/* Chrome disc: a light-to-dark metal gradient with a bright inner top edge and
   a dark inner bottom edge — the same bevel trick as the panel rim, at a
   smaller radius so it reads as a machined button. */
.emergency-callout__icon {
  flex: 0 0 auto;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  position: relative;
  background:
    linear-gradient(160deg, rgba(255, 255, 255, 0.42) 0%, rgba(255, 255, 255, 0.10) 45%, rgba(0, 0, 0, 0.18) 100%);
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.65),
    inset 0 -2px 3px rgba(0, 0, 0, 0.35),
    inset 0 0 0 1px rgba(255, 255, 255, 0.28),
    0 3px 8px rgba(70, 10, 8, 0.45);
  transition: transform var(--dur) var(--ease-spring);
}

.emergency-callout:hover .emergency-callout__icon {
  transform: scale(1.06) rotate(-6deg);
}

.emergency-callout__icon::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.55);
  animation: cgw-emergency-pulse 2.4s var(--ease-out) infinite;
}

@keyframes cgw-emergency-pulse {
  0%   { transform: scale(1);    opacity: 0.75; }
  70%  { transform: scale(1.45); opacity: 0; }
  100% { transform: scale(1.45); opacity: 0; }
}

.emergency-callout__icon span {
  width: 21px;
  height: 21px;
  background-color: #FFFFFF;
  -webkit-mask: var(--icon-phone) center / contain no-repeat;
  mask: var(--icon-phone) center / contain no-repeat;
}

.emergency-callout__text { flex: 1 1 14rem; min-width: 0; }

.emergency-callout__label {
  display: block;
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #FFD9D5;
  margin-bottom: 2px;
}

.emergency-callout__text p {
  margin: 0;
  color: #FFE8E6 !important;
  font-size: var(--step--1);
  max-width: none !important;
}

/* The number itself: white on the red ground (7.6:1), large, and a full-width
   tap target on phones. */
/* The number is the whole point of the panel, so it gets display size, a soft
   drop shadow to lift it off the red, and a chrome underline that widens on
   hover. Kept as flat white rather than a gradient fill so it stays at a
   measured 6.54:1 — a metallic gradient on the text itself would look sharp
   and read badly, which is the wrong trade on an emergency number. */
.emergency-callout a[href^="tel:"],
#page-content .emergency-callout a[href^="tel:"] {
  display: inline-block;
  color: #FFFFFF;
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
  text-decoration: none;
  text-shadow: 0 2px 6px rgba(72, 10, 8, 0.5);
  border-bottom: 0;
  padding-bottom: 4px;
  position: relative;
  transition: transform var(--dur) var(--ease-out);
}

.emergency-callout a[href^="tel:"]::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 38%;
  background: linear-gradient(90deg, var(--metal-light), rgba(255, 255, 255, 0.9), transparent);
  transition: width var(--dur-slow) var(--ease-out);
}

.emergency-callout a[href^="tel:"]:hover,
.emergency-callout a[href^="tel:"]:focus-visible,
#page-content .emergency-callout a[href^="tel:"]:hover {
  color: #FFFFFF !important;
  transform: translateY(-1px);
}

.emergency-callout a[href^="tel:"]:hover::after,
.emergency-callout a[href^="tel:"]:focus-visible::after {
  width: 100%;
}

.emergency-callout a[href^="tel:"]::before { display: none; }

@media (max-width: 480px) {
  .emergency-callout { padding: var(--space-m); }
  .emergency-callout__text { flex-basis: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .emergency-callout__icon::after { animation: none; opacity: 0.5; transform: none; }
  .emergency-callout::after { display: none; }
  .emergency-callout:hover { transform: none; }
  .emergency-callout:hover .emergency-callout__icon { transform: none; }
}

/* --------------------------------------------------------------------------
   4c. LEGACY ICON BITMAPS -> CSS MASKS
   --------------------------------------------------------------------------
   The old PNG icons were fixed black, non-retina, and invisible against a
   dark background. Rather than edit 55 pieces of markup, each <img> is
   converted in place: `content: ""` suppresses the bitmap and the element
   becomes a mask that inherits currentColor. If a browser doesn't support
   `content` on a replaced element, the original PNG simply shows — the page
   degrades to exactly what it looks like today.
   -------------------------------------------------------------------------- */
img[src*="download-icon"],
img[src*="fa-link-icon"],
img[src*="pdf-icon"],
img[src*="home-icon"] {
  content: "";
  display: inline-block;
  width: 1.02em;
  height: 1.02em;
  margin-right: 0.3em;
  vertical-align: -0.13em;
  background-color: currentColor;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  opacity: 0.75;
}

img[src*="download-icon"] { -webkit-mask-image: var(--icon-download); mask-image: var(--icon-download); }
img[src*="fa-link-icon"]  { -webkit-mask-image: var(--icon-external); mask-image: var(--icon-external); }
img[src*="pdf-icon"]      { -webkit-mask-image: var(--icon-doc);      mask-image: var(--icon-doc); }
img[src*="home-icon"]     { -webkit-mask-image: var(--icon-pin);      mask-image: var(--icon-pin); }

.list-group-item-action:hover img[src*="download-icon"],
.list-group-item-action:hover img[src*="fa-link-icon"],
.list-group-item-action:hover img[src*="pdf-icon"] {
  opacity: 1;
}

/* These two sit next to a tel:/mailto: link that already carries its own
   mark, so the legacy bitmap would be a second, duplicate icon. */
img[src*="phone-icon"],
img[src*="email-icon"] {
  display: none;
}

/* Fax: deliberately NOT a link, so it must not look like one. Muted colour,
   no icon, and a small label chip that says plainly why it behaves
   differently — rather than leaving people to click a number that does
   nothing. */
.contact-fax {
  display: flex;
  align-items: center;
  gap: 0.5em;
  color: var(--text-mute);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.contact-fax__label {
  font-size: 0.7em;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-mute);
  background: var(--surface-sunk);
  border: 1px solid var(--edge);
  border-radius: var(--radius-pill);
  padding: 0.25em 0.7em;
  line-height: 1.4;
}

/* --------------------------------------------------------------------------
   5. BUTTONS — hover state and shadow on every one, per the house standard
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   THE METAL RECIPE
   --------------------------------------------------------------------------
   One surface treatment, driven by a single --btn-base colour. Every lighter
   and darker tone is derived from that base with color-mix(), so changing a
   button's colour is one line and it stays internally consistent — the
   highlight, the shade and the shadow all move together.

   The four ingredients that make a flat fill read as lit metal:
     1. a radial highlight, off-centre, standing in for a light source
     2. a linear ombre from base to shade, giving the surface curvature
     3. an inner top highlight + inner bottom shade — the bevel
     4. a coloured drop shadow derived from the base, never neutral grey

   Applied to the buttons here and to .emergency-callout, so the red panel and
   the blue buttons are visibly the same material in different colours.
   -------------------------------------------------------------------------- */
.btn-homepage,
#page-content .btn:not(.btn-link):not(.btn-outline-secondary),
.btn-metal {
  --btn-base: var(--brand-primary);
  --btn-lit: color-mix(in srgb, var(--btn-base) 62%, #FFFFFF);
  --btn-shade: color-mix(in srgb, var(--btn-base) 52%, #000000);

  position: relative;
  isolation: isolate;
  overflow: hidden;

  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: 0.012em;
  min-height: 44px;
  color: #FFFFFF;

  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: var(--radius-s);

  background:
    radial-gradient(125% 150% at 16% -35%, var(--btn-lit) 0%, transparent 60%),
    linear-gradient(158deg, var(--btn-base) 0%, var(--btn-shade) 100%);

  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.42),
    inset 0 -1px 0 rgba(0, 0, 0, 0.28),
    0 2px 4px color-mix(in srgb, var(--btn-shade) 42%, transparent),
    0 8px 20px color-mix(in srgb, var(--btn-shade) 34%, transparent);

  transition: transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              filter var(--dur) var(--ease-out);
}

/* Specular sweep, parked off to the left and travelling across on hover. */
.btn-homepage::after,
#page-content .btn:not(.btn-link):not(.btn-outline-secondary)::after,
.btn-metal::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(105deg,
    transparent 32%,
    rgba(255, 255, 255, 0.18) 45%,
    rgba(255, 255, 255, 0.38) 50%,
    rgba(255, 255, 255, 0.18) 55%,
    transparent 68%);
  transform: translateX(-120%);
  transition: transform 750ms var(--ease-out);
  pointer-events: none;
}

.btn-homepage:hover,
.btn-homepage:focus-visible,
#page-content .btn:not(.btn-link):not(.btn-outline-secondary):hover,
#page-content .btn:not(.btn-link):not(.btn-outline-secondary):focus-visible,
.btn-metal:hover,
.btn-metal:focus-visible {
  color: #FFFFFF;
  transform: translateY(-2px);
  filter: brightness(1.06);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    inset 0 -1px 0 rgba(0, 0, 0, 0.28),
    0 4px 8px color-mix(in srgb, var(--btn-shade) 46%, transparent),
    0 14px 30px color-mix(in srgb, var(--btn-shade) 42%, transparent);
}

.btn-homepage:hover::after,
.btn-homepage:focus-visible::after,
#page-content .btn:not(.btn-link):not(.btn-outline-secondary):hover::after,
.btn-metal:hover::after,
.btn-metal:focus-visible::after {
  transform: translateX(120%);
}

/* Pressed: the bevel inverts, so the button reads as pushed in rather than
   just moving down. */
.btn-homepage:active,
#page-content .btn:not(.btn-link):not(.btn-outline-secondary):active,
.btn-metal:active {
  transform: translateY(1px);
  filter: brightness(0.96);
  box-shadow:
    inset 0 2px 5px rgba(0, 0, 0, 0.34),
    inset 0 -1px 0 rgba(255, 255, 255, 0.18),
    0 1px 2px color-mix(in srgb, var(--btn-shade) 40%, transparent);
}

/* Expanded (a notice panel is open) stays distinct from hover: darker base,
   inverted bevel, and it holds that state. Colour is never the only signal —
   the pressed-in bevel carries it too. */
.btn-homepage.active,
.btn-homepage[aria-expanded="true"] {
  --btn-base: var(--brand-deep);
  transform: none;
  filter: none;
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.38),
    inset 0 -1px 0 rgba(255, 255, 255, 0.16),
    0 1px 2px color-mix(in srgb, var(--btn-shade) 40%, transparent);
}

.btn-homepage.active::after,
.btn-homepage[aria-expanded="true"]::after { opacity: 0; }

/* Emergency red and the gas-safety buttons are the same material, different
   base — proof the recipe is doing the work rather than being hand-tuned. */
.btn-emergency, .btn-metal--signal { --btn-base: var(--signal); }
.btn-metal--deep { --btn-base: var(--brand-deep); }

@media (prefers-reduced-motion: reduce) {
  .btn-homepage::after,
  #page-content .btn::after,
  .btn-metal::after { display: none; }
  .btn-homepage:hover,
  .btn-metal:hover { transform: none; }
}

/* --------------------------------------------------------------------------
   6. CARDS
   -------------------------------------------------------------------------- */
#page-content .card {
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-s);
  overflow: hidden;
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}

#page-content .card:hover { transform: translateY(-3px); box-shadow: var(--shadow-l); }
#page-content .card-body { padding: var(--space-m); }

/* Content images get the same surface language as the cards around them. */
#page-content img:not(.tile-video-fallback):not([class*="icon"]) {
  border-radius: var(--radius-m);
}

/* --------------------------------------------------------------------------
   7. SIDEBAR
   -------------------------------------------------------------------------- */
/* :not(.page-image-slot) so that component can keep its own dashed border and
   gradient fill — this generic rule outranks it on specificity (ID selector)
   otherwise and flattens it back to a plain white card. */
.sidebar,
#our-location > *:not(.page-image-slot),
#call-before-you-dig > * {
  background: var(--surface) !important;
  border: 1px solid var(--edge);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-s);
  padding: var(--space-m);
}

/* Leaflet builds its tile grid and a far-offset zoom-proxy element before it
   settles into the container, and for a beat during load that spills past the
   viewport and the page can be dragged sideways. It self-corrects in about a
   second, but "self-corrects" is not the same as "correct". overflow-x: clip
   contains it without creating a scroll container, so — unlike overflow:
   hidden — it can't break position: sticky further up the tree. */
#our-location,
#call-before-you-dig,
.sidebar {
  overflow-x: clip;
}

.leaflet-container {
  max-width: 100%;
  border-radius: var(--radius-s);
}

/* --------------------------------------------------------------------------
   8. TABLES
   -------------------------------------------------------------------------- */
#page-content table {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  border: 1px solid var(--edge);
  border-radius: var(--radius-m);
  overflow: hidden;
  box-shadow: var(--shadow-xs);
}

#page-content th {
  background: var(--surface-sunk);
  color: var(--heading);
  font-weight: 700;
  text-align: left;
}

#page-content th, #page-content td {
  padding: var(--space-s) var(--space-m);
  border-bottom: 1px solid var(--edge);
}

#page-content tbody tr:last-child td { border-bottom: 0; }
#page-content tbody tr:hover { background: var(--surface-sunk); }

/* --------------------------------------------------------------------------
   8a. PAGE KICKER — eyebrow label above a page heading
   --------------------------------------------------------------------------
   The small uppercase label the design standard calls for on every page,
   in the accent colour, sitting above the h1. One class, reusable anywhere
   a page wants a proper title treatment instead of dropping straight into
   a breadcrumb-then-paragraph with no heading at all.
   -------------------------------------------------------------------------- */
#page-content .page-kicker {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-transform: uppercase;
  letter-spacing: .14em;
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--accent-dark);
  margin: 0 0 6px;
}
#page-content .page-kicker::before {
  content: "";
  width: 20px;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), transparent);
}
#page-content h1 { margin-bottom: var(--space-m); }

/* --------------------------------------------------------------------------
   8a-1. HOURS CARD
   --------------------------------------------------------------------------
   A scannable day/time table instead of hours buried mid-paragraph — the
   single most-asked question on a utility site deserves to be readable at a
   glance, not parsed out of a sentence.
   -------------------------------------------------------------------------- */
.hours-card {
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-s);
  overflow: hidden;
  margin: var(--space-m) 0 var(--space-l);
}
.hours-card__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
  padding: var(--space-s) var(--space-m);
  border-bottom: 1px solid var(--edge);
  font-variant-numeric: tabular-nums;
}
.hours-card__row:last-child { border-bottom: 0; }
.hours-card__day {
  font-weight: 600;
  color: var(--heading);
}
.hours-card__time {
  font-weight: 600;
  color: var(--brand-primary);
}
.hours-card__row--closed .hours-card__time { color: var(--text-mute); font-weight: 500; }
.hours-card__row--emergency {
  background: color-mix(in srgb, var(--signal) 7%, transparent);
}
.hours-card__row--emergency .hours-card__day::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--signal);
  margin-right: 8px;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--signal) 20%, transparent);
}
.hours-card__row--emergency .hours-card__time { color: var(--signal); }

/* --------------------------------------------------------------------------
   8b. BLOCKQUOTE — indented pull-quote
   --------------------------------------------------------------------------
   Applies to any <blockquote> sitewide automatically — no per-page CSS
   needed. Indented, a metallic left rule instead of a plain line, and a
   large kicker quotation mark that sits in the margin rather than fighting
   the text for space.
   -------------------------------------------------------------------------- */
#page-content blockquote {
  position: relative;
  margin: var(--space-l) 0;
  padding: 4px 0 4px var(--space-l);
  border-left: 3px solid transparent;
  border-image: linear-gradient(180deg, var(--metal-light), var(--brand-primary), var(--metal-dark)) 1;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--heading);
  max-width: var(--measure) !important;
}
#page-content blockquote::before {
  content: "\201C";
  position: absolute;
  left: -6px;
  top: -0.28em;
  font-family: Georgia, serif;
  font-style: normal;
  font-size: 2.6em;
  line-height: 1;
  color: var(--brand-mid);
  opacity: 0.5;
  transform: translateX(-100%);
}
#page-content blockquote footer,
#page-content blockquote cite {
  display: block;
  margin-top: var(--space-xs);
  font-family: var(--font-body);
  font-style: normal;
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--text-mute);
}
@media (max-width: 480px) {
  #page-content blockquote::before { display: none; }
}

/* --------------------------------------------------------------------------
   8c. IMAGE SLOT — swappable square placeholder
   --------------------------------------------------------------------------
   Reserves a spot for a photo the customer will supply later. Square by
   design (per instruction), inside the same metallic-rimmed card language as
   everything else — so the page looks intentional NOW, with a real photo
   later, not "half-built until content arrives." Swap it for a plain <img>
   with the same "page-image-slot" class and the frame keeps working, no CSS
   changes needed.

   Sizing: source images should be at least 800x800px, 1:1 (square), JPG or
   WebP under ~200KB. The frame is fully fluid — one size covers every
   breakpoint, the browser scales down, never up.
   -------------------------------------------------------------------------- */
.page-image-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  width: 100%;
  border-radius: var(--radius-m);
  overflow: hidden;
  position: relative;
  isolation: isolate;
  background:
    radial-gradient(120% 130% at 20% -10%, color-mix(in srgb, var(--brand-mid) 22%, transparent), transparent 60%),
    linear-gradient(160deg, var(--surface-sunk) 0%, var(--surface-raised) 100%);
  border: 1px dashed color-mix(in srgb, var(--brand-primary) 45%, transparent);
  box-shadow: var(--shadow-s);
  margin-bottom: var(--space-m);
}
.page-image-slot::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--ombre-metal);
  opacity: .8;
}
.page-image-slot__hint {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--brand-primary);
  text-align: center;
  padding: var(--space-m);
}
.page-image-slot__hint svg {
  width: 30%;
  max-width: 46px;
  height: auto;
  opacity: .55;
}
.page-image-slot__hint span {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: .02em;
  opacity: .7;
}

/* Once a real photo is dropped in — <img class="page-image-slot"> instead of
   the placeholder markup — it fills the same square frame, cropped to cover,
   metallic rim and all. */
img.page-image-slot {
  object-fit: cover;
  display: block;
  border-style: solid;
}

/* --------------------------------------------------------------------------
   9. HORIZONTAL RULES
   -------------------------------------------------------------------------- */
#page-content hr,
#page-content .bighr {
  border: 0;
  height: 1px;
  background: var(--ombre-metal);
  opacity: 0.7;
  margin: var(--space-l) 0;
}

/* --------------------------------------------------------------------------
   10. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
  #page-content > .container:not(:has(.home-glass-panel)) {
    padding: var(--space-l) var(--space-m);
    border-radius: var(--radius-m);
  }
}

/* Browsers without :has() get the plain (pre-card) treatment rather than a
   broken one — the page still reads correctly, it just isn't lifted. */
@supports not selector(:has(*)) {
  #page-content > .container {
    background: var(--surface);
    border-radius: var(--radius-l);
    padding: var(--space-xl) var(--space-l);
    box-shadow: var(--shadow-m);
  }
}
