/* pages.css — page-specific styles that don't belong on any other module.
   Each section is one page's surface: anonymous /splash,
   /pricing (plan toggle + plans + contact lead form), /news (posts +
   latest-news + compose), /admin nav. */

/* ============================================================
   accessibility utilities
   ============================================================ */

/* Visually hidden but exposed to assistive tech (labels, live-region status). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Skip link: off-screen until focused, then parks top-left (WCAG 2.4.1). */
.skip-link {
  position: absolute;
  left: 8px;
  top: -48px;
  z-index: 100;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--ink);
  padding: 0.4rem 0.7rem;
  border-radius: 4px;
  transition: top 0.15s ease;
}
.skip-link:focus { top: 8px; }

/* ============================================================
   marketing landing (anonymous /)
   ============================================================ */
.splash {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding: 3.25rem 1rem 2.5rem;
  border-bottom: 3px double var(--ink);
}
.splash > * { position: relative; z-index: 1; }
.splash-eyebrow {
  text-transform: lowercase;
  letter-spacing: 0.22em;
  font-size: 12px;
  color: var(--faint);
  margin: 0 0 0.6rem;
}
.splash-title {
  font-variation-settings: var(--mono);
  font-size: clamp(1.9rem, 5.2vw, 3.3rem);
  line-height: 1.12;
  letter-spacing: 0.01em;
  border: none;
  margin: 0 0 0.9rem;
}
.splash-lede {
  font-variation-settings: var(--prose);
  color: var(--grey);
  max-width: 44rem;
  margin: 0 auto 1.6rem;
  font-size: 15px;
}
.splash-cta { display: flex; gap: 0.6rem; justify-content: center; flex-wrap: wrap; }
.splash-btn {
  font-size: 13px;
  color: var(--ink);
  text-decoration: none;
  border: 1px solid var(--ink);
  padding: 0.5rem 1.4rem;
  background: var(--paper);
}
.splash-btn:hover { background: var(--ink); color: var(--paper); }
.splash-btn-primary { background: var(--ink); color: var(--paper); }
.splash-btn-primary:hover { opacity: 0.85; }

.value-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1rem;
  margin: 2rem 0;
}
.value { border: 1px solid var(--hair); padding: 1rem 1.1rem 1.15rem; background: var(--paper); }
.value h2 { font-size: 15px; margin: 0 0 0.4rem; }
.value p { margin: 0; color: var(--grey); font-variation-settings: var(--prose); font-size: 13px; }

.splash-foot { text-align: center; margin: 2.5rem 0 1rem; }
.splash-foot h2 { font-size: clamp(1.2rem, 3vw, 1.7rem); margin: 0 0 0.4rem; border: none; }
.splash-foot .lede { margin: 0 auto; } /* auto margins center the max-width:64ch block */
.splash-foot .splash-cta { margin-top: 1.6rem; } /* breathing room between the lede and the bottom CTAs */

/* ---- marketing content blocks appended below the landing value-grid:
   the gap (generic vs. repo managers), the how-it-works pipeline, the
   capabilities grid, and the economics band. Shared section furniture
   first, then per-block grids. All lean on the same hairline-card
   vocabulary as .value so the page reads as one surface. ---- */
.mkt { margin: 2.75rem 0; }
.mkt-eyebrow {
  font-variation-settings: var(--mono);
  text-transform: lowercase;
  letter-spacing: 0.18em;
  font-size: 11px;
  color: var(--faint);
  margin: 0 0 0.4rem;
}
.mkt-title {
  font-size: clamp(1.25rem, 3vw, 1.8rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0 0 0.6rem;
  border: none;
}
.mkt-lede {
  font-variation-settings: var(--prose);
  color: var(--grey);
  max-width: 60ch;
  margin: 0 0 1.4rem;
  font-size: 14px;
}

/* the gap — two-column contrast, hairline-divided */
.gap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
}
.gap-cell { background: var(--paper); padding: 1.1rem 1.2rem 1.2rem; }
.gap-k {
  font-variation-settings: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 10px;
  color: var(--faint);
  margin: 0 0 0.45rem;
}
.gap-cell h3 { font-size: 15px; margin: 0 0 0.4rem; border: none; }
.gap-cell p { margin: 0; color: var(--grey); font-variation-settings: var(--prose); font-size: 13px; }

/* how-it-works pipeline — numbered steps, hairline-divided cells */
.pipe {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(6, 1fr); /* all six steps on one line */
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
}
/* narrow screens can't fit six across — fall back to two rows of three */
.pipe-4 { grid-template-columns: repeat(4, 1fr); } /* a four-step pipe (e.g. /federation) without the 6-col layout's trailing empty cells */
@media (max-width: 680px) { .pipe { grid-template-columns: repeat(2, 1fr); } }
.pipe-step { background: var(--paper); padding: 1rem 1.05rem 1.1rem; position: relative; }
/* the › sits on each step's right edge, straddling the hairline gap, paper
   background so it reads as a connector between steps. Hidden on the last
   step (no following step) and on the stacked mobile layout. */
.pipe-tick {
  position: absolute;
  right: -7px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  font-variation-settings: var(--mono);
  color: var(--faint);
  background: var(--paper);
  line-height: 1;
  padding: 1px 0;
}
.pipe-step:last-child .pipe-tick { display: none; }
@media (max-width: 680px) { .pipe-tick { display: none; } }
.pipe-no { font-variation-settings: var(--mono); font-size: 11px; color: var(--ochre); letter-spacing: 0.06em; }
.pipe-step h3 { font-size: 14px; margin: 0.35rem 0 0.3rem; border: none; }
.pipe-step p { margin: 0; color: var(--grey); font-variation-settings: var(--prose); font-size: 13px; line-height: 1.45; }
.pipe-step code { font-size: 0.92em; }

/* capabilities grid — same card as .value, six tiles */
.cap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1rem;
}
.cap {
  border: 1px solid var(--hair);
  padding: 1rem 1.1rem 1.15rem;
  background: var(--paper);
  transition: background 0.14s ease, border-color 0.14s ease;
}
.cap:hover { background: color-mix(in srgb, var(--ochre) 12%, var(--paper)); border-color: var(--ochre); }
.cap h3 { font-size: 14px; margin: 0 0 0.35rem; border: none; }
.cap p { margin: 0; color: var(--grey); font-variation-settings: var(--prose); font-size: 13px; }

/* economics band — a single inked-border panel to close the page body */
.mkt-band { border: 1px solid var(--ink); background: var(--paper); padding: 1.4rem 1.4rem 1.5rem; }
.band-points { margin: 0; padding: 0 0 0 1.1rem; }
.band-points li { color: var(--grey); font-variation-settings: var(--prose); font-size: 13px; margin: 0 0 0.4rem; }
.band-points li:last-child { margin-bottom: 0; }

