/* Property skin and editorial composition. Core UI remains the component owner. */
:root {
  --ui-color-accent: #2563eb;
  --ui-color-accent-ink: #ffffff;
  --ui-color-accent-tint: #eff6ff;
  --ui-color-focus: #2563eb;
  --ui-container: 72rem;
  /* The sticky masthead's real height (~89px measured), rounded up. Sticky
     content below it (the editorial aside) and anchor targets offset by this
     so nothing slides under the bar. */
  --site-masthead-h: 5.75rem;
  --scanner-warning-bg: #fffaeb;
  --scanner-warning-border: #b45309;
  --scanner-evidence-bg: #0b1020;
  --scanner-evidence-ink: #f5f7ff;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ui-color-accent: #93c5fd;
    --ui-color-accent-ink: #0c1a33;
    --ui-color-accent-tint: #0f2039;
    --ui-color-focus: #93c5fd;
    --scanner-warning-bg: #3a2b12;
    --scanner-warning-border: #fbbf24;
    --scanner-evidence-bg: #05070f;
    --scanner-evidence-ink: #f5f7ff;
  }
}

:root[data-theme="dark"] {
  --ui-color-accent: #93c5fd;
  --ui-color-accent-ink: #0c1a33;
  --ui-color-accent-tint: #0f2039;
  --ui-color-focus: #93c5fd;
  --scanner-warning-bg: #3a2b12;
  --scanner-warning-border: #fbbf24;
  --scanner-evidence-bg: #05070f;
  --scanner-evidence-ink: #f5f7ff;
}

.site-brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-4);
  flex-wrap: wrap;
  min-width: 0;
}

.site-brand__name {
  color: var(--ui-color-ink);
  font-size: var(--ui-text-lg);
  font-weight: 780;
  letter-spacing: -0.015em;
  text-decoration: none;
}

.site-brand__promise {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  margin: 0;
}

/* The primary nav lives INSIDE the masthead bar, as the comp draws it:
   brand left, links centre, controls right. The base layout's nav slot is
   unused so no second band renders. */
.site-nav {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2) var(--ui-space-4);
  flex: 1 1 auto;
  flex-wrap: wrap;
  justify-content: center;
  min-width: 0;
}

.site-footer a,
.site-prose a:not(.ui-btn),
.site-privacy-panel > a,
.site-banner > a {
  color: var(--ui-color-accent);
  text-underline-offset: 0.18em;
}

.site-nav a {
  color: rgba(255, 255, 255, 0.72);
  font-size: var(--ui-text-sm);
  font-weight: 600;
  text-decoration: none;
}

.site-nav a:hover,
.site-nav a:focus-visible {
  color: #ffffff;
}

.site-nav a[aria-current="page"] {
  color: #ffffff;
  text-decoration: underline;
  text-decoration-color: var(--site-accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.5rem;
}

.site-hero {
  display: grid;
  gap: var(--ui-space-4);
  padding-block: var(--ui-space-5);
}

.site-hero__lede {
  font-size: var(--ui-text-xl);
  line-height: 1.45;
  max-width: 49rem;
  margin: 0;
}

.site-kicker {
  color: var(--ui-color-accent);
  font-size: var(--ui-text-sm);
  font-weight: 760;
  letter-spacing: 0.065em;
  margin: 0;
  text-transform: uppercase;
}

.site-scope,
.site-warning {
  border: 1px solid var(--ui-color-border-strong);
  border-inline-start: 0.35rem solid var(--ui-color-accent);
  border-radius: 0.75rem;
  padding: var(--ui-space-4) var(--ui-space-5);
}

.site-scope {
  background: var(--ui-color-accent-tint);
  max-inline-size: calc(72ch + 2 * var(--ui-space-5));
}

.site-warning {
  background: var(--scanner-warning-bg);
  border-inline-start-color: var(--scanner-warning-border);
}

.site-scope > :first-child,
.site-warning > :first-child,
.site-prose > :first-child,
.site-section > :first-child {
  margin-top: 0;
}

.site-scope > :last-child,
.site-warning > :last-child,
.site-prose > :last-child,
.site-section > :last-child {
  margin-bottom: 0;
}

.site-grid {
  display: grid;
  gap: var(--ui-space-5);
}

.site-grid--cards {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}

.site-section {
  margin-block: var(--ui-space-7);
}

.site-section + .site-section {
  border-top: 1px solid var(--ui-color-border);
  padding-top: var(--ui-space-7);
}

.site-prose {
  max-width: 50rem;
}

.site-prose p,
.site-prose li,
.site-section p,
.site-section li {
  max-width: 72ch;
}

.site-table-wrap {
  margin-block: var(--ui-space-5);
  overflow-x: auto;
}

.site-table {
  border-collapse: collapse;
  width: 100%;
}

.site-table th[scope="row"] {
  width: 34%;
}

.site-table th,
.site-table td {
  border-bottom: 1px solid var(--ui-color-border);
  padding: var(--ui-space-3);
  text-align: start;
  vertical-align: top;
}

.site-table th {
  background: var(--ui-color-surface-sunken);
  font-weight: 750;
}

.site-example {
  background: var(--scanner-evidence-bg);
  border: 1px solid var(--ui-color-border-strong);
  border-radius: var(--ui-radius-md);
  color: var(--scanner-evidence-ink);
  direction: ltr;
  font-family: var(--ui-font-mono);
  line-height: 1.65;
  overflow-wrap: anywhere;
  padding: var(--ui-space-4);
  unicode-bidi: isolate;
}

.site-flow {
  counter-reset: scanner-flow;
  display: grid;
  gap: var(--ui-space-3);
  list-style: none;
  padding: 0;
}

.site-flow > li {
  align-items: start;
  counter-increment: scanner-flow;
  display: grid;
  gap: var(--ui-space-3);
  grid-template-columns: 2rem 1fr;
}

.site-flow > li::before {
  align-items: center;
  background: var(--ui-color-accent-tint);
  border: 1px solid var(--ui-color-border-strong);
  border-radius: 999px;
  color: var(--ui-color-accent);
  content: counter(scanner-flow);
  display: inline-flex;
  font-size: var(--ui-text-sm);
  font-weight: 750;
  height: 2rem;
  justify-content: center;
  width: 2rem;
}

.site-actions {
  display: flex;
  gap: var(--ui-space-3);
  flex-wrap: wrap;
  margin-block: var(--ui-space-5);
}

.site-source-list,
.site-meta {
  font-size: var(--ui-text-sm);
}

/* Footer — a fixed dark band that bookends the dark masthead, with a brand
   lockup, categorized link columns and a legal bottom bar. The solid
   background-color under the gradient is what the AA-contrast gate composites
   footer links against (it ignores gradient images). */
.ui-footer {
  position: relative;
  background-color: var(--site-ink-deep);
  /* Depth, not a flat plate: a cyan wash from the top-right and a blue wash
     from the top-left over the dark gradient, echoing the masthead. */
  background-image:
    radial-gradient(90% 130% at 100% 0%, rgba(6, 182, 212, 0.09), transparent 58%),
    radial-gradient(85% 130% at 0% 0%, rgba(37, 99, 235, 0.16), transparent 55%),
    linear-gradient(180deg, #10122b 0%, var(--site-ink-deep) 100%);
  /* The band is full-bleed, so it butts against the content above (a top
     margin would open a light strip); its own padding gives the breathing
     room. --ui-space-8/9 do not exist (the scale tops out at 7 = 3rem);
     referencing them voided the whole padding shorthand, which is why the
     footer had no vertical padding at all. Use real tokens. */
  margin-top: 0;
  padding-block: var(--ui-space-7);
  color: #aab2d8;
}
/* The top edge is sealed by a brand scan-line — cyan sweeping into blue, the
   same gesture as the masthead accent and the section ticks — rather than a
   plain rule, which layered with a leftover border read as an odd light line. */
.ui-footer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--site-scan) 22%, var(--site-accent) 56%, transparent);
  opacity: 0.7;
}
.site-footer {
  display: grid;
  gap: var(--ui-space-7);
}
.site-footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 2.4fr);
  gap: var(--ui-space-7);
}
.site-footer__brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: #ffffff;
  font-size: 1.05rem;
  font-weight: 800;
  text-decoration: none;
}
.site-footer__brand .site-brand__mark {
  width: 1.6rem;
  height: 1.6rem;
  color: var(--site-scan);
  filter: drop-shadow(0 0 10px rgba(34, 211, 238, 0.45));
}
.site-footer__tagline {
  margin: var(--ui-space-3) 0 0;
  max-width: 34ch;
  font-size: var(--ui-text-sm);
  line-height: 1.6;
  color: #99a2cc;
}
.site-footer__cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--ui-space-6);
}
.site-footer__col {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}
.site-footer__heading {
  margin: 0 0 0.35rem;
  font-family: var(--ui-font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #8891bd;
}
.site-footer__col a {
  color: #c3cbe8;
  text-decoration: none;
  font-size: var(--ui-text-sm);
  width: fit-content;
}
.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-space-2) var(--ui-space-5);
  padding-top: var(--ui-space-5);
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  font-size: var(--ui-text-sm);
}
.site-footer__bottom p { margin: 0; }
.site-footer__copy { color: #c3cbe8; font-weight: 600; }
.site-footer__note { color: #99a2cc; }
.site-footer__disclaimer { color: #8891bd; flex-basis: 100%; }

@media (max-width: 52rem) {
  .site-footer__top { grid-template-columns: minmax(0, 1fr); gap: var(--ui-space-6); }
  .site-footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ui-space-5); }
}
@media (max-width: 30rem) {
  .site-footer__cols { grid-template-columns: minmax(0, 1fr); }
}

.site-workbench-intro {
  max-width: 54rem;
  margin-bottom: var(--ui-space-6);
}

.site-workbench-boundary {
  font-size: var(--ui-text-sm);
  margin-bottom: var(--ui-space-4);
  padding: var(--ui-space-3) var(--ui-space-4);
}

.site-export-warning {
  font-size: var(--ui-text-sm);
  margin-block: var(--ui-space-3);
  padding: var(--ui-space-3) var(--ui-space-4);
}

/* Core buttons declare display, so preserve the HTML hidden contract inside the workbench. */
.ui-utility-workbench [hidden] {
  display: none !important;
}

.site-steps > li {
  margin-block: var(--ui-space-3);
  padding-inline-start: var(--ui-space-2);
}

@media (max-width: 40rem) {
  .site-hero__lede {
    font-size: var(--ui-text-lg);
  }

  .site-nav {
    justify-content: flex-start;
  }
}

@media (forced-colors: active) {
  .site-scope,
  .site-warning,
  .site-example,
  .site-table th,
  .site-table td,
  .site-flow > li::before,
  .site-scan-card,
  .site-scan-card__zone,
  .site-privacy-panel,
  .site-feature-band,
  .site-banner {
    border-color: CanvasText;
  }
}

/* -- LANDING SURFACE ----------------------------------------------------
   The comp's shape, built on Core UI's tokens rather than beside them: a
   dark masthead, one accent, and cards that carry their own icon. Nothing
   here changes the workbench, which keeps its own no-egress surface. */

:root {
  --site-ink-deep: #0b0d1f;
  --site-surface: #f4f5fb;
  --site-surface-2: #eef0f8;
  --site-card: #ffffff;
  --site-line: #e4e6f1;
  --site-line-strong: #d3d6e6;
  --site-accent: #2563eb;
  --site-accent-strong: #1d4ed8;
  --site-accent-soft: #eff6ff;
  /* Cohesion: one authority accent. The former cyan "scan-signal" now resolves
     to the royal-blue accent, so a single hand is visibly in charge. */
  --site-scan: #2563eb;
  --site-scan-soft: #ecfeff;
  /* Figures render in the scan-signal, but the pure cyan is too light for AA on
     a white tile — this is a darkened teal that clears 4.5:1 and still reads cyan. */
  --site-figure-ink: #0e7490;
  --site-danger-soft: #fee2e2;
  --site-danger-ink: #b91c1c;
  --site-warn-soft: #fef3c7;
  --site-warn-ink: #92400e;
  --site-ok-soft: #dcfce7;
  --site-ok-ink: #166534;

  /* Depth, motion and shape — the elevation system. */
  --site-shadow-sm: 0 1px 2px rgba(11, 13, 31, 0.04), 0 1px 3px rgba(11, 13, 31, 0.06);
  --site-shadow-md: 0 6px 16px -8px rgba(11, 13, 31, 0.14), 0 2px 6px -2px rgba(11, 13, 31, 0.08);
  --site-shadow-lg: 0 24px 48px -28px rgba(37, 33, 120, 0.35), 0 8px 20px -12px rgba(11, 13, 31, 0.12);
  --site-shadow-accent: 0 12px 28px -14px rgba(37, 99, 235, 0.5);
  --site-ring: 0 0 0 3px rgba(37, 99, 235, 0.32);
  --site-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --site-dur: 180ms;
  --site-r-sm: 0.625rem;
  --site-r-md: 0.9rem;
  --site-r-lg: 1.15rem;
  --site-grid-dot: transparent;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --site-surface: #080a16;
    --site-surface-2: #0d1022;
    --site-card: #12142b;
    --site-line: #262a4d;
    --site-line-strong: #343a63;
    --site-accent: #60a5fa;
    --site-accent-strong: #93c5fd;
    --site-accent-soft: #0f2039;
    --site-scan: #60a5fa;
    --site-scan-soft: #0c2a33;
    --site-figure-ink: #22d3ee;
    --site-danger-soft: #3a1a1a;
    --site-danger-ink: #fca5a5;
    --site-warn-soft: #3a2b12;
    --site-warn-ink: #fcd34d;
    --site-ok-soft: #10281a;
    --site-ok-ink: #86efac;
    --site-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --site-shadow-md: 0 8px 20px -10px rgba(0, 0, 0, 0.6);
    --site-shadow-lg: 0 28px 56px -30px rgba(0, 0, 0, 0.75);
    --site-shadow-accent: 0 12px 28px -14px rgba(96, 165, 250, 0.4);
    --site-ring: 0 0 0 3px rgba(96, 165, 250, 0.4);
    --site-grid-dot: transparent;
  }
}

:root[data-theme="dark"] {
  --site-surface: #080a16;
  --site-surface-2: #0d1022;
  --site-card: #12142b;
  --site-line: #262a4d;
  --site-line-strong: #343a63;
  --site-accent: #60a5fa;
  --site-accent-strong: #93c5fd;
  --site-accent-soft: #0f2039;
  --site-scan: #60a5fa;
  --site-scan-soft: #0c2a33;
  --site-figure-ink: #22d3ee;
  --site-danger-soft: #3a1a1a;
  --site-danger-ink: #fca5a5;
  --site-warn-soft: #3a2b12;
  --site-warn-ink: #fcd34d;
  --site-ok-soft: #10281a;
  --site-ok-ink: #86efac;
  --site-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --site-shadow-md: 0 8px 20px -10px rgba(0, 0, 0, 0.6);
  --site-shadow-lg: 0 28px 56px -30px rgba(0, 0, 0, 0.75);
  --site-shadow-accent: 0 12px 28px -14px rgba(96, 165, 250, 0.4);
  --site-ring: 0 0 0 3px rgba(96, 165, 250, 0.4);
  --site-grid-dot: transparent;
}

/* The masthead is dark in both schemes: it is the product's one fixed
   surface, and a nav that inverts with the theme reads as a different
   site rather than the same one at night. */
.ui-header {
  background: var(--site-ink-deep);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.ui-header .site-brand__name,
.ui-header .site-brand__promise {
  color: #ffffff;
}

.ui-header .site-brand__promise {
  color: rgba(255, 255, 255, 0.62);
}

.site-brand__lockup {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-3);
  min-width: 0;
}

/* A flex item's default min-width is its content, so the brand text pushed
   the masthead wider than a 320px viewport at 200% zoom. */
.site-brand__lockup > div {
  min-width: 0;
}

.site-brand__mark {
  color: var(--site-accent);
  flex: none;
  height: 2.25rem;
  width: 2.25rem;
}

.site-badge {
  background: var(--ui-color-accent);
  border-radius: 999px;
  color: var(--ui-color-accent-ink);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  margin-left: var(--ui-space-2);
  padding: 0.125rem 0.5rem;
  text-transform: uppercase;
  vertical-align: middle;
}

.site-kicker--pill {
  align-items: center;
  background: var(--site-accent-soft);
  border-radius: 999px;
  color: var(--site-accent);
  display: inline-flex;
  font-size: var(--ui-text-sm);
  font-weight: 650;
  gap: var(--ui-space-2);
  letter-spacing: 0.02em;
  padding: 0.375rem 0.875rem;
}

.site-hero__title {
  font-size: clamp(2.1rem, 4.5vw, 3.1rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.08;
  margin: var(--ui-space-3) 0;
}

.site-hero__title em {
  color: var(--site-accent);
  font-style: normal;
}

.site-trust {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-3) var(--ui-space-4);
  list-style: none;
  margin: var(--ui-space-4) 0 0;
  padding: 0;
}

.site-trust li {
  align-items: center;
  color: var(--ui-color-muted);
  display: flex;
  font-size: 0.8125rem;
  font-weight: 600;
  gap: var(--ui-space-2);
  white-space: nowrap;
}

.site-trust svg {
  color: var(--site-accent);
  flex: none;
  height: 1.125rem;
  width: 1.125rem;
}

/* Feature and detection cards. The icon tile is decorative and is hidden
   from assistive technology; the heading carries the meaning. */
.site-feature-grid {
  display: grid;
  gap: var(--ui-space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  margin-top: var(--ui-space-5);
}

.site-feature {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 0.875rem;
  padding: var(--ui-space-5);
}

.site-feature h3 {
  font-size: var(--ui-text-base);
  margin: var(--ui-space-3) 0 var(--ui-space-2);
}

.site-feature p {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  margin: 0;
}

.site-tile {
  align-items: center;
  border-radius: 0.625rem;
  display: inline-flex;
  height: 2.5rem;
  justify-content: center;
  width: 2.5rem;
}

.site-tile svg { height: 1.25rem; width: 1.25rem; }
.site-tile--accent { background: var(--site-accent-soft); color: var(--site-accent); }
.site-tile--danger { background: var(--site-danger-soft); color: var(--site-danger-ink); }
.site-tile--warn { background: var(--site-warn-soft); color: var(--site-warn-ink); }
.site-tile--ok { background: var(--site-ok-soft); color: var(--site-ok-ink); }

.site-example-chip {
  /* Literal tokens as LIGHT inline-code (matching the reference's tinted
     example pills), not miniature dark blocks — a subtle tinted surface, a
     hairline, monospace. The dark "evidence" surface is reserved for the real
     result excerpt only. */
  background: var(--site-accent-soft);
  border: 1px solid color-mix(in srgb, var(--site-accent) 16%, transparent);
  border-radius: 0.4rem;
  color: color-mix(in srgb, var(--site-accent) 82%, var(--ui-color-ink));
  direction: ltr;
  unicode-bidi: isolate;
  display: inline-block;
  font-family: var(--ui-font-mono);
  font-size: 0.78rem;
  letter-spacing: -0.01em;
  line-height: 1.5;
  margin-top: var(--ui-space-3);
  overflow-wrap: anywhere;
  padding: 0.28rem 0.55rem;
}

.site-cta-panel {
  align-items: center;
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-4);
  justify-content: space-between;
  margin-top: var(--ui-space-6);
  padding: var(--ui-space-5);
}

