/* ============================================================================
   Dynalabz — landing page styles
   ----------------------------------------------------------------------------
   Design thesis: HVAC is cooling meeting heating. A disciplined cool navy/slate
   foundation carries the page; a single warm amber accent carries the action.
   The one signature element is a thin cool -> warm gradient hairline
   (--climate), used sparingly: under section eyebrows, in the hero, in the
   "Cooling / Heating" mark, and above the footer. Nothing else competes.

   Contents
     00  Fonts
     01  Tokens
     02  Reset & base
     03  Typography
     04  Layout primitives
     05  Motion primitives (reveal / hero entrance)
     06  Buttons & links
     07  Header, language switch, mobile menu
     08  Hero
     09  Cards, icons, lists
     10  Services
     11  Process
     12  Focus (dark) section
     13  Outcomes
     14  FAQ
     15  About
     16  Final CTA & form
     17  Footer
     18  Reduced motion
   ========================================================================== */


/* 00  Fonts --------------------------------------------------------------
   Two self-hosted variable faces, Latin subset, one file each. The weight
   range means Sora 600 and 700 (and anything between) come from a single
   24 KB file instead of two static cuts.

   The two *fallback* faces below exist so a font swap can't move the layout.
   Measured against Arial at 100px, Sora runs 7.6% wider for the same string,
   so `size-adjust` scales the fallback to match and the line count survives
   the swap. Measured CLS is 0: preloaded and same-origin, the real font wins
   the race to first paint even under simulated Slow 4G, so in practice there
   is no swap at all. If one ever happens, the residual is a single reflowed
   line in the headline at widths under ~400px — `text-wrap: balance` picks
   break points from the font's own metrics, which no size-adjust can align.
   ---------------------------------------------------------------------- */

