/* ==========================================================================
   RPG Green Technology — Design tokens
   ========================================================================== */
:root {
  --navy-900: #060b4d;
  --navy-800: #0c1360;
  --navy-700: #12185f;
  --red-600: #d12424;
  --red-700: #ad1c1c;
  --gray-50: #f3f4f6;
  --gray-100: #e7eaee;
  --gray-400: #8a8fa8; /* decorative / non-text use only (fails AA as text-on-white) */
  --gray-600: #6b7089; /* 4.88:1 on white — use for small label text */
  --white: #ffffff;
  --ink: #1a1f3d;

  --font-heading: 'Plus Jakarta Sans', 'Segoe UI', sans-serif;
  --font-body: 'Plus Jakarta Sans', 'Segoe UI', sans-serif;

  --container: 1440px;
  --scrollbar-w: 0px; /* set from script.js; keeps the fixed header's right
                          edge lined up with in-flow content on browsers
                          that reserve a non-overlay scrollbar gutter */
  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  --space-1: clamp(0.5rem, 0.45rem + 0.25vw, 0.75rem);
  --space-2: clamp(0.75rem, 0.65rem + 0.4vw, 1.25rem);
  --space-3: clamp(1.25rem, 1rem + 1vw, 2rem);
  --space-4: clamp(2rem, 1.6rem + 1.6vw, 3.5rem);
  --space-5: clamp(3rem, 2.2rem + 3vw, 6rem);

  --fs-h1: clamp(2.1rem, 1.5rem + 3vw, 3.6rem);
  /* Section headlines (.section-heading h2, used by Facts, Process,
     Calculator, Financing, Trusted, Reviews, FAQ, Projects). Sized to
     stay clearly, unmistakably larger than both .section-eyebrow (~12px)
     and the subhead paragraph (~16–18px) at every viewport — roughly
     2.3–4x the eyebrow and ~2x the paragraph, floor to ceiling — while
     staying under --fs-h1 so the hero headline still reads as the single
     biggest thing on the page. */
  --fs-h2: clamp(2.6rem, 2.1rem + 2.5vw, 3.5rem);
  --fs-h3: clamp(1.5rem, 1.25rem + 1.2vw, 2.15rem);
  --fs-lede: clamp(1rem, 0.93rem + 0.35vw, 1.15rem);
  --fs-body: clamp(0.95rem, 0.92rem + 0.15vw, 1.02rem);
  --fs-stat: clamp(1.5rem, 1.3rem + 1vw, 2.1rem);

  --shadow-card: 0 10px 30px -12px rgba(6, 11, 77, 0.25);
  --ease: cubic-bezier(.4,0,.2,1);
}

/* ==========================================================================
   Reset
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 96px; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

body, h1, h2, h3, p, ul, li, figure, form, fieldset, address {
  margin: 0;
  padding: 0;
}
ul { list-style: none; }
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, select { font: inherit; color: inherit; }
svg { flex-shrink: 0; }

/* "clip", not "hidden": per spec, an element can't mix visible/non-visible
   overflow-x and overflow-y — setting only overflow-x:hidden here forces
   overflow-y to auto-promote to "auto", which silently turns html/body
   into their own scroll container instead of leaving the real viewport as
   the one true scroller. That's harmless-looking until something depends
   on the actual viewport specifically: it's what broke "position: sticky"
   site-wide the moment about.html's plain (non-overlay) header/subnav
   tried to use it — both computed sticky's "nearest scrolling ancestor"
   as this new html/body scroll container rather than the viewport, so
   they just scrolled away with the page instead of sticking. "clip" gets
   the exact same 100vw-breakout-safe horizontal clipping without that
   axis-mixing rule ever kicking in, since clip has no such pairing
   requirement with the other axis. */
html, body { overflow-x: clip; }

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--ink);
  line-height: 1.6;
  background: var(--white);
}

h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: 1.15;
  color: var(--navy-900);
}
h1 { font-size: var(--fs-h1); color: var(--white); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }

.text-navy { color: var(--navy-900); }
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.text-red { color: var(--red-600); }

/* ==========================================================================
   Shared section heading (eyebrow + h2 + subhead) — used by Facts, Process,
   Calculator, Trusted, Reviews and FAQ so every section opens the same,
   deliberate way instead of a bare h2 with no visual lead-in.
   ========================================================================== */
.section-heading {
  max-width: 760px;
  margin-inline: auto;
  margin-bottom: clamp(2.5rem, 2rem + 2vw, 3.5rem);
  text-align: center;
}
/* Deliberately small and quiet — this is a label sitting ABOVE the actual
   headline, not a second headline. Keeping it clearly smaller than both
   the h2 below and the body copy is what makes the h2 read as dominant;
   this is the thing that was missing before (eyebrow and h2 were too
   close in size, so nothing on the page read as "the important part"). */
.section-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.85rem;
  font-family: var(--font-heading);
  font-size: 0.68rem;
  font-weight: 700;
  /* Wide letter-spacing on all-caps text makes it visually "spread" and
     read as loud/large regardless of its actual font-size — tightened
     this considerably so the eyebrow stays a compact, quiet label instead
     of stretching out to compete with the (much bigger, but shorter and
     mixed-case) headline below it. */
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--red-600);
}
.section-eyebrow::before { content: ''; display: inline-block; width: 16px; height: 2px; background: var(--red-600); }
/* Matches the same text-2xl/3xl/4xl scale the Tailwind sections (Segments,
   Engineered) already use for their headings, so a vanilla .section-heading
   h2 and a Tailwind h2/h3 read as the same "size of big heading" site-wide
   instead of two different scales that happen to look similar. */
.section-heading h2 {
  margin: 0;
  font-weight: 800;
  letter-spacing: -0.02em;
  font-size: 1.5rem;
  line-height: 2rem;
}
@media (min-width: 640px) {
  .section-heading h2 { font-size: 1.875rem; line-height: 2.25rem; }
}
@media (min-width: 1024px) {
  .section-heading h2 {
    font-size: 2.25rem;
    line-height: 2.5rem;
  }
}
/* THE actual bug behind both the "no hierarchy" and "eyebrow renders gray
   not red" reports: .section-eyebrow is a <p> tag too (it needs to be, for
   proper document structure), so a bare ".section-heading p" selector
   matches it as well as the real subhead paragraph. That rule has higher
   specificity than ".section-eyebrow" alone (class+element beats class),
   so it was silently overriding the eyebrow's font-size and color with
   the subhead's every time, regardless of what .section-eyebrow said.
   :not() here excludes the eyebrow so each rule only ever touches the
   paragraph it was actually written for. */
.section-heading p:not(.section-eyebrow) { margin: 1.1rem auto 0; max-width: 52ch; color: var(--gray-600); font-size: var(--fs-lede); }

/* The one accented word/phrase inside a section heading (the pattern the
   Engineered section set: a small red eyebrow line above, paired with a
   confident, mostly-dark headline) — a diagonal red-to-navy gradient
   instead of flat red, so the "brand color pairing" carries into the
   headline itself rather than stopping at the eyebrow. Scoped to inside
   .section-heading specifically so it doesn't change .text-red elsewhere
   (eyebrows, buttons, small tags) that are meant to stay flat red. */
.section-heading h2 .text-red {
  background: linear-gradient(120deg, var(--red-600) 25%, var(--navy-900) 115%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--navy-900);
  color: var(--white);
  padding: 0.75rem 1.25rem;
  z-index: 1000;
  border-radius: 0 0 8px 0;
}
.skip-link:focus {
  left: 0;
}

:focus-visible {
  outline: 3px solid var(--red-600);
  outline-offset: 3px;
}

/* Named .site-container (not .container) on purpose: Tailwind ships its own
   core "container" utility class with completely different breakpoint
   max-widths and NO padding. Since Tailwind's CDN script runs globally on
   this page, a class literally named .container collides with it — same
   specificity, so whichever rule lands later in the cascade wins, which is
   exactly what was causing the header/hero/section width to drift out of
   sync with each other despite "identical" CSS. */
.site-container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 1rem + 2vw, 2.5rem);
}

/* NOTE: .container--flush was removed — the Hero and Engineered sections
   now handle their own left-edge alignment via Tailwind utilities
   (see index.html <head> for the Tailwind CDN config). */

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.95rem;
  padding: 0.9rem 1.6rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease), background-color 0.25s var(--ease);
}
.btn svg { transition: transform 0.25s var(--ease); }
.btn:hover { transform: translateY(-2px); }
.btn:hover svg { transform: translateX(3px); }
.btn:active { transform: translateY(0); }

.btn-red {
  background: var(--red-600);
  color: var(--white);
  box-shadow: 0 10px 24px -8px rgba(209, 36, 36, 0.55);
}
.btn-red:hover { background: var(--red-700); }

.btn-navy {
  background: var(--navy-900);
  color: var(--white);
  box-shadow: 0 10px 24px -8px rgba(6, 11, 77, 0.45);
}
.btn-navy:hover { background: var(--navy-800); }

.btn-outline-navy {
  background: transparent;
  color: var(--navy-900);
  border: 1.5px solid rgba(6, 11, 77, 0.25);
}
.btn-outline-navy:hover { background: rgba(6, 11, 77, 0.06); border-color: rgba(6, 11, 77, 0.4); }

/* ==========================================================================
   Header
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(6, 11, 77, 0.06);
}

/* Anchor-jump targets on the home page (CTAs linking to #home, #proof,
   #builder, #segments, #engineered, #quote) need clearance from the
   header, which is position:fixed and therefore never pushes content
   down on its own — without this, jumping straight to a section (e.g.
   tapping "See What You Could Save") lands with its heading tucked
   behind the header instead of below it. */
#home, #proof, #builder, #segments, #engineered, #quote {
  scroll-margin-top: 90px;
}

/* Overlay variant — used on the homepage so the header floats transparently
   "in" the hero photo instead of sitting above it as a separate white bar.
   It only solidifies into a full-width bar once the page scrolls past the
   hero (JS toggles .is-scrolled on scroll — see script.js). */
.site-header--overlay {
  position: fixed;
  left: 0;
  right: var(--scrollbar-w); /* not "right: 0" — on browsers/OS settings that
                                 reserve a visible scrollbar gutter, a fixed
                                 element's right:0 sits past where in-flow
                                 content actually ends, throwing the header
                                 out of alignment with the hero/stat-strip
                                 by the gutter's width. */
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
  transition: background-color 0.3s ease, backdrop-filter 0.3s ease, border-color 0.3s ease;
}
.site-header--overlay.is-scrolled {
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(10px);
  border-bottom-color: rgba(6, 11, 77, 0.06);
}
.site-header--overlay .nav-toggle span { background: var(--white); }
.site-header--overlay.is-scrolled .nav-toggle span { background: var(--navy-900); }

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding-block: 0.85rem;
  transition: padding-block 0.35s var(--ease);
}
.brand {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 0.45rem 0.9rem;
  box-shadow: 0 10px 24px -12px rgba(6, 11, 77, 0.25);
  transition: padding 0.35s var(--ease);
}
.brand img { height: 34px; width: auto; display: block; transition: height 0.35s var(--ease); }

.main-nav ul {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 0.5rem + 1.5vw, 2.1rem);
}
.main-nav a, .dropdown-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-weight: 600;
  font-size: 0.96rem;
  color: var(--navy-900);
  padding: 0.5rem 0;
  position: relative;
  white-space: nowrap;
}
.main-nav a.active,
.main-nav a:hover,
.dropdown-toggle:hover { color: var(--red-600); }
.main-nav a.active::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -4px;
  height: 3px;
  border-radius: 3px;
  background: var(--navy-900);
}

.has-dropdown { position: relative; }
.dropdown-menu {
  position: absolute;
  top: calc(100% + 0.6rem);
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  background: var(--white);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  min-width: 190px;
  padding: 0.5rem;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease), visibility 0.2s;
}
.has-dropdown:hover .dropdown-menu,
.has-dropdown:focus-within .dropdown-menu,
.has-dropdown.is-open .dropdown-menu {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}
.dropdown-menu li a {
  display: block;
  padding: 0.6rem 0.8rem;
  border-radius: 8px;
  font-weight: 500;
  font-size: 0.92rem;
}
.dropdown-menu li a:hover { background: var(--gray-50); color: var(--red-600); }

/* ==========================================================================
   Mega menu (Solutions / Products) — a wide multi-column panel instead of
   a narrow single-column dropdown. Positioned relative to the <header>
   itself (see .has-dropdown--mega below removing its own position:relative
   at desktop widths), so it's always centered on the viewport rather than
   the specific nav item that triggered it — this keeps it from clipping
   off the right edge for a nav item that sits near the header's edge.
   Bug this replaced: the old .dropdown-menu links were plain <a> tags
   living inside .main-nav, so the "%.nav-pill .main-nav a { color: white }"
   rule further down matched them too — white text on a white dropdown
   background, i.e. invisible. See the higher-specificity override inside
   the desktop nav-pill media block that fixes this for the new markup. */
/* Opening/closing is driven entirely by JS now (see the hover-intent
   block in script.js), not CSS :hover — three rounds of pure-CSS fixes
   (plain :hover, an invisible bridge over the gap, then a staggered
   transition-delay) each fixed one problem and opened another: :hover
   alone closed mid-transit through the gap between trigger and panel;
   a bridge wide enough to cover that gap also covered the OTHER nav
   triggers, blocking hover from ever reaching them; splitting the
   close delay across opacity/visibility/pointer-events left a window
   where the panel was visibly still open but pointer-events had
   already gone to "none", so hovering anything inside it did nothing.
   A single JS-managed .is-open class means there's exactly one thing
   to keep in sync, and the "give it time to cross the gap" grace
   period is a plain, debuggable setTimeout instead of four
   independently-timed CSS properties. :focus-within is kept as a
   plain CSS fallback alongside the JS focusin/focusout handling. */
.mega-menu {
  position: absolute;
  top: calc(100% + 0.9rem);
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  width: min(760px, 92vw);
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: 0 30px 60px -20px rgba(6, 11, 77, 0.35);
  padding: 1.75rem;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease), visibility 0.2s;
  z-index: 40;
}
.has-dropdown--mega.is-open .mega-menu,
.has-dropdown--mega:focus-within .mega-menu {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
.mega-menu-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25rem;
}
/* Our Work's dropdown only has 2 real destinations (Projects, News), not
   3 like Solutions/Products — reusing the fixed 3-col grid as-is would
   leave a dangling empty column. Narrower 2-col override, applied only
   here via the extra modifier class. */
.mega-menu-grid.mega-menu-grid--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  max-width: 420px;
  margin-inline: auto;
}
.mega-menu-item {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  border-radius: var(--radius-md);
  transition: background 0.2s var(--ease), transform 0.2s var(--ease);
}
/* .mega-menu-item is an <a> living inside .main-nav, so it's also
   caught by ".main-nav a { padding: 0.5rem 0 }" (meant for the short
   top-level links) — that rule has a class + a type selector, so it's
   MORE specific than the plain single-class ".mega-menu-item" padding
   above and was winning outright, collapsing this card's padding down
   to 8px top/bottom and 0 on the sides. Content sat flush against the
   left/right edges of the card (and of its own hover highlight) with
   no breathing room at all. Scoping the real padding to this two-class
   selector instead settles the specificity fight properly. */
.mega-menu-grid .mega-menu-item { padding: 0.85rem 0.75rem; }
.mega-menu-item:hover { background: var(--gray-50); transform: translateY(-2px); }
/* Was height:92px with no width set at all — .mega-menu-item ended up
   computing align-items:center for its flex children (not stretch,
   despite nothing here requesting that), so instead of spanning the
   card width like the fixed height implied, the thumb shrank to fit
   just its 26px icon and stayed 92px tall: a narrow, oddly-tall pill
   instead of an icon tile. Explicit width + height turns it into a
   proper compact square tile regardless of the parent's align-items,
   and align-self: flex-start keeps it pinned to its own size instead
   of ever stretching again. */
.mega-menu-thumb {
  width: 48px;
  height: 48px;
  align-self: flex-start;
  flex-shrink: 0;
  border-radius: var(--radius-md);
  display: grid;
  place-items: center;
  color: var(--white);
  background: linear-gradient(135deg, var(--navy-900), #1d3fd6);
}
/* .mega-menu-item is itself an <a>, so it's also caught by the
   ".main-nav a { white-space: nowrap }" rule meant for short top-level
   links like "Home" — and white-space inherits, so without this it
   silently applies to the much longer description copy in here too.
   Instead of wrapping inside its ~220px column, the whole sentence
   rendered as one unbroken line and overflowed straight across the
   neighboring columns (desktop grid) or the other stacked items
   (mobile list), overlapping all of them. Explicit reset needed on
   both the heading and the description since both inherit it. */
.mega-menu-body { display: flex; flex-direction: column; gap: 0.3rem; white-space: normal; }
.mega-menu-body strong { font-family: var(--font-heading); font-weight: 700; font-size: 0.95rem; }
.mega-menu-desc { font-size: 0.82rem; line-height: 1.5; color: var(--gray-600); white-space: normal; }
.mega-menu-tags { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.4rem; }
.mega-menu-tags span {
  font-size: 0.74rem;
  font-weight: 600;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--gray-50);
  border: 1px solid var(--gray-100);
  color: var(--gray-600);
}
.mega-menu-foot {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--gray-100);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.86rem;
  color: var(--gray-600);
}
/* Same bleed-through as .mega-menu-item above: this "Get Free Quote"
   is a .btn, but it's ALSO an <a> living inside .main-nav, so
   ".main-nav a { padding: 0.5rem 0 }" — one class + one type, more
   specific than the plain single-class ".btn" rule — was overriding
   .btn's own 0.9rem/1.6rem padding down to 8px top/bottom and none on
   the sides, squashing it into a cramped sliver instead of the same
   pill every other button on the site uses. Repeating .btn's real
   padding at two-class specificity here beats that cleanly. */
.mega-menu-foot .btn { flex-shrink: 0; padding: 0.9rem 1.6rem; }
/* Same story again, this time for text color. The real culprit here is
   further down: ".nav-pill .main-nav .mega-menu a { color: var(--ink) }"
   and its ":hover" sibling (color: var(--red-600)) exist so mega-menu
   card links stay dark-on-white instead of inheriting the nav-pill's
   light nav-bar text color — but at 3-4 classes deep they're far more
   specific than plain ".btn-red { color: white }" and catch this
   "Get Free Quote" .btn too, since it's also an <a> inside .mega-menu.
   On hover that turned its text the exact same red as its own
   background, making the label vanish entirely. Matching (and beating)
   that selector's specificity here, scoped down to just this button,
   fixes it without touching the mega-menu-item rule it was built for. */
.nav-pill .main-nav .mega-menu-foot .btn,
.nav-pill .main-nav .mega-menu-foot .btn:hover { color: var(--white); }

.header-cta { flex-shrink: 0; }

/* ==========================================================================
   Desktop nav pill (navy bar wrapping links + CTA, per PNB-style reference)
   ========================================================================== */
@media (min-width: 900px) {
  .brand { padding: 0.55rem 1.15rem; }
  .brand img { height: 38px; }

  /* The nav bar is always the full expanded width now (below), so the
     separate white header backdrop is redundant — keep the header itself
     transparent at this breakpoint. */
  .site-header--overlay.is-scrolled {
    background: transparent;
    backdrop-filter: none;
    border-bottom-color: transparent;
  }

  /* Default / "grown" state: the full-width bar spanning the exact same
     container the hero headline and stat-card strip use — header-inner is
     display:flex + justify-content:space-between, so this pill's right
     edge always lands on the container's right edge in this state,
     matching the hero text and stat-strip below it. This is also the
     permanent state for any non-overlay header (other pages). */
  .nav-pill {
    display: flex;
    align-items: center;
    gap: 1.75rem;
    flex: 1 1 auto;
    background: var(--navy-900);
    border-radius: var(--radius-lg);
    padding: 0.55rem 0.55rem 0.55rem 2rem;
    box-shadow: 0 14px 30px -14px rgba(6, 11, 77, 0.45);
    transition: flex-grow 0.4s var(--ease), padding 0.35s var(--ease), box-shadow 0.35s var(--ease);
  }
  .main-nav { flex: 1 1 auto; transition: flex-grow 0.4s var(--ease); }
  .main-nav ul { width: 100%; justify-content: space-between; }

  /* Compact "short" state — only on the homepage overlay header, only
     before scrolling: the pill shrinks to hug its own content (no fixed
     max-width, so with white-space:nowrap on every link it can never be
     forced to wrap) instead of stretching across the container. Because
     header-inner is justify-content:space-between, it still hugs the
     container's right edge here too — only its LEFT edge moves, so it
     never drifts out of alignment with anything below it; it's just
     visibly shorter. Scrolling adds .is-scrolled (script.js) and it grows
     into the full-width rule above — the "grow on scroll" the reference
     design calls for. */
  .site-header--overlay:not(.is-scrolled) .nav-pill { flex: 0 1 auto; }
  .site-header--overlay:not(.is-scrolled) .main-nav { flex: 0 1 auto; }
  .site-header--overlay:not(.is-scrolled) .main-nav ul { width: auto; justify-content: flex-start; }

  /* "Solidify" on scroll: on top of growing to full width, the bar + logo
     also get noticeably shorter and the shadow deepens, so scrolling reads
     as a clear, deliberate transition rather than a single subtle change. */
  .site-header--overlay.is-scrolled .header-inner { padding-block: 0.4rem; }
  .site-header--overlay.is-scrolled .brand { padding: 0.3rem 0.75rem; }
  .site-header--overlay.is-scrolled .brand img { height: 26px; }
  .site-header--overlay.is-scrolled .nav-pill {
    padding-block: 0.3rem;
    box-shadow: 0 18px 36px -14px rgba(6, 11, 77, 0.55);
  }

  .nav-pill .main-nav a,
  .nav-pill .dropdown-toggle {
    color: rgba(255, 255, 255, 0.8);
  }
  .nav-pill .main-nav a:hover,
  .nav-pill .dropdown-toggle:hover,
  .nav-pill .main-nav a.active {
    color: var(--white);
  }
  .nav-pill .main-nav a.active::after {
    background: var(--red-600);
  }

  /* The mega menu's own links live inside .main-nav too, so without this
     override they'd inherit the white nav-pill text color above and
     vanish against the mega menu's white background (higher specificity
     here — 3 classes vs. 2 — guarantees this wins regardless of source
     order in the stylesheet). */
  .nav-pill .main-nav .mega-menu a,
  .nav-pill .main-nav .mega-menu-body strong {
    color: var(--ink);
  }
  .nav-pill .main-nav .mega-menu-desc { color: var(--gray-600); }
  .nav-pill .main-nav .mega-menu-item:hover > .mega-menu-body strong,
  .nav-pill .main-nav .mega-menu a:hover { color: var(--red-600); }
  .nav-pill .main-nav .mega-menu-tags a { color: var(--gray-600); }
  .nav-pill .main-nav .mega-menu-tags a:hover { color: var(--red-600); }
  .nav-pill .main-nav .mega-menu-foot { color: var(--gray-600); }

  /* Let the mega panel position relative to <header> (a fixed/sticky
     positioned ancestor) instead of this single nav item, so left:50% +
     translateX(-50%) centers it on the whole header/viewport rather than
     under whichever link happens to trigger it — the item second from
     the right otherwise pushes the panel off-screen. */
  .has-dropdown--mega { position: static; }

  .nav-pill .header-cta {
    padding: 0.65rem 1.4rem;
    font-size: 0.9rem;
    box-shadow: none;
  }
  .nav-pill .header-cta:hover { transform: none; }
}

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  /* Without this, tapping the button on Android Chrome/WebView paints the
     browser's default translucent gray tap-highlight rectangle sized to
     this 40x40 box. On the home page the header starts fully transparent
     (.site-header--overlay, no background until scrolled), so that
     highlight rectangle shows up as a small floating white/gray box with
     the navy hero visible on every side of it — the "gap" around the
     hamburger icon. Desktop mouse clicks never trigger this, which is why
     it doesn't show up testing with a mouse/DevTools emulation. */
  -webkit-tap-highlight-color: transparent;
}
.nav-toggle span {
  display: block;
  height: 2px;
  width: 24px;
  background: var(--navy-900);
  border-radius: 2px;
  transition: transform 0.25s var(--ease), opacity 0.25s var(--ease);
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ==========================================================================
   Hero + Engineered sections
   These now live in index.html as Tailwind utility classes (Play CDN,
   configured in <head>). The rules that used to be here (.hero, .hero-media,
   .hero-overlay, .hero-leaf, .stat-bar-wrap, .stat-bar, .stat-card,
   .scroll-hint*, .engineered*, .float-card*, .service-list, .grass-edge)
   were removed to avoid dead/duplicate CSS. .hero-dot is kept below since
   script.js still toggles its is-active state directly.
   ========================================================================== */
.hero-dot {
  /* generous hit area for touch, small visual dot for design fidelity */
  width: 24px; height: 24px;
  display: grid;
  place-items: center;
  border-radius: 50%;
}
.hero-dot::after {
  content: '';
  width: 9px; height: 9px;
  border-radius: 50%;
  background: rgba(255,255,255,0.4);
  transition: background 0.25s var(--ease), transform 0.25s var(--ease);
}
.hero-dot.is-active::after { background: var(--white); transform: scale(1.2); }

/* Stat strip (430+/2,540+/etc. impact numbers) hidden below the sm
   breakpoint by request — on mobile it's the 2x2 bento-tile layout
   (grid-cols-2, no sm: prefix) rather than the flush desktop bar, and
   floating over the hero/segments seam with negative margins made it
   feel cramped/heavy at phone widths. Desktop/tablet (sm: and up,
   640px+) is unaffected. */
@media (max-width: 639px) {
  #statBarWrap { display: none; }
}

/* Engineered-section illustration: background was flood-filled to real
   transparency, so it now floats directly on the section backdrop rather
   than sitting in an opaque white card — a slow continuous bob gives it
   a touch of life without competing with the reveal-in animation on
   mount. Respects reduced-motion. */
.engineered-diagram-float {
  animation: engineeredDiagramFloat 6s ease-in-out infinite;
}
@keyframes engineeredDiagramFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-14px); }
}
@media (prefers-reduced-motion: reduce) {
  .engineered-diagram-float { animation: none; }
}

/* ==========================================================================
   Solutions
   ========================================================================== */