.site-cta-panel h2 {
  font-size: var(--ui-text-lg);
  margin: 0 0 var(--ui-space-2);
}

.site-cta-panel p {
  color: var(--ui-color-muted);
  margin: 0;
  max-width: 46ch;
}

/* Decorations (the hero magnifier, sparkles) may poke past the container
   under zoom; clip at the root so they never widen the scrollable area. */
:root {
  overflow-x: clip;
}

.ui-page {
  background: var(--site-surface);
  overflow-x: clip;
}

/* An inline-flex pill inside a stretching flex column still fills the
   row; this keeps it the width of its own words. */
.site-kicker--pill {
  align-self: flex-start;
  width: fit-content;
}

.site-hero {
  display: flex;
  flex-direction: column;
}

.site-hero__lede {
  max-width: 54ch;
}

/* -- THE WORKBENCH, TWO PANELS ------------------------------------------
   Input on the left, results on the right, as the comps show. The runtime
   finds its controls by data-utility-role rather than by position, so the
   slot can be restructured freely — but the tab ORDER is a contract the
   keyboard test drives, so nothing here is display:none and the source,
   file and run controls stay reachable in that order. */
.scan-privacy-strip {
  align-items: center;
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 0.75rem;
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-3);
  margin-bottom: var(--ui-space-5);
  padding: var(--ui-space-3) var(--ui-space-4);
}

.scan-privacy-strip svg {
  color: var(--site-accent);
  flex: none;
  height: 1.25rem;
  width: 1.25rem;
}

.scan-privacy-strip p {
  color: var(--ui-color-muted);
  flex: 1 1 min(24rem, 100%);
  font-size: var(--ui-text-sm);
  margin: 0;
}

.scan-privacy-strip strong { color: var(--ui-color-ink); }
.scan-privacy-strip a { font-size: var(--ui-text-sm); font-weight: 600; }

.scan-grid {
  align-items: stretch;
  display: grid;
  gap: var(--ui-space-5);
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
}

/* Pre-scan, let the resting viewport grow so the results card matches the
   height of the taller input card — two balanced panels, not one floating. */
.scan-panel--results:has(.ui-utility-result:empty) .ui-utility-result:empty { flex: 1 1 auto; }

@media (max-width: 60rem) {
  .scan-grid { grid-template-columns: minmax(0, 1fr); }
}

.scan-panel {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-4);
  padding: var(--ui-space-5);
}

.scan-panel__title {
  font-size: var(--ui-text-lg);
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0;
}

.scan-panel__trust {
  border-top: 1px solid var(--site-line);
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  margin: 0;
  padding-top: var(--ui-space-3);
}

.scan-lookfor h3 {
  font-size: var(--ui-text-base);
  margin: 0 0 var(--ui-space-3);
}

.scan-lookfor ul {
  display: grid;
  gap: var(--ui-space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}

.scan-lookfor li {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
}

.scan-lookfor strong {
  color: var(--ui-color-ink);
  display: block;
  margin: var(--ui-space-2) 0 0.125rem;
}

.scan-lookfor .site-tile { height: 2rem; width: 2rem; }
.scan-lookfor .site-tile svg { height: 1rem; width: 1rem; }

/* On the workbench the panels are the page, so the intro is a caption
   rather than a landing hero. */
.site-workbench-intro {
  margin-bottom: var(--ui-space-4);
}

.site-workbench-intro .ui-h1 {
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  margin: var(--ui-space-2) 0;
}

.site-workbench-intro .site-hero__lede {
  font-size: var(--ui-text-base);
  margin: 0;
}

/* The empty state lives in CSS because the result section is genuinely
   empty until a scan renders into it: no script has to remember to clear
   a placeholder, and it cannot survive a result by accident. */
.ui-utility-result:empty {
  border: 1px dashed var(--site-line);
  border-radius: 0.875rem;
  display: block;
  padding: var(--ui-space-7) var(--ui-space-5);
  text-align: center;
}

.ui-utility-result:empty::before {
  color: var(--ui-color-muted);
  content: "No scan results yet — paste text or choose a file, then run the scan.";
  display: block;
  font-size: var(--ui-text-sm);
  margin: 0 auto;
  max-width: 32ch;
}

.site-workbench-intro .site-kicker { margin-bottom: 0; }
.site-workbench-intro + .ui-utility-workbench,
.ui-utility-workbench { margin-top: var(--ui-space-4); }
.site-hero.site-workbench-intro { gap: var(--ui-space-2); }

/* The hero is two columns above 60rem, as the comps show: the promise on
   the left, a decorative scanned document on the right. */
.site-hero-split {
  align-items: center;
  display: grid;
  gap: var(--ui-space-6);
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
}

@media (max-width: 60rem) {
  .site-hero-split { grid-template-columns: minmax(0, 1fr); }
  .site-hero-art { display: none; }
}

.site-hero-art {
  position: relative;
  padding: var(--ui-space-6) 0;
}

.site-hero-art__doc {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 0.875rem;
  box-shadow: 0 18px 40px -24px rgba(15, 16, 36, 0.45);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-left: auto;
  padding: var(--ui-space-5);
  width: min(100%, 22rem);
}

.site-hero-art__dots { display: flex; gap: 0.375rem; margin-bottom: var(--ui-space-2); }
.site-hero-art__dots i { background: var(--site-line); border-radius: 999px; height: 0.5rem; width: 0.5rem; }

.site-hero-art__line {
  background: var(--site-line);
  border-radius: 999px;
  height: 0.5rem;
}

.site-hero-art__line--short { width: 62%; }

.site-hero-art__chip {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 999px;
  box-shadow: 0 10px 24px -16px rgba(15, 16, 36, 0.5);
  font-size: 0.8125rem;
  font-weight: 600;
  margin: 0;
  padding: 0.4375rem 0.875rem;
  position: absolute;
  white-space: nowrap;
}

.site-hero-art__chip--danger { color: var(--site-danger-ink); left: 0; top: 12%; }
.site-hero-art__chip--warn { color: var(--site-warn-ink); left: 6%; top: 44%; }
.site-hero-art__chip--accent { color: var(--site-accent); left: 0; top: 74%; }

/* The comp's magnifying glass, drawn rather than shipped: a ring with a
   rotated handle, laid over the document's lower-right corner. */
.site-hero-art__glass {
  border: 0.5rem solid var(--site-accent);
  border-radius: 999px;
  bottom: 6%;
  height: 5.25rem;
  opacity: 0.9;
  position: absolute;
  right: 4%;
  width: 5.25rem;
}

.site-hero-art__glass::after {
  background: var(--site-accent);
  border-radius: 999px;
  bottom: -1.55rem;
  content: "";
  height: 0.85rem;
  position: absolute;
  right: -1.85rem;
  transform: rotate(45deg);
  width: 2.75rem;
}

/* Sparkle accents beside the document, as the comp scatters them. */
.site-hero-art::before,
.site-hero-art::after {
  color: var(--site-accent);
  content: "\2726";
  opacity: 0.55;
  position: absolute;
}

.site-hero-art::before { font-size: 1.1rem; left: 34%; top: 4%; }
.site-hero-art::after { bottom: 10%; font-size: 0.8rem; left: 42%; }

.site-brand__actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-3);
  min-width: 0;
}

.site-theme-toggle {
  align-items: center;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 999px;
  color: #ffffff;
  cursor: pointer;
  display: inline-flex;
  font: inherit;
  font-size: var(--ui-text-sm);
  font-weight: 600;
  gap: var(--ui-space-2);
  padding: 0.4375rem 0.875rem;
}

.site-theme-toggle:hover { background: rgba(255, 255, 255, 0.1); }
.site-theme-toggle svg { height: 1rem; width: 1rem; }

/* Tabs, samples and tiles. The markup is the property's; the behaviour is
   the engine's, so nothing here binds an event. */
.scan-tabs {
  border-bottom: 1px solid var(--site-line);
  display: flex;
  gap: var(--ui-space-4);
}

.scan-tabs [role="tab"] {
  background: none;
  border: 0;
  border-bottom: 2.5px solid transparent;
  color: var(--ui-color-muted);
  cursor: pointer;
  font: inherit;
  font-size: 1.02rem;
  font-weight: 700;
  margin-bottom: -1px;
  padding: 0 0 var(--ui-space-3);
}

.scan-tabs [role="tab"][aria-selected="true"] {
  border-bottom-color: var(--site-accent);
  color: var(--site-accent);
}

.scan-tabpanel { display: flex; flex-direction: column; gap: var(--ui-space-4); }

.scan-samples { display: flex; flex-wrap: wrap; gap: var(--ui-space-2); }

.scan-samples__label {
  color: var(--ui-color-muted);
  flex: 1 0 100%;
  font-size: var(--ui-text-sm);
  font-weight: 600;
  margin: 0;
}

/* -- WORKBENCH INPUT: a real textarea and a real dropzone --------------- */

/* The paste box: a themed sunken surface (not a bare white/near-black field),
   a comfortable measure, and a clear accent focus ring. */
.ui-utility-input__control {
  width: 100%;
  min-height: 15rem;
  padding: var(--ui-space-5);
  background: color-mix(in srgb, var(--site-accent) 5%, var(--site-field-bg));
  border: 2px solid color-mix(in srgb, var(--site-accent) 30%, var(--site-line-strong));
  border-radius: 0.85rem;
  box-shadow: inset 0 1px 2px rgba(11, 13, 31, 0.06);
  color: var(--ui-color-ink);
  font: inherit;
  font-size: 1.05rem;
  line-height: 1.6;
  resize: vertical;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.ui-utility-input__control::placeholder {
  color: color-mix(in srgb, var(--ui-color-ink) 42%, transparent);
  font-size: 1rem;
  opacity: 1;
}
.ui-utility-input__control:focus,
.ui-utility-input__control:focus-visible {
  outline: none;
  border-color: var(--site-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--site-accent) 22%, transparent);
}
.ui-utility-input__control:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}
/* The meter reads as quiet metadata beneath the box. */
.ui-utility-input__meter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-1) var(--ui-space-4);
  margin-top: var(--ui-space-2);
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  font-variant-numeric: tabular-nums;
}
.ui-utility-input__meter b { color: var(--ui-color-ink); font-weight: 650; }

/* The file dropzone: the native input sits transparent over the whole area,
   so the browser handles drag-drop AND click with no script; the face is the
   visual and never intercepts the pointer. */
.scan-dropzone {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-2);
}
.scan-dropzone__area {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 15rem;
  padding: var(--ui-space-5);
  background: color-mix(in srgb, var(--site-accent) 5%, var(--site-field-bg));
  border: 2px dashed color-mix(in srgb, var(--site-accent) 40%, var(--site-line-strong));
  border-radius: 0.85rem;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.scan-dropzone__input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
}
.scan-dropzone__input:disabled { cursor: not-allowed; }
.scan-dropzone__area:hover,
.scan-dropzone__area:focus-within {
  border-color: var(--site-accent);
  background: color-mix(in srgb, var(--site-accent) 7%, var(--site-field-bg));
}
.scan-dropzone__area:has(.scan-dropzone__input:disabled) {
  opacity: 0.7;
}
.scan-dropzone__area:has(.scan-dropzone__input:disabled):hover {
  border-color: var(--site-line-strong);
  background: var(--site-field-bg);
}
.scan-dropzone__face {
  pointer-events: none;
  display: grid;
  justify-items: center;
  gap: var(--ui-space-2);
  text-align: center;
}
.scan-dropzone__icon {
  width: 2.85rem;
  height: 2.85rem;
  color: var(--site-accent);
}
.scan-dropzone__title { margin: 0; font-size: 1.05rem; font-weight: 700; color: var(--ui-color-ink); }
.scan-dropzone__title span { color: var(--site-accent); text-decoration: underline; text-underline-offset: 0.15em; }
.scan-dropzone__formats {
  margin: 0;
  font-family: var(--ui-font-mono);
  font-size: var(--ui-text-sm);
  color: var(--ui-color-muted);
}

.scan-sample {
  background: var(--site-surface);
  border: 1px solid var(--site-line);
  border-radius: 999px;
  color: var(--ui-color-ink);
  cursor: pointer;
  font: inherit;
  font-size: 0.8125rem;
  padding: 0.3125rem 0.75rem;
}

.scan-sample:hover { border-color: var(--site-accent); color: var(--site-accent); }

.scan-tiles {
  display: grid;
  gap: var(--ui-space-3);
  grid-template-columns: repeat(auto-fit, minmax(min(6.25rem, 100%), 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}

.scan-tiles li {
  background: var(--site-surface);
  border: 1px solid var(--site-line);
  border-radius: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  padding: var(--ui-space-3);
}

.scan-tiles__label {
  color: var(--ui-color-muted);
  font-size: 0.75rem;
  font-weight: 600;
}

.scan-tiles strong { font-size: var(--ui-text-lg); font-weight: 750; }
.scan-tiles .site-tile { height: 1.75rem; margin-bottom: var(--ui-space-2); width: 1.75rem; }
.scan-tiles .site-tile svg { height: 0.875rem; width: 0.875rem; }

.site-detect-grid {
  display: grid;
  gap: var(--ui-space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  margin-top: var(--ui-space-4);
}

.site-detect-grid .site-feature h3 { margin-top: 0; }

.site-detect-grid .site-feature h2 {
  font-size: var(--ui-text-base);
  margin: 0 0 var(--ui-space-2);
}

/* -- THE LANDING SCAN CARD ----------------------------------------------
   The comp's "Start a scan" panel beside its privacy panel. The card is an
   ENTRANCE, not the workbench: every control in it is a link to /scan,
   because scanning only happens on the no-egress surface. */
.site-scan-cta {
  align-items: stretch;
  display: grid;
  gap: var(--ui-space-5);
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  margin-block: var(--ui-space-5) var(--ui-space-6);
}

@media (max-width: 60rem) {
  .site-scan-cta { grid-template-columns: minmax(0, 1fr); }
}

.site-scan-card {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-4);
  padding: var(--ui-space-5);
}

.site-scan-card__title {
  font-size: var(--ui-text-lg);
  letter-spacing: -0.01em;
  margin: 0;
}

.site-scan-card__lede {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  margin: calc(-1 * var(--ui-space-3)) 0 0;
}

.site-scan-card__tabs {
  border-bottom: 1px solid var(--site-line);
  display: flex;
  gap: var(--ui-space-4);
  margin: 0;
}

.site-scan-card__tabs span,
.site-scan-card__tabs a {
  border-bottom: 2px solid transparent;
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  font-weight: 650;
  margin-bottom: -1px;
  padding-bottom: var(--ui-space-2);
  text-decoration: none;
}

.site-scan-card__tabs a:hover,
.site-scan-card__tabs a:focus-visible {
  color: var(--ui-color-ink);
}

.site-scan-card__tabs .is-active {
  border-bottom-color: var(--site-accent);
  color: var(--site-accent);
}

.site-scan-card__zone {
  align-items: center;
  border: 1.5px dashed var(--ui-color-border-strong);
  border-radius: 0.75rem;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-2);
  padding: var(--ui-space-6) var(--ui-space-5);
  text-align: center;
  text-decoration: none;
}

.site-scan-card__zone:hover,
.site-scan-card__zone:focus-visible {
  border-color: var(--site-accent);
}

.site-scan-card__zone svg {
  color: var(--ui-color-muted);
  height: 2rem;
  width: 2rem;
}

.site-scan-card__zone strong { font-size: var(--ui-text-base); }
.site-scan-card__zone span { color: var(--ui-color-muted); font-size: var(--ui-text-sm); }

.site-scan-card__meta {
  color: var(--ui-color-muted);
  font-size: 0.8125rem;
  margin: 0;
}

.site-scan-card__cta {
  box-sizing: border-box;
  font-size: var(--ui-text-base);
  gap: var(--ui-space-2);
  justify-content: center;
  padding-block: var(--ui-space-3);
  width: 100%;
}

.site-scan-card__cta svg { height: 1.125rem; width: 1.125rem; }

.site-privacy-panel {
  align-items: center;
  justify-content: center;
  background: var(--site-accent-soft);
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-4);
  padding: var(--ui-space-5);
  text-align: center;
}

.site-privacy-panel__mark {
  background: var(--site-card);
  border-radius: 999px;
  height: 3rem;
  width: 3rem;
}

.site-privacy-panel__mark svg { height: 1.5rem; width: 1.5rem; }

.site-privacy-panel h2 {
  font-size: var(--ui-text-lg);
  margin: 0;
}

.site-privacy-panel ul {
  align-self: stretch;
  display: grid;
  gap: var(--ui-space-3);
  list-style: none;
  margin: 0;
  padding: 0;
  text-align: start;
}

.site-privacy-panel li {
  align-items: flex-start;
  color: var(--ui-color-muted);
  display: flex;
  font-size: var(--ui-text-sm);
  gap: var(--ui-space-3);
}

.site-privacy-panel li svg {
  color: var(--site-accent);
  flex: none;
  height: 1.125rem;
  margin-top: 0.1rem;
  width: 1.125rem;
}

.site-privacy-panel > a {
  font-size: var(--ui-text-sm);
  font-weight: 650;
}

.site-warning--slim {
  font-size: var(--ui-text-sm);
  margin-block: var(--ui-space-5);
  padding: var(--ui-space-3) var(--ui-space-4);
}

/* The comp's compact feature strip: four items sharing one card, each an
   icon circle beside its words. */
.site-section--flush {
  margin-block: var(--ui-space-5);
}

.site-section--flush + .site-section {
  border-top: 0;
  padding-top: 0;
}

.site-feature-band {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  display: grid;
  gap: var(--ui-space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  padding: var(--ui-space-5);
}

.site-feature--flat {
  align-items: flex-start;
  background: none;
  border: 0;
  border-radius: 0;
  display: flex;
  gap: var(--ui-space-3);
  padding: 0;
}

.site-feature--flat .site-tile {
    flex: none;
}

.site-feature--flat h3 {
  font-size: var(--ui-text-sm);
  margin: 0 0 0.25rem;
}

.site-banner {
  align-items: center;
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-3) var(--ui-space-4);
  margin-block: var(--ui-space-5);
  padding: var(--ui-space-4) var(--ui-space-5);
}

.site-banner__icon {
  border-radius: 999px;
  height: 2rem;
  width: 2rem;
}

.site-banner__icon svg { height: 1rem; width: 1rem; }

.site-banner p {
  color: var(--ui-color-muted);
  flex: 1 1 20rem;
  font-size: var(--ui-text-sm);
  margin: 0;
}

.site-banner p strong { color: var(--site-accent); }

.site-banner > a {
  font-size: var(--ui-text-sm);
  font-weight: 650;
  margin-left: auto;
  white-space: nowrap;
}

/* Local-only preview of the reviewed ad slot; never rendered in production. */
.site-ad-preview {
  border: 1.5px dashed var(--ui-color-border-strong);
  border-radius: 1rem;
  margin-block: var(--ui-space-5);
  padding: var(--ui-space-5);
  text-align: center;
}

