/* Generated from tokens.json by src/generate-tokens.ts. Do not edit; regenerate with `pnpm --filter @st/design run generate`. */
:root {
  color-scheme: light dark;
  --paper: #f6f3ed;
  --paper-raised: #fffdf9;
  --paper-sunk: #eee8dd;
  --rule: #e2dacc;
  --rule-strong: #8f8477;
  --ink: #17140f;
  --ink-2: #48423b;
  --ink-3: #6b6258;
  --on-ink: #fffdf9;
  --heather: #f2e3ec;
  --heather-ink: #7d3a65;
  --focus: var(--heather-ink);
  --link: var(--ink);
  --pass-text: #145a3a;
  --pass-tint: #dcebe0;
  --pass-border: #2f7a55;
  --fail-text: #9e1b30;
  --fail-tint: #f7dfe1;
  --fail-border: #b4233a;
  --caution-text: #7a4e00;
  --caution-tint: #f5e9c9;
  --caution-border: #a06a0a;
  --blocked-text: #8a3a10;
  --blocked-tint: #f8e2d4;
  --blocked-border: #b5541f;
  --agent-text: #3f4c63;
  --agent-tint: #e3e8ef;
  --agent-border: #5b6b85;
  --ungraded-text: #5e574e;
  --ungraded-tint: #efeae1;
  --ungraded-border: #8f8578;
  --info-text: #1c4f8a;
  --info-tint: #e0eaf5;
  --info-border: #2e66a8;
  --bar-muted: #cfc4b2;
  --shadow-panel: 0 32px 64px -32px rgba(52, 38, 22, 0.28), 0 2px 6px rgba(52, 38, 22, 0.06);
  --shadow-button: 0 1px 0 rgba(23, 20, 15, 0.3), 0 6px 16px -8px rgba(23, 20, 15, 0.45);
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 18px;
  --radius-pill: 999px;
  --font-display: "Source Serif 4", "Iowan Old Style", Georgia, serif;
  --font-sans: "Schibsted Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
@media screen and (prefers-color-scheme: dark) {
  :root {
    --paper: #14120f;
    --paper-raised: #1d1a16;
    --paper-sunk: #27231e;
    --rule: #38312a;
    --rule-strong: #7a7064;
    --ink: #f2ece2;
    --ink-2: #cbc1b3;
    --ink-3: #a59b8e;
    --on-ink: #17140f;
    --heather: #3a2633;
    --heather-ink: #e7afcf;
    --pass-text: #8fd3ae;
    --pass-tint: #16301f;
    --pass-border: #4fa57a;
    --fail-text: #f2a3ae;
    --fail-tint: #3a1a1f;
    --fail-border: #d9586c;
    --caution-text: #e9c16f;
    --caution-tint: #352812;
    --caution-border: #c28f2a;
    --blocked-text: #f0ae86;
    --blocked-tint: #3a2216;
    --blocked-border: #cf7a45;
    --agent-text: #b7c3d8;
    --agent-tint: #222833;
    --agent-border: #7f8da6;
    --ungraded-text: #b5ab9e;
    --ungraded-tint: #24201b;
    --ungraded-border: #7d7468;
    --info-text: #9dc1ee;
    --info-tint: #172638;
    --info-border: #5b8dcb;
    --bar-muted: #4a4239;
    --shadow-panel: 0 32px 64px -32px rgba(0, 0, 0, 0.75), 0 2px 6px rgba(0, 0, 0, 0.4);
    --shadow-button: 0 1px 0 rgba(0, 0, 0, 0.5), 0 6px 16px -8px rgba(0, 0, 0, 0.7);
  }
}
@media print {
  :root {
    color-scheme: light;
  }
}
@font-face {
  font-family: "Source Serif 4";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url(/assets/fonts/source-serif-4-latin-opsz-normal.f2ea9c12.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: 200 900;
  font-display: swap;
  src: url(/assets/fonts/source-serif-4-latin-ext-opsz-normal.155f6e70.woff2) format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C4,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Source Serif 4";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/source-serif-4-latin-400-italic.882b7c15.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;
  font-display: swap;
  src: url(/assets/fonts/source-serif-4-latin-ext-400-italic.d0625311.woff2) format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C4,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url(/assets/fonts/schibsted-grotesk-latin-wght-normal.4c8b93f4.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: "Schibsted Grotesk";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url(/assets/fonts/schibsted-grotesk-latin-ext-wght-normal.ee9eeb23.woff2) format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/schibsted-grotesk-latin-400-italic.b10306ed.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: "Schibsted Grotesk";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/schibsted-grotesk-latin-ext-400-italic.8e7de7bb.woff2) format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/ibm-plex-mono-latin-400-normal.08949f72.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(/assets/fonts/ibm-plex-mono-latin-ext-400-normal.6bc0f226.woff2) format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/assets/fonts/ibm-plex-mono-latin-500-normal.01d28544.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: 500;
  font-display: swap;
  src: url(/assets/fonts/ibm-plex-mono-latin-ext-500-normal.6bb06407.woff2) format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
/* Element-level foundation for every SendTilly page. Colours, fonts and spacing come from the token stylesheet that precedes this file. No component classes and no motion here. */

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 16px / 26px var(--font-sans);
  overflow-wrap: anywhere;
  -webkit-font-smoothing: antialiased;
}

/* The page hook on `<body class="st-root">` of /bot and every share page. */
.st-root {
  color: var(--ink);
  background: var(--paper);
  font: 400 16px / 26px var(--font-sans);
}

a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

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

code,
pre,
kbd,
samp {
  font-family: var(--font-mono);
}

.st-mono {
  font-family: var(--font-mono);
}

.st-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
/* Component rules for the SendTilly design system: the type helpers and the pieces the pages built on this package use. Every selector starts with .st-. Colours come only from var(--...) tokens. No motion and no case changes. */

/* Type helpers: each one equals the matching tokens.json type style. */
.st-display-xl {
  font: 400 64px / 68px var(--font-display);
  letter-spacing: -0.02em;
  font-optical-sizing: auto;
  text-wrap: balance;
  margin: 0;
}

.st-display-l {
  font: 400 44px / 50px var(--font-display);
  letter-spacing: -0.015em;
  font-optical-sizing: auto;
  text-wrap: balance;
  margin: 0;
}

.st-display-m {
  font: 400 30px / 38px var(--font-display);
  letter-spacing: -0.01em;
  font-optical-sizing: auto;
  text-wrap: balance;
  margin: 0;
}

.st-display-s {
  font: 400 24px / 30px var(--font-display);
  font-optical-sizing: auto;
  text-wrap: balance;
  margin: 0;
}

.st-lead {
  font: 400 19px / 33px var(--font-sans);
  color: var(--ink-2);
  max-width: 31em;
}

.st-body {
  font: 400 16px / 26px var(--font-sans);
}

.st-body-strong {
  font: 600 16px / 26px var(--font-sans);
}

.st-small {
  font: 400 14px / 22px var(--font-sans);
}

.st-eyebrow-text {
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.12em;
}

.st-data {
  font: 400 14px / 22px var(--font-mono);
}

.st-data-s {
  font: 400 12px / 18px var(--font-mono);
}

.st-figure {
  font: 500 26px / 32px var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.st-figure-l {
  font: 500 38px / 40px var(--font-mono);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

/* Wordmark: plain text, never a link on its own. */
.st-wordmark {
  font: 500 23px / 1 var(--font-display);
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
}

.st-wordmark em {
  font-style: italic;
  font-weight: 400;
  color: var(--heather-ink);
}

/* Page column: at least a 16 px gutter on phones, a wider one from 760 px. */
.st-page {
  width: 100%;
  max-width: 760px;
  margin-inline: auto;
  padding-inline: var(--space-4);
}

@media (min-width: 760px) {
  .st-page {
    padding-inline: var(--space-6);
  }
}

/* Header bar: the wordmark beside the language navigation. */
.st-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-3);
  border-bottom: 1px solid var(--rule);
}

.st-bar nav a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  font: 400 14px / 22px var(--font-sans);
}

/* Vertical rhythm for running content. */
.st-flow {
  padding-bottom: var(--space-7);
}

.st-flow > h1 {
  margin: var(--space-7) 0 var(--space-5);
}

.st-flow section {
  margin-top: var(--space-7);
}

.st-flow h2 {
  margin: 0 0 var(--space-4);
}

.st-flow p,
.st-flow ul,
.st-flow pre {
  margin: 0 0 var(--space-4);
}

.st-flow ul {
  padding-left: var(--space-5);
}

.st-flow li + li {
  margin-top: var(--space-2);
}

/* Panel: the framed object. It does not clip, so long values wrap instead of being cut. */
.st-panel {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
  margin-bottom: var(--space-4);
}

/* Definition rows. */
.st-defs {
  margin: 0;
  padding: var(--space-4) var(--space-5);
}

.st-defs dt {
  font: 600 16px / 26px var(--font-sans);
}

.st-defs dd {
  margin: var(--space-1) 0 0;
}

.st-defs dd + dt {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--rule);
}