/* section accent pics — a hand-drawn mark above each marketing section's
   eyebrow, and a smaller one per capability tile. Kept decorative + faint. */
.mkt-ico { margin: 0 0 0.2rem -2px; }
.mkt-ico svg { width: 52px; height: 52px; display: block; }
:root[data-theme="dark"] .mkt-ico { opacity: 0.88; }

/* one-product "versus" — the incumbent stack vs gastropod, hairline split */
.versus {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
  margin-top: 1.3rem;
}
.versus-col { background: var(--paper); padding: 1.1rem 1.2rem 1.2rem; }
.versus-us { background: color-mix(in srgb, var(--ochre) 9%, var(--paper)); }
.versus-k {
  font-variation-settings: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 10px;
  color: var(--faint);
  margin: 0 0 0.6rem;
}
.versus-col ul { list-style: none; margin: 0; padding: 0; }
.versus-col li {
  font-variation-settings: var(--prose);
  font-size: 13px;
  color: var(--grey);
  padding: 0.28rem 0;
  border-top: 1px solid var(--hair);
}
.versus-col li:first-child { border-top: none; }
.versus-col .plus { color: var(--ochre); font-variation-settings: var(--mono); font-weight: 700; }
.versus-sum { color: var(--ink) !important; font-weight: 700; margin-top: 0.2rem; }

/* split teaser — text beside a small pic, for the lean home "product" tease */
.mkt-split { display: grid; grid-template-columns: 1.3fr 0.7fr; gap: 1.5rem; align-items: center; }
/* reversed: graphic in the (narrower) left column, text on the right */
.mkt-split-rev { grid-template-columns: 0.7fr 1.3fr; }
.mkt-split-art { display: flex; justify-content: center; }
.mkt-split-art svg { width: 100%; max-width: 280px; height: auto; }
.mkt-split-art-sm svg { max-width: 210px; } /* 25% smaller (e.g. the trust-section bubble) */
@media (max-width: 640px) { .mkt-split { grid-template-columns: 1fr; } .mkt-split-art { display: none; } }

/* product-page section headings (inside the .panel, not .mkt) */
.section-h { font-size: clamp(1.1rem, 2.5vw, 1.5rem); margin: 2.4rem 0 0.4rem; border: none; letter-spacing: -0.01em; }
.section-sub { max-width: 60ch; margin: 0 0 1.3rem; font-size: 14px; }

/* ecosystems grid — supported registries, each a hand-drawn mark + name +
   the one client line you change. Drop an <img> into .eco-mark to use a real
   logo instead of the pic. */
.eco-grid {
  display: grid;
  /* fixed 4 columns (not auto-fit) so the trailing "more" tile can span an
     exact, known number of leftover cells — see .eco-more below. */
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  /* paper backing so the framed cells read as white, not a grey void; each tile
     draws its own hairline frame (below), so the separator lines only appear
     around filled cells. */
  background: var(--paper);
  border: 1px solid var(--hair);
}
@media (max-width: 860px) { .eco-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px) { .eco-grid { grid-template-columns: repeat(2, 1fr); } }
/* eco-grid-2: a two-tile variant (e.g. federation's "open standards") that
   wraps tight around its tiles instead of leaving empty cells in the wider
   4-column grid. fit-content keeps the hairline frame around the two boxes
   only; it stacks to one column on narrow screens. */
.eco-grid.eco-grid-2 { grid-template-columns: repeat(2, 15rem); width: fit-content; max-width: 100%; }
@media (max-width: 620px) { .eco-grid.eco-grid-2 { grid-template-columns: 1fr; width: auto; } }
.eco-tile { background: var(--paper); box-shadow: 0 0 0 1px var(--hair); padding: 1rem 1.1rem 1.1rem; display: flex; flex-direction: column; gap: 0.25rem; }
.eco-mark img, .eco-mark svg { width: 44px; height: 44px; display: block; object-fit: contain; }
.eco-tile h3 { font-size: 14px; margin: 0.2rem 0 0; border: none; }
.eco-set { margin: 0; }
.eco-set code { font-variation-settings: var(--mono); font-size: 11.5px; color: var(--grey); }
/* trailing tile filling the last row's empty space; centred so it reads as a
   quiet placeholder rather than a real ecosystem entry. With 9 ecosystems it
   spans the 3 leftover cells at 4 cols and the 1 leftover at 2 cols; at 3 cols
   the nine fill exactly, so it sits full-width on its own row. */
.eco-more { align-items: center; justify-content: center; text-align: center; }
.eco-more p { margin: 0; font-size: 13px; }
.eco-grid .eco-more { grid-column: span 3; }
@media (max-width: 620px) { .eco-grid .eco-more { grid-column: span 1; } }

/* capability tiles get an icon above the heading */
.cap-ico { margin-bottom: 0.4rem; }
.cap-ico svg { width: 40px; height: 40px; display: block; }

/* /demo two-column: what we'll cover beside the request form */
.demo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin-top: 1.5rem; }
.demo-points h2 { font-size: 15px; margin: 0 0 0.6rem; border: none; }
.demo-list { list-style: none; margin: 0 0 1rem; padding: 0; }
.demo-list li {
  font-variation-settings: var(--prose);
  font-size: 13px;
  color: var(--grey);
  padding: 0.45rem 0;
  border-top: 1px solid var(--hair);
}
.demo-list li:first-child { border-top: none; }
.demo-aside { font-size: 13px; }
@media (max-width: 720px) { .demo-grid { grid-template-columns: 1fr; } }

/* /security trust cards + candor band */
.trust-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}
.trust-card { border: 1px solid var(--hair); padding: 1rem 1.1rem 1.15rem; background: var(--paper); }
.trust-card h2 { font-size: 14px; margin: 0 0 0.35rem; border: none; }
.trust-card p { margin: 0; color: var(--grey); font-variation-settings: var(--prose); font-size: 13px; }
.candor { border: 1px solid var(--ink); background: var(--paper); padding: 1.3rem 1.4rem; margin-top: 1.6rem; }
.candor.candor-bare { border: none; background: none; padding-left: 0; padding-right: 0; }
.candor h2 { font-size: 15px; margin: 0 0 0.4rem; border: none; }
.candor-list { margin: 0.6rem 0; padding: 0 0 0 1.1rem; }
.candor-list li { color: var(--grey); font-variation-settings: var(--prose); font-size: 13px; margin: 0 0 0.5rem; }

/* feature comparison chart (product page) — gastropod vs a generic repo
   manager, dot-matrix in the engineering-drawing style. */