.site-ad-preview__label {
  color: var(--ui-color-muted);
  display: block;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  margin-bottom: var(--ui-space-2);
  text-transform: uppercase;
}

.site-ad-preview p {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  margin: 0 auto;
  max-width: 52ch;
}

/* -- EDITORIAL COMPS ----------------------------------------------------
   The wide editorial surface: value-prop strip, step flow, technique grid,
   the see-versus-reads panel, the promise band and the sidebar. All of it
   renders from SiteContent arrays; nothing here binds behaviour. */
.site-editorial {
  max-width: none;
}

.site-editorial .site-hero__lede {
  max-width: 60ch;
}

.site-valueprops {
  display: grid;
  gap: var(--ui-space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr));
  list-style: none;
  margin: var(--ui-space-5) 0;
  padding: 0;
}

.site-valueprops li {
  align-content: start;
  display: grid;
  gap: 0.25rem;
  justify-items: start;
}

.site-valueprops strong { font-size: var(--ui-text-sm); }

.site-valueprops li > span:last-child {
  color: var(--ui-color-muted);
  font-size: 0.8125rem;
}

.site-valueprops .site-tile {
  border-radius: 999px;
  margin-bottom: var(--ui-space-2);
}

.site-editorial-grid {
  align-items: start;
  display: grid;
  gap: var(--ui-space-6);
  grid-template-columns: minmax(0, 8fr) minmax(0, 4fr);
}

@media (max-width: 60rem) {
  .site-editorial-grid { grid-template-columns: minmax(0, 1fr); }
}

.site-editorial-main > .site-section:first-child { margin-top: var(--ui-space-5); }

/* An editorial page with no aside (e.g. How it works) renders its main column
   alone. The shared 44rem prose cap below would otherwise leave a narrow band
   hugging the left under a full-width hero, and its step/detail grids cramped
   into three ~220px columns. Widen the column so the grids breathe and stay
   aligned with the hero's left edge; running prose keeps the readable 44rem
   measure so lines never grow uncomfortably long. */
.site-editorial-solo .site-editorial-main {
  max-width: 60rem;
}
/* Cap running prose only — NOT the step/detail grids (which are themselves
   ol/ul and must fill the widened column). Paragraphs inside grid cards are
   already narrower than this, so the cap leaves them untouched. */
.site-editorial-solo .site-editorial-main :is(p, blockquote, .site-hero__lede) {
  max-width: 44rem;
}

/* Anchored headings clear the sticky masthead too, so a jump link never lands
   with its target hidden under the bar. */
:where(.site-section, h2, h3, h4)[id] {
  scroll-margin-top: calc(var(--site-masthead-h) + var(--ui-space-3));
}

.site-editorial-aside {
  background: var(--site-card);
  position: sticky;
  /* Clear the sticky masthead, or the card's heading tucks up under the bar
     as the page scrolls. */
  top: calc(var(--site-masthead-h) + var(--ui-space-3));
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  display: grid;
  gap: var(--ui-space-4);
  margin-top: var(--ui-space-5);
  padding: var(--ui-space-5);
}

.site-editorial-aside h2 {
  color: var(--site-accent);
  font-size: var(--ui-text-lg);
  margin: 0;
}

.site-editorial-aside > p {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  margin: 0;
}

.site-aside-box {
  border: 1px solid var(--site-line);
  border-radius: 0.75rem;
  padding: var(--ui-space-4);
}

.site-aside-box h3 {
  font-size: var(--ui-text-sm);
  margin: 0 0 var(--ui-space-3);
}

.site-aside-box ul {
  display: grid;
  gap: var(--ui-space-3);
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-aside-box li {
  align-items: flex-start;
  display: flex;
  font-size: var(--ui-text-sm);
  gap: var(--ui-space-2);
}

.site-aside-box__mark {
  color: var(--site-danger-ink);
  flex: none;
  height: 1.05rem;
  margin-top: 0.1rem;
  width: 1.05rem;
}

.site-aside-box__mark svg { height: 100%; width: 100%; }

.site-aside-cta {
  border-top: 1px solid var(--site-line);
  display: grid;
  gap: var(--ui-space-3);
  padding-top: var(--ui-space-4);
}

.site-aside-cta h3 { font-size: var(--ui-text-base); margin: 0; }

.site-aside-cta p {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  margin: 0;
}

.site-aside-cta__button {
  box-sizing: border-box;
  justify-content: center;
  width: 100%;
}

.site-aside-cta__button svg { height: 1rem; width: 1rem; }

.site-steps-flow {
  counter-reset: none;
  display: grid;
  gap: var(--ui-space-4);
  /* A wider minimum so the six steps settle at three balanced columns (3+3)
     in the widened editorial column rather than auto-fitting to five with a
     lone orphan; still collapses to two, then one, on narrower screens. */
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  list-style: none;
  margin: var(--ui-space-5) 0 0;
  padding: 0;
}

.site-steps-flow li {
  align-content: start;
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 0.875rem;
  display: grid;
  gap: var(--ui-space-2);
  justify-items: start;
  padding: var(--ui-space-4);
  position: relative;
}

.site-steps-flow__number {
  align-items: center;
  background: var(--ui-color-accent);
  border-radius: 999px;
  color: var(--ui-color-accent-ink);
  display: inline-flex;
  font-size: 0.75rem;
  font-weight: 700;
  height: 1.5rem;
  justify-content: center;
  left: var(--ui-space-3);
  position: absolute;
  top: calc(-1 * var(--ui-space-2));
  width: 1.5rem;
}

.site-steps-flow li .site-tile { margin-top: var(--ui-space-2); }

.site-steps-flow h3 { font-size: var(--ui-text-sm); margin: var(--ui-space-2) 0 0; }

.site-steps-flow p {
  color: var(--ui-color-muted);
  font-size: 0.8125rem;
  margin: 0;
}

.site-underhood {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  display: grid;
  gap: var(--ui-space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  margin-top: var(--ui-space-5);
  padding: var(--ui-space-5);
}

.site-underhood__item {
  align-items: flex-start;
  display: flex;
  gap: var(--ui-space-3);
}

.site-underhood__item .site-tile { flex: none; }

.site-underhood__item h3 { font-size: var(--ui-text-sm); margin: 0 0 0.25rem; }

.site-underhood__item p {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  margin: 0;
}

.site-compare {
  align-items: stretch;
  display: grid;
  gap: var(--ui-space-4);
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  margin-top: var(--ui-space-5);
}

@media (max-width: 60rem) {
  .site-compare { grid-template-columns: minmax(0, 1fr); }
  .site-compare .site-compare__arrow { justify-self: center; transform: rotate(90deg); }
}

.site-compare__pane {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  padding: var(--ui-space-5);
}

.site-compare__pane--findings {
  background: var(--site-accent-soft);
}

.site-compare__pane h3 { font-size: var(--ui-text-base); margin: 0; }

.site-compare__caption {
  color: var(--ui-color-muted);
  font-size: 0.8125rem;
  margin: 0.25rem 0 var(--ui-space-4);
}

.site-compare__doc {
  background: var(--site-surface);
  border: 1px solid var(--site-line);
  border-radius: 0.75rem;
  font-family: var(--ui-font-serif, Georgia, serif);
  padding: var(--ui-space-4);
}

.site-compare__doc p {
  font-size: var(--ui-text-sm);
  margin: 0 0 var(--ui-space-3);
}

.site-compare__doc p:last-child { margin-bottom: 0; }

.site-compare__doc-heading { font-weight: 700; }

.site-compare__arrow {
  align-items: center;
  align-self: center;
  background: var(--ui-color-accent);
  border-radius: 999px;
  color: var(--ui-color-accent-ink);
  display: inline-flex;
  font-size: 1.1rem;
  height: 2.25rem;
  justify-content: center;
  width: 2.25rem;
}

.site-compare__pane--findings ul {
  display: grid;
  gap: var(--ui-space-3);
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-compare__item {
  align-items: center;
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 0.625rem;
  display: flex;
  font-size: var(--ui-text-sm);
  gap: var(--ui-space-3);
  padding: var(--ui-space-3);
}

.site-compare__item--danger { border-inline-start: 0.25rem solid var(--site-danger-ink); }
.site-compare__item--warn { border-inline-start: 0.25rem solid var(--site-warn-ink); }
.site-compare__item--accent { border-inline-start: 0.25rem solid var(--site-accent); }
.site-compare__item--ok { border-inline-start: 0.25rem solid var(--site-ok-ink); }

.site-compare__item .site-tile { border-radius: 999px; flex: none; height: 2rem; width: 2rem; }
.site-compare__item .site-tile svg { height: 1rem; width: 1rem; }

.site-compare__note {
  color: var(--ui-color-muted);
  font-size: 0.8125rem;
  margin: var(--ui-space-3) 0 0;
}

.site-stats-band {
  align-items: center;
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 1rem;
  display: grid;
  gap: var(--ui-space-5);
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  margin-top: var(--ui-space-5);
  padding: var(--ui-space-5);
}

@media (max-width: 60rem) {
  .site-stats-band { grid-template-columns: minmax(0, 1fr); }
}

.site-stats-band__lead {
  align-items: flex-start;
  display: flex;
  gap: var(--ui-space-3);
}

.site-stats-band__lead .site-tile { flex: none; }

.site-stats-band__lead h3 { font-size: var(--ui-text-base); margin: 0 0 0.25rem; }

.site-stats-band__lead p {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  margin: 0;
}

.site-stats-band ul {
  display: grid;
  gap: var(--ui-space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-stats-band li {
  align-content: start;
  display: grid;
  gap: 0.125rem;
  justify-items: start;
}

.site-stats-band li strong { font-size: var(--ui-text-sm); }

.site-stats-band li > span:last-child {
  color: var(--ui-color-muted);
  font-size: 0.8125rem;
}

.site-stats-band__check {
  color: var(--site-ok-ink);
  height: 1.25rem;
  margin-bottom: var(--ui-space-2);
  width: 1.25rem;
}

.site-stats-band__check svg { height: 100%; width: 100%; }

.site-detect-grid .site-feature .site-tile {
  border-radius: 999px;
  margin-bottom: var(--ui-space-3);
}

/* Inside the sidebar layout the main column is narrower, so the detect
   cards drop to the comp's three-across density. */
.site-editorial-grid .site-detect-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(11.5rem, 100%), 1fr));
}

/* -- GOLD-STANDARD PASS -------------------------------------------------
   The audit round before launch: interaction affordances, workbench
   states, mobile chrome, and print. Property-side only. */

/* Subtle color transitions on every interactive surface. Color-only, so
   nothing moves and no reduced-motion exception is owed. */
.site-nav a,
.site-theme-toggle,
.scan-sample,
.scan-tabs [role="tab"],
.site-scan-card__tabs span,
.site-scan-card__zone,
.site-footer a,
.site-privacy-panel > a,
.site-banner > a {
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}

.scan-tabs [role="tab"]:hover {
  border-bottom-color: var(--site-line);
  color: var(--ui-color-ink);
}

/* Hit areas: nav links, sample chips, the toggle and footer links reach
   comfortable touch sizes without shifting the visual layout. */
.site-nav a {
  display: inline-block;
  margin: calc(-1 * var(--ui-space-2)) calc(-1 * var(--ui-space-1));
  padding: var(--ui-space-2) var(--ui-space-1);
}

.scan-sample {
  min-height: 2.25rem;
  padding: 0.4375rem 0.875rem;
}

.site-theme-toggle {
  min-height: 2.25rem;
}

.site-footer__links a {
  display: inline-block;
  margin-block: calc(-1 * var(--ui-space-2));
  padding-block: var(--ui-space-2);
}

.site-footer a:hover,
.site-footer a:focus-visible {
  color: #ffffff;
}

.site-scan-card__zone:hover,
.site-scan-card__zone:focus-visible {
  background: var(--site-accent-soft);
}

/* Measure caps the shared 72ch rule cannot reach. */
.scan-privacy-strip p,
.site-footer p {
  max-width: 72ch;
}

/* Reading column centres on prose-only pages; wide editorial unaffected. */
.site-prose {
  margin-inline: auto;
}

/* The masthead is fixed dark in both schemes, so its accents hold one
   palette instead of flipping with the theme against an unchanged bar. */
.ui-header .site-badge {
  background: #2563eb;
  color: #ffffff;
}

.ui-header .ui-btn--accent {
  /* Quiet bordered pill, matched to the theme toggle — no loud fill, so the
     primary action sits in the masthead's own restrained palette. The base
     .ui-btn carries a 2.4rem min-height and generous padding sized for a body
     button; in the masthead it must instead sit at the toggle's compact height
     so the pair reads as one control set. */
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.22);
  color: #ffffff;
  border-radius: 999px;
  box-shadow: none;
  min-height: 0;
  height: 2.25rem;
  padding-block: 0;
  padding-inline: 1.15rem;
  line-height: 1;
}

.ui-header .site-brand__mark {
  color: #60a5fa;
}

.site-nav a[aria-current="page"] {
  text-decoration-color: #60a5fa;
}

/* -- WORKBENCH STATES ----------------------------------------------- */

/* The progress row exists only while the runtime says the workbench is
   busy; an indeterminate bar at rest reads as a stuck scan. */
.ui-utility-workbench:not([aria-busy="true"]) .ui-utility-progress {
  display: none;
}

/* Before the first result, the export caution and report actions serve
   nothing and the empty panel should say only one thing. */
.scan-panel--results:has(.ui-utility-result:empty) .site-export-warning,
.scan-panel--results:has(.ui-utility-result:empty) .site-actions {
  display: none;
}

/* NOTHING HAS BEEN SCANNED YET, SO SAY NOTHING.
   Before a scan the panel rendered a finished-looking verdict: the heading
   "Scan results" over five counters all reading 0. With JavaScript blocked —
   and this audience runs blockers — that is the whole page: a completed scan
   of a document nobody submitted, reporting no findings. The empty result is
   the pre-scan state, which the rule above already relies on. */
.scan-panel--results:has(.ui-utility-result:empty) .scan-results-head,
.scan-panel--results:has(.ui-utility-result:empty) .scan-tiles,
.scan-panel--results:has(.ui-utility-result:empty) .scan-results-note,
.scan-panel--results:has(.ui-utility-result:empty) .scan-results-footnote {
  display: none;
}

/* THE VERDICT MUST BE ON SCREEN WHEN THE PAGE STOPS MOVING.
   The post-scan scroll landed the results panel under the sticky masthead, so
   on a phone the one sentence this product exists to deliver was above the
   fold line and invisible. Same allowance the anchored headings already take. */
.scan-panel--results {
  scroll-margin-top: calc(var(--site-masthead-h) + var(--ui-space-3));
}

/* AN UNFINISHED CHECK IS NOT A CLEAN ONE.
   "We couldn't check this" rendered in the same green as "No red flags found",
   with five counters reading zero — so a document the scanner could not read
   looked exactly like a document it had cleared. Neutral chrome, and the
   zeroed counters read as absent rather than as a score. */
.scan-panel--results:has([data-utility-outcome="scanner.incomplete"]) {
  background: var(--site-card);
  border-color: var(--site-line);
}
.scan-panel--results:has([data-utility-outcome="scanner.incomplete"]) .scan-tiles {
  opacity: 0.55;
}

/* The cleared status region means the worker is ready; say so. */
.ui-utility-workbench [data-utility-role="status"]:empty::before {
  color: var(--ui-color-muted);
  content: "Ready — nothing leaves this browser.";
}

/* The empty state carries its own glyph, so it reads as intentional. */
.ui-utility-result:empty {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='1.6'%3E%3Cpath d='M6 3h7l5 5v13H6V3Z'/%3E%3Cpath d='M13 3v5h5'/%3E%3Ccircle cx='11' cy='13.5' r='2.4'/%3E%3Cpath d='m12.8 15.3 2.7 2.7'/%3E%3C/svg%3E") no-repeat center calc(var(--ui-space-7) - 0.5rem) / 2.5rem;
  padding-top: calc(var(--ui-space-7) + 2.5rem);
}

/* Summary rows read as a ledger: label left, value right. */
.scan-panel--results [data-utility-view="summary"] dl > div {
  display: grid;
  gap: 0 var(--ui-space-3);
  grid-template-columns: minmax(11rem, 16rem) 1fr;
}

.scan-panel--results [data-utility-view="summary"] dd {
  font-weight: 600;
  margin: 0;
}

@media (max-width: 40rem) {
  .scan-panel--results [data-utility-view="summary"] dl > div {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* A clean result is the product's most common outcome and earns a
   positive signal: the summary card goes ok-toned when the rendered
   result carries no findings — keyed off the result itself, so the
   card can never disagree with what is printed beside it. */
.scan-panel--results .ui-utility-result:has([data-utility-view="summary"]):not(:has([data-utility-view="findings"] [data-severity])) [data-utility-view="summary"] {
  background: var(--site-ok-soft);
  border-inline-start: 0.35rem solid var(--site-ok-ink);
  border-radius: 0.75rem;
  padding-inline-start: var(--ui-space-4);
}

/* Severity is the card's most scannable fact; render it as a chip. */
.scan-panel--results [data-utility-view="findings"] article[data-severity] > h3 + p {
  border-radius: 999px;
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 650;
  padding: 0.125rem 0.625rem;
}

.scan-panel--results [data-utility-view="findings"] article[data-severity="high"] > h3 + p {
  background: var(--site-danger-soft);
  color: var(--site-danger-ink);
}

.scan-panel--results [data-utility-view="findings"] article[data-severity]:not([data-severity="high"]) > h3 + p {
  background: var(--site-warn-soft);
  color: var(--site-warn-ink);
}

/* The four report actions read as one compact toolbar on the results
   panel, not a list of body links. */
.scan-panel--results .site-actions {
  gap: var(--ui-space-2) var(--ui-space-3);
}

.scan-panel--results .site-actions .ui-btn--quiet {
  border: 1px solid var(--site-line);
  border-radius: 999px;
  font-size: var(--ui-text-sm);
  padding: 0.25rem 0.75rem;
  text-decoration: none;
}

@media (max-width: 30rem) {
  .scan-tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* === RESULTS OVERHAUL — a plain-language verdict, then scannable cards ==
   The result is core-rendered semantic HTML (summary dl, coverage list,
   finding articles, limitations). This restyles it into something a
   non-expert can read at a glance: the answer is loud, each finding is a
   card whose passage reads as code and whose plain-English meaning leads,
   and the detector bookkeeping is demoted to a quiet footer. */

/* 1 · Summary → a verdict card. The headline answer is large; a red dot
   leads it when anything was flagged. The 13-row ledger becomes small,
   two-tone metadata beneath the verdict rather than the main event. */
.scan-panel--results [data-utility-view="summary"] {
  border: 1px solid var(--site-line);
  border-radius: 0.9rem;
  padding: var(--ui-space-5);
  background: var(--site-card);
}
.scan-panel--results [data-utility-view="summary"] > p:first-child {
  margin: 0 0 var(--ui-space-4);
  font-size: clamp(1.15rem, 2.4vw, 1.4rem);
  font-weight: 760;
  letter-spacing: -0.015em;
  line-height: 1.25;
  color: var(--ui-color-ink);
  display: flex;
  align-items: center;
  gap: var(--ui-space-3);
}
.scan-panel--results .ui-utility-result:has([data-utility-view="findings"] [data-severity]) [data-utility-view="summary"] > p:first-child::before {
  content: "";
  flex: none;
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 999px;
  background: var(--site-danger-ink);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--site-danger-ink) 20%, transparent);
}
.scan-panel--results [data-utility-view="summary"] dl {
  margin: 0;
  display: grid;
  gap: var(--ui-space-2);
  font-size: var(--ui-text-sm);
  line-height: 1.5;
}
.scan-panel--results [data-utility-view="summary"] dt {
  color: var(--ui-color-muted);
  font-weight: 500;
}
.scan-panel--results [data-utility-view="summary"] dd {
  color: var(--ui-color-ink);
  font-weight: 600;
}

/* 2 · Coverage → a compact row of inspected-state pills. */
.scan-panel--results [data-utility-view="coverage"] ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-2);
}
.scan-panel--results [data-utility-view="coverage"] li {
  font-size: var(--ui-text-sm);
  font-weight: 600;
  padding: 0.2rem 0.7rem;
  border-radius: 999px;
  background: var(--site-ok-soft);
  color: var(--site-ok-ink);
}
.scan-panel--results [data-utility-view="coverage"] li[data-state]:not([data-state="inspected"]) {
  background: var(--site-warn-soft);
  color: var(--site-warn-ink);
}

