/**
 * Aurah — components.
 * Requires tokens.css (see <head>).
 *
 * Structure: a page that scrolls. One reading column is the subject; the
 * rail carries context with no tile chrome at all, so it recedes instead
 * of competing. Nothing here uses a shadow, a gradient or a counter.
 */

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

body {
  margin: 0;
  background: var(--color-page-bg);
  color: var(--text-ink);
  font-family: var(--font-ui);
  font-size: var(--text-13);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
}

/* Paper. Fixed so it never scrolls with content, and inert to the pointer. */

button { margin: 0; padding: 0; border: 0; background: none; font: inherit; color: inherit; cursor: pointer; }
input, textarea { font: inherit; }
::placeholder { color: var(--text-placeholder); opacity: 1; }
img { max-width: 100%; display: block; }
/* An element carrying [hidden] is hidden, whatever display it was given.
   Without this a flex or grid rule silently overrides the attribute. */
[hidden] { display: none !important; }

::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-thumb { background: var(--color-scrollbar); border-radius: var(--radius-pill); border: 3px solid var(--color-page-bg); }
::-webkit-scrollbar-track { background: transparent; }
* { scrollbar-width: thin; scrollbar-color: var(--color-scrollbar) transparent; }

a { color: var(--green-link); text-decoration: none; }
a:hover { color: var(--green-link-hover); }
a:active { color: var(--green-link-active); }

:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); border-radius: 3px; }

.visually-hidden {
  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 {
  position: absolute; left: var(--space-12); top: -60px;
  z-index: 20;
  background: var(--color-surface); color: var(--green-fill);
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  padding: var(--space-8) var(--space-14);
  font-size: var(--text-12-5);
  transition: top 160ms var(--ease-settle);
}
.skip-link:focus { top: var(--space-12); }

/* ==================================================================
   The mark — a ring with its halo. One asset; also the favicon,
   the loading state and the empty-state glyph.
   ================================================================== */
.mark { display: block; color: var(--green-fill); flex: none; }
.mark__halo { opacity: 0.38; }
/* Where the mark stands in for absent content — the end of the feed, an
   empty Today — it uses the sage from the focus token: present enough to
   read as a mark, quiet enough not to become an illustration. */
.mark--quiet { color: var(--border-focus); }

/* ==================================================================
   Top bar
   ================================================================== */
.bar {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--color-page-bg);
  border-bottom: 1px solid var(--border-divider);
}
.bar__inner {
  max-width: var(--shell-max);
  margin-inline: auto;
  min-height: var(--bar-h);
  padding: var(--space-10) var(--shell-pad);
  display: flex;
  align-items: center;
  gap: var(--space-24);
}

.brand {
  display: inline-flex; align-items: center; gap: var(--space-8);
  font-family: var(--font-display);
  font-size: var(--text-17);
  color: var(--text-ink);
  letter-spacing: 0.01em;
  flex: none;
}
.brand:hover { color: var(--green-fill); }

.nav { display: flex; align-items: center; gap: var(--space-4); flex: 1; min-width: 0; }
.nav__link {
  display: inline-flex; align-items: center; gap: var(--space-6);
  padding: var(--space-6) var(--space-11);
  border-radius: var(--radius-sm);
  font-size: var(--text-12-5);
  color: var(--text-body-muted);
  white-space: nowrap;
}
.nav__link:hover { background: var(--color-row-hover); color: var(--green-fill); }
.nav__link[aria-current="page"] { color: var(--text-ink); font-weight: 500; }
/* Current place is marked by a rule under the word, not a filled pill —
   quieter, and it survives being read at a glance. */
.nav__link[aria-current="page"] .nav__underline {
  display: block; height: 1.5px; background: var(--green-fill);
  border-radius: 1px; margin-top: 3px;
}
.nav__count {
  font-size: var(--text-11);
  color: var(--green-fill);
  background: var(--color-inset);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  padding: 0 var(--space-6);
  line-height: 1.55;
}

.bar__end { display: flex; align-items: center; gap: var(--space-12); flex: none; }

.search {
  display: flex; align-items: center; gap: var(--space-8);
  background: var(--color-surface);
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
  padding: var(--space-6) var(--space-8) var(--space-6) var(--space-11);
  width: clamp(150px, 20vw, 232px);
}
.search:focus-within { border-color: var(--border-focus); }
.search svg { flex: none; stroke: var(--text-meta); }
.search input {
  flex: 1; min-width: 0; border: 0; background: transparent; outline: none;
  color: var(--text-ink); font-size: var(--text-12-5);
}
.kbd {
  flex: none;
  border: 1px solid var(--border-default); border-radius: var(--radius-xs);
  padding: 0 var(--space-5);
  font-size: var(--text-11); color: var(--text-meta);
  background: var(--color-row-zebra);
}

.me { display: inline-flex; align-items: center; gap: var(--space-8); font-size: var(--text-12-5); color: var(--text-body-muted); }
.me:hover { color: var(--green-fill); }

/* ==================================================================
   Shell — one reading column, one sticky rail
   ================================================================== */
.home {
  position: relative;
  z-index: 1;
  max-width: var(--shell-max);
  margin-inline: auto;
  padding: var(--space-40) var(--shell-pad) var(--space-64);
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--rail-w);
  gap: var(--gutter);
  align-items: start;
}

.feed { min-width: 0; max-width: var(--feed-max); }

.rail {
  min-width: 0;
  position: sticky;
  top: var(--rail-top);
  display: flex;
  flex-direction: column;
  gap: var(--space-32);
}

/* A sticky column taller than the viewport parks its top and hides its own
   bottom: you scroll, it locks, and there is a short unreachable tail. So it
   is only sticky while it fits. When it doesn't, it travels with the page and
   you simply read to the end of it. app.js measures and sets this. */
.rail.is-loose,
.convos__list.is-loose { position: static; }

/* ==================================================================
   Compose — the input is set in the face the note will be read in
   ================================================================== */
.compose {
  background: var(--color-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-tile);
  padding: var(--space-16) var(--space-18);
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
}
.compose:focus-within { border-color: var(--border-focus); }