.solutions { padding-block: clamp(1rem, 1vw, 2rem) clamp(4rem, 3rem + 3vw, 6rem); }
.solution-row {
  display: grid;
  gap: clamp(2rem, 1.5rem + 3vw, 4rem);
  align-items: center;
  padding-block: clamp(3rem, 2rem + 3vw, 5rem);
}
@media (min-width: 900px) {
  .solution-row { grid-template-columns: 1fr 1fr; }
  .solution-row--reverse .solution-media { order: 2; }
}
.solution-media { position: relative; }
.solution-media img { border-radius: var(--radius-lg); aspect-ratio: 4/3; object-fit: cover; }
.media-arrows {
  position: absolute;
  left: 1rem; bottom: 1rem;
  display: flex;
  gap: 0.5rem;
}
.media-arrows button {
  width: 38px; height: 38px;
  border-radius: 50%;
  background: rgba(255,255,255,0.35);
  color: var(--white);
  display: grid;
  place-items: center;
  backdrop-filter: blur(4px);
  transition: background 0.2s var(--ease);
}
.media-arrows button:hover { background: var(--red-600); }

.eyebrow {
  font-weight: 700;
  color: var(--red-600);
  margin-bottom: 0.4rem;
  font-size: 0.9rem;
}
.solution-copy h3 { margin-bottom: var(--space-2); }
.solution-copy p { max-width: 46ch; color: var(--ink); opacity: 0.85; margin-bottom: var(--space-3); }

/* ==========================================================================
   Completed Projects — full-bleed, continuously auto-scrolling marquee.
   Same seamless-loop technique as the Trusted logo strip further down:
   two identical <ul> tracks placed side by side, animating the whole
   flex row by -100% of one track's width loops cleanly forever since the
   second half is a pixel-perfect repeat of the first.
   ========================================================================== */
/* No local overflow-x here on purpose — html/body already carry the
   page-wide overflow-x:clip that keeps 100vw breakout elements from
   causing a horizontal scrollbar. Adding "overflow-x: hidden" again on
   the section itself would make the browser auto-promote the section's
   own overflow-y to "auto" per spec (an element can't mix visible/
   non-visible overflow-x and overflow-y with the "hidden" value —
   "clip" doesn't have this pairing rule, which is exactly why html/body
   use clip and not hidden now), silently turning the section into its
   own scroll container — which is exactly the "why is this section
   scrollable and clipping its own content" bug that bit .facts below,
   and separately, the "why won't position:sticky stick" bug that bit
   about.html's header/subnav before html/body switched to clip. */
.projects { background: var(--white); padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); }

/* Dense photo grid — was a 6-card scrollable strip where only 1-2 large
   cards showed at once, which read as "not many projects" even though
   the same 6 photos were there. Small square cards, tight gaps, all 12
   visible at once on desktop with zero scrolling needed: the point is
   volume at a glance, sales convincing a visitor by sheer weight of
   real work shown, not a slow reveal one card at a time. */
.projects-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.6rem;
  margin-top: clamp(2rem, 1.5rem + 2vw, 3rem);
}
@media (min-width: 560px) {
  .projects-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 860px) {
  .projects-grid { grid-template-columns: repeat(4, 1fr); gap: 0.75rem; }
}
@media (min-width: 1200px) {
  .projects-grid { grid-template-columns: repeat(6, 1fr); }
}
.projects-grid-card {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: 0 8px 18px -12px rgba(6, 11, 77, 0.28);
}
.projects-grid-card img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s var(--ease);
}
.projects-grid-card:hover img { transform: scale(1.08); }
.projects-grid-card-overlay {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 1.5rem 0.7rem 0.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  background: linear-gradient(0deg, rgba(6, 11, 77, 0.88) 0%, transparent 100%);
  color: var(--white);
}
.projects-grid-card-overlay span {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #ff8a8a;
}
.projects-grid-card-overlay strong { font-family: var(--font-heading); font-size: 0.78rem; font-weight: 700; line-height: 1.25; }

.projects-cta {
  display: flex;
  justify-content: center;
  margin-top: clamp(1.75rem, 1.4rem + 1.5vw, 2.5rem);
}

/* ==========================================================================
   Key Facts
   ========================================================================== */
/* No local overflow-x here — see the note on .projects above. This one
   matters even more: .facts-scene deliberately bleeds past the bottom of
   this section into .process via a negative margin, and a stray
   overflow-y:auto here (the side effect of adding overflow-x:hidden
   directly on this section) would clip that bleed and turn the section
   into its own tiny scrollable box instead of just flowing with the page. */
/* No background/padding of its own on purpose — the full-bleed sky
   scene inside now IS the section's visual body (heading, legend and
   the house diagram all live inside .facts-scene), so this outer
   element only needs to exist as the positioning/flow parent. */
.facts { position: relative; }

/* Full-bleed sky "scene", edge-to-edge regardless of where the section
   sits (same 100vw + negative-margin trick as .projects-marquee above —
   horizontal clipping comes from html/body's page-wide overflow-x:hidden,
   not from this section, on purpose). Day/night is one class toggle here
   — ::before is the day sky, ::after is a starry night sky, and they
   cross-fade on opacity so no second photo is needed. The negative
   bottom margin + z-index deliberately bleed the scene down over the top
   of the next section, so the house reads as sitting "in front of" the
   page rather than boxed inside its own card. Extra padding-block vs the
   old version because the heading/legend copy now lives inside here too
   (left column, house diagram on the right) instead of in its own boxed
   row above the scene. */
.facts-scene {
  position: relative;
  z-index: 2;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  /* This deep a negative pull only actually makes sense in the desktop
     2-column layout it was tuned for (grid-template-columns kicks in at
     960px below) — the house's own bottom edge sits at the true bottom
     of the scene there, so the bleed lands on real grass. Below 960px
     the stacked layout doesn't have that same relationship, and the
     same pull just left too little breathing room before "How It
     Works" — measured out to only ~55-60px of actual visible gap,
     which read as cramped/messy against a dark night-mode background.
     Scaled back hard for that range below. */
  margin-bottom: clamp(-12rem, -3.5rem - 6vw, -5.5rem);
  padding-block: clamp(3.5rem, 2.6rem + 4.5vw, 6rem) clamp(0.6rem, 0.4rem + 0.8vw, 1rem);
  isolation: isolate;
}
@media (max-width: 959px) {
  .facts-scene {
    margin-bottom: clamp(-4rem, -1.5rem - 2vw, -2rem);
  }
}
/* Desktop's own gap (the bleed effect is real and correct here — this
   just softens it a little) measured out to only ~60-75px of visible
   space before "How It Works", noticeably tighter than the ~115-130px
   the stacked layout gets above. Pulling the negative margin back by
   roughly 30-40px closes that gap between the two without undoing the
   grass/house bleed the desktop 2-column layout was built around. */
@media (min-width: 960px) {
  .facts-scene {
    margin-bottom: clamp(-9rem, -2.2rem - 5vw, -4.5rem);
  }
}
/* Long diagonal sweep across the whole scene (full width/height, not
   scoped to the house) — z-index:-1 puts it behind every normal-flow
   child of .facts-scene (the grid content, the house, the hotspots),
   since in-flow/positioned-with-z-index content always paints above a
   negative-z-index sibling regardless of DOM order or how the shape
   happens to sit underneath it. That means the house/copy/hotspots
   never get CUT by this — but a solid white shape sitting directly
   behind near-white night-mode text is still a contrast problem even
   though it paints underneath (white-on-white), so the polygon is
   still tuned to stay clear of the legend list, just against real
   measured rects instead of guesswork: stacked mobile/tablet layout
   keeps a shallow rise (legend bottom sits as low as ~60% of the scene
   there), while the desktop 2-column layout stays flat at the very
   bottom through the text column's own width (~41% measured, 42% used
   for margin) before rising steeply through the house's side only. */
.facts-diagonal {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--white);
  clip-path: polygon(0% 100%, 100% 68%, 100% 100%);
}
@media (min-width: 960px) {
  .facts-diagonal {
    clip-path: polygon(0% 100%, 42% 100%, 100% 30%, 100% 100%);
  }
}
/* At night the wedge's top-right corner reaches high enough to land in
   open sky (right where the moon sits). Two color-matching attempts
   (flat white, then a dark-to-white gradient) both still showed up as a
   distinct shape against the sky — any gradient stops that don't
   perfectly match .facts-scene::after's sky gradient pixel-for-pixel
   read as a visible patch or beam. Turns out the wedge isn't actually
   needed here at all: the area it would otherwise cover at the bottom
   is already covered by the house/ground artwork sitting in front of
   it, so simply hiding it for night mode removes the artifact with no
   visible seam anywhere (checked 745/1024/1440px). */
.facts-scene.is-night .facts-diagonal {
  opacity: 0;
}
.facts-scene-inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2rem, 1.5rem + 2vw, 3rem);
  align-items: center;
}
@media (min-width: 960px) {
  .facts-scene-inner {
    /* End-aligned (not centered) on purpose: the copy column is usually
       shorter than the house/diagram column, and centering the shorter
       one left a dead band of empty sky under the house before the
       negative-margin bleed even started, so the grass never actually
       reached the next section — it just looked like the sky ended early.
       Anchoring both columns to the row's bottom means the house's own
       bottom edge sits at the true bottom of the scene, so the bleed
       margin below actually lands on the grass. */
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    gap: clamp(2.5rem, 1.5rem + 4vw, 4.5rem);
    align-items: end;
  }
  /* The grid row's own height is set by the house/diagram column (the
     taller of the two), and align-items:end above anchors BOTH columns
     to that row's bottom edge — necessary for the bleed (see comment
     above), but it also means the much-shorter copy column gets pushed
     all the way down to match, leaving a tall dead gap above "WHY RPG"
     that the house doesn't have, so the headline reads noticeably lower
     than the house/toggle it's sitting next to. align-self:stretch pulls
     just the copy column back to the row's full height without touching
     the row's own height or the visual column's position, then the
     flex column centers its actual content within that height — so the
     headline lines up with the house's vertical centre instead of its
     bottom edge. */
  .facts-copy.section-heading {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}
.facts-copy.section-heading {
  text-align: left;
  max-width: none;
  margin-inline: 0;
  margin-bottom: 0;
}
.facts-copy .section-eyebrow,
.facts-copy h2,
.facts-copy p:not(.section-eyebrow) {
  transition: color 0.6s ease;
}
.facts-copy p:not(.section-eyebrow) { margin-inline: 0; max-width: 42ch; }
.facts-copy .facts-legend { margin-inline: 0; }
.facts-scene.is-night .facts-copy h2 { color: var(--white); }
.facts-scene.is-night .facts-copy .text-red {
  background: linear-gradient(120deg, #ff6b6b 25%, #ffffff 115%);
  -webkit-background-clip: text;
  background-clip: text;
}
.facts-scene.is-night .facts-copy p:not(.section-eyebrow) { color: rgba(255, 255, 255, 0.78); }
.facts-scene.is-night .facts-copy .facts-legend li { color: rgba(255, 255, 255, 0.82); }
.facts-visual { min-width: 0; }
.facts-scene::before,
.facts-scene::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -2;
  transition: opacity 0.7s ease;
}
.facts-scene::before {
  opacity: 1;
  background:
    radial-gradient(60% 55% at 80% 10%, rgba(255, 196, 110, 0.5) 0%, rgba(255, 196, 110, 0) 60%),
    linear-gradient(180deg, #dbe9fb 0%, #eaf2fb 38%, #f5f8fb 72%, #eef1e6 100%);
}
.facts-scene::after {
  opacity: 0;
  background:
    radial-gradient(1.6px 1.6px at 12% 22%, rgba(255,255,255,0.9), transparent 60%),
    radial-gradient(1.6px 1.6px at 82% 14%, rgba(255,255,255,0.85), transparent 60%),
    radial-gradient(1.2px 1.2px at 42% 62%, rgba(255,255,255,0.75), transparent 60%),
    radial-gradient(1.6px 1.6px at 66% 78%, rgba(255,255,255,0.8), transparent 60%),
    radial-gradient(1.2px 1.2px at 24% 82%, rgba(255,255,255,0.65), transparent 60%),
    radial-gradient(1.6px 1.6px at 92% 58%, rgba(255,255,255,0.75), transparent 60%),
    radial-gradient(1.2px 1.2px at 55% 30%, rgba(255,255,255,0.65), transparent 60%),
    radial-gradient(1.2px 1.2px at 8% 55%, rgba(255,255,255,0.6), transparent 60%),
    linear-gradient(180deg, #0a0f38 0%, #131a5e 45%, #1c2470 78%, #232a63 100%);
}
.facts-scene.is-night::before { opacity: 0; }
.facts-scene.is-night::after { opacity: 1; }

/* Two soft cloud shapes drifting slowly left-to-right across the sky. A
   wide (200%) tiled layer animated with a plain transform loops forever
   without a visible seam, since translating by exactly one tile width
   (480px) lands back on an identical frame. Fades out at night so it
   doesn't compete with the stars. */
.facts-clouds {
  position: absolute;
  top: 6%;
  left: 0;
  right: 0;
  height: 40%;
  overflow: hidden;
  z-index: -1;
  pointer-events: none;
}
.facts-clouds::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 200%;
  height: 100%;
  background-color: #ffffff;
  -webkit-mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgMjAwIj4KICA8ZGVmcz4KICAgIDxmaWx0ZXIgaWQ9InNvZnQiIHg9Ii01MCUiIHk9Ii01MCUiIHdpZHRoPSIyMDAlIiBoZWlnaHQ9IjIwMCUiPgogICAgICA8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSI1Ii8+CiAgICA8L2ZpbHRlcj4KICA8L2RlZnM+CiAgPGcgZmlsbD0iIzAwMCIgZmlsdGVyPSJ1cmwoI3NvZnQpIj4KICAgIDxlbGxpcHNlIGN4PSIxMTAiIGN5PSIxMTAiIHJ4PSI1OCIgcnk9IjE4IiBvcGFjaXR5PSIwLjc1Ii8+CiAgICA8ZWxsaXBzZSBjeD0iMTUwIiBjeT0iOTUiIHJ4PSI0MiIgcnk9IjIyIiBvcGFjaXR5PSIwLjkiLz4KICAgIDxlbGxpcHNlIGN4PSIxOTUiIGN5PSIxMDgiIHJ4PSI0NyIgcnk9IjE2IiBvcGFjaXR5PSIwLjc4Ii8+CiAgICA8ZWxsaXBzZSBjeD0iNzAiIGN5PSIxMDUiIHJ4PSIzMiIgcnk9IjEzIiBvcGFjaXR5PSIwLjU1Ii8+CiAgICA8ZWxsaXBzZSBjeD0iMzQ1IiBjeT0iODgiIHJ4PSI1MCIgcnk9IjE2IiBvcGFjaXR5PSIwLjY4Ii8+CiAgICA8ZWxsaXBzZSBjeD0iMzgwIiBjeT0iNzIiIHJ4PSIzOCIgcnk9IjIwIiBvcGFjaXR5PSIwLjg1Ii8+CiAgICA8ZWxsaXBzZSBjeD0iNDE1IiBjeT0iODYiIHJ4PSI0MCIgcnk9IjE0IiBvcGFjaXR5PSIwLjYiLz4KICA8L2c+Cjwvc3ZnPg==');
  mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0ODAgMjAwIj4KICA8ZGVmcz4KICAgIDxmaWx0ZXIgaWQ9InNvZnQiIHg9Ii01MCUiIHk9Ii01MCUiIHdpZHRoPSIyMDAlIiBoZWlnaHQ9IjIwMCUiPgogICAgICA8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSI1Ii8+CiAgICA8L2ZpbHRlcj4KICA8L2RlZnM+CiAgPGcgZmlsbD0iIzAwMCIgZmlsdGVyPSJ1cmwoI3NvZnQpIj4KICAgIDxlbGxpcHNlIGN4PSIxMTAiIGN5PSIxMTAiIHJ4PSI1OCIgcnk9IjE4IiBvcGFjaXR5PSIwLjc1Ii8+CiAgICA8ZWxsaXBzZSBjeD0iMTUwIiBjeT0iOTUiIHJ4PSI0MiIgcnk9IjIyIiBvcGFjaXR5PSIwLjkiLz4KICAgIDxlbGxpcHNlIGN4PSIxOTUiIGN5PSIxMDgiIHJ4PSI0NyIgcnk9IjE2IiBvcGFjaXR5PSIwLjc4Ii8+CiAgICA8ZWxsaXBzZSBjeD0iNzAiIGN5PSIxMDUiIHJ4PSIzMiIgcnk9IjEzIiBvcGFjaXR5PSIwLjU1Ii8+CiAgICA8ZWxsaXBzZSBjeD0iMzQ1IiBjeT0iODgiIHJ4PSI1MCIgcnk9IjE2IiBvcGFjaXR5PSIwLjY4Ii8+CiAgICA8ZWxsaXBzZSBjeD0iMzgwIiBjeT0iNzIiIHJ4PSIzOCIgcnk9IjIwIiBvcGFjaXR5PSIwLjg1Ii8+CiAgICA8ZWxsaXBzZSBjeD0iNDE1IiBjeT0iODYiIHJ4PSI0MCIgcnk9IjE0IiBvcGFjaXR5PSIwLjYiLz4KICA8L2c+Cjwvc3ZnPg==');
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
  -webkit-mask-size: 480px 100%;
  mask-size: 480px 100%;
  opacity: 0.88;
  animation: factsCloudsDrift 70s linear infinite;
  transition: opacity 0.7s ease;
}
.facts-scene.is-night .facts-clouds::before { opacity: 0.16; }
@keyframes factsCloudsDrift {
  from { transform: translateX(0); }
  to { transform: translateX(-480px); }
}
@media (prefers-reduced-motion: reduce) {
  .facts-clouds::before { animation: none; }
}

.facts-scene-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
}
.facts-scene-label {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--gray-600);
  transition: color 0.5s ease;
}
.facts-scene-label[data-state="day"] { color: var(--navy-900); }
.facts-scene.is-night .facts-scene-label[data-state="day"] { color: rgba(255, 255, 255, 0.5); }
.facts-scene.is-night .facts-scene-label[data-state="night"] { color: var(--white); }

