/* headlint — design tokens & foundation.
   Palette: light "editor theme" — cool paper, navy ink, and one syntax-derived
   hue per tool: amber = favicon, teal = preview, iris = validator. */

:root {
  --paper: #f6f7f9;
  --surface: #ffffff;
  --ink: #16192b;
  --ink-2: #4a5068;
  --line: #e3e5ec;
  --code-bg: #eef0f5;

  --iris: #5348c7;
  --iris-soft: #edecfa;
  --teal: #0e7c6b;
  --teal-soft: #e6f4f1;
  --amber: #b45309;
  --amber-soft: #faf1e6;

  --ok: #15803d;
  --warn: #b45309;
  --err: #b91c1c;

  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --radius: 8px;
  --content: 60rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #12141c;
    --surface: #1a1d28;
    --ink: #e8eaf2;
    --ink-2: #9ba1b5;
    --line: #2a2e3d;
    --code-bg: #232734;

    --iris: #8b83e8;
    --iris-soft: #262347;
    --teal: #34c0a9;
    --teal-soft: #10312c;
    --amber: #e8963e;
    --amber-soft: #382510;

    --ok: #4ade80;
    --warn: #e8963e;
    --err: #f87171;
  }
}

@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter-latin-500-normal.woff2') format('woff2');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter-latin-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/assets/fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/assets/fonts/jetbrains-mono-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}