/* While you are writing, everything that is not the field recedes. Not a
   modal and not a scrim — the page is still there, still in place, just
   turned down. Nothing moves; only luminance changes. Dimming .bar__inner
   rather than .bar keeps the bar's ground opaque, so the feed does not
   show through it.

   Opacity compounds, so an ancestor of the field can never be dimmed —
   it would take the field down with it. The rule therefore dims every
   element that is neither the field nor on the path to it, at both the
   levels a reading column ever nests: Today puts the compose straight
   into .feed, a gathering puts it inside a section. */
.bar__inner,
.rail > *,
.feed > *,
.feed > * > * {
  transition: opacity var(--duration-dim) var(--ease-settle);
}
body:has(.compose:focus-within) .bar__inner,
body:has(.compose:focus-within) .rail > *,
body:has(.compose:focus-within) .feed > *:not(.compose):not(:has(.compose:focus-within)),
body:has(.compose:focus-within) .feed > :has(.compose:focus-within) > *:not(.compose):not(:has(.compose:focus-within)) {
  opacity: var(--dim-opacity);
}
.compose__field { display: flex; gap: var(--space-12); align-items: flex-start; }
.compose__input {
  flex: 1; min-width: 0;
  border: 0; outline: none; resize: none; background: transparent;
  font-family: var(--font-display);
  font-size: var(--text-read);
  line-height: var(--leading-read);
  color: var(--text-ink);
  height: calc(var(--text-read) * var(--leading-read) * 2);
  padding-top: 2px;
}
.compose__foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-12);
  padding-top: var(--space-12);
  border-top: 1px solid var(--border-divider);
}
.compose__hint { font-size: var(--text-11-5); color: var(--text-meta); }

.btn-primary {
  border: 1px solid var(--green-fill); background: var(--green-fill);
  color: var(--color-page-bg);
  border-radius: var(--radius-sm);
  padding: var(--space-8) var(--space-16);
  font-size: var(--text-12); font-weight: 500;
}
/* colour is restated on both states because a.btn-primary would otherwise
   inherit the global a:hover green — dark text on a dark ground. */
.btn-primary:hover { background: var(--green-fill-hover); border-color: var(--green-fill-hover); color: var(--color-page-bg); }
.btn-primary:active { background: var(--green-fill-active); border-color: var(--green-fill-active); color: var(--color-page-bg); }
.btn-primary:disabled { opacity: var(--disabled-opacity); cursor: default; }

.btn-quiet {
  border: 1px solid var(--border-default); background: transparent;
  color: var(--text-btn-secondary);
  border-radius: var(--radius-sm);
  padding: var(--space-6) var(--space-13);
  font-size: var(--text-12);
}
.btn-quiet:hover { background: var(--color-row-hover); color: var(--green-fill); }
.btn-quiet:active { background: var(--color-row-active); }

/* A small green text link that underlines on hover. It was written out
   five times — a note's actions, a rail's "more", a disclosure's act, a
   thread's head and its "earlier" — before it had a name. Anything that
   is a verb in words rather than a button is this. */
.quiet-link,
.note__action,
.block__more,
.aside-set__act,
.thread-head__act,
.thread__earlier { color: var(--green-link); }
.quiet-link:hover,
.note__action:hover,
.block__more:hover,
.aside-set__act:hover,
.thread-head__act:hover,
.thread__earlier:hover { color: var(--green-link-hover); text-decoration: underline; text-underline-offset: 3px; }
.quiet-link:active,
.note__action:active { color: var(--green-link-active); }

/* ==================================================================
   Day marker — time is the ornament. The date sits on the rule.
   ================================================================== */
.day {
  display: flex; align-items: baseline; gap: var(--space-12);
  margin: var(--space-40) 0 var(--space-20);
}
.day:first-of-type { margin-top: var(--space-32); }
.day__name { font-family: var(--font-display); font-size: var(--text-day); color: var(--text-ink); flex: none; }
.day__rule { flex: 1; height: 1px; background: var(--border-default); }
.day__date {
  flex: none;
  font-size: var(--text-11); letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--text-label);
}

/* ==================================================================
   Note (the post). No counters, no icon row, full measure for reading.
   ================================================================== */
.note { padding: var(--space-4) 0 var(--space-28); }
.note + .note { border-top: 1px solid var(--border-divider); padding-top: var(--space-28); }