.facts-daynight {
  position: relative;
  width: 50px;
  height: 27px;
  border-radius: var(--radius-pill);
  border: none;
  padding: 3px;
  background: linear-gradient(90deg, #ffd27a, #ffb347);
  cursor: pointer;
  transition: background 0.5s ease;
  flex-shrink: 0;
}
.facts-daynight-thumb {
  display: block;
  width: 21px;
  height: 21px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: 0 2px 6px rgba(6, 11, 77, 0.3);
  transform: translateX(0);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), background 0.5s ease;
}
.facts-scene.is-night .facts-daynight { background: linear-gradient(90deg, #2b3570, #10143f); }
.facts-scene.is-night .facts-daynight-thumb { transform: translateX(23px); background: #e8ebff; }
.facts-daynight:focus-visible { outline: 3px solid var(--red-600); outline-offset: 3px; }

.facts-scene-caption {
  text-align: center;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--gray-600);
  margin: 0.5rem auto clamp(0.75rem, 0.5rem + 0.8vw, 1.1rem);
  max-width: 34rem;
  transition: color 0.6s ease;
}
.facts-scene-caption-night { display: none; }
.facts-scene.is-night .facts-scene-caption { color: rgba(255, 255, 255, 0.82); }
.facts-scene.is-night .facts-scene-caption-day { display: none; }
.facts-scene.is-night .facts-scene-caption-night { display: inline; }

/* Battery status badge — the concrete payoff that makes day/night mean
   something rather than just a colour swap: the fill animates upward
   (charging from solar) by day and downward (discharging to power the
   home instead of TNB) by night. */
.facts-battery {
  position: absolute;
  /* Sized up a bit from the original pill — the power line's day-mode
     start point lands right at this corner, and a small pill left the
     line's node/dashes poking out past the rounded corner instead of
     being covered by it. Padding alone can't fix that (the box's own
     top edge was sitting ~24px down while the line's node was only
     ~14px down, i.e. above the pill entirely) so `top` moves up too —
     bigger pill, pulled further into the corner, actually sits on top
     of that point now instead of just growing away from it. */
  left: clamp(0.75rem, 2vw, 1.5rem);
  top: clamp(0.35rem, 1vw, 0.65rem);
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 0.95rem 0.6rem 0.75rem;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.9);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--navy-900);
  z-index: 3;
  transition: background 0.6s ease, color 0.6s ease;
  white-space: nowrap;
  animation: factsBatteryGlow 2.4s ease-in-out infinite;
}
@keyframes factsBatteryGlow {
  0%, 100% { box-shadow: 0 10px 22px -12px rgba(6, 11, 77, 0.4), 0 0 0 0 rgba(47, 174, 92, 0); }
  50% { box-shadow: 0 10px 22px -12px rgba(6, 11, 77, 0.4), 0 0 14px 3px rgba(47, 174, 92, 0.45); }
}
.facts-scene.is-night .facts-battery { animation-name: factsBatteryGlowNight; }
@keyframes factsBatteryGlowNight {
  0%, 100% { box-shadow: 0 10px 22px -12px rgba(0, 0, 0, 0.5), 0 0 0 0 rgba(125, 211, 252, 0); }
  50% { box-shadow: 0 10px 22px -12px rgba(0, 0, 0, 0.5), 0 0 14px 3px rgba(125, 211, 252, 0.5); }
}
.facts-battery-icon {
  position: relative;
  width: 22px;
  height: 13px;
  border: 1.6px solid var(--navy-900);
  border-radius: 2px;
  flex-shrink: 0;
  transition: border-color 0.6s ease;
}
.facts-battery-icon::after {
  content: '';
  position: absolute;
  right: -4px;
  top: 50%;
  transform: translateY(-50%);
  width: 2.5px;
  height: 5px;
  background: var(--navy-900);
  border-radius: 0 1px 1px 0;
  transition: background 0.6s ease;
}
.facts-battery-fill {
  position: absolute;
  left: 1.5px;
  top: 1.5px;
  bottom: 1.5px;
  width: 35%;
  background: #2fae5c;
  border-radius: 1px;
  animation: factsBatteryCharge 2.4s ease-in-out infinite;
}
@keyframes factsBatteryCharge {
  0%, 100% { width: 25%; }
  50% { width: 90%; }
}
@keyframes factsBatteryDischarge {
  0%, 100% { width: 90%; }
  50% { width: 25%; }
}
.facts-battery-bolt {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 9px;
  height: 9px;
  transform: translate(-50%, -50%) scale(0.85);
  fill: rgba(255, 255, 255, 0.95);
  filter: drop-shadow(0 0 1.5px rgba(0, 0, 0, 0.3));
  opacity: 0.6;
  animation: factsBoltPulse 2.4s ease-in-out infinite;
  pointer-events: none;
}
@keyframes factsBoltPulse {
  0%, 100% { opacity: 0.55; transform: translate(-50%, -50%) scale(0.8); }
  50% { opacity: 1; transform: translate(-50%, -50%) scale(1.2); }
}
.facts-battery-dots {
  position: absolute;
  left: 2px;
  top: 50%;
  width: 20px;
  height: 26px;
  transform: translateY(-50%);
  pointer-events: none;
}
.facts-battery-dots span {
  position: absolute;
  bottom: -2px;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: #2fae5c;
  opacity: 0;
  animation: factsDotRise 2.4s ease-in infinite;
}
.facts-battery-dots span:nth-child(1) { left: 1px; animation-delay: 0s; }
.facts-battery-dots span:nth-child(2) { left: 8px; animation-delay: 0.5s; }
.facts-battery-dots span:nth-child(3) { left: 15px; animation-delay: 1s; }
@keyframes factsDotRise {
  0% { opacity: 0; transform: translateY(0); }
  15% { opacity: 1; }
  70% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(-22px); }
}
@keyframes factsDotFall {
  0% { opacity: 0; transform: translateY(0); }
  15% { opacity: 1; }
  70% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(22px); }
}
.facts-battery-label--night { display: none; }
.facts-scene.is-night .facts-battery { background: rgba(15, 20, 60, 0.82); color: var(--white); }
.facts-scene.is-night .facts-battery-icon { border-color: var(--white); }
.facts-scene.is-night .facts-battery-icon::after { background: var(--white); }
.facts-scene.is-night .facts-battery-fill { background: #7dd3fc; animation-name: factsBatteryDischarge; }
.facts-scene.is-night .facts-battery-dots span { bottom: auto; top: -2px; background: #7dd3fc; animation-name: factsDotFall; }
.facts-scene.is-night .facts-battery-label--day { display: none; }
.facts-scene.is-night .facts-battery-label--night { display: inline; }

@media (prefers-reduced-motion: reduce) {
  .facts-battery-fill { animation: none; width: 60%; }
  .facts-battery { animation: none; }
  .facts-battery-bolt { animation: none; opacity: 0.85; transform: translate(-50%, -50%) scale(1); }
  .facts-battery-dots span { animation: none; opacity: 0; }
}

/* House + rooftop-solar illustration with 6 hotspots — replaces the old
   dense 6-card text grid. Same "diagram + click-anchored tooltip" pattern
   as the Financing radial (positioning math, clamping, open/close
   behavior all mirror it deliberately, for one consistent interaction
   language across the site). */
.facts-diagram {
  position: relative;
  width: 100%;
  max-width: 58rem;
  margin: 0 auto;
  padding-inline: clamp(1rem, 4vw, 2rem);
}
.facts-photo {
  position: relative;
  width: 100%;
}
.facts-photo-house {
  width: 100%;
  height: auto;
  display: block;
  position: relative;
  z-index: 1;
  filter: brightness(1) saturate(1) hue-rotate(0deg);
  transition: filter 0.7s ease;
}
.facts-scene.is-night .facts-photo-house {
  filter: brightness(0.55) saturate(0.85) contrast(1.08) hue-rotate(-6deg);
}

/* Warm "lights on" glow blobs over the window/glass areas — screen-blended
   so they only ever add light on top of the darkened night house filter,
   never a flat colour wash. Off by day (the house photo's own daylight
   glass reads fine on its own); cross-fade in with the rest of the night
   state. Percentages are eyeballed against the actual house.png crop. */
.facts-window-glow {
  position: absolute;
  z-index: 2;
  pointer-events: none;
  border-radius: 50%;
  filter: blur(4px);
  background: radial-gradient(circle, rgba(255, 214, 145, 1) 0%, rgba(255, 195, 120, 0.85) 40%, rgba(255, 180, 100, 0) 78%);
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.8s ease;
}
.facts-scene.is-night .facts-window-glow { opacity: 1; }
/* Positions re-measured directly against the house.png pixels (cropping
   and zooming in on each window) rather than eyeballing the full photo,
   since the first pass left the bedroom/loft glows centred slightly off
   the actual glass and reading much fainter than the dining one. */
.facts-window-glow--loft { left: 25%; top: 15%; width: 21%; height: 20%; }
.facts-window-glow--bedroom { left: 15%; top: 47%; width: 13%; height: 24%; }
.facts-window-glow--dining { left: 43%; top: 44%; width: 16%; height: 30%; }
/* The loft and bedroom windows start from a paler/cooler base (reflected
   sky, thin curtains) than the dining glass, so the same screen-blended
   glow reads as a pale wash there instead of a warm lit-room colour —
   stronger, more saturated stops compensate so all three read as
   consistently "lit" rather than dining being the only convincing one. */
.facts-window-glow--loft,
.facts-window-glow--bedroom {
  filter: blur(3px);
  background: radial-gradient(circle, rgba(255, 205, 120, 1) 0%, rgba(255, 175, 90, 1) 35%, rgba(255, 160, 70, 0) 78%);
}
@media (prefers-reduced-motion: reduce) {
  .facts-window-glow { transition: none; }
}

/* Power flow line — day: panels charging the battery; night: battery
   powering the house. Two separate paths (not one path animated in
   reverse) since they're conceptually different connections, cross-
   faded the same way as the sun/moon. viewBox 0 0 100 100 +
   preserveAspectRatio="none" maps path coordinates straight onto
   left/top percentages, same coordinate space the hotspots use, so it
   stays correctly anchored to the panels/battery/house at any size. */
.facts-power {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  pointer-events: none;
  overflow: visible;
}
/* v3: a real neon-cable look — a wide, blurred, solid "glow" line sits
   underneath the crisp dashed line on top, the way a bright cable glows
   into the surface around it rather than just having a thin drop-shadow
   fringe. Both layers use vector-effect: non-scaling-stroke so their
   width stays true screen pixels regardless of this SVG's non-uniform
   stretch. Routing was reworked to keep real distance from every hotspot
   marker (v2 accidentally ran right past two of them, which is why it
   read as clutter rather than its own system) — colours still match the
   battery's own day/night palette (#2fae5c charging green, #7dd3fc
   discharging blue) so the line, the battery fill and the dots read as
   one consistent system. */
.facts-power-glow {
  fill: none;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 6;
  filter: blur(2.5px);
  /* No crossfade on purpose — a day/night pair that fades in/out over
     0.6s leaves a window where both are partially visible at once, which
     showed up as a stray "ghost" node of the other mode's colour still
     hanging in the sky if a screenshot (or just a glance) caught it
     mid-transition. Everything in the power-line system switches
     instantly instead, so there's never a frame with both states on
     screen together. */
  transition: none;
}
.facts-power-glow--day {
  stroke: rgba(47, 174, 92, 0.55);
  opacity: 1;
}
.facts-power-glow--night {
  stroke: rgba(125, 211, 252, 0.55);
  opacity: 0;
}
.facts-scene.is-night .facts-power-glow--day { opacity: 0; }
.facts-scene.is-night .facts-power-glow--night { opacity: 1; }
.facts-power-path {
  fill: none;
  stroke-width: 2.2;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 4.5 3.5;
  animation: factsPowerFlow 1s linear infinite;
  transition: none;
}
.facts-power-path--day {
  stroke: #baf7d1;
  opacity: 1;
  filter: drop-shadow(0 0 2px rgba(47, 174, 92, 0.95));
}
.facts-power-path--night {
  stroke: #eaf8ff;
  opacity: 0;
  filter: drop-shadow(0 0 2px rgba(125, 211, 252, 0.95));
}
.facts-scene.is-night .facts-power-path--day { opacity: 0; }
.facts-scene.is-night .facts-power-path--night { opacity: 1; }
@keyframes factsPowerFlow {
  to { stroke-dashoffset: -16; }
}
/* Nodes and the animated dot are plain HTML spans, not SVG circles —
   .facts-power's viewBox is stretched non-uniformly (preserveAspectRatio:
   none) to map path coordinates to left/top %, and while straight path
   segments survive that stretch fine, SVG <circle> elements don't: they
   squash into visibly lopsided ellipses. A span with border-radius:50%
   is sized in real pixels against the actual (non-square) box, so it
   stays a true circle. Positioned with the same left/top % coordinate
   space the hotspots already use. */
.facts-power-node {
  position: absolute;
  z-index: 2;
  width: 9px;
  height: 9px;
  margin-left: -4.5px;
  margin-top: -4.5px;
  border-radius: 50%;
  pointer-events: none;
  transition: none;
}
.facts-power-node--day {
  background: #eafff2;
  opacity: 1;
  box-shadow: 0 0 0 2px rgba(47, 174, 92, 0.35), 0 0 8px 2px rgba(47, 174, 92, 0.9);
}
.facts-power-node--night {
  background: #f2fbff;
  opacity: 0;
  box-shadow: 0 0 0 2px rgba(125, 211, 252, 0.35), 0 0 8px 2px rgba(125, 211, 252, 0.9);
}
.facts-scene.is-night .facts-power-node--day { opacity: 0; }
.facts-scene.is-night .facts-power-node--night { opacity: 1; }
.facts-power-dot {
  position: absolute;
  z-index: 2;
  left: 0;
  top: 0;
  width: 7.5px;
  height: 7.5px;
  margin-left: -3.75px;
  margin-top: -3.75px;
  border-radius: 50%;
  pointer-events: none;
  transition: none;
}
/* The real bug behind the "stray dot left glowing in the sky" report:
   these dots animate their OWN opacity as part of the travel keyframes
   (fade in, travel, fade out), so pausing the animation to hide the
   inactive mode's dot (animation-play-state: paused) just freezes it at
   whatever point its 1.7s loop happened to be on — including moments
   where its own keyframe opacity is 1. The frozen animated value wins
   over the plain `opacity: 0` declared right there in the same rule, so
   the "hidden" dot could stay stuck fully visible after leaving that
   mode, indefinitely, until the mode was switched back on. Fix: don't
   pause it, detach the animation entirely (animation: none) whenever
   the mode is inactive, so the element has nothing left to override its
   own opacity:0 with. Restarting fresh from 0% each time a mode
   re-activates is fine — this is a decorative loop, not something that
   needs to resume mid-cycle. */
.facts-power-dot--day {
  background: #eafff2;
  opacity: 0;
  box-shadow: 0 0 9px 3px #2fae5c;
}
.facts-power-dot--night {
  background: #f2fbff;
  opacity: 0;
  box-shadow: 0 0 9px 3px #7dd3fc;
}
.facts-scene:not(.is-night) .facts-power-dot--day {
  opacity: 1;
  animation: factsPowerDotDay 1.7s ease-in-out infinite;
}
.facts-scene.is-night .facts-power-dot--night {
  opacity: 1;
  animation: factsPowerDotNight 1.7s ease-in-out infinite;
}
/* Keyframe stops follow the path's own vertices (start / elbow / end)
   rather than a curve interpolation, weighted roughly by each segment's
   share of the total path length so the dot doesn't appear to speed up
   or slow down at the corner. */
@keyframes factsPowerDotDay {
  0%, 6% { left: 14%; top: 32%; opacity: 0; }
  16% { opacity: 1; }
  60% { left: 14%; top: 13%; }
  86% { opacity: 1; }
  94%, 100% { left: 6%; top: 6%; opacity: 0; }
}
@keyframes factsPowerDotNight {
  0%, 6% { left: 7%; top: 9%; opacity: 0; }
  16% { opacity: 1; }
  60% { left: 7%; top: 45%; }
  86% { opacity: 1; }
  94%, 100% { left: 22%; top: 58%; opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .facts-power-path { animation: none; }
  .facts-power-dot { animation: none; opacity: 0; }
}

/* CSS-drawn sun (was a PNG glow blob — the asset had a visibly jagged,
   scalloped edge instead of a clean radial bloom). Same size/position as
   .facts-moon so the two sit exactly on top of one another and cross-
   fade cleanly instead of jumping between two different spots. Layered
   radial-gradient disc (bright core fading to a soft orange edge) plus
   two box-shadow rings gives the glow/bloom the PNG was trying for,
   without the hard edge. */
.facts-sun {
  position: absolute;
  top: -9%;
  left: 88%;
  width: 13%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #fffdf2 0%, #ffedb0 22%, #ffcd6b 48%, #ffab3d 75%, rgba(255, 171, 61, 0) 100%);
  box-shadow: 0 0 36px 12px rgba(255, 197, 110, 0.55), 0 0 80px 30px rgba(255, 176, 90, 0.28);
  z-index: 0;
  pointer-events: none;
  /* Disabled for day mode — the day scene already reads bright on its
     own, the sun disc on top of it felt redundant. Not deleted: still
     fully styled above, just switch this to opacity: 1 (and drop the
     is-night override below, which would otherwise fight it) to bring
     it back. */
  opacity: 0;
  transition: opacity 0.6s ease;
}
.facts-scene.is-night .facts-sun { opacity: 0; }
.facts-moon {
  position: absolute;
  top: -9%;
  left: 88%;
  width: 13%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #fdfdff 0%, #e4e8f5 45%, #b9c0dc 100%);
  box-shadow: 0 0 55px 16px rgba(210, 220, 255, 0.4);
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.7s ease;
}
.facts-scene.is-night .facts-moon { opacity: 1; }
/* This warm (orange-toned) ambient glow was built for the sun, back
   before .facts-sun existed as its own CSS-drawn disc with its own
   bloom (box-shadow rings). It ended up wired to opacity:1 only in
   night mode instead — the exact opposite of a sun glow's daytime job —
   so it's been screen-blending an orange-tinted patch over the moon at
   night this whole time. That's the rectangular light patch that kept
   surviving the .facts-diagonal fixes: two completely different
   elements were producing similar-looking artifacts in the same corner.
   The moon already has its own matching-toned halo via its own
   box-shadow, so this glow isn't needed for either day or night —
   left fully retired (opacity: 0 always, in both rules below) rather
   than deleted outright, in case a future glow effect wants to reuse
   the positioning/gradient. */
.facts-glow {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: radial-gradient(28% 30% at 92% 4%, rgba(255, 210, 140, 0.55) 0%, rgba(255, 210, 140, 0) 70%);
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.7s ease;
}
.facts-scene.is-night .facts-glow { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .facts-scene::before, .facts-scene::after, .facts-photo-house,
  .facts-sun, .facts-moon, .facts-glow, .facts-daynight, .facts-daynight-thumb,
  .facts-scene-label { transition: none; }
}

.facts-hotspot {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  z-index: 3;
}
.facts-hotspot-dot {
  position: relative;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--red-600);
  border: 2.5px solid var(--white);
  box-shadow: 0 2px 6px rgba(6, 11, 77, 0.3);
  transition: transform 0.2s var(--ease);
}
.facts-hotspot-dot::after {
  content: '';
  position: absolute;
  inset: -8px;
  border-radius: 50%;
  border: 1.5px solid var(--red-600);
  opacity: 0.55;
  animation: factsHotspotPulse 2.2s var(--ease) infinite;
}
.facts-hotspot:hover .facts-hotspot-dot,
.facts-hotspot:focus-visible .facts-hotspot-dot,
.facts-hotspot.is-active .facts-hotspot-dot { transform: scale(1.2); }
.facts-hotspot.is-active .facts-hotspot-dot::after { animation-play-state: paused; opacity: 0.3; }
@keyframes factsHotspotPulse {
  0% { transform: scale(0.7); opacity: 0.55; }
  100% { transform: scale(1.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .facts-hotspot-dot::after { animation: none; opacity: 0.35; }
}

/* Positioned in JS (facts hotspot section of script.js) relative to
   whichever dot was clicked, using the exact same viewport/landmark
   clamping approach as the Financing tooltip so it never covers the
   heading above or runs off past the illustration's own edges. */
.facts-tooltip {
  position: absolute;
  width: min(260px, calc(100% - 16px));
  max-width: 260px;
  background: var(--white);
  border: 1.5px solid rgba(6, 11, 77, 0.14);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 0.9rem 1.05rem;
  text-align: left;
  z-index: 5;
  /* Purely informational, so let clicks pass straight through to
     whatever's underneath — on narrow viewports (and with several
     hotspots fairly close together) this box can end up covering a
     neighboring hotspot; without this, tapping there would just hit the
     tooltip's own background and do nothing instead of switching. */
  pointer-events: none;
}
.facts-tooltip::before {
  content: '';
  position: absolute;
  left: var(--arrow-left, 50%);
  width: 12px;
  height: 12px;
  background: var(--white);
  border: 1.5px solid rgba(6, 11, 77, 0.14);
  transform: translateX(-50%) rotate(45deg);
}
.facts-tooltip.is-below::before { top: -7px; border-right: none; border-bottom: none; }
.facts-tooltip.is-above::before { bottom: -7px; border-left: none; border-top: none; }
.facts-tooltip-stat {
  display: block;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.3rem;
  color: var(--red-600);
  line-height: 1.15;
}
.facts-tooltip h3 { font-size: 0.9rem; margin: 0.15rem 0 0.35rem; color: var(--gray-600); font-weight: 700; }
.facts-tooltip p { font-size: 0.84rem; color: var(--gray-600); line-height: 1.55; margin: 0; }

/* Quiet static legend under the diagram — orients the eye at a glance
   (what each dot means) without requiring every hotspot to be clicked
   just to know what's on offer. Decorative/redundant with the hotspots'
   own accessible names, so it's aria-hidden. */
.facts-legend {
  list-style: none;
  margin: clamp(1.5rem, 1.2rem + 1vw, 2rem) auto 0;
  padding: 0;
  max-width: 40rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.55rem;
}
@media (min-width: 640px) and (max-width: 959px) {
  .facts-legend { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
}
/* Desktop had no override here at all, so it fell back to the 1-column
   base rule — 6 items stacked into 6 rows, reading much taller/heavier
   than the rest of the copy block next to it. 2 rows instead, by request.
   A no-wrap auto-sized-column layout (grid-auto-flow: column) looks
   great in isolation, but the copy column here (.facts-copy) only runs
   ~330-515px wide across the whole 960-1920px desktop range — never
   enough room for 3 nowrap columns side by side ("Net Energy Metering
   Credits" alone needs ~200px). So instead: equal-width 3-column grid,
   wrapping allowed. 6 items / 3 columns always lands as exactly 2 rows
   structurally; the longest item or two may wrap to a second line
   within its own cell on the narrower end of the range, but the grid
   itself never grows past 2 rows and every cell in a row still aligns. */
@media (min-width: 960px) {
  .facts-legend {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-flow: row;
    column-gap: 1.25rem;
    row-gap: 0.5rem;
    max-width: none;
  }
  .facts-legend li { white-space: normal; }
}
.facts-legend li {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.82rem;
  color: var(--gray-600);
}
.facts-legend-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--red-600); flex-shrink: 0; }

/* ==========================================================================
   How It Works (process timeline)
   ========================================================================== */
/* Extra top padding (beyond the usual section rhythm) makes room for
   .facts-scene's negative bottom margin to bleed the house/garden down
   over this section without ever crowding the heading text below it. */
.process {
  /* z-index:0 (not just position:relative) is required here, not
     decorative — without an explicit z-index this element never
     actually establishes its own stacking context, so .process-texture's
     z-index:-1 doesn't stay scoped "behind this section's own content"
     the way it looks like it should; it escapes all the way up to the
     page's root stacking context instead and ends up behind literally
     everything on the page, .process's own white background included,
     which is indistinguishable from "not rendering at all". Confirmed by
     forcing the texture to solid red: invisible at z-index:-1 without
     this, fully visible once this was added. */
  position: relative;
  z-index: 0;
  background: var(--white);
  padding-bottom: clamp(3.5rem, 2.8rem + 3vw, 6.5rem);
  /* Was clamp(8rem, 5rem + 9vw, 14rem) — that oversized top padding was
     sized to swallow .facts-scene's negative-margin bleed back when Key
     Facts sat directly above this section. Sections got reordered since
     (.edge now absorbs that bleed with its own large padding-top), so
     .process no longer needs to reserve extra space here; leftover value
     was showing up as a huge dead gap under "See All Projects". */
  padding-top: clamp(3.5rem, 2.8rem + 3vw, 6.5rem);
}
/* Soft gradient instead of a dot-grid pattern (tried that first, it read
   as noisy/dirty rather than a subtle surface) — a faint red glow in the
   top-left and navy glow in the bottom-right, on a barely-there white-to-
   gray wash, so the section still reads as having some depth without
   ever stopping being a plain light background. Sits behind
   .site-container (z-index:-1) so it never competes with the simulator/
   content on top of it. */
.process-texture {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: -1;
  background-image:
    radial-gradient(48% 40% at 12% 8%, rgba(209, 36, 36, 0.06), transparent 65%),
    radial-gradient(52% 42% at 92% 96%, rgba(6, 11, 77, 0.07), transparent 65%),
    linear-gradient(160deg, #ffffff 0%, #f8f9fc 55%, #f3f4f8 100%);
}

/* Interactive date simulator — redesigned as a clear top-to-bottom flow
   instead of one row of four loosely arrow-connected columns (which kept
   reading as unaligned/unclear no matter how precisely the columns were
   measured, because the underlying structure was the actual problem):
   an input on top, feeding down into two self-contained outcome CARDS.
   Each card owns its own border/background, so alignment is no longer a
   pixel-matching exercise across independent flex columns — every card
   just lays out its own icon/label/value internally and they naturally
   line up because they're the same component repeated. The two
   go-live dates (fast vs. typical) are now ONE card with a small
   secondary note, instead of two equally-weighted stats that looked like
   competing, unrelated numbers. */
.process-simulate {
  margin: clamp(2rem, 1.5rem + 2vw, 3rem) auto 0;
  max-width: 42rem;
  padding: 1.5rem;
  background: linear-gradient(165deg, rgba(209, 36, 36, 0.06), rgba(6, 11, 77, 0.05));
  border: 1px solid rgba(209, 36, 36, 0.18);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
}
.process-simulate-input {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  text-align: center;
}
.process-simulate-input label {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-600);
}
.process-simulate-input input[type="date"] {
  font: inherit;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--navy-900);
  padding: 0.6rem 1rem;
  border-radius: var(--radius-md);
  border: 1.5px solid rgba(6, 11, 77, 0.22);
  background: var(--white);
  box-shadow: 0 6px 16px -8px rgba(6, 11, 77, 0.2);
}
.process-simulate-arrow { display: flex; color: rgba(209, 36, 36, 0.55); }
.process-simulate-outcomes {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
}
.process-outcome {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  background: var(--white);
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-md);
  padding: 1rem 1.1rem;
  text-align: left;
}
.process-outcome-icon {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  color: var(--navy-900);
  background: linear-gradient(135deg, rgba(6, 11, 77, 0.08), rgba(209, 36, 36, 0.08));
}
.process-outcome--highlight .process-outcome-icon { color: var(--red-600); }
.process-outcome-body { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.process-outcome-label { font-size: 0.78rem; color: var(--gray-600); }
.process-outcome-body strong { font-family: var(--font-heading); font-weight: 700; color: var(--navy-900); font-size: 1.15rem; line-height: 1.25; }
.process-outcome--highlight .process-outcome-body strong { color: var(--red-600); }
.process-outcome-note { font-size: 0.78rem; color: var(--gray-600); }
.process-outcome-note strong { font-family: inherit; font-weight: 700; font-size: inherit; color: var(--navy-900); line-height: inherit; }

/* Flowchart: numbered cards in a single connected row on wide screens
   (arrow chevrons between each), collapsing to a vertical stack with
   down-pointing arrows on narrow ones. */
.process-flow {
  list-style: none;
  margin: clamp(2.5rem, 2rem + 2vw, 3.5rem) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}
.process-flow-item {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  background: var(--white);
  border: 1.5px solid var(--gray-100);
  border-radius: var(--radius-lg);
  padding: 1.5rem 1.35rem 1.35rem;
  box-shadow: var(--shadow-card);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease), border-color 0.25s var(--ease);
  cursor: pointer;
}
.process-flow-item:hover,
.process-flow-item:focus-visible {
  transform: translateY(-4px);
  box-shadow: 0 22px 36px -18px rgba(6, 11, 77, 0.3);
  border-color: rgba(209, 36, 36, 0.35);
  outline: none;
}
.process-flow-item.is-active { border-color: var(--red-600); box-shadow: 0 0 0 3px rgba(209, 36, 36, 0.14); }

/* One-time "wave" that sweeps left-to-right across steps 1→5 the first
   time the flowchart scrolls into view (see script.js) — each card lifts
   and flashes its border/icon red in turn, on a stagger, so the sequence
   itself reads as motion/progression through the steps rather than all
   five cards just fading in together. */
.process-flow-item.is-pulsing {
  animation: processFlowPulse 0.85s var(--ease);
}
.process-flow-item.is-pulsing .process-flow-icon { color: var(--red-600); }
@keyframes processFlowPulse {
  0% { transform: translateY(0); border-color: var(--gray-100); box-shadow: var(--shadow-card); }
  40% { transform: translateY(-6px); border-color: var(--red-600); box-shadow: 0 22px 36px -18px rgba(6, 11, 77, 0.32); }
  100% { transform: translateY(0); border-color: var(--gray-100); box-shadow: var(--shadow-card); }
}
/* Reduced-motion visitors still get the sequenced highlight (script.js
   isn't gated on this — it always runs), just without the lift/transform:
   a plain color-only flash on the same stagger instead of no effect at
   all. */
@media (prefers-reduced-motion: reduce) {
  .process-flow-item.is-pulsing {
    animation: processFlowPulseStatic 0.85s var(--ease);
  }
  @keyframes processFlowPulseStatic {
    0% { border-color: var(--gray-100); }
    40% { border-color: var(--red-600); }
    100% { border-color: var(--gray-100); }
  }
}
.process-flow-badge {
  position: absolute;
  top: -14px;
  right: 16px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--red-600);
  color: var(--white);
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 0.95rem;
  box-shadow: 0 6px 14px -4px rgba(209, 36, 36, 0.55);
}
.process-flow-icon {
  display: inline-grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  margin-bottom: 0.85rem;
  color: var(--navy-900);
  background: linear-gradient(135deg, rgba(6, 11, 77, 0.08), rgba(209, 36, 36, 0.08));
  transition: color 0.25s var(--ease), background 0.25s var(--ease);
}
.process-flow-item:hover .process-flow-icon,
.process-flow-item.is-active .process-flow-icon { color: var(--red-600); }
.process-flow-body h3 { font-size: 1.02rem; margin: 0 0 0.4rem; }
.process-flow-body p { font-size: 0.86rem; color: var(--gray-600); margin: 0 0 0.85rem; line-height: 1.55; }
.process-flow-chip {
  display: inline-block;
  padding: 0.28rem 0.75rem;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(209, 36, 36, 0.35);
  color: var(--red-600);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.process-flow-chip-date {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--gray-600);
  text-transform: none;
  letter-spacing: 0.01em;
}
.process-flow-arrow {
  display: none;
  align-self: center;
  flex-shrink: 0;
  color: var(--gray-400);
}

@media (min-width: 960px) {
  .process-flow { flex-direction: row; align-items: stretch; gap: 0; }
  .process-flow-arrow { display: flex; padding-inline: 0.6rem; }
}

@media (max-width: 959px) {
  .process-flow-item { margin-bottom: 1.5rem; }
  .process-flow-arrow {
    display: flex;
    justify-content: center;
    margin: -0.75rem 0 0.75rem;
    transform: rotate(90deg);
  }
}

@media (max-width: 640px) {
  .process-simulate { padding: 1.1rem; }
  .process-simulate-input input[type="date"] { width: 100%; }
  .process-outcome { padding: 0.85rem 0.9rem; }
}

@media (prefers-reduced-motion: reduce) {
  .process-flow-item { transition: none; }
}

/* ==========================================================================
   Real TNB Bill Proof
   ========================================================================== */
.bill-proof {
  background: var(--white);
  /* Top padding is deliberately much larger than the bottom: this section
     now sits directly after #statBarWrap (index.html), whose stat cards
     overlap the seam above via a negative bottom margin of up to -6rem
     (see #statBarWrap). Without extra top clearance here, that overlap
     leaves almost no breathing room before this section's own heading. */
  padding-top: clamp(6rem, 4.2rem + 8vw, 11rem);
  padding-bottom: clamp(3.5rem, 2.8rem + 3vw, 6rem);
}
.bill-proof-grid {
  display: grid;
  gap: clamp(2rem, 1.5rem + 2vw, 3rem);
  /* Was align-items: center, which let the short media column float in a
     large empty void against the much taller content column. Starting
     both columns at the same top edge lines the bill photo up with the
     "Verified Real Result" eyebrow instead, so the two columns read as
     one balanced row rather than a small image adrift next to a tall
     block of copy. */
  align-items: start;
}
@media (min-width: 900px) {
  /* Content (the numbers, chart, CTA) is the section's actual sales case,
     so it gets the larger share — the real bill screenshot is supporting
     evidence, not the headline visual, hence the smaller, capped-width
     column instead of a flat 50/50 split. */
  .bill-proof-grid { grid-template-columns: 0.78fr 1fr; }
}
/* Content has grown taller than the media column since the RM figures got
   bigger, so align-items:start on the grid now leaves a block of dead
   whitespace under the image. align-self:stretch makes this column take
   the full row height, and justify-content:center splits that extra
   space evenly above/below the image+badge instead of dumping it all at
   the bottom — reads as an intentional balanced layout either way. */
.bill-proof-media { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; align-self: stretch; width: 100%; }
.bill-proof-media-label {
  align-self: flex-start;
  font-family: var(--font-heading);
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--gray-600);
  margin: 0 0 0.9rem;
}

/* Plain, flat presentation of the bill screenshot — no tilt, no
   polaroid-style border/shadow, no click-to-zoom. Fills the full width
   of its media column (no artificial cap) so it reads at the same scale
   as the content column beside it instead of looking small/orphaned. */
