/* =============================================================
   The Agentic City — house stylesheet
   -------------------------------------------------------------
   Shared by both halves of the site: the Astro marketing pages at
   / and the FastAPI app at /futures. Same reason as tokens.css for
   living here — see the note at the top of that file.

   Everything shared between the two lives here: page frame, nav,
   footer, type, links, buttons, forms, tables, lists. App-specific
   things (the graph, the detail drawer, admin tools) stay in
   app.css / signals.css.

   The house style is a document:
     · system type, normal weights, no negative tracking
     · white paper, hairline rules, no shadows, no bands of color
     · one accent, on links and the primary button
     · a measure that stops prose before it gets unreadable
   If a rule here exists to decorate rather than to clarify, it is
   in the wrong file.
   ============================================================= */

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

/* The browser's own `[hidden] { display: none }` lives in the UA
   stylesheet, so any author rule that sets `display` beats it —
   `.btn { display: inline-block }` was keeping the signal list's
   "show more" button on screen after JS had hidden it. Anything
   toggled via `el.hidden` needs this to actually disappear. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: 1.55;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Inter's tabular figures on by default: dates, counts and scores
     line up in every column without each rule asking for it. */
  font-variant-numeric: tabular-nums;
}

/* Every hover and focus change fades over the same beat. Listed once
   here rather than per rule; anything interactive that isn't in this
   list snaps, which is a bug in the list, not a design choice. */
a, button, .btn, .row, .filter, .chip, .linklist li, .gallery-card,
input, select, textarea, .member, .queue-item, .lst-kind-btn {
  transition:
    color var(--dur) var(--ease),
    background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease),
    text-decoration-color var(--dur) var(--ease);
}

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

/* ---------- frame ---------- */

.container {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--space-5);
}

/* Every page's content well. */
.main { padding: 0 0 var(--space-6); }

/* ---------- page header ----------
   The title and summary sit on a tint that runs to both edges,
   which separates them from the body without adding another
   horizontal rule to a page that already had too many. A ground,
   not a line.

   The tint bleeds via a pseudo-element rather than by moving the
   header outside .container, so a page stays a heading followed by
   its content — no wrapper markup, no named slots. */
/* --haze, not --paper: at 2% off white the tint read as a printing
   artefact rather than as a deliberate zone. The graph stage stays
   on the lighter --paper — a figure sitting inside the body should
   be quieter than the page's own header.

   Bleeds via spread shadow + clip-path rather than a -50vw
   pseudo-element. The pseudo-element version overflowed the
   viewport, which needed `overflow-x: clip` on body to hide, and
   that made body a containing block for fixed-position descendants
   — which left the detail drawer stuck open on every page. This
   paints outside the box without occupying any space, so nothing
   overflows and nothing has to be clipped. */
.pagehead {
  padding: var(--space-5) 0 var(--space-3);
  margin-bottom: var(--space-4);
}

/* The header's own padding is the gap; its last child shouldn't
   add another. Scoped to :last-child only — a page header can now
   stack more than one .lead paragraph (the Horizon Scan intro, the
   home page), and the old rule zeroed the bottom margin on all of
   them, collapsing the gaps between them to nothing. */
.pagehead > :last-child { margin-bottom: 0; }

/* ---------- nav ---------- */

/* The one rule on the page, and it's a hairline. Structure comes
   from space and from type size; drawing a line at every boundary
   turned the pages into a stack of bars. */
.nav {
  background: var(--accent);
  color: var(--text-on-dark);
  border-bottom: 8px solid var(--accent-hover);
}
.nav .brand { color: var(--text-on-dark); text-decoration: none; }
/* The global a:hover darkens links toward the accent, which on an
   accent-coloured bar makes them vanish. Everything in the masthead
   stays white on hover; the underline is what moves. */
.nav a:hover, .nav .brand:hover, .nav .linkbutton:hover { color: var(--text-on-dark); }

.nav-inner {
  display: flex;
  align-items: baseline;
  gap: var(--space-5);
  padding: var(--space-3) var(--space-5);
  max-width: var(--maxw);
  margin: 0 auto;
  flex-wrap: wrap;
}

