/* ============================================================================
   testedpeptides.com — the only stylesheet.
   Precision instrument: cool paper, ink, hairlines, one ultramarine, tabular
   numerals. Semantic green/red appear ONLY on pass/fail data. Every colour and
   face is a --tp-* token; no hardcoded hex below :root.
   ========================================================================== */

/* ── faces ─────────────────────────────────────────────────────────────── */

/* Archivo variable (wght 100–900, wdth 62–125): UI, display, giant numerals. */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("/fonts/archivo-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

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

/* ── tokens ────────────────────────────────────────────────────────────── */

:root {
  /* surfaces + ink. Cool paper, never cream. */
  --tp-paper: #fbfbfa;
  --tp-paper-sunk: #f4f4f1;
  --tp-ink: #141413;
  --tp-ink-2: #55554f; /* 7.3:1 on paper */
  --tp-ink-3: #6e6e67; /* 5.0:1 on paper — still body-text legal */
  --tp-rule: #e4e4df;
  --tp-rule-2: #c9c9c1;

  /* one accent: deep ultramarine, oklch(45% 0.19 264). 7.5:1 on paper. */
  --tp-accent: #1a48bc;
  --tp-accent-2: #1639a6;

  /* pass/fail data only. Never decoration, never a background wash. */
  --tp-pass: #1b7f4b;
  --tp-fail: #c13529;

  --tp-font-ui: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --tp-font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* The rendered PDF page. Not a surface of ours — it is the document's own
     paper, and it stays white in dark mode because inverting a lab certificate
     would misrepresent what the lab issued. */
  --tp-sheet: #ffffff;

  --tp-shell: 1180px;
  --tp-gutter: clamp(20px, 5vw, 64px);

  /* One height for the document box, shared by the iframe fallback and the
     canvas viewer so the progressive-enhancement swap moves nothing. */
  --tp-doc-h: clamp(420px, 80vh, 1080px);
}

@media (prefers-color-scheme: dark) {
  :root {
    /* instrument dark: near-black body, warm grey ink, same accent lifted. No glow. */
    --tp-paper: #131312;
    --tp-paper-sunk: #1c1c1a;
    --tp-ink: #edede8;
    --tp-ink-2: #a8a8a0;
    --tp-ink-3: #8a8a82;
    --tp-rule: #2c2c28;
    --tp-rule-2: #474741;
    --tp-accent: #789bef;
    --tp-accent-2: #9ab4f5;
    --tp-pass: #54b66e;
    --tp-fail: #e66f62;
  }
}

/* ── reset ─────────────────────────────────────────────────────────────── */

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

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

body {
  margin: 0;
  min-height: 100svh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: var(--tp-paper);
  color: var(--tp-ink);
  font: 400 15px/1.55 var(--tp-font-ui);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
p,
dl,
dd {
  margin: 0;
}

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

a:hover {
  color: var(--tp-accent-2);
}

table {
  border-collapse: collapse;
}

iframe {
  border: 0;
}

/* ── utilities ─────────────────────────────────────────────────────────── */

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

/* Off screen until focused, then the first row of the page. */
.tp-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 20;
  font: 500 13px/1 var(--tp-font-ui);
  color: var(--tp-paper);
  background: var(--tp-ink);
  padding: 10px 14px;
  text-decoration: none;
}

.tp-skip:focus {
  left: 8px;
  top: 8px;
}

.tp-mono {
  font-family: var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
}

.tp-eyebrow {
  font: 400 11px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--tp-ink-3);
  margin-bottom: 18px;
}

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

/* ── shell ─────────────────────────────────────────────────────────────── */

.tp-head {
  max-width: var(--tp-shell);
  width: 100%;
  margin-inline: auto;
  padding: 22px var(--tp-gutter) 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
}

.tp-wordmark {
  font: 600 15px/1 var(--tp-font-ui);
  font-stretch: 98%;
  letter-spacing: -0.005em;
  color: var(--tp-ink);
  text-decoration: none;
  view-transition-name: tp-wordmark;
}

.tp-wordmark-b {
  font-weight: 400;
  color: var(--tp-ink-2);
}

.tp-head-note {
  font: 400 12px/1 var(--tp-font-mono);
  letter-spacing: 0.06em;
  color: var(--tp-ink-3);
  font-variant-numeric: tabular-nums;
}

.tp-main {
  min-width: 0;
}

.tp-foot {
  max-width: var(--tp-shell);
  width: 100%;
  margin-inline: auto;
  padding: 72px var(--tp-gutter) 30px;
}

.tp-foot p {
  font: 400 12px/1.5 var(--tp-font-mono);
  letter-spacing: 0.02em;
  color: var(--tp-ink-3);
}

/* ── home / 404 ────────────────────────────────────────────────────────── */

/* Vertical placement puts the field itself at roughly 40% of the viewport. */
.tp-home {
  max-width: var(--tp-shell);
  margin-inline: auto;
  padding: clamp(48px, 28svh, 340px) var(--tp-gutter) 0;
  display: grid;
  grid-template-columns: minmax(0, 620px) minmax(190px, 250px);
  gap: 0 clamp(40px, 7vw, 116px);
  align-items: start;
}

/* The aside column is too narrow for label-beside-value; stack it instead. */
.tp-home-spec .tp-spec-row {
  grid-template-columns: minmax(0, 1fr);
  gap: 3px;
  padding: 9px 0 11px;
}

.tp-home-primary {
  min-width: 0;
}

.tp-h1 {
  font: 600 clamp(26px, 3.5vw, 37px)/1.05 var(--tp-font-ui);
  font-stretch: 96%;
  letter-spacing: -0.025em;
  color: var(--tp-ink);
  text-wrap: balance;
}

/* ── search field: the hero ────────────────────────────────────────────── */

.tp-search {
  position: relative;
  margin-top: clamp(24px, 3.5vh, 38px);
}

.tp-search-field {
  position: relative;
  display: flex;
  align-items: center;
}

.tp-search-input {
  width: 100%;
  min-width: 0;
  font: 400 clamp(24px, 4.4vw, 38px)/1.15 var(--tp-font-mono);
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
  color: var(--tp-ink);
  background: transparent;
  border: 1px solid var(--tp-rule-2);
  border-radius: 2px;
  padding: 17px 68px 17px 19px;
  transition: border-color 140ms ease, box-shadow 140ms ease;
}

