@layer tokens, base, components, templates, pages, utilities;

/* == tokens.css == */
@layer tokens {
/* Datapink design tokens — Direction B (Paper & Ink)
   Generated from the approved design canvas. Do not hand-edit: change the canvas, re-export. */

:root {
  /* ground */
  --dp-bg: #FAFAF7;
  --dp-surface: #FFFFFF;
  --dp-surface-subtle: #F1F2EE;
  --dp-border: #E1E3DD;

  /* text */
  --dp-text: #14171F;
  --dp-text-secondary: #4B5262;
  --dp-text-muted: #7A8194;        /* non-text use only — 3.7:1 on --dp-bg */

  /* accent — pink is an accent, never a full-bleed background behind long text */
  --dp-pink-500: #E5397A;          /* focus ring, active node, active tab underline */
  --dp-pink-600: #C42A64;          /* primary CTA fill, small pink text — 5.5:1 with white */
  --dp-pink-700: #A82255;          /* hover / pressed */
  --dp-pink-100: #FCE4EE;          /* tint */

  /* pipeline & state — full strength: rules, dots, outlines, diagram nodes */
  --dp-blue-500: #3B7BFF;          /* acquisition, extraction, inputs */
  --dp-violet-500: #7C5CFF;        /* language & domain intelligence */
  --dp-teal-500: #1FB8A6;          /* accepted / valid / outputs */
  --dp-amber-500: #E8A317;         /* review band, limitations, duplication */
  --dp-red-500: #E0443E;           /* rejected, privacy, prohibitions */

  /* state colours darkened for label text — the full strengths fail 4.5:1 on paper */
  --dp-blue-text: #2A56C6;
  --dp-violet-text: #5B3FD6;
  --dp-teal-text: #067468;         /* darkened from #0E7C70 (2026-09-19): 4.37:1 on --dp-teal-tint chip
                                       background failed the 4.5:1 body-text bar (axe color-contrast,
                                       Task 27). 4.88:1 on tint, 5.42:1 on paper. */
  --dp-amber-text: #8A5A06;
  --dp-red-text: #B3302B;

  /* 12% tints for chips, callouts and table cells */
  --dp-blue-tint: rgba(59, 123, 255, 0.12);
  --dp-violet-tint: rgba(124, 92, 255, 0.12);
  --dp-teal-tint: rgba(31, 184, 166, 0.12);
  --dp-amber-tint: rgba(232, 163, 23, 0.12);
  --dp-red-tint: rgba(224, 68, 62, 0.12);

  /* graphite inset — one per page, for the block that earns contrast */
  --dp-graphite-bg: #0F1420;
  --dp-graphite-surface: #161C2B;
  --dp-graphite-raised: #1E2536;
  --dp-graphite-border: #2A3247;
  --dp-graphite-text: #F3F5F9;
  --dp-graphite-text-secondary: #A8B0C2;
  --dp-graphite-line: #3A4358;

  /* on-dark state-label text (added 2026-09-19, Task 27) — .dp-section--graphite swaps
     --dp-{state}-text from the paper-darkened value to the full-strength -500 tone, which clears
     4.5:1 on plain --dp-graphite-bg for every state EXCEPT blue/violet/red, which also render on
     a --dp-{state}-tint badge background (a 12%-opacity overlay on graphite, e.g. #14203B for
     blue), where -500 alone falls short of 4.5:1. These three are the same hue lightened just
     enough to clear 4.5:1 against both cases — verified: blue 5.97:1 (graphite-bg) / 5.24:1
     (own tint), violet 6.18:1 / 5.47:1, red 5.96:1 / 5.38:1 — teal-500 (7.42:1) and amber-500
     (8.48:1) already clear both cases and don't need one. */
  --dp-blue-500-ondark: #5A8FFF;
  --dp-violet-500-ondark: #9C82FF;
  --dp-red-500-ondark: #E86D64;

  /* schema / code blocks — dark in both directions */
  --dp-code-bg: #0B0F19;
  --dp-code-text: #E6EAF2;
  --dp-code-dim: #8A93A6;

  /* type */
  --dp-font-display: 'Inter Tight', Inter, system-ui, sans-serif;
  --dp-font-body: Inter, system-ui, sans-serif;
  --dp-font-mono: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace;
  --dp-leading-display: 1.15;
  --dp-leading-body: 1.55;
  --dp-tracking-display: -0.015em;

  /* geometry */
  --dp-radius-card: 12px;
  --dp-radius-button: 10px;
  --dp-radius-schema: 8px;
  --dp-radius-chip: 6px;
  --dp-container: 1200px;
  --dp-gutter: 24px;
  --dp-section-y: 48px;          /* halved from 96px on 2026-09-19 at the owner's request */
  --dp-touch-target: 44px;
}

@media (max-width: 767px) {
  :root { --dp-section-y: 28px; }   /* halved from 56px, same request */
}

/* Focus is never removed and never colour-only. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--dp-pink-500);
  outline-offset: 2px;
}

/* One document token travels the pipeline stepper. Nothing else animates on scroll. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}

}

/* == fonts.css == */
@layer base {
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap; src: url('/assets/fonts/Inter-400.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 500; font-display: swap; src: url('/assets/fonts/Inter-500.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap; src: url('/assets/fonts/Inter-600.woff2') format('woff2'); }
@font-face { font-family: 'Inter Tight'; font-style: normal; font-weight: 500; font-display: swap; src: url('/assets/fonts/InterTight-500.woff2') format('woff2'); }
@font-face { font-family: 'Inter Tight'; font-style: normal; font-weight: 600; font-display: swap; src: url('/assets/fonts/InterTight-600.woff2') format('woff2'); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/assets/fonts/JetBrainsMono-400.woff2') format('woff2'); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/assets/fonts/JetBrainsMono-500.woff2') format('woff2'); }

}

/* == base.css == */
@layer base {
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--dp-bg); color: var(--dp-text); font-family: var(--dp-font-body);
  font-size: 16px; line-height: var(--dp-leading-body); }
h1, h2, h3, h4 { font-family: var(--dp-font-display); line-height: var(--dp-leading-display);
  letter-spacing: var(--dp-tracking-display); margin: 0 0 .5em; font-weight: 600; }
h1 { font-size: clamp(32px, 4.5vw, 52px); } h2 { font-size: clamp(26px, 3vw, 36px); } h3 { font-size: 22px; } h4 { font-size: 18px; }
p { margin: 0 0 1em; } a { color: inherit; }
code, pre, .dp-mono { font-family: var(--dp-font-mono); font-size: 14px; }
img, svg { max-width: 100%; height: auto; }
.dp-container { width: min(100% - 2 * var(--dp-gutter), var(--dp-container)); margin-inline: auto; }
.dp-section { padding-block: var(--dp-section-y); }
.dp-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--dp-gutter); }
.dp-eyebrow { font-family: var(--dp-font-mono); font-size: 14px; color: var(--dp-text-secondary); text-transform: none; margin: 0 0 12px; }
.dp-lede { font-size: 18px; color: var(--dp-text-secondary); max-width: 62ch; }
.dp-skip { position: absolute; left: 8px; top: -100px; background: var(--dp-surface); padding: 12px 16px; border-radius: var(--dp-radius-button); z-index: 100; }
.dp-skip:focus { top: 8px; }
.dp-visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* Plain text link with a trailing arrow — for a CTA-shaped link whose label is not on the
   approved CTA list (content/copy.md §"CTA labels"), so it must not carry the dp-btn class.
   Same visual treatment as .dp-hero__links a, generalised for use outside the hero. */
.dp-link-arrow { color: var(--dp-pink-600); font-weight: 500; text-decoration: none; }
.dp-link-arrow:hover { text-decoration: underline; }
[hidden] { display: none !important; }
.no-js .dp-drawer[hidden] { display: block !important; }
@media (min-width: 1024px) {
  .no-js .dp-drawer[hidden] { display: none !important; }
}
.no-js .dp-stepper__detail[hidden] { display: block !important; }
/* Tabs (dp_tabs()): without JS the tablist controls nothing, so hide it and force every panel
   visible. Each panel's own label — normally only carried by its (now-hidden) tab button —
   surfaces as a heading instead of staying visually-hidden. */
.no-js .dp-tabs__list { display: none; }
.no-js .dp-tabs__panel[hidden] { display: block !important; }
.no-js .dp-tabs__panel + .dp-tabs__panel { border-top: 1px solid var(--dp-border); margin-top: 16px; padding-top: 16px; }
.no-js .dp-tabs__panel-label { position: static !important; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal;
  font-family: var(--dp-font-display); font-weight: 600; font-size: 18px; margin: 0 0 8px; }

}

/* == breadcrumb.css == */
@layer components {
.dp-crumb { font: 14px var(--dp-font-mono); color: var(--dp-text-secondary); padding-block: 16px; }
.dp-crumb ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; }
.dp-crumb li { display: flex; align-items: center; }
.dp-crumb li + li::before { content: '/'; margin: 0 8px; color: var(--dp-text-secondary); }
.dp-crumb a { color: var(--dp-text-secondary); text-decoration: none; }
.dp-crumb a:hover { color: var(--dp-text); text-decoration: underline; }
.dp-crumb li[aria-current="page"] { color: var(--dp-text); }

}

/* == button.css == */
@layer components {
.dp-btn { display: inline-flex; align-items: center; gap: 8px; min-height: var(--dp-touch-target); padding: 10px 20px;
  border-radius: var(--dp-radius-button); font: 500 16px/1.2 var(--dp-font-body); text-decoration: none; cursor: pointer; border: 1px solid transparent; transition: background-color .15s, color .15s, border-color .15s;
  white-space: nowrap; }
.dp-btn--primary { background: var(--dp-pink-600); color: var(--dp-surface); }
.dp-btn--primary:hover { background: var(--dp-pink-700); }
.dp-btn--primary:active { background: var(--dp-pink-700); transform: translateY(1px); }
.dp-btn--secondary { background: transparent; color: var(--dp-text); border-color: var(--dp-text); }
.dp-btn--secondary:hover { background: var(--dp-surface-subtle); }
.dp-btn--text { background: none; color: var(--dp-pink-600); padding-inline: 4px; }
.dp-btn[disabled], .dp-btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }
.dp-btn[data-loading="true"] { position: relative; color: transparent; }
.dp-btn[data-loading="true"]::after { content: ""; position: absolute; inset: 0; margin: auto; width: 18px; height: 18px; border: 2px solid var(--dp-surface); border-right-color: transparent; border-radius: 50%; animation: dp-spin .8s linear infinite; }
@keyframes dp-spin { to { transform: rotate(360deg); } }
.dp-btn-row { display: flex; flex-wrap: wrap; gap: 12px; }

}

