/* ==========================================================================
   kelvinbytes — Site styles
   --------------------------------------------------------------------------
   Built entirely on the semantic tokens in tokens.css.

   The organising idea is a printed service manual: a masthead, section rules,
   a numbered index, spec tables, and marginalia. Structure is carried by
   rules and alignment rather than by boxes. There are no gradients, no
   backdrop blur, no drop shadows on content, and nothing moves on hover
   except colour.
   ========================================================================== */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--kb-header-height) + var(--kb-space-6));
}

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

body {
  background: var(--kb-surface-base);
  color: var(--kb-text-primary);
  font-family: var(--kb-font-sans);
  font-size: var(--kb-text-body);
  line-height: var(--kb-leading-normal);
  letter-spacing: var(--kb-tracking-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: none; padding: 0; }
ul, ol { padding: 0; list-style: none; }
table { border-collapse: collapse; width: 100%; }

/* Links are underlined. An underline is how a link has been signalled since
   the first browser; removing it and colouring the word instead is a habit
   worth breaking on a site people read at 2am. */
a {
  color: var(--kb-accent-text);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.16em;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
  transition: color var(--kb-duration-fast) var(--kb-ease),
              text-decoration-color var(--kb-duration-fast) var(--kb-ease);
}
a:hover {
  color: var(--kb-accent-hover);
  text-decoration-color: currentColor;
}

:focus-visible {
  outline: 2px solid var(--kb-accent);
  outline-offset: 2px;
}
:focus:not(:focus-visible) { outline: none; }

::selection {
  background: var(--kb-accent);
  color: var(--kb-text-on-accent);
}

/* --------------------------------------------------------------------------
   Typography primitives
   -------------------------------------------------------------------------- */

/* Editorial voice is set in the serif; interface furniture is set in the
   mono. Nothing on this site is a bold grotesk headline, which is the one
   thing every generated page has in common. */
h1, h2, h3, h4 {
  font-family: var(--kb-font-display);
  font-weight: var(--kb-weight-semibold);
  font-optical-sizing: auto;
  line-height: var(--kb-leading-snug);
  letter-spacing: var(--kb-tracking-tight);
  color: var(--kb-text-primary);
  text-wrap: balance;
}
h5, h6 {
  font-family: var(--kb-font-sans);
  font-weight: var(--kb-weight-semibold);
  color: var(--kb-text-primary);
}

code, kbd, samp, pre { font-family: var(--kb-font-mono); }

/* The label: small mono, wide-tracked, uppercase. Every piece of machine-
   readable furniture on the site — kickers, column heads, meta, index
   numbers — uses it, so the reader learns to tell prose from apparatus. */
.kb-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--kb-space-2);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  color: var(--kb-text-muted);
}
.kb-eyebrow--accent { color: var(--kb-accent-text); }
.kb-eyebrow a { color: inherit; text-decoration: none; }
.kb-eyebrow a:hover { color: var(--kb-accent-text); text-decoration: underline; }

.kb-lead {
  font-size: var(--kb-text-lead);
  line-height: 1.58;
  color: var(--kb-text-secondary);
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */
.kb-shell {
  width: 100%;
  max-width: var(--kb-width-content);
  margin-inline: auto;
  padding-inline: var(--kb-gutter);
}
.kb-shell--wide { max-width: var(--kb-width-wide); }
.kb-shell--narrow { max-width: 780px; }

/* Sections are deliberately not all the same height. An index of links is a
   dense thing; an article opening is a spacious one. Uniform vertical
   rhythm everywhere is what makes a page feel machine-set. */
.kb-section { padding-block: clamp(1.75rem, 1.4rem + 1.6vw, 2.75rem); }
.kb-section--tight { padding-block: clamp(1.25rem, 1rem + 1vw, 1.75rem); }
.kb-section--sunken { background: var(--kb-surface-sunken); }
.kb-divider { border-top: var(--kb-rule) solid var(--kb-border-subtle); }

/* Section furniture: a mono label sitting on a heavy rule, with the "see
   everything" link parked at the far end of it. Newspaper practice. */
.kb-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--kb-space-3) var(--kb-space-5);
  padding-bottom: var(--kb-space-2);
  margin-bottom: var(--kb-space-5);
  border-bottom: 2px solid var(--kb-text-primary);
}
.kb-section-head h1,
.kb-section-head h2 {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-semibold);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  line-height: 1.4;
}
.kb-section-head p {
  color: var(--kb-text-secondary);
  margin-top: var(--kb-space-2);
  max-width: 60ch;
}

/* A page-level heading — the one on an index page — is editorial, so it
   keeps the serif and sits above its own rule rather than on it. */
.kb-page-head {
  padding-bottom: var(--kb-space-5);
  margin-bottom: var(--kb-space-6);
  border-bottom: 2px solid var(--kb-text-primary);
}
.kb-page-head h1 {
  font-size: var(--kb-text-h1);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-display);
  line-height: var(--kb-leading-tight);
  margin-block: var(--kb-space-3) var(--kb-space-4);
  max-width: 20ch;
}
.kb-page-head .kb-lead { max-width: 62ch; }

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

.kb-skip-link {
  position: absolute;
  top: var(--kb-space-2);
  left: var(--kb-space-2);
  z-index: 999;
  padding: var(--kb-space-2) var(--kb-space-4);
  background: var(--kb-text-primary);
  color: var(--kb-surface-base);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform var(--kb-duration) var(--kb-ease);
}
.kb-skip-link:focus { transform: translateY(0); color: var(--kb-surface-base); }

/* --------------------------------------------------------------------------
   Brand lockup — <kelvinbytes>

   The name written as a code tag. Set in JetBrains Mono 500, all lowercase,
   as live text: mono is fixed-pitch, so the brackets frame the word at
   exactly one character either side at every size, with no optical
   correction and no image file. Brackets are Signal Amber; the name takes
   the page's own ink.
   -------------------------------------------------------------------------- */