@font-face {
  font-family: "Sora";
  src: url("../assets/fonts/sora-var-latin.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
  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;
}

@font-face {
  font-family: "Inter";
  src: url("../assets/fonts/inter-var-latin.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  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;
}

@font-face {
  font-family: "Sora fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  font-weight: 400 800;
  size-adjust: 107.6%;
  ascent-override: 97%;
  descent-override: 29%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Inter fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Liberation Sans");
  font-weight: 300 700;
  /* 105.7% is the raw glyph-width ratio; 106.5% is what actually reproduces
     this page's line breaks, swept across seven viewport widths against the
     real copy. Prose runs more lowercase than a synthetic sample string. */
  size-adjust: 106.5%;
  ascent-override: 97%;
  descent-override: 24%;
  line-gap-override: 0%;
}


/* 01  Tokens ------------------------------------------------------------- */

:root {
  /* Colour */
  --ink:          #0A1A2F;
  --ink-soft:     #10263F;
  --brand:        #1B4F8A;
  --brand-bright: #2E74C0;
  --heat:         #F59E0B;
  --heat-deep:    #DB7C06;
  --paper:        #FFFFFF;
  --paper-alt:    #F4F8FC;
  --line:         #E1EAF3;      /* decorative dividers and card edges */
  --body:         #435066;

  /* Muted, but still WCAG AA at caption sizes. The lighter slate this brand
     started from (#7A8CA3) only reaches 3.2:1 on --paper-alt, which fails for
     the 12–14px labels it is used on, so it is darkened here and split by
     surface: --muted for light, --muted-dark for navy. */
  --muted:        #5F7488;      /* 4.9:1 on --paper, 4.6:1 on --paper-alt */
  --muted-dark:   #93A9C4;      /* 7.3:1 on --ink */

  /* Amber reads as a bright graphic but a weak text colour. --heat and
     --heat-deep are for fills and icons; --heat-text is the one safe for copy. */
  --heat-text:    #A85B02;      /* 5.0:1 on --paper */

  /* Borders that identify a control (inputs, ghost buttons, icon buttons) have
     to clear 3:1 on their own — --line does not, so they use this instead. */
  --field-line:   #8494AB;      /* 3.1:1 on --paper */

  /* On dark surfaces */
  --on-dark:      #F2F7FC;
  --on-dark-soft: #B6CBE2;
  --on-dark-cool: #9FC3EC;
  --on-dark-warm: #FBBF24;

  /* The signature */
  --climate: linear-gradient(90deg, var(--brand) 0%, var(--heat) 100%);

  /* Type. The fallback face carries the metric overrides from section 00. */
  --font-display: "Sora", "Sora fallback", Arial, sans-serif;
  --font-body: "Inter", "Inter fallback", Arial, sans-serif;

  /* A deliberately wide scale: the small end stays quiet and the display end
     is allowed to get genuinely large, so hierarchy comes from contrast in
     size rather than from decoration. */
  --step--2: clamp(0.75rem, 0.735rem + 0.07vw, 0.8125rem);
  --step--1: clamp(0.8125rem, 0.79rem + 0.11vw, 0.875rem);
  --step-0:  clamp(1rem, 0.985rem + 0.08vw, 1.0625rem);
  --step-1:  clamp(1.0625rem, 1.01rem + 0.28vw, 1.25rem);
  --step-2:  clamp(1.1875rem, 1.09rem + 0.5vw, 1.5rem);
  --step-3:  clamp(1.375rem, 1.19rem + 0.92vw, 2rem);
  --step-4:  clamp(1.875rem, 1.42rem + 2.3vw, 3.375rem);
  --step-5:  clamp(2.25rem, 1.35rem + 4.4vw, 4.5rem);

  /* Space & shape */
  --container: 75rem;          /* ~1200px */
  --gutter: clamp(1.25rem, 4vw, 2rem);
  --section-y: clamp(4rem, 8vw, 7rem);
  --header-h: 4.75rem;
  --radius-card: 14px;
  --radius-btn: 10px;

  /* Elevation. A tight contact shadow plus a wide, negative-spread ambient
     one — two layers reading as a single soft light, rather than one blur
     that just looks like a grey halo. */
  --shadow-card:   0 1px 2px rgba(10, 26, 47, 0.04), 0 10px 30px -12px rgba(10, 26, 47, 0.14);
  --shadow-card-h: 0 2px 4px rgba(10, 26, 47, 0.06), 0 18px 44px -14px rgba(10, 26, 47, 0.20);
  --shadow-panel:  0 2px 6px rgba(10, 26, 47, 0.05), 0 30px 70px -24px rgba(10, 26, 47, 0.30);

  /* Grain. An feTurbulence tile as a data URI — ~380 bytes, one paint, no
     request. It is the difference between "flat navy" and a surface. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23g)'/%3E%3C/svg%3E");

  /* Durations live in tokens so `prefers-reduced-motion` can zero them all
     out in one place, with no specificity fights and no !important. */
  --dur-fast: 0.16s;
  --dur: 0.26s;
  --dur-slow: 0.62s;
  /* A long, decelerating tail — motion that settles instead of stopping. */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out: cubic-bezier(0.33, 1, 0.68, 1);

  --ring: var(--brand-bright);
}


/* 02  Reset & base ------------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
/* Set by the mobile menu so the page behind it can't scroll. */
html.menu-open { overflow: hidden; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--body);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

svg {
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

ul, ol { list-style: none; margin: 0; padding: 0; }

button { font: inherit; color: inherit; }

::selection {
  background: rgba(245, 158, 11, 0.28);
  color: var(--ink);
}
/* On navy, amber-on-amber would smother the text — go cool instead. */
.hero ::selection,
.section-focus ::selection,
.section-cta ::selection,
.site-footer ::selection {
  background: rgba(107, 165, 228, 0.35);
  color: #FFFFFF;
}

/* One focus style, everywhere: a crisp ring held off the element so it reads
   on both light and dark. --ring flips to amber on dark surfaces. */
:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 3px;
  border-radius: 5px;
}

/* Parked above the viewport by offset rather than a percentage transform, so
   it stays put regardless of its own rendered height. */
.skip-link {
  position: fixed;
  inset-inline-start: 1rem;
  inset-block-start: -4rem;
  z-index: 200;
  padding: 0.7rem 1.15rem;
  border-radius: 8px;
  background: var(--ink);
  color: var(--on-dark);
  font-size: var(--step--1);
  font-weight: 600;
  text-decoration: none;
  transition: inset-block-start var(--dur) var(--ease);
}
.skip-link:focus { inset-block-start: 1rem; }

/* Offset anchor targets so the sticky header never covers a heading. */
section[id],
main[id] { scroll-margin-top: calc(var(--header-h) + 1.25rem); }


/* 03  Typography --------------------------------------------------------- */

h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.12;
  /* Large type needs negative tracking to stop looking loose; the optical
     correction scales with size, so it is set per level below. */
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty; /* no orphans where supported; ignored elsewhere */
}

.eyebrow {
  margin: 0 0 1.15rem;
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brand);
}

/* The signature hairline. */
.eyebrow::after {
  content: "";
  display: block;
  width: 56px;
  height: 2px;
  margin-top: 0.75rem;
  border-radius: 2px;
  background: var(--climate);
}

.eyebrow-light { color: var(--on-dark-cool); }

.section-title {
  font-size: var(--step-4);
  line-height: 1.06;
  letter-spacing: -0.028em;
  max-width: 26ch;
}
.section-title-light { color: var(--on-dark); }

.section-intro {
  margin-top: 1.25rem;
  max-width: 58ch;
  font-size: var(--step-1);
  color: var(--body);
}

/* Body measure ceiling. Anything longer than this is hard to track back to
   the next line, so no prose block is allowed past it. */
.section-intro,
.card-body,
.step-body,
.focus-body,
.about-body,
.cta-sub,
.faq-answer,
.outcome-item p { max-width: 65ch; }


/* 04  Layout primitives -------------------------------------------------- */

/* Every section shares one container, so section-to-section left edges always
   line up. Narrower content is capped with max-width on the content itself
   rather than by shrinking the container. */
.container {
  width: min(100% - (var(--gutter) * 2), var(--container));
  margin-inline: auto;
}

.section { padding-block: var(--section-y); }
.section-alt { background: var(--paper-alt); }

.section-head { margin-bottom: clamp(2.25rem, 4.5vw, 3.5rem); }

.grid {
  display: grid;
  gap: clamp(1rem, 2.2vw, 1.75rem);
}
/* Column counts are declared rather than left to auto-fit. auto-fit is
   shorter, but it decides the count from available width alone, which strands
   the last item on a row of its own — 3+1 outcomes at 1200px, 2+1 services and
   3+1 steps at tablet width. Stepping the counts explicitly keeps every row
   full at every size. */
