/* ═══════════════════════════════════════════════════════════════
   go-module.css — GENERATED SUBSET of go.css. Do not hand-edit.
   Regenerate with: python3 _internal/gen-go-module-css.py --apply

   Why this file exists: the /go conversion module and page tail are
   stamped onto the channel/*.html persona pages, which do not load
   go.css. go.css cannot be linked there because it carries page-global
   rules (body background, section h2, a:active, the whole homepage
   chrome block) that would visibly alter unrelated parts of those pages.
   This file is the block-scoped subset that is safe to load anywhere.
   ═══════════════════════════════════════════════════════════════ */

/* ── Accessibility ── */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* ── Section divider ── */
.scan-divider {
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(43, 205, 238, 0.2) 30%,
    rgba(78, 214, 214, 0.15) 70%,
    transparent
  );
  margin: 0 32px;
}
/* ── Gradient text ── */
.scan-gradient-text {
  background: linear-gradient(135deg, var(--color-fg) 0%, var(--color-primary) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
/* ── Eyebrow label (Mono — intentional, label context) ── */
.scan-eyebrow {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}
.scan-eyebrow-rule {
  display: inline-block;
  width: 22px;
  height: 2px;
  background: currentColor;
  flex-shrink: 0;
}
/* ═══════════════════════════════════════
   SCAN INPUT — shared across 3 positions
   ═══════════════════════════════════════ */
.scan-input-wrap {
  display: flex;
  align-items: stretch;
  background: rgba(22, 42, 46, 0.65);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(43, 205, 238, 0.3);
  box-shadow:
    0 0 0 4px rgba(43, 205, 238, 0.1),
    0 10px 40px rgba(0, 0, 0, 0.4);
  border-radius: 14px;
  overflow: hidden;
  max-width: 620px;
  width: 100%;
}
.scan-input-prefix {
  display: flex;
  align-items: center;
  padding-left: 18px;
  color: var(--color-primary);
  font-family: "JetBrains Mono", monospace;
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  flex-shrink: 0;
}
.scan-input-field {
  flex: 1;
  padding: 18px 12px;
  background: transparent;
  border: 0;
  outline: 0;
  font-family: "JetBrains Mono", monospace;
  font-size: 16px;
  color: var(--color-fg);
  letter-spacing: 0.01em;
  min-width: 0;
}
.scan-input-field::placeholder {
  color: rgba(255, 255, 255, 0.3);
}
.scan-input-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 26px;
  border: 0;
  cursor: pointer;
  background: linear-gradient(to right, var(--color-primary), #22d3ee);
  color: var(--color-bg-deep);
  font-family: "Inter", sans-serif;
  font-weight: 800;
  font-size: 15px;
  letter-spacing: -0.01em;
  box-shadow:
    0 4px 25px rgba(43, 205, 238, 0.4),
    0 0 60px rgba(43, 205, 238, 0.18);
  white-space: nowrap;
  flex-shrink: 0;
  transition: filter 0.2s;
}
.scan-input-btn:hover {
  filter: brightness(1.06);
}
/* ═══════════════════════════════════════
   1. HERO
   ═══════════════════════════════════════ */
.scan-hero {
  position: relative;
  /* Top 24 -> 56. The 24 was set on the theory that the tabs' own 22px of
     bottom padding covered this seam. It does not: .go-paths is STICKY, so
     once it pins it overlays this section and its padding travels with it,
     leaving the .go-proof logo strip flush against the pinned bar. 56 is
     the value this had before the tabs existed and it is the right one --
     it reads as a gap under the bar at every scroll position, not only in
     the one where the two happen to sit adjacent in flow. */
  padding: 56px 32px 60px;
  overflow: hidden;
}
.scan-hero-orb {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}
.scan-hero-orb--cyan {
  left: -8%;
  top: 5%;
  width: 560px;
  height: 560px;
  background: rgba(43, 205, 238, 0.22);
  filter: blur(180px);
}
.scan-hero-orb--teal {
  right: -10%;
  bottom: -10%;
  width: 520px;
  height: 520px;
  background: rgba(78, 214, 214, 0.16);
  filter: blur(180px);
}
.scan-hero-orb--rose {
  right: 20%;
  top: -10%;
  width: 360px;
  height: 360px;
  background: rgba(236, 85, 103, 0.1);
  filter: blur(160px);
}
.scan-hero-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(236, 85, 103, 0.1) 1px, transparent 1px),
    linear-gradient(90deg, rgba(236, 85, 103, 0.1) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(
    ellipse 80% 70% at 50% 40%,
    #000 25%,
    transparent 70%
  );
  -webkit-mask-image: radial-gradient(
    ellipse 80% 70% at 50% 40%,
    #000 25%,
    transparent 70%
  );
  animation: heroGridDrift 10s linear infinite;
}
@keyframes heroGridDrift {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 56px 56px;
  }
}
.scan-hero-inner {
  position: relative;
  max-width: 1100px;
  margin: 0 auto;
  text-align: center;
}
.scan-hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(236, 85, 103, 0.1);
  border: 1px solid rgba(236, 85, 103, 0.32);
  text-decoration: none;
  margin-bottom: 26px;
}
.scan-hero-eyebrow-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-rose);
  box-shadow: 0 0 10px var(--color-rose);
  flex-shrink: 0;
}
.scan-hero-eyebrow-text {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-rose);
}
/* The cap is measured, not chosen. The hero column tops out at 1100px and the
   second headline line renders 15.53px wide per px of font-size in English, so
   anything over 70.8px wraps it to three lines -- and the break lands on the
   hyphen inside the product name, printing "Auto-" / "Repair". 68px keeps it on
   one line at every desktop width with ~4% of slack for font-metric variance. */