.kb-logo {
  display: inline-flex;
  align-items: baseline;
  font-family: var(--kb-font-brand);
  font-size: 1.125rem;
  font-weight: var(--kb-weight-medium);
  letter-spacing: -0.012em;
  color: var(--kb-wordmark);
  text-decoration: none;
  white-space: nowrap;
}
.kb-logo:hover { color: var(--kb-wordmark); }

/* Brackets sit tight against the word — the mono cell is the only gap the
   lockup gets. Never add margin here. */
.kb-logo__bracket { color: var(--kb-bracket); }
.kb-logo__word { color: inherit; }

.kb-logo--lg { font-size: 1.5rem; }
.kb-logo--xl { font-size: 2.25rem; }

/* --------------------------------------------------------------------------
   Cursor

   From the intro, where the name is typed and the cursor rests in amber. On
   the page it is decorative punctuation: once per view, never in the header,
   where it would blink on every page.
   -------------------------------------------------------------------------- */
.kb-cursor {
  display: inline-block;
  width: 0.58em;
  height: 1.02em;
  margin-left: 0.08em;
  background: var(--kb-cursor);
  vertical-align: -0.14em;
  animation: kb-blink 1.06s steps(1, end) infinite;
}
@keyframes kb-blink { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }

/* A blinking block is exactly what this setting is for. Hold it solid rather
   than letting the global rule freeze it on an arbitrary frame. */
@media (prefers-reduced-motion: reduce) {
  .kb-cursor { animation: none; opacity: 1; }
}

/* --------------------------------------------------------------------------
   Tagline
   -------------------------------------------------------------------------- */
.kb-tagline {
  font-family: var(--kb-font-brand);
  font-size: var(--kb-text-sm);
  font-weight: var(--kb-weight-regular);
  letter-spacing: 0.04em;
  color: var(--kb-text-muted);
}

/* --------------------------------------------------------------------------
   Header
   Solid, ruled, and opaque. Frosted glass is a decorative effect that costs
   a compositor pass and tells the reader nothing.
   -------------------------------------------------------------------------- */
.kb-header {
  position: sticky;
  top: 0;
  z-index: var(--kb-z-header);
  min-height: var(--kb-header-height);
  display: flex;
  align-items: center;
  background: var(--kb-surface-base);
  border-bottom: var(--kb-rule) solid var(--kb-text-primary);
}

.kb-header__inner {
  display: flex;
  align-items: center;
  gap: var(--kb-space-6);
  width: 100%;
}

.kb-nav {
  display: flex;
  align-items: stretch;
  margin-left: auto;
}
.kb-nav a {
  display: flex;
  align-items: center;
  padding: var(--kb-space-2) var(--kb-space-4);
  border-left: var(--kb-rule) solid var(--kb-border-subtle);
  color: var(--kb-text-secondary);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  text-decoration: none;
  transition: color var(--kb-duration-fast) var(--kb-ease),
              box-shadow var(--kb-duration-fast) var(--kb-ease);
}
.kb-nav a:last-child { border-right: var(--kb-rule) solid var(--kb-border-subtle); }
.kb-nav a:hover {
  color: var(--kb-text-primary);
  box-shadow: inset 0 -2px 0 var(--kb-accent);
}
.kb-nav a[aria-current="page"] {
  color: var(--kb-text-primary);
  box-shadow: inset 0 -2px 0 var(--kb-text-primary);
}

.kb-header__actions {
  display: flex;
  align-items: center;
  gap: var(--kb-space-2);
}

.kb-icon-btn {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  color: var(--kb-text-secondary);
  border: var(--kb-rule) solid var(--kb-border);
  transition: color var(--kb-duration-fast) var(--kb-ease),
              border-color var(--kb-duration-fast) var(--kb-ease);
}
.kb-icon-btn:hover { color: var(--kb-text-primary); border-color: var(--kb-text-primary); }
.kb-icon-btn svg { width: 16px; height: 16px; }

/* Theme toggle icons. Both ship in the markup and CSS picks one from the
   data-theme attribute the no-flash script sets before first paint, so a
   dark-mode reader never sees the wrong icon.

   Also declared in src/styles/base.css, which the Next app loads and these
   static pages do not — the two surfaces have no stylesheet in common
   besides this one and the tokens. */
.kb-theme-icon--sun { display: none; }
.kb-theme-icon--moon { display: block; }
[data-theme="dark"] .kb-theme-icon--sun { display: block; }
[data-theme="dark"] .kb-theme-icon--moon { display: none; }

.kb-nav-toggle { display: none; }

@media (max-width: 900px) {
  .kb-nav {
    position: fixed;
    inset: var(--kb-header-height) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    padding-inline: var(--kb-gutter);
    background: var(--kb-surface-base);
    border-bottom: var(--kb-rule) solid var(--kb-text-primary);
    display: none;
  }
  .kb-nav[data-open="true"] { display: flex; }
  .kb-nav a {
    padding: var(--kb-space-4) 0;
    border-left: 0;
    border-bottom: var(--kb-rule) solid var(--kb-border-subtle);
    font-size: var(--kb-text-xs);
  }
  .kb-nav a:last-child { border-right: 0; border-bottom: 0; }
  .kb-nav a:hover { box-shadow: none; color: var(--kb-accent-text); }
  .kb-nav-toggle { display: inline-grid; }
  .kb-header__actions { margin-left: auto; }
}

/* --------------------------------------------------------------------------
   Masthead
   The homepage opening. A rule, the title, a dateline, a standfirst — the
   top of a publication, not a product launch. No centred column, no radial
   glow behind the headline, no pair of call-to-action buttons.
   -------------------------------------------------------------------------- */
.kb-masthead {
  padding-block: clamp(2rem, 1.4rem + 2.4vw, 3.5rem) 0;
}
/* The masthead states the name at display size, so it IS the wordmark and
   has to be set as one — in the brand face, not the editorial serif. Setting
   it in Newsreader would give the site a second, contradictory wordmark. */
