@charset "utf-8";

/* Aftermath Web Design
   One stylesheet: tokens, reset, primitives, parts.
   Every colour comes from a token. No hex values below :root. */

/* -- Fonts ---------------------------------------------------------------- */

@font-face {
  font-family: Archivo;
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(../fonts/archivo-var-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Source Serif 4";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(../fonts/source-serif-4-var-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Source Serif 4";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url(../fonts/source-serif-4-var-italic-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/ibm-plex-mono-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Metric-matched fallbacks, so the swap does not reflow the page. Took a
   text-heavy page from 0.041 CLS to nothing. size-adjust is webfont advance
   width over fallback advance width, measured in the browser; ascent and
   descent are the webfont's own ratios divided by that size-adjust, because
   the override applies to the already-adjusted em. Re-measure on a font
   change. */

@font-face {
  font-family: "Archivo Fallback";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 107.2%;
  ascent-override: 82.09%;
  descent-override: 19.59%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Source Serif Fallback";
  src: local("Times New Roman"), local("Times"), local("Liberation Serif");
  size-adjust: 114.72%;
  ascent-override: 90.66%;
  descent-override: 29.64%;
  line-gap-override: 0%;
}

/* -- Tokens --------------------------------------------------------------- */

:root {
  /* Palette */
  --carbon: #0f1215;
  --concrete: #e7e8e3;
  --plaster: #f6f6f3;
  --slate: #626c76;
  --ultramarine: #1b3ad6;
  --flare: #ff5a1f;

  /* Text-safe derivatives. --slate reads 4.34:1 on concrete and --ultramarine
     reads 2.35:1 on carbon, so neither can carry body text where it is used.
     The brand values stay put; text picks up these instead. */
  --slate-ink: #545e67;
  --ultramarine-lift: #7e97f5;

  /* Audit score states. Semantic, never decorative. The plan's #1E7A4A read
     4.33:1 on concrete, so pass is darkened to clear 4.5:1. Neither holds on
     carbon, so a score never appears inside an inverted band. */
  --pass: #17663d;
  --fail: #b3261e;

  /* Surface roles. An inverted band repoints these six and nothing else. */
  --field: var(--concrete);
  --surface: var(--plaster);
  --ink: var(--carbon);
  --ink-quiet: var(--slate-ink);
  --link: var(--ultramarine);
  --hairline: color-mix(in srgb, var(--slate) 25%, transparent);

  /* Type */
  --font-display: Archivo, "Archivo Fallback", "Helvetica Neue", Arial, sans-serif;
  --font-body: "Source Serif 4", "Source Serif Fallback", Georgia, "Times New Roman", serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --t-12: 0.75rem;
  --t-14: 0.875rem;
  --t-18: 1.125rem;
  --t-22: 1.375rem;
  --t-28: 1.75rem;
  --t-40: clamp(1.625rem, 1.283rem + 1.522vw, 2.5rem);
  --t-64: clamp(2rem, 1.217rem + 3.478vw, 4rem);
  --t-88: clamp(2.5rem, 1.326rem + 5.217vw, 5.5rem);

  --leading-tight: 1.05;
  --leading-snug: 1.2;
  --leading-body: 1.6;
  --tracking-display: -0.02em;
  --tracking-mono: 0.12em;
  --measure: 66ch;

  /* Layout */
  --maxw: 1280px;
  --pad: clamp(1.25rem, 4vw, 3rem);
  --gutter: clamp(1.5rem, 5.6vw, 4.5rem);
  --rail: 140px;

  /* Space. Vertical rhythm lives on sections; everything inside uses .flow. */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-s: 1rem;
  --space-m: 1.5rem;
  --space-l: 2.5rem;
  --space-xl: 4rem;
  --space-2xl: 6rem;
  --space-section: clamp(3.5rem, 2rem + 6vw, 7rem);

  /* Motion */
  --ease: cubic-bezier(0.2, 0, 0, 1);
  --dur-fast: 120ms;
  --dur-draw: 400ms;
}

.band--invert {
  --field: var(--carbon);
  --surface: color-mix(in srgb, var(--concrete) 8%, var(--carbon));
  --ink: var(--concrete);
  --ink-quiet: color-mix(in srgb, var(--concrete) 72%, var(--carbon));
  --link: var(--ultramarine-lift);
  --hairline: color-mix(in srgb, var(--concrete) 22%, transparent);
}

/* -- Reset ---------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

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

body {
  background: var(--field);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-18);
  line-height: var(--leading-body);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

img,
svg,
picture,
video {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  cursor: pointer;
}

ul,
ol {
  list-style: none;
  padding: 0;
}

fieldset {
  border: 0;
  padding: 0;
  min-width: 0;
}

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

/* Author rules beat the UA sheet, so any component that sets display would
   otherwise ignore the hidden attribute. Several of them do. */
[hidden] {
  display: none !important;
}

:target {
  scroll-margin-block-start: var(--space-xl);
}

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

::selection {
  background: var(--ultramarine);
  color: var(--plaster);
}

/* -- Type ----------------------------------------------------------------- */

/* Every display-set component shares one block. Only the size, and any
   line-height that genuinely differs, stays on the component. */
.section__title,
.card__title,
.problem__title,
.process__title,
.steps__title,
.drivers__title,
.srow__title,
.faq__q,
.wordmark__name,
.proof__stat,
.dial__score,
.fixes__title {
  font-family: var(--font-display);
  font-weight: 620;
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-display);
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 620;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
}

h1 {
  font-size: var(--t-88);
}
h2 {
  font-size: var(--t-64);
}
h3 {
  font-size: var(--t-40);
  line-height: var(--leading-snug);
}
h4 {
  font-size: var(--t-22);
  line-height: var(--leading-snug);
}

p,
li {
  max-width: var(--measure);
  text-wrap: pretty;
}

strong,
b {
  font-weight: 650;
}

a {
  color: var(--link);
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 0 100%;
  background-repeat: no-repeat;
  background-size: 0 1px;
  transition: background-size var(--dur-fast) var(--ease);
}

a:hover,
a:focus-visible {
  background-size: 100% 1px;
}

.mono,
.eyebrow,
.rule__label,
.field__label,
.btn,
.nav__link,
.meta,
.nav__toggle,
.wordmark__tag,
.link-mono,
.form__legend,
.form__status,
.field__error,
.metric__label,
.metric__value,
.footer__heading,
.dial__verdict,
.fixes__index,
.fixes__saving,
.progress__step,
.report__compare,
.audit__error-title,
.switch__btn,
.report__url {
  font-family: var(--font-mono);
  font-size: var(--t-12);
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: var(--tracking-mono);
  font-variant-numeric: tabular-nums;
}

.eyebrow {
  display: block;
  color: var(--ink-quiet);
}

.lede {
  font-size: var(--t-22);
  line-height: 1.5;
  color: var(--ink);
}

.skip-link {
  position: absolute;
  inset-inline-start: var(--space-s);
  inset-block-start: var(--space-s);
  z-index: 10;
  padding: var(--space-xs) var(--space-s);
  background: var(--ultramarine);
  color: var(--plaster);
  translate: 0 -200%;
}

.skip-link:focus {
  translate: 0;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* -- Layout --------------------------------------------------------------- */

/* Secondary text. One value, one place, rather than the same declaration
   repeated on every component that has a supporting line. */
.problem__body,
.card__body,
.srow__summary,
.dial__note,
.steps__body,
.drivers__body,
.fixes__saving,
.progress__note,
.vignette__line,
.metric__note,
.metric__label,
.field__hint,
.rail__callout,
.srow__index,
.footer__bottom,
.srow__included,
.quiet {
  color: var(--ink-quiet);
}

/* Components that stack their children in a column. Only the gap differs,
   so it stays on the component and the two structural lines live here. */
.card,
.field,
.intake,
.hero__copy,
.hero__intake,
.vignette,
.process__step,
.steps,
.srows,
.srow__body,
.faq,
.audit__status,
.progress,
.audit__error,
.report,
.report__cta,
.fixes,
.fixes__item,
.footer__list {
  display: flex;
  flex-direction: column;
}

/* Blocks introduced by a hairline above them, which is how every list of
   peers on the site is separated. */
.vignette,
.process__step,
.drivers__item,
.fixes__item {
  padding-block-start: var(--space-s);
  border-block-start: 1px solid var(--hairline);
  max-width: none;
}

.wrap {
  width: min(100% - (2 * var(--pad)), var(--maxw));
  margin-inline: auto;
}

.section {
  padding-block: var(--space-section);
  background: var(--field);
  color: var(--ink);
}

.section--tight {
  padding-block: var(--space-xl);
}

main {
  flex: 1;
}

.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--gutter);
}

.flow > * + * {
  margin-block-start: var(--flow, var(--space-m));
}

.flow--tight {
  --flow: var(--space-xs);
}

.flow--loose {
  --flow: var(--space-l);
}

/* The left rail: mono callout plus a vertical hairline down the block edge. */
.rail {
  position: relative;
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  gap: var(--gutter);
}

.rail::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--rail);
  width: 1px;
  background: var(--hairline);
}

