/* Swarm — screen layer. tokens.css holds the world; this holds the rooms.
   Nothing here invents a value: every colour, size, radius and gap is a token from
   tokens.css, because DESIGN.md's spacing rhythm (4 8 16 24 32 48 72) and its 1px/2px
   /3px radius vocabulary are the whole reason the interface reads as one piece of
   stock rather than a dashboard. A 12px gap or a 6px radius in here is a bug. */

.wrap { max-width: 1060px; margin: 0 auto; padding: 0 var(--s-3); }
@media (max-width: 820px) { .wrap { padding: 0 var(--s-2); } }

/* ==================================================================== the spine
   The signed-in shell is a folder spine on the left and the page beside it.
   It replaced a row of tabs across the top for three reasons, in order of how
   much they cost:

   1. A horizontal tab strip is a fixed budget. Eight destinations already filled
      it at 1024px and scrolled off the edge at phone width with no affordance
      saying so — Projects was simply invisible and nothing told you. A vertical
      list has room to grow and room to GROUP, which is what turns eight equal
      tabs into "three things you live in and five you visit".
   2. The centred 1060px column left ~380px of empty board on a 1440 screen while
      every list row inside it truncated. This is a tool people read lists in all
      day; the width belongs to the list.
   3. Where you are should not move. A tab strip reflows as counts change.

   The selected item is a divider tab turned on its side: page-tone fill, hairline,
   top and bottom corners rounded away from the page, and the right border removed
   so the tab and the page read as one piece of stock. Same silhouette as the
   horizontal tab it replaces, same reason. It is NOT a coloured left border — that
   is forbidden, and the tonal step is the system's answer for exactly this job. */

.app {
  display: grid;
  grid-template-columns: var(--rail-w, 236px) minmax(0, 1fr);
  min-height: 100vh;
  align-items: start;
}
:root { --rail-w: 236px; }
:root[data-rail="collapsed"] { --rail-w: 60px; }

.rail {
  position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column;
  background: var(--rail);
  border-right: 1px solid var(--hairline);
  padding: var(--s-2) 0 var(--s-1);
  overflow: hidden auto;
  scrollbar-width: thin;
}
.rail__brand {
  display: flex; align-items: baseline; gap: var(--s-1);
  font-size: var(--t-18); font-weight: 800; letter-spacing: -0.01em;
  color: var(--text); padding: 0 var(--s-2) var(--s-2);
  min-height: 36px;
}
.rail__seal {
  font-family: var(--font-mono); font-size: var(--t-11); font-weight: 700;
  letter-spacing: 0.08em; padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--gold); color: var(--on-gold);
}
.rail__group { padding: var(--s-2) 0 0; }
.rail__group-label {
  font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint);
  padding: 0 var(--s-2) var(--s-0);
}
.rail__item {
  display: flex; align-items: center; gap: var(--s-1);
  min-height: 36px; padding: 0 var(--s-2);
  margin-left: var(--s-1);
  color: var(--muted); text-decoration: none;
  font-size: var(--t-14); font-weight: 600;
  border: 1px solid transparent; border-right: none;
  border-radius: var(--r-spine);
  white-space: nowrap;
}
.rail__item:hover { background: var(--sunken); color: var(--text); }
.rail__item[aria-current="page"] {
  background: var(--surface); color: var(--text); font-weight: 700;
  border-color: var(--hairline);
}
.rail__item:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
/* The glyph is a Courier mark, not an icon font and not an emoji — the system has
   one mono face and marks are set in it. */
.rail__mark { flex: none; width: 18px; height: 18px; }
.rail__item[aria-current="page"] .rail__mark { color: var(--gold-ink); }
.rail__label { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; }
.rail__n {
  font-family: var(--font-mono); font-size: var(--t-11); font-weight: 700;
  color: var(--muted); flex: none;
}
.rail__item[aria-current="page"] .rail__n { color: var(--text); }
.rail__spacer { flex: 1 1 auto; min-height: var(--s-2); }
.rail__foot {
  display: flex; flex-direction: column; gap: 2px;
  padding-top: var(--s-1); border-top: 1px solid var(--hairline);
  margin-top: var(--s-2);
}
.rail__who {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--faint);
  padding: var(--s-0) var(--s-2); overflow: hidden; text-overflow: ellipsis;
}

/* Collapsed: marks and counts only. The label is removed from the accessibility
   tree too, not merely hidden, because a name read aloud that nobody can see is
   worse than the title attribute that replaces it. */
:root[data-rail="collapsed"] .rail__label,
:root[data-rail="collapsed"] .rail__group-label,
:root[data-rail="collapsed"] .rail__who,
:root[data-rail="collapsed"] .rail__brand span:not(.rail__seal) { display: none; }
:root[data-rail="collapsed"] .rail__brand { padding: 0 0 var(--s-2); justify-content: center; }
:root[data-rail="collapsed"] .rail__item { padding: 0; justify-content: center; margin-left: 0; }
:root[data-rail="collapsed"] .rail__n {
  position: absolute; margin-left: 26px; margin-top: -14px;
  font-size: var(--t-11);
}
:root[data-rail="collapsed"] .rail__item { position: relative; }

/* Air around the content, not inside the rows.
   The three tools Arvind put up are not spacious because they are white — their
   ROWS are as tight as these. What has room is the chrome: page margins, the gap
   between regions, the header. So the gutters grow and the row padding does not,
   because a row is the thing you scan and every pixel of padding in one is a row
   you cannot see. */
.main { min-width: 0; padding: 0 var(--s-4) var(--s-6); }
.main__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-1); min-height: 56px;
  border-bottom: 1px solid var(--hairline); margin-bottom: var(--s-4);
  position: sticky; top: 0; z-index: 4; background: var(--canvas);
}
.main__bar-left { display: flex; align-items: center; gap: var(--s-1); min-width: 0; }
.main__bar-right { display: flex; align-items: center; gap: var(--s-0); }
.main__inner { max-width: 1440px; }

.rail__toggle {
  display: flex; align-items: center; gap: var(--s-1);
  min-height: 36px; padding: 0 var(--s-2); margin-left: var(--s-1);
  background: none; border: 1px solid transparent; border-radius: var(--r-spine);
  color: var(--faint); font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: 0.14em; text-transform: uppercase; cursor: pointer;
  text-align: left; width: calc(100% - var(--s-1));
}
.rail__toggle:hover { background: var(--sunken); color: var(--text); }
.rail__toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
:root[data-rail="collapsed"] .rail__toggle { justify-content: center; padding: 0; margin-left: 0; width: 100%; }

/* The menu button and the scrim exist only at phone width. */
.rail__scrim { display: none; }
#rail-open { display: none; }

@media (max-width: 1100px) {
  :root { --rail-w: 60px; }
}

/* Below 820 the rail is a drawer over the page rather than a column beside it.
   Reusing the same markup rather than building a second navigation is deliberate:
   two navigations drift, and the one on the phone is the one that gets forgotten. */