.kb-masthead__title {
  font-family: var(--kb-font-brand);
  font-size: clamp(2.25rem, 1.5rem + 3.4vw, 4rem);
  font-weight: var(--kb-weight-medium);
  letter-spacing: -0.03em;
  line-height: var(--kb-leading-tight);
  color: var(--kb-wordmark);
}
.kb-masthead__title .kb-logo__bracket { color: var(--kb-bracket); }

/* Lowercase with its full stop, as specified — an uppercase transform here
   would break the one rule the tagline has. */
.kb-masthead__tagline {
  margin-top: var(--kb-space-4);
  font-family: var(--kb-font-brand);
  font-size: var(--kb-text-sm);
  letter-spacing: 0.04em;
  color: var(--kb-text-muted);
}

/* The dateline strip: metadata left, standfirst right, split 4:7 rather
   than down the middle, because an even split reads as a template. */
.kb-masthead__rule {
  display: grid;
  gap: var(--kb-space-4) var(--kb-space-8);
  margin-top: var(--kb-space-6);
  padding-block: var(--kb-space-4);
  border-top: 2px solid var(--kb-text-primary);
}
@media (min-width: 800px) {
  .kb-masthead__rule { grid-template-columns: 4fr 7fr; }
}
.kb-masthead__dateline {
  display: flex;
  flex-wrap: wrap;
  gap: var(--kb-space-1) var(--kb-space-3);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-wide);
  text-transform: uppercase;
  color: var(--kb-text-muted);
  align-content: start;
}
/* The separator trails its own item rather than leading the next one, so a
   wrapped dateline never starts a line with a stray slash. */
.kb-masthead__dateline span:not(:last-child)::after {
  content: "/";
  margin-left: var(--kb-space-3);
  color: var(--kb-border-strong);
}
.kb-masthead__standfirst {
  font-size: var(--kb-text-lead);
  line-height: 1.55;
  color: var(--kb-text-secondary);
  text-wrap: pretty;
  max-width: 62ch;
}

/* --------------------------------------------------------------------------
   Featured — the lead item
   Ruled top and bottom, indented like a pulled quote, and given the only
   full-size serif headline on the page. It does not need a card to be
   the most important thing here; it needs to be bigger.
   -------------------------------------------------------------------------- */
.kb-featured {
  display: grid;
  gap: var(--kb-space-4) var(--kb-space-10);
  padding-block: var(--kb-space-8);
  border-bottom: var(--kb-rule) solid var(--kb-border);
}
@media (min-width: 900px) {
  .kb-featured { grid-template-columns: 7fr 4fr; align-items: start; }
}
.kb-featured__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kb-space-3);
  margin-bottom: var(--kb-space-4);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-wide);
  text-transform: uppercase;
  color: var(--kb-text-muted);
}
.kb-featured h2,
.kb-featured h3 {
  font-size: var(--kb-text-h1);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-display);
  line-height: 1.08;
  text-wrap: balance;
}
.kb-featured h2 a,
.kb-featured h3 a {
  color: inherit;
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size var(--kb-duration) var(--kb-ease);
}
.kb-featured h2 a:hover,
.kb-featured h3 a:hover {
  color: var(--kb-accent-text);
  background-size: 100% 1px;
}
.kb-featured .kb-lead { align-self: start; }

/* The lead item is the one place a photograph earns its space, so it gets
   the real cover image at a real size rather than a thumbnail in a row. */
.kb-featured__image {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border: var(--kb-rule) solid var(--kb-border);
}

/* --------------------------------------------------------------------------
   The index
   The site's main way of listing things. A numbered, ruled table of
   contents — the shape a manual uses — instead of a grid of identical
   cards with identical excerpts and a hover lift.
   -------------------------------------------------------------------------- */
.kb-index { border-top: var(--kb-rule) solid var(--kb-border); }

.kb-entry {
  position: relative;
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr) auto;
  gap: var(--kb-space-3) var(--kb-space-5);
  align-items: baseline;
  padding-block: var(--kb-space-4);
  border-bottom: var(--kb-rule) solid var(--kb-border);
  transition: background-color var(--kb-duration-fast) var(--kb-ease);
}
.kb-entry:hover { background: var(--kb-surface-inset); }

.kb-entry__num {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--kb-text-faint);
  transition: color var(--kb-duration-fast) var(--kb-ease);
}
.kb-entry:hover .kb-entry__num { color: var(--kb-accent); }

.kb-entry__title {
  font-size: clamp(1.125rem, 1.05rem + 0.35vw, 1.3125rem);
  font-weight: var(--kb-weight-medium);
  line-height: 1.24;
  letter-spacing: var(--kb-tracking-tight);
  text-wrap: pretty;
}
.kb-entry__title a {
  color: var(--kb-text-primary);
  text-decoration: none;
}
/* The title link is stretched over the whole row, so the row is the target
   and the anchor is still the only focusable thing in it. */
.kb-entry__title a::after {
  content: "";
  position: absolute;
  inset: 0;
}
.kb-entry:hover .kb-entry__title a,
.kb-score-row:hover .kb-entry__title a { color: var(--kb-accent-text); }

.kb-entry__kicker {
  display: block;
  margin-bottom: var(--kb-space-1);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  color: var(--kb-accent-text);
}

.kb-entry__excerpt {
  margin-top: var(--kb-space-2);
  max-width: 68ch;
  font-size: var(--kb-text-sm);
  line-height: 1.55;
  color: var(--kb-text-secondary);
  text-wrap: pretty;
  overflow-wrap: anywhere;
}

.kb-entry__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--kb-tracking-wide);
  text-transform: uppercase;
  color: var(--kb-text-faint);
  white-space: nowrap;
}

@media (max-width: 640px) {
  .kb-entry {
    grid-template-columns: 2rem minmax(0, 1fr);
  }
  .kb-entry__meta {
    grid-column: 2;
    flex-direction: row;
    align-items: baseline;
    justify-content: flex-start;
    gap: var(--kb-space-3);
    margin-top: var(--kb-space-2);
  }
}