/* Text-favicon preview fonts — the same files the server renders with. */
@font-face {
  font-family: 'Liberation Sans';
  src: url('/assets/fonts/liberation/LiberationSans-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Liberation Serif';
  src: url('/assets/fonts/liberation/LiberationSerif-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Liberation Mono';
  src: url('/assets/fonts/liberation/LiberationMono-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}

/* ---- base ---- */

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 1rem/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  font-family: var(--mono);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 0 0 0.5rem;
}

h1 {
  font-size: clamp(1.6rem, 4vw, 2.3rem);
}
h2 {
  font-size: clamp(1.2rem, 3vw, 1.5rem);
  margin-top: 3rem;
}
h3 {
  font-size: 1.05rem;
  margin-top: 1.5rem;
}

p {
  margin: 0.5rem 0 1rem;
}

a {
  color: var(--iris);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
a:hover {
  text-decoration-thickness: 2px;
}

code,
pre {
  font-family: var(--mono);
  font-size: 0.875em;
}

code {
  background: var(--code-bg);
  padding: 0.1em 0.35em;
  border-radius: 4px;
}

pre {
  background: var(--code-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1rem;
  overflow-x: auto;
  line-height: 1.55;
}
pre code {
  background: none;
  padding: 0;
}

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

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

/* ---- shell ---- */

.shell {
  max-width: var(--content);
  margin: 0 auto;
  padding: 0 1.25rem;
}

.site-header {
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.site-header .shell {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 3.5rem;
  flex-wrap: wrap;
}

.logo {
  font-family: var(--mono);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--ink);
  text-decoration: none;
}
.logo .bracket {
  color: var(--iris);
}

.site-nav {
  display: flex;
  gap: 1.25rem;
  margin-left: auto;
  flex-wrap: wrap;
}
.site-nav a {
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ink-2);
  text-decoration: none;
}
.site-nav a:hover,
.site-nav a[aria-current='page'] {
  color: var(--ink);
}
.site-nav a[aria-current='page'] {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}

main.shell {
  padding-top: 2.5rem;
  padding-bottom: 4rem;
}

.site-footer {
  border-top: 1px solid var(--line);
  padding: 1.5rem 0 2.5rem;
  color: var(--ink-2);
  font-size: 0.85rem;
}
.site-footer .shell {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.site-footer a {
  color: var(--ink-2);
}

/* ---- eyebrows: tag-syntax section labels ---- */

.eyebrow {
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 400;
  display: block;
  margin-bottom: 0.35rem;
}
.eyebrow .bracket {
  color: var(--ink-2);
}
.eyebrow--favicon {
  color: var(--amber);
}
.eyebrow--preview {
  color: var(--teal);
}
.eyebrow--meta {
  color: var(--iris);
}

.lead {
  font-size: 1.05rem;
  color: var(--ink-2);
  max-width: 44rem;
}

/* The one tag rendered inside a heading wears the tag color, same as the hero. */
h1 .tag {
  color: var(--iris);
}

/* Small Inter note directly under a .url-form ("…or pick a single checker"). */
.form-hint {
  font-size: 0.8rem;
  color: var(--ink-2);
  margin: -1rem 0 0;
}

/* ---- signature: the annotated <head> index (home) ----
   One panel that is both the brand device and the navigation: real head markup
   in the left column, the checker that verifies each line in the right. It
   replaced a decorative markup hero sitting above a card grid of the same ten
   tools — two lists of one thing, neither dense enough to scan. Lines run in
   loading-priority order, so the panel never models a head we would flag. */

.head-index {
  margin: 1rem 0 2.5rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  /* No `overflow: hidden` here: it would keep the hover fill inside the panel's
     rounded corners, but it also clips the global 2px focus ring off every row.
     The end rows round their own corners instead (below), so the fill still
     follows the panel and a keyboard ring stays fully visible. */
  /* The markup column is sized once, on the panel, and every row borrows it
     through subgrid — so the code lines align down the list without a magic
     track width, and the column is exactly as wide as its longest line. */
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
}

.hx-row {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  /* baseline, not center: the markup line and the tool name are the row's first
     line, and the gloss hangs beneath the name. */
  align-items: baseline;
  gap: 0.15rem 1.5rem;
  padding: 0.7rem 1.25rem;
  color: var(--ink);
  text-decoration: none;
  border-top: 1px solid var(--line);
}
.hx-row:first-child {
  border-top: 0;
  border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0;
}
.hx-row:last-child {
  border-radius: 0 0 calc(var(--radius) - 1px) calc(var(--radius) - 1px);
}
a.hx-row:hover,
a.hx-row:focus-visible {
  background: var(--code-bg);
}

/* Two lines no tool owns — charset and viewport. They keep the modelled head in
   the order capo.js actually wants, so they are context rather than navigation:
   no name, no hover, not a link. */
.hx-row--context {
  padding-top: 0.35rem;
  padding-bottom: 0.35rem;
}
/* The two of them read as one preamble block; the hairline before the first
   named entry stays. */
.hx-row--context + .hx-row--context {
  border-top: 0;
}
/* The note fills the band's right column. Left empty, the panel's only hole sat
   second from the top and read as two entries whose tool names failed to load. */
.hx-note {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-2);
}

/* The markup itself, in the three syntax hues. */
.hx-code {
  font-family: var(--mono);
  /* Floor 0.75rem: the row's own padding keeps every link far above the WCAG
     2.2 24px target minimum, so the type can stay compact. */
  font-size: clamp(0.75rem, 1.7vw, 0.85rem);
  white-space: pre;
  color: var(--ink-2);
  /* Grid items floor at min-content, and a non-wrapping markup line has a wide
     one: without this the longest line widens the whole page on a phone instead
     of scrolling inside its own row. */
  min-width: 0;
}
.hx-code .tag {
  color: var(--iris);
}
.hx-code .attr {
  color: var(--teal);
}
.hx-code .val {
  color: var(--amber);
}

.hx-name {
  font-family: var(--mono);
  font-weight: 700;
  font-size: 0.9rem;
  transition: color 120ms;
}
/* At rest the row is ink; the destination family's hue arrives on hover and
   focus. This is the family axis's only appearance on this page — see The Three
   Hues Rule in DESIGN.md for why it has no resting carrier here. */
.hx-row--meta:hover .hx-name,
.hx-row--meta:focus-visible .hx-name {
  color: var(--iris);
}
.hx-row--preview:hover .hx-name,
.hx-row--preview:focus-visible .hx-name {
  color: var(--teal);
}
.hx-row--favicon:hover .hx-name,
.hx-row--favicon:focus-visible .hx-name {
  color: var(--amber);
}

.hx-gloss {
  grid-column: 2;
  font-size: 0.85rem;
  color: var(--ink-2);
}

/* Narrow: the markup stacks above the tool it belongs to. Below this width the
   two tracks would leave the gloss a column too thin to read. */
@media (max-width: 54rem) {
  .head-index {
    grid-template-columns: minmax(0, 1fr);
  }
  .hx-row {
    gap: 0.2rem;
  }
  .hx-code,
  .hx-gloss {
    grid-column: 1;
  }
  .hx-code {
    /* Soft-wrap the markup the way an editor does, rather than scrolling it: a
       clipped line ends mid-attribute with nothing to say it continues, and a
       hidden scrollbar is not an affordance on a phone. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
}

/* No family-hue legend on this page: inside the index panel iris, teal and
   amber already mean tag, attribute and value, so glossing the same three hues
   as tool families one line below would give them two meanings in one view. The
   family hue arrives on hover and focus (above); the tool pages carry the axis
   at rest, on their eyebrows and submit buttons. */

/* The home page's proof block borrows the report's masthead grammar
   (.record-meta: mono term over a plain-language value on a hairline surface),
   but its values are whole sentences rather than single fields, so the rows need
   more air between them than the masthead's field pairs do. */
.record-meta--proof {
  gap: 1.4rem 2.5rem;
  padding: 1.25rem;
}

/* ---- forms & buttons ---- */

.field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin-bottom: 1rem;
}
.field label {
  font-size: 0.85rem;
  font-weight: 600;
}
.field input[type='text'],
.field input[type='url'],
.field select,
.field textarea {
  font: inherit;
  color: inherit;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.55rem 0.75rem;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--iris);
  outline: none;
}
.field .hint {
  font-size: 0.8rem;
  color: var(--ink-2);
}

.url-form {
  display: flex;
  gap: 0.6rem;
  margin: 1.5rem 0;
  flex-wrap: wrap;
}
.url-form input[name='url'] {
  flex: 1;
  min-width: 16rem;
  font: inherit;
  color: inherit;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.6rem 0.8rem;
}
.url-form input[name='url']:focus {
  border-color: var(--iris);
  outline: none;
}

.btn {
  font: 600 0.95rem var(--sans);
  color: #fff;
  background: var(--iris);
  border: none;
  border-radius: var(--radius);
  padding: 0.6rem 1.2rem;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
}
.btn:hover {
  filter: brightness(1.1);
}
.btn--favicon {
  background: var(--amber);
}
.btn--preview {
  background: var(--teal);
}
.btn:disabled {
  opacity: 0.5;
  cursor: default;
}

.btn-secondary {
  font: 500 0.85rem var(--sans);
  color: var(--ink);
  background: var(--code-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.4rem 0.8rem;
  cursor: pointer;
}
.btn-secondary:hover {
  border-color: var(--ink-2);
}

/* ---- spec tables ---- */

table {
  border-collapse: collapse;
  width: 100%;
  margin: 1rem 0;
  font-size: 0.9rem;
}
th,
td {
  text-align: left;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--line);
}
th {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 400;
  color: var(--ink-2);
}
td code {
  white-space: nowrap;
}
.table-scroll {
  overflow-x: auto;
}

/* ---- structured data ---- */

.sd-blocks {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin: 0.75rem 0 1rem;
}
.sd-block-chip code {
  font-size: 0.78rem;
}

/* ---- indexability verdict ---- */

.verdict {
  display: flex;
  align-items: baseline;
  gap: 0.8rem;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left-width: 3px;
  border-radius: var(--radius);
  margin: 1.25rem 0;
}
.verdict p {
  margin: 0;
}
.verdict--ok {
  border-left-color: var(--ok);
}
.verdict--warn {
  border-left-color: var(--warn);
}
.verdict--error {
  border-left-color: var(--err);
}
.verdict .sev {
  font-size: 0.8rem;
  padding: 0.2rem 0.6rem;
  white-space: nowrap;
}

/* ---- redirect chain ---- */

.chain {
  list-style: none;
  margin: 1.25rem 0;
  padding: 0;
}
.chain-hop {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.45rem 0.6rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
  margin-bottom: 0;
  font-size: 0.88rem;
  overflow-wrap: anywhere;
}
.chain-hop + .chain-hop {
  margin-top: 1.4rem;
  position: relative;
}
.chain-hop + .chain-hop::before {
  content: '↓';
  position: absolute;
  top: -1.35rem;
  left: 1rem;
  color: var(--ink-2);
  font-size: 0.9rem;
}
.chain-arrow {
  display: none;
}
.chain-hop--canonical {
  border-style: dashed;
}

/* ---- head-order analyzer ---- */

.ho-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: 1.5rem;
  margin: 1.5rem 0;
}
.ho-list {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.ho-el {
  display: grid;
  grid-template-columns: 1.6rem 1fr;
  grid-template-areas: 'w label' 'w cat';
  column-gap: 0.55rem;
  padding: 0.4rem 0.6rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 0.8rem;
  min-width: 0;
}
.ho-weight {
  grid-area: w;
  align-self: center;
  font-family: var(--mono);
  font-weight: 700;
  font-size: 0.72rem;
  text-align: center;
  border-radius: 4px;
  padding: 0.25rem 0;
  color: #fff;
}
.ho-el--early .ho-weight {
  background: var(--iris);
}
.ho-el--network .ho-weight {
  background: var(--teal);
}
.ho-el--render .ho-weight {
  background: var(--amber);
}
.ho-el--hint .ho-weight {
  background: var(--ink-2);
}
.ho-el--other .ho-weight {
  background: var(--line);
  color: var(--ink-2);
}
.ho-label {
  grid-area: label;
  background: none;
  padding: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.ho-cat {
  grid-area: cat;
  font-size: 0.7rem;
  color: var(--ink-2);
}
.ho-el--misplaced {
  border-color: var(--warn);
}
.ho-el--misplaced .ho-cat {
  color: var(--warn);
}
.ho-el--invalid {
  border-color: var(--err);
}
.ho-el--invalid .ho-cat {
  color: var(--err);
}
.ho-el--collapsed {
  border-style: dashed;
  background: none;
}
.ho-el--collapsed .ho-label {
  color: var(--ink-2);
}

/* ---- SERP snippet replica ---- */
/* Fixed palette: it must look like Google's result page, not like this site. */

.serp-card {
  max-width: 600px;
  background: #fff;
  border: 1px solid #dadce0;
  border-radius: 12px;
  padding: 1.1rem 1.25rem;
  margin: 1.5rem 0 1rem;
  font-family: Arial, sans-serif;
}
.serp-src {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.55rem;
}
.serp-favicon {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #f1f3f4;
  border: 1px solid #ecedef;
  display: grid;
  place-items: center;
  font: 700 13px Arial, sans-serif;
  color: #5f6368;
  flex: none;
}
.serp-src-lines {
  display: flex;
  flex-direction: column;
  line-height: 1.3;
  min-width: 0;
}
.serp-site {
  font-size: 14px;
  color: #202124;
}
.serp-url {
  font-size: 12px;
  color: #4d5156;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.serp-title {
  display: block;
  font-size: 20px;
  line-height: 1.3;
  color: #1a0dab;
  margin-bottom: 0.3rem;
  cursor: pointer;
}
.serp-title:hover {
  text-decoration: underline;
}
.serp-desc {
  font-size: 14px;
  line-height: 1.58;
  color: #474747;
  margin: 0;
}

@media (prefers-color-scheme: dark) {
  .serp-card {
    background: #202124;
    border-color: #3c4043;
  }
  .serp-site {
    color: #dadce0;
  }
  .serp-url {
    color: #bdc1c6;
  }
  .serp-favicon {
    background: #303134;
    border-color: #3c4043;
    color: #9aa0a6;
  }
  .serp-title {
    color: #99c3ff;
  }
  .serp-desc {
    color: #bdc1c6;
  }
}

/* ---- favicon checker: asset table ---- */

/* Long icon URLs must wrap, or they shove the verdict columns off-screen —
   but never below a readable column width: past that, .table-scroll takes over. */
.asset-table td code {
  white-space: normal;
  overflow-wrap: anywhere;
}
.asset-table .asset-file {
  min-width: 22ch;
}
.asset-table th {
  white-space: nowrap;
}
.asset-table td:last-child .sev,
.asset-table td:first-child code {
  white-space: nowrap;
}

/* ---- FAQ ---- */

details {
  border-bottom: 1px solid var(--line);
  padding: 0.75rem 0;
}
summary {
  font-weight: 600;
  cursor: pointer;
}
details p {
  margin-top: 0.6rem;
  color: var(--ink-2);
}

/* ---- findings (validation results) ---- */

.finding {
  display: grid;
  /* minmax(0, 1fr), not 1fr: a bare 1fr floors at min-content, so a fix-it
     snippet in a <pre> (which does not wrap) forced the TRACK wider than the
     viewport. The <pre> itself already scrolls — `overflow-x: auto` on the base
     `pre` rule above — but a blown-out track meant it never had to. Capping the
     track is what lets that scrolling do its job. Verified at 390px with an
     843px snippet: page width stays 390. Affects every checker page that
     renders a fix snippet on a narrow screen, not just the report. */
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.6rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.92rem;
}
.finding .sev {
  font-family: var(--mono);
  font-size: 0.72rem;
  align-self: start;
  margin-top: 0.15rem;
  padding: 0.1rem 0.45rem;
  border-radius: 4px;
  white-space: nowrap;
}
.sev--error {
  color: var(--err);
  background: color-mix(in srgb, var(--err) 12%, transparent);
}
.sev--warn {
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 12%, transparent);
}
.sev--info {
  color: var(--ink-2);
  background: var(--code-bg);
}
.sev--ok {
  color: var(--ok);
  background: color-mix(in srgb, var(--ok) 12%, transparent);
}
.finding pre {
  margin: 0.5rem 0 0;
  padding: 0.6rem 0.8rem;
  font-size: 0.8rem;
}

/* ---- favicon tool ---- */

.favicon-form {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin: 1.5rem 0;
}

.favicon-form fieldset {
  border: none;
  padding: 0;
  margin: 0 0 1rem;
}
.favicon-form legend {
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--ink-2);
  padding: 0;
  margin-bottom: 0.5rem;
}

/* Without JS all mode sections show, radios pick the mode; JS turns them into tabs. */
.mode-tabs {
  display: flex;
  gap: 0.25rem;
  margin-bottom: 1.25rem;
  border-bottom: 1px solid var(--line);
}
.mode-tab {
  cursor: pointer;
  padding: 0.45rem 1rem;
  font: 600 0.9rem var(--sans);
  color: var(--ink-2);
  border-bottom: 2px solid transparent;
}
.mode-tab:has(input:checked) {
  color: var(--amber);
  border-bottom-color: var(--amber);
}
.favicon-form.js .mode-tab input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.field-row {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}
.field-row .field {
  min-width: 7rem;
}
.field input[type='color'] {
  inline-size: 3.5rem;
  block-size: 2.4rem;
  padding: 0.15rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.field input[type='file'] {
  font-size: 0.9rem;
}

.package-options {
  border-top: 1px solid var(--line) !important;
  padding-top: 1rem !important;
}

/* preview contexts */
.pv-grid {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  margin: 1.25rem 0;
}
.pv {
  margin: 0;
  text-align: center;
}
.pv figcaption {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-2);
  margin-top: 0.4rem;
}
.pv-slot {
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.pv-slot > * {
  display: block;
}
.pv--tab-light .pv-slot {
  width: 12rem;
  height: 2.2rem;
  background: #dee1e6;
  border-radius: 10px 10px 0 0;
  grid-template-columns: 1.5rem 1fr;
  padding: 0 0.5rem;
  place-items: center start;
}
.pv--tab-light .pv-slot::after {
  content: 'Your page title';
  font: 0.72rem var(--sans);
  color: #202124;
  white-space: nowrap;
  overflow: hidden;
}
.pv--tab-dark .pv-slot {
  width: 12rem;
  height: 2.2rem;
  background: #202124;
  border-radius: 10px 10px 0 0;
  grid-template-columns: 1.5rem 1fr;
  padding: 0 0.5rem;
  place-items: center start;
}
.pv--tab-dark .pv-slot::after {
  content: 'Your page title';
  font: 0.72rem var(--sans);
  color: #e8eaed;
  white-space: nowrap;
  overflow: hidden;
}
.pv--tab-light .pv-slot > *,
.pv--tab-dark .pv-slot > * {
  width: 16px;
  height: 16px;
}
.pv--ios .pv-slot {
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 22.5%;
  background: var(--code-bg);
}
.pv--ios .pv-slot > * {
  width: 100%;
  height: 100%;
  border-radius: 22.5%;
  object-fit: cover;
}
.pv--android .pv-slot {
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  background: var(--code-bg);
}
.pv--android .pv-slot > * {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

/* generated (text/emoji) icon rendering inside previews */
.pv-gen {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  font-weight: 700;
  line-height: 1;
}
.pv-gen--rounded {
  border-radius: 20%;
}
.pv-gen--circle {
  border-radius: 50%;
}
.pv-gen--font-sans {
  font-family: 'Liberation Sans', Arial, sans-serif;
}
.pv-gen--font-serif {
  font-family: 'Liberation Serif', 'Times New Roman', serif;
}
.pv-gen--font-mono {
  font-family: 'Liberation Mono', Consolas, monospace;
}
.pv-native-emoji {
  font-size: 200%;
}

.form-error {
  color: var(--err);
  font-weight: 600;
}

.tool-result {
  border-top: 1px solid var(--line);
  margin-top: 2rem;
}
.warnings {
  color: var(--warn);
  font-size: 0.9rem;
}
.warnings:empty {
  display: none;
}
.snippet-tabs {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
  margin-bottom: 0.6rem;
}
.snippet-tabs button[aria-selected='true'] {
  border-color: var(--amber);
  color: var(--amber);
}

/* ---- preview checker: platform report + card replicas ---- */

.fetch-summary {
  font-size: 0.85rem;
  color: var(--ink-2);
  overflow-wrap: anywhere;
}

.platform-report {
  border-top: 1px solid var(--line);
  padding: 1.5rem 0;
}
.platform-report h3 {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.verified-at {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 400;
  color: var(--ink-2);
}
.verified-at a {
  color: var(--ink-2);
}

.provenance {
  font-size: 0.8rem;
  color: var(--ink-2);
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
}
.prov-item code {
  color: var(--teal);
}

/* Card replicas: platform-plausible approximations with fixed (non-themed)
   palettes — a card must look like its platform, not like this site. */
.card {
  max-width: 31rem;
  border-radius: 12px;
  overflow: hidden;
  margin: 0.75rem 0;
  font-size: 0.9rem;
  line-height: 1.35;
  background: #fff;
  color: #0f1419;
  border: 1px solid #d0d7de;
}
.card--compact {
  display: flex;
  align-items: stretch;
  gap: 0;
}
.card--compact .card-body {
  flex: 1;
  min-width: 0;
}
.card--compact .card-img {
  flex: 0 0 5.5rem;
  width: 5.5rem;
  object-fit: cover;
  border-left: 1px solid #d0d7de;
}
.card--large .card-img {
  width: 100%;
  object-fit: cover;
  display: block;
}
.card-img--missing {
  display: grid;
  place-items: center;
  background: #e8ebee;
  color: #66757f;
  font: 0.75rem var(--mono);
  min-height: 4rem;
}
.card-body {
  padding: 0.7rem 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.card-site {
  font-size: 0.78rem;
  color: #536471;
  text-transform: lowercase;
}
.card-title {
  font-weight: 700;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.card-desc {
  color: #536471;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card--x {
  border-radius: 16px;
  font-family: -apple-system, 'Segoe UI', sans-serif;
}
.card--facebook {
  border-radius: 0;
  background: #f2f3f5;
  font-family: Helvetica, Arial, sans-serif;
}
.card--facebook .card-site {
  text-transform: uppercase;
  font-size: 0.72rem;
}
.card--linkedin {
  border-radius: 2px;
  font-family: -apple-system, 'Segoe UI', sans-serif;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
  border: none;
}
.card--slack {
  border: none;
  border-left: 4px solid #dddddd;
  border-radius: 4px;
  background: transparent;
  color: var(--ink);
  font-family: Lato, sans-serif;
}
.card--slack .card-title {
  color: #1264a3;
}
.card--slack .card-desc,
.card--slack .card-site {
  color: var(--ink-2);
}
.card--discord {
  background: #2b2d31;
  color: #dbdee1;
  border: none;
  border-left: 4px solid #1e1f22;
  border-radius: 4px;
  font-family: 'gg sans', 'Noto Sans', sans-serif;
}
.card--discord .card-title {
  color: #00a8fc;
}
.card--discord .card-site,
.card--discord .card-desc {
  color: #b5bac1;
}
.card--imessage {
  border-radius: 18px;
  background: #e9e9eb;
  border: none;
  color: #000;
  font-family: -apple-system, 'SF Pro Text', sans-serif;
}
.card--whatsapp {
  border-radius: 8px;
  background: #d9fdd3;
  border: none;
  color: #111b21;
  font-family: -apple-system, Roboto, sans-serif;
}
.card--whatsapp .card-site,
.card--whatsapp .card-desc {
  color: #667781;
}
.card--telegram {
  border: none;
  border-left: 3px solid #3390ec;
  border-radius: 4px;
  background: transparent;
  color: var(--ink);
  font-family: Roboto, -apple-system, sans-serif;
}
.card--telegram .card-site {
  color: #3390ec;
  font-weight: 600;
}

@media (prefers-color-scheme: dark) {
  .card {
    border-color: #38444d;
  }
  .card--x {
    background: #15202b;
    color: #f7f9f9;
  }
  .card--facebook {
    background: #3a3b3c;
    color: #e4e6eb;
  }
  .card--facebook .card-site,
  .card--facebook .card-desc {
    color: #b0b3b8;
  }
  .card--linkedin {
    background: #1b1f23;
    color: #f5f5f5;
  }
  .card--imessage {
    background: #3b3b3d;
    color: #fff;
  }
  .card--whatsapp {
    background: #005c4b;
    color: #e9edef;
  }
  .card--whatsapp .card-site,
  .card--whatsapp .card-desc {
    color: #99beb7;
  }
}

/* ---- meta validator: truncation bars + generator ---- */

.trunc {
  margin: 0.6rem 0;
  max-width: 40rem;
}
.trunc-bar {
  position: relative;
  height: 6px;
  background: var(--code-bg);
  border-radius: 3px;
  overflow: hidden;
}
/* Budget tick: where the platform's limit falls when the text overruns it. */
.trunc-limit {
  position: absolute;
  top: -1px;
  bottom: -1px;
  width: 2px;
  margin-left: -1px;
  background: var(--ink);
}
.trunc-bar span {
  display: block;
  height: 100%;
  background: var(--ok);
  border-radius: 3px;
}
.trunc-bar span.over {
  background: var(--warn);
}
.trunc-text {
  font-size: 0.85rem;
  margin: 0.3rem 0 0;
  overflow-wrap: anywhere;
}
.trunc-text mark {
  background: color-mix(in srgb, var(--warn) 25%, transparent);
  color: inherit;
  text-decoration: line-through;
}
.trunc-count {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-2);
}

.finding-cta {
  display: inline-block;
  margin-top: 0.4rem;
  font-weight: 600;
}

.generator-form {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin: 1rem 0;
}
.generator-form textarea {
  resize: vertical;
}
.generator-result {
  margin: 1rem 0 2rem;
}
.live-measure:empty {
  display: none;
}
.copy-fix {
  margin: 0.25rem 0 0.5rem;
}

/* ---- the findings as a brief for a coding agent ----
   A closed <details> after the findings: the brief is long by design, and the
   page already shows every finding it contains, so it opens on request. */
.agent-prompt {
  margin: 1.25rem 0 0.5rem;
  border-top: 1px solid var(--line);
}
.agent-prompt > summary {
  font-family: var(--mono);
  font-size: 0.85rem;
}
.agent-prompt > p {
  font-size: 0.9rem;
}
.agent-prompt > p code {
  overflow-wrap: anywhere;
}
.agent-prompt .btn-secondary {
  margin: 0.5rem 0;
}
/* Wrapped, not scrolled sideways: a brief is prose with snippets in it, and
   the reader is checking what they are about to hand over, not copying a line. */
.agent-prompt-text {
  max-height: 28rem;
  overflow: auto;
  white-space: pre-wrap;
  font-size: 0.78rem;
  margin: 0.5rem 0 0;
}

/* ---- cross-tool CTA ---- */

.next-step {
  display: block;
  margin: 2rem 0;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--iris);
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--ink);
}
.next-step:hover {
  border-color: var(--ink-2);
}
.next-step--favicon {
  border-left-color: var(--amber);
}
.next-step--preview {
  border-left-color: var(--teal);
}
.next-step .eyebrow {
  margin-bottom: 0.1rem;
}

/* ---- full head report: the inspection record ----
   A dated record, not a dashboard: hairline rules, mono field labels, severity
   chips as stamps, and exactly one 3px accent edge — on the conclusion. No
   shadows, no gauges, no new hue. Every colour is a token, so the dark scheme
   is inherited rather than reimplemented. */

.record {
  margin: 2rem 0;
}
.record-note {
  font-size: 0.9rem;
  color: var(--ink-2);
  max-width: 44rem;
}

/* Masthead: what was inspected, when, against which rubric. */
.record-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0.75rem 1.5rem;
  margin: 1rem 0 1.5rem;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.record-meta--stacked {
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
}
.record-meta dt {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-2);
}
.record-meta dd {
  margin: 0.15rem 0 0;
  font-size: 0.9rem;
  overflow-wrap: anywhere;
}
.record-meta dd code {
  background: none;
  padding: 0;
  font-size: 0.85rem;
}

/* The manifest: every check named before (and while) it runs. */
.record-manifest {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  border-top: 1px solid var(--line);
}
/* Column widths are FIXED, not fractional: each row is its own grid container,
   so content-sized tracks would resolve per row and the columns would not line
   up down the list. */
.record-manifest-row {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr) 12rem;
  gap: 0.6rem 1rem;
  /* baseline, not center: the name is the row's first line, so the standard and
     the maximum sit on the line they describe instead of floating between the
     name and the tag-syntax label beneath it. */
  align-items: baseline;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--line);
}
.record-manifest--compact .record-manifest-row {
  /* Single track: the compact list is navigation, so it carries no cap column. */
  grid-template-columns: minmax(0, 1fr);
  padding: 0.45rem 0;
}
.record-manifest-name {
  display: flex;
  flex-direction: column;
  font-weight: 500;
}
.record-manifest-name .eyebrow {
  margin: 0.1rem 0 0;
}
.record-manifest-name a {
  color: var(--ink);
  text-decoration: none;
}
.record-manifest-name a:hover {
  color: var(--iris);
  text-decoration: underline;
}
.record-manifest-standard {
  font-size: 0.85rem;
  color: var(--ink-2);
}
.record-manifest-budget {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-2);
  white-space: nowrap;
  text-align: right;
}

/* One item of the record. Separation is a hairline, as everywhere else —
   eight accent edges would be noise, so the hue lives in the eyebrow. */
.record-item {
  border-top: 1px solid var(--line);
  padding: 1.25rem 0 0.5rem;
}
.record-item > h2 {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 0.5rem;
  /* The documented "title" step: these read as the h3-scale section heads that
     .platform-report already uses, despite being h2 semantically. */
  font-size: 1.05rem;
}
.record-cost {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 400;
  color: var(--ink-2);
  margin-left: auto;
}
.record-item-standard {
  font-size: 0.85rem;
  color: var(--ink-2);
  margin: 0.35rem 0 1rem;
}
/* Stamps and inline chips need the padded chip treatment that .finding gives
   them; the base .sev rule only carries colour. */
.record-item > h2 .sev,
.record-manifest .sev,
.ledger .sev,
.record-exhibit .sev,
.sd-blocks .sev {
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.1rem 0.45rem;
  border-radius: 4px;
  white-space: nowrap;
}

/* Exhibits: evidence, explicitly worth no points. */
.record-exhibit {
  margin: 0 0 1.25rem;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.record-exhibit figcaption {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-2);
  margin-top: 0.75rem;
}
.record-exhibit table {
  margin: 0;
}
.record-exhibit .chain {
  margin: 0;
}
.record-exhibit .ho-list {
  gap: 0.4rem;
}
.record-exhibit .verdict {
  margin: 0;
}

.record-fix {
  display: inline-block;
  margin: 0.75rem 0 0.5rem;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--iris);
}
.record-fix.next-step--preview {
  color: var(--teal);
}
.record-fix.next-step--favicon {
  color: var(--amber);
}

