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

/* delta-component:badge */
/* The wrapper is part of this component: badges are a set, and the gap between
   them is what makes them read as one row rather than loose boxes. It carries
   no margin of its own — the block around it owns that spacing. */
.badges {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  margin: 0;
  padding: 0;
}

/* inline-flex, not inline-block: the box must hold its height when the label
   wraps, and a bare inline box does not. */
.badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2xs) var(--space-xs);
  border: var(--rule);
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  line-height: var(--text-xs-leading);
  color: var(--color-ink-muted);
}

/* For the one badge in a set that is the point of the set. Use it sparingly —
   colour every badge and none of them reads as marked. */
.badge--action {
  border-color: var(--color-action);
  color: var(--color-action);
}

/* delta-component:blockquote */
.quote {
  margin: 0;
  padding-inline-start: var(--space-lg);
  border-inline-start: var(--space-3xs) solid var(--color-action);
  max-width: var(--layout-content);
}

.quote__body {
  margin: 0;
}

/* The lead step, not the body step: the size is what marks this as a break in
   the page. Size and leading travel together — do not recombine across steps. */
.quote__body p {
  margin: 0 0 var(--space-md);
  font-family: var(--font-title);
  font-size: var(--text-lg-size);
  line-height: var(--text-lg-leading);
  letter-spacing: var(--text-lg-tracking);
  color: var(--color-ink);
  text-wrap: pretty;
}

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

.quote__by {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2xs) var(--space-xs);
  margin-top: var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--text-xs-size);
  line-height: var(--text-xs-leading);
}

.quote__who {
  color: var(--color-ink);
}

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

/* Centred display variant for a section that is only the quote. The edge rule
   moves to the block start, because a centred column with a left rule reads
   as misaligned against everything around it. */
.quote--display {
  max-width: var(--layout-wide);
  margin-inline: auto;
  padding-inline-start: 0;
  padding-block-start: var(--space-lg);
  border-inline-start: 0;
  border-block-start: var(--space-3xs) solid var(--color-action);
  text-align: center;
}

/* The size step comes from the title scale but the leading does not: a heading
   leading is set for one or two lines, and a quotation runs to four or five.
   Loosened off the title value so the two still move together. */
.quote--display .quote__body p {
  font-size: var(--title-sm-size);
  line-height: calc(var(--title-sm-leading) + 0.2);
  letter-spacing: var(--title-sm-tracking);
}

.quote--display .quote__by {
  justify-content: center;
}

/* Testimonial variant: a quotation used as evidence rather than as a pull from
   the surrounding copy. It carries its own ground, so it does not need a
   section around it, and the edge rule moves to the block start. */
.quote--testimonial {
  max-width: none;
  padding: var(--space-2xl) var(--pad);
  padding-inline-start: var(--pad);
  border-inline-start: 0;
  border-block-start: var(--space-3xs) solid var(--color-action);
  background: var(--color-surface-subtle);
}

/* Same reasoning as the display variant: title size, but a reading leading. */
.quote--testimonial .quote__body p {
  max-width: var(--line-length-sm);
  font-size: var(--title-sm-size);
  line-height: calc(var(--title-sm-leading) + 0.2);
  letter-spacing: var(--title-sm-tracking);
}

.quote--testimonial .quote__by {
  margin-top: var(--space-lg);
}

/* delta-component:button */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  /* Block padding is the in-page size. The header bar is tighter and overrides
     it from the header template, so changing this does not move the bar. */
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--radius-none);
  font-family: var(--font-text);
  font-size: var(--text-sm-size);
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  text-decoration: none;
  border: var(--border-width) solid transparent;
  cursor: pointer;
  transition: transform 0.2s ease, background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

/* The icon pack ships a 24px glyph, which is taller than the label's line box
   and made a button with an icon 6px taller than one without — visible the
   moment two are stacked. Sized to the label instead. */
.btn svg {
  inline-size: var(--space-md);
  block-size: var(--space-md);
}

.btn:hover {
  transform: translateY(-1px);
}