.cmp-scroll { overflow-x: auto; border: 1px solid var(--hair); margin-top: 1rem; }
table.cmp { border-collapse: collapse; width: 100%; min-width: 540px; background: var(--paper); }
table.cmp th, table.cmp td { text-align: left; padding: 0.6rem 0.85rem; border-bottom: 1px solid var(--hair); font-size: 13px; vertical-align: middle; }
table.cmp thead th {
  font-variation-settings: var(--mono);
  font-size: 11px;
  text-transform: lowercase;
  letter-spacing: 0.08em;
  color: var(--grey);
  border-bottom: 1.5px solid var(--ink);
}
table.cmp td:first-child { font-variation-settings: var(--prose); color: var(--ink); }
table.cmp .cmp-us { background: color-mix(in srgb, var(--ochre) 9%, var(--paper)); }
table.cmp thead th.cmp-us { color: var(--ink); }
table.cmp tbody tr:last-child td { border-bottom: none; }
table.cmp tbody td { transition: background 0.14s ease; }
table.cmp tbody tr:hover td { background: color-mix(in srgb, var(--ochre) 12%, var(--paper)); }
table.cmp td .dot { margin-right: 0.4em; }
.dot { display: inline-block; width: 12px; height: 12px; border-radius: 50%; border: 1.5px solid var(--ink); vertical-align: -1px; }
.dot.full { background: var(--ink); }
.dot.part { background: linear-gradient(90deg, var(--ink) 50%, transparent 50%); }
.dot.none { background: transparent; border-color: var(--hair); }
.cmp-legend { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 0.7rem; font-size: 11.5px; color: var(--grey); }
.cmp-legend span { display: inline-flex; align-items: center; gap: 0.4em; }
.cmp-note { margin-top: 0.6rem; font-size: 12px; max-width: 72ch; }

/* full feature list (product page) — grouped "everything included" checklist */
.featlist { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; margin-top: 1rem; }
.featgroup { border: 1px solid var(--hair); padding: 1rem 1.1rem 1.1rem; background: var(--paper); }
.featgroup h3 { font-variation-settings: var(--mono); font-size: 12px; margin: 0 0 0.5rem; border: none; text-transform: lowercase; letter-spacing: 0.06em; color: var(--ink); }
.featgroup ul { list-style: none; margin: 0; padding: 0; }
.featgroup li {
  font-variation-settings: var(--prose);
  font-size: 12.5px;
  color: var(--grey);
  padding: 0.32rem 0 0.32rem 1.1rem;
  position: relative;
  border-top: 1px solid var(--hair);
}
.featgroup li:first-child { border-top: none; }
.featgroup li::before { content: "+"; position: absolute; left: 0; color: var(--ochre); font-variation-settings: var(--mono); font-weight: 700; }
.featgroup code { font-variation-settings: var(--mono); font-size: 0.92em; }

/* product screenshots ("see it in action") — framed real UI shots, with the
   hand-drawn offset shadow so they sit in the engineering-drawing aesthetic. */
.shot { margin: 1.1rem 0 0; }
.shot img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--hair);
  border-radius: 3px;
  box-shadow: 3px 4px 0 var(--hair);
}
.shot figcaption { font-variation-settings: var(--prose); font-size: 12.5px; color: var(--grey); margin-top: 0.6rem; max-width: 64ch; }
.shot-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 1.3rem; margin-top: 1.3rem; align-items: start; }
@media (max-width: 680px) { .shot-pair { grid-template-columns: 1fr; } }

/* selectable gallery (JS-free): a row of thumbnails above one full-width viewer;
   hidden radios drive selection via :checked ~ sibling so it costs no script.
   The thumbnail strip sits ABOVE the large image on purpose: the screenshots
   differ wildly in height, so if the thumbs were below, switching would resize
   the image above them and jump the thumbs (and the page) under the cursor.
   With the strip on top nothing above it moves, so only the area below reflows. */
.gallery { margin-top: 1.1rem; }
.gallery-radio { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.gallery-large { display: none; margin: 0; }
.gallery-large img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--hair); border-radius: 3px; box-shadow: 3px 4px 0 var(--hair);
}
.gallery-large figcaption { font-variation-settings: var(--prose); font-size: 12.5px; color: var(--grey); margin-top: 0.6rem; max-width: 64ch; }
/* show (with a soft fade, not a hard cut) the figure whose radio is checked */
#shot-dashboard:checked ~ .gallery-stage .gl-dashboard,
#shot-malware:checked ~ .gallery-stage .gl-malware,
#shot-audit:checked ~ .gallery-stage .gl-audit { display: block; animation: gallery-fade 0.25s ease; }
@keyframes gallery-fade { from { opacity: 0; } to { opacity: 1; } }

.gallery-thumbs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.9rem; }
.gallery-stage { margin-top: 1.2rem; }
.gallery-thumb { cursor: pointer; display: block; }
.gallery-thumb img {
  display: block; width: 100%; height: 92px; object-fit: cover; object-position: top;
  border: 2px solid var(--hair); border-radius: 3px; background: var(--paper);
  transition: border-color 0.14s ease;
}
.gallery-thumb:hover img { border-color: var(--ink); }
.gallery-thumb span { display: block; font-variation-settings: var(--prose); font-size: 11.5px; color: var(--grey); margin-top: 0.4rem; }
/* the highlighted (selected) thumbnail */
#shot-dashboard:checked ~ .gallery-thumbs .gt-dashboard img,
#shot-malware:checked ~ .gallery-thumbs .gt-malware img,
#shot-audit:checked ~ .gallery-thumbs .gt-audit img { border-color: var(--ochre); }
@media (max-width: 560px) { .gallery-thumbs { grid-template-columns: 1fr; } }

/* ============================================================
   pricing: plan-toggle + plans grid + open-source sponsor note
   ============================================================ */
/* cloud / self-hosted segmented toggle above the plan grid */
.plan-toggle {
  display: inline-flex;
  border: 1px solid var(--ink);
  margin: 1.25rem 0 0.4rem;
}
.plan-toggle-btn {
  font-family: inherit;
  font-variation-settings: var(--mono);
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink);
  background: var(--paper);
  border: none;
  padding: 0.35rem 1rem;
  min-width: 8.5rem;        /* equal-width segments regardless of label length */
  text-align: center;
  cursor: pointer;
}
.plan-toggle-btn + .plan-toggle-btn { border-left: 1px solid var(--ink); }
.plan-toggle-btn:hover { background: var(--surface); }
.plan-toggle-btn.on, .plan-toggle-btn.on:hover { background: var(--ink); color: var(--paper); }
.plan-toggle-note { margin: 0 0 0.5rem; font-size: 12px; }
/* author display:grid on .plans beats the UA [hidden] rule, so hide explicitly */
.plan-group[hidden] { display: none; }
/* open-source sponsorship callout on the pricing page */
.sponsor-note { border: 1px solid var(--ink); border-left: 3px solid var(--ink); padding: 0.9rem 1.1rem; margin: 1.75rem 0; background: var(--surface); }
.sponsor-note h2 { font-size: 15px; margin: 0 0 0.3rem; border: none; }
.sponsor-note p { margin: 0; color: var(--grey); font-variation-settings: var(--prose); font-size: 13px; }

.plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
  margin: 0.5rem 0 1.75rem;
  align-items: stretch;
}
.plan {
  border: 1px solid var(--ink);
  background: var(--paper);
  padding: 1rem 1rem 1.1rem;
  display: flex;
  flex-direction: column;
}
.plan-featured {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
.plan-head h2 {
  font-size: 0.95rem;
  font-weight: 700;
  text-transform: lowercase;
  letter-spacing: 0.04em;
  margin: 0;
}
.plan-price { display: flex; align-items: baseline; gap: 0.3rem; margin: 0.55rem 0 0.4rem; }
.plan-amt { font-size: 1.9rem; font-weight: 800; line-height: 1; }
.plan-unit {
  font-variation-settings: var(--mono);
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--grey);
}
.plan-tag { font-size: 12.5px; color: var(--grey); margin: 0 0 0.7rem; min-height: 2.4em; }
.plan-feats {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  font-size: 12.5px;
  flex: 1;
  border-top: 1px solid var(--hair);
}
.plan-feats li { padding: 0.32rem 0 0.32rem 1.1rem; position: relative; border-bottom: 1px solid var(--hair); }
.plan-feats li::before { content: "+"; position: absolute; left: 0; color: var(--grey); }
.plan-cta {
  display: block;
  text-align: center;
  font-variation-settings: var(--mono);
  font-size: 12px;
  text-transform: lowercase;
  letter-spacing: 0.04em;
  text-decoration: none;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
}
.plan-cta:hover { background: var(--paper); color: var(--ink); }
.plan-cta-alt { background: var(--paper); color: var(--ink); }
.plan-cta-alt:hover { background: var(--ink); color: var(--paper); }

/* ---- contact / lead form (bottom of pricing) ---- */
.contact-wrap { margin-top: 2.25rem; border-top: 3px double var(--ink); padding-top: 1.25rem; }
.contact-wrap h2 { font-size: 1rem; font-weight: 700; text-transform: lowercase; margin: 0 0 0.3rem; }
.req { color: var(--ink); font-weight: 700; }
.contact {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.9rem 1rem;
  max-width: 640px;
  margin-top: 1rem;
}
.field { display: flex; flex-direction: column; gap: 0.25rem; }
.field-wide { grid-column: 1 / -1; }
.field-label {
  font-variation-settings: var(--mono);
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--grey);
}
.contact input, .contact select, .contact textarea {
  font-family: inherit;
  font-size: 13px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 0.4rem 0.5rem;
}
.contact textarea { resize: vertical; }
.contact input:focus, .contact select:focus, .contact textarea:focus {
  outline: 2px solid var(--ink); outline-offset: -2px;
}
.field-err { font-size: 11.5px; color: var(--ink); font-weight: 700; }
.field-err::before { content: "▲ "; }
.contact-err-top {
  grid-column: 1 / -1;
  font-size: 12.5px; font-weight: 700;
  border: 1px solid var(--ink); padding: 0.4rem 0.6rem;
}
.contact-submit {
  font-family: inherit;
  font-variation-settings: var(--mono);
  font-size: 12px; text-transform: lowercase; letter-spacing: 0.04em;
  color: var(--paper); background: var(--ink);
  border: 1px solid var(--ink);
  padding: 0.5rem 1.1rem; cursor: pointer;
}
.contact-submit:hover { background: var(--paper); color: var(--ink); }
.htmx-request .contact-submit { opacity: 0.5; }
.contact-ok {
  border: 1px solid var(--ink);
  border-left: 3px solid var(--ink);
  padding: 0.7rem 0.9rem;
  font-size: 13px;
  max-width: 640px;
  margin-top: 1rem;
}

/* ============================================================
   pricing: metered model — guarantee, included band, tier cards,
   rate card, and the bill calculator (the signature instrument)
   ============================================================ */
/* The load-bearing claim. Stated plainly, no exclamation. */
.guarantee {
  margin: 1.5rem 0 0.5rem;
  border: 1px solid var(--ink);
  border-left: 3px solid var(--ink);
  background: var(--surface);
  padding: 0.9rem 1.1rem;
}
.guarantee-head { margin: 0; font-size: clamp(1rem, 2.4vw, 1.3rem); font-weight: 800; letter-spacing: -0.01em; }
.guarantee-sub { margin: 0.35rem 0 0; font-size: 13px; color: var(--grey); font-variation-settings: var(--prose); }

/* The annual saving lives inside the annual segment as a faint suffix
   ("annual −15%"), so it can't orphan beside the control. currentColor +
   opacity keeps it legible whether the segment is active (paper on ink) or
   not (ink on paper). */
/* Slanted via the Recursive "slnt" axis rather than font-style:italic, since
   the button pins font-variation-settings (var(--mono)) which would otherwise
   win and keep it upright. */
.toggle-sub { margin-left: 0.2rem; font-size: 10px; letter-spacing: 0; opacity: 0.6; font-variation-settings: "MONO" 1, "CASL" 0, "slnt" -14, "CRSV" 0; }

/* "everything, every tier" band — differentiation is rates + SLA, not
   feature withholding, so the included-everywhere list reads as one block. */
.included-band { border: 1px solid var(--ink); background: var(--surface); padding: 0.9rem 1.1rem; margin: 1rem 0 1.25rem; }
.included-band h2 { font-size: 13px; text-transform: lowercase; letter-spacing: 0.04em; margin: 0 0 0.5rem; font-weight: 700; border: none; }
.included-list {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0.25rem 1.25rem; font-size: 12.5px;
}
.included-list li { padding: 0.25rem 0 0.25rem 1.2rem; position: relative; color: var(--grey); font-variation-settings: var(--prose); }
.included-list li::before { content: "✓"; position: absolute; left: 0; color: var(--ink); }
.included-list strong { color: var(--ink); font-weight: 700; }

/* metered tier cards build on the shared .plan card; .tier-meta is the
   quiet, label/value detail list that replaces the bulleted feature list. */