.brand {
  font-weight: var(--w-bold);
  font-size: 1.3125rem;
  letter-spacing: -0.01em;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
}

.nav-links {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.nav-links a {
  color: var(--text-on-dark);
  text-decoration: none;
  font-size: var(--step-0);
  font-weight: var(--w-medium);
  padding-bottom: 2px;
  border-bottom: 3px solid transparent;
}
.nav-links a:hover { border-bottom-color: rgba(255,255,255,0.6); }
.nav-links a.active { border-bottom-color: var(--text-on-dark); }

/* Pushed to the far end of the bar. A text link, not a button:
   signing in is navigation, not the point of the page. */
.nav-end { margin-left: auto; display: flex; gap: var(--space-4); align-items: baseline; }
.nav-end a { color: var(--text-on-dark); text-decoration: none; font-size: var(--step-0); font-weight: var(--w-medium); }
.nav-end a:hover { text-decoration: underline; text-decoration-color: currentColor; }
/* Your handle, in the account slot. A link (to your profile) that reads
   as an identifier, not a menu item. */
.nav-who { color: rgba(255,255,255,0.8); font-family: var(--font-mono); font-size: var(--step--1); }
.nav-end a.nav-who { color: rgba(255,255,255,0.8); font-size: var(--step--1); font-weight: var(--w-regular); }
.nav .linkbutton { color: var(--text-on-dark); font-weight: var(--w-medium); }
.nav .linkbutton:hover { color: var(--text-on-dark); text-decoration: underline; }
.nav-end form { margin: 0; }

/* ---------- section bar ----------
   The Horizon Scan's own row under the masthead: what you can see here,
   a rule, then what you can do. Same type as the masthead links so it
   reads as the second line of one navigation, not a toolbar; a hairline
   below closes it. On a phone it scrolls sideways rather than wrapping —
   eight short words wrap into a three-line block, and a row you can
   nudge is easier to scan than a block you have to read. */
.sectionbar {
  border-bottom: 1px solid var(--border);
  background: var(--bg-subtle);
}
/* Which masthead tab this bar belongs to. Small caps at the head of the
   row, like the Manage sub-nav's own label one level down. */
.sectionbar a.sectionbar-label {
  align-self: center;
  padding: 0; margin: 0 var(--space-2) 0 0; border: 0;
  font-size: var(--step--1); font-weight: var(--w-bold);
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-subtle);
}
.sectionbar a.sectionbar-label:hover { color: var(--text); }
/* The active masthead tab, when a section bar follows, is drawn as a tab:
   it takes the bar's fill and its two side hairlines run down through the
   masthead's bottom edge and open into the bar, so the bar reads as the
   inside of that tab and not as a second menu. :has() scopes this to the
   app — the marketing pages share the masthead but have no section bar. */
.nav:has(+ .sectionbar) .nav-links a.active {
  position: relative;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-bottom: 0;
  margin-bottom: -1px;
}
.nav:has(+ .sectionbar) .nav-links a.active::after {
  content: "";
  position: absolute;
  left: -1px; right: -1px; top: 100%;
  height: var(--nav-tab-drop, var(--space-4));
  background: var(--bg-subtle);
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
}
/* On a phone the masthead links wrap onto two lines, so the tab can't
   reach the bar below; the bar's own label does the job there. */
@media (max-width: 640px) {
  .nav:has(+ .sectionbar) .nav-links a.active { background: none; border: 0; margin-bottom: 0; }
  .nav:has(+ .sectionbar) .nav-links a.active::after { display: none; }
}
.sectionbar-inner {
  display: flex;
  align-items: stretch;
  gap: var(--space-5);
  padding: 0 var(--space-5);
  max-width: var(--maxw);
  margin: 0 auto;
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
}
.sectionbar-inner::-webkit-scrollbar { display: none; }
/* Tabs: the active item is underlined by a 2px rule that sits on the
   bar's own hairline, so "where am I" is a mark rather than a weight. */