/* The lift is decoration. Fill, ink and edge all still change on hover, so
   nothing that carries meaning is lost when the movement is dropped. */
@media (prefers-reduced-motion: reduce) {
  .btn {
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
  }

  .btn:hover {
    transform: none;
  }
}

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

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

/* The resting edge is --color-ink-muted, not --color-border. --color-border is
   the layout hairline, about 1.19:1 on the page ground: correct for a rule
   between blocks, and a failure on a control, where WCAG 1.4.11 asks 3:1 of
   the boundary that identifies it. The secondary button carries no fill, so
   this border is the only thing that makes it read as a button at all. Hover
   steps on to full ink, because the muted step is now the resting value.

   Both values are rebound inside .inverted, so the pair follows the dark band
   without a rule of its own. */
.btn--ghost {
  background: var(--color-surface-subtle);
  color: var(--color-ink);
  border-color: var(--color-ink-muted);
}

.btn--ghost:hover {
  border-color: var(--color-ink);
}

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

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

/* delta-component:card */
.card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: var(--space-xl);
  background: var(--color-surface-body);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-none);
}

.card__eyebrow {
  margin: 0 0 var(--space-xs);
  font-family: var(--font-mono);
  font-size: var(--text-xs-size);
  line-height: var(--text-xs-leading);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}

.card__title {
  margin: 0 0 var(--space-xs);
  font-family: var(--font-title);
  font-size: var(--title-xs-size);
  line-height: var(--title-xs-leading);
  letter-spacing: var(--title-xs-tracking);
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
}

.card__body {
  margin: 0;
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-leading);
  color: var(--color-ink-muted);
  max-width: var(--line-length-md);
}

/* margin-top:auto pins the link to the bottom, so cards of unequal body length
   still align their links across a row. */
.card__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-top: auto;
  padding-top: var(--space-lg);
  padding-bottom: var(--space-3xs);
  font-family: var(--font-mono);
  font-size: var(--text-xs-size);
  color: var(--color-ink);
  text-decoration: none;
  border-bottom: var(--border-width) solid var(--color-action);
}

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

/* Sits one step off the page ground. Not for use inside an inverted band —
   there the subtle surface is already rebound and the card would disappear. */
.card--subtle {
  background: var(--color-surface-subtle);
}

/* Flush variant for a ruled grid: the grid owns the hairlines, so the card
   drops its own border and radius rather than doubling them. */
.card--flush {
  border: 0;
  border-radius: var(--radius-none);
  background: transparent;
}

/* delta-component:checklist */
.checks {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: var(--rule);
}

/* center, not flex-start: items are one line of text, and the icon box is
   taller than that line, so flex-start left the text riding high in the row. */
.checks__item {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding-block: var(--space-md);
  border-bottom: var(--rule);
}

/* The icon sits in a square box on a soft action wash, the same treatment the
   feature cell uses, one step smaller because this repeats on every line. The
   fill and the hairline are both mixed from --color-action, so a token change
   recolours the box and the glyph together — never a colour literal here.
   flex:none stops the square collapsing when the line beside it wraps;
   colouring the svg directly would leave nothing to hold it. */
.checks__ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  inline-size: var(--space-xl);
  block-size: var(--space-xl);
  color: var(--color-action);
  background: color-mix(in oklch, var(--color-action) 12%, transparent);
  border: var(--border-width) solid color-mix(in oklch, var(--color-action) 28%, transparent);
}

/* The glyph keeps its own size inside the box. Without this the icon pack's
   24px svg fills the square edge to edge and the wash disappears behind it. */
.checks__ico svg {
  inline-size: var(--space-md);
  block-size: var(--space-md);
}

.checks__text {
  margin: 0;
  color: var(--color-ink);
}

/* delta-component:feature-card */
/* The grid owns the hairlines. Cells draw no border of their own, which is why
   this pairs with a wrapper that sets the outer rules. */
.feature {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: var(--space-xl) var(--pad);
}

/* The icon sits in a square box on a soft action wash, the same geometry as the
   mark in the site header: hard corners, no radius. The fill and the hairline
   are both mixed from --color-action, so a token change recolours the box and
   the glyph together — never write a colour literal here. flex:none keeps the
   square from collapsing in the cell's column flex. */
