/* One stylesheet for every page — the authored ones and the ones render_docs.py produces from the
   repository's markdown. They share a nav, so they must share a nav's styling; a second stylesheet
   would drift on the first change that touched only one of them.

   Dark by default because the tool is a terminal application and the site is usually opened from a
   terminal. The light override follows the reader's system setting rather than a toggle: a toggle
   needs JavaScript and state, and this site is static files that must work opened from disk. */

:root {
  --bg: #080a0c;
  --bg-raised: #141820;
  --bg-code: #05070a;
  --fg: #a9b6c2;
  --fg-dim: #6d7d8b;
  --fg-bright: #e8edf2;
  /* cxagent's own prompt renders green, so the accent comes from the product rather than being
     chosen. Same structure as the SharpConsoleUI site, its own signal. */
  --accent: #3ddc84;
  --accent-dim: #2a9b5d;
  --accent-bg: rgba(61, 220, 132, 0.08);
  --accent-glow: rgba(61, 220, 132, 0.22);
  --border: #22303a;
  --border-dim: #161f27;
  --warn: #ffbd2e;
  --ok: #3ddc84;
  --red: #ff5f57;
  --dot-green: #28c840;
  --radius: 10px;
  --radius-sm: 6px;

  --font-prose: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: "Fragment Mono", ui-monospace, "SF Mono", "JetBrains Mono", Consolas,
               "DejaVu Sans Mono", monospace;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #ffffff;
    --bg-raised: #f6f7f9;
    --bg-code: #f2f3f6;
    --fg: #24282f;
    --fg-dim: #5d636e;
    --fg-bright: #0d1015;
    --accent: #1a5fb4;
    --accent-dim: #7a9dcc;
    --border: #dde0e6;
    --warn: #8a6100;
    --ok: #1f7a4d;
  }
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

/* SCROLL-PADDING, NOT JUST SMOOTH SCROLLING. The nav is sticky, so an anchor target lands
   underneath it without this and the reader sees the wrong heading at the top of the page. */
html { scroll-padding-top: 4.5rem; }

/* EVERY ANIMATION HERE IS OPTIONAL. Motion is decoration on a documentation site, and for a reader
   who has asked their system to stop moving things it is worse than decoration. */
@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 {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-prose);
  font-size: 17px;
  line-height: 1.65;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* --- Navigation ------------------------------------------------------------------------------ */

.site-nav {
  /* CENTRED, NOT BASELINE. An inline-flex brand containing an image takes its baseline from the
     image's box rather than from the wordmark's text, so `baseline` sat the brand nine pixels above
     the links beside it. Centring aligns what a reader actually compares: the middles. */
  align-items: center;
  position: sticky;
  top: 0;
  z-index: 20;
  transition: box-shadow 0.2s ease, background 0.2s ease;
  display: flex;
  flex-wrap: wrap;
  gap: 1.4rem;
  padding: 0.9rem 1.6rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-raised);
  font-size: 0.95rem;
}

/* THE SHADOW APPEARS ONLY ONCE THERE IS SOMETHING UNDERNEATH. At the top of the page the nav sits
   on the background and a shadow would be drawing a line for no reason. */
.site-nav.scrolled {
  box-shadow: 0 6px 24px -8px rgba(0, 0, 0, 0.55);
  border-bottom-color: var(--border);
}

/* WHERE YOU ARE, in a nav whose links otherwise look identical. */
.site-nav a[aria-current="page"] {
  color: var(--accent);
  border-bottom: 2px solid var(--accent);
  padding-bottom: 2px;
}

.site-nav a { color: var(--fg-dim); }
.site-nav a:hover { color: var(--fg-bright); }

.site-nav .brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--fg-bright);
  margin-right: auto;
  text-decoration: none;
}

/* THE MARK CARRIES NO alt TEXT, because the wordmark beside it already says "cxagent" — a screen
   reader announcing the name twice is worse than not announcing the picture. */
.brand-mark { display: block; border-radius: 5px; }

/* The nav wraps onto a second line on a narrow screen; `margin-right: auto` on the brand would
   then push the links to the far edge, so it is dropped once there is no room for two columns. */
@media (max-width: 34rem) {
  .site-nav { gap: 1rem; }
  .site-nav .brand { margin-right: 0; width: 100%; }
}

/* --- Page shells ----------------------------------------------------------------------------- */