/* 3 · Findings → cards. A severity rail, the passage as a dark code block,
   the plain-English reading in body ink, and the detector references /
   evidence locations / objective demoted to a small muted footer grid. */
.scan-panel--results [data-utility-view="findings"] > h2 {
  margin-bottom: var(--ui-space-3);
}
.scan-panel--results [data-utility-view="findings"] article[data-severity] {
  display: grid;
  gap: var(--ui-space-3);
  margin-top: var(--ui-space-4);
  padding: var(--ui-space-4);
  border: 1px solid var(--site-line);
  border-inline-start: 0.3rem solid var(--site-warn-ink);
  border-radius: 0.8rem;
  background: var(--site-card);
  box-shadow: var(--site-shadow-sm);
}
.scan-panel--results [data-utility-view="findings"] article[data-severity="high"] {
  border-inline-start-color: var(--site-danger-ink);
}
.scan-panel--results [data-utility-view="findings"] article[data-severity] > h3 {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
}
/* The passage reads as code — the scanner's own evidence surface. */
.scan-panel--results .ui-utility-visible-excerpt {
  margin: 0;
  padding: var(--ui-space-3) var(--ui-space-4);
  background: var(--scanner-evidence-bg);
  color: var(--scanner-evidence-ink);
  border: 1px solid var(--ui-color-border-strong);
  border-radius: 0.6rem;
  font-family: var(--ui-font-mono);
  font-size: 0.82rem;
  line-height: 1.65;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  direction: ltr;
  unicode-bidi: isolate;
}
/* The plain-English reading + action (the paragraphs after the metadata)
   stay in body ink and lead the eye. */
.scan-panel--results [data-utility-view="findings"] article[data-severity] > p:not(:first-of-type) {
  margin: 0;
  color: var(--ui-color-ink);
  line-height: 1.55;
}
.scan-panel--results [data-utility-view="findings"] article[data-severity] > p:last-of-type {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
}
/* The four detector dl blocks collapse into one compact muted footer. */
.scan-panel--results [data-utility-view="findings"] article[data-severity] dl {
  margin: 0;
  font-size: var(--ui-text-sm);
  line-height: 1.4;
}
.scan-panel--results [data-utility-view="findings"] article[data-severity] dl + dl {
  margin-top: 0.15rem;
}
.scan-panel--results [data-utility-view="findings"] article[data-severity] dl > div {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.scan-panel--results [data-utility-view="findings"] article[data-severity] dl dt {
  color: var(--ui-color-muted);
  font-weight: 500;
}
.scan-panel--results [data-utility-view="findings"] article[data-severity] dl dt::after { content: ":"; }
.scan-panel--results [data-utility-view="findings"] article[data-severity] dl dd {
  margin: 0;
  color: var(--ui-color-soft, var(--ui-color-muted));
  font-weight: 600;
}

/* 4 · Limitations → a quiet closing note, not a loud section. */
.scan-panel--results [data-utility-view="limitations"] {
  margin-top: var(--ui-space-5);
  padding-top: var(--ui-space-4);
  border-top: 1px solid var(--site-line);
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
}
.scan-panel--results [data-utility-view="limitations"] h2 {
  font-size: 0.72rem;
  font-family: var(--ui-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ui-color-muted);
  margin-bottom: var(--ui-space-2);
}

/* -- EDITORIAL BALANCE ---------------------------------------------- */

.site-detect-grid .site-feature {
  align-items: flex-start;
  display: flex;
  flex-direction: column;
}

.site-detect-grid .site-feature p {
  margin-bottom: var(--ui-space-3);
}

.site-detect-grid .site-example-chip {
  margin-top: auto;
}

/* The In-depth quartet reads as a balanced two-by-two on wide screens. */
@media (min-width: 60rem) {
  .site-indepth {
    display: grid;
    gap: var(--ui-space-6) var(--ui-space-7);
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .site-indepth .site-section {
    border-top: 1px solid var(--ui-color-border);
    margin-block: 0;
    padding-top: var(--ui-space-6);
  }
}

.site-section--bordered {
  border-top: 1px solid var(--ui-color-border);
  padding-top: var(--ui-space-7);
}

@media (max-width: 60rem) {
  /* Two near-identical primary CTAs would stack within one screen. */
  .site-aside-cta {
    display: none;
  }

  .site-editorial-aside {
    position: static;
  }
}

/* -- MOBILE CHROME -------------------------------------------------- */

@media (max-width: 40rem) {
  .site-brand__promise {
    display: none;
  }

  .site-nav {
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .site-nav a {
    white-space: nowrap;
  }

  .site-kicker--pill {
    font-size: 0.75rem;
    letter-spacing: 0.02em;
  }
}

/* -- FORCED COLORS AND PRINT ---------------------------------------- */

@media (forced-colors: active) {
  .scan-tabs [role="tab"],
  .site-scan-card__tabs span {
    border-bottom-style: none;
    padding-bottom: calc(var(--ui-space-3) + 2px);
  }

  .scan-tabs [role="tab"][aria-selected="true"],
  .site-scan-card__tabs .is-active {
    border-bottom: 2px solid Highlight;
    padding-bottom: var(--ui-space-3);
  }

  .site-hero-art__line,
  .site-hero-art__dots i,
  .site-hero-art__glass::after {
    background: CanvasText;
  }
}

@media print {
  .ui-header {
    background: none;
    border-bottom: 1px solid #000000;
  }

  .ui-header .site-brand__name,
  .ui-header .site-brand__promise,
  .site-nav a {
    color: #000000;
  }

  .site-brand__actions,
  .scan-samples,
  .site-actions,
  .site-theme-toggle {
    display: none;
  }

  .site-example {
    background: #ffffff;
    border-color: #000000;
    color: #000000;
  }
}

/* ==========================================================================
   ELEVATION LAYER (v1.6) — a "forensic scanner" identity built on the tokens
   above: layered depth, a monospace technical eyebrow, an indigo authority +
   cyan scan-signal palette, section rhythm, and disciplined micro-interaction.
   Appended last so it refines the composition without rewriting a single rule.
   ========================================================================== */

/* 1 · Ground the page: a faint scan-grid gives the flat surface depth, drawn
   with a gradient so nothing is fetched. */
.ui-page {
  background:
    radial-gradient(circle at 1px 1px, var(--site-grid-dot) 1px, transparent 1.4px) 0 0 / 26px 26px,
    linear-gradient(180deg, var(--site-surface) 0%, var(--site-surface-2) 100%);
  background-attachment: fixed;
}

::selection { background: color-mix(in srgb, var(--site-scan) 34%, transparent); }

:where(a, button, summary, .ui-btn, .site-feature, .scan-sample, .scan-tiles li,
  .site-scan-card, .site-theme-toggle, .site-example-chip, .scan-tabs [role="tab"],
  .site-detect-grid .site-feature, .site-source-list a) {
  transition: color var(--site-dur) var(--site-ease),
    background-color var(--site-dur) var(--site-ease),
    border-color var(--site-dur) var(--site-ease),
    box-shadow var(--site-dur) var(--site-ease),
    transform var(--site-dur) var(--site-ease);
}

:where(a, button, [role="tab"], summary, input, textarea):focus-visible {
  outline: 2px solid transparent;
  box-shadow: var(--site-ring);
  border-radius: 0.4rem;
}

/* 2 · Masthead: sticky, faintly luminous, with the brand mark lit by the
   scan accent. */
.ui-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background:
    radial-gradient(120% 140% at 0% 0%, rgba(37, 99, 235, 0.28), transparent 55%),
    linear-gradient(180deg, #10122b 0%, var(--site-ink-deep) 100%);
  backdrop-filter: saturate(1.2);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05), 0 10px 30px -20px rgba(0, 0, 0, 0.7);
}
.site-brand__mark {
  color: var(--site-scan);
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--site-scan) 55%, transparent));
}
.site-badge {
  background: linear-gradient(135deg, var(--site-scan), var(--site-accent));
  color: #fff;
  box-shadow: 0 4px 12px -4px rgba(6, 182, 212, 0.6);
}

/* 3 · The eyebrow becomes a monospace scan marker — the product speaks in
   precise, versioned terms, so its labels should read that way. */
.site-kicker {
  font-family: var(--ui-font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--site-accent);
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}
.site-kicker::before {
  content: "";
  width: 1.5rem;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--site-scan), var(--site-accent));
  box-shadow: 0 0 8px color-mix(in srgb, var(--site-scan) 60%, transparent);
}
.site-kicker--pill {
  font-family: var(--ui-font-mono);
  letter-spacing: 0.08em;
  background: linear-gradient(180deg, var(--site-accent-soft), color-mix(in srgb, var(--site-accent-soft) 60%, var(--site-card)));
  border: 1px solid color-mix(in srgb, var(--site-accent) 22%, var(--site-line));
  box-shadow: var(--site-shadow-sm);
}
.site-kicker--pill::before { display: none; }

/* 4 · Hero: bigger, tighter headline; the accent word gets a cyan scan
   highlight, as if the scanner marked it. */
.site-hero__title {
  font-size: clamp(2.35rem, 5vw, 3.6rem);
  letter-spacing: -0.037em;
  line-height: 1.03;
}
.site-hero__title em {
  color: var(--site-accent);
  background: linear-gradient(180deg, transparent 64%, color-mix(in srgb, var(--site-scan) 32%, transparent) 64%, color-mix(in srgb, var(--site-scan) 32%, transparent) 92%, transparent 92%);
}
.site-hero__lede { color: var(--ui-color-muted); font-size: clamp(1.06rem, 1.5vw, 1.28rem); }

/* 5 · Buttons — the primary CTA gains an indigo gradient, a soft glow and a
   press response; quiet actions stay calm. */
.ui-btn--accent, .ui-btn--primary {
  /* A solid base under the gradient so the contrast gate can composite the
     button text against a real colour; the gradient still paints over it, and
     its range matches the token so measured and visible contrast agree. */
  background-color: var(--ui-color-accent);
  background-image: linear-gradient(180deg, var(--site-accent) 0%, var(--site-accent-strong) 100%);
  border-color: transparent;
  box-shadow: var(--site-shadow-accent), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  font-weight: 650;
}
.ui-btn--accent:hover, .ui-btn--primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 16px 34px -14px rgba(37, 99, 235, 0.62), inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.ui-btn--accent:active, .ui-btn--primary:active { transform: translateY(0); }
.ui-header .ui-btn--accent:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.4);
  box-shadow: none;
  transform: none;
}

/* 6 · Cards — layered elevation, a hover lift, and a hairline scan-line along
   the top edge so they read as objects sitting on the grid. */
.site-feature, .site-scan-card, .site-cta-panel, .site-privacy-panel,
.scan-panel, .site-aside-box, .site-detect-grid .site-feature, .scan-tiles li {
  box-shadow: var(--site-shadow-sm);
  border-radius: var(--site-r-md);
  position: relative;
  overflow: clip;
}
.site-feature::before, .site-scan-card::before, .scan-panel::before,
.site-detect-grid .site-feature::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--site-accent) 55%, transparent), transparent);
  opacity: 0;
  transition: opacity var(--site-dur) var(--site-ease);
}
.site-feature:hover, .site-detect-grid .site-feature:hover {
  transform: translateY(-3px);
  box-shadow: var(--site-shadow-md);
  border-color: var(--site-line-strong);
}
.site-feature:hover::before, .site-detect-grid .site-feature:hover::before { opacity: 1; }

/* Icon tiles gain a soft gradient + ring for depth. */
.site-tile {
  border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), var(--site-shadow-sm);
}
.site-tile--accent { background: linear-gradient(160deg, var(--site-accent-soft), color-mix(in srgb, var(--site-scan-soft) 50%, var(--site-accent-soft))); }

/* 7 · The landing scan card is the entrance — make it the brightest object. */
.site-scan-card {
  box-shadow: var(--site-shadow-lg);
  border-color: color-mix(in srgb, var(--site-accent) 16%, var(--site-line));
}
.site-privacy-panel {
  background: linear-gradient(165deg, var(--site-accent-soft), color-mix(in srgb, var(--site-scan-soft) 40%, var(--site-card)));
  border-color: color-mix(in srgb, var(--site-accent) 20%, var(--site-line));
}
.site-scan-card__zone {
  background:
    radial-gradient(circle at 1px 1px, var(--site-grid-dot) 1px, transparent 1.4px) 0 0 / 20px 20px,
    var(--site-surface);
  transition: border-color var(--site-dur) var(--site-ease), background-color var(--site-dur) var(--site-ease);
}
.site-scan-card__zone:hover { border-color: var(--site-accent); }

/* 8 · Workbench polish: elevated panels, tab as a lit underline, sample
   chips, and data tiles with a monospace figure. */
.scan-panel { box-shadow: var(--site-shadow-md); }
.scan-tabs [role="tab"][aria-selected="true"] {
  border-bottom-color: var(--site-accent);
  color: var(--site-accent);
  text-shadow: 0 0 12px color-mix(in srgb, var(--site-accent) 30%, transparent);
}
.scan-sample:hover { border-color: var(--site-accent); color: var(--site-accent); box-shadow: var(--site-shadow-sm); transform: translateY(-1px); }
.scan-tiles li:hover { border-color: var(--site-line-strong); box-shadow: var(--site-shadow-sm); }
.scan-tiles strong { font-family: var(--ui-font-mono); letter-spacing: -0.02em; color: var(--ui-color-ink); }
.scan-privacy-strip {
  background: linear-gradient(180deg, var(--site-scan-soft), var(--site-card));
  border-color: color-mix(in srgb, var(--site-scan) 22%, var(--site-line));
  box-shadow: var(--site-shadow-sm);
}
.scan-privacy-strip svg { color: var(--site-scan); }

/* 9 · Section rhythm — tinted feature bands and a true dark "evidence" panel
   so long pages breathe instead of blurring into one white column. */
.site-feature-band, .site-stats-band {
  background: linear-gradient(180deg, var(--site-card), var(--site-surface-2));
  border: 1px solid var(--site-line);
  border-radius: var(--site-r-lg);
  box-shadow: var(--site-shadow-sm);
  padding: var(--ui-space-6);
}
.site-example {
  background:
    linear-gradient(180deg, rgba(6, 182, 212, 0.05), transparent 40%),
    var(--scanner-evidence-bg);
  border: 1px solid rgba(96, 165, 250, 0.28);
  box-shadow: var(--site-shadow-lg);
  border-radius: var(--site-r-md);
  position: relative;
}
.site-example::before {
  content: none;
  position: absolute;
  top: 0.75rem;
  right: 0.9rem;
  font-family: var(--ui-font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.2em;
  color: var(--site-scan);
  opacity: 0.7;
}

/* 10 · Tables read like a data grid: sunken monospace-friendly header,
   hairline rows, a hover highlight. */
.site-table { border: 1px solid var(--site-line); border-radius: var(--site-r-md); overflow: clip; box-shadow: var(--site-shadow-sm); }
.site-table th {
  background: var(--site-surface-2);
  font-size: 0.82rem;
  font-weight: 650;
  color: var(--ui-color-ink);
}
.site-table th[scope="row"] { font-weight: 600; color: var(--ui-color-ink); }
.site-table tbody tr { transition: background-color var(--site-dur) var(--site-ease); }
.site-table tbody tr:hover { background: var(--site-accent-soft); }

/* 11 · Callouts get a left scan-bar and a soft field. */
.site-scope { border-inline-start-color: var(--site-accent); box-shadow: var(--site-shadow-sm); }
.site-warning { box-shadow: var(--site-shadow-sm); }

/* 12 · Numbered steps: the counter chip is lit like a signal node. */
.site-flow > li::before, .site-steps-flow__number {
  background: linear-gradient(180deg, var(--site-accent-soft), var(--site-card));
  border-color: color-mix(in srgb, var(--site-accent) 30%, var(--site-line));
  color: var(--site-accent);
  box-shadow: var(--site-shadow-sm);
  font-family: var(--ui-font-mono);
}

/* 13 · Editorial: a comfortable measure, a refined rule that reads as a scan
   pass, and links underlined with intent. */
.site-editorial-main, .site-prose { max-width: 44rem; }
.site-editorial-main :is(h2, h3), .site-prose :is(h2, h3) { letter-spacing: -0.02em; }
.site-editorial-main hr, .site-section + .site-section {
  border: 0;
  border-top: 1px solid transparent;
  border-image: linear-gradient(90deg, var(--site-scan), var(--site-accent) 40%, transparent) 1;
}
/* The accent tick before each editorial heading already marks the section
   break. The fading gradient rule stacked just above it read as a stray
   second line ("what's with the lines"), so between editorial sections the
   tick carries the break alone; explicit <hr>s keep the rule. */
:is(.site-editorial-main, .site-prose) .site-section + .site-section {
  border-top: 0;
  border-image: none;
  padding-top: 0;
}
.site-source-list a { text-underline-offset: 0.2em; text-decoration-color: color-mix(in srgb, var(--site-accent) 40%, transparent); }

/* 14 · Footer: the dark band, its scan-line edge, spacing and columns are all
   defined up top with the other masthead-dark surfaces. (The old base-plate
   border-top lived here and, sitting inside the dark band, read as a stray
   light line — removed.) */
.site-footer__links a:hover { color: var(--site-accent); }

/* 15 · The hero document gets a live scan-line sweeping across it — the whole
   product, in one gesture. Reduced-motion users get a static accent instead. */
.site-hero-art__doc {
  box-shadow: var(--site-shadow-lg);
  border-color: var(--site-line-strong);
  position: relative;
  overflow: clip;
}
.site-hero-art__doc::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 40%;
  top: -40%;
  background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--site-scan) 22%, transparent), transparent);
  animation: site-scanline 3.4s var(--site-ease) infinite;
  pointer-events: none;
}
.site-hero-art__chip { box-shadow: var(--site-shadow-md); border-color: var(--site-line-strong); font-weight: 600; }
.site-hero-art__glass {
  border-color: var(--site-scan);
  box-shadow: 0 0 24px -4px color-mix(in srgb, var(--site-scan) 60%, transparent);
}
.site-hero-art__glass::after { background: var(--site-scan); }