.bill-proof-frame {
  position: relative;
  display: block;
  width: 100%;
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 1px solid rgba(6, 11, 77, 0.1);
}
.bill-proof-frame img { display: block; width: 100%; height: auto; }
.bill-proof-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 1.1rem;
  padding: 0.4rem 0.85rem;
  border-radius: var(--radius-pill);
  background: var(--gray-50);
  color: var(--navy-900);
  font-size: 0.85rem;
  font-weight: 700;
}
.bill-proof-badge svg { color: #1a9d5c; flex-shrink: 0; }

.bill-proof-eyebrow {
  font-family: var(--font-heading);
  font-size: 0.95rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #1a9d5c;
  margin: 0 0 0.6rem;
}

.bill-proof-highlight {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  padding: 1.15rem 1.4rem;
  background: linear-gradient(120deg, rgba(209, 36, 36, 0.08), rgba(26, 157, 92, 0.1));
  border: 1px solid rgba(6, 11, 77, 0.08);
  border-radius: var(--radius-lg);
  margin-bottom: 1.5rem;
}
.bill-proof-before, .bill-proof-after {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  flex: 1 1 auto;
  min-width: 7rem;
}
.bill-proof-after { align-items: flex-end; text-align: right; }
/* Three-tier hierarchy inside each before/after block, by size AND color
   (not size alone) so it still reads correctly at a glance: the date is
   the smallest, most muted label; the RM figure is the biggest, darkest/
   most saturated number (the one people scan for); kWh usage sits in
   between on both axes. Direct-child combinator (>) is deliberate here —
   a plain descendant selector also matches the digit <span> nested
   inside <strong> (data-count-decimal), which was silently overriding
   the big RM figure down to this small date-label size. */
.bill-proof-before > span, .bill-proof-after > span {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gray-400);
}
.bill-proof-before strong, .bill-proof-after strong {
  display: inline-flex;
  align-items: baseline;
  gap: 0.15rem;
  font-family: var(--font-heading);
  /* The actual RM figure is the number people scan for — it's the section's
     dominant figure, sized well above the percent badge (a secondary,
     supporting stat) so the two read with clear hierarchy instead of
     competing for attention. */
  font-size: clamp(3.1rem, 2.7rem + 1.7vw, 3.75rem);
  font-weight: 800;
  color: var(--navy-900);
  line-height: 1;
}
.bill-proof-after strong { color: #1a9d5c; }
.bill-proof-currency {
  font-size: 0.4em;
  font-weight: 700;
  color: var(--gray-600);
}
.bill-proof-after .bill-proof-currency { color: #1a9d5c; opacity: 0.75; }
.bill-proof-before em, .bill-proof-after em {
  font-style: normal;
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--gray-600);
}
/* The arrow and the percent drop now sit together as one unit, centered
   between the before/after figures — not pushed to the far right edge of
   a wide row via margin-left: auto, which left an oversized, unbalanced
   gap between the RM cluster and the percent figure. */
.bill-proof-arrow-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  flex-shrink: 0;
}
.bill-proof-arrow { color: var(--gray-400); width: 26px; height: 15px; }
/* Below ~640px the row-based layout (before | arrow | after, wrapping as
   needed) doesn't have room for the now much bigger RM figures — it wraps
   each block onto its own line but keeps the row's flex-wrap gaps and the
   "after" block's right-alignment, leaving the arrow/percent stranded in
   the middle and MEI-26 floating disconnected on the right. Below this
   breakpoint it switches to a plain top-to-bottom stack instead: before,
   then a compact horizontal arrow+percent divider, then after — both
   blocks left-aligned so nothing floats off on its own. */
@media (max-width: 640px) {
  .bill-proof-highlight {
    flex-direction: column;
    align-items: stretch;
    gap: 0.9rem;
  }
  .bill-proof-before, .bill-proof-after {
    min-width: 0;
    width: 100%;
  }
  .bill-proof-after {
    align-items: flex-start;
    text-align: left;
  }
  .bill-proof-arrow-wrap {
    flex-direction: row;
    justify-content: flex-start;
    gap: 0.6rem;
  }
  .bill-proof-arrow { transform: rotate(90deg); }
}
.bill-proof-percent {
  display: inline-block;
  padding: 0.2rem 0.65rem;
  border-radius: var(--radius-pill);
  background: var(--red-600);
  font-family: var(--font-heading);
  font-size: clamp(1.1rem, 1rem + 0.4vw, 1.3rem);
  font-weight: 800;
  color: var(--white);
  white-space: nowrap;
  line-height: 1;
}

.bill-proof-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
  margin-bottom: 1.25rem;
}
.bill-proof-table th, .bill-proof-table td {
  padding: 0.55rem 0.6rem;
  text-align: left;
  border-bottom: 1px solid rgba(6,11,77,0.08);
}
.bill-proof-table thead th {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gray-600);
  font-weight: 700;
  border-bottom-color: rgba(6,11,77,0.14);
}
.bill-proof-table td, .bill-proof-table tbody th { color: var(--navy-900); font-weight: 600; }
.bill-proof-table tbody th { font-weight: 700; }
.bill-proof-table-latest th, .bill-proof-table-latest td { color: #1a9d5c; }

.bill-proof-note {
  font-size: 1rem;
  color: var(--gray-600);
  max-width: 48ch;
}

/* ----- Interactive chart ---------------------------------------------- */
.bill-proof-chart-wrap { margin-bottom: 1.5rem; }
.bill-proof-chart-toggle {
  display: inline-flex;
  gap: 0.3rem;
  padding: 0.25rem;
  background: var(--gray-50);
  border-radius: var(--radius-pill);
  margin-bottom: 1rem;
}
.bill-proof-chart-toggle-btn {
  padding: 0.4rem 0.9rem;
  border-radius: var(--radius-pill);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--gray-600);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.bill-proof-chart-toggle-btn.is-active { background: var(--navy-900); color: var(--white); }
.bill-proof-chart {
  display: flex;
  align-items: flex-end;
  gap: clamp(0.5rem, 0.3rem + 1vw, 1rem);
  height: 160px;
  padding: 0 0.25rem;
  border-bottom: 1.5px solid rgba(6, 11, 77, 0.1);
}
.bill-proof-bar-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
  justify-content: flex-end;
  gap: 0.5rem;
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  position: relative;
}
.bill-proof-bar {
  width: 100%;
  max-width: 34px;
  border-radius: 6px 6px 0 0;
  background: var(--navy-900);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.7s cubic-bezier(.4,0,.2,1), background 0.2s var(--ease);
}
.bill-proof-chart.is-visible .bill-proof-bar { transform: scaleY(1); }
.bill-proof-bar-col:nth-child(1) .bill-proof-bar { transition-delay: 0s; }
.bill-proof-bar-col:nth-child(2) .bill-proof-bar { transition-delay: 0.06s; }
.bill-proof-bar-col:nth-child(3) .bill-proof-bar { transition-delay: 0.12s; }
.bill-proof-bar-col:nth-child(4) .bill-proof-bar { transition-delay: 0.18s; }
.bill-proof-bar-col:nth-child(5) .bill-proof-bar { transition-delay: 0.24s; }
.bill-proof-bar-col:nth-child(6) .bill-proof-bar { transition-delay: 0.3s; }
.bill-proof-bar-col.is-latest .bill-proof-bar { background: #1a9d5c; }
.bill-proof-bar-col:hover .bill-proof-bar,
.bill-proof-bar-col:focus-visible .bill-proof-bar,
.bill-proof-bar-col.is-active .bill-proof-bar { background: var(--red-600); }
.bill-proof-bar-col.is-latest:hover .bill-proof-bar,
.bill-proof-bar-col.is-latest:focus-visible .bill-proof-bar,
.bill-proof-bar-col.is-latest.is-active .bill-proof-bar { background: #1a9d5c; }
.bill-proof-bar-label {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--gray-600);
}
.bill-proof-bar-tooltip {
  position: absolute;
  bottom: calc(100% + 0.4rem);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: 0.4rem 0.6rem;
  border-radius: var(--radius-sm);
  background: var(--navy-900);
  color: var(--white);
  font-size: 0.8rem;
  font-weight: 700;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s var(--ease), transform 0.15s var(--ease);
  z-index: 2;
}
.bill-proof-bar-col:hover .bill-proof-bar-tooltip,
.bill-proof-bar-col:focus-visible .bill-proof-bar-tooltip,
.bill-proof-bar-col.is-active .bill-proof-bar-tooltip {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.bill-proof-chart-hint {
  margin: 0.75rem 0 1.5rem;
  font-size: 0.85rem;
  color: var(--gray-400);
}
@media (prefers-reduced-motion: reduce) {
  .bill-proof-bar { transition: none; transform: scaleY(1); }
}

.bill-proof-cta { margin-top: 0.5rem; }

/* ==========================================================================
   Quote Modal — name + phone, then straight to WhatsApp. Injected into
   <body> by js/script.js (window.RPGQuote) rather than hand-placed markup
   per page, since every "data-carrying" quote CTA site-wide (home page
   builder, packages.html tier & DIY "Get a Quote" buttons) shares the
   exact same modal.
   ========================================================================== */
.quote-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s var(--ease);
}
.quote-modal.is-open { opacity: 1; pointer-events: auto; }
.quote-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(6, 11, 77, 0.55);
  backdrop-filter: blur(2px);
}
.quote-modal-body {
  position: relative;
  width: 100%;
  max-width: 420px;
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 2.1rem 1.75rem 1.75rem;
  box-shadow: 0 30px 60px -20px rgba(6, 11, 77, 0.45);
  transform: translateY(12px) scale(0.98);
  transition: transform 0.25s var(--ease);
}
.quote-modal.is-open .quote-modal-body { transform: translateY(0) scale(1); }
.quote-modal-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--gray-50);
  color: var(--navy-900);
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.quote-modal-close:hover { background: var(--red-600); color: var(--white); }
.quote-modal-eyebrow {
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #1a9d5c;
  margin: 0 0 0.4rem;
}
.quote-modal-body h3 {
  margin: 0 0 0.5rem;
  font-family: var(--font-heading);
  font-size: 1.3rem;
  color: var(--navy-900);
}
.quote-modal-lede {
  margin: 0 0 1.35rem;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--gray-600);
}
.quote-modal-body .field { margin-bottom: 1rem; }
.quote-modal-body label {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--navy-900);
}
.quote-modal-body input {
  width: 100%;
  padding: 0.7rem 0.85rem;
  border-radius: var(--radius-md);
  border: 1.5px solid rgba(6, 11, 77, 0.14);
  font: inherit;
  font-size: 0.95rem;
  color: var(--navy-900);
}
.quote-modal-body input:focus { outline: none; border-color: var(--red-600); }
.quote-modal-error {
  margin: -0.4rem 0 0.9rem;
  font-size: 0.82rem;
  color: var(--red-600);
}
.quote-modal-submit { width: 100%; justify-content: center; }
body.quote-modal-open { overflow: hidden; }

/* ==========================================================================
   Calculator
   ========================================================================== */
.calculator {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--gray-50);
  padding-block: clamp(4rem, 3rem + 4vw, 7rem);
}
/* Dot-grid pattern + soft glows so the section "protrudes" instead of
   sitting as a flat grey block between Trusted and FAQ. */
.calculator-pattern {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: radial-gradient(rgba(6, 11, 77, 0.08) 1.4px, transparent 1.4px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000 40%, transparent 100%);
  mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000 40%, transparent 100%);
}
.calculator-glow {
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  filter: blur(60px);
  pointer-events: none;
}
.calculator-glow--a { top: -10%; right: -6%; width: 380px; height: 380px; background: rgba(209, 36, 36, 0.14); }
.calculator-glow--b { bottom: -14%; left: -8%; width: 420px; height: 420px; background: rgba(6, 11, 77, 0.12); }
.calculator > .site-container { position: relative; z-index: 1; }

.calculator-grid {
  display: grid;
  gap: clamp(2rem, 1.5rem + 2vw, 3rem);
}
@media (min-width: 900px) {
  .calculator-grid { grid-template-columns: 0.85fr 1.15fr; align-items: start; }
}

.calc-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.field label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.5rem;
  color: var(--navy-900);
  font-size: 0.92rem;
}
.field select,
.field input,
.input-prefix {
  width: 100%;
  background: var(--white);
  border: 1px solid rgba(6,11,77,0.12);
  border-radius: var(--radius-sm);
  padding: 0.9rem 1rem;
  font-size: 1rem;
  color: var(--navy-900);
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.field select:focus,
.field input:focus,
.input-prefix:focus-within {
  border-color: var(--red-600);
  box-shadow: 0 0 0 4px rgba(209,36,36,0.12);
  outline: none;
}
.input-prefix { display: flex; align-items: center; gap: 0.5rem; padding-block: 0; }
.input-prefix span { color: var(--gray-600); font-weight: 600; }
.input-prefix input { border: 0; padding-left: 0; flex: 1; }
.input-prefix input:focus { box-shadow: none; }

.calc-error { color: var(--red-700); font-size: 0.85rem; font-weight: 600; }

/* Range slider — a second, more tactile way to set the bill amount that
   stays in sync with the number input above it. */
.calc-range {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  height: 5px;
  margin: 0.85rem 0 0.4rem;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--red-600) 0%, var(--red-600) 15%, var(--gray-100) 15%, var(--gray-100) 100%);
  cursor: pointer;
}
.calc-range::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--white);
  border: 3px solid var(--red-600);
  box-shadow: 0 2px 6px rgba(6, 11, 77, 0.25);
  transition: transform 0.15s var(--ease);
}
.calc-range::-webkit-slider-thumb:hover { transform: scale(1.15); }
.calc-range::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--white);
  border: 3px solid var(--red-600);
  box-shadow: 0 2px 6px rgba(6, 11, 77, 0.25);
}
.calc-range::-moz-range-track { height: 5px; border-radius: var(--radius-pill); background: var(--gray-100); }
.calc-range-scale {
  display: flex;
  justify-content: space-between;
  font-size: 0.72rem;
  color: var(--gray-400);
}

.calc-results {
  background: var(--gray-100);
  border-radius: var(--radius-lg);
  padding: clamp(1.25rem, 1rem + 1vw, 2rem);
  container-type: inline-size;
  container-name: calc-results;
}
.calc-summary {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: rgba(6,11,77,0.08);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin-bottom: var(--space-3);
}
/* Only go 4-across once the results panel is actually wide enough
   for four stats to sit inline without cramping — otherwise stay
   a clean 2x2 grid instead of an awkward 3+1 wrap. */
@container calc-results (min-width: 620px) {
  .calc-summary {
    grid-template-columns: repeat(4, 1fr);
  }
}
.calc-stat {
  background: var(--white);
  padding: 1.1rem 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.calc-stat span { font-size: 0.78rem; color: var(--gray-600); font-weight: 500; }
.calc-stat strong { font-family: var(--font-heading); color: var(--navy-900); font-size: 1.4rem; }
.calc-stat.is-live strong { color: var(--red-600); animation: calcPulse 0.4s var(--ease); }
@keyframes calcPulse {
  0% { transform: scale(1); }
  40% { transform: scale(1.08); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .calc-stat.is-live strong { animation: none; }
}

.chart-wrap { background: var(--white); border-radius: var(--radius-md); padding: 1rem clamp(0.75rem, 0.5rem + 1vw, 1.5rem) 0.5rem; }
#savingsChart { width: 100%; height: auto; display: block; }
.chart-legend {
  display: flex;
  gap: 1.5rem;
  justify-content: center;
  padding-block: 0.75rem;
  font-size: 0.85rem;
  color: var(--navy-900);
}
.chart-legend span { display: inline-flex; align-items: center; gap: 0.4rem; }
.swatch { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
.swatch--red { background: var(--red-600); }
.swatch--navy { background: var(--navy-900); }
.swatch--line {
  width: 16px;
  height: 0;
  border-radius: 0;
  border-top: 2.5px dashed #c8960c;
  background: none;
}
.chart-note {
  margin: 0.25rem 0 0.5rem;
  padding: 0 clamp(0.25rem, 0.2rem + 0.3vw, 0.5rem);
  font-size: 0.82rem;
  color: var(--gray-600);
  text-align: center;
}
.chart-note strong { color: var(--navy-900); font-family: var(--font-heading); }

/* ==========================================================================
   Why Hybrid (The Hybrid Advantage)
   ========================================================================== */
.hybrid-advantage { background: var(--gray-50); padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); text-align: center; }
.hybrid-advantage .section-heading p { margin-inline: auto; }
.hybrid-compare {
  display: grid;
  gap: 1.25rem;
  max-width: 960px;
  margin: 0 auto clamp(1.5rem, 1.2rem + 1vw, 2rem);
  text-align: left;
}
@media (min-width: 700px) { .hybrid-compare { grid-template-columns: 1fr 1fr; } }
.hybrid-compare-col {
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 1.2rem + 1vw, 2rem);
}
.hybrid-compare-col--ongrid {
  background: var(--white);
  border: 1px solid var(--gray-100);
  opacity: 0.85;
}
.hybrid-compare-col--hybrid {
  background: var(--navy-900);
  color: var(--white);
  box-shadow: 0 24px 48px -18px rgba(6, 11, 77, 0.4);
  transform: scale(1.02);
}
.hybrid-compare-tag {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-pill);
  margin-bottom: 0.75rem;
}
.hybrid-compare-col--ongrid .hybrid-compare-tag { background: var(--gray-100); color: var(--gray-600); }
.hybrid-compare-col--hybrid .hybrid-compare-tag { background: var(--red-600); color: var(--white); }
.hybrid-compare-col h3 { font-size: 1.1rem; margin: 0 0 1rem; }
.hybrid-compare-col--ongrid h3 { color: var(--navy-900); }
.hybrid-compare-col--hybrid h3 { color: var(--white); }
.hybrid-compare-col ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.hybrid-compare-col li { display: flex; align-items: flex-start; gap: 0.6rem; font-size: 0.92rem; line-height: 1.5; }
.hybrid-compare-col--ongrid li { color: var(--gray-600); }
.hybrid-compare-col--hybrid li { color: rgba(255, 255, 255, 0.92); }
.hybrid-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  font-size: 0.7rem;
  font-weight: 700;
  flex-shrink: 0;
  margin-top: 0.15rem;
}
.hybrid-mark--x { background: var(--gray-100); color: var(--gray-600); }
.hybrid-mark--check { background: var(--red-600); color: var(--white); }
.hybrid-compare-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 1.25rem;
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--white);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, 0.4);
  transition: text-decoration-color 0.2s var(--ease);
}
.hybrid-compare-cta:hover { text-decoration-color: var(--white); }
.hybrid-compare-cta svg { transform: rotate(-90deg); flex-shrink: 0; }
.hybrid-advantage-note {
  max-width: 60ch;
  margin: 0 auto 1.5rem;
  color: var(--gray-600);
  font-size: 0.95rem;
  line-height: 1.7;
}

/* ==========================================================================
   Competitive Analysis (home page — right after Key Facts)
   ========================================================================== */
/* Key Facts' .facts-scene deliberately bleeds its house/grass artwork
   down over whatever section follows it (negative bottom margin — up to
   -4rem on mobile, -9rem on desktop) — that's correct when the next
   section is meant to sit "under" the grass. Edge now follows Facts
   directly, so its own top padding has to clear that bleed on each
   breakpoint, or its heading gets cut off by the grass artwork sitting on
   top of it. */
.edge {
  position: relative;
  overflow: hidden;
  background: linear-gradient(180deg, var(--white) 0%, #fdf5f1 100%);
  padding-top: clamp(4.5rem, 3.2rem + 4vw, 6rem);
  padding-bottom: clamp(3.5rem, 2.8rem + 3vw, 6.5rem);
}
@media (min-width: 960px) {
  .edge { padding-top: clamp(7rem, 3.5rem + 8vw, 11.5rem); }
}
/* Faint diagonal hairline sweep in the corner (same device used on the
   Segments section, lighter here) so the section has some texture even
   before anyone touches it — not just flat white space. */
.edge::before {
  content: '';
  position: absolute;
  top: -10%;
  right: -8%;
  width: 46%;
  aspect-ratio: 1;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(45deg, rgba(209, 36, 36, 0.09) 0, rgba(209, 36, 36, 0.09) 1px, transparent 1px, transparent 30px);
  -webkit-mask-image: radial-gradient(circle at 70% 30%, #000 40%, transparent 75%);
  mask-image: radial-gradient(circle at 70% 30%, #000 40%, transparent 75%);
}
.edge .site-container { position: relative; z-index: 1; }

.edge-panel {
  display: grid;
  gap: 1.25rem;
}
@media (min-width: 860px) {
  .edge-panel { grid-template-columns: 0.8fr 1.2fr; gap: 2rem; align-items: stretch; }
}

.edge-tabs { display: flex; flex-direction: column; gap: 0.6rem; }
.edge-tab {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  text-align: left;
  padding: 0.95rem 1.1rem;
  background: var(--white);
  border: 1px solid var(--gray-100);
  border-left: 4px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background 0.25s var(--ease), border-color 0.25s var(--ease), transform 0.2s var(--ease), box-shadow 0.25s var(--ease);
}
.edge-tab:hover { transform: translateX(3px); }
.edge-tab.is-active {
  background: rgba(209, 36, 36, 0.06);
  border-left-color: var(--red-600);
  box-shadow: var(--shadow-card);
}
.edge-tab:focus-visible { outline: 3px solid var(--red-600); outline-offset: 2px; }
.edge-tab-num {
  flex-shrink: 0;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 0.85rem;
  color: rgba(6, 11, 77, 0.3);
  transition: color 0.25s var(--ease);
}
.edge-tab.is-active .edge-tab-num { color: var(--red-600); }
.edge-tab-label { font-family: var(--font-heading); font-weight: 700; font-size: 0.95rem; color: var(--gray-600); transition: color 0.25s var(--ease); }
.edge-tab.is-active .edge-tab-label { color: var(--navy-900); }
/* Instagram-story-style progress underline — fills over the auto-advance
   interval (JS sets the animation via .is-filling) and shows visitors a
   clear, unmissable sign that this section is alive and timed, not just a
   static list. */
.edge-tab-progress {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: rgba(6, 11, 77, 0.08);
}
.edge-tab-progress-bar {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--red-600);
}
.edge-tab-progress-bar.is-filling { width: 100%; transition: width 5s linear; }

.edge-display {
  position: relative;
  display: grid;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--navy-900);
  box-shadow: 0 30px 60px -24px rgba(6, 11, 77, 0.45);
}
.edge-display-panel {
  grid-area: 1 / 1;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 260px;
  padding: clamp(2rem, 1.6rem + 2vw, 3rem);
  opacity: 0;
  transform: translateY(6px);
  pointer-events: none;
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}
.edge-display-panel.is-active { opacity: 1; transform: none; pointer-events: auto; }
.edge-display-num {
  position: absolute;
  top: -0.5rem;
  right: 0.5rem;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(6rem, 5rem + 4vw, 9rem);
  line-height: 1;
  color: rgba(255, 255, 255, 0.06);
  pointer-events: none;
  user-select: none;
}
.edge-display-body { position: relative; z-index: 1; max-width: 34ch; }
.edge-display-body h3 { font-family: var(--font-heading); font-size: clamp(1.3rem, 1.15rem + 0.6vw, 1.6rem); font-weight: 800; color: var(--white); margin: 0 0 0.75rem; }
.edge-display-body p { color: rgba(255, 255, 255, 0.78); font-size: 0.98rem; line-height: 1.7; margin: 0; }
@media (max-width: 859px) {
  .edge-tabs { flex-direction: row; flex-wrap: wrap; }
  .edge-tab { flex: 1 1 calc(50% - 0.3rem); }
  .edge-tab-label { font-size: 0.85rem; }
}

/* ==========================================================================
   Custom Hybrid System Builder (home page)
   ========================================================================== */
.builder {
  background: var(--white);
  padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem);
}
.builder-grid {
  display: grid;
  gap: clamp(1.5rem, 1.1rem + 1.6vw, 2.5rem);
}
@media (min-width: 900px) {
  .builder-grid { grid-template-columns: 0.85fr 1.15fr; align-items: start; }
}
.builder-card {
  background: var(--white);
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-lg);
  padding: clamp(1.25rem, 1rem + 1.2vw, 2rem);
  box-shadow: var(--shadow-card);
}
.builder-inputs { display: flex; flex-direction: column; gap: var(--space-4); }
.builder-step { display: flex; flex-direction: column; gap: var(--space-3); }
.builder-step h3 {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 1.02rem;
  color: var(--navy-900);
  margin: 0;
}
.builder-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--navy-900);
  color: var(--white);
  font-size: 0.85rem;
  font-weight: 700;
  flex-shrink: 0;
}
.builder-hint { font-size: 0.8rem; color: var(--gray-600); margin: 0.4rem 0 0; }
.builder-chip {
  display: inline-block;
  background: rgba(6, 11, 77, 0.08);
  color: var(--navy-900);
  border-radius: var(--radius-pill);
  padding: 0.1rem 0.55rem;
  font-weight: 700;
}

/* Toggle: RM vs kWh input mode */
.builder-toggle { display: flex; border: 1px solid rgba(6,11,77,0.12); border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 0.6rem; }
.builder-toggle-btn {
  flex: 1;
  padding: 0.6rem 0.5rem;
  border: 0;
  background: var(--white);
  font-family: var(--font-heading);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--gray-600);
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.builder-toggle-btn.is-active { background: var(--navy-900); color: var(--white); }
.builder-usage-prefix { margin-top: 0; }

/* Day/night usage bar — signature element carried over from the client's
   reference tool, restyled into RPG's sun/navy palette instead of the
   original amber/slate pairing. */