/* Scorecards — the reviews index. A review's headline fact is its number,
   so the number is set at display size in the left rail and everything
   else hangs off it. */
.kb-scores { border-top: var(--kb-rule) solid var(--kb-border); }

.kb-score-row {
  position: relative;
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr) auto;
  gap: var(--kb-space-2) var(--kb-space-5);
  align-items: baseline;
  padding-block: var(--kb-space-5);
  border-bottom: var(--kb-rule) solid var(--kb-border);
  transition: background-color var(--kb-duration-fast) var(--kb-ease);
}
.kb-score-row:hover { background: var(--kb-surface-inset); }

.kb-score-row__value {
  font-family: var(--kb-font-mono);
  font-size: 2rem;
  font-weight: var(--kb-weight-medium);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--kb-text-primary);
}
.kb-score-row__value small {
  display: block;
  margin-top: 2px;
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-regular);
  letter-spacing: var(--kb-tracking-wide);
  color: var(--kb-text-faint);
}
.kb-score-row__unrated {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-wide);
  color: var(--kb-text-faint);
}

@media (max-width: 640px) {
  .kb-score-row { grid-template-columns: 3.25rem minmax(0, 1fr); }
  .kb-score-row__value { font-size: 1.5rem; }
  .kb-score-row .kb-entry__meta {
    grid-column: 2;
    flex-direction: row;
    gap: var(--kb-space-3);
  }
}

/* Build rows — a parts list is a price list, so the money is set in
   tabular mono and right-aligned to a column, the way an invoice is. */
.kb-buildrow__price {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-body);
  font-variant-numeric: tabular-nums;
  color: var(--kb-text-primary);
  letter-spacing: -0.01em;
}

/* --------------------------------------------------------------------------
   Topics
   A run-in list, set as a line of text with rule separators, rather than a
   grid of tiles that each contain two words.
   -------------------------------------------------------------------------- */
.kb-topics {
  display: flex;
  flex-wrap: wrap;
  gap: var(--kb-space-2) 0;
}
.kb-topic {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  padding-inline: var(--kb-space-4);
  border-left: var(--kb-rule) solid var(--kb-border);
  color: var(--kb-text-primary);
  text-decoration: none;
  transition: color var(--kb-duration-fast) var(--kb-ease);
}
.kb-topic:first-child { padding-left: 0; border-left: 0; }
.kb-topic:hover { color: var(--kb-accent-text); }
.kb-topic__name {
  font-family: var(--kb-font-display);
  font-size: 1.125rem;
  font-weight: var(--kb-weight-medium);
}
.kb-topic:hover .kb-topic__name { text-decoration: underline; text-underline-offset: 0.16em; }
/* The count is set as a superior figure, the way a footnote marker is. */
.kb-topic__count {
  align-self: flex-start;
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--kb-text-faint);
}

/* --------------------------------------------------------------------------
   Buttons
   Square, ruled, mono. A button here looks like a key on a machine, not
   like a pill with a glow under it.
   -------------------------------------------------------------------------- */
.kb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--kb-space-2);
  padding: 0.55rem 1rem;
  border: var(--kb-rule) solid var(--kb-text-primary);
  color: var(--kb-text-primary);
  background: transparent;
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--kb-duration-fast) var(--kb-ease),
              border-color var(--kb-duration-fast) var(--kb-ease),
              color var(--kb-duration-fast) var(--kb-ease);
}
.kb-btn:hover {
  background: var(--kb-text-primary);
  color: var(--kb-surface-base);
}
.kb-btn svg { width: 14px; height: 14px; flex: none; }

.kb-btn--primary {
  background: var(--kb-accent);
  border-color: var(--kb-accent);
  color: var(--kb-text-on-accent);
}
.kb-btn--primary:hover {
  background: var(--kb-accent-hover);
  border-color: var(--kb-accent-hover);
  color: var(--kb-text-on-accent);
}

.kb-btn--secondary {
  border-color: var(--kb-border-strong);
  color: var(--kb-text-primary);
}

.kb-btn--sm { padding: 0.3rem 0.6rem; }

.kb-btn--ghost {
  padding-inline: 0.35rem;
  border-color: transparent;
  color: var(--kb-text-muted);
}
.kb-btn--ghost:hover {
  background: transparent;
  border-color: var(--kb-border-strong);
  color: var(--kb-text-primary);
}

/* The "see all" link that ends a section rule. Not a button at all — a
   labelled arrow, so it never competes with a real action. */
.kb-btn--link {
  padding: 0;
  border: 0;
  color: var(--kb-text-muted);
}
.kb-btn--link:hover {
  background: transparent;
  color: var(--kb-accent-text);
}
.kb-btn--link::after { content: "→"; }

/* --------------------------------------------------------------------------
   Tags
   -------------------------------------------------------------------------- */
.kb-tag {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 0.4em;
  padding: 0.15rem 0.45rem;
  border: var(--kb-rule) solid var(--kb-border-strong);
  color: var(--kb-text-secondary);
  background: transparent;
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}
a.kb-tag:hover { border-color: var(--kb-accent); color: var(--kb-accent-text); }

.kb-tag--warm { border-color: var(--kb-warm); color: var(--kb-warm-text); }
.kb-tag--success { border-color: var(--kb-success); color: var(--kb-success-text); }
.kb-tag--danger { border-color: var(--kb-danger); color: var(--kb-danger-text); }
.kb-tag--neutral { border-color: var(--kb-border); color: var(--kb-text-muted); }

/* --------------------------------------------------------------------------
   Legacy hero / stat strip
   Kept for the static reference pages under /design. Stripped of the glow
   and the grid overlay they used to carry.
   -------------------------------------------------------------------------- */
