/* CandidPDF — one stylesheet, no external assets, no build step.

   Four things in here are load-bearing rather than decorative:

   1. Every colour is a token declared in :root and redeclared in the dark
      block. tools/a11y.test.mjs parses this file, pairs the tokens the way the
      pages actually pair them, and fails the build under 4.5:1. Introduce a
      colour by editing a token, never by inlining a hex in a rule, or it goes
      unchecked.

   2. Gradients get their endpoints declared as tokens (--wash-1, --wash-2) and
      those endpoints are contrast-tested like any other background. sRGB
      interpolation keeps every intermediate luminance between the two, so
      testing the ends bounds the whole ramp. Text NEVER sits on a gradient
      whose ends are not tokens.

   3. The severity colours are a presentation of facts the engine reported.
      They are not a score, a grade, or a rating, and nothing in the markup
      says "good" or "bad" -- the sentence next to the colour carries the
      meaning, so the page still works with the colour removed.

   4. No inline style attributes anywhere, in markup or generated. The deployed
      CSP is `style-src 'self'` with no 'unsafe-inline', which silently zeroes
      them: the split bar shipped as style="width:18.6%" and rendered as an
      empty grey track in production while every local check passed. Widths
      that must be computed are set through the CSSOM, which CSP does not
      block. tools/viewport.test.mjs now fails on any CSP violation. */

:root {
  color-scheme: light dark;

  /* --- surfaces --- */
  --bg: #fbfcfe;
  --wash-1: #eef3fc;
  --wash-2: #fbfcfe;
  --panel: #ffffff;
  --panel-2: #f5f8fd;
  --line: #dde4ef;

  /* --- ink --- */
  --ink: #0d1526;
  --ink-soft: #3e4a5e;

  /* --- brand and the one electric accent --- */
  --brand: #0f2f56;
  --on-brand: #ffffff;
  --accent: #0b53d8;
  --accent-soft: #e6eeff;
  --on-accent: #ffffff;

  /* --- carried forward --- */
  --brand-soft: #e6eeff;
  --warn-bg: #fdf4e3;
  --warn-line: #e6c68b;
  --ok: #1d6b3f;
  --bad: #9a2c2c;

  /* --- severity: applied by rule, not by taste. See sevOf() in results.js --- */
  --sev-critical: #a52020;
  --sev-critical-bg: #fdecea;
  --sev-critical-line: #f0b4ae;
  --sev-caution: #8a5300;
  --sev-caution-bg: #fdf4e3;
  --sev-caution-line: #e6c68b;
  --sev-clear: #146b3a;
  --sev-clear-bg: #e9f6ee;
  --sev-clear-line: #a9d8bd;

  /* --- form --- */
  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 18px;
  --radius-xl: 26px;
  --measure: 34rem;

  --shadow-1: 0 1px 2px rgba(13, 21, 38, 0.05);
  --shadow-2: 0 1px 2px rgba(13, 21, 38, 0.05), 0 8px 24px -14px rgba(13, 21, 38, 0.22);
  --shadow-3: 0 2px 4px rgba(13, 21, 38, 0.05), 0 18px 40px -20px rgba(13, 21, 38, 0.3);
  --ring: 0 0 0 1px rgba(11, 83, 216, 0.16);

  /* --- type. No webfont: the deployed CSP is default-src 'none' and adding
         one would mean either loosening it or shipping a licensed binary, so
         the pairing is built from faces the platform already has. --- */
  --font-ui: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: "SF Pro Display", ui-sans-serif, -apple-system, "Segoe UI Variable Display", "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;

  /* --- motion --- */
  --dur-fast: 130ms;
  --dur: 240ms;
  --dur-slow: 520ms;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-spring: cubic-bezier(0.16, 1, 0.3, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #080e1c;
    --wash-1: #101b35;
    --wash-2: #080e1c;
    --panel: #111a2e;
    --panel-2: #16223c;
    --line: #25324e;

    --ink: #e9effc;
    --ink-soft: #adbdd8;

    --brand: #9dc4e8;
    --on-brand: #071021;
    --accent: #78aeff;
    --accent-soft: #152444;
    --on-accent: #071021;

    --brand-soft: #152444;
    --warn-bg: #2a2318;
    --warn-line: #6b5730;
    --ok: #6cc08d;
    --bad: #e08585;

    --sev-critical: #ff9d95;
    --sev-critical-bg: #2b1917;
    --sev-critical-line: #6b3630;
    --sev-caution: #e8b968;
    --sev-caution-bg: #2a2318;
    --sev-caution-line: #6b5730;
    --sev-clear: #74c795;
    --sev-clear-bg: #15241b;
    --sev-clear-line: #2f5a41;

    --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.45);
    --shadow-2: 0 1px 2px rgba(0, 0, 0, 0.45), 0 10px 28px -16px rgba(0, 0, 0, 0.85);
    --shadow-3: 0 2px 6px rgba(0, 0, 0, 0.5), 0 22px 48px -22px rgba(0, 0, 0, 0.95);
    --ring: 0 0 0 1px rgba(120, 174, 255, 0.22);
  }
}