.tp-search-input::placeholder {
  color: var(--tp-ink-3);
  opacity: 1;
}

/* Focus sharpens the hairline to 2px of accent — inset, so no blur, no glow. */
.tp-search-input:focus,
.tp-search-input:focus-visible {
  outline: none;
  border-color: var(--tp-accent);
  box-shadow: inset 0 0 0 1px var(--tp-accent);
}

.tp-kbd {
  position: absolute;
  right: 15px;
  top: 50%;
  transform: translateY(-50%);
  font: 400 12px/1 var(--tp-font-mono);
  color: var(--tp-ink-3);
  border: 1px solid var(--tp-rule);
  border-radius: 2px;
  padding: 5px 8px;
  transition: opacity 120ms ease;
}

.tp-search-input:focus ~ .tp-kbd,
.tp-search-input:not(:placeholder-shown) ~ .tp-kbd {
  opacity: 0;
}

.tp-kbd-inline {
  font: 400 11.5px/1 var(--tp-font-mono);
  border: 1px solid var(--tp-rule);
  border-radius: 2px;
  padding: 2px 5px;
}

.tp-search-help {
  margin-top: 14px;
  font-size: 12.5px;
  color: var(--tp-ink-3);
}

.tp-search-status {
  margin-top: 10px;
  font: 400 12.5px/1.5 var(--tp-font-mono);
  color: var(--tp-ink-2);
}

/* Collapsed, not removed: a role="status" region at display:none is out of the
   accessibility tree, and inserting text into a region that only then becomes
   visible is announced unreliably (or not at all) by VoiceOver and NVDA. */
.tp-search-status:empty {
  height: 0;
  margin: 0;
  overflow: hidden;
}

/* ── typeahead: rows, not cards ────────────────────────────────────────── */

.tp-suggest {
  list-style: none;
  margin: -1px 0 0;
  padding: 0;
  border: 1px solid var(--tp-rule-2);
  background: var(--tp-paper);
  position: relative;
  z-index: 5;
}

.tp-suggest[hidden] {
  display: none;
}

.tp-sug {
  display: grid;
  grid-template-columns: minmax(110px, 0.9fr) minmax(0, 1.4fr) auto;
  gap: 4px 20px;
  align-items: baseline;
  padding: 13px 16px;
  cursor: pointer;
  border-top: 1px solid var(--tp-rule);
  transition: background-color 120ms ease;
}

.tp-sug:first-child {
  border-top: 0;
}

/* Selection is a rule and a shift in ground, never a filled pill. */
.tp-sug[aria-selected="true"] {
  background: var(--tp-paper-sunk);
  box-shadow: inset 2px 0 0 var(--tp-accent);
}

.tp-sug-batch {
  font: 400 15px/1.3 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  color: var(--tp-ink);
}

.tp-sug-name {
  min-width: 0;
  font-size: 14px;
  color: var(--tp-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tp-sug-company {
  color: var(--tp-ink-3);
}

.tp-sug-meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  justify-self: end;
}

.tp-sug-date {
  font: 400 12px/1.3 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--tp-ink-3);
}

.tp-badge {
  font: 400 10.5px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--tp-ink-2);
  border: 1px solid var(--tp-rule-2);
  border-radius: 1px;
  padding: 1px 5px;
  white-space: nowrap;
}

.tp-badge--fail {
  color: var(--tp-fail);
  border-color: var(--tp-fail);
  font-weight: 600;
}

/* ── spec grid (label / value, hairline per row) ───────────────────────── */

.tp-spec {
  border-top: 1px solid var(--tp-rule);
}

.tp-spec-row {
  display: grid;
  grid-template-columns: minmax(88px, 42%) minmax(0, 1fr);
  gap: 0 16px;
  align-items: baseline;
  padding: 10px 0;
  border-bottom: 1px solid var(--tp-rule);
}

.tp-spec dt {
  font: 400 11px/1.5 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tp-ink-3);
}

.tp-spec dd {
  font: 400 13px/1.5 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--tp-ink);
}

.tp-spec-wrap {
  word-break: break-all;
}

/* ── certificate page ─────────────────────────────────────────────────── */

.tp-coa {
  max-width: var(--tp-shell);
  margin-inline: auto;
  padding: 0 var(--tp-gutter);
}

.tp-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.28fr) minmax(250px, 0.72fr);
  gap: clamp(32px, 5vw, 80px);
  padding: clamp(26px, 5vh, 52px) 0 clamp(30px, 5vh, 54px);
  border-bottom: 1px solid var(--tp-rule-2);
}

.tp-hero-main {
  min-width: 0;
}

/* A failed endotoxin result outranks everything else on the page. */
.tp-alarm {
  font: 700 clamp(22px, 3.4vw, 34px)/1.1 var(--tp-font-ui);
  font-stretch: 92%;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  color: var(--tp-fail);
  border-left: 2px solid var(--tp-fail);
  padding: 3px 0 3px 14px;
  margin-bottom: 26px;
}

.tp-alarm-note {
  display: block;
  margin-top: 7px;
  font: 400 12px/1.4 var(--tp-font-mono);
  letter-spacing: 0.04em;
  text-transform: none;
  font-weight: 400;
}

.tp-product {
  font: 600 clamp(31px, 4.6vw, 50px)/1.02 var(--tp-font-ui);
  font-stretch: 96%;
  letter-spacing: -0.028em;
  color: var(--tp-ink);
  text-wrap: balance;
}

.tp-volume {
  display: inline-block;
  margin-left: 0.42em;
  font: 400 0.34em/1 var(--tp-font-mono);
  letter-spacing: 0;
  color: var(--tp-ink-3);
  vertical-align: 0.28em;
}

.tp-company {
  margin-top: 11px;
  font-size: 16px;
  color: var(--tp-ink-2);
}

.tp-metric {
  margin-top: clamp(26px, 4vh, 44px);
}

.tp-metric-value {
  font-family: var(--tp-font-ui);
  font-size: clamp(58px, 10.5vw, 104px);
  font-weight: 800;
  font-stretch: 88%;
  line-height: 0.9;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  color: var(--tp-ink);
}