.note__head { display: flex; align-items: center; gap: var(--space-10); margin-bottom: var(--space-12); }
.note__who { display: inline-flex; align-items: center; gap: var(--space-10); min-width: 0; color: inherit; }
.note__who:hover .note__name { color: var(--green-fill); }
.note__name { font-size: var(--text-13); font-weight: 500; color: var(--text-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.note__room { font-size: var(--text-11-5); color: var(--text-meta); flex: none; }
.note__time { margin-left: auto; flex: none; font-size: var(--text-11-5); color: var(--text-meta); }

.note__body { font-family: var(--font-display); font-size: var(--text-read); line-height: var(--leading-read); color: var(--text-ink); }
/* §11.1: notes are plain text, rendered with escaping + preserved line breaks. */
.note__body p { margin: 0; text-wrap: pretty; white-space: pre-wrap; }
.note__body p + p { margin-top: var(--space-12); }

.note__quote {
  margin-top: var(--space-16);
  border-left: 1px solid var(--border-input);
  padding: var(--space-4) 0 var(--space-4) var(--space-16);
}
.note__quote-source { font-family: var(--font-ui); font-size: var(--text-11); letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-label); }
.note__quote-text { margin: var(--space-6) 0 0; font-family: var(--font-display); font-style: italic; font-size: var(--text-read-sm); line-height: 1.5; color: var(--text-body-muted); }

.note__actions { display: flex; gap: var(--space-20); margin-top: var(--space-16); }
.note__action { font-size: var(--text-12-5); }

/* ==================================================================
   Feed end — a real stopping point, not an infinite scroll
   ================================================================== */
.feed__end {
  margin: var(--space-40) 0 0;
  padding-top: var(--space-28);
  border-top: 1px solid var(--border-divider);
  display: flex; flex-direction: column; align-items: center; gap: var(--space-10);
  text-align: center;
}
.feed__end p { margin: 0; font-family: var(--font-display); font-size: var(--text-read-sm); color: var(--text-body-muted); }
.feed__end small { font-size: var(--text-11-5); color: var(--text-meta); }

/* ==================================================================
   Rail — no surface, no border, no header bar. Type and space only.
   ================================================================== */
.block { display: flex; flex-direction: column; gap: var(--space-12); }
.block__label,
.field__label {
  margin: 0;
  display: flex; align-items: baseline; gap: var(--space-8);
  font-family: var(--font-ui);
  font-size: var(--text-11); font-weight: 600;
  letter-spacing: var(--label-tracking); text-transform: uppercase;
  color: var(--text-label);
}
.block__count { font-weight: 400; color: var(--text-meta); letter-spacing: 0.04em; }
.block__more { font-size: var(--text-11-5); align-self: flex-start; }

.block__list { display: flex; flex-direction: column; }

/* --- Contact request: the one place in the rail with any material.
       The reason is set on paper, in the serif, like a note.
       White while it still needs an answer from you — the two surfaces
       do the work a badge would otherwise do. --- */
.request {
  background: var(--color-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  padding: var(--space-14);
  display: flex; flex-direction: column; gap: var(--space-11);
}
.request + .request { margin-top: var(--space-10); }
.request__who { display: flex; align-items: center; gap: var(--space-10); }
.request__name { font-size: var(--text-12-5); font-weight: 500; color: var(--text-ink); }
.request__when { font-size: var(--text-11); color: var(--text-meta); margin-top: 1px; }
.request__why {
  margin: 0;
  font-family: var(--font-display); font-style: italic;
  font-size: var(--text-why); line-height: 1.5;
  color: var(--text-body-muted);
  text-wrap: pretty;
}
.request__actions { display: flex; align-items: center; gap: var(--space-8); }
.request__actions .btn-primary { padding: var(--space-6) var(--space-14); }

/* The authored moment. Accepting settles the note and keeps it. */
.request__kept {
  display: none;
  font-size: var(--text-11-5); line-height: 1.45; color: var(--text-meta);
  border-top: 1px solid var(--border-default);
  padding-top: var(--space-10);
}
.request.is-accepted .request__actions { display: none; }
.request.is-accepted .request__kept { display: block; }
/* Answered, so it drops from raised to recessed and stops asking. */
.request.is-accepted {
  background: var(--color-inset);
  animation: settle var(--duration-settle) var(--ease-settle) both;
}
@keyframes settle {
  from { transform: translateY(-3px); background: var(--color-surface); }
  to   { transform: none;             background: var(--color-inset); }
}

.request__empty { font-family: var(--font-display); font-size: var(--text-read-sm); color: var(--text-body-muted); margin: 0; }

/* The same note, much later. On a person's page the request was answered
   long ago and always has been, so it takes the settled ground without
   the settling — motion belongs to the moment a thing happens, not to
   every time you open the page it ended up on. */
.request--kept { background: var(--color-inset); }

/* ==================================================================
   The date chip — the day marker's motif, boxed.

   Serif numeral over an uppercase month on white paper. It was written
   out twice, identically, for the rail's event row and the room's
   gathering row; this is that one object, at whatever size the context
   asks for. In a page head it takes --size-hero and the numeral grows,
   because there it is the only thing identifying the page.
   ================================================================== */
.datechip,
.event__date,
.gathering__date {
  flex: none; width: var(--size-date-chip);
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  background: var(--color-surface);
  padding: var(--space-5) 0 var(--space-4);
  text-align: center;
}
.datechip__day,
.event__day,
.gathering__day { display: block; font-family: var(--font-display); font-size: var(--text-17); line-height: 1; color: var(--text-ink); }
.datechip__month,
.event__month,
.gathering__month { display: block; margin-top: var(--space-2); font-size: var(--text-10); letter-spacing: 0.09em; text-transform: uppercase; color: var(--text-label); }

/* In a page head: the same chip at the hero square, numeral at the size
   a room's name would be. */
.datechip--lg {
  width: var(--size-hero); height: var(--size-hero);
  border-radius: var(--radius-md);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-3);
  padding: 0;
}
.datechip--lg .datechip__day { font-size: var(--text-room); }
.datechip--lg .datechip__month { margin-top: 0; font-size: var(--text-11); }

/* --- Gathering: the alpha's best object, promoted into the motif --- */
.event {
  display: flex; align-items: flex-start; gap: var(--space-12);
  padding: var(--space-10) 0;
  color: inherit;
}
.event + .event { border-top: 1px solid var(--border-divider); }
.event:hover .event__name { color: var(--green-fill); }
.event__meta { min-width: 0; padding-top: 1px; }
.event__name { display: block; font-size: var(--text-12-5); font-weight: 500; color: var(--text-ink); line-height: 1.35; text-wrap: pretty; }
.event__where { display: block; margin-top: var(--space-3); font-size: var(--text-11-5); color: var(--text-meta); }

/* --- Room --- */
.room { display: flex; align-items: center; gap: var(--space-10); padding: var(--space-8) 0; color: inherit; }
.room + .room { border-top: 1px solid var(--border-divider); }
.room:hover .room__name { color: var(--green-fill); }
.room__cover {
  flex: none; width: var(--size-room-cover); height: var(--size-room-cover);
  border-radius: var(--radius-xs); overflow: hidden;
  background: var(--image-placeholder);
  position: relative;
}
.room__name { font-size: var(--text-12-5); color: var(--text-ink); min-width: 0; }
.room__new { margin-left: auto; flex: none; font-size: var(--text-11); color: var(--text-meta); }

.block__empty { font-size: var(--text-12-5); line-height: 1.5; color: var(--text-meta); margin: 0; text-wrap: pretty; }
/* A reassurance under a populated list — not an empty state. */
.block__note { font-size: var(--text-11-5); line-height: 1.5; color: var(--text-meta); margin: 0; text-wrap: pretty; }

/* ==================================================================
   The plate — one square of graded photography.

   This treatment already existed three times over, written out once per
   context: a room's thumb in the rail, its thumb in the index, and its
   cover on its own page. Naming it collapses those three into one, and
   gives a person's photographs somewhere to live without inventing
   anything: a photograph is the same object, larger.

   Size and radius stay with the context. Only the material is shared.
   ================================================================== */
.plate,
.room__cover,
.room-row__cover,
.page-head__cover {
  position: relative;
  overflow: hidden;
  background: var(--image-placeholder);
}
.plate img,
.room__cover img,
.room-row__cover img,
.page-head__cover img { width: 100%; height: 100%; object-fit: cover; }
/* The warm overlay is what makes every photograph belong to Aurah. */
/* No wash over photographs: they are shown as they are. */

/* --- Someone's photographs: a contact sheet, not a tile wall.
       Three across at reading width is ~200px each — large enough that
       each one is a picture you look at, not a swatch you count. § 9
       allows photography as a subject; the alpha's crime was grids of
       *other people's faces*, which is a different object entirely. --- */
.plates {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--space-8);
}
.plate {
  display: block;
  aspect-ratio: 1;
  border-radius: var(--radius-md);
}