/* THE PAGE IS WIDE; THE PROSE INSIDE IT IS NOT. Constraining the whole column to 72ch also
   constrains the things that are not prose — terminal captures, wide tables, the catalog — and
   those become unreadable long before a paragraph does. So every page gets the same shell the
   landing page uses, and the measure is applied to paragraphs instead (see .page-head p, .footnote
   p below). A page that is half empty on a laptop reads as an afterthought beside its own
   landing page. */
main {
  max-width: 1180px;
  margin: 0 auto;
  padding: 2.5rem 2rem 5rem;
}

/* Long-form reading, where the eye tracking back matters more than the room: the rendered
   documents are the one place a narrow column is right. Their tables and code blocks scroll
   inside it rather than widening it. */
main.doc { max-width: 82ch; }

footer {
  max-width: 1180px;
  margin: 0 auto;
  padding: 1.5rem 1.5rem 4rem;
  border-top: 1px solid var(--border);
  color: var(--fg-dim);
  font-size: 0.9rem;
}

h1, h2, h3, h4 {
  color: var(--fg-bright);
  line-height: 1.25;
  margin: 2.4rem 0 0.8rem;
}

h1 { font-size: 2.1rem; margin-top: 0.5rem; }
h2 { font-size: 1.45rem; padding-top: 0.6rem; border-top: 1px solid var(--border); }
h3 { font-size: 1.15rem; }
h4 { font-size: 1rem; }

h1 + p.lede {
  font-size: 1.15rem;
  color: var(--fg-dim);
  margin-top: 0;
}

blockquote {
  margin: 1.4rem 0;
  padding: 0.6rem 1.2rem;
  border-left: 3px solid var(--accent-dim);
  background: var(--bg-raised);
  color: var(--fg);
}

blockquote p:first-child { margin-top: 0; }
blockquote p:last-child { margin-bottom: 0; }

hr { border: 0; border-top: 1px solid var(--border); margin: 2.5rem 0; }

/* --- Code ------------------------------------------------------------------------------------ */

code, kbd, samp {
  font-family: var(--font-mono);
  font-size: 0.88em;
}

/* Inline code only. A <code> inside a <pre> inherits the block's background instead, or every
   line in a listing gets its own pill.

   `overflow-wrap: anywhere` because an inline run has no scroll container to escape into: a long
   unbreakable path in running prose widens the whole PAGE on a phone, and a document-wide
   horizontal scrollbar is worse than a path broken mid-token. A <pre> keeps `white-space: pre`
   and scrolls instead, which is where commands meant for copying live. */
:not(pre) > code {
  background: var(--bg-code);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.1em 0.35em;
  overflow-wrap: anywhere;
}

/* NO WRAPPING. These are commands to copy: a wrapped one hides where the line actually ends, and
   a reader who selects it gets a newline the shell will run at. Horizontal scroll instead. */
pre {
  background: var(--bg-code);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.9rem 1rem;
  overflow-x: auto;
  white-space: pre;
  line-height: 1.5;
}

pre code { background: none; border: 0; padding: 0; }

/* --- Tables ---------------------------------------------------------------------------------- */

/* The rendered docs are table-heavy — CONFIG.md is largely tables — and a borderless table of
   three-word cells is unreadable. The wrapper scrolls so a wide table never widens the page. */
.table-scroll { overflow-x: auto; margin: 1.2rem 0; }

/* `display: block` with its own scroll, NOT just a wrapper. The rendered pages emit a bare
   <table> with nothing around it, so a table narrow enough to fit but too rigid to shrink still
   pushes the document sideways on a phone. Making the table itself the scroll container means a
   wide one is scrollable wherever it appears, wrapped or not. `width: max-content` with a
   `min-width` keeps it filling the column when it fits and overflowing into its own scroll when
   it does not. */
table {
  display: block;
  overflow-x: auto;
  border-collapse: collapse;
  width: max-content;
  min-width: 100%;
  max-width: 100%;
  font-size: 0.94rem;
}

th, td {
  border: 1px solid var(--border);
  padding: 0.45rem 0.7rem;
  text-align: left;
  vertical-align: top;
}

th { background: var(--bg-raised); color: var(--fg-bright); font-weight: 600; }

/* --- Images ---------------------------------------------------------------------------------- */

img { max-width: 100%; height: auto; display: block; }

figure {
  margin: 2rem 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  background: var(--bg-raised);
}

figure img { border-bottom: 1px solid var(--border); }

figcaption {
  padding: 0.8rem 1rem;
  font-size: 0.92rem;
  color: var(--fg-dim);
}

figcaption strong { color: var(--fg-bright); }

