/**
 * Component CSS — generated from component records.
 * Do not edit. Write CSS on the component via upsert-component / patch-component.
 */

/* delta-component:abilities-marquee */
/* delta-component:check-list */
/* Redesign 3 Oct 2026: a plain 1.5px ink check, no box and no tint (prototype
   "Who it's for" rows). Text 16px, muted. */
.feature__list { display: flex; flex-direction: column; gap: var(--space-xs); }

.feature__item { display: flex; align-items: start; gap: var(--space-sm); color: var(--color-ink-muted); font-size: var(--text-md-size); line-height: var(--text-md-leading); }

.feature__check { flex: none; width: var(--space-lg); height: var(--space-lg); color: var(--color-ink); stroke-width: 1.5; }

/* delta-component:backup/integrations-marquee-2026-09-07 */
/* ---------- integrations logo marquee ----------
   One continuous strip of plugin tiles sliding left. The track holds TWO
   identical sets; the loop travels one set plus one gap, which with a gapped
   flex row is calc(-50% - gap/2) — plain -50% would land half a gap short and
   the strip would visibly jump each cycle. The second set is aria-hidden and
   the strip is a labelled group, so a screen reader gets each plugin once.
   Logos are <img>, not inline SVG: third-party marks keep their own palettes.
   Reduced motion: animation off, duplicate set hidden, row scrolls by hand. */
.logomq {
  --logomq-gap: var(--space-lg);
  display: flex;
  gap: var(--logomq-gap);
  overflow: hidden;
  width: 100%;
  max-width: var(--layout-wide);
  margin-inline: auto;
  -webkit-mask-image: linear-gradient(to right, transparent, black 12%, black 88%, transparent);
  mask-image: linear-gradient(to right, transparent, black 12%, black 88%, transparent);
}
.logomq__set {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--logomq-gap);
  list-style: none;
  margin: 0;
  padding: 0;
  animation: logomq 36s linear infinite;
}
.logomq:hover .logomq__set { animation-play-state: paused; }
.logomq__item {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-lg) var(--space-sm) var(--space-sm);
  background: var(--color-surface-subtle);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-full);
  color: var(--color-ink-muted);
  font-size: var(--text-sm-size);
  white-space: nowrap;
}
.logomq__logo {
  width: 2.5rem;
  height: 2.5rem;
  display: block;
  /* Rounded square, not a circle: several marks in the row are square-format
     lockups, and a full radius clipped their corners. */
  border-radius: var(--radius-lg);
}
@keyframes logomq {
  to { transform: translateX(calc(-100% - var(--logomq-gap))); }
}

/* delta-component:backup/roadmap-kanban-2026-09-07 */
/* ---------- roadmap kanban ----------
   Three columns, Planned / Doing / Done. Column status is data-status on the
   column; the head dot reads it.
   Mobile is the plain shape: one column, every list open to its full length,
   every card as tall as its own copy. No fixed height anywhere, so the page
   holds no scroll area of its own.
   From 48rem the rhythm comes back, in the block at the end of this section:
   every list is the same height, four cards tall, and scrolls inside itself
   behind a top and bottom fade, so a long Planned column and a one-card Done
   column sit level. The card height there is a cap, not a floor, so a card
   with less copy stays short. That block comes last because it and the base
   rules have the same weight: source order is what makes it win. */
.kanban {
  --kanban-card-h: calc(var(--space-3xl) * 2);
  --kanban-rows: 4;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-xl);
}
@media (min-width: 48rem) {
  .kanban { grid-template-columns: repeat(3, 1fr); gap: var(--space-2xl); }
}
.kanban__col {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  min-width: 0;
}
.kanban__head {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-mono);
  font-size: var(--text-xs-size);
  font-weight: var(--weight-regular, 400);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-ink-muted);
}
.kanban__head::before {
  content: "";
  width: 0.5rem; height: 0.5rem;
  border-radius: var(--radius-full);
  border: var(--border-width) solid var(--color-action);
  background: transparent;
}
.kanban__col[data-status="doing"] .kanban__head::before {
  background: var(--color-action);
  animation: timeline-breathe 2.4s ease-in-out infinite;
}
.kanban__col[data-status="done"] .kanban__head::before { background: var(--color-action); }
.kanban__count {
  color: color-mix(in oklch, var(--color-ink-muted) 60%, transparent);
}
.kanban__list {
  list-style: none;
  margin: 0;
  padding: var(--space-sm) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}