@keyframes site-scanline {
  0% { top: -40%; opacity: 0; }
  12% { opacity: 1; }
  88% { opacity: 1; }
  100% { top: 100%; opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .site-hero-art__doc::after { animation: none; opacity: 0; }
  :where(a, button, .ui-btn, .site-feature, .scan-sample):hover { transform: none !important; }
}

/* 16 · Center the single-column article so the constrained measure sits
   balanced in the container instead of hugging the left rail. */
.site-prose { margin-inline: auto; }
.site-prose > .site-hero { text-align: left; }

/* ==========================================================================
   ELEVATION LAYER v2 — from the adversarial design critique. Commits the
   ownable signature (cyan corner-bracket "detection frame" + mono telemetry),
   carries the display voice + depth to every page, and gives the scroll a
   banded rhythm so the site reads as one authored instrument.
   ========================================================================== */

/* r6 · Lift light-mode elevation + crisper lines. */
:root {
  --site-shadow-sm: 0 1px 2px rgba(11, 13, 31, 0.05), 0 4px 10px -3px rgba(11, 13, 31, 0.10);
  --site-grid-dot: transparent;
  --site-line: #dfe1ee;
  --site-line-strong: #c9cde1;
  /* The workbench field surface (textarea, dropzone) — a subtle sunken tone
     distinct from the card in both themes, so an input never reads as an
     unstyled white/near-black void. */
  --site-field-bg: #f5f8fd;
}
:root:not([data-theme="dark"]) :where(.site-feature, .site-scan-card, .scan-panel, .site-detect-grid .site-feature, .scan-tiles li) {
  box-shadow: var(--site-shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

/* r7 · Cooler, wider dark-mode staircase. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --site-surface: #0a0c1c; --site-surface-2: #11142e; --site-card: #1a1d40;
    --site-line: #2e3369; --site-line-strong: #414892; --site-grid-dot: transparent;
    --site-field-bg: #10132c;
    --site-shadow-md: 0 10px 26px -12px rgba(0, 0, 0, 0.7), 0 2px 6px -2px rgba(0, 0, 0, 0.5);
    --site-shadow-lg: 0 32px 64px -32px rgba(0, 0, 0, 0.8), 0 10px 24px -14px rgba(0, 0, 0, 0.55);
  }
}
:root[data-theme="dark"] {
  --site-surface: #0a0c1c; --site-surface-2: #11142e; --site-card: #1a1d40;
  --site-line: #2e3369; --site-line-strong: #414892; --site-grid-dot: transparent;
  --site-field-bg: #10132c;
  --site-shadow-md: 0 10px 26px -12px rgba(0, 0, 0, 0.7), 0 2px 6px -2px rgba(0, 0, 0, 0.5);
  --site-shadow-lg: 0 32px 64px -32px rgba(0, 0, 0, 0.8), 0 10px 24px -14px rgba(0, 0, 0, 0.55);
}
:root[data-theme="dark"] :where(.site-feature, .site-scan-card, .scan-panel, .site-cta-panel, .scan-tiles li, .site-aside-box),
:root:not([data-theme="light"]) :where(.site-feature, .site-scan-card, .scan-panel, .site-cta-panel, .scan-tiles li, .site-aside-box) {
  box-shadow: var(--site-shadow-md), inset 0 1px 0 rgba(147, 197, 253, 0.08);
}

/* The hero accent word is simply the accent colour — the corner-bracket
   "detection frame" (a bolted-on HUD motif) is retired for one calm accent. */
.site-hero__title em {
  color: var(--site-accent);
  font-style: normal;
}

/* r3 · Carry the display voice to interior + workbench titles. */
:is(.site-prose, .site-editorial) .site-hero .ui-h1 {
  font-size: clamp(2.2rem, 4.4vw, 3.15rem);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.05;
  margin: var(--ui-space-3) 0;
  text-wrap: balance;
}
.site-workbench-intro .ui-h1 {
  font-size: clamp(1.9rem, 3.4vw, 2.7rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.08;
  margin: var(--ui-space-2) 0;
  text-wrap: balance;
}

/* r4 · A real mid-level heading tier + a repeating scan-tick landmark. */
:is(.site-section, .site-editorial-main, .site-prose) :is(.ui-h2, h2) {
  font-size: clamp(1.4rem, 2.1vw, 1.8rem);
  font-weight: 760;
  letter-spacing: -0.022em;
  line-height: 1.18;
  margin: var(--ui-space-7) 0 var(--ui-space-4);
  text-wrap: balance;
}
:is(.site-section, .site-editorial-main, .site-prose) > :is(.ui-h2, h2):first-child { margin-top: 0; }
.site-editorial-main h2::before, .site-prose h2::before {
  content: "";
  display: block;
  width: 2rem;
  height: 2px;
  margin-bottom: var(--ui-space-3);
  border-radius: 2px;
  background: linear-gradient(90deg, var(--site-scan), var(--site-accent));
}

/* Cohesion: the resting scan-line on every card is retired — cards are calm
   surfaces of the one card system, not HUD panels. Data figures keep tabular
   numerals but in ordinary ink, not a rival accent. */
.site-feature::before, .site-scan-card::before, .scan-panel::before, .site-detect-grid .site-feature::before {
  content: none;
}
.scan-tiles strong, .site-stats-band li strong {
  color: var(--site-figure-ink);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* r8 · Hero right column: rebalanced, a crisp scan beam, mono telemetry
   instead of decorative sparkles. */
.site-hero-split { grid-template-columns: minmax(0, 6.4fr) minmax(0, 5.6fr); gap: var(--ui-space-7); align-items: center; }
.site-hero-art { padding-block: var(--ui-space-3); }
.site-hero-art__doc { width: min(100%, 27rem); padding: var(--ui-space-6); }
.site-hero-art__glass { height: 6rem; width: 6rem; }
.site-hero-art__doc::after {
  height: 34%;
  background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--site-scan) 24%, transparent) 80%, color-mix(in srgb, var(--site-scan) 48%, transparent) 96%);
  border-bottom: 1.5px solid color-mix(in srgb, var(--site-scan) 85%, transparent);
  box-shadow: 0 2px 16px -1px color-mix(in srgb, var(--site-scan) 60%, transparent);
}
.site-hero-art::before {
  content: none;
  font-family: var(--ui-font-mono);
  font-size: 0.6rem; letter-spacing: 0.14em;
  color: var(--site-scan); opacity: 0.75;
  left: auto; right: 3%; top: -0.1rem;
}
.site-hero-art::after {
  content: none;
  font-family: var(--ui-font-mono);
  font-size: 0.58rem; letter-spacing: 0.16em;
  color: var(--site-accent); opacity: 0.6;
  left: 2%; bottom: 1%;
}

/* r9 · Carry the signature to the workbench: the empty result reads as an
   instrument at rest — a specimen viewport. */
.ui-utility-result:empty {
  border: 1.5px solid color-mix(in srgb, var(--site-scan) 22%, var(--site-line));
  background:
    radial-gradient(circle at 1px 1px, var(--site-grid-dot) 1px, transparent 1.4px) 0 0 / 18px 18px,
    linear-gradient(180deg, color-mix(in srgb, var(--site-scan) 4%, var(--site-card)), var(--site-card));
  position: relative;
  overflow: clip;
}
.ui-utility-result:empty::after {
  content: none;
  position: absolute;
  top: 0.9rem; left: 1.1rem;
  font-family: var(--ui-font-mono);
  font-size: 0.6rem; letter-spacing: 0.18em;
  color: var(--site-scan); opacity: 0.65;
}

/* r10 · Body comfort for long-form reading. */
.site-prose p, .site-editorial-main p { font-size: 1.05rem; line-height: 1.62; text-wrap: pretty; }
.site-hero__lede { line-height: 1.5; text-wrap: balance; }

/* r11 · A sharper, intentional signature eyebrow. */
.site-kicker {
  font-size: 0.78rem; font-weight: 650; letter-spacing: 0.14em;
  margin-bottom: var(--ui-space-2);
  /* Solid accent (not a color-mix) so it composites as rgb() for the AA gate;
     the cyan identity lives in the ::before scan-bar. */
  color: var(--site-accent);
}
.site-kicker::before { width: 2rem; height: 2px; }

/* r12 · Two-tier radius (crisp instruments, rounded prose) + fix dark warning. */
.scan-tiles li, .site-table, .site-example { border-radius: 0.5rem; }
.site-kicker--pill { border-radius: 0.4rem; }
:root[data-theme="dark"] .site-warning,
:root:not([data-theme="light"]) .site-warning {
  background: linear-gradient(180deg, #3a2b12, #2a1f0d);
  color: var(--ui-color-ink);
  border-color: color-mix(in srgb, var(--scanner-warning-border) 40%, var(--site-line));
}
:root[data-theme="dark"] .site-warning :is(strong, a),
:root:not([data-theme="light"]) .site-warning :is(strong, a) { color: #fcd34d; }

/* r13 · Mobile masthead breathing room + the dropzone as an entry aperture. */
@media (max-width: 40rem) {
  .ui-header { padding-block: var(--ui-space-3); }
  .site-brand__mark { height: 1.9rem; width: 1.9rem; }
  /* The right-edge fade is gone. It was a STATIC mask, so it could not know
     the scroll position: at the far right of the track it still faded most of
     "Limitations" to alpha 0, making the last nav item unreadable at EVERY
     scroll offset rather than only before you reached it. No static CSS mask
     can say "there is more to the right" without also fading whatever is
     currently at the right. Removed in place rather than overridden, so no
     contradictory dead rule is left behind. The gap is unchanged. */
  .site-nav { gap: var(--ui-space-4); }
}
.site-scan-card__zone {
  border-color: color-mix(in srgb, var(--site-scan) 26%, var(--site-line));
  background:
    radial-gradient(circle at 1px 1px, var(--site-grid-dot) 1px, transparent 1.4px) 0 0 / 20px 20px,
    linear-gradient(180deg, color-mix(in srgb, var(--site-scan) 5%, var(--site-surface)), var(--site-surface));
}

/* r1 · Banded rhythm — edge-to-edge tonal bands with no markup, via a spread
   shadow + clip-path. Applied to the distinct bands (robust); alternating
   sections are verified visually below. */
.site-feature-band, .site-stats-band {
  box-shadow: 0 0 0 100vmax var(--site-surface-2);
  clip-path: inset(0 -100vmax);
  border-radius: 0;
  border-left: 0; border-right: 0;
}

/* ==========================================================================
   BACKDROP FIX — every gradient background gets a solid background-color base
   so the WCAG-AA contrast gate (which composites against the nearest solid
   backgroundColor, not the gradient image) measures a real colour in BOTH
   schemes. The gradient still paints over the solid; only the measurable
   backdrop is restored. Longhand after the shorthand, so the image survives.
   ========================================================================== */
.ui-page { background-color: var(--site-surface); }
.ui-header { background-color: var(--site-ink-deep); }
.site-feature-band, .site-stats-band { background-color: var(--site-surface-2); }
.scan-privacy-strip { background-color: var(--site-card); }
.site-scan-card__zone { background-color: var(--site-surface); }
.ui-utility-result:empty { background-color: var(--site-card); }
.site-privacy-panel { background-color: var(--site-accent-soft); }
.site-kicker--pill { background-color: var(--site-accent-soft); }
.site-badge { background-color: var(--site-accent); }
:root[data-theme="dark"] .site-warning,
:root:not([data-theme="light"]) .site-warning { background-color: #3a2b12; }
/* The accent word keeps its corner-bracket signature but drops the tinted fill
   so its large text composites cleanly against the page rather than a saturated
   cyan wash. */
.site-hero__title em { background: none; }

/* ==========================================================================
   MASTHEAD CONTROLS — the theme toggle reduces to a single icon; its label is
   kept for assistive tech (accessible name still flips dark/light). The
   "Scan text" CTA is restyled above as a bordered pill matched to the toggle.
   ========================================================================== */
.site-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.site-theme-toggle {
  width: 2.25rem;
  min-width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  gap: 0;
  justify-content: center;
}


/* =======================================================================
   DESIGN SYSTEM UNIFICATION — one card, one accent, one spacing rhythm, one
   component kit. Authored as non-overlapping slices, appended last so it wins.
   ======================================================================= */


/* --------- SLICE: cards-surfaces --------- */

/* CARDS & SURFACES - one card primitive.
   One skin for every rectangular surface: --site-card background, a 1px
   --site-line hairline, ONE 0.875rem radius, and the elevation-token shadow
   (--site-shadow-sm in light, --site-shadow-md in dark). Padding comes only
   from the scale. The coloured LEFT rail is reserved strictly for finding
   severity, so the advisory callouts (.site-warning, .site-scope) drop their
   accent bar and read as a soft-tinted instance of the same card. Surfaces
   only - nothing here touches icons, buttons or type. Appended last, so these
   win over the older per-section surface rules at equal-or-greater specificity. */

/* 1 - The card skin. In dark mode var(--site-card) resolves one step LIGHTER
   than the page surface, so a card lifts off the ground with no theme rule. */
.site-feature,
.scan-panel,
.site-scan-card,
.site-cta-panel,
.site-aside-box,
.site-editorial-aside,
.scan-tiles li {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 0.875rem;
}

/* 2 - Elevation: sm in light, md in dark, pinned across all four theme states
   (explicit + system default). Held at low specificity (:where) so the :hover
   lift and the existing per-card shadow rules still refine it; this states the
   shared intent and, in particular, gives the editorial aside the shadow it
   never had. */
:where(.site-feature, .scan-panel, .site-scan-card, .site-cta-panel,
  .site-aside-box, .site-editorial-aside, .scan-tiles li) {
  box-shadow: var(--site-shadow-sm);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) :where(.site-feature, .scan-panel,
    .site-scan-card, .site-cta-panel, .site-aside-box, .site-editorial-aside,
    .scan-tiles li) {
    box-shadow: var(--site-shadow-md);
  }
}
:root[data-theme="dark"] :where(.site-feature, .scan-panel, .site-scan-card,
  .site-cta-panel, .site-aside-box, .site-editorial-aside, .scan-tiles li) {
  box-shadow: var(--site-shadow-md);
}

/* 3 - Internal padding by role, all from the scale. Panels (the big
   two-column surfaces) get the roomiest measure; standard cards the card step;
   the nested aside box a tighter step; and the stat tiles are the SAME card at
   the smallest padding. */
.scan-panel,
.site-scan-card {
  padding: 1.75rem;
}
.site-feature,
.site-cta-panel,
.site-editorial-aside {
  padding: var(--ui-space-5);
}
.site-aside-box {
  padding: var(--ui-space-4);
}
.scan-tiles li {
  padding: var(--ui-space-3);
}

/* 4 - Advisory callouts: the same card frame with a soft SEMANTIC tint and NO
   left accent bar. The `border` shorthand resets the old 0.35rem inline-start
   rail to the shared hairline (this also strips the bar in dark, where the
   existing rule only recolours it). Padding is left to the base/slim rules so
   the --slim, workbench-boundary and export-warning variants keep theirs; the
   dark .site-warning keeps its warm treatment via its higher-specificity rules. */
.site-warning,
.site-scope {
  border: 1px solid var(--site-line);
  border-radius: 0.875rem;
  box-shadow: var(--site-shadow-sm);
}
.site-warning {
  background: var(--site-warn-soft);
  border-color: color-mix(in srgb, var(--site-warn-ink) 24%, var(--site-line));
}
.site-scope {
  background: var(--site-accent-soft);
  border-color: color-mix(in srgb, var(--site-accent) 22%, var(--site-line));
}


/* --------- SLICE: icon-badges --------- */

/* ============================================================
   ICON BADGES — one rounded-square badge, four soft tones.
   Unifies every .site-tile into a single calm shape: a ~2.5rem
   rounded square with a soft category tint and a matching
   coloured icon. No circles, no glow, no gradient, no ring.
   ============================================================ */

/* Base badge — the one shape, used everywhere. Rounded square,
   grid-centred icon, flat surface. Neutral/info tint by default
   (blue), which the tone modifiers recolour. flex:none keeps it
   from squishing inside the flex rows that used to carry it. */
.site-tile {
  display: grid;
  place-items: center;
  flex: none;
  height: 2.5rem;
  width: 2.5rem;
  border: 0;
  border-radius: 0.65rem;
  background: var(--site-accent-soft);
  color: var(--site-accent);
  box-shadow: none;
}

.site-tile svg {
  height: 1.25rem;
  width: 1.25rem;
}

/* Tone variants — soft category tint surface + matching icon ink.
   Flat fills only (these override the legacy accent gradient). */
.site-tile--accent { background: var(--site-accent-soft); color: var(--site-accent); }
.site-tile--danger { background: var(--site-danger-soft); color: var(--site-danger-ink); }
.site-tile--warn   { background: var(--site-warn-soft);   color: var(--site-warn-ink); }
.site-tile--ok     { background: var(--site-ok-soft);     color: var(--site-ok-ink); }

/* Shape + calm reset, boosted so it out-specifies every legacy
   section override. The old circular rules reach 0,3,0
   (.site-detect-grid .site-feature .site-tile); a repeated class
   matches that without coupling this badge to any one section.
   Forces the single radius and kills the ring / inset highlight /
   shadow / gradient everywhere, while deliberately NOT setting
   width/height so intentional dense-context sizes (scanner stat
   tiles at 1.75rem, look-for and compare tiles at 2rem) survive. */
.site-tile.site-tile.site-tile {
  border: 0;
  border-radius: 0.65rem;
  box-shadow: none;
  background-image: none;
}


/* --------- SLICE: spacing-rhythm --------- */

/* ============================================================
   SPACING & RHYTHM  —  authoritative module
   Impose the 8px scale, make card rows equal height and share
   one baseline, and give ledger rows a comfortable rhythm.
   Spacing / layout ONLY — no colour, border or type changes.
   Every value is a shared spacing token.
   ============================================================ */

/* 1 · SECTION RHYTHM
   One gap value between major sections, top to bottom. Already
   the scale value in the base sheet; asserted here so the module
   wins over anything appended earlier and the cadence is locked. */
.site-section {
  margin-block: var(--ui-space-7);
}
.site-section + .site-section {
  padding-top: var(--ui-space-7);
}

/* 2 · CARD GRIDS ARE EQUAL HEIGHT
   Every card grid stretches its children, so cards on the same
   row match the tallest one instead of settling to their own
   content height. */
.site-feature-grid,
.site-detect-grid,
.site-feature-band,
.site-steps-flow,
.scan-tiles {
  align-items: stretch;
}

/* 3 · CARDS ARE COLUMNS THAT SHARE A BASELINE
   A feature / detect card becomes a flex column so its trailing
   element — the example chip, or a CTA — can be pinned to the
   card floor with margin-top:auto. Cards in a row then line their
   chips up on one baseline regardless of copy length.
   This unifies (and supersedes) the detect-grid-only rules. */
.site-feature-grid .site-feature,
.site-detect-grid .site-feature {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.site-feature-grid .site-feature .site-example-chip,
.site-detect-grid .site-feature .site-example-chip {
  margin-top: auto;
}

/* Stat tiles: drop the value to the card floor so every number
   in the row aligns on one baseline even when a label wraps to
   two lines. */
.scan-tiles li {
  display: flex;
  flex-direction: column;
}
.scan-tiles strong {
  margin-top: auto;
}

/* 4 · LEDGER RHYTHM
   The summary reads as a ledger: each label/value row gets real
   vertical breathing (~half a step top and bottom) instead of a
   hairline gap, so a long summary scans as a calm table. */
.scan-panel--results [data-utility-view="summary"] dl {
  gap: 0;
}
.scan-panel--results [data-utility-view="summary"] dl > div {
  padding-block: var(--ui-space-2);
}

/* The home "next action" ledger table carries the same comfortable
   row rhythm — a full step of vertical padding, not a hairline. */
.site-table th,
.site-table td {
  padding-block: var(--ui-space-3);
}


/* --------- SLICE: components-buttons-chips --------- */

/* =======================================================================
   COMPONENTS · BUTTONS + CHIPS — one authoritative spec.
   Appended last, so plain-class rules win on source order; the header and
   results-toolbar rules are restated at their original specificity so they
   win regardless of whether the old rules are deleted. Values are shared
   tokens only. Flat fills, no gradient/glow, no hover lift — one height,
   one radius, one weight, one pill.
   ======================================================================= */

/* -- The one solid button ----------------------------------------------- */
/* Flat accent fill, white/accent-ink text (the token is #fff in light and a
   legible dark ink in dark, keeping the AA gate green). One height, one
   radius, one weight — no gradient, no glow, no press-lift. */
.ui-btn--accent,
.ui-btn--primary {
  min-height: 2.6rem;
  padding-block: 0.55rem;
  padding-inline: 1.25rem;
  border: 1px solid var(--site-accent);
  border-radius: 0.6rem;
  background: var(--site-accent);
  background-image: none;
  color: var(--ui-color-accent-ink);
  font-weight: 650;
  text-decoration: none;
  box-shadow: none;
}
.ui-btn--accent:hover,
.ui-btn--primary:hover {
  background: var(--site-accent-strong);
  background-image: none;
  border-color: var(--site-accent-strong);
  color: var(--ui-color-accent-ink);
  box-shadow: none;
  filter: none;
  transform: none;
}
.ui-btn--accent:active,
.ui-btn--primary:active {
  transform: none;
  box-shadow: none;
}

/* -- The quiet button --------------------------------------------------- */
/* A real button — full height and target — that loses only the fill: a
   hairline outline and ink text, never an underlined link. */
.ui-btn--quiet {
  min-height: 2.6rem;
  padding-block: 0.55rem;
  padding-inline: 1.25rem;
  border: 1px solid var(--site-line);
  border-radius: 0.6rem;
  background: transparent;
  color: var(--ui-color-ink);
  font-weight: 650;
  text-decoration: none;
  box-shadow: none;
}
.ui-btn--quiet:hover {
  background: var(--site-surface-2);
  border-color: var(--site-line-strong);
  color: var(--ui-color-ink);
  text-decoration: none;
}

/* The report toolbar's actions are the same quiet button (restated at the
   original selector's specificity so the unified look wins). */
.scan-panel--results .site-actions .ui-btn--quiet {
  min-height: 2.6rem;
  padding-block: 0.5rem;
  padding-inline: 1rem;
  border: 1px solid var(--site-line);
  border-radius: 0.6rem;
  background: transparent;
  color: var(--ui-color-ink);
  text-decoration: none;
}
.scan-panel--results .site-actions .ui-btn--quiet:hover {
  background: var(--site-surface-2);
  border-color: var(--site-line-strong);
  color: var(--ui-color-ink);
}

/* -- The masthead CTA --------------------------------------------------- */
/* The SAME solid fill on every route — never a ghost pill — but compact to
   pair with the theme toggle. The masthead is theme-fixed dark, so its fill
   is pinned to the accent's light value (the same reason .site-badge above
   is pinned): a token that flipped to pale blue would drop white text below
   AA on the dark bar. */
.ui-header .ui-btn--accent {
  min-height: 0;
  height: 2.25rem;
  padding-block: 0;
  padding-inline: 1.15rem;
  border: 1px solid #2563eb;
  border-radius: 0.6rem;
  background: #2563eb;
  background-image: none;
  color: #ffffff;
  font-weight: 650;
  line-height: 1;
  box-shadow: none;
}
.ui-header .ui-btn--accent:hover {
  background: #1d4ed8;
  background-image: none;
  border-color: #1d4ed8;
  color: #ffffff;
  box-shadow: none;
  transform: none;
}

/* -- The one pill chip -------------------------------------------------- */
/* .scan-sample (interactive sample) and .site-example-chip (static example)
   are one primitive: one shape, one size, a hairline, proportional type.
   Only the colour role differs. */
.scan-sample,
.site-example-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-2);
  min-height: 2rem;
  padding: 0.375rem 0.75rem;
  border: 1px solid var(--site-line);
  border-radius: 999px;
  background: var(--site-surface);
  color: var(--ui-color-ink);
  font: inherit;
  font-size: var(--ui-text-xs);
  font-weight: 600;
  line-height: 1.4;
  max-width: 100%;
  overflow-wrap: anywhere;
}

/* The sample is a button: pointer, and a calm accent tint on hover — colour
   only, no lift, no shadow. */
.scan-sample {
  cursor: pointer;
}
.scan-sample:hover {
  border-color: color-mix(in srgb, var(--site-accent) 45%, var(--site-line));
  background: var(--site-accent-soft);
  color: var(--site-accent);
  box-shadow: none;
  transform: none;
}

/* Example chips recolour by the card's category tone — the same pill,
   tinted. Default is the neutral/info (accent) tint. */
.site-example-chip {
  border-color: color-mix(in srgb, var(--site-accent) 22%, var(--site-line));
  background: var(--site-accent-soft);
  color: color-mix(in srgb, var(--site-accent) 82%, var(--ui-color-ink));
}
.site-feature:has(.site-tile--danger) .site-example-chip {
  border-color: color-mix(in srgb, var(--site-danger-ink) 22%, var(--site-line));
  background: var(--site-danger-soft);
  color: var(--site-danger-ink);
}
.site-feature:has(.site-tile--warn) .site-example-chip {
  border-color: color-mix(in srgb, var(--site-warn-ink) 22%, var(--site-line));
  background: var(--site-warn-soft);
  color: var(--site-warn-ink);
}
.site-feature:has(.site-tile--ok) .site-example-chip {
  border-color: color-mix(in srgb, var(--site-ok-ink) 22%, var(--site-line));
  background: var(--site-ok-soft);
  color: var(--site-ok-ink);
}


/* --------- SLICE: components-eyebrow-callouts-type --------- */

/* ==========================================================================
   COHESION MODULE — EYEBROW · CALLOUTS · TYPE
   Authoritative. Appended last, so it wins on source order at equal
   specificity; where an older rule is more specific these selectors match or
   exceed it. Values come only from the shared tokens (accent is BLUE).
   ========================================================================== */

/* -- 1 · EYEBROW ------------------------------------------------------------
   One .site-kicker treatment for every page. Sans (not mono), uppercase, a
   small SOLID-blue tick before it. .site-kicker--pill is retired: it renders
   identically to a plain kicker (no pill, no border, no shadow, no mono). */
.site-kicker,
.site-kicker--pill {
  display: flex;
  width: fit-content;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 var(--ui-space-3);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  background-color: transparent;
  box-shadow: none;
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--site-accent);
}

/* The tick: a short, solid blue mark — the same signal as the editorial h2
   eyebrow. No gradient, no glow. */
.site-kicker::before,
.site-kicker--pill::before {
  content: "";
  display: inline-block;
  flex: none;
  width: 1.25rem;
  height: 2px;
  border-radius: 999px;
  background: var(--site-accent);
  box-shadow: none;
}

/* Any inline icon that shipped inside a kicker (the home shield) is dropped so
   every eyebrow presents the one tick and reads identically. */
.site-kicker > svg,
.site-kicker--pill > svg {
  display: none;
}

/* -- 2 · CALLOUTS -----------------------------------------------------------
   One frame: single radius, consistent padding, a left icon drawn from the
   variant colour. Variants differ by COLOUR only — amber caution is the
   default; --info is the neutral/accent tint. The thick coloured left bar is
   replaced by a hairline + icon. */
.site-warning {
  position: relative;
  background: var(--site-warn-soft);
  border: 1px solid var(--site-line);
  border-radius: 0.875rem;
  padding: var(--ui-space-4);
  /* room for the left icon: icon box + a sibling gap */
  padding-inline-start: calc(var(--ui-space-4) + 1.15rem + var(--ui-space-3));
  color: var(--ui-color-ink);
}

.site-warning::before {
  content: "";
  position: absolute;
  inset-block-start: var(--ui-space-4);
  inset-inline-start: var(--ui-space-4);
  width: 1.15rem;
  height: 1.15rem;
  background-color: var(--site-warn-ink);
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.85'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M12%204.6%203.7%2018.8h16.6L12%204.6Z'/%3E%3Cpath%20d='M12%209.8v4.2'/%3E%3Cpath%20d='M12%2016.9h.01'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.85'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M12%204.6%203.7%2018.8h16.6L12%204.6Z'/%3E%3Cpath%20d='M12%209.8v4.2'/%3E%3Cpath%20d='M12%2016.9h.01'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Lead-in emphasis carries the variant ink, not a rival colour. */
.site-warning strong {
  color: var(--site-warn-ink);
}

/* A callout is its own eyebrow — suppress the editorial h2 tick inside one so
   a callout heading never carries two marks. */
.site-warning h2::before {
  content: none;
}

/* Info / neutral variant — accent tint, accent icon (circle-i). */
.site-warning--info {
  background: var(--site-accent-soft);
}
.site-warning--info::before {
  background-color: var(--site-accent);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.85'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='12'%20r='8.6'/%3E%3Cpath%20d='M12%2011.2v4.6'/%3E%3Cpath%20d='M12%208.2h.01'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.85'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='12'%20r='8.6'/%3E%3Cpath%20d='M12%2011.2v4.6'/%3E%3Cpath%20d='M12%208.2h.01'/%3E%3C/svg%3E");
}
.site-warning--info strong {
  color: var(--site-accent);
}

/* Dark / system-default: re-assert the flat token tint over the older brown
   gradient (which used identical selectors, so match them and land later).
   The tokens already carry the dark values, so the same rule is correct in
   system-light (no attribute) too. --info ordered after the generic rule so
   it wins for an element carrying both classes. */
:root[data-theme="dark"] .site-warning,
:root:not([data-theme="light"]) .site-warning {
  background: var(--site-warn-soft);
  background-color: var(--site-warn-soft);
  border-color: var(--site-line);
  color: var(--ui-color-ink);
}
:root[data-theme="dark"] .site-warning--info,
:root:not([data-theme="light"]) .site-warning--info {
  background: var(--site-accent-soft);
  background-color: var(--site-accent-soft);
}
:root[data-theme="dark"] .site-warning--info :is(strong, a),
:root:not([data-theme="light"]) .site-warning--info :is(strong, a) {
  color: var(--site-accent);
}

/* -- 3 · TYPE ---------------------------------------------------------------
   One H1 spec for EVERY page title — home hero, interior, prose, editorial and
   the workbench — dropping the bespoke per-page hero sizes and the scan-line
   ornament. The last selector matches the most specific older rule exactly, so
   it wins by source order. */
.site-hero__title,
.site-hero .ui-h1,
.site-workbench-intro .ui-h1,
:is(.site-prose, .site-editorial) .site-hero .ui-h1 {
  font-size: clamp(2.1rem, 4vw, 3.25rem);
  font-weight: 800;
  letter-spacing: -0.028em;
  line-height: 1.08;
  margin: 0 0 var(--ui-space-4);
  color: var(--ui-color-ink);
  text-wrap: balance;
}

/* The accent word stays one calm blue — no tinted fill, no bracket. */
.site-hero__title em {
  color: var(--site-accent);
  font-style: normal;
  background: none;
}

/* THE section eyebrow: the single blue accent tick before each editorial h2,
   now a SOLID blue mark (was a cyan→blue gradient) matching the .site-kicker
   tick. Scoped to real section headings (editorial/prose h2), never cards. */
.site-editorial-main h2::before,
.site-prose h2::before {
  content: "";
  display: block;
  width: 2rem;
  height: 2px;
  margin-bottom: var(--ui-space-3);
  border-radius: 999px;
  background: var(--site-accent);
}

/* Metric labels are sentence case — uppercase is reserved to eyebrows. */
.scan-tiles__label {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-xs);
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
}

/* -- RESULT DISCLOSURES -----------------------------------------------
   The scan-details ledger and the per-finding detector metadata collapse
   behind a quiet native <summary> toggle, closed by default, so the result
   leads with the verdict and the plain reading — not a wall of technical rows. */
.scan-panel--results details.ui-utility-scan-details,
.scan-panel--results details.ui-utility-finding-detail {
  margin-top: var(--ui-space-3);
}
.scan-panel--results details > summary {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  font-weight: 600;
  list-style: none;
  user-select: none;
}
.scan-panel--results details > summary::-webkit-details-marker { display: none; }
.scan-panel--results details > summary::before {
  content: "\25B8";
  font-size: 0.75em;
  transition: transform 0.15s ease;
}
.scan-panel--results details[open] > summary::before { transform: rotate(90deg); }
.scan-panel--results details.ui-utility-scan-details > summary:hover,
.scan-panel--results details.ui-utility-finding-detail > summary:hover { color: var(--site-accent); }

/* -- RESULTS: master-detail (matches the reference dashboard) ----------- */
.ui-utility-findings-layout {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: var(--ui-space-4);
  align-items: start;
  margin-top: var(--ui-space-3);
}
@media (max-width: 60rem) { .ui-utility-findings-layout { grid-template-columns: minmax(0, 1fr); } }
.ui-utility-findings-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--ui-space-2);
  max-height: 30rem; overflow-y: auto;
}
.ui-utility-findings-list li { margin: 0; }
.ui-utility-finding-row {
  /* A raw <button>: without an appearance reset WebKit renders it as a native
     control and ignores our background AND color, leaving near-white system
     text on a translucent chrome fill that fails AA in dark. */
  appearance: none; -webkit-appearance: none;
  width: 100%; text-align: left; cursor: pointer; font: inherit;
  display: grid; gap: 0.2rem;
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-left: 0.25rem solid var(--site-warn-ink);
  border-radius: 0.6rem;
  padding: 0.7rem 0.85rem;
  transition: border-color .12s ease, background .12s ease;
}
.ui-utility-findings-list li[data-severity="high"] .ui-utility-finding-row { border-left-color: var(--site-danger-ink); }
.ui-utility-finding-row:hover { border-color: var(--site-accent); }
.ui-utility-finding-row[aria-current="true"] { border-color: var(--site-accent); background: var(--site-accent-soft); }
.ui-utility-finding-row__title { font-weight: 650; color: var(--ui-color-ink); font-size: 0.95rem; }
.ui-utility-finding-row__severity { font-size: 0.72rem; font-weight: 650; color: var(--site-warn-ink); }
.ui-utility-findings-list li[data-severity="high"] .ui-utility-finding-row__severity { color: var(--site-danger-ink); }
.ui-utility-finding-detail-panel {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 0.8rem;
  padding: var(--ui-space-5);
  box-shadow: var(--site-shadow-sm);
  display: grid; gap: var(--ui-space-3);
}
.ui-utility-finding-detail__head { display: flex; align-items: center; gap: var(--ui-space-3); flex-wrap: wrap; }
.ui-utility-finding-detail__head h3 { margin: 0; font-size: 1.1rem; }
.ui-utility-finding-detail__severity { border-radius: 999px; padding: 0.15rem 0.6rem; font-size: 0.72rem; font-weight: 650; background: var(--site-warn-soft); color: var(--site-warn-ink); }
.ui-utility-finding-detail__severity[data-severity="high"] { background: var(--site-danger-soft); color: var(--site-danger-ink); }
.ui-utility-finding-detail-panel > p { margin: 0; color: var(--ui-color-ink); line-height: 1.55; }
.ui-utility-finding-detail-panel > p:last-of-type { color: var(--ui-color-muted); font-size: var(--ui-text-sm); }