/* Smooth cross-document transitions where the browser supports them; a silent
   no-op everywhere else, and disabled entirely under reduced motion below. */
@view-transition { navigation: auto; }

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 17px/1.6 var(--font-ui);
  font-feature-settings: "kern" 1;
  text-rendering: optimizeLegibility;
  /* The wash. Both endpoints are tokens and both are contrast-tested. */
  background-image: linear-gradient(180deg, var(--wash-1) 0%, var(--wash-2) 46rem);
  background-repeat: no-repeat;
}

main { max-width: 64rem; margin: 0 auto; padding: 0 1.25rem 4rem; }

h1, h2, h3 {
  font-family: var(--font-display);
  line-height: 1.13;
  letter-spacing: -0.025em;
  font-weight: 700;
}

a { color: var(--accent); text-underline-offset: 0.15em; }

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

svg.icon { flex: none; width: 1.25rem; height: 1.25rem; }

/* ------------------------------------------------------------------ motion

   Everything below is opt-in through a class, so a page with JavaScript
   turned off shows the finished state rather than an empty one: .reveal is
   only applied by motion.js, which immediately marks the first screen ready.

   The last block is the important one. Reduced motion is not "slightly less
   motion" -- it is none, including the count-up and the bar sweep, both of
   which are driven from JS that checks the same media query. */

.reveal { opacity: 0; transform: translateY(14px); }
.reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease-spring);
}

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

@keyframes shimmer {
  from { background-position: -140% 0; }
  to { background-position: 240% 0; }
}

@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal, .reveal.is-in { opacity: 1; transform: none; }
  .skeleton { animation: none !important; background-image: none !important; }
}

/* ---------------------------------------------------------------- chrome */

header.site {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  max-width: 64rem;
  margin: 0 auto;
  padding: 0.9rem 1.25rem;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font: 700 1.22rem/1 var(--font-display);
  color: var(--ink);
  text-decoration: none;
  letter-spacing: -0.03em;
}
.wordmark-text span { color: var(--accent); }
.mark { width: 1.55rem; height: 1.55rem; flex: none; }

header.site nav { display: flex; gap: 1.25rem; font-size: 0.92rem; }
header.site nav a { color: var(--ink-soft); text-decoration: none; }
header.site nav a:hover { color: var(--accent); text-decoration: underline; }

footer.site {
  border-top: 1px solid var(--line);
  margin-top: 3rem;
  padding: 1.75rem 1.25rem 3rem;
}
footer.site p {
  max-width: 52rem;
  margin: 0 auto;
  color: var(--ink-soft);
  font-size: 0.84rem;
  line-height: 1.65;
}

/* ---------------------------------------------------------------- hero */

.hero { padding: 3rem 0 2.5rem; display: grid; gap: 2.25rem; align-items: center; }
@media (min-width: 56rem) {
  .hero { grid-template-columns: 1.05fr 1fr; gap: 3.25rem; }
  .hero h1 { font-size: clamp(2rem, 3.1vw, 2.65rem); max-width: 19ch; }
}
/* Round 7 turned the headline from a four-word slogan into a plain sentence.
   Slogan type sizes make a sentence shout, so the scale came down and the
   measure went up. */
.hero h1 {
  font-size: clamp(1.95rem, 6.2vw, 2.75rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  margin: 0 0 1.15rem;
  max-width: 21ch;
}
.hero h1 .accent { color: var(--accent); }
.subhead {
  font-size: clamp(1.04rem, 1.6vw, 1.2rem);
  color: var(--ink-soft);
  max-width: 38rem;
  margin: 0;
  line-height: 1.55;
}

.hero-cta { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 1.6rem 0 0.7rem; }
.hero-sub { margin: 0; font-size: 0.86rem; color: var(--ink-soft); }

.btn {
  display: inline-block;
  font-weight: 650;
  background: var(--accent);
  color: var(--on-accent);
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 0.8rem 1.5rem;
  text-decoration: none;
  box-shadow: var(--shadow-2);
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur) var(--ease), filter var(--dur-fast) var(--ease);
}
.btn:hover { filter: brightness(1.07); transform: translateY(-1px); box-shadow: var(--shadow-3); }
.btn:active { transform: translateY(1px); box-shadow: var(--shadow-1); }
.btn-quiet { background: var(--panel); color: var(--accent); border-color: var(--line); box-shadow: var(--shadow-1); }

/* --- the interactive sample card --- */