@media (max-width: 820px) {
  .app { grid-template-columns: minmax(0, 1fr); }
  .rail {
    position: fixed; inset: 0 auto 0 0; width: 264px; z-index: 30;
    background: var(--rail);
    box-shadow: 0 18px 44px oklch(22% 0.015 265 / 0.16);
    transform: translateX(-100%); transition: transform var(--d-panel) var(--e);
  }
  :root[data-rail-open="1"] .rail { transform: none; }
  :root[data-rail="collapsed"] .rail__label,
  :root[data-rail="collapsed"] .rail__group-label,
  :root[data-rail="collapsed"] .rail__who,
  :root[data-rail="collapsed"] .rail__brand span:not(.rail__seal) { display: revert; }
  :root[data-rail="collapsed"] .rail__item { padding: 0 var(--s-2); justify-content: flex-start; margin-left: var(--s-1); }
  :root[data-rail="collapsed"] .rail__n { position: static; margin: 0; }
  :root[data-rail="collapsed"] .rail__brand { padding: 0 var(--s-2) var(--s-2); justify-content: flex-start; }
  .rail__toggle { display: none; }
  #rail-open { display: inline-flex; }
  :root[data-rail-open="1"] .rail__scrim {
    display: block; position: fixed; inset: 0; z-index: 20;
    background: oklch(22% 0.015 265 / 0.38);
  }
  .main { padding: 0 var(--s-2) var(--s-5); }
}
@media (prefers-reduced-motion: reduce) { .rail { transition: none; } }

/* ------------------------------------------------------------- the bundle cover */
.topbar {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-2); padding-top: var(--s-2);
  border-bottom: 1px solid var(--hairline);
}
.mark {
  display: flex; align-items: baseline; gap: var(--s-1);
  font-size: var(--t-20); font-weight: 800; letter-spacing: -0.01em;
  color: var(--text); padding-bottom: var(--s-2);
}
.mark__seal {
  font-family: var(--font-mono); font-size: var(--t-11); font-weight: 700;
  letter-spacing: 0.08em; padding: 2px 6px; border-radius: var(--r-xs);
  background: var(--gold); color: var(--on-gold); transform: translateY(-2px);
}
.topbar__right {
  display: flex; align-items: center; gap: var(--s-1); padding-bottom: var(--s-1);
}
/* At phone width the name and workspace wrap onto two lines and crowd the seal, and
   neither is information the person needs while working — they know who they are.
   The theme control stays, because that one is a choice. */
@media (max-width: 560px) { #whoami { display: none; } }

/* The divider tab: the system's one curved form, top corners only, sitting flush on
   the stock it indexes. Used for navigation because that is literally what a tab
   index is for. */
.tab, .sw-nav__tab {
  font-family: var(--font-mono); font-size: var(--t-11);
  text-transform: uppercase; letter-spacing: 0.14em;
  background: var(--sunken); color: var(--muted);
  border: 1px solid var(--hairline); border-bottom: none;
  border-radius: var(--r-tab);
  padding: 5px 10px 6px;
}
.sw-nav {
  display: flex; gap: var(--s-0); overflow-x: auto;
  padding: var(--s-2) 0 0 var(--s-1);
  border-bottom: 1px solid var(--hairline);
  margin-bottom: var(--s-3);
  scrollbar-width: none;
}
.sw-nav::-webkit-scrollbar { display: none; }
.sw-nav__tab {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 36px; text-decoration: none; white-space: nowrap;
  margin-bottom: -1px; cursor: pointer;
}
.sw-nav__tab:hover { color: var(--text); }
.sw-nav__tab[aria-current="page"] {
  background: var(--surface); color: var(--text); border-bottom: 1px solid var(--surface);
}
.sw-nav__n {
  font-size: var(--t-11); font-weight: 700; letter-spacing: 0.04em;
  color: var(--muted);
}
.sw-nav__tab[aria-current="page"] .sw-nav__n { color: var(--text); }

/* --------------------------------------------------------------------- headings */
.page { padding-bottom: var(--s-6); }
.page__head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-2); flex-wrap: wrap; margin-bottom: var(--s-4);
}
.page__head h1 { margin: 0; }          /* one Display element per screen */
.page__asof {
  font-family: var(--font-mono); font-size: var(--t-12); color: var(--faint);
}
.hero { padding: var(--s-5) 0 var(--s-4); max-width: 660px; }
.hero h1 { margin-bottom: var(--s-2); }
.hero p { font-size: var(--t-18); color: var(--muted); margin: 0 0 var(--s-3); }

.grid { display: grid; gap: var(--s-2); grid-template-columns: repeat(3, 1fr); padding-bottom: var(--s-5); }
@media (max-width: 820px) { .grid { grid-template-columns: 1fr; } }
.card-title { font-family: var(--font-ui); font-size: var(--t-16); font-weight: 700; color: var(--text); margin: 0 0 var(--s-1); }
.card-body { color: var(--muted); font-size: var(--t-14); margin: 0; }

.state { display: none; }
.state--on { display: block; }
/* The shell is a grid when it is on; `display: block` from .state--on would
   collapse the rail onto the page. An author display rule beats the generic one
   (I-012's sibling), so the more specific selector has to exist. */
.state--on.app { display: grid; }
#cover[hidden] { display: none; }

/* ---------------------------------------------------------------------- banners */
.banner {
  border: 1px solid var(--risk); background: var(--surface);
  border-radius: var(--r-sm); padding: var(--s-2); margin: var(--s-3) 0;
  font-size: var(--t-14); color: var(--text);
  display: flex; gap: var(--s-1); align-items: flex-start;
}
/* An author `display` rule beats the UA rule for [hidden] (I-012), so an empty
   banner renders on every clean load unless this is said explicitly. */
.banner[hidden] { display: none; }
.banner__mark { font-family: var(--font-mono); font-weight: 700; color: var(--risk); flex: none; }
.banner--ok { border-color: var(--ok); }
.banner--ok .banner__mark { color: var(--ok); }

/* --------------------------------------------------------------------- sections */
.sw-section { margin-bottom: var(--s-5); }
.sw-section__tabs { display: flex; padding-left: var(--s-2); }
.sw-section__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-2); padding: var(--s-2) var(--s-2) var(--s-1);
  background: var(--surface);
  border: 1px solid var(--hairline); border-bottom: none;
  border-top-left-radius: 0;
}
.sw-section__head h2 { font-size: var(--t-18); font-weight: 700; }
.sw-section__note { font-size: var(--t-13); color: var(--muted); }
.sw-section__body {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 0 var(--r-sm) var(--r-sm) var(--r-sm);
  padding: 0 var(--s-2);
}

/* ------------------------------------------------- the ruled index: a bundle row */
/* The row is a container now, not a link: it holds a tick and a link, and a
   button inside an anchor is invalid markup and a click trap besides. */
