/* Open Sans is the CUSP portal's face. Bundled here (from the protos repo's
   marketing assets) so the app stays offline and never loads a CDN. */
@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("fonts/open-sans-latin.woff2") format("woff2");
}

/* Sharestack Report Studio -- on-screen styles.
 *
 * Self-contained on purpose: no @import, no CDN, no webfont, no framework. The
 * machine that builds a client report has no internet, and a stylesheet that
 * silently fails to load turns a client report into unformatted text.
 *
 * Two things live in this file:
 *   1. the app shell (top bar, uploads, coverage, editor) -- screen only;
 *   2. the report document itself, in the SAME visual language as print.css.
 * The document is written out twice rather than shared because print.css has to
 * work when it is the only stylesheet on the page (the standalone HTML export
 * and headless Edge both load it that way). Document type sizes are multiples
 * of --fs-*, so the preview and the PDF differ by exactly one number:
 * .document{font-size}. That is what makes the preview worth trusting.
 *
 * Every selector here matches markup that the templates under app/render and
 * studio.js actually emit. The colours and type sizes were measured out of the
 * ten reference PDFs in reference/sample-reports-pdf, not invented.
 */

:root {
  /* Brand. --brand is the house blue; --brand-deep is the darker ink the
     reference reports use for the cover title and section headings. */
  --brand:        #267864;   /* CUSP primary (rgb 38 120 100) */
  --brand-deep:   #1e5f50;   /* darker green for headings */
  --brand-mid:    #2f8f78;
  --brand-light:  #94c6b2;   /* CUSP primary-label */
  --brand-pale:   #d3e7df;
  --brand-tint:   #eef6f3;

  /* Warm greys, straight off the reference PDFs. Warm rather than blue-grey is
     what stops the printed page looking cold beside the blue bars. */
  --ink:          #1a1a1a;   /* CUSP text-primary */
  --body:         #575757;   /* CUSP data-table text */
  --muted:        #6b6b6b;   /* CUSP text-secondary */
  --rule:         #e6e6e6;
  --rule-soft:    #f0f0f0;
  --panel:        #fafafa;   /* CUSP input background */
  --paper:        #ffffff;
  --app-bg:       #f3f3f3;   /* CUSP page background */

  /* Sentiment. Dark enough to survive greyscale printing, and never the only
     signal -- the arrow and the words carry it too. */
  --good:         #1f811f;   /* CUSP status closed */
  --good-ink:     #006300;
  --good-bar:     #3dd598;   /* CUSP light green */
  --good-tint:    #eef8f2;
  --bad:          #c0392b;   /* CUSP semantic red */
  --bad-tint:     #fdf0ef;
  --warn:         #8a5e10;   /* CUSP amber text */
  --warn-tint:    #fff4d9;   /* CUSP amber background */
  --neutral:      #52514e;
  --accent:       #fbb040;   /* CUSP accent amber (the logo's second colour) */

  --focus:        #267864;
  --shadow:       0 1px 2px rgba(11, 11, 11, .06), 0 6px 18px rgba(11, 11, 11, .06);

  --font: "Open Sans", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto,
          "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif;
  --font-mono: "Cascadia Mono", Consolas, "SFMono-Regular", "Liberation Mono",
          "Courier New", monospace;

  --radius:    6px;
  --radius-lg: 8px;
}

/* ------------------------------------------------------------------ base */

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

body {
  background: var(--app-bg);
  color: var(--body);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  color: var(--ink);
  font-weight: 700;
  line-height: 1.25;
  margin: 0 0 .5em;
}
h1 { font-size: 22px; letter-spacing: -.2px; }
h2 { font-size: 16.5px; }
h3 { font-size: 14.5px; }
h4 { font-size: 13.5px; }

p { margin: 0 0 .85em; }
p:last-child { margin-bottom: 0; }

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

strong, b { color: var(--ink); font-weight: 700; }

code, kbd, samp, .mono, pre { font-family: var(--font-mono); font-size: .92em; }
code {
  background: var(--rule-soft);
  border-radius: 3px;
  padding: 1px 4px;
  color: var(--ink);
}
pre {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 10px 12px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

hr { border: 0; border-top: 1px solid var(--rule); margin: 20px 0; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 3px;
}

/* The quiet second line, used all over the app. */
.sub  { color: var(--muted); font-size: 13.5px; margin: 0 0 14px; }
.hint { color: var(--muted); font-size: 12.5px; font-weight: 400; }
.tiny { color: var(--muted); font-size: 11.5px; line-height: 1.45; }
.tiny.warn { color: var(--warn); }
.fineprint {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.55;
  margin-top: 14px;
}

/* --------------------------------------------------------------- app shell */

.topbar {
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  padding: 0 20px;
  display: flex;
  align-items: center;
  gap: 18px;
  min-height: 54px;
  flex-wrap: wrap;
  position: sticky;
  top: 0;
  z-index: 20;
}
.topbar .brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0;
  white-space: nowrap;
}
.topbar .brand img { height: 26px; width: auto; display: block; }
.topbar .brand .brand-app { padding-left: 10px; border-left: 1px solid var(--rule); }
.topbar .brand:hover { text-decoration: none; }

/* Whose report, and which period. The most expensive mistake this app could
   make is quietly working on the wrong one, so it stays in the corner of
   your eye on every screen. */
.context {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  padding: 4px 10px;
  background: var(--brand-tint);
  border: 1px solid var(--brand-pale);
  border-radius: var(--radius);
  font-size: 13px;
  color: var(--body);
  min-width: 0;
}
.context a { color: var(--ink); font-weight: 700; }
.context .sep { color: var(--muted); }

.topnav {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-wrap: wrap;
  margin-left: auto;
}
.topnav a {
  color: var(--body);
  padding: 7px 11px;
  border-radius: var(--radius);
  font-size: 13.5px;
  white-space: nowrap;
}
.topnav a:hover { background: var(--rule-soft); text-decoration: none; }
.topnav a.active { background: var(--brand-tint); color: var(--brand-deep); font-weight: 600; }
.topnav .who {
  color: var(--muted);
  font-size: 12.5px;
  padding-left: 12px;
  margin-left: 6px;
  border-left: 1px solid var(--rule);
}
.topnav form.inline { margin: 0; display: inline-flex; align-items: center; }

.wrap {
  display: block;
  max-width: 1120px;
  margin: 0 auto;
  padding: 22px 20px 60px;
}
.wrap > h1 { margin-bottom: 4px; }