.rail__callout {
  padding-inline-end: var(--space-m);
}

@media (max-width: 900px) {
  .rail {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-m);
  }

  .rail::before {
    display: none;
  }

  .rail__callout {
    padding-inline-end: 0;
  }
}

/* -- Dimension rule ------------------------------------------------------- */

.rule {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 1.25rem;
}

.rule__line {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 50%;
  height: 1px;
  background: var(--slate);
  transform-origin: left center;
}

.band--invert .rule__line {
  background: var(--hairline);
}

.rule__line::before,
.rule__line::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  translate: 0 -50%;
  width: 1px;
  height: 8px;
  background: var(--flare);
}

.rule__line::before {
  inset-inline-start: 0;
}

.rule__line::after {
  inset-inline-end: 0;
}

.rule__label {
  position: relative;
  margin-inline-start: var(--space-m);
  padding-inline-end: var(--space-s);
  background: var(--field);
  color: var(--ink-quiet);
}

.rule__index {
  color: var(--ink);
}

/* Once the label would wrap, it stops sitting on the line and sits above it.
   A wrapped label stretches to the full width and its field-coloured ground
   paints straight over the hairline it is supposed to be resting on. */
@media (max-width: 700px) {
  .rule {
    display: block;
    min-height: 0;
  }

  .rule__label {
    display: block;
    margin-inline-start: 0;
    margin-block-start: var(--space-2xs);
    padding-inline-end: 0;
    background: none;
  }

  .rule__line {
    position: relative;
    inset-block-start: auto;
    display: block;
  }
}