.sw-row {
  display: grid; grid-template-columns: 26px 1fr; align-items: start;
  border-bottom: 1px solid var(--hairline);
}
.sw-row:last-child { border-bottom: 0; }
.sw-row:hover { background: var(--sunken); }
.sw-row__main {
  display: grid;
  grid-template-columns: 132px 96px 1fr auto;
  gap: var(--s-2); align-items: baseline;
  padding: 11px 0; font-size: var(--t-14); text-decoration: none; color: inherit;
  min-width: 0;
}
.sw-row__main--grouped { grid-template-columns: 96px 1fr auto; }
.sw-row__main:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* The tick. A square that fills when the thing is done — the one place in this
   system where a square is a CONTROL rather than a document, because that is what
   a checkbox is everywhere and inventing a new shape for it would be cleverness
   at a person's expense.

   Disabled is 0.3 and keeps its border: a tick you cannot use must still show you
   there is a tick, or the column looks broken on exactly the rows where the state
   machine is doing its job. */
.sw-tick {
  appearance: none; -webkit-appearance: none;
  margin: 12px 0 0; padding: 0;
  width: 17px; height: 17px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1.5px solid var(--muted);
  border-radius: var(--r-xs); color: var(--st-done);
  cursor: pointer;
}
.sw-tick:hover:not(:disabled) { border-color: var(--st-done); background: var(--st-done-bg); }
.sw-tick:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.sw-tick[aria-pressed="true"] { border-color: var(--st-done); background: var(--st-done-chip); }
.sw-tick:disabled { opacity: 0.3; cursor: default; }
.sw-row__code {
  font-family: var(--font-mono); font-size: var(--t-13); color: var(--muted);
}
.sw-row__title { color: var(--text); font-weight: 600; }
.sw-row__where { color: var(--muted); font-size: var(--t-13); }
/* The owner is in the right column on a pointer screen and on the meta line
   on a phone. Rendered once, shown in one place or the other. */
.sw-row__who-sm { display: none; }
.sw-row__right {
  display: flex; align-items: baseline; gap: var(--s-2); justify-self: end;
  font-family: var(--font-mono); font-size: var(--t-13); color: var(--muted);
  white-space: nowrap;
}
.sw-row__date--late { color: var(--risk); font-weight: 700; }
.sw-row__who { font-family: var(--font-ui); font-size: var(--t-13); }

/* A phone row used to stack every field onto its own line: state, code, title,
   facets, two lines of project, then owner and date. Six lines per item, four
   items a screen. "Running the day from a phone" is a product principle, and four
   items is not a day.

   The same four fields, arranged as a card rather than a column: state and code
   and date on one line, the title on its own, everything else on a third. Three
   lines, eight items a screen, and the date — the thing you are scanning for —
   sits at a fixed right edge instead of hiding at the bottom of a stack. */
@media (max-width: 820px) {
  .sw-row {
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      "status code   date"
      "title  title  title"
      "meta   meta   meta";
    gap: 2px var(--s-1);
    padding: var(--s-1) 0;
  }
  .sw-row > :nth-child(1) { grid-area: status; }
  .sw-row__code { grid-area: code; }
  .sw-row > :nth-child(3) { grid-area: title; }
  .sw-row__right {
    grid-area: date; justify-self: end; align-self: baseline;
  }
  /* The owner moves down to the meta line; the date stays on the top line, which
     is the one a thumb scans. */
  .sw-row__who { display: none; }
  .sw-row__who-sm { display: inline; }
  .sw-row__where::after { content: ""; }
  .sw-row__facets { margin-left: 0; display: flex; margin-top: 2px; }
}

/* Status: a mark, then a label, then a colour — in that order of importance, so the
   interface still works in greyscale and for a colour-blind reader. */
.sw-status { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-13); font-weight: 600; }

/* The inference marker. A derived item never looks like a stated one. */
.sw-derived {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--font-mono); font-size: var(--t-11);
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted);
}
.sw-derived__ref { color: var(--gold-ink); }

/* ---------------------------------------------------------- detail: the meta grid */
.sw-meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; margin: 0; }
@media (max-width: 560px) { .sw-meta { grid-template-columns: 1fr; } }
.sw-meta__row {
  display: flex; justify-content: space-between; gap: var(--s-2);
  padding: 11px var(--s-2) 11px 0; border-bottom: 1px solid var(--hairline);
  font-size: var(--t-14);
}
.sw-meta__row dt { color: var(--muted); margin: 0; }
.sw-meta__row dd { margin: 0; color: var(--text); font-family: var(--font-mono); font-size: var(--t-13); text-align: right; }
.sw-meta__row dd.is-ui { font-family: var(--font-ui); }

.row {
  display: flex; justify-content: space-between; gap: var(--s-2);
  padding: 11px 0; border-bottom: 1px solid var(--hairline); font-size: var(--t-14);
}
.row:last-child { border-bottom: 0; }
.row dt { color: var(--muted); margin: 0; }
.row dd { margin: 0; color: var(--text); font-family: var(--font-mono); font-size: var(--t-13); }

/* -------------------------------------------------------------------- the detail */
.detail__head { margin-bottom: var(--s-3); }
.detail__codeline {
  display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap;
  margin-bottom: var(--s-1);
}
.detail__code { font-family: var(--font-mono); font-size: var(--t-13); color: var(--muted); }
.detail__title { font-size: var(--t-28); font-weight: 800; line-height: 1.15; letter-spacing: -0.015em; }
.detail__body { color: var(--body); max-width: 70ch; margin: var(--s-2) 0 0; }
.detail__cols { display: grid; grid-template-columns: 1fr; gap: var(--s-3); }

.sw-block {
  border: 1px solid var(--risk); background: var(--surface);
  border-radius: var(--r-sm); padding: var(--s-2); margin: var(--s-2) 0;
  display: flex; gap: var(--s-1); align-items: flex-start; font-size: var(--t-14);
}
.sw-block__mark { color: var(--risk); margin-top: 1px; }
.sw-block__since { display: block; font-family: var(--font-mono); font-size: var(--t-12); color: var(--muted); margin-top: var(--s-0); }

.sw-list { list-style: none; margin: 0; padding: 0; }
.sw-list__item {
  padding: 11px 0; border-bottom: 1px solid var(--hairline); font-size: var(--t-14);
}
.sw-list__item:last-child { border-bottom: 0; }
.sw-list__meta { font-family: var(--font-mono); font-size: var(--t-12); color: var(--muted); }

.sw-check { display: flex; align-items: center; gap: var(--s-1); min-height: 36px; cursor: pointer; }
.sw-check input { width: 16px; height: 16px; accent-color: var(--gold-ink); margin: 0; flex: none; }
.sw-check--done span { color: var(--muted); text-decoration: line-through; }