.scan-h1 {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: clamp(44px, 5.4vw, 68px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin: 0;
  color: var(--color-fg);
  /* This element is an <h2> (the page's own hero owns the single <h1>), which
     puts it in reach of the unnamespaced `section h2` glow further down this
     file. That glow is tuned for body-scale section headings and reads as a
     smear at 68px, so it is refused here rather than inherited. Removing this
     line silently restyles the headline on /go the moment the tag changes. */
  text-shadow: none;
}
/* German runs 17.22px per px of font-size on that same line ("manuellen Pentest
   & Auto-Repair" against "Manual Pentest & Auto-Repair"), 11% wider, so the
   shared curve wraps it to three lines from 1280px up and again between 768 and
   900px. It gets its own curve rather than dragging the English headline down
   to fit German compounds. Bounded to >=768px so the mobile rule below -- which
   this selector would otherwise outrank on specificity -- still wins on phones. */
@media (min-width: 768px) {
  html[lang="de"] .scan-h1 {
    font-size: clamp(38px, 5.2vw, 62px);
  }
}
.scan-h1-line {
  display: block;
}
.scan-h1-strike-wrap {
  position: relative;
  display: inline-block;
}
.scan-h1-strike {
  position: absolute;
  left: -2%;
  right: -2%;
  top: 55%;
  height: 6px;
  background: var(--color-rose);
  transform: rotate(-1.5deg);
  border-radius: 4px;
  box-shadow: 0 0 14px rgba(236, 85, 103, 0.55);
  pointer-events: none;
}
.scan-h1-logo {
  height: 0.72em;
  width: auto;
  vertical-align: middle;
  margin-left: 0.18em;
  margin-bottom: 0.06em;
  display: inline-block;
}
.scan-h1-attack {
  color: var(--color-fg);
  -webkit-text-fill-color: var(--color-fg);
  position: relative;
  z-index: 1;
}
.scan-h1-attack .scan-h1-strike {
  z-index: 2;
}
/* ═══════════════════════════════════════
   1b. ICP ENTRY BLOCK  (first thing in the campaign hero)
   The hook a cold email or a social post led with, restated at the top of
   the page it lands on, with a button back to whatever that campaign was
   actually about.

   It used to be the announcement pill under the menu bar, which was the
   wrong slot twice over: too small to register as the reason the visitor
   clicked, and pinned to an on-page anchor, so a campaign could never
   send a persona to its own landing page. This block is the reason the
   pill-pinning code is gone rather than moved.

   Sized to be read before the logos and the headline -- it is the
   continuity between the message and the page, and continuity that has to
   be hunted for is not continuity. Two accents only, inherited from the
   arc the page already uses: cyan for the free surface view, rose for the
   paid proof. A third colour here would be inventing meaning the rest of
   the page does not carry.
   ═══════════════════════════════════════ */
.go-icp {
  --go-icp-accent: var(--color-primary);
  --go-icp-accent-rgb: 43, 205, 238;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 22px;
  max-width: 780px;
  margin: 0 auto 32px;
  padding: 18px 20px 18px 24px;
  text-align: left;
  border-radius: 18px;
  border: 1px solid rgba(var(--go-icp-accent-rgb), 0.42);
  background:
    linear-gradient(
      135deg,
      rgba(var(--go-icp-accent-rgb), 0.17),
      rgba(var(--go-icp-accent-rgb), 0.04)
    ),
    rgba(10, 18, 21, 0.6);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
/* .go-icp sets an author-level `display`, which beats the UA sheet's
   [hidden] rule, so the hidden state has to be declared here or the empty
   block flashes on every load before ?icp= resolves. Anonymous and
   organic traffic never sees it at all. */
.go-icp[hidden] {
  display: none;
}
.go-icp[data-approach="pentest"],
.go-icp[data-approach="autorepair"] {
  --go-icp-accent: var(--color-rose);
  --go-icp-accent-rgb: 236, 85, 103;
}
.go-icp-body {
  flex: 1 1 320px;
  min-width: 0;
}
/* Approach label: Mono, intentional — a category marker, not prose */
.go-icp-tag {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--go-icp-accent);
}
.go-icp-hook {
  margin: 7px 0 0;
  font-family: "Montserrat", sans-serif;
  font-weight: 800;
  font-size: clamp(20px, 2.3vw, 27px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-wrap: balance;
  color: var(--color-fg);
}
.go-icp-cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex-shrink: 0;
  padding: 15px 22px;
  border-radius: 12px;
  background: var(--go-icp-accent);
  color: var(--color-bg-deep);
  font-family: "Inter", sans-serif;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.01em;
  white-space: nowrap;
  text-decoration: none;
  transition: filter 0.2s;
}
.go-icp-cta:hover {
  filter: brightness(1.08);
}
.go-icp-cta-arrow {
  transition: transform 0.2s;
}
.go-icp-cta:hover .go-icp-cta-arrow {
  transform: translateX(3px);
}
.go-icp-cta:focus-visible {
  outline: 2px solid var(--color-fg);
  outline-offset: 3px;
}
/* Hero body text — Inter, matching testimonial style */
.scan-hero-sub {
  font-family: "Inter", system-ui, sans-serif;
  margin: 26px auto 0;
  max-width: 720px;
  font-size: 17px;
  line-height: 1.65;
  color: var(--color-fg-secondary);
}
.scan-input-center {
  display: flex;
  justify-content: center;
  margin-top: 36px;
}
/* Trust row: Mono label context (intentional) */
.scan-trust-row {
  margin-top: 14px;
  display: inline-flex;
  align-items: center;
  gap: 18px;
  font-family: "JetBrains Mono", monospace;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
  flex-wrap: wrap;
  justify-content: center;
}
.scan-trust-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.scan-trust-check {
  color: var(--color-success);
}
.scan-trust-sep {
  color: rgba(255, 255, 255, 0.25);
}
/* ═══════════════════════════════════════
   2. PROOF STRIP + TWO TRACKS  (campaign hero)
   The two things /go has that /scan does not, both answering what a cold
   visitor asks in the first two seconds: who else trusts this, and what
   can I actually do right now. Replaces the old .scan-trusted section,
   which /go no longer renders — its logos moved above the h1.
   ═══════════════════════════════════════ */
.go-proof {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 28px;
  flex-wrap: wrap;
  /* 30 -> 18: the strip is 22px tall and now sits 28px below the path
     tabs rather than opening the page, so it reads as attached to the
     headline underneath it instead of floating between two modules. */
  margin-bottom: 18px;
}
/* Proof label: Mono, intentional — a context label, not running text */
.go-proof-label {
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-muted);
}
/* All three logos arrive in a different colour space: bitExpert is a mid
   grey (#9CA3AF), Codeligence is near-black (#080d2b) plus a saturated
   mark, Gameforge is a full-colour PNG. The treatment inherited from
   /scan -- grayscale(1) brightness(2) -- only works on the light one; it
   maps Codeligence's near-black to roughly #1a1a1a, which is invisible on
   this ground, so the strip rendered one and a half logos. brightness(0)
   flattens any source to solid black and invert(1) lifts it to solid
   white, which is the one treatment that does not care what colour the
   file was; opacity alone then carries the wash. Gameforge keeps a lower
   opacity only because its wordmark is optically heavier at the same
   height, not because it needs a different filter. */
.go-proof-logo {
  height: 22px;
  width: auto;
  opacity: 0.55;
  filter: brightness(0) invert(1);
}
.go-proof-logo--gameforge {
  height: 20px;
  opacity: 0.42;
}
/* Two tracks, equal weight. Cyan is See, rose is Prove — the same two
   accents the arc uses everywhere else on the site, so the colour is
   carrying meaning rather than decorating a card. */
.go-tracks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  margin-top: 40px;
  text-align: left;
}
.go-track {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
  padding: 26px;
  border-radius: 16px;
  /* Dark glass, same treatment as every other raised surface on the site.
     A white-card inversion was tried here and rejected: the page is
     dark-only by brand, and two lit slabs above the fold read as a
     different site rather than as this one's two front doors. The tinted
     borders are what separate See from Prove, not the ground. */
  background: rgba(22, 42, 46, 0.5);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.go-track--see {
  border-color: rgba(43, 205, 238, 0.28);
}
.go-track--prove {
  border-color: rgba(236, 85, 103, 0.28);
}
.go-track-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}
/* Step number + meta: Mono, intentional — ordinal and unit labels */
.go-track-step {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--color-fg-muted);
}
.go-track-verb {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: 26px;
  line-height: 1;
  letter-spacing: -0.02em;
}
.go-track--see .go-track-verb {
  color: var(--color-primary);
}
.go-track--prove .go-track-verb {
  color: var(--color-rose);
}
.go-track-meta {
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
}
.go-track-desc {
  margin: 0;
  font-family: "Inter", system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  color: var(--color-fg-secondary);
}
/* margin-top:auto pins both action blocks to the bottom edge of their
   card, so the two tracks end on a shared baseline however long the
   descriptions run. Note it aligns the block, not the button: the two
   trust rows wrap to different line counts (four short items on See,
   three long ones on Prove), so the buttons themselves sit a line
   apart. Equalising those would mean either padding See's row with
   whitespace or cutting "DORA - ISO 27001 - GDPR-ready PDF" down, and
   those standard names are the whole point of the row for a compliance
   buyer. A shared bottom edge is the alignment worth having here. */