.tp-metric-unit {
  font-size: 0.33em;
  font-weight: 500;
  font-stretch: 100%;
  letter-spacing: 0;
  margin-left: 0.09em;
  color: var(--tp-ink-2);
}

.tp-verdict {
  font-family: var(--tp-font-ui);
  font-size: clamp(29px, 5vw, 54px);
  font-weight: 780;
  font-stretch: 88%;
  line-height: 1;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--tp-ink);
}

.tp-verdict--fail {
  color: var(--tp-fail);
}

.tp-metric-label {
  margin-top: 15px;
  font: 400 11.5px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--tp-ink-3);
}

.tp-hero-spec {
  align-self: end;
}

/* ── sections + data tables ───────────────────────────────────────────── */

.tp-section {
  padding-top: clamp(34px, 5vh, 54px);
}

.tp-section-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 15px;
  font: 400 11.5px/1 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--tp-ink-2);
}

.tp-section-no {
  color: var(--tp-ink-3);
  font-variant-numeric: tabular-nums;
}

.tp-table {
  width: 100%;
  border-top: 1px solid var(--tp-rule-2);
}

.tp-table th,
.tp-table td {
  text-align: left;
  vertical-align: baseline;
  font-weight: 400;
  padding: 14px 0;
  border-bottom: 1px solid var(--tp-rule);
}

.tp-table th[scope="row"] {
  width: 34%;
  padding-right: 24px;
  font-size: 13px;
  color: var(--tp-ink-3);
}

.tp-table td {
  font-size: 15px;
  color: var(--tp-ink);
}

.tp-table td.tp-mono {
  font-size: 14px;
  letter-spacing: -0.01em;
}

.tp-table--components {
  margin-top: 26px;
}

.tp-table--components thead th {
  font: 400 11px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tp-ink-3);
  padding-bottom: 9px;
  border-bottom: 1px solid var(--tp-rule-2);
}

.tp-table--components tbody th[scope="row"] {
  font-family: var(--tp-font-mono);
  font-size: 14px;
  color: var(--tp-ink);
}

.tp-result {
  font: 600 13px/1 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.11em;
}

.tp-result--pass {
  color: var(--tp-pass);
}

.tp-result--fail {
  color: var(--tp-fail);
}

/* ── the document itself ──────────────────────────────────────────────── */

.tp-doc {
  isolation: isolate;
}

.tp-doc-frame {
  position: relative;
  z-index: 0;
  border: 1px solid var(--tp-rule-2);
  background: var(--tp-paper-sunk);
}

/* One offset hairline behind the sheet — a paper edge, not a drop shadow. */
.tp-doc-frame::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 6px;
  right: -6px;
  bottom: -6px;
  border: 1px solid var(--tp-rule);
  z-index: -1;
  pointer-events: none;
}

.tp-doc-view {
  display: block;
  width: 100%;
  height: var(--tp-doc-h);
  background: var(--tp-paper);
}

/* ── the skinned viewer (progressive enhancement over .tp-doc-view) ─────── */

/* Same box the iframe occupied, so the swap does not move the page. `relative` is
   load-bearing, not cosmetic: coa-doc.js reads each page's offsetTop to decide
   what to decode, and that is only the offset inside this box while this box is
   the offset parent. */
.tp-viewer-scroll {
  position: relative;
  height: var(--tp-doc-h);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--tp-paper-sunk);
}

/* Held while pdf.js loads, at the height the frame will keep. */
.tp-viewer-wait {
  display: grid;
  place-items: center;
  height: var(--tp-doc-h);
  font: 400 12.5px/1.4 var(--tp-font-mono);
  letter-spacing: 0.04em;
  color: var(--tp-ink-3);
}

/* A rendered page is a sheet of white paper in both themes — that is what the
   document is, and inverting a lab certificate would misrepresent it. */
.tp-page {
  position: relative;
  background: var(--tp-sheet);
  border-bottom: 1px solid var(--tp-rule-2);
}

.tp-page:last-child {
  border-bottom: 0;
}

.tp-page-canvas {
  display: block;
  width: 100%;
}

.tp-page-fail {
  padding: 22px 18px;
  font: 400 12.5px/1.5 var(--tp-font-mono);
  color: var(--tp-ink-2);
}

.tp-page--failed {
  min-height: 0;
  height: auto !important;
  background: var(--tp-paper-sunk);
}

.tp-viewer-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 12px;
  border-top: 1px solid var(--tp-rule-2);
  background: var(--tp-paper);
}

/* Text buttons with a drawn arrow, not a control strip of icons. */
.tp-pagebtn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font: 500 12.5px/1 var(--tp-font-ui);
  color: var(--tp-accent);
  background: none;
  border: 0;
  border-bottom: 1px solid transparent;
  border-radius: 1px;
  padding: 4px 1px;
  cursor: pointer;
  transition: border-color 130ms ease, color 130ms ease;
}

.tp-pagebtn:hover:not(:disabled) {
  border-bottom-color: currentColor;
}

.tp-pagebtn:disabled {
  color: var(--tp-ink-3);
  cursor: default;
}

.tp-pageno {
  font: 400 11.5px/1 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.07em;
  color: var(--tp-ink-2);
}

.tp-doc-links {
  display: flex;
  flex-wrap: wrap;
  gap: 26px;
  margin-top: 24px;
}

.tp-doc-links a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--tp-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: border-color 130ms ease, color 130ms ease;
}

.tp-doc-links a:hover {
  border-bottom-color: currentColor;
}

.tp-glyph {
  display: block;
  overflow: visible;
}

.tp-doc-print {
  display: none;
}

/* ── sibling certificates on the same batch ───────────────────────────── */

.tp-sib-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--tp-rule-2);
}

.tp-sib {
  border-bottom: 1px solid var(--tp-rule);
}

.tp-sib > a {
  display: grid;
  grid-template-columns: 96px 84px minmax(0, 1fr) auto auto;
  gap: 4px 20px;
  align-items: baseline;
  padding: 12px 14px;
  color: inherit;
  text-decoration: none;
  transition: background-color 120ms ease;
}