/* ------------------------------------------------------------------- the actions */
.sw-actions { display: flex; flex-wrap: wrap; gap: var(--s-1); margin: var(--s-2) 0; align-items: center; }
/* Cancelled is not the next step. The gap says so before the label does. */
.sw-actions__sep { flex: none; width: 1px; height: 24px; background: var(--hairline); margin: 0 var(--s-1); }
.sw-button .sw-mark { margin-right: 6px; }
.sw-field { display: flex; flex-wrap: wrap; gap: var(--s-1); align-items: center; margin: var(--s-2) 0; }
.sw-label--inline { flex: none; }

.sw-input, .sw-select, .sw-textarea {
  font-family: var(--font-ui); font-size: var(--t-14); color: var(--text);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-sm); padding: 0 var(--s-1); min-height: 44px;
}
.sw-textarea { padding: var(--s-1); min-height: 72px; line-height: 1.5; width: 100%; resize: vertical; }
.sw-input:focus-visible, .sw-select:focus-visible, .sw-textarea:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 1px;
}
.sw-input--grow { flex: 1 1 220px; min-width: 0; }

.sw-filters {
  display: flex; flex-wrap: wrap; gap: var(--s-1); align-items: center;
  padding-bottom: var(--s-2); margin-bottom: var(--s-2);
  border-bottom: 1px solid var(--hairline);
}
.sw-chip--button { cursor: pointer; min-height: 36px; padding: 0 var(--s-2); font-family: var(--font-ui); }

/* ------------------------------------------------------- the stage bar
   One control per state, each carrying its own count, and the counts come from the
   whole workspace rather than from the rows on screen — a filter that only counts
   what it can already see tells you nothing you did not know.

   This replaced a single flat row of five unrelated toggles (Open, Everything,
   Mine, Blocked, Needs routing) that mixed a state filter, a scope filter and two
   flags with no grouping, so nothing said which of them were alternatives and
   which combined. They are now three labelled groups, and the state group is the
   pipeline: you can see at a glance that 63 of 109 items are sitting in triage,
   which is a fact the old control actively hid. */
.sw-facets {
  margin-bottom: var(--s-3); padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--hairline);
}
.sw-facets .sw-input { min-height: 36px; }
.sw-facets__group {
  display: flex; align-items: center; gap: var(--s-1);
  padding: var(--s-0) 0;
}
.sw-facets__label {
  font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint);
  flex: none; width: 56px;
}
/* A horizontal scroller needs to SAY it scrolls. The old nav did not, and at phone
   width a whole destination was simply off the edge with nothing to suggest it. */
.sw-facets__track {
  display: flex; gap: var(--s-0); overflow-x: auto; scrollbar-width: none;
  padding: 2px 0; -webkit-overflow-scrolling: touch;
  mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
}
.sw-facets__track::-webkit-scrollbar { display: none; }
/* Wide enough to show them all: wrap rather than scroll, so nothing is hidden on a
   screen that has the room. The pill count is fixed (one per state plus two
   rollups), so wrapping cannot make the bar jump as counts change. */
@media (min-width: 1200px) {
  .sw-facets__track { flex-wrap: wrap; overflow: visible; mask-image: none; }
}
/* Retuned in M8 after "the pills look so chunky". 32px of height for a 13px word
   is a button, and these are not buttons, they are a row of adjectives you can
   switch on. 28px with the mark carrying 16 of it is the Linear/Notion figure and
   it is what lets eleven of them sit on one line without the bar becoming a wall.

   `center`, not `baseline`: a drawn mark has no baseline. */
.sw-stage {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 28px; padding: 0 10px; border-radius: var(--r-pill);
  background: var(--sunken); border: 1px solid var(--hairline);
  color: var(--body); font-size: var(--t-13); font-weight: 600; line-height: 1;
  white-space: nowrap; cursor: pointer;
}
.sw-stage__label { display: block; }
.sw-stage:hover { color: var(--text); border-color: var(--muted); }
.sw-stage:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
/* The count is a number in a row of numbers, so it is tabular and mono — that IS
   a reference. It is also the one thing here allowed to be quiet. */
.sw-stage__n {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.sw-stage[aria-pressed="true"] {
  background: var(--gold-quiet); border-color: var(--gold-ink); color: var(--text);
  font-weight: 700;
}
.sw-stage[aria-pressed="true"] .sw-stage__n { color: var(--text); }
/* Selection survives greyscale: the gold wash is the third channel, the check is
   the first. A selected control that differs only in colour is not selected for
   everybody. */
/* Selection survives greyscale. It used to add a ✓ after the mark — a character,
   in Courier, which does not have one. It is now a ring the pill draws itself. */
.sw-stage[aria-pressed="true"] { box-shadow: inset 0 0 0 1px var(--gold-ink); }
.sw-stage--empty { opacity: 0.55; }

.sw-row__facets { display: inline-flex; gap: var(--s-0); flex-wrap: wrap; margin-left: var(--s-1); }
.sw-facetline { display: flex; flex-wrap: wrap; gap: var(--s-0); margin-top: var(--s-1); }

.sw-count {
  font-family: var(--font-mono); font-size: var(--t-12); color: var(--muted);
}

footer { border-top: 1px solid var(--hairline); padding: var(--s-3) 0; color: var(--faint); font-size: var(--t-13); }
footer a { color: var(--faint); }

/* The toast genuinely floats, so it is one of the three things in this product
   allowed a shadow. It carries NO border: a 1px edge plus a wide diffuse shadow is a
   recurring generated-UI signature, and Impeccable is right that a thing should commit
   to one or the other. The tonal step from board to page is the second signal, as it
   is everywhere else here.
   A refusal is marked and labelled rather than outlined, which is the Status rule
   (mark, then label, then colour) applied to a message instead of a row. */
.sw-toast {
  position: fixed; left: 50%; bottom: var(--s-3); transform: translateX(-50%);
  background: var(--surface); color: var(--text);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-panel);
  padding: var(--s-1) var(--s-2); font-size: var(--t-14);
  max-width: calc(100vw - var(--s-4)); z-index: 20;
  display: flex; align-items: flex-start; gap: var(--s-1);
}
.sw-toast[hidden] { display: none; }
.sw-toast__mark { color: var(--risk); margin-top: 2px; }

/* ------------------------------------------------------------- the proposals */
/* A proposal is not a work item and must not look like one. It is a reading of a
   message, shown with the sentence it was read from, waiting for somebody to say
   what it is. The exhibit is the largest thing in it on purpose. */
.sw-proposal {
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--hairline);
}
.sw-proposal:last-child { border-bottom: 0; }
.sw-proposal__head {
  display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap;
  margin-bottom: var(--s-1);
}
.sw-proposal__ref {
  font-family: var(--font-mono); font-size: var(--t-12);
  color: var(--gold-ink); text-decoration: none;
}
.sw-proposal__ref:hover { text-decoration: underline; }
.sw-proposal__from { font-size: var(--t-13); color: var(--muted); }
.sw-proposal__title {
  font-size: var(--t-18); font-weight: 700; color: var(--text);
  margin: 0 0 var(--s-1);
}
.sw-proposal__meta { font-size: var(--t-13); color: var(--muted); margin: var(--s-1) 0 0; }
.sw-mono { font-family: var(--font-mono); font-size: var(--t-13); }