/* -- RESULTS TAKE THE FULL WIDTH once a scan has run (reference dashboard) --
   The input/results two-up is for composing a scan; the moment a result
   exists the results claim the whole window and the input collapses below,
   so the stat cards + master-detail read across the screen, not a half column. */
.scan-grid:has(.scan-panel--results .ui-utility-result:not(:empty)) {
  grid-template-columns: minmax(0, 1fr);
}
.scan-grid:has(.scan-panel--results .ui-utility-result:not(:empty)) .scan-panel--results { order: -1; }
.scan-grid:has(.scan-panel--results .ui-utility-result:not(:empty)) .scan-panel:not(.scan-panel--results) {
  order: 1;
}

/* Cleaner than reordering: once a result exists, the compose panel steps aside
   entirely so the results own the window from the top (Start over lives in the
   results toolbar). */
.scan-grid:has(.scan-panel--results .ui-utility-result:not(:empty)) .scan-panel:not(.scan-panel--results) {
  display: none;
}

/* -- COMPACT RESULTS CHROME (fit the reference in one screen) ----------- */
.scan-results-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--ui-space-3); flex-wrap: wrap; margin-bottom: var(--ui-space-4);
}
.scan-results-head .scan-panel__title { margin: 0; }
.scan-results-head .site-actions { margin: 0; gap: var(--ui-space-2); }
.scan-results-head .site-actions .ui-btn { font-size: var(--ui-text-sm); padding: 0.3rem 0.75rem; }
/* Slim verdict — a one-line banner, not a fat card. */
.scan-panel--results [data-utility-view="summary"] { padding: var(--ui-space-4); margin: var(--ui-space-4) 0; }
.scan-panel--results [data-utility-view="summary"] > p:first-child { margin: 0; font-size: 1.1rem; }
.scan-panel--results [data-utility-view="summary"] details.ui-utility-scan-details { margin-top: var(--ui-space-2); }
/* Coverage — a slim inline strip. */
.scan-panel--results [data-utility-view="coverage"] { display: flex; align-items: center; gap: var(--ui-space-2) var(--ui-space-3); flex-wrap: wrap; margin: var(--ui-space-3) 0; }
.scan-panel--results [data-utility-view="coverage"] h2 { margin: 0; font-size: 0.72rem; font-family: var(--ui-font-mono); text-transform: uppercase; letter-spacing: 0.12em; color: var(--ui-color-muted); }
.scan-panel--results [data-utility-view="coverage"] ul { margin: 0; }
/* Findings heading tight; footnote small + muted. */
.scan-panel--results [data-utility-view="findings"] > h2 { margin: var(--ui-space-4) 0 var(--ui-space-2); }
.scan-results-footnote { margin-top: var(--ui-space-4); padding-top: var(--ui-space-3); border-top: 1px solid var(--site-line); font-size: var(--ui-text-sm); color: var(--ui-color-muted); line-height: 1.5; }
/* The honesty note above the result: a finding is a pattern to review, not a
   verdict. Small and muted so it frames without shouting; muted-on-card clears
   AA the same way the footnote does. */
