/* Exploit Hound marketing site
   One stylesheet, no external requests, no webfonts: the site must load fast
   and work on a server with no outbound connectivity. */

:root {
  --bg: #0b1020;
  --bg-soft: #121a33;
  --bg-card: #16203d;
  --line: #24325a;
  --text: #e8edf9;
  --muted: #a5b1cd;
  --accent: #4f8cff;
  --accent-soft: rgba(79, 140, 255, 0.14);
  --danger: #ff6b6b;
  --warn: #ffb347;
  --ok: #4ade80;
  --radius: 14px;
  --max: 1120px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 20px; }

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(11, 16, 32, 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 64px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--text);
}
.brand:hover { text-decoration: none; }
.brand .mark {
  /* The hound, cropped to head and shoulders. The full-body logo turns to
     mush below about 40px, and this sits at 32px. Served at 96px so it stays
     sharp on high-density displays. */
  width: 32px; height: 32px;
  background: url("/assets/hound-mark.png") center / contain no-repeat;
  display: inline-block;
  flex: none;
}




.nav-links { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.nav-links a {
  color: var(--muted);
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 0.94rem;
}
.nav-links a:hover { color: var(--text); background: var(--bg-soft); text-decoration: none; }
.nav-links a[aria-current="page"] { color: var(--text); background: var(--bg-soft); }

.dropdown { position: relative; }
.dropdown > button {
  background: none; border: 0; cursor: pointer;
  color: var(--muted); font: inherit; font-size: 0.94rem;
  padding: 8px 12px; border-radius: 8px;
}
.dropdown > button:hover { color: var(--text); background: var(--bg-soft); }
.dropdown-menu {
  position: absolute; top: 100%; left: 0; min-width: 250px;
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: 12px; padding: 8px; display: none;
  box-shadow: 0 18px 40px rgba(0,0,0,0.45);
}
.dropdown:hover .dropdown-menu,
.dropdown:focus-within .dropdown-menu { display: block; }
.dropdown-menu a { display: block; padding: 9px 12px; border-radius: 8px; color: var(--text); font-size: 0.92rem; }
.dropdown-menu a:hover { background: var(--bg-soft); text-decoration: none; }
.dropdown-menu a span { display: block; color: var(--muted); font-size: 0.8rem; }

.btn {
  display: inline-block;
  padding: 11px 20px;
  border-radius: 10px;
  font-weight: 600;
  font-size: 0.95rem;
  border: 1px solid transparent;
  cursor: pointer;
}
.btn-primary { background: var(--accent); color: #06122b; }
.btn-primary:hover { background: #6ea0ff; text-decoration: none; }
.btn-ghost { border-color: var(--line); color: var(--text); }
.btn-ghost:hover { background: var(--bg-soft); text-decoration: none; }

/* ---------- sections ---------- */

section { padding: 72px 0; border-top: 1px solid transparent; }
section + section { border-top-color: var(--line); }

.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--accent);
  margin: 0 0 12px;
}

h1 { font-size: clamp(2.1rem, 5vw, 3.3rem); line-height: 1.1; margin: 0 0 20px; letter-spacing: -0.02em; }
h2 { font-size: clamp(1.6rem, 3.4vw, 2.2rem); line-height: 1.2; margin: 0 0 16px; letter-spacing: -0.01em; }
h3 { font-size: 1.12rem; margin: 0 0 8px; }
p { margin: 0 0 16px; color: var(--muted); }
p.lead { font-size: 1.12rem; color: var(--text); max-width: 62ch; }

.hero { padding: 96px 0 80px; }
.hero h1 span { display: block; }
.hero h1 .l2 { color: var(--muted); }
.hero h1 .l3 { color: var(--accent); }
.hero-actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 28px; }
.hero-note { font-size: 0.86rem; color: var(--muted); margin-top: 18px; }

.grid { display: grid; gap: 20px; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

.card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px;
}
.card h3 { color: var(--text); }
.card p:last-child { margin-bottom: 0; }

/* ---------- the five-step story ---------- */

.story { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.story-step {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  position: relative;
}
.story-step .n {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--accent);
  letter-spacing: 0.1em;
}
.story-step h3 { margin-top: 6px; letter-spacing: 0.04em; }
.story-step ul { margin: 0; padding-left: 18px; color: var(--muted); font-size: 0.9rem; }
.story-step li { margin-bottom: 3px; }

/* ---------- fix first illustration ---------- */

.demo {
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
}
.demo-label {
  font-family: var(--mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  margin-bottom: 14px;
}
.fix-row {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  padding: 13px 14px;
  border-radius: 10px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  margin-bottom: 10px;
}
.fix-row:last-child { margin-bottom: 0; }
.fix-row .what { font-weight: 600; font-size: 0.95rem; }
.fix-row .impact {
  font-family: var(--mono);
  font-size: 0.85rem;
  color: var(--warn);
  white-space: nowrap;
}
.disclaimer {
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 14px;
  font-style: italic;
}

/* ---------- attack path chain ---------- */

.chain { list-style: none; margin: 0; padding: 0; }
.chain li {
  position: relative;
  padding: 0 0 26px 26px;
  border-left: 2px solid var(--line);
}
.chain li:last-child { padding-bottom: 0; border-left-color: transparent; }
.chain li::before {
  content: "";
  position: absolute; left: -7px; top: 4px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--accent);
}
.chain li:last-child::before { background: var(--danger); }
.chain .node { font-weight: 600; }
.chain .edge { font-size: 0.84rem; color: var(--muted); font-family: var(--mono); }