.tp-sib > a:hover,
.tp-sib > a:focus-visible {
  background: var(--tp-paper-sunk);
  box-shadow: inset 2px 0 0 var(--tp-accent);
}

.tp-sib-type {
  font: 400 12px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tp-ink-2);
}

.tp-sib-vol,
.tp-sib-val,
.tp-sib-date,
.tp-sib-id {
  font: 400 12.5px/1.4 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--tp-ink);
}

.tp-sib-date,
.tp-sib-id {
  color: var(--tp-ink-3);
}

.tp-sib-fail,
.tp-sib-pass {
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.tp-sib-fail {
  color: var(--tp-fail);
  font-weight: 600;
}

.tp-sib-pass {
  color: var(--tp-pass);
}

.tp-disclaimer {
  margin-top: clamp(40px, 6vh, 64px);
  max-width: 66ch;
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--tp-ink-3);
}

/* ==========================================================================
   AUTH + PORTAL + ADMIN (phase 3)
   The signed-in side of the same instrument: identical tokens, hairlines and
   mono data, with forms and tables added. Nothing below is used by a public page.
   ========================================================================== */

:root {
  /* Working column for the signed-in side: narrower than the public shell,
     because these pages are read as forms and rows, not as spreads. */
  --tp-col: 900px;
}

/* ── signed-in bar ─────────────────────────────────────────────────────── */

/* Full-bleed hairline, content on the column axis. */
.tp-bar {
  border-bottom: 1px solid var(--tp-rule);
}

.tp-bar-inner {
  max-width: var(--tp-col);
  width: 100%;
  margin-inline: auto;
  padding: 18px var(--tp-gutter) 17px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}

.tp-bar-id,
.tp-bar-who {
  display: flex;
  align-items: baseline;
  gap: 14px;
  min-width: 0;
}

/* The section name sits behind a hairline, the way a panel legend would. */
.tp-bar-section {
  padding-left: 14px;
  border-left: 1px solid var(--tp-rule-2);
  font: 400 11.5px/1 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--tp-ink-3);
}

.tp-bar-email {
  font: 400 12.5px/1 var(--tp-font-mono);
  color: var(--tp-ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tp-bar-out {
  font-size: 12.5px;
  color: var(--tp-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 130ms ease;
}

.tp-bar-out:hover {
  border-bottom-color: currentColor;
}

/* ── content column ────────────────────────────────────────────────────── */

.tp-pane {
  max-width: var(--tp-col);
  margin-inline: auto;
  padding: clamp(30px, 6vh, 58px) var(--tp-gutter) 0;
}

.tp-body--auth .tp-main {
  display: grid;
  align-content: start;
}

.tp-auth {
  width: 100%;
  max-width: 430px;
  margin-inline: auto;
  padding: clamp(40px, 14svh, 150px) var(--tp-gutter) 0;
}

.tp-auth-intro {
  margin-top: 12px;
  font-size: 14px;
  color: var(--tp-ink-2);
}

.tp-section-title {
  font: 400 11.5px/1 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--tp-ink-2);
  margin: 0;
}

.tp-section-count {
  margin-left: auto;
  font: 400 11.5px/1 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--tp-ink-3);
}

/* ── card + prose ──────────────────────────────────────────────────────── */

.tp-card {
  margin-top: 22px;
  padding: 24px;
  border: 1px solid var(--tp-rule-2);
  background: var(--tp-paper);
}

.tp-card--prose {
  display: grid;
  gap: 12px;
  font-size: 14.5px;
  line-height: 1.6;
}

.tp-note {
  margin-top: 10px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--tp-ink-3);
}

.tp-note--spaced {
  margin-top: 20px;
}

/* ── forms ─────────────────────────────────────────────────────────────── */

.tp-label {
  display: block;
  font: 400 11px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tp-ink-3);
  margin-bottom: 7px;
}

/* "optional", "empty = the built-in prompt" — quiet, but it is instruction text,
   so it sits on --tp-ink-3 (4.96:1) and not on a hairline tint (1.61:1). */
.tp-label-opt {
  text-transform: none;
  letter-spacing: 0.02em;
  color: var(--tp-ink-3);
}

.tp-input {
  width: 100%;
  min-width: 0;
  font: 400 15px/1.3 var(--tp-font-ui);
  color: var(--tp-ink);
  background: transparent;
  border: 1px solid var(--tp-rule-2);
  border-radius: 2px;
  padding: 11px 13px;
  transition: border-color 130ms ease, box-shadow 130ms ease;
}

.tp-input--mono {
  font-family: var(--tp-font-mono);
  font-size: 14px;
}

/* The code is the one number on the page, so it is set like one. */
.tp-input--code {
  font: 400 26px/1.15 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.36em;
  text-indent: 0.36em;
  padding: 13px;
}

.tp-input::placeholder {
  color: var(--tp-ink-3);
  opacity: 1;
}

.tp-input:focus,
.tp-input:focus-visible {
  outline: none;
  border-color: var(--tp-accent);
  box-shadow: inset 0 0 0 1px var(--tp-accent);
}

.tp-form-head {
  font: 400 11.5px/1 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--tp-ink-3);
  margin-bottom: 18px;
}

.tp-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 18px 20px;
}

.tp-field {
  min-width: 0;
}

/* ── buttons ───────────────────────────────────────────────────────────── */

.tp-btn {
  margin-top: 20px;
  display: inline-block;
  font: 500 14px/1 var(--tp-font-ui);
  color: var(--tp-paper);
  background: var(--tp-ink);
  border: 1px solid var(--tp-ink);
  border-radius: 2px;
  padding: 12px 20px;
  cursor: pointer;
  transition: background-color 130ms ease, border-color 130ms ease, opacity 130ms ease;
}

.tp-btn:hover:not(:disabled) {
  background: var(--tp-accent);
  border-color: var(--tp-accent);
}

/* "Publish all clean" ships disabled and its label carries the count, so the
   disabled state still has to be readable. */
.tp-btn:disabled {
  opacity: 0.68;
  cursor: default;
}