/* -- Header --------------------------------------------------------------- */

.header {
  position: relative;
  z-index: 5;
  background: var(--field);
  border-block-end: 1px solid var(--hairline);
  view-transition-name: site-header;
}

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
  min-height: 72px;
}

.wordmark {
  display: flex;
  align-items: baseline;
  gap: var(--space-2xs);
  color: var(--ink);
  background: none;
}

.wordmark__name {
  font-size: var(--t-22);
}

.wordmark__tag {
  color: var(--ink-quiet);
}

.nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-m);
}

.nav__link {
  color: var(--ink);
  padding-block: var(--space-2xs);
}

.nav__link[aria-current="page"] {
  color: var(--ultramarine);
  background-size: 100% 1px;
}

.nav__toggle {
  display: none;
  color: var(--ink);
  padding: var(--space-2xs);
}

@media (max-width: 900px) {
  .js .nav__toggle {
    display: block;
  }

  .js .nav__list {
    display: none;
    position: absolute;
    inset-inline: 0;
    inset-block-start: 100%;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: var(--space-s) var(--pad) var(--space-l);
    background: var(--field);
    border-block-end: 1px solid var(--hairline);
  }

  .js .nav[data-open="true"] .nav__list {
    display: flex;
  }

  .js .nav__link {
    padding-block: var(--space-xs);
  }

  .nav__list {
    flex-wrap: wrap;
    gap: var(--space-s) var(--space-m);
  }
}