/* ---------- badges ---------- */

.badge {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.badge-potential { background: rgba(165,177,205,0.16); color: var(--muted); }
.badge-high { background: rgba(79,140,255,0.18); color: #9dbcff; }
.badge-validated { background: rgba(74,222,128,0.16); color: var(--ok); }
.badge-roadmap { background: rgba(255,179,71,0.16); color: var(--warn); }

.signal-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.signal-list li {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 0.88rem;
  color: var(--text);
}

/* ---------- tables ---------- */

.table-scroll { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 0.92rem; min-width: 640px; }
th, td { text-align: left; padding: 11px 12px; border-bottom: 1px solid var(--line); }
th { color: var(--text); font-weight: 600; }
td { color: var(--muted); }
td.yes { color: var(--ok); }
td.no { color: var(--muted); }
td.unverified { color: var(--warn); }

/* ---------- cta ---------- */

.cta {
  background: linear-gradient(135deg, var(--bg-soft), var(--bg-card));
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 44px;
  text-align: center;
}
.cta h2 { margin-bottom: 12px; }
.cta .hero-actions { justify-content: center; }

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--line);
  padding: 44px 0 60px;
  color: var(--muted);
  font-size: 0.9rem;
}
.footer-grid { display: grid; gap: 28px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.footer-grid h4 { margin: 0 0 10px; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text); }
.footer-grid ul { list-style: none; margin: 0; padding: 0; }
.footer-grid li { margin-bottom: 7px; }
.footer-bottom { margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--line); }

/* ---------- floating version badge ---------- */

/* Pinned bottom-right on every page. Collapsed it is a small pill; hover or
   keyboard focus expands it to name the product. Kept out of the tab order's
   way and out of the footer's way, and it never covers page content because it
   sits in its own corner with a viewport-relative max width. */
.version-badge {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 60;
  font-size: 0.78rem;
  line-height: 1;
}

.version-badge a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: calc(100vw - 32px);
  padding: 9px 13px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(18, 26, 51, 0.86);
  backdrop-filter: blur(8px);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
  transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
  overflow: hidden;
  white-space: nowrap;
}

.version-badge a:hover,
.version-badge a:focus-visible {
  color: var(--text);
  border-color: var(--accent);
  background: rgba(22, 32, 61, 0.96);
  text-decoration: none;
}

.version-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ok);
  flex: none;
}

.version-number { font-weight: 600; }

/* The detail text is collapsed to zero width and revealed on interaction, so
   the resting state stays unobtrusive. max-width rather than display:none so it
   animates and so screen readers still reach it. */
.version-detail {
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-width 0.28s ease, opacity 0.18s ease;
}

.version-badge a:hover .version-detail,
.version-badge a:focus-visible .version-detail {
  max-width: 46ch;
  opacity: 1;
}

@media (max-width: 640px) {
  .version-badge { right: 10px; bottom: 10px; font-size: 0.72rem; }
  /* On a small screen the expanded text would cover the page, so the pill
     stays collapsed and the number alone is the information. */
  .version-badge a:hover .version-detail,
  .version-badge a:focus-visible .version-detail { max-width: 0; opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .version-badge a,
  .version-detail { transition: none; }
}

.skip-link {
  position: absolute; left: -9999px;
  background: var(--accent); color: #06122b; padding: 10px 16px; border-radius: 8px;
}
.skip-link:focus { left: 12px; top: 12px; z-index: 100; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 820px) {
  .nav { flex-wrap: wrap; padding: 10px 0; }
  .nav-links { order: 3; width: 100%; }
  section { padding: 56px 0; }
  .cta { padding: 32px 22px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ==========================================================================
   Product showcase
   ==========================================================================
   The site sells a visual platform, so it has to show one. These mockups are
   built from real markup rather than screenshots: they stay sharp at any
   resolution, reflow on a phone, are readable by a screen reader, cost no
   extra requests under the `default-src 'self'` CSP, and cannot leak customer
   data because there is none in them. Every value shown is synthetic.
   ========================================================================== */

.app-frame {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-soft);
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
}

.app-frame-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: rgba(9, 13, 27, 0.75);
  border-bottom: 1px solid var(--line);
}

.app-frame-dots { display: flex; gap: 6px; flex: none; }
.app-frame-dots span {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--line);
}

.app-frame-title {
  font-size: 0.78rem;
  color: var(--muted);
  font-family: var(--mono);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.app-frame-body { padding: 18px; }

/* ---------- metric tiles ---------- */

.metric-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  gap: 12px;
}

.metric {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
}

.metric-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

.metric-value {
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
  margin-top: 2px;
}