/* --- Landing page ---------------------------------------------------------------------------- */

.hero { padding: 1rem 0 0.5rem; }

.hero h1 {
  font-family: var(--font-mono);
  font-size: 2.6rem;
  letter-spacing: -0.02em;
}

.hero .tagline {
  font-size: 1.25rem;
  color: var(--fg);
  max-width: 58ch;
}

.install-line {
  margin: 1.6rem 0 0.4rem;
}

.note { color: var(--fg-dim); font-size: 0.92rem; }

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
  margin: 1.5rem 0;
  padding: 0;
  list-style: none;
}

.card {
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-raised);
  padding: 1rem 1.1rem;
}

.card h3 { margin: 0 0 0.3rem; font-size: 1.05rem; }
.card p { margin: 0; color: var(--fg-dim); font-size: 0.94rem; }

/* --- Marketplace ----------------------------------------------------------------------------- */

.plugin-card {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-raised);
  padding: 1.2rem 1.3rem;
  margin: 1.5rem 0;
}

.plugin-card h3 { margin: 0; font-size: 1.25rem; }

.plugin-card .plugin-name {
  font-family: var(--font-mono);
  color: var(--fg-dim);
  font-size: 0.9rem;
}

.plugin-card .meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
  margin: 0.8rem 0;
  padding: 0;
  list-style: none;
  font-size: 0.9rem;
  color: var(--fg-dim);
}

.plugin-card .meta strong { color: var(--fg); font-weight: 600; }

.tools { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.6rem 0 0; padding: 0; list-style: none; }

.tool {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.15rem 0.7rem;
  background: var(--bg-code);
}

/* A tool that can stop and ask is the fact a reader is here for, so it is marked rather than
   described in a column they have to look up. */
.tool.gated { border-color: var(--warn); }
.tool .gate-note { color: var(--warn); font-family: var(--font-prose); font-size: 0.8rem; }
.tool .gate-note.never { color: var(--fg-dim); }

.catalog-error {
  border: 1px solid var(--warn);
  border-radius: 6px;
  padding: 1rem 1.2rem;
  background: var(--bg-raised);
}

.catalog-error code { word-break: break-all; }

/* --- Docs index ------------------------------------------------------------------------------ */

.doc-group { margin: 1.6rem 0; }
.doc-group ul { margin: 0.5rem 0 0; padding-left: 1.2rem; }
.doc-group li { margin: 0.35rem 0; }
.doc-group li span { color: var(--fg-dim); }

/* --- Landing page ------------------------------------------------------------------------------
   The landing page follows the same shape as the SharpConsoleUI site: a wide split hero with a live
   terminal window beside the pitch, window chrome as the recurring device, "// SECTION" markers, and
   a sidebar explorer instead of a column of screenshots. The two projects share an author and a
   stack, so they read as a family; the accent is the one thing that differs. */

body.landing { max-width: none; }
.landing main { max-width: 1180px; padding: 0 32px 0; }
.landing section { padding: 56px 0; }

/* nav */
.landing .site-nav {
  position: sticky; top: 0; z-index: 20;
  background: rgba(8, 10, 12, 0.82);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border-dim);
}

/* split hero */
.hero-split { display: flex; align-items: center; gap: 56px; padding: 64px 0 56px; }
.hero-text { flex: 1; min-width: 0; }
.hero-media { flex: 0 0 520px; max-width: 520px; }

.landing h1 {
  font: 700 clamp(2.4rem, 5vw, 3.4rem)/1.07 var(--font-prose);
  letter-spacing: -0.035em; color: var(--fg-bright); margin: 0 0 18px; border: 0; padding: 0;
}
.landing h1 em { font-style: normal; color: var(--accent); }
.hero-text .tagline { font-size: 1.06rem; line-height: 1.6; max-width: 46ch; margin: 0 0 24px; }

.pills { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 22px; }
.pill {
  font-family: var(--font-mono); font-size: 0.72rem; color: var(--fg-dim);
  border: 1px solid var(--border); border-radius: 99px; padding: 4px 11px;
}
.pill b { color: var(--accent); font-weight: 400; }