.kanban__list::-webkit-scrollbar { display: none; }
.kanban__list:focus-visible { outline: none; }
.kanban__list:focus-visible .kanban__card { border-color: color-mix(in oklch, var(--color-action) 40%, var(--color-border)); }
.kanban__card {
  flex: none;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  padding: var(--space-md);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-subtle);
  scroll-snap-align: start;
  transition: border-color 0.18s var(--ease, ease);
}
.kanban__col[data-status="done"] .kanban__card {
  border-color: color-mix(in oklch, var(--color-action) 35%, var(--color-border));
}
.kanban__title {
  margin: 0;
  flex: none;
  font-family: var(--font-title);
  font-size: var(--text-md-size, 1rem);
  line-height: var(--text-md-leading, 1.4);
  font-weight: var(--weight-semibold);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kanban__text {
  margin: 0;
  flex: none;
  color: var(--color-ink-muted);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-leading, 1.5);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Kanban, 48rem and up: the four-card column rhythm and the inner scroll. */
@media (min-width: 48rem) {
  .kanban__list {
    height: calc(var(--kanban-rows) * var(--kanban-card-h) + (var(--kanban-rows) - 1) * var(--space-sm) + 2 * var(--space-sm));
    overflow-y: auto;
    scrollbar-width: none;
    scroll-snap-type: y proximity;
    scroll-padding-block: var(--space-sm);
    -webkit-mask-image: linear-gradient(to bottom, transparent, black 10%, black 88%, transparent);
    mask-image: linear-gradient(to bottom, transparent, black 10%, black 88%, transparent);
  }
  .kanban__card { max-height: var(--kanban-card-h); }
}

/* delta-component:boxed-icon-card */
/* ---------- boxed icon card ----------
   Icon-led feature card. The icon sits in a square box with an action-tinted
   fill (color-mix). Glyph SVG is per-instance inside .boxed-icon-card__icon. */
.boxed-icon-card {
  --boxed-icon-card-icon-size: var(--space-2xl);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-md);
  /* Filled, so no border (3 Oct 2026). The icon square keeps its outline. */
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  background: var(--color-surface-subtle);
}

.boxed-icon-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--boxed-icon-card-icon-size);
  height: var(--boxed-icon-card-icon-size);
  flex: none;
  /* The one site border (John, 4 Oct 2026), no tint. The icon stays ink. */
  color: var(--color-ink);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
}

.boxed-icon-card__icon svg {
  width: var(--space-lg);
  height: var(--space-lg);
}

.boxed-icon-card__icon svg * {
  vector-effect: non-scaling-stroke;
}

.boxed-icon-card__title {
  font-family: var(--font-title);
  font-size: var(--title-card-size);
  line-height: var(--title-sm-leading);
  letter-spacing: var(--title-sm-tracking);
  font-weight: var(--title-weight, var(--weight-semibold));
  text-wrap: pretty;
}

.boxed-icon-card__body {
  color: var(--color-ink-muted);
  font-size: var(--text-md-size);
  line-height: var(--text-md-leading);
  letter-spacing: var(--text-md-tracking);
  text-wrap: pretty;
}

/* Plain modifier: same card, no box. Used where the section already carries a
   surface (a wash or a grid canvas) and six bordered panels would double it.
   Only the outer chrome goes; the icon keeps its square. */
.boxed-icon-card--plain {
  border: 0;
  border-radius: 0;
  padding: 0;
  background: transparent;
}