.metric-value.is-danger { color: var(--danger); }
.metric-value.is-warn { color: var(--warn); }
.metric-value.is-ok { color: var(--ok); }

.metric-delta { font-size: 0.75rem; color: var(--muted); }
.metric-delta.is-ok { color: var(--ok); }

/* ---------- risk card ----------
   Reused on the marketing site and intended to match the console's own card,
   so the site shows the thing the product actually renders. */

.risk-card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-left: 3px solid var(--danger);
  border-radius: 10px;
  padding: 14px 16px;
}

.risk-card.is-high { border-left-color: var(--warn); }
.risk-card.is-moderate { border-left-color: var(--accent); }

.risk-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.risk-band {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--danger);
}
.risk-card.is-high .risk-band { color: var(--warn); }
.risk-card.is-moderate .risk-band { color: var(--accent); }

.risk-score {
  font-size: 1.6rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.risk-score small { font-size: 0.8rem; font-weight: 500; color: var(--muted); }

.risk-cve {
  font-family: var(--mono);
  font-size: 0.9rem;
  margin: 6px 0 10px;
}

/* The factor list is the point: the score is a sum of named reasons, so the
   marketing site shows the arithmetic rather than a mysterious number. */
.risk-factors { list-style: none; margin: 0; padding: 0; }
.risk-factors li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 0.83rem;
  padding: 3px 0;
  border-bottom: 1px dashed rgba(36, 50, 90, 0.6);
}
.risk-factors li:last-child { border-bottom: 0; }
.risk-factors .pts {
  font-family: var(--mono);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  flex: none;
}

/* ---------- rows / tables inside mockups ---------- */

.mock-rows { display: grid; gap: 8px; }

.mock-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 12px;
  align-items: center;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 0.85rem;
}

.mock-row-main { min-width: 0; }
.mock-row-title { font-weight: 600; }
.mock-row-sub { color: var(--muted); font-size: 0.78rem; }

.pill {
  display: inline-block;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 7px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--muted);
  white-space: nowrap;
}
.pill.is-danger { color: var(--danger); border-color: rgba(255, 107, 107, 0.4); background: rgba(255, 107, 107, 0.1); }
.pill.is-warn { color: var(--warn); border-color: rgba(255, 179, 71, 0.4); background: rgba(255, 179, 71, 0.1); }
.pill.is-ok { color: var(--ok); border-color: rgba(74, 222, 128, 0.4); background: rgba(74, 222, 128, 0.1); }
.pill.is-accent { color: var(--accent); border-color: rgba(79, 140, 255, 0.4); background: var(--accent-soft); }

/* ---------- attack path chain ---------- */

.path-chain {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
}

.path-node {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px 11px;
  font-family: var(--mono);
  white-space: nowrap;
}
.path-node.is-entry { border-color: rgba(255, 107, 107, 0.5); color: var(--danger); }
.path-node.is-target { border-color: rgba(255, 179, 71, 0.55); color: var(--warn); }

.path-arrow { color: var(--muted); flex: none; }

/* ---------- trend bars ---------- */

.trend {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  height: 96px;
  padding-top: 8px;
}
.trend-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.trend-bar {
  width: 100%;
  border-radius: 5px 5px 0 0;
  background: linear-gradient(180deg, var(--accent), rgba(79, 140, 255, 0.35));
  /* Height is set per column inline; the value is also written in the label
     beneath, so the chart is not the only way to read the number. */
}
.trend-label { font-size: 0.7rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   "See Exploit Hound in action" — stepper
   ========================================================================== */

.stepper { display: grid; grid-template-columns: 300px 1fr; gap: 28px; align-items: start; }

.step-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }

.step-btn {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: border-color 0.18s ease, background 0.18s ease;
}
.step-btn:hover { border-color: var(--accent); }
.step-btn[aria-selected="true"] {
  border-left-color: var(--accent);
  background: var(--accent-soft);
}
.step-num {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--accent);
  letter-spacing: 0.1em;
}
.step-name { font-weight: 700; display: block; }
.step-detail { font-size: 0.8rem; color: var(--muted); display: block; margin-top: 2px; }

/* Without JavaScript every panel stays visible, so the section still explains
   the workflow -- it simply reads as a list rather than a stepper. */
.step-panel[hidden] { display: none; }