.builder-daynight { border-radius: var(--radius-sm); overflow: hidden; border: 1px solid rgba(6,11,77,0.12); }
.builder-dn-bar { display: flex; height: 44px; font-size: 0.78rem; font-weight: 700; color: var(--white); font-family: var(--font-heading); }
.builder-dn-day {
  background: linear-gradient(90deg, #f6a821, var(--red-600));
  display: flex;
  align-items: center;
  padding-left: 0.75rem;
  white-space: nowrap;
  overflow: hidden;
  transition: width 0.15s var(--ease);
}
.builder-dn-night {
  background: linear-gradient(90deg, #1d3fd6, var(--navy-900));
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 0.75rem;
  white-space: nowrap;
  overflow: hidden;
  flex: 1;
}

.builder-auto-btn { justify-content: center; width: 100%; margin-top: 0.25rem; }

/* Results side */
.builder-results { display: flex; flex-direction: column; }
.builder-lowbill h3 { font-size: 1.2rem; color: var(--navy-900); margin: 0.75rem 0 0.5rem; }
.builder-lowbill-icon { font-size: 2.4rem; line-height: 1; }
.builder-lowbill p { color: var(--gray-600); margin: 0 0 0.75rem; }
.builder-lowbill ul { margin: 0 0 0.9rem 1.1rem; padding: 0; color: var(--gray-600); font-size: 0.88rem; }
.builder-lowbill li { margin-bottom: 0.4rem; }
.builder-lowbill-next {
  background: var(--gray-50);
  border-radius: var(--radius-md);
  padding: 0.9rem 1rem;
  font-size: 0.88rem;
  color: var(--navy-900);
  margin-bottom: 1rem;
}

.builder-bill-compare { display: flex; align-items: stretch; gap: 0.75rem; margin-bottom: 1.1rem; }
.builder-bill-box { flex: 1; border-radius: var(--radius-md); padding: 0.9rem 1rem; text-align: center; }
.builder-bill-box .t { display: block; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.85; }
.builder-bill-box .v { display: block; font-family: var(--font-heading); font-size: clamp(1.25rem, 1.05rem + 0.9vw, 1.65rem); margin-top: 0.25rem; }
.builder-bill-box--before { background: rgba(209, 36, 36, 0.08); color: var(--red-700); }
.builder-bill-box--after { background: rgba(6, 11, 77, 0.06); color: var(--navy-900); }
.builder-bill-arrow { align-self: center; color: var(--red-600); flex-shrink: 0; }

.builder-save-banner {
  background: var(--navy-900);
  color: var(--white);
  border-radius: var(--radius-md);
  padding: 0.9rem 1.1rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.1rem;
}
.builder-save-banner span { display: block; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.85; }
.builder-save-banner strong { display: block; font-family: var(--font-heading); font-size: clamp(1.15rem, 0.95rem + 0.8vw, 1.5rem); margin-top: 0.15rem; }
.builder-save-pct-block { text-align: right; }

.builder-legend { display: flex; gap: 0.9rem; flex-wrap: wrap; font-size: 0.74rem; color: var(--gray-600); margin-bottom: 0.4rem; }
.builder-legend span { display: inline-flex; align-items: center; gap: 0.35rem; }
.builder-swatch { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
.builder-swatch--sun { background: var(--red-600); }
.builder-swatch--batt { background: var(--navy-900); }
.builder-swatch--exp { background: #7fa6ff; }
.builder-swatch--imp { background: var(--gray-100); }

.builder-flowviz { display: flex; gap: 4px; height: 9px; border-radius: var(--radius-pill); overflow: hidden; margin-bottom: 1rem; }
.builder-flowviz span { display: block; height: 100%; transition: width 0.4s var(--ease); }

.builder-rowlines { margin-bottom: 0.25rem; }
.builder-rowlines .rowline {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.85rem;
  padding: 0.55rem 0;
  border-bottom: 1px dashed var(--gray-100);
}
.builder-rowlines .rowline:last-child { border-bottom: 0; }
.builder-rowlines .k { color: var(--gray-600); }
.builder-rowlines .v { font-weight: 700; color: var(--navy-900); }

.builder-status { border-radius: var(--radius-sm); padding: 0.8rem 0.9rem; font-size: 0.85rem; font-weight: 600; margin-top: 0.6rem; }
.builder-status.is-ok { background: rgba(22, 163, 74, 0.12); color: #14532d; }
.builder-status.is-warn { background: rgba(245, 158, 11, 0.14); color: #92400e; }

.builder-sys-summary { background: var(--gray-50); border-radius: var(--radius-sm); padding: 0.75rem 0.9rem; font-size: 0.85rem; color: var(--navy-900); margin: 0.75rem 0 0; }

.builder-cta { width: 100%; justify-content: center; margin-top: 1.1rem; }

.builder-disclaimer {
  font-size: 0.75rem;
  color: var(--gray-600);
  margin-top: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
  border-top: 1px solid var(--gray-100);
  padding-top: 1rem;
  max-width: 90ch;
}

/* ==========================================================================
   Financing Plans
   ========================================================================== */
/* Light navy-tinted background distinguishes this from the plain white
   Calculator/Trusted sections either side of it. */
.financing { background: rgba(6, 11, 77, 0.035); padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); }

/* Radial diagram: a square container, everything inside positioned with
   left/top percentages that all share one coordinate system (see the inline
   styles + SVG line coordinates in index.html — both use the same five
   pentagon points, so the spokes always meet their node dead-center
   regardless of viewport width). Sized generously (36rem, up from 30rem)
   now that the circles themselves are bigger. */
.financing-radial {
  position: relative;
  width: 100%;
  max-width: 36rem;
  aspect-ratio: 1 / 1;
  margin: clamp(3.5rem, 2.8rem + 3vw, 5rem) auto 0;
}

/* Decorative dashed rings behind the hub — background texture that echoes
   the concentric-circle reference image, purely visual (pointer-events:none,
   aria-hidden), sitting beneath the spoke lines/nodes in the stack order. */
.financing-ring {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 1.5px dashed rgba(6, 11, 77, 0.12);
  pointer-events: none;
  z-index: 0;
}
.financing-ring--inner { width: 46%; height: 46%; }
.financing-ring--outer { width: 74%; height: 74%; border-color: rgba(209, 36, 36, 0.1); }

.financing-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  z-index: 1;
}
.financing-lines line {
  stroke: rgba(6, 11, 77, 0.16);
  stroke-width: 0.6;
  vector-effect: non-scaling-stroke;
  transition: stroke 0.25s var(--ease), stroke-width 0.25s var(--ease);
}
.financing-lines line.is-active { stroke: var(--red-600); stroke-width: 1.1; }

.financing-hub {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: clamp(108px, 26%, 148px);
  height: clamp(108px, 26%, 148px);
  border-radius: 50%;
  display: grid;
  place-items: center;
  text-align: center;
  background: var(--navy-900);
  color: var(--white);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.25;
  box-shadow: 0 16px 34px -14px rgba(6, 11, 77, 0.5);
  z-index: 2;
}

.financing-node {
  position: absolute;
  transform: translate(-50%, -50%);
  width: clamp(104px, 24%, 140px);
  height: clamp(104px, 24%, 140px);
  border-radius: 50%;
  display: grid;
  place-items: center;
  gap: 0.3rem;
  text-align: center;
  padding: 0.75rem;
  background: var(--white);
  border: 1.5px solid rgba(6, 11, 77, 0.14);
  cursor: pointer;
  font: inherit;
  color: var(--navy-900);
  box-shadow: 0 10px 22px -14px rgba(6, 11, 77, 0.3);
  transition: transform 0.25s var(--ease), border-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
  z-index: 3;
}
.financing-node:hover,
.financing-node:focus-visible,
.financing-node.is-active {
  border-color: var(--red-600);
  box-shadow: 0 12px 26px -12px rgba(209, 36, 36, 0.35);
}
.financing-node.is-active { transform: translate(-50%, -50%) scale(1.06); }
.financing-node-icon {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  color: var(--navy-900);
  background: linear-gradient(135deg, rgba(6, 11, 77, 0.08), rgba(209, 36, 36, 0.08));
  transition: color 0.25s var(--ease);
}
.financing-node.is-active .financing-node-icon,
.financing-node:hover .financing-node-icon,
.financing-node:focus-visible .financing-node-icon { color: var(--red-600); }
.financing-node-body { display: flex; flex-direction: column; align-items: center; gap: 0.1rem; min-width: 0; }
.financing-node-title { font-size: 0.82rem; font-weight: 700; line-height: 1.25; }
.financing-node-desc { display: none; }

/* Floating tooltip: positioned in JS (financingRadial section of script.js)
   relative to whichever node was clicked, flipping above/below depending on
   which half of the diagram that node sits in so it never runs past the
   container's top/bottom edge, and clamped horizontally so it never runs
   past the left/right edge either. The little triangle is aimed at the
   node via the --arrow-left custom property JS sets per open. */
.financing-tooltip {
  position: absolute;
  width: min(260px, calc(100% - 16px));
  max-width: 260px;
  background: var(--white);
  border: 1.5px solid rgba(6, 11, 77, 0.14);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 0.9rem 1.05rem;
  text-align: left;
  z-index: 5;
  /* Purely informational (no links/buttons inside), so let clicks pass
     straight through to whatever's underneath — on narrow viewports this
     box can end up covering a neighboring node, and without this a click
     there would just hit the tooltip's own background and do nothing
     instead of switching to that node like the user expects. */
  pointer-events: none;
}
.financing-tooltip::before {
  content: '';
  position: absolute;
  left: var(--arrow-left, 50%);
  width: 12px;
  height: 12px;
  background: var(--white);
  border: 1.5px solid rgba(6, 11, 77, 0.14);
  transform: translateX(-50%) rotate(45deg);
}
.financing-tooltip.is-below::before { top: -7px; border-right: none; border-bottom: none; }
.financing-tooltip.is-above::before { bottom: -7px; border-left: none; border-top: none; }
.financing-tooltip h3 { font-size: 0.95rem; margin: 0 0 0.3rem; }
.financing-tooltip p { font-size: 0.84rem; color: var(--gray-600); line-height: 1.55; margin: 0; }

/* Below this, a radial layout stops being usable — no room for the
   diagram, and no hover on touch — so it collapses to a plain stacked
   list with each plan's description shown inline instead of behind a
   tooltip. */
@media (max-width: 720px) {
  .financing-radial {
    aspect-ratio: auto;
    max-width: none;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    margin-top: clamp(2rem, 1.6rem + 2vw, 3rem);
  }
  .financing-ring,
  .financing-lines,
  .financing-hub { display: none; }
  .financing-node {
    position: static;
    transform: none;
    width: 100%;
    height: auto;
    border-radius: var(--radius-lg);
    grid-template-columns: auto 1fr;
    display: grid;
    justify-items: start;
    text-align: left;
    gap: 0 1rem;
    padding: 1.1rem 1.25rem;
  }
  .financing-node:hover,
  .financing-node:focus-visible,
  .financing-node.is-active { transform: none; }
  .financing-node-icon { width: 40px; height: 40px; }
  .financing-node-body { align-items: flex-start; grid-column: 2; gap: 0.3rem; }
  .financing-node-title { font-size: 0.98rem; }
  .financing-node-desc {
    display: block;
    font-size: 0.85rem;
    color: var(--gray-600);
    line-height: 1.55;
  }
  .financing-tooltip { display: none; }
}

.financing-banks { margin-top: clamp(2.5rem, 2rem + 2vw, 3.5rem); }
.financing-banks-label {
  text-align: center;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--gray-600);
  margin: 0 0 1.25rem;
}
/* Real bank logos — shown at full original color, no desaturate/hover
   treatment (the earlier "as featured in" grayscale-then-color-on-hover
   style was a holdover from the text placeholders; the user wants these
   plain and bigger). */
.bank-logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 76px;
  min-width: 170px;
  padding: 0.7rem 1.6rem;
  border-radius: var(--radius-md);
  background: var(--white);
  border: 1px solid var(--gray-100);
}
.bank-logo img { max-height: 44px; width: auto; max-width: 100%; display: block; }
/* CIMB's logo file is a white wordmark on a transparent background, so
   without its own backing it would vanish on this section's white card —
   give it a dark chip matching the mark's own brand red. */
.bank-logo--cimb { background: #8a0011; border-color: #8a0011; }
.bank-logo--cimb img { max-height: 34px; }

/* ==========================================================================
   Trusted logos
   ========================================================================== */
.trusted { padding-block: clamp(3.5rem, 2.5rem + 3vw, 6rem); }

/* Auto-scrolling marquee: two identical <ul> tracks sit side by side inside
   a flex wrapper that's twice as wide as the viewport; animating that
   wrapper from 0 to -50% loops seamlessly since the second half is a
   pixel-perfect repeat of the first. Fade masks on the wrapper hide the
   hard edges. Pauses on hover/focus for readability & accessibility. */
.logo-marquee {
  display: flex;
  overflow: hidden;
  margin-top: clamp(2rem, 1.5rem + 2vw, 3rem);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 64px, #000 calc(100% - 64px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 64px, #000 calc(100% - 64px), transparent 100%);
}
.logo-marquee:hover .logo-strip,
.logo-marquee:focus-within .logo-strip {
  animation-play-state: paused;
}
.logo-strip {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 1rem + 3vw, 4rem);
  flex-shrink: 0;
  width: max-content;
  padding-right: clamp(1.5rem, 1rem + 3vw, 4rem);
  animation: logoMarquee 26s linear infinite;
}
.logo-placeholder {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 56px;
  min-width: 150px;
  padding: 0 1.5rem;
  border-radius: var(--radius-md);
  background: var(--gray-50);
  border: 1px dashed var(--gray-100);
  color: var(--gray-400);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  filter: grayscale(1);
  opacity: 0.75;
  transition: filter 0.3s var(--ease), opacity 0.3s var(--ease), transform 0.3s var(--ease), color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.logo-placeholder:hover {
  filter: grayscale(0);
  opacity: 1;
  color: var(--navy-900);
  border-color: rgba(209, 36, 36, 0.35);
  transform: translateY(-2px);
}
/* Real client logos — bigger and always shown in full colour (no
   grayscale-at-rest/hover-to-colour treatment, no hover effect at all —
   just the logos, sized up from the original placeholder-box rhythm). */
.logo-item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 88px;
  min-width: 160px;
  padding: 0 1.5rem;
}
.logo-item img {
  height: 100%;
  width: auto;
  max-width: 220px;
  object-fit: contain;
}
@keyframes logoMarquee {
  from { transform: translateX(0); }
  to { transform: translateX(-100%); }
}
@media (prefers-reduced-motion: reduce) {
  .logo-strip { animation: none; }
  .logo-marquee { overflow-x: auto; }
}

/* ==========================================================================
   As Featured In (homepage, early strip)
   ========================================================================== */
/* Sits right after the hero — a quick, low-chrome credibility strip before
   any sales copy. Same "plain wordmark, no card" idea as .news-press-*
   on news.php, kept as its own class here since this is homepage-scoped
   and two of the four outlets currently have no confirmed link yet. */
.home-press { padding-block: clamp(2rem, 1.6rem + 1.5vw, 3rem); background: var(--gray-50); border-bottom: 1px solid rgba(6, 11, 77, 0.06); }
.home-press-label {
  text-align: center;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--gray-600);
  margin: 0 0 1.1rem;
}
.home-press-logos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(1.75rem, 1.4rem + 1.6vw, 3rem);
}
.home-press-logos a { display: flex; align-items: center; opacity: 0.85; transition: opacity 0.2s var(--ease); }
.home-press-logos a:hover, .home-press-logos a:focus-visible { opacity: 1; }
.home-press-wordmark {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.15rem;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
/* Colours below are a generic approximation for quick visual distinction,
   not verified brand hex codes — happy to swap in exact colours or real
   logo files once available. */
.home-press-wordmark--rtm { color: var(--navy-900); }
.home-press-wordmark--star { color: #e6242a; }
.home-press-wordmark--bh { color: var(--navy-900); }
.home-press-wordmark--ml { color: var(--red-600); }
/* The Star / Berita Harian render as plain (non-link) text until a real
   article/segment URL is confirmed — greyed slightly so they read as
   "mentioned" rather than falsely implying they're clickable. */
span.home-press-wordmark--star, span.home-press-wordmark--bh { opacity: 0.75; }

/* ==========================================================================
   Google reviews slider
   ========================================================================== */
.reviews { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); }
.reviews-widget { min-height: 120px; margin-top: clamp(1.5rem, 1rem + 1.5vw, 2.5rem); }

/* .section-heading keeps its normal centered, standalone look (matching
   every other section) — the rating pill sits centered underneath it
   instead of sharing a space-between row, which is what was forcing the
   heading to left-align before. */
.reviews-head {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.reviews-rating {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: -1rem;
  padding: 0.6rem 1.1rem;
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
.reviews-score { font-family: var(--font-heading); font-weight: 800; font-size: 1.15rem; color: var(--navy-900); }
.reviews-stars { color: #f5b400; letter-spacing: 0.05em; font-size: 0.9rem; }
.reviews-count { font-size: 0.82rem; color: var(--gray-600); }

.reviews-slider-wrap {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: clamp(2rem, 1.5rem + 2vw, 3rem);
}
.reviews-track {
  list-style: none;
  margin: 0;
  padding: 0.25rem 0.25rem 0.5rem;
  display: flex;
  gap: 1.25rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  flex: 1 1 auto;
}
.reviews-track::-webkit-scrollbar { display: none; }
.review-card {
  scroll-snap-align: start;
  flex: 0 0 auto;
  width: min(320px, 82vw);
  background: var(--white);
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-lg);
  padding: 1.5rem 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.review-card-top { display: flex; align-items: center; gap: 0.75rem; }
.review-card-top div { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.review-card-top strong { font-family: var(--font-heading); font-size: 0.95rem; color: var(--ink); }
.review-date { font-size: 0.76rem; color: var(--gray-400); }
.review-avatar {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--navy-900);
  color: var(--white);
  font-family: var(--font-heading);
  font-weight: 700;
}
.review-google-icon { flex-shrink: 0; }
.review-stars { color: #f5b400; letter-spacing: 0.05em; font-size: 0.85rem; }
.review-card p { margin: 0; font-size: 0.92rem; color: var(--gray-600); line-height: 1.65; }

.reviews-nav {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid var(--gray-100);
  background: var(--white);
  color: var(--navy-900);
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), transform 0.2s var(--ease);
}
.reviews-nav:hover { background: var(--red-600); color: var(--white); transform: scale(1.05); }

.reviews-dots { display: flex; justify-content: center; gap: 0.5rem; margin-top: 1.25rem; }
.reviews-dots span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gray-100);
  transition: background 0.2s var(--ease), transform 0.2s var(--ease);
}
.reviews-dots span.is-active { background: var(--red-600); transform: scale(1.3); }

.reviews-more {
  text-align: center;
  margin-top: 1.5rem;
  font-size: 0.9rem;
}
.reviews-more a {
  color: var(--navy-900);
  font-weight: 700;
  text-decoration: none;
  border-bottom: 1.5px solid rgba(6, 11, 77, 0.25);
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.reviews-more a:hover { color: var(--red-600); border-color: var(--red-600); }

@media (max-width: 640px) {
  .reviews-nav { display: none; }
}

/* ==========================================================================
   FAQ
   ========================================================================== */
.faq { background: var(--gray-50); padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); }

.faq-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: clamp(1.5rem, 1rem + 2vw, 3rem);
  align-items: start;
  margin-top: clamp(2.5rem, 2rem + 2vw, 3.5rem);
}

.faq-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.faq-question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.35rem;
  background: var(--white);
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-md);
  text-align: left;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.98rem;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease), transform 0.2s var(--ease);
}
.faq-question:hover { transform: translateX(2px); border-color: rgba(209, 36, 36, 0.3); }
.faq-question.is-active {
  border-color: var(--navy-900);
  box-shadow: 0 12px 24px -16px rgba(6, 11, 77, 0.35);
  color: var(--navy-900);
}
.faq-icon {
  position: relative;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--gray-50);
}
.faq-question.is-active .faq-icon { background: var(--red-600); }
.faq-icon::before,
.faq-icon::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--gray-600);
  transform: translate(-50%, -50%);
  transition: transform 0.2s var(--ease), background 0.2s var(--ease);
}
.faq-icon::before { width: 10px; height: 2px; }
.faq-icon::after { width: 2px; height: 10px; }
.faq-question.is-active .faq-icon::before,
.faq-question.is-active .faq-icon::after { background: var(--white); }
.faq-question.is-active .faq-icon::after { transform: translate(-50%, -50%) rotate(90deg) scaleY(0); }

.faq-answer {
  position: relative;
  background: var(--navy-900);
  color: var(--white);
  border-radius: var(--radius-lg);
  padding: clamp(2rem, 1.6rem + 2vw, 3rem);
  min-height: 100%;
}
.faq-answer-index {
  display: inline-block;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  color: var(--red-600);
  margin-bottom: 0.75rem;
}
/* Bug fix: h1/h2/h3 all get a hardcoded navy color from the global type
   rule above, so without this override the answer title inherited navy
   text on this panel's navy background — same color as the background,
   effectively invisible. */
.faq-answer h3 { margin: 0 0 0.9rem; font-size: clamp(1.2rem, 1.05rem + 0.6vw, 1.5rem); color: var(--white); }
.faq-answer p { margin: 0; color: rgba(255, 255, 255, 0.78); font-size: 0.98rem; line-height: 1.7; max-width: 46ch; }
.faq-answer.is-fading { animation: faqFadeIn 0.35s var(--ease); }

@keyframes faqFadeIn {
  from { opacity: 0.4; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Per-question accordion panel, nested directly under each question in
   the mobile layout. Hidden entirely on desktop, where the shared
   .faq-answer side panel is used instead. Collapsed via max-height so the
   open/close motion animates smoothly without layout jumps. */
.faq-item-panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.35s var(--ease);
}
.faq-item-panel-inner { padding: 0.9rem 1.35rem 1.35rem; }
.faq-item-panel-inner p { margin: 0; color: var(--gray-600); font-size: 0.95rem; line-height: 1.7; }

@media (min-width: 801px) {
  .faq-item-panel { display: none; }
}

@media (max-width: 800px) {
  .faq-grid { grid-template-columns: 1fr; }
  .faq-answer { display: none; }
  .faq-question.is-active { border-color: var(--navy-900); border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
  .faq-item-panel.is-open { background: var(--white); border: 1px solid var(--gray-100); border-top: 0; border-bottom-left-radius: var(--radius-md); border-bottom-right-radius: var(--radius-md); }
}

@media (prefers-reduced-motion: reduce) {
  .faq-answer.is-fading { animation: none; }
}

/* ==========================================================================
   CTA banner
   ========================================================================== */
.cta-banner {
  position: relative;
  isolation: isolate;
  padding-block: clamp(4rem, 3rem + 5vw, 7rem);
  text-align: center;
  overflow: hidden;
}
.cta-banner img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
}
.cta-overlay {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(160deg, rgba(48,24,84,0.85) 0%, rgba(90,24,60,0.75) 45%, rgba(179,40,40,0.7) 100%);
}
.cta-content h2 { color: var(--white); margin-bottom: 0; max-width: 20ch; margin-inline: auto; }
.cta-content .btn { margin-inline: auto; }
/* Wraps the CTA heading in the same .section-heading structure every
   other section uses (eyebrow + h2 at the shared size/weight scale)
   instead of the bare oversized h2 it had before, so this reads as the
   same "kind" of headline as Facts/Process/Financing/etc. Only the
   colour needs overriding for the dark photo backdrop — h2's own
   margin-bottom is zeroed above so .section-heading's margin-bottom is
   the only thing spacing it from the button below. */
.cta-heading.section-heading { margin-bottom: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem); }
.cta-heading .section-eyebrow { color: #ff8a8a; }
.cta-heading .section-eyebrow::before { background: #ff8a8a; }
/* .section-heading h2 .text-red normally fades red into navy-900 — reads
   fine on the light sections it was designed for, but on this banner's
   dark red/navy photo backdrop that navy end blends straight into the
   background and the accent word goes muddy/illegible. Swap the gradient
   to fade into the same light coral (#ff8a8a) already used for the
   eyebrow on this section instead, so it stays legible against the dark
   overlay. Same specificity as the base rule (2 classes + 1 tag); wins on
   source order since it's declared later. */
.cta-heading h2 .text-red {
  background: linear-gradient(120deg, var(--red-600) 15%, #ff8a8a 115%);
  -webkit-background-clip: text;
  background-clip: text;
}
/* Same root cause as the headline above: .section-heading's paragraph
   rule uses --gray-600, a mid-grey tuned for legibility on white
   sections. Against this banner's dark, busy photo it reads as a flat,
   low-contrast smudge. Bumped to the same rgba(255,255,255,0.85) used
   for lede text on every other dark-photo hero on the site
   (pkg-hero-lede, about/contact-hero-lede) for consistency. */
.cta-heading p:not(.section-eyebrow) { color: rgba(255, 255, 255, 0.85); }

/* ==========================================================================
   Footer
   ========================================================================== */
/* Was a completely flat navy-900 fill — every other dark section on the
   page (Engineered, Segments) gets a radial red/blue brand-color glow
   plus a faint dot-grid/grain texture to read as a surface instead of a
   flat color swatch, but the footer never got the same treatment and so
   read as an afterthought by comparison. Same two-layer approach here
   (see the two aria-hidden divs right inside <footer>, plus the reused
   .section-texture class), and a thin brand-gradient hairline right at
   the top edge so the footer announces itself as its own distinct block
   rather than just trailing off the section above it. position:relative
   + overflow:hidden scope those absolutely-positioned overlay layers to
   the footer itself; .site-footer .site-container below lifts the real
   content back above them. */
.site-footer { position: relative; overflow: hidden; background: var(--navy-900); color: rgba(255,255,255,0.85); padding-top: clamp(2.5rem, 2rem + 2vw, 4rem); }
.site-footer::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, transparent, var(--red-600) 20%, #ffab3d 50%, var(--red-600) 80%, transparent);
  z-index: 2;
}
.site-footer .site-container { position: relative; z-index: 1; }
/* Went through two passes here. First reused .section-texture (the same
   faint dot-grid/grain used on Engineered), but that combo — a
   0.16-alpha dot further muted by mix-blend-mode:overlay at 0.55
   opacity — worked out to roughly 0.09 effective alpha, essentially
   invisible once screenshotted/compressed. Fixed that by giving the
   footer a plain, undampened dot layer of its own — but a uniform grid
   at even, consistent opacity edge-to-edge reads more like a repeating
   wallpaper tile than an intentional finish. The mask below is what
   makes the difference between those two: same fine dot grid, but
   faded out via a soft radial mask so it's most present up near the
   logo/CTA row and quietly dissolves before it reaches the bottom
   legal line — texture with a deliberate falloff instead of flat
   repetition is what actually reads as a designed surface rather than
   a stock pattern fill, and it's a smaller dot at lower alpha than the
   first pass so it stays a quiet finish rather than a visible grid. */
.footer-pattern {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(255, 255, 255, 0.12) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(85% 75% at 50% 0%, #000 0%, transparent 85%);
  mask-image: radial-gradient(85% 75% at 50% 0%, #000 0%, transparent 85%);
}
.footer-top {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  align-items: center;
  justify-content: space-between;
  padding-bottom: clamp(2rem, 1.5rem + 2vw, 3rem);
  border-bottom: 1px solid rgba(255,255,255,0.12);
}
.footer-logo { height: 48px; width: auto; }

.footer-grid {
  display: grid;
  gap: clamp(2rem, 1.5rem + 2vw, 3rem);
  padding-block: clamp(2rem, 1.5rem + 2vw, 3rem);
}
@media (min-width: 900px) {
  .footer-grid { grid-template-columns: 1.4fr 1.6fr 0.6fr; }
}

.footer-company { color: var(--red-600); font-weight: 700; font-size: 1.05rem; margin-bottom: 1rem; }
.footer-office { color: var(--red-600); font-weight: 600; margin-bottom: 0.3rem; font-size: 0.9rem; }
address { font-style: normal; margin-bottom: 1rem; line-height: 1.7; }
.footer-contact a:hover { color: var(--red-600); }
.footer-contact { line-height: 1.8; }

.footer-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 1.5rem;
}
.footer-links div { display: flex; flex-direction: column; gap: 0.7rem; }
.footer-links a { font-weight: 600; font-size: 0.92rem; }
.footer-links a:hover { color: var(--red-600); }

.footer-social {
  display: flex;
  gap: 0.75rem;
  align-self: flex-start;
  justify-content: flex-start;
}
@media (min-width: 900px) {
  .footer-social { justify-content: flex-end; }
}
.footer-social a {
  width: 38px; height: 38px;
  border-radius: 8px;
  background: rgba(255,255,255,0.08);
  display: grid;
  place-items: center;
  transition: background 0.2s var(--ease), transform 0.2s var(--ease);
}
.footer-social a:hover { background: var(--red-600); transform: translateY(-2px); }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  justify-content: space-between;
  padding-block: 1.5rem;
  border-top: 1px solid rgba(255,255,255,0.12);
  font-size: 0.82rem;
}
.footer-legal { display: flex; gap: 0.75rem; }
.footer-legal a:hover { color: var(--red-600); }

/* ==========================================================================
   Scroll reveal
   ========================================================================== */
[data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* ==========================================================================
   Mobile nav
   ========================================================================== */
@media (max-width: 899px) {
  .nav-toggle { display: flex; }
  .header-cta { display: none; }

  /* The mobile-nav-open fix a few lines down only covers backdrop-filter
     while the panel is actually open — but .site-header--overlay.is-scrolled
     turns backdrop-filter on the instant you scroll the page at all,
     nav open or not (see script.js's onScrollHeader). Same containing-block
     hazard explained below, just a different trigger: scrolling down on
     ANY mobile page was enough to warp the (closed, meant-to-be-offscreen)
     nav panel into a small stray white box with slivers of its own nav
     text peeking out, sitting near the header. Blur is a nicety here, not
     load-bearing (the background colour underneath still gives it
     contrast) — simplest fix is just not to turn it on at this width at
     all, rather than chase every state that can flip it on. */
  .site-header,
  .site-header--overlay.is-scrolled {
    backdrop-filter: none;
  }

  /* #mainNav below is "position: fixed" so its slide-in panel is meant to
     span the full viewport height/width via "inset: 0 0 0 30%". But
     .site-header has "backdrop-filter: blur(...)", and a backdrop-filter
     (like a transform or filter) makes its element the containing block
     for any fixed-position descendant. That silently confines #mainNav's
     "fixed" panel to the header's own small box instead of the viewport,
     rendering as a tiny sliver up top with the page visible everywhere
     else. script.js adds this class to #siteHeader for as long as the
     mobile menu is open, temporarily removing the backdrop-filter so
     #mainNav's containing block goes back to being the viewport. */
  .site-header.mobile-nav-open { backdrop-filter: none !important; }

  .main-nav {
    position: fixed;
    inset: 0 0 0 30%;
    background: var(--white);
    z-index: 90;
    padding: 6rem 1.75rem 2rem;
    transform: translateX(100%);
    transition: transform 0.35s var(--ease);
    box-shadow: -10px 0 30px rgba(6,11,77,0.15);
    overflow-y: auto;
  }
  .main-nav.is-open { transform: translateX(0); }
  .main-nav ul { flex-direction: column; align-items: flex-start; gap: 0.25rem; width: 100%; }
  .main-nav li { width: 100%; }
  .main-nav a, .dropdown-toggle { width: 100%; padding: 0.85rem 0; font-size: 1.05rem; justify-content: space-between; }
  .dropdown-menu {
    position: static;
    transform: none;
    opacity: 1;
    visibility: visible;
    box-shadow: none;
    display: none;
    padding-left: 0.5rem;
    min-width: 0;
  }
  .has-dropdown.is-open > .dropdown-menu { display: block; }
  .has-dropdown.is-open > .dropdown-toggle svg { transform: rotate(180deg); }
  .main-nav .btn { margin-top: 1.5rem; width: 100%; justify-content: center; }

  /* Mega menu collapses to a simple single-column stacked list on mobile —
     same slide-in panel, same .is-open toggle, just no thumbnails/grid.
     Needs the ".has-dropdown--mega.is-open .mega-menu" selector repeated
     here (not just plain ".mega-menu") to actually win: that desktop
     hover/open rule further up is 3 classes deep and this mobile reset
     was only 1, so on mobile the desktop rule's own transform (which
     centers the menu via translateX(-50%), a leftover from the desktop
     "float centered under the nav item" positioning) kept beating this
     "transform: none", dragging the entire mobile panel ~108px further
     left than intended — off the edge of the white slide-in panel and
     onto the dark hero photo behind it, where the navy text became
     unreadable (the "still transparent" / "nothing happen" look this
     produced was actually unreadable text over a photo, not real
     transparency). */
  .has-dropdown--mega.is-open .mega-menu,
  .mega-menu {
    position: static;
    width: auto;
    transform: none;
    opacity: 1;
    visibility: visible;
    box-shadow: none;
    padding: 0 0 0 0.5rem;
    /* display:none/block (the old approach) is an instant, un-animatable
       jump cut — there's no in-between state for a transition to run
       through. max-height + overflow:hidden gives the browser something
       to actually interpolate, so opening/closing reads as a smooth
       slide instead of a flash. 640px is just a generous ceiling above
       the tallest real content (Products' 3-item list); the panel's own
       intrinsic height still determines where it visually stops. */
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.3s var(--ease), padding 0.3s var(--ease);
  }
  .has-dropdown.is-open > .mega-menu { max-height: 640px; padding: 0.25rem 0 0.5rem 0.5rem; }
  .mega-menu-grid { display: flex; flex-direction: column; gap: 0.25rem; }
  /* Needs the two-class ".mega-menu-grid .mega-menu-item" selector, not
     plain ".mega-menu-item" — the desktop padding fix above uses that
     same two-class selector at equal specificity, and this rule has to
     come after it in the file (it does) to actually win here; a plain
     single-class selector would lose that specificity match and this
     mobile row layout would inherit the desktop card's side padding,
     which isn't wanted once the icon is hidden and it's just a stacked
     list. */
  .mega-menu-grid .mega-menu-item { flex-direction: row; align-items: center; padding: 0.6rem 0; }
  .mega-menu-thumb { display: none; }
  .mega-menu-tags { margin-top: 0.3rem; }
  .mega-menu-foot { flex-direction: column; align-items: flex-start; gap: 0.75rem; }
}

.nav-scrim {
  position: fixed;
  inset: 0;
  background: rgba(6,11,77,0.4);
  z-index: 80;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s var(--ease), visibility 0.3s;
}
.nav-scrim.is-visible { opacity: 1; visibility: visible; }

/* ==========================================================================
   About page (about.html)
   ========================================================================== */

/* Photo hero, same treatment family as the homepage's: full-bleed image +
   a diagonal navy gradient for text legibility, drifting leaf decorations,
   and the content fading/rising into place on load (no scroll-trigger
   needed up here — it's the first thing painted). */
.about-hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(6rem, 5rem + 5vw, 9rem) clamp(4rem, 3.2rem + 4vw, 6rem);
  text-align: left;
  color: var(--white);
}
.about-hero-media { position: absolute; inset: 0; z-index: 0; }
.about-hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: 75% center; display: block; }
/* Same diagonal wash as the homepage hero: opaque navy behind the text on
   the left, fading all the way to fully transparent by 88% so the photo
   itself is visible and un-tinted on the right — instead of the old flat
   0.55-alpha navy that never lifted anywhere on the image, which read as a
   dull, uniformly dark slab rather than a photo. */
.about-hero-gradient {
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, rgba(6,11,77,0.94) 0%, rgba(6,11,77,0.86) 28%, rgba(90,20,50,0.55) 52%, rgba(6,11,77,0.15) 72%, rgba(6,11,77,0) 88%);
}
.about-hero-leaf {
  position: absolute;
  width: 84px;
  opacity: 0.85;
  z-index: 1;
  pointer-events: none;
  animation: aboutLeafDrift 7s ease-in-out infinite;
}
.about-hero-leaf--1 { left: 6%; top: 20%; }
/* Kept on the same (darker) left side as leaf--1, matching the homepage
   hero's convention — now that the gradient fades to fully transparent on
   the right, a leaf sitting there would float oddly over the bare photo. */
