/* Plain CSS, no build step. Light and dark via prefers-color-scheme. */

:root {
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #f0f2f5;
  --border: #dfe3e8;
  --border-strong: #c4cad2;
  --text: #16191d;
  --text-dim: #5c636e;
  --text-faint: #878e99;

  --good: #0b8a4b;
  --good-bg: #e6f4ec;
  --average: #a9690a;
  --average-bg: #fbf1e0;
  --poor: #c02b1d;
  --poor-bg: #fbeae8;
  --fail: #6b7280;
  --fail-bg: #eceef1;

  --accent: #2b5cd9;

  --cat-performance: #2b5cd9;
  --cat-accessibility: #0b8a4b;
  --cat-seo: #8b5cf6;
  --cat-best_practices: #d97706;

  --radius: 10px;
  --shadow: 0 1px 2px rgb(16 24 40 / 6%), 0 1px 3px rgb(16 24 40 / 4%);
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14161a;
    --surface: #1c1f24;
    --surface-2: #23272e;
    --border: #2e333b;
    --border-strong: #414751;
    --text: #e8eaed;
    --text-dim: #a8b0bb;
    --text-faint: #7c848f;

    --good: #4ade80;
    --good-bg: #12301f;
    --average: #fbbf24;
    --average-bg: #33260c;
    --poor: #f87171;
    --poor-bg: #351816;
    --fail: #9ca3af;
    --fail-bg: #262a30;

    --accent: #7ba2ff;

    --cat-performance: #7ba2ff;
    --cat-accessibility: #4ade80;
    --cat-seo: #c4a6ff;
    --cat-best_practices: #fbbf24;

    --shadow: 0 1px 2px rgb(0 0 0 / 40%);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.wrap {
  max-width: 1080px;
  margin: 0 auto;
  padding: 20px 16px 56px;
}

a { color: var(--accent); }

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

.masthead {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 14px;
}

h1 {
  margin: 0;
  font-size: 19px;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.masthead .meta {
  font-size: 12.5px;
  color: var(--text-faint);
}

/* ---------- heartbeat ---------- */

.heartbeat {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  align-items: center;
  padding: 10px 14px;
  margin-bottom: 18px;
  border: 1px solid var(--border);
  border-left: 4px solid var(--good);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 13.5px;
  box-shadow: var(--shadow);
}

.heartbeat .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--good);
  flex: none;
}

.heartbeat strong { font-weight: 650; }
.heartbeat .sub { color: var(--text-dim); }

.heartbeat.is-stale {
  border-left-color: var(--poor);
  border-color: var(--poor);
  background: var(--poor-bg);
  color: var(--poor);
  font-weight: 600;
  font-size: 14.5px;
}
.heartbeat.is-stale .dot { background: var(--poor); animation: pulse 1.6s ease-in-out infinite; }
.heartbeat.is-stale .sub { color: var(--poor); }

@keyframes pulse { 50% { opacity: 0.25; } }

@media (prefers-reduced-motion: reduce) {
  .heartbeat.is-stale .dot { animation: none; }
}

/* ---------- toolbar ---------- */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.segmented {
  display: inline-flex;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-2);
}

.segmented button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: 13px;
  font-weight: 550;
  padding: 5px 13px;
  border-radius: 6px;
  cursor: pointer;
}

.segmented button[aria-pressed="true"] {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
}

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

/* ---------- cards ---------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 16px;
  overflow: hidden;
}

.card > h2 {
  margin: 0;
  padding: 12px 16px;
  font-size: 13px;
  font-weight: 650;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
}

.card-body { padding: 16px; }

/* De-emphasised qualifier inside a card heading, e.g. "median of 3 runs". */
.card > h2 .qualifier {
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-faint);
}

/* ---------- overview client cards ---------- */