.st-defs .st-mono {
  font: 400 14px / 22px var(--font-mono);
  overflow-wrap: break-word;
}

/* Code box: a focusable scroller, so its boundary is a 3:1 rule. */
.st-code {
  padding: var(--space-4);
  background: var(--paper-sunk);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-md);
  font: 400 14px / 22px var(--font-mono);
  overflow-x: auto;
}

.st-code code {
  font: inherit;
}

.st-muted {
  color: var(--ink-2);
}

/* Icon: an inline SVG drawn from the page's sprite with <use>. Without a size an SVG fills 300 by 150, so the base size is set here; where an icon sits beside smaller or larger text, its container sets the size. */
.st-icon {
  width: 16px;
  height: 16px;
  flex: none;
}

.st-chip .st-icon {
  width: 12px;
  height: 12px;
}

.st-tag .st-icon {
  width: 14px;
  height: 14px;
}

.st-box__title .st-icon {
  width: 18px;
  height: 18px;
}

/* Chip: a small mono label on sunk paper. The family variant arrives with the status component. */
.st-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: 24px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-xs);
  background: var(--paper-sunk);
  color: var(--ink-2);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.08em;
  white-space: nowrap;
  overflow-wrap: normal;
  word-break: normal;
}

/* Callout: a note set apart from the running text. */
.st-callout {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-md);
  font: 400 16px / 26px var(--font-sans);
}

.st-callout--note {
  border: 1px dashed var(--rule-strong);
  background: var(--paper-raised);
  color: var(--ink);
}

/* Box: a framed group on raised paper. It may shrink inside a grid track, so long values wrap. */
.st-box {
  display: grid;
  gap: var(--space-4);
  align-content: start;
  min-width: 0;
  padding: var(--space-5);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
}

.st-box__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.st-box__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font: 600 16px / 26px var(--font-sans);
}

/* Tag: one retailer or mode label. A name of any length wraps instead of widening the page. */
.st-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: 24px;
  max-width: 100%;
  margin: 0;
  padding: 3px var(--space-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius-xs);
  color: var(--ink-2);
  font: 500 12px / 16px var(--font-mono);
  overflow-wrap: anywhere;
}

.st-tag--strong {
  border-color: var(--ink);
}

.st-tag--soft {
  background: var(--paper-sunk);
}

/* Eyebrow: a mono label that may open with a number on an ink tile. */
.st-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.12em;
  color: var(--ink-2);
}

.st-eyebrow__num {
  display: inline-grid;
  place-items: center;
  min-width: 32px;
  min-height: 24px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--ink);
  color: var(--on-ink);
  letter-spacing: 0.04em;
}

/* Subhead: a quiet mono caption over a group. */
.st-subhead {
  margin: 0 0 var(--space-3);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.12em;
  color: var(--ink-3);
}

/* Question: the shopper's question, set in a thin ink frame. */
.st-question {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--ink);
  border-radius: var(--radius-md);
}

.st-question .st-icon {
  width: 18px;
  height: 18px;
}

/* Status badge: a glyph, a label and a family colour always travel together, so a verdict is never told by colour alone. The base rule holds the ungraded triple, so a badge without a family still has text, tint and border; the family rules below replace the triple. */
.st-status {
  --st-t: var(--ungraded-text);
  --st-bg: var(--ungraded-tint);
  --st-b: var(--ungraded-border);
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  box-sizing: border-box;
  height: 24px;
  padding: 0 var(--space-3) 0 var(--space-2);
  border: 1px solid var(--st-b);
  border-radius: var(--radius-pill);
  background: var(--st-bg);
  color: var(--st-t);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow-wrap: normal;
  word-break: normal;
}

.st-status--lg {
  height: 32px;
  gap: var(--space-2);
  padding: 0 var(--space-4) 0 var(--space-3);
  font: 500 14px / 16px var(--font-mono);
}

.st-status--sm {
  height: 20px;
  padding: 0 var(--space-2);
}

/* The line is the second cue in greyscale and in print: dashed for the agent and ungraded states. */
.st-status[data-line="dashed"] {
  border-style: dashed;
}

.st-glyph {
  flex: none;
  width: 12px;
  height: 12px;
}

.st-status--lg .st-glyph {
  width: 14px;
  height: 14px;
}

.st-status__label {
  min-width: 0;
  overflow-wrap: normal;
  word-break: normal;
}

/* Status families. A family reaches a status part only through the part's own class and its data-family attribute, as the text, tint and border of one variable triple; the part's rule reads the three. Agent and ungraded parts also carry data-line="dashed" where they draw a border, so they stay apart from a store failure without colour. */
.st-status[data-family="pass"],
.st-cell[data-family="pass"],
.st-chip[data-family="pass"],
.st-fault[data-family="pass"],
.st-stat[data-family="pass"],
.st-cause[data-family="pass"],
.st-stackbar__seg[data-family="pass"],
.st-legend__item[data-family="pass"] {
  --st-t: var(--pass-text);
  --st-bg: var(--pass-tint);
  --st-b: var(--pass-border);
}