/* The abstention. Marked and labelled, not outlined — a coloured edge on one side is
   the anti-pattern this system has a tonal step for. */
.sw-abstain {
  display: flex; gap: var(--s-1); align-items: flex-start;
  background: var(--sunken); border-radius: var(--r-sm);
  padding: var(--s-1) var(--s-2); margin: var(--s-2) 0 0;
  font-size: var(--t-14); color: var(--body);
}
.sw-abstain { display: flex; align-items: flex-start; gap: var(--s-0); }
.sw-abstain__mark { color: var(--risk); margin-top: 2px; }

.sw-button--small { min-height: 36px; font-size: var(--t-13); padding: 0 var(--s-1); }

/* ------------------------------------------------- the command bar and the bell */
/* The command bar floats, so it is one of the very few things entitled to a shadow
   (the design rule is: depth is a tonal step; shadow is only for what genuinely
   leaves the page). No border — the surface step and the shadow are the edge, which
   is also why the toast and the panel lost theirs in I-018. */
.sw-cmd {
  position: fixed; inset: 0; z-index: 40;
  background: oklch(22% 0.015 265 / 0.28);
  display: flex; align-items: flex-start; justify-content: center;
  padding: var(--s-5) var(--s-2);
}
.sw-cmd[hidden] { display: none; }
.sw-cmd__box {
  background: var(--surface); border-radius: var(--r-md);
  box-shadow: var(--shadow-panel);
  width: 100%; max-width: 620px; overflow: hidden;
}
.sw-cmd__input {
  width: 100%; box-sizing: border-box;
  font-family: var(--font-mono); font-size: var(--t-16);
  color: var(--text); background: transparent;
  border: 0; border-bottom: 1px solid var(--hairline);
  padding: var(--s-2); outline-offset: -3px;
}
.sw-cmd__input::placeholder { color: var(--faint); }
/* The answer is prose, not a status chip. A refusal is a sentence a person reads. */
.sw-cmd__answer:not(:empty) {
  padding: var(--s-2); font-size: var(--t-14); color: var(--text);
  white-space: pre-wrap;
}
.sw-cmd__answer .mark { display: inline-block; vertical-align: -3px; margin-right: var(--s-0); }
.sw-cmd__answer--refused .mark { color: var(--risk); }
.sw-cmd__answer--asked .mark { color: var(--attention); }
.sw-cmd__answer--done .mark { color: var(--ok); }
.sw-cmd__hint {
  padding: var(--s-1) var(--s-2); background: var(--sunken);
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--faint);
}
.sw-cmd__cands { margin-top: var(--s-1); display: flex; flex-wrap: wrap; gap: var(--s-0); }

/* The notification drawer. Anchored to the top bar it came from. */
.sw-drawer {
  position: fixed; right: var(--s-2); top: 64px; z-index: 30;
  width: min(420px, calc(100vw - var(--s-3)));
  max-height: min(70vh, 560px); overflow-y: auto;
  background: var(--surface); border-radius: var(--r-md);
  box-shadow: var(--shadow-panel);
}
.sw-drawer[hidden] { display: none; }
.sw-drawer__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-1); padding: var(--s-1) var(--s-1) var(--s-1) var(--s-2);
  border-bottom: 1px solid var(--hairline); position: sticky; top: 0;
  background: var(--surface);
}
.sw-drawer__title { margin: 0; font-size: var(--t-14); letter-spacing: 0.02em; }
.sw-alert {
  display: block; padding: var(--s-2); text-decoration: none; color: inherit;
  border-bottom: 1px solid var(--hairline);
}
.sw-alert:last-child { border-bottom: 0; }
.sw-alert:hover { background: var(--sunken); }
/* Unread is marked, not merely coloured — the third-signal rule applies to a list
   row exactly as it does to a status chip. */
.sw-alert--unread { background: var(--gold-quiet); }
.sw-alert__ref {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--faint);
  display: block; margin-bottom: 2px;
}
/* On the tinted unread row, `--faint` came to 4.37:1 in dark mode — under the floor,
   and only visible once check_contrast.py learned to composite the tint's alpha. The
   metadata steps up one level rather than the floor stepping down. */
.sw-alert--unread .sw-alert__ref { color: var(--muted); }
.sw-alert__subject { font-size: var(--t-14); font-weight: 600; }
.sw-alert__body {
  font-size: var(--t-13); color: var(--muted); margin: var(--s-0) 0 0;
  white-space: pre-wrap;
}
.sw-alert__unread-mark {
  font-family: var(--font-mono); font-weight: 700; color: var(--gold-ink);
  margin-right: var(--s-0);
}
.sw-drawer__empty {
  padding: var(--s-3) var(--s-2); font-size: var(--t-14); color: var(--muted);
}
/* The bell's count. Same treatment as the nav counts, so two numbers meaning
   "things waiting for you" do not look like different kinds of thing. */
.sw-bell__n {
  font-family: var(--font-mono); font-size: var(--t-11); font-weight: 700;
  margin-left: var(--s-0);
}

@media (max-width: 540px) {
  .sw-drawer { right: var(--s-1); left: var(--s-1); width: auto; top: 56px; }
  .sw-cmd { padding: var(--s-3) var(--s-1); }
}

/* ========================================================================
   M5 — plan. Two new shapes, and one rule governing both.

   A dependency wait and a projected date are INFERENCES (D035). A stated
   block is a fact somebody wrote. They must not be able to be mistaken for
   one another at a glance, so the wait carries the same `¶ Derived` marker
   the rest of the system uses for a drawn conclusion, and the block keeps
   its own heavier treatment. Nothing here borrows `.sw-block`.
   ===================================================================== */

.sw-wait {
  display: flex; gap: var(--s-1); align-items: baseline;
  padding: 11px var(--s-2);
  border-bottom: 1px solid var(--hairline);
}
.sw-wait:last-child { border-bottom: 0; }
/* A short code is a reference somebody transcribes. Breaking one across two lines
   at 360px turned WRK-0001 into "WRK-" / "0001", which is a different string. */
.sw-wait__code { font-family: var(--font-mono); font-weight: 700; white-space: nowrap; }
.sw-wait__title { flex: 1 1 auto; min-width: 0; }
.sw-wait__meta {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
}
/* A settled predecessor no longer holds anything up, and says so with a mark
   before it says so with a colour. */
.sw-wait--settled .sw-wait__code { color: var(--muted); }

/* The projected date. Divider stock, because it is drawn rather than stated —
   the same material the exhibit block uses for the same reason. */