.tp-btn-quiet {
  margin-left: 14px;
  font: 400 12.5px/1 var(--tp-font-ui);
  color: var(--tp-accent);
  background: none;
  border: 0;
  padding: 4px 0;
  cursor: pointer;
  border-bottom: 1px solid transparent;
  transition: border-color 130ms ease;
}

.tp-btn-quiet:hover {
  border-bottom-color: currentColor;
}

/* ── messages ──────────────────────────────────────────────────────────── */

.tp-msg {
  margin-top: 16px;
  font: 400 12.5px/1.55 var(--tp-font-mono);
  color: var(--tp-ink-2);
}

/* Collapsed, not removed — see .tp-search-status:empty above. */
.tp-msg:empty {
  height: 0;
  margin: 0;
  overflow: hidden;
}

.tp-msg--error {
  color: var(--tp-fail);
}

.tp-auth-sent {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 4px;
  margin-bottom: 22px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--tp-rule);
  font-size: 13px;
  color: var(--tp-ink-2);
}

.tp-auth-sent .tp-mono {
  font-size: 13.5px;
  color: var(--tp-ink);
}

.tp-auth-foot {
  margin-top: 26px;
  font-size: 12.5px;
  color: var(--tp-ink-3);
}

/* ── empty states ──────────────────────────────────────────────────────── */

.tp-empty {
  padding: 26px 0 28px;
  border-top: 1px solid var(--tp-rule-2);
  border-bottom: 1px solid var(--tp-rule);
}

.tp-empty-line {
  font-size: 15px;
  color: var(--tp-ink);
}

/* ── data tables ───────────────────────────────────────────────────────── */

/* Wide tables scroll inside their own box; the page never does. */
.tp-scroll {
  overflow-x: auto;
}

.tp-data {
  width: 100%;
  min-width: 560px;
  border-top: 1px solid var(--tp-rule-2);
}

.tp-data thead th {
  text-align: left;
  font: 400 11px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tp-ink-3);
  padding: 9px 18px 9px 0;
  border-bottom: 1px solid var(--tp-rule-2);
  white-space: nowrap;
}

/* The first cell of a queue/board row is a th[scope="row"], so every control and
   pill further along the row inherits the filename as context. It is styled as a
   plain cell — the row header is structure, not emphasis. */
.tp-data td,
.tp-data tbody th[scope="row"] {
  font-size: 13.5px;
  font-weight: 400;
  text-align: left;
  color: var(--tp-ink);
  vertical-align: baseline;
  padding: 12px 18px 12px 0;
  border-bottom: 1px solid var(--tp-rule);
}

.tp-data thead th:last-child,
.tp-data td:last-child {
  padding-right: 0;
}

.tp-data td.tp-mono {
  font-size: 12.5px;
}

.tp-data .tp-note {
  margin-top: 0;
}

.tp-state {
  font: 400 11px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tp-ink);
}

.tp-state--muted {
  color: var(--tp-ink-3);
}

/* ==========================================================================
   UPLOAD + REVIEW (phase 4)
   The working surfaces: a drop target, a queue of hundreds of rows, and the
   review board with its PDF beside a four-column field grid. Same tokens, same
   hairlines. Two colour rules carry over unchanged from the public side —
   --tp-fail means a real failure and nothing else, and everything that merely
   wants a human's attention is the one accent.
   ========================================================================== */

/* The review board is the only surface that needs more than a reading measure:
   a PDF and a Field/A/B/Final grid side by side. The bar follows the same axis. */
.tp-body--wide {
  --tp-col: 1320px;
}

/* ── the one primary action on a page ──────────────────────────────────── */

.tp-lead {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 22px;
  margin-top: 26px;
}

.tp-btn--link {
  text-decoration: none;
  margin-top: 0;
}

.tp-lead-note {
  max-width: 46ch;
  font-size: 13px;
  line-height: 1.6;
  color: var(--tp-ink-3);
}

.tp-lead-note--solo {
  margin-top: 14px;
  max-width: 62ch;
}

.tp-num {
  font-variant-numeric: tabular-nums;
}

/* ── status pills: the phase-2 badge, in five tones ────────────────────── */

.tp-pills {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 5px 7px;
}

.tp-badge--accent {
  color: var(--tp-accent);
  border-color: var(--tp-accent);
}

.tp-badge--quiet {
  color: var(--tp-ink-3);
  border-color: var(--tp-rule);
}

.tp-badge--pass {
  color: var(--tp-pass);
  border-color: var(--tp-pass);
}

/* ── drop target ───────────────────────────────────────────────────────── */

/* Not a dashed rectangle: the same hairline-and-sunk-ground treatment as every
   other input on the site, and the focus/drag state is the accent inset the
   search field uses. */
.tp-drop {
  display: grid;
  gap: 5px;
  place-items: center;
  margin-top: 30px;
  padding: 46px 24px 50px;
  border: 1px solid var(--tp-rule-2);
  border-radius: 2px;
  background: var(--tp-paper-sunk);
  cursor: pointer;
  transition: border-color 130ms ease, box-shadow 130ms ease;
}

.tp-drop:hover,
.tp-drop--over,
.tp-drop:focus-within {
  border-color: var(--tp-accent);
  box-shadow: inset 0 0 0 1px var(--tp-accent);
}

.tp-drop-line {
  font: 500 16px/1.2 var(--tp-font-ui);
  color: var(--tp-ink);
}

.tp-drop-note {
  font: 400 12.5px/1.4 var(--tp-font-mono);
  color: var(--tp-ink-3);
}

/* ── running totals + a determinate hairline ───────────────────────────── */

.tp-counts {
  font: 400 13px/1.6 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--tp-ink-2);
}

/* No spinner anywhere on these screens: the numbers above are the progress and
   this is the same fact drawn once. */
.tp-meter {
  margin-top: 11px;
  height: 2px;
  background: var(--tp-rule);
}

.tp-meter[hidden] {
  display: none;
}

.tp-meter-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--tp-accent);
  transition: width 180ms linear;
}

/* ── queue + board tables ──────────────────────────────────────────────── */

.tp-data--queue {
  min-width: 520px;
  margin-top: 20px;
}

.tp-data--board {
  min-width: 780px;
  margin-top: 6px;
}