/* -- Buttons -------------------------------------------------------------- */

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  padding: var(--space-s) var(--space-m);
  background: var(--ultramarine);
  color: var(--plaster);
  border: 1px solid var(--ultramarine);
  transition: translate var(--dur-fast) var(--ease);
}

.btn::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: -1px;
  height: 2px;
  background: var(--flare);
  scale: 0 1;
  transform-origin: left center;
  transition: scale var(--dur-fast) var(--ease);
}

.btn:hover,
.btn:focus-visible {
  translate: 0 -1px;
}

.btn:hover::after,
.btn:focus-visible::after {
  scale: 1 1;
}

.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
}

.band--invert .btn--ghost {
  border-color: var(--hairline);
}

.btn--ghost:hover {
  border-color: var(--link);
  color: var(--link);
}

/* A row of calls to action: one primary, then quieter options beside it. */
.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-s) var(--space-m);
  max-width: none;
}

/* A text link that carries the mono treatment, used for secondary actions. */
.link-mono {
}

/* -- Cards ---------------------------------------------------------------- */

.card {
  gap: var(--space-xs);
  padding: var(--space-m);
  background: var(--surface);
  border: 1px solid var(--hairline);
}

.card__title {
  font-size: var(--t-22);
}

.card__body {
  font-size: var(--t-18);
  flex: 1;
}

.card__index {
  color: var(--ink-quiet);
}

/* -- Forms ---------------------------------------------------------------- */

.field {
  gap: var(--space-2xs);
}

.field__label {
  color: var(--ink-quiet);
}

.field__req {
  color: var(--flare);
}

.field__input,
.field__textarea,
.field__select {
  width: 100%;
  padding: var(--space-xs) var(--space-s);
  background: var(--surface);
  color: var(--ink);
  border: 1px solid color-mix(in srgb, var(--slate) 55%, transparent);
  border-radius: 0;
  font-size: var(--t-18);
  font-family: var(--font-body);
}

.field__textarea {
  min-height: 8rem;
  resize: vertical;
}

.field__select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 1.1rem center, right 0.85rem center;
  background-size: 5px 5px;
  background-repeat: no-repeat;
  padding-inline-end: var(--space-l);
}

.field__input:focus-visible,
.field__textarea:focus-visible,
.field__select:focus-visible {
  outline: 2px solid var(--ultramarine);
  outline-offset: 2px;
  border-color: var(--ultramarine);
}

.field__hint {
  font-size: var(--t-14);
  line-height: 1.4;
}

.field__error {
  color: var(--ultramarine);
}

.field__input[aria-invalid="true"],
.field__textarea[aria-invalid="true"],
.field__select[aria-invalid="true"] {
  border-color: var(--ultramarine);
  border-width: 2px;
}

/* Honeypot. Off-screen rather than display:none, which bots skip. */
.field--trap {
  position: absolute;
  inset-inline-start: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__legend {
  color: var(--ink-quiet);
}

.form__status {
  color: var(--ink);
}

/* The single-input intake field: mono label, one input, one button. */
.intake {
  gap: var(--space-2xs);
  max-width: 34rem;
}

.intake__row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
}

.intake__input {
  flex: 1 1 14rem;
  min-width: 0;
  padding: var(--space-s);
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 0;
  font-size: var(--t-18);
}