.sectionbar a {
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.9375rem;
  flex: none;
  padding: var(--space-3) 0 calc(var(--space-3) - 3px);
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
}
.sectionbar a:hover { color: var(--text); }
.sectionbar a.active { color: var(--text); font-weight: var(--w-semibold); border-bottom-color: var(--accent); }
.sectionbar-divider {
  flex: none;
  align-self: center;
  width: 1px;
  height: 1.1em;
  background: var(--border-strong);
}
/* A count that needs acting on — pending review — in the accent. */
.badge-count {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: var(--w-bold);
  line-height: 1.5;
  padding: 0 0.5em;
  margin-left: 0.35em;
  background: var(--cta);
  color: var(--text-on-dark, #fff);
  vertical-align: 0.15em;
}

/* A button that reads as a link. For actions that must be a POST —
   signing out — but that belong in a row of navigation. */
.linkbutton {
  font: inherit;
  font-size: var(--step-0);
  color: var(--text-muted);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.linkbutton:hover { color: var(--text); }


/* ---------- type ---------- */

/* The heading ladder moves on two axes at once — size and weight —
   because size alone wasn't carrying it: h1/h2/list-title used to run
   30/20/18px all at the same weight and colour, so a section heading
   and the items inside it were nearly indistinguishable.

     h1  30px / bold        the page
     h2  22px / semibold    a section of it
     h3  18px / semibold    a subsection
     titles 17px / semibold an item in a list  (.linklist .t, .row-title)
     body   16px / regular

   Each step is a clear size drop, and the top of the ladder is the
   only bold thing on the page. */
h1, h2, h3, h4 {
  /* The one webfont, and only here. Body, tables, nav and forms stay on
     the system stack, so headings are the only thing that waits on a
     download — and the only place the site has a voice of its own. */
  font-family: var(--font-display);
  font-weight: var(--w-semibold);
  line-height: 1.25;
  color: var(--text);
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: var(--step-5); font-weight: var(--w-bold); letter-spacing: -0.01em; line-height: 1.1; }
/* Sections are separated by space, not by a rule. A generous gap
   above and a tight one below binds a heading to the text it
   introduces, which is all a section break has to do. */
/* Asymmetric on purpose: a big gap above and a small one below is
   what binds a heading to its own section rather than leaving it
   floating equidistant between two. Without that, the size step
   alone has to carry the grouping, and it can't. */
h2 {
  font-size: var(--step-3);
  font-weight: var(--w-bold);
  margin: var(--space-6) 0 var(--space-2);
}
h3 { font-size: var(--step-2); margin-top: var(--space-5); margin-bottom: var(--space-2); }
h4 { font-size: var(--step-0); margin-top: var(--space-5); }

/* A heading's top margin separates it from what came before, so when
   nothing came before there's nothing to separate it from. Without
   this, the first heading in a column gets pushed down by 48px while
   the column beside it starts at the top — which is what made the
   two halves of .withside sit on different lines. */
h1:first-child, h2:first-child, h3:first-child, h4:first-child { margin-top: 0; }
.main > :first-child, .main > .container > :first-child { margin-top: 0; }

p { margin: 0 0 var(--space-4); max-width: 68ch; }

/* One step up from body, muted. The page's opening sentence — it
   replaces the eyebrow + display-headline + lead stack. */
.lead {
  font-size: 1.125rem;
  line-height: 1.45;
  color: var(--text);
  max-width: 60ch;
  margin: var(--space-2) 0 var(--space-3);
}

/* Underlines are a shade lighter than the text and go solid on
   hover — the link is still obviously a link, but a paragraph with
   three of them no longer reads as three red bars. */
a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
a:hover { color: var(--accent-hover); text-decoration-thickness: 3px; }
/* GOV.UK focus: a yellow ground with a black underline. It works on any
   background and reads as "here" even to someone who can't see colour. */
a:focus-visible, .linkbutton:focus-visible {
  outline: 3px solid transparent;
  color: var(--ink);
  background: var(--focus);
  box-shadow: 0 -2px var(--focus), 0 4px var(--ink);
  text-decoration: none;
}

strong { font-weight: var(--w-semibold); }

.muted { color: var(--text-muted); }
.icon { width: 1em; height: 1em; vertical-align: -0.125em; fill: none; display: inline-block; flex: none; }
.icon-lg { width: 1.5em; height: 1.5em; }
.small { font-size: var(--step--1); }

/* Dates, counts, categories and labels are set in mono throughout.
   It's the one piece of deliberate texture in the system: it
   separates *facts about* a thing from the thing itself at a
   glance, and gives the pages the character of an instrument
   rather than a brochure — without adding a colour or a weight. */
.meta {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  color: var(--text-subtle);
}

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

ul, ol { margin: 0 0 var(--space-4); padding-left: 1.25rem; max-width: 68ch; }
li { margin-bottom: var(--space-2); }

/* A bulleted list where each item is a link plus a sentence saying
   what it is. The link stays ink until hovered — same rule as
   .linklist .t — and the gloss after the dash is muted, so the
   scannable part is the label. */
.itemlist { margin-top: calc(var(--space-2) * -1); }
.itemlist li { color: var(--text-muted); }
.itemlist li > a {
  color: var(--text);
  font-weight: var(--w-medium);
  text-decoration: none;
}
.itemlist li > a:hover { color: var(--accent); text-decoration: underline; }

/* A list of links with a short gloss each — the workhorse layout
   for "here is what's on this site". Replaces card grids. */
.linklist { list-style: none; padding: 0; max-width: 68ch; }
/* The GOV.UK homepage pattern: an arrow in a tinted circle before each
   link, so a list of destinations reads as destinations. The arrow is
   the sprite's i-arrow as a data URI so it needs no markup. */
.linklist li {
  position: relative;
  padding: var(--space-1) 0 var(--space-1) 3rem;
  margin: 0 0 var(--space-3);
  min-height: 2.25rem;
}
.linklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(var(--space-1) + 0.05em);
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background-color: var(--accent-wash);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6' fill='none' stroke='%230E7C86' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 1.25rem;
}
/* A title in a list is structure, not a link inside a sentence, so
   it reads as ink and earns its underline on hover. The accent is
   kept for links that appear mid-prose, where there's nothing but
   colour to mark them. */
.linklist .t {
  font-weight: var(--w-bold);
  font-size: var(--step-1);
  color: var(--link);
}
.linklist p { margin: var(--space-1) 0 0; color: var(--text-muted); font-size: 0.9375rem; }

/* ---------- rows ---------- */

/* A dated, categorised entry: the signal feed, and anything else
   that is fundamentally a list of things with a date. Deliberately
   not a card — cards made three items look like a product grid. */
.rows { margin-top: var(--space-4); }

.row {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: var(--space-2) var(--space-5);
  padding: var(--space-3);
  /* pull the padding back out to the left so the text still lines
     up with the prose above it, and the hover fill has somewhere to
     go */
  margin: 0 calc(var(--space-3) * -1);
  border-radius: var(--radius-md);
  align-items: baseline;
  cursor: pointer;
}

/* The rows are clickable (they open the drawer), so they need to
   say so on approach — a card at least looked pressable. */
.row:hover { background: var(--haze); }
.row:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; background: var(--haze); }