.grid-2,
.grid-3,
.grid-4 { grid-template-columns: minmax(0, 1fr); }

@media (min-width: 30rem) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 34rem) {
  .grid-2,
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Three items across two columns always orphans the third. Rather than
     leave a half-empty row, let it take the full width. */
  .grid-3 > :nth-child(3):last-child { grid-column: 1 / -1; }
}
@media (min-width: 58rem) {
  .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-3 > :nth-child(3):last-child { grid-column: auto; }
  .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.climate-rule {
  height: 2px;
  background: var(--climate);
}


/* 05  Motion primitives -------------------------------------------------- */

/* Every element that moves composes its transform from two variables, so a
   scroll reveal and a hover lift can never cancel each other out. */
[data-reveal],
.card,
.step,
.btn,
.faq-item,
.outcome-item,
.showcase-frame {
  transform: translateY(calc(var(--reveal-off, 0px) + var(--lift, 0px)))
             scale(var(--press, 1));
}

.js [data-reveal] {
  --reveal-off: 18px;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease),
              transform var(--dur-slow) var(--ease);
}
.js [data-reveal].is-visible {
  --reveal-off: 0px;
  opacity: 1;
}

/* Printing never scrolls, so nothing would ever get revealed — without this
   every card, step and answer prints blank. */
@media print {
  .js [data-reveal] {
    --reveal-off: 0px;
    opacity: 1;
  }
}

/* Hero entrance: one short, orchestrated stagger on load. */
.js [data-hero] {
  opacity: 0;
  animation: hero-in 0.65s var(--ease) forwards;
}
.js [data-hero="1"] { animation-delay: 0.04s; }
.js [data-hero="2"] { animation-delay: 0.11s; }
.js [data-hero="3"] { animation-delay: 0.18s; }
.js [data-hero="4"] { animation-delay: 0.25s; }
.js [data-hero="5"] { animation-delay: 0.32s; }

@keyframes hero-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}


/* 06  Buttons & links ---------------------------------------------------- */

a {
  color: var(--brand-bright);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--dur-fast) var(--ease);
}
a:hover { color: var(--brand); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.95rem 1.6rem;
  border: 1px solid transparent;
  border-radius: var(--radius-btn);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              color var(--dur) var(--ease);
}

.btn-primary {
  background: var(--heat);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(10, 26, 47, 0.08), 0 10px 24px rgba(245, 158, 11, 0.22);
}
.btn-primary:hover {
  --lift: -2px;
  background: var(--heat-deep);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(10, 26, 47, 0.1), 0 14px 30px rgba(219, 124, 6, 0.28);
}

/* Press: the button gives, slightly. Transform only — no reflow. */
.btn:active {
  --lift: 0px;
  --press: 0.985;
  transition-duration: var(--dur-fast);
}

.btn-ghost {
  background: transparent;
  border-color: var(--field-line);
  color: var(--ink);
}
.btn-ghost:hover {
  --lift: -2px;
  border-color: var(--brand-bright);
  color: var(--brand);
}

.btn-ghost-light {
  background: transparent;
  border-color: rgba(242, 247, 252, 0.42);
  color: var(--on-dark);
}
.btn-ghost-light:hover {
  --lift: -2px;
  background: rgba(242, 247, 252, 0.08);
  border-color: rgba(242, 247, 252, 0.6);
  color: var(--on-dark);
}

/* Visually hidden but still announced. Carries the "opens in a new tab" hint
   on every outbound demo link — display:none would drop it from the
   accessibility tree, which is the entire point of having it. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The demo link. Deliberately a text link, not a button: it is a side door,
   and a third button anywhere on this page would blunt the audit CTA. */
.demo-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 1.1rem;
  font-size: var(--step--1);
  font-weight: 600;
  /* --brand, not --brand-bright: the brighter blue is 4.48:1 on --paper-alt,
     two hundredths under AA, and this link appears on that background. */
  color: var(--brand);
  text-decoration: none;
}
.demo-link svg {
  width: 1em;
  height: 1em;
  stroke-width: 2;
  transition: transform var(--dur) var(--ease);
}
.demo-link:hover {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.demo-link:hover svg { transform: translateX(3px); }

/* On the dark CTA panel, cool rather than amber — amber belongs to the audit
   button there and nothing else should reach for it. */
.demo-link-light { color: var(--on-dark-cool); }
.demo-link-light:hover { color: #FFFFFF; }

.btn-sm {
  padding: 0.7rem 1.1rem;
  font-size: var(--step--1);
}
.btn-block { width: 100%; }


/* 07  Header, language switch, mobile menu ------------------------------- */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 50;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(12px);
  border-block-end: 1px solid transparent;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.site-header.is-scrolled {
  background: rgba(255, 255, 255, 0.95);
  border-block-end-color: var(--line);
  box-shadow: 0 1px 2px rgba(10, 26, 47, 0.04), 0 8px 22px rgba(10, 26, 47, 0.06);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2.5vw, 2.5rem);
  min-height: var(--header-h);
  transition: min-height var(--dur) var(--ease);
}
.site-header.is-scrolled .header-inner { min-height: 4.125rem; }

/* Wordmark: display face, amber period. No logo file needed. */
.wordmark {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.1rem + 0.5vw, 1.4375rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.wordmark-dot { color: var(--heat); }
.wordmark-light { color: var(--on-dark); }

.nav-desktop { margin-inline-start: auto; }

.nav-list {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2vw, 1.85rem);
}
.nav-list a {
  position: relative;
  font-size: var(--step--1);
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
}
.nav-list a::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: -0.4rem;
  height: 2px;
  border-radius: 2px;
  background: var(--climate);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur) var(--ease);
}
.nav-list a:hover::after,
.nav-list a:focus-visible::after { transform: scaleX(1); }