.intake__input:focus-visible {
  outline: 2px solid var(--ultramarine);
  outline-offset: 2px;
}

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

.section__title {
  font-size: var(--t-40);
  max-width: 20ch;
}

.hero {
  padding-block: var(--space-xl) var(--space-section);
}

.hero__layout {
  display: grid;
  gap: var(--gutter);
  align-items: center;
}

.hero__copy {
  gap: var(--space-m);
}

.hero__title {
  max-width: 14ch;
}

.hero__lede {
  max-width: 46ch;
}

.hero__intake {
  gap: var(--space-s);
}

.intake__label {
  font-size: var(--t-14);
  color: var(--ink);
}

.hero__plate,
.intro__portrait {
  display: block;
}

.hero__plate img,
.intro__portrait img {
  width: 100%;
  height: auto;
  border: 1px solid var(--hairline);
}

@media (min-width: 60rem) {
  .hero__layout {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  }
}

.intro {
  display: grid;
  gap: var(--space-l);
  align-items: start;
}

@media (min-width: 60rem) {
  .intro {
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    gap: var(--gutter);
  }
}

.problems {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-l) var(--gutter);
}

.problem__title {
  font-size: var(--t-22);
  margin-block-end: var(--space-2xs);
}

.services-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--gutter);
}

.proof__stat {
  font-size: var(--t-88);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.vignettes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--space-l) var(--gutter);
}

.vignette {
  gap: var(--space-2xs);
}

.vignette__sector {
  color: var(--ink);
}

.vignette__line {
  font-size: var(--t-14);
  line-height: 1.5;
}

.vignette__line .mono {
  display: block;
}

/* Four steps, so the track has to hold four across or fall to two. Three plus
   an orphan reads as a broken grid rather than a sequence. */
.process {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: var(--space-l) var(--gutter);
}

.process__step {
  gap: var(--space-2xs);
}

.process__index {
  color: var(--link);
}

/* A sequence of three to five steps reads as stacked rows. A grid would leave
   an orphan on every count that is not a multiple of the column tracks. */
.steps {
  border-block-end: 1px solid var(--hairline);
}

.steps__item {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr);
  gap: var(--space-m);
  padding-block: var(--space-m);
  border-block-start: 1px solid var(--hairline);
  max-width: none;
}

.steps__index {
  color: var(--link);
}

.steps__title {
  font-size: var(--t-22);
  margin-block-end: var(--space-2xs);
}

@media (max-width: 700px) {
  .steps__item {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-2xs);
  }
}

.process__title {
  font-size: var(--t-22);
}

.process__body {
  color: var(--ink-quiet);
  font-size: var(--t-14);
  line-height: 1.5;
}

/* Services overview: one full-width row per service on the rail grid. */

.srow {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  gap: var(--gutter);
  padding-block: var(--space-l);
  border-block-start: 1px solid var(--hairline);
  max-width: none;
}

.srow:last-child {
  border-block-end: 1px solid var(--hairline);
}

.srow__body {
  gap: var(--space-s);
}

.srow__title {
  font-size: var(--t-28);
}

@media (max-width: 900px) {
  .srow {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-s);
  }
}

/* Lists that read as an itemised scope rather than prose. */
.ticked {
  display: grid;
  gap: var(--space-xs);
}

.ticked--two {
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--space-xs) var(--gutter);
}

.ticked li {
  position: relative;
  padding-inline-start: var(--space-m);
}

.ticked li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.75em;
  width: 10px;
  height: 1px;
  background: var(--ink-quiet);
}

/* Four items, so two columns fill evenly. auto-fit would give three and leave
   an orphan on the second row. */
.srow__included {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3xs) var(--gutter);
  font-size: var(--t-14);
}

@media (max-width: 700px) {
  .srow__included {
    grid-template-columns: minmax(0, 1fr);
  }
}

.srow__included li {
  position: relative;
  padding-inline-start: var(--space-s);
}