.go-track-actions {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
/* The shared scan bar is capped at 620px for a centred hero; inside a
   track column it fills the column instead. */
.go-track .scan-input-wrap {
  max-width: none;
}
/* Centred at hero width these rows sat on one line, so the interpuncts
   between items never landed anywhere awkward. In a track column they wrap
   to two and three lines, and a separator that falls at a line break is
   left dangling at the end of the row with nothing after it. Inside a
   track the interpuncts are therefore dropped and the gap does the
   separating -- every item already opens with its own green check, which
   is a stronger delimiter than the interpunct was. Row and column gaps
   differ deliberately: the wider column gap keeps items apart on a line,
   the tighter row gap keeps the wrapped block reading as one row. */
.go-track .scan-trust-row {
  margin-top: 0;
  justify-content: flex-start;
  column-gap: 16px;
  row-gap: 7px;
}
.go-track .scan-trust-sep {
  display: none;
}
.go-track-ctas {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}
.go-btn-prove,
.go-btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 17px 26px;
  border-radius: 14px;
  text-decoration: none;
  font-family: "Inter", sans-serif;
  font-size: 15px;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.go-btn-prove {
  border: 0;
  cursor: pointer;
  background: linear-gradient(to right, var(--color-rose), #f4788a);
  color: var(--color-bg-deep);
  font-weight: 800;
  box-shadow:
    0 4px 25px rgba(236, 85, 103, 0.35),
    0 0 60px rgba(236, 85, 103, 0.14);
  transition: filter 0.2s;
}
.go-btn-prove:hover {
  filter: brightness(1.06);
}
.go-btn-ghost {
  border: 1px solid rgba(255, 255, 255, 0.16);
  color: var(--color-fg);
  font-weight: 700;
  transition:
    border-color 0.2s,
    background 0.2s;
}
.go-btn-ghost:hover {
  border-color: rgba(255, 255, 255, 0.32);
  background: rgba(255, 255, 255, 0.04);
}
.go-btn-prove:focus-visible,
.go-btn-ghost:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
}
/* ═══════════════════════════════════════
   2c. THE ARC STRIP  (campaign hero, under the tracks)
   The same component /scan ships, ported rather than reinvented: one
   strip, one wording for the journey, so the two pages cannot narrate it
   differently. It replaces the five numbered steps that used to sit under
   the video -- that strip was written for this job and the arc says it in
   the words the rest of the site already uses.

   Dark glass, same as the See/Prove cards above it and as the copy on
   /scan -- the strip is the third raised surface in one band and all
   three read as one material.

   The rose cell is a painted door and is marked as one. Auto-repair is
   shipping:false in campaigns/config/icp-approach-map.json, which is why
   it carries "Coming very soon" and why it is the only cell that does.
   ═══════════════════════════════════════ */
.scan-stat-strip {
  margin-top: 28px;
  display: inline-flex;
  align-items: stretch;
  padding: 18px 28px;
  background: rgba(22, 42, 46, 0.55);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
}
.scan-stat-item {
  padding: 0 24px;
  text-align: left;
}
/* The negative block margin cancels this cell's own padding, so the one
   highlighted step keeps the same baseline as the four plain ones instead
   of standing a row proud of them. */
.scan-stat-item--next {
  background: rgba(236, 85, 103, 0.09);
  border: 1px solid rgba(236, 85, 103, 0.28);
  border-radius: 10px;
  padding: 8px 20px;
  margin: -8px 0;
}
.scan-stat-value {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: 28px;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--color-fg);
}
.scan-stat-value--primary {
  color: var(--color-primary);
}
.scan-stat-value--next {
  color: var(--color-rose);
}
/* Step label: Mono, intentional — a fixed caption under each verb */
.scan-stat-label {
  margin-top: 4px;
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
}
.scan-stat-note {
  margin-top: 2px;
  font-family: "Inter", system-ui, sans-serif;
  font-size: 10px;
  color: rgba(255, 255, 255, 0.4);
}
.scan-stat-divider {
  width: 1px;
  align-self: stretch;
  background: rgba(255, 255, 255, 0.1);
}
/* 960, not 860: the strip's intrinsic width is set by its widest mono
   label ("AUTONOMOUS REMEDIATION", about 187px) plus four siblings and
   the hero's 32px gutters, which lands near 968px. Leaving this to the
   860 breakpoint below would let it overflow across the 860-968 band. */
@media (max-width: 960px) {
  .scan-stat-strip {
    flex-wrap: wrap;
    justify-content: center;
    padding: 14px 18px;
  }
  .scan-stat-item {
    padding: 10px 18px;
    text-align: center;
  }
  /* The baseline trick above only makes sense in a single row; once the
     cells wrap it would pull this one into its neighbour. */
  .scan-stat-item--next {
    margin: 0;
  }
  .scan-stat-divider {
    display: none;
  }
}
@media (max-width: 860px) {
  .go-tracks {
    grid-template-columns: minmax(0, 1fr);
    margin-top: 32px;
  }
  .go-proof {
    gap: 18px;
    margin-bottom: 24px;
  }
  /* Stacked, the button stops being a trailing afterthought on its own
     line and becomes the block's own full-width action. */
  .go-icp {
    padding: 16px 18px;
    gap: 16px;
    margin-bottom: 26px;
  }
  .go-icp-cta {
    width: 100%;
    justify-content: center;
  }
}
/* ═══════════════════════════════════════
   2d. THE LEAD HERO  (shared .hp-hero, re-spaced for this page)

   Supersedes the compression this block used to carry. That version
   squeezed the hero hard -- min-height 100vh -> auto, 80+40 above ->
   16+8, 96 below -> 20, copy gap 2rem -> 1.125rem -- for exactly one
   reason: the path tabs and the arc headline had to share the fold
   with it.

   They no longer do. 2e is a sticky bar now, so it earns its
   visibility by pinning the moment you scroll, instead of buying it
   out of the fold budget of the module above it. The arc headline
   follows it below the fold on purpose.

   With that constraint gone the compression is just packing, so the
   band goes back to the hero: it fills the screen it actually leads.
   min-height is the fold MINUS the chrome above it rather than a bare
   100vh, so the hero ends where the visible area ends and the sticky
   bar's top edge lands on the fold line -- a real "there is more" cue
   rather than a guess. That chrome is 81px, the measured .site-header,
   and nothing else: this page's .announcement-banner is display:none,
   so subtracting the 48px it occupies elsewhere would cut the hero
   short by a whole banner it never renders. min-height, not height:
   content taller than that still grows the band normally.

   The copy gap lands at 1.75rem, not back at the base 2rem. Six
   elements means five gaps, so the last 4px per gap is 20px of column
   height bought for no rhythm gained.

   Scoped to >=768px on purpose: styles-site.css's own
   `@media (max-width: 767px)` block already flattens this section for
   mobile, and go.css loads after it, so an unmediated rule here would
   quietly outrank the mobile treatment.
   ═══════════════════════════════════════ */