/* == callout.css == */
@layer components {
.dp-callout { border-left: 3px solid var(--dp-blue-500); background: var(--dp-blue-tint); border-radius: 0 var(--dp-radius-card) var(--dp-radius-card) 0; padding: 16px 20px; }
.dp-callout--amber { border-left-color: var(--dp-amber-500); background: var(--dp-amber-tint); }
.dp-callout--red { border-left-color: var(--dp-red-500); background: var(--dp-red-tint); }
.dp-callout__head { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; }
.dp-callout__icon { width: 16px; height: 16px; flex-shrink: 0; color: var(--dp-blue-text); }
.dp-callout--amber .dp-callout__icon { color: var(--dp-amber-text); }
.dp-callout--red .dp-callout__icon { color: var(--dp-red-text); }
.dp-callout__label { font: 500 14px/1.3 var(--dp-font-mono); text-transform: none; letter-spacing: 0; color: var(--dp-blue-text); }
.dp-callout--amber .dp-callout__label { color: var(--dp-amber-text); }
.dp-callout--red .dp-callout__label { color: var(--dp-red-text); }
.dp-callout__title { margin: 0 0 4px; font-weight: 600; }
.dp-callout__body { margin: 0; color: var(--dp-text); }
.dp-callout__body p:first-child { margin-top: 0; }
.dp-callout__body p:last-child { margin-bottom: 0; }

}

/* == card.css == */
@layer components {
.dp-card { background: var(--dp-surface); border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 20px; display: flex; flex-direction: column; gap: 10px; }

/* Service / product card — top rule carries the section's semantic tone; the title text still
   carries the meaning, colour is never the only signal. */
.dp-card--service { border-top: 3px solid var(--dp-text-muted); }
.dp-card--service.dp-card--blue { border-top-color: var(--dp-blue-500); }
.dp-card--service.dp-card--violet { border-top-color: var(--dp-violet-500); }
.dp-card--service.dp-card--teal { border-top-color: var(--dp-teal-500); }
.dp-card--service.dp-card--amber { border-top-color: var(--dp-amber-500); }
.dp-card--service.dp-card--red { border-top-color: var(--dp-red-500); }
.dp-card__title { margin: 0; font-size: 20px; }
.dp-card__desc { margin: 0; color: var(--dp-text-secondary); }
.dp-card__chips { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; }
/* min-height/inline-flex keep the tap target >=44px tall even though only the "label ->" text is
   the link, not the whole card (reviewer item c) */
.dp-card__link { color: var(--dp-pink-600); font-weight: 500; text-decoration: none; display: inline-flex; align-items: center; min-height: var(--dp-touch-target); }
.dp-card__link:hover { text-decoration: underline; }

/* Metric / definition card */
.dp-card--metric .dp-card__def { color: var(--dp-text-secondary); }
.dp-card__how { margin: 0; font-size: 14px; color: var(--dp-text-secondary); }
.dp-card__how-label { font: 500 14px/1.3 var(--dp-font-mono); text-transform: none; letter-spacing: 0; }

/* Metric grid — dp_metric_grid(). One column below 480; auto-fit cards from 200px at ≥1024 so a
   5-card grid (the usual quality-checks count) settles into an even row without a fixed count. */
.dp-metric-grid { display: grid; gap: var(--dp-gutter); grid-template-columns: repeat(2, 1fr); }
@media (max-width: 479px) { .dp-metric-grid { grid-template-columns: 1fr; } }
@media (min-width: 1024px) { .dp-metric-grid { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } }

/* dp_metric_grid(['cols' => 4]) — a fixed count instead of auto-fit, mirroring .dp-card-grid's
   breakpoints: 1 below 480, 2 from 480, 4 from 1024 (quality-provenance's eleven dimensions
   settle 4+4+3 instead of auto-fit's uneven wrap). */
@media (min-width: 480px) { .dp-metric-grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .dp-metric-grid--4 { grid-template-columns: repeat(4, 1fr); } }

.dp-twocol { display: grid; grid-template-columns: 1fr; gap: 24px; }
@media (min-width: 768px) { .dp-twocol { grid-template-columns: 1fr 1fr; } }
.dp-twocol p { max-width: 72ch; }

/* Generic card grid wrapper — dp_card_grid(). Column count is a data attribute the caller passes
   as a class modifier; it collapses to one column below 480 and two below 768 regardless of the
   requested count. */
.dp-card-grid { display: grid; grid-template-columns: 1fr; gap: 24px; }
@media (min-width: 480px) { .dp-card-grid--2, .dp-card-grid--3, .dp-card-grid--4 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .dp-card-grid--3 { grid-template-columns: repeat(3, 1fr); } .dp-card-grid--4 { grid-template-columns: repeat(4, 1fr); } }

/* Five-card grid (the datasets hub) — a fixed 5-column grid would orphan one card alone on its
   own row at 1024–1439. Flex-wrap + centred justification instead: 3+2 centred from 1024, one
   3 + 2 centred at every desktop width (a row of five at 1440 would squeeze each card to 220px inside
   the 1200px container), one column below 480 like every other dp-card-grid count. */
@media (min-width: 480px) {
  .dp-card-grid--5 { display: flex; flex-wrap: wrap; justify-content: center; gap: 24px; }
  .dp-card-grid--5 > * { flex: 0 1 calc((100% - 24px) / 2); min-width: 280px; }
}
@media (min-width: 1024px) { .dp-card-grid--5 > * { flex-basis: calc((100% - 48px) / 3); } }

/* Plain numbered card — dp_card_plain(), used where a card has no link (e.g. "what this stage
   does" capability cards, layer E.1–E.3 detail cards). Reuses the service card's tone rule. */
.dp-card--plain { border-top: 3px solid var(--dp-text-muted); }
.dp-card--plain.dp-card--blue { border-top-color: var(--dp-blue-500); }
.dp-card--plain.dp-card--violet { border-top-color: var(--dp-violet-500); }
.dp-card--plain.dp-card--teal { border-top-color: var(--dp-teal-500); }
.dp-card--plain.dp-card--amber { border-top-color: var(--dp-amber-500); }
.dp-card--plain.dp-card--red { border-top-color: var(--dp-red-500); }
.dp-card__num { color: var(--dp-text-secondary); }

/* Reason-code line — dp_card_plain(['code' => ...]), e.g. home quality-layer cards. */
.dp-card__code { margin: 0; padding-top: 10px; border-top: 1px solid var(--dp-border); font-size: 14px; color: var(--dp-text-secondary); }

}

/* == chip.css == */
@layer components {
.dp-chips { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; }
.dp-chip { display: inline-flex; align-items: center; height: 28px; padding: 0 10px; border-radius: var(--dp-radius-chip); font-size: 14px; background: var(--dp-surface-subtle); border: 1px solid var(--dp-border); color: var(--dp-text); }
.dp-chip--mono { font-family: var(--dp-font-mono); }

/* Tone: tint fill + outline + the label text itself — colour is never the only carrier. */
.dp-chip--blue { background: var(--dp-blue-tint); border-color: var(--dp-blue-500); color: var(--dp-blue-text); }
.dp-chip--violet { background: var(--dp-violet-tint); border-color: var(--dp-violet-500); color: var(--dp-violet-text); }
.dp-chip--teal { background: var(--dp-teal-tint); border-color: var(--dp-teal-500); color: var(--dp-teal-text); }
.dp-chip--amber { background: var(--dp-amber-tint); border-color: var(--dp-amber-500); color: var(--dp-amber-text); }
.dp-chip--red { background: var(--dp-red-tint); border-color: var(--dp-red-500); color: var(--dp-red-text); }

/* dp_draft_chip() — dev-only flag on copy that isn't sourced from the approved design. */
.dp-draft { display: inline-flex; align-items: center; height: 20px; padding: 0 6px; margin-left: 4px;
  border-radius: var(--dp-radius-chip); border: 1px solid var(--dp-amber-500); font-family: var(--dp-font-mono);
  font-size: 14px; font-weight: 500; color: var(--dp-amber-text); vertical-align: middle; }

}

/* == code-block.css == */
@layer components {
.dp-code { background: var(--dp-code-bg); color: var(--dp-code-text); border-radius: var(--dp-radius-schema); overflow: hidden; }
.dp-code__bar { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding: 8px 12px; border-bottom: 1px solid var(--dp-graphite-border); }
.dp-code__bar .dp-tabs { flex: 1 1 auto; }
.dp-code__bar .dp-tabs__list { border-bottom: none; }
.dp-code__bar .dp-tabs__tab { color: var(--dp-code-dim); }
.dp-code__bar .dp-tabs__tab[aria-selected="true"] { color: var(--dp-code-text); }
.dp-code__copy { display: inline-flex; align-items: center; min-height: var(--dp-touch-target); padding: 0 16px;
  border: 1px solid var(--dp-graphite-border); border-radius: var(--dp-radius-button); background: transparent;
  color: var(--dp-code-text); font: 500 16px/1.2 var(--dp-font-body); cursor: pointer; }
.dp-code__copy:hover { background: var(--dp-graphite-raised); }
/* Own background so axe (and any scroll container) sees the code text against the code surface — the
   collapsed variant scrolls, and a scrolling element without a background makes the contrast check
   fall through to the page paper. */
.dp-code__pre { margin: 0; padding: 16px; overflow-x: auto; background: var(--dp-code-bg); }
/* dp_code_block(['collapsed' => true]) — long illustrative samples (e.g. the Croissant registry
   extract) get a capped, scrollable height instead of stretching the page; the <pre> is made
   keyboard-focusable so the scroll region is reachable without a mouse. */
.dp-code--collapsed .dp-code__pre { max-height: 480px; overflow: auto; }
.dp-code__pre code { font-family: var(--dp-font-mono); font-size: 14px; color: var(--dp-code-text); background: var(--dp-code-bg); }
.dp-code__note { margin: 0; padding: 10px 16px; font-size: 14px; color: var(--dp-code-dim); border-top: 1px solid var(--dp-graphite-border); }

/* Below 1024 tabs.css turns tabs into bordered chips and fills the selected one pink-100 — on the
   dark code bar that leaves light text on a light chip. Keep the chip shape, use the bar's own
   surfaces so the selected label stays readable. */
@media (max-width: 1023px) {
  .dp-code__bar .dp-tabs__tab[aria-selected="true"] { background: var(--dp-graphite-raised); border-color: var(--dp-pink-500); color: var(--dp-code-text); }
  .dp-code__bar .dp-tabs__tab { border-color: var(--dp-graphite-border); }
}

}

/* == cookie-sheet.css == */
@layer components {
.dp-cookie { position: fixed; inset: auto 16px 16px 16px; max-width: 560px; margin-inline: auto; z-index: 60;
  background: var(--dp-surface); border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card);
  box-shadow: 0 12px 32px rgba(20, 23, 31, .16); padding: 20px; }
.dp-cookie__title { margin: 0 0 8px; font-size: 18px; }
.dp-cookie__form p { font-size: 14px; color: var(--dp-text-secondary); margin: 0 0 16px; }
.dp-cookie__cats { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; }
.dp-toggle { display: flex; align-items: center; gap: 8px; font-size: 14px; min-height: 44px; }
.dp-toggle small { color: var(--dp-text-secondary); }
.dp-cookie .dp-btn-row { flex-wrap: wrap; }

}