.feature__ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  inline-size: var(--space-2xl);
  block-size: var(--space-2xl);
  margin: 0 0 var(--space-lg);
  color: var(--color-action);
  background: color-mix(in oklch, var(--color-action) 12%, transparent);
  border: var(--border-width) solid color-mix(in oklch, var(--color-action) 28%, transparent);
}

/* The glyph keeps its own size inside the box. Without this the icon pack's
   24px svg fills the square edge to edge and the wash disappears behind it. */
.feature__ico svg {
  inline-size: var(--space-lg);
  block-size: var(--space-lg);
}

.feature__title {
  margin: 0 0 var(--space-2xs);
  font-family: var(--font-title);
  font-size: var(--title-xs-size);
  line-height: var(--title-xs-leading);
  letter-spacing: var(--title-xs-tracking);
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
}

.feature__meta {
  margin: 0 0 var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink-muted);
}

.feature__body {
  margin: 0;
  max-width: var(--line-length-sm);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-leading);
  color: var(--color-ink-muted);
}

/* margin-top:auto pins the link to the bottom so links align across a row of
   cells with bodies of different lengths. Needs the column flex context above. */
.feature__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-top: auto;
  padding-top: var(--space-lg);
  padding-bottom: var(--space-3xs);
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink);
  text-decoration: none;
  border-bottom: var(--border-width) solid var(--color-action);
}

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

/* delta-component:field */
/* The field owns its own vertical rhythm with gap, not margins on the children.
   --gap-tight, because a label and the control it names are one thing. */
.field {
  display: grid;
  gap: var(--gap-tight);
}

.field__lbl {
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--color-ink);
}

.field__req {
  color: var(--color-action);
}

/* The control edge is --color-field-border, not --rule. The layout hairline is
   1.19:1 against the panel: right for a rule between blocks, and a failure for
   something a person types into, where WCAG 1.4.11 asks 3:1. */
.field__in {
  inline-size: 100%;
  padding: var(--space-sm);
  border: var(--border-width) solid var(--color-field-border);
  border-radius: var(--radius-none);
  background: var(--color-surface-body);
  font-family: var(--font-mono);
  font-size: var(--text-sm-size);
  color: var(--color-ink);
}

/* The native select arrow sits hard against the right border and ignores
   padding — padding moves the text, not the glyph. The only way to inset it is
   to remove it and draw our own.

   The chevron is two 45-degree gradients rather than an SVG data URI, so it is
   painted in currentColor and inherits the control's ink. No colour literal,
   and it follows the token if the ink changes.

   background-image is a longhand and this rule comes after the shorthand above,
   so the surface colour set there survives. */
select.field__in {
  appearance: none;
  padding-inline-end: var(--space-2xl);
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-size: var(--space-xs) var(--space-xs);
  background-position:
    right var(--space-lg) top 50%,
    right var(--space-md) top 50%;
  background-repeat: no-repeat;
}

.field__in--area {
  resize: vertical;
  min-block-size: var(--space-4xl);
  line-height: var(--text-sm-leading);
}

.field__hint {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink-muted);
}

.field--invalid .field__in {
  border-color: var(--color-danger);
}

.field__err {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-danger);
}

/* A checkbox reads left to right, so it is a row rather than the stacked grid,
   and its label drops the uppercase treatment because it is a sentence. */
.field__check {
  display: flex;
  align-items: center;
  gap: var(--gap-inline);
}

.field__box {
  inline-size: var(--space-md);
  block-size: var(--space-md);
  accent-color: var(--color-action);
}

.field__lbl--inline {
  text-transform: none;
  letter-spacing: var(--tracking-none);
}

/* delta-component:intake-form */
/* The root exists so the script has one thing to bind to and the caption stays
   attached to the form. It sets no layout: the block that places it decides
   the padding and the column it sits in. */
.intake {
  display: block;
}

/* The terminal caption (.prompt) is a shared idiom in site.css — the method
   grid uses the same one. Do not restyle it from here. */