.kb-hero {
  padding-block: clamp(2.5rem, 1.8rem + 3vw, 4rem);
  border-bottom: 2px solid var(--kb-text-primary);
}
.kb-hero__inner { max-width: 54rem; }
.kb-hero h1 {
  font-size: var(--kb-text-display);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-display);
  line-height: var(--kb-leading-tight);
  margin-block: var(--kb-space-4);
}
.kb-hero h1 em { font-style: italic; color: var(--kb-accent-text); }
.kb-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--kb-space-3);
  margin-top: var(--kb-space-6);
}

.kb-stats {
  display: flex;
  flex-wrap: wrap;
  margin-top: var(--kb-space-8);
  border-top: var(--kb-rule) solid var(--kb-border);
}
.kb-stat {
  display: flex;
  flex-direction: column-reverse;
  padding: var(--kb-space-4) var(--kb-space-6) var(--kb-space-4) 0;
  margin-right: var(--kb-space-6);
  border-right: var(--kb-rule) solid var(--kb-border);
}
.kb-stat:last-child { border-right: 0; }
.kb-stat__value {
  font-family: var(--kb-font-mono);
  font-size: 1.5rem;
  font-weight: var(--kb-weight-medium);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  color: var(--kb-text-primary);
}
.kb-stat__label {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  color: var(--kb-text-muted);
  margin-bottom: var(--kb-space-1);
}

/* Retained so the reference pages and any CMS content that still emits a
   card grid stay readable. New work uses .kb-index. */
.kb-grid {
  display: grid;
  gap: var(--kb-space-5);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
}
.kb-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--kb-space-3);
  padding-block: var(--kb-space-4);
  border-top: var(--kb-rule) solid var(--kb-border);
}
.kb-card__title {
  font-family: var(--kb-font-display);
  font-size: 1.1875rem;
  font-weight: var(--kb-weight-medium);
  line-height: 1.25;
}
.kb-card__title a { color: inherit; text-decoration: none; }
.kb-card__title a::after { content: ""; position: absolute; inset: 0; }
.kb-card:hover .kb-card__title a { color: var(--kb-accent-text); }
.kb-card__excerpt {
  color: var(--kb-text-secondary);
  font-size: var(--kb-text-sm);
  line-height: 1.55;
  text-wrap: pretty;
  overflow-wrap: anywhere;
}
.kb-card__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kb-space-2);
  margin-top: auto;
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--kb-tracking-wide);
  color: var(--kb-text-faint);
}

/* --------------------------------------------------------------------------
   Callouts — core to a troubleshooting publication.
   A marked-off block with a heavy rule on the reading edge, like a warning
   panel printed in a manual. No tinted rounded box.
   -------------------------------------------------------------------------- */
.kb-callout {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--kb-space-3);
  padding: var(--kb-space-4) var(--kb-space-5);
  margin-block: var(--kb-space-6);
  border-left: 3px solid var(--kb-accent);
  background: var(--kb-surface-inset);
  font-size: var(--kb-text-body);
  line-height: 1.6;
}
.kb-callout__icon { color: var(--kb-accent); padding-top: 1px; }
.kb-callout__icon svg { width: 16px; height: 16px; }
.kb-callout__title {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-semibold);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  margin-bottom: var(--kb-space-2);
  color: var(--kb-text-primary);
}
.kb-callout p { color: var(--kb-text-secondary); }
.kb-callout p + p { margin-top: var(--kb-space-2); }

.kb-callout--warn { border-left-color: var(--kb-warm); }
.kb-callout--warn .kb-callout__icon,
.kb-callout--warn .kb-callout__title { color: var(--kb-warm-text); }

.kb-callout--danger { border-left-color: var(--kb-danger); }
.kb-callout--danger .kb-callout__icon,
.kb-callout--danger .kb-callout__title { color: var(--kb-danger-text); }

.kb-callout--success { border-left-color: var(--kb-success); }
.kb-callout--success .kb-callout__icon,
.kb-callout--success .kb-callout__title { color: var(--kb-success-text); }

/* --------------------------------------------------------------------------
   Code
   Always dark, in both themes. A terminal does not change colour when the
   reader switches to light mode, and neither should a block of commands.
   -------------------------------------------------------------------------- */
.kb-code {
  margin-block: var(--kb-space-6);
  border: var(--kb-rule) solid var(--kb-ink-800);
  background: var(--kb-surface-code);
}
.kb-code__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--kb-space-3);
  padding: var(--kb-space-2) var(--kb-space-2) var(--kb-space-2) var(--kb-space-4);
  border-bottom: var(--kb-rule) solid var(--kb-ink-800);
}
.kb-code__lang {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  color: var(--kb-ink-300);
}
.kb-code__copy {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.3rem 0.55rem;
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-wide);
  text-transform: uppercase;
  color: var(--kb-ink-250);
  border: var(--kb-rule) solid transparent;
  transition: color var(--kb-duration-fast) var(--kb-ease),
              border-color var(--kb-duration-fast) var(--kb-ease);
}
.kb-code__copy:hover { color: var(--kb-ink-25); border-color: var(--kb-ink-700); }
.kb-code__copy svg { width: 13px; height: 13px; }
.kb-code__copy[data-copied="true"] { color: var(--kb-green-300); }

.kb-code pre {
  margin: 0;
  padding: var(--kb-space-4) var(--kb-space-5);
  overflow-x: auto;
  font-size: var(--kb-text-xs);
  line-height: 1.75;
  color: var(--kb-ink-100);
  tab-size: 2;
}
.kb-code code { font-family: inherit; }

/* Minimal, hand-applied token colours. Enough to read a PowerShell block
   without shipping a syntax highlighter. */
.t-cmd { color: var(--kb-blue-300); }
.t-param { color: var(--kb-amber-300); }
.t-str { color: var(--kb-green-300); }
.t-var { color: var(--kb-flame-300); }
.t-com { color: var(--kb-ink-400); font-style: italic; }
.t-num { color: var(--kb-amber-200); }