/* Hundreds of rows: a long filename must not push the status column off screen. */
.tp-file {
  max-width: 40ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tp-cell-note {
  display: block;
  margin-top: 3px;
  font: 400 11.5px/1.45 var(--tp-font-mono);
  color: var(--tp-ink-3);
}

.tp-cell-note--bad {
  display: block;
  margin-top: 3px;
  font: 400 11.5px/1.45 var(--tp-font-mono);
  color: var(--tp-fail);
}

.tp-cell-link {
  display: inline-block;
  margin-top: 3px;
  font: 400 11.5px/1.45 var(--tp-font-mono);
}

.tp-done {
  margin-top: 26px;
  padding: 18px 0 0;
  border-top: 1px solid var(--tp-rule-2);
}

.tp-done[hidden] {
  display: none;
}

.tp-done-line {
  font-size: 14.5px;
  color: var(--tp-ink);
}

/* ── board header ──────────────────────────────────────────────────────── */

.tp-inline-spec {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 40px;
  margin: 24px 0 0;
  padding-bottom: 17px;
  border-bottom: 1px solid var(--tp-rule);
}

.tp-inline-spec dt {
  font: 400 11px/1.5 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tp-ink-3);
}

.tp-inline-spec dd {
  margin: 2px 0 0;
  font-size: 13px;
  color: var(--tp-ink);
}

.tp-board-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 16px;
  margin-top: 18px;
}

.tp-board-actions .tp-btn {
  margin-top: 0;
}

.tp-board-actions .tp-btn-quiet {
  margin-left: 0;
}

.tp-poll {
  font: 400 11.5px/1.4 var(--tp-font-mono);
  letter-spacing: 0.03em;
  color: var(--tp-ink-3);
}

.tp-btn--sm {
  margin-top: 0;
  font-size: 12.5px;
  padding: 8px 13px;
}

/* ── expandable rows ───────────────────────────────────────────────────── */

/* A real button, so Enter, Space and focus-visible all work without a keydown
   handler pretending to be a control. */
.tp-rowtoggle {
  font: inherit;
  font-family: var(--tp-font-mono);
  font-size: 12.5px;
  color: var(--tp-ink);
  text-align: left;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  max-width: 34ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-bottom: 1px solid transparent;
  transition: border-color 130ms ease;
}

.tp-rowtoggle:hover {
  border-bottom-color: var(--tp-rule-2);
}

.tp-rowtoggle[aria-expanded="true"] {
  color: var(--tp-accent);
  border-bottom-color: currentColor;
}

.tp-detail-row > td {
  padding: 0 0 26px;
  border-bottom: 1px solid var(--tp-rule-2);
}

.tp-detail {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: 28px;
  padding-top: 6px;
}

.tp-detail-doc,
.tp-detail-data {
  min-width: 0;
}

.tp-pdf {
  border: 1px solid var(--tp-rule-2);
  background: var(--tp-paper-sunk);
}

.tp-pdf-view {
  display: block;
  width: 100%;
  height: clamp(340px, 66vh, 860px);
  background: var(--tp-paper);
}

/* ── product mapping ───────────────────────────────────────────────────── */

.tp-picker {
  padding: 15px 16px 17px;
  border: 1px solid var(--tp-rule-2);
  background: var(--tp-paper-sunk);
}

.tp-picker-head {
  font: 400 11px/1 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--tp-ink-3);
  margin-bottom: 11px;
}

.tp-picker-state {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
}

.tp-picker-name {
  font: 500 15px/1.2 var(--tp-font-ui);
  color: var(--tp-ink);
}

.tp-picker-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 9px;
  margin-top: 15px;
}

.tp-picker-new {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 9px;
  margin-top: 11px;
}

.tp-picker-new[hidden] {
  display: none;
}

.tp-picker-new .tp-input {
  width: auto;
  flex: 1 1 200px;
}

.tp-picker-new .tp-note {
  flex: 1 1 100%;
  margin-top: 0;
}

.tp-picker .tp-btn {
  margin-top: 0;
}

.tp-select {
  flex: 1 1 190px;
  min-width: 0;
  font: 400 13.5px/1.3 var(--tp-font-ui);
  color: var(--tp-ink);
  background: var(--tp-paper);
  border: 1px solid var(--tp-rule-2);
  border-radius: 2px;
  padding: 9px 10px;
}

.tp-select:focus,
.tp-select:focus-visible {
  outline: none;
  border-color: var(--tp-accent);
  box-shadow: inset 0 0 0 1px var(--tp-accent);
}

/* ── the field grid: Field | Agent A | Agent B | Final ─────────────────── */

/* Every row carries the same template rather than the container carrying it: the
   same pattern as .tp-spec-row and .tp-sug elsewhere in this file, and it keeps
   the validation messages between rows as plain blocks. */
.tp-fgrid {
  margin-top: 22px;
  border-top: 1px solid var(--tp-rule-2);
}

.tp-frow {
  display: grid;
  grid-template-columns: minmax(112px, 0.95fr) minmax(0, 1fr) minmax(0, 1fr) minmax(132px, 1.15fr);
  align-items: center;
  gap: 0 14px;
  padding: 6px 0 6px 10px;
  border-bottom: 1px solid var(--tp-rule);
}

.tp-frow--head {
  padding-bottom: 8px;
  font: 400 11px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tp-ink-3);
  border-bottom: 1px solid var(--tp-rule-2);
}

/* The one thing a reviewer scans for. Accent, not red: red on this site means a
   failure, and a disagreement is not one. */
.tp-frow--conflict {
  box-shadow: inset 2px 0 0 var(--tp-accent);
  background: var(--tp-paper-sunk);
}

/* An edit the server refused. */
.tp-frow--bad {
  box-shadow: inset 2px 0 0 var(--tp-fail);
}

.tp-fname {
  font-size: 11.5px;
  color: var(--tp-ink-2);
  overflow-wrap: anywhere;
}

.tp-fagent {
  min-width: 0;
  font-size: 12px;
  color: var(--tp-ink-2);
  overflow-wrap: anywhere;
}

/* The em dash IS the cell's content — "this agent returned nothing" is a reading,
   not decoration, so it gets readable ink rather than a hairline tint. */
.tp-fagent--empty {
  color: var(--tp-ink-3);
}