.row-meta {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--text-subtle);
  font-variant-numeric: tabular-nums;
}

.row-title { font-weight: var(--w-bold); font-size: var(--step-1); }
.row-title a { color: var(--text); text-decoration: none; }
.row-title a:hover { text-decoration: underline; }
.row p { margin: var(--space-1) 0 0; color: var(--text); font-size: 0.9375rem; }

/* ---------- buttons ---------- */

.btn {
  display: inline-block;
  font: inherit;
  font-size: 1rem;
  font-weight: var(--w-bold);
  line-height: 1.2;
  padding: 0.55rem 0.9rem 0.45rem;
  border: 2px solid transparent;
  background: var(--cta);
  color: var(--text-on-accent);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: 0 2px 0 var(--cta-shadow);
  margin-bottom: 2px;
}
.btn:hover { background: var(--cta-hover); color: var(--text-on-accent); }
.btn:active { top: 2px; position: relative; box-shadow: none; }

.btn-secondary {
  background: var(--haze);
  color: var(--text);
  box-shadow: 0 2px 0 #929191;
}
.btn-secondary:hover { background: #dbdad9; color: var(--text); }

/* Kept because templates still say btn-primary; it is just .btn. */
.btn-primary { }

.btn-danger { background: var(--error); box-shadow: 0 2px 0 #942514; }
.btn-danger:hover { background: #AA2A16; }

.btn-sm { padding: 0.3rem 0.65rem 0.25rem; font-size: var(--step--1); }

.btn[disabled], .btn:disabled { opacity: 0.5; cursor: not-allowed; }

:focus-visible { outline: 3px solid var(--focus); outline-offset: 0; box-shadow: inset 0 0 0 2px var(--ink); }
.btn:focus-visible { background: var(--focus); color: var(--ink); box-shadow: 0 2px 0 var(--ink); outline: 3px solid transparent; }

/* ---------- forms ---------- */

.form { display: flex; flex-direction: column; gap: var(--space-4); max-width: 34rem; }
.field { display: flex; flex-direction: column; gap: var(--space-1); }

.field > label, .field > legend, .form label.label {
  font-size: 1rem;
  font-weight: var(--w-bold);
  color: var(--text);
}

.hint { color: var(--text-subtle); font-weight: var(--w-regular); font-size: var(--step--1); }

input[type="text"], input[type="email"], input[type="password"],
input[type="url"], input[type="search"], input[type="date"],
select, textarea {
  font: inherit;
  font-size: 0.9375rem;
  padding: 0.5rem 0.7rem;
  border: 2px solid var(--ink);
  background: var(--bg);
  color: var(--text);
  width: 100%;
}
input::placeholder, textarea::placeholder { color: var(--mist); }

textarea { resize: vertical; min-height: 5rem; }

/* A soft halo rather than a hard outline: the field is clearly the
   one you're in without a second red rectangle around it. */
input:focus, select:focus, textarea:focus {
  outline: 3px solid var(--focus);
  outline-offset: 0;
  box-shadow: inset 0 0 0 2px var(--ink);
}

fieldset { border: 0; padding: 0; margin: 0; }

.checks { display: grid; gap: var(--space-2); margin-top: var(--space-2); }
.check {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.9375rem;
  font-weight: var(--w-regular);
  cursor: pointer;
}
.check input { width: auto; accent-color: var(--accent); }

/* Help text for a single option, indented to sit under that option's
   label rather than under its checkbox — so it reads as belonging to
   the choice above it and not to the list as a whole. */
.check-note {
  margin: var(--space-1) 0 0 1.65rem;
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--text-muted);
  max-width: 52ch;
}

/* ---------- tables ---------- */

table { width: 100%; border-collapse: collapse; margin: var(--space-4) 0; font-size: 0.9375rem; }
th, td { text-align: left; padding: var(--space-2) var(--space-3) var(--space-2) 0; border-bottom: 1px solid var(--border); vertical-align: top; }
/* Column labels small, spaced and quiet, so the data is the loudest
   thing in the table. */
th { font-weight: var(--w-bold); color: var(--text); font-size: 0.9375rem; padding-top: 0; }
tbody tr:hover > td { background: var(--haze); }

/* ---------- panels & notices ---------- */

.panel {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  margin: var(--space-5) 0;
}

.notice {
  border-left: 10px solid var(--cloud);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-4) 0;
  font-size: 0.9375rem;
}
.notice p:last-child { margin-bottom: 0; }

/* ---------- category dot ----------
   The one place colour is allowed to mean something. Sits before a
   category label in a list and matches that record's node in the
   graph, so the same signal is the same colour in both. Baseline
   aligned rather than centred, so it sits on the line of type it
   belongs to rather than floating. */
.cat-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 0.4rem;
  vertical-align: 0.05em;
  flex: none;
}