.tiers { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.tier-custom { background: var(--surface); }
.tier-meta { margin: 0 0 1rem; padding: 0; border-top: 1px solid var(--hair); flex: 1; }
.tier-meta > div { padding: 0.45rem 0; border-bottom: 1px solid var(--hair); }
.tier-meta dt { font-variation-settings: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--faint); margin: 0 0 0.1rem; }
.tier-meta dd { margin: 0; font-size: 12px; color: var(--ink); font-variation-settings: var(--prose); line-height: 1.4; }

/* rate card: tabular numerals, aligned decimals, units always shown. */
.rate-card { border: 1px solid var(--ink); padding: 1rem 1.1rem 1.15rem; margin: 0 0 1.75rem; }
.rate-card > h2 { font-size: 15px; margin: 0 0 0.3rem; border: none; font-weight: 700; text-transform: lowercase; letter-spacing: 0.04em; }
.rate-card > p.muted { margin: 0 0 0.8rem; font-size: 12.5px; }
.rate-scroll { overflow-x: auto; }
.rates { width: 100%; border-collapse: collapse; font-size: 13px; }
.rates th, .rates td { text-align: right; padding: 0.45rem 0.7rem; border-bottom: 1px solid var(--hair); white-space: nowrap; }
.rates thead th { font-variation-settings: var(--mono); font-size: 11px; text-transform: lowercase; letter-spacing: 0.05em; color: var(--ink); border-bottom: 1px solid var(--ink); }
.rates th[scope="row"], .rates .rate-rowhead { text-align: left; font-variation-settings: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--faint); font-weight: 400; }
.rates td { font-variant-numeric: tabular-nums; color: var(--ink); }
.rate-unit { color: var(--faint); font-size: 10px; font-variation-settings: var(--mono); text-transform: none; letter-spacing: 0; }
.rate-low { font-variation-settings: var(--prose); color: var(--grey); font-size: 12px; }
.rates .rate-featured { background: var(--surface); }
.rate-foot { margin: 0.8rem 0 0; font-size: 12px; }

/* calculator: the instrument. Precise, immediate, legible. */
.calc { border: 1px solid var(--ink); border-top: 3px solid var(--ink); padding: 1.1rem 1.2rem 1.3rem; margin: 0 0 1.75rem; background: var(--paper); }
.calc-head h2 { font-size: 1rem; margin: 0 0 0.2rem; border: none; font-weight: 800; text-transform: lowercase; letter-spacing: 0.02em; }
.calc-head p { margin: 0 0 1rem; font-size: 12.5px; }
.calc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; align-items: start; }
.calc-controls { display: flex; flex-direction: column; gap: 1.1rem; }
.calc-field { display: flex; flex-direction: column; gap: 0.4rem; }
.calc-label { font-variation-settings: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--grey); display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
.calc-out { font-variation-settings: var(--mono); font-size: 14px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: 0; }
/* one metric, two ways in: the log slider and an exact-GiB box (its native
   arrows step by a fixed amount). They share a row and stay in sync
   (pricing-calc.js); on a narrow column the number box wraps below the slider
   rather than crushing it. */
.calc-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.5rem; }
.calc-row input[type="range"] { flex: 1 1 6rem; min-width: 0; accent-color: var(--ink); height: 1.6rem; cursor: pointer; }
/* exact entry: narrow, right-aligned, tabular — reads like the readout it is */
.calc-num {
  flex: 0 0 auto; width: 4.75rem; padding: 0.3rem 0.4rem;
  border: 1px solid var(--hair); background: var(--paper); color: var(--ink);
  font-family: inherit; font-size: 13px; font-variation-settings: var(--mono);
  font-variant-numeric: tabular-nums; text-align: right;
}
.calc-num:focus { outline: none; border-color: var(--ink); }
.calc-num:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.calc-adv { display: flex; align-items: center; gap: 0.45rem; font-size: 12px; color: var(--grey); cursor: pointer; }
.calc-adv input { accent-color: var(--ink); }
.calc-results { display: flex; flex-direction: column; gap: 0.6rem; }
.calc-tier { border: 1px solid var(--hair); padding: 0.6rem 0.8rem; }
.calc-tier-head { display: flex; align-items: baseline; gap: 0.5rem; }
.calc-tier-name { font-weight: 700; text-transform: lowercase; letter-spacing: 0.03em; font-size: 13px; }
.calc-tier-amt { font-size: 1.5rem; font-weight: 800; line-height: 1.1; margin: 0.2rem 0 0.1rem; font-variant-numeric: tabular-nums; }
.calc-tier-break { margin: 0; font-size: 11.5px; color: var(--grey); font-variation-settings: var(--prose); }
/* The differentiator line — what the tier gives you (SLA + support). Set off
   from the cost breakdown by a dotted rule so value reads distinct from price. */
.calc-tier-perk { margin: 0.35rem 0 0; padding-top: 0.35rem; border-top: 1px dotted var(--hair); font-size: 11.5px; color: var(--ink); font-variation-settings: var(--prose); }
.calc-tier-burst { margin: 0.3rem 0 0; font-size: 11.5px; color: var(--faint); font-variation-settings: var(--mono); }
.calc-guarantee { margin: 0.3rem 0 0; font-size: 12px; font-weight: 700; border-top: 1px solid var(--hair); padding-top: 0.6rem; }
.calc-ent { border: 1px solid var(--ink); background: var(--surface); padding: 0.9rem 1rem; }
.calc-ent-head { margin: 0 0 0.3rem; font-weight: 800; font-size: 1rem; }
.calc-ent-sub { margin: 0 0 0.8rem; font-size: 12.5px; color: var(--grey); font-variation-settings: var(--prose); }
.calc-ent-cta { display: inline-block; }
@media (max-width: 640px) {
  .calc-grid { grid-template-columns: 1fr; gap: 1.1rem; }
}

/* ============================================================
   news / posts (+ latest-news segment on the home page)
   ============================================================ */
.write-link { font-variation-settings: var(--mono); font-size: 12.5px; color: var(--ink); text-decoration: underline; }
.write-link:hover { text-decoration-thickness: 2px; }
/* post-meta lives next to the title link on each post-list row; its
   text is faint by design (date + author), but the inline edit/delete
   actions are <a> tags that without explicit colour fall through to
   browser defaults (blue). Match the faint of the surrounding line
   plus underline so they read as actions but stay subordinate to the
   title. */
.post-meta a { color: var(--faint); text-decoration: underline; }
.post-meta a:hover { color: var(--ink); }
.post-list { list-style: none; padding: 0; margin: 0.5rem 0; }
.post-list li { padding: 0.45rem 0; border-bottom: 1px solid var(--hair); }
/* No trailing rule under the final row — a dangling hairline below the
   last post reads as an unfinished table. The list is always the end of
   its block or sits above a "see all" link, so the last divider is just
   noise. */