.probe {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-3);
  padding: 1.4rem 1.4rem 1.25rem;
  margin: 0;
}
.probe-head { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.probe-num {
  font-family: var(--font-display);
  font-size: 2.7rem;
  font-weight: 700;
  letter-spacing: -0.045em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.probe-unit { font-size: 0.9rem; font-weight: 650; color: var(--ink-soft); }
.probe-good .probe-num { color: var(--sev-clear); }

.probe-part + .probe-part {
  margin-top: 1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--line);
}
/* Part two is a worklist, not a shortfall. Same ink as the rest of the card,
   no severity colour, no track behind it. */
.probe-worklist .probe-rest { color: var(--ink); font-size: 0.92rem; line-height: 1.5; margin: 0; }
.probe-rest-n { font-weight: 700; font-variant-numeric: tabular-nums; }
.probe-caption { margin: 0.3rem 0 0; }

.probe-price { margin: 0.35rem 0 0; font-size: 0.95rem; color: var(--ink-soft); }
.probe-price-n {
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--ink);
}


.probe-caption { margin: 0 0 0.9rem; font-size: 0.87rem; color: var(--ink-soft); min-height: 2.9em; line-height: 1.45; }

.probe-cats { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0; padding: 0; list-style: none; }
.probe-cat {
  font: inherit;
  font-size: 0.84rem;
  font-weight: 650;
  background: var(--panel-2);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 99px;
  padding: 0.3rem 0.7rem;
  cursor: pointer;
  box-shadow: none;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.probe-cat:hover:not(:disabled) { border-color: var(--accent); transform: translateY(-1px); filter: none; box-shadow: none; }
.probe-cat:active:not(:disabled) { transform: translateY(1px); }
.probe-cat[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); }
.probe-hint { margin: 0.8rem 0 0; font-size: 0.85rem; color: var(--ink-soft); }
.probe-foot { margin-top: 0.8rem; font-size: 0.85rem; color: var(--ink-soft); }

/* ---------------------------------------------------------------- upload */

.upload {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2);
  padding: 1.75rem;
  margin: 1rem 0 3.5rem;
}
.upload h2 { margin: 0 0 1.1rem; font-size: 1.35rem; }

.dropzone {
  display: block;
  position: relative;
  border: 2px dashed var(--line);
  border-radius: var(--radius);
  background: var(--brand-soft);
  padding: 2.1rem 1.25rem;
  text-align: center;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), transform var(--dur-fast) var(--ease), box-shadow var(--dur) var(--ease);
}
/* The real input is clipped for styling, so it keeps focus but shows no ring.
   Put the ring on the visible control instead, or keyboard users are lost. */
.dropzone:focus-within { outline: 3px solid var(--accent); outline-offset: 2px; }
.dropzone:hover { border-color: var(--accent); }
.dropzone.dragging {
  border-color: var(--accent);
  border-style: solid;
  transform: scale(1.012);
  box-shadow: var(--shadow-3), var(--ring);
}
.dropzone.has-file { border-style: solid; border-color: var(--accent); }
.dropzone input[type="file"] {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.dz-main { display: block; font-weight: 700; font-size: 1.05rem; }
.dz-sub { display: block; margin-top: 0.4rem; font-size: 0.88rem; color: var(--ink-soft); }

button {
  font: inherit;
  font-weight: 650;
  background: var(--accent);
  color: var(--on-accent);
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 0.8rem 1.5rem;
  cursor: pointer;
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-fast) var(--ease), filter var(--dur-fast) var(--ease), box-shadow var(--dur) var(--ease);
}
button:hover:not(:disabled) { filter: brightness(1.07); transform: translateY(-1px); box-shadow: var(--shadow-2); }
button:active:not(:disabled) { transform: translateY(1px); box-shadow: var(--shadow-1); }
button:disabled { opacity: 0.45; cursor: not-allowed; }
button.secondary { background: var(--panel); color: var(--accent); border-color: var(--line); }