/* The result: the grade as arithmetic you can check, not a gauge. */
.record-result {
  border-top: 1px solid var(--line);
  padding-top: 0.5rem;
}
.ledger-key {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-2);
  margin: 0 0 0.75rem;
}
.ledger {
  width: 100%;
}
.ledger th[scope='row'] {
  font-weight: 500;
  white-space: nowrap;
}
.ledger th[scope='row'] a {
  color: var(--ink);
  text-decoration: none;
}
.ledger th[scope='row'] a:hover {
  text-decoration: underline;
}
.ledger-num {
  font-family: var(--mono);
  text-align: right;
  white-space: nowrap;
}
.ledger-row--incomplete th[scope='row'],
.ledger-row--incomplete td {
  color: var(--ink-2);
}
.ledger tfoot tr {
  border-top: 1px solid var(--line);
}
.ledger tfoot th[scope='row'] {
  font-family: var(--mono);
  font-size: 0.8rem;
}
/* The grade sits in the total row it results from, at display scale. */
.ledger-grade th[scope='row'] {
  font-size: 0.9rem;
  font-weight: 700;
}
.ledger-grade td {
  color: var(--ink-2);
}
.ledger-grade .ledger-num {
  color: var(--ink);
}
.ledger-grade strong {
  font-family: var(--mono);
  /* The floor of DESIGN.md's display clamp — the page's one display moment,
     taken from the ramp rather than invented for this table. */
  font-size: 1.6rem;
  letter-spacing: -0.02em;
}
.ledger-grade--void .ledger-num,
.ledger-grade--void strong {
  /* Disqualified: the grade stays readable but yields the emphasis to the band. */
  color: var(--ink-2);
  font-weight: 400;
}
.ledger-of {
  font-family: var(--mono);
  font-size: 0.85rem;
  color: var(--ink-2);
  margin-left: 0.25rem;
}