.header-actions {
  display: flex;
  align-items: center;
  gap: clamp(0.5rem, 1.5vw, 1rem);
  margin-inline-start: auto;
}
.nav-desktop + .header-actions { margin-inline-start: 0; }

/* EN | ES — a text switch, not a flag: a language is not a nationality. */
.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
}
.lang-btn {
  padding: 0.3rem 0.4rem;
  border: 0;
  border-radius: 6px;
  background: none;
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--muted);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}
.lang-btn:hover { color: var(--ink); }
.lang-btn.is-active { color: var(--ink); }
.lang-btn.is-active::after {
  content: "";
  display: block;
  height: 2px;
  margin-top: 2px;
  border-radius: 2px;
  background: var(--climate);
}
.lang-sep {
  color: var(--line);
  font-size: var(--step--1);
}

.menu-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid var(--field-line);
  border-radius: var(--radius-btn);
  background: var(--paper);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease);
}
.menu-toggle:hover { border-color: var(--brand-bright); }

.menu-toggle-bars {
  display: grid;
  gap: 4px;
  width: 1.125rem;
}
.menu-toggle-bars span {
  display: block;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
}

@media (max-width: 62rem) {
  .nav-desktop { display: none; }
  .menu-toggle { display: inline-flex; }
}
@media (max-width: 30rem) {
  .header-cta { display: none; }
}

/* Never ship a dead control. Without JavaScript the hamburger can't open
   anything and the language switch can't switch anything, so the links move
   into the header and the EN | ES toggle steps out. English is the document
   language, so nothing is lost. */
html:not(.js) .menu-toggle,
html:not(.js) .lang-switch { display: none; }
@media (max-width: 62rem) {
  html:not(.js) .nav-desktop { display: block; margin-inline-start: 0; }
  html:not(.js) .header-inner {
    flex-wrap: wrap;
    padding-block: 0.85rem;
    row-gap: 0.5rem;
  }
  html:not(.js) .nav-list { flex-wrap: wrap; gap: 0.35rem 1.15rem; }
}

/* Mobile menu overlay */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(10, 26, 47, 0.6);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.mobile-menu.is-open { opacity: 1; }

.mobile-menu-panel {
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  display: flex;
  flex-direction: column;
  gap: 2rem;
  width: min(88vw, 21.5rem);
  padding: clamp(1.5rem, 5vw, 2.25rem);
  padding-block-start: 5rem;
  overflow-y: auto;
  background: var(--paper);
  box-shadow: var(--shadow-panel);
  transform: translateX(100%);
  transition: transform var(--dur-slow) var(--ease);
}
.mobile-menu.is-open .mobile-menu-panel { transform: none; }

.mobile-nav-list {
  display: grid;
  gap: 0.25rem;
}
.mobile-nav-list a {
  display: block;
  padding: 0.85rem 0;
  border-block-end: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
}
.mobile-nav-list a:hover { color: var(--brand); }

.mobile-menu-cta { display: grid; gap: 0.75rem; }

.mobile-menu-close {
  position: absolute;
  inset-block-start: 1.15rem;
  inset-inline-end: 1.15rem;
  width: 2.6rem;
  height: 2.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--field-line);
  border-radius: var(--radius-btn);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease);
}
.mobile-menu-close:hover { border-color: var(--brand-bright); }
.mobile-menu-close svg { width: 1.15rem; height: 1.15rem; }


/* 08  Hero --------------------------------------------------------------- */

/* Cool light from the upper left, a warm bloom low and right, over a navy
   that is itself a gradient rather than a flat fill. */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(4.75rem, 11vw, 9rem);
  color: var(--on-dark);
  background:
    radial-gradient(120% 130% at 6% 2%, rgba(27, 79, 138, 0.42) 0%, rgba(27, 79, 138, 0) 58%),
    radial-gradient(95% 115% at 97% 88%, rgba(245, 158, 11, 0.15) 0%, rgba(245, 158, 11, 0) 62%),
    linear-gradient(168deg, #0C2039 0%, #0A1A2F 54%, #091628 100%);
  --ring: var(--on-dark-warm);
}

.hero-bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
}

/* Anchored low and right, so the warm core lands past the end of the headline
   and reinforces the warm radial already in the section background. The outer
   contours are far larger than the viewBox, so they still sweep the whole
   field behind the copy. */
.hero-motif {
  position: absolute;
  inset-inline-end: -13%;
  inset-block-end: -24%;
  width: min(70rem, 116%);
  height: auto;
  aspect-ratio: 900 / 700;
}

/* Grain, on top of the field but under the copy. */
.hero::before,
.section-focus::before,
.section-cta::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--grain);
  background-size: 140px 140px;
  opacity: 0.055;
  mix-blend-mode: overlay;
  pointer-events: none;
}