.srow__included li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.7em;
  width: 6px;
  height: 1px;
  background: var(--ink-quiet);
}

/* What moves the effort: a definition list, not a price table. */
.drivers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(21rem, 1fr));
  gap: var(--space-l) var(--gutter);
}

.drivers__title {
  font-size: var(--t-22);
  margin-block-end: var(--space-2xs);
}

.drivers__body {
  margin: 0;
  font-size: var(--t-14);
  line-height: 1.5;
  max-width: var(--measure);
}

/* FAQ. Native disclosure, so it works with no script at all. */
.faq {
  border-block-start: 1px solid var(--hairline);
}

.faq__item {
  border-block-end: 1px solid var(--hairline);
}

.faq__q {
  display: flex;
  justify-content: space-between;
  gap: var(--space-m);
  padding-block: var(--space-s);
  font-size: var(--t-22);
  cursor: pointer;
  list-style: none;
}

.faq__q::-webkit-details-marker {
  display: none;
}

.faq__q::after {
  content: "+";
  font-family: var(--font-mono);
  font-size: var(--t-18);
  color: var(--link);
  flex: none;
}

.faq__item[open] .faq__q::after {
  content: "\2212";
}

.faq__a {
  padding-block-end: var(--space-m);
  color: var(--ink-quiet);
}

/* -- Audit ---------------------------------------------------------------- */

/* The runner needs script, so it only exists once the js class is set. Without
   it the page still explains what the tool measures and where to go instead. */
.audit__runner {
  display: none;
  flex-direction: column;
  gap: var(--space-m);
}

.js .audit__runner {
  display: flex;
}

.js .audit__nojs {
  display: none;
}

.audit__status {
  gap: var(--space-s);
}

.progress {
  gap: var(--space-2xs);
  max-width: none;
}

.progress__step {
  position: relative;
  padding-inline-start: var(--space-l);
  color: var(--ink-quiet);
  max-width: none;
}

.progress__step::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.7em;
  width: 20px;
  height: 1px;
  background: var(--ink-quiet);
}

.progress__step[data-state="running"] {
  color: var(--ink);
}

.progress__step[data-state="running"]::before {
  background: var(--flare);
}

.progress__step[data-state="done"]::after {
  content: "done";
  margin-inline-start: var(--space-2xs);
  color: var(--link);
}

.progress__note {
  font-size: var(--t-14);
}

.audit__error {
  gap: var(--space-2xs);
  padding: var(--space-m);
  background: var(--surface);
  border-inline-start: 2px solid var(--flare);
}

.audit__error-title {
  color: var(--ink);
}

.audit__turnstile,
.cf-turnstile {
  margin-block: var(--space-s);
}

.report {
  gap: var(--space-l);
}

.report:focus-visible {
  outline: none;
}

.report__head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-s);
  padding-block-end: var(--space-s);
  border-block-end: 1px solid var(--hairline);
}

.report__url {
  overflow-wrap: anywhere;
}

.switch {
  display: flex;
  border: 1px solid var(--hairline);
}

.switch__btn {
  padding: var(--space-2xs) var(--space-s);
  color: var(--ink-quiet);
}

.switch__btn[aria-pressed="true"] {
  background: var(--ultramarine);
  color: var(--plaster);
}

/* The number and the word carry the verdict. Colour only agrees with them. */
.dial {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-s) var(--gutter);
}

.dial__score {
  font-size: var(--t-88);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.dial__read {
  flex: 1 1 18rem;
}

[data-state="pass"] .dial__score,
[data-state="pass"] .dial__verdict {
  color: var(--pass);
}

[data-state="fail"] .dial__score,
[data-state="fail"] .dial__verdict {
  color: var(--fail);
}

[data-state="mid"] .dial__score,
[data-state="mid"] .dial__verdict {
  color: var(--ink-quiet);
}

.report__compare {
  color: var(--ink);
}

.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(24rem, 1fr));
  gap: var(--space-m) var(--gutter);
}