/* A quiet metadata pill. Outlined, never filled with color —
   filled pills read as status even when they aren't. */
.tag {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--ink);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-muted);
  white-space: nowrap;
  vertical-align: 0.15em;
}

/* ---------- footer ---------- */

.footer {
  margin-top: var(--space-6);
  padding: var(--space-7) 0;
  background: var(--haze);
  border-top: 10px solid var(--accent);
  color: var(--text);
  font-size: var(--step--1);
}

/* Logo on the left, everything else stacked to its right. Top-aligned:
   the lockup runs much taller than the text beside it. */
.footer-inner { display: flex; gap: var(--space-6); flex-wrap: wrap; align-items: flex-start; }

/* Full Cornell Tech / Jacobs Institute / Technion / Cornell lockup.
   Intrinsic size is 238x948 — tall and narrow, so it's constrained by
   width, not height. */
.footer-logo { width: 64px; height: auto; flex: none; }

.footer-main { flex: 1 1 320px; min-width: 0; }

.footer-row {
  display: flex;
  gap: var(--space-6);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}

.footer-about { flex: 1 1 380px; min-width: 0; }
.footer-about h3 {
  margin: 0 0 var(--space-3);
  color: var(--text);
  font-size: var(--step-1);
  font-weight: 700;
}
.footer-about p { margin: 0 0 var(--space-3); max-width: 52ch; }
.footer-about p:last-child { margin-bottom: 0; }
.footer-about a { color: var(--link); }