#upload-form { display: grid; gap: 1rem; justify-items: start; }
#upload-form button { width: 100%; }
@media (min-width: 34rem) { #upload-form button { width: auto; } }

.status {
  margin-top: 1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
  font-size: 0.94rem;
  animation: fold-in var(--dur) var(--ease);
}
.status.error { border-left-color: var(--bad); color: var(--bad); }

.privacy {
  margin-top: 1.5rem;
  padding: 1rem 1.15rem;
  background: var(--warn-bg);
  border: 1px solid var(--warn-line);
  border-radius: 10px;
}
.privacy h3 { margin: 0 0 0.4rem; font-size: 0.95rem; }
.privacy p { margin: 0 0 0.5rem; font-size: 0.86rem; line-height: 1.6; }
.privacy p:last-child { margin-bottom: 0; }
.privacy-life { font-weight: 650; }
.privacy-warn { color: var(--ink-soft); }

.facts { list-style: none; margin: 0 0 0.6rem; padding: 0; display: grid; gap: 0.35rem; }
.facts li { display: flex; align-items: flex-start; gap: 0.5rem; font-size: 0.86rem; line-height: 1.5; }
.fact-i { flex: none; width: 1.15rem; height: 1.15rem; margin-top: 0.15rem; color: var(--ink-soft); }

/* ---------------------------------------------------------------- blocks */

section { scroll-margin-top: 1.5rem; }
section h2 { font-size: clamp(1.5rem, 3.4vw, 2.05rem); }

.section-head { max-width: 44rem; margin-bottom: 1.5rem; }
.section-head h2 { margin: 0 0 0.5rem; }
.section-head p { margin: 0; color: var(--ink-soft); }

/* --- honesty block: the signature element --- */

.honesty {
  background: var(--brand);
  color: var(--on-brand);
  border-radius: var(--radius-xl);
  padding: clamp(1.75rem, 5vw, 3rem);
  margin: 1rem 0 3.5rem;
  box-shadow: var(--shadow-3);
}
.honesty h2 {
  margin: 0 0 1.1rem;
  font-size: clamp(1.7rem, 4.6vw, 2.6rem);
  max-width: 18ch;
}
.honesty p { max-width: 42rem; color: var(--on-brand); }
.honesty .lead { font-size: clamp(1.08rem, 2vw, 1.28rem); font-weight: 650; margin: 0 0 0.9rem; }
.contrast {
  display: grid;
  gap: 0.9rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  margin: 1.4rem 0 0;
}
.contrast-col {
  border: 1px solid currentColor;
  border-radius: var(--radius-lg);
  padding: 1rem 1.1rem 1.1rem;
}
.contrast-col h3 {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 0.6rem;
  font-size: 0.95rem;
  color: var(--on-brand);
}
.contrast-col .fact-i { width: 1.15rem; height: 1.15rem; color: var(--on-brand); margin: 0; }
.contrast-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.35rem; }
.contrast-col li { color: var(--on-brand); font-size: 0.92rem; line-height: 1.4; }

.honesty .claim {
  font-size: 0.92rem;
  margin: 1.5rem 0 0;
  padding-top: 1.25rem;
  border-top: 1px solid currentColor;
}

/* --- scanned-document block --- */

.scanned {
  border: 1px solid var(--sev-critical-line);
  background: var(--sev-critical-bg);
  border-radius: var(--radius-lg);
  padding: 1.5rem 1.6rem;
  margin: 0 0 3.5rem;
  display: flex;
  gap: 1.1rem;
  align-items: flex-start;
}
.scanned .icon { color: var(--sev-critical); width: 1.6rem; height: 1.6rem; margin-top: 0.15rem; }
.scanned h2 { margin: 0 0 0.4rem; font-size: 1.25rem; }
.scanned p { margin: 0; max-width: 44rem; }
.scanned strong { color: var(--sev-critical); }

/* --- personas --- */

.personas { margin: 0 0 3.5rem; }
.persona-cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
}
.persona {
  background: var(--accent-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.35rem 1.4rem;
}
.personas h2 { margin: 0 0 1rem; }
.persona .fact-i { width: 1.5rem; height: 1.5rem; margin: 0 0 0.6rem; color: var(--accent); }
.persona h3 { margin: 0 0 0.4rem; font-size: 1.08rem; }
.persona p { margin: 0; color: var(--ink-soft); font-size: 0.93rem; line-height: 1.55; }

/* --- measured numbers --- */

.measured { margin: 0 0 3.5rem; }
.stats {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  margin: 0 0 1rem;
}
.stats > div {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.15rem 1.25rem;
  box-shadow: var(--shadow-1);
}
.stats dt { font-size: 0.85rem; color: var(--ink-soft); line-height: 1.35; }
.stats dd {
  margin: 0.4rem 0 0;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- pricing */

.bands {
  list-style: none;
  padding: 0;
  margin: 1.5rem 0 1.25rem;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}
.bands > li {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.25rem 1.3rem 1.4rem;
  box-shadow: var(--shadow-1);
  display: flex;
  flex-direction: column;
}
.pages { display: block; font-size: 0.82rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.09em; font-weight: 700; }
.price {
  display: block;
  font-family: var(--font-display);
  font-size: 2.1rem;
  font-weight: 700;
  letter-spacing: -0.035em;
  margin: 0.25rem 0 0.9rem;
}
.deliverables {
  margin: 0;
  padding: 0.9rem 0 0;
  border-top: 1px solid var(--line);
  list-style: none;
  font-size: 0.86rem;
  color: var(--ink-soft);
}
.deliverables li { margin-bottom: 0.4rem; padding-left: 1.3rem; position: relative; }
.deliverables li:last-child { margin-bottom: 0; }
.deliverables li::before {
  content: "";
  position: absolute;
  left: 0.15rem;
  top: 0.42em;
  width: 0.42rem;
  height: 0.22rem;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}

.deliverables-once { border-top: 0; padding-top: 0.6rem; margin-top: 0.75rem; }

.pricing { margin: 0 0 1rem; }

/* ---------------------------------------------------- the approval email */

.approval { margin: 2.5rem 0 1rem; }
.draft {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.15rem 1.25rem 1.1rem;
  box-shadow: var(--shadow-1);
}
/* The email is real selectable text, not a JS-injected value, so it can be
   copied by hand if the clipboard call is ever refused. */
#approval-text {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  font: inherit;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--ink);
}
.draft-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; margin: 1rem 0 0; }
.copy-done { font-size: 0.88rem; font-weight: 650; color: var(--sev-clear); }
.fineprint { font-size: 0.88rem; color: var(--ink-soft); max-width: 44rem; }