/* Inline code */
:not(pre) > code {
  padding: 0.08em 0.32em;
  background: var(--kb-surface-inset);
  border: var(--kb-rule) solid var(--kb-border-subtle);
  font-size: 0.88em;
  color: var(--kb-text-primary);
  word-break: break-word;
}

kbd {
  display: inline-block;
  padding: 0.05em 0.4em;
  border: var(--kb-rule) solid var(--kb-border-strong);
  border-bottom-width: 2px;
  background: var(--kb-surface-raised);
  font-family: var(--kb-font-mono);
  font-size: 0.82em;
  font-weight: var(--kb-weight-medium);
  line-height: 1.5;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Article opening
   The metadata sits in a left margin rail on wide screens, the way a
   figure caption or a marginal note does in printed documentation, rather
   than stacking under the title in the middle of the column.
   -------------------------------------------------------------------------- */
.kb-article-head {
  padding-bottom: var(--kb-space-5);
  border-bottom: 2px solid var(--kb-text-primary);
  margin-bottom: var(--kb-space-8);
}
.kb-article-head h1 {
  font-size: var(--kb-text-h1);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-display);
  line-height: 1.08;
  margin-block: var(--kb-space-3) var(--kb-space-5);
  max-width: 24ch;
}
.kb-article-head .kb-lead { max-width: var(--kb-width-prose); }

.kb-byline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--kb-space-2) var(--kb-space-4);
  margin-top: var(--kb-space-6);
  padding-top: var(--kb-space-3);
  border-top: var(--kb-rule) solid var(--kb-border);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-wide);
  text-transform: uppercase;
  color: var(--kb-text-muted);
}
.kb-byline span:first-child { color: var(--kb-text-primary); }
.kb-byline strong { color: var(--kb-text-primary); font-weight: var(--kb-weight-medium); }
.kb-byline__avatar {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  background: var(--kb-surface-inverse);
  color: var(--kb-text-inverse);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-semibold);
}

/* --------------------------------------------------------------------------
   Prose
   -------------------------------------------------------------------------- */
.kb-prose {
  max-width: var(--kb-width-prose);
  font-size: var(--kb-text-prose);
  line-height: var(--kb-leading-prose);
  color: var(--kb-text-primary);
  text-wrap: pretty;
}
.kb-prose > * + * { margin-top: var(--kb-space-5); }

/* Headings inside prose carry a mono section number's worth of weight
   without a number: a rule above, tight leading, serif. */
.kb-prose h2 {
  font-size: var(--kb-text-h2);
  font-weight: var(--kb-weight-medium);
  margin-top: var(--kb-space-12);
  padding-top: var(--kb-space-3);
  border-top: var(--kb-rule) solid var(--kb-border);
  scroll-margin-top: calc(var(--kb-header-height) + 2rem);
}
.kb-prose h3 {
  font-size: var(--kb-text-h3);
  font-weight: var(--kb-weight-semibold);
  margin-top: var(--kb-space-8);
  scroll-margin-top: calc(var(--kb-header-height) + 2rem);
}
.kb-prose strong { color: var(--kb-text-primary); font-weight: var(--kb-weight-semibold); }
.kb-prose ul, .kb-prose ol { padding-left: var(--kb-space-6); color: var(--kb-text-secondary); }
.kb-prose ul { list-style: square; }
.kb-prose ol { list-style: decimal; }
.kb-prose li + li { margin-top: var(--kb-space-2); }
.kb-prose li::marker { color: var(--kb-accent); font-family: var(--kb-font-mono); }

/* A pulled quote, set in the display serif and hung into the margin. */
.kb-prose blockquote {
  padding-left: var(--kb-space-5);
  border-left: 2px solid var(--kb-text-primary);
  font-family: var(--kb-font-display);
  font-size: var(--kb-text-h3);
  font-style: italic;
  font-weight: var(--kb-weight-regular);
  line-height: 1.45;
  color: var(--kb-text-primary);
}
.kb-prose hr {
  border: 0;
  border-top: var(--kb-rule) solid var(--kb-border);
  margin-block: var(--kb-space-10);
}
.kb-prose figcaption {
  margin-top: var(--kb-space-2);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-wide);
  color: var(--kb-text-muted);
}
/* Apparatus escapes the prose measure — a command line needs the width. */
.kb-prose .kb-code,
.kb-prose .kb-callout,
.kb-prose .kb-table-wrap,
.kb-prose .kb-steps { max-width: min(100%, 780px); }

/* Numbered procedure — the signature editorial component. The number is a
   square plate in the margin with a rail running between plates, so a long
   procedure reads as one continuous run of steps. */
.kb-steps,
.kb-prose ol.kb-steps {
  counter-reset: kb-step;
  list-style: none;
  padding-left: 0;
}
.kb-steps > li {
  position: relative;
  counter-increment: kb-step;
  padding-left: var(--kb-space-12);
  padding-bottom: var(--kb-space-6);
}
.kb-steps > li + li { margin-top: 0; }
.kb-steps > li::before {
  content: counter(kb-step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 1px;
  display: grid;
  place-items: center;
  width: 28px;
  height: 24px;
  background: var(--kb-text-primary);
  color: var(--kb-surface-base);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-semibold);
  letter-spacing: 0.04em;
}
.kb-steps > li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 13px;
  top: 30px;
  bottom: 2px;
  width: var(--kb-rule);
  background: var(--kb-border);
}
.kb-steps > li > :first-child {
  margin-top: 0;
  font-weight: var(--kb-weight-semibold);
  color: var(--kb-text-primary);
  font-size: var(--kb-text-prose);
}
.kb-steps > li > * + * { margin-top: var(--kb-space-3); }

/* Tables — spec sheets. Heavy rules top and bottom, hairlines between
   rows, tabular figures. No rounded container, no zebra striping. */