/* Inline modifier: the icon square sits on the inline start and the copy runs
   left aligned beside it. Two-column grid — the square holds column one and
   spans both rows, title and body stack in column two. Composes with --plain.
   Use it for a compact row of facts inside a section; the stacked default
   stays the primary card. */
.boxed-icon-card--inline {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-md);
  row-gap: var(--space-2xs);
  align-items: start;
  text-align: start;
}

.boxed-icon-card--inline .boxed-icon-card__icon {
  grid-row: 1 / span 2;
}

/* The title row is at least as tall as the icon square, and the title centres
   inside it. A one-line title then sits on the icon's centre line instead of
   its top edge; a title that wraps past the icon height is unaffected. */
.boxed-icon-card--inline .boxed-icon-card__title {
  display: flex;
  align-items: center;
  min-height: var(--boxed-icon-card-icon-size);
}

/* delta-component:button */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  /* Redesign 3 Oct 2026 (prototype buttons): one control height shared with
     fields, 18px label at weight 500, colour-only hover (no lift). */
  height: var(--control-height);
  padding: 0 var(--space-md);
  /* Shape comes from the site's control radius (site.css --button-radius),
     shared with fields; never a literal here. */
  border-radius: var(--button-radius);
  font-family: var(--font-text);
  font-size: var(--text-lg-size);
  font-weight: var(--weight-medium);
  line-height: 1;
  text-decoration: none;
  border: var(--border-width) solid transparent;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--curve-standard), color var(--duration-fast) var(--curve-standard), border-color var(--duration-fast) var(--curve-standard);
}

.btn--primary {
  background: var(--color-action);
  color: var(--color-on-action);
}

.btn--primary:hover {
  background: var(--color-action-hover);
  color: var(--color-on-action);
}

/* Ghost carries no border at all: it is a filled button, and next to the solid
   action button an outline read as a third weight. The transparent hairline
   from .btn stays, so the box keeps the same size as its neighbours and the
   row does not shift. --secondary is the outline variant. */
.btn--ghost {
  background: color-mix(in oklch, var(--color-ink) 6%, transparent);
  color: var(--color-ink);
}

.btn--ghost:hover {
  background: color-mix(in oklch, var(--color-ink) 10%, transparent);
  color: var(--color-ink);
}

.btn--secondary {
  background: transparent;
  color: var(--color-ink);
  border-color: currentColor;
}

.btn--secondary:hover {
  color: var(--color-action-hover);
}

/* Large: the one main ask in a hero or closing band. */
.btn--lg {
  font-size: var(--text-xl-size);
  padding-inline: calc(var(--space-md) * 1.25);
}

.btn__icon, .btn .delta-icon { width: 1.125rem; height: 1.125rem; flex: none; }

@media (prefers-reduced-motion: reduce) {
.btn, .pager a, .sitesearch__input, .sitesearch__submit { transition: none; }

}

/* delta-component:check-list */
/* Redesign 3 Oct 2026: a plain 1.5px ink check, no box and no tint (prototype
   "Who it's for" rows). Text 16px, muted. */
.feature__list { display: flex; flex-direction: column; gap: var(--space-xs); }
.feature__item { display: flex; align-items: start; gap: var(--space-sm); color: var(--color-ink-muted); font-size: var(--text-md-size); line-height: var(--text-md-leading); }
.feature__check { flex: none; width: var(--space-lg); height: var(--space-lg); color: var(--color-ink); stroke-width: 1.5; }

/* delta-component:code-block */
/* ---------- code block ----------
   Code sample with a pinned bar and syntax colour. The inner scroll area owns
   both axes with a height cap, so the bar (language + copy) stays at the top
   of the box and the horizontal scrollbar is always in reach. Nothing here is
   sticky. Written as .prose .code-block too: .prose figure is 0,1,1 and would
   otherwise win the margin. Syntax colours are composed from tokens.
   Redesign 3 Oct 2026 (John): code boxes are BLACK. The box sits on the dark
   contrast surface with the -on-contrast text and rule pair. Syntax marks:
   cyan keywords, yellow strings, orange numbers (status colours as marks
   only); everything else light or muted-on-contrast. No blue on black. */