/* ---------------------------------------------------------------- results */

.doc-meta {
  color: var(--ink-soft);
  font-size: 0.84rem;
  margin: 0.75rem 0 0.85rem;
  word-break: break-word;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* The verdict. One panel, one dominant number, one sentence -- everything the
   phone acceptance test measures. */

.verdict {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--panel);
  box-shadow: var(--shadow-2);
  padding: 1.4rem 1.35rem 1.35rem;
  border-top: 5px solid var(--line);
}
/* ROUND 8: the verdict card used to wear its severity as a coloured top edge
   and a coloured count. Together they read as a failing grade on the reader's
   document, which is the framing this round removes. The count is now plain
   ink and the card has no severity edge.

   The ALARM inside it keeps its full alarm treatment, because that one is a
   genuine warning about their document rather than a score of it: a scanned
   file really does read as nothing to assistive technology, and that is the
   most useful sentence on the page. Severity colouring elsewhere (chips,
   rule groups) is still driven by structural facts, unchanged. */

.verdict-count {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  flex-wrap: wrap;
  margin: 0;
  font-size: 1rem;
}
.verdict-num {
  font-family: var(--font-display);
  font-size: clamp(3.4rem, 17vw, 4.6rem);
  line-height: 0.92;
  letter-spacing: -0.05em;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.verdict-unit {
  font-size: 0.95rem;
  font-weight: 650;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  text-transform: uppercase;
}
.verdict-num { color: var(--ink); }

.verdict-line { margin: 0.7rem 0 0; font-size: 1.02rem; line-height: 1.45; }
.verdict-scope { margin: 0.6rem 0 0; font-size: 0.85rem; color: var(--ink-soft); line-height: 1.5; }

/* The alarm. Our most arresting true sentence, and it gets the loudest
   treatment on the site -- but it is still a sentence, so a reader who cannot
   see the colour loses nothing. */
.alarm {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  margin: 0.9rem 0 0;
  padding: 0.85rem 0.95rem;
  background: var(--sev-critical-bg);
  border: 1px solid var(--sev-critical-line);
  border-left: 5px solid var(--sev-critical);
  border-radius: 10px;
  font-size: 0.95rem;
  line-height: 1.45;
  animation: fold-in var(--dur-slow) var(--ease);
}
.alarm .icon { color: var(--sev-critical); margin-top: 0.1rem; }
.alarm strong { color: var(--sev-critical); }

/* --- the green half of the arc --- */

.card.success { border-top: 5px solid var(--sev-clear); }
.card.success > h2 { display: flex; align-items: center; gap: 0.5rem; }
.h-icon { color: var(--sev-clear); }

.success-count { display: flex; align-items: baseline; gap: 0.55rem; flex-wrap: wrap; margin: 0.2rem 0 0.9rem; }
.success-num {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 11vw, 3.2rem);
  line-height: 0.95;
  letter-spacing: -0.045em;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--sev-clear);
}
.success-unit { font-size: 0.95rem; font-weight: 650; color: var(--ink-soft); }
.success-guard { margin: 0 0 0.9rem; font-size: 0.85rem; color: var(--ink-soft); line-height: 1.5; }

/* Proportional, and written out underneath. On a document where we fix 18%
   the green segment is 18% wide -- that is the honest picture, not a
   decoration, so it must never be styled to look fuller than it is. The width
   is set through the CSSOM by results.js; an inline style attribute would be
   dropped by the CSP and the bar would read as empty. */
/* ------------------------------------------------------------- work bar

   Two kinds of work, side by side. Green is what software does, blue is the
   site's own accent and marks what a person does. Neither is a severity
   colour, there is no track showing "remaining", and nothing here is a
   progress bar: the element is role="img" with a name that says "two counts
   of work", and the legend states both counts in text so the geometry never
   carries the meaning alone.

   Widths arrive from motion.js through the CSSOM. An inline style attribute
   would be dropped by the deployed CSP (style-src 'self') and the bar would
   render as an empty track, which is exactly how this shipped broken once. */

.workbar {
  display: flex;
  height: 0.6rem;
  border-radius: 99px;
  overflow: hidden;
  background: var(--line);
  margin: 0.95rem 0 0.55rem;
  gap: 2px;
}
.wb-seg {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 99px;
  transition: width var(--dur-slow) var(--ease-spring);
}
.wb-fix { background: var(--sev-clear); }
.wb-person { background: var(--accent); }