.form {
  display: grid;
  gap: var(--space-lg);
}

/* The field primitives (.field, .field__lbl, .field__in and the rest) live on
   the `field` component. Component CSS applies by class across the whole site,
   so the search bar on the 404 and results templates takes the same controls
   without being a marked instance. This component owns the layout, the
   validation states it triggers, and the script; not the controls. */

.form__send {
  justify-self: start;
}

.form__fine {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink-muted);
}

.form__msg {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm-size);
  color: var(--color-success);
}

.form__msg:empty {
  display: none;
}

/* Two columns from md up. The wide field, the footer and both messages span
   the full width, so the count here and the span list must change together. */
@media (min-width: 64rem) {
  .form {
    grid-template-columns: repeat(2, 1fr);
    align-content: start;
  }

  .field--wide,
  .form__foot,
  .form__msg,
  .form__fine {
    grid-column: 1 / -1;
  }
}

/* delta-component:person */
.person {
  padding: var(--space-xl) var(--pad);
}

/* Fixed square ratio with overflow hidden. Portraits vary in intrinsic size and
   an auto ratio would let the row go ragged. */
.person__fig {
  margin: 0 0 var(--space-lg);
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--color-surface-subtle);
}

.person__fig img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

/* The role is an eyebrow — a short label naming what follows — so it carries
   the shared .eyebrow utility and takes its type and colour from there. This
   rule only sets the space below it. --gap-tight read as cramped at this size:
   the mono uppercase label and the title-face name are different enough that
   they need a real step between them, not a hairline. */
/* Scoped to .person for 0,2,0. The role carries the eyebrow class, and
   `.eyebrow { margin: 0 }` in site.css loads after this file — a bare
   `.person__role` tied at 0,1,0 and lost, leaving no gap at all. */
.person .person__role {
  margin: 0 0 var(--gap-stack);
}

.person__name {
  margin: 0 0 var(--space-xs);
  font-family: var(--font-title);
  font-size: var(--title-xs-size);
  line-height: var(--title-xs-leading);
  letter-spacing: var(--title-xs-tracking);
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
}

.person__line {
  margin: 0;
  max-width: var(--line-length-xs);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-leading);
  color: var(--color-ink-muted);
}

/* The specialities are the badge component. This rule only says where the set
   sits: .badges carries no margin of its own, so the block around it decides. */
.person .badges {
  margin-top: var(--space-lg);
}

.person__mail {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-top: var(--space-lg);
  padding-bottom: var(--space-3xs);
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink);
  text-decoration: none;
  border-bottom: var(--border-width) solid var(--color-action);
}

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

/* Profile variant: portrait beside the copy rather than above it, and the role
   takes the action colour because it is the scan target in a two-column row. */
.person--profile {
  display: grid;
  padding: 0;
}

.person--profile .person__fig {
  margin: 0;
}

.person--profile .person__body {
  padding: var(--space-xl) var(--pad);
}

.person--profile .person__name {
  font-size: var(--title-sm-size);
  line-height: var(--title-sm-leading);
  letter-spacing: var(--title-sm-tracking);
}

.person--profile .person__line {
  max-width: var(--line-length-sm);
}

/* Two columns from sm up. The portrait column stretches (the grid default), so
   the figure drops its square ratio and takes the height the copy beside it
   sets; the img covers whatever that comes to. Keep the 1:1 ratio below sm,
   where there is no neighbouring column to set a height. */
@media (min-width: 40rem) {
  .person--profile {
    grid-template-columns: 1fr 1fr;
  }

  .person--profile .person__fig {
    aspect-ratio: auto;
  }
}

/* delta-component:post-card */
.pcard {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

/* Fixed ratio with cover: featured images arrive at different intrinsic sizes
   and an auto ratio makes the row ragged. */
.pcard__media {
  display: block;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--color-surface-subtle);
  border-bottom: var(--rule);
}

.pcard__media img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center;
}

.pcard__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  flex: 1;
  padding: var(--space-xl) var(--pad);
}