.footer-nav { display: flex; flex-direction: column; gap: var(--space-2); flex: none; }
.footer-nav a { color: var(--text); font-weight: var(--w-semibold); }

.footer-end { color: var(--text-muted); }
.footer a { text-decoration: underline; text-underline-offset: 0.15em; }
.footer-nav a { text-decoration: none; }
.footer-nav a:hover { text-decoration: underline; }

/* ---------- responsive ---------- */

@media (max-width: 640px) {
  .container, .nav-inner, .sectionbar-inner { padding-left: var(--space-4); padding-right: var(--space-4); }
  .nav-inner { gap: var(--space-3); }
  .nav-end { margin-left: 0; width: 100%; }
  .row { grid-template-columns: 1fr; gap: var(--space-1); }
  .footer-row { gap: var(--space-4); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ---------- content with a sidebar ----------
   Body text on the left at a readable measure, a standing block on
   the right. For things that should be reachable without scrolling
   past the whole page to find them. */

.withside {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 17rem;
  gap: var(--space-6);
  align-items: start;
}

.side {
  background: var(--haze);
  padding: var(--space-4);
  /* Pull the panel up by its own padding so its first line of text sits
     on the same line as the first heading in the column beside it.
     Aligning the box edge instead leaves the two headings 16px apart,
     which is close enough to look like a mistake rather than a choice. */
  margin-top: calc(var(--space-4) * -1);
}

/* Its own heading, a step down from an h2 in the body — it labels a
   block, it doesn't open a section of the page. */
.side-title {
  font-size: var(--step-0);
  font-weight: var(--w-semibold);
  margin: 0 0 var(--space-3);
}

.side-list { list-style: none; padding: 0; margin: 0; }
.side-list li { margin: 0 0 var(--space-3); }
.side-list li:last-child { margin-bottom: 0; }
/* Ink, like .linklist .t — these are titles of items in a list, not
   links inside a sentence, so the accent isn't what marks them. */
.side-list > li > a {
  font-weight: var(--w-semibold);
  color: var(--text);
  text-decoration: none;
}
.side-list > li > a:hover { color: var(--accent); text-decoration: underline; }
.side-list p {
  margin: var(--space-1) 0 0;
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--text-muted);
  max-width: none;
}

@media (max-width: 820px) {
  .withside { grid-template-columns: 1fr; gap: var(--space-5); }
  /* Stacked, there's no column to align to — and the offset would pull
     the panel up into the text above it. */
  .side { margin-top: 0; }
}