.code-block,
.prose .code-block {
  --code-kw: var(--color-success);
  --code-fn: var(--color-ink-on-contrast);
  --code-var: var(--color-success);
  --code-str: var(--color-warning);
  --code-attr: var(--color-ink-muted-on-contrast);
  --code-num: var(--color-danger);
  --code-tag: var(--color-ink-on-contrast);
  --code-com: var(--color-ink-muted-on-contrast);
  --code-pun: var(--color-ink-muted-on-contrast);
  --code-bad: var(--color-danger);
  display: flex;
  flex-direction: column;
  min-width: 0;
  margin: 0 0 var(--space-md);
  color: var(--color-ink-on-contrast);
  background: var(--color-surface-contrast);
  border: 0; /* filled box: no outer border (John, 4 Oct) */
  border-radius: var(--radius-md);
  overflow: hidden;
  tab-size: 2;
}

.code-block__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  margin: 0;
  padding: var(--space-2xs) var(--space-xs) var(--space-2xs) var(--space-md);
  color: var(--color-ink-on-contrast);
  background: transparent;
  border-bottom: var(--border-width) solid var(--color-border-on-contrast);
}

/* The language label is an .eyebrow (site.css sets its type). The box is
   black, so the label follows the light bar text instead of ink. */
.code-block__lang { white-space: nowrap; }
.code-block__bar .eyebrow { color: inherit; }

.code-block__scroll {
  max-height: 34rem;
  min-width: 0;
  overflow: auto;
}

/* The pre gives up its own box: the figure owns border and ground, the scroll
   area owns overflow. */
.code-block__pre,
.prose .code-block__pre {
  margin: 0;
  padding: var(--space-sm) var(--space-md);
  border: 0;
  border-radius: 0;
  background: none;
  overflow: visible;
  width: max-content;
  min-width: 100%;
  box-sizing: border-box;
  color: var(--color-ink-on-contrast);
  font-family: var(--font-mono);
  font-size: var(--text-md-size);
  line-height: var(--text-md-leading);
}

.code-block__copy {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0;
  padding: var(--space-2xs) var(--space-xs);
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--color-ink-on-contrast);
  background: transparent;
  font-family: var(--font-text);
  font-size: var(--text-xs-size);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  text-transform: none;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--curve-standard);
}
.code-block__copy:hover {
  color: var(--color-ink-on-contrast);
  background: color-mix(in oklch, var(--color-ink-on-contrast) 14%, transparent);
}
.code-block__copy:focus-visible { outline: 2px solid var(--color-ink-on-contrast); outline-offset: 2px; }
/* Inline code chips inside the box drop the light-ground chip. */
.code-block code { color: inherit; background: none; padding: 0; }
.code-block__copy-label { white-space: nowrap; }
.code-block__copy-icon { display: none; width: 0.875rem; height: 0.875rem; }
.code-block__copy-icon svg { display: block; width: 100%; height: 100%; }
.code-block__copy-icon--idle { display: block; }
.code-block__copy.is-copied .code-block__copy-icon--idle { display: none; }
.code-block__copy.is-copied .code-block__copy-icon--done { display: block; }

/* Syntax colour. Plain text stays ink. */
.code-block .tok-kw { color: var(--code-kw); }
.code-block .tok-fn { color: var(--code-fn); }
.code-block .tok-var { color: var(--code-var); }
.code-block .tok-str { color: var(--code-str); }
.code-block .tok-attr { color: var(--code-attr); }
.code-block .tok-num { color: var(--code-num); }
.code-block .tok-tag { color: var(--code-tag); font-weight: var(--weight-medium); }
.code-block .tok-sel { color: var(--code-tag); }
.code-block .tok-com { color: var(--code-com); font-style: italic; }
.code-block .tok-pun { color: var(--code-pun); }
.code-block .tok-bad { color: var(--code-bad); }