.pcard__meta {
  margin: 0 0 var(--space-sm);
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink-muted);
}

.pcard__dot {
  color: var(--color-action);
}

.pcard__title {
  margin: 0 0 var(--space-sm);
  font-family: var(--font-title);
  font-size: var(--title-xs-size);
  line-height: var(--title-xs-leading);
  letter-spacing: var(--title-xs-tracking);
  font-weight: var(--weight-semibold);
}

/* The title link inherits rather than taking the action colour: the whole card
   is the target, and a coloured heading in a grid of cards reads as noise. */
.pcard__title a {
  color: var(--color-ink);
  text-decoration: none;
}

.pcard__title a:hover {
  color: var(--color-action);
}

.pcard__excerpt {
  margin: 0;
  max-width: var(--line-length-md);
  font-size: var(--text-sm-size);
  line-height: var(--text-sm-leading);
  color: var(--color-ink-muted);
}

.pcard__more {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-top: auto;
  padding-top: var(--space-lg);
  padding-bottom: var(--space-3xs);
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink);
  text-decoration: none;
  border-bottom: var(--border-width) solid var(--color-action);
}

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

/* delta-component:section-head */
/* Uniform rhythm, so the parent owns it: eyebrow, title and lead all sit one
   --gap-stack apart and none of them carries a margin. */
.sechead {
  display: flex;
  flex-direction: column;
  gap: var(--gap-stack);
  padding: var(--space-3xl) var(--pad) var(--space-xl);
}

/* No rule for the eyebrow: the .eyebrow utility in site.css carries the type,
   the colour and the space below it. Eyebrows on this site take no icon, so
   there is no icon row to lay out here either. */

/* Section titles take the lg step. A page title takes xl — see below. Before
   this split every head rendered at xl, so a page's h1 and every h2 under it
   were the same size and the page read as a flat list of equal shouts. */
.sechead__title {
  margin: 0;
  font-family: var(--font-title);
  font-size: var(--title-lg-size);
  line-height: var(--title-lg-leading);
  letter-spacing: var(--title-lg-tracking);
  font-weight: var(--weight-bold);
  max-width: var(--line-length-title);
  text-wrap: balance;
}

/* Keyed on the h1, not a modifier class, for the same reason the lead below is:
   it follows the heading level and cannot fall out of sync with it. One h1 per
   page means one xl title per page, without anyone having to remember a class. */
.sechead:has(h1) .sechead__title {
  font-size: var(--title-xl-size);
  line-height: var(--title-xl-leading);
  letter-spacing: var(--title-xl-tracking);
  max-width: var(--line-length-title-page);
}

.sechead__lead {
  margin: 0;
  max-width: var(--layout-content);
  color: var(--color-ink-muted);
}

/* The lead under a page title takes the lead step; under a section title it
   stays at body size. Keyed on the h1 rather than a modifier class, so it
   follows the heading level and cannot fall out of sync with it. */
.sechead:has(h1) .sechead__lead {
  font-size: var(--text-lg-size);
  line-height: var(--text-lg-leading);
  letter-spacing: var(--text-lg-tracking);
}

/* delta-component:stat-bar */
/* The bar draws its bottom edge, not its top one. Every block on this site
   closes itself with a bottom rule, and the block above the bar already draws
   one — a top rule here stacked a second hairline against it and left the bar
   with no edge at all underneath. */
.stats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  border-bottom: var(--rule);
  /* Two per row from the smallest screen up. A figure and a short mono label
     fit half a phone width comfortably, and one per row turned four facts into
     a column of four screens' worth of scrolling. */
  grid-template-columns: repeat(2, 1fr);
}

.stats__cell {
  padding: var(--space-xl) var(--pad);
  border-bottom: var(--rule);
  border-right: var(--rule);
}

.stats__cell:nth-child(2n) {
  border-right: 0;
}

/* The bottom row is closed by the bar's own bottom rule. */
.stats > .stats__cell:nth-last-child(-n+2) {
  border-bottom: 0;
}