.st-status[data-family="fail"],
.st-cell[data-family="fail"],
.st-chip[data-family="fail"],
.st-fault[data-family="fail"],
.st-stat[data-family="fail"],
.st-cause[data-family="fail"],
.st-stackbar__seg[data-family="fail"],
.st-legend__item[data-family="fail"] {
  --st-t: var(--fail-text);
  --st-bg: var(--fail-tint);
  --st-b: var(--fail-border);
}

.st-status[data-family="caution"],
.st-cell[data-family="caution"],
.st-chip[data-family="caution"],
.st-fault[data-family="caution"],
.st-stat[data-family="caution"],
.st-cause[data-family="caution"],
.st-stackbar__seg[data-family="caution"],
.st-legend__item[data-family="caution"] {
  --st-t: var(--caution-text);
  --st-bg: var(--caution-tint);
  --st-b: var(--caution-border);
}

.st-status[data-family="blocked"],
.st-cell[data-family="blocked"],
.st-chip[data-family="blocked"],
.st-fault[data-family="blocked"],
.st-stat[data-family="blocked"],
.st-cause[data-family="blocked"],
.st-stackbar__seg[data-family="blocked"],
.st-legend__item[data-family="blocked"] {
  --st-t: var(--blocked-text);
  --st-bg: var(--blocked-tint);
  --st-b: var(--blocked-border);
}

.st-status[data-family="agent"],
.st-cell[data-family="agent"],
.st-chip[data-family="agent"],
.st-fault[data-family="agent"],
.st-stat[data-family="agent"],
.st-cause[data-family="agent"],
.st-stackbar__seg[data-family="agent"],
.st-legend__item[data-family="agent"] {
  --st-t: var(--agent-text);
  --st-bg: var(--agent-tint);
  --st-b: var(--agent-border);
}

.st-status[data-family="ungraded"],
.st-cell[data-family="ungraded"],
.st-chip[data-family="ungraded"],
.st-fault[data-family="ungraded"],
.st-stat[data-family="ungraded"],
.st-cause[data-family="ungraded"],
.st-stackbar__seg[data-family="ungraded"],
.st-legend__item[data-family="ungraded"] {
  --st-t: var(--ungraded-text);
  --st-bg: var(--ungraded-tint);
  --st-b: var(--ungraded-border);
}

.st-status[data-family="info"],
.st-cell[data-family="info"],
.st-chip[data-family="info"],
.st-fault[data-family="info"],
.st-stat[data-family="info"],
.st-cause[data-family="info"],
.st-stackbar__seg[data-family="info"],
.st-legend__item[data-family="info"] {
  --st-t: var(--info-text);
  --st-bg: var(--info-tint);
  --st-b: var(--info-border);
}

/* Results cell: one verdict of one mission. The glyph, the label and the family colour travel together, so the verdict is never told by colour alone. The note, when there is one, sits under the label in the family text colour (never the quiet ink on a tint). The base rule holds the ungraded triple; the family rules above replace it. A link cell and a plain cell look the same. */
.st-cell {
  --st-t: var(--ungraded-text);
  --st-bg: var(--ungraded-tint);
  --st-b: var(--ungraded-border);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: var(--space-2);
  box-sizing: border-box;
  min-height: 32px;
  min-width: min-content;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-xs);
  overflow-wrap: normal;
  word-break: normal;
  background: var(--st-bg);
  box-shadow: inset 0 0 0 1px var(--st-b);
  color: var(--st-t);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.05em;
  text-decoration: none;
}

/* The dashed line stands in for the inset border on the agent and ungraded states, as it does on the badge. */
.st-cell[data-line="dashed"] {
  box-shadow: none;
  outline: 1px dashed var(--st-b);
  outline-offset: -1px;
}

.st-cell__label {
  grid-column: 2;
  min-width: 0;
  overflow-wrap: normal;
  word-break: normal;
  white-space: nowrap;
}

.st-cell__note {
  grid-column: 2;
  min-width: 0;
  font: 400 12px / 16px var(--font-mono);
  letter-spacing: 0;
  color: var(--st-t);
  overflow-wrap: anywhere;
}

/* A product and store pair nobody selected: a quiet dash on the page, with no tint, line or label. */
.st-cell--none {
  display: flex;
  justify-content: center;
  background: none;
  box-shadow: none;
  color: var(--ink-3);
}

/* The store name above a cell. It is shown only where the head row is not (a phone); report.css hides it from 720 px. */
.st-cell__store {
  display: block;
  margin-bottom: var(--space-1);
  font: 400 12px / 16px var(--font-mono);
  color: var(--ink-3);
  overflow-wrap: anywhere;
}

/* Fault marker: whose fault a failure is, in mono words after a filled square in the family border colour. The family rules above set the text and border colours; the words carry the meaning, the square only marks where they start. */
.st-fault {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.08em;
  color: var(--st-t);
  white-space: nowrap;
}

.st-fault::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  background: var(--st-b);
}

/* Stat pairs: a quiet mono label over a value in words, one pair under another, each under a rule but the first. Only the words of a pair that carries a family take its text colour; the label and the rule stay neutral, so the meaning never rests on colour. */
.st-stats {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  margin: 0;
}

.st-stat {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--rule);
}

.st-stat:first-child {
  padding-top: 0;
  border-top: 0;
}

/* biome-ignore lint/style/noDescendingSpecificity: a stat's label never sits in the definition list of .st-defs */
.st-stat dt {
  margin: 0;
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.1em;
  color: var(--ink-3);
}

.st-stat dd {
  margin: 0;
  font: 400 16px / 26px var(--font-sans);
  color: var(--ink);
  overflow-wrap: break-word;
}

.st-stat[data-family] dd {
  color: var(--st-t);
}

/* Evidence container and its views: the views of the modes follow each other, each under its own title. Once the script builds tabs it hides all but one. */
.st-ev {
  display: grid;
  gap: var(--space-6);
  min-width: 0;
}

.st-view {
  display: grid;
  gap: var(--space-4);
  min-width: 0;
}

.st-view[hidden] {
  display: none;
}

.st-view__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.12em;
}

/* Compare: two sides of one comparison on raised paper behind a 1px rule, one column until the page gives it room (report.css switches it to two). Each side has a head band, then its rows; the quote rows span the foot. A differing row is tinted and its words differ too, so a difference never rests on colour (D-21). */
.st-compare {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.st-compare__side {
  min-width: 0;
}

.st-compare__side + .st-compare__side {
  border-top: 1px solid var(--rule);
}

.st-compare__side dl {
  margin: 0;
}

.st-compare__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}

.st-compare__head > div {
  display: grid;
  min-width: 0;
}

.st-compare__head b {
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.08em;
  color: var(--ink-3);
}

.st-compare__head span:not(.st-tile) {
  font: 400 14px / 20px var(--font-sans);
  color: var(--ink);
}