.record-rubric {
  margin-top: 1rem;
}
.record-rubric p {
  margin-top: 0.6rem;
  color: var(--ink-2);
  max-width: 44rem;
}
.rubric-list {
  margin: 0.75rem 0 0.25rem;
  padding-left: 1.1rem;
  font-size: 0.9rem;
  color: var(--ink-2);
  max-width: 44rem;
}
.rubric-list li {
  margin-bottom: 0.4rem;
}
.rubric-list strong {
  color: var(--ink);
}

.record-provenance {
  border-top: 1px solid var(--line);
  padding-top: 0.5rem;
}

@media (max-width: 34rem) {
  .record-manifest-row {
    grid-template-columns: 1fr auto;
  }
  /* The standard spans the full width beneath the name rather than squeezing
     into a third column nobody can read. */
  .record-manifest-standard {
    grid-column: 1 / -1;
  }
  .record-cost {
    margin-left: 0;
  }

  /* Keep the result's arithmetic visible as one table on phones. The generic
     table treatment preserves min-content widths and scrolls, which let this
     ledger's Cost column (and the grade it contains) sit off-screen on iPhone.
     This ledger has four short, known columns, so give them an explicit mobile
     measure and let only the long item names wrap. */
  .ledger {
    table-layout: fixed;
    font-size: 0.85rem;
  }
  .ledger th,
  .ledger td {
    padding-inline: 0.35rem;
  }
  .ledger thead th:nth-child(1) {
    width: 40%;
  }
  .ledger thead th:nth-child(2) {
    width: 27%;
  }
  .ledger thead th:nth-child(3) {
    width: 13%;
  }
  .ledger thead th:nth-child(4) {
    width: 20%;
  }
  .ledger th[scope='row'] {
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .ledger .sev {
    white-space: normal;
  }
  .ledger-of {
    display: block;
    margin-left: 0;
  }
}