.hero-inner {
  position: relative;
  z-index: 1;
  max-width: 60rem;
}

.hero .eyebrow::after {
  width: 96px;
  height: 3px;
}

.hero-title {
  font-size: var(--step-5);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.034em;
  color: #FFFFFF;
}

/* The one expressive moment on the page: cool-to-warm, inside the word.
   Base colour first so the text is never invisible if the clip is
   unsupported, and forced-colors gets a plain system colour. */
.hero-accent { color: var(--on-dark-warm); }

@supports (-webkit-background-clip: text) or (background-clip: text) {
  .hero-accent {
    background-image: linear-gradient(96deg, #6BA5E4 4%, var(--heat) 72%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}
@media (forced-colors: active) {
  .hero-accent {
    background-image: none;
    color: CanvasText;
    -webkit-text-fill-color: CanvasText;
  }
}

.hero-sub {
  margin-top: clamp(1.35rem, 2.5vw, 1.9rem);
  /* rem, not ch, on purpose. `ch` is the width of the font's own "0", so a
     ch-based cap resolves to a different pixel width for the webfont than for
     the fallback — which changes the line count across a font swap. That is a
     layout shift, and this block sits directly under the LCP element. Prose
     further down the page keeps ch, where measure matters more than certainty. */
  max-width: 40rem;
  font-size: var(--step-1);
  color: var(--on-dark-soft);
}

@media (max-width: 56rem) {
  /* Keep the warm core out from behind the headline on narrow screens. */
  .hero-motif {
    inset-block-end: -12%;
    inset-inline-end: -46%;
    width: 172%;
    opacity: 0.7;
  }
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
}

.hero-note {
  margin-top: 1.25rem;
  font-size: var(--step--1);
  color: var(--on-dark-soft);
}


/* 09  Cards, icons, lists ------------------------------------------------ */

.card {
  position: relative;
  padding: clamp(1.5rem, 2.8vw, 2rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--paper);
  box-shadow: var(--shadow-card);
  transition: border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}

/* A 1px climate edge along the top, revealed on hover. Opacity only, so it
   composites on the GPU and never touches layout. */
.card::before {
  content: "";
  position: absolute;
  inset-block-start: -1px;
  inset-inline: clamp(1rem, 4%, 2rem);
  height: 2px;
  border-radius: 2px;
  background: var(--climate);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.card:hover {
  --lift: -3px;
  border-color: #CFE0F1;
  box-shadow: var(--shadow-card-h);
}
.card:hover::before { opacity: 1; }

.card-list .card { display: flex; flex-direction: column; }

/* Icon chips: a soft gradient wash, a hairline inset ring, and a single-pixel
   top highlight — depth without a box. The icons themselves are drawn for this
   page, two-tone: cool line work with one warm element carrying the point. */
.icon-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  margin-bottom: 1.5rem;
  border-radius: 13px;
  background: linear-gradient(152deg, rgba(46, 116, 192, 0.14) 0%, rgba(27, 79, 138, 0.035) 100%);
  box-shadow: inset 0 0 0 1px rgba(27, 79, 138, 0.10),
              inset 0 1px 0 rgba(255, 255, 255, 0.65);
  color: var(--brand);
}
.icon-badge svg {
  width: 2rem;
  height: 2rem;
  stroke-width: 1.8;
}
.icon-badge .i-accent { stroke: var(--heat-text); }

.icon-badge-heat {
  background: linear-gradient(152deg, rgba(245, 158, 11, 0.22) 0%, rgba(245, 158, 11, 0.05) 100%);
  box-shadow: inset 0 0 0 1px rgba(245, 158, 11, 0.22),
              inset 0 1px 0 rgba(255, 255, 255, 0.7);
  color: var(--brand);
}

.card-title {
  font-size: var(--step-2);
  margin-bottom: 0.7rem;
}
.card-body { color: var(--body); }

.list-label {
  margin-block: 1.5rem 0.7rem;
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}

.check-list {
  display: grid;
  gap: 0.55rem;
  font-size: var(--step--1);
  color: var(--body);
}
.check-list li {
  position: relative;
  padding-inline-start: 1.5rem;
}
.check-list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.52em;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  border: 2px solid var(--brand);
}


/* 10  Services ----------------------------------------------------------- */

.service-list .service-card {
  display: flex;
  flex-direction: column;
}

.service-tag {
  margin-bottom: 0.6rem;
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
}

.outcome {
  margin-top: auto;
  padding-top: 0.25rem;
}
.outcome .list-label { margin-block-start: 1.75rem; }
.outcome-text {
  padding-top: 0.9rem;
  border-block-start: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.012em;
  color: var(--ink);
}

/* The flagship offer: amber border, deeper shadow, a ribbon. No layout
   trickery, so the scroll reveal and hover lift stay intact. */
.service-card.is-flagship {
  border-color: rgba(245, 158, 11, 0.55);
  box-shadow: var(--shadow-card-h);
}
.service-card.is-flagship:hover {
  border-color: var(--heat);
  box-shadow: var(--shadow-panel);
}
/* Already the warmest card — the cool half of the edge would fight it. */
.service-card.is-flagship::before { background: var(--heat); }
.service-card.is-flagship .service-tag { color: var(--heat-text); }
.service-card.is-flagship .check-list li::before { border-color: var(--heat-text); }
.service-card.is-flagship .outcome-text { border-block-start-color: rgba(245, 158, 11, 0.4); }

.ribbon {
  position: absolute;
  inset-block-start: -0.8rem;
  inset-inline-end: 1.25rem;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  background: var(--heat);
  color: var(--ink);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
}


/* 11  Process ------------------------------------------------------------ */

.step {
  padding-top: 1.35rem;
  border-block-start: 1px solid var(--line);
  transition: border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.step:hover {
  --lift: -3px;
  border-block-start-color: var(--brand);
}
.step:last-child:hover { border-block-start-color: var(--heat); }

.step-num {
  margin-bottom: 0.85rem;
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  color: var(--muted);
}
/* Last step is the payoff — the only warm note in the sequence. */
.step:last-child .step-num { color: var(--heat-text); }

.step-title {
  font-size: var(--step-1);
  margin-bottom: 0.6rem;
}
.step-body {
  font-size: var(--step--1);
  color: var(--body);
}


/* 12  Focus (dark) section ----------------------------------------------- */

.section-focus {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: var(--on-dark-soft);
  background:
    radial-gradient(100% 130% at 4% 0%, rgba(27, 79, 138, 0.34) 0%, rgba(27, 79, 138, 0) 56%),
    radial-gradient(80% 110% at 99% 100%, rgba(245, 158, 11, 0.12) 0%, rgba(245, 158, 11, 0) 58%),
    linear-gradient(176deg, #0B1E35 0%, #0A1A2F 100%);
  --ring: var(--on-dark-warm);
}

.focus-inner {
  display: grid;
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}
@media (min-width: 56rem) {
  .focus-inner { grid-template-columns: minmax(0, 1.5fr) auto; }
}

.focus-body {
  margin-top: 1.5rem;
  max-width: 62ch;
  font-size: var(--step-1);
  color: var(--on-dark-soft);
}

/* Cooling / heating, stated plainly — the thesis as a small mark.
   Wide: a stacked column with the gradient running cool at the top to warm at
   the bottom. Narrow: the same thing laid on its side. */
.focus-mark {
  display: flex;
  align-items: center;
  gap: 1rem;
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.focus-mark-cool { color: var(--on-dark-cool); }
.focus-mark-warm { color: var(--on-dark-warm); }
.focus-mark-rule {
  flex: 1 1 auto;
  min-width: 3rem;
  height: 2px;
  border-radius: 2px;
  background: var(--climate);
}
@media (min-width: 56rem) {
  .focus-mark {
    flex-direction: column;
    gap: 1.15rem;
    text-align: center;
  }
  .focus-mark-rule {
    /* Reset the horizontal sizing, or the flex basis keeps it 3rem wide and
       the hairline renders as a block. */
    flex: 0 0 auto;
    width: 2px;
    min-width: 0;
    height: 7.5rem;
    background: linear-gradient(180deg, var(--brand) 0%, var(--heat) 100%);
  }
}


/* 13  Outcomes ----------------------------------------------------------- */

.outcome-list { gap: clamp(1.25rem, 2.5vw, 2rem); }

.outcome-item {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  padding: 1.25rem 1.35rem;
  border-radius: var(--radius-card);
  background: var(--paper-alt);
  transition: background-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.outcome-item:hover {
  --lift: -2px;
  background: #EDF4FB;
}
.outcome-item p { color: var(--body); }
.outcome-item strong {
  font-weight: 600;
  color: var(--ink);
}

.tick {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  margin-top: 0.15rem;
  border-radius: 50%;
  background: rgba(245, 158, 11, 0.16);
  color: var(--heat-deep);
}
.tick svg { width: 1rem; height: 1rem; stroke-width: 2.2; }


/* 14  FAQ ---------------------------------------------------------------- */

/* Heading beside the questions on wide screens: fills the column, and keeps
   the section's left edge aligned with every other section. */
.faq-inner {
  display: grid;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}
@media (min-width: 58rem) {
  .faq-inner { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); }
  .faq-head { margin-bottom: 0; }
}

.faq-list {
  border-block-start: 1px solid var(--line);
}

.faq-item { border-block-end: 1px solid var(--line); }

.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  padding-block: 1.2rem;
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
  transition: color var(--dur-fast) var(--ease);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--brand); }
.faq-item[open] summary { color: var(--brand); }

.faq-chevron {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: rgba(27, 79, 138, 0.07);
  color: var(--brand);
}
.faq-chevron svg {
  width: 1rem;
  height: 1rem;
  transition: transform var(--dur) var(--ease);
}
.faq-item[open] .faq-chevron svg { transform: rotate(180deg); }

.faq-answer {
  padding-block-end: 1.45rem;
  padding-inline-end: 3rem;
  max-width: 68ch;
  color: var(--body);
}


/* 15  About ------------------------------------------------------------- */

.about-body {
  margin-top: 1.5rem;
  max-width: 68ch;
  font-size: var(--step-1);
  color: var(--body);
}


/* 16  Final CTA & form -------------------------------------------------- */

/* The warm glow sits low and right, where the form is — heat, held back.
   Folded into the background stack so ::before is free for the grain. */
.section-cta {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: var(--on-dark-soft);
  background:
    radial-gradient(75% 105% at 86% 112%, rgba(245, 158, 11, 0.20) 0%, rgba(245, 158, 11, 0) 62%),
    radial-gradient(70% 100% at 2% -14%, rgba(46, 116, 192, 0.20) 0%, rgba(46, 116, 192, 0) 56%),
    linear-gradient(174deg, #11293F 0%, #0E2237 100%);
  --ring: var(--on-dark-warm);
}

.cta-inner {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4rem);
  align-items: start;
}
@media (min-width: 58rem) {
  .cta-inner { grid-template-columns: minmax(0, 1fr) minmax(0, 25rem); }
}

.cta-sub {
  margin-top: 1.5rem;
  max-width: 52ch;
  font-size: var(--step-1);
  color: var(--on-dark-soft);
}
.cta-or { margin-top: 2rem; }
.cta-note {
  margin-top: 1.25rem;
  font-size: var(--step--1);
  color: var(--on-dark-soft);
}

.cta-demo {
  margin-top: 1.6rem;
  padding-top: 1.4rem;
  border-block-start: 1px solid rgba(242, 247, 252, 0.14);
  font-size: var(--step--1);
  color: var(--on-dark-soft);
}
.cta-demo .demo-link { margin-top: 0.35rem; display: flex; }

.form-card {
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border-radius: var(--radius-card);
  background: var(--paper);
  box-shadow: var(--shadow-panel);
  --ring: var(--brand-bright);
}
.form-title {
  font-size: var(--step-2);
  margin-bottom: 1.5rem;
}

.audit-form { display: grid; gap: 1.15rem; }

.field { display: grid; gap: 0.4rem; }
.field label {
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--ink);
}
.field-optional {
  font-weight: 400;
  color: var(--muted);
}

.field input[type="text"],
.field input[type="email"] {
  width: 100%;
  padding: 0.8rem 0.95rem;
  border: 1px solid var(--field-line);
  border-radius: var(--radius-btn);
  background: var(--paper);
  font-family: var(--font-body);
  font-size: 1rem; /* 16px minimum: stops iOS zooming on focus */
  color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.field input::placeholder { color: var(--muted); }
.field input:hover { border-color: var(--brand); }
.field input:focus {
  border-color: var(--brand-bright);
  outline: none;
  box-shadow: 0 0 0 3px rgba(46, 116, 192, 0.18);
}
.field input:focus-visible { outline: none; }
.field input[aria-invalid="true"] { border-color: #C0392F; }

.field-error {
  font-size: var(--step--1);
  color: #A6291F;
}

/* Honeypot: out of sight for people, still in the DOM for bots. */
.hp {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
}

.form-status {
  font-size: var(--step--1);
  font-weight: 500;
}
.form-status:empty { display: none; }
.form-status.is-pending { color: var(--muted); }
.form-status.is-success {
  padding: 0.8rem 1rem;
  border-radius: var(--radius-btn);
  background: rgba(15, 122, 74, 0.09);
  color: #0B6039;
}
.form-status.is-error {
  padding: 0.8rem 1rem;
  border-radius: var(--radius-btn);
  background: rgba(192, 57, 47, 0.08);
  color: #A6291F;
}

.form-fineprint {
  font-size: var(--step--2);
  line-height: 1.55;
  color: var(--muted);
}

/* Sent: the fields step aside and the confirmation is all that's left. */
.audit-form.is-sent .field,
.audit-form.is-sent .form-fineprint,
.audit-form.is-sent button[type="submit"] { display: none; }


/* 17  Footer ------------------------------------------------------------ */

.site-footer {
  background: var(--ink);
  color: var(--on-dark-soft);
  --ring: var(--on-dark-warm);
}

.footer-inner {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  padding-block: clamp(3rem, 6vw, 4.5rem);
}
@media (min-width: 46rem) {
  .footer-inner { grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr) minmax(0, 1fr); }
}

.footer-brand .wordmark { display: block; margin-bottom: 1rem; }
.footer-tagline {
  max-width: 34ch;
  color: var(--on-dark-soft);
}
.footer-serving {
  margin-top: 0.9rem;
  font-size: var(--step--1);
  color: var(--muted-dark);
}

.footer-heading {
  margin-bottom: 1.1rem;
  font-family: var(--font-body);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--on-dark);
}

.footer-col ul { display: grid; gap: 0.65rem; }
.footer-col a {
  font-size: var(--step--1);
  color: var(--on-dark-soft);
  text-decoration: none;
}
.footer-col a:hover {
  color: var(--on-dark);
  text-decoration: underline;
}

.footer-legal {
  padding-block: 1.5rem 2rem;
  border-block-start: 1px solid rgba(242, 247, 252, 0.14);
  font-size: var(--step--2);
  color: var(--muted-dark);
}


/* 18  Reduced motion ---------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  /* Zeroing the duration tokens disables every transition on the page
     without a single specificity override. */
  :root {
    --dur-fast: 1ms;
    --dur: 1ms;
    --dur-slow: 1ms;
  }
  html { scroll-behavior: auto; }

  .js [data-reveal] {
    --reveal-off: 0px;
    opacity: 1;
  }
  .js [data-hero] {
    opacity: 1;
    animation: none;
  }
  .card:hover,
  .step:hover,
  .btn:hover,
  .outcome-item:hover { --lift: 0px; }
  .btn:active { --press: 1; }
}


/* 19  Demo showcase & demo CTAs -----------------------------------------
   Hierarchy, deliberately: amber solid = the audit (primary, one per screen),
   azure = the demo (secondary), plain text link = "book a call" and the quiet
   footer/CTA demo links (tertiary). Nothing here reaches for amber.
   -------------------------------------------------------------------- */

.showcase {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: var(--on-dark-soft);
  background:
    radial-gradient(90% 120% at 6% 0%, rgba(27, 79, 138, 0.34) 0%, rgba(27, 79, 138, 0) 58%),
    radial-gradient(70% 100% at 96% 100%, rgba(245, 158, 11, 0.10) 0%, rgba(245, 158, 11, 0) 58%),
    linear-gradient(170deg, #0B1E33 0%, #0A1A2F 100%);
  --ring: var(--on-dark-warm);
}
.showcase::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--grain);
  background-size: 140px 140px;
  opacity: 0.055;
  mix-blend-mode: overlay;
  pointer-events: none;
}
/* The signature hairline as this band's top edge — the same job it does above
   the footer, marking a shift in register. */