.about-hero-leaf--2 { left: 14%; top: 32%; width: 56px; transform: scaleX(-1); animation-name: aboutLeafDriftFlip; animation-delay: 1.4s; }
@keyframes aboutLeafDrift {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  50% { transform: translate(6px, -14px) rotate(8deg); }
}
@keyframes aboutLeafDriftFlip {
  0%, 100% { transform: scaleX(-1) translate(0, 0) rotate(0deg); }
  50% { transform: scaleX(-1) translate(-6px, -12px) rotate(-6deg); }
}
.about-hero-inner { position: relative; z-index: 2; }
.about-hero .section-eyebrow,
.about-hero h1,
.about-hero-lede,
.about-hero-chips {
  opacity: 0;
  transform: translateY(16px);
  animation: aboutHeroIn 0.7s var(--ease) forwards;
}
.about-hero .section-eyebrow { animation-delay: 0.05s; color: #ff8a8a; }
.about-hero .section-eyebrow::before { background: #ff8a8a; }
.about-hero h1 { animation-delay: 0.15s; }
.about-hero-lede { animation-delay: 0.28s; }
.about-hero-chips { animation-delay: 0.42s; }
@keyframes aboutHeroIn {
  to { opacity: 1; transform: none; }
}
.about-hero h1 {
  margin: 0.6rem 0 0;
  max-width: 46rem;
  font-size: clamp(2rem, 1.6rem + 2vw, 3rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--white);
}
.about-hero-lede {
  margin: 1.25rem 0 0;
  max-width: 56ch;
  color: rgba(255, 255, 255, 0.85);
  font-size: var(--fs-lede);
}
.about-hero-chips {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 0.6rem;
  max-width: 640px;
}
.about-hero-chips li {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.22);
  backdrop-filter: blur(6px);
  border-radius: var(--radius-pill);
  padding: 0.5rem 1rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--white);
}
.about-hero-chips li svg { color: #ff8a8a; flex-shrink: 0; }
@media (prefers-reduced-motion: reduce) {
  .about-hero-leaf { animation: none; }
  .about-hero .section-eyebrow,
  .about-hero h1,
  .about-hero-lede,
  .about-hero-chips {
    opacity: 1;
    transform: none;
    animation: none;
  }
}

/* Bridges the hero's claims straight into numbers, right before the
   reader hits the Overview copy. Counts up from 0 the first time it
   scrolls into view — see the [data-count-to] block in script.js. */
.impact-strip {
  background: var(--navy-900);
  padding-block: clamp(2rem, 1.6rem + 1.6vw, 2.75rem);
}
.impact-strip-inner {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.75rem 1rem;
  text-align: center;
}
@media (min-width: 760px) {
  .impact-strip-inner { grid-template-columns: repeat(4, 1fr); }
}
.impact-stat { display: flex; flex-direction: column; gap: 0.35rem; }
.impact-stat strong {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(1.6rem, 1.3rem + 1.2vw, 2.25rem);
  color: var(--white);
  letter-spacing: -0.01em;
}
.impact-stat-label {
  font-size: 0.82rem;
  color: rgba(255, 255, 255, 0.68);
  font-weight: 600;
}

/* Sticky under the header — top offset reads --header-h, a CSS var
   script.js keeps synced to the header's real rendered height (same
   trick it already uses for --scrollbar-w), so this doesn't need a
   hardcoded pixel guess that drifts out of sync if the header's height
   ever changes. Scroll-spy (script.js) toggles .is-active per link. */
.about-subnav {
  position: sticky;
  top: var(--header-h, 80px);
  z-index: 30;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--gray-100);
}
.about-subnav-inner {
  display: flex;
  gap: clamp(1rem, 0.6rem + 1.5vw, 2.25rem);
  overflow-x: auto;
  padding-block: 0.9rem;
}
.about-subnav a {
  flex-shrink: 0;
  position: relative;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--gray-600);
  white-space: nowrap;
  padding-bottom: 0.3rem;
  transition: color 0.2s var(--ease);
}
.about-subnav a::after {
  content: '';
  position: absolute;
  left: 0; right: 100%;
  bottom: 0;
  height: 2px;
  background: var(--red-600);
  transition: right 0.3s var(--ease);
}
.about-subnav a:hover { color: var(--navy-900); }
.about-subnav a.is-active { color: var(--red-600); }
.about-subnav a.is-active::after { right: 0; }

/* Floating scroll-to-top control — hidden until the reader has scrolled
   roughly a viewport's worth down (see script.js), then fades/lifts in.
   Kept off pages/breakpoints where it'd just be clutter is a JS call,
   not CSS, since "how far is a viewport" only makes sense at runtime. */
.back-to-top {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 60;
  display: inline-grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--navy-900);
  color: var(--white);
  box-shadow: 0 14px 30px -12px rgba(6, 11, 77, 0.5);
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease), visibility 0.3s, background 0.2s var(--ease);
}
.back-to-top.is-visible { opacity: 1; visibility: visible; transform: none; }
.back-to-top:hover { background: var(--red-600); }
@media (prefers-reduced-motion: reduce) {
  .about-subnav a::after { transition: none; }
  .back-to-top { transition: opacity 0.2s, visibility 0.2s; }
}

.about-overview { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); background: var(--white); }
.about-overview-grid {
  display: grid;
  gap: clamp(2rem, 1.5rem + 2vw, 3.5rem);
  align-items: center;
}
@media (min-width: 900px) {
  .about-overview-grid { grid-template-columns: 1.1fr 0.9fr; }
}
.about-overview-media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: 0 30px 60px -30px rgba(6, 11, 77, 0.35);
}
.about-overview-media img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.5s var(--ease); }
.about-overview-media:hover img { transform: scale(1.06); }
.about-overview-body p { margin: 0 0 1.1rem; color: var(--gray-600); line-height: 1.75; }
.about-overview-body p:last-child { margin-bottom: 0; }
.about-overview-body a { color: var(--red-600); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }

.mission-vision { padding-block: clamp(4rem, 3rem + 4vw, 7rem); background: var(--white); text-align: center; }
.mv-block { max-width: 780px; margin: 0 auto; }
.mv-block--vision { margin-top: clamp(2.5rem, 2rem + 2vw, 4rem); }
.mv-block .section-eyebrow { justify-content: center; }
.mv-statement {
  margin: 0.75rem 0 0;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(1.3rem, 1.1rem + 1vw, 1.7rem);
  line-height: 1.55;
  color: var(--navy-900);
}
.mv-block--vision .mv-statement { color: var(--ink); }

.values { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); background: var(--white); }
.values-grid { display: grid; gap: 1.5rem; grid-template-columns: 1fr; }
@media (min-width: 640px) {
  .values-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .values-grid { grid-template-columns: repeat(3, 1fr); }
}
.value-card {
  position: relative;
  overflow: hidden;
  background: var(--gray-50);
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 1.2rem + 1.2vw, 2rem);
  /* Entrance state (opacity/translateY) plus the existing hover lift share
     this one transition list — .values.is-visible below flips the resting
     state to visible, and :hover layers its own transform on top of that
     same resting position, so the two never fight over the property. */
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease), box-shadow 0.25s var(--ease), border-color 0.25s var(--ease);
}
.values.is-visible .value-card { opacity: 1; transform: translateY(0); }
/* Cascading stagger: each card a beat behind the last, same idea as the
   homepage stat strip's per-card entrance delay. */
.values.is-visible .value-card:nth-child(1) { transition-delay: 0ms; }
.values.is-visible .value-card:nth-child(2) { transition-delay: 90ms; }
.values.is-visible .value-card:nth-child(3) { transition-delay: 180ms; }
.values.is-visible .value-card:nth-child(4) { transition-delay: 270ms; }
.values.is-visible .value-card:nth-child(5) { transition-delay: 360ms; }
.value-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 24px 50px -30px rgba(6, 11, 77, 0.3);
  border-color: rgba(209, 36, 36, 0.25);
}
/* :hover never fires on touch, so without this a tap here did nothing
   visible at all — unlike the credential cards, which flip either way.
   :active covers the actual press instant on touch (and briefly on
   mouse), giving the same "this responded to me" feedback tap-only
   visitors were missing. */
.value-card:active {
  transform: translateY(-2px) scale(0.98);
  transition-duration: 0.1s;
}
.value-card:active .value-badge { transform: rotate(-6deg) scale(1.05); }
.value-num {
  position: absolute;
  top: 0.75rem;
  right: 1.1rem;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 2.2rem;
  color: var(--navy-900);
  opacity: 0.06;
  line-height: 1;
  pointer-events: none;
}
.value-badge {
  display: inline-grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, var(--navy-900), #1d3fd6);
  color: var(--white);
  margin-bottom: 1.1rem;
  box-shadow: 0 12px 24px -12px rgba(29, 63, 214, 0.55);
  transition: transform 0.35s var(--ease);
}
.value-card:hover .value-badge { transform: rotate(-6deg) scale(1.08); }
.value-card h3 { position: relative; margin: 0 0 0.6rem; font-size: 1.1rem; color: var(--navy-900); }
.value-card p { position: relative; margin: 0; color: var(--gray-600); font-size: 0.95rem; line-height: 1.7; }
@media (prefers-reduced-motion: reduce) {
  .value-card { opacity: 1; transform: none; transition: box-shadow 0.25s, border-color 0.25s; }
  .value-card:hover .value-badge { transform: none; }
}

.credentials { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); background: rgba(6, 11, 77, 0.035); }
.credentials-grid { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
@media (min-width: 640px) {
  .credentials-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .credentials-grid { grid-template-columns: repeat(5, 1fr); }
}
/* Outer element: owns the scroll-in entrance (opacity/translateY, staggered
   per card) AND the 3D perspective the inner flip lives inside. Splitting
   entrance from flip onto outer/inner means the two transforms never
   collide — the entrance never needs to know the card's rotateY angle,
   and the flip never needs to know the entrance offset. */
.credential-flip {
  position: relative;
  min-height: 176px;
  perspective: 1200px;
  cursor: pointer;
  opacity: 0;
  transform: translateY(24px) scale(0.97);
  transition: opacity 0.55s var(--ease), transform 0.55s var(--ease);
}
.credential-flip:focus-visible { outline: 3px solid var(--red-600); outline-offset: 4px; border-radius: var(--radius-md); }
.credentials.is-visible .credential-flip { opacity: 1; transform: translateY(0) scale(1); }
.credentials.is-visible .credential-flip:nth-child(1) { transition-delay: 0ms; }
.credentials.is-visible .credential-flip:nth-child(2) { transition-delay: 80ms; }
.credentials.is-visible .credential-flip:nth-child(3) { transition-delay: 160ms; }
.credentials.is-visible .credential-flip:nth-child(4) { transition-delay: 240ms; }
.credentials.is-visible .credential-flip:nth-child(5) { transition-delay: 320ms; }

.credential-flip-inner {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: inherit;
  transform-style: preserve-3d;
  transition: transform 0.6s var(--ease);
}
/* Hover flips on anything that can hover; script.js's .is-flipped class
   (click + Enter/Space) covers touch and keyboard on top of that — both
   just set the same rotateY, so it doesn't matter which one triggered it. */
@media (hover: hover) {
  .credential-flip:hover .credential-flip-inner { transform: rotateY(180deg); }
}
.credential-flip.is-flipped .credential-flip-inner { transform: rotateY(180deg); }

.credential-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  background: var(--white);
  border: 1px solid var(--gray-100);
  border-top: 3px solid transparent;
  border-radius: var(--radius-md);
  padding: 1.75rem 1.25rem 1.5rem;
  text-align: center;
  box-shadow: 0 16px 32px -26px rgba(6, 11, 77, 0.25);
  transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.credential-flip:hover .credential-face--front,
.credential-flip.is-flipped .credential-face--front {
  border-top-color: var(--red-600);
  box-shadow: 0 24px 44px -26px rgba(6, 11, 77, 0.3);
}
.credential-face--back {
  transform: rotateY(180deg);
  display: flex;
  align-items: center;
  background: linear-gradient(150deg, var(--navy-900), #1d3fd6);
  border-top-color: transparent;
}
.credential-face--back p { margin: 0; color: rgba(255, 255, 255, 0.92); font-size: 0.86rem; line-height: 1.55; }
/* Wraps the badge so the little "verified" checkmark can be pinned to its
   corner without the card itself needing position:relative bookkeeping. */
.credential-badge-wrap { position: relative; display: inline-block; margin-bottom: 0.9rem; }
.credential-badge {
  display: inline-grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(209, 36, 36, 0.95), rgba(6, 11, 77, 0.95));
  color: var(--white);
  box-shadow: 0 12px 24px -12px rgba(209, 36, 36, 0.5);
  transition: transform 0.35s var(--ease);
}
.credential-flip:hover .credential-badge { transform: scale(1.08); }
.credential-check {
  position: absolute;
  bottom: -2px;
  right: -2px;
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #1a9d5c;
  border: 2px solid var(--white);
}
.credential-face strong { display: block; font-size: 0.95rem; color: var(--navy-900); margin-bottom: 0.25rem; }
.credential-face > span { display: block; font-size: 0.82rem; color: var(--gray-600); line-height: 1.5; }
@media (prefers-reduced-motion: reduce) {
  .credential-flip { opacity: 1; transform: none; }
  .credential-flip-inner { transition: none; }
  .credential-flip:hover .credential-badge { transform: none; }
}

/* Shared "this copy is a placeholder" flag, used across Our Leaders and
   Our Story wherever RPG hasn't supplied real content yet. Dashed border
   + amber tone deliberately reads as "unfinished draft", never as
   finished, publishable copy. */
.draft-notice {
  display: inline-block;
  background: #fff7ed;
  color: #9a3412;
  border: 1px dashed #f59e0b;
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.9rem;
  font-size: 0.82rem;
  font-weight: 600;
  margin: 0 0 1.5rem;
}
.draft-notice--inline { margin: 0.5rem 0; }
.story-placeholder { color: #9a3412; font-style: italic; }

/* ==========================================================================
   Our Leaders (about.html) — horizontal photo strip
   ========================================================================== */
.leaders { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); background: var(--white); }
/* Small circular avatars (not full-bleed portrait tiles) so a roster this
   size — directors, operations, and the full sales team — stays "just
   nice" rather than a handful of oversized headshots. People whose photo
   hasn't been supplied yet get a plain person-icon avatar instead of a
   stock/placeholder photo, clearly marked rather than faked. */
.team-group + .team-group { margin-top: clamp(2.5rem, 2rem + 2vw, 3.5rem); }
.team-group-title {
  font-family: var(--font-heading);
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--navy-900);
  margin: 0 0 1.25rem;
  text-align: center;
}
.team-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.75rem 1rem;
}
@media (min-width: 640px) { .team-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 900px) { .team-grid { grid-template-columns: repeat(4, 1fr); } }
/* The directors group only ever has 2 people — stretching them across the
   same 4-column grid as the bigger teams left them stranded at opposite
   edges with a huge gap between. Centered flex row with a capped card
   width instead, so the two sit close together regardless of viewport. */
.team-grid--centered {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.75rem 3rem;
}
.team-grid--centered .team-card { width: 140px; flex: 0 0 auto; }
.team-card { text-align: center; }
.team-avatar {
  width: 92px;
  height: 92px;
  border-radius: 50%;
  overflow: hidden;
  margin: 0 auto 0.75rem;
  background: var(--gray-100);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--gray-400);
  border: 3px solid var(--white);
  box-shadow: var(--shadow-card);
}
.team-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.team-card h3 { font-size: 0.9rem; color: var(--navy-900); margin: 0 0 0.15rem; font-weight: 700; }
.team-card span { display: block; font-size: 0.76rem; color: var(--gray-600); font-style: italic; line-height: 1.35; }

/* ==========================================================================
   Our Story — Timeline (about.html)
   ========================================================================== */
.story { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); background: rgba(6, 11, 77, 0.035); }
.timeline { position: relative; max-width: 640px; margin: 0 auto; }
.timeline::before {
  content: '';
  position: absolute;
  left: 19px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: var(--gray-100);
}
.timeline-item { position: relative; padding-left: 60px; margin-bottom: clamp(2rem, 1.6rem + 1.6vw, 3rem); }
.timeline-item:last-child { margin-bottom: 0; }
.timeline-dot {
  position: absolute;
  left: 11px;
  top: 6px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--white);
  border: 3px solid var(--red-600);
  z-index: 1;
}
.timeline-item--verified .timeline-dot { border-color: #1a9d5c; }
.timeline-item--future .timeline-dot { border-color: var(--gray-400); border-style: dashed; }
.timeline-photo {
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 16 / 9;
  margin-bottom: 1rem;
}
.timeline-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.timeline-photo--placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  background: var(--gray-50);
  border: 1px dashed var(--gray-100);
  color: var(--gray-400);
  font-size: 0.78rem;
  font-weight: 600;
}
.timeline-year {
  display: inline-block;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.25rem;
  color: var(--red-600);
}
.timeline-item--verified .timeline-year { color: #1a9d5c; }
.timeline-body h3 { font-size: 1.1rem; color: var(--navy-900); margin: 0.4rem 0 0.5rem; }
.timeline-body p { color: var(--gray-600); line-height: 1.7; margin: 0; }
.timeline-item--verified .timeline-body { background: var(--white); border-radius: var(--radius-lg); padding: clamp(1.25rem, 1rem + 1vw, 1.75rem); box-shadow: var(--shadow-card); margin-top: -0.25rem; }
.timeline-item--verified .timeline-photo { margin: 0 0 1rem; }

/* ==========================================================================
   Awards Recognition (about.html)
   ========================================================================== */
.awards { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); background: var(--white); }
/* Three verified recognitions now (National Energy Awards, SolaX Rising
   Star Installer — Shanghai, SolaX factory visit China) — responsive
   grid that lays out 3-up on desktop, 2-up on tablet, 1-up on mobile. */
.awards-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.25rem, 1rem + 1vw, 2rem);
}
@media (max-width: 900px) { .awards-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .awards-grid { grid-template-columns: 1fr; } }
.award-card {
  width: 100%;
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.award-card img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; }
.award-card-body { padding: clamp(1.25rem, 1rem + 1vw, 1.75rem); }
.award-card-body h3 { font-size: 1.1rem; color: var(--navy-900); margin: 0 0 0.4rem; }
.award-card-body p { color: var(--gray-600); font-size: 0.9rem; line-height: 1.6; margin: 0; }

/* ==========================================================================
   Contact page (contact.html)
   ========================================================================== */
.contact-hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(6rem, 5rem + 5vw, 9rem) clamp(4rem, 3.2rem + 4vw, 6rem);
  text-align: left;
  color: var(--white);
}
.contact-hero-media { position: absolute; inset: 0; z-index: 0; }
.contact-hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: 75% center; display: block; }
/* Same diagonal wash as the homepage hero — see .about-hero-gradient for
   the full rationale (fades to fully transparent on the right instead of
   sitting at a flat 0.55 alpha across the whole photo). */