@media (min-width: 768px) {
  .hp-hero {
    min-height: calc(100vh - 81px);
    padding-top: 3rem;
  }
  .hp-hero-grid {
    padding-top: 2rem;
    padding-bottom: 3rem;
  }
  .hp-hero-copy {
    gap: 1.75rem;
  }
  .hp-hero-title {
    margin-bottom: 0.25rem;
  }
  .hp-hero-ctas {
    padding-top: 0.5rem;
  }
  .hp-stat-strip {
    padding-top: 1.25rem;
  }
}
/* ═══════════════════════════════════════
   2e. PATH TABS  (.go-paths) -- the sticky bar

   Six destinations in one band: all six labels always visible, one
   description and one action at a time. It sits in flow directly under
   the lead hero and pins there, so from the moment the visitor starts
   scrolling it IS this page's navigation -- every module below runs
   under it, and the other five paths stay one click away the whole way
   down.

   It pins at top:81px, directly under the sticky header, not at top:0.
   Before PR #840 this bar really was the only pinned chrome on the
   page: .site-header declared position:sticky;top:0, but its parent
   #header-placeholder was exactly 81px, the header's own height, so
   the header had zero sticky travel and scrolled away like static
   content, and top:0 was correct. #840 wrapped the header in
   header[role=banner] { position: sticky; top: 0; z-index: 60 }
   (styles-site.css), which gives the header real travel -- it now
   stays pinned for the entire scroll. With the header genuinely
   pinned above it, top:0 would put this bar directly under the
   header's box for the header's height, i.e. visually behind it.
   top:81px moves this bar's pin line down to the header's bottom
   edge, so it slots in below the header the instant both are stuck.
   z-index 48 still sits under the header (60/50) and banner (49);
   that ordering was already correct and stays correct -- only the
   top offset needed to change.

   81px is header[role=banner]'s height ONLY when its child
   .announcement-banner is display:none -- 80px .site-nav-bar + 1px
   .site-header border-bottom, with the banner contributing 0. That is
   not the only state: .announcement-banner is position:sticky, which
   keeps it in normal flow rather than removing it, so whenever it is
   visible its own height (64px desktop, styles-site.css) is added
   straight onto the header's rendered box -- ~145px, not 81px. And it
   flips between the two live, with no reload: consent.js suppresses it
   for a fresh visitor until they answer the consent prompt
   (`render()`), then un-suppresses it the instant they do
   (`decide()`), and a returning visitor with a stored consent decision
   never suppresses it at all -- the banner is visible from first
   paint for them. A hardcoded top therefore cannot be correct for
   every visitor. The value here is the JS-off / banner-hidden
   fallback; go.html's inline script (immediately before the
   .is-stuck sync IIFE below the marker block) measures
   header.getBoundingClientRect().height at runtime and overwrites
   this via bar.style.top on load, scroll, resize, and on a
   MutationObserver watching the banner's own style attribute -- the
   one event class that flips the banner's visibility without also
   firing scroll or resize.

   Nothing has to cooperate for position:sticky to work here, which is
   worth recording because the usual failure is silent. body is
   `overflow-x: clip`, and clip -- unlike hidden -- does not create a
   scroll container, so it does not capture the stickiness. Nothing
   between body and this section sets overflow at all. The sticky range
   is therefore the whole of <main>, which is what lets it hold from the
   hero all the way to the footer.

   Geometry is IDENTICAL stuck and unstuck, and that is a decision, not
   an omission. The obvious move is to compress on pin -- drop the
   description, tighten the rows -- but a sticky element stays in flow
   while it is stuck, so shrinking it yanks every module below it upward
   by the difference at the exact instant it pins. Only the chrome
   changes (.is-stuck). It also means the description and CTA this bar
   was asked to carry never vanish at the moment they are most useful.

   It pins at EVERY width, and that is deliberate. The first cut scoped
   position:sticky to >=768px because the mobile panel puts the
   description on its own row and the band was too tall to pin -- 165.6px
   measured, a quarter of an iPhone SE viewport, not the "~130px" an
   earlier version of this comment guessed. But scoping the pin to a
   breakpoint gave one question ("is this bar this page's navigation?")
   two answers depending on viewport width, and mobile silently got the
   answer no: the bar scrolled away and the page lost its navigation
   entirely on the devices most likely to need it. The fix is to make the
   bar short enough to pin rather than to stop pinning, so the mobile
   block hides the description instead (see there for why that is
   honest rather than lossy).

   The panel keeps a min-height so switching tabs does not reflow the
   page underneath it; the tallest description sets that number.
   `[hidden]` needs the explicit display:none because the panel is a
   flex container and `display: flex` would otherwise win.
   ═══════════════════════════════════════ */
.go-paths {
  position: sticky;
  top: 81px;
  z-index: 48;
  padding: 8px 32px 10px;
  background: rgba(16, 31, 34, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
/* Chrome only. No geometry -- see the note above. */
.go-paths.is-stuck {
  border-bottom-color: rgba(43, 205, 238, 0.22);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.38);
}
/* A pinned bar swallows in-page anchors, and this page is full of them:
   four of the six tab CTAs are anchors, and #pricing, #case-studies and
   #auto-repair each landed at y:0 -- entirely underneath the bar -- with
   nothing to tell the visitor the click had worked. The pinned chrome an
   anchor now has to clear is the header PLUS this bar, stacked: 81px of
   sticky header (see above) then 109px of bar, the bar's measured height
   from 768px up, plus 16px of clearance so the target heading doesn't sit
   flush against the bar's edge -- 81 + 109 + 16 = 206px. Before #840 the
   header contributed nothing here (it couldn't travel), so this value was
   125px (109 + 16); it grows by exactly the header's height now that the
   header is genuinely pinned above the bar. The mobile block overrides
   this with its own measured number -- go.js reads the COMPUTED value at
   click time rather than carrying its own copy, so each breakpoint's
   figure is stated exactly once, here in CSS.

   206px is the JS-off / banner-hidden fallback, same caveat as the top
   offset above: 81px of it is header height that assumes
   .announcement-banner is display:none. When the banner is visible the
   header is genuinely taller, so a static number here is wrong for a
   returning visitor (or a fresh one who just answered the consent
   prompt) the same way a static `top` would be. go.html's offset-sync
   script owns this too -- it sets
   document.documentElement.style.scrollPaddingTop from the SAME
   measurement pass that sets bar.style.top (live header height + live
   bar height + 16px clearance), so both numbers move together instead
   of drifting apart. go.js's anchorOffset() already reads
   scroll-padding-top via getComputedStyle at click time rather than
   caching it, so it picks up the inline override with no code change on
   its side. */
html {
  scroll-padding-top: 206px;
}
.go-paths-inner {
  max-width: 1184px;
  margin: 0 auto;
}
.go-paths-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.go-paths-tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 13px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--color-fg-muted);
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition:
    color 0.16s ease,
    border-color 0.16s ease;
}
.go-paths-tab .material-symbols-outlined {
  font-size: 17px;
}
.go-paths-tab:hover {
  color: var(--color-fg-secondary);
}
.go-paths-tab[aria-selected="true"] {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
}
.go-paths-tab:focus-visible {
  outline: none;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  box-shadow: 0 0 0 2px rgba(43, 205, 238, 0.5);
}
.go-paths-panel {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
  /* 54px, not the tallest panel at desktop width (50px): between 768 and
     ~819px the Benchmark and Auto-repair descriptions wrap to a second line,
     and with a smaller value the bar grew 4px on those two tabs and shoved
     every module below it down. A min-height that only holds at wide widths
     is not doing the job this one exists for. */
  min-height: 54px;
  padding: 10px 2px 0;
}
.go-paths-panel[hidden] {
  display: none;
}
.go-paths-desc {
  flex: 1 1 340px;
  margin: 0;
  color: var(--color-fg-secondary);
  font-size: 14.5px;
  line-height: 1.5;
}
.go-paths-go {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex: none;
  padding: 9px 17px;
  border: 0;
  border-radius: 999px;
  background: var(--color-primary);
  color: #001014;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.16s ease;
}
.go-paths-go:hover {
  background: var(--color-primary-hover);
}
.go-paths-go .material-symbols-outlined {
  font-size: 16px;
}
/* ═══════════════════════════════════════
   3. X-RAY LAYERS
   ═══════════════════════════════════════ */