.cards {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* The whole card is the click target, so it's a button — but it must not look
   or lay out like one. */
.client-card {
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.client-card:hover {
  border-color: var(--border-strong);
  box-shadow: 0 2px 8px rgb(16 24 40 / 8%);
}

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

.client-card.is-inactive { opacity: 0.6; }

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

/* --- card header: identity + current scores --- */

.cc-head {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 20px;
  align-items: flex-start;
  justify-content: space-between;
  padding: 14px 16px 12px;
}

.cc-id { min-width: 0; flex: 1 1 220px; }

.cc-name {
  display: block;
  font-size: 17px;
  font-weight: 650;
  letter-spacing: -0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cc-url {
  display: block;
  margin-top: 1px;
  font-size: 12.5px;
  color: var(--text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cc-extra { font-size: 12px; color: var(--text-faint); font-weight: 500; }

.cc-scores {
  display: flex;
  gap: 14px;
  flex: none;
}

.cc-score {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 44px;
}

.cc-score-label {
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 3px;
}

/* --- card body: chart + aside --- */

.cc-body {
  display: grid;
  grid-template-columns: minmax(0, 1.9fr) minmax(210px, 1fr);
  border-top: 1px solid var(--border);
}

/* The aside is often taller than the chart, and the grid stretches both to
   match. Centre the chart in its cell so any leftover room is split above and
   below instead of pooling underneath. */
.cc-chart {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  padding: 10px 4px 6px 8px;
}

.cc-chart .legend { padding: 0 10px 6px; }

.cc-aside {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 16px 14px;
  border-left: 1px solid var(--border);
  background: var(--surface-2);
  min-width: 0;
}

.cc-aside-label {
  display: block;
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 4px;
}

.cc-excerpt {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-dim);
  /* Let the reader select the text even though the card is a button. */
  user-select: text;
  /* Cap the height so the aside can't stretch the row taller than the chart —
     otherwise the grid leaves dead space under the graph. The JS already trims
     the text; this is the belt-and-braces visual cap. */
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.cc-aside-empty {
  margin: 0;
  font-size: 12.5px;
  color: var(--text-faint);
  font-style: italic;
}

.cc-top { margin-top: auto; }

.cc-top-title {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
}

.cc-top-savings {
  display: inline-block;
  margin-top: 2px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 650;
  color: var(--average);
  font-variant-numeric: tabular-nums;
}

/* ---------- score cells ---------- */

.cell { text-align: center; }

.score {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  padding: 3px 8px;
  border-radius: 6px;
  font-family: var(--mono);
  font-size: 14.5px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}

.score.good { color: var(--good); background: var(--good-bg); }
.score.average { color: var(--average); background: var(--average-bg); }
.score.poor { color: var(--poor); background: var(--poor-bg); }

/* A missing/failed audit must not look like a low score. */
.score.failed,
.score.missing {
  color: var(--fail);
  background: var(--fail-bg);
  font-weight: 600;
  border: 1px dashed var(--border-strong);
}

.delta {
  display: block;
  margin-top: 3px;
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
}

.delta.up { color: var(--good); }
.delta.down { color: var(--poor); }

.spark { text-align: right; line-height: 0; }

/* ---------- detail ---------- */

.back {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-bottom: 12px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 13.5px;
  cursor: pointer;
}
.back:hover { text-decoration: underline; }

.detail-head {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 20px;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 14px;
}

.dh-id { min-width: 0; flex: 1 1 240px; }

.detail-head h2 {
  margin: 0 0 2px;
  font-size: 21px;
  font-weight: 650;
  letter-spacing: -0.015em;
}
.detail-url {
  font-size: 12.5px;
  color: var(--text-faint);
  word-break: break-all;
}

.detail-head .notes {
  margin: 6px 0 0;
  font-size: 13.5px;
  color: var(--text-dim);
}

.url-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}

.url-tabs button {
  padding: 5px 11px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-dim);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}

.url-tabs button[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  padding: 0 16px 14px;
  font-size: 12.5px;
  color: var(--text-dim);
}

.legend span { display: inline-flex; align-items: center; gap: 6px; }
.legend i {
  width: 11px;
  height: 3px;
  border-radius: 2px;
  background: currentColor;
}

.chart-holder { padding: 4px 8px 12px; }
.chart-holder svg { display: block; width: 100%; height: auto; }

/* ---------- vitals ---------- */

.vitals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 1px;
  background: var(--border);
}

.vital {
  padding: 12px 14px;
  background: var(--surface);
}

.vital .label {
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.vital .value {
  margin-top: 3px;
  font-family: var(--mono);
  font-size: 19px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}

.vital .value.good { color: var(--good); }
.vital .value.average { color: var(--average); }
.vital .value.poor { color: var(--poor); }
.vital .value.missing { color: var(--text-faint); }

.vital .band { font-size: 11.5px; color: var(--text-dim); margin-top: 1px; }

/* ---------- opportunities ---------- */

.opps { list-style: none; margin: 0; padding: 0; }

.opp {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  align-items: baseline;
  justify-content: space-between;
  padding: 11px 16px;
  border-top: 1px solid var(--border);
}
.opp:first-child { border-top: 0; }

.opp-title { font-size: 14px; }
.opp-id { display: block; font-size: 11.5px; color: var(--text-faint); font-family: var(--mono); }

.opp-savings {
  flex: none;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 650;
  color: var(--average);
  font-variant-numeric: tabular-nums;
}

.summary-text { margin: 0; white-space: pre-wrap; font-size: 14px; line-height: 1.62; }

.empty { padding: 16px; color: var(--text-faint); font-size: 13.5px; }

.failures { list-style: none; margin: 0; padding: 0; }
.failures li {
  padding: 10px 16px;
  border-top: 1px solid var(--border);
  font-size: 13px;
}
.failures li:first-child { border-top: 0; }
.failures time { font-family: var(--mono); color: var(--text-dim); margin-right: 8px; }
.failures .msg { color: var(--poor); }

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

.footnote {
  margin-top: 24px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-faint);
}

.footnote code { font-family: var(--mono); font-size: 11.5px; }

/* ---------- responsive ---------- */

/* Stack the chart and aside once there isn't room for two columns. */
@media (max-width: 860px) {
  .cc-body { grid-template-columns: 1fr; }

  .cc-aside {
    border-left: 0;
    border-top: 1px solid var(--border);
  }
}

@media (max-width: 560px) {
  .cc-head { gap: 10px; }

  /* Spread the four scores across the full width rather than crowding right. */
  .cc-scores {
    flex: 1 1 100%;
    justify-content: space-between;
    gap: 6px;
  }

  .cc-score { min-width: 0; flex: 1; }
  .cc-name { font-size: 16px; }
}
