/* ============================================================
   RIEL Compliance Suite — Marketing Website
   Design tokens and base classes.
   Palette, type scale and spacing are fixed — see task brief.
   ============================================================ */

:root{
  --navy:#123A5D; --navy-deep:#0D2B45; --teal:#18A999; --teal-deep:#0F7F73;
  --sky:#E8F4FA; --slate:#4A5568; --offwhite:#F7FAFC; --white:#FFFFFF;
  /* Fondo de .band--navy, distinto de --navy. Las tres infografias del
     cliente (F3) tienen esquinas casi negras (#000D27 / #010F27); contra
     --navy (#123A5D) la costura entre imagen y banda era evidente. --navy
     sigue siendo el color de marca usado como TEXTO (h2, .mega-menu a,
     .pr__item p, .btn--primary en banda clara, etc.) y no se toca. */
  --navy-band:#0A1E38;
  /* Footer: un paso mas oscuro que --navy-band, para que el cierre de la
     pagina lea como la superficie mas oscura. Eleccion distinta de --navy-deep
     (#0D2B45) que se usa en otros sitios (hover primario y dos textos). */
  --navy-footer:#051220;
  --fs-1:13px; --fs-2:15px; --fs-3:17px; --fs-4:20px;
  --fs-5:28px; --fs-6:40px; --fs-7:56px;
  --sp-section:112px; --sp-section-sm:64px; --radius:14px; --wrap:1200px;
  /* How far the hero screenshot deliberately crosses the bottom edge of the
     navy band into the section below (S2 spec). Single source of truth: both
     .hero__shot's negative margin and .problem's compensating top padding are
     derived from it, so the visible white gap under the shot stays equal to
     the site's --sp-section rhythm no matter how this value is tuned. */
  --hero-overlap:72px;
}

@media (max-width:1024px){
  :root{ --hero-overlap:48px; }
}

/* ---- Fonts --------------------------------------------------
   Inter, self-hosted (Website/fonts/), subconjunto latin, variable
   font que cubre el rango de pesos 400-800 usado en el sitio.
   Sin dependencias de terceros en runtime: nada de fonts.googleapis.com
   ni fonts.gstatic.com en el HTML final. */