.scan-xray {
  position: relative;
  /* Top 100 -> 72. The band the visitor reads below the second hero is
     this section's top padding plus that hero's bottom padding, and the
     hero's half cannot absorb the whole cut without the stat strip
     reading as clipped against the background boundary. Bottom stays at
     100 -- that boundary was never the complaint. The mobile block below
     re-declares the whole shorthand, so this is desktop-only. */
  padding: 72px 32px 100px;
  overflow: hidden;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(43, 205, 238, 0.03) 50%,
    transparent 100%
  );
}
.scan-xray-inner {
  max-width: 1180px;
  margin: 0 auto;
}
.scan-xray-header {
  text-align: center;
  max-width: 760px;
  margin: 0 auto 56px;
}
.scan-xray-h2 {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: clamp(36px, 4.5vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--color-fg);
}
/* Body text in section — Inter */
.scan-xray-sub {
  font-family: "Inter", sans-serif;
  font-size: 17px;
  line-height: 1.65;
  color: var(--color-fg-secondary);
  margin-top: 18px;
}
.scan-xray-stack {
  position: relative;
  padding: 20px 0 0;
}
.scan-xray-depth {
  position: absolute;
  left: -8px;
  top: 0;
  bottom: 0;
  width: 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding-top: 10px;
  padding-bottom: 30px;
  pointer-events: none;
}
.scan-xray-depth-label {
  font-family: "JetBrains Mono", monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.scan-xray-layers {
  margin-left: 70px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.scan-layer {
  padding: 20px 24px;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow:
    0 10px 30px rgba(0, 0, 0, 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.scan-layer--free {
  background: rgba(43, 205, 238, 0.06);
  border: 1px solid rgba(43, 205, 238, 0.35);
}
.scan-layer--signup {
  background: rgba(43, 205, 238, 0.1);
  border: 1px solid rgba(43, 205, 238, 0.55);
}
.scan-layer--pentest {
  background: rgba(236, 85, 103, 0.08);
  border: 1px solid rgba(236, 85, 103, 0.45);
}
.scan-layer-left {
  display: flex;
  align-items: center;
  gap: 18px;
  flex: 1;
  min-width: 0;
}
/* Layer badge: Mono (L1–L5 label) */
.scan-layer-badge {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  font-weight: 700;
  flex-shrink: 0;
}
.scan-layer-badge--free {
  background: rgba(43, 205, 238, 0.1);
  border: 1px solid rgba(43, 205, 238, 0.35);
  color: var(--color-primary);
}
.scan-layer-badge--signup {
  background: rgba(43, 205, 238, 0.18);
  border: 1px solid rgba(43, 205, 238, 0.55);
  color: var(--color-primary);
}
.scan-layer-badge--pentest {
  background: rgba(236, 85, 103, 0.14);
  border: 1px solid rgba(236, 85, 103, 0.45);
  color: var(--color-rose-bright);
}
/* Layer heading: Montserrat */
.scan-layer-label {
  font-family: "Montserrat", sans-serif;
  font-weight: 800;
  font-size: 20px;
  color: var(--color-fg);
  letter-spacing: -0.01em;
}
/* Layer body text: Inter — matches testimonial/paragraph style */
.scan-layer-sub {
  font-family: "Inter", sans-serif;
  font-size: 14px;
  line-height: 1.6;
  color: #b6c0c4;
  margin-top: 4px;
}
.scan-layer-ex {
  font-family: "Inter", sans-serif;
  font-size: 13px;
  font-style: italic;
  color: #7e8a91;
  margin-top: 5px;
  line-height: 1.5;
}
/* Tier pills: Mono (functional label) */
.scan-layer-pill {
  padding: 6px 14px;
  border-radius: 999px;
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
.scan-layer-pill--free {
  background: rgba(43, 205, 238, 0.1);
  border: 1px solid rgba(43, 205, 238, 0.35);
  color: var(--color-primary);
}
.scan-layer-pill--signup {
  background: rgba(43, 205, 238, 0.18);
  border: 1px solid rgba(43, 205, 238, 0.55);
  color: var(--color-primary);
}
.scan-layer-pill--pentest {
  background: rgba(236, 85, 103, 0.14);
  border: 1px solid rgba(236, 85, 103, 0.45);
  color: var(--color-rose-bright);
}
.scan-pill-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  display: inline-block;
}
.scan-pill-dot--cyan {
  background: var(--color-primary);
}
.scan-pill-dot--rose {
  background: var(--color-rose);
}
/* ═══════════════════════════════════════
   4. MID-PAGE SCAN CTA
   ═══════════════════════════════════════ */
.scan-mid-cta {
  position: relative;
  padding: 0 32px 60px;
}
.scan-mid-card {
  max-width: 980px;
  margin: 0 auto;
  padding: 40px 44px;
  border-radius: 18px;
  background: linear-gradient(
    135deg,
    rgba(43, 205, 238, 0.1),
    rgba(78, 214, 214, 0.06)
  );
  border: 1px solid rgba(43, 205, 238, 0.3);
  box-shadow:
    0 0 0 4px rgba(43, 205, 238, 0.06),
    0 20px 60px rgba(0, 0, 0, 0.4);
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 32px;
  align-items: center;
}
.scan-mid-eyebrow {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-primary);
  margin-bottom: 10px;
}
.scan-mid-h3 {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: 32px;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--color-fg);
  margin: 0;
}
/* Body text: Inter */
.scan-mid-sub {
  font-family: "Inter", sans-serif;
  font-size: 15px;
  line-height: 1.65;
  color: #b6c0c4;
  margin-top: 10px;
}
.scan-mid-right {
  display: flex;
  justify-content: flex-end;
}
/* ═══════════════════════════════════════
   5. EDGE SECTION
   ═══════════════════════════════════════ */
.scan-edge {
  position: relative;
  padding: 60px 32px 100px;
}
.scan-edge-inner {
  max-width: 1180px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: 56px;
  align-items: center;
}
/* Iceberg */
.scan-iceberg {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: 16px;
  overflow: hidden;
  background: linear-gradient(
    to bottom,
    rgba(43, 205, 238, 0.06) 0%,
    rgba(43, 205, 238, 0.1) 36%,
    rgba(10, 18, 21, 0.55) 36%,
    rgba(10, 18, 21, 0.95) 100%
  );
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow:
    0 20px 60px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.scan-iceberg-waterline {
  position: absolute;
  left: 0;
  right: 0;
  top: 36%;
  border-top: 1.5px dashed rgba(43, 205, 238, 0.55);
}
.scan-iceberg-wall {
  position: absolute;
  right: 16px;
  top: calc(36% - 22px);
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-primary);
  background: rgba(10, 18, 21, 0.55);
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid rgba(43, 205, 238, 0.3);
}
.scan-iceberg-above {
  position: absolute;
  left: 22px;
  right: 22px;
  top: 22px;
}
.scan-iceberg-below {
  position: absolute;
  left: 22px;
  right: 22px;
  top: 44%;
}
.scan-iceberg-pill {
  padding: 5px 12px;
  border-radius: 999px;
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.scan-iceberg-pill--cyan {
  background: rgba(43, 205, 238, 0.14);
  border: 1px solid rgba(43, 205, 238, 0.4);
  color: var(--color-primary);
}
.scan-iceberg-pill--rose {
  background: rgba(236, 85, 103, 0.16);
  border: 1px solid rgba(236, 85, 103, 0.45);
  color: var(--color-rose-bright);
}
.scan-iceberg-pill-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}
.scan-iceberg-pill-dot--cyan {
  background: var(--color-primary);
  box-shadow: 0 0 8px var(--color-primary);
}
.scan-iceberg-pill-dot--rose {
  background: var(--color-rose);
  box-shadow: 0 0 8px var(--color-rose);
}
.scan-iceberg-h4 {
  font-family: "Montserrat", sans-serif;
  font-weight: 800;
  font-size: 18px;
  color: var(--color-fg);
  margin: 12px 0 6px;
}
/* Iceberg body text: Inter */
.scan-iceberg-desc {
  font-family: "Inter", sans-serif;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--color-fg-muted);
}
.scan-iceberg-list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: "Inter", sans-serif;
  font-size: 13.5px;
  line-height: 1.75;
  color: #b6c0c4;
}
.scan-iceberg-list li.scan-iceberg-cta-line {
  color: var(--color-primary);
  margin-top: 8px;
}
/* Comparison table */
.scan-compare-wrap {
  background: rgba(22, 42, 46, 0.55);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
.scan-compare-header {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr;
  padding: 16px 22px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
}
.scan-compare-header-squr {
  color: var(--color-primary);
}
.scan-compare-row {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr;
  padding: 14px 22px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  align-items: center;
}
.scan-compare-row:last-child {
  border-bottom: none;
}
.scan-compare-row--highlight {
  background: rgba(43, 205, 238, 0.04);
}
/* Table label: Inter */
.scan-compare-cell-label {
  font-family: "Inter", sans-serif;
  color: var(--color-fg-secondary);
  font-size: 14.5px;
  line-height: 1.5;
}
.scan-compare-cell {
  text-align: center;
  font-family: "JetBrains Mono", monospace;
  font-size: 14px;
}
.scan-compare-cell--no {
  color: var(--color-muted);
}
.scan-compare-cell--yes {
  color: var(--color-primary);
  font-weight: 600;
}
/* Mobile responsive comparison table — fit within viewport (no h-scroll) */
@media (max-width: 767px) {
  .scan-compare-wrap {
    overflow-x: visible;
  }
  .scan-compare-header,
  .scan-compare-row {
    min-width: 0;
    grid-template-columns: 1.4fr 0.8fr 0.9fr;
    column-gap: 8px;
    padding: 12px 14px;
  }
  .scan-compare-header {
    font-size: 9.5px;
    letter-spacing: 0.08em;
  }
  .scan-compare-cell-label {
    font-size: 12.5px;
  }
  .scan-compare-cell {
    font-size: 12.5px;
  }
}
/* Right-column copy */
.scan-edge-h2 {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: clamp(32px, 3.6vw, 44px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0 0 18px;
  color: var(--color-fg);
}
/* Lede: Inter — paragraph, matches testimonials */
.scan-edge-lede {
  font-family: "Inter", sans-serif;
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--color-fg-secondary);
  margin-bottom: 28px;
}
/* ═══════════════════════════════════════
   5b. AUTONOMOUS REMEDIATION (not live yet)
   Rose throughout, deliberately: this is the only band on the page
   describing something we cannot do TODAY, and the colour is what keeps
   it visibly separate from the shipped capabilities above it.
   ═══════════════════════════════════════ */
.scan-repair {
  position: relative;
  padding: 20px 32px 80px;
}
.scan-repair-card {
  max-width: 1180px;
  margin: 0 auto;
  padding: 44px 40px;
  border-radius: 20px;
  border: 1px solid rgba(236, 85, 103, 0.32);
  background: linear-gradient(
    160deg,
    rgba(236, 85, 103, 0.1),
    rgba(236, 85, 103, 0.02) 60%
  );
}
.scan-repair-h2 {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: clamp(30px, 3.4vw, 42px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0 0 18px;
  color: var(--color-fg);
}
.scan-repair-lede {
  font-family: "Inter", sans-serif;
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--color-fg-secondary);
  max-width: 720px;
  margin: 0 0 32px;
}
/* Three steps, the third one pending — same visual grammar as the hero
   ladder, so a visitor who read "Fix · coming very soon" up top meets the
   same promise here with the detail attached. */
.scan-repair-steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-bottom: 28px;
}
.scan-repair-step {
  padding: 18px 20px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(0, 0, 0, 0.2);
}
.scan-repair-step--next {
  border-color: rgba(236, 85, 103, 0.42);
  background: rgba(236, 85, 103, 0.08);
}
/* Step index: Mono, intentional — a numbered sequence, not prose */
.scan-repair-step-n {
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
  margin-bottom: 8px;
}
.scan-repair-step--next .scan-repair-step-n {
  color: var(--color-rose);
}
.scan-repair-step-t {
  font-family: "Montserrat", sans-serif;
  font-weight: 800;
  font-size: 17px;
  line-height: 1.2;
  color: var(--color-fg);
  margin-bottom: 6px;
}
.scan-repair-step-b {
  font-family: "Inter", sans-serif;
  font-size: 14px;
  line-height: 1.55;
  color: var(--color-fg-secondary);
}
/* The honesty line. Small, but it is the reason this band is allowed to
   exist next to the free scan without blurring the two products. */