.scan-results-note { margin: 0 0 var(--ui-space-2); font-size: var(--ui-text-sm); color: var(--ui-color-muted); line-height: 1.5; }

/* ======================================================================
   THE SCAN PAGE IS THE PRODUCT — initial-state polish (Aug 25)
   The pre-scan view is what a first-time visitor judges the tool by, so it
   is composed, not left as a bare form. Everything here concerns the state
   BEFORE the first result; the result view is styled above.
   ====================================================================== */

/* The stage scopes the :has() that steps the educational content aside once
   a real result exists, so the result view is the whole page. */
.scan-stage { display: flex; flex-direction: column; gap: var(--ui-space-6); }

/* Pre-read: what the scan looks for + how to read a result. It is guidance
   for the empty workbench; once a result is on screen it has served its
   purpose and gets out of the way (this also keeps it from floating,
   half-aligned, beneath the full-width result). */
.scan-preread { display: flex; flex-direction: column; gap: var(--ui-space-6); }
.scan-stage:has(.scan-panel--results .ui-utility-result:not(:empty)) .scan-preread { display: none; }

.scan-lookfor-head {
  align-items: baseline;
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-2) var(--ui-space-4);
  justify-content: space-between;
  margin-bottom: var(--ui-space-4);
}
.scan-lookfor-head h2 { margin: 0; }
.scan-lookfor-head a { font-size: var(--ui-text-sm); font-weight: 600; white-space: nowrap; }

/* A quiet, tinted aside under the paste box — reassurance, not a control. */
.scan-tip {
  align-items: flex-start;
  background: var(--site-accent-soft);
  border: 1px solid color-mix(in srgb, var(--site-accent) 18%, transparent);
  border-radius: 0.625rem;
  color: var(--ui-color-muted);
  display: flex;
  font-size: var(--ui-text-sm);
  gap: var(--ui-space-3);
  line-height: 1.5;
  margin: 0;
  padding: var(--ui-space-3) var(--ui-space-4);
}
.scan-tip strong { color: var(--ui-color-ink); }
.scan-tip__icon {
  color: var(--site-accent);
  flex: none;
  line-height: 1;
}
.scan-tip__icon svg { height: 1.1rem; width: 1.1rem; display: block; }

/* -- The resting result viewport -----------------------------------------
   A composed empty state: a glyph, a heading and one line of guidance,
   centred in a panel that is clearly *waiting for input* rather than broken.
   Higher specificity than every earlier :empty rule above, so it is the one
   that renders. */
.scan-panel--results .ui-utility-result:empty {
  align-items: center;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3h7l5 5v13H6V3Z'/%3E%3Cpath d='M13 3v5h5'/%3E%3Ccircle cx='11' cy='13.5' r='2.4'/%3E%3Cpath d='m12.8 15.3 2.7 2.7'/%3E%3C/svg%3E")
      no-repeat center calc(50% - 4.25rem) / 2.5rem,
    linear-gradient(180deg, var(--site-accent-soft), var(--site-card));
  border: 1.5px dashed var(--site-line-strong);
  border-radius: 0.875rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  justify-content: center;
  min-height: 16rem;
  overflow: clip;
  padding: var(--ui-space-6) var(--ui-space-5);
  text-align: center;
}
/* Reset the earlier HUD ::after (absolute, monospace) that these rules
   otherwise inherit — this ::after is body text in normal flow. */
.scan-panel--results .ui-utility-result:empty::before,
.scan-panel--results .ui-utility-result:empty::after {
  position: static;
  font-family: inherit;
  opacity: 1;
  margin: 0;
  max-width: 34ch;
}
.scan-panel--results .ui-utility-result:empty::before {
  color: var(--ui-color-ink);
  content: "No scan results yet";
  font-size: var(--ui-text-lg);
  font-weight: 700;
  letter-spacing: -0.01em;
}
.scan-panel--results .ui-utility-result:empty::after {
  color: var(--ui-color-muted);
  content: "Paste text or open a file, then run the scan. You\2019ll see whether anything looks risky \2014  and what to do about it.";
  font-size: var(--ui-text-sm);
  letter-spacing: normal;
  line-height: 1.5;
}
/* Pre-scan, the report caution has nothing to caution about yet. */
.scan-panel--results:has(.ui-utility-result:empty) .scan-results-footnote,
.scan-panel--results:has(.ui-utility-result:empty) .scan-results-note { display: none; }

/* -- "Scan something else": the visible way back -------------------------
   The compose panel is hidden while a result is on screen, so the single
   reset control lives in the results header instead. Hidden until a result
   exists, so the resting workbench shows only "Scan results". */
.scan-results-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-2) var(--ui-space-3);
}
.scan-results-actions .site-actions { margin: 0; }
.scan-newscan {
  align-items: center;
  display: inline-flex;
  font-size: var(--ui-text-sm);
  gap: 0.4rem;
  padding: 0.4rem 0.9rem;
}
.scan-newscan svg { flex: none; }
.scan-panel--results:has(.ui-utility-result:empty) .scan-results-actions { display: none; }

/* -- PRE-SCAN: no results panel; paste + upload shown together ----------
   Before the first scan the results panel is hidden and the compose panel
   owns the full width, showing the paste box and the upload dropzone side by
   side — both available the moment the page loads, no tab to discover. */
.scan-grid:has(.scan-panel--results .ui-utility-result:empty) {
  grid-template-columns: minmax(0, 1fr);
}
.scan-grid:has(.scan-panel--results .ui-utility-result:empty) .scan-panel--results {
  display: none;
}
.scan-inputs {
  align-items: stretch;
  display: grid;
  gap: var(--ui-space-4);
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
}
@media (max-width: 48rem) { .scan-inputs { grid-template-columns: minmax(0, 1fr); } }
.scan-input { display: flex; flex-direction: column; min-width: 0; }
/* Both fields fill their column so the two boxes stand the same height. */
.scan-input--paste .ui-utility-input { display: flex; flex: 1 1 auto; flex-direction: column; }
.scan-input--paste .ui-utility-input__control { flex: 1 1 auto; }
.scan-input--upload .scan-dropzone { display: flex; flex: 1 1 auto; flex-direction: column; gap: var(--ui-space-2); }
.scan-input--upload .scan-dropzone__area { flex: 1 1 auto; }

/* ======================================================================
   SCAN PAGE — matched to the reference comp (Aug 25): centred hero with
   trust chips, one compose card (two-option header + numbered Paste/Upload
   columns + action bar), and a closing "private by design" banner.
   ====================================================================== */

/* -- Centred hero ------------------------------------------------------*/
.scan-hero {
  align-items: center;
  gap: var(--ui-space-3);
  margin-bottom: var(--ui-space-6);
  text-align: center;
}
.scan-hero .ui-h1 {
  font-size: clamp(1.9rem, 4vw, 2.9rem);
  line-height: 1.08;
  margin: var(--ui-space-2) 0 0;
  max-width: 20ch;
}
.scan-hero__badge {
  align-self: center;
  align-items: center;
  background: var(--site-accent-soft);
  border-radius: 999px;
  color: var(--site-accent-strong);
  display: inline-flex;
  font-size: 0.72rem;
  font-weight: 700;
  gap: 0.4rem;
  letter-spacing: 0.1em;
  margin: 0;
  padding: 0.35rem 0.8rem;
  text-transform: uppercase;
}
.scan-hero__badge::before { content: none; }   /* kill the kicker dash */
.scan-hero__badge svg { height: 0.95rem; width: 0.95rem; }
.scan-hero__lede {
  color: var(--ui-color-ink);
  font-size: clamp(1.05rem, 2vw, 1.3rem);
  font-weight: 650;
  margin: var(--ui-space-2) 0 0;
  max-width: 40ch;
}
.scan-hero__sublede {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-base);
  margin: 0;
  max-width: 46ch;
}
.scan-trust {
  color: var(--ui-color-muted);
  display: flex;
  flex-wrap: wrap;
  font-size: var(--ui-text-sm);
  font-weight: 600;
  gap: var(--ui-space-3) var(--ui-space-5);
  justify-content: center;
  list-style: none;
  margin: var(--ui-space-3) 0 0;
  padding: 0;
}
.scan-trust li { align-items: center; display: inline-flex; gap: 0.4rem; }
.scan-trust li svg { color: var(--site-accent); height: 1.05rem; width: 1.05rem; }
.scan-trust__hi {
  background: var(--site-warn-soft);
  border-radius: 999px;
  color: var(--site-warn-ink);
  padding: 0.25rem 0.7rem;
}
.scan-trust__hi svg { color: var(--site-warn-ink) !important; }

/* -- The compose card --------------------------------------------------*/
.scan-compose { gap: var(--ui-space-5); padding: var(--ui-space-6); }

/* Two-option header: focus shortcuts styled as a segmented control. */
.scan-modes {
  display: grid;
  gap: var(--ui-space-3);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 40rem) { .scan-modes { grid-template-columns: 1fr; } }
.scan-mode {
  align-items: center;
  background: var(--site-field-bg);
  border: 1.5px solid var(--site-line);
  border-radius: 0.75rem;
  color: var(--ui-color-muted);
  display: flex;
  gap: var(--ui-space-3);
  padding: var(--ui-space-3) var(--ui-space-4);
  text-decoration: none;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.scan-mode:hover { border-color: var(--site-line-strong); }
.scan-mode--active {
  background: var(--site-accent-soft);
  border-color: color-mix(in srgb, var(--site-accent) 45%, transparent);
}
.scan-mode__icon {
  align-items: center;
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-radius: 0.55rem;
  color: var(--site-accent);
  display: inline-flex;
  flex: none;
  height: 2.2rem;
  justify-content: center;
  width: 2.2rem;
}
.scan-mode__icon svg { height: 1.15rem; width: 1.15rem; }
.scan-mode__text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.scan-mode__text strong { color: var(--ui-color-ink); font-size: var(--ui-text-base); }
.scan-mode--active .scan-mode__text strong { color: var(--site-accent-strong); }
.scan-mode__text small { color: var(--ui-color-muted); font-size: var(--ui-text-sm); }

/* -- Numbered column headers -------------------------------------------*/
.scan-input__head { align-items: flex-start; display: flex; gap: var(--ui-space-3); margin-bottom: var(--ui-space-1); }
.scan-step {
  align-items: center;
  background: var(--site-accent);
  border-radius: 999px;
  color: #fff;
  display: inline-flex;
  flex: none;
  font-size: 0.85rem;
  font-weight: 700;
  height: 1.6rem;
  justify-content: center;
  width: 1.6rem;
}
/* In dark the accent is a light blue (#60a5fa); white on it is only ~2.5:1.
   The pill keeps the accent fill but flips to dark ink there, which clears AA. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .scan-step { color: #0a0c1c; }
}
:root[data-theme="dark"] .scan-step { color: #0a0c1c; }
.scan-input__heading { min-width: 0; }
.scan-input__title { font-size: var(--ui-text-base); font-weight: 700; margin: 0; }
.scan-input__opt { color: var(--ui-color-muted); font-weight: 500; }
.scan-input__sub { color: var(--ui-color-muted); font-size: var(--ui-text-sm); margin: 0.15rem 0 0; }

/* The composed label lives in the numbered header, so the control's own
   label is for assistive tech only. */
.scan-input--paste .ui-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* -- Dropzone: document glyph with sparkles, matching the comp ----------*/
.scan-dropzone__badge { position: relative; display: inline-block; }
.scan-dropzone__icon { color: var(--site-accent); height: 3rem; width: 3rem; }
.scan-dropzone__spark { color: var(--site-accent); opacity: 0.55; position: absolute; }
.scan-dropzone__spark--a { height: 0.85rem; width: 0.85rem; top: -0.2rem; right: -0.7rem; }
.scan-dropzone__spark--b { height: 0.6rem; width: 0.6rem; bottom: 0.1rem; left: -0.7rem; opacity: 0.4; }
.scan-dropzone__or { margin: 0; color: var(--ui-color-muted); font-size: var(--ui-text-sm); }
.scan-dropzone__or span { color: var(--site-accent); font-weight: 650; text-decoration: underline; text-underline-offset: 0.15em; }

/* Green reassurance under the dropzone. */
.scan-upload-ok {
  align-items: center;
  background: var(--site-ok-soft);
  border-radius: 0.6rem;
  color: var(--site-ok-ink);
  display: flex;
  font-size: var(--ui-text-sm);
  font-weight: 600;
  gap: 0.5rem;
  margin: 0;
  padding: var(--ui-space-3) var(--ui-space-4);
}
.scan-upload-ok svg { flex: none; height: 1.1rem; width: 1.1rem; }

/* -- Bottom action bar -------------------------------------------------*/
.scan-actionbar {
  align-items: center;
  border-top: 1px solid var(--site-line);
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-3) var(--ui-space-5);
  justify-content: space-between;
  padding-top: var(--ui-space-4);
}
.scan-actionbar__meta { align-items: center; display: flex; flex-wrap: wrap; gap: var(--ui-space-3) var(--ui-space-4); }
.scan-actionbar__meta .ui-utility-profile {
  align-items: center; display: flex; gap: 0.5rem; margin: 0;
  font-size: var(--ui-text-sm); color: var(--ui-color-muted);
}
.scan-actionbar__meta .ui-utility-profile output {
  background: var(--site-card); border: 1px solid var(--site-line-strong);
  border-radius: 0.5rem; color: var(--ui-color-ink); font-weight: 650; padding: 0.3rem 0.6rem;
}
.scan-actionbar__meta .ui-utility-profile output::after { color: var(--ui-color-muted); content: "\25BE"; margin-left: 0.45rem; }
.scan-learn { align-items: center; color: var(--site-accent); display: inline-flex; font-size: var(--ui-text-sm); font-weight: 600; gap: 0.35rem; }
.scan-learn svg { height: 1rem; width: 1rem; }
/* Action-bar buttons sit at the right; status is a quiet line, not a control. */
.scan-actionbar .ui-utility-action-bar { align-items: center; display: flex; flex-wrap: wrap; gap: var(--ui-space-2); margin: 0; }
.scan-run, .scan-reset { align-items: center; display: inline-flex; gap: 0.4rem; }
.scan-actionbar [data-utility-role="cancel"] { display: none; }
.ui-utility-workbench[aria-busy="true"] .scan-actionbar [data-utility-role="cancel"] { display: inline-flex; }
.scan-actionbar [data-utility-role="status"] { color: var(--ui-color-muted); font-size: var(--ui-text-sm); flex-basis: 100%; text-align: right; margin-top: var(--ui-space-1); }

/* -- Closing "private by design" banner --------------------------------*/
.scan-privacy-banner {
  align-items: center;
  background: var(--site-accent-soft);
  border: 1px solid color-mix(in srgb, var(--site-accent) 16%, transparent);
  border-radius: 0.9rem;
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-3) var(--ui-space-4);
  padding: var(--ui-space-4) var(--ui-space-5);
}
.scan-privacy-banner__icon { color: var(--site-accent); flex: none; }
.scan-privacy-banner__icon svg { height: 1.5rem; width: 1.5rem; }
.scan-privacy-banner p { color: var(--ui-color-muted); flex: 1 1 20rem; font-size: var(--ui-text-sm); margin: 0; }
.scan-privacy-banner strong { color: var(--ui-color-ink); }
.scan-privacy-banner .ui-btn { flex: none; white-space: nowrap; }

/* -- Comp pass 2: match Image #21 more exactly -------------------------*/
/* Headline + ledes sit on one line at desktop (they wrap only when narrow). */
.scan-hero { gap: var(--ui-space-2); }
.scan-hero .ui-h1 {
  font-size: clamp(1.7rem, 3.1vw, 2.5rem);
  line-height: 1.1;
  margin: var(--ui-space-1) 0 0;
  max-width: none;
  text-wrap: balance;
}
.scan-hero__lede {
  font-size: clamp(1rem, 1.5vw, 1.18rem);
  margin: var(--ui-space-1) 0 0;
  max-width: none;
}
.scan-hero__sublede { max-width: none; }

/* "Clear" — the single reset, shown as a quiet link in the column header. */
.scan-input__head { position: relative; }
.scan-clear {
  align-items: center;
  align-self: flex-start;
  background: none !important;
  border: 0 !important;
  box-shadow: none !important;
  color: var(--ui-color-muted) !important;
  display: inline-flex;
  font-size: var(--ui-text-sm);
  font-weight: 600;
  gap: 0.3rem;
  margin-left: auto;
  padding: 0.15rem 0.3rem !important;
}
.scan-clear:hover { color: var(--site-danger-ink) !important; }
.scan-clear svg { flex: none; }

/* Compact character/byte meter, right-aligned under the box. */
.scan-meter {
  color: var(--ui-color-muted);
  font-size: var(--ui-text-sm);
  font-variant-numeric: tabular-nums;
  margin: 0;
  text-align: right;
}
.scan-meter span { color: var(--ui-color-ink); font-weight: 650; }

/* The idle "Ready …" status is noise once the layout speaks for itself;
   it returns while a scan is actually running.

   `:empty` is load-bearing, and its absence was a serious defect. Keyed on
   busy-ness alone this hid the status in every state EXCEPT mid-scan — which is
   precisely when it carries the things a visitor needs:

     empty box   "Add some content before running the scan."
     oversize    "This content is larger than one scan accepts …"
     completed   "This looks risky — review it before you trust it to an AI"

   All three were written correctly into the DOM and computed to display:none,
   0x0, every time. Pasting something oversized and pressing Scan did visibly
   nothing at all, forever, which reads as a broken site.

   The idle state is the EMPTY one — that is the "Ready …" text injected by the
   :empty::before rule above — so hiding on emptiness suppresses exactly the
   noise this rule was written for and nothing else. */
.ui-utility-workbench:not([aria-busy="true"]) .scan-actionbar [data-utility-role="status"]:empty { display: none; }

/* -- Comp pass 3: adversarial-diff findings against Image #21 -----------*/
/* Pill eyebrow: a real tinted pill with the shield glyph (was rendering bare). */
.scan-hero__badge {
  align-items: center;
  align-self: center;
  /* Solid tint, not a translucent color-mix(): the AA gate reads the
     composited backdrop, and a translucent surface leaves accent-strong
     text sitting over the near-black page it cannot see through. */
  background: var(--site-accent-soft);
  border-radius: 999px;
  color: var(--site-accent-strong);
  display: inline-flex;
  font-size: 0.72rem;
  font-weight: 700;
  gap: 0.4rem;
  letter-spacing: 0.09em;
  margin: 0;
  padding: 0.35rem 0.85rem;
  text-transform: uppercase;
}
.scan-hero__badge::before { content: none; }
.scan-hero__badge svg { height: 0.95rem; width: 0.95rem; flex: none; }
.scan-hero__lede { font-weight: 600; }