.wb-key {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 1.1rem;
  margin: 0;
  font-size: 0.87rem;
  color: var(--ink);
  line-height: 1.45;
}
.wb-k { display: inline-flex; align-items: baseline; gap: 0.4rem; }
.wb-dot {
  flex: none;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 99px;
  transform: translateY(-0.05em);
}
.wb-k-fix .wb-dot { background: var(--sev-clear); }
.wb-k-person .wb-dot { background: var(--accent); }
.wb-n { font-weight: 700; font-variant-numeric: tabular-nums; }
.wb-k-fix .wb-n { color: var(--sev-clear); }
.wb-k-person .wb-n { color: var(--accent); }

.workbar-wrap { margin: 0 0 1rem; }

@media (prefers-reduced-motion: reduce) {
  .wb-seg { transition: none; }
}

/* The worklist line. Deliberately NOT an alarm: this is the list we produce
   for them, so it takes ordinary ink on the ordinary raised surface. The
   number is emphasised because it is useful, not because it is bad. */
.worklist {
  margin: 0 0 0.75rem;
  color: var(--ink);
  font-size: 0.95rem;
  line-height: 1.5;
}
.worklist-n { font-weight: 700; font-variant-numeric: tabular-nums; }

/* One priced button. The price is not a separate line to read and then act
   on; it is the action. */
.buy-row { margin: 0.35rem 0 0.5rem; }
.cta-buy {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  padding: 0.95rem 1.2rem;
  font-size: 1.05rem;
  text-align: left;
}
.cta-main { font-weight: 700; }
.cta-price { font-family: var(--font-display); font-size: 1.25rem; font-weight: 700; letter-spacing: -0.025em; white-space: nowrap; }

.chips-ok { margin-top: 1rem; }
.chip-ok { border-left-color: var(--sev-clear); }
.chip-icon-ok { background: var(--sev-clear-bg); color: var(--sev-clear); }

/* --- category chips --- */

.chips { list-style: none; margin: 0.9rem 0 0; padding: 0; display: grid; gap: 0.7rem; }
@media (min-width: 40rem) { .chips { grid-template-columns: 1fr 1fr; } }
.chip {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-2);
  border-left: 4px solid var(--line);
  transition: transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease);
}
.chip:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); }
.chip.sev-critical { border-left-color: var(--sev-critical); }
.chip.sev-caution { border-left-color: var(--sev-caution); }
.chip.sev-clear { border-left-color: var(--sev-clear); }
.chip-icon { display: flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; border-radius: 8px; background: var(--accent-soft); color: var(--accent); flex: none; }
.chip-icon svg { width: 1.1rem; height: 1.1rem; }
.chip-body { min-width: 0; flex: 1; }
.chip-label { display: block; font-weight: 650; font-size: 0.96rem; line-height: 1.3; }
.chip-meta { display: flex; flex-wrap: wrap; gap: 0.4rem 0.75rem; align-items: center; margin-top: 0.3rem; font-size: 0.85rem; color: var(--ink-soft); }
.chip-count { font-variant-numeric: tabular-nums; font-weight: 650; color: var(--ink); }

.tag { display: inline-block; font-size: 0.82rem; font-weight: 650; padding: 0.1rem 0.5rem; border-radius: 99px; border: 1px solid currentColor; white-space: nowrap; }
.tag.automated { color: var(--ok); }
.tag.human { color: var(--bad); }
.tag.mixed { color: var(--ink-soft); }

/* --- cards, notes, folds --- */

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.3rem 1.35rem;
  margin: 1.1rem 0;
  box-shadow: var(--shadow-1);
}
.card > h2 { margin-top: 0; font-size: 1.15rem; }
.card > h3 { font-size: 1rem; }

.note {
  background: var(--warn-bg);
  border: 1px solid var(--warn-line);
  border-radius: 10px;
  padding: 0.8rem 0.95rem;
  font-size: 0.89rem;
  margin: 0.85rem 0;
}
.note strong { display: block; margin-bottom: 0.2rem; }

.figures { display: flex; flex-wrap: wrap; gap: 1.25rem 2.25rem; margin: 0.5rem 0 1rem; padding: 0; list-style: none; }
.figures div { min-width: 7rem; }
.figures dt, .fig-label { font-size: 0.82rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.07em; font-weight: 700; }
.figures dd, .fig-value {
  margin: 0.15rem 0 0;
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
}

.tables-card .statement {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  font-size: 1.04rem;
  margin-top: 0;
}
.tables-card .statement .icon { color: var(--ink-soft); margin-top: 0.2rem; }
.remainder-card > h2 { margin-bottom: 0.3rem; }