.pagehead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.pagehead h1 { margin-bottom: 4px; }
.pagehead .sub { margin-bottom: 0; max-width: 62ch; }

/* ------------------------------------------------------------ flash / pills */

.flashes {
  max-width: 1120px;
  margin: 14px auto -4px;
  padding: 0 20px;
}
.flash {
  border: 1px solid var(--rule);
  border-left: 4px solid var(--muted);
  background: var(--paper);
  border-radius: var(--radius);
  padding: 10px 14px;
  margin-bottom: 8px;
  font-size: 13.5px;
  color: var(--body);
}
.flash-ok, .flash-success   { border-left-color: var(--good); background: var(--good-tint); }
.flash-warn, .flash-warning { border-left-color: var(--warn); background: var(--warn-tint); }
.flash-error, .flash-danger { border-left-color: var(--bad);  background: var(--bad-tint); }
.flash-info, .flash-message { border-left-color: var(--brand); background: var(--brand-tint); }

.pill {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1;
  padding: 4px 8px;
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: var(--rule-soft);
  color: var(--body);
  white-space: nowrap;
}
.pill.good  { background: var(--good-tint); border-color: #cfe6d8; color: var(--good); }
.pill.warn  { background: var(--warn-tint); border-color: #ecdcba; color: var(--warn); }
.pill.bad   { background: var(--bad-tint);  border-color: #e9cfcb; color: var(--bad); }
.pill.final { background: var(--brand-tint); border-color: var(--brand-pale); color: var(--brand-deep); }

/* ------------------------------------------------------------------ panels */

.panel {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 18px 20px 20px;
  margin: 0 0 18px;
}
.panel > h2:first-child, .panel > h3:first-child { margin-top: 0; }
.panel.muted { background: var(--panel); }
.panel.errorpanel { border-left: 4px solid var(--bad); }

h3.minor {
  font-size: 12.5px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
  margin: 18px 0 8px;
}
h3.minor.good { color: var(--good); }
h3.minor.warn { color: var(--warn); }

.two-col {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px;
}

/* ----------------------------------------------------------------- buttons */

.btn,
form button:not(.linkish),
button.primary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.2;
  padding: 8px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}
.btn:hover, form button:not(.linkish):hover { background: var(--rule-soft); text-decoration: none; }
.btn:active { transform: translateY(1px); }

.btn.primary,
button.primary {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
.btn.primary:hover, button.primary:hover { background: var(--brand-deep); border-color: var(--brand-deep); }

.primary.wide, .btn.wide { width: 100%; justify-content: center; }

.btn.disabled, .btn[disabled], button[disabled] {
  opacity: .45;
  cursor: not-allowed;
  pointer-events: none;
}

/* A button that has to read as a link: "choose files", "Show me", "Remove". */
.linkish {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font-family: inherit;
  font-size: inherit;
  font-weight: 600;
  color: var(--brand);
  cursor: pointer;
}
.linkish:hover { text-decoration: underline; }
.linkish.danger { color: var(--bad); }

form.inline { display: inline; }
.spacer { flex: 1 1 auto; }

/* ------------------------------------------------------------ form controls */

label { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink); margin-bottom: 5px; }

/* Match by exclusion, not by listing types: a bare <input> with no type
   attribute defaults to text but is NOT matched by input[type="text"], which
   silently left half the settings forms unstyled. */
input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"]):not([type="hidden"]),
select, textarea {
  width: 100%;
  font-family: inherit;
  font-size: 13.5px;
  color: var(--ink);
  background: #fff;
  border: 1px solid #d6d4cc;
  border-radius: var(--radius);
  padding: 8px 10px;
  line-height: 1.4;
  margin-bottom: 14px;
}
select { padding-right: 6px; }
textarea { resize: vertical; min-height: 78px; line-height: 1.55; }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(31, 95, 169, .14);
}
input[type="checkbox"], input[type="radio"] {
  width: auto;
  margin: 0 8px 0 0;
  accent-color: var(--brand);
}

.field-row { display: flex; gap: 16px; flex-wrap: wrap; }
.field-row > div { flex: 1 1 190px; min-width: 0; }

/* One-line "type a name, pick a thing, press Add" form. */
.period-form { max-width: 560px; }
.period-form button { margin-top: 4px; }
.rowform { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.rowform input, .rowform select { margin-bottom: 0; flex: 1 1 180px; }
.rowform.tight input, .rowform.tight select { flex: 0 1 170px; }

.check, .radio {
  display: flex;
  align-items: flex-start;
  gap: 4px;
  font-weight: 400;
  font-size: 13.5px;
  color: var(--body);
  margin-bottom: 10px;
  cursor: pointer;
}
.check input, .radio input { margin-top: 3px; }
.check strong, .radio strong { display: block; }
.check em, .radio em {
  display: block;
  font-style: normal;
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.45;
  margin-top: 2px;
}
/* The US-only declaration changes what the report says in its data notes, so it
   is deliberately harder to skip past than an ordinary checkbox. */
.check.us-only {
  background: var(--warn-tint);
  border: 1px solid #ecdcba;
  border-radius: var(--radius);
  padding: 10px 12px;
  margin-bottom: 0;
}
.checkgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 4px 18px;
}

fieldset {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 12px 14px 6px;
  margin: 0 0 16px;
  min-width: 0;
}
legend { font-size: 12px; font-weight: 700; color: var(--muted); padding: 0 6px; }
.inline-fieldset { flex: 1 1 320px; margin-bottom: 0; }
.inline-fieldset .radio { margin-bottom: 6px; }

/* --------------------------------------------------------- sign-in screens */

.auth-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 40px 18px;
}
.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 30px 30px 26px;
}
.auth-card.wide-card { max-width: 470px; }
.auth-card h1 { color: var(--brand-deep); font-size: 20px; margin-bottom: 3px; }
.auth-card .sub { margin-bottom: 22px; }
.auth-card label { margin-top: 15px; }
.auth-card label:first-of-type { margin-top: 0; }
.auth-card input { margin-bottom: 0; }
.auth-card button { margin-top: 22px; }
.auth-card .fineprint {
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
}

/* --------------------------------------------------------------- drop zone */

.dropzone-controls {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  align-items: flex-start;
  margin-bottom: 16px;
}
.dropzone-controls > .check { flex: 1 1 320px; }