@media (max-width: 860px) {
  .stepper { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Capability strip
   ========================================================================== */

.cap-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 26px;
}
.cap-strip span {
  border: 1px solid var(--line);
  background: rgba(18, 26, 51, 0.6);
  border-radius: 999px;
  padding: 7px 13px;
  font-size: 0.82rem;
  color: var(--muted);
}

/* ==========================================================================
   Motion
   ==========================================================================
   Everything above is static by default. The only motion is a short fade when
   a stepper panel changes, and it is removed entirely under reduced-motion. */

.step-panel { animation: panel-in 0.22s ease both; }

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

@media (prefers-reduced-motion: reduce) {
  .step-panel { animation: none; }
  .step-btn { transition: none; }
  html { scroll-behavior: auto; }
}

/* ==========================================================================
   Utilities
   ==========================================================================
   These exist because the site sets `style-src 'self'` with no 'unsafe-inline'.
   A style="" attribute is inline style and the browser blocks it, so spacing
   that used to live in attributes lives here instead. Weakening the CSP to
   allow inline styles would have been the easier fix and the wrong one: the
   same relaxation that permits a margin also permits an injected style.
   ========================================================================== */

.m-0 { margin: 0; }
.mx-auto { margin-left: auto; margin-right: auto; }
.mt-20 { margin-top: 20px; }
.mt-24 { margin-top: 24px; }
.mt-28 { margin-top: 28px; }
.mt-32 { margin-top: 32px; }
.my-20 { margin: 20px 0; }
.my-20-26 { margin: 20px 0 26px; }
.items-start { align-items: start; }
.row-wrap { display: flex; gap: 8px; flex-wrap: wrap; }
.h1-lg { font-size: clamp(2rem, 4vw, 2.8rem); }
.hero-sm { padding: 72px 0 48px; }

/* Trend bar heights. Same reason: a per-column height cannot be an inline
   style, so the fixed set of heights the mockups use are named here. */
.bar-10 { height: 10%; } .bar-20 { height: 20%; } .bar-30 { height: 30%; }
.bar-40 { height: 40%; } .bar-50 { height: 50%; } .bar-60 { height: 60%; }
.bar-70 { height: 70%; } .bar-80 { height: 80%; } .bar-90 { height: 90%; }
.bar-100 { height: 100%; }




/* ==========================================================================
   Intro splash
   ==========================================================================
   Injected by /assets/site.js on first arrival in a session, never present in
   the HTML. Styles live here so the animation is declarative and so a visitor
   who blocks scripts is never left with an overlay nothing can remove.
   ========================================================================== */

.intro {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  background: radial-gradient(120% 90% at 50% 40%, #16203d 0%, var(--bg) 62%);
  animation: intro-in 0.42s ease both;
}

.intro.is-leaving {
  animation: intro-out 0.6s ease both;
  pointer-events: none;
}

.intro-art {
  width: min(340px, 62vw);
  height: auto;
  animation: intro-art 1.5s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

.intro-word {
  font-size: clamp(1.25rem, 3.4vw, 1.9rem);
  font-weight: 800;
  letter-spacing: 0.03em;
  color: var(--text);
  animation: intro-word 1.5s ease both 0.24s;
}

/* The sweep: a single accent line crossing the hound once, standing in for a
   scan pass. One pass only -- a looping effect reads as a stuck page. */
.intro-scan {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  opacity: 0;
  animation: intro-scan 1.35s ease-in-out both 0.18s;
}

/* While the overlay is up the page behind must not scroll. */
.intro-active, .intro-active body { overflow: hidden; }

@keyframes intro-in   { from { opacity: 0; } to { opacity: 1; } }
@keyframes intro-out  { from { opacity: 1; } to { opacity: 0; visibility: hidden; } }
@keyframes intro-art  {
  0%   { opacity: 0; transform: translateY(14px) scale(0.94); }
  55%  { opacity: 1; transform: none; }
  100% { opacity: 1; transform: none; }
}
@keyframes intro-word {
  0%   { opacity: 0; transform: translateY(8px); }
  60%  { opacity: 1; transform: none; }
  100% { opacity: 1; transform: none; }
}
@keyframes intro-scan {
  0%   { opacity: 0; transform: translateY(-70px); }
  20%  { opacity: 0.9; }
  80%  { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(70px); }
}

/* Reduced motion: the splash still appears, because the preference asks for
   less movement rather than for a blank screen where the brand should be. It
   simply holds still -- no entrance transform, no sweep -- and clears sooner.
   site.js also omits the sweep element entirely in this case. */
.intro-static,
.intro-static .intro-art,
.intro-static .intro-word { animation: none; opacity: 1; transform: none; }

.intro-static.is-leaving { animation: intro-out 0.3s ease both; }

@media (prefers-reduced-motion: reduce) {
  .intro, .intro-art, .intro-word { animation: none; opacity: 1; transform: none; }
  .intro-scan { display: none; }
  .intro.is-leaving { animation: intro-out 0.3s ease both; }
}

/* ==========================================================================
   Annotated product shots
   ==========================================================================
   Callouts are HTML positioned over the image, not burned into it. That keeps
   them real text -- readable by a screen reader, translatable, restyleable, and
   correctable without re-exporting a screenshot. Percentage coordinates mean
   they track the image as it scales.
   ========================================================================== */

.shot {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-soft);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.4);
}

.shot img { display: block; width: 100%; height: auto; }

.shot-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 13px;
  background: rgba(9, 13, 27, 0.8);
  border-bottom: 1px solid var(--line);
}
.shot-bar span.dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line); flex: none; }
.shot-bar .path {
  font-family: var(--mono); font-size: 0.74rem; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* A numbered marker pinned to a point in the interface. */
.pin {
  position: absolute;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--accent);
  color: #06122b;
  font-weight: 800;
  font-size: 0.82rem;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 4px rgba(79, 140, 255, 0.25);
  transform: translate(-50%, -50%);
}

/* The matching explanation, listed beneath the image rather than floated over
   it: overlaid text is unreadable on a phone and covers the thing it explains. */