/* ==================================================================
   Fields — the product's first real forms.

   Everything before this was a single unlabelled input inside its own
   object: a search, a filter, a compose. Making a room, a gathering or
   an account needs labelled fields, so there is one field primitive and
   these four pages use nothing else.

   The rule the compose already followed, generalised: **a field is set
   in the face its content will be read in.** A room's description is
   read in the sans on the index, so its field is sans. The sentence you
   write when you ask to know someone is read in serif italic on their
   page forever, so that one is a .compose and not a field at all.
   ================================================================== */
.field { display: flex; flex-direction: column; gap: var(--space-6); }
.field + .field,
.field-row + .field,
.field + .field-row { margin-top: var(--space-20); }

.field__input,
.field__area {
  width: 100%;
  background: var(--color-surface);
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
  padding: var(--space-10) var(--space-12);
  color: var(--text-ink);
  font-size: var(--text-13);
  line-height: var(--leading-body);
  outline: none;
}
.field__input:focus,
.field__area:focus { border-color: var(--border-focus); }
/* A field that states rather than asks. It takes the settled ground, the
   same way an answered request does, so it doesn't sit there looking
   editable. */
.field__input[readonly],
.field__area[readonly] {
  background: var(--color-inset);
  color: var(--text-body-muted);
  cursor: default;
}
.field__area { resize: vertical; min-height: calc(var(--text-13) * var(--leading-body) * 3 + var(--space-20)); }
.field__hint { margin: 0; font-size: var(--text-11-5); line-height: 1.5; color: var(--text-meta); text-wrap: pretty; }
/* Two fields that are one fact — a start time and an end time. */
/* A revealed branch of a form — the fields behind "Online", or behind
   "I'll pay my way in". Spaced like a field, because that is what it is
   a group of. Scoped to div so the same attribute can also drive a
   preview line elsewhere on the page. */
div[data-kind-panel],
div[data-door-panel] { margin-top: var(--space-20); }

.field-row { display: flex; gap: var(--space-12); flex-wrap: wrap; }
.field-row > .field { flex: 1; min-width: 140px; margin-top: 0; }

/* Choose one. .btn-quiet is already the shape; pressed is the only
   state it was missing. */
.choice { display: flex; flex-wrap: wrap; gap: var(--space-8); }
.btn-quiet[aria-pressed="true"] {
  border-color: var(--green-fill);
  color: var(--green-fill);
  background: var(--color-row-active);
}

/* A cover, before there is one. The plate at the size it will be, holding
   nothing — no dashed rectangle, no cloud icon, no drop language. */
.cover-pick { display: flex; align-items: center; gap: var(--space-14); }
.cover-pick .plate { width: var(--size-hero); height: var(--size-hero); flex: none; aspect-ratio: auto; }

/* ==================================================================
   The gate — the one page you see before you are in.

   No bar, no nav, no rail: there is nothing to navigate yet. One
   reading column on the same paper, and the mark doing the work the
   bar does everywhere else.
   ================================================================== */
/* Two columns: the page on the left, and a held space on the right for
   one graphic. The panel is --image-placeholder because that is exactly
   what it is — the ground an image has not been put on yet. It stays
   still while the column scrolls, and below 940px it is simply not
   there: it carries no information. */
.gate {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  /* The row is never shorter than the panel, so a full-height sticky
     panel can't overflow the grid on a short viewport. */
  min-height: 100vh;
}
.gate__col {
  min-width: 0;
  max-width: calc(var(--feed-max) + var(--shell-pad) * 2);
  margin-left: auto;
  padding: var(--space-32) var(--shell-pad) var(--space-64);
}

/* A gate that fits its viewport: the column sits centred between top and
   bottom, so the space above and below it is equal, and the page does not
   scroll. One rhythm throughout — space-24 between elements — doubled to
   space-48 at the three places where the hierarchy actually changes:
   the bar to the mark, the mark to the form, the form to the principles. */
.gate__col--centred {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100vh;
  min-height: 100svh;
  padding-block: var(--space-32);
  gap: var(--space-24);
}

/* The children carry their own margins for the scrolling pages; inside the
   centred column the gap is the only thing setting the rhythm. */
.gate__col--centred > *,
.gate__col--centred .gate__top,
.gate__col--centred .gate__head,
.gate__col--centred .gate__foot,
.gate__col--centred .section-head { margin-top: 0; margin-bottom: 0; }

.gate__col--centred .gate__top { margin-bottom: var(--space-24); }
.gate__col--centred .gate__head { margin-bottom: var(--space-24); }
.gate__col--centred .gate__foot { margin-top: var(--space-24); padding-top: var(--space-24); }
.gate__panel {
  /* The photograph is chosen per visit (lib/photos.ts) and arrives as
     --gate-src. Without one the placeholder colour stands in, so the gate
     still reads correctly before any images are installed. */
  background-color: var(--image-placeholder);
  background-image: var(--gate-src, none);
  background-size: cover;
  background-position: center;
  position: sticky; top: 0;
  align-self: start;
  height: 100vh;
}

/* Signing in is not a footnote. It sits above everything, where someone
   who already has an account looks first. */
.gate__top {
  display: flex; justify-content: flex-end; align-items: baseline; gap: var(--space-8);
  font-size: var(--text-12-5); color: var(--text-meta);
  margin-bottom: var(--space-40);
}
.gate__head { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-16); margin-bottom: var(--space-48); }
.gate__head .blank__sub { max-width: 54ch; }
.gate .section-head { margin-top: var(--space-48); }
.gate form > .section-head:first-child { margin-top: 0; }