.dropzone {
  border: 2px dashed #c9c6bc;
  border-radius: var(--radius-lg);
  background: var(--panel);
  padding: 30px 22px;
  text-align: center;
  color: var(--body);
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
.dz-inner { max-width: 46ch; margin: 0 auto; }
.dz-icon { font-size: 26px; color: var(--muted); line-height: 1; }
.dz-lead { font-size: 15px; font-weight: 700; color: var(--ink); margin: 8px 0 2px; }
.dz-sub  { color: var(--muted); font-size: 12.5px; margin: 0; }

.dropzone:hover { border-color: var(--brand); background: var(--brand-tint); }
/* .over = files are over the zone right now (studio.js sets it on dragover). */
.dropzone.over {
  border-color: var(--brand);
  border-style: solid;
  background: var(--brand-pale);
}
.dropzone.over .dz-lead, .dropzone.over .dz-icon { color: var(--brand-deep); }
/* .busy = an upload is in flight, so the zone stops inviting more. */
.dropzone.busy { opacity: .6; cursor: progress; border-style: solid; }
/* .rejected = wrong type or too big; the reason goes in .dz-sub. */
.dropzone.rejected { border-color: var(--bad); background: var(--bad-tint); }
.dropzone.rejected .dz-lead, .dropzone.rejected .dz-icon { color: var(--bad); }

/* One card per file, newest first, colour-coded by what happened to it. */
.results { margin-top: 14px; }
.result {
  border: 1px solid var(--rule);
  border-left: 4px solid var(--muted);
  border-radius: var(--radius);
  background: var(--paper);
  padding: 10px 14px;
  margin-bottom: 8px;
}
.result-name { font-weight: 700; color: var(--ink); font-size: 13.5px; word-break: break-all; }
.result-status { font-size: 12.5px; color: var(--body); margin-top: 2px; }
.result-hint { font-size: 12px; color: var(--muted); margin-top: 5px; }
.result-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 7px; }
.result.pending { border-left-color: var(--brand-light); }
.result.good    { border-left-color: var(--good); }
.result.bad     { border-left-color: var(--bad);  background: var(--bad-tint); }
.result.dupe    { border-left-color: var(--warn); background: var(--warn-tint); }

.progress {
  height: 4px;
  background: var(--rule);
  border-radius: 2px;
  overflow: hidden;
  margin-top: 8px;
}
.progress > i { display: block; height: 100%; width: 0; background: var(--brand); }

.result-details, details.tiny, .errordetail { margin-top: 7px; font-size: 12px; }
.result-details > summary,
details.tiny > summary,
.errordetail > summary {
  cursor: pointer;
  color: var(--brand);
  font-weight: 600;
}
.result-details ul, details.tiny ul { margin: 6px 0 0; padding-left: 18px; color: var(--body); }
.result-details.warnbox {
  background: var(--warn-tint);
  border: 1px solid #ecdcba;
  border-radius: var(--radius);
  padding: 7px 10px;
}
.reload-hint { margin-top: 10px; font-size: 12.5px; }

/* Detection evidence is shown verbatim: it is the answer to "why did it think
   this was a GA4 file?", so it is never paraphrased or trimmed. */
.evidence {
  list-style: none;
  margin: 6px 0 0;
  padding: 8px 10px;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--body);
  max-height: 220px;
  overflow: auto;
}
.evidence li { padding: 2px 0; }

/* ---------------------------------------------------- day-by-day coverage */

.covrow {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr) 108px;
  align-items: center;
  gap: 12px;
  margin-bottom: 9px;
}
.covlabel { font-size: 12.5px; color: var(--body); }
.covgrid { display: flex; flex-wrap: wrap; gap: 3px; }
.covgrid .cell {
  width: 17px;
  height: 17px;
  border-radius: 3px;
  border: 1px solid rgba(11, 11, 11, .08);
  background: var(--rule);
  display: inline-block;
}
/* Green = the day is complete, amber = thin, red = nothing landed that day.
   Both spellings the ingest side might use are covered on purpose. */