.metric__note {
  grid-column: 1 / -1;
  font-size: var(--t-14);
  line-height: 1.4;
}

.metric[data-state="none"] {
  opacity: 0.55;
}

.fixes,
.report__cta {
  gap: var(--space-s);
}

.fixes__list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-m) var(--gutter);
}

.fixes__item {
  gap: var(--space-3xs);
}

.fixes__title {
  font-size: var(--t-22);
}

/* Before and after pairs, two per row on anything wider than a phone. */
.wbars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-s) var(--gutter);
  margin-block-start: var(--space-2xs);
}

.fixes__index {
  color: var(--link);
}

/* -- Metric bar ----------------------------------------------------------- */

.metric {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-3xs) var(--space-s);
  align-items: baseline;
}

.metric__label,
.metric__value {
  font-variant-numeric: tabular-nums;
}

.metric__track {
  grid-column: 1 / -1;
}

.metric__rail {
  fill: none;
  stroke: var(--hairline);
  stroke-width: 1;
}

.metric__fill {
  fill: none;
  stroke: var(--ink);
  stroke-width: 3;
}

.metric__fill--after {
  stroke: var(--ultramarine);
}

.metric__tick {
  stroke: var(--flare);
  stroke-width: 1;
}

/* -- Motion --------------------------------------------------------------- */

/* Undrawn start states only exist when JS is present to draw them back. */
.js .rule__line {
  scale: 0 1;
}

.js .rule.is-drawn .rule__line {
  scale: 1 1;
  transition: scale var(--dur-draw) var(--ease);
}

.js .rule__line::before,
.js .rule__line::after {
  opacity: 0;
}

.js .rule.is-drawn .rule__line::before,
.js .rule.is-drawn .rule__line::after {
  opacity: 1;
  transition: opacity var(--dur-fast) var(--ease) var(--dur-draw);
}

.hero__line {
  display: block;
  overflow: hidden;
}

.hero__line > span {
  display: block;
}

.js .hero__line > span {
  translate: 0 110%;
}

.js .hero.is-loaded .hero__line > span {
  translate: 0;
  transition: translate 500ms var(--ease);
  transition-delay: calc(var(--dur-draw) + (var(--i, 0) * 60ms));
}

.js .hero__intake {
  opacity: 0;
}

.js .hero.is-loaded .hero__intake {
  opacity: 1;
  transition: opacity 300ms var(--ease);
  transition-delay: calc(var(--dur-draw) + 240ms);
}

/* Cross-document transitions. Header and page title are named so they persist
   instead of blinking. Under 200ms: slower makes a fast site feel slower. */
@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 180ms;
}

h1 {
  view-transition-name: page-title;
}

@media (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: none;
  }

  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
  }

  /* Jump to the end state rather than animating toward it. */
  .js .rule__line,
  .js .hero__line > span {
    scale: 1 1;
    translate: 0;
  }

  .js .rule__line::before,
  .js .rule__line::after,
  .js .hero__intake {
    opacity: 1;
  }

  .btn:hover,
  .btn:focus-visible {
    translate: 0;
  }
}

/* -- Footer --------------------------------------------------------------- */

.footer {
  padding-block: var(--space-xl) var(--space-l);
  background: var(--field);
  color: var(--ink);
}

.footer__top {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: var(--space-l) var(--gutter);
}

.footer__heading {
  color: var(--ink-quiet);
  margin-block-end: var(--space-s);
}

.footer__list {
  gap: var(--space-2xs);
}

.footer__list a {
  color: var(--ink);
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-s) var(--space-m);
  margin-block-start: var(--space-xl);
  padding-block-start: var(--space-s);
  border-block-start: 1px solid var(--hairline);
}

.receipt {
  font-variant-numeric: tabular-nums;
}