/* Trust chips read Title Case like the comp. */
.scan-trust li { text-transform: capitalize; }

/* Mode toggle: a compact, content-sized segmented control on the left,
   flat icons, and an underline accent on the active tab. */
.scan-modes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-space-3);
  grid-template-columns: none;
}
.scan-mode { flex: 0 1 auto; padding: var(--ui-space-2) var(--ui-space-4); position: relative; }
.scan-mode__icon { background: transparent; border: 0; height: auto; width: auto; }
.scan-mode__icon svg { height: 1.4rem; width: 1.4rem; }
.scan-mode--active::after {
  background: var(--site-accent);
  border-radius: 2px;
  bottom: -1px;
  content: "";
  height: 3px;
  left: var(--ui-space-4);
  position: absolute;
  width: 2rem;
}

/* Tip lightbulb, amber. */
.scan-tip__icon { color: var(--site-warn-ink); }
.scan-tip__icon svg { height: 1.15rem; width: 1.15rem; }

/* Dropzone rests NEUTRAL grey; blue is the hover/drag state (already set). */
.scan-dropzone__area {
  background: var(--site-field-bg);
  border-color: var(--site-line-strong);
}
/* Coloured sparkles, actually visible. */
.scan-dropzone__spark { opacity: 1; }
.scan-dropzone__spark--a { color: #84cc16; }
.scan-dropzone__spark--b { color: #f59e0b; }
/* "click to browse": plain link at rest, underline on hover. */
.scan-dropzone__or span { text-decoration: none; }
.scan-dropzone__or span:hover { text-decoration: underline; }

/* Learn more: no default underline. */
.scan-learn { text-decoration: none; }
.scan-learn:hover { text-decoration: underline; }

/* "Reading it as" caret: a thin chevron, not a filled triangle. */
.scan-actionbar__meta .ui-utility-profile output::after { content: none; }
.scan-actionbar__meta .ui-utility-profile output {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-position: right 0.55rem center;
  background-repeat: no-repeat;
  background-size: 0.8rem;
  padding-right: 1.7rem;
}
.scan-howitworks svg { flex: none; margin-left: 0.25rem; vertical-align: -0.2em; }

/* Slightly tighter hero rhythm to match the comp's compactness. */
.scan-hero { margin-bottom: var(--ui-space-5); }
.scan-stage { gap: var(--ui-space-5); }

/* -- Comp pass 4: live fixes (button size, footer brand, trust colours) - */
/* The action bar's real class is .ui-utility-actions; earlier rules targeted
   the wrong name, so the buttons were stretched to ~61px. Target correctly and
   stop them stretching — normal button height. */
.scan-actionbar .ui-utility-actions { align-items: center; }
.scan-actionbar .ui-utility-actions__controls { align-items: center; display: flex; flex-wrap: wrap; gap: var(--ui-space-2); }
.scan-actionbar .ui-btn { align-self: center; height: auto; min-height: 2.4rem; }
.scan-actionbar .ui-btn svg { flex: none; height: 1rem; width: 1rem; }

/* Footer brand text reads white on the navy footer (a generic strong rule
   was tinting it accent-blue). */
.site-footer__brand strong { color: #ffffff; }

/* Trust icons are colour-coded like the comp (shield blue, lock green,
   no-tracking violet, cloud amber). */
.scan-trust li:nth-child(2) svg { color: var(--site-ok-ink); }
.scan-trust li:nth-child(3) svg { color: #7c3aed; }

/* Hero first sub-line: medium weight, not semibold. */
.scan-hero__lede { font-weight: 500; }

/* Upload glyph: larger, soft pastel; sparkles visible + flanking both sides. */
.scan-dropzone__icon { color: color-mix(in srgb, var(--site-accent) 48%, #ffffff); height: 3.4rem; width: 3.4rem; }
.scan-dropzone__spark { opacity: 0.9; }
.scan-dropzone__spark--a { color: #84cc16; height: 0.95rem; width: 0.95rem; top: -0.3rem; right: -1rem; }
.scan-dropzone__spark--b { color: #f59e0b; height: 0.8rem; width: 0.8rem; top: 0; left: -1rem; opacity: 0.85; }
.scan-dropzone__spark--c { color: #84cc16; height: 0.6rem; width: 0.6rem; bottom: -0.15rem; right: -0.4rem; opacity: 0.7; position: absolute; }

/* Banner "How it works": blue label + filled play-circle. */
.scan-howitworks { color: var(--site-accent) !important; }

/* Results-header buttons: normal size. The accent button's inline SVG was
   uncapped here (the action-bar svg cap is scoped to .scan-actionbar), which
   stretched "Scan something else" to ~56px. Cap the glyph + hold min-height. */
.scan-results-actions .ui-btn { align-self: center; min-height: 2.4rem; }
.scan-results-actions .ui-btn svg { flex: none; height: 1rem; width: 1rem; }
.scan-newscan { padding: 0.45rem 0.95rem; }

/* Pin ALL results-header buttons to one explicit height so the accent
   "Scan something else" matches the quiet report buttons exactly. */
.scan-results-head .scan-results-actions .ui-btn {
  height: 2.35rem;
  min-height: 0;
  padding-top: 0;
  padding-bottom: 0;
}
.scan-results-head .scan-results-actions .ui-btn svg { height: 1rem; width: 1rem; }

/* One compact height for EVERY button on the scan page (some quiet buttons
   and the banner button were stretching to ~58-61px). Explicit height +
   zeroed block padding + align-self:center defeats both the inflated
   min-height and any flex-stretch, and the glyphs are capped. */
.scan-stage .ui-btn,
.scan-privacy-banner .ui-btn {
  align-self: center;
  height: 2.3rem;
  min-height: 0;
  padding-top: 0;
  padding-bottom: 0;
}
.scan-stage .ui-btn svg,
.scan-privacy-banner .ui-btn svg { flex: none; height: 1rem; width: 1rem; }

/* -- Smooth the scan↔results transition (was a hard display swap) --------
   Results fade+rise in when a scan completes; the compose panel does the
   same when "Scan something else" resets in place. Motion-safe. */
@keyframes scanPanelIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.scan-grid:has(.scan-panel--results .ui-utility-result:not(:empty)) .scan-panel--results {
  animation: scanPanelIn 0.34s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.scan-grid:has(.scan-panel--results .ui-utility-result:empty) .scan-panel:not(.scan-panel--results) {
  animation: scanPanelIn 0.3s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
/* The rendered result's own sections stagger in a touch behind the panel. */
.scan-panel--results .ui-utility-result:not(:empty) > * {
  animation: scanPanelIn 0.4s ease both;
}
@media (prefers-reduced-motion: reduce) {
  .scan-grid .scan-panel,
  .scan-panel--results .ui-utility-result > * { animation: none !important; }
}

/* The no-JS notice: this is the whole page for a visitor with scripting off,
   so it reads first and does not hide behind the hero's styling. */
.scan-noscript {
  background: var(--site-card);
  border: 1px solid var(--site-line);
  border-left: 4px solid var(--ui-color-accent, currentColor);
  border-radius: 0.75rem;
  margin: 0 0 var(--ui-space-4);
  padding: var(--ui-space-4);
}
.scan-noscript p { margin: 0 0 var(--ui-space-2); }
.scan-noscript p:last-child { margin-bottom: 0; }

/* === THE ANSWER FIRST, AND ONLY THE REAL SIGNAL LOUD ===================
   Two defects, both of which made the page argue against its own purpose. */

/* 1 · THE VERDICT WAS BELOW THE NUMBERS.
   "This looks risky" is the answer to the question the visitor arrived with,
   and it rendered beneath five counters and two grey paragraphs — quieter than
   the privacy chip in the hero. The result is core-rendered, so its sections
   cannot be reordered in markup; ordering the panel does it instead.

   NOT DONE WITH `display: contents`, though that is the obvious way to get the
   counters between the verdict and the findings. An element with
   display:contents generates no box: it stops being measurable, and it stops
   being the labelled region it is marked up as. The accessibility suite caught
   it by name — the result must still report a width at 200% zoom on a 320px
   viewport — and it was right to. Dissolving a labelled region to move a
   counter is a bad trade.

   So the panel reorders the result AS A WHOLE and the counters follow it. The
   verdict leads the card, which was the actual defect; the counters read as
   supporting detail rather than as the headline, which they never should have
   been. */
.scan-panel--results {
  display: flex;
  flex-direction: column;
}
.scan-panel--results .scan-results-head { order: 1; }
.scan-panel--results .ui-utility-result { order: 2; }
.scan-panel--results .scan-tiles { order: 3; }
.scan-panel--results .scan-results-note { order: 4; }
.scan-panel--results .site-export-warning { order: 5; }
.scan-panel--results .scan-results-footnote { order: 6; }

/* The verdict earns severity colour rather than sharing the card's neutral
   chrome, so the answer is legible before any number is read. Filled, not
   tinted — a hairline accent reads as decoration at a glance. */
.scan-panel--results .ui-utility-result:has([data-utility-view="findings"] [data-severity="high"]) [data-utility-view="summary"] {
  background: var(--site-danger-soft);
  border-color: var(--site-danger-ink);
  border-inline-start: 0.35rem solid var(--site-danger-ink);
}
.scan-panel--results .ui-utility-result:has([data-utility-view="findings"] [data-severity="high"]) [data-utility-view="summary"] > p:first-child {
  color: var(--site-danger-ink);
}

/* 2 · ORDINARY WHITESPACE IS NOT EVIDENCE.
   The engine boxes every control, format, zero-width, bidi and
   default-ignorable scalar in one identical high-contrast chip. In real
   documents the overwhelming majority of those are LINE FEEDS — a scan of a
   61-line ticket produced three of them inside a single excerpt and not one
   genuinely invisible character. The signal the whole product exists to surface
   was rendered indistinguishably from pressing Enter.

   The demoted set is closed and enumerated: the C0 whitespace controls plus
   NEL. Everything else — zero-width, bidi overrides, tag characters, soft
   hyphen, and anything nobody has thought of yet — keeps the loud treatment by
   default. This direction is deliberate for a security tool: an unfamiliar
   codepoint fails LOUD, never quiet. Demoting by exception can only ever hide
   a character someone chose to list. */
.scan-panel--results .ui-utility-visible-token[data-core-visible-token="U+0009"],
.scan-panel--results .ui-utility-visible-token[data-core-visible-token="U+000A"],
.scan-panel--results .ui-utility-visible-token[data-core-visible-token="U+000B"],
.scan-panel--results .ui-utility-visible-token[data-core-visible-token="U+000C"],
.scan-panel--results .ui-utility-visible-token[data-core-visible-token="U+000D"],
.scan-panel--results .ui-utility-visible-token[data-core-visible-token="U+0085"] {
  background: transparent;
  border-color: transparent;
  color: inherit;
  font-size: 0.8em;
  opacity: 0.32;
}

/* The genuinely invisible ones now carry the weight the newlines were
   borrowing. Colour is set as a literal rather than mixed, because the
   contrast gate cannot parse color-mix() and scores the mixed value as a
   failure. */
.scan-panel--results .ui-utility-visible-token {
  background: #7f1d1d;
  border-color: #fca5a5;
  color: #fee2e2;
  font-weight: 650;
}

/* 3 · THE SEVERITY CHIP RULES WERE DEAD.
   These targeted `article[data-severity]`, and the engine renders findings as
   `li[data-severity]` containing `.ui-utility-finding-row__severity` — there is
   no <article> in the findings view at all. The rules had never applied, so the
   tier that matters most carried no colour. Re-pointed at what is really
   rendered, and at the detail panel's badge beside it. */
.scan-panel--results [data-utility-view="findings"] .ui-utility-finding-row__severity,
.scan-panel--results [data-utility-view="findings"] .ui-utility-finding-detail__severity {
  border-radius: 999px;
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 650;
  padding: 0.125rem 0.625rem;
}
.scan-panel--results [data-utility-view="findings"] .ui-utility-finding-row__severity[data-severity="high"],
.scan-panel--results [data-utility-view="findings"] .ui-utility-finding-detail__severity[data-severity="high"] {
  background: var(--site-danger-soft);
  color: var(--site-danger-ink);
}
.scan-panel--results [data-utility-view="findings"] .ui-utility-finding-row__severity:not([data-severity="high"]),
.scan-panel--results [data-utility-view="findings"] .ui-utility-finding-detail__severity:not([data-severity="high"]) {
  background: var(--site-warn-soft);
  color: var(--site-warn-ink);
}

/* 4 · THE COUNTERS WERE ALL ONE COLOUR, INCLUDING THE TELEMETRY.
   Five cards in identical blue gave "Characters scanned" the same weight as
   "Strong indicators", so nothing said which number was the point. The two
   severity counts take severity colour; the diagnostics recede. */
.scan-tiles [data-ui-tile="strong"] [data-ui-tile-value] { color: var(--site-danger-ink); }
.scan-tiles [data-ui-tile="review"] [data-ui-tile-value] { color: var(--site-warn-ink); }
.scan-tiles [data-ui-tile="scanned"],
.scan-tiles [data-ui-tile="findings"] {
  opacity: 0.72;
}
.scan-tiles [data-ui-tile="scanned"] [data-ui-tile-value],
.scan-tiles [data-ui-tile="findings"] [data-ui-tile-value] {
  font-size: 1.15rem;
}

/* 5 · The exports stop competing without being hidden.
   "Scan something else" is what most readers do next; exporting is what a few
   do. The exports keep their own row beneath the primary action, at small size
   and in muted ink, so the ranking is legible at a glance — and every one of
   them stays in the accessibility tree, focusable and clickable, which a
   collapsed disclosure would not. */
.scan-export-group {
  flex-basis: 100%;
  font-size: var(--ui-text-sm);
  margin-top: var(--ui-space-2);
  opacity: 0.8;
}
.scan-export-group .ui-btn {
  font-size: var(--ui-text-sm);
  padding: 0.2rem 0.6rem;
}
.scan-export-group:focus-within,
.scan-export-group:hover {
  opacity: 1;
}

.scan-howitworks-row {
  display: flex;
  justify-content: center;
  margin: var(--ui-space-5) 0 0;
}

/* === MOBILE FIXES =======================================================
   Measured: 13 pages x 5 viewports x 2 engines. No page-level horizontal
   overflow anywhere; the defects were sticky chrome, sub-44px targets, text
   under 12px, and prose clipped away on /privacy.

   48rem for every FLOOR rule (target size, type size, wrap) because those were
   measured failing at every width including 768. Narrower scopes are for
   layout-shaping only. All inside max-width queries: desktop is untouched.

   THIS BLOCK MUST STAY LAST — several rules restate an earlier selector at
   equal specificity and win on source order alone. */

/* Home hero: the <=60rem collapse was DEAD, beaten by a later unconditional
   grid-template-columns at equal specificity. That left the text in a 6.4fr
   track beside an empty 5.6fr one — 128px at 320px, which is the cell that
   "clipped" the trust chip. Root cause, not the nowrap. */
@media (max-width: 60rem) {
  .site-hero-split { grid-template-columns: minmax(0, 1fr); }
}

/* Safety net below that, for narrower devices and text scaling. */
@media (max-width: 40rem) {
  .site-trust li { white-space: normal; }
}

/* /privacy printed a 45-char URL 318px wide in a 288px column, and
   `overflow-x: clip` opens no scroll port — the tail was unreadable AND
   unreachable. `anywhere` also lowers min-content, so a long token cannot blow
   out a track; it breaks only tokens that cannot fit a line alone, and cannot
   override white-space: nowrap. */
@media (max-width: 48rem) {
  .site-prose,
  .site-editorial { overflow-wrap: anywhere; }
}

/* Type floor. Measured 11px badge, 11.5px kicker and footer heading. The
   kicker pays for its extra fraction out of tracking, so it gains no wrapped
   line at 320px. */
@media (max-width: 48rem) {
  .site-kicker,
  .site-kicker--pill,
  .site-footer__heading { font-size: var(--ui-text-xs); }

  .site-kicker,
  .site-kicker--pill { letter-spacing: 0.08em; }

  .site-badge,
  .scan-hero__badge { font-size: 0.75rem; }
}

/* Touch targets, 2.8rem = 44.8px (at 2.75rem the shortest label measured
   43.98px — sub-pixel short is still short).

   box-sizing is LOAD-BEARING: there is no global border-box reset here, so a
   <button> gets it from the UA sheet and an <a> does not. That split is why one
   shared height rule measured 37px on a button and 39px on the link beside it.

   Inline prose links are deliberately absent — WCAG 2.5.5/2.5.8 exempt a target
   inside a sentence, and padding them would overlap adjacent lines and send
   taps to the wrong link. */
@media (max-width: 48rem) {
  .ui-btn {
    box-sizing: border-box;
    min-height: 2.8rem;
  }

  /* NO min-width on a flex item: it replaces the implicit `min-width: auto`
     that stops the item shrinking below its content. Setting it made 416 nav
     links render 44px wide holding 50-65px of text, clipping their own labels.
     `flex: none` first; padding gives the short labels their width. */
  .site-nav a {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    min-height: 2.8rem;
    min-width: 2.8rem;
    padding-inline: 0.5rem;
  }

  /* The masthead CTA is pinned to the toggle's height on purpose, so the two
     move together or the pairing breaks. */
  .site-theme-toggle {
    box-sizing: border-box;
    width: 2.8rem;
    min-width: 2.8rem;
    height: 2.8rem;
    min-height: 2.8rem;
  }
  .ui-header .ui-btn--accent {
    box-sizing: border-box;
    height: 2.8rem;
  }

  /* The `display` change is required, not cosmetic: .site-brand__name declares
     none, so it is an inline <a> and min-height alone is a silent no-op. */
  .ui-header .site-brand__name,
  .ui-skip {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    min-height: 2.8rem;
  }

  /* Footer: padding alone would overlap neighbours at a 33px pitch, so the
     pitch grows. width:auto overrides an earlier fit-content. */
  .site-footer__col { gap: 0; }
  .site-footer__col a {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    min-height: 2.8rem;
    min-width: 2.8rem;
    width: auto;
  }
  .site-footer__brand {
    box-sizing: border-box;
    min-height: 2.8rem;
  }

  /* height:auto releases earlier explicit pins so min-height can do the work. */
  .scan-actionbar .ui-btn,
  .scan-stage .ui-btn,
  .scan-export-group .ui-btn,
  .scan-results-actions .ui-btn,
  .scan-results-head .scan-results-actions .ui-btn {
    box-sizing: border-box;
    height: auto;
    min-height: 2.8rem;
  }

  /* Not a .ui-btn: a bare inline-flex link, and the only route from the
     workbench to the methodology. */
  .scan-learn,
  .scan-modes a,
  .site-scan-card__tabs a,
  .ui-main aside > a,
  .site-banner > a {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    min-height: 2.8rem;
  }

  .ui-header .site-brand__promise { display: none; }
}

/* The masthead measured 215px — 38% of a 568px screen, sticky, on every page.
   Unsticking beats collapsing behind a toggle: this site shipped a <details>
   menu once and had to take it back, because a closed disclosure removes its
   contents from the accessibility tree. Every link stays reachable. */
@media (max-width: 48rem) {
  .ui-header { position: static; }
}