.post-list li:last-child { border-bottom: none; }
/* Title link colour follows the brand's ink token like every other
   in-content link; the browser default (blue / underline) leaks
   through if we only set font-weight. Matches .post-body a so
   navigating from "news index" to "open post" doesn't visually
   change register. */
.post-list a { font-weight: 600; color: var(--ink); text-decoration: underline; }
.post-list a:hover { text-decoration-thickness: 2px; }
.post-meta { font-variation-settings: var(--mono); font-size: 11px; color: var(--faint); }
.post-list .post-meta { margin-left: 0.5rem; }
.draft-badge { border: 1px solid var(--ink); padding: 0 4px; font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; }

.post .post-meta { display: block; margin: 0 0 1.25rem; }
.post-body { font-variation-settings: var(--prose); max-width: 64ch; line-height: 1.6; }
.post-body h2, .post-body h3 { font-variation-settings: var(--mono); font-weight: 700; margin: 1.5rem 0 0.4rem; }
.post-body p { margin: 0 0 1rem; }
.post-body pre { background: var(--surface); border: 1px solid var(--hair); padding: 0.6rem; overflow-x: auto; font-size: 12.5px; }
.post-body code { font-size: 0.9em; background: var(--surface-2); padding: 0 3px; }
.post-body pre code { background: none; padding: 0; }
.post-body blockquote {
  border-left: 3px solid var(--hair); background: var(--surface);
  margin: 1rem 0; padding: 0.4rem 0.8rem; color: var(--grey);
}
.post-body blockquote code { background: var(--surface-2); }
.post-body a { color: var(--ink); text-decoration: underline; }

/* ---- pic / goat inline figures in prose: theme-aware colour ----
   Both renderers emit <svg> blocks inline via the goldmark pipeline.
   Pic correctly sets fill="currentColor" on every <text> it emits;
   goat does NOT (it relies on the surrounding element's `color`).
   SVG <text>'s default fill is **black** — meaning in dark mode every
   label inside a goat diagram renders as black against the warm-near-
   black paper and disappears. Force fill:currentColor so labels follow
   the theme's --ink token in either palette.

   The rule lives on the figure (not the article body) so it applies
   anywhere a goat / pic figure shows up: news posts, /docs, news
   previews, future surfaces. Pic already sets fill on every text but
   the rule is a cheap backstop. */
figure.goat svg text,
figure.pic svg text { fill: currentColor; }

/* Inline figures stretch to the prose column with a comfortable gap
   before and after. Default browser <figure> margin is `1em 40px`
   which leaves a wide gutter that looks wrong inside a 64ch column. */
.post-body figure.pic,
.post-body figure.goat {
  margin: 1rem 0;
  text-align: center;
  color: var(--ink);
}
.post-body figure.pic svg,
.post-body figure.goat svg {
  max-width: 100%;
  height: auto;
}

/* ---- pic-spotlight: a pic figure that becomes a backsplash for the
   following markdown block. Fence info is `pic-spotlight`; the renderer
   adds the .pic-spotlight class to the figure (see goat.go). The next
   sibling element gets pulled up with z-index so it overlays.

   The pull-up is driven by --spotlight-pull (default 6rem).

   Width matches the post-body column exactly: no max-width cap, no
   auto-centering. A capped figure under a full-width heading would
   leave the heading hanging past the picture's left edge — a visible
   misalignment. Locking figure width to the post-body keeps the
   heading and the backdrop sharing the same left/right rails. */
.post-body figure.pic-spotlight {
  margin: 0.75rem 0 calc(-1 * var(--spotlight-pull, 6rem));
  width: 100%;
  position: relative;
  z-index: 0;
  opacity: 0.30;
  pointer-events: none;
}
.post-body figure.pic-spotlight svg {
  width: 100%;
  height: auto;
  display: block;
}
.post-body figure.pic-spotlight + * {
  position: relative;
  z-index: 1;
}
:root[data-theme="dark"] .post-body figure.pic-spotlight { opacity: 0.42; }

.publish-form { margin: 0 0 1.25rem; }
.publish-form button, .post-form button {
  font-family: inherit; font-variation-settings: var(--mono); font-size: 12px;
  color: var(--paper); background: var(--ink); border: 1px solid var(--ink);
  padding: 0.3rem 0.9rem; cursor: pointer;
}
/* template strip + save form on /news/new. Chips link to
   /news/new?template=ID; each chip has a tiny × to delete. The
   save form below the editor stays disclosed to avoid noise. */
.template-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 0.5rem 0 1rem;
  font-size: 12px;
}
.template-strip-label {
  font-variation-settings: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.template-chip {
  display: inline-flex;
  align-items: center;
  gap: 0;
  border: 1px solid var(--hair);
  background: var(--paper);
}
.template-chip a {
  font-variation-settings: var(--mono);
  font-size: 11.5px;
  color: var(--ink);
  text-decoration: none;
  padding: 0.2rem 0.5rem;
  border-right: 1px solid var(--hair);
}
.template-chip a:hover { background: var(--surface); }
.template-chip-x {
  font-family: inherit;
  background: var(--paper);
  border: none;
  color: var(--grey);
  cursor: pointer;
  padding: 0.1rem 0.45rem;
  font-size: 14px;
  line-height: 1;
}
.template-chip-x:hover { color: var(--ink); }
.template-save { margin-top: 1.25rem; font-size: 12px; }
.template-save summary {
  cursor: pointer;
  font-variation-settings: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--grey);
}
.template-save summary:hover { color: var(--ink); }
.template-save-form { display: flex; gap: 0.5rem; margin-top: 0.5rem; }
.template-save-form input {
  flex: 1 1 18rem;
  max-width: 26rem;
  font-family: inherit;
  font-variation-settings: var(--mono);
  font-size: 12px;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--hair);
  background: var(--paper);
  color: var(--ink);
}
.template-save-form input:focus { outline: none; border-color: var(--ink); }
.template-save-form input:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.template-save-form button {
  font-family: inherit;
  font-variation-settings: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border: 1px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  padding: 0.3rem 0.7rem;
  cursor: pointer;
}
.template-save-form button:hover { background: var(--ink); color: var(--paper); }
.template-manage-link {
  margin-left: auto;
  font-variation-settings: var(--mono);
  font-size: 11px;
  text-transform: lowercase;
  letter-spacing: 0.06em;
  color: var(--grey);
  text-decoration: none;
}
.template-manage-link:hover { color: var(--ink); }

/* /news/templates manage page — one card per saved template, with
   inline rename + body edit. Cards stack vertically; each is its own
   <article> so htmx can swap one card in place after an edit. */