@font-face{
  font-family:"Inter";
  font-style:normal;
  font-weight:400 800;
  font-display:swap;
  src:url("../fonts/inter-latin-variable.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

/* ---- Reset ------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
body{margin:0}

body{
  font-family:Inter,system-ui,-apple-system,"Segoe UI",sans-serif;
  color:var(--slate);
  background:var(--white);
  font-size:var(--fs-3);
  line-height:1.5;
}

/* Anchored sections must clear the fixed header or the nav links
   leave the section title hidden underneath it. */
section[id]{scroll-margin-top:76px}

/* Smooth scroll only when the visitor has not asked for reduced
   motion. Anchor links (#platform, #modules, ...) still work
   without this — the jump just becomes instant instead of eased. */
@media (prefers-reduced-motion: no-preference){
  html{scroll-behavior:smooth}
}

/* ============================================================
   .reveal — scroll-triggered fade-in (Task 10, site.js initReveal()).

   The hidden (opacity:0) state is gated behind html.js, added by
   site.js as its very first statement, NOT baked into the bare
   .reveal rule. Two reasons:
   1. No-JS safety: if the script fails to load or run, html never
      gets .js and every .reveal element stays at its default
      opacity:1 — the page can never render blank because of this
      feature.
   2. Reduced motion: initReveal() adds .is-visible to every .reveal
      element immediately when the visitor prefers reduced motion,
      skipping the IntersectionObserver entirely. Because the hidden
      state itself requires html.js, this pairs correctly whether or
      not JS class landed a frame earlier.
   ============================================================ */
.reveal{
  transition:opacity .4s ease-out, transform .4s ease-out;
}

/* initReveal() skips the IntersectionObserver under reduced motion and
   flips every .reveal to .is-visible at once — but the transition on
   the base rule above still animated that flip, so the visitor got the
   whole page fading in over 400ms anyway. Kill the transition itself,
   which is the only thing left that moves. */
@media (prefers-reduced-motion: reduce){
  .reveal{ transition:none; }
}

html.js .reveal{
  opacity:0;
  transform:translateY(16px);
}

html.js .reveal.is-visible{
  opacity:1;
  transform:none;
}

/* ---- Layout -------------------------------------------------- */
.wrap{
  max-width:var(--wrap);
  margin-inline:auto;
  padding-inline:24px;
}

.band{
  padding-block:var(--sp-section);
}

@media (max-width:1024px){
  .band{
    padding-block:var(--sp-section-sm);
  }
}

/* --navy-band, not --navy: see the :root comment. The radial glow mirrors
   the soft vignette already baked into the three infographics (F3) — teal,
   very low opacity, centered high in the band — so a navy band that hosts
   one of them (or sits next to the cost-of-delay numbers) reads as depth,
   not as a flat color swap. */
.band--navy{
  background-color:var(--navy-band);
  background-image:radial-gradient(ellipse 70% 55% at 50% 0%, rgba(24,169,153,.09), rgba(24,169,153,0) 70%);
  color:var(--white);
}

.band--offwhite{
  background:var(--offwhite);
}

/* ---- Buttons --------------------------------------------------
   NON-NEGOTIABLE: .btn--primary is never teal-filled. var(--teal)
   behind white text is 2.92:1 and fails WCAG AA at every size —
   that is the rule this comment exists to protect, and it holds on
   every background. Do not "brand" the button by filling it teal.

   The fill itself flips with the band, because a primary button has
   to out-rank the secondary one and no single fill does that on both
   backgrounds:
     - on light bands  -> navy fill / white text  (base rule below)
     - on navy bands   -> white fill / navy text  (scoped rule near
                          the header block, further down)
   A navy fill on a navy band is literally the same color as what it
   sits on: 1.00:1, invisible except for a border. That was the state
   this pair of rules replaced. Keep both halves. */
.btn{
  display:inline-block;
  font-family:inherit;
  font-size:var(--fs-3);
  font-weight:600;
  line-height:1.2;
  text-decoration:none;
  text-align:center;
  padding:14px 28px;
  border-radius:var(--radius);
  border:1px solid transparent;
  cursor:pointer;
  transition:background-color .15s ease, color .15s ease, border-color .15s ease;
}

.btn--primary{
  background:var(--navy);
  color:var(--white);
  border-color:var(--navy);
}

.btn--primary:hover,
.btn--primary:focus-visible{
  background:var(--navy-deep);
  border-color:var(--navy-deep);
}

/* Ghost button: 1px currentColor border on transparent background,
   meant to sit on top of the navy band. */
.btn--ghost{
  background:transparent;
  color:currentColor;
  border-color:currentColor;
}

.btn--ghost:hover,
.btn--ghost:focus-visible{
  background:rgba(255,255,255,.12);
}

/* ---- Accessibility utility ------------------------------------ */
.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}

a:focus-visible,
button:focus-visible{
  outline:2px solid var(--teal);
  outline-offset:2px;
}

/* ---- Copy helpers (shared) -------------------------------------
   Structural rules only. Color is not set here on purpose: these
   classes get reused on both the navy hero (S2) and light bands
   (S4/S5/S8), and inherit --slate/--white from their band by
   default. The navy-specific dimmed variant is scoped below. */
/* flex-start, not center: the eyebrow wraps to two lines on narrow
   screens, and with align-items:center the 6px dot centered itself
   against the whole two-line block — ~36px away from the text it
   belongs to, pinned against the left margin like a stray bullet.
   Anchored to the top instead, the ::before offset below parks it
   on the first line's optical center and it stays there at every
   width. */
.eyebrow{
  display:inline-flex;
  align-items:flex-start;
  gap:8px;
  margin:0 0 20px;
  font-size:var(--fs-1);
  font-weight:700;
  letter-spacing:.08em;
  text-transform:uppercase;
}

.eyebrow::before{
  content:'';
  width:6px;
  height:6px;
  /* (line-height 1.5 x 13px - 6px dot) / 2, in em so it tracks
     --fs-1 if the eyebrow's size ever changes. */
  margin-top:.52em;
  flex-shrink:0;
  border-radius:50%;
  background:var(--teal);
}

/* Below 768px the eyebrow is wider than the column and wraps, and the
   flex layout then pins the dot to the left edge while the hero's
   centered text pulls line 1 toward the middle — the dot ends up
   floating ~36px from the words it belongs to. Dropping to a plain
   block makes the dot an inline part of line 1, so it travels with
   the centered text instead of being laid out beside the whole
   two-line block. */
@media (max-width:767px){
  .eyebrow{
    display:block;
  }

  .eyebrow::before{
    display:inline-block;
    margin:0 8px 2px 0;
    vertical-align:middle;
  }
}

.lede{
  margin:0 0 40px;
  font-size:var(--fs-4);
  line-height:1.6;
}

.band--navy .eyebrow,
.band--navy .lede{
  color:rgba(255,255,255,.82);
}

/* ============================================================
   Header / Nav (S1) — Task 5
   Fixed and transparent over the hero; initNav() (site.js) toggles
   .is-scrolled after 40px so the bar stays legible once white
   sections scroll underneath it.
   ============================================================ */
header{
  position:fixed;
  inset:0 0 auto 0;
  z-index:100;
  background:transparent;
  border-bottom:1px solid transparent;
  transition:background-color .25s ease, border-color .25s ease;
}

header.is-scrolled{
  background:rgba(18,58,93,.92);
  -webkit-backdrop-filter:blur(12px);
  backdrop-filter:blur(12px);
  border-bottom-color:rgba(255,255,255,.08);
}

.nav__inner{
  display:flex;
  align-items:center;
  gap:40px;
  padding-block:17px;
}

.nav__logo{
  display:inline-flex;
  align-items:center;
}

.nav__logo img{
  display:block;
  height:32px;
  width:auto;
}

.nav__links{
  display:flex;
  align-items:center;
  gap:32px;
}

.nav__links a{
  padding-block:4px;
  border-bottom:2px solid transparent;
  color:rgba(255,255,255,.82);
  font-size:var(--fs-2);
  font-weight:500;
  text-decoration:none;
  white-space:nowrap;
  transition:color .15s ease, border-color .15s ease;
}

.nav__links a:hover,
.nav__links a:focus-visible{
  color:var(--white);
  border-bottom-color:var(--teal);
}

.nav__cta{
  margin-left:auto;
  flex-shrink:0;
  padding:10px 22px;
  font-size:var(--fs-2);
}

/* Primary button on a navy background: white fill, navy text.
   The base rule's navy fill measures 1.00:1 against var(--navy) —
   the same color — which left the button readable only by its drop
   shadow and a 1.62:1 rim, so the outlined .btn--ghost beside it in
   the hero read as the louder of the two and the form's submit was
   the least visible control in its own panel. Inverting the fill on
   navy puts it at 11.86:1 against the band and 9.85:1 against the
   translucent form panel, and restores the primary/secondary order.
   Scoped, not a base-rule change: on light bands (S4/S5/S7) the navy
   fill is correct and stays exactly as it is.

   Covers three places: the header CTA (the bar is navy in both its
   transparent-over-hero and .is-scrolled states), the hero CTA, and
   the S9 form submit. */
.band--navy .btn--primary,
header .btn--primary{
  background:var(--white);
  color:var(--navy);
  border-color:var(--white);
}

/* Explicit hover/focus pair: the base .btn--primary:hover rule sits
   earlier in this file at equal specificity, so without these the
   contextual white fill above would win over it and the button would
   have no hover state at all on navy. */
.band--navy .btn--primary:hover,
.band--navy .btn--primary:focus-visible,
header .btn--primary:hover,
header .btn--primary:focus-visible{
  background:var(--sky);
  border-color:var(--sky);
  color:var(--navy-deep);
}

/* With the primary now filled white, a full-strength white rim made
   the ghost button compete with it instead of deferring to it. The
   border drops to 45% white (still a clear affordance); the label
   stays pure white so the button's own text contrast is untouched
   at 11.74:1. */
.band--navy .btn--ghost{
  border-color:rgba(255,255,255,.45);
}

.band--navy .btn--ghost:hover,
.band--navy .btn--ghost:focus-visible{
  border-color:rgba(255,255,255,.8);
}

/* Tablet: tighter gaps so the five links stay on one line instead of
   wrapping and unbalancing the row. Desktop (>1024px) has the room to
   keep the wider gaps. */
@media (max-width:1024px){
  .nav__inner{ gap:20px; }
  .nav__links{ gap:18px; }
}

@media (max-width:767px){
  .nav__links{ display:none; }
}

/* ============================================================
   Mega-menu (Modules) — Task 5 follow-up
   Desktop/tablet only (.nav__links carries it and is hidden below
   767px, where the mobile panel's own accordion takes over). The
   trigger reuses .nav__links a's color/size instead of new type
   rules; only what a <button> does not inherit for free (background,
   border, cursor, layout) is set explicitly.
   ============================================================ */
.nav__item{
  position:relative;
}

.nav__trigger{
  display:inline-flex;
  align-items:center;
  gap:6px;
  background:none;
  border:none;
  padding-block:4px;
  border-bottom:2px solid transparent;
  color:rgba(255,255,255,.82);
  font:inherit;
  font-size:var(--fs-2);
  font-weight:500;
  white-space:nowrap;
  cursor:pointer;
  transition:color .15s ease, border-color .15s ease;
}

.nav__trigger:hover,
.nav__trigger:focus-visible,
.nav__trigger[aria-expanded="true"]{
  color:var(--white);
  border-bottom-color:var(--teal);
}

.nav__chevron{
  flex-shrink:0;
  transition:transform .15s ease;
}

@media (prefers-reduced-motion: reduce){
  .nav__chevron{ transition:none; }
}

.nav__trigger[aria-expanded="true"] .nav__chevron{
  transform:rotate(180deg);
}

.mega-menu{
  position:absolute;
  top:calc(100% + 16px);
  left:50%;
  transform:translateX(-50%) translateY(-8px);
  width:520px;
  max-width:calc(100vw - 48px);
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:2px;
  padding:12px;
  background:var(--white);
  border-radius:var(--radius);
  box-shadow:0 24px 60px rgba(9,30,54,.28);
  opacity:0;
  z-index:110;
  transition:opacity .15s ease, transform .15s ease;
}

.mega-menu[hidden]{
  display:none;
}

.mega-menu.is-open{
  opacity:1;
  transform:translateX(-50%) translateY(0);
}

@media (prefers-reduced-motion: reduce){
  .mega-menu{ transition:none; }
}

.mega-menu a{
  display:block;
  padding:10px 12px;
  border-radius:8px;
  color:var(--navy);
  font-size:var(--fs-2);
  font-weight:500;
  line-height:1.3;
  text-decoration:none;
  transition:background-color .15s ease, color .15s ease;
}

.mega-menu a:hover,
.mega-menu a:focus-visible{
  background:var(--sky);
  color:var(--navy-deep);
}

/* ============================================================
   Mobile nav toggle + panel — net-new below 767px, where
   .nav__links (and its mega-menu) disappears entirely today.
   ============================================================ */
.nav__mobile-toggle{
  display:none;
  align-items:center;
  justify-content:center;
  flex-shrink:0;
  background:none;
  border:none;
  padding:8px;
  margin-left:12px;
  border-radius:8px;
  color:var(--white);
  cursor:pointer;
}

.nav__mobile-toggle:hover,
.nav__mobile-toggle:focus-visible{
  background:rgba(255,255,255,.12);
}

@media (max-width:767px){
  .nav__mobile-toggle{ display:inline-flex; }
}

/* Solid backdrop while the mobile panel is open, even at scrollY 0
   over the transparent hero — otherwise the panel's links would sit
   over whatever the hero screenshot happens to show underneath. */
header.nav__mobile-open{
  background:rgba(18,58,93,.92);
  -webkit-backdrop-filter:blur(12px);
  backdrop-filter:blur(12px);
  border-bottom-color:rgba(255,255,255,.08);
}

.nav__mobile-panel{
  position:absolute;
  top:100%;
  left:0;
  right:0;
  max-height:calc(100vh - 64px);
  overflow-y:auto;
  background:var(--navy);
  box-shadow:0 24px 60px rgba(9,30,54,.28);
  padding:8px 24px 24px;
  opacity:0;
  transform:translateY(-8px);
  transition:opacity .2s ease, transform .2s ease;
}

.nav__mobile-panel[hidden]{
  display:none;
}

.nav__mobile-panel.is-open{
  opacity:1;
  transform:none;
}

@media (prefers-reduced-motion: reduce){
  .nav__mobile-panel{ transition:none; }
}

/* Guard against a resize crossing 768px while the panel happens to be
   open: the toggle that opens/closes it is gone above 767px, so the
   panel itself must not be able to render there either. */
@media (min-width:768px){
  .nav__mobile-panel{ display:none !important; }
}

.nav__mobile-nav{
  display:flex;
  flex-direction:column;
  gap:2px;
}

.nav__mobile-link{
  padding:16px 4px;
  border-bottom:1px solid rgba(255,255,255,.14);
  color:var(--white);
  font-size:var(--fs-4);
  font-weight:600;
  text-decoration:none;
}

.nav__mobile-link:hover,
.nav__mobile-link:focus-visible{
  background:rgba(255,255,255,.08);
}

.nav__mobile-group{
  border-bottom:1px solid rgba(255,255,255,.14);
}

.nav__mobile-subtrigger{
  display:flex;
  width:100%;
  align-items:center;
  justify-content:space-between;
  gap:8px;
  background:none;
  border:none;
  padding:16px 4px;
  color:var(--white);
  font:inherit;
  font-size:var(--fs-4);
  font-weight:600;
  text-align:left;
  cursor:pointer;
}

.nav__mobile-subtrigger:hover,
.nav__mobile-subtrigger:focus-visible{
  background:rgba(255,255,255,.08);
}

.nav__mobile-subtrigger[aria-expanded="true"] .nav__chevron{
  transform:rotate(180deg);
}

.nav__mobile-sublist{
  display:flex;
  flex-direction:column;
  gap:2px;
  padding:0 0 12px 12px;
}

.nav__mobile-sublist[hidden]{
  display:none;
}

.nav__mobile-sublink{
  padding:12px 4px;
  color:rgba(255,255,255,.82);
  font-size:var(--fs-3);
  text-decoration:none;
}

.nav__mobile-sublink:hover,
.nav__mobile-sublink:focus-visible{
  color:var(--white);
}

/* ============================================================
   Hero (S2, #top, .band--navy) — Task 5
   Centered eyebrow/h1/lede/CTAs, near-full-width screenshot below
   that bleeds into the following section via a negative margin.
   Top padding is set explicitly (not inherited from .band) because
   this is the one section that sits flush under the fixed header
   on first paint — .band's responsive padding alone (64px at
   <=1024px) is shorter than the header and would clip the eyebrow.
   ============================================================ */
.hero{
  padding-top:152px;
  padding-bottom:var(--sp-section);
  text-align:center;
}

@media (max-width:1024px){
  .hero{
    padding-top:128px;
    padding-bottom:var(--sp-section-sm);
  }
}

@media (max-width:767px){
  .hero{ padding-top:112px; }
}

.hero__inner{
  display:flex;
  flex-direction:column;
  align-items:center;
}

.hero h1{
  max-width:820px;
  margin:0 0 24px;
  color:var(--white);
  font-size:var(--fs-7);
  font-weight:800;
  line-height:1.08;
  letter-spacing:-.02em;
}

@media (max-width:767px){
  .hero h1{ font-size:var(--fs-6); }
}

.hero .lede{
  max-width:640px;
}

.hero__ctas{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:16px;
  margin-bottom:64px;
}

@media (max-width:479px){
  .hero__ctas{
    flex-direction:column;
    align-items:stretch;
    width:100%;
  }
}

/* The screenshot is meant to cross the bottom edge of the navy band
   into the section below (S2 spec) — the seam between the two is the
   one place on the page where a single element ties them together.
   The pull has to clear the hero's own padding-bottom before any of
   it becomes visible overflow, so it is (padding + overlap), not the
   overlap alone: a bare -80px against a 112px padding-bottom left
   the shot ending 32px *above* the band edge, overlapping nothing.
   .problem's top padding is derived from the same --hero-overlap, so
   the two always move together. */
.hero__shot{
  width:100%;
  margin-bottom:calc(-1 * (var(--sp-section) + var(--hero-overlap)));
}

@media (max-width:1024px){
  .hero__shot{
    margin-bottom:calc(-1 * (var(--sp-section-sm) + var(--hero-overlap)));
  }
}

/* ============================================================
   .shot — CSS-only browser frame. Generic on purpose: any <img>
   dropped inside works regardless of its aspect ratio, since S6-S8
   (Tasks 6-8) reuse it for four more screenshots.
   ============================================================ */
.shot{
  position:relative;
  border-radius:var(--radius);
  overflow:hidden;
  background:var(--offwhite);
  box-shadow:0 24px 60px rgba(9,30,54,.28);
}

.shot::after{
  content:'';
  position:absolute;
  inset:0;
  border-radius:inherit;
  box-shadow:0 0 0 1px rgba(24,169,153,.25);
  pointer-events:none;
}

.shot__bar{
  display:flex;
  align-items:center;
  gap:6px;
  height:32px;
  padding-inline:14px;
  background:var(--offwhite);
}

.shot__bar span{
  width:10px;
  height:10px;
  border-radius:50%;
  background:#D0D6DE;
}

.shot__bar span:nth-child(1){ background:#FF5F57; }
.shot__bar span:nth-child(2){ background:#FEBC2E; }
.shot__bar span:nth-child(3){ background:#28C840; }

/* height:auto is load-bearing, not a tidy-up. An <img>'s width/height content
   attributes are presentational hints for the CSS width/height properties.
   This rule used to set width only, so the height attribute survived as the
   used value and every screenshot on the site rendered stretched to it:
   shot-provider.jpg, an 860x165 strip, came out 582x768 — a vertical block
   at 0.76:1 instead of 5.21:1 — and the hero was stretched 39%. Dropping the
   height hint hands the height back to the intrinsic ratio, while the
   attributes stay on the markup and keep reserving the right box before the
   file arrives (no layout shift). Keep the attributes in sync with the real
   pixel dimensions of each file: they are what the browser uses for that
   reservation, and they were 1600x77x — the pre-crop sizes — while this was
   broken, which is exactly why nobody noticed. */
.shot img{
  display:block;
  width:100%;
  height:auto;
}

/* ============================================================
   .infographic — client-provided infographics (F3), deliberately
   NOT wrapped in .shot. .shot simulates a browser window; these
   three images are diagrams, not product screenshots, and putting
   them in browser chrome would misrepresent them as captured UI.
   Same width:100%/height:auto contract as .shot img (see the
   comment above — width/height attributes stay the source of the
   layout reservation) plus its own radius/shadow so it still reads
   as a deliberate piece of content, not a bare inline image.
   ============================================================ */
.infographic{
  display:block;
  width:100%;
  height:auto;
  border-radius:var(--radius);
  box-shadow:0 24px 60px rgba(9,30,54,.28);
}

/* ============================================================
   Section headings (S3 onward) — Task 6
   Hero (S2) is the only section that uses h1; every section from
   here down titles itself with h2. Navy on the light bands by
   default; .band--navy overrides to white in case a later task
   reuses h2 on a navy band (S6/S9).
   ============================================================ */
main h2{
  margin:0 0 24px;
  color:var(--navy);
  font-size:var(--fs-6);
  font-weight:700;
  line-height:1.15;
  letter-spacing:-.02em;
}

.band--navy h2{
  color:var(--white);
}

/* Mobile step-down, mirroring .hero h1's 56->40px. At 40px a section
   title like "Built for how credentialing actually works in Puerto
   Rico." runs to five lines on a 375px screen and eats most of the
   viewport before any body copy appears; --fs-5 keeps every h2 on
   the site to three lines or fewer. */
@media (max-width:767px){
  main h2{ font-size:var(--fs-5); }
}

/* ============================================================
   S3 — Problem framing (.problem, three columns, white band)
   Extra top clearance equal to --hero-overlap: the hero screenshot
   really does hang that far into this section, so this padding is
   the room the image occupies, not blank space. Deriving it from the
   same variable as .hero__shot's negative margin is what keeps the
   *visible* white gap under the shot at --sp-section (112px desktop
   / 64px at <=1024px), matching every other section on the page.
   Change --hero-overlap and both ends stay in step.
   ============================================================ */
.problem{
  padding-top:calc(var(--sp-section) + var(--hero-overlap));
}

@media (max-width:1024px){
  .problem{
    padding-top:calc(var(--sp-section-sm) + var(--hero-overlap));
  }
}

.problem__title{
  max-width:820px;
  margin:0 auto 64px;
  text-align:center;
}

.problem__grid{
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  gap:48px;
}

@media (max-width:767px){
  .problem__grid{
    grid-template-columns:1fr;
    gap:40px;
  }
}

.problem__item h3{
  margin:0 0 12px;
  color:var(--navy);
  font-size:var(--fs-4);
  font-weight:600;
  line-height:1.3;
}

.problem__item p{
  margin:0;
  color:var(--slate);
  font-size:var(--fs-3);
  line-height:1.6;
}

/* ============================================================
   .split / .split--reverse — generic two-column media+text
   layout. Task 6 introduces it for S4; Tasks 7-8 reuse it for
   S5/S7/S8, including .split--reverse to put the media on the
   left. Order (not grid-template-columns) drives the left/right
   swap so the responsive collapse rule only has to reset order.
   ============================================================ */
.split{
  display:grid;
  grid-template-columns:1fr 1.15fr;
  gap:64px;
  align-items:center;
}

.split__text{ order:1; }
.split__media{ order:2; }

/* --reverse flips which side each piece sits on, but .split__media
   must stay the wide (1.15fr) column in both modes — it holds a
   dense interface screenshot that needs the extra room regardless
   of which edge it's pinned to. order alone would carry the width
   along with the position, so --reverse also swaps the column
   track sizes to match. */
.split--reverse{
  grid-template-columns:1.15fr 1fr;
}

.split--reverse .split__text{ order:2; }
.split--reverse .split__media{ order:1; }

@media (max-width:1024px){
  .split{
    grid-template-columns:1fr;
    gap:40px;
  }

  /* Image always after text below 1024px, regardless of
     --reverse: the mobile reading order is text first. */
  .split__text,
  .split--reverse .split__text{ order:1; }
  .split__media,
  .split--reverse .split__media{ order:2; }
}

/* ============================================================
   S4 — Readiness (#platform, .band--offwhite, .split)
   ============================================================ */
.split__text > p{
  margin:0 0 32px;
  font-size:var(--fs-3);
  color:var(--slate);
}

.split__bullets{
  list-style:none;
  margin:0;
  padding:0;
  display:flex;
  flex-direction:column;
  gap:16px;
}

.split__bullets li{
  display:flex;
  align-items:flex-start;
  gap:12px;
  font-size:var(--fs-3);
  color:var(--navy);
  font-weight:500;
}

.split__bullets svg{
  flex-shrink:0;
  margin-top:2px;
  color:var(--teal);
}

/* ============================================================
   S5 — Providers & PSV (.split--reverse, white band)
   Reuses .split/.split--reverse/.shot/.split__bullets as-is; no
   section-specific rules needed.
   ============================================================ */

/* ============================================================
   .stat / .stat__num / .stat__label — generic stat card. Color
   is deliberately NOT set on the bare classes so a light variant
   would be a pure additive modifier instead of an override; only
   the navy-band case is scoped here, the same pattern already
   used for .eyebrow/.lede above.

   The home page's cost-of-delay section used to be the only
   consumer. That section is gone — its numbers now come out of
   the live model on roi.html — and this family stayed because
   roi.html's sticky KPI strip reuses it verbatim (roi.css only
   adds the loss/gain colours and the compact sizing on top).
   Do not fold these rules into roi.css: the .stat-row responsive
   collapse and the .band--navy colour tiers are site-level
   behaviour that any future page can pick up.
   ============================================================ */
.stat__num{
  margin:0 0 8px;
  font-size:var(--fs-7);
  font-weight:800;
  letter-spacing:-.02em;
  line-height:1.1;
}

.stat__label{
  margin:0 0 10px;
  font-size:var(--fs-1);
  font-weight:700;
  letter-spacing:.08em;
}

.stat__sub{
  margin:0;
  font-size:var(--fs-2);
  line-height:1.4;
}

.band--navy .stat__num{ color:var(--teal); }
.band--navy .stat__label{ color:rgba(255,255,255,.82); }
.band--navy .stat__sub{ color:rgba(255,255,255,.6); }

/* ============================================================
   S6 — ROI teaser (#roi, .band--navy)
   Replaces the old cost-of-delay block, which hard-coded three
   illustrative dollar figures and a regulatory citation in the
   markup. Those numbers now come from the live model on
   roi.html, where every assumption behind them is visible and
   editable; the home page only points at it. Centered header
   pattern, same as .problem__title (S3).

   Everything the old block needed beyond this (.cost__inner,
   .cost__note, .cost__close, .cost__honesty, .cost__shot,
   .cost__disclaimer) was deleted with it.
   ============================================================ */
.roi-teaser{
  text-align:center;
}

.roi-teaser h2{
  max-width:820px;
  margin-inline:auto;
}

.roi-teaser .lede{
  max-width:680px;
  margin-inline:auto;
}

.stat-row{
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  margin:48px 0 40px;
}

.stat{
  min-width:0;
  padding-inline:32px;
  border-left:1px solid rgba(255,255,255,.15);
}

.stat:first-child{
  padding-left:0;
  border-left:none;
}

/* max-width:768px (inclusive), not the usual 767px mobile cutoff used
   elsewhere in this file: the task's own acceptance check tests the
   stacked layout at exactly 768px, so the boundary is widened by 1px
   here to satisfy it without affecting any other component.
   roi.css re-opens this same breakpoint to keep the KPI strip three
   columns wide — see the note there. */
@media (max-width:768px){
  .stat-row{
    grid-template-columns:1fr;
    gap:24px;
    margin:40px 0 32px;
  }

  .stat{
    padding-inline:0;
    padding-top:24px;
    border-left:none;
    border-top:1px solid rgba(255,255,255,.15);
  }

  .stat:first-child{
    padding-top:0;
    border-top:none;
  }
}

/* ============================================================
   S7 — Built for Puerto Rico (#puerto-rico, .band--offwhite)
   Centered title/lede over a three-column icon grid, following the
   same centered-header pattern as .problem (S3). Icons are teal —
   valid only as icons/decoration (2.92:1 fails as text; see the
   .btn--primary note above), never as the item text color.
   ============================================================ */
.pr__title{
  max-width:760px;
  margin:0 auto 24px;
  text-align:center;
}

.pr .lede{
  max-width:680px;
  margin-inline:auto;
  text-align:center;
}

.pr__grid{
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  gap:40px;
  margin-top:56px;
}

@media (max-width:767px){
  .pr__grid{
    grid-template-columns:1fr;
    gap:32px;
    margin-top:40px;
  }
}

.pr__item{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
}

.pr__icon{
  color:var(--teal);
  margin-bottom:16px;
}

.pr__item p{
  margin:0;
  color:var(--navy);
  font-size:var(--fs-3);
  font-weight:500;
  line-height:1.5;
}

/* ============================================================
   S9 — Demo form (#contact, .band--navy)
   Two columns: intro/alt-contact on the left, the form on the
   right. Inputs are rendered on a white fill rather than
   transparent-on-navy: it sidesteps every small-text contrast
   question for field content (navy text on white is ~12:1
   regardless of size) and leaves only the *surrounding* copy
   (labels, hints, status message) needing the navy-band check —
   those all reuse the rgba(255,255,255,.82)/(.6) tiers already
   measured for S2/S6, never var(--teal) as a text fill.
   ============================================================ */
.contact__inner{
  display:grid;
  grid-template-columns:1fr 1.3fr;
  gap:64px;
  align-items:start;
}

@media (max-width:1024px){
  .contact__inner{
    grid-template-columns:1fr;
    gap:40px;
  }
}

.contact__intro h2{ margin-bottom:20px; }
.contact__intro .lede{ margin-bottom:40px; }

.contact__altlabel{
  margin:0 0 8px;
  font-size:var(--fs-1);
  font-weight:700;
  letter-spacing:.04em;
  text-transform:uppercase;
  color:rgba(255,255,255,.6);
}

.contact__alt{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:10px;
}

.contact__alt a{
  color:var(--white);
  font-size:var(--fs-3);
  font-weight:600;
  text-decoration:underline;
  text-decoration-color:rgba(255,255,255,.4);
  text-underline-offset:3px;
}

.contact__alt a:hover{
  text-decoration-color:var(--white);
}

.contact__form{
  display:flex;
  flex-direction:column;
  gap:20px;
  padding:40px;
  background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.14);
  border-radius:var(--radius);
}

.contact__required-note{
  margin:0 0 -4px;
  font-size:var(--fs-1);
  color:rgba(255,255,255,.6);
}

.form__row{
  display:flex;
  flex-direction:column;
  gap:8px;
}

.form__row label{
  font-size:var(--fs-2);
  font-weight:600;
  color:var(--white);
}

.form__required{
  color:var(--white);
}

.form__optional{
  font-weight:400;
  color:rgba(255,255,255,.6);
}

/* Scoped to the actual text-entry types (not [type="checkbox"]): the
   honeypot below reuses the shared .sr-only utility to disappear, and
   a bare `input` selector here would out-specificity .sr-only's
   width:1px and blow it back out to full width. */
.contact__form input[type="text"],
.contact__form input[type="email"],
.contact__form input[type="tel"],
.contact__form textarea{
  width:100%;
  padding:12px 16px;
  font:inherit;
  font-size:var(--fs-3);
  color:var(--navy);
  background:var(--white);
  border:1px solid transparent;
  border-radius:10px;
}

.contact__form textarea{
  resize:vertical;
  min-height:96px;
}

.contact__form input[type="text"]:focus-visible,
.contact__form input[type="email"]:focus-visible,
.contact__form input[type="tel"]:focus-visible,
.contact__form textarea:focus-visible{
  outline:2px solid var(--teal);
  outline-offset:2px;
}

.contact__submit{
  margin-top:4px;
  align-self:flex-start;
}

.contact__status{
  min-height:1.4em;
  font-size:var(--fs-2);
  font-weight:600;
  color:var(--white);
}

/* ============================================================
   S10 — Footer
   Darkest surface on the page, more than --navy-band, so S9 and S10
   form a clear visual hierarchy with no seam or fusion between them.
   ============================================================ */
footer{
  background:var(--navy-footer);
  color:var(--white);
}

.footer__inner{
  display:flex;
  flex-wrap:wrap;
  justify-content:space-between;
  align-items:flex-start;
  gap:40px;
  padding-block:56px 32px;
}

.footer__logo{
  display:block;
  height:28px;
  width:auto;
  margin-bottom:16px;
}

.footer__name{
  margin:0 0 6px;
  font-size:var(--fs-4);
  font-weight:700;
  color:var(--white);
}

.footer__tagline{
  margin:0;
  font-size:var(--fs-2);
  color:rgba(255,255,255,.82);
}

.footer__contact{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:10px;
}

.footer__contact a{
  color:rgba(255,255,255,.82);
  font-size:var(--fs-2);
  font-weight:500;
  text-decoration:none;
}

.footer__contact a:hover{
  color:var(--white);
  text-decoration:underline;
}

.footer__bottom{
  padding-block:24px;
  border-top:1px solid rgba(255,255,255,.14);
}

.footer__bottom p{
  margin:0;
  font-size:var(--fs-1);
  color:rgba(255,255,255,.6);
}

@media (max-width:767px){
  .footer__inner{
    flex-direction:column;
    gap:32px;
  }
}

/* ============================================================
   S6b — Modules carousel (#modules, .band--offwhite) — tanda 2

   Ten slides, one module each, full container width. Built on CSS
   scroll-snap rather than a transform track, and that choice is
   load-bearing for three separate behaviours:

   1. Deep links. The mega-menu points at #module-hrsa ... #module-tasks.
      Because every slide is a real, always-laid-out element inside a
      scrollable box, the browser's own fragment navigation scrolls the
      track horizontally *and* the page vertically to it. That works with
      JavaScript disabled; initModules() only mirrors the resulting
      position into the counter and the dots.
   2. Touch. Horizontal swipe is the browser's native overflow scrolling,
      so there is no pointer/gesture code to get wrong.
   3. Failure mode. If the script never runs, the section degrades to a
      horizontally scrollable strip with every module readable, instead
      of to a single frozen slide.

   Consequently: never give .module-slide display:none, visibility:hidden
   or position:absolute for the off-screen ones — each of those breaks the
   snap geometry and the native anchor at the same time.
   ============================================================ */
.modules__carousel{
  margin-top:8px;
}

/* position:relative makes the track its children's offsetParent, so
   slide.offsetLeft is a coordinate inside the scrolled content and can be
   fed straight to track.scrollTo() (see initModules()). */
.modules__track{
  position:relative;
  display:flex;
  overflow-x:auto;
  scroll-snap-type:x mandatory;
  scroll-behavior:smooth;
  /* Bottom padding is room for the .shot / .module-viz drop shadow, which
     overflow-x:auto would otherwise clip into a hard edge. Box shadows are
     ink overflow, never scrollable overflow, so this adds no scrollbar. */
  padding-block:4px 28px;
  /* Hide the horizontal scrollbar without disabling the scrolling itself. */
  scrollbar-width:none;
  -ms-overflow-style:none;
}

.modules__track::-webkit-scrollbar{ display:none; }

/* The track is the keyboard entry point for the carousel (tabindex="0"),
   so its focus ring has to be visible: --teal-deep, not --teal, because
   #18A999 on the --offwhite band is 2.92:1 and misses the 3:1 threshold
   for a non-text indicator. */
.modules__track:focus-visible{
  outline:3px solid var(--teal-deep);
  outline-offset:2px;
  border-radius:var(--radius);
}

@media (prefers-reduced-motion: reduce){
  .modules__track{ scroll-behavior:auto; }
}

.module-slide{
  flex:0 0 100%;
  min-width:0;
  scroll-snap-align:center;
  /* Native fragment navigation would otherwise park the slide's top edge
     flush against the viewport top, under the fixed header (~66px tall).
     section[id]'s own 76px does not cascade here: the slide is an article
     inside the section, and it is the slide the browser scrolls to. */
  scroll-margin-top:100px;
  /* Lateral breathing room for the media shadow, inside the flex basis
     (border-box), so the slide still measures exactly 100% of the track. */
  padding-inline:18px;
}

.module-slide__head{
  margin-bottom:16px;
}

.module-slide h3{
  margin:0;
  color:var(--navy);
  font-size:var(--fs-5);
  font-weight:700;
  line-height:1.2;
  letter-spacing:-.01em;
}

/* ---- Illustrated visual (six modules without a real screenshot) -------
   Deliberately NOT .shot. Six of the ten modules have no screenshot that
   honestly represents them, and dropping an illustration inside the
   browser-chrome frame would present a drawing as captured software. This
   panel shares the palette, radius and shadow language of the rest of the
   site but has no title bar, no window buttons and a literal "Illustration"
   caption, so it cannot be mistaken for a product screenshot.
   aria-hidden: every string inside it repeats the slide's own heading and
   .split__bullets verbatim, so exposing it would read the module twice. */
.module-viz{
  display:flex;
  flex-direction:column;
  gap:24px;
  padding:32px;
  background:var(--white);
  border:1px solid rgba(18,58,93,.12);
  border-radius:var(--radius);
  box-shadow:0 18px 44px rgba(9,30,54,.12);
}

.module-viz__head{
  display:flex;
  align-items:center;
  gap:16px;
}

.module-viz__icon{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  flex-shrink:0;
  width:64px;
  height:64px;
  border-radius:16px;
  background:var(--sky);
  /* --teal on --sky is 2.61:1; --teal-deep is 4.36:1 and clears the 3:1
     graphical-object threshold. */
  color:var(--teal-deep);
}

.module-viz__title{
  margin:0;
  color:var(--navy);
  font-size:var(--fs-4);
  font-weight:700;
  line-height:1.25;
}

.module-viz__chips{
  list-style:none;
  margin:0;
  padding:0;
  display:flex;
  flex-wrap:wrap;
  gap:10px;
}

.module-viz__chips li{
  display:inline-flex;
  align-items:center;
  gap:8px;
  padding:10px 16px;
  border-radius:999px;
  background:var(--sky);
  color:var(--navy);
  font-size:var(--fs-2);
  font-weight:600;
  line-height:1.3;
}

.module-viz__chips li::before{
  content:'';
  flex-shrink:0;
  width:6px;
  height:6px;
  border-radius:50%;
  background:var(--teal-deep);
}

.module-viz__note{
  margin:0;
  font-size:var(--fs-1);
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--slate);
}

/* ---- Controls -------------------------------------------------------
   Hidden until site.js sets html.js. Without the script they would be
   buttons that do nothing; the track stays scrollable and every module
   anchor still resolves, so nothing is lost by removing them. */
.modules__controls{
  display:none;
  align-items:center;
  flex-wrap:wrap;
  gap:16px;
  margin-top:8px;
  padding-inline:18px;
}

html.js .modules__controls{
  display:flex;
}

.modules__arrow{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  flex-shrink:0;
  width:44px;
  height:44px;
  padding:0;
  background:var(--white);
  border:1px solid var(--navy);
  border-radius:50%;
  color:var(--navy);
  cursor:pointer;
  transition:background-color .15s ease, color .15s ease;
}

.modules__arrow:hover:not([disabled]),
.modules__arrow:focus-visible{
  background:var(--navy);
  color:var(--white);
}

.modules__arrow:focus-visible{
  outline:3px solid var(--teal-deep);
  outline-offset:2px;
}

/* At the first and the last module the arrows disable rather than wrap.
   The dots below them are absolute positions, not relative steps, so a
   wrapping arrow would be the one control on the page whose model differs
   from the indicator sitting next to it. Disabled controls are exempt from
   the contrast minimum, which is why this is the only dimmed thing here. */
.modules__arrow[disabled]{
  opacity:.32;
  cursor:default;
}

.modules__counter{
  margin:0;
  font-size:var(--fs-2);
  font-weight:700;
  letter-spacing:.08em;
  color:var(--navy);
  font-variant-numeric:tabular-nums;
}

.modules__dots{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:8px;
  margin-left:auto;
}

.modules__dot{
  position:relative;
  width:10px;
  height:10px;
  padding:0;
  border:none;
  border-radius:50%;
  /* #6E819A on --offwhite is 3.82:1 — above the 3:1 floor for a UI
     component, so an inactive dot is visible on its own, not only by
     comparison with the active one. */
  background:#6E819A;
  cursor:pointer;
  transition:background-color .15s ease, width .15s ease;
}

/* Enlarges the pointer/touch target well past the 10px dot without
   changing the layout or the gap between dots. */
.modules__dot::before{
  content:'';
  position:absolute;
  inset:-10px -4px;
}

.modules__dot:focus-visible{
  outline:3px solid var(--teal-deep);
  outline-offset:4px;
}

/* Active state carries on two channels, colour and shape, so it survives
   a monochrome or colour-blind read. */
.modules__dot[aria-current="true"]{
  width:28px;
  border-radius:5px;
  background:var(--navy);
}

@media (prefers-reduced-motion: reduce){
  .modules__arrow,
  .modules__dot{ transition:none; }
}

@media (max-width:1024px){
  .modules__carousel{ margin-top:0; }
  .module-slide{ scroll-margin-top:88px; }
}

@media (max-width:767px){
  .module-slide{ padding-inline:10px; }
  .modules__controls{
    padding-inline:10px;
    gap:12px;
  }
  /* Below 768px the ten dots plus two arrows plus the counter no longer
     fit on one line; the dots move to their own row instead of wrapping
     mid-group. */
  .modules__dots{
    margin-left:0;
    width:100%;
    order:3;
  }
  .module-viz{ padding:24px; }
  .module-viz__icon{ width:56px; height:56px; }
}

/* ============================================================
   #ai-operations — RIEL Operational Engine (F3 fusion)
   Was two sections saying the same thing twice: this one drew the
   signals->engine->roles funnel by hand and listed four capability
   cards; a separate .ai section repeated the human-in-the-loop
   stance and four stat cards further down the page. shot-ai-engine.jpg
   already contains the flow, the five capabilities and the
   human-reviewed banner, so this section is now: heading, one line
   of lede, the infographic at generous width, and the two sentences
   of human-in-the-loop copy that have to stay real text (an image
   is not read by a screen reader or indexed by search). The section
   is .band--navy so the infographic's near-black corners sit against
   --navy-band instead of the lighter --navy, and to give the page a
   second navy beat between the offwhite #modules/readiness bands.
   ============================================================ */
.ai-ops__shot{
  margin-top:48px;
}

@media (max-width:767px){
  .ai-ops__shot{ margin-top:32px; }
}

.ai-ops__close{
  max-width:760px;
  margin:40px auto 0;
  text-align:center;
}

.ai-ops__close p{
  margin:0;
  font-size:var(--fs-3);
  color:rgba(255,255,255,.82);
  line-height:1.6;
}

.ai-ops__close p + p{
  margin-top:16px;
}