@media (max-width: 940px) {
  .gate { grid-template-columns: minmax(0, 1fr); }
  .gate__panel { display: none; }
  .gate__col { margin-inline: auto; }
}
.gate__word {
  font-family: var(--font-display);
  font-size: var(--text-room); line-height: 1;
  color: var(--text-ink); letter-spacing: 0.01em;
}
.gate__foot {
  margin-top: var(--space-48);
  padding-top: var(--space-24);
  border-top: 1px solid var(--border-divider);
  display: flex; flex-direction: column; gap: var(--space-10);
}
.gate__foot p { margin: 0; font-size: var(--text-11-5); line-height: 1.6; color: var(--text-meta); text-wrap: pretty; }

/* ==================================================================
   Avatars — inherited tones, kept monochrome for people
   ================================================================== */
.avatar {
  flex: none;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  color: var(--text-avatar-initials);
  background: var(--avatar-bg);
  overflow: hidden;
}
.avatar--xs { width: var(--size-avatar-xs); height: var(--size-avatar-xs); border-radius: var(--radius-xs); font-size: var(--text-11); }
.avatar--sm { width: var(--size-avatar-sm); height: var(--size-avatar-sm); border-radius: var(--radius-sm); font-size: var(--text-12); }
.avatar--md { width: var(--size-avatar-md); height: var(--size-avatar-md); border-radius: var(--radius-sm); font-size: var(--text-13); }
.avatar--lg { width: var(--size-hero); height: var(--size-hero); border-radius: var(--radius-md); font-size: var(--text-room); font-weight: 400; font-family: var(--font-display); }
.avatar img { width: 100%; height: 100%; object-fit: cover; }

/* ==================================================================
   Empty state — the first fortnight, which the alpha never designed
   ================================================================== */
.blank {
  margin-top: var(--space-32);
  padding: var(--space-48) var(--space-24) var(--space-40);
  border: 1px solid var(--border-divider);
  border-radius: var(--radius-tile);
  background: var(--color-surface);
  display: flex; flex-direction: column; align-items: center; gap: var(--space-14);
  text-align: center;
}
.blank .mark { color: var(--border-input); }
.blank__line { margin: 0; font-family: var(--font-display); font-size: var(--text-blank); line-height: 1.45; color: var(--text-ink); max-width: 30ch; text-wrap: balance; }
.blank__sub { margin: 0; font-size: var(--text-12-5); line-height: 1.55; color: var(--text-meta); max-width: 42ch; text-wrap: pretty; }
.blank__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-8); margin-top: var(--space-4); }

/* ==================================================================
   Adaptation
   ================================================================== */
@media (max-width: 940px) {
  .home { grid-template-columns: minmax(0, 1fr); gap: var(--space-48); }
  .feed { max-width: none; }
  .rail { position: static; display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--space-32); }
}

@media (max-width: 680px) {
  .bar__inner { flex-wrap: wrap; gap: var(--space-12) var(--space-16); }
  .nav { order: 3; flex-basis: 100%; gap: var(--space-2); }
  .bar__end { margin-left: auto; }
  .search { width: clamp(120px, 34vw, 200px); }
  .me span:not(.avatar) { display: none; }
  .rail { grid-template-columns: 1fr; }
  .day { margin: var(--space-32) 0 var(--space-16); }
}

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

/* ==================================================================
   PEOPLE
   The relationships. Not an address book — a ledger, where every
   entry carries the note that started it. There is deliberately no
   total anywhere on this page: a contact count is a score, and the
   product discourages collecting people.
   ================================================================== */

/* --- A section heading inside the reading column.
       The rail uses small uppercase labels; the reading column uses
       the serif, because these head content you read. --- */
.section-head {
  display: flex; align-items: baseline; gap: var(--space-12);
  margin: 0 0 var(--space-16);
}
.section-head__title {
  font-family: var(--font-display); font-weight: 400;
  font-size: var(--text-section); line-height: 1.2;
  color: var(--text-ink);
  flex: none;
}
.section-head__rule { flex: 1; height: 1px; background: var(--border-divider); }
.section-head__note { flex: none; font-size: var(--text-11-5); color: var(--text-meta); }

.people-section + .people-section { margin-top: var(--space-48); }

/* A heading standing directly in the reading column rather than inside a
   .people-section — which is how a section containing a compose has to be
   built, since opacity cannot skip an ancestor. It still owes the column
   the same air a section does. */
.feed > .section-head:not(:first-child) { margin-top: var(--space-48); }

/* --- Incoming request at reading width.
       Same component as the rail's, given room to breathe. --- */
.request--wide { padding: var(--space-18) var(--space-20); gap: var(--space-14); }
.request--wide .request__why { font-size: var(--text-read-sm); }
.request--wide .request__actions { margin-top: var(--space-2); }

/* --- Set aside. Nothing is ever rejected or deleted; it waits,
       reversibly, behind a disclosure. --- */