/* == deliverables.css == */
@layer components {
.dp-deliverables { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr; gap: 10px; }
@media (min-width: 768px) { .dp-deliverables { grid-template-columns: 1fr 1fr; } }
.dp-deliverables__item { display: flex; align-items: flex-start; gap: 10px; font-size: 16px; }
.dp-deliverables__icon { width: 18px; height: 18px; flex-shrink: 0; color: var(--dp-text-secondary); margin-top: 2px; }
.dp-deliverables__name { display: block; }
.dp-deliverables__desc { display: block; font-size: 14px; color: var(--dp-text-secondary); }

}

/* == diagram.css == */
@layer components {
/* Eleven inline-SVG diagrams — abstract schematics only, no hex here (classes only, see tools/check-tokens.php). */

.dp-diagram { display: block; width: 100%; height: auto; }

/* dg_wrap()'s optional vertical variant: horizontal shows at >=768, vertical below. A diagram
   without a vertical variant has no data-orientation attribute and is unaffected. */
.dp-diagram-set { display: block; }
.dp-diagram[data-orientation="v"] { display: none; }
@media (max-width: 767px) {
  .dp-diagram[data-orientation="h"] { display: none; }
  .dp-diagram[data-orientation="v"] { display: block; }
}

.dp-figure { margin: 0; display: flex; flex-direction: column; gap: 12px; }
.dp-figure figcaption { font-size: 14px; color: var(--dp-text-secondary); }

/* dg_wrap()'s dp-diagram--scroll class (acquisition lanes, reference architecture: too wide for a
   useful vertical stack). dp_diagram_block() wraps that svg in a labelled, focusable scroll region. */
.dp-figure__scroll { overflow-x: auto; position: relative; -webkit-overflow-scrolling: touch; }
.dp-figure__scroll .dp-diagram { min-width: 640px; }
@media (min-width: 768px) { .dp-figure__scroll .dp-diagram { min-width: 0; } }
/* Fade affordance — the same device CLAUDE.md §8 allows for scrolling tables below 1024, extended
   here to figures with a horizontal-scroll wrapper: a functional scroll cue, not decoration.
   Tokens only, no hex. */
.dp-figure__scroll::after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 32px; pointer-events: none;
  background: linear-gradient(to right, transparent, var(--dp-bg)); }
@media (min-width: 768px) { .dp-figure__scroll::after { display: none; } }

.dg-node { fill: var(--dp-surface); stroke: var(--dp-border); stroke-width: 1.5; }
.dg-line { stroke: var(--dp-graphite-line); fill: none; stroke-width: 1.5; }
.dg-dashed { stroke-dasharray: 5 4; }
.dg-arrowhead { fill: var(--dp-graphite-line); }

.dg-blue { stroke: var(--dp-blue-500); }
.dg-blue-fill { fill: var(--dp-blue-tint); }
.dg-violet { stroke: var(--dp-violet-500); }
.dg-violet-fill { fill: var(--dp-violet-tint); }
.dg-teal { stroke: var(--dp-teal-500); }
.dg-teal-fill { fill: var(--dp-teal-tint); }
.dg-amber { stroke: var(--dp-amber-500); }
.dg-amber-fill { fill: var(--dp-amber-tint); }
.dg-red { stroke: var(--dp-red-500); }
.dg-red-fill { fill: var(--dp-red-tint); }

/* Solid fill — a stronger mark than the tinted -fill classes above, for small glyphs (e.g. the
   stage/layer matrix's write dots) where a 12%-opacity tint reads the same as an empty outline. */
.dg-blue-solid { fill: var(--dp-blue-500); }
.dg-violet-solid { fill: var(--dp-violet-500); }
.dg-teal-solid { fill: var(--dp-teal-500); }
.dg-amber-solid { fill: var(--dp-amber-500); }
.dg-red-solid { fill: var(--dp-red-500); }

.dg-text { font-family: var(--dp-font-body); font-size: 14px; font-weight: 500; line-height: 1.3; fill: var(--dp-text); }
.dg-text-secondary { font-family: var(--dp-font-body); font-size: 14px; font-weight: 500; line-height: 1.3; fill: var(--dp-text-secondary); }
.dg-mono { font-family: var(--dp-font-mono); font-size: 14px; line-height: 1.3; fill: var(--dp-text-secondary); }

.dg-blue-text { fill: var(--dp-blue-text); }
.dg-violet-text { fill: var(--dp-violet-text); }
.dg-teal-text { fill: var(--dp-teal-text); }
.dg-amber-text { fill: var(--dp-amber-text); }
.dg-red-text { fill: var(--dp-red-text); }

/* Shape marks — colour is never the only signal, so every state also gets a distinct glyph. */
.dg-mark { font-family: var(--dp-font-body); font-size: 14px; font-weight: 700; line-height: 1; text-anchor: middle; }

.dg-dark { fill: var(--dp-graphite-bg); }
.dg-dark .dg-node { fill: var(--dp-graphite-surface); stroke: var(--dp-graphite-border); }
.dg-dark .dg-text { fill: var(--dp-graphite-text); }
.dg-dark .dg-text-secondary { fill: var(--dp-graphite-text-secondary); }
.dg-dark .dg-mono { fill: var(--dp-graphite-text-secondary); }
.dg-dark .dg-line { stroke: var(--dp-graphite-line); }

}

/* == faq.css == */
@layer components {
.dp-faq { border-top: 1px solid var(--dp-border); }
.dp-faq h3 { margin: 0; font-size: 16px; }
.dp-faq__q { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  min-height: var(--dp-touch-target); padding: 16px 4px; border: none; border-bottom: 1px solid var(--dp-border);
  background: none; text-align: left; font: 500 16px/1.3 var(--dp-font-body); color: var(--dp-text); cursor: pointer; }
.dp-faq__sign { position: relative; flex: none; width: 16px; height: 16px; }
.dp-faq__sign::before, .dp-faq__sign::after { content: ""; position: absolute; background: var(--dp-text); }
.dp-faq__sign::before { left: 0; top: 7px; width: 16px; height: 2px; }
.dp-faq__sign::after { left: 7px; top: 0; width: 2px; height: 16px; transition: transform .15s; }
.dp-faq__q[aria-expanded="true"] .dp-faq__sign::after { transform: scaleY(0); }
.dp-faq__a { padding: 4px 4px 20px; color: var(--dp-text-secondary); max-width: 72ch; }

}

/* == final-cta.css == */
@layer components {
.dp-final-cta { background: var(--dp-surface-subtle); padding-block: var(--dp-section-y); text-align: center; }
.dp-final-cta h2 { max-width: 40ch; margin-inline: auto; }
.dp-final-cta p { max-width: 56ch; margin-inline: auto; color: var(--dp-text-secondary); font-size: 18px; }
.dp-final-cta .dp-btn-row { justify-content: center; margin-top: 24px; }

}

/* == footer.css == */
@layer components {
.dp-footer { border-top: 1px solid var(--dp-border); padding-block: 56px 32px; }
.dp-footer__grid { display: grid; grid-template-columns: 1fr; gap: 32px; }
.dp-footer__title { margin: 0; font: 600 15px var(--dp-font-display); }
.dp-footer__toggle { display: block; width: 100%; text-align: left; background: none; border: 0; padding: 0 0 12px; font: inherit; color: inherit; cursor: default; }
.dp-footer__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.dp-footer__list a { text-decoration: none; color: var(--dp-text-secondary); font-size: 15px; }
.dp-footer__list a:hover { color: var(--dp-text); }
.dp-footer__contact p { margin: 8px 0 0; }
.dp-footer__contact .dp-btn-row, .dp-footer__contact .dp-btn { margin-top: 12px; }
.dp-footer__bottom { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; border-top: 1px solid var(--dp-border); margin-top: 40px; padding-top: 24px; font-size: 14px; color: var(--dp-text-secondary); }
/* Every <p> in the bottom row must lose base.css's 1em bottom margin: in this centred
   flex row an unreset margin makes that line's box taller and shifts its text upward. */
.dp-footer__bottom p { margin: 0; }
.dp-footer__legal-links { list-style: none; margin: 0 0 0 auto; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; }
.dp-footer__legal-links a { color: var(--dp-text-secondary); font-size: 14px; text-decoration: none; }
.dp-footer__legal-links a:hover { color: var(--dp-text); }

@media (max-width: 767px) {
  .dp-footer__toggle { cursor: pointer; display: flex; align-items: center; justify-content: space-between; padding: 12px 0; min-height: 44px; }
  .dp-footer__toggle::after { content: '+'; font-size: 18px; }
  .dp-footer__toggle[aria-expanded="true"]::after { content: '–'; }
  .dp-footer__col { border-bottom: 1px solid var(--dp-border); }
  .dp-footer__list { padding-bottom: 12px; }
}
@media (min-width: 768px) {
  .dp-footer__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .dp-footer__grid { grid-template-columns: repeat(5, 1fr); }
}

}

/* == form.css == */
@layer components {
.dp-field { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; border: 0; }
.dp-field > label, .dp-field > legend { font: 500 14px/1.3 var(--dp-font-body); color: var(--dp-text); padding: 0; }
.dp-field__req { color: var(--dp-pink-600); }
.dp-input { min-height: var(--dp-touch-target); padding: 10px 12px; border: 1px solid var(--dp-border); border-radius: var(--dp-radius-button); background: var(--dp-surface); color: var(--dp-text); font: 400 16px/1.4 var(--dp-font-body); width: 100%; }
.dp-input--area { min-height: 120px; resize: vertical; }
.dp-input:focus-visible { outline: 2px solid var(--dp-pink-500); outline-offset: 2px; }
.dp-input[aria-invalid="true"], fieldset.dp-field[aria-invalid="true"] { border-color: var(--dp-red-500); }
.dp-field__help { font-size: 14px; color: var(--dp-text-secondary); margin: 0; }
.dp-field__error { color: var(--dp-red-text); font-size: 14px; display: flex; align-items: flex-start; gap: 6px; margin: 0; }
.dp-field__icon { flex: none; width: 16px; height: 16px; display: block; }
.dp-field__error .dp-field__icon { margin-top: 1px; }
.dp-field--error > label, .dp-field--error > legend { color: var(--dp-red-text); }

.dp-error-summary { border: 1px solid var(--dp-red-500); border-left-width: 3px; background: var(--dp-red-tint); padding: 16px; border-radius: var(--dp-radius-card); }
.dp-error-summary:focus-visible { outline: 2px solid var(--dp-pink-500); outline-offset: 2px; }
.dp-error-summary__title { display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--dp-red-text); margin: 0 0 8px; }
.dp-error-summary__title svg { width: 16px; height: 16px; flex: none; }
.dp-error-summary ul { margin: 0; padding: 0 0 0 1.2em; }
.dp-error-summary a { color: var(--dp-red-text); }