.tp-ffinal {
  min-width: 0;
  font-size: 12.5px;
  color: var(--tp-ink);
  overflow-wrap: anywhere;
}

/* An agent value worth adopting reads as text until you reach for it. */
.tp-adopt {
  font: 400 12px/1.4 var(--tp-font-mono);
  color: var(--tp-accent);
  text-align: left;
  background: none;
  border: 0;
  padding: 1px 0;
  cursor: pointer;
  border-bottom: 1px dashed var(--tp-rule-2);
  overflow-wrap: anywhere;
}

.tp-adopt:hover {
  border-bottom-style: solid;
  border-bottom-color: currentColor;
}

/* These are the only cells on the board you type into, so the boundary has to be
   findable: --tp-rule was 1.2:1 against the row ground, which is no boundary. */
.tp-input--cell {
  font-size: 12.5px;
  padding: 5px 7px;
  border-color: var(--tp-rule-2);
}

.tp-input--cell:hover {
  border-color: var(--tp-ink-3);
}

.tp-input--cell[aria-invalid="true"] {
  border-color: var(--tp-fail);
}

.tp-input--saving {
  border-color: var(--tp-accent);
}

.tp-input--bad {
  border-color: var(--tp-fail);
}

/* ── validation issues ─────────────────────────────────────────────────── */

/* Placed in the grid, immediately under the field they name. */
.tp-fissue {
  margin: 0;
}

.tp-issues {
  margin-top: 4px;
}

.tp-issue {
  padding: 7px 0 8px 10px;
  font: 400 12px/1.55 var(--tp-font-mono);
  color: var(--tp-fail);
  box-shadow: inset 2px 0 0 var(--tp-fail);
  border-bottom: 1px solid var(--tp-rule);
}

.tp-issue--warn {
  color: var(--tp-ink-2);
  box-shadow: inset 2px 0 0 var(--tp-rule-2);
}

.tp-issue--ok {
  color: var(--tp-pass);
  box-shadow: inset 2px 0 0 var(--tp-pass);
  border-bottom: 0;
}

.tp-detail-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 14px;
  margin-top: 22px;
}

.tp-detail-actions .tp-btn,
.tp-detail-actions .tp-btn-quiet {
  margin-top: 0;
  margin-left: 0;
}

/* ── admin: settings + audit ───────────────────────────────────────────── */

.tp-textarea {
  width: 100%;
  min-height: 190px;
  font: 400 12.5px/1.6 var(--tp-font-mono);
  color: var(--tp-ink);
  background: transparent;
  border: 1px solid var(--tp-rule-2);
  border-radius: 2px;
  padding: 11px 12px;
  resize: vertical;
}

.tp-textarea:focus,
.tp-textarea:focus-visible {
  outline: none;
  border-color: var(--tp-accent);
  box-shadow: inset 0 0 0 1px var(--tp-accent);
}

.tp-field--spaced {
  margin-top: 26px;
}

/* The one checkbox on the site. The native control, tinted with the accent —
   a drawn box would be a second focus treatment to keep in step with .tp-input
   and .tp-select for no gain. The text is the label, so the whole row is the
   hit target. */
.tp-check {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  cursor: pointer;
}

.tp-check input {
  flex: none;
  width: 15px;
  height: 15px;
  margin: 1px 0 0;
  accent-color: var(--tp-accent);
  cursor: pointer;
}

.tp-check-text {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--tp-ink-2);
}

.tp-settings-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 14px;
  margin-top: 8px;
}

.tp-data--audit {
  min-width: 720px;
}

.tp-audit-summary {
  max-width: 52ch;
  font: 400 11.5px/1.5 var(--tp-font-mono);
  color: var(--tp-ink-2);
  overflow-wrap: anywhere;
}

/* ── admin console ─────────────────────────────────────────────────────── */

/* Rail and content. The console keeps the portal's 900px column rather than
   widening to the review board's: these are pages of rows and forms, the tables
   that outgrow the measure already scroll inside .tp-scroll, and one width across
   the whole signed-in side means the bar overhead never shifts as you cross from
   the portal into administration. */
.tp-admin {
  display: grid;
  grid-template-columns: 176px minmax(0, 1fr);
  gap: 0 32px;
  align-items: start;
}

.tp-admin-body {
  min-width: 0;
}

/* It follows a long board down the page — nine links are cheaper to keep than to
   scroll back for. */
.tp-rail {
  display: grid;
  gap: 2px;
  position: sticky;
  top: 24px;
  padding-top: 8px;
  border-top: 1px solid var(--tp-rule-2);
}

/* Every item reserves the accent edge whether or not it is showing one, so no
   label moves by a pixel as you go down the rail. */
.tp-rail-item {
  font: 400 13px/1 var(--tp-font-ui);
  color: var(--tp-ink-2);
  text-decoration: none;
  padding: 9px 8px 9px 11px;
  border-left: 1px solid transparent;
  transition: color 130ms ease, border-color 130ms ease;
}

.tp-rail-item:hover {
  color: var(--tp-ink);
}

.tp-rail-item[aria-current="page"] {
  color: var(--tp-ink);
  border-left-color: var(--tp-accent);
}

/* ── stat tiles ────────────────────────────────────────────────────────── */

/* Each tile carries its own hairline rather than the row being one panel divided
   by gaps: a tile count that does not fill its last row is the normal case here
   (three on the overview, more later), and a divided panel draws the leftover
   cell as an empty box. */
.tp-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 8px;
  margin-top: 22px;
}

.tp-stat {
  display: grid;
  align-content: start;
  gap: 7px;
  min-width: 0;
  padding: 15px 16px 17px;
  border: 1px solid var(--tp-rule);
}

/* A tile that is a link is still a tile: the accent belongs to the hover, not to
   nine permanently blue numbers. */
a.tp-stat {
  color: inherit;
  text-decoration: none;
  transition: background-color 130ms ease, border-color 130ms ease;
}

a.tp-stat:hover {
  border-color: var(--tp-rule-2);
  background: var(--tp-paper-sunk);
}

a.tp-stat:hover .tp-stat-value {
  color: var(--tp-accent);
}

.tp-stat-label {
  font: 400 11px/1.4 var(--tp-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--tp-ink-3);
}