details.fold > summary {
  position: relative;
  padding-right: 2rem;
  cursor: pointer;
  list-style: none;
  border-radius: var(--radius-sm);
  transition: color var(--dur-fast) var(--ease);
}
details.fold > summary:hover { color: var(--accent); }
details.fold > summary::-webkit-details-marker { display: none; }
details.fold > summary::after {
  content: "";
  position: absolute;
  right: 0.4rem;
  top: 0.5rem;
  width: 0.55rem;
  height: 0.55rem;
  border-right: 2px solid var(--ink-soft);
  border-bottom: 2px solid var(--ink-soft);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease-spring), top var(--dur) var(--ease-spring);
}
details.fold[open] > summary::after { top: 0.75rem; transform: rotate(-135deg); }
details.fold > summary h2 { display: inline; margin: 0; font-size: 1.15rem; }
.fold-note { display: block; margin-top: 0.2rem; font-size: 0.85rem; font-weight: 400; color: var(--ink-soft); }
details.fold[open] > summary { margin-bottom: 1rem; border-bottom: 1px solid var(--line); padding-bottom: 0.8rem; }
/* Open animates; close is instant. Animating the close would mean taking the
   open/closed state away from the browser, and native <details> is where the
   keyboard and screen-reader behaviour comes from. */
details.fold[open] > .fold-body { animation: fold-in var(--dur) var(--ease-spring); }
.fold-body > *:last-child { margin-bottom: 0; }

.rules { margin: 0.4rem 0 0; padding-left: 1.1rem; color: var(--ink-soft); font-size: 0.85rem; }
.rule-list { margin: 0; padding: 0; list-style: none; }
.rule-list > li { padding: 0.75rem 0; border-bottom: 1px solid var(--line); }
.rule-list > li:last-child { border-bottom: 0; padding-bottom: 0; }
.rule-head { display: flex; flex-wrap: wrap; gap: 0.4rem 0.75rem; align-items: baseline; }
.rule-head strong { font-size: 0.97rem; }
.rule-help { display: block; margin-top: 0.2rem; font-size: 0.85rem; color: var(--ink-soft); }

/* --- what is left, one line per item --- */

.left-head { margin: 1.4rem 0 0.4rem; font-size: 0.95rem; }
.left-list { list-style: none; margin: 0.6rem 0 0; padding: 0; }
.left-item { border-top: 1px solid var(--line); }
.left-item:first-child { border-top: 0; }
.left-line { display: flex; gap: 0.7rem; align-items: flex-start; line-height: 1.45; }
.left-line .icon { color: var(--ink-soft); margin-top: 0.15rem; transition: color var(--dur-fast) var(--ease); }
.left-item > .left-line { padding: 0.8rem 0; }
.left-fold > summary {
  padding: 0.8rem 1.6rem 0.8rem 0;
  cursor: pointer;
  list-style: none;
  position: relative;
}
.left-fold > summary:hover .icon { color: var(--accent); }
.left-fold > summary::-webkit-details-marker { display: none; }
.left-fold > summary::after {
  content: "";
  position: absolute;
  right: 0.35rem;
  top: 1.15rem;
  width: 0.45rem;
  height: 0.45rem;
  border-right: 2px solid var(--ink-soft);
  border-bottom: 2px solid var(--ink-soft);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease-spring), top var(--dur) var(--ease-spring);
}
.left-fold[open] > summary::after { top: 1.3rem; transform: rotate(-135deg); }
.left-detail {
  margin: 0 0 0.9rem;
  padding: 0 0 0 2rem;
  list-style: none;
  color: var(--ink-soft);
  font-size: 0.9rem;
  animation: fold-in var(--dur) var(--ease-spring);
}
.left-detail li { margin-bottom: 0.35rem; }
.left-detail li:last-child { margin-bottom: 0; }

/* --- the sample report --- */

.sample-banner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.25rem;
  align-items: center;
  justify-content: space-between;
  background: var(--accent-soft);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.8rem 1rem;
  margin: 0.75rem 0 0;
  font-size: 0.9rem;
}
.sample-banner p { margin: 0; }
.sample-banner a { font-weight: 650; }

/* --- small print, forms --- */

.stub-note { font-size: 0.85rem; color: var(--ink-soft); }
.lede { max-width: 44rem; }
.hero-text { min-width: 0; }

.emailform { display: grid; gap: 0.7rem; justify-items: start; margin-top: 0.6rem; }
.emailform input[type="email"] {
  font: inherit;
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-2);
  color: var(--ink);
  width: min(24rem, 100%);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur) var(--ease);
}
.emailform input[type="email"]:focus { border-color: var(--accent); box-shadow: var(--ring); }
.emailform button { text-align: left; line-height: 1.35; }
.consent { font-size: 0.85rem; color: var(--ink-soft); max-width: 34rem; margin: 0; }

.scroll-x { overflow-x: auto; }

/* --- loading: a skeleton of the real thing, not a bare spinner --- */