.dp-chip-check-row, .dp-radio-row { display: flex; flex-wrap: wrap; gap: 8px; }
.dp-chip-check, .dp-radio { display: inline-flex; align-items: center; gap: 8px; min-height: var(--dp-touch-target); padding: 0 14px; border: 1px solid var(--dp-border); border-radius: var(--dp-radius-chip); background: var(--dp-surface); cursor: pointer; }
.dp-chip-check input, .dp-radio input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.dp-chip-check__box { width: 16px; height: 16px; border: 1.5px solid var(--dp-border); border-radius: 4px; position: relative; flex: none; }
.dp-chip-check input:checked + .dp-chip-check__box { border-color: var(--dp-pink-500); background: var(--dp-pink-100); }
.dp-chip-check input:checked + .dp-chip-check__box::after { content: ""; position: absolute; left: 3px; top: 0px; width: 4px; height: 8px; border: solid var(--dp-pink-600); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.dp-chip-check:has(input:checked) { border-color: var(--dp-pink-500); background: var(--dp-pink-100); }
.dp-chip-check input:focus-visible + .dp-chip-check__box, .dp-radio input:focus-visible + .dp-radio__dot { outline: 2px solid var(--dp-pink-500); outline-offset: 2px; }
.dp-radio__dot { width: 16px; height: 16px; border: 1.5px solid var(--dp-border); border-radius: 50%; position: relative; flex: none; }
.dp-radio input:checked + .dp-radio__dot { border-color: var(--dp-pink-500); }
.dp-radio input:checked + .dp-radio__dot::after { content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--dp-pink-600); }
.dp-radio:has(input:checked) { border-color: var(--dp-pink-500); background: var(--dp-pink-100); }

.dp-field--check { flex-direction: row; }
.dp-check { display: inline-flex; align-items: flex-start; gap: 10px; cursor: pointer; min-height: var(--dp-touch-target); }
.dp-check input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.dp-check__box { width: 18px; height: 18px; margin-top: 2px; border: 1.5px solid var(--dp-border); border-radius: 4px; position: relative; flex: none; }
.dp-check input:checked + .dp-check__box { border-color: var(--dp-pink-500); background: var(--dp-pink-100); }
.dp-check input:checked + .dp-check__box::after { content: ""; position: absolute; left: 4px; top: 1px; width: 5px; height: 9px; border: solid var(--dp-pink-600); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.dp-check input:focus-visible + .dp-check__box { outline: 2px solid var(--dp-pink-500); outline-offset: 2px; }

.dp-formstep { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); margin-bottom: 16px; }
.dp-formstep__title { margin: 0; font-size: 16px; }
.dp-formstep__toggle { width: 100%; text-align: left; min-height: var(--dp-touch-target); padding: 16px; background: none; border: 0; font: 600 16px/1.3 var(--dp-font-body); color: var(--dp-text); cursor: pointer; }
.dp-formstep__toggle:focus-visible { outline: 2px solid var(--dp-pink-500); outline-offset: 2px; }
.dp-formstep__body { padding: 0 16px 16px; display: flex; flex-direction: column; gap: 20px; }

/* dp_fieldset(['plain' => true]) — a static heading (no accordion button) for a fieldset that
   already sits inside another native disclosure, e.g. <details class="dp-rfq__more"> on /contact/
   (reviewer item d). Matches the toggle button's padding/type so desktop looks unchanged. */
.dp-formstep--plain .dp-formstep__title { min-height: var(--dp-touch-target); padding: 16px; display: flex; align-items: center; font: 600 16px/1.3 var(--dp-font-body); color: var(--dp-text); }

.dp-submit-bar { display: flex; justify-content: flex-end; gap: 12px; padding: 16px; }
@media (max-width: 767px) {
    .dp-submit-bar { position: sticky; bottom: 0; background: var(--dp-surface); border-top: 1px solid var(--dp-border); z-index: 2; }
    .dp-submit-bar .dp-btn { width: 100%; justify-content: center; }
}

/* Honeypot field (rfq handler: dp_honeypot_hit()) — present in the DOM and reachable by a bot
   that ignores CSS, but visually and programmatically out of a sighted/keyboard user's way. */
.dp-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Tag-input chip preview (rfq.js progressive enhancement of dp_tag_input's comma-separated field). */
.dp-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; padding: 0; list-style: none; }
.dp-tags:empty { display: none; }

}

/* == header.css == */
@layer components {
.dp-header { position: sticky; top: 0; z-index: 50; background: var(--dp-bg); border-bottom: 1px solid transparent; }
.dp-header.is-scrolled { border-bottom-color: var(--dp-border); }
.dp-header__row { display: flex; align-items: center; gap: 24px; height: 64px; }
.dp-logo { font: 600 20px var(--dp-font-display); letter-spacing: var(--dp-tracking-display); text-decoration: none; }
.dp-nav { display: none; flex: 1; } .dp-header__cta { display: none; }
.dp-nav__list { list-style: none; margin: 0; padding: 0; display: flex; gap: 4px; }
.dp-nav__item { position: relative; }
.dp-nav__link { display: inline-flex; align-items: center; min-height: 44px; padding: 0 12px; border: 0; background: none; font: 500 15px var(--dp-font-body); color: var(--dp-text-secondary); text-decoration: none; cursor: pointer; border-radius: var(--dp-radius-chip); }
.dp-nav__link:hover, .dp-nav__link[aria-expanded="true"] { color: var(--dp-text); background: var(--dp-surface-subtle); }
.dp-nav__link[aria-current] { color: var(--dp-text); box-shadow: inset 0 -2px 0 var(--dp-pink-500); }
.dp-mega { position: absolute; top: 100%; left: 0; min-width: 320px; background: var(--dp-surface); border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 12px; box-shadow: 0 12px 32px rgba(20, 23, 31, .08); }
.dp-mega--two-col .dp-mega__list { columns: 2; column-gap: 12px; min-width: 560px; }
.dp-mega__list { list-style: none; margin: 0; padding: 0; }
.dp-mega__link { display: block; padding: 10px 12px; border-radius: var(--dp-radius-chip); text-decoration: none; break-inside: avoid; }
.dp-mega__link:hover { background: var(--dp-surface-subtle); }
.dp-mega__label { display: block; font-weight: 500; } .dp-mega__desc { display: block; font-size: 14px; color: var(--dp-text-secondary); }
.dp-nav__burger { margin-left: auto; width: 44px; height: 44px; border: 1px solid var(--dp-border); background: var(--dp-surface); border-radius: var(--dp-radius-button); display: grid; place-content: center; gap: 4px; cursor: pointer; }
.dp-burger__bar { width: 18px; height: 2px; background: var(--dp-text); }
.dp-drawer { position: fixed; inset: 64px 0 0 0; background: var(--dp-bg); overflow: auto; padding: 16px var(--dp-gutter) 32px; z-index: 49; }
.dp-drawer__cta { position: sticky; top: 0; background: var(--dp-bg); padding-bottom: 12px; }
.dp-drawer__list { list-style: none; margin: 0; padding: 0; }
.dp-drawer .dp-nav__link--parent { position: relative; width: 100%; justify-content: space-between; }
.dp-drawer .dp-nav__link--parent::after { content: ""; width: 8px; height: 8px; margin-left: 8px; border-right: 2px solid currentcolor; border-bottom: 2px solid currentcolor; transform: rotate(45deg); transition: transform .2s ease; }
.dp-drawer .dp-nav__link--parent[aria-expanded="true"]::after { transform: rotate(-135deg); }
@media (prefers-reduced-motion: reduce) { .dp-drawer .dp-nav__link--parent::after { transition: none; } }
.dp-drawer .dp-mega { position: static; box-shadow: none; border: 0; padding: 0 0 0 12px; min-width: 0; }
.dp-drawer .dp-mega--two-col .dp-mega__list { columns: 1; min-width: 0; }
.no-js .dp-mega { display: block; position: static; box-shadow: none; }
.no-js .dp-nav__burger { display: none; }
.no-js .dp-drawer { position: static; inset: auto; padding: 8px 0; }
.no-js .dp-drawer .dp-mega { display: block; }
@media (min-width: 1024px) {
  .dp-nav { display: block; } .dp-header__cta { display: block; margin-left: auto; }
  .dp-nav__burger, .dp-drawer { display: none; }
}

}

/* == hero.css == */
@layer components {
.dp-hero { padding-block: 48px; }
.dp-hero__grid { display: grid; grid-template-columns: 1fr; gap: 32px; align-items: start; }
@media (min-width: 1024px) { .dp-hero__grid { grid-template-columns: 1fr 1fr; gap: 48px; } }
.dp-hero__copy h1 { margin: 8px 0 16px; }
/* `links` prop — a CTA-shaped text link whose label isn't on the approved CTA list, so it can't
   go through dp_button() (used e.g. on /process/ for "See Quality & Provenance →"). */
.dp-hero__links { margin: 12px 0 0; }
.dp-hero__links a { color: var(--dp-pink-600); font-weight: 500; text-decoration: none; }
.dp-hero__links a:hover { text-decoration: underline; }
.dp-hero__aside { display: flex; flex-direction: column; gap: 24px; }
.dp-glance { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 20px; background: var(--dp-surface); }
.dp-glance__title { margin: 0 0 12px; font: 500 14px/1.3 var(--dp-font-mono); color: var(--dp-text-secondary); }
.dp-glance dl { display: grid; gap: 12px; margin: 0; }
.dp-glance dl > div { display: flex; justify-content: space-between; gap: 12px; border-top: 1px solid var(--dp-border); padding-top: 10px; }
.dp-glance dl > div:first-child { border-top: none; padding-top: 0; }
.dp-glance dt { font-size: 14px; color: var(--dp-text-secondary); }
.dp-glance dd { margin: 0; font-size: 14px; font-weight: 500; text-align: right; }

}

/* == layer-stack.css == */
@layer components {
.dp-layers { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--dp-border); }
.dp-layers__item { border-bottom: 1px solid var(--dp-border); }
.dp-layers__item h3 { margin: 0; font-size: 16px; }
.dp-layer__toggle { width: 100%; display: flex; align-items: center; min-height: var(--dp-touch-target);
  padding: 16px 4px; border: none; background: none; text-align: left; font: 600 16px/1.3 var(--dp-font-display);
  color: var(--dp-text); cursor: pointer; }
.dp-layer__facts { display: grid; grid-template-columns: repeat(5, 1fr); gap: 16px; margin: 0; padding: 4px 4px 20px; }
.dp-layer__facts > div { display: flex; flex-direction: column; min-width: 0; }
.dp-layer__facts dt { font-size: 14px; color: var(--dp-text-secondary); margin: 0 0 6px; }
.dp-layer__facts dd { margin: 0; }
.dp-layer__keep { color: var(--dp-teal-text); }
.dp-layer__mark { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--dp-teal-500); margin-right: 6px; }
.dp-layer__reject-label { color: var(--dp-red-text); font-size: 14px; margin-left: 8px; }
.dp-layer__reject { color: var(--dp-red-text); }

.dp-badge { display: inline-flex; align-items: center; min-height: 28px; padding: 0 10px; border-radius: var(--dp-radius-chip);
  font-size: 14px; border: 1px solid var(--dp-border); background: var(--dp-surface-subtle); color: var(--dp-text); }
.dp-badge--automated { border-color: var(--dp-blue-500); color: var(--dp-blue-text); background: var(--dp-blue-tint); }
.dp-badge--human { border-color: var(--dp-violet-500); color: var(--dp-violet-text); background: var(--dp-violet-tint); }
.dp-badge--both { border-color: var(--dp-teal-500); color: var(--dp-teal-text); background: var(--dp-teal-tint); }