@media (prefers-reduced-motion: reduce) {
  .code-block__copy { transition: none; }
}
@media print {
  .code-block__scroll { max-height: none; overflow: visible; }
  .code-block__pre { width: auto; white-space: pre-wrap; }
  .code-block__copy { display: none; }
}

/* delta-component:delta-badge */
/* ---------- Built by Delta badge ----------
   A pill link: Delta mark, title and one line of copy, with a comet of the
   text colour that circles the border. CSS only, no script.
   Colours come from the host's Delta tokens when they exist, with Delta's own
   values as the fallback, so the badge works on any site. The comet is a
   conic gradient masked to a 1.5px ring; the angle is an @property so it can
   animate. Reduced motion: the comet stops. */
@property --delta-badge-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
.delta-badge {
  --delta-badge-accent: var(--color-action, #A3E635);
  --delta-badge-ink: var(--color-ink, #F6F4F1);
  --delta-badge-bg: var(--color-surface-body, #0E0C0A);
  --delta-badge-line: color-mix(in srgb, var(--delta-badge-ink) 16%, transparent);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm, 0.75rem);
  min-height: var(--control-height, 2.75rem);
  padding: var(--space-xs, 0.5rem) var(--space-md, 1rem);
  /* Same corner as the buttons and fields: the seed's control radius. */
  border-radius: var(--button-radius, 0.375rem);
  background: var(--delta-badge-bg);
  box-shadow: inset 0 0 0 1px var(--delta-badge-line);
  color: var(--delta-badge-ink);
  font-family: var(--font-text, system-ui, sans-serif);
  line-height: 1.3;
  text-decoration: none;
  transition: box-shadow 150ms ease;
}
.delta-badge::before {
  content: "";
  position: absolute;
  inset: 0;
  padding: 1.5px;
  border-radius: inherit;
  background: conic-gradient(from var(--delta-badge-angle),
    transparent 0turn 0.8turn,
    color-mix(in srgb, var(--delta-badge-ink) 35%, transparent) 0.92turn,
    var(--delta-badge-ink) 0.995turn,
    transparent 1turn);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  animation: delta-badge-orbit 6s linear infinite;
  pointer-events: none;
}
@keyframes delta-badge-orbit { to { --delta-badge-angle: 1turn; } }
.delta-badge:hover { --delta-badge-line: color-mix(in srgb, var(--delta-badge-ink) 45%, transparent); }
.delta-badge:focus-visible { outline: 2px solid var(--delta-badge-accent); outline-offset: 3px; }
/* The mark is plain: the logo in the ink colour, no circle, no box. */
.delta-badge__mark { flex: none; display: block; color: var(--delta-badge-ink); }
.delta-badge__mark svg { display: block; width: 1.125rem; height: 1.125rem; }
.delta-badge__copy { display: grid; }
.delta-badge__title { font-size: 0.875rem; font-weight: 600; letter-spacing: -0.01em; color: var(--delta-badge-ink); }
@media (prefers-reduced-motion: reduce) {
  .delta-badge::before { animation: none; }
  .delta-badge { transition: none; }
}

/* delta-component:doc-callout */
/* Doc callout: a short aside inside documentation prose. Put the two classes
   on the paragraph itself:
   <p class="doc-callout doc-callout--success">…</p>

   Four tones — info, success, warning, danger. The tone sets the fill, the rule
   and the text; the shape never changes, so a callout reads as the same object
   whatever it is saying. Keep one to a sentence or two: anything longer belongs
   in the copy it is interrupting.

   The tone colour drives the text as well as the rule. That is the contract the
   *-bg tokens already carry — danger-bg holds danger text, and the same for
   success and warning — so the pair cannot come apart.

   Doubled class for 0,2,0: `.prose p` is 0,1,1 and sets both margin and colour,
   so a single class would lose to it and the callout would render as ordinary
   muted body copy. Same reason as .pagehero.pagehero in the docs hub template. */
/* Redesign 3 Oct 2026: the tone sets the fill only; text stays ink (cyan,
   yellow and orange text fail contrast on the light ground). Status colours
   are fills and marks, never text. Filled, so no border. */
.doc-callout.doc-callout {
  margin: 0 0 var(--space-md);
  padding: var(--space-sm) var(--space-md);
  border: 0;
  border-radius: var(--radius-md);
  font-size: var(--text-md-size);
  line-height: var(--text-md-leading);
  color: var(--color-ink);
}


.doc-callout.doc-callout--info {
  background: var(--color-surface-subtle);
}


.doc-callout.doc-callout--success {
  background: var(--color-success-bg);
}


.doc-callout.doc-callout--warning {
  background: var(--color-warning-bg);
}


.doc-callout.doc-callout--danger {
  background: var(--color-danger-bg);
}


/* Links inherit the tone rather than turning action-teal inside a coloured
   band, which would be a second accent fighting the first. */
.doc-callout a:not([class]) {
  color: inherit;
  text-decoration: underline;
}


.doc-callout code {
  font-family: var(--font-mono);
  overflow-wrap: anywhere;
}

/* delta-component:doc-card */
/* ---------- doc card ----------
   The card is the link, so the whole box is the target. Used by the Doc Card
   loop item (template doc-card) and by any page that loops it, which is why
   these rules live here and not on the template.
   Redesign 3 Oct 2026: flat, filled and borderless (filled cards carry no
   border); no colour change and no lift on hover (John, 4 Oct 2026).
   Category label in ink mono, card title 24px. .recipe-card (Recipe Card loop item)
   shares the shell so the two card families cannot drift. */
.doc-card, .recipe-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  padding: var(--space-lg);
  background: var(--color-surface-subtle);
  border-radius: var(--radius-lg);
  text-decoration: none;
  color: var(--color-ink);
}

/* The category label's type is the shared .eyebrow class (site.css). */

.doc-card__title, .recipe-card__title {
  font-size: var(--title-card-size);
  line-height: var(--title-sm-leading);
  letter-spacing: var(--title-sm-tracking);
  color: var(--color-ink);
  margin: 0;
}

.doc-card__excerpt, .recipe-card__desc {
  font-size: var(--text-md-size);
  line-height: var(--text-md-leading);
  color: var(--color-ink-muted);
  margin: 0;
}

/* delta-component:grid-bg */
/* Same rule as site.css. Parent band needs position:relative and overflow:hidden; site.css applies both through .section:has(> .grid-bg) / .pagehero:has(> .grid-bg). */
.grid-bg {
  position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;
  background-image: linear-gradient(to right, color-mix(in oklch, var(--color-ink) 2.5%, transparent) 1px, transparent 1px), linear-gradient(to bottom, color-mix(in oklch, var(--color-ink) 2.5%, transparent) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(85% 60% at 50% 50%, black 65%, transparent 100%);
  mask-image: radial-gradient(85% 60% at 50% 50%, black 65%, transparent 100%);
}

/* delta-component:person-card */
/* ---------- person card (founder profile) ----------
   A tall stepped photo beside name, role and a short bio or a website link.
   One look for the front page (10 · Who builds Delta) and About (John, 4 Oct 2026).
   Replaces the filled card with the square portrait (.person-card, .person-grid).
   .people is the grid: one column on phones, two from 48rem. */
.people {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2xl);
  width: 100%;
}
@media (min-width: 48rem) {
  .people { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* With scroll reveal, the second profile arrives a beat after the first (120ms). */
.people > [data-reveal] + [data-reveal] { transition-delay: calc(var(--reveal-duration) * 0.15); }
.person {
  --person-photo: calc(var(--space-4xl) * 1.25); /* the 120px photo column */
  display: grid;
  grid-template-columns: var(--person-photo) minmax(0, 1fr);
  gap: var(--space-xl);
  align-items: start;
}
/* Photo box: 4:5 on a dark ground. A modifier cuts it to a stepped outline. */
.person__photo {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--color-surface-contrast);
  border-radius: var(--radius-md);
}
/* Two outlines, so two profiles side by side do not repeat. Alternate them. */
.person__photo--a { clip-path: polygon(0 12%, 18% 12%, 18% 0, 82% 0, 82% 8%, 100% 8%, 100% 70%, 92% 70%, 92% 100%, 30% 100%, 30% 92%, 0 92%); }
.person__photo--b { clip-path: polygon(0 0, 70% 0, 70% 10%, 100% 10%, 100% 58%, 90% 58%, 90% 100%, 12% 100%, 12% 86%, 0 86%); }
.person__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.05);
}
/* Scanlines over the photo (decoration): a 1px dark line every 3px. */
.person__scan {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(0deg, color-mix(in oklch, var(--color-surface-contrast) 16%, transparent) 0 calc(var(--border-width) * 2 / 3), transparent calc(var(--border-width) * 2 / 3) calc(var(--border-width) * 2));
  pointer-events: none;
}
.person__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  min-width: 0;
}
.person__name {
  margin: 0;
  font-family: var(--font-title);
  font-size: var(--title-md-size);
  line-height: var(--title-md-leading);
  letter-spacing: var(--title-md-tracking);
  font-weight: var(--title-weight, var(--weight-semibold));
  color: var(--color-ink);
}
/* Role type is the shared .eyebrow class (site.css); layout only here. */
.person__role { margin: 0; }
.person__bio,
.person__link {
  margin: 0;
  padding-top: var(--space-xs);
  font-size: var(--text-lg-size);
  line-height: var(--text-lg-leading);
  letter-spacing: var(--text-lg-tracking);
}
.person__bio { color: var(--color-ink-muted); text-wrap: pretty; }