.contact-hero-gradient {
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, rgba(6,11,77,0.94) 0%, rgba(6,11,77,0.86) 28%, rgba(90,20,50,0.55) 52%, rgba(6,11,77,0.15) 72%, rgba(6,11,77,0) 88%);
}
.contact-hero-inner { position: relative; z-index: 2; }
.contact-hero .section-eyebrow,
.contact-hero h1,
.contact-hero-lede,
.contact-hero .about-hero-chips {
  opacity: 0;
  transform: translateY(16px);
  animation: aboutHeroIn 0.7s var(--ease) forwards;
}
.contact-hero .section-eyebrow { animation-delay: 0.05s; color: #ff8a8a; }
.contact-hero .section-eyebrow::before { background: #ff8a8a; }
.contact-hero h1 {
  animation-delay: 0.15s;
  margin: 0.6rem 0 0;
  max-width: 42rem;
  font-size: clamp(2rem, 1.6rem + 2vw, 3rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--white);
}
.contact-hero-lede {
  animation-delay: 0.28s;
  margin: 1.25rem 0 0;
  max-width: 54ch;
  color: rgba(255, 255, 255, 0.85);
  font-size: var(--fs-lede);
}
.contact-hero .about-hero-chips { animation-delay: 0.42s; }
@media (prefers-reduced-motion: reduce) {
  .contact-hero .section-eyebrow,
  .contact-hero h1,
  .contact-hero-lede,
  .contact-hero .about-hero-chips {
    opacity: 1;
    transform: none;
    animation: none;
  }
}

/* ----- Quick contact cards ------------------------------------------- */
.contact-cards { padding-block: clamp(2.5rem, 2rem + 2vw, 4rem); background: var(--white); }
.contact-cards-grid {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 640px) {
  .contact-cards-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .contact-cards-grid { grid-template-columns: repeat(3, 1fr); }
}
.contact-card {
  position: relative;
  background: var(--gray-50);
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-lg);
  padding: 1.75rem 1.5rem;
  text-align: center;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease), border-color 0.25s var(--ease);
}
.contact-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 24px 50px -30px rgba(6, 11, 77, 0.3);
  border-color: rgba(209, 36, 36, 0.25);
}
.contact-card-icon {
  display: inline-grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, var(--navy-900), #1d3fd6);
  color: var(--white);
  margin-bottom: 1rem;
  box-shadow: 0 12px 24px -12px rgba(29, 63, 214, 0.55);
}
.contact-card h3 { margin: 0 0 0.5rem; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--gray-600); }
.contact-card-value {
  display: block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--navy-900);
  word-break: break-word;
}
a.contact-card-value:hover { color: var(--red-600); }
.contact-card-note { display: block; margin-top: 0.35rem; font-size: 0.8rem; color: var(--gray-600); }
.contact-copy {
  margin-top: 0.75rem;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--gray-400);
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-pill);
  padding: 0.3rem 0.85rem;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.contact-copy:hover { color: var(--navy-900); border-color: var(--gray-400); }
.contact-copy.is-copied { color: #1a9d5c; border-color: #1a9d5c; background: rgba(26, 157, 92, 0.08); }
.contact-hours-status { display: flex; align-items: center; justify-content: center; gap: 0.4rem; }
.contact-hours-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--gray-400);
  flex-shrink: 0;
}
.contact-hours-status.is-open .contact-hours-dot { background: #1a9d5c; box-shadow: 0 0 0 3px rgba(26, 157, 92, 0.18); }
.contact-hours-status.is-closed .contact-hours-dot { background: var(--red-600); box-shadow: 0 0 0 3px rgba(209, 36, 36, 0.15); }

/* ----- Large interactive map ------------------------------------------ */
.contact-map { padding-block: clamp(1rem, 0.6rem + 1vw, 1.75rem) clamp(3.5rem, 2.8rem + 3vw, 6rem); background: var(--white); }
/* 100vw + negative-margin breakout — same technique as .projects-marquee
   and .facts-scene — so the map reads as genuinely large/full-bleed
   rather than boxed into the same width as body copy. */
.contact-map-frame {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  height: clamp(340px, 32vw + 200px, 560px);
  background: var(--gray-50);
}
.contact-map-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
.contact-map-card {
  position: absolute;
  left: clamp(1rem, 4vw, 4rem);
  bottom: clamp(1rem, 4vw, 2.5rem);
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  align-items: flex-start;
  max-width: 320px;
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  box-shadow: 0 30px 60px -24px rgba(6, 11, 77, 0.45);
}
.contact-map-card-badge {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(209, 36, 36, 0.95), rgba(6, 11, 77, 0.95));
  color: var(--white);
}
.contact-map-card strong { display: block; font-size: 1rem; color: var(--navy-900); margin-bottom: 0.3rem; }
.contact-map-card address { font-style: normal; font-size: 0.86rem; color: var(--gray-600); line-height: 1.5; }
.contact-map-card .btn { width: 100%; justify-content: center; padding: 0.7rem 1.2rem; font-size: 0.88rem; }
@media (max-width: 639px) {
  .contact-map-card { position: static; max-width: none; border-radius: 0; box-shadow: none; border-top: 3px solid var(--red-600); }
}

/* ----- Contact form ----------------------------------------------------- */
.contact-form-section { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6.5rem); background: var(--gray-50); }
.contact-form-grid {
  display: grid;
  gap: clamp(2rem, 1.5rem + 2vw, 3rem);
}
@media (min-width: 960px) {
  .contact-form-grid { grid-template-columns: 1.6fr 1fr; align-items: start; }
}
.contact-form-panel {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: clamp(1.75rem, 1.4rem + 1.6vw, 2.75rem);
  box-shadow: 0 30px 60px -36px rgba(6, 11, 77, 0.3);
}
.contact-form-heading { text-align: left; margin-bottom: clamp(1.5rem, 1.2rem + 1.2vw, 2rem); max-width: none; }
.contact-form-heading p:not(.section-eyebrow) { margin-left: 0; }

.form-row { display: grid; gap: 1rem; }
@media (min-width: 560px) {
  .form-row { grid-template-columns: 1fr 1fr; }
}
.form-field { margin-bottom: 1.1rem; display: flex; flex-direction: column; gap: 0.4rem; }
.form-field label { font-size: 0.86rem; font-weight: 700; color: var(--navy-900); }
.form-field label span[aria-hidden] { color: var(--red-600); }
.form-optional { font-weight: 500; color: var(--gray-400); }
.form-field input,
.form-field select,
.form-field textarea {
  width: 100%;
  border: 1.5px solid var(--gray-100);
  border-radius: var(--radius-md);
  padding: 0.75rem 0.9rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--white);
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  outline: none;
  border-color: var(--navy-900);
  box-shadow: 0 0 0 3px rgba(6, 11, 77, 0.1);
}
.form-field textarea { resize: vertical; min-height: 120px; }
.form-field.has-error input,
.form-field.has-error textarea { border-color: var(--red-600); }
.form-field.has-error label { color: var(--red-600); }
.form-error { font-size: 0.78rem; color: var(--red-600); min-height: 1em; }
.form-field-foot { display: flex; justify-content: space-between; gap: 1rem; }
.form-counter { font-size: 0.76rem; color: var(--gray-400); white-space: nowrap; }
.form-submit { margin-top: 0.5rem; width: 100%; justify-content: center; }
.form-submit[disabled] { opacity: 0.6; cursor: not-allowed; }
/* ":not([hidden])", not a plain ".form-success" — the element starts
   [hidden] in the markup and script.js only ever removes that attribute
   once the form actually submits. A bare "display: flex" here is a class
   selector at the same specificity as the browser's own "[hidden] {
   display: none }" rule, and author styles win any specificity tie
   against the UA stylesheet — so it was silently overriding "hidden" and
   showing the success message on every page load, submitted or not. */
.form-success:not([hidden]) {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  margin: 1rem 0 0;
  padding: 0.9rem 1rem;
  border-radius: var(--radius-md);
  background: rgba(26, 157, 92, 0.08);
  color: #157a48;
  font-size: 0.88rem;
  line-height: 1.5;
}
.form-success svg { flex-shrink: 0; margin-top: 0.1rem; }

.contact-side-panel {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}
.contact-side-panel h3 { margin: 0 0 0.25rem; font-size: 1rem; color: var(--navy-900); }
.contact-side-link {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  background: var(--white);
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-md);
  padding: 1rem 1.1rem;
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), border-color 0.2s var(--ease);
}
.contact-side-link:hover {
  transform: translateY(-3px);
  box-shadow: 0 20px 40px -28px rgba(6, 11, 77, 0.3);
  border-color: rgba(209, 36, 36, 0.25);
}
.contact-side-icon {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(6, 11, 77, 0.06);
  color: var(--navy-900);
  flex-shrink: 0;
}
.contact-side-link strong { display: block; font-size: 0.95rem; color: var(--navy-900); }
.contact-side-link span span { display: block; font-size: 0.8rem; color: var(--gray-600); margin-top: 0.1rem; }
.contact-side-social {
  margin-top: 0.5rem;
  padding: 1rem 1.1rem;
  background: var(--white);
  border: 1px solid var(--gray-100);
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.contact-side-social > span { font-size: 0.85rem; font-weight: 700; color: var(--navy-900); }
.contact-side-social > div { display: flex; gap: 0.5rem; }
.contact-side-social a {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--gray-50);
  color: var(--navy-900);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.contact-side-social a:hover { background: var(--navy-900); color: var(--white); }

/* ==========================================================================
   Packages page (packages.html)
   ========================================================================== */

/* ----- Hero: solid navy + dot-grid + glows, not a photo hero ------------ */
/* team-install.jpg is a real RPG photo (Gombak install), shown as a framed
   card that floats beside the copy instead of behind it — same navy/red-
   glow/dot-grid visual language as the footer (see .footer-pattern) so
   this still reads as part of the same site, just without reusing the
   photo-hero treatment a third time. */
.pkg-hero {
  position: relative;
  overflow: hidden;
  background: linear-gradient(160deg, var(--navy-900) 0%, var(--navy-800) 100%);
  padding-block: clamp(6.5rem, 5.5rem + 5vw, 9.5rem) clamp(3.5rem, 2.8rem + 3vw, 5.5rem);
}
.pkg-hero-pattern {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(255, 255, 255, 0.12) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(75% 65% at 30% 20%, #000 0%, transparent 85%);
  mask-image: radial-gradient(75% 65% at 30% 20%, #000 0%, transparent 85%);
}
.pkg-hero-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  pointer-events: none;
}
.pkg-hero-glow--a { width: 480px; height: 480px; left: -8%; top: -15%; background: rgba(209, 36, 36, 0.22); }
.pkg-hero-glow--b { width: 460px; height: 460px; right: -10%; bottom: -20%; background: rgba(29, 63, 214, 0.28); }
.pkg-hero-inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: clamp(2.5rem, 2rem + 2vw, 3.5rem);
  align-items: center;
}
.pkg-hero-copy .section-eyebrow { color: #ff8a8a; }
.pkg-hero-copy .section-eyebrow::before { background: #ff8a8a; }
.pkg-hero-copy h1 {
  color: var(--white);
  max-width: 22ch;
  font-size: clamp(2.4rem, 1.8rem + 3.2vw, 4.2rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.pkg-hero-lede { margin-top: 1.1rem; max-width: 46ch; color: rgba(255, 255, 255, 0.85); font-size: var(--fs-lede); }
.pkg-hero-copy .btn { margin-top: 1.75rem; }
.pkg-hero-chips { justify-content: flex-start; margin: 1.75rem 0 0; max-width: none; }
/* Was a floating transparent-cutout stock photo (drop-shadow only works on
   a silhouetted PNG). Swapped to a real RPG install photo, which has a
   background/edges — so this is now a framed card (border + radius +
   shadow) that gently floats, rather than a fake cutout silhouette. */
.pkg-hero-art {
  position: relative;
  display: flex;
  justify-content: center;
}
.pkg-hero-art-frame {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 460px;
  border-radius: 20px;
  overflow: hidden;
  border: 6px solid var(--white);
  box-shadow: 0 30px 50px -12px rgba(6, 11, 77, 0.45);
  animation: pkgHeroFloat 6s ease-in-out infinite;
}
.pkg-hero-art-frame img {
  display: block;
  width: 100%;
  aspect-ratio: 13 / 10;
  object-fit: cover;
}
.pkg-hero-art-caption {
  position: absolute;
  left: 1rem;
  bottom: 1rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  background: rgba(6, 11, 77, 0.75);
  backdrop-filter: blur(6px);
  color: var(--white);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.pkg-hero-art-caption svg { flex-shrink: 0; color: var(--red-400, #ff8a8a); }
.pkg-hero-art-glow {
  position: absolute;
  inset: 10% 8%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.14), transparent 70%);
}
@keyframes pkgHeroFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-14px); }
}
@media (min-width: 900px) {
  .pkg-hero-inner { grid-template-columns: 1.05fr 0.95fr; }
}
@media (max-width: 899px) {
  .pkg-hero-art { order: -1; margin-bottom: 0.5rem; }
  .pkg-hero-art-frame { max-width: 340px; }
}
@media (prefers-reduced-motion: reduce) {
  .pkg-hero-art-frame { animation: none; }
}

/* ----- Quiz -------------------------------------------------------------- */
.pkg-quiz { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6rem); background: var(--gray-50); }
.pkg-quiz-card {
  max-width: 760px;
  margin: clamp(2rem, 1.5rem + 2vw, 3rem) auto 0;
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: clamp(1.75rem, 1.4rem + 1.5vw, 2.75rem);
}
.pkg-quiz-progress {
  display: flex;
  justify-content: center;
  gap: clamp(1rem, 0.6rem + 1.5vw, 2.25rem);
  list-style: none;
  margin: 0 0 clamp(1.75rem, 1.4rem + 1.5vw, 2.5rem);
  padding: 0;
}
.pkg-quiz-progress li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--gray-400);
  transition: color 0.25s var(--ease);
}
.pkg-quiz-progress li span {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--gray-100);
  color: var(--gray-600);
  font-size: 0.76rem;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.pkg-quiz-progress li.is-active,
.pkg-quiz-progress li.is-done { color: var(--navy-900); }
.pkg-quiz-progress li.is-active span { background: var(--red-600); color: var(--white); }
.pkg-quiz-progress li.is-done span { background: var(--navy-900); color: var(--white); }
.pkg-quiz-progress li[hidden] { display: none; }

.pkg-quiz-step { display: none; }
.pkg-quiz-step.is-active {
  display: block;
  animation: pkgStepIn 0.4s var(--ease);
}
@keyframes pkgStepIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
.pkg-quiz-step h3 {
  text-align: center;
  font-size: clamp(1.15rem, 1.05rem + 0.5vw, 1.4rem);
  margin-bottom: 1.5rem;
}
.pkg-quiz-hint {
  text-align: center;
  font-size: 0.85rem;
  color: var(--gray-600);
  margin: -0.9rem 0 1.5rem;
}
.pkg-quiz-back {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--gray-600);
  margin-bottom: 1.25rem;
}
.pkg-quiz-back:hover { color: var(--red-600); }

.pkg-bill-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.9rem;
}
@media (min-width: 640px) {
  .pkg-bill-grid { grid-template-columns: repeat(3, 1fr); }
}
.pkg-bill-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 1.1rem 0.75rem;
  border: 1.6px solid var(--gray-100);
  border-radius: var(--radius-md);
  background: var(--white);
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.pkg-bill-btn strong { font-family: var(--font-heading); font-size: 1.15rem; color: var(--navy-900); }
.pkg-bill-btn span { font-size: 0.76rem; color: var(--gray-600); }
.pkg-bill-btn:hover {
  border-color: var(--red-600);
  transform: translateY(-3px);
  box-shadow: 0 14px 26px -16px rgba(6, 11, 77, 0.3);
}
.pkg-bill-btn:active { transform: translateY(0); }

.pkg-phase-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.9rem;
}
@media (min-width: 560px) {
  .pkg-phase-grid { grid-template-columns: 1fr 1fr; }
}
.pkg-phase-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.35rem;
  padding: 1.25rem 1.4rem;
  border: 1.6px solid var(--gray-100);
  border-radius: var(--radius-md);
  background: var(--white);
  text-align: left;
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.pkg-phase-btn strong { font-family: var(--font-heading); font-size: 1.05rem; color: var(--navy-900); }
.pkg-phase-btn span { font-size: 0.82rem; color: var(--gray-600); }
.pkg-phase-btn:hover {
  border-color: var(--red-600);
  transform: translateY(-3px);
  box-shadow: 0 14px 26px -16px rgba(6, 11, 77, 0.3);
}
.pkg-phase-btn.is-active {
  border-color: var(--red-600);
  background: rgba(209, 36, 36, 0.05);
  box-shadow: 0 0 0 1.5px var(--red-600) inset;
}

/* ----- Mode toggle (Suggest My System / Build My Own) -------------------- */
.pkg-mode-toggle {
  display: flex;
  justify-content: center;
  gap: 0.6rem;
  max-width: 760px;
  margin: clamp(2rem, 1.5rem + 2vw, 3rem) auto 0;
  flex-wrap: wrap;
}
.pkg-mode-btn {
  padding: 0.7rem 1.3rem;
  border-radius: var(--radius-pill);
  border: 1.6px solid var(--gray-100);
  background: var(--white);
  color: var(--gray-600);
  font-weight: 700;
  font-size: 0.88rem;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease), background 0.2s var(--ease);
}
.pkg-mode-btn:hover { border-color: rgba(209, 36, 36, 0.4); color: var(--navy-900); }
.pkg-mode-btn.is-active {
  border-color: var(--red-600);
  background: var(--red-600);
  color: var(--white);
}

/* ----- Build Your Own ----------------------------------------------------- */
.pkg-diy h3 { margin: 0 0 0.5rem; font-size: clamp(1.3rem, 1.15rem + 0.7vw, 1.7rem); text-align: center; }
.pkg-diy-field { margin-top: 1.75rem; }
.pkg-diy-field > label {
  display: block;
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--navy-900);
  margin-bottom: 0.7rem;
}
.pkg-diy-stepper {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.pkg-diy-stepper-btn {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1.6px solid var(--gray-100);
  background: var(--white);
  color: var(--navy-900);
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease), color 0.2s var(--ease);
}
.pkg-diy-stepper-btn:hover { border-color: var(--red-600); background: var(--red-600); color: var(--white); }
.pkg-diy-stepper input[type="number"] {
  flex: 1;
  text-align: center;
  font-family: var(--font-heading);
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--navy-900);
  border: 1.6px solid var(--gray-100);
  border-radius: var(--radius-sm);
  padding: 0.6rem;
  -moz-appearance: textfield;
}
.pkg-diy-stepper input[type="number"]::-webkit-outer-spin-button,
.pkg-diy-stepper input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pkg-diy-range {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  height: 5px;
  margin-top: 1rem;
  border-radius: var(--radius-pill);
  background: var(--gray-100);
  cursor: pointer;
}
.pkg-diy-range::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--white);
  border: 3px solid var(--red-600);
  box-shadow: 0 2px 6px rgba(6, 11, 77, 0.25);
}
.pkg-diy-range::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--white);
  border: 3px solid var(--red-600);
  box-shadow: 0 2px 6px rgba(6, 11, 77, 0.25);
}
.pkg-diy-range-scale { margin: 0.5rem 0 0; font-size: 0.75rem; color: var(--gray-400); text-align: center; }
.pkg-diy #pkgDiyResult { margin-top: 2rem; }

/* ----- Result spec card (mirrors the flyer layout) ----------------------- */
.pkg-result {
  animation: pkgStepIn 0.45s var(--ease);
}
.pkg-result-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--gray-100);
  margin-bottom: 1.5rem;
}
.pkg-result-head h3 { margin: 0; font-size: clamp(1.3rem, 1.15rem + 0.7vw, 1.7rem); text-align: left; }
.pkg-result-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--navy-900);
  color: var(--white);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.95rem;
  padding: 0.45rem 1rem;
  border-radius: var(--radius-pill);
}
.pkg-result-grid {
  display: grid;
  gap: 1.5rem;
}
@media (min-width: 720px) {
  .pkg-result-grid { grid-template-columns: 1fr 1fr; }
}
.pkg-result-specs { display: flex; flex-direction: column; gap: 0.6rem; }
.pkg-result-spec {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.7rem 1rem;
  background: var(--gray-50);
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
}
.pkg-result-spec-icon {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(209, 36, 36, 0.1);
  color: var(--red-600);
}
.pkg-result-spec-text { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex: 1; min-width: 0; }
.pkg-result-spec-text span:first-child { color: var(--gray-600); }
.pkg-result-spec-text span:last-child { font-weight: 700; color: var(--navy-900); text-align: right; }
.pkg-result-note {
  margin-top: 0.35rem;
  font-size: 0.8rem;
  color: var(--gray-600);
}
.pkg-result-note a { color: var(--red-600); font-weight: 700; text-decoration: underline; }

.pkg-result-price {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  background: linear-gradient(160deg, var(--navy-900), var(--navy-800));
  border-radius: var(--radius-md);
  padding: 1.75rem 1.5rem;
  text-align: center;
  color: var(--white);
}
.pkg-result-price span { font-size: 0.8rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: rgba(255, 255, 255, 0.7); }
.pkg-result-price strong { font-family: var(--font-heading); font-size: clamp(2rem, 1.7rem + 1vw, 2.6rem); font-weight: 800; }
.pkg-result-cta {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  width: 100%;
  margin-top: 0.5rem;
}
.pkg-result-cta .btn { width: 100%; justify-content: center; }
.pkg-result-cta .btn-outline-white {
  background: transparent;
  border: 1.6px solid rgba(255, 255, 255, 0.4);
  color: var(--white);
}
.pkg-result-cta .btn-outline-white:hover { background: rgba(255, 255, 255, 0.12); }

/* ----- Compare-all strip -------------------------------------------------- */
/* Soft version of the dark-section texture used on the hero/footer: two
   low-opacity brand-color glows plus a faint dot-grid, scaled way down in
   intensity since this sits behind white/gray content instead of navy. */
.pkg-compare { position: relative; overflow: hidden; padding-block: clamp(3.5rem, 2.8rem + 3vw, 6rem); background: var(--white); }
.pkg-compare::before,
.pkg-compare::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  pointer-events: none;
  z-index: 0;
}
.pkg-compare::before { width: 420px; height: 420px; left: -6%; top: -10%; background: rgba(209, 36, 36, 0.05); }
.pkg-compare::after { width: 420px; height: 420px; right: -8%; bottom: -15%; background: rgba(29, 63, 214, 0.06); }
.pkg-compare > .site-container { position: relative; z-index: 1; }
.pkg-compare-toolbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-top: clamp(1.75rem, 1.4rem + 1.5vw, 2.5rem);
}
.pkg-compare-hint { font-size: 0.8rem; color: var(--gray-600); margin-right: auto; }
.pkg-compare-nav-group { display: flex; gap: 0.5rem; }
.pkg-compare-nav {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--gray-100);
  background: var(--white);
  color: var(--navy-900);
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), transform 0.2s var(--ease);
}
.pkg-compare-nav:hover { background: var(--red-600); color: var(--white); transform: scale(1.05); }
@media (max-width: 640px) {
  .pkg-compare-nav-group, .pkg-compare-hint { display: none; }
  .pkg-compare-toolbar { margin-top: 1rem; }
}

/* Scrollbar hidden entirely (Firefox via scrollbar-width, WebKit/Blink via
   ::-webkit-scrollbar) — between autoplay and the arrow buttons there's
   already a clear affordance that this scrolls, so the bar itself was just
   extra visual noise under the cards. The edge mask still fades whatever
   card sits at the scroller's physical left/right edge, as a polish touch
   and a "there's more this way" hint. */
.pkg-compare-scroller {
  overflow-x: auto;
  padding: 0.25rem 0 0.5rem;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
}
.pkg-compare-scroller::-webkit-scrollbar { display: none; }
.pkg-compare-grid {
  display: flex;
  gap: 1.1rem;
  list-style: none;
  margin: 0;
  padding: 0.5rem 28px 0.5rem;
  width: max-content;
}
.pkg-compare-card {
  position: relative;
  overflow: hidden;
  width: 210px;
  flex-shrink: 0;
  border: 1.6px solid var(--gray-100);
  border-radius: var(--radius-md);
  padding: 1.35rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  background: var(--white);
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.pkg-compare-card:hover { transform: translateY(-4px); box-shadow: 0 16px 28px -18px rgba(6, 11, 77, 0.28); }
.pkg-compare-card.is-selected { border-color: var(--red-600); box-shadow: 0 16px 28px -16px rgba(209, 36, 36, 0.3); }
.pkg-compare-card.is-recommended { border-color: rgba(209, 36, 36, 0.35); padding-top: 2.65rem; }
/* Plain horizontal bar across the top of the card, not a diagonal corner
   ribbon — a rotated ribbon needs ~150px of text-width to read cleanly,
   which doesn't fit a 210px-wide card at any font size without wrapping or
   overflowing. A full-width bar has no such constraint: at the card's own
   width "Recommended" fits with room to spare, guaranteed, and the card's
   existing overflow:hidden + border-radius already clips its corners to
   match the card shape, so no extra rounding needed here. */
.pkg-compare-ribbon {
  position: absolute;
  z-index: 2;
  top: 0;
  left: 0;
  right: 0;
  padding: 0.5rem 0.5rem;
  background: var(--red-600);
  color: var(--white);
  font-size: 0.68rem;
  font-weight: 800;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  text-align: center;
}
/* Large faint watermark icon in the corner — same "physical surface, not a
   flat swatch" trick as the homepage stat strip's corner glyphs — so each
   card reads as a little illustrated tile rather than a stack of numbers. */
.pkg-compare-card-watermark {
  position: absolute;
  bottom: -14px;
  right: -14px;
  width: 76px;
  height: 76px;
  color: var(--navy-900);
  opacity: 0.05;
  pointer-events: none;
}
.pkg-compare-card-icon {
  position: relative;
  z-index: 1;
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(209, 36, 36, 0.1);
  color: var(--red-600);
  margin-bottom: 0.35rem;
}
.pkg-compare-card-bill { position: relative; z-index: 1; font-size: 0.76rem; font-weight: 700; color: var(--gray-600); text-transform: uppercase; letter-spacing: 0.04em; }
.pkg-compare-card-kwp { position: relative; z-index: 1; font-family: var(--font-heading); font-size: 1.3rem; font-weight: 800; color: var(--navy-900); }
.pkg-compare-card-meta { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.8rem; color: var(--gray-600); }
.pkg-compare-card-meta span { display: flex; align-items: center; gap: 0.35rem; }
.pkg-compare-card-meta svg { flex-shrink: 0; color: var(--gray-400); }
.pkg-compare-card-price { position: relative; z-index: 1; font-family: var(--font-heading); font-weight: 800; color: var(--red-600); font-size: 1.05rem; margin-top: 0.15rem; }
.pkg-compare-card button {
  position: relative;
  z-index: 1;
  margin-top: 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--navy-900);
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}
.pkg-compare-card button:hover { color: var(--red-600); }