@media (max-width: 1023px) {
  .dp-layer__facts { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 767px) {
  .dp-layer__facts { grid-template-columns: 1fr; }
}

}

/* == proof.css == */
@layer components {
.dp-proof { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 32px; display: flex; flex-direction: column; gap: 10px; background: var(--dp-surface); }
.dp-proof__pending { margin: 0; font-weight: 600; font-size: 18px; }
.dp-proof__body { margin: 0; color: var(--dp-text-secondary); max-width: 68ch; }
.dp-proof__pattern { margin: 0; font-size: 14px; color: var(--dp-text-secondary); }

.dp-case-study { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 32px; display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; background: var(--dp-surface-subtle); }
.dp-case-study__mark { width: 40px; height: 40px; border-radius: 50%; border: 1.5px solid var(--dp-text-muted); background: var(--dp-surface); }
.dp-case-study__label { margin: 0; font-weight: 500; color: var(--dp-text-secondary); }

}

/* == read-next.css == */
@layer components {
.dp-readnext { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 768px) { .dp-readnext { grid-template-columns: repeat(2, 1fr); } }
.dp-readnext__item { display: flex; flex-direction: column; gap: 6px; border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 18px; text-decoration: none; color: var(--dp-text); background: var(--dp-surface); }
.dp-readnext__item:hover .dp-readnext__title { text-decoration: underline; }
.dp-readnext__kicker { font-size: 14px; color: var(--dp-text-secondary); }
.dp-readnext__title { font-weight: 600; font-size: 18px; }
.dp-readnext__desc { font-size: 14px; color: var(--dp-text-secondary); }

}

/* == section-head.css == */
@layer components {
.dp-section-head { display: flex; flex-direction: column; gap: 12px; margin-bottom: 28px; }
.dp-section-head__row { display: flex; align-items: baseline; gap: 16px; border-bottom: 1px solid var(--dp-border); padding-bottom: 14px; flex-wrap: wrap; }
.dp-section-head__num { font: 14px/1 var(--dp-font-mono); color: var(--dp-pink-600); }
/* --dp-pink-600 is calibrated for white/paper surfaces (5.5:1) — inside the one dark "graphite"
   inset (.dp-section--graphite, see templates/t1.css) it drops to 3.38:1 on --dp-graphite-bg and
   fails the 4.5:1 body-text bar. --dp-pink-500 clears it there (4.55:1), matching the same
   *-500-on-dark swap the graphite scope already does for the five state-label colours. */
.dp-section--graphite .dp-section-head__num { color: var(--dp-pink-500); }
.dp-section-head__title { margin: 0; }
.dp-section-head__kicker { font-size: 14px; color: var(--dp-text-secondary); }
.dp-section-head__title--as-kicker { font-size: 14px; font-weight: 400; color: var(--dp-text-secondary); }
.dp-section-head__lede { margin: 0; color: var(--dp-text-secondary); max-width: 60ch; }

}

/* == stepper.css == */
@layer components {
.dp-stepper { position: relative; }
.dp-stepper__track { position: absolute; left: 22px; right: 22px; top: 22px; height: 2px; background: var(--dp-border); }
.dp-stepper__token { position: absolute; top: -4px; left: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--dp-pink-500); }
.dp-stepper__list { list-style: none; margin: 0; padding: 0; position: relative;
  display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-flow: row; column-gap: 16px; row-gap: 16px; }
.dp-stepper__stage { grid-row: 1; min-width: 0; }
/* Column count travels via data-stages on the .dp-stepper root (CSP-safe — no inline style="--stages:…").
   Explicit rule per count, desktop only; the default 7-column rule above covers unlisted counts. */
.dp-stepper[data-stages="3"] .dp-stepper__list { grid-template-columns: repeat(3, 1fr); }
.dp-stepper[data-stages="4"] .dp-stepper__list { grid-template-columns: repeat(4, 1fr); }
.dp-stepper[data-stages="5"] .dp-stepper__list { grid-template-columns: repeat(5, 1fr); }
.dp-stepper[data-stages="6"] .dp-stepper__list { grid-template-columns: repeat(6, 1fr); }
.dp-stepper[data-stages="7"] .dp-stepper__list { grid-template-columns: repeat(7, 1fr); }
/* 8/9/10 stages: two pill rows of ceil(N/2) columns each, instead of one row so narrow the
   titles wrap to slivers. .dp-stepper__stage--row2 (set in dp_pipeline_stepper.php, since the
   row split is data-driven, not a fixed nth-child pattern the interleaved detail-row <li>s would
   break) moves the second half of the stages onto grid-row 2; the detail row moves to grid-row 3
   so it always sits below both pill rows.
   The connecting .dp-stepper__track is a single straight line across one row's worth of pill
   centres — it does not make sense stretched across two stacked rows (it would either cut through
   row 1's pills or float at the wrong height), and there is no per-row token animation for these
   pipelines (`animate:false` on every 8–10 stage instance in the codebase), so the track and its
   token are hidden at ≥1024 rather than trying to draw two lines. Below 1024 the list is a single
   vertical column again (see the max-width:1023px block below), so the existing vertical track
   is left alone there. */
.dp-stepper[data-stages="8"] .dp-stepper__list { grid-template-columns: repeat(4, 1fr); }
.dp-stepper[data-stages="9"] .dp-stepper__list { grid-template-columns: repeat(5, 1fr); }
.dp-stepper[data-stages="10"] .dp-stepper__list { grid-template-columns: repeat(5, 1fr); }
@media (min-width: 1024px) {
  .dp-stepper[data-stages="8"] .dp-stepper__track,
  .dp-stepper[data-stages="9"] .dp-stepper__track,
  .dp-stepper[data-stages="10"] .dp-stepper__track { display: none; }
}
.dp-stepper[data-stages="8"] .dp-stepper__stage--row2,
.dp-stepper[data-stages="9"] .dp-stepper__stage--row2,
.dp-stepper[data-stages="10"] .dp-stepper__stage--row2 { grid-row: 2; }
.dp-stepper[data-stages="8"] .dp-stepper__detail-row,
.dp-stepper[data-stages="9"] .dp-stepper__detail-row,
.dp-stepper[data-stages="10"] .dp-stepper__detail-row { grid-row: 3; }
.dp-stepper__detail-row { grid-column: 1 / -1; grid-row: 2; }
.dp-stepper__pill { display: flex; width: 100%; align-items: center; gap: 8px; min-height: var(--dp-touch-target);
  padding: 8px 16px; border: 1px solid var(--dp-border); border-radius: 999px; background: var(--dp-surface);
  font: 500 16px/1.2 var(--dp-font-body); color: var(--dp-text); cursor: pointer; }
.dp-stepper__pill--static { cursor: default; }
.dp-stepper__num { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  border-radius: 50%; background: var(--dp-surface-subtle); font-size: 14px; font-family: var(--dp-font-mono); }
/* A narrow (desktop, many-stage) column can be narrower than the stage title's longest word;
   grid items default to min-width:auto, which forced the pill — and the whole grid track — wider
   than the stepper, causing page-level horizontal scroll at 1024. `overflow-wrap: break-word` once
   fixed that by breaking mid-word ("Requiremen/ts", "Deduplicati/on" — design audit 2026-09-20 D1),
   which read worse than the overflow it replaced. Titles now only wrap between words (`normal`);
   any stage whose longest word would still overflow a narrow column gets a short pill label via
   `short` in dp_pipeline_stepper() (full title stays in the DOM as the detail heading), guarded by
   a test that caps pill words at 11 characters. */
.dp-stepper__title { min-width: 0; overflow-wrap: normal; hyphens: manual; }
.dp-stepper__detail-title { margin: 0 0 12px; font: 600 16px/1.3 var(--dp-font-body); }
.dp-stepper__stage.is-open .dp-stepper__pill { border-color: var(--dp-pink-500); }
.dp-stepper__artifact { margin: 8px 0 0; font-size: 14px; color: var(--dp-text-secondary); }
/* Same slot/typography as .dp-stepper__artifact, minus the mono "artifact ·" label — for a
   collapsed stage's plain one-line description (no artefact literally named in the design). */
.dp-stepper__note { margin: 8px 0 0; font-size: 14px; color: var(--dp-text-secondary); }
.dp-stepper__detail { margin-top: 16px; }
.dp-stepper__cells { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin: 0; }
.dp-stepper__cell { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 12px; }
.dp-stepper__cell dt { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--dp-text-secondary); margin: 0 0 6px; }
.dp-stepper__cell dt::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--dp-text-muted); }
.dp-stepper__cell dd { margin: 0; }
.dp-stepper__cell--blue dt::before { background: var(--dp-blue-500); }
.dp-stepper__cell--violet dt::before { background: var(--dp-violet-500); }
.dp-stepper__cell--teal dt::before { background: var(--dp-teal-500); }
.dp-stepper__cell--amber dt::before { background: var(--dp-amber-500); }
.dp-stepper__link { margin-top: 16px; }
.dp-stepper__link a { color: var(--dp-pink-600); font-weight: 500; }

@media (max-width: 1023px) {
  .dp-stepper__track { left: 22px; right: auto; top: 22px; bottom: 22px; width: 2px; height: auto; }
  /* Vertical stack: normal block flow, so each detail-row sits directly under its own stage — the
     DOM already orders them that way (see dp_pipeline_stepper.php). */
  .dp-stepper__list { display: block; }
  .dp-stepper__stage { margin-bottom: 16px; }
  .dp-stepper__detail-row { margin-bottom: 16px; }
  .dp-stepper__cells { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 767px) {
  .dp-stepper__cells { grid-template-columns: 1fr; }
}

}

