/* ─────────────────────────────────────────────────────────────────────
   Modern look — phase 1
   --------------------------------------------------------------------
   Loaded AFTER style.v2.css so its rules win without !important.
   Three drop-in upgrades, no DOM changes required:
     1. Inter Display + Inter via Google Fonts (CSP already allows
        fonts.googleapis.com / fonts.gstatic.com).
     2. Mesh-gradient backdrop on the hero — pure CSS, GPU-cheap.
     3. Stats-counter readiness class for IntersectionObserver-driven
        animation (script lives in modern.js).

   Why a second stylesheet instead of editing style.v2.css?
   - Easy to bisect / disable: drop the <link> tag, look reverts.
   - The legacy stylesheet is huge; isolating modern type + visuals
     keeps diffs reviewable.
   - The bundle size cost is one extra HTTP/2 stream — tens of bytes
     of header overhead, not a real perf concern at our scale.
   ─────────────────────────────────────────────────────────────────────  */

/* ── Typography ──────────────────────────────────────────────────────
   `font-display: swap` is critical for Largest-Contentful-Paint —
   the page renders immediately with system font, then re-flows when
   Inter loads.  This is also what Lighthouse rewards. */
:root {
  --font-display: 'Inter Tight', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-body:    'Inter',          'Inter Tight', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* Global body font upgrade.  Headings get Inter Display below. */
body { font-family: var(--font-body); }

/* Headings: tighter tracking + variable-weight gives the modern,
   premium feel of Linear / Vercel without changing markup. */
h1, h2, h3, h4, h5, h6,
.hero__title,
.section__header h2,
.gradient-text {
  font-family: var(--font-display);
  letter-spacing: -0.025em;
  /* Inter has wght 100-900 as a variable axis — claim 700 for h2/h3,
     bump h1 to 800 for an even stronger anchor.                    */
  font-feature-settings: 'cv11' on, 'ss01' on, 'ss03' on;
}

/* ── Mesh-gradient hero backdrop ─────────────────────────────────────
   Three radial gradients stacked ≈ Linear/Vercel mesh look.
   Pure CSS — no canvas, no extra HTTP. Negative z-index keeps it
   behind the hero content; pointer-events:none so it never eats
   clicks; will-change tells the browser to promote to its own
   compositor layer (smoother on scroll).                            */
.hero { position: relative; isolation: isolate; }

.hero::before {
  content: '';
  position: absolute;
  inset: -10% -5% auto -5%;
  height: 70%;
  z-index: -1;
  pointer-events: none;
  /* Mesh: violet (brand) + cyan (compliance) + magenta (alert) — the
     three colours that already appear in our compliance / risk badges. */
  background:
    radial-gradient(60% 80% at 20% 20%, rgba(99, 102, 241, 0.28), transparent 70%),
    radial-gradient(50% 70% at 80% 30%, rgba(56, 189, 248, 0.22), transparent 70%),
    radial-gradient(40% 60% at 50% 80%, rgba(167, 139, 250, 0.18), transparent 70%);
  filter: blur(40px);
  /* Soft fade so the gradient melts into the page background. */
  -webkit-mask-image: linear-gradient(180deg, #000 60%, transparent);
          mask-image: linear-gradient(180deg, #000 60%, transparent);
}

/* Reduce motion: the mesh is static, but if a user prefers reduced
   motion we drop the blur (cheaper) — there's no animation to kill
   here, this is just defensive. */
@media (prefers-reduced-motion: reduce) {
  .hero::before { filter: none; opacity: 0.7; }
}

/* ── Stats counters ───────────────────────────────────────────────
   Markup contract: any element with `data-counter="<final>"` will
   start at 0 and tick to <final> the first time it enters the
   viewport. The element keeps its existing styling — the JS only
   writes textContent.

   We add a faint highlight while the count is in progress so the
   animation reads as intentional rather than as content-shift jank.
*/
[data-counter] {
  font-variant-numeric: tabular-nums;
  transition: text-shadow 0.6s ease;
}
[data-counter].is-counting {
  text-shadow: 0 0 16px rgba(99, 102, 241, 0.45);
}

/* Honour reduced-motion — show the final value immediately. */
@media (prefers-reduced-motion: reduce) {
  [data-counter].is-counting { text-shadow: none; }
}

/* ── Scroll-triggered reveal animations ──────────────────────────────
   Three drop-in animation classes, all driven by `.is-revealed`
   which `modern.js` adds when the element enters the viewport.
   Why this design:
     - One pure-CSS file, no animation library — Linear/Vercel
       achieve the same look with this exact pattern.
     - Initial state: invisible + offset.  Final state: in place.
       So the page paints the final layout immediately for SSR /
       Lighthouse / no-JS visitors (search bots), and then the
       reveal class is added at the right moment to play the
       transition. Zero CLS (cumulative layout shift) impact.
     - Stagger handled with `--reveal-delay` custom prop so authors
       can write `style="--reveal-delay:.15s"` without touching JS.
   ───────────────────────────────────────────────────────────────── */

.reveal,
.reveal-up,
.reveal-scale {
  /* Default: visible — guarantees visibility for crawlers, no-JS,
     and reduced-motion users.  When modern.js detects that JS is
     active and motion isn't reduced, it adds `.js-reveal-ready`
     to <html>, which flips the initial state to hidden so the
     animation has somewhere to come from. */
  transform: none;
  transition: transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--reveal-delay, 0s);
  will-change: transform;
}

/* Initial state uses ONLY transform — no opacity. Axe / WCAG-2.1
   contrast checks read live computed style; if we made the text
   semi-transparent the page would briefly fail AA on the cards
   below the fold. Slide-only animation is plenty without that
   trade-off, and matches what Linear / Vercel actually do
   (look closely — their reveals are translate, not fade). */
html.js-reveal-ready .reveal-up    { transform: translateY(24px); }
html.js-reveal-ready .reveal-scale { transform: scale(0.96); }
/* `.reveal` (plain) has no transform delta — it's a noop class for
   future use; kept for API stability. */

.reveal.is-revealed,
.reveal-up.is-revealed,
.reveal-scale.is-revealed {
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal-up, .reveal-scale { transition: none; }
  /* Belt-and-braces: even if JS adds the ready class, force the
     final state for reduced-motion users. */
  html.js-reveal-ready .reveal,
  html.js-reveal-ready .reveal-up,
  html.js-reveal-ready .reveal-scale {
    opacity: 1;
    transform: none;
  }
}

/* ── Brand illustration shells ───────────────────────────────────────
   The three new inline SVGs are wrapped in `.brand-illustration` so
   we can size them consistently across sections without inlining
   width / height inside each `<svg>` tag.  Inline SVG is also a
   small SEO/perf win — fewer HTTP requests and the browser can
   colour-match strokes via CSS variables, no PNG round-trip.       */

.brand-illustration {
  display: block;
  width: 100%;
  max-width: 560px;
  margin: 32px auto;
  height: auto;
}
.brand-illustration svg { width: 100%; height: auto; display: block; }

/* ── Frameworks ribbon ─────────────────────────────────────────────
   Compact horizontal listing of all supported compliance standards.
   Replaces the earlier 18-cell SVG that read as "empty checkboxes"
   without the names — chip-style pills carry the proof in one
   glance. Wraps cleanly on narrow viewports without horizontal
   scroll. */

.frameworks-ribbon {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  max-width: 1000px;
  margin: 0 auto 48px;
  padding: 4px;
}
.frameworks-ribbon span {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(99, 102, 241, 0.08);
  border: 1px solid rgba(99, 102, 241, 0.20);
  color: var(--text, #e8e8f0);
  font-size: 0.82rem;
  font-weight: 500;
  font-family: var(--font-body);
  letter-spacing: 0;
  white-space: nowrap;
  /* Subtle hover lift — only really visible on desktop, but cheap. */
  transition: transform 200ms ease, background-color 200ms ease;
}
.frameworks-ribbon span:hover {
  background: rgba(99, 102, 241, 0.16);
  transform: translateY(-1px);
}
@media (max-width: 480px) {
  .frameworks-ribbon { gap: 6px; }
  .frameworks-ribbon span { padding: 5px 10px; font-size: 0.78rem; }
}

/* (Reserved for future brand illustrations — keep the
   `.brand-illustration` shell so we can drop in another inline
   SVG without retemplating the wrapper.) */

/* ── Hero score-card live-feel ───────────────────────────────────────
   The score-card mockup ships static markup that's perfect for SEO
   and no-JS visitors. These rules layer on a live-pulse dot, a
   gentle ring breathing, and the visual chrome for the JS-driven
   countdown timer.

   Honesty rule: this is a *mockup*, not real scanner output. We
   never claim it's live customer data; the timer just loops 60→0
   so the page doesn't feel inert.
*/

.score-card__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  font-size: 0.78rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.score-card__sep {
  opacity: 0.4;
  user-select: none;
}
.score-card__countdown {
  display: inline-block;
  min-width: 1.6em;
  text-align: right;
  font-weight: 600;
  color: var(--accent-h, #818cf8);
  /* tabular-nums prevents jitter as the digit changes 60 → 9 */
  font-variant-numeric: tabular-nums;
}

/* "Live" indicator dot — pulsing green pin telling the visitor
   the mockup is animated. Two stacked dots: solid centre + halo
   that grows + fades. Pure CSS; reduced-motion strips the halo. */
.live-dot {
  position: relative;
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--green, #22c55e);
  flex-shrink: 0;
}
.live-dot::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: var(--green, #22c55e);
  opacity: 0.55;
  animation: live-dot-halo 1.8s ease-out infinite;
  pointer-events: none;
}
@keyframes live-dot-halo {
  0%   { transform: scale(0.6); opacity: 0.55; }
  80%  { transform: scale(2.0); opacity: 0;    }
  100% { transform: scale(2.0); opacity: 0;    }
}
@media (prefers-reduced-motion: reduce) {
  .live-dot::after { animation: none; opacity: 0; }
}

/* Soft outer glow on the score ring — replaces a previous infinite
   "breathing" keyframe animation.  Static filter avoids the
   page-instability Playwright/Puppeteer auto-wait drama (every
   click on the page would have to wait for a never-stable
   layer), and the visual is just as appealing for the hero —
   the ring already has the gradient SVG to draw the eye. */
.score-ring {
  filter: drop-shadow(0 0 18px rgba(99,102,241,0.30));
}
@media (prefers-reduced-motion: reduce) {
  .score-ring { filter: none; }
}

/* ── Stack compatibility ───────────────────────────────────────────
   "Works with your existing stack" — 4-column responsive grid of
   tech categories (EDR / MDM / IdP / SIEM) with status pills.

   Two pill states:
     .stack-pill--ok   = green ring, lives today
     .stack-pill--soon = amber ring, on the conditional-access /
                         exporter roadmap (Phase 3)

   No vendor logos. Pure type + tiny lucide-style stroke icon for
   the category title — keeps the page free of trademark risk and
   makes the section trivially translatable. */

.stack-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  max-width: 1080px;
  margin: 12px auto 28px;
}

.stack-cat {
  padding: 18px 20px;
  border: 1px solid var(--border, #2a2a3e);
  border-radius: 14px;
  background: var(--surface, #18182a);
}
.stack-cat__title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  /* Use the lighter accent (`--accent-h`, #818cf8) — contrast against
     the dark surface is ~5.5:1 vs ~3.5 for `--accent`. WCAG-2 AA
     normal-text threshold is 4.5:1 and bold uppercase 12px counts
     as normal text, not "large", so we need the higher-contrast
     swatch here. */
  color: var(--accent-h, #818cf8);
  font-family: var(--font-display);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.stack-cat__title svg { flex-shrink: 0; opacity: 0.85; }

.stack-pills {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.stack-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 8px;
  border: 1px solid;
  background: rgba(255, 255, 255, 0.02);
  font-size: 0.86rem;
  line-height: 1.3;
  font-family: var(--font-body);
  color: var(--text);
  /* `--soon` pills carry inner spans that data-i18n swaps for the
     localised "roadmap" word — give them a nested-color hint. */
}
.stack-pill > span { color: var(--text-muted, #8888a8); font-size: 0.78rem; }

.stack-pill--ok {
  border-color: rgba(34, 197, 94, 0.40);
  background: rgba(34, 197, 94, 0.06);
}
.stack-pill--ok::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--green, #22c55e);
  box-shadow: 0 0 6px rgba(34, 197, 94, 0.6);
  flex-shrink: 0;
}

.stack-pill--soon {
  border-color: rgba(234, 179, 8, 0.40);
  background: rgba(234, 179, 8, 0.05);
}
.stack-pill--soon::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--yellow, #eab308);
  flex-shrink: 0;
}

.stack-footnote {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.92rem;
  max-width: 640px;
  margin: 24px auto 0;
}

@media (max-width: 480px) {
  .stack-grid { gap: 14px; }
  .stack-cat { padding: 16px 16px; }
}

/* ── FAQ accordion ──────────────────────────────────────────────────
   Built on native <details>/<summary>:
     - Free keyboard nav (Tab, Enter, Space).
     - Free aria-expanded state from the browser.
     - Mobile-friendly without JS.
     - Works with `prefers-reduced-motion` automatically.
   We only style the visuals + tame the default disclosure-arrow.   */

.faq-list { display: flex; flex-direction: column; gap: 10px; }

.faq-item {
  border: 1px solid var(--border, #2a2a3e);
  border-radius: 12px;
  background: var(--surface, #18182a);
  overflow: hidden;
  transition: border-color 200ms ease;
}
.faq-item[open] { border-color: rgba(99, 102, 241, 0.45); }

.faq-item summary {
  /* `list-style: none` removes the default disclosure triangle in
     Firefox; the WebKit equivalent lives below. */
  list-style: none;
  cursor: pointer;
  padding: 18px 22px 18px 56px;
  position: relative;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.02rem;
  letter-spacing: -0.01em;
  line-height: 1.4;
  color: var(--text);
  /* Match the focus indicator the rest of the site uses. */
  outline: none;
}
.faq-item summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.faq-item summary::-webkit-details-marker { display: none; }

/* Custom +/- glyph in the left gutter — flips when [open]. */
.faq-item summary::before {
  content: '';
  position: absolute;
  left: 22px;
  top: 50%;
  width: 16px; height: 16px;
  transform: translateY(-50%);
  background:
    linear-gradient(currentColor, currentColor) center/16px 2px no-repeat,
    linear-gradient(currentColor, currentColor) center/2px 16px no-repeat;
  color: var(--accent, #6366f1);
  transition: transform 200ms ease;
}
.faq-item[open] summary::before {
  /* Rotate so the vertical bar overlaps the horizontal — visually
     becomes a single horizontal "minus". */
  transform: translateY(-50%) rotate(45deg);
}
@media (prefers-reduced-motion: reduce) {
  .faq-item[open] summary::before { transform: translateY(-50%); }
  .faq-item[open] summary::before {
    background: linear-gradient(currentColor, currentColor) center/16px 2px no-repeat;
  }
}

.faq-item summary:hover {
  background: rgba(99, 102, 241, 0.04);
}

.faq-item__body {
  padding: 0 22px 22px 56px;
  color: var(--text-muted, #8888a8);
  line-height: 1.7;
  font-size: 0.95rem;
}
.faq-item__body a { color: var(--accent-h, #818cf8); }
@media (max-width: 480px) {
  .faq-item summary { padding: 14px 18px 14px 44px; font-size: 0.96rem; }
  .faq-item summary::before { left: 16px; }
  .faq-item__body { padding: 0 18px 18px 44px; }
}

/* ── Staggered reveal for grid cards ─────────────────────────────────
   When the parent grid is .reveal-up-children, each direct child
   gets the same animation as `.reveal-up`, with a small CSS-only
   stagger via :nth-child().  We can't use IO on the parent for the
   staggering because all children would reveal together — instead
   we use the timing variable so they cascade visually. */

.reveal-up-children > * {
  transform: none;
  transition: transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
/* Slide-only (no opacity) for the same reason as the parent
   `.reveal-up`: keeps WCAG contrast checks happy and matches the
   crisper reveal pattern Linear / Vercel actually use. */
html.js-reveal-ready .reveal-up-children > * {
  transform: translateY(20px);
}
.reveal-up-children.is-revealed > *:nth-child(1) { transition-delay: 0ms;   }
.reveal-up-children.is-revealed > *:nth-child(2) { transition-delay: 80ms;  }
.reveal-up-children.is-revealed > *:nth-child(3) { transition-delay: 160ms; }
.reveal-up-children.is-revealed > *:nth-child(4) { transition-delay: 240ms; }
.reveal-up-children.is-revealed > *:nth-child(5) { transition-delay: 320ms; }
.reveal-up-children.is-revealed > *:nth-child(6) { transition-delay: 400ms; }
.reveal-up-children.is-revealed > *:nth-child(7) { transition-delay: 460ms; }
.reveal-up-children.is-revealed > *:nth-child(8) { transition-delay: 520ms; }
.reveal-up-children.is-revealed > *:nth-child(n+9) { transition-delay: 580ms; }
.reveal-up-children.is-revealed > * {
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .reveal-up-children > *,
  html.js-reveal-ready .reveal-up-children > * {
    transform: none;
    transition: none;
  }
}