.template-cards {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  margin-top: 1.25rem;
}
.template-card {
  border: 1px solid var(--hair);
  background: var(--paper);
  padding: 1rem 1.1rem;
}
.template-card-header {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin: 0 0 0.6rem;
}
.template-card-header h2 {
  font-size: 16px;
  font-variation-settings: var(--mono);
  margin: 0;
  flex: 0 0 auto;
}
.template-card-header h2 a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px dotted var(--hair);
}
.template-card-header h2 a:hover { border-bottom-color: var(--ink); }
.template-card-meta { font-size: 11px; }
.template-card-edit { display: flex; flex-direction: column; gap: 0.6rem; }
.template-card-edit label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-variation-settings: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--grey);
}
.template-card-edit input,
.template-card-edit textarea {
  font-family: inherit;
  font-variation-settings: var(--mono);
  font-size: 12.5px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hair);
  border-left: 3px solid var(--ink);
  padding: 0.4rem 0.55rem;
}
.template-card-edit textarea { resize: vertical; line-height: 1.5; }
.template-card-edit input:focus,
.template-card-edit textarea:focus { outline: none; border-color: var(--ink); }
.template-card-edit textarea:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.template-card-actions { display: flex; gap: 0.5rem; }
.template-card-actions button {
  font-family: inherit;
  font-variation-settings: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border: 1px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  padding: 0.35rem 0.85rem;
  cursor: pointer;
}
.template-card-actions button:hover { background: var(--ink); color: var(--paper); }
.template-card-delete { border-color: var(--hair); color: var(--grey); }
.template-card-delete:hover { background: var(--grey); color: var(--paper); border-color: var(--grey); }

.post-form { display: flex; flex-direction: column; gap: 1rem; max-width: 64ch; margin-top: 1rem; }
.post-form label { display: flex; flex-direction: column; gap: 0.3rem; font-variation-settings: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--grey); }
.post-form input, .post-form select, .post-form textarea {
  font-family: inherit; font-variation-settings: var(--mono); font-size: 13px;
  color: var(--ink); background: var(--paper); border: 1px solid var(--ink); padding: 0.4rem 0.5rem;
}
.post-form textarea { resize: vertical; line-height: 1.5; }
.form-actions { display: flex; align-items: center; gap: 1rem; }

/* compose: editor on the left, live (htmx-morphed) markdown preview on the right */
.compose { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1.75rem; align-items: start; }
.compose .post-form { max-width: none; margin-top: 0; }
.post-preview { position: sticky; top: 1rem; border: 1px solid var(--hair); background: var(--surface); padding: 0.5rem 1rem 1rem; min-height: 8rem; }
.post-preview > h2 { font-variation-settings: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; margin: 0.4rem 0 0.6rem; }
.post-preview .post-body:empty::before { content: "nothing to preview yet"; color: var(--grey); font-style: italic; }
@media (max-width: 820px) { .compose { grid-template-columns: 1fr; } .post-preview { position: static; } }

/* draft controls on a post page: edit + publish side by side */
.draft-controls { display: flex; align-items: center; gap: 1rem; margin: 0 0 1.25rem; }
.draft-controls .publish-form { margin: 0; }

/* latest-news segment: snail-shell rule + two connecting lines */
.latest-news { margin: 1.5rem 0 0.75rem; }
.news-rule { display: flex; align-items: center; gap: 0.45rem; margin-bottom: 0.25rem; }
.news-rule .shell { height: 24px; width: auto; flex: none; }
/* the two lines run continuously from the shell to the right edge; the label
   floats in the gap between them, so neither line is broken. */
.news-rule .rule { position: relative; flex: 1; height: 17px; }
.news-rule .rule::before,
.news-rule .rule::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px solid var(--ink);
}
.news-rule .rule::before { top: 0; }
.news-rule .rule::after  { bottom: 0; }
.news-rule .label {
  position: absolute;
  left: 0.4rem;
  top: 50%;
  transform: translateY(-50%);
  background: var(--paper);
  padding: 0 0.4rem;
  font-variation-settings: var(--mono);
  font-size: 10px;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--grey);
}
.latest-news .post-list { margin: 0.25rem 0; }
.latest-news .post-list li { padding: 0.3rem 0; }
.latest-news .hint { margin-top: 0.5rem; }

/* news lists: avatar adjacent to each item */
.post-list li { display: flex; align-items: center; gap: 0.55rem; }
.post-list li a { flex: none; }
.post-byline { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 1.25rem; }
.post-byline .post-meta { margin: 0; }

/* ============================================================
   admin console
   ============================================================ */
.admin-nav { list-style: none; padding: 0; margin: 1.1rem 0; }
.admin-nav li { padding: 0.45rem 0; border-bottom: 1px solid var(--hair); }
.admin-nav a { font-weight: 600; }

/* ---- splash-pic: the generative golden spiral behind the title ----
   Replaces the old splash.svg backdrop entirely. Fills the whole splash
   section so the mark IS the marketing surface; contain-fit keeps the
   aspect ratio rather than stretching it across a 3:1 strip. */
.splash-pic {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0.16;
  color: var(--ink);
  pointer-events: none;
}
:root[data-theme="dark"] .splash-pic { opacity: 0.24; }
.splash-pic svg {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  display: block;
}

/* ---- pic playground (/docs/pic/playground) ----
   Two-column live editor: textarea on the left, htmx-driven SVG output
   on the right. Stacks under 720px so the textarea stays editable on a
   phone. The output figure is a fixed-aspect viewport so the page
   doesn't jump around as the user types. */