/* == table.css == */
@layer components {
.dp-table-wrap { position: relative; }
.dp-table { width: 100%; border-collapse: collapse; }
.dp-table caption { text-align: left; font-weight: 600; padding-bottom: 12px; }
.dp-table th, .dp-table td { text-align: left; padding: 12px 16px; border-bottom: 1px solid var(--dp-border); font-size: 16px; }
.dp-table th { position: sticky; top: 64px; z-index: 1; background: var(--dp-surface); font-weight: 600; }
.dp-table--zebra tbody tr:nth-child(even) { background: var(--dp-surface-subtle); }

/* Below 1024: card transformation for mobile="cards" */
@media (max-width: 1023px) {
  .dp-table-wrap[data-mobile="cards"] table { width: 100%; }
  .dp-table-wrap[data-mobile="cards"] thead { display: none; }
  .dp-table-wrap[data-mobile="cards"] tbody, .dp-table-wrap[data-mobile="cards"] tr { display: block; }
  .dp-table-wrap[data-mobile="cards"] tr { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); margin-bottom: 12px; }
  .dp-table-wrap[data-mobile="cards"] td, .dp-table-wrap[data-mobile="cards"] th[scope="row"] { display: grid; grid-template-columns: 40% 1fr; border-bottom: 1px solid var(--dp-border); }
  .dp-table-wrap[data-mobile="cards"] tr > :last-child { border-bottom: none; }
  .dp-table-wrap[data-mobile="cards"] td::before, .dp-table-wrap[data-mobile="cards"] th[scope="row"]::before { content: attr(data-label); font-weight: 500; color: var(--dp-text-secondary); }

  /* Below 1024: horizontal scroll with a fade affordance for mobile="scroll" */
  .dp-table-wrap[data-mobile="scroll"] { overflow-x: auto; }
  .dp-table-wrap[data-mobile="scroll"]::after {
    content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 32px; pointer-events: none;
    background: linear-gradient(to right, transparent, var(--dp-bg)); opacity: 0; transition: opacity .15s;
  }
  .dp-table-wrap[data-mobile="scroll"].has-more-right::after { opacity: 1; }
  .dp-table-wrap[data-mobile="scroll"]::before {
    content: ""; position: absolute; top: 0; left: 0; bottom: 0; width: 32px; pointer-events: none;
    background: linear-gradient(to left, transparent, var(--dp-bg)); opacity: 0; transition: opacity .15s;
  }
  .dp-table-wrap[data-mobile="scroll"].has-more-left::before { opacity: 1; }

  /* Below 1024: one-line cards for mobile="compact" — the illustrative registry tables (F10).
     thead stays in the DOM (visually-hidden, not display:none) so the th/scope header
     association survives for screen readers; sighted mobile users get the header label back
     via data-label prefixes on the meta segments instead. */
  .dp-table-wrap[data-mobile="compact"] thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .dp-table-wrap[data-mobile="compact"] tbody, .dp-table-wrap[data-mobile="compact"] tr { display: block; }
  .dp-table-wrap[data-mobile="compact"] tr { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 12px 16px; margin-bottom: 12px;
    display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; }
  .dp-table-wrap[data-mobile="compact"] td, .dp-table-wrap[data-mobile="compact"] th[scope="row"] { border: 0; padding: 0; text-align: left; }
  .dp-table-wrap[data-mobile="compact"] td[data-role="title"], .dp-table-wrap[data-mobile="compact"] th[data-role="title"] { grid-column: 1; font-weight: 600; }
  .dp-table-wrap[data-mobile="compact"] td[data-role="chip"] { grid-column: 2; grid-row: 1; justify-self: end; }
  .dp-table-wrap[data-mobile="compact"] td[data-role="meta"] { grid-column: 1 / -1; display: inline; font: 400 14px/1.5 var(--dp-font-mono); color: var(--dp-text-secondary); }
  .dp-table-wrap[data-mobile="compact"] td[data-role="meta"]::before { content: attr(data-label) " "; color: var(--dp-text-secondary); }
  .dp-table-wrap[data-mobile="compact"] td[data-role="meta"] + td[data-role="meta"]::before { content: " · " attr(data-label) " "; }
}

}

/* == tabs.css == */
@layer components {
.dp-tabs__list { display: flex; gap: 4px; border-bottom: 1px solid var(--dp-border); overflow-x: auto; scrollbar-width: none; }
.dp-tabs__list::-webkit-scrollbar { display: none; }
.dp-tabs__tab { display: inline-flex; align-items: center; min-height: var(--dp-touch-target); padding: 0 16px; border: none;
  background: none; font: 500 16px/1.2 var(--dp-font-body); color: var(--dp-text-secondary); cursor: pointer; white-space: nowrap; }
.dp-tabs__tab[aria-selected="true"] { box-shadow: inset 0 -2px 0 var(--dp-pink-500); color: var(--dp-text); }
.dp-tabs__tab[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.dp-tabs__badge { display: inline-flex; align-items: center; min-height: 20px; margin-left: 6px; padding: 0 6px;
  border-radius: var(--dp-radius-chip); background: var(--dp-surface-subtle); color: var(--dp-text-secondary);
  font: 500 14px/1 var(--dp-font-mono); }
.dp-tabs__panel { padding-block: 16px; }

@media (max-width: 1023px) {
  .dp-tabs__list { border-bottom: none; gap: 8px; }
  .dp-tabs__tab { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-chip); padding: 0 14px; }
  .dp-tabs__tab[aria-selected="true"] { box-shadow: none; border-color: var(--dp-pink-500); background: var(--dp-pink-100); color: var(--dp-text); }
}

}

/* == toc.css == */
@layer components {
.dp-toc__dropdown { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 4px 16px; }
.dp-toc__dropdown summary { min-height: var(--dp-touch-target); display: flex; align-items: center; cursor: pointer; font-weight: 500; }
.dp-toc__dropdown ol, .dp-toc__rail { list-style: none; margin: 0; padding: 0; }
.dp-toc__dropdown ol { padding: 8px 0 12px; }
.dp-toc__dropdown li + li, .dp-toc__rail li + li { margin-top: 8px; }
.dp-toc__dropdown a, .dp-toc__rail a { color: var(--dp-text-secondary); text-decoration: none; font-size: 14px; }
.dp-toc__dropdown a:hover, .dp-toc__rail a:hover { color: var(--dp-text); }
.dp-toc__rail { display: none; }
.dp-toc__rail a[aria-current="location"] { color: var(--dp-pink-600); font-weight: 500; box-shadow: inset 2px 0 0 var(--dp-pink-500); padding-left: 12px; }

@media (min-width: 1024px) {
  .dp-toc__dropdown { display: none; }
  .dp-toc__rail { display: block; position: sticky; top: 88px; }
}

}

/* == trust-strip.css == */
@layer components {
.dp-trust { list-style: none; margin: 0; padding: 0; display: inline-flex; flex-wrap: wrap; gap: 8px 24px;
  font: 14px var(--dp-font-mono); color: var(--dp-text-secondary); }
.dp-trust li { display: inline-flex; align-items: center; gap: 8px; }
.dp-trust__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--dp-teal-500); display: inline-block; }

}

/* == verification-strip.css == */
@layer components {
.dp-vstrip { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr; gap: 24px; }
.dp-vstrip__num { display: block; color: var(--dp-text-secondary); margin-bottom: 8px; }
.dp-vstrip h3 { margin: 0 0 4px; font-size: 18px; }
.dp-vstrip p { margin: 0; color: var(--dp-text-secondary); }

@media (min-width: 768px) {
  .dp-vstrip { grid-template-columns: repeat(4, 1fr); }
}

}

/* == t1.css == */
@layer templates {
/* T1 — service page. Section rhythm plus the two T1-specific grids: the "what this stage does"
   capability grid and the "inputs / outputs" two-column interface list. */

.dp-t1 > .dp-section:first-child { padding-top: 0; }
.dp-t1 .dp-section + .dp-section { border-top: 1px solid var(--dp-border); }

/* Graphite inset — the page's one dark section (dp_section(['graphite' => true])). Re-scopes the
   light-mode ground/text tokens locally so every nested component (section head, layer stack,
   callout, card grid) renders correctly without a separate dark variant of each. State-label
   colours swap from the *-text (darkened for paper) to a tone that clears 4.5:1 on
   --dp-graphite-bg: teal/amber's full-strength -500 already does; blue/violet/red also render on
   a --dp-*-tint badge background (a translucent overlay on graphite, not itself re-scoped) where
   -500 alone drops under 4.5:1, so those three use the dedicated *-500-ondark token instead
   (design/tokens.css — added Task 27, see that file's comment for the numbers). */
.dp-section--graphite {
  --dp-bg: var(--dp-graphite-bg);
  --dp-surface: var(--dp-graphite-surface);
  --dp-surface-subtle: var(--dp-graphite-raised);
  --dp-border: var(--dp-graphite-border);
  --dp-text: var(--dp-graphite-text);
  --dp-text-secondary: var(--dp-graphite-text-secondary);
  --dp-blue-text: var(--dp-blue-500-ondark);
  --dp-violet-text: var(--dp-violet-500-ondark);
  --dp-teal-text: var(--dp-teal-500);
  --dp-amber-text: var(--dp-amber-500);
  --dp-red-text: var(--dp-red-500-ondark);
  background: var(--dp-bg);
  color: var(--dp-text);
}

/* "What this stage does" — dp_card_grid(['cols' => 4]) already renders 4 → 2 → 1 columns; no
   template override needed beyond the shared component grid in components/card.css. */

/* Inputs / outputs — dp_two_col() with a semantic rule per column: blue for inputs (acquisition),
   teal for outputs (accepted / valid), per the state-colour table. */
.dp-io__col { border-top: 3px solid var(--dp-text-muted); padding-top: 16px; }
.dp-io__col--blue { border-top-color: var(--dp-blue-500); }
.dp-io__col--teal { border-top-color: var(--dp-teal-500); }
.dp-io__col h3 { margin-bottom: 12px; }
.dp-io__col ul { margin: 0; padding-left: 20px; color: var(--dp-text-secondary); display: flex; flex-direction: column; gap: 10px; }

/* Rejection report preview — illustrative bars only, never a real proportion; every row carries
   the reason code as text and "[share] · illustrative" as a label, so colour/length is never the
   only signal. */
.dp-rejection { display: flex; flex-direction: column; gap: 16px; }
.dp-rejection__caption { color: var(--dp-text); font-weight: 600; }
.dp-rejection__scope { color: var(--dp-text-secondary); }
.dp-rejection__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.dp-rejection__list li { display: grid; grid-template-columns: minmax(0, 220px) minmax(80px, 1fr) auto; align-items: center; gap: 16px; }
.dp-rejection__list code { font-size: 14px; color: var(--dp-text); }
.dp-rejection__bar { display: block; height: 10px; border-radius: var(--dp-radius-chip); background: var(--dp-amber-tint); border: 1px solid var(--dp-amber-500); }
.dp-rejection__share { font-size: 14px; color: var(--dp-text-secondary); white-space: nowrap; }
@media (max-width: 767px) {
  .dp-rejection__list li { grid-template-columns: 1fr; gap: 6px; }
}

.dp-note { font-size: 14px; color: var(--dp-text-secondary); margin: 16px 0 0; }

}

/* == t2.css == */
@layer templates {
/* T2 — dataset product page. Section rhythm plus the T2-specific "what you provide" checklist.
   The 8-card configurable-dimensions grid and the 5-card metric grid reuse the shared
   dp-card-grid / dp-metric-grid rules in components/card.css (4 cols ≥1024, 2 cols 480–1023,
   1 col below 480 — matches the brief's 4×2 / 2-col / 1-col behaviour with no override needed
   here). The page's one graphite inset (block 07, sample schema) uses `.dp-section--graphite`,
   defined once in templates/t1.css and shared here via the CSS bundle — not redefined per
   template. */

.dp-t2 > .dp-section:first-child { padding-top: 0; }
.dp-t2 .dp-section + .dp-section { border-top: 1px solid var(--dp-border); }

/* "What you provide" — a two-column dotted checklist (blue dot: acquisition-stage input from the
   customer). Colour is never the only signal: each item still carries its full text label. */
.dp-dotlist {
  list-style: none; margin: 0 0 24px; padding: 0;
  display: grid; grid-template-columns: 1fr; gap: 12px 48px;
}
@media (min-width: 768px) { .dp-dotlist { grid-template-columns: 1fr 1fr; } }
.dp-dotlist li { display: flex; gap: 12px; align-items: flex-start; font-size: 16px; line-height: 1.6; color: var(--dp-text-secondary); }
.dp-dotlist__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--dp-blue-500); margin-top: 10px; flex-shrink: 0; }

}