.aside-set { margin-top: var(--space-16); }
.aside-set > summary {
  cursor: pointer; list-style: none;
  display: inline-flex; align-items: center; gap: var(--space-6);
  font-size: var(--text-12-5); color: var(--green-link);
  padding: var(--space-4) 0;
}
.aside-set > summary::-webkit-details-marker { display: none; }
.aside-set > summary:hover { color: var(--green-link-hover); }
.aside-set > summary::after {
  content: ""; width: 5px; height: 5px; margin-left: var(--space-2);
  border-right: 1px solid currentColor; border-bottom: 1px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
}
.aside-set[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.aside-set__body { padding-top: var(--space-12); display: flex; flex-direction: column; gap: var(--space-10); }
.aside-set__item {
  display: flex; flex-direction: column; gap: var(--space-4);
  padding: var(--space-12) var(--space-14);
  border: 1px dashed var(--border-input); border-radius: var(--radius-md);
}
.aside-set__name { font-size: var(--text-12-5); font-weight: 500; color: var(--text-body-muted); }
.aside-set__why { margin: 0; font-family: var(--font-display); font-style: italic; font-size: var(--text-why); color: var(--text-meta); }
.aside-set__act { align-self: flex-start; margin-top: var(--space-4); font-size: var(--text-12); color: var(--green-link); }

/* --- Filter + order.
       Filtering matches the name AND the reason you met, which is the
       point: you can find someone by what you remember about them. --- */
.listctl {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: var(--space-12);
  margin-bottom: var(--space-8);
}
.filter {
  display: flex; align-items: center; gap: var(--space-8);
  background: var(--color-surface);
  border: 1px solid var(--border-input); border-radius: var(--radius-md);
  padding: var(--space-6) var(--space-11);
  flex: 1 1 260px; min-width: 0;
}
.filter:focus-within { border-color: var(--border-focus); }
.filter svg { flex: none; stroke: var(--text-meta); }
.filter input {
  flex: 1; min-width: 0; border: 0; background: transparent; outline: none;
  color: var(--text-ink); font-size: var(--text-12-5);
}
.order { display: flex; align-items: center; gap: var(--space-4); flex: none; }
.order__btn {
  font-size: var(--text-12); color: var(--text-meta);
  padding: var(--space-4) var(--space-8); border-radius: var(--radius-xs);
}
.order__btn:hover { color: var(--green-fill); background: var(--color-row-hover); }
.order__btn[aria-pressed="true"] { color: var(--text-ink); background: var(--color-row-active); }

.listctl__status { flex-basis: 100%; font-size: var(--text-11-5); color: var(--text-meta); }
.listctl__status:empty { display: none; }

/* --- The ledger --- */
/* Rows — the one list primitive, shared by the ledger, the conversation
   list, the room index and a room's topics. Hairline-separated rows
   directly on the page ground: no container, no header bar, no zebra.
   Those need a box and a white surface, and both belong to the design
   this one replaced. */
.rows { list-style: none; margin: 0; padding: 0; }
.rows > li { border-top: 1px solid var(--border-divider); }
.rows > li:last-child { border-bottom: 1px solid var(--border-divider); }

.person__link,
.pick-row {
  display: flex; align-items: flex-start; gap: var(--space-12);
  padding: var(--space-14) var(--space-8);
  color: inherit;
}
.person__link:hover { background: var(--color-row-hover); }
.person__link:hover .person__name { color: var(--green-fill); }
.person__body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: var(--space-3); }
.person__name { font-size: var(--text-13); font-weight: 500; color: var(--text-ink); }
.person__why {
  font-family: var(--font-display); font-style: italic;
  font-size: var(--text-why); line-height: 1.45; color: var(--text-body-muted);
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden;
}
.person__met { flex: none; font-size: var(--text-11-5); color: var(--text-meta); padding-top: var(--space-2); }

/* A row you act on rather than follow: a person, and the button that
   invites them. Same geometry as a ledger entry, no hover, because the
   row itself goes nowhere. */
.pick-row { align-items: center; }
.pick-row .btn-quiet { flex: none; }

.rows__none {
  margin: var(--space-24) 0 0;
  font-family: var(--font-display); font-size: var(--text-read-sm);
  color: var(--text-body-muted);
}

/* --- Rail: an open conversation --- */
.convo { display: flex; align-items: flex-start; gap: var(--space-10); padding: var(--space-10) 0; color: inherit; }
.convo + .convo { border-top: 1px solid var(--border-divider); }
.convo:hover .convo__name { color: var(--green-fill); }
.convo__body { min-width: 0; flex: 1; }
.convo__name { display: block; font-size: var(--text-12-5); font-weight: 500; color: var(--text-ink); }
.convo__last {
  display: block; margin-top: var(--space-2);
  font-family: var(--font-display); font-style: italic;
  font-size: var(--text-why); line-height: 1.4; color: var(--text-meta);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.convo__when { flex: none; font-size: var(--text-11); color: var(--text-meta); padding-top: var(--space-2); }

/* --- Rail: dormant.
       Stated, never nagged. No count, no badge, no call to action. --- */
.dormant { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-10); padding: var(--space-8) 0; color: inherit; }
.dormant + .dormant { border-top: 1px solid var(--border-divider); }
.dormant:hover .dormant__name { color: var(--green-fill); }
.dormant__name { font-size: var(--text-12-5); color: var(--text-ink); min-width: 0; }
.dormant__since { flex: none; font-size: var(--text-11); color: var(--text-meta); }

/* --- Rail: a request you sent. No action — it is their turn. --- */
.sent { padding: var(--space-10) 0; display: flex; flex-direction: column; gap: var(--space-4); }
.sent + .sent { border-top: 1px solid var(--border-divider); }
.sent__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-10); }
.sent__name { font-size: var(--text-12-5); font-weight: 500; color: var(--text-ink); }
.sent__when { flex: none; font-size: var(--text-11); color: var(--text-meta); }
.sent__why {
  margin: 0; font-family: var(--font-display); font-style: italic;
  font-size: var(--text-why); line-height: 1.45; color: var(--text-meta);
}

/* ==================================================================
   CONVERSATIONS
   You can only write to someone who agreed to know you, so there is
   no discovery step and no cold message. The address book is the
   ledger, which means starting a conversation needs a field, not a
   picker: type a name — or a word from how you met — and write.

   Deliberately absent: read receipts and typing indicators. Both
   manufacture the pressure this product exists to remove.
   ================================================================== */

/* --- Write to someone. A combobox, not a modal: nothing overlays
       the page, and the keyboard drives all of it. --- */
.starter { position: relative; margin-bottom: var(--space-18); }
.starter__field {
  display: flex; align-items: center; gap: var(--space-10);
  background: var(--color-surface);
  border: 1px solid var(--border-input); border-radius: var(--radius-md);
  padding: var(--space-11) var(--space-14);
}
.starter__field:focus-within { border-color: var(--border-focus); }
.starter__field svg { flex: none; stroke: var(--text-meta); }
.starter__input {
  flex: 1; min-width: 0; border: 0; background: transparent; outline: none;
  font-family: var(--font-display); font-size: var(--text-read);
  line-height: 1.3; color: var(--text-ink);
}

.starter__results {
  list-style: none; margin: var(--space-6) 0 0; padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--border-default); border-radius: var(--radius-md);
  max-height: 306px; overflow-y: auto;
}
.starter__option {
  display: flex; align-items: flex-start; gap: var(--space-10);
  padding: var(--space-10) var(--space-11);
  border-radius: var(--radius-xs);
  cursor: pointer;
}
.starter__option[aria-selected="true"] { background: var(--color-row-active); }
.starter__option:hover { background: var(--color-row-hover); }
.starter__body { min-width: 0; flex: 1; }
.starter__name { display: block; font-size: var(--text-12-5); font-weight: 500; color: var(--text-ink); }
.starter__why {
  display: block; margin-top: var(--space-2);
  font-family: var(--font-display); font-style: italic;
  font-size: var(--text-why); line-height: 1.4; color: var(--text-meta);
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
}
.starter__none { padding: var(--space-12) var(--space-11); font-size: var(--text-12-5); color: var(--text-meta); }