/* The not-equal mark sits on the seam of the head bands, only when the compare has two columns. */
.st-compare__ne {
  display: none;
  position: absolute;
  top: calc(var(--space-3) + 4px);
  left: 50%;
  width: 28px;
  height: 28px;
  place-items: center;
  transform: translateX(-50%);
  background: var(--ink);
  color: var(--on-ink);
  border-radius: var(--radius-pill);
}

.st-compare__ne .st-icon {
  width: 14px;
  height: 14px;
}

.st-compare__quote {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-1);
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--rule);
  font: 400 14px / 22px var(--font-sans);
  color: var(--ink-2);
}

.st-compare__quote q {
  font: 400 14px / 22px var(--font-mono);
  color: var(--ink);
  overflow-wrap: break-word;
}

/* A row: the label quiet at the left, the value in mono at the right. A tinted row takes the text and tint of its meaning and its label follows, so no quiet label sits on a tint. */
.st-field {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  color: var(--ink);
}

.st-field + .st-field {
  border-top: 1px solid var(--rule);
}

/* biome-ignore lint/style/noDescendingSpecificity: a field's label never sits in the definition list of .st-defs */
.st-field dt {
  flex: none;
  margin: 0;
  font: 400 12px / 16px var(--font-mono);
  letter-spacing: 0.08em;
  color: var(--ink-3);
}

/* biome-ignore lint/style/noDescendingSpecificity: a field's value never sits in a stat pair */
.st-field dd {
  min-width: 0;
  margin: 0;
  font: 500 14px / 22px var(--font-mono);
  text-align: right;
  overflow-wrap: break-word;
}

.st-field[data-diff="miss"] {
  background: var(--fail-tint);
  color: var(--fail-text);
}

.st-field[data-diff="truth"] {
  background: var(--pass-tint);
  color: var(--pass-text);
}

.st-field[data-diff="gap"] {
  background: var(--caution-tint);
  color: var(--caution-text);
}

.st-field[data-diff="miss"] dt,
.st-field[data-diff="truth"] dt,
.st-field[data-diff="gap"] dt {
  color: inherit;
}

/* Monogram tile: two letters on a 28px square. Heather marks the first vendor, info blue the second, pass green the store's own page, and a quiet ghost a mode or a request. */
.st-tile {
  display: grid;
  flex: none;
  place-items: center;
  width: 28px;
  height: 28px;
  background: var(--paper-sunk);
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.02em;
}

.st-tile--a {
  background: var(--heather);
  color: var(--heather-ink);
}

.st-tile--b {
  background: var(--info-tint);
  color: var(--info-text);
}

.st-tile--truth {
  background: var(--pass-tint);
  color: var(--pass-text);
}

.st-tile--ghost {
  background: var(--paper-sunk);
  box-shadow: inset 0 0 0 1px var(--rule-strong);
  color: var(--ink-2);
}

/* The product page address: selectable text under a quiet label, never a link. One click selects all of it, which is the copy fallback without the script. */
.st-address {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-1);
  min-width: 0;
  padding: var(--space-3) var(--space-4);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  font: 400 14px / 22px var(--font-mono);
  overflow-wrap: break-word;
}

.st-address .st-mono {
  user-select: all;
}

/* The row of copy controls the script builds. Without the script the hook is empty and takes no room. */
.st-view__tools {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.st-view__tools:empty {
  display: none;
}

/* Tabs: the script turns the views of an evidence container into one tablist. The strip sits on paper with a rule under it and scrolls sideways inside itself on a narrow screen. A tab is 40px tall; the selected one is ink with a 2px ink rule under it. Without the script none of this exists and every view shows under its title. */
.st-tabs {
  display: flex;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-4);
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  overflow-x: auto;
}

.st-tab {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: var(--space-2);
  height: 40px;
  margin: 0;
  padding: 0 var(--space-3);
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--ink-2);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.08em;
  white-space: nowrap;
  cursor: pointer;
}

.st-tab[aria-selected="true"] {
  border-bottom-color: var(--ink);
  color: var(--ink);
}

/* Once the tab carries the title, the title stays for screen readers and print only. */
.st-ev.is-tabbed {
  gap: var(--space-5);
}

.st-ev.is-tabbed .st-view__title {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Buttons: 40px, a 1px rule, the small radius, mono 12 w500. The quiet one has no fill; the small one is 32px, for a row of controls above a panel. */
.st-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: 40px;
  margin: 0;
  padding: 0 var(--space-4);
  background: var(--paper-raised);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.08em;
  white-space: nowrap;
  cursor: pointer;
}

.st-btn--quiet {
  background: transparent;
  border-color: var(--rule);
  color: var(--ink-2);
}

.st-btn--sm {
  height: 32px;
  padding: 0 var(--space-3);
}

/* The screenshot of a finding: a framed figure on raised paper, the picture over one caption line (the kind of moment on the left, the full-size link on the right). The caps on the picture sit in report.css. */
.st-shot {
  margin: var(--space-4) 0;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.st-shot figcaption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-3);
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--rule);
}

.st-evidence__kind {
  font: 500 12px / 16px var(--font-mono);
  color: var(--ink-3);
}

.st-shot__open {
  font: 500 12px / 16px var(--font-mono);
}

.st-foot {
  padding-block: var(--space-5);
  border-top: 1px solid var(--rule);
  font: 400 14px / 22px var(--font-sans);
  color: var(--ink-2);
}
/* Report layout, timeline and print rules on `st-` classes, served last in the design stylesheet. Colours, fonts and spacing come from the token stylesheet that precedes this file; no colour literal and no motion here. Later plans append their rules below. */

/* The printed page: A4 with a 16 mm margin. Print always uses the light theme (tokens.css). */
@page {
  size: A4;
  margin: 16mm;
}

/* Anything that only makes sense on a screen (controls, the preview banner, the skip link, the script-added bar) is hidden in print. */
@media print {
  .st-no-print,
  .st-banner,
  .st-skip,
  .st-secnav,
  .st-hint {
    display: none;
  }
}

/* Page column of a report: wider than the shared 760 px column. The gutter stays the shared one. */
.st-page--report {
  max-width: 1120px;
}

/* Preview banner: a note above the topbar. The markup also carries .st-callout and .st-callout--note, which draw the dashed box, so only its place is set here. It is replaced by nothing on a shared page. */
.st-banner {
  margin: var(--space-3) var(--space-4);
}

/* Skip link: out of sight until it takes keyboard focus. */
.st-skip {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.12em;
}

.st-skip:focus {
  top: var(--space-2);
  left: var(--space-2);
  z-index: 20;
  width: auto;
  height: auto;
  overflow: visible;
  clip: auto;
  padding: var(--space-2) var(--space-3);
  background: var(--paper-raised);
  border: 1px solid var(--rule-strong);
  color: var(--ink);
}

/* Save hint: one quiet line above the topbar. */
.st-note {
  margin-block: 0;
  padding-block: var(--space-2);
  font: 400 12px / 18px var(--font-mono);
  color: var(--ink-3);
}