.btns { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 22px; }
.btn {
  font-family: var(--font-mono); font-size: 0.85rem; padding: 11px 20px;
  border-radius: var(--radius-sm); border: 1px solid var(--border);
  color: var(--fg-bright); text-decoration: none;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.btn-primary { background: var(--accent); color: #04150c; border-color: var(--accent); font-weight: 500; }
.btn-primary:hover { box-shadow: 0 0 0 4px var(--accent-glow); }
.btn-ghost:hover { border-color: var(--accent); background: var(--accent-bg); }

/* window chrome — the recurring device */
.win {
  border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden;
  background: var(--bg-raised);
  box-shadow: 0 28px 70px rgba(0,0,0,0.55), 0 0 0 1px var(--border-dim);
}
.win-bar {
  display: flex; align-items: center; gap: 10px; padding: 11px 15px;
  background: var(--bg-raised); border-bottom: 1px solid var(--border); user-select: none;
}
.tl-dots { display: flex; gap: 7px; }
.tl-dot { width: 12px; height: 12px; border-radius: 50%; }
.tl-dot.r { background: var(--red); }
.tl-dot.y { background: var(--warn); }
.tl-dot.g { background: var(--dot-green); }
.tl-title {
  flex: 1; text-align: center; font-family: var(--font-mono);
  font-size: 0.72rem; color: var(--fg-dim); letter-spacing: 0.04em;
}
.win > img { display: block; width: 100%; height: auto; }

/* section markers */
.section-label {
  display: block;
  font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.12em;
  color: var(--fg-dim); text-transform: uppercase; margin-bottom: 14px;
}
/* The label names the page, so the heading follows immediately rather than carrying the browser's
   default top margin, which would leave the two floating apart. */
.section-label + h1 { margin-top: 0; }
.section-label span { color: var(--accent); margin-right: 8px; }
.landing h2 {
  font: 700 1.9rem/1.2 var(--font-prose); letter-spacing: -0.025em;
  color: var(--fg-bright); margin: 0 0 10px; border: 0; padding: 0;
}
.section-sub { max-width: 62ch; margin: 0 0 26px; }

/* the session explorer */
.explorer { display: grid; grid-template-columns: 250px 1fr; }
.exp-nav { background: var(--bg-raised); border-right: 1px solid var(--border); padding: 8px 0; }
.exp-item {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  background: none; border: 0; border-left: 2px solid transparent;
  padding: 11px 16px; cursor: pointer; color: var(--fg);
  font: 400 0.9rem var(--font-prose);
}
.exp-item:hover { background: var(--accent-bg); }
.exp-item[aria-selected="true"] {
  background: var(--accent-bg); border-left-color: var(--accent); color: var(--accent);
}
.exp-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.exp-icon { font-size: 1.05rem; opacity: 0.9; flex-shrink: 0; }
.exp-body { display: flex; flex-direction: column; min-width: 0; }
.exp-shot { background: var(--bg-code); border-bottom: 1px solid var(--border); }
.exp-shot img { display: block; width: 100%; height: auto; }
.exp-text { padding: 20px 24px; }
.exp-text h3 { font: 500 1.02rem var(--font-prose); color: var(--fg-bright); margin: 0 0 7px; }
.exp-text p { margin: 0; font-size: 0.94rem; line-height: 1.62; max-width: 74ch; }

/* numbered differentiators — order is real here, they are not decoration */
/* THREE ACROSS, NOT auto-fit. With five items, auto-fit packs four onto the first row and strands
   the fifth beside three empty cells — which reads as a layout bug rather than a fifth point. Three
   columns give 3 + 2, where the short row is a pair and looks deliberate. */
.uniques {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 1px; background: var(--border-dim);
  border: 1px solid var(--border-dim); border-radius: var(--radius); overflow: hidden;
}
.u-item { background: var(--bg-raised); padding: 22px 24px; }
.u-num { font-family: var(--font-mono); font-size: 0.72rem; color: var(--accent); margin-bottom: 9px; }
.u-title { font: 500 1rem var(--font-prose); color: var(--fg-bright); margin: 0 0 6px; }
.u-body { font-size: 0.92rem; line-height: 1.6; margin: 0; }

/* link chips */
.chips { display: flex; flex-wrap: wrap; gap: 9px; }
.chip {
  font-family: var(--font-mono); font-size: 0.82rem; color: var(--fg);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 9px 14px; text-decoration: none;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.chip:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-bg); }
.chip b { color: var(--fg-dim); font-weight: 400; margin-right: 7px; }

.landing .install-line pre {
  background: var(--bg-code);
  /* Keep the wrap: a scrollbar under the page's primary call to action is worse than two lines. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.warn-block { border-left: 2px solid var(--warn); padding-left: 18px; }
.warn-block p { max-width: 66ch; }
.warn-block b { color: var(--fg-bright); }

/* No JS: the sidebar is inert, so it stays hidden and every capture stacks with its text. */
.exp-nav { display: none; }
.js .exp-nav { display: block; }
.js .exp-body > [hidden] { display: none; }
/* Stacked without JS: each capture keeps a rule between it and the next. */
.exp-pane + .exp-pane { border-top: 1px solid var(--border); }

/* AN ANIMATION, NOT A TRANSITION. Panes are shown and hidden with the `hidden` attribute, and
   display:none has no intermediate state to transition from — so the reveal is keyframed instead.
   Short and small: the point is to let the eye follow the swap, not to perform. */
@keyframes exp-reveal {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.js .exp-pane:not([hidden]) { animation: exp-reveal 0.18s ease-out; }

@media (max-width: 60rem) {
  .hero-split { flex-direction: column; align-items: stretch; gap: 34px; }
  .hero-media { flex: 1; max-width: none; }
  .explorer { grid-template-columns: 1fr; }
  .uniques { grid-template-columns: 1fr; }
  .js .exp-nav { display: flex; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--border); }
  .exp-item { border-left: 0; border-bottom: 2px solid transparent; white-space: nowrap; }
  .exp-item[aria-selected="true"] { border-left-color: transparent; border-bottom-color: var(--accent); }
  .landing main { padding: 0 20px; }
}

/* ---- Inner pages: the landing page's shell, with prose kept readable inside it ------------- */

/* THE MEASURE MOVED FROM THE PAGE TO THE PARAGRAPH. main is 1180px so tables, captures and the
   catalog have room; a run of text inside it would be unreadable at that width, so the elements
   that ARE prose carry the limit themselves. */
main > p,
main > ul,
main > ol,
main > blockquote,
.page-head .lede,
.footnote p,
.footnote ul { max-width: 74ch; }

.page-head { padding: 1rem 0 2.5rem; border-bottom: 1px solid var(--border-dim); margin-bottom: 2.5rem; }
.page-head h1 { margin: 0.4rem 0 0.6rem; }
.page-head .lede { color: var(--fg); font-size: 1.08rem; line-height: 1.6; margin: 0; }

/* ---- The catalog: one row per plugin, detail behind a disclosure --------------------------- */

#catalog { margin: 0 0 4rem; }

.plugin-row {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-raised);
  margin: 0 0 0.75rem;
  overflow: hidden;
}

.plugin-row > summary {
  cursor: pointer;
  padding: 1rem 1.25rem;
  display: grid;
  grid-template-columns: minmax(15rem, 22rem) 1fr;
  grid-template-areas: "title blurb" "facts facts";
  gap: 0.35rem 1.5rem;
  align-items: baseline;
  list-style: none;
}
.plugin-row > summary::-webkit-details-marker { display: none; }

/* THE MARKER IS DRAWN, NOT INHERITED. A default disclosure triangle sits on the baseline of the
   first line and drifts out of alignment once the summary becomes a grid. */
.plugin-row > summary::after {
  content: "▸";
  position: absolute;
  right: 1.25rem;
  top: 1.05rem;
  color: var(--accent-dim);
  font-size: 0.9rem;
  transition: transform 0.15s ease;
}
.plugin-row[open] > summary::after { content: "▾"; }
.plugin-row > summary { position: relative; padding-right: 3rem; }

.plugin-title { grid-area: title; display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.plugin-title strong { font-size: 1.05rem; color: var(--fg-bright); }
.plugin-slug { font-family: var(--font-mono); font-size: 0.85rem; color: var(--fg-dim); }
/* CLAMPED TO TWO LINES. A row's height must not depend on how verbose its author was, or the list
   stops being scannable at exactly the moment it gets long. The full text is one click away. */
.plugin-blurb {
  grid-area: blurb;
  color: var(--fg);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* UNCLAMPED WHEN OPEN, which is what makes the claim above true. Expanding a row reveals its
   requirements, tools and metadata but left the blurb clamped, so the full sentence was not one
   click away — it was nowhere on the page. */
.plugin-row[open] .plugin-blurb {
  -webkit-line-clamp: unset;
  display: block;
  overflow: visible;
}
.plugin-facts {
  grid-area: facts;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--fg-dim);
}

.plugin-row:hover { border-color: var(--accent-dim); }
.plugin-row[open] { border-color: var(--accent-dim); }

.plugin-detail {
  padding: 0.25rem 1.25rem 1.25rem;
  border-top: 1px solid var(--border-dim);
  margin-top: 0.25rem;
}
.plugin-detail > p { max-width: 74ch; }

/* A RUN, NOT A LIST. Publisher, licence and repository are three short facts; bullets give them a
   visual weight that competes with the tools above them. */
.plugin-detail .meta {
  list-style: none;
  padding: 0;
  margin: 1rem 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.75rem;
  font-size: 0.9rem;
  color: var(--fg-dim);
}
.plugin-detail .meta strong { color: var(--fg); font-weight: 500; }
.plugin-links { margin-top: 1rem; }

/* ---- Footnotes below the catalog: present, but plainly secondary to it --------------------- */

.plugin-footnotes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: 2.5rem;
  padding-top: 2.5rem;
  border-top: 1px solid var(--border-dim);
}
.footnote h2 { font-size: 1.05rem; margin: 0 0 0.75rem; }
.footnote p { font-size: 0.95rem; }

/* ---- Copy buttons on code blocks ----------------------------------------------------------- */

pre.has-copy { position: relative; }

/* HIDDEN UNTIL WANTED on a pointer device, and always present without one. A button that only
   appears on hover is invisible to a touch screen, which has no hover to give. */
.copy-button {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  padding: 0.25rem 0.6rem;
  font: 500 0.75rem/1 var(--font-mono);
  color: var(--fg-dim);
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 5px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
pre.has-copy:hover .copy-button,
.copy-button:focus-visible { opacity: 1; }
.copy-button:hover { color: var(--fg-bright); border-color: var(--accent-dim); }
.copy-button.copied { color: var(--accent); border-color: var(--accent); opacity: 1; }

@media (hover: none) {
  .copy-button { opacity: 1; }
}

/* A quiet aside under an explorer caption: the thread between two captures of one session. */
.exp-aside {
  margin-top: 0.7rem;
  color: var(--fg-dim);
  font-size: 0.9rem;
  font-style: italic;
}

/* A thematic break between a document's sections. Quiet: it separates, it does not decorate. */
.doc hr {
  border: 0;
  border-top: 1px solid var(--border-dim);
  margin: 3rem 0;
}

/* A rendered document whose captures are the content, not decoration around it. */
main.doc-wide { max-width: 1180px; }

/* FILLED, NOT MERELY CAPPED. The captures were taken at different window sizes, so `max-width: 100%`
   alone leaves a 1499px shot and a 1746px shot rendering at different widths down the page -- and
   the smaller ones sitting in whitespace they could have used. Terminal text is the content here,
   and every pixel of column is a pixel of legibility. */
main.doc-wide img {
  width: 100%;
  border: 1px solid var(--border-dim);
  border-radius: 6px;
}
/* Its prose still reads at a sane measure inside that width -- but a paragraph that is nothing but a
   capture is not prose, and the measure would cap the picture it wraps. :has lets the rule skip
   exactly those. */
main.doc-wide > p,
main.doc-wide > ul,
main.doc-wide > ol,
main.doc-wide > blockquote { max-width: 78ch; }
main.doc-wide > p:has(> img) { max-width: none; }

/* ITS OWN ROW, ALWAYS. Left to wrap it sat beside `models` at 1440px, alone at 1100px and alone
   again at 900px -- landing wherever there happened to be room, which reads as an accident rather
   than a decision. A flex-basis of 100% breaks the line before it every time.
   
   IT IS ALSO NOT THE SAME KIND OF FACT as the three above it: those are fixed properties of the
   software, this one changes with every release. A row of its own says so without a caption. */
/* A ROW OF ITS OWN, forced rather than left to chance. Wrapping naturally it sat beside `models` at
   1440px, alone at 1100px and alone again at 900px -- landing wherever there was room, which reads
   as an accident. `.pills` wraps, so a full-width spacer before this pill breaks the line every
   time; the pill itself keeps its own width, since one stretched across the hero stops looking like
   a pill at all.

   IT IS ALSO NOT THE SAME KIND OF FACT as the three above: those are fixed properties of the
   software, this changes with every release. Its own row says so without needing a caption. */
.pill-break { flex-basis: 100%; height: 0; }
/* Hidden with the pill it precedes: a spacer left behind when the version cannot be read would push
   nothing onto a row that then holds nothing. */
.pill-break:has(+ .pill-link[hidden]) { display: none; }
.pill-link { margin-top: 2px; }
.pill-link {
  color: var(--accent);
  border-color: var(--accent-dim);
  text-decoration: none;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.pill-link:hover { border-color: var(--accent); color: var(--fg-bright); }