.showcase::after {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 2px;
  background: var(--climate);
}

.showcase-inner {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: center;
}
@media (min-width: 62rem) {
  .showcase-inner { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); }
}
.showcase-sub {
  margin-top: 1.2rem;
  max-width: 54ch;
  font-size: var(--step-1);
  color: var(--on-dark-soft);
}
.showcase-copy .btn { margin-top: 1.9rem; }

/* Azure, not amber. It reads unmistakably as a button while leaving the audit
   CTA the only warm thing on the page. White on --brand-bright is 4.9:1. */
.btn-demo {
  background: var(--brand-bright);
  color: #FFFFFF;
  box-shadow: 0 1px 2px rgba(10, 26, 47, 0.2), 0 12px 26px -10px rgba(46, 116, 192, 0.55);
}
.btn-demo:hover {
  --lift: -2px;
  background: var(--brand);
  color: #FFFFFF;
  box-shadow: 0 2px 4px rgba(10, 26, 47, 0.22), 0 16px 32px -12px rgba(46, 116, 192, 0.6);
}
/* The base .btn has no svg sizing rule on this site, so an inline icon with
   no width/height fills the button. Every icon inside a button needs both. */
.btn svg,
.btn-demo svg {
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
  stroke-width: 2;
  transition: transform var(--dur) var(--ease);
}
.btn-demo:hover svg { transform: translateX(3px); }