/* delta-component:prompt */
/* ---------- prompt ----------
   Copyable prompt block. Clipboard lives in site.js (delegation on .prompt__copy).
   .prompt-list / .intg-prompts wrap a stack; field HTML may still be a ul. */
.prompt-list,
.intg-prompts > ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  list-style: none;
  margin: 0;
  padding: 0;
}


.prompt,
.intg-prompts li,
.prompt-list li {
  /* The rule is the one site border (John, 4 Oct 2026). */
  position: relative;
  margin: 0;
  border-inline-start: var(--border-width) solid var(--color-border);
  padding: var(--space-xs) var(--space-md);
  color: var(--color-ink);
  font-family: var(--font-mono);
  font-size: var(--text-md-size);
  line-height: var(--text-md-leading);
  letter-spacing: var(--text-md-tracking);
}


.prompt__text {
  margin: 0;
  font: inherit;
  color: inherit;
}


.prompt__copy {
  position: absolute;
  /* Dark badge (John, 9 Oct 2026): a filled pill, so it reads on any ground (page or card). */
  inset-block-start: var(--space-2xs);
  inset-inline-end: var(--space-2xs);
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: 0;
  padding: var(--space-2xs) var(--space-sm);
  border: 0;
  border-radius: var(--radius-full);
  background: var(--color-surface-contrast);
  color: var(--color-ink-on-contrast);
  font-family: var(--font-text);
  font-size: var(--text-xs-size);
  font-weight: var(--weight-medium);
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--duration-fast) var(--curve-standard), background-color var(--duration-fast) var(--curve-standard);
}