.scan-repair-note {
  font-family: "Inter", sans-serif;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--color-fg-muted);
  margin: 0;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
/* Early-access form. Rose, not cyan: the hero's cyan input starts a scan
   that runs right now, this one joins a list for something that does not
   exist yet. Same shape so it reads as a sibling, different colour so it
   never gets mistaken for the free scan. */
.scan-wait {
  margin: 26px 0 0;
  padding-top: 24px;
  border-top: 1px solid rgba(236, 85, 103, 0.22);
}
.scan-wait-h {
  font-family: "Montserrat", sans-serif;
  font-weight: 800;
  font-size: 18px;
  line-height: 1.25;
  color: var(--color-fg);
  margin: 0 0 6px;
}
.scan-wait-sub {
  font-family: "Inter", sans-serif;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--color-fg-secondary);
  max-width: 560px;
  margin: 0 0 18px;
}
.scan-wait-form {
  display: flex;
  align-items: stretch;
  background: rgba(22, 42, 46, 0.65);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(236, 85, 103, 0.34);
  border-radius: 14px;
  overflow: hidden;
  max-width: 560px;
  width: 100%;
}
.scan-wait-field {
  flex: 1;
  padding: 15px 18px;
  background: transparent;
  border: 0;
  outline: 0;
  font-family: "JetBrains Mono", monospace;
  font-size: 15px;
  color: var(--color-fg);
  min-width: 0;
}
.scan-wait-field::placeholder {
  color: rgba(255, 255, 255, 0.3);
}
.scan-wait-btn {
  padding: 0 24px;
  border: 0;
  cursor: pointer;
  background: var(--color-rose);
  color: var(--color-fg);
  font-family: "Inter", sans-serif;
  font-weight: 800;
  font-size: 14.5px;
  white-space: nowrap;
  flex-shrink: 0;
  transition: filter 0.2s;
}
.scan-wait-btn:hover {
  filter: brightness(1.1);
}
.scan-wait-btn[disabled] {
  cursor: default;
  filter: grayscale(0.5) brightness(0.8);
}
/* The honeypot. Off-screen rather than display:none — some bots skip
   hidden fields but fill positioned ones, and a real user tabbing through
   never reaches it because it is aria-hidden and tabindex="-1". */
.scan-wait-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.scan-wait-msg {
  font-family: "Inter", sans-serif;
  font-size: 13.5px;
  line-height: 1.6;
  margin: 12px 0 0;
  min-height: 1.6em;
}
.scan-wait-msg[data-state="ok"] {
  color: var(--color-primary);
}
.scan-wait-msg[data-state="err"] {
  color: var(--color-rose);
}
.scan-wait-fine {
  font-family: "Inter", sans-serif;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--color-fg-muted);
  margin: 10px 0 0;
  max-width: 560px;
}
/* ═══════════════════════════════════════
   6. PRICING LADDER
   ═══════════════════════════════════════ */