.cell.ok, .cell.full, .cell.complete   { background: #2fa15f; }
.cell.partial, .cell.some, .cell.thin  { background: #e2a53c; }
.cell.missing, .cell.none, .cell.empty { background: #d97a6d; }
.cell.outside { background: var(--rule-soft); border-style: dashed; }
.covcount { font-size: 12px; color: var(--muted); text-align: right; }
.covcount.ok   { color: var(--good); }
.covcount.warn { color: var(--warn); }

.empty-inline {
  color: var(--muted);
  font-size: 12.5px;
  background: var(--panel);
  border: 1px dashed #d3d0c7;
  border-radius: var(--radius);
  padding: 10px 12px;
}

.ticklist { list-style: none; margin: 0; padding: 0; font-size: 13px; }
.ticklist li { position: relative; padding: 3px 0 3px 20px; color: var(--body); }
.ticklist li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: .72em;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--good);
}
.ticklist.blocked li::before { background: var(--warn); }
.ticklist li em { font-style: normal; color: var(--muted); font-size: 12px; }

.steps { margin: 0 0 4px; padding-left: 20px; }
.steps li { margin-bottom: 8px; }

/* ------------------------------------------------------------- empty states */

.empty {
  text-align: center;
  padding: 34px 22px;
  border: 1px dashed #d3d0c7;
  border-radius: var(--radius-lg);
  background: var(--panel);
  color: var(--muted);
}
.empty p { max-width: 52ch; margin: 0 auto .9em; }
.empty .btn { margin-top: 6px; }

/* ------------------------------------------------------------- card lists */

.cardlist { list-style: none; margin: 0; padding: 0; }
.cardlist .card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}
.cardlist .card:last-child { border-bottom: 0; padding-bottom: 0; }
.card-main { min-width: 0; }
.card-title { font-size: 14.5px; font-weight: 700; color: var(--ink); }
a.card-title:hover { color: var(--brand); }
.card-sub { color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.card-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* --------------------------------------------------------- app data tables */

.datatable { width: 100%; border-collapse: collapse; font-size: 13px; }
.datatable th {
  text-align: left;
  font-weight: 700;
  color: var(--muted);
  font-size: 12px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
.datatable td {
  padding: 9px 10px;
  border-bottom: 1px solid var(--rule-soft);
  color: var(--body);
  vertical-align: top;
}
.datatable th:first-child, .datatable td:first-child { padding-left: 0; }
.datatable th:last-child, .datatable td:last-child { padding-right: 0; }
.datatable tr:last-child td { border-bottom: 0; }
.datatable .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.datatable tr.refused td, .datatable tr.row-off td { background: var(--bad-tint); }
.datatable td .evidence { max-height: 150px; }

/* ==================================================== report page layout */

.reportwrap {
  display: block;
  max-width: 1320px;
  margin: 0 auto;
  padding: 18px 20px 60px;
}
.reportlayout { display: block; }
.reportlayout.with-rail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 330px;
  gap: 22px;
  align-items: start;
}
.documentcol { min-width: 0; }
/* With no rail beside it the document would stretch to the window; a report is
   easier to read at roughly the width it will be printed at. */
.reportlayout:not(.with-rail) .documentcol { max-width: 880px; margin: 0 auto; }

.doctoolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

/* ------------------------------------------------------- the client's view */

/* What a client sees: the finished document, a way to save it, nothing else.
   Quieter than the working view on purpose -- no drafts, no findings. */
.clientbar { align-items: baseline; }
.clientgreeting { color: var(--body); font-size: 13.5px; }
.clientfoot {
  color: var(--muted);
  font-size: 12.5px;
  text-align: center;
  margin: 18px auto 0;
  max-width: 60ch;
}
.previewbanner {
  background: var(--warn-tint);
  border: 1px solid #ecdcba;
  border-radius: var(--radius);
  padding: 10px 14px;
  margin-bottom: 14px;
  font-size: 13px;
  color: var(--body);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.previewbanner .btn { margin-left: auto; }

/* The findings rail sticks: each item points at a figure you are scrolling
   past, so it has to stay beside them. */
.rail {
  position: sticky;
  top: 70px;
  max-height: calc(100vh - 92px);
  overflow: auto;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 14px 16px 16px;
}
.rail-head h2 { font-size: 14.5px; margin-bottom: 8px; }
.rail-counts { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.rail-ok {
  color: var(--good);
  background: var(--good-tint);
  border: 1px solid #cfe6d8;
  border-radius: var(--radius);
  padding: 8px 10px;
  font-size: 12.5px;
  margin: 0 0 10px;
}
.rail-blocked {
  color: var(--bad);
  background: var(--bad-tint);
  border: 1px solid #e9cfcb;
  border-radius: var(--radius);
  padding: 8px 10px;
  font-size: 12.5px;
  margin: 0 0 10px;
}

.rail .findings { list-style: none; margin: 0; padding: 0; }
.finding {
  border-left: 3px solid var(--rule);
  padding: 8px 0 8px 10px;
  margin-bottom: 10px;
  font-size: 12.5px;
  color: var(--body);
}
.finding:last-child { margin-bottom: 0; }
.finding-msg { color: var(--ink); font-weight: 600; }
.finding-fix { color: var(--body); margin-top: 3px; }
.finding-actions { display: flex; gap: 12px; margin-top: 5px; }
.finding-actions .linkish { font-size: 12px; }
/* Severities as the lint module names them: block / warn / style. */
.finding.sev-block { border-left-color: var(--bad); }
.finding.sev-warn  { border-left-color: var(--warn); }
.finding.sev-style { border-left-color: var(--brand-light); }
.finding.sev-info  { border-left-color: var(--brand); }

/* Jumping from the rail to a block: a short, quiet highlight, so you can see
   where you landed without the page flashing at you. */
.flash-target {
  box-shadow: 0 0 0 3px var(--brand-pale);
  border-radius: 5px;
  transition: box-shadow .3s ease;
}

/* ------------------------------------------------------ editing affordances */

.prose.editable {
  border: 1px dashed transparent;
  border-radius: var(--radius);
  padding: 6px 8px;
  margin: -6px -8px 10px;
  min-height: 2.4em;
  outline: none;
}
.prose.editable:hover { border-color: #d3d0c7; background: rgba(255, 255, 255, .7); }
.prose.editable:focus {
  border-color: var(--brand);
  border-style: solid;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(31, 95, 169, .12);
}
.prose.editable.saving { border-color: var(--warn); border-style: solid; }
.prose.editable.saved  { border-color: var(--good); border-style: solid; }
.prose.editable.error  { border-color: var(--bad);  border-style: solid; background: var(--bad-tint); }

.prose-editor { margin-bottom: 12px; }
.prose-help {
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.5;
  margin-top: 4px;
}
.prose-help code { font-size: 11px; }
.prose-preview {
  border-left: 3px solid var(--brand-pale);
  padding-left: 10px;
  margin-top: 10px;
  color: var(--body);
}

/* A slot is a sentence only a person can write. An empty required one is meant
   to be impossible to walk past. */
.slot {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper);
  padding: 10px 12px;
  margin: 10px 0;
}
.slot.slot-open { border-color: var(--warn); background: var(--warn-tint); }
.slot-prompt { font-size: 12.5px; color: var(--ink); margin-bottom: 6px; }
.slot-req {
  display: inline-block;
  margin-left: 6px;
  font-size: 11px;
  font-weight: 700;
  color: var(--warn);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.slot-input { margin-bottom: 0; }
.slot-input.saving { border-color: var(--warn); }
.slot-input.saved  { border-color: var(--good); }
.slot-input.error  { border-color: var(--bad); }

.block-unavailable {
  border: 1px dashed #d3d0c7;
  border-radius: var(--radius);
  background: var(--panel);
  padding: 12px 14px;
  color: var(--muted);
}
.block-unavailable h2 { font-size: 14px; color: var(--muted); margin-bottom: 4px; }

/* Hover a figure to read the English formula behind it. */
.has-provenance { border-bottom: 1px dotted var(--brand-light); cursor: help; }

/* ================================================================ DOCUMENT
 * The report itself. print.css restates all of this in points; the only real
 * difference is the base font-size, which is what makes this a true preview.
 * ======================================================================== */

.document {
  --fs-title:  1.76em;   /* the cover title */
  --fs-banner: 1.36em;   /* a heading that opens a page */
  --fs-head:   1.12em;   /* exhibit headings */
  --fs-sub:    0.96em;   /* labels inside exhibits */
  --fs-prose:  0.92em;   /* "What this means" prose */
  --fs-small:  0.88em;   /* table text, captions */
  --fs-tiny:   0.76em;   /* footer, data notes */
  --fs-tile:   1.68em;   /* the big number on a tile */
  --doc-pad:   38px;

  font-size: 13px;
  line-height: 1.52;
  color: var(--body);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 4px;
  box-shadow: var(--shadow);
  padding: var(--doc-pad) var(--doc-pad) 26px;
  font-variant-numeric: tabular-nums;
}
/* The standalone HTML export has no app around it, so it makes its own margin. */
body.printdoc { background: var(--app-bg); padding: 26px 18px; }
body.printdoc .document { max-width: 780px; margin: 0 auto; }

.document p { margin: 0 0 .8em; orphans: 3; widows: 3; }
.document p:last-child { margin-bottom: 0; }
.document h2 {
  font-size: var(--fs-head);
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 6px;
}
.document h3 {
  font-size: var(--fs-sub);
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 5px;
}
/* Square bullets, matching the reference reports' "Other findings" lists. */
.document ul { margin: 8px 0 0; padding: 0; list-style: none; }
.document ul li { position: relative; padding-left: 14px; margin-bottom: 8px; }
.document ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .55em;
  width: 4px;
  height: 4px;
  background: var(--body);
}

/* Each exhibit is one block, and most sit on an off-white card exactly like the
   reference reports. The cover, the tiles and the notes deliberately do not --
   they read as part of the page rather than as a panel. */
.block {
  --pad-x: 18px;
  --pad-y: 14px;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: 5px;
  padding: var(--pad-y) var(--pad-x) 16px;
  margin: 0 0 16px;
}
.block > *:last-child { margin-bottom: 0; }
.block-cover,
.block-kpi_tiles,
.block-data_notes,
.block-next_steps {
  --pad-x: 0px;
  --pad-y: 0px;
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
}
.block-exec_summary { background: var(--brand-tint); border-color: var(--brand-pale); }

/* -------------------------------------------------------------- cover block */

.cover { margin-bottom: 4px; }
.cover-title {
  font-size: var(--fs-title);
  font-weight: 700;
  line-height: 1.16;
  letter-spacing: -.2px;
  color: var(--brand-deep);
  margin: 0 0 6px;
}
.cover-sub {
  font-size: var(--fs-head);
  color: var(--body);
  margin: 0 0 5px;
}
.cover-dates {
  font-size: var(--fs-small);
  font-style: italic;
  color: var(--muted);
  margin: 0;
}

/* A heading that opens its own page in the PDF. Either the renderer marks the
   block .starts-page, or it emits an .section-banner heading; both look the
   same, so a page always breaks somewhere a person chose. */
.section-banner,
.block.starts-page > h2:first-child {
  font-size: var(--fs-banner);
  font-weight: 700;
  color: var(--brand-deep);
  /* The rule runs the full width of the exhibit card rather than stopping at
     its padding, so the heading reads as the top of a section and not as a
     label inside a box. --pad-* is 0 on the blocks that carry no card. */
  margin: calc(4px - var(--pad-y, 0px)) calc(-1 * var(--pad-x, 0px)) 12px;
  padding: 0 var(--pad-x, 0px) 5px;
  border-bottom: 1.5px solid var(--brand-deep);
}

/* ------------------------------------------------------------------- prose */

/* "What this means" always follows an exhibit, so it carries its own air above
   rather than relying on whatever came before it to provide it. */
.prose { font-size: var(--fs-prose); color: var(--body); margin-top: 11px; }
.block > .prose:first-of-type:first-child { margin-top: 0; }
.block-exec_summary .prose.lead { margin-top: 0; }
.prose p { margin: 0 0 .8em; }
.prose strong, .prose b { color: var(--ink); font-weight: 700; }
/* The executive summary is one dense paragraph, a shade larger than body copy
   and never bulleted -- the house style in all ten reference reports. */
.prose.lead { font-size: 1.02em; }
.prose.analyst { margin-top: 10px; }
.block-next_steps .prose.analyst {
  border-left: 3px solid var(--brand);
  padding-left: 11px;
  margin-bottom: 10px;
}

.caption, .legend, .footnote {
  font-size: var(--fs-small);
  color: var(--muted);
  margin: 0 0 10px;
}
.footnote { margin: 6px 0 0; }

/* ---------------------------------------------------------------- KPI tiles */

/* Four across, always. A wrapped fifth tile or a 3+1 row is the tell-tale sign
   of something gone wrong upstream. */
.tiles {
  display: grid;
  grid-template-columns: repeat(var(--tile-cols, 4), minmax(0, 1fr));
  gap: 11px;
  margin: 0 0 16px;
}
.tile {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: 5px;
  padding: 10px 8px 11px;
  text-align: center;
  min-width: 0;
}
.tile-label {
  font-size: var(--fs-small);
  color: var(--body);
  margin-bottom: 3px;
  overflow-wrap: break-word;
}
.tile-value {
  font-size: var(--fs-tile);
  font-weight: 700;
  line-height: 1.1;
  color: var(--ink);
  margin-bottom: 5px;
}
/* A figure we could not compute shows an em dash, never a zero. */
.tile-value.missing, .missing { color: var(--muted); }
.tile-delta {
  font-size: var(--fs-tiny);
  font-weight: 700;
  color: var(--neutral);
  white-space: nowrap;
}

/* Sentiment inside the document. The class comes from the metric's
   good_direction, NEVER from the arrow glyph: a rising cost per lead is an up
   arrow AND a red chip. */
.tile-delta.good, .bar-caption.good, .bigstat-delta.good, .document .good { color: var(--good-ink); }
.tile-delta.bad,  .bar-caption.bad,  .bigstat-delta.bad,  .document .bad  { color: var(--bad); }
.tile-delta.neutral, .bar-caption.neutral, .bigstat-delta.neutral,
.document .neutral { color: var(--neutral); }

/* -------------------------------------------------------- paired comparison */

/* Every bar in this document is a plain element with an inline percentage
   width. There is no charting library offline and none is needed: each exhibit
   is one dimension deep, and a plain bar prints perfectly. */
.bars {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 26px;
}
.barset { min-width: 0; }
.barset > .bar-label {
  font-size: var(--fs-sub);
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 5px;
}
.bar-pair { margin: 0; }
.bar-row {
  display: grid;
  grid-template-columns: 5.2em minmax(0, 1fr) 4em;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}
.bar-tag, .bar-row > .bar-label {
  font-size: var(--fs-small);
  color: var(--body);
  text-align: right;
  white-space: nowrap;
}
.bar {
  display: block;
  height: 11px;
  min-width: 2px;
  border-radius: 2px;
  background: var(--brand);
}
.bar.prior   { background: var(--brand-light); }
.bar.current { background: var(--brand); }
.bar-val {
  font-size: var(--fs-small);
  font-weight: 700;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
}
.bar-caption {
  font-size: var(--fs-small);
  color: var(--neutral);
  margin-top: 3px;
}

/* ---------------------------------------------------------- share breakdown */

.shares { margin: 0; }
.share-row {
  display: grid;
  grid-template-columns: minmax(6em, 13em) minmax(0, 1fr) 3.6em auto;
  align-items: center;
  gap: 10px;
  margin-bottom: 7px;
}
.share-row:last-child { margin-bottom: 0; }
.share-name { font-size: var(--fs-sub); color: var(--ink); overflow-wrap: break-word; }
.share-bar {
  display: block;
  background: #f0efe9;
  border-radius: 2px;
  overflow: hidden;
}
.share-bar > i {
  display: block;
  height: 12px;
  min-width: 2px;
  background: var(--brand);
  border-radius: 2px;
}
/* Successive rows step down through the blues so a stacked share reads as one
   picture rather than four identical bars. */
.share-row:nth-child(2) .share-bar > i { background: var(--brand-mid); }
.share-row:nth-child(3) .share-bar > i { background: var(--brand-light); }
.share-row:nth-child(4) .share-bar > i { background: var(--muted); }
.share-row:nth-child(5) .share-bar > i { background: var(--accent); }
.share-pct {
  font-size: var(--fs-sub);
  font-weight: 700;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
}
.share-val {
  font-size: var(--fs-small);
  color: var(--muted);
  text-align: right;
  white-space: nowrap;
}
.shares.tight .share-row { margin-bottom: 5px; }
.shares.tight .share-bar > i { height: 9px; }

/* -------------------------------------------------------------- single stat */

.bigstat {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.bigstat-value {
  font-size: var(--fs-tile);
  font-weight: 700;
  color: var(--ink);
  line-height: 1.1;
}
.bigstat-delta { font-size: var(--fs-sub); font-weight: 700; color: var(--neutral); }
.bigstat-prior { font-size: var(--fs-small); color: var(--muted); }

.statbar { background: var(--rule); border-radius: 2px; overflow: hidden; margin-bottom: 10px; }
.statbar > i {
  display: block;
  height: 12px;
  min-width: 2px;
  background: var(--good-bar);
  border-radius: 2px;
}

/* ------------------------------------------------------------------- funnel */

.funnel { margin: 0; }
.funnel-step {
  display: grid;
  grid-template-columns: 11.5em minmax(0, 1fr) 3.6em;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.funnel-step:last-child { margin-bottom: 0; }
.funnel-label { font-size: var(--fs-sub); color: var(--ink); }
.funnel-bar {
  display: block;
  height: 13px;
  min-width: 2px;
  border-radius: 2px;
  background: var(--brand);
}
/* One shade darker at each step down the funnel. */
.funnel-step:nth-of-type(1) .funnel-bar { background: #6da7ec; }
.funnel-step:nth-of-type(2) .funnel-bar { background: #3987e5; }
.funnel-step:nth-of-type(3) .funnel-bar { background: #256abf; }
.funnel-step:nth-of-type(4) .funnel-bar { background: #184f95; }
.funnel-step:nth-of-type(5) .funnel-bar { background: #123c72; }
.funnel-val {
  font-size: var(--fs-sub);
  font-weight: 700;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
}

/* ------------------------------------------------------------ report tables */

/* Light horizontal rules only. Vertical borders turn a readable table into a
   spreadsheet screenshot. */
.tablewrap { overflow-x: auto; }
.report-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-small);
  margin: 0;
}
.report-table th {
  text-align: left;
  font-weight: 700;
  color: var(--muted);
  padding: 5px 8px;
  border-bottom: 1px solid var(--rule);
  vertical-align: bottom;
}
.report-table th:first-child { color: var(--ink); }
.report-table td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--rule);
  color: var(--body);
  vertical-align: top;
}
.report-table td:first-child { color: var(--ink); }
.report-table th:first-child, .report-table td:first-child { padding-left: 0; }
.report-table th:last-child, .report-table td:last-child { padding-right: 0; }
.report-table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.report-table tr.total-row td {
  font-weight: 700;
  color: var(--ink);
  border-top: 1px solid var(--rule);
  border-bottom: 0;
  background: rgba(31, 95, 169, .045);
}

/* ------------------------------------------------------------ wins & cards */

.document .cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 26px;
}
.wincard {
  border-left: 3px solid var(--good);
  padding: 2px 0 2px 11px;
  font-size: var(--fs-prose);
  color: var(--body);
  min-width: 0;
}
.wincard-title { color: var(--ink); font-weight: 700; margin-bottom: 2px; }
.wincard-body { color: var(--body); }
.block-next_steps .wincard { border-left-color: var(--brand); }

/* ---------------------------------------------------------- notes & footer */

.datanotes {
  font-size: var(--fs-tiny);
  color: var(--muted);
  line-height: 1.55;
  margin-top: 14px;
}
.datanotes h3 { font-size: var(--fs-small); color: var(--body); margin-bottom: 4px; }
.datanotes p { margin-bottom: .6em; }

/* On screen the running footer appears once, at the end of the document. In
   print it repeats at the foot of every page -- see print.css. */
.docfooter {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  border-top: 1px solid var(--rule);
  margin-top: 20px;
  padding-top: 8px;
  font-size: var(--fs-tiny);
  color: var(--muted);
}

/* -------------------------------------------------------------- responsive */

@media screen and (max-width: 1080px) {
  .reportlayout.with-rail { grid-template-columns: minmax(0, 1fr); }
  .rail { position: static; max-height: none; }
}

@media screen and (max-width: 860px) {
  .wrap, .reportwrap, .flashes { padding-left: 14px; padding-right: 14px; }
  .two-col { grid-template-columns: minmax(0, 1fr); }
  .covrow { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .covcount { text-align: left; }
  .document { --doc-pad: 22px; font-size: 12.5px; }
  .bars { grid-template-columns: minmax(0, 1fr); }
  .document .cards { grid-template-columns: minmax(0, 1fr); }
  .share-row { grid-template-columns: 8em minmax(0, 1fr) 3.4em auto; }
  .funnel-step { grid-template-columns: 8em minmax(0, 1fr) 3.2em; }
}

@media screen and (max-width: 620px) {
  .topbar { padding: 8px 12px; gap: 10px; }
  .topnav { margin-left: 0; width: 100%; }
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pagehead { flex-direction: column; }
  .doctoolbar .btn { flex: 1 1 auto; justify-content: center; }
  .report-table, .datatable { font-size: 12px; }
  .bar-row { grid-template-columns: 4.4em minmax(0, 1fr) 3.4em; gap: 6px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .btn:active { transform: none; }
}

/* ---------------------------------------------------------------- viewing as
   Deliberately loud. Forgetting you are impersonating a client and then
   "fixing" something is a real hazard, so this bar is impossible to miss. */
.impersonating{
  display:flex; align-items:center; gap:1rem; flex-wrap:wrap;
  background:#4a3410; color:#ffe9c2;
  padding:.6rem 1.1rem; font-size:.86rem; line-height:1.45;
  border-bottom:3px solid #c98a1d;
}
.impersonating strong{color:#fff;}
.impersonating .btn{
  background:#ffe9c2; color:#4a3410; border-color:#ffe9c2;
  padding:.28rem .7rem; font-size:.82rem; white-space:nowrap;
}
.impersonating .btn:hover{background:#fff; border-color:#fff;}
.impersonating form{margin-left:auto;}
/* The "real customer can't sign in yet" line: on its own line so it isn't
   read as part of the sentence about who you're viewing as. */
.impersonating .impersonating-note{display:block; color:#ffd48a; font-weight:600;}

/* ---------------------------------------------------------------- accounts
   Websites, Chargebee IDs and the Missing details page. */
.sitetable-wrap { overflow-x: auto; }
/* Same :not() chain as the global input rule, so this actually outranks it:
   fields inside a table row need no bottom gap. */
.sitetable input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"]):not([type="hidden"]),
.sitetable select {
  margin-bottom: 0;
  min-width: 11em;
}
.sitetable td { vertical-align: middle; }
.sitetable .check { margin: 0; }
.sitetable .pill + .tiny { margin-top: 3px; }
.sitetable .btn { margin-top: 6px; padding: 4px 10px; font-size: 12.5px; }
.sitetable tr.newrow td { background: var(--panel); }
.fielderror {
  color: var(--bad);
  font-size: 12.5px;
  line-height: 1.4;
  margin: 4px 0 10px;
}
.sitetable .fielderror { margin-bottom: 0; }
/* Switches that could let internal findings near a customer. */
.panel.cautionpanel { border-left: 4px solid var(--warn); }
.gaplist { margin: 0; padding-left: 18px; font-size: 13px; }
.gaplist li { margin-bottom: 2px; }

/* ---------------------------------------------------------------- open-ended lists
   Headline tiles and targets: one row per item, Remove on the row, Add under the
   list. The third column is sized to the button so the fields still line up. */
.repeat-list { display: grid; gap: 2px; margin-bottom: 8px; }
.repeat-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
  gap: 14px;
  align-items: end;
}
.repeat-remove { padding-bottom: 22px; }
.repeat-empty { margin: 2px 0 12px; }
@media (max-width: 720px) {
  .repeat-row { grid-template-columns: 1fr; gap: 0; }
  .repeat-remove { padding-bottom: 10px; }
}

/* ---------------------------------------------------------------- support messages
   Customer-typed text keeps its own line breaks (pre-wrap) and never widens the
   page (overflow-wrap), whatever gets pasted in. */
.messages { list-style: none; margin: 0; padding: 0; }
.message { border-top: 1px solid var(--rule); padding: 12px 0; }
.message:first-child { border-top: 0; padding-top: 0; }
.message-head { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; margin-bottom: 4px; }
.message-body { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--body); }

/* ---------------------------------------------------------------- notes
   Customer notes get a blue tag so it is obvious at a glance which ones the
   customer can read. */
.pill.note-customer { background: var(--brand-tint); border-color: var(--brand-pale);
  color: var(--brand-deep); }
.note-form { margin-bottom: 18px; }
.note-visibility { display: grid; gap: 2px; margin-bottom: 10px; }

/* ---------------------------------------------------------------- setup checklist
   Numbered steps that tick themselves off (SEO scans page). */
.steps { margin: 0; padding-left: 22px; }
.steps > li { margin-bottom: 12px; }
.steps > li.done > strong { color: var(--good-ink); }
.steps .pill { margin-left: 6px; }

/* ---------------------------------------------------------------- upsell websites
   Header button beside the title; the pick list and "or type it" box stack. */
.pagehead-actions { flex-shrink: 0; }
.datatable select { max-width: 100%; }
.datatable select + input[type="text"] { display: block; margin-top: 6px; width: 100%; max-width: 360px; }
#seo-chat-message { width: 100%; font-size: 12px; }

/* ---------------------------------------------------------------- SEO for this account
   A tick or a cross in front of each condition, worked out live. */
.seo-checks { list-style: none; margin: 0 0 12px; padding: 0; }
.seo-checks > li { position: relative; padding: 4px 0 4px 26px; }
.seo-checks > li::before { position: absolute; left: 0; top: 3px; width: 18px; height: 18px;
  border-radius: 50%; text-align: center; font-size: 12px; line-height: 18px; font-weight: 700; }
.seo-checks > li.ok::before { content: "\2713"; background: var(--good-tint); color: var(--good); }
.seo-checks > li.no::before { content: "\2715"; background: var(--bad-tint); color: var(--bad); }
.seo-checks ul { margin: 4px 0 0; padding-left: 18px; }
#seo h3 { margin: 16px 0 6px; font-size: 14px; }

/* ---------------------------------------------------------------- SEO note on a report */
.seo-hint { border-left: 3px solid var(--warn); }
.seo-hint ul { margin: 6px 0 0; padding-left: 20px; }
.seo-hint li { margin-bottom: 8px; }
.seo-hint form.inline { margin-left: 6px; }

/* ---------------------------------------------------------------- SEO for customers */
.seo-health-line { margin: 4px 0 10px; }
.tiles.seo-health { margin-bottom: 14px; }
.seo-preview-note ul { margin: 6px 0 0; padding-left: 20px; }
.wording-table td:first-child { width: 32%; }
.wording-table textarea { width: 100%; min-height: 56px; }

/* ---------------------------------------------------------------- support requests
   Replies and internal notes sit under the message, indented; the update form
   folds away so the inbox stays a list. */
.replies { list-style: none; margin: 8px 0 0 14px; padding: 0 0 0 12px; border-left: 2px solid var(--rule); }
.reply { margin: 8px 0; }
.reply .message-body { margin-top: 2px; }
.update-request { margin-top: 8px; }
.update-request summary { cursor: pointer; color: var(--brand); font-size: 13px; }
.update-request form { margin-top: 8px; max-width: 640px; }


/* ---------------------------------------------------------------- organic search (Search Console)
   The two sections reuse the bars, share rows and report tables above. A second
   exhibit inside one section needs air above it, and the team's own notes sit
   apart from what the customer reads. */
.organic-part { margin-top: 16px; }
.block-organic_summary .footnote,
.block-organic_pages .footnote { margin-top: 8px; }
.team-notes {
  margin: 0 0 12px;
  padding: 8px 12px;
  border-left: 3px solid var(--warn);
  background: var(--warn-tint);
  border-radius: 4px;
}
.team-notes p.tiny { margin: 0 0 4px; color: var(--body); }
.team-notes p.tiny:last-child { margin-bottom: 0; }
#brand-terms textarea { max-width: 420px; }


/* ---------------------------------------------------------------- figures typed in from Semrush
   The "Figures from Semrush" panel on a period's Data page: what is saved for
   each of the two Semrush reports, the form to type or replace it, and its
   history. Then the two report sections built from those figures. */
.typed-kind { border-top: 1px solid var(--rule); margin-top: 16px; padding-top: 14px; }
.typed-kind > h3 { margin-bottom: 8px; }
.typed-saved { margin-bottom: 6px; }
.typed-table { max-width: 760px; margin-bottom: 6px; }
.typed-form { max-width: 820px; margin-top: 12px; }
/* Same :not() chain as the global input rule, so this outranks it: a box in a
   table row or a field row needs no bottom gap of its own. */
.typed-form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"]):not([type="hidden"]),
.typed-form select { margin-bottom: 0; }
.typed-form .datatable { margin: 8px 0 12px; }
.typed-form .datatable td { vertical-align: middle; }
.typed-form .datatable th .hint { font-weight: 400; }
.typed-form .field-row { margin-bottom: 12px; }
.typed-form .field-row > div { flex: 0 1 220px; }
.typed-form .field-row > .typed-wide { flex: 1 1 300px; }
.typed-form input[type="file"] { display: block; font-size: 12.5px; margin-bottom: 6px; }
.typed-form .check { margin: 4px 0 0; }
/* The box a refusal is about. The :not() chain again, to outrank the global rule. */
.typed-form input.typed-bad:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"]):not([type="hidden"]),
.typed-form select.typed-bad { border-color: var(--bad); background: var(--bad-tint); }
.typed-form input[type="file"].typed-bad { color: var(--bad); }
.typed-form > .hint { display: block; margin-bottom: 10px; }
.typed-errors { margin: 4px 0 0; padding-left: 18px; }
.typed-errors li { margin-bottom: 2px; }
details.typed-replace { margin-top: 8px; }
details.typed-replace > summary { list-style: none; }
details.typed-replace > summary::-webkit-details-marker { display: none; }
.typed-remove { margin-top: 8px; font-size: 12.5px; }

/* In the report. The team's line about who typed the figures never prints
   and is not in a customer's copy at all. */
.typed-staff {
  margin: 0 0 12px;
  padding: 8px 12px;
  border-left: 3px solid var(--brand-light);
  background: var(--brand-tint);
  border-radius: 4px;
}
.typed-staff p.tiny { margin: 0 0 4px; color: var(--body); }
.typed-staff p.tiny:last-child { margin-bottom: 0; }
.typed-staff p.tiny.warn { color: var(--warn); }
.typed-tiles { margin-bottom: 12px; }
.typed-part { margin-top: 16px; }

/* Semrush's three groups as one bar. The key underneath repeats it in words
   and numbers, so the colours are never the only signal. */
.toxbar {
  display: flex;
  height: 14px;
  margin: 6px 0 9px;
  background: var(--rule);
  border-radius: 2px;
  overflow: hidden;
}
.toxbar > i { display: block; height: 100%; }
.toxbar > i.risky, .toxkey-swatch.risky { background: var(--bad); }
.toxbar > i.maybe, .toxkey-swatch.maybe { background: var(--accent); }
.toxbar > i.clear, .toxkey-swatch.clear { background: var(--brand-light); }
.toxkey { margin: 0 0 4px; }
.toxkey-row {
  display: grid;
  grid-template-columns: 11px minmax(0, 1fr) 4.5em 4.5em;
  align-items: center;
  gap: 9px;
  margin-bottom: 5px;
}
.toxkey-swatch { display: block; width: 11px; height: 11px; border-radius: 2px; }
.toxkey-name { font-size: var(--fs-sub); color: var(--ink); }
.toxkey-count {
  font-size: var(--fs-sub);
  font-weight: 700;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
}
.toxkey-share { font-size: var(--fs-small); color: var(--muted); text-align: right; white-space: nowrap; }
.semrush-own { font-size: var(--fs-prose); color: var(--body); margin: 10px 0 0; }
.semrush-score { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 14px 0 4px; }
.semrush-score-label { font-size: var(--fs-sub); font-weight: 700; color: var(--ink); }
.semrush-score-value { font-size: var(--fs-tile); font-weight: 700; line-height: 1.1; color: var(--ink); }
.semrush-score-date { font-size: var(--fs-small); color: var(--muted); }

/* The account page: everything about one customer (Tim, 10/14). */
.hub-nav { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 0 0 14px; font-size: 13px; }
.hub-tiles a.tile { color: inherit; text-decoration: none; }
.hub-tiles a.tile:hover { border-color: var(--brand-pale); }
.hub-grid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 0 16px; }
.hub-list { list-style: none; padding: 0; margin: 0 0 10px; }
.hub-list > li { padding: 7px 0; border-bottom: 1px solid var(--rule-soft); }
.hub-list > li:last-child { border-bottom: 0; }
@media (max-width: 900px) {
  .hub-grid { grid-template-columns: minmax(0, 1fr); }
  .hub-tiles { --tile-cols: 2 !important; }
}
.template-pick { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 4px 0 8px; }
.template-pick select { width: auto; max-width: 320px; margin-bottom: 0; padding-top: 3px; padding-bottom: 3px; }
.template-pick label { margin: 0; }
tr.row-muted td { color: var(--muted); }