/* --- A conversation in the list --- */
.convo-row {
  display: flex; align-items: flex-start; gap: var(--space-12);
  padding: var(--space-14) var(--space-8);
  color: inherit;
}
.convo-row:hover { background: var(--color-row-hover); }
.convo-row:hover .convo-row__name { color: var(--green-fill); }
.convo-row[aria-current="true"] { background: var(--color-row-active); }
.convo-row__body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: var(--space-3); }
.convo-row__name { font-size: var(--text-13); font-weight: 500; color: var(--text-ink); }
.convo-row__last {
  font-family: var(--font-display); font-style: italic;
  font-size: var(--text-why); line-height: 1.45; color: var(--text-body-muted);
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
}
.convo-row__when { flex: none; font-size: var(--text-11-5); color: var(--text-meta); padding-top: var(--space-2); }
.convo-row__yours { color: var(--text-meta); }

/* ==================================================================
   The conversation screen — two panes.
   The page still scrolls: the list pane is sticky, the thread is the
   document. No overflow:hidden anywhere, per DESIGN_SYSTEM.md § 6.
   ================================================================== */
.convos {
  position: relative; z-index: 1;
  max-width: var(--shell-max);
  margin-inline: auto;
  padding: var(--space-32) var(--shell-pad) var(--space-48);
  display: grid;
  grid-template-columns: var(--convo-list-w) minmax(0, 1fr);
  gap: var(--gutter);
  align-items: start;
}
.convos__list {
  min-width: 0;
  position: sticky; top: var(--rail-top);
  display: flex; flex-direction: column; gap: var(--space-14);
}
.convos__thread { min-width: 0; }

/* --- Who you are reading --- */
.thread-head {
  display: flex; align-items: center; gap: var(--space-12);
  padding-bottom: var(--space-16);
  border-bottom: 1px solid var(--border-default);
}
.thread-head__body { min-width: 0; flex: 1; }
.thread-head__name { display: block; font-family: var(--font-display); font-size: var(--text-section); line-height: 1.2; color: var(--text-ink); }
.thread-head__why {
  display: block; margin-top: var(--space-4);
  font-family: var(--font-display); font-style: italic;
  font-size: var(--text-why); color: var(--text-meta);
}
.thread-head__act { flex: none; font-size: var(--text-12-5); color: var(--green-link); }

/* --- Correspondence, not bubbles.
       No alignment flip, no tails, no containers. Turns are separated
       by space and named, the way a transcript is. --- */
.thread__earlier { display: block; margin: var(--space-24) 0 var(--space-8); font-size: var(--text-12-5); color: var(--green-link); }

/* Turns are boxes of identical geometry; only the ground differs, so the
   text of both voices starts on exactly the same left edge. The ground
   bleeds wider than the measure, which reads as a passage set on paper
   rather than as a bubble — no tail, no indent, no alignment flip. */
.turn {
  margin: var(--space-16) calc(var(--space-16) * -1) 0;
  padding: var(--space-14) var(--space-16);
  border-radius: var(--radius-md);
}
.turn--theirs { background: var(--color-passage); }
.turn__who { display: flex; align-items: baseline; gap: var(--space-10); margin-bottom: var(--space-6); }
.turn__name { font-size: var(--text-12-5); font-weight: 500; color: var(--text-ink); }
.turn__time { font-size: var(--text-11-5); color: var(--text-meta); }
.turn__body {
  margin: 0;
  font-family: var(--font-display); font-size: var(--text-read);
  line-height: var(--leading-read); color: var(--text-ink);
  text-wrap: pretty;
  white-space: pre-wrap;
}
.turn__body + .turn__body { margin-top: var(--space-10); }
/* Your own turns sit on the page itself and read a step quieter — you
   already know what you said, and the eye should fall on their reply. */
.turn--mine { background: transparent; }
.turn--mine .turn__name { color: var(--text-body-muted); }
.turn--mine .turn__body { color: var(--text-body-muted); }

/* --- Write back. Sticky to the bottom of the viewport so a long
       correspondence never means scrolling to answer. --- */
.reply {
  position: sticky; bottom: 0;
  margin: var(--space-32) calc(var(--space-16) * -1) 0;
  padding: var(--space-16) var(--space-16) var(--space-20);
  background: var(--color-page-bg);
}
.reply__card {
  background: var(--color-surface);
  border: 1px solid var(--border-default); border-radius: var(--radius-tile);
  padding: var(--space-14) var(--space-16);
  display: flex; flex-direction: column; gap: var(--space-12);
}
.reply__card:focus-within { border-color: var(--border-focus); }
.reply__input {
  border: 0; outline: none; resize: none; background: transparent;
  font-family: var(--font-display); font-size: var(--text-read);
  line-height: var(--leading-read); color: var(--text-ink);
  height: calc(var(--text-read) * var(--leading-read) * 2);
}
.reply__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-12); }
.reply__hint { font-size: var(--text-11-5); color: var(--text-meta); }

@media (max-width: 940px) {
  .convos { grid-template-columns: minmax(0, 1fr); gap: var(--space-32); }
  .convos__list { position: static; }
}

/* ==================================================================
   ROOMS
   A room is a community, and the shape it wants is the one forums
   already solved: a table you can read at a glance — name, what it
   is, who spoke last, and when. Density is the warmth here, so this
   is the one place the reading column takes material instead of
   losing it. Boards sit on paper; everything else stays on cream.

   What comes back from that era: descriptions on everything, visible
   rules, named moderators, "last by X", zebra rows, real categories.
   What does not: post-count ranks, signatures, reputation, presence.
   ================================================================== */