.sw-feasible {
  background: var(--sunken); border: 1px solid var(--hairline);
  border-radius: var(--r-sm);
  padding: var(--s-2); margin: var(--s-1) 0 var(--s-3);
}
.sw-feasible__label {
  font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
  display: block; margin-bottom: var(--s-0);
}
.sw-feasible__date {
  font-family: var(--font-mono); font-size: var(--t-16); font-weight: 700;
}
.sw-feasible__because {
  font-size: var(--t-13); color: var(--body); margin: var(--s-0) 0 0;
}
/* An abstention is a real answer and is set in reading type, not in the
   quiet tier — "we do not know when WRK-13 lands" is the useful sentence. */
.sw-feasible__unknown { font-size: var(--t-14); color: var(--body); margin: var(--s-0) 0 0; }

/* ------------------------------------------------------------ the impact
   What a date move breaks, shown before it is saved (D037). It is a
   consequence, not an error: mark, then label, then colour. */
.sw-impact {
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
  background: var(--sunken); margin: var(--s-2) 0;
}
.sw-impact[hidden] { display: none; }
.sw-impact__head {
  display: flex; gap: var(--s-1); align-items: center;
  padding: var(--s-2); border-bottom: 1px solid var(--hairline);
}
.sw-impact__mark { color: var(--risk); }
.sw-impact__title { font-weight: 700; font-size: var(--t-16); }
.sw-impact__list { list-style: none; margin: 0; padding: 0; }
.sw-impact__item { padding: 11px var(--s-2); border-bottom: 1px solid var(--hairline); }
.sw-impact__item:last-child { border-bottom: 0; }
.sw-impact__party { font-weight: 700; }
.sw-impact__dates {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
  display: block; margin-top: 2px;
}
.sw-impact__via {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
}
.sw-impact__foot { padding: var(--s-2); }
/* Gold link text comes to 3.98:1 on divider stock — under the floor, and caught by
   check_contrast.py the first time these two regions were declared to it. Links in
   here are underlined ink instead. It also keeps the Seal Rule: gold appears at
   most twice on a screen, and neither of them is a reference in a warning panel. */
.sw-impact a, .sw-feasible a { color: var(--text); text-decoration: underline; }

/* ---------------------------------------------------------- the workload
   One claim per row, and the items that produced it directly underneath. */
.sw-load { border: 1px solid var(--hairline); border-radius: var(--r-sm);
           background: var(--surface); margin-bottom: var(--s-3); }
.sw-load__who {
  display: flex; gap: var(--s-1); align-items: baseline; flex-wrap: wrap;
  padding: var(--s-2); border-bottom: 1px solid var(--hairline);
}
.sw-load__name { font-weight: 700; font-size: var(--t-18); }
.sw-load__cap {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
}
.sw-load__day {
  padding: 11px var(--s-2); border-bottom: 1px solid var(--hairline);
}
.sw-load__day:last-child { border-bottom: 0; }
.sw-load__line {
  display: flex; gap: var(--s-1); align-items: baseline; flex-wrap: wrap;
}
.sw-load__date { font-family: var(--font-mono); font-weight: 700; min-width: 11ch; }
.sw-load__mins { font-family: var(--font-mono); }
/* The bar is a ruled measure, not a chart: divider stock with a hairline, a
   fill in ink, and a tick where the stated capacity sits. No gradient, no
   rounded cap — it is drawn in the same vocabulary as everything else. */
.sw-load__meter {
  position: relative; height: 8px; margin: var(--s-0) 0 0;
  background: var(--sunken); border: 1px solid var(--hairline);
  border-radius: var(--r-xs); overflow: hidden;
}
.sw-load__fill { height: 100%; background: var(--body); }
.sw-load__fill--over { background: var(--risk); }
.sw-load__tick {
  position: absolute; top: 0; bottom: 0; width: 1px; background: var(--text);
}
.sw-load__items { list-style: none; margin: var(--s-0) 0 0; padding: 0; }
.sw-load__item {
  display: flex; gap: var(--s-1); align-items: baseline;
  font-size: var(--t-13); padding: 2px 0;
}
.sw-load__item .sw-row__code { font-family: var(--font-mono); white-space: nowrap; }
.sw-load__est { font-family: var(--font-mono); color: var(--muted); margin-left: auto; }
/* Unsized work is the caveat on the number above it, so it sits with the
   number rather than in a footnote (D036). */
.sw-load__unsized { color: var(--attention); }
.sw-load__note {
  padding: var(--s-2); font-size: var(--t-14); color: var(--body);
  border-bottom: 1px solid var(--hairline);
}

@media (max-width: 540px) {
  .sw-load__est { margin-left: 0; }
  .sw-wait { flex-wrap: wrap; }
}

/* ========================================================================
   M6 — decide. Versions, approvals and decisions.

   One rule governs the lot: these are records of things that happened, and
   the screen has to make a *superseded* one still legible rather than hide
   it. A withdrawn version and a superseded decision both stay on the page,
   marked, because the record is the product (D041).

   Note what is NOT here: no `¶ Derived` mark. An approval rollup is
   arithmetic over answers people gave, not an inference Swarm drew — it is
   a status, so it gets a mark, a label and then a colour, in that order,
   like every other status in the system.
   ===================================================================== */

.sw-version {
  padding: 11px var(--s-2);
  border-bottom: 1px solid var(--hairline);
}
.sw-version:last-child { border-bottom: 0; }
.sw-version__line {
  display: flex; gap: var(--s-1); align-items: baseline; flex-wrap: wrap;
}
.sw-version__no {
  font-family: var(--font-mono); font-weight: 700; white-space: nowrap;
}
.sw-version__label { flex: 1 1 auto; min-width: 0; }
.sw-version__right {
  display: flex; gap: var(--s-1); align-items: baseline;
  margin-left: auto; flex-wrap: nowrap;
}
.sw-version__current {
  font-family: var(--font-mono); font-size: var(--t-11); font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; white-space: nowrap;
}
.sw-version__meta {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
}
/* The URI is a reference somebody may need to transcribe, so it is set in
   Courier and never broken mid-token. */
.sw-version__uri {
  font-family: var(--font-mono); font-size: var(--t-11);
  display: block; margin-top: 2px; overflow-wrap: anywhere;
}
.sw-version__fingerprint {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
}
/* Withdrawn stays on the page. Struck, with its reason, because "there was a
   v2 and it was pulled on Tuesday" is information and deleting the row would
   be the lie. */
.sw-version--withdrawn .sw-version__label { text-decoration: line-through; }
.sw-version--withdrawn { color: var(--muted); }
.sw-version__withdrawn {
  font-size: var(--t-13); color: var(--body); display: block; margin-top: var(--s-0);
}

.sw-approval {
  display: flex; gap: var(--s-1); align-items: baseline; flex-wrap: wrap;
  font-size: var(--t-13); padding: 2px 0 2px var(--s-2);
}
.sw-approval__party { font-weight: 600; }
.sw-approval__note {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
  display: block; padding-left: var(--s-2);
}