/* == t3.css == */
@layer templates {
/* T3 — use-case page. Section rhythm shared with T1/T2. Situation cards (3-up) and product cards
   (4-up) reuse the shared dp-card-grid rules in components/card.css (already 3/4 → 2 → 1 at the
   right breakpoints — no override needed here). The decision-helper table reuses dp_table() with
   `mobile => 'cards'`, same as the T1/T2 comparison tables. */

.dp-t3 > .dp-section:first-child { padding-top: 0; }
.dp-t3 .dp-section + .dp-section { border-top: 1px solid var(--dp-border); }

/* Decision helper — graphite-toned inset in the approved design (dark background, symptom →
   product table). The page's callouts (template rule) and formats chips sit on the default
   paper ground either side of it. */
.dp-t3 .dp-section--graphite .dp-table { color: inherit; }

}

/* == t4.css == */
@layer templates {
/* T4 — resource article. Rail + article grid: 240px toc rail beside the article at >=1024 (the
   dp-toc component itself already swaps rail/dropdown per breakpoint, see components/toc.css);
   below 1024 the grid collapses to a single column and the dropdown sits above the body. Article
   measure is capped near 68ch — Parsedown's own headings/paragraphs/lists/tables/code blocks are
   styled here rather than in base.css, since only article bodies contain them. */

.dp-t4-head { padding-block: var(--dp-section-y) 24px; }
.dp-t4-head h1 { margin: 8px 0 16px; }
.dp-t4-head__byline { color: var(--dp-text-secondary); font-size: 14px; margin: 0 0 16px; }

.dp-t4-grid { display: grid; grid-template-columns: 1fr; gap: 32px; padding-bottom: var(--dp-section-y); align-items: start; }
/* Grid items default to min-width:auto (their content's min-content), which can force an `1fr`
   track wider than the grid's own box and cause page-level horizontal scroll — seen on this
   template's TOC nav below 1024. Let both items shrink to the track instead. */
.dp-t4-grid > * { min-width: 0; }
@media (min-width: 1024px) {
  .dp-t4-grid { grid-template-columns: 240px 1fr; gap: 48px; }
}

.dp-article { max-width: 68ch; }
.dp-article h2 { font-size: 26px; margin: 48px 0 16px; scroll-margin-top: 96px; }
.dp-article h2:first-child { margin-top: 0; }
.dp-article h3 { font-size: 20px; margin: 32px 0 12px; scroll-margin-top: 96px; }
.dp-article p { margin: 0 0 16px; line-height: 1.7; }
.dp-article ul, .dp-article ol { margin: 0 0 16px; padding-left: 24px; line-height: 1.7; }
.dp-article li + li { margin-top: 6px; }
.dp-article code { font-family: var(--dp-font-mono); font-size: 0.9em; background: var(--dp-surface-subtle); border-radius: 4px; padding: 0.15em 0.4em; }
.dp-article pre { background: var(--dp-graphite-bg); color: var(--dp-graphite-text); border-radius: var(--dp-radius-card); padding: 16px 20px; overflow-x: auto; margin: 0 0 16px; }
.dp-article pre code { background: none; padding: 0; font-size: 14px; }
/* Markdown tables are wrapped server-side (dp_wrap_article_tables()) in the same
   .dp-table-wrap[data-mobile="scroll"] markup dp_table() produces, so they get the shared
   sticky-header + fade-affordance behaviour from components/table.css for free below 1024. Only
   article-specific spacing/measure lives here. */
.dp-article .dp-table-wrap { margin: 0 0 16px; }
.dp-article table { font-size: 15px; }

.dp-article .dp-diagram { max-width: 100%; height: auto; margin: 0 0 24px; }

.dp-article__refs { margin-top: 48px; padding-top: 32px; border-top: 1px solid var(--dp-border); }
.dp-article__refs ol { padding-left: 24px; }
.dp-article__refs-note { color: var(--dp-text-secondary); font-size: 14px; margin-top: 16px; }

}

/* == t5.css == */
@layer templates {
/* T5 — legal / policy page. Plain numbered sections a reader can cite: no cards, no decorative
   treatment. Measure capped near 70ch per the brief; a sticky two-column layout at >=1024 puts
   the Contents nav in a left rail (matching the article TOC pattern), stacked above the body
   below that. */

.dp-legal__head { padding-block: var(--dp-section-y) 24px; }
.dp-legal__head h1 { margin: 8px 0 12px; }
.dp-legal__meta { color: var(--dp-text-secondary); font-size: 14px; font-family: var(--dp-font-mono); margin: 0 0 24px; }

.dp-legal { display: grid; grid-template-columns: 1fr; gap: 32px; padding-bottom: var(--dp-section-y); align-items: start; }
@media (min-width: 1024px) {
  .dp-legal { grid-template-columns: 240px 1fr; gap: 48px; }
}

.dp-legal__toc { font-size: 14px; }
.dp-legal__toc-label { font-family: var(--dp-font-mono); font-size: 14px; color: var(--dp-text-secondary); margin: 0 0 12px; text-transform: uppercase; letter-spacing: 0.02em; }
.dp-legal__toc ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.dp-legal__toc a { color: var(--dp-text-secondary); text-decoration: none; }
.dp-legal__toc a:hover, .dp-legal__toc a:focus-visible { color: var(--dp-text); text-decoration: underline; }
@media (min-width: 1024px) {
  .dp-legal__toc { position: sticky; top: 88px; }
}

.dp-legal__body { max-width: 70ch; }
.dp-legal__section { padding-block: 32px; border-top: 1px solid var(--dp-border); scroll-margin-top: 96px; }
.dp-legal__section:first-child { border-top: none; padding-top: 0; }
.dp-legal__section h2 { font-size: 22px; margin: 0 0 12px; }
.dp-legal__summary { color: var(--dp-text-secondary); margin: 0 0 16px; line-height: 1.6; }

.dp-legal__contact { padding-top: 32px; margin-top: 32px; border-top: 1px solid var(--dp-border); }
.dp-legal__contact h2 { font-size: 20px; margin: 0 0 12px; }
.dp-legal__contact p { color: var(--dp-text-secondary); margin: 0 0 6px; line-height: 1.6; }

}