.prompt:hover .prompt__copy,
.prompt:focus-within .prompt__copy,
.intg-prompts li:hover .prompt__copy,
.intg-prompts li:focus-within .prompt__copy,
.prompt-list li:hover .prompt__copy,
.prompt-list li:focus-within .prompt__copy {
  opacity: 1;
}


/* Hover: blue fill, as on the primary button. */
.prompt__copy:hover,
.prompt__copy:focus-visible {
  background: var(--color-action-hover);
  color: var(--color-ink-on-contrast);
}


.prompt__copy:focus-visible {
  opacity: 1;
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}


.prompt__copy-label { white-space: nowrap; }


.prompt__copy-icon {
  display: none;
  width: 0.875rem;
  height: 0.875rem;
}


.prompt__copy-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}


.prompt__copy-icon--idle { display: block; }

.prompt__copy.is-copied .prompt__copy-icon--idle { display: none; }

.prompt__copy.is-copied .prompt__copy-icon--done { display: block; }


@media (hover: none) {
.prompt__copy { opacity: 1; }
}


@media (prefers-reduced-motion: reduce) {
.prompt__copy { transition: none; }
}

/* delta-component:prose */
/* Redesign 3 Oct 2026: running text 18px, h2 40px, h3 28px (measured scale,
   pages-log Revision 2). Links take the site link rule (ink, underline). */