.scan-pricing {
  position: relative;
  padding: 100px 32px;
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(43, 205, 238, 0.04)
  );
}
.scan-pricing-inner {
  max-width: 1180px;
  margin: 0 auto;
}
.scan-pricing-header {
  text-align: center;
  max-width: 720px;
  margin: 0 auto 56px;
}
.scan-pricing-h2 {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: clamp(36px, 4.5vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--color-fg);
}
/* Body text: Inter */
.scan-pricing-sub {
  font-family: "Inter", sans-serif;
  font-size: 17px;
  line-height: 1.65;
  color: var(--color-fg-secondary);
  margin-top: 14px;
}
.scan-pricing-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 20px;
  align-items: stretch;
}
.scan-tier {
  padding: 28px 26px;
  border-radius: 16px;
  position: relative;
  display: flex;
  flex-direction: column;
}
.scan-tier--ghost {
  background: rgba(22, 42, 46, 0.55);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
.scan-tier--hot {
  background: linear-gradient(
    135deg,
    rgba(236, 85, 103, 0.08),
    rgba(43, 205, 238, 0.06)
  );
  border: 1px solid rgba(236, 85, 103, 0.4);
  box-shadow:
    0 0 0 4px rgba(236, 85, 103, 0.06),
    0 20px 60px rgba(0, 0, 0, 0.4);
}
.scan-tier-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}
/* Tag: Mono (label) */
.scan-tier-tag {
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
  margin-bottom: 8px;
}
.scan-tier-tag--hot {
  color: var(--color-rose-bright);
}
.scan-tier-name {
  font-family: "Montserrat", sans-serif;
  font-weight: 800;
  font-size: 22px;
  color: var(--color-fg);
  margin: 0;
}
.scan-tier-edge-pill {
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(236, 85, 103, 0.16);
  border: 1px solid rgba(236, 85, 103, 0.4);
  font-family: "JetBrains Mono", monospace;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-rose-bright);
  white-space: nowrap;
}
.scan-tier-price-row {
  margin-top: 18px;
  display: flex;
  align-items: baseline;
  gap: 4px;
}
.scan-tier-price {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: 44px;
  color: var(--color-fg);
  letter-spacing: -0.02em;
}
.scan-tier-unit {
  font-family: "JetBrains Mono", monospace;
  font-size: 13px;
  color: var(--color-fg-muted);
}
.scan-tier-bullets {
  list-style: none;
  padding: 0;
  margin: 20px 0 24px;
  flex: 1;
}
/* Bullet text: Inter — matches testimonial paragraph weight */
.scan-tier-bullets li {
  font-family: "Inter", sans-serif;
  font-size: 14px;
  line-height: 1.6;
  color: var(--color-fg-secondary);
  margin-bottom: 10px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.scan-tier-check {
  flex-shrink: 0;
  margin-top: 1px;
}
.scan-tier-check--cyan {
  color: var(--color-primary);
}
.scan-tier-check--rose {
  color: var(--color-rose-bright);
}
.scan-tier-cta {
  padding: 12px 18px;
  border-radius: 12px;
  cursor: pointer;
  font-family: "Inter", sans-serif;
  font-weight: 700;
  font-size: 14px;
  transition: filter 0.2s;
  text-align: center;
  text-decoration: none;
  display: block;
  border: 0;
}
.scan-tier-cta:hover {
  filter: brightness(1.06);
}
.scan-tier-cta--outline {
  background: rgba(43, 205, 238, 0.1);
  color: var(--color-primary);
  border: 1px solid rgba(43, 205, 238, 0.3) !important;
}
.scan-tier-cta--rose {
  background: linear-gradient(135deg, var(--color-rose), var(--color-rose-bright));
  color: var(--color-fg);
  box-shadow: 0 4px 25px rgba(236, 85, 103, 0.4);
}
/* ═══════════════════════════════════════
   7. FOOTER CTA
   ═══════════════════════════════════════ */
.scan-footer-cta {
  position: relative;
  padding: 80px 32px 100px;
  overflow: hidden;
}
.scan-footer-orb {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 720px;
  height: 380px;
  border-radius: 50%;
  background: rgba(43, 205, 238, 0.18);
  filter: blur(180px);
  pointer-events: none;
}
.scan-footer-inner {
  position: relative;
  max-width: 820px;
  margin: 0 auto;
  text-align: center;
}
.scan-footer-live {
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(0, 255, 157, 0.1);
  border: 1px solid rgba(0, 255, 157, 0.3);
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-success);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.scan-footer-live-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-success);
  box-shadow: 0 0 8px var(--color-success);
  animation: scan-pulse 2s ease-in-out infinite;
}
@keyframes scan-pulse {
  0%,
  100% {
    opacity: 1;
    box-shadow: 0 0 0 0 rgba(0, 255, 157, 0.5);
  }
  50% {
    opacity: 0.8;
    box-shadow: 0 0 0 6px rgba(0, 255, 157, 0);
  }
}
.scan-footer-h2 {
  font-family: "Montserrat", sans-serif;
  font-weight: 900;
  font-size: clamp(40px, 5.5vw, 72px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin: 20px 0 18px;
  color: var(--color-fg);
}
/* Body text: Inter */
.scan-footer-sub {
  font-family: "Inter", sans-serif;
  font-size: 17px;
  line-height: 1.65;
  color: var(--color-fg-secondary);
  margin-top: 8px;
  margin-bottom: 32px;
}
/* Footer pills: Mono (label/tag context) */
.scan-footer-pills {
  margin-top: 18px;
  display: inline-flex;
  align-items: center;
  gap: 18px;
  font-family: "JetBrains Mono", monospace;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
  flex-wrap: wrap;
  justify-content: center;
}
/* ═══════════════════════════════════════
   RESPONSIVE
   ═══════════════════════════════════════ */
@media (max-width: 1023px) {
  .scan-xray-layers .scan-layer {
    margin-left: 0 !important;
  }
  .scan-edge-inner {
    grid-template-columns: 1fr;
  }
  .scan-edge-inner > div {
    min-width: 0;
  }
  .scan-mid-card {
    grid-template-columns: 1fr;
  }
  .scan-mid-card > div {
    min-width: 0;
  }
  .scan-mid-right {
    justify-content: flex-start;
  }
  .scan-pricing-grid {
    grid-template-columns: 1fr;
  }
  /* Three steps stack rather than squeeze — the third one carries the
     whole point of the band and must not end up as a sliver. */
  .scan-repair-steps {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 767px) {
  .scan-hero {
    /* Top 24 -> 40, same correction as the desktop rule: the sticky bar
       overlays this section rather than sitting above it, so the tabs'
       own padding never lands here. Held under the desktop 56 because the
       mobile bar is a single scrolling tab row (the description is
       display:none below), so it needs less clearance beneath it. */
    padding: 40px 20px 40px;
  }
  /* The benchmark badge now sits BETWEEN the h1 and the tagline (it used to
     lead the column). styles-site.css:11166 matches it inside this same
     breakpoint via [class*="badge"] and applies flex-wrap:wrap /
     justify-content:center / text-align:center — harmless while the badge
     stood alone at the top, but in its new position it blows the pill out
     to full column width across three rows (dot, wrapped text, arrow) and
     visually severs "in 24 Hours" from "for European SMEs". Keeping the
     dot/text/arrow on one row and letting only the text wrap restores it to
     a caption under the headline, which is what it is.
     `.hp-hero-copy > .hp-hero-badge--rose` is 0,2,0 against that rule's
     0,1,0 and go.css loads last (go.html:183), so this wins without editing
     the stylesheet the other 199 pages share. */
  .hp-hero-copy > .hp-hero-badge--rose {
    align-self: flex-start;
    flex-wrap: nowrap;
    justify-content: flex-start;
    text-align: left;
    max-width: 100%;
    gap: 0.5rem;
    padding: 0.45rem 0.85rem;
    /* .hp-hero-copy is a gap-based flex column (styles-site.css:5575), so
       per-child spacing can only be trimmed with margins. Pull the badge up
       toward the headline it qualifies and down toward the tagline it
       introduces, so headline/badge/tagline read as one block. */
    margin-block: -0.65rem -0.45rem;
  }
  /* Six tabs wrap to three rows at 390px, which costs ~110px of column
     for labels the reader is not reading yet. One scrolling row costs 40
     and keeps the whole strip a strip. The scroll lives on .go-paths-tabs
     so the page body never scrolls sideways with it; scrollbar-width:none
     hides the track because the cut-off sixth tab is the affordance. */
  .go-paths {
    /* Vertical padding is tighter than the desktop 8/10 rule only in that
       it has to survive being pinned: every px here is a px of phone
       screen the page below never gets back. */
    padding: 8px 20px 10px;
  }
  .go-paths-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .go-paths-tabs::-webkit-scrollbar {
    display: none;
  }
  .go-paths-tab {
    flex: none;
    padding: 9px 11px;
    font-size: 13px;
  }
  .go-paths-panel {
    gap: 12px;
    min-height: 0;
    padding-top: 10px;
  }
  /* The description is dropped on phones, and it is worth being straight
     about the trade rather than burying it. The bar was asked to carry
     tabs + a sentence + a CTA. Carrying all three costs 165.6px here --
     a quarter of an iPhone SE viewport -- which is why the first cut
     refused to pin at all. Truncating the sentence to one line was
     measured as the alternative and rejected: across all six tabs it
     renders 136-199px of 442-526px of text, so roughly a third of every
     sentence, which reads as a broken string rather than as supporting
     copy. Hiding it costs 70px and loses nothing the reader can act on,
     because the tab label already names the destination and the CTA
     already names the action ("Stories" -> "Read the stories"). The
     sentence returns in full at 768px, where there is room for it. */
  .go-paths-desc {
    display: none;
  }
  /* The bar's measured height at this breakpoint + the same 16px of
     clearance the desktop rule uses gave 123px before #840; the header's
     81px (banner-hidden) now stacks on top of that same number, same
     reasoning as the base rule above: 81 + 123 = 204px. Stated here
     rather than in go.js: anchorOffset() reads the computed value at
     click time, so this one number is the whole contract. Same live
     caveat as the base rule too -- this is the JS-off / banner-hidden
     fallback, and go.html's offset-sync script overrides it identically
     at this breakpoint via the same live-measured formula, no separate
     mobile branch needed on the JS side. */
  html {
    scroll-padding-top: 204px;
  }
  .scan-h1 {
    font-size: clamp(36px, 9vw, 56px);
    /* styles-site.css:10644 sets `hyphens: auto` on every h1-h6 below 767px.
       On a 900-weight display face that prints "Vom kostenlo-/sen Scan zum"
       and "manuellen Pent-/est" in German. Words still hard-break if one
       genuinely overflows -- overflow-wrap: break-word is untouched. */
    hyphens: manual;
  }
  /* Same 11% width penalty as on desktop, and on a phone it costs whole lines:
     at 360px the shared curve prints the German headline over six. This curve
     holds it to four from 320px up and hands over continuously to the desktop
     rule -- both sides are ~40px at the 767/768 boundary. */
  html[lang="de"] .scan-h1 {
    font-size: clamp(26px, 8.5vw, 40px);
  }
  .scan-hero-sub {
    font-size: 16px;
  }
  .scan-stat-item {
    width: 50%;
    padding: 12px 10px;
  }
  /* Five cells over two columns leave one over; making it the last means
     the odd one out is SQUR itself, which reads as the destination rather
     than as an orphan. */
  .scan-stat-item:last-child {
    width: 100%;
  }
  .scan-input-wrap {
    flex-direction: column;
    border-radius: 14px;
  }
  .scan-input-prefix {
    padding: 14px 18px 0;
  }
  .scan-input-field {
    padding: 10px 18px;
  }
  .scan-input-btn {
    min-height: 48px;
    justify-content: center;
    border-radius: 0;
  }
  .scan-xray {
    padding: 60px 20px;
  }
  .scan-xray-depth {
    display: none;
  }
  .scan-xray-layers {
    margin-left: 0;
  }
  .scan-layer {
    flex-wrap: wrap;
  }
  .scan-mid-card {
    padding: 28px 20px;
  }
  .scan-edge {
    padding: 40px 20px 60px;
  }
  .scan-repair {
    padding: 12px 20px 56px;
  }
  .scan-repair-card {
    padding: 32px 22px;
  }
  .scan-pricing {
    padding: 60px 20px;
  }
  .scan-pricing-grid {
    padding: 0 4px;
  }
  .scan-footer-cta {
    padding: 60px 20px 80px;
  }
  .scan-divider {
    margin: 0 20px;
  }
}
/* ── Short viewports (landscape phones, mostly) ──────────────────────
   The pinned bar is 106.6px. That is 16% of an iPhone SE held upright
   and 28.4% of the same phone turned sideways -- past the point where
   the bar stops being navigation and becomes the page. Anything under
   480px of viewport height therefore puts the BAR back in normal flow,
   which is precisely how every width behaved before this change: the
   fallback is the known-good state, not a new third one. `relative`
   rather than `static` because that is the exact value the base rule
   carried.

   The header does not get the same fallback: header[role=banner]
   (styles-site.css, added by #840) carries no height-based media query,
   so it stays sticky at every viewport height, short ones included.
   scroll-padding-top therefore cannot drop to 0 here the way it could
   before the header was pinned -- an anchor landing at y:0 would still
   sit underneath the header's 81px. It drops to exactly 81px instead:
   the header alone, since the bar itself is unpinned at this breakpoint
   and contributes nothing to clear. 81px is the banner-hidden figure,
   same fallback caveat as the other two blocks.

   go.html's offset-sync script is breakpoint-aware here too, on
   purpose: it only writes bar.style.top when
   getComputedStyle(bar).position === "sticky", which is false at this
   breakpoint, so it correctly leaves the bar's inline top untouched
   (relative, no offset needed) rather than fighting this rule. It still
   sets scroll-padding-top from the live header height alone (no bar
   term, matching the reasoning above) -- so a visible announcement
   banner is accounted for here too, not just above the breakpoint.

   This block must stay LAST of the three that touch scroll-padding-top
   (base 206px, <=767px 204px, here 81px) -- they have equal specificity,
   so source order is what decides. go.js reads the computed value, so it
   follows automatically. */
@media (max-height: 480px) {
  .go-paths {
    position: relative;
  }
  html {
    scroll-padding-top: 81px;
  }
}
/* ── homepage inline styles (identical in EN and DE) ────────── */
/* ── Homepage-specific inline styles (not Tailwind-dependent) ── */
.glow-cyan {
  box-shadow: 0 0 30px rgba(43, 205, 238, 0.4);
}
.glass {
  background: rgba(22, 42, 46, 0.65);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.glass:hover {
  border-color: rgba(43, 205, 238, 0.25);
  box-shadow: 0 0 20px rgba(43, 205, 238, 0.08);
}
button.hp-dropdown-trigger {
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}
.progress-bar {
  height: 6px;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
  margin-top: 10px;
}
.progress-fill {
  height: 100%;
  border-radius: 9999px;
  box-shadow: 0 0 8px currentColor;
}
/* CTA button glow */
.hp-btn-primary-gradient,
.hp-btn-primary-gradient-sm,
.hp-btn-primary-gradient-lg {
  box-shadow:
    0 4px 25px rgba(43, 205, 238, 0.35),
    0 0 60px rgba(43, 205, 238, 0.1);
}
.hp-btn-primary-gradient:hover,
.hp-btn-primary-gradient-sm:hover,
.hp-btn-primary-gradient-lg:hover {
  box-shadow:
    0 4px 35px rgba(43, 205, 238, 0.5),
    0 0 80px rgba(43, 205, 238, 0.15);
}
.glass:active {
  border-color: rgba(236, 85, 103, 0.4) !important;
  box-shadow: 0 0 25px rgba(236, 85, 103, 0.15);
}
.hp-btn-primary-gradient:active,
.hp-btn-primary-gradient-sm:active,
.hp-btn-primary-gradient-lg:active {
  background: var(--color-rose) !important;
  background-image: none !important;
  box-shadow: 0 0 20px rgba(236, 85, 103, 0.3);
}
.hp-btn-secondary:active,
.hp-btn-secondary-lg:active {
  border-color: rgba(236, 85, 103, 0.4) !important;
  box-shadow: 0 0 15px rgba(236, 85, 103, 0.12);
}
/* Enhanced card hover */
.glass {
  transition:
    border-color 0.3s,
    box-shadow 0.3s;
}
/* Homepage blog card images */
.hp-blog-card-image {
  aspect-ratio: 16/9;
  overflow: hidden;
  position: relative;
}
.hp-blog-card-image-gradient {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.5s ease;
}
.hp-blog-card:hover .hp-blog-card-image-gradient {
  transform: scale(1.04);
}
.hp-blog-cat-benchmarks .hp-blog-card-image-gradient {
  background: linear-gradient(
    135deg,
    rgba(16, 185, 129, 0.25) 0%,
    rgba(16, 31, 34, 0.9) 100%
  );
}
.hp-blog-cat-ai-security .hp-blog-card-image-gradient {
  background: linear-gradient(
    135deg,
    rgba(168, 85, 247, 0.25) 0%,
    rgba(16, 31, 34, 0.9) 100%
  );
}
.hp-blog-cat-pentesting .hp-blog-card-image-gradient {
  background: linear-gradient(
    135deg,
    rgba(78, 214, 214, 0.25) 0%,
    rgba(16, 31, 34, 0.9) 100%
  );
}
.hp-blog-card-image-icon {
  font-size: 2.5rem;
  opacity: 0.35;
}
/* Reduce motion for accessibility */
@media (prefers-reduced-motion: reduce) {
  .fade-up,
  .scale-in {
    transition: opacity 0.3s ease !important;
    transform: none !important;
  }
  .glass:hover {
    transform: none !important;
  }
}