/* ------------------------------------------------------------- decisions */
.sw-decision {
  padding: var(--s-2);
  border-bottom: 1px solid var(--hairline);
}
.sw-decision:last-child { border-bottom: 0; }
.sw-decision__subject {
  font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
  display: block; margin-bottom: var(--s-0);
}
.sw-decision__chose { font-weight: 700; font-size: var(--t-16); }
.sw-decision__rationale { margin: var(--s-0) 0 0; font-size: var(--t-14); }
.sw-decision__considered {
  display: flex; gap: var(--s-0); flex-wrap: wrap; margin-top: var(--s-1);
}
.sw-decision__meta {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
  display: block; margin-top: var(--s-1);
}
/* A superseded decision is not struck through — it was true, it was acted on,
   and somebody may have to read it to understand why something looks the way
   it does. It is quieted and labelled, not crossed out. */
.sw-decision--superseded .sw-decision__chose {
  font-weight: 400; color: var(--muted);
}

/* ------------------------------------------------- the approvals list page */
.sw-ask {
  display: block; padding: 11px var(--s-2);
  border-bottom: 1px solid var(--hairline); color: inherit; text-decoration: none;
}
.sw-ask:last-of-type { border-bottom: 0; }
.sw-ask:hover { background: var(--sunken); }
.sw-ask__line {
  display: flex; gap: var(--s-1); align-items: baseline; flex-wrap: wrap;
}
.sw-ask__who { font-weight: 700; }
.sw-ask__meta {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
}
.sw-ask__actions {
  display: flex; gap: var(--s-1); flex-wrap: wrap; padding: var(--s-1) var(--s-2);
  border-bottom: 1px solid var(--hairline);
}

@media (max-width: 540px) {
  .sw-approval { padding-left: var(--s-1); }
  .sw-approval__note { padding-left: var(--s-1); }
}


/* ---------------------------------------------------------- the shortcut sheet
   One of the three things in this product that genuinely floats, so it is one of
   the three allowed a shadow (DESIGN.md § Elevation). */
.sw-keys {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: oklch(22% 0.015 265 / 0.38); padding: var(--s-2);
}
.sw-keys[hidden] { display: none; }
.sw-keys__box {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: var(--s-3);
  box-shadow: 0 18px 44px oklch(22% 0.015 265 / 0.16);
  max-width: 480px; width: 100%; max-height: 80vh; overflow: auto;
}
.sw-keys__title { font-size: var(--t-18); font-weight: 700; margin: 0 0 var(--s-2); }
.sw-keys__list {
  display: grid; grid-template-columns: auto 1fr; gap: var(--s-0) var(--s-2);
  margin: 0; align-items: baseline;
}
.sw-keys__list dt { margin: 0; white-space: nowrap; }
.sw-keys__list dd { margin: 0; color: var(--body); font-size: var(--t-14); }
.sw-keys kbd {
  font-family: var(--font-mono); font-size: var(--t-11); font-weight: 700;
  background: var(--sunken); border: 1px solid var(--hairline);
  border-radius: var(--r-sm); padding: 2px 6px; color: var(--text);
}
.sw-keys__note {
  margin: var(--s-2) 0 0; padding-top: var(--s-2);
  border-top: 1px solid var(--hairline);
  font-size: var(--t-13); color: var(--muted);
}

/* The row the keyboard is on. It is a focus state as well as a tint, because a
   highlight a screen reader cannot follow is a cursor for some people only. */
.sw-row--cursor { background: var(--sunken); }
.sw-row--cursor:focus-visible, .sw-row:focus-visible {
  outline: 2px solid var(--focus); outline-offset: -2px;
}

/* ------------------------------------------------------------- empty and waiting */
.sw-empty__head { margin: 0; color: var(--text); font-weight: 600; }
.sw-empty__help {
  margin: var(--s-0) 0 0; color: var(--muted); font-size: var(--t-13);
  max-width: 62ch;
}

.sw-skel { padding: var(--s-2) 0; }
.sw-skel__row {
  display: flex; gap: var(--s-2); align-items: center;
  padding: 14px 0; border-bottom: 1px solid var(--hairline);
}
.sw-skel__bar {
  height: 10px; border-radius: var(--r-pill); background: var(--sunken);
  animation: sw-breathe 1.4s var(--e) infinite;
}
.sw-skel__row:nth-child(2) .sw-skel__bar { animation-delay: 80ms; }
.sw-skel__row:nth-child(3) .sw-skel__bar { animation-delay: 160ms; }
.sw-skel__row:nth-child(4) .sw-skel__bar { animation-delay: 240ms; }
.sw-skel__row:nth-child(5) .sw-skel__bar { animation-delay: 320ms; }
.sw-skel__row:nth-child(6) .sw-skel__bar { animation-delay: 400ms; }
@keyframes sw-breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
/* A pulse is decoration; somebody who has asked for less motion should get the
   bars and none of the breathing. */
@media (prefers-reduced-motion: reduce) {
  .sw-skel__bar { animation: none; }
}


/* ======================================================= the views, and the board */
.sw-views {
  display: flex; align-items: flex-end; gap: var(--s-0);
  border-bottom: 1px solid var(--hairline);
  margin-bottom: var(--s-3); padding-left: var(--s-1);
}
/* A divider tab, because a tab is literally an index of views — the one job this
   system's curved silhouette already has. */
.sw-views__tab {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--t-12); font-weight: 600; letter-spacing: 0.01em;
  background: var(--sunken); color: var(--muted);
  border: 1px solid var(--hairline); border-bottom: none;
  border-radius: var(--r-tab);
  padding: 7px 12px 8px; margin-bottom: -1px;
  text-decoration: none; min-height: 36px; white-space: nowrap;
}
.sw-views__tab:hover { color: var(--text); }
.sw-views__tab[aria-selected="true"] {
  background: var(--surface); color: var(--text);
  border-bottom: 1px solid var(--surface);
}
.sw-views__tab:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.sw-views__tab .sw-mark { width: 15px; height: 15px; }
.sw-views__soon {
  margin-left: auto; padding-bottom: var(--s-1);
  font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: 0.08em; color: var(--faint); cursor: help;
}

.sw-board {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(248px, 1fr);
  gap: var(--s-2); overflow-x: auto; padding-bottom: var(--s-2);
  align-items: start; scrollbar-width: thin;
}
/* The colour is on the column AND on a chip at its head, at two strengths. The
   column gets a breath of tint so five columns read as five bands at a glance;
   the chip gets the real colour so the stage is named in it at reading distance.
   Putting the full strength on the column made the board look like a box of
   sweets — the Notion reference has it right and it is the chip that carries it. */