/* Topbar: the wordmark, the private chip and, on a shared page, the expiry note pushed to the right. */
.st-topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding-block: var(--space-3);
  border-bottom: 1px solid var(--rule);
}

.st-topbar__note {
  margin: 0 0 0 auto;
  font: 400 12px / 18px var(--font-mono);
  color: var(--ink-3);
}

/* Hero: eyebrow, store name and the facts. The single track may shrink, so a long name wraps. */
.st-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  padding-block: var(--space-8);
}

.st-hero__eyebrow {
  margin: 0;
  color: var(--ink-3);
}

/* On paper the hero keeps all it shows and gives back the screen's top and bottom room, so the first printed page holds more than the hero (PR-09). */
@media print {
  .st-hero {
    padding-block: var(--space-5);
  }
}

@media (width < 560px) {
  .st-hero .st-display-l {
    font: 400 30px / 38px var(--font-display);
  }
}

/* Facts: an auto-fit grid between two rules. Each fact is a label over its value. */
.st-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(208px, 1fr));
  gap: var(--space-4);
  margin: 0;
  padding-block: var(--space-4);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.st-facts > div {
  display: grid;
  align-content: start;
  gap: var(--space-1);
  min-width: 0;
}

.st-facts dt {
  margin: 0;
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.12em;
  color: var(--ink-3);
}

.st-facts dd {
  margin: 0;
  font: 400 16px / 26px var(--font-sans);
}

@media (min-width: 860px) {
  .st-facts__q {
    grid-column: span 2;
  }
}

/* Report footer: a rule, then two quiet lines. */
.st-foot--report {
  padding-block: var(--space-6) var(--space-7);
  border-top: 1px solid var(--rule);
  font: 400 14px / 22px var(--font-sans);
  color: var(--ink-2);
}

.st-foot--report p {
  margin: 0 0 var(--space-2);
}

/* Section nav: six static anchors in one row. The nav sits inside main, which already holds the page column, so the column width and the gutters it also carries are switched off here. */
.st-secnav.st-page {
  max-width: none;
  padding-inline: 0;
}

/* The list scrolls sideways inside the nav on narrow screens; the links stay focusable, so the scroller can be reached by keyboard. The box is exactly as tall as the links and would cut their focus ring (2 px offset plus the 2 px line), so the padding gives the ring its room and the equal negative margin takes it back: the bar keeps its size and its layout. */
.st-secnav ul {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-2);
  margin: calc(-1 * var(--space-1));
  padding: var(--space-1);
  list-style: none;
  overflow-x: auto;
}

.st-secnav li {
  flex: none;
  margin: 0;
}

.st-secnav a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: var(--space-3) var(--space-2);
  border-bottom: 2px solid transparent;
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.1em;
  color: var(--ink-3);
  text-decoration: none;
  white-space: nowrap;
}

.st-secnav a:hover {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

/* Focus under the sticky nav (WCAG 2.2 SC 2.4.11). A browser that scrolls a focused control only as far as needed (Firefox, Safari) would leave it under the sticky nav, so every control below the nav, and in the footer, keeps clear of it by the nav height plus a gap. The nav is 49 px tall. The nav's own links are not listed: they sit in the bar. The selectors begin with .st-, and the site's landing.css sets the same property later for the sample page, where a taller header sits above this nav. */
.st-root {
  --st-clear: calc(49px + var(--space-4));
}

.st-secnav ~ * a,
.st-secnav ~ * button,
.st-secnav ~ * input,
.st-secnav ~ * select,
.st-secnav ~ * textarea,
.st-secnav ~ * summary,
.st-secnav ~ * [tabindex],
.st-foot--report a {
  scroll-margin-top: var(--st-clear);
}

/* Sticky on screen only; print hides the nav above. */
@media screen {
  .st-secnav {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
  }
}

/* Section block: a head over the content, a rule between blocks. The first block sits under the nav's own rule and needs none. */
.st-block {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  padding-block: var(--space-7);
  border-top: 1px solid var(--rule);
  scroll-margin-top: 48px;
}

.st-secnav + .st-block {
  border-top: 0;
}

.st-block__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
}

.st-block__meta {
  font: 400 12px / 18px var(--font-mono);
  color: var(--ink-3);
}

/* What we checked: the terms of the equation, then the definitions, the filled question and the four steps. */
.st-equation {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-5);
}

.st-term {
  display: grid;
  flex: 1 1 200px;
  gap: var(--space-2);
  min-width: 0;
}

.st-term__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
}

.st-term__label {
  font: 400 16px / 22px var(--font-sans);
  color: var(--ink-2);
}

.st-op {
  flex: none;
  font: 400 30px / 38px var(--font-mono);
  color: var(--ink-3);
}

@media (width < 860px) {
  .st-op {
    display: none;
  }
}

.st-taglist {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.st-termdefs {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--rule);
}

.st-termdefs > div {
  display: grid;
  grid-template-columns: 136px minmax(0, 1fr);
  align-items: center;
  gap: var(--space-3);
  font: 400 14px / 22px var(--font-mono);
  color: var(--ink-2);
}

.st-termdefs dt {
  display: flex;
  margin: 0;
}

.st-termdefs dd {
  margin: 0;
}

@media (width < 560px) {
  .st-termdefs > div {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-1);
  }
}

/* The four steps: one column on a phone, two from 560 px, four from 860 px, each under a 2 px ink rule. */
.st-process {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

.st-process > li {
  display: grid;
  gap: var(--space-3);
  align-content: start;
  justify-items: start;
  margin: 0;
  padding-top: var(--space-4);
  border-top: 2px solid var(--ink);
}

.st-process p {
  margin: 0;
  font: 400 16px / 26px var(--font-sans);
  color: var(--ink-2);
}

@media (min-width: 560px) {
  .st-process {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 860px) {
  .st-process {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* The icon and glyph sprite: in the page, drawn nowhere, read by <use>. */
.st-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* Results at a glance: one box for each mode that ran, side by side when they fit. */
.st-modes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: var(--space-4);
}

.st-modes__sentence {
  margin: 0;
  color: var(--ink-2);
}

.st-modes__figure {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-3);
  margin: 0;
}

.st-modes__figure .st-body {
  color: var(--ink-2);
}

/* The stack bar is an SVG of numeric units, so its size comes from here: the full width of its box, 16 px high, and nothing drawn behind the segments (D-20: an ungraded segment never sits on sunk paper). A solid segment is filled with its family border and set off from the next by a 2 px stroke in the box colour. */
.st-stackbar {
  display: block;
  width: 100%;
  height: 16px;
}

.st-stackbar__seg {
  fill: var(--st-b);
  stroke: var(--paper-raised);
  stroke-width: 2px;
  vector-effect: non-scaling-stroke;
}

/* An agent or ungraded segment keeps its tint and a dashed border, so it stays apart from a store failure in greyscale. */
.st-stackbar__seg[data-line="dashed"] {
  fill: var(--st-bg);
  stroke: var(--st-b);
  stroke-dasharray: 3 2;
  stroke-width: 1px;
  vector-effect: non-scaling-stroke;
}

/* The legend is the accessible text of the bar: a glyph, a count and the label of each verdict present. */
.st-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font: 500 12px / 18px var(--font-mono);
}

.st-legend__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  color: var(--ink-2);
}