/* --- A room in the index --- */
.room-row { display: flex; align-items: flex-start; gap: var(--space-14); padding: var(--space-14) var(--space-8); color: inherit; }
.room-row:hover { background: var(--color-row-hover); }
.room-row:hover .room-row__name { color: var(--green-fill); }
.room-row__cover {
  flex: none; width: var(--size-room-thumb); height: var(--size-room-thumb);
  border-radius: var(--radius-xs); overflow: hidden;
  background: var(--image-placeholder); position: relative;
}
.room-row__body { min-width: 0; flex: 1; }
.room-row__name { display: block; font-family: var(--font-display); font-size: var(--text-17); line-height: 1.2; color: var(--text-ink); }
.room-row__desc { display: block; margin-top: var(--space-3); font-size: var(--text-12-5); line-height: 1.45; color: var(--text-body-muted); text-wrap: pretty; }
.room-row__last { display: block; margin-top: var(--space-6); font-size: var(--text-11-5); color: var(--text-meta); }
.room-row__side { flex: none; text-align: right; padding-top: var(--space-2); }
.room-row__size { display: block; font-size: var(--text-11-5); color: var(--text-meta); }
.room-row__in { display: block; margin-top: var(--space-4); font-size: var(--text-11); color: var(--green-link); }

/* --- A topic in a room. The forum row, kept whole:
       title, who started it, how much discussion, who spoke last. --- */
.topic-row { display: flex; align-items: baseline; gap: var(--space-16); padding: var(--space-14) var(--space-8); color: inherit; }
.topic-row:hover { background: var(--color-row-hover); }
.topic-row:hover .topic-row__title { color: var(--green-fill); }
.topic-row__main { min-width: 0; flex: 1; }
.topic-row__title { display: block; font-family: var(--font-display); font-size: var(--text-17); line-height: 1.25; color: var(--text-ink); text-wrap: pretty; }
.topic-row__byline { display: block; margin-top: var(--space-4); font-size: var(--text-11-5); color: var(--text-meta); }
.topic-row__side { flex: none; text-align: right; }
.topic-row__replies { display: block; font-size: var(--text-12-5); color: var(--text-body-muted); white-space: nowrap; }
.topic-row__last { display: block; margin-top: var(--space-3); font-size: var(--text-11); color: var(--text-meta); white-space: nowrap; }

/* A pinned or closed topic says so in words, not an icon nobody can read. */
.topic-tag {
  display: inline-block; margin-right: var(--space-8);
  font-family: var(--font-ui);
  font-size: var(--text-10); letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--text-label);
  border: 1px solid var(--border-input); border-radius: var(--radius-xs);
  padding: 1px var(--space-5);
  vertical-align: 2px;
}
.topic-row--closed .topic-row__title { color: var(--text-body-muted); }

/* --- The head of a page that is about one thing: a room, or a person.
       Same geometry either way — a 76px square, then the name in the
       serif at --text-room, a description, a meta line, and a side
       column for what you can do here. A room puts its cover in the
       square; a person puts an avatar at the same size. --- */
.page-head { display: flex; align-items: flex-start; gap: var(--space-18); padding-bottom: var(--space-20); border-bottom: 1px solid var(--border-default); }
.page-head__cover {
  flex: none; width: var(--size-hero); height: var(--size-hero);
  border-radius: var(--radius-md); overflow: hidden;
  background: var(--image-placeholder); position: relative;
}
.page-head__body { min-width: 0; flex: 1; }
.page-head__name { margin: 0; font-family: var(--font-display); font-weight: 400; font-size: var(--text-room); line-height: 1.15; color: var(--text-ink); }
.page-head__desc { margin: var(--space-8) 0 0; font-size: var(--text-13); line-height: 1.55; color: var(--text-body-muted); max-width: 56ch; text-wrap: pretty; }
.page-head__meta { margin-top: var(--space-10); font-size: var(--text-11-5); color: var(--text-meta); }
.page-head__side { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-6); }
.page-head__in { font-size: var(--text-11-5); color: var(--text-meta); }

/* --- A gathering. Meetup's job, without the machinery around it. --- */
.gathering { display: flex; align-items: flex-start; gap: var(--space-16); padding: var(--space-16) var(--space-8); color: inherit; }
.gathering__body { min-width: 0; flex: 1; }
.gathering__name { display: block; font-family: var(--font-display); font-size: var(--text-17); line-height: 1.25; color: var(--text-ink); }
.gathering__where { display: block; margin-top: var(--space-3); font-size: var(--text-12); color: var(--text-meta); }
.gathering__note { margin: var(--space-8) 0 0; font-size: var(--text-12-5); line-height: 1.55; color: var(--text-body-muted); max-width: 56ch; text-wrap: pretty; }
/* A control, and the sentence saying what pressing it does. Under a
   gathering row, under a form, under a download. */
.act-row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-14); margin-top: var(--space-10); }
.field + .act-row,
.rows + .act-row,
.record + .act-row { margin-top: var(--space-24); }
.gathering__going,
.act-row__note { font-size: var(--text-11-5); line-height: 1.5; color: var(--text-meta); text-wrap: pretty; }

/* --- The room's record. Small caps, hairlines, tabular values —
       the archival density the alpha's about-card almost had. --- */
.record { display: flex; flex-direction: column; gap: var(--space-8); }
.record__row { display: flex; gap: var(--space-10); align-items: baseline; }
.record__label {
  flex: none; width: var(--record-label-w);
  font-size: var(--text-10); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-label);
}
.record__value { min-width: 0; flex: 1; font-size: var(--text-12-5); line-height: 1.4; color: var(--text-ink); }
.record__value a { color: var(--green-link); }
.record__people {
  display: flex; flex-wrap: wrap; gap: var(--space-4) var(--space-8);
  font-size: var(--text-12-5); line-height: 1.4;
}

/* --- Recent activity: the human trace that made a forum feel inhabited --- */
.section-after { margin: var(--space-14) 0 0; font-size: var(--text-11-5); line-height: 1.5; color: var(--text-meta); }

.trace { display: flex; align-items: baseline; gap: var(--space-10); padding: var(--space-8) 0; }
.trace + .trace { border-top: 1px solid var(--border-divider); }
.trace__text { min-width: 0; flex: 1; font-size: var(--text-12); line-height: 1.45; color: var(--text-body-muted); text-wrap: pretty; }
.trace__text a { color: var(--green-link); }
.trace__when { flex: none; font-size: var(--text-11); color: var(--text-meta); }

@media (max-width: 620px) {
  .topic-row { flex-direction: column; gap: var(--space-6); }
  .topic-row__side { text-align: left; }
  .topic-row__last { display: inline-block; margin: 0 0 0 var(--space-8); }
  .room-row__side { display: none; }
  .page-head { flex-wrap: wrap; }
  .page-head__side { align-items: flex-start; }
}