/* == about.css == */
@layer pages {
/* About (/about/) — layout specific to this page only. See app/templates/custom/about.php and
   app/pages/about.php. Shared visuals (card, chips, callout, two-col) come from components/*.css. */

/* dp_card_grid(['cols' => 5]) — the working-principles row (P20 draws five cards in one row at
   desktop). dp-card-grid's shared breakpoints only define --2/--3/--4; this page is the first
   caller to need five, so the extra column count is added here rather than in the shared
   component file. */
.dp-card-grid--5 { grid-template-columns: 1fr; }
@media (min-width: 480px) { .dp-card-grid--5 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .dp-card-grid--5 { grid-template-columns: repeat(5, 1fr); } }

/* Partners / where-we-are / careers strip — a bare container (P20 draws no section heading
   above these three cards). */
.dp-about__strip { padding-block: 8px 0; }

/* Team — four [NAME]/[FOCUS] profile cards with a neutral CSS shape standing in for a
   photograph. Never an <img>; see app/pages/about.php's dp_about_team(). */
.dp-team { display: grid; grid-template-columns: 1fr; gap: 24px; margin-bottom: 20px; }
@media (min-width: 480px) { .dp-team { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .dp-team { grid-template-columns: repeat(4, 1fr); } }

.dp-profile { background: var(--dp-surface); border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 20px; display: flex; flex-direction: column; gap: 10px; }
.dp-profile__shape { display: block; width: 64px; height: 64px; border-radius: var(--dp-radius-card); background: var(--dp-surface-subtle); border: 1px solid var(--dp-border); }
.dp-profile__name { margin: 0; font-size: 19px; }
.dp-profile__role { margin: 0; font-size: 14px; color: var(--dp-pink-600); }
.dp-profile__desc { margin: 0; font-size: 14px; color: var(--dp-text-secondary); }

.dp-about__note { color: var(--dp-text-secondary); margin: 0 0 16px; }

}

/* == contact.css == */
@layer pages {
/* Contact / RFQ (/contact/) — layout specific to this page. Shared field/fieldset/chip/error/
   submit-bar visuals come from components/form.css; this file only lays out the two-column
   form + aside grid and the "what happens next" / "while you wait" aside content. */

.dp-rfq__head { margin-bottom: 32px; }
.dp-rfq__head .dp-hero__copy { max-width: 640px; }
.dp-rfq__head .dp-hero__grid { gap: 24px; }
.dp-rfq__head .dp-rfq__next { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 20px; background: var(--dp-surface); }

.dp-rfq__grid { display: flex; flex-direction: column; gap: 40px; }

.dp-rfq__form { display: flex; flex-direction: column; gap: 0; min-width: 0; }

.dp-rfq__upload-note { margin: 16px 0 0; }

.dp-rfq__aside { display: flex; flex-direction: column; gap: 24px; }
.dp-rfq__aside h2 { font-size: 18px; margin: 0 0 12px; }

.dp-rfq__steps { list-style: none; margin: 0 0 16px; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.dp-rfq__steps li { display: flex; gap: 12px; align-items: baseline; }
.dp-rfq__stepnum { font: 600 14px/1 var(--dp-font-mono); color: var(--dp-text-secondary); flex: none; }
.dp-rfq__steps p { margin: 0; }
.dp-rfq__nda { color: var(--dp-text-secondary); margin: 0; }

/* Progressive disclosure (Task 16): the seven-field "Your brief" block always shows; everything
   else sits inside the native <details>, which works with no JavaScript and needs no accordion.js
   toggle of its own — .dp-formstep/.dp-formstep__title/.dp-formstep__body (components/form.css)
   already give it the same card look as the fieldsets nested inside <details>. */
.dp-rfq__essentials-title { padding: 16px 16px 0; }
.dp-rfq__essentials .dp-formstep__body { padding-top: 20px; }

.dp-rfq__more {
  border: 1px solid var(--dp-border);
  border-radius: var(--dp-radius-card);
  margin-bottom: 16px;
}
.dp-rfq__more[open] { padding-bottom: 16px; }
.dp-rfq__more > summary {
  list-style: none;
  cursor: pointer;
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 16px;
  font: 600 16px/1.3 var(--dp-font-body);
  color: var(--dp-text);
}
.dp-rfq__more > summary::-webkit-details-marker { display: none; }
.dp-rfq__more > summary::before {
  content: '';
  flex: none;
  width: 10px;
  height: 10px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}
.dp-rfq__more[open] > summary::before { transform: rotate(45deg); }
.dp-rfq__more > summary:focus-visible {
  outline: 2px solid var(--dp-pink-500);
  outline-offset: 2px;
}
.dp-rfq__more-body { padding: 0 16px; display: flex; flex-direction: column; gap: 16px; }
.dp-rfq__more-body .dp-formstep:last-child { margin-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .dp-rfq__more > summary::before { transition: none; }
}

@media (min-width: 1024px) {
  .dp-rfq__grid { flex-direction: row; align-items: flex-start; gap: 40px; }
  .dp-rfq__form { flex: 7; }
  .dp-rfq__aside { flex: 5; position: sticky; top: 88px; }
}

/* The "What happens next" block sits in the hero's right column (design audit D4). Match the glance
   card the other heroes use: bordered surface, mono label instead of a display heading. */
.dp-hero__aside .dp-rfq__next { border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card); padding: 20px; background: var(--dp-surface); }
.dp-hero__aside .dp-rfq__next h2 { margin: 0 0 12px; font: 500 14px/1.3 var(--dp-font-mono); color: var(--dp-text-secondary); }

}

/* == dev-components.css == */
@layer pages {
/* Dev-only component showcase grid — not shipped as design system, just a layout aid for /_dev/components/. */
.dp-dev-components .dp-section + .dp-section { border-top: 1px solid var(--dp-border); }
.dp-dev-components h2 { margin-top: 0; }
.dp-dev-components h3 { margin-top: 32px; }

.dp-dev-row { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-block: 12px; }
.dp-dev-state { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.dp-dev-state__label { color: var(--dp-text-secondary); }

.dp-dev-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 24px; margin-block: 12px; }

.dp-dev-diagrams { display: grid; grid-template-columns: 1fr; gap: 32px; margin-top: 24px; }
@media (min-width: 768px) {
  .dp-dev-diagrams { grid-template-columns: 1fr 1fr; }
}
.dp-dev-diagrams svg { width: 100%; height: auto; border: 1px solid var(--dp-border); border-radius: 8px; background: var(--dp-surface); }

}

/* == home.css == */
@layer pages {
/* Home (/) — layout specific to this page only; shared visuals (cards, stepper, trust strip,
   proof band, deliverables, FAQ) come from components/*.css. See app/templates/custom/home.php
   and app/pages/home.php. */

/* Trust strip sits directly under the hero, before the first section — no extra top padding so
   it reads as part of the hero band rather than its own section. */
.dp-home__trust { padding-block: 0 40px; }

/* 01 products — 1 col below 768, 2 cols 768–1023, 4 cols >=1024 (overrides the shared
   dp-card-grid--4 default, which switches to 2 columns at 480). */
.dp-home-products .dp-card-grid--4 { grid-template-columns: 1fr; }
@media (min-width: 768px) and (max-width: 1023px) { .dp-home-products .dp-card-grid--4 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .dp-home-products .dp-card-grid--4 { grid-template-columns: repeat(4, 1fr); } }

/* 04 who it is for — left-border tone card with a "use case" mono kicker above a linked title.
   1 col below 768, 2 cols 768–1023, 4 cols >=1024, matching the products grid above. */
.dp-home-usecases { display: grid; grid-template-columns: 1fr; gap: 24px; }
@media (min-width: 768px) and (max-width: 1023px) { .dp-home-usecases { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .dp-home-usecases { grid-template-columns: repeat(4, 1fr); } }

.dp-home-usecase {
  background: var(--dp-surface); border: 1px solid var(--dp-border); border-left: 3px solid var(--dp-text-muted);
  border-radius: var(--dp-radius-card); padding: 20px; display: flex; flex-direction: column; gap: 8px;
}
.dp-home-usecase--blue { border-left-color: var(--dp-blue-500); }
.dp-home-usecase--violet { border-left-color: var(--dp-violet-500); }
.dp-home-usecase--teal { border-left-color: var(--dp-teal-500); }
.dp-home-usecase--amber { border-left-color: var(--dp-amber-500); }
.dp-home-usecase--red { border-left-color: var(--dp-red-500); }
.dp-home-usecase__kicker { display: block; font-size: 14px; color: var(--dp-text-secondary); }
.dp-home-usecase__title { margin: 0; font-size: 19px; }
.dp-home-usecase__title a { color: inherit; text-decoration: none; }
.dp-home-usecase__title a:hover { text-decoration: underline; }
.dp-home-usecase__desc { margin: 0; font-size: 14px; color: var(--dp-text-secondary); }

/* 06 quality & provenance — neutral card, coloured mono inset line (not a top-tone card). */
.dp-home-provenance { display: grid; grid-template-columns: 1fr; gap: 24px; margin-bottom: 20px; }
@media (min-width: 768px) { .dp-home-provenance { grid-template-columns: repeat(3, 1fr); } }
.dp-home-provenance__card {
  background: var(--dp-surface); border: 1px solid var(--dp-border); border-radius: var(--dp-radius-card);
  padding: 26px; display: flex; flex-direction: column; gap: 12px;
}
.dp-home-provenance__title { margin: 0; font-size: 19px; }
.dp-home-provenance__desc { margin: 0; font-size: 14px; color: var(--dp-text-secondary); }
.dp-home-provenance__code {
  margin: 0; padding: 10px 12px; background: var(--dp-surface-subtle); border-left: 2px solid var(--dp-text-muted);
  border-radius: 4px; font-size: 14px;
}
.dp-home-provenance__code--blue { border-left-color: var(--dp-blue-500); }
.dp-home-provenance__code--violet { border-left-color: var(--dp-violet-500); }
.dp-home-provenance__code--teal { border-left-color: var(--dp-teal-500); }
.dp-home-provenance__code--amber { border-left-color: var(--dp-amber-500); }
.dp-home-provenance__code--red { border-left-color: var(--dp-red-500); }
.dp-home-provenance__link { margin: 0; }
.dp-home-provenance__link a { color: var(--dp-pink-600); font-weight: 600; text-decoration: none; }
.dp-home-provenance__link a:hover { text-decoration: underline; }

}

/* == hub.css == */
@layer pages {
/* Shared hub layout (/datasets/, /use-cases/) — see app/templates/custom/hub.php. Shared visuals
   (card grid) come from components/card.css; this file only tightens the column breakpoints for
   the hub's card grid. */

/* Card grid — 1 col below 768, 2 cols 768–1023, 3 cols >=1024 (overrides the shared
   dp-card-grid--3 default, which switches to 2 columns at 480). */
.dp-hub .dp-card-grid--3 { grid-template-columns: 1fr; }
@media (min-width: 768px) and (max-width: 1023px) { .dp-hub .dp-card-grid--3 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .dp-hub .dp-card-grid--3 { grid-template-columns: repeat(3, 1fr); } }

}

/* == llm.css == */
@layer pages {
/* LLM Training Data page (/datasets/llm-training-data/) — page-scoped layout only.
   Colour comes exclusively from tokens.css custom properties; no hex here. */

/* 01 the two halves — two-column card layout already covered by .dp-card-grid--2 (card.css);
   nothing extra needed there. Kept as a marker comment for the block this file is scoped to. */

/* 02 training-stage selector — panel headings above the shared .dp-dotlist (t2.css). Not the
   tab-selector label (that is .dp-tabs__tab in tabs.css, already sentence case) — this is the
   in-panel sub-heading, aligned to the site's lowercase-mono kicker voice (audit §4, D1). */
.dp-stage-panel__head {
  margin: 0 0 8px; font: 500 14px/1.3 var(--dp-font-mono); letter-spacing: 0;
  text-transform: none; color: var(--dp-text-secondary);
}
.dp-stage-panel__head:not(:first-child) { margin-top: 20px; }
.dp-stage-panel .dp-dotlist { grid-template-columns: 1fr; margin-bottom: 0; }

/* 07 mixture, splits & decontamination — four equal-width labelled bars. Widths are deliberately
   equal (never proportional) so the layout cannot be read as implying a split ratio. */
.dp-split-bars { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; list-style: none; margin: 0; padding: 0; }
@media (min-width: 768px) { .dp-split-bars { grid-template-columns: repeat(4, 1fr); } }

.dp-split-bars__bar {
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
  min-height: 64px; padding: 14px 12px; box-sizing: border-box;
  background: var(--dp-surface); border: 1px solid var(--dp-border); border-top: 3px solid var(--dp-text-muted);
  border-radius: var(--dp-radius-card);
}
.dp-split-bars__bar--train { border-top-color: var(--dp-blue-500); }
.dp-split-bars__bar--dev { border-top-color: var(--dp-violet-500); }
.dp-split-bars__bar--test { border-top-color: var(--dp-amber-500); }
.dp-split-bars__bar--private-eval { border-top-color: var(--dp-red-500); }

.dp-split-bars__label {
  font-family: var(--dp-font-mono); font-size: 14px; color: var(--dp-text);
}

/* Role word under each pill — colour never carries the meaning alone (audit §3): a reader in
   greyscale still gets "fit / tune / report / never trained on". Private eval also gets a
   heavier border rather than a lock icon, so the distinction survives without adding a glyph
   that would need its own text equivalent. */
.dp-split-bars__role {
  margin-top: 4px; font-size: 14px; color: var(--dp-text-secondary);
}
.dp-split-bars__role--locked { font-weight: 500; }
.dp-split-bars__bar--private-eval { border-width: 2px; }

}

/* == not-found.css == */
@layer pages {
/* 404 — layout specific to this page only. See app/templates/custom/not-found.php and
   app/pages/not-found.php. */
.dp-notfound { padding-block: 64px; display: flex; flex-direction: column; gap: 40px; }
.dp-notfound__head { display: flex; flex-direction: column; gap: 16px; align-items: center; text-align: center; margin: 0 auto; max-width: 640px; }

}

/* == process.css == */
@layer pages {
/* Process (/process/) — layout specific to this page only. See app/templates/custom/process.php
   and app/pages/process.php. Shared visuals (tabs, stepper, code block, table, diagram,
   read-next) come from components/*.css. */

/* Example switcher — dp_tabs plus the ten-stage stepper sit in a bare dp-container (P11 draws no
   section heading here, so dp_section is not used), so this page supplies the vertical rhythm
   dp_section would otherwise have provided: a small gap under the hero, and enough padding below
   the stepper before block A ("sample artifacts") starts. */
.dp-process__example { padding-block: 8px 40px; display: flex; flex-direction: column; gap: 16px; }
.dp-process__note { margin: 0; }

}

/* == resources.css == */
@layer pages {
/* Resources index. Cards reuse .dp-card / .dp-card--service (components/card.css); this file only
   adds the header spacing, the topic chip row and the two small meta lines each card needs
   (author/reviewer, date/reading-time placeholders — see app/templates/custom/resources.php). */

.dp-resources-hero { padding-block: var(--dp-section-y) 24px; }
.dp-resources-hero h1 { margin: 0 0 12px; }

.dp-resources-grid {
  display: grid; grid-template-columns: 1fr; gap: 24px;
  padding-block: 32px var(--dp-section-y);
}
@media (min-width: 768px) { .dp-resources-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .dp-resources-grid { grid-template-columns: repeat(3, 1fr); } }

.dp-resources-card__kicker { margin: 0; font-size: 14px; color: var(--dp-text-secondary); font-family: var(--dp-font-mono); }
.dp-resources-card__meta { margin: 0; font-size: 14px; color: var(--dp-text-secondary); }

.dp-resources-note { color: var(--dp-text-secondary); padding-bottom: var(--dp-section-y); }

}