.kb-table-wrap {
  margin-block: var(--kb-space-6);
  overflow-x: auto;
  border-top: 2px solid var(--kb-text-primary);
  border-bottom: 2px solid var(--kb-text-primary);
}
.kb-table {
  font-size: var(--kb-text-body);
  font-variant-numeric: tabular-nums;
}
.kb-table th,
.kb-table td {
  padding: var(--kb-space-3) var(--kb-space-4) var(--kb-space-3) 0;
  text-align: left;
  border-bottom: var(--kb-rule) solid var(--kb-border);
  vertical-align: top;
}
.kb-table th:last-child,
.kb-table td:last-child { padding-right: 0; }
.kb-table thead th {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  color: var(--kb-text-muted);
  white-space: nowrap;
  border-bottom-color: var(--kb-border-strong);
}
.kb-table tbody tr:last-child td,
.kb-table tbody tr:last-child th { border-bottom: none; }
.kb-table tbody th {
  font-family: var(--kb-font-sans);
  font-weight: var(--kb-weight-medium);
  color: var(--kb-text-primary);
}
.kb-table td { color: var(--kb-text-secondary); }

/* Verdict panel — closes every hardware review. */
.kb-verdict {
  margin-block: var(--kb-space-10);
  padding-block: var(--kb-space-5);
  border-top: 2px solid var(--kb-text-primary);
  border-bottom: 2px solid var(--kb-text-primary);
}
.kb-verdict__score {
  display: flex;
  align-items: baseline;
  gap: var(--kb-space-2);
  font-family: var(--kb-font-mono);
  margin-block: var(--kb-space-3) var(--kb-space-4);
}
.kb-verdict__score b {
  font-size: 2.75rem;
  font-weight: var(--kb-weight-medium);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.045em;
  line-height: 1;
  color: var(--kb-text-primary);
}
.kb-verdict__score span { color: var(--kb-text-faint); font-size: var(--kb-text-body); }
.kb-verdict__cols {
  display: grid;
  gap: var(--kb-space-5) var(--kb-space-8);
  margin-top: var(--kb-space-5);
  padding-top: var(--kb-space-5);
  border-top: var(--kb-rule) solid var(--kb-border);
  font-size: var(--kb-text-body);
  line-height: 1.6;
}
@media (min-width: 700px) { .kb-verdict__cols { grid-template-columns: 1fr 1fr; } }
.kb-verdict__cols h4 {
  display: flex;
  align-items: center;
  gap: var(--kb-space-2);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-semibold);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  margin-bottom: var(--kb-space-3);
}
.kb-verdict__cols h4.is-good { color: var(--kb-success-text); }
.kb-verdict__cols h4.is-bad { color: var(--kb-danger-text); }
.kb-verdict__cols ul,
.kb-prose .kb-verdict__cols ul { list-style: none; padding-left: 0; }
.kb-verdict__cols li {
  position: relative;
  padding-left: var(--kb-space-5);
  color: var(--kb-text-secondary);
}
.kb-verdict__cols li + li { margin-top: var(--kb-space-2); }
.kb-verdict__cols li::before {
  position: absolute;
  left: 0;
  font-family: var(--kb-font-mono);
}
.kb-verdict__cols .is-good + ul li::before { content: "+"; color: var(--kb-success); }
.kb-verdict__cols .is-bad + ul li::before { content: "−"; color: var(--kb-danger); }

/* Test conditions — the strongest trust signal the brand has, and the one
   component that is mandatory on every guide and review. Set as a labelled
   plate: ink rule on the reading edge, mono throughout, nothing decorative. */
.kb-testbed {
  margin-block: var(--kb-space-6);
  padding: var(--kb-space-4) var(--kb-space-5);
  border-left: 3px solid var(--kb-text-primary);
  background: var(--kb-surface-inset);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-xs);
  line-height: 1.8;
  color: var(--kb-text-secondary);
}
.kb-testbed dt {
  display: inline;
  color: var(--kb-text-faint);
  text-transform: uppercase;
  letter-spacing: var(--kb-tracking-wide);
}
.kb-testbed dt::after { content: "  "; white-space: pre; }
.kb-testbed dd { display: inline; margin: 0; color: var(--kb-text-primary); }
.kb-testbed dd::after { content: "\A"; white-space: pre; }

/* --------------------------------------------------------------------------
   Newsletter
   -------------------------------------------------------------------------- */
.kb-signup {
  display: grid;
  gap: var(--kb-space-6);
  align-items: start;
  padding-block: var(--kb-space-8);
  border-top: 2px solid var(--kb-text-primary);
  border-bottom: var(--kb-rule) solid var(--kb-border);
}
@media (min-width: 860px) {
  .kb-signup { grid-template-columns: 1fr minmax(300px, 360px); gap: var(--kb-space-10); }
}
.kb-signup h2 { font-size: var(--kb-text-h3); margin-block: var(--kb-space-3) var(--kb-space-2); }
.kb-signup p { color: var(--kb-text-secondary); max-width: 50ch; }

.kb-field { display: flex; gap: var(--kb-space-2); flex-wrap: wrap; }
.kb-input {
  flex: 1 1 240px;
  padding: 0.55rem 0.7rem;
  border: var(--kb-rule) solid var(--kb-border-strong);
  background: var(--kb-surface-raised);
  color: var(--kb-text-primary);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-sm);
  transition: border-color var(--kb-duration-fast) var(--kb-ease);
}
.kb-input::placeholder { color: var(--kb-text-faint); }
.kb-input:focus { outline: none; border-color: var(--kb-accent); }
.kb-field-note {
  margin-top: var(--kb-space-3);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  color: var(--kb-text-faint);
}

/* --------------------------------------------------------------------------
   Contact
   The form is the page and the rail is marginalia, so the split is 7:4 and
   the rail sits behind a rule rather than inside a card.
   -------------------------------------------------------------------------- */
.kb-contact {
  display: grid;
  gap: var(--kb-space-10);
  align-items: start;
}
@media (min-width: 900px) {
  .kb-contact {
    grid-template-columns: 7fr 4fr;
    gap: var(--kb-space-12);
  }
}
.kb-contact > * { min-width: 0; }