.sw-board__col {
  background: var(--st-bg, var(--sunken));
  border: 1px solid color-mix(in oklch, var(--st-ink, var(--hairline)) 18%, transparent);
  border-radius: var(--r-md); padding: var(--s-1);
  min-height: 120px;
}

.sw-board__head {
  display: flex; align-items: center; gap: var(--s-1);
  margin: 0; padding: var(--s-0) 2px var(--s-1);
}
/* The stage's name is a chip, not a heading in colour. A chip is a thing you can
   point at; a coloured heading is a heading somebody has coloured in. */
.sw-board__label {
  display: inline-flex; align-items: center; gap: 6px;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: var(--st-chip, var(--sunken)); color: var(--st-ink, var(--text));
  border-radius: var(--r-pill); padding: 3px 10px 3px 8px;
  font-size: var(--t-12); font-weight: 700; letter-spacing: 0.01em; line-height: 1;
}
.sw-board__n {
  margin-right: auto; font-family: var(--font-mono); font-size: var(--t-12);
  font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums;
}
.sw-board__more {
  display: block; padding: var(--s-1); font-size: var(--t-12);
  color: var(--muted); text-align: center; text-decoration: underline;
}
.sw-board__stack { display: flex; flex-direction: column; gap: var(--s-0); }
.sw-board__empty {
  margin: 0; padding: var(--s-2) var(--s-1); color: var(--faint);
  font-size: var(--t-13);
}

/* A card on the board. Square, like everything that IS a surface; the labels on
   it are the round ones. */
.sw-card2 {
  display: flex; flex-direction: column; gap: 5px;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-sm); padding: var(--s-1);
  text-decoration: none; color: inherit; cursor: grab;
}
.sw-card2:hover { border-color: var(--muted); }
.sw-card2:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.sw-card2__code { font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted); }
.sw-card2__title { color: var(--text); font-weight: 600; font-size: var(--t-14); line-height: 1.35; }
.sw-card2__where { font-size: var(--t-12); color: var(--muted); }
.sw-card2__foot {
  display: flex; justify-content: space-between; gap: var(--s-1);
  font-family: var(--font-mono); font-size: var(--t-12); color: var(--muted);
}
.sw-card2 .sw-row__facets { margin-left: 0; }
.sw-card2.is-dragging { opacity: 0.4; cursor: grabbing; }

/* Where the card may land, and where it may not. The state machine is shown
   during the drag rather than explained by a toast after it. */
.sw-board__col.is-over {
  border-color: var(--gold-ink); background: var(--gold-quiet);
}
.sw-board__col.is-shut { opacity: 0.3; filter: saturate(0.2); }
.sw-board__col.is-shut .sw-board__head::after {
  content: " \2014 not from here"; letter-spacing: 0; text-transform: none;
  font-size: var(--t-11); color: var(--muted);
}

@media (max-width: 820px) {
  .sw-board { grid-auto-columns: minmax(82vw, 1fr); }
  .sw-views__soon { display: none; }
}

/* A mark that knows its stage. Only the MARK takes the hue — a whole row set in
   violet because it happens to be in review would be colour as the first channel,
   which is exactly the thing the Status rule forbids. The word stays ink. */
.sw-mark--stage { color: var(--st-ink, currentColor); }

/* A stage pill wears a hint of its colour at rest and the full tint when it is the
   one you are standing in. The gold ring still marks selection, because selection
   is a different fact from which stage this is and they must not share a channel. */
.sw-stage[data-st] .sw-mark { color: var(--st-ink, currentColor); }
.sw-stage[data-st][aria-pressed="true"] {
  background: var(--st-bg, var(--gold-quiet));
  border-color: color-mix(in oklch, var(--st-ink) 45%, transparent);
}

/* ------------------------------------------------------------ the group heading
   A heading over a stage, not a pill. The stage bar above already uses pills for
   the same seven words, and a second row of the same pills doing a different job
   is how a person learns that a control means nothing. */
.sw-group { margin-bottom: var(--s-3); }
/* Same chip as the board head, for the same reason: a person who has seen violet
   mean "in review" on the board must not have to learn it again on the list. */
.sw-group__head {
  display: flex; align-items: center; gap: var(--s-1);
  margin: 0 0 var(--s-1); padding: 0 2px;
}
.sw-group__label {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--st-chip, var(--sunken)); color: var(--st-ink, var(--text));
  border-radius: var(--r-pill); padding: 3px 10px 3px 8px;
  font-size: var(--t-12); font-weight: 700; letter-spacing: 0.01em; line-height: 1;
}
.sw-group__n {
  font-family: var(--font-mono); font-size: var(--t-11); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* There WAS a 3px spine of the stage's ink down the left of each group. Impeccable
   flagged it, and it was right: a thick coloured bar on one side of a card is the
   single most recognisable signature of a generated interface. It was also
   redundant — the heading directly above already carries the stage's mark, word
   and colour, so the spine was saying a third time what had just been said twice.
   The group is separated by space and a heading, which is how a document does it. */

/* ------------------------------------------------------------------- the table
   Horizontal scroll rather than a wrap, because a table whose columns wrap has
   stopped being a table. The first column is sticky so the stage stays readable
   while the rest slides — the stage is the reason this view exists. */
.sw-tbl__scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.sw-tbl {
  width: 100%; border-collapse: collapse; background: var(--surface);
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
  font-size: var(--t-13);
}
.sw-tbl th {
  text-align: left; font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint);
  font-weight: 400; padding: var(--s-1) var(--s-2);
  border-bottom: 1px solid var(--hairline); white-space: nowrap;
}
.sw-tbl td {
  padding: 9px var(--s-2); border-bottom: 1px solid var(--hairline);
  vertical-align: middle; color: var(--body);
}
.sw-tbl tbody tr:last-child td { border-bottom: 0; }
.sw-tbl tbody tr:hover td { background: var(--sunken); }
.sw-tbl__stage {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--st-ink, var(--body)); font-weight: 600; white-space: nowrap;
}
.sw-tbl__code {
  font-family: var(--font-mono); font-size: var(--t-12); color: var(--muted);
  white-space: nowrap;
}
.sw-tbl__title { min-width: 22ch; }
.sw-tbl__title a { color: var(--text); font-weight: 600; text-decoration: none; }
.sw-tbl__title a:hover { text-decoration: underline; }
.sw-tbl__who, .sw-tbl__where { white-space: nowrap; color: var(--muted); }
.sw-tbl__date {
  font-family: var(--font-mono); font-size: var(--t-12); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.sw-tbl__quiet { color: var(--muted); }

@media (max-width: 820px) {
  /* Six of the eight columns are context. On a phone the two that answer the
     question stay and the rest go, rather than the whole table shrinking to
     illegible. */
  .sw-tbl__where, .sw-tbl__who, .sw-tbl th:nth-child(5), .sw-tbl th:nth-child(6),
  .sw-tbl td:nth-child(8), .sw-tbl th:nth-child(8) { display: none; }
}