.shot-notes { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 10px; }
.shot-notes li { display: grid; grid-template-columns: 26px 1fr; gap: 12px; align-items: start; }
.shot-notes .n {
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid rgba(79, 140, 255, 0.45);
  font-weight: 800; font-size: 0.8rem;
  display: flex; align-items: center; justify-content: center;
}
.shot-notes p { margin: 2px 0 0; font-size: 0.92rem; }
.shot-notes strong { display: block; }

.tour-step { display: grid; grid-template-columns: 1fr 1fr; gap: 34px; align-items: start; }
.tour-step.flip > .tour-visual { order: -1; }

@media (max-width: 900px) {
  .tour-step { grid-template-columns: 1fr; gap: 22px; }
  .tour-step.flip > .tour-visual { order: 0; }
  /* Pins are meaningless at phone width -- the notes below carry the same
     information in reading order. */
  .pin { display: none; }
}

.tour-index { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px; }
.tour-index a {
  border: 1px solid var(--line); border-radius: 999px;
  padding: 7px 13px; font-size: 0.85rem; color: var(--muted);
}
.tour-index a:hover { border-color: var(--accent); color: var(--text); text-decoration: none; }

/* Callout positions, generated per tour step. */
.pin-overview-1{left:22%;top:33%}
.pin-overview-2{left:50%;top:33%}
.pin-overview-3{left:78%;top:33%}
.pin-discover-1{left:62%;top:40%}
.pin-discover-2{left:76%;top:44%}
.pin-discover-3{left:36%;top:40%}
.pin-identify-1{left:20%;top:45%}
.pin-identify-2{left:46%;top:45%}
.pin-paths-1{left:14%;top:33%}
.pin-paths-2{left:20%;top:62%}
.pin-paths-3{left:82%;top:60%}
.pin-fix-1{left:18%;top:33%}
.pin-fix-2{left:30%;top:49%}
.pin-fix-3{left:88%;top:47%}
.pin-verify-1{left:24%;top:30%}
.pin-verify-2{left:40%;top:52%}
.pin-msp-1{left:30%;top:40%}
.pin-msp-2{left:70%;top:40%}


/* ---------- walkthrough video ----------
   Self-hosted so it stays inside `default-src 'self'`. Not autoplaying and not
   looping: a video that starts by itself is an obstacle on a page someone came
   to read, and `preload="none"` means the 1.3 MB is only fetched if the visitor
   actually presses play. */
.video-frame {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: #000;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.4);
}
.video-frame video { display: block; width: 100%; height: auto; }
.video-meta { color: var(--muted); font-size: 0.86rem; margin-top: 10px; }

/* The Fix First illustrative rows hold two long strings in a two-column flex,
   and overflowed the page at 390px and again at 768px -- where the row sits
   inside a narrow grid column, so the viewport width says nothing useful about
   the space available. Wrapping on the row's own constraints fixes it at every
   width instead of chasing breakpoints. min-width:0 is required or the flex
   items refuse to shrink below their content. */
.fix-row { flex-wrap: wrap; }
.fix-row .what { min-width: 0; }
.fix-row .impact { min-width: 0; }

/* The nav bar has to hold two dropdowns plus five links and a button without
   wrapping to a second row, which pushed the header to 85px on every desktop
   width. Tighter horizontal padding and a slightly smaller label buy the room
   without shrinking the tap targets vertically. */
@media (min-width: 981px) {
  .nav-links { gap: 2px; }
  .nav-links a, .dropdown > button { padding-left: 9px; padding-right: 9px; font-size: 0.9rem; }
}

@media (min-width: 981px) and (max-width: 1179px) {
  .nav-links a[href="/resources/"] { display: none; }
  .nav-links a, .dropdown > button { padding-left: 7px; padding-right: 7px; font-size: 0.86rem; }
  .site-header .btn-primary { padding-left: 14px; padding-right: 14px; font-size: 0.88rem; }
}

/* ---------- "See it in action" stepper ----------
   Real screenshots, one per stage, with the stage list as tabs. Without
   JavaScript every panel renders in sequence, so the section still reads as a
   five-step walkthrough -- it simply scrolls instead of switching. */