.st-legend__item svg {
  width: 12px;
  height: 12px;
  flex: none;
  color: var(--st-t);
}

.st-legend__item b {
  color: var(--ink);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.st-muted-lines {
  margin: 0;
  padding: 0;
  list-style: none;
  font: 400 14px / 22px var(--font-sans);
  color: var(--ink-2);
}

.st-muted-lines li {
  margin: 0;
}

/* What the labels mean: a badge and its meaning for each verdict present. One column on a phone, two columns of pairs from 860 px, each pair a 172 px badge column and the meaning. The old list margins on dl, dt and dd are cleared here. */
.st-legend-defs {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3) var(--space-6);
  margin: 0;
}

.st-legend-defs > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  align-items: start;
}

.st-legend-defs dt {
  margin: 0;
}

.st-legend-defs dd {
  margin: 0;
  font: 400 14px / 22px var(--font-sans);
  color: var(--ink-2);
}

@media (min-width: 860px) {
  .st-legend-defs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .st-legend-defs > div {
    grid-template-columns: 172px minmax(0, 1fr);
  }
}

/* Who the failures belong to: a cause is a figure under a caption, topped by a 3 px rule in its family colour (dashed for the agent). The caption starts with a marker square, filled for a fault of the site and hollow for the agent, so the two read apart without colour. */
.st-causes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 232px), 1fr));
  gap: var(--space-4);
}

.st-cause {
  display: grid;
  align-content: start;
  gap: var(--space-1);
  min-width: 0;
  padding-top: var(--space-3);
  border-top: 3px solid var(--st-b);
}

.st-cause[data-family="agent"] {
  border-top-style: dashed;
}

.st-cause p {
  margin: 0;
}

.st-cause__caption {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.12em;
  color: var(--st-t);
}

.st-cause__caption::before {
  content: "";
  flex: none;
  width: 10px;
  height: 10px;
  box-sizing: border-box;
  background: var(--st-b);
  border: 2px solid var(--st-b);
}

.st-cause[data-family="agent"] .st-cause__caption::before {
  background: none;
}

/* Method and limits: a ruled definition grid. The term sits beside its text from 860 px and over it below. */
.st-method {
  margin: 0;
  border-top: 1px solid var(--rule);
}

.st-method__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-1) var(--space-5);
  padding-block: var(--space-4);
  border-bottom: 1px solid var(--rule);
}

@media (min-width: 860px) {
  .st-method__row {
    grid-template-columns: 220px minmax(0, 1fr);
  }
}

.st-method dt {
  margin: 0;
  font: 500 12px / 22px var(--font-mono);
  letter-spacing: 0.08em;
  color: var(--ink-3);
}

.st-method dd {
  max-width: 46em;
  margin: 0;
  font: 400 16px / 26px var(--font-sans);
}

.st-method p {
  margin: 0 0 var(--space-2);
}

.st-method p:last-child {
  margin-bottom: 0;
}

.st-method ul {
  margin: 0;
  padding-left: var(--space-5);
}

.st-method li {
  margin: 0 0 var(--space-2);
}

/* A row and a legend item are not split across a printed page. A box is: the What we checked box and the access boxes can be taller than the room left on a page, and an unbreakable box is pushed whole to the next page (PR-01, PR-05). */
@media print {
  .st-method__row,
  .st-legend__item {
    break-inside: avoid;
  }

  .st-legend-defs > div {
    break-inside: avoid;
  }
}

/* Results by product and store: one framed panel that clips its own corners and sits flush with the line under it. The body padding is 24 px by 32 px, 16 px on a phone. */
.st-panel--framed {
  overflow: hidden;
  margin-bottom: 0;
}

.st-results {
  padding: var(--space-5) var(--space-6);
}

@media (width < 560px) {
  .st-results {
    padding: var(--space-4);
  }
}

.st-view__caption {
  margin: 0;
  color: var(--ink-2);
}

/* The table scrolls sideways inside its own focusable region and never widens the page. */
.st-grid-wrap {
  overflow-x: auto;
}

.st-grid {
  width: 100%;
  border-collapse: collapse;
  font: 400 14px / 22px var(--font-sans);
}

/* Column heads are typed capitals and store names as stored; a long name wraps. The first head and the row headers sit left, the count column sits right. */
.st-grid th {
  padding: 0 var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--rule);
  font: 500 12px / 16px var(--font-mono);
  letter-spacing: 0.1em;
  color: var(--ink-3);
  text-align: left;
  overflow-wrap: anywhere;
}

.st-grid thead th:last-child {
  text-align: right;
}

.st-grid th[scope="row"] {
  min-width: 160px;
  padding: var(--space-2) var(--space-3) var(--space-2) 0;
  border-bottom: 1px solid var(--rule);
  font: 500 16px / 24px var(--font-sans);
  letter-spacing: 0;
  color: var(--ink);
}

.st-grid__variant {
  display: block;
  font: 400 12px / 16px var(--font-mono);
  color: var(--ink-3);
}

.st-grid td {
  padding: var(--space-2) var(--space-1);
  border-bottom: 1px solid var(--rule);
  vertical-align: middle;
}

.st-grid .st-grid__score {
  padding-left: var(--space-3);
  font: 500 14px / 22px var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
}

/* A cell that links to its finding is outlined in ink while it is pointed at or marked by the script; the outline is the cue in greyscale. Keyboard focus keeps the global ring. */
.st-cell[href]:hover,
.st-cell.is-linked {
  outline: 2px solid var(--ink);
  outline-offset: 1px;
}

.st-cell[href]:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* The hint line under the panel keeps a line of room, so the active sentence never moves the page. */
.st-hint {
  margin: 0;
  min-height: 24px;
  font: 400 12px / 18px var(--font-mono);
  color: var(--ink-3);
}

/* The access table is a plain table at every width: its verdict cells stay on one line, so on a phone the region scrolls sideways and the page does not. Same specificity as the base rules above; the rules follow them. */
.st-grid--access thead th:last-child {
  text-align: left;
}

.st-grid--access td {
  padding: var(--space-2) var(--space-2) var(--space-2) 0;
  white-space: nowrap;
}

/* The matched cell is words with spaces ("own group, line 9"), so it may wrap at them, down to a width that keeps a phrase readable. */
.st-grid--access td:last-child {
  min-width: 120px;
  overflow-wrap: normal;
  white-space: normal;
}

/* The token over its vendor: the token in mono, the company quiet on its own line. */
.st-grid--access .st-mono {
  font: 500 14px / 22px var(--font-mono);
}