.stats__figure {
  display: block;
  font-family: var(--font-title);
  font-size: var(--title-lg-size);
  line-height: var(--title-lg-leading);
  letter-spacing: var(--title-lg-tracking);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
}

.stats__label {
  display: block;
  margin-top: var(--space-xs);
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink-muted);
}

/* Four across from md. The nth-child maths is tied to the column count, so the
   2n rule from the two-column layout has to be put back before the 4n rule
   takes over. */
@media (min-width: 64rem) {
  .stats {
    grid-template-columns: repeat(4, 1fr);
  }

  .stats__cell {
    border-bottom: 0;
  }

  .stats__cell:nth-child(2n) {
    border-right: var(--rule);
  }

  .stats__cell:nth-child(4n) {
    border-right: 0;
  }
}

/* delta-component:step-card */
/* The grid owns the hairlines. Cells draw no border of their own, which is why
   this pairs with a .cells wrapper that sets the outer rules. */
.step {
  padding: var(--space-xl) var(--pad);
}

/* The caption is the shared .prompt idiom in site.css. Only its spacing is set
   here: in a form it opens a block and needs the larger gap, in a cell it is a
   heading with a meta line directly under it. */
.step .prompt {
  margin-bottom: var(--space-sm);
}

.step__meta {
  margin: 0 0 var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink-muted);
}

.step__body {
  margin: 0;
  max-width: var(--line-length-md);
  color: var(--color-ink-muted);
}

/* delta-component:tabs */
/* The root is the scope the script uses to group a tab set, and it bounds the
   panel background. Without a rule here two sets on one page share nothing. */
.tabs {
  background: var(--color-surface-body);
}

/* Underline tabs, not folder tabs. A folder tab needs an unbroken row: the
   selected one hides the seam by covering the container's bottom rule, and the
   moment the row wraps that trick breaks and the second line sits over nothing.
   An underline indicator survives both wrapping and scrolling, so it holds at
   every width. */
.tabs__list {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-lg);
  margin: 0;
  padding: 0 var(--pad);
  border-bottom: var(--rule);
  /* One row that scrolls sideways, never a second row. */
  overflow-x: auto;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
  overscroll-behavior-x: contain;
}

.tabs__list::-webkit-scrollbar {
  display: none;
}

.tabs__tab {
  appearance: none;
  position: relative;
  flex: none;
  scroll-snap-align: start;
  padding: var(--space-md) 0;
  border: 0;
  border-bottom: var(--space-3xs) solid transparent;
  border-radius: var(--radius-none);
  background: none;
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  color: var(--color-ink-muted);
  white-space: nowrap;
  cursor: pointer;
}

.tabs__tab:hover {
  color: var(--color-ink);
}

/* The indicator is the tab's own bottom border sitting on the container rule,
   so nothing has to overlap anything. */
.tabs__tab[aria-selected="true"] {
  border-bottom-color: var(--color-action);
  color: var(--color-ink);
}

.tabs__panel {
  padding: var(--space-xl) var(--pad) var(--space-2xl);
}

.tabs__panel[hidden] {
  display: none;
}

/* delta-component:ticker */
.ticker {
  overflow: hidden;
  padding-block: var(--space-sm);
  background: var(--color-surface-contrast);
  color: var(--color-ink-on-contrast);
}

.ticker__track {
  display: flex;
  width: max-content;
  animation: ticker-scroll 48s linear infinite;
}

.ticker:hover .ticker__track {
  animation-play-state: paused;
}

/* Each run is one full copy of the list. Two identical runs sit side by side and
   the track shifts by exactly half its width, so the loop has no visible seam.
   Changing the number of runs without changing the -50% breaks that. */
.ticker__run {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  padding-inline: var(--space-lg);
  margin: 0;
  list-style: none;
  font-family: var(--font-mono);
  font-size: var(--mono-sm);
  white-space: nowrap;
}

.ticker__item::after {
  content: "/";
  margin-inline-start: var(--space-lg);
  color: var(--color-action);
}

@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .ticker__track {
    animation: none;
    width: 100%;
    overflow-x: auto;
  }

  .ticker__run + .ticker__run {
    display: none;
  }
}