.pic-playground {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin: 1.5rem 0 1rem;
}
.pic-playground-src {
  width: 100%;
  font-family: inherit;
  font-variation-settings: var(--mono);
  font-size: 12px;
  line-height: 1.55;
  padding: 0.7rem 0.85rem;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--hair);
  border-left: 3px solid var(--ink);
  resize: vertical;
}
.pic-playground-src:focus {
  outline: none;
  border-color: var(--ink);
}
.pic-playground-src:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.pic-playground-output {
  margin: 0;
  background: var(--paper);
  border: 1px solid var(--hair);
  padding: 0.9rem 1rem;
  min-height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.pic-playground-output svg {
  max-width: 100%;
  max-height: 100%;
  height: auto;
  display: block;
}
.pic-playground-presets-label {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  margin: 0.4rem 0 0.5rem;
}
.pic-playground-presets {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
  margin: 0 0 0.75rem;
}
.pic-playground-preset {
  font-family: inherit;
  font-variation-settings: var(--mono);
  font-size: 11px;
  text-decoration: none;
  text-transform: lowercase;
  letter-spacing: 0.06em;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--hair);
  padding: 0.3rem 0.65rem;
}
.pic-playground-preset:hover {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.pic-playground-preset.on {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
@media (max-width: 720px) {
  .pic-playground { grid-template-columns: 1fr; }
}

/* detail-map: a fixed table of contents in the left gutter of the package
   detail sheet, so a long page's sections are one click away. Folds away when
   the viewport is too narrow to fit it beside the centered 880px sheet. */
.detail-map {
  position: fixed;
  top: 5.5rem;
  left: calc((100vw - 880px) / 2 - 9.25rem);
  width: 8rem;
  font-variation-settings: var(--mono);
  font-size: 11.5px;
  line-height: 1.55;
  z-index: 5;
}
.detail-map ul { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--hair); }
.detail-map li { margin: 0; }
.detail-map a {
  display: block; padding: 0.12rem 0 0.12rem 0.7rem; margin-left: -1px;
  color: var(--grey); text-decoration: none;
  border-left: 2px solid transparent;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.detail-map a:hover { color: var(--ink); border-left-color: var(--ink); }
.detail-map .map-flag { color: var(--ochre); font-weight: 700; }
.detail-map .map-count { color: var(--grey); font-variant-numeric: tabular-nums; }
@media (max-width: 1200px) { .detail-map { display: none; } }
/* a jumped-to section heading clears the top edge (package + docs pages) */
h1[id], h2[id], h3[id] { scroll-margin-top: 1.25rem; }

/* Community comment threads (org manage federation): the package is the "story",
   researcher replies thread under it (HN-style), in the page's own palette. */
.cthreads { margin-top: .5rem; }
.cthread { padding: .85rem 0; }
.cthread + .cthread { border-top: 1px solid var(--hair); }
.cthread .chead { margin: 0 0 .5rem; font-weight: 600; font-size: 1rem; }
.cthread .chead .count { margin-left: .5rem; color: var(--faint); font-weight: 400; font-size: .85em; }
.clist { list-style: none; margin: 0; padding: 0 0 0 .9rem; border-left: 2px solid var(--hair); }
.citem { padding: .5rem 0; }
.citem + .citem { border-top: 1px solid var(--hair); }
/* nested replies carry their own connector line at their indent, so the
   conversation structure (who replied to whom) reads at a glance even several
   levels deep with multiple participants. */
.citem.cnest { border-left: 2px solid var(--hair); padding-left: .75rem; }
/* the public package thread is the whole conversation — no outer spine, the
   purl heading above is the root. */
.cthread-public { padding-left: 0; border-left: none; }
.cmeta { color: var(--faint); font-size: .82em; margin-bottom: .15rem; }
.cavatar { width: 20px; height: 20px; border-radius: 5px; vertical-align: -5px; margin-right: .35rem; background: var(--surface); }
.cbody { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.5; } /* body is the focus, meta is muted above */
/* Comment actions: a tight inline row of small, unobtrusive buttons — not the
   full-width default of button.more. The edit disclosure summary is styled to
   match the buttons, so edit/hide/delete read as one consistent set. */
.cactions { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; margin-top: .35rem; }
.cactions .inline-form { display: inline-flex; margin: 0; }
.cactions button.more, .cactions summary.more { width: auto; font-size: 11px; padding: .1rem .5rem; line-height: 1.45; }
.cactions summary.more {
  font-family: inherit; font-variation-settings: var(--mono);
  color: var(--ink); background: var(--paper); border: 1px solid var(--ink);
  cursor: pointer; list-style: none; display: inline-block;
}
.cactions summary.more::-webkit-details-marker { display: none; }
.cactions summary.more:hover { background: var(--ink); color: var(--paper); }
.cactions .cedit { display: inline-block; }
.cactions .cedit[open] { flex-basis: 100%; margin-top: .3rem; } /* editor drops to its own row */
.cstatus-pending { color: var(--ochre); }
.cstatus-approved { color: var(--sage); }
.citem.cmine { border-left: 2px solid var(--sage); margin-left: -.9rem; padding-left: .75rem; }
.cyou { color: var(--sage); font-weight: 600; }
.creply { margin-top: .4rem; }
.creply textarea { display: block; width: 100%; max-width: 42rem; resize: vertical; font: inherit; }
.creply button { margin-top: .3rem; }
.cdm-toggle { display: block; margin: .3rem 0; color: var(--faint); font-size: .85em; }
.cdm { color: var(--lavender); font-weight: 600; }

/* Org branding icons. */
.org-icon-sm { width: 22px; height: 22px; border-radius: 5px; vertical-align: -5px; margin-right: .4rem; }
.org-icon-edit { display: flex; align-items: center; gap: .6rem 1rem; flex-wrap: wrap; margin: .6rem 0 1rem; }
.org-icon-edit form { display: inline-flex; align-items: center; gap: .5rem; margin: 0; }
.org-icon-edit button { width: auto; flex: none; }
.org-icon-edit input[type=file] { max-width: 16rem; }
.org-icon { width: 64px; height: 64px; border-radius: 12px; border: 1px solid var(--hair); flex: none; }

/* Header notification bell + unread badge. The bell is a pic glyph ({{bellicon}})
   drawn in currentColor, so its color follows .tag-bell (grey, ink on
   hover/unread); only size it here, never pin its color. */
.tag-bell { position: relative; display: inline-flex; align-items: center; color: var(--grey); margin-right: .35rem; }
.tag-bell svg { width: 18px; height: 18px; display: block; }
.tag-bell:hover, .tag-bell.has-unread { color: var(--ink); }
.tag-bell-badge {
  position: absolute; top: -.35rem; right: -.45rem; min-width: 1.05rem; height: 1.05rem;
  padding: 0 .25rem; border-radius: .6rem; background: var(--ochre); color: var(--ink-on-accent);
  font-size: .65rem; font-weight: 700; line-height: 1.05rem; text-align: center;
}

/* Notifications feed. */
.notif-list { list-style: none; margin: .5rem 0 0; padding: 0; }
.notif { display: flex; gap: .75rem; padding: .7rem 0; border-top: 1px solid var(--hair); }
.notif:first-child { border-top: none; }
.notif-unread { border-left: 2px solid var(--ochre); margin-left: -.75rem; padding-left: .75rem; }
.notif-kind {
  flex: none; align-self: start; margin-top: .15rem; padding: .05rem .4rem; border-radius: .35rem;
  background: var(--surface); color: var(--faint); font-size: .7rem; text-transform: lowercase;
}
.notif-avatar { flex: none; align-self: start; margin-top: .15rem; width: 22px; height: 22px; border-radius: 5px; background: var(--surface); object-fit: cover; }
.notif-dismiss { margin-left: auto; align-self: start; }
.notif-title { font-weight: 600; }
.notif-body { color: var(--grey); margin-top: .1rem; overflow-wrap: anywhere; }
.notif-when { font-size: .8em; margin-top: .15rem; }