.skeleton {
  border-radius: var(--radius-sm);
  background-color: var(--panel-2);
  background-image: linear-gradient(90deg, var(--panel-2) 0%, var(--line) 42%, var(--panel-2) 84%);
  background-size: 220% 100%;
  animation: shimmer 1.5s linear infinite;
  color: transparent;
}
.sk-line { height: 0.85rem; margin: 0.55rem 0; }
.sk-num { height: 3.4rem; width: 8rem; margin: 0.2rem 0 1rem; }
.sk-w-90 { width: 90%; }
.sk-w-70 { width: 70%; }
.sk-w-50 { width: 50%; }
.sk-bar { height: 0.6rem; border-radius: 99px; margin: 1rem 0 0.6rem; }

.spinner {
  display: inline-block;
  width: 0.85em; height: 0.85em;
  margin-right: 0.45em;
  border: 2px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  vertical-align: -0.1em;
}

/* --- 404 --- */

.oops { padding: 3.5rem 0 2rem; max-width: 40rem; }
.oops h1 { font-size: clamp(2.2rem, 7vw, 3.2rem); margin: 0 0 0.9rem; letter-spacing: -0.04em; }
.oops p { color: var(--ink-soft); font-size: 1.05rem; }
.oops .hero-cta { margin-top: 1.6rem; }

/* --- phone budget ---

   The arc -- red number, sentence, green number, priced button -- has to land
   inside 844px, and every line added above the button eats into that. These
   are the millimetres that buy the guard sentence its place.
   tools/viewport.test.mjs fails the build if this stops adding up. */

@media (max-width: 30rem) {
  .card, .verdict { padding-left: 1.1rem; padding-right: 1.1rem; }
  .card { margin: 0.85rem 0; }
  .verdict { padding-top: 1.15rem; padding-bottom: 1.15rem; }
  .verdict-num { font-size: clamp(3rem, 15vw, 4rem); }
  .verdict-line { margin-top: 0.6rem; font-size: 0.99rem; }
  .success-num { font-size: clamp(2.1rem, 10vw, 2.8rem); }
  .success-count { margin-bottom: 0.45rem; }
  .worklist { margin-bottom: 0.45rem; }
  .success-guard { margin-bottom: 0.55rem; }
  .alarm { margin-top: 0.75rem; }

  /* The work bar and its legend cost the phone's first screen about 80px,
     and round 2's rule is that the verdict, the price and one action all
     land without scrolling. The bar stays; the air around it goes. */
  .workbar { margin: 0.5rem 0 0.4rem; }
  .workbar-wrap { margin-bottom: 0.45rem; }
  .wb-key { font-size: 0.85rem; gap: 0.15rem 0.9rem; line-height: 1.35; }

  /* Sample-only chrome. It is the reason this page is the tight case: a real
     report has no banner above the verdict. */
  .sample-banner { padding: 0.5rem 0.8rem; font-size: 0.9rem; line-height: 1.35; }
  .sample-banner p + p { margin-top: 0.25rem; }
}

/* --- paid state -----------------------------------------------------------

   Replaces the buy row once our SERVER has confirmed a payment. Three shapes:
   working, delivered, and the one nobody else builds -- we took your money and
   could not finish. That last one is styled as loudly as the alarm, because a
   quiet failure after a charge is the worst thing this page could do.

   Severity colour follows the same rule as the rest of the report: it comes
   from a fact (paid / delivered / failed), never from a score. */

.paid {
  margin: 0.6rem 0 0.9rem;
  padding: 1.15rem 1.25rem;
  border: 1px solid var(--sev-clear-line);
  border-left: 4px solid var(--sev-clear);
  border-radius: var(--radius);
  background: var(--sev-clear-bg);
}
.paid h2 { margin: 0 0 0.6rem; font-size: 1.08rem; letter-spacing: -0.015em; }
.paid p { margin: 0.5rem 0 0; }
/* The delivered case is the base .paid look. Stated explicitly rather than
   left implicit: a class with no rule is how a style silently goes missing,
   which is why render.test.mjs fails the build for one. */
.paid-done { border-left-color: var(--sev-clear); }
.paid-working { border-left-color: var(--sev-caution); border-color: var(--sev-caution-line); background: var(--sev-caution-bg); }
.paid-failed,
.paid-refunded { border-left-color: var(--sev-critical); border-color: var(--sev-critical-line); background: var(--sev-critical-bg); }

.dl-list { list-style: none; margin: 0.75rem 0 0; padding: 0; display: grid; gap: 0.6rem; }
.dl {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.8rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  text-decoration: none;
  color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.dl:hover { border-color: var(--accent); transform: translateY(-1px); }
.dl:active { transform: translateY(0); }
.dl-label { font-weight: 650; }
.dl-meta { font-size: 0.85rem; color: var(--ink-soft); }

.checkout-error {
  margin: 0.6rem 0 0;
  padding: 0.7rem 0.9rem;
  border-left: 3px solid var(--sev-critical);
  border-radius: var(--radius-sm);
  background: var(--sev-critical-bg);
  color: var(--ink);
  font-size: 0.93rem;
}

@media (max-width: 30rem) {
  .paid { padding: 1rem 1.1rem; }
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