/* In-content variant for light cards: outlined, so a card can carry a real
   button without shouting over the amber one further down the page. */
.btn-demo-soft {
  background: transparent;
  border-color: var(--brand-bright);
  color: var(--brand);
}
.btn-demo-soft:hover {
  --lift: -2px;
  background: rgba(46, 116, 192, 0.09);
  border-color: var(--brand);
  color: var(--brand);
}
.demo-cta { margin-top: 1.15rem; align-self: flex-start; }
.demo-cta svg { width: 1em; height: 1em; stroke-width: 2; transition: transform var(--dur) var(--ease); }
.demo-cta:hover svg { transform: translateX(3px); }

/* Mock browser chrome around the screenshot. aspect-ratio reserves the box
   before the lazy image arrives, so nothing shifts. */
.showcase-frame {
  display: block;
  border: 1px solid rgba(242, 247, 252, 0.14);
  border-radius: 14px;
  overflow: hidden;
  background: #0E2436;
  box-shadow: 0 2px 6px rgba(4, 12, 22, 0.4), 0 34px 70px -26px rgba(4, 12, 22, 0.75);
  text-decoration: none;
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.showcase-frame:hover {
  --lift: -4px;
  border-color: rgba(242, 247, 252, 0.32);
  box-shadow: 0 4px 10px rgba(4, 12, 22, 0.45), 0 44px 88px -28px rgba(4, 12, 22, 0.85);
}
.frame-chrome {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 0.8rem;
  background: rgba(242, 247, 252, 0.07);
  border-block-end: 1px solid rgba(242, 247, 252, 0.1);
}
.frame-dots { display: flex; gap: 0.32rem; flex: 0 0 auto; }
.frame-dots span {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: rgba(242, 247, 252, 0.26);
}
.frame-url {
  flex: 1 1 auto;
  padding: 0.18rem 0.7rem;
  border-radius: 999px;
  background: rgba(8, 20, 34, 0.55);
  font-size: var(--step--2);
  color: var(--on-dark-soft);
  text-align: center;
}
.showcase-frame img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1120 / 700;
}

/* Hero: a text CTA, not a third button. Underlined and arrowed so it is
   obviously tappable, but it cannot pull focus from the amber audit button. */
.hero-demo { margin-top: 1.15rem; }
.hero-demo .demo-link {
  margin-top: 0;
  padding-block: 0.3rem;
  color: var(--on-dark);
  text-decoration: underline;
  text-decoration-color: rgba(244, 248, 252, 0.5);
  text-underline-offset: 4px;
}
.hero-demo .demo-link:hover {
  color: #FFFFFF;
  text-decoration-color: #FFFFFF;
}
.hero-demo .demo-link svg { transition: transform var(--dur) var(--ease); }
.hero-demo .demo-link:hover svg { transform: translateX(3px); }