.tp-stat-value {
  font: 500 28px/1.05 var(--tp-font-ui);
  font-stretch: 96%;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--tp-ink);
  transition: color 130ms ease;
  overflow-wrap: anywhere;
}

.tp-stat-note {
  font: 400 11.5px/1.45 var(--tp-font-mono);
  color: var(--tp-ink-3);
}

/* ── filter bar + pager ────────────────────────────────────────────────── */

/* A plain GET form: it survives a reload, it is what gets pasted to somebody
   else, and it needs no script to exist. */
.tp-filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 10px;
  margin-top: 16px;
}

.tp-filters .tp-input {
  flex: 1 1 200px;
  width: auto;
  font-size: 13.5px;
  padding: 9px 11px;
}

.tp-filters .tp-select {
  flex: 0 1 150px;
}

.tp-filters .tp-btn {
  flex: none;
}

/* A filter row that is nothing but GET links (the cost window switcher). Pager
   typography, because both rows answer "where am I in this data"; the current
   one sits on full ink — it is a fact about the page, not an action — and
   aria-current says the same thing to a reader. */
.tp-filter-link {
  font: 400 12px/1.5 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--tp-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 130ms ease;
}

.tp-filter-link:hover {
  border-bottom-color: currentColor;
}

.tp-filter-link--on {
  color: var(--tp-ink);
}

.tp-pager {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin-top: 16px;
  font: 400 12px/1.5 var(--tp-font-mono);
  font-variant-numeric: tabular-nums;
}

.tp-pager-link {
  color: var(--tp-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 130ms ease;
}

.tp-pager-link:hover {
  border-bottom-color: currentColor;
}

/* The unavailable direction is a fact about where you are, not decoration, so it
   sits on ink-3 (5.0:1) and never on a hairline tint. */
.tp-pager-link--off {
  color: var(--tp-ink-3);
}

.tp-pager-count {
  color: var(--tp-ink-2);
}

@media (max-width: 1100px) {
  /* The rail becomes a strip above the page: one line, scrolled sideways when it
     must be. Wrapped into a block of links it would be a menu the content has to
     get past, every time, on the narrowest screens. */
  .tp-admin {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }

  /* Stacked, the strip's closing hairline would otherwise sit on the eyebrow. */
  .tp-admin-body {
    padding-top: 24px;
  }

  .tp-rail {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    position: static;
    gap: 0 2px;
    padding-top: 0;
    border-top: 0;
    border-bottom: 1px solid var(--tp-rule-2);
  }

  .tp-rail-item {
    flex: none;
    white-space: nowrap;
    padding: 7px 10px 9px;
    border-left: 0;
    border-bottom: 1px solid transparent;
  }

  .tp-rail-item[aria-current="page"] {
    border-bottom-color: var(--tp-accent);
  }
}

/* ── narrow viewports (phase 4 surfaces) ───────────────────────────────── */

@media (max-width: 1100px) {
  /* The PDF stops being useful long before the grid does; stack, document first. */
  .tp-detail {
    grid-template-columns: minmax(0, 1fr);
  }

  .tp-pdf-view {
    height: clamp(300px, 52vh, 620px);
  }
}

@media (max-width: 700px) {
  /* Two columns: the field name beside each agent reading, and Final gets the row
     to itself — it is the only cell you type in. */
  .tp-frow {
    grid-template-columns: minmax(92px, 0.8fr) minmax(0, 1fr);
    row-gap: 4px;
    padding-bottom: 10px;
  }

  .tp-frow--head .tp-ffinal {
    display: none;
  }

  .tp-frow .tp-fname {
    grid-row: span 2;
  }

  .tp-ffinal {
    grid-column: 1 / -1;
  }
}

/* ── narrow viewports ─────────────────────────────────────────────────── */

@media (max-width: 860px) {
  .tp-home {
    grid-template-columns: minmax(0, 1fr);
    padding-top: clamp(40px, 13svh, 120px);
  }

  .tp-home-spec {
    margin-top: 56px;
  }

  .tp-hero {
    grid-template-columns: minmax(0, 1fr);
    gap: 34px;
  }

  .tp-hero-spec {
    align-self: start;
  }

  /* Stacked, the spec's closing hairline sits a hair under the hero rule and
     reads as an empty row. One line is enough. */
  .tp-hero-spec .tp-spec-row:last-child {
    border-bottom: 0;
  }

  .tp-table th[scope="row"] {
    width: 42%;
  }

  .tp-sib > a {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .tp-sib-id {
    display: none;
  }
}

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

  .tp-sug-meta {
    justify-self: start;
  }
}

/* ── motion: one signature moment, everything else ~130ms ─────────────── */

@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* ── print: the certificate as a paper report ─────────────────────────── */

@page {
  margin: 16mm;
}

@media print {
  :root {
    --tp-paper: #fff;
    --tp-paper-sunk: #fff;
    --tp-ink: #000;
    --tp-ink-2: #333;
    --tp-ink-3: #555;
    --tp-rule: #bbb;
    --tp-rule-2: #666;
    --tp-accent: #000;
    --tp-accent-2: #000;
    --tp-shell: 100%;
    --tp-gutter: 0px;
  }

  body {
    font-size: 11pt;
    display: block;
  }

  .tp-head {
    padding-top: 0;
    border-bottom: 1px solid var(--tp-rule-2);
    padding-bottom: 6pt;
  }

  .tp-search,
  .tp-doc-frame,
  .tp-doc-links,
  .tp-foot,
  .tp-kbd {
    display: none;
  }

  .tp-doc-print {
    display: block;
    font-size: 10pt;
    color: var(--tp-ink-2);
  }

  .tp-hero {
    padding: 14pt 0;
    break-after: avoid;
  }

  .tp-metric-value {
    font-size: 46pt;
  }

  .tp-verdict {
    font-size: 24pt;
  }

  .tp-product {
    font-size: 22pt;
  }

  .tp-section {
    padding-top: 16pt;
    break-inside: avoid;
  }

  .tp-table tr,
  .tp-spec-row {
    break-inside: avoid;
  }

  .tp-table th,
  .tp-table td {
    padding: 5pt 0;
  }
}