/* ----- Shared inclusions --------------------------------------------------- */
.pkg-inclusions { position: relative; overflow: hidden; padding-block: clamp(3.5rem, 2.8rem + 3vw, 6rem); background: var(--gray-50); }
.pkg-inclusions-pattern {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(6, 11, 77, 0.05) 1px, transparent 1px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(70% 60% at 50% 30%, #000 0%, transparent 85%);
  mask-image: radial-gradient(70% 60% at 50% 30%, #000 0%, transparent 85%);
}
.pkg-inclusions > .site-container { position: relative; z-index: 1; }
.pkg-inclusions-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  max-width: 720px;
  margin: clamp(1.75rem, 1.4rem + 1.5vw, 2.5rem) auto 0;
}
@media (min-width: 640px) {
  .pkg-inclusions-stats { grid-template-columns: repeat(4, 1fr); }
}
.pkg-inclusions-stat {
  background: var(--white);
  border-radius: var(--radius-md);
  padding: 1.5rem 0.75rem 1.25rem;
  text-align: center;
  box-shadow: var(--shadow-card);
}
.pkg-inclusions-stat-icon {
  position: relative;
  display: inline-block;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(209, 36, 36, 0.1);
  color: var(--red-600);
  margin-bottom: 0.6rem;
}
/* Went with inline-flex + align/justify-center first, which should have
   been enough on its own — but it visibly wasn't landing (icon kept
   sitting top-left in the circle, screenshot to screenshot, even after
   the flex change was in place), so rather than keep guessing at why
   flow-based centering wasn't taking, switched to absolute positioning:
   pull the svg fully out of flow and place it by raw geometry against
   the circle's own center. This doesn't depend on flex/inline-block
   behavior working "correctly" in whatever's rendering this — top:50%;
   left:50% locates the svg's top-left corner at the circle's exact
   center, and translate(-50%,-50%) shifts it back by exactly half its
   own box, which is a fixed, engine-agnostic calculation with nothing
   left to go wrong. */
.pkg-inclusions-stat-icon svg {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 26px;
  height: 26px;
  color: var(--red-600);
}
.pkg-inclusions-stat strong { display: block; font-family: var(--font-heading); font-size: 1.4rem; font-weight: 800; color: var(--red-600); }
.pkg-inclusions-stat span { display: block; margin-top: 0.25rem; font-size: 0.76rem; color: var(--gray-600); }
.pkg-inclusions-list {
  list-style: none;
  margin: clamp(2rem, 1.6rem + 1.6vw, 2.75rem) auto 0;
  padding: 0;
  max-width: 760px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.9rem 2rem;
}
@media (min-width: 640px) {
  .pkg-inclusions-list { grid-template-columns: 1fr 1fr; }
}
.pkg-inclusions-list li {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.92rem;
  color: var(--ink);
}
.pkg-inclusions-list li svg {
  flex-shrink: 0;
  color: var(--white);
  background: var(--red-600);
  border-radius: 50%;
  padding: 3px;
  width: 20px;
  height: 20px;
}

/* ----- Disclaimer ------------------------------------------------------- */
.pkg-disclaimer { padding-block: clamp(2.5rem, 2rem + 2vw, 4rem); background: var(--white); }
.pkg-disclaimer-card {
  position: relative;
  max-width: 900px;
  margin: 0 auto;
  padding: clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem);
  background: var(--gray-50);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--red-600);
}
/* Was italic gray text with no icon — read as an afterthought rather
   than an intentional label. Small red warning-triangle icon + solid
   uppercase tag styling brings it in line with how every other section
   on this page labels itself (.section-eyebrow pattern), instead of it
   looking like a stray line of body copy. */
.pkg-disclaimer-card h3 {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.78rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--red-600);
  margin-bottom: 1rem;
}
.pkg-disclaimer-card h3 svg { flex-shrink: 0; }
/* The <ol> here was relying on the browser's native decimal markers for
   numbering — except the site loads the Tailwind CDN script at runtime,
   whose Preflight reset (menu,ol,ul{list-style:none}) strips exactly
   that, and since it's loaded after this stylesheet it wins on any
   selector this specific. Net result: the 1.2rem left padding was still
   reserving indent space, but the numbers that padding was meant to
   make room for were invisible — three paragraphs with a mystery gap on
   the left and no visual separation between them. Rather than fight
   Tailwind's reset, this now builds its own numbered badges with CSS
   counters, matching the red-tinted circle-icon language already used
   for the checkmarks in .pkg-inclusions-list and the stat icons above. */
.pkg-disclaimer-card ol {
  list-style: none;
  counter-reset: disclaimer;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.pkg-disclaimer-card li {
  position: relative;
  counter-increment: disclaimer;
  padding-left: 2.15rem;
  font-size: 0.85rem;
  color: var(--gray-700, var(--gray-600));
  line-height: 1.6;
}
.pkg-disclaimer-card li::before {
  content: counter(disclaimer);
  position: absolute;
  left: 0;
  top: 0.05rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 50%;
  background: rgba(209, 36, 36, 0.12);
  color: var(--red-600);
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 0.72rem;
}

/* ==========================================================================
   Projects page (projects.html)
   ========================================================================== */
/* Hero: identical structure/formula to .about-hero/.contact-hero (photo +
   diagonal navy-to-transparent gradient, reusing .about-hero-chips for the
   chip row) — kept as its own named block rather than just reusing
   .about-hero directly so the photo/copy pairing stays semantically tied
   to this page, matching the established one-hero-class-per-page pattern. */
.projects-hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(6rem, 5rem + 5vw, 9rem) clamp(4rem, 3.2rem + 4vw, 6rem);
  text-align: left;
  color: var(--white);
}
.projects-hero-media { position: absolute; inset: 0; z-index: 0; }
.projects-hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 35%; display: block; }
.projects-hero-gradient {
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, rgba(6,11,77,0.94) 0%, rgba(6,11,77,0.86) 28%, rgba(90,20,50,0.55) 52%, rgba(6,11,77,0.15) 72%, rgba(6,11,77,0) 88%);
}
.projects-hero-inner { position: relative; z-index: 2; }
.projects-hero .section-eyebrow,
.projects-hero h1,
.projects-hero-lede,
.projects-hero .about-hero-chips {
  opacity: 0;
  transform: translateY(16px);
  animation: aboutHeroIn 0.7s var(--ease) forwards;
}
.projects-hero .section-eyebrow { animation-delay: 0.05s; color: #ff8a8a; }
.projects-hero .section-eyebrow::before { background: #ff8a8a; }
.projects-hero h1 {
  animation-delay: 0.15s;
  color: var(--white);
  margin: 0.6rem 0 0;
  max-width: 46rem;
  font-size: clamp(2rem, 1.6rem + 2vw, 3rem);
  font-weight: 800;
}
.projects-hero-lede { animation-delay: 0.28s; margin: 1.1rem 0 0; max-width: 46ch; color: rgba(255, 255, 255, 0.85); font-size: var(--fs-lede); }
.projects-hero .about-hero-chips { animation-delay: 0.42s; justify-content: flex-start; }
@media (prefers-reduced-motion: reduce) {
  .projects-hero .section-eyebrow,
  .projects-hero h1,
  .projects-hero-lede,
  .projects-hero .about-hero-chips {
    opacity: 1;
    transform: none;
    animation: none;
  }
}

/* ----- Gallery ---------------------------------------------------------- */
.projects-gallery { position: relative; overflow: hidden; padding-block: clamp(3.5rem, 2.8rem + 3vw, 6rem); background: var(--gray-50); }
.projects-gallery-pattern {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(6, 11, 77, 0.05) 1px, transparent 1px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(70% 60% at 50% 0%, #000 0%, transparent 85%);
  mask-image: radial-gradient(70% 60% at 50% 0%, #000 0%, transparent 85%);
}
.projects-gallery > .site-container { position: relative; z-index: 1; }

.projects-filter {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  margin: clamp(1.75rem, 1.4rem + 1.5vw, 2.5rem) auto 0;
}
.projects-filter-btn {
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--navy-900);
  background: var(--white);
  border: 1px solid rgba(6, 11, 77, 0.12);
  border-radius: var(--radius-pill);
  padding: 0.55rem 1.15rem;
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.projects-filter-btn:hover { border-color: rgba(209, 36, 36, 0.4); }
.projects-filter-btn.is-active { background: var(--red-600); border-color: var(--red-600); color: var(--white); }

/* CSS columns rather than grid for the masonry-ish layout — the tall
   Langkawi lift shot (.projects-card--tall) sits naturally among the
   wide landscape shots without empty gaps or a JS layout library. Cards
   are <button>s (not <a>/<div>) since each one opens the lightbox — real
   interactive elements get real keyboard/focus support for free instead
   of a click handler bolted onto a non-interactive tag. */
.projects-grid {
  columns: 1;
  gap: 1rem;
  margin: clamp(2rem, 1.6rem + 1.6vw, 2.75rem) auto 0;
}
@media (min-width: 640px) { .projects-grid { columns: 2; } }
@media (min-width: 1024px) { .projects-grid { columns: 3; } }
.projects-card {
  position: relative;
  display: block;
  width: 100%;
  break-inside: avoid;
  margin-bottom: 1rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: pointer;
  background: var(--navy-900);
  box-shadow: var(--shadow-card);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.projects-card:hover,
.projects-card:focus-visible { transform: translateY(-4px); box-shadow: 0 20px 40px -18px rgba(6, 11, 77, 0.35); }
.projects-card img { display: block; width: 100%; height: auto; }
.projects-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(6, 11, 77, 0.82) 100%);
  pointer-events: none;
}
.projects-card-tag {
  position: absolute;
  z-index: 1;
  top: 0.75rem;
  left: 0.75rem;
  background: rgba(209, 36, 36, 0.92);
  color: var(--white);
  font-size: 0.65rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.3rem 0.65rem;
  border-radius: var(--radius-pill);
}
.projects-card-caption {
  position: absolute;
  z-index: 1;
  left: 0.9rem;
  right: 0.9rem;
  bottom: 0.8rem;
  color: var(--white);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.9rem;
  text-align: left;
}
/* Hidden-but-not-removed (rather than display:none via JS) — keeps the
   masonry column flow simple to reason about and gives the filter a fade
   to animate, instead of cards jumping between columns as items are
   added/removed from the layout mid-transition. */
.projects-card.is-filtered-out {
  display: none;
}
.projects-empty {
  text-align: center;
  color: var(--gray-600);
  margin: 2.5rem 0 0;
}

/* ----- Lightbox ----------------------------------------------------------- */
.projects-lightbox { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: 1.5rem; }
.projects-lightbox[hidden] { display: none; }
.projects-lightbox-backdrop { position: absolute; inset: 0; background: rgba(6, 11, 77, 0.88); backdrop-filter: blur(4px); }
.projects-lightbox-inner {
  position: relative;
  z-index: 1;
  max-width: min(90vw, 1100px);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.projects-lightbox-inner img {
  display: block;
  max-width: 100%;
  max-height: 76vh;
  width: auto;
  border-radius: var(--radius-md);
  box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.5);
}
.projects-lightbox-caption {
  margin: 0.85rem 0 0;
  color: var(--white);
  font-size: 0.9rem;
  text-align: center;
}
.projects-lightbox-close,
.projects-lightbox-nav {
  position: absolute;
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: var(--white);
  border: 1px solid rgba(255, 255, 255, 0.25);
  cursor: pointer;
  transition: background 0.2s var(--ease);
}
.projects-lightbox-close:hover,
.projects-lightbox-nav:hover { background: rgba(255, 255, 255, 0.22); }
.projects-lightbox-close { top: -0.5rem; right: -0.5rem; }
@media (min-width: 640px) { .projects-lightbox-close { top: 0; right: -3rem; } }
.projects-lightbox-prev { left: 0.5rem; top: 50%; transform: translateY(-50%); }
.projects-lightbox-next { right: 0.5rem; top: 50%; transform: translateY(-50%); }
@media (min-width: 900px) {
  .projects-lightbox-prev { left: -3.5rem; }
  .projects-lightbox-next { right: -3.5rem; }
}
@media (prefers-reduced-motion: reduce) {
  .projects-card { transition: none; }
}

/* ==========================================================================
   News page (news.html)
   ========================================================================== */
/* Hero: same photo + diagonal-gradient formula as about/contact/projects. */
.news-hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(6rem, 5rem + 5vw, 9rem) clamp(4rem, 3.2rem + 4vw, 6rem);
  text-align: left;
  color: var(--white);
}
.news-hero-media { position: absolute; inset: 0; z-index: 0; }
.news-hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 40%; display: block; }
.news-hero-gradient {
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, rgba(6,11,77,0.94) 0%, rgba(6,11,77,0.86) 28%, rgba(90,20,50,0.55) 52%, rgba(6,11,77,0.15) 72%, rgba(6,11,77,0) 88%);
}
.news-hero-inner { position: relative; z-index: 2; }
.news-hero .section-eyebrow,
.news-hero h1,
.news-hero-lede,
.news-hero .about-hero-chips {
  opacity: 0;
  transform: translateY(16px);
  animation: aboutHeroIn 0.7s var(--ease) forwards;
}
.news-hero .section-eyebrow { animation-delay: 0.05s; color: #ff8a8a; }
.news-hero .section-eyebrow::before { background: #ff8a8a; }
.news-hero h1 {
  animation-delay: 0.15s;
  color: var(--white);
  margin: 0.6rem 0 0;
  max-width: 42rem;
  font-size: clamp(2rem, 1.6rem + 2vw, 3rem);
  font-weight: 800;
}
.news-hero-lede { animation-delay: 0.28s; margin: 1.1rem 0 0; max-width: 46ch; color: rgba(255, 255, 255, 0.85); font-size: var(--fs-lede); }
.news-hero .about-hero-chips { animation-delay: 0.42s; justify-content: flex-start; }
@media (prefers-reduced-motion: reduce) {
  .news-hero .section-eyebrow,
  .news-hero h1,
  .news-hero-lede,
  .news-hero .about-hero-chips {
    opacity: 1;
    transform: none;
    animation: none;
  }
}

/* ----- As Featured In ---------------------------------------------------- */
.news-press { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6rem); background: var(--white); }

/* Plain logo strip for recognition at a glance — no card, no border, no
   background. This is the part a visitor actually scans ("oh, Bernama,
   Utusan — okay, legit"), so it should read instantly rather than
   competing with box chrome around it. Greyscale-by-default + colour on
   hover is the standard "as seen in" treatment for exactly this reason:
   it stays quiet until someone actually looks at it. */
.news-press-logos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(2rem, 1.6rem + 2vw, 3.5rem);
  margin: clamp(2rem, 1.6rem + 1.6vw, 2.75rem) auto 0;
  padding-bottom: clamp(2rem, 1.6rem + 1.6vw, 2.75rem);
  border-bottom: 1px solid rgba(6, 11, 77, 0.08);
}
.news-press-logos a {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  filter: grayscale(1);
  opacity: 0.55;
  transition: filter 0.2s var(--ease), opacity 0.2s var(--ease);
}
.news-press-logos a:hover,
.news-press-logos a:focus-visible { filter: grayscale(0); opacity: 1; }
.news-press-logos img { display: block; height: 30px; width: auto; object-fit: contain; }
.news-press-logos span:not(.news-press-wordmark) { font-family: var(--font-heading); font-weight: 800; font-size: 0.95rem; color: var(--navy-900); }
.news-press-wordmark {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.2rem;
  letter-spacing: -0.01em;
}
.news-press-wordmark em { font-style: normal; font-weight: 700; }
/* Sinar Harian's real mark is a bold italic red "Sinar" lockup with a
   thinner "Harian" trailing it — approximated here in the same red as
   their masthead. Colour is kept even at rest (unlike the photo logos
   above) since grayscale-filtering a hand-built wordmark just makes it
   look broken rather than muted. */
.news-press-wordmark--sinar { color: #e6242a; font-style: italic; }
.news-press-wordmark--sinar em { color: var(--navy-900); font-size: 0.85em; margin-left: 0.15em; }
.news-press-logos a:has(.news-press-wordmark) { filter: none; opacity: 0.7; }
.news-press-logos a:has(.news-press-wordmark):hover { opacity: 1; }
/* Utusan Malaysia's masthead is a plain bold navy/black wordmark, no
   italic or color accent — kept flat and structural to match. */
.news-press-wordmark--utusan { color: var(--navy-900); font-size: 1.05rem; letter-spacing: 0.02em; }
.news-press-wordmark--utusan em { font-weight: 800; }

/* Editorial list underneath — headline as the link, outlet + date as a
   plain byline, separated by hairlines. Reads like an actual press page
   rather than four more product cards. */
.news-press-list {
  list-style: none;
  margin: clamp(1.75rem, 1.4rem + 1.5vw, 2.5rem) auto 0;
  padding: 0;
  max-width: 760px;
}
.news-press-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 1.5rem;
  padding: 1.1rem 0;
  border-bottom: 1px solid rgba(6, 11, 77, 0.08);
}
.news-press-list li:first-child { padding-top: 0; }
.news-press-list a {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.4;
  color: var(--navy-900);
  text-decoration: none;
  max-width: 48ch;
  transition: color 0.15s var(--ease);
}
.news-press-list a:hover { color: var(--red-600); }
.news-press-byline { flex-shrink: 0; font-size: 0.78rem; color: var(--gray-600); white-space: nowrap; }

/* ----- Featured story ------------------------------------------------- */
.news-story { position: relative; overflow: hidden; padding-block: clamp(3.5rem, 2.8rem + 3vw, 6rem); background: var(--gray-50); }
.news-story-pattern {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(6, 11, 77, 0.05) 1px, transparent 1px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(70% 60% at 50% 0%, #000 0%, transparent 85%);
  mask-image: radial-gradient(70% 60% at 50% 0%, #000 0%, transparent 85%);
}
.news-story > .site-container { position: relative; z-index: 1; }
.news-story-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  max-width: 1000px;
  margin: clamp(2rem, 1.6rem + 1.6vw, 2.75rem) auto 0;
}
@media (min-width: 860px) { .news-story-grid { grid-template-columns: 1.6fr 1fr; } }
.news-story-copy p { color: var(--gray-700, var(--gray-600)); line-height: 1.75; margin: 0 0 1.1rem; }
.news-story-quote {
  margin: 1.5rem 0;
  padding: 1rem 1.25rem;
  background: var(--white);
  border-left: 3px solid var(--red-600);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}
.news-story-quote p { margin: 0 0 0.5rem; font-style: italic; color: var(--navy-900); font-size: 1.02rem; }
.news-story-quote cite { font-style: normal; font-size: 0.8rem; color: var(--gray-600); }
.news-story-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.85rem;
  align-content: start;
}
.news-story-stat {
  background: var(--white);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 1.1rem 1rem;
  text-align: center;
}
.news-story-stat strong { display: block; font-family: var(--font-heading); font-size: 1.35rem; font-weight: 800; color: var(--red-600); }
.news-story-stat span { display: block; margin-top: 0.3rem; font-size: 0.75rem; color: var(--gray-600); line-height: 1.4; }
.news-story-gallery { margin-top: clamp(2.5rem, 2rem + 2vw, 3.5rem); }

/* ----- Company update (LV TOPSUN visit) --------------------------------- */
.news-update { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6rem); background: var(--white); }
.news-update-card {
  display: grid;
  grid-template-columns: 1fr;
  max-width: 1000px;
  margin: clamp(2rem, 1.6rem + 1.6vw, 2.75rem) auto 0;
  background: var(--gray-50);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
@media (min-width: 860px) { .news-update-card { grid-template-columns: 1fr 1fr; } }
.news-update-media { position: relative; min-height: 220px; }
.news-update-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.news-update-body { padding: clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem); display: flex; flex-direction: column; }
.news-update-tag {
  display: inline-block;
  align-self: flex-start;
  background: rgba(209, 36, 36, 0.1);
  color: var(--red-600);
  font-size: 0.68rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-pill);
  margin-bottom: 0.75rem;
}
.news-update-body h3 { margin: 0 0 0.6rem; font-size: 1.25rem; }
.news-update-body p { margin: 0; color: var(--gray-700, var(--gray-600)); line-height: 1.65; }
.news-update-thumbs { display: flex; gap: 0.6rem; margin-top: 1.1rem; }
.news-update-thumbs img { width: 50%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-md); box-shadow: var(--shadow-card); }
/* Multiple cards stacked in one section (Deye/SolaX visits, NEA award,
   Solar for Ummah) — spacing between them, and alternating media/copy
   sides on desktop so a long stack doesn't read as a repetitive template. */
.news-update-card + .news-update-card { margin-top: clamp(1.5rem, 1.2rem + 1.2vw, 2rem); }
@media (min-width: 860px) {
  .news-update-card--flip .news-update-media { order: 2; }
  .news-update-card--flip .news-update-body { order: 1; }
}
.news-update-tag--award { background: rgba(217, 164, 6, 0.14); color: #9a7000; }

/* ==========================================================================
   Floating Contact Button (home page)
   ========================================================================== */
.contact-fab {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 70;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.75rem;
}
.contact-fab-menu {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.6rem;
  pointer-events: none;
}
.contact-fab-item {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.65rem 1.1rem 0.65rem 0.8rem;
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--navy-900);
  font-weight: 700;
  font-size: 0.88rem;
  box-shadow: 0 12px 26px -10px rgba(6, 11, 77, 0.35);
  opacity: 0;
  transform: translateY(8px) scale(0.96);
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease);
}
.contact-fab-item-icon {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--gray-50);
  color: var(--red-600);
  flex-shrink: 0;
}
.contact-fab.is-open .contact-fab-menu { pointer-events: auto; }
.contact-fab.is-open .contact-fab-item {
  opacity: 1;
  transform: none;
}
.contact-fab.is-open .contact-fab-item:nth-child(1) { transition-delay: 0.02s; }
.contact-fab.is-open .contact-fab-item:nth-child(2) { transition-delay: 0.06s; }
.contact-fab.is-open .contact-fab-item:nth-child(3) { transition-delay: 0.1s; }

.contact-fab-toggle {
  display: inline-grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--red-600);
  color: var(--white);
  box-shadow: 0 16px 32px -10px rgba(209, 36, 36, 0.55);
  transition: background 0.2s var(--ease), transform 0.2s var(--ease);
}
.contact-fab-toggle:hover { background: var(--red-700); transform: translateY(-2px); }
.contact-fab-icon-close { display: none; }
.contact-fab.is-open .contact-fab-icon-open { display: none; }
.contact-fab.is-open .contact-fab-icon-close { display: block; }
.contact-fab.is-open .contact-fab-toggle { background: var(--navy-900); }

@media (prefers-reduced-motion: reduce) {
  .contact-fab-item, .contact-fab-toggle { transition: opacity 0.15s, background 0.15s; }
}
@media (max-width: 480px) {
  .contact-fab { right: 1rem; bottom: 1rem; }
  .contact-fab-toggle { width: 50px; height: 50px; }
}

/* ==========================================================================
   Video Gallery
   ========================================================================== */
.videos { padding-block: clamp(3.5rem, 2.8rem + 3vw, 6rem); background: var(--gray-50); }
.video-grid {
  display: grid;
  gap: clamp(1rem, 0.8rem + 1vw, 1.5rem);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 640px) {
  .video-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 960px) {
  /* Deliberately NOT "repeat(<video count>, 1fr)" — that only ever looks
     right for the exact number of videos on the day it was written, then
     needs re-tuning every time a video is added/removed. 4 columns is a
     stable density that just wraps to however many rows the current video
     count needs. */
  .video-grid { grid-template-columns: repeat(4, 1fr); }
}
/* Only the 2- and 3-column (sub-960px) layouts get the "stretch the last
   card" treatment: at just 2 or 3 columns, a lone leftover card on the
   final row leaves a conspicuously large empty gap right next to it (this
   is literally the "kosong" bug reported earlier). At 4 columns (960px+)
   the same leftover card just ends its row a bit early — normal-looking
   grid trailing space, not a visible hole — so no fix is needed there.
   This only helps when the last row has exactly one card; it doesn't
   assume any particular total video count. */
@media (max-width: 959px) {
  .video-grid > .video-card:last-child { grid-column: 1 / -1; }
}
.video-card {
  position: relative;
  display: block;
  border-radius: var(--radius-md);
  overflow: hidden;
  aspect-ratio: 16 / 9;
  background: var(--navy-900);
  box-shadow: 0 12px 26px -14px rgba(6, 11, 77, 0.35);
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.video-card:hover { transform: translateY(-3px); box-shadow: 0 18px 34px -14px rgba(6, 11, 77, 0.45); }
/* Featured hero video sits above the thumbnail grid, full-width, so the
   newest/most important video reads as the headline pick rather than one
   of five equal-weight tiles. Bigger play button + title scale to match. */
.video-card--hero {
  margin-bottom: clamp(1rem, 0.8rem + 1vw, 1.5rem);
  aspect-ratio: 21 / 9;
  border-radius: var(--radius-lg);
}
.video-card--hero .video-card-play {
  width: 74px;
  height: 74px;
}
.video-card--hero .video-card-play svg { width: 32px; height: 32px; }
.video-card--hero .video-card-title {
  padding: 3rem 1.5rem 1.1rem;
  font-size: clamp(1rem, 0.85rem + 0.6vw, 1.3rem);
}
@media (max-width: 640px) {
  .video-card--hero { aspect-ratio: 16 / 9; }
}
.video-card img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.video-card-play {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(209, 36, 36, 0.92);
  color: var(--white);
  box-shadow: 0 8px 20px -8px rgba(0, 0, 0, 0.5);
}
.video-card-play svg { margin-left: 2px; }
.video-card-title {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 1.5rem 0.65rem 0.6rem;
  background: linear-gradient(0deg, rgba(6, 11, 77, 0.88) 0%, transparent 100%);
  color: var(--white);
  font-size: 0.74rem;
  font-weight: 700;
  line-height: 1.3;
  text-align: left;
}
/* ----- Lightbox (shared overlay, one iframe reused for all 5 videos) ----- */
.video-lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 1.5rem;
}
.video-lightbox-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(6, 11, 77, 0.9);
  backdrop-filter: blur(4px);
}
.video-lightbox-body {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 960px;
}
.video-lightbox-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: #000;
  box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.6);
}
.video-lightbox-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.video-lightbox-close,
.video-lightbox-nav {
  position: absolute;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: var(--white);
  border: 1px solid rgba(255, 255, 255, 0.25);
  transition: background 0.2s var(--ease);
}
.video-lightbox-close:hover,
.video-lightbox-nav:hover { background: rgba(255, 255, 255, 0.22); }
.video-lightbox-close { top: -0.5rem; right: -0.5rem; }
@media (min-width: 640px) { .video-lightbox-close { top: 0; right: -3rem; } }
.video-lightbox-nav--prev { left: 0.5rem; top: 50%; transform: translateY(-50%); }
.video-lightbox-nav--next { right: 0.5rem; top: 50%; transform: translateY(-50%); }
@media (min-width: 900px) {
  .video-lightbox-nav--prev { left: -3.5rem; }
  .video-lightbox-nav--next { right: -3.5rem; }
}