.kb-contact__rail {
  display: grid;
  gap: var(--kb-space-5);
  align-content: start;
}

.kb-rail-item {
  padding-top: var(--kb-space-3);
  border-top: var(--kb-rule) solid var(--kb-border);
}
.kb-rail-item h2 {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-semibold);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  margin-bottom: var(--kb-space-2);
}
.kb-rail-item p {
  font-size: var(--kb-text-sm);
  line-height: 1.6;
  color: var(--kb-text-secondary);
  text-wrap: pretty;
}
.kb-rail-item__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--kb-space-2) var(--kb-space-4);
  margin-top: var(--kb-space-3);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-wide);
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   Forms
   Labels are apparatus, so they are set in mono above the control. The
   controls themselves carry what a person typed, so they are set in the
   reading face. Focus is a two-pixel accent rule, not a soft glow ring.
   -------------------------------------------------------------------------- */
.kb-form {
  display: grid;
  gap: var(--kb-space-5);
  max-width: 44rem;
}

.kb-form__field { display: grid; gap: var(--kb-space-2); }

.kb-form__label {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  color: var(--kb-text-muted);
}
.kb-form__label span { color: var(--kb-accent); }

.kb-form__control {
  width: 100%;
  padding: 0.6rem 0.75rem;
  border: var(--kb-rule) solid var(--kb-border-strong);
  background: var(--kb-surface-raised);
  color: var(--kb-text-primary);
  font-family: var(--kb-font-sans);
  font-size: var(--kb-text-body);
  line-height: 1.55;
  transition: border-color var(--kb-duration-fast) var(--kb-ease),
              box-shadow var(--kb-duration-fast) var(--kb-ease);
}
.kb-form__control::placeholder { color: var(--kb-text-faint); }
.kb-form__control:focus {
  outline: none;
  border-color: var(--kb-accent);
  box-shadow: inset 0 0 0 1px var(--kb-accent);
}
/* Only after a real attempt, so a field is never red before it is filled. */
.kb-form__control:user-invalid {
  border-color: var(--kb-danger);
  box-shadow: inset 0 0 0 1px var(--kb-danger);
}

.kb-form__control--body {
  min-height: 12rem;
  resize: vertical;
}

.kb-form__hint {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  line-height: 1.6;
  color: var(--kb-text-faint);
}

.kb-form__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kb-space-3) var(--kb-space-5);
  padding-top: var(--kb-space-4);
  border-top: var(--kb-rule) solid var(--kb-border);
}

.kb-form__status {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  letter-spacing: var(--kb-tracking-wide);
  color: var(--kb-text-muted);
}

/* --------------------------------------------------------------------------
   Footer
   Ends with a colophon. A publication says what it is set in and who made
   it; that line is the difference between a site and a page.
   -------------------------------------------------------------------------- */
.kb-footer {
  margin-top: var(--kb-space-16);
  padding-block: var(--kb-space-10) var(--kb-space-8);
  border-top: 2px solid var(--kb-text-primary);
}
.kb-footer__grid {
  display: grid;
  gap: var(--kb-space-8);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr));
}
.kb-footer__brand { grid-column: 1 / -1; max-width: 34ch; }
@media (min-width: 860px) { .kb-footer__brand { grid-column: span 2; } }
.kb-footer__brand strong {
  font-family: var(--kb-font-display);
  font-size: 1.25rem;
  font-weight: var(--kb-weight-semibold);
}
.kb-footer__brand p {
  margin-top: var(--kb-space-3);
  color: var(--kb-text-muted);
  font-size: var(--kb-text-sm);
  line-height: 1.6;
}
.kb-footer h3 {
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  font-weight: var(--kb-weight-medium);
  letter-spacing: var(--kb-tracking-label);
  text-transform: uppercase;
  color: var(--kb-text-faint);
  margin-bottom: var(--kb-space-3);
  padding-bottom: var(--kb-space-2);
  border-bottom: var(--kb-rule) solid var(--kb-border);
}
.kb-footer li + li { margin-top: var(--kb-space-2); }
.kb-footer li a {
  color: var(--kb-text-secondary);
  font-size: var(--kb-text-sm);
  text-decoration: none;
}
.kb-footer li a:hover { color: var(--kb-accent-text); text-decoration: underline; }

.kb-footer__base {
  display: grid;
  gap: var(--kb-space-3);
  margin-top: var(--kb-space-10);
  padding-top: var(--kb-space-4);
  border-top: var(--kb-rule) solid var(--kb-border);
  font-family: var(--kb-font-mono);
  font-size: var(--kb-text-2xs);
  line-height: 1.7;
  color: var(--kb-text-faint);
}
@media (min-width: 860px) {
  .kb-footer__base { grid-template-columns: 1fr auto; align-items: end; }
}
.kb-colophon { max-width: 62ch; }
.kb-colophon b { color: var(--kb-text-muted); font-weight: var(--kb-weight-medium); }

/* --------------------------------------------------------------------------
   Overflow containment

   Grid and flex items default to `min-width: auto`, which refuses to shrink
   below their content. A single long command line inside a code block is
   therefore enough to push the whole page wider than a phone viewport.
   Every container that can hold unbreakable content needs an explicit floor.
   -------------------------------------------------------------------------- */
.kb-header__inner > *,
.kb-featured > *,
.kb-grid > *,
.kb-masthead__rule > *,
.kb-entry > *,
.kb-score-row > *,
.kb-signup > *,
.kb-footer__grid > *,
.kb-callout > *,
.kb-verdict__cols > *,
.kb-stats > * { min-width: 0; }

.kb-code,
.kb-table-wrap,
.kb-prose,
.kb-card,
.kb-steps > li,
.kb-testbed { min-width: 0; }

/* The testbed is mono and unwrappable by default; let long values break. */
.kb-testbed dd { overflow-wrap: anywhere; }

/* Nav is out of flow on mobile, but the logo must never widen the header. */
.kb-logo { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