.st-grid--access .st-small {
  display: block;
  font: 400 12px / 16px var(--font-mono);
  color: var(--ink-3);
}

/* Below 720 px, and on paper at every width, the head row is visually hidden, each product is a block and each cell is preceded by its store name. The access table is left as a table. A print rule cannot lean on the width query alone: Chromium lays an A4 PDF out about 673 px wide while its media queries see about 794 px, so the phone reflow never applied to a printed copy and a wide grid squeezed a verdict word to a letter per line (D-19). */
@media (max-width: 719.98px), print {
  .st-grid:not(.st-grid--access) thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .st-grid:not(.st-grid--access),
  .st-grid:not(.st-grid--access) tbody,
  .st-grid:not(.st-grid--access) tr,
  .st-grid:not(.st-grid--access) th,
  .st-grid:not(.st-grid--access) td {
    display: block;
  }

  .st-grid:not(.st-grid--access) tr {
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--rule);
  }

  .st-grid:not(.st-grid--access) th[scope="row"] {
    min-width: 0;
    padding: 0 0 var(--space-2);
    border-bottom: 0;
  }

  .st-grid:not(.st-grid--access) td {
    padding: var(--space-1) 0;
    border-bottom: 0;
  }

  .st-grid:not(.st-grid--access) .st-grid__score {
    padding-left: 0;
    text-align: left;
  }
}

@media (min-width: 720px) {
  .st-cell__store {
    display: none;
  }
}

/* On paper the store name is shown above its cell at every width, after the rule above so it wins at the same specificity: a stacked verdict is never read as another store's. The cells of one product flow left to right as whole cells, the row header takes a full line and the score its own line. */
@media print {
  .st-cell__store {
    display: block;
  }

  .st-grid:not(.st-grid--access) tr {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--space-2) var(--space-3);
  }

  .st-grid:not(.st-grid--access) th[scope="row"],
  .st-grid:not(.st-grid--access) .st-grid__score {
    flex: 0 0 100%;
  }

  .st-grid:not(.st-grid--access) td {
    flex: 0 1 auto;
    max-width: 100%;
  }
}

/* A table row is not split across a printed page, and a view the script hid is shown in full. */
@media print {
  .st-grid tr {
    break-inside: avoid;
  }

  .st-view[hidden] {
    display: block;
  }
}

/* Access: the robots table and the declared-visit box side by side from 860 px, one under the other below. A lone box takes the whole row. */
.st-access {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
}

.st-access > .st-box:only-child {
  grid-column: 1 / -1;
}

@media (min-width: 860px) {
  .st-access {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  }
}

/* A definition list inside a box: the box pads, so the list does not pad twice. A long retailer word breaks instead of widening the box. */
.st-box > .st-defs {
  padding: 0;
}

.st-box > .st-defs dd {
  overflow-wrap: anywhere;
}

/* Findings: one framed card for each, in a grid. The card is a size container, so its three parts follow the card's own width and not the window's. A jump to a finding lands under the sticky nav and rings the card in the heather ink, the one place heather marks a place on this page. */
.st-block > .st-callout,
.st-block > .st-evidence__kind {
  margin: 0;
}

.st-findings {
  display: grid;
  gap: var(--space-6);
}

.st-finding {
  container-type: inline-size;
  scroll-margin-top: 64px;
}

.st-finding:target {
  box-shadow:
    var(--shadow-panel),
    0 0 0 2px var(--heather-ink);
}

/* Top row: the number, the status, the mode and the fault on the left; how many missions it affects on the right. */
.st-finding__top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-6) 0;
}

.st-finding__caption {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.st-finding__affects {
  display: grid;
  grid-template-columns: auto auto;
  align-items: baseline;
  justify-items: start;
  gap: var(--space-1) var(--space-3);
}

.st-finding__affects .st-eyebrow-text {
  grid-column: 1 / -1;
}

.st-finding__unit {
  max-width: 12em;
  font: 400 14px / 22px var(--font-sans);
  color: var(--ink-2);
}

.st-finding__main {
  display: grid;
  gap: var(--space-4);
  min-width: 0;
  padding: var(--space-4) var(--space-6) var(--space-5);
}

@media (width < 560px) {
  .st-finding__main .st-display-m {
    font: 400 24px / 30px var(--font-display);
  }
}

/* Agreement: the tag that says which vendors' assistants agreed, then the counts in small text. */
.st-agree {
  display: grid;
  justify-items: start;
  gap: var(--space-2);
}

.st-agree .st-small {
  margin: 0;
  color: var(--ink-2);
}

/* Affected products and stores: each product over its stores as tags; the old list margins on dl, dt and dd are cleared. */
.st-affected {
  display: grid;
  gap: var(--space-3);
  min-width: 0;
}

.st-affected .st-subhead {
  margin: 0;
}

.st-affected__list {
  display: grid;
  gap: var(--space-3);
  margin: 0;
}

.st-affected__row {
  display: grid;
  gap: var(--space-2);
}

.st-affected__row dt {
  margin: 0;
}

.st-affected__row dt .st-data-s {
  color: var(--ink-3);
}

/* One visited page under a product (D-17): the PAGE label and the address as text, set in the small data style. */
.st-affected__page {
  display: block;
  margin-top: var(--space-1);
  font: 400 12px / 18px var(--font-mono);
  color: var(--ink-3);
  overflow-wrap: break-word;
}

/* biome-ignore lint/style/noDescendingSpecificity: an affected row never sits in the definition list of a box */
.st-affected__row dd {
  margin: 0;
}

.st-affected .st-small {
  margin: 0;
}

/* The three parts: one column, and three columns once the finding itself is 760px wide. */
.st-parts {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--rule);
}