.act { display: grid; grid-template-columns: 260px 1fr; gap: 30px; align-items: start; }
.act-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.act-btn {
  display: block; width: 100%; text-align: left;
  background: transparent; border: 1px solid transparent; border-left: 2px solid var(--line);
  border-radius: 0 10px 10px 0; padding: 11px 14px; color: var(--muted);
  font: inherit; cursor: pointer; transition: color .18s ease, border-color .18s ease, background .18s ease;
}
.act-btn:hover { color: var(--text); border-left-color: var(--accent); }
.act-btn[aria-selected="true"] {
  color: var(--text); border-left-color: var(--accent);
  background: linear-gradient(90deg, var(--accent-soft), transparent);
}
.act-btn .k { display: block; font-family: var(--mono); font-size: .7rem; color: var(--accent); letter-spacing: .1em; }
.act-btn .t { font-weight: 700; }
.act-btn .d { display: block; font-size: .82rem; color: var(--muted); margin-top: 2px; }
.act-panel[hidden] { display: none; }
.act-panel { animation: act-in .2s ease both; }
@keyframes act-in { from { opacity: 0 } to { opacity: 1 } }
@media (max-width: 900px) { .act { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) { .act-panel { animation: none } .act-btn { transition: none } }

/* ---------- Fix First feature component ----------
   Deliberately mirrors the console's own card so the marketing page and the
   product do not look like two different products. The #1 action is given the
   weight; runners-up are compact, because the whole claim is that one action
   matters more than the rest. */
.ff { display: grid; gap: 14px; }

.ff-hero {
  display: grid; grid-template-columns: auto 1fr; gap: 22px;
  background: linear-gradient(180deg, rgba(22,32,61,.95), var(--bg-card));
  border: 1px solid var(--line); border-left: 3px solid var(--danger);
  border-radius: 14px; padding: 20px 22px;
}
.ff-rank { font-family: var(--mono); font-size: .78rem; color: var(--muted); letter-spacing: .12em; }
.ff-title { font-size: 1.28rem; font-weight: 800; line-height: 1.25; margin: 2px 0 4px; }
.ff-sub { color: var(--muted); font-size: .88rem; margin: 0; }

.ff-score { text-align: center; min-width: 108px; }
.ff-score .v { font-size: 2.9rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; color: var(--danger); }
.ff-score .o { color: var(--muted); font-size: .95rem; font-weight: 500; }
.ff-score .band {
  display: inline-block; margin-top: 6px; font-size: .64rem; font-weight: 800;
  letter-spacing: .12em; text-transform: uppercase; color: var(--danger);
  border: 1px solid rgba(255,107,107,.4); background: rgba(255,107,107,.1);
  border-radius: 999px; padding: 3px 9px;
}

.ff-metrics { display: grid; grid-template-columns: repeat(auto-fit,minmax(120px,1fr)); gap: 12px; margin-top: 16px; }
.ff-metric { background: rgba(11,16,32,.5); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; }
.ff-metric .n { font-size: 1.5rem; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.ff-metric .l { font-size: .72rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }

.ff-why { margin-top: 16px; }
.ff-why h4 { font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin: 0 0 8px; }

.ff-row {
  display: grid; grid-template-columns: auto 1fr auto; gap: 16px; align-items: center;
  background: var(--bg-card); border: 1px solid var(--line);
  border-left: 3px solid var(--warn); border-radius: 11px; padding: 13px 16px;
}
.ff-row.is-moderate { border-left-color: var(--accent); }
.ff-row .r { font-family: var(--mono); font-size: .78rem; color: var(--muted); }
.ff-row .t { font-weight: 650; font-size: .96rem; }
.ff-row .m { color: var(--muted); font-size: .8rem; }
.ff-row .s { font-size: 1.3rem; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--warn); }
.ff-row.is-moderate .s { color: var(--accent); }

@media (max-width: 720px) {
  .ff-hero { grid-template-columns: 1fr; gap: 14px; }
  .ff-score { text-align: left; display: flex; align-items: baseline; gap: 10px; }
  .ff-score .band { margin-top: 0; }
  .ff-row { grid-template-columns: 1fr auto; }
  .ff-row .r { grid-column: 1 / -1; }
}

/* The header CTA was 239px of the 1120px bar -- more than the brand and a fifth
   of the whole header. The label stays "Start Finding Exposure" for consistency
   with every other primary CTA; only this instance is set tighter, which buys
   back roughly 60px without introducing a fourth wording. */
@media (min-width: 981px) {
  .site-header .btn-primary {
    padding: 9px 15px;
    font-size: 0.88rem;
    white-space: nowrap;
  }
  .brand { font-size: 1rem; }
}

/* ==========================================================================
   Attack path graph
   ==========================================================================
   Restrained on purpose. Node meaning is carried by shape and by a written
   label, never by color alone -- a graph where "critical" is only red is
   unreadable to a chunk of the audience and unusable in print.
   ========================================================================== */

.apg { display: grid; grid-template-columns: 1.15fr 1fr; gap: 30px; align-items: start; }

.apg-canvas {
  background: linear-gradient(180deg, rgba(18,26,51,.9), var(--bg-soft));
  border: 1px solid var(--line); border-radius: var(--radius); padding: 12px;
}
.apg-canvas svg { display: block; width: 100%; height: auto; }

/* Node fills stay near the surface color; the border carries the type. */
.apg-node rect { fill: var(--bg-card); stroke: var(--line); stroke-width: 1.5; }
.apg-node.is-entry rect { stroke: var(--danger); }
.apg-node.is-vuln  rect { stroke: var(--warn); stroke-dasharray: 4 3; }
.apg-node.is-ident rect { stroke: var(--accent); stroke-dasharray: 4 3; }
.apg-node.is-crit  rect { stroke: var(--warn); stroke-width: 2.5; }
.apg-node text { fill: var(--text); font-family: var(--mono); font-size: 12px; }
.apg-node .sub { fill: var(--muted); font-size: 10px; font-family: var(--font); }

.apg-node { cursor: pointer; }
.apg-node:hover rect, .apg-node:focus-visible rect { stroke-width: 2.5; }
.apg-node:focus-visible { outline: none; }
.apg-node:focus-visible rect { stroke: var(--accent); }
.apg-node[aria-pressed="true"] rect { fill: rgba(79,140,255,.14); stroke: var(--accent); }

.apg-edge { stroke: var(--line); stroke-width: 1.5; fill: none; }
.apg-edge.is-observed { stroke: var(--accent); }
.apg-edge-label { fill: var(--muted); font-size: 10px; font-family: var(--font); }

/* Evidence panel: the claim is that edges are evidence-backed, so the evidence
   has to be visible rather than implied. */
.apg-ev { background: var(--bg-card); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px 20px; }
.apg-ev h4 { margin: 0 0 4px; font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.apg-ev .subject { font-weight: 800; font-size: 1.05rem; margin: 0 0 12px; font-family: var(--mono); }
.apg-ev dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 0; font-size: .88rem; }
.apg-ev dt { color: var(--muted); }
.apg-ev dd { margin: 0; }
.apg-ev .hint { color: var(--muted); font-size: .84rem; }

.apg-legend { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 14px; font-size: .8rem; color: var(--muted); }
.apg-legend span { display: inline-flex; align-items: center; gap: 6px; }
.apg-legend i { width: 13px; height: 13px; border: 1.5px solid var(--line); border-radius: 3px; display: inline-block; }
.apg-legend i.entry { border-color: var(--danger); }
.apg-legend i.vuln { border-color: var(--warn); border-style: dashed; }
.apg-legend i.ident { border-color: var(--accent); border-style: dashed; }
.apg-legend i.crit { border-color: var(--warn); border-width: 2.5px; }

/* The written path. Always present -- it is the accessible equivalent of the
   diagram and what a phone gets instead of a cramped graph. */
.apg-text { margin-top: 18px; font-size: .9rem; }
.apg-text ol { margin: 8px 0 0; padding-left: 20px; }
.apg-text li { margin-bottom: 5px; }

@media (max-width: 940px) {
  .apg { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .apg-node, .apg-node rect { transition: none; }
}

/* `display: grid` on the evidence list beats the hidden attribute's
   `display: none`, so the empty list rendered before anything was selected.
   The attribute has to win. */
.apg-ev dl[hidden] { display: none; }

/* ---------- explainable risk score ----------
   The claim is that the score is a sum of named factors rather than a black
   box, so the component shows the arithmetic: each factor's contribution as a
   proportional bar, and a total line that visibly adds up. */
.rsk { display: grid; grid-template-columns: 240px 1fr; gap: 30px; align-items: start; }

.rsk-dial {
  background: linear-gradient(180deg, rgba(22,32,61,.95), var(--bg-card));
  border: 1px solid var(--line); border-left: 3px solid var(--danger);
  border-radius: 14px; padding: 22px; text-align: center;
}
.rsk-dial .lab { font-size: .68rem; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.rsk-dial .v { font-size: 3.6rem; font-weight: 800; line-height: 1; color: var(--danger); font-variant-numeric: tabular-nums; }
.rsk-dial .v small { font-size: 1.1rem; font-weight: 500; color: var(--muted); }
.rsk-dial .band {
  display: inline-block; margin-top: 10px; font-size: .66rem; font-weight: 800;
  letter-spacing: .12em; text-transform: uppercase; color: var(--danger);
  border: 1px solid rgba(255,107,107,.4); background: rgba(255,107,107,.1);
  border-radius: 999px; padding: 4px 11px;
}
.rsk-dial .ver { margin-top: 12px; font-size: .72rem; color: var(--muted); font-family: var(--mono); }

.rsk-factors { display: grid; gap: 9px; }
.rsk-f { display: grid; grid-template-columns: 1fr 62px; gap: 14px; align-items: center; }
.rsk-f .n { font-size: .9rem; }
.rsk-f .bar { height: 7px; border-radius: 4px; background: rgba(79,140,255,.16); margin-top: 5px; overflow: hidden; }
.rsk-f .bar i { display: block; height: 100%; border-radius: 4px; background: var(--accent); }
.rsk-f .p { font-family: var(--mono); font-weight: 700; text-align: right; color: var(--accent); font-variant-numeric: tabular-nums; }
/* Contribution widths. Named rather than inline so the CSP holds. */
.w20 { width: 100% } .w18 { width: 90% } .w15 { width: 75% }
.w12 { width: 60% } .w11 { width: 55% }

.rsk-total {
  display: grid; grid-template-columns: 1fr 62px; gap: 14px;
  border-top: 1px solid var(--line); margin-top: 6px; padding-top: 11px;
  font-weight: 800;
}
.rsk-total .p { font-family: var(--mono); text-align: right; color: var(--danger); }

@media (max-width: 820px) { .rsk { grid-template-columns: 1fr; } }

/* ---------- product montage ----------
   Three real console views, overlapped. Offset and depth only -- no rotation,
   because a tilted screenshot of a data-dense interface stops being legible and
   the whole point is that these are readable real screens. */
.mont { position: relative; height: 520px; margin-top: 30px; }

.mont figure {
  position: absolute; margin: 0;
  border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
  background: var(--bg-soft); box-shadow: 0 26px 60px rgba(0,0,0,.55);
  transition: transform .2s ease, box-shadow .2s ease;
}
.mont figure img { display: block; width: 100%; height: auto; }
.mont figcaption {
  position: absolute; left: 0; top: 0; right: 0;
  background: linear-gradient(180deg, rgba(9,13,27,.94), transparent);
  color: var(--text); font-size: .76rem; padding: 8px 12px 20px;
  font-family: var(--mono); letter-spacing: .06em;
}

/* Back to front. The most distinctive screen sits on top. */
.mont .m1 { width: 50%; left: 0;    top: 0;    z-index: 1; }
.mont .m2 { width: 50%; right: 0;   top: 34px; z-index: 2; }
.mont .m3 { width: 52%; left: 24%;  bottom: 0; z-index: 3; }

.mont figure:hover, .mont figure:focus-within { transform: translateY(-4px); z-index: 4; }

.mont-labels {
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 26px;
}
.mont-labels span {
  border: 1px solid var(--line); border-radius: 999px; padding: 6px 13px;
  font-size: .74rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}

@media (max-width: 900px) {
  /* Overlap needs room. Below this the frames stack and each is readable at
     full width, which matters more than the collage effect. */
  .mont { height: auto; display: grid; gap: 16px; }
  .mont figure { position: static; width: 100%; }
  .mont figure:hover { transform: none; }
}
@media (prefers-reduced-motion: reduce) { .mont figure { transition: none; } }

/* ---------- remediation lifecycle ----------
   States are the product's own LifecycleStatus values, not a prettier invented
   sequence, so the page cannot drift from what the console actually shows. */
.life { display: flex; flex-wrap: wrap; align-items: stretch; gap: 8px; margin-top: 26px; }

.life-step {
  flex: 1 1 118px; min-width: 0;
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: 10px; padding: 11px 12px;
}
.life-step .k { font-family: var(--mono); font-size: .64rem; color: var(--muted); letter-spacing: .1em; }
.life-step .s { font-weight: 700; font-size: .84rem; margin-top: 2px; }
.life-step .w { font-size: .72rem; color: var(--muted); margin-top: 3px; }

/* The last two are what the section is about: the product does not stop at
   "someone said they fixed it". */
.life-step.is-check { border-color: rgba(79,140,255,.5); }
.life-step.is-done { border-color: rgba(74,222,128,.55); background: rgba(74,222,128,.07); }
.life-step.is-done .s { color: var(--ok); }

.ba { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 22px; }
.ba-card { border: 1px solid var(--line); border-radius: 12px; padding: 16px 18px; background: var(--bg-card); }
.ba-card h4 { margin: 0 0 10px; font-size: .68rem; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.ba-card ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; font-size: .88rem; }
.ba-card li::before { content: "— "; color: var(--muted); }
.ba-card.is-after { border-color: rgba(74,222,128,.4); }
.ba-card.is-after li::before { content: "✓ "; color: var(--ok); }

@media (max-width: 720px) { .ba { grid-template-columns: 1fr; } }

/* ==========================================================================
   Measure and rhythm
   ==========================================================================
   Measured on the rendered page rather than judged by eye: body paragraphs were
   running 128-157 characters per line at 1440px against a comfortable 60-75,
   and every section shared one transparent background so nothing separated them.
   ========================================================================== */

/* Only paragraphs that are direct children of a section's wrap. Text inside
   cards, grids and product panels is already constrained by its container, and
   capping it again would leave odd short columns. */
section > .wrap > p,
section > .wrap > .lead {
  max-width: 68ch;
}

/* The hero lead may run a little wider -- it sits alone above the fold with no
   competing column, and breaking it earlier makes the opening feel cramped. */
.hero > .wrap > .lead { max-width: 72ch; }

/* Alternating tone. A hairline and a barely-there tint, not boxes: sections
   should read as one continuous page with structure, rather than a stack of
   separate cards. */
section:nth-of-type(even) {
  background: linear-gradient(180deg, rgba(18, 26, 51, 0.38), rgba(18, 26, 51, 0));
  border-top: 1px solid rgba(36, 50, 90, 0.5);
}
section:nth-of-type(odd) { border-top: 1px solid rgba(36, 50, 90, 0.28); }
.hero { border-top: 0; }

/* Consistent vertical rhythm. 96px was applied to some sections and 72px to
   others with no rule behind which got which. */
section { padding: 88px 0; }
.hero { padding: 76px 0 60px; }
.hero-sm { padding: 72px 0 48px; }

@media (max-width: 720px) {
  section { padding: 56px 0; }
  .hero { padding: 48px 0 40px; }
}

/* Captions and disclaimers wrap to several lines, so they need a measure like
   any other prose. The other wide elements the audit flagged -- eyebrows, card
   subtitles -- are single-line labels in a wide box, where the element is wide
   but the text is not, and capping those would only create ragged columns. */
.video-meta { max-width: 78ch; }