.prose {
  max-width: var(--layout-content);
  font-size: var(--text-lg-size);
  line-height: var(--text-lg-leading);
  letter-spacing: var(--text-lg-tracking);
  color: var(--color-ink);
}


.prose h2,
.prose h3 {
  font-family: var(--font-title);
  font-weight: var(--title-weight, var(--weight-medium));
  margin: var(--space-xl) 0 var(--space-sm);
}


.prose h2 {
  font-size: var(--title-prose-size);
  line-height: var(--title-md-leading);
  letter-spacing: var(--title-md-tracking);
}


.prose h3 {
  font-size: var(--title-prose-sm-size);
  line-height: var(--title-sm-leading);
  letter-spacing: var(--title-sm-tracking);
}

.prose > :first-child {
  margin-top: 0;
}

.prose strong {
  color: var(--color-ink);
  font-weight: var(--weight-semibold);
}


.prose p {
  margin: 0 0 var(--space-md);
  color: var(--color-ink-muted);
}


.prose figure {
  margin: var(--space-lg) 0;
}

.prose figure img {
  display: block;
  width: 100%;
  height: auto;
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
}

.prose ul,
.prose ol {
  margin: 0 0 var(--space-md);
  padding-left: var(--space-lg);
  color: var(--color-ink-muted);
}

/* Inline code in running text: 0.9 of the text size with a slim side pad
   (designs, 4 Oct 2026). Code inside pre keeps the block style. */
.prose :not(pre) > code {
  font-size: 0.9em;
  padding: 0 var(--space-2xs);
}

.prose ul {
  list-style: disc;
}

.prose ol {
  list-style: decimal;
}

.prose li {
  margin-bottom: var(--space-2xs);
}

.prose li::marker {
  color: var(--color-ink); /* list markers are text colour, never the action colour (John, 11 Oct 2026) */
}



/* Code blocks in docs prose. Scroll inside the block, never the page.
   Black box (John, 3 Oct 2026), same as the code-block component; the
   component script upgrades most of these into .code-block anyway. */
.prose pre {
  margin: 0 0 var(--space-md);
  padding: var(--space-sm) var(--space-md);
  background: var(--color-surface-contrast);
  border: var(--border-width) solid var(--color-border-on-contrast);
  border-radius: var(--radius-md);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--text-md-size);
  line-height: var(--text-md-leading);
  color: var(--color-ink-on-contrast);
}

.prose pre code {
  color: inherit;
}



/* .prose p is 0,1,1 and paints body copy muted, which would flatten a quote
   back into the paragraph it was promoted out of. The element defaults for
   blockquote live in site.css; only the ink has to be reclaimed here, because
   this file loads after it. */
.prose blockquote p {
  color: var(--color-ink);
  font-size: inherit;
  line-height: inherit;
}

/* delta-component:stack */
.stack {
  display: flex;
  flex-direction: column;
}

.stack > * + * {
  margin-top: var(--space-md);
}

.stack--sm > * + * {
  margin-top: var(--space-sm);
}

.stack--lg > * + * {
  margin-top: var(--space-lg);
}

.stack--xl > * + * {
  margin-top: var(--space-xl);
}