@container (min-width: 760px) {
  .st-parts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.st-parts p:not(.st-subhead) {
  margin: 0;
  font: 400 16px / 26px var(--font-sans);
}

/* The evidence band sits under the main column behind a rule; it is 24px by 32px, 16px on a phone. */
.st-finding > .st-ev {
  padding: var(--space-5) var(--space-6);
  border-top: 1px solid var(--rule);
}

@media (width < 560px) {
  .st-finding > .st-ev {
    padding: var(--space-4);
  }
}

/* Evidence panels. Inside a finding each view is a size container, so the compare takes two columns from a 560px view and not from a wide window around a narrow card. */
.st-finding .st-view {
  container-type: inline-size;
}

@container (min-width: 560px) {
  .st-compare {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .st-compare__side + .st-compare__side {
    border-top: 0;
    border-left: 1px solid var(--rule);
  }

  .st-compare__ne {
    display: grid;
  }
}

/* The steps to reproduce: a counted list, the number in a 24px sunk tile before the text. */
.st-repro {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: st-repro;
}

.st-repro li {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: var(--space-3);
  align-items: start;
  counter-increment: st-repro;
  font: 400 16px / 26px var(--font-sans);
  overflow-wrap: break-word;
}

.st-repro li::before {
  content: counter(st-repro);
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  margin-top: 1px;
  background: var(--paper-sunk);
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  font: 500 12px / 16px var(--font-mono);
}

/* A compare may continue on the next printed page, but one of its rows and one of its quotes may not be split, and the copy buttons have no use on paper. The row itself stays: in an agent session it holds the vendor tag, which the printed page needs. An empty hook takes no room anyway. */
@media print {
  .st-field,
  .st-compare__quote {
    break-inside: avoid;
  }

  .st-view__tools button {
    display: none;
  }
}

/* On paper every view is shown, one under the other, each under its own title: the tab strip is dropped, a view the script hid is shown again (the rule next to the grid rows above), and the title the tab replaced is back. */
@media print {
  .st-tabs {
    display: none;
  }

  .st-ev.is-tabbed .st-view__title {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip: auto;
    white-space: normal;
  }

  /* A shown view that the script hid is a block, not a grid, so its title gets the gap the grid would have given. */
  .st-ev.is-tabbed .st-view[hidden] .st-view__title {
    margin-bottom: var(--space-4);
  }
}

/* A finding card may continue on the next printed page: a card that must stay whole and is taller than the room left leaves a blank page behind it, and a card taller than a page is cut off. Its small units stay whole (rows, steps, fields, quotes), and a heading stays with the first line under it. */
@media print {
  .st-finding__top,
  .st-finding__main .st-display-m,
  .st-block__head,
  .st-box__head,
  .st-view__title,
  .st-subhead {
    break-after: avoid;
  }

  /* The top row is one small unit: it is not split between its caption and its count. */
  .st-finding__top {
    break-inside: avoid;
  }

  /* The main column is a grid with padding above its first row, and Chromium allows a break in that padding: the top row is left at the foot of one page and the title starts the next. As a block with the same gap between its children it has no such break, and the title stays with the top row. */
  .st-finding__main {
    display: block;
  }

  .st-finding__main > * + * {
    margin-top: var(--space-4);
  }

  .st-finding__main .st-display-m {
    break-before: avoid;
  }

  .st-cause,
  .st-stat {
    break-inside: avoid;
  }

  /* Every box that clips its content on screen (the framed panel clips its corners, the grid and the compare scroll sideways) is one unbreakable piece in print and is cut off at the foot of the page when it is taller. In print they show everything and can flow onto the next page. The visually hidden helpers keep their clip. */
  .st-grid-wrap,
  .st-compare,
  .st-shot,
  .st-panel--framed,
  .st-results,
  .st-finding {
    overflow: visible;
  }

  /* The findings and the access boxes are one column of blocks on paper. As grid tracks their fragments overlap across tracks (the declared-visit box painted over the robots table), and a box that cannot break leaves a gap. */
  .st-findings,
  .st-access {
    display: block;
  }

  .st-findings > * + * {
    margin-top: var(--space-6);
  }

  .st-access > * + * {
    margin-top: var(--space-4);
  }
}

/* The screenshot of a finding: the picture is capped at 480px on screen, contained and anchored to the top, so a long page shows its first screen and the figure never pushes the findings off the view. The frame and the caption are in components.css. The width and height attributes reserve the box. */
.st-shot img {
  display: block;
  max-width: 100%;
  max-height: 480px;
  object-fit: contain;
  object-position: top;
  border: 0;
}

/* On paper the picture is capped at 90mm, the full-size link has no use, and the figure is not split across a page. */
@media print {
  .st-shot {
    break-inside: avoid;
  }

  .st-shot img {
    max-height: 90mm;
  }

  .st-shot__open {
    display: none;
  }
}

/* The agent session: the steps a shopper would see, in order and with no times. A one-pixel spine runs behind the marks; each step is a grid of its number, its mark, its words and (on the ending row) the finding's badge. The list is fully visible as it stands: the motion below only plays when the script adds .is-playing. */
.st-journey {
  position: relative;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: st-step;
}

.st-journey::before {
  content: "";
  position: absolute;
  top: 14px;
  bottom: 14px;
  left: calc(28px + var(--space-3) + 5.5px);
  width: 1px;
  background: var(--rule);
}

.st-step {
  display: grid;
  grid-template-columns: 28px 12px minmax(0, 1fr) auto;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) 0;
  color: var(--ink);
}

.st-step__n {
  counter-increment: st-step;
}

.st-step__n::before {
  content: counter(st-step);
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  background: var(--paper-sunk);
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  font: 500 12px / 16px var(--font-mono);
}

.st-mark {
  position: relative;
  z-index: 1;
  display: block;
  box-sizing: border-box;
  width: 12px;
  height: 12px;
}

.st-mark--done {
  background: var(--ink);
}

.st-mark--fail {
  background: var(--paper-raised);
  color: var(--fail-border);
}

.st-step__text {
  min-width: 0;
  font: 400 14px / 22px var(--font-mono);
  overflow-wrap: break-word;
}

.st-step--failed .st-step__text {
  color: var(--fail-text);
}

.st-step--end .st-step__text {
  font: 500 14px / 22px var(--font-mono);
}

.st-step__end {
  justify-self: end;
}

/* A step is not split across a printed page. */
@media print {
  .st-step {
    break-inside: avoid;
  }
}

/* Motion is opt-in and plays once (D-07): when the script adds .is-playing after the reader opens the session, each step fades in and rises 6px, 110ms after the one before it. The delays are rules here, not values in the markup. In print the steps never animate. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes st-step-in {
    from {
      opacity: 0;
      transform: translateY(6px);
    }

    to {
      opacity: 1;
      transform: none;
    }
  }

  .st-journey.is-playing .st-step {
    animation: st-step-in 450ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
  }

  .st-journey.is-playing .st-step:nth-child(2) {
    animation-delay: 110ms;
  }

  .st-journey.is-playing .st-step:nth-child(3) {
    animation-delay: 220ms;
  }

  .st-journey.is-playing .st-step:nth-child(4) {
    animation-delay: 330ms;
  }

  .st-journey.is-playing .st-step:nth-child(5) {
    animation-delay: 440ms;
  }

  .st-journey.is-playing .st-step:nth-child(6) {
    animation-delay: 550ms;
  }

  .st-journey.is-playing .st-step:nth-child(7) {
    animation-delay: 660ms;
  }

  .st-journey.is-playing .st-step:nth-child(8) {
    animation-delay: 770ms;
  }

  .st-journey.is-playing .st-step:nth-child(9) {
    animation-delay: 880ms;
  }

  .st-journey.is-playing .st-step:nth-child(10) {
    animation-delay: 990ms;
  }

  .st-journey.is-playing .st-step:nth-child(11) {
    animation-delay: 1100ms;
  }

  .st-journey.is-playing .st-step:nth-child(12) {
    animation-delay: 1210ms;
  }

  .st-journey.is-playing .st-step:nth-child(13) {
    animation-delay: 1320ms;
  }

  @media print {
    .st-journey .st-step {
      /* biome-ignore lint/complexity/noImportantStyles: the print reset has to beat the more specific .is-playing rule above */
      animation: none !important;
    }
  }
}
