/* Component layer. Consumes tokens.css only — no raw colors or font stacks.
   Every component renders under Paper and Console (ADR 0004). */

* {
  box-sizing: border-box;
}

/* The status row is a sibling of whatever fills the viewport, so the column is
   what subtracts its height instead of letting a report push the page taller. */
body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.45;
  background: var(--surface);
  color: var(--text);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  transition:
    background var(--dur) var(--ease),
    color var(--dur) var(--ease);
}

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

.ic {
  fill: none;
  vertical-align: -0.2em;
  flex-shrink: 0;
}

/* Machine matter is monospaced, human matter is not */
.machine {
  font-family: var(--font-mono);
}

/* Present to assistive tech only (state words like "unread") */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

kbd {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  border: 1px solid var(--rule-strong);
  padding: 0 4px;
  line-height: 15px;
  color: var(--text-soft);
  background: var(--surface);
}

/* ── App shell ─────────────────────────────────────────────────────────── */

.app {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr);
}

.side {
  min-width: 0;
  background: var(--surface-sunken);
  border-right: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* The desk is the second grid column: the page under the Quick View drawer it
   opens (ADR 0017), and the box the drawer's panel is positioned and clipped
   against so a closed one rests off the desk rather than off the viewport.

   `clip`, never `hidden`. A closed panel parks a panel's width past the right
   edge, which makes the desk overflow, and `hidden` overflow is still a scroll
   container — invisible to the user, fully scrollable to the engine. Anything
   that scrolls something into view inside it then slides the whole desk, board
   and all, by that width and eases back: the lurch that reads as the board
   flickering when the drawer opens. `clip` creates no scroll container at all,
   so there is nothing left to scroll. Nothing here should ever scroll — the
   pane and the board columns each own their own. */
.desk {
  position: relative;
  min-width: 0;
  min-height: 0;
  display: flex;
  overflow: clip;
}

.main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* Soft, themed scrollbars on every scroll surface — a thin thumb over a
   transparent track, so the rails don't wear the chunky OS default. */
.side,
.main,
.issue-main,
.issue-props {
  scrollbar-width: thin;
  scrollbar-color: var(--rule-strong) transparent;
}

.side::-webkit-scrollbar,
.main::-webkit-scrollbar,
.issue-main::-webkit-scrollbar,
.issue-props::-webkit-scrollbar {
  width: 9px;
  height: 9px;
}

.side::-webkit-scrollbar-track,
.main::-webkit-scrollbar-track,
.issue-main::-webkit-scrollbar-track,
.issue-props::-webkit-scrollbar-track {
  background: transparent;
}

.side::-webkit-scrollbar-thumb,
.main::-webkit-scrollbar-thumb,
.issue-main::-webkit-scrollbar-thumb,
.issue-props::-webkit-scrollbar-thumb {
  background: var(--rule-strong);
  border-radius: 5px;
}

.side::-webkit-scrollbar-thumb:hover,
.main::-webkit-scrollbar-thumb:hover,
.issue-main::-webkit-scrollbar-thumb:hover,
.issue-props::-webkit-scrollbar-thumb:hover {
  background: var(--text-faint);
}

.brand {
  padding: 14px 16px 12px;
  border-bottom: 1px solid var(--rule);
}

.brand-word {
  display: block;
  font-weight: 600;
  font-size: var(--text-md);
}

.brand-word::before {
  content: "";
  display: inline-block;
  width: 9px;
  height: 9px;
  background: var(--accent);
  margin-right: 8px;
}

.brand-domain {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  color: var(--text-faint);
  letter-spacing: 0.08em;
  margin-left: 17px;
}

.workspace {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--rule);
  cursor: pointer;
}

.workspace:hover {
  background: var(--surface-raised);
}

.workspace-mark {
  width: 20px;
  height: 20px;
  border: 1px solid var(--rule-strong);
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  flex-shrink: 0;
}

.workspace-name {
  font-weight: 600;
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nav {
  flex: 1;
  padding: 10px 0 6px;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 5px 16px;
  border: 0;
  border-left: 2px solid transparent;
  background: none;
  font: inherit;
  text-align: left;
  color: var(--text-soft);
  cursor: pointer;
}

.nav-item:hover {
  background: var(--surface-raised);
  color: var(--text);
}

.nav-item.active {
  background: var(--surface);
  border-left-color: var(--accent);
  color: var(--text);
  font-weight: 600;
}

.nav-item .lbl {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nav-section {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.18em;
  color: var(--text-faint);
  padding: 16px 16px 5px;
  text-transform: uppercase;
}

.nav-sub {
  padding-left: 37px;
}

.team-key {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.05em;
}

.side-foot {
  border-top: 1px solid var(--rule);
  padding: 10px 16px 12px;
}

.me {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
}

.me .name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agent-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--agent-text);
  padding: 4px 0 0 9px;
}

.theme-toggle {
  margin-top: 12px;
  width: 100%;
  justify-content: center;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 20px;
  border-bottom: 1px solid var(--rule);
}

.crumb {
  color: var(--text-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The trail carries its own separator, because its leading step is not always a
   link: on the board, which is its Team's own URL, the Team crumb is plain text
   and would otherwise run into the crumb beside it once the name ellipsizes. */
.crumb + .crumb::before {
  content: "/";
  margin-inline-end: 14px;
  color: var(--text-faint);
}

.crumb-here {
  font-weight: 600;
  color: var(--text);
}

/* On a phone this is the only way back — the sidebar is a drawer — so the
   padding buys a 24px target and the negative margin keeps the bar its height. */
.crumb-back {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: 4px;
  padding: 6px 8px;
  margin: -6px -8px;
  text-decoration: none;
}

.crumb-back:hover {
  color: var(--text);
}

/* The underline stays off the glyph */
.crumb-back:hover .crumb-back-label {
  text-decoration: underline;
}

.spacer {
  flex: 1;
}

/* ── Buttons ───────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  padding: 5px 12px;
  border: 1px solid transparent;
  background: none;
  color: var(--text);
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}

.btn-primary {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: var(--text-on-accent);
}

.btn-primary:hover {
  background: var(--accent);
  border-color: var(--accent);
}

.btn-ghost {
  border-color: var(--rule-strong);
  color: var(--text-soft);
}

.btn-ghost:hover {
  border-color: var(--text);
  color: var(--text);
}

.btn-text {
  color: var(--text-soft);
  padding-left: 6px;
  padding-right: 6px;
}

.btn-text:hover {
  color: var(--text);
  background: var(--surface-raised);
}

.btn:disabled {
  opacity: 0.55;
  cursor: default;
  pointer-events: none;
}

/* ── Inputs ────────────────────────────────────────────────────────────── */

.field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

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

.field-label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-soft);
}

.input {
  font: inherit;
  font-size: var(--text-base);
  padding: 5px 9px;
  border: 1px solid var(--rule);
  background: var(--surface);
  color: var(--text);
}

.input::placeholder {
  color: var(--text-faint);
}

.input:hover {
  border-color: var(--rule-strong);
}

.input:focus,
.chooser-trigger[aria-expanded="true"] {
  outline: 2px solid var(--focus);
  outline-offset: -1px;
  border-color: var(--focus);
}

.input:disabled {
  opacity: 0.55;
  background: var(--surface-sunken);
}

/* The closed control the native <select> left behind (ADR 0010): its chevron is
   two token-colored background strokes rather than an icon, and it carries no
   pointer cursor, because that is the geometry every value-holding trigger was
   built to match and moving it now would move every picker in the product. The
   glyph form holds no value and takes none of this (ADR 0015). */
button.input.chooser-trigger {
  appearance: none;
  padding-right: 24px;
  background-image:
    linear-gradient(
      45deg,
      transparent calc(50% - 1.1px),
      var(--text-faint) calc(50% - 0.5px),
      var(--text-faint) calc(50% + 0.5px),
      transparent calc(50% + 1.1px)
    ),
    linear-gradient(
      135deg,
      transparent calc(50% - 1.1px),
      var(--text-faint) calc(50% - 0.5px),
      var(--text-faint) calc(50% + 0.5px),
      transparent calc(50% + 1.1px)
    );
  background-repeat: no-repeat;
  background-size: 4px 4px;
  background-position:
    right 13px center,
    right 9px center;
}

/* ── Chooser: the listbox every picker opens (ADR 0010) ────────────────── */

.chooser {
  position: relative;
  display: inline-flex;
  max-width: 100%;
}

.chooser-trigger,
.chooser-mark,
.chooser-option-mark {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

/* A <button> centers and wraps its text; a <select> does neither. */
.chooser-trigger {
  text-align: start;
  white-space: nowrap;
}

/* Atoms are taller than text (a 20px avatar against one line box of
   --text-base), so the mark is held to one line box and the closed control
   keeps its height whatever rides in it. */
.chooser-mark {
  height: 1lh;
  overflow: hidden;
}

/* `text-overflow` needs a block box, which an inline-flex mark is not and a
   flex item is, and `min-width: 0` is what lets that item shrink at all —
   without it the timezone list's longest label reaches the mark's clip. */
.chooser-mark .chooser-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chooser-panel {
  position: absolute;
  top: calc(100% + 2px);
  inset-inline-start: 0;
  z-index: 30;
  min-width: 100%;
  max-width: min(320px, calc(100vw - 24px));
  border: 1px solid var(--rule-strong);
  background: var(--surface-raised);
}

.chooser-panel:not([hidden]) {
  display: flex;
  flex-direction: column;
}

/* The scroller is the listbox alone, so a filter above it stays put while the
   options move under it. */
.chooser-list {
  max-height: 240px;
  overflow-y: auto;
}

.chooser-panel,
.chooser-list {
  outline: none;
}

/* The menu form: the trigger is a glyph, so it takes none of the select's
   geometry, and its ring sits outside the mark rather than across it. */
.chooser-icon .chooser-trigger {
  padding: 3px;
  border: 0;
  outline-offset: 1px;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
}

.chooser-icon .chooser-trigger:hover,
.chooser-icon .chooser-trigger[aria-expanded="true"] {
  color: var(--text);
}

/* Anchored to the glyph's end edge, because it opens at the end of the row it
   acts on. `width: max-content` because shrink-to-fit against a 22px anchor
   collapses every option name. */
.chooser-icon .chooser-panel {
  inset-inline: auto 0;
  width: max-content;
}

.chooser-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 5px 7px;
  border-bottom: 1px solid var(--rule);
}

/* The sheet's alone: an anchored panel opens under a trigger that still says
   what it chooses. `flex-basis: 100%` gives it the row above the filter. */
.chooser-title {
  display: none;
  flex: 1 0 100%;
  padding: 2px;
  font-size: var(--text-md);
  font-weight: 600;
}

.chooser-filter {
  flex: 1;
  min-width: 0;
  padding: 2px;
  border: 0;
  background: none;
  font-size: var(--text-sm);
}

.chooser-filter:focus {
  outline: none;
}

/* The sheet's only way out, and only the sheet's: touch has no Escape key, and
   a panel filling the viewport leaves nothing outside it to tap. */
.chooser-close {
  display: none;
  flex: none;
  align-items: center;
  padding: 6px;
  border: 0;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
}

.chooser-close:hover {
  color: var(--text);
}

.chooser-group-head {
  padding: 6px 10px 4px;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* A menu's head names what picking does, in a sentence; the letter-spaced caps
   are for the one- and two-word category names they were set for. */
.chooser-icon .chooser-group-head {
  letter-spacing: normal;
  text-transform: none;
}

.chooser-option {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  font-size: var(--text-sm);
  color: var(--text);
  cursor: pointer;
}

.chooser-option[hidden] {
  display: none;
}

/* The keyboard cursor, in the treatment .palette-cmd.active and .row.selected
   already use: the wash alone is far too faint to read as a cursor. */
.chooser-option:hover,
.chooser-option.active {
  background: var(--surface-selected);
  box-shadow: inset 2px 0 0 var(--accent);
}

.chooser-check {
  margin-inline-start: auto;
  flex: none;
  visibility: hidden;
}

.chooser-option[aria-selected="true"] .chooser-check {
  visibility: visible;
}

.chooser-empty {
  padding: 6px 10px;
  font-size: var(--text-sm);
  color: var(--text-faint);
}

/* The wheel renders plain text, so a panel is the only surface that can carry
   the atom on touch; its rows are sized for a finger there. */
@media (pointer: coarse) {
  .chooser-option {
    padding-block: 10px;
  }

  /* A glyph is the sweep's only affordance, and 16px of it clears no finger. */
  .chooser-icon .chooser-trigger {
    padding: 8px;
  }
}

/* The sheet ADR 0010 trades the native mobile picker for. The z-index clears
   .nav-toggle (fixed at 30) wherever the chooser is not itself inside a
   stacking context — .bulk-bar's sticky z-index makes one, and there the sheet
   cannot rise past it. `width` is reset alongside `max-width` because the icon
   form sizes itself `max-content`, which a full-viewport surface must not. */
@media (width <= 640px) {
  .chooser-long .chooser-panel {
    position: fixed;
    inset: 0;
    z-index: 40;
    width: auto;
    max-width: none;
  }

  .chooser-long .chooser-list {
    flex: 1;
    max-height: none;
    padding-bottom: 16px;
    overscroll-behavior: contain;
  }

  .chooser-long .chooser-title {
    display: block;
  }

  /* 16px of glyph clears no finger, and this one is the only way out. */
  .chooser-long .chooser-close {
    display: inline-flex;
    padding: 10px;
  }

  /* iOS Safari zooms the layout on focusing anything under 16px, and the sheet
     is focused the moment it opens; a zoomed viewport is smaller than the
     fixed panel, which puts the close glyph off screen. ADR 0009 has no 16px
     step, so this takes the one above rather than a literal. */
  .chooser-long .chooser-filter {
    font-size: var(--text-lg);
  }
}

/* ── Chips, badges, labels ─────────────────────────────────────────────── */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.03em;
  background: var(--accent-wash);
  border: 1px solid var(--accent);
  color: var(--text);
  padding: 2px 9px;
}

.badge {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  padding: 0 5px;
  line-height: 16px;
  border: 1px solid var(--rule-strong);
  color: var(--text);
  min-width: 20px;
  text-align: center;
}

.badge-hot {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: var(--text-on-accent);
  font-weight: 600;
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.05em;
  color: var(--text-soft);
  border: 1px solid var(--rule);
  padding: 0 6px;
  line-height: 16px;
  background: var(--surface);
}

.tag i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  flex-shrink: 0;
}

.lamp {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--lamp-ok);
}

/* ── Label management rows (workspace settings and the team Labels page) ── */

.label-rows {
  list-style: none;
  margin: 0;
  padding: 0;
}

.label-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 3px 0;
  border-bottom: 1px solid var(--rule);
}

.label-count {
  flex: 1;
  font-size: var(--text-xs);
  color: var(--text-faint);
}

/* ── The user-pickable palette: state dots and label dots ──────────────── */

.palette-gray {
  background: var(--palette-gray);
}

.palette-red {
  background: var(--palette-red);
}

.palette-orange {
  background: var(--palette-orange);
}

.palette-amber {
  background: var(--palette-amber);
}

.palette-green {
  background: var(--palette-green);
}

.palette-teal {
  background: var(--palette-teal);
}

.palette-blue {
  background: var(--palette-blue);
}

.palette-purple {
  background: var(--palette-purple);
}

/* ── Workflow states: named steps, machine-readable categories ─────────── */

.state-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}

.state-cat {
  margin-bottom: 16px;
}

.state-cat-head {
  display: flex;
  align-items: center;
  gap: 10px;
  border-bottom: 1px solid var(--rule-strong);
  padding-bottom: 3px;
}

.state-cat-name {
  margin: 0;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.state-cat-code {
  margin-left: auto;
  font-size: var(--text-xs);
  letter-spacing: 0.16em;
  color: var(--text-faint);
}

.state-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.state-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 3px 0;
  border-bottom: 1px solid var(--rule);
}

.state-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.color-options {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.color-option {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 10px;
  border: 1px solid var(--rule);
  font-size: var(--text-sm);
  cursor: pointer;
}

.color-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.color-option:hover {
  border-color: var(--rule-strong);
}

.color-option:has(input:checked) {
  border-color: var(--rule-strong);
  background: var(--surface-selected);
}

.color-option:has(input:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* ── Attribution: humans are round ink, agents are machine-printed chips ── */

.avatar {
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--text);
  color: var(--surface);
  font-size: var(--text-micro);
  font-weight: 600;
  flex-shrink: 0;
}

.agent-mark {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 0 6px;
  line-height: 18px;
  background: var(--agent-bg);
  color: var(--agent-fg);
  border: 1px solid var(--agent-border);
  white-space: nowrap;
}

.agent-name {
  overflow: hidden;
  text-overflow: ellipsis;
}

.agent-owner {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  color: var(--text-faint);
}

/* An Agent's avatar: a square machine dot in its chosen palette color.
   Rimmed in agent ink so it stays legible on Console's reverse-video chip. */
.agent-dot {
  width: 8px;
  height: 8px;
  flex-shrink: 0;
  box-shadow: 0 0 0 1px var(--agent-fg);
}

/* ── Hairline list primitives ──────────────────────────────────────────── */

.group-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 14px 20px 6px;
  border-bottom: 1px solid var(--rule-strong);
}

.group-title {
  font-weight: 700;
  font-size: var(--text-sm);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.group-count {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.group-cat {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.16em;
  color: var(--text-faint);
  text-transform: uppercase;
}

.group-more {
  padding: 6px 20px 12px 14px;
  border-bottom: 1px solid var(--rule);
}

.row {
  display: grid;

  /* Key hugs its content (cross-team keys outgrow a fixed column), title
     flexes; every later cell (labels, state, meta, actions) sizes to content
     in its own implicit column. */
  grid-auto-flow: column;
  grid-template-columns: minmax(74px, max-content) minmax(0, 1fr);
  grid-auto-columns: auto;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
  height: 36px;
  border-bottom: 1px solid var(--rule);
}

/* Team, Project and Triage rows reuse this shell without the whole-row click,
   so only a row that follows may claim to be clickable. */
.row:has([data-follow-link-target]) {
  cursor: pointer;
}

.row:has(.row-check) {
  grid-template-columns: auto minmax(74px, max-content) minmax(0, 1fr);
}

.row-check {
  width: 14px;
  height: 14px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.row:hover {
  background: var(--surface-sunken);
}

.row.selected {
  background: var(--surface-selected);
  box-shadow: inset 2px 0 0 var(--accent);
}

.row-key {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
  color: var(--text-soft);
}

.row-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.row-meta {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

/* One anchor per row; spans keep their grid cells */
.row-link {
  display: contents;
}

@media (width <= 640px) {
  .row-meta {
    display: none;
  }
}

/* ── Empty states teach the next action ────────────────────────────────── */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 32px 20px;
  border: 1px dashed var(--rule-strong);
  text-align: center;
}

.empty-title {
  font-weight: 600;
}

.empty-body {
  color: var(--text-soft);
  max-width: 42ch;
}

/* ── Search: one field, ranked results, highlighted matches ────────────── */

.search-form {
  padding: 14px 20px;
  border-bottom: 1px solid var(--rule);
}

.search-field {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 640px;
}

.search-field-icon {
  color: var(--text-faint);
  flex: none;
}

.search-input {
  flex: 1;
}

.search-result {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 9px 20px;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  color: inherit;
}

.search-result:hover {
  background: var(--surface-sunken);
}

.search-result-head {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.search-result-title {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.search-result-labels {
  display: flex;
  gap: 4px;
  flex: none;
}

.search-result-state {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
  font-size: var(--text-xs);
  color: var(--text-soft);
}

.search-result-by {
  flex: none;
}

.search-snippet {
  font-size: var(--text-sm);
  color: var(--text-soft);
  line-height: 1.5;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.search-snippet mark {
  background: var(--accent-wash);
  color: var(--accent-strong);
  font-weight: 600;
  border-radius: 2px;
  padding: 0 1px;
}

@media (width <= 640px) {
  .search-result-state-name,
  .search-result-labels {
    display: none;
  }
}

/* ── Auth: the door to the desk ────────────────────────────────────────── */

.auth {
  flex: 1;
  min-height: 0;
  display: grid;
  place-items: center;
  padding: 20px;
}

.auth-card {
  width: min(360px, 100%);
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.auth-brand {
  padding-bottom: 12px;
  border-bottom: 1px solid var(--rule);
}

.auth-title {
  margin: 0 0 4px;
  font-size: var(--text-md);
  font-weight: 700;
}

.auth-body {
  margin: 0;
  color: var(--text-soft);
}

/* Emails are unbroken machine strings; let them wrap inside the card */
.auth-body .machine {
  overflow-wrap: anywhere;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.auth-form .btn {
  justify-content: center;
}

.input-code {
  font-size: var(--text-xl);
  letter-spacing: 0.35em;
  text-align: center;
}

.auth-note {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-faint);
  border-top: 1px dashed var(--rule);
  padding-top: 12px;
}

.auth-alt {
  display: flex;
  gap: 8px;
}

/* ── Onboarding: pick your instrument ──────────────────────────────────── */

.onboard {
  flex: 1;
  min-height: 0;
  display: grid;
  place-items: center;
  padding: 24px 20px;
}

.onboard-card {
  width: min(680px, 100%);
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.onboard-head {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.onboard-eyebrow {
  font-size: var(--text-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.onboard-title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 700;
}

.onboard-body {
  margin: 0;
  color: var(--text-soft);
  max-width: 60ch;
}

.onboard-note {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.onboard-submit {
  align-self: flex-start;
}

.theme-picker {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.theme-options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
  margin: 0;
  padding: 0;
  border: 0;
}

.theme-option {
  position: relative;
  display: block;
  cursor: pointer;
}

.theme-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.theme-option-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--rule);
  transition: border-color var(--dur) var(--ease);
}

.theme-option:hover .theme-option-card {
  border-color: var(--rule-strong);
}

.theme-option:has(input:checked) .theme-option-card {
  border-color: var(--accent);
  background: var(--surface-selected);
}

.theme-option:has(input:focus-visible) .theme-option-card {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.theme-option-name {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.theme-option-label {
  font-weight: 600;
}

.theme-option-tag {
  font-size: var(--text-sm);
  color: var(--text-soft);
}

/* A live theme island: nested data-theme resolves the other instrument's
   tokens (ADR 0004), so both render true, side by side, before you choose. */
.tp-preview {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-body);
  border: 1px solid var(--rule);
}

.tp-topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--rule);
}

.tp-crumb {
  font-size: var(--text-xs);
  color: var(--text-soft);
}

.tp-spacer {
  flex: 1;
}

.tp-btn {
  padding: 3px 8px;
  font-size: var(--text-xs);
  background: var(--accent);
  color: var(--text-on-accent);
}

.tp-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tp-key {
  font-size: var(--text-xs);
  color: var(--text-soft);
}

.tp-title {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The footer toggle is a form now (persists per user); lay the button out
   as if the form were not there. */
.theme-form {
  display: contents;
}

/* ── Status row: what you just did, server- or client-written (ADR 0011) ── */

/* A grid, not a row: a refused attachment reports its notice and its alert
   together, and two messages belong under each other, not beside each other. */
.status-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 10px;
  padding: 0 20px;
  background: var(--surface-sunken);
}

.status-row:has(.status-row-text:not(:empty)) {
  border-bottom: 1px solid var(--rule);
}

.status-row-text {
  grid-column: 1;
  margin: 0;
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

.status-row-text:not(:empty) {
  padding: 7px 0;
}

.status-row-text[role="alert"] {
  color: var(--accent-strong);
}

.status-row-dismiss {
  display: inline-flex;
  align-items: center;
  grid-column: 2;
  grid-row: 1;
  padding: 6px;
  border: 0;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
}

.status-row-dismiss[hidden] {
  display: none;
}

.status-row-dismiss:hover {
  color: var(--text);
}

/* ── Settings: the device list is the safety valve ─────────────────────── */

.settings-body {
  max-width: 720px;
  width: 100%;
  margin: 0 auto;
  padding: 24px 20px;
}

.settings-title {
  margin: 0 0 4px;
  font-size: var(--text-md);
  font-weight: 700;
}

.settings-note {
  margin: 0 0 20px;
  color: var(--text-soft);
}

.settings-whoami {
  font-size: var(--text-xs);
  color: var(--text-soft);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* group-head's full-bleed padding double-indents inside the padded settings column */
.settings-body .group-head {
  padding-inline: 0;
}

.settings-section {
  margin-bottom: 28px;
}

.session-list {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
}

.session-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
}

.session-device {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  min-width: 0;
}

.session-meta {
  font-size: var(--text-xs);
  color: var(--text-faint);
  white-space: nowrap;
}

@media (width <= 640px) {
  .session-row {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .session-meta {
    grid-column: 1 / -1;
    grid-row: 2;
    white-space: normal;
  }
}

/* ── Workspace switcher: a details disclosure, no JS ───────────────────── */

.switcher summary {
  list-style: none;
}

.switcher summary::-webkit-details-marker {
  display: none;
}

.switcher[open] > summary .ic {
  transform: rotate(180deg);
}

.switcher-menu {
  padding: 4px 0;
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--rule);
}

/* ── Links and button_to forms inside flex/grid shells ─────────────────── */

a.nav-item,
a.btn,
.row a {
  text-decoration: none;
}

.row a {
  color: inherit;
}

.row-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}

.row-actions form,
.foot-links form,
.topbar form {
  display: contents;
}

.foot-links {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding-top: 8px;
}

/* ── Standalone forms ──────────────────────────────────────────────────── */

.form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: 420px;
  margin-bottom: 28px;
}

.form .btn {
  align-self: flex-start;
}

.field-hint {
  margin: 0;
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.field-error {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--accent-strong);
}

.slug-input {
  display: flex;
  align-items: center;
  gap: 6px;
}

.slug-prefix {
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.slug-input .input {
  flex: 1;
  min-width: 0;
}

.main > .empty {
  margin: 20px;
}

/* ── Issue rows: key and state are machine matter ──────────────────────── */

.row-state {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
  color: var(--text-soft);
  white-space: nowrap;
}

.row-labels {
  display: flex;
  align-items: center;
  gap: 5px;

  /* Chips never crush the issue title */
  max-width: 30%;
  overflow: hidden;
}

/* Long label names ellipsize inside the chip instead of bursting it */
.tag-name {
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (width <= 640px) {
  .row-state-name,
  .row-labels {
    display: none;
  }
}

/* ── Collapsible state groups: the list remembers what you folded ──────── */

.group > .group-head {
  align-items: center;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.group > .group-head::-webkit-details-marker {
  display: none;
}

.group-caret {
  color: var(--text-faint);
  transition: transform var(--dur-fast) var(--ease);
}

.group:not([open]) .group-caret {
  transform: rotate(-90deg);
}

/* ── The sweep menu: a board column head and a list group head ─────────── */

.sweep-menu {
  display: flex;
}

/* The board pushes its menu out with the column name's `flex`; a list group
   head has nothing that grows. */
.group > .group-head .sweep-menu {
  margin-inline-start: auto;
}

/* Hidden by design: the picker that submits it lives in the state's head,
   inside that surface's bulk form, and a form cannot nest. */
.sweep-form {
  display: none;
}

/* ── Filter bar: every filtered view is a URL ──────────────────────────── */

.filter-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 20px;
  border-bottom: 1px solid var(--rule);
  background: var(--surface-sunken);
}

.filter-bar-mark {
  color: var(--text-faint);
  flex-shrink: 0;
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
  line-height: 20px;
  padding: 1px 2px 1px 8px;
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  white-space: nowrap;
}

.filter-chip-dim {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.filter-chip-x {
  display: inline-flex;
  align-items: center;
  padding: 3px;
  color: var(--text-faint);
}

.filter-chip-x:hover {
  color: var(--text);
}

/* The bar's pickers are choosers, and their triggers carry .input, so the
   whole row keeps one geometry from the one rule (ADR 0010). */
.filter-bar .input {
  font-size: var(--text-sm);
  padding: 3px 7px;
}

/* ── Bulk bar: select rows, dispatch them together ─────────────────────── */

.bulk-bar[hidden] {
  display: none;
}

.bulk-bar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 20px;
  background: var(--surface-raised);
  border-bottom: 1px solid var(--rule-strong);
}

.bulk-bar .input {
  font-size: var(--text-sm);
  padding: 3px 7px;
}

.bulk-count {
  font-size: var(--text-xs);
  color: var(--text-soft);
}

.bulk-limit {
  padding: 3px 7px;
  font-size: var(--text-xs);
  color: var(--text);
  background: var(--accent-wash);
  border: 1px solid var(--accent-strong);
}

/* ── Ticker: the team's last change, live and attributed ───────────────── */

.ticker {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 7px 20px;
  border-bottom: 1px solid var(--rule);
  color: var(--text-soft);
  white-space: nowrap;
}

.ticker-issue {
  flex-shrink: 0;
  text-decoration: none;
}

.ticker-issue:hover .row-key {
  color: var(--text);
}

.ticker-who {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  min-width: 0;
  max-width: 45%;
}

.ticker-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Agent entries print in mono: the attribution language of the product */
.ticker-agent .ticker-text {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}

.ticker time {
  margin-left: auto;
  font-size: var(--text-sm);
  color: var(--text-faint);
}

/* ── Board: columns by state, drag is the transition ───────────────────── */

.board {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.board-hint {
  margin: 0;
  padding: 6px 20px 0;
  font-size: var(--text-sm);
  color: var(--text-soft);
}

.board-cols {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: stretch;
  overflow-x: auto;
}

/* A card wide enough for several labels is what growing buys. */
.board-col {
  flex: 1 0 236px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--rule);
}

/* Only some columns carry a sweep menu, and its trigger is taller than the
   head's text: without a floor the rule would land at a different height per
   column and stop reading as one line across the row. */

/* A fixed height, not a floor: the rule beneath these runs across the whole row,
   and only some columns carry a sweep trigger. A floor has to be re-derived
   every time that trigger's box changes — it was, in MACH-49, and the rule
   stepped 4px for months. The trigger centres and overflows its content box
   instead, which also absorbs the coarse-pointer size. */
.board-col-head {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  padding: 10px 12px 7px;
  border-bottom: 1px solid var(--rule-strong);
}

.board-col-name {
  flex: 1;
  min-width: 0;
  font-weight: 700;
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.board-count {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.board-cards {
  flex: 1;
  min-height: 120px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
}

.board-more {
  align-self: flex-start;
  margin: 4px 8px 10px;
}

/* .board-cols clips to its own box whether or not it currently overflows, and
   its clip edge lands wherever the row is scrolled to — inside a middle column
   as readily as at the first one's start edge. So the cap is what keeps a panel
   inside its own column, anchored 12px in from the column's end. A full-width
   list row has no such edge and takes the chooser's own cap. */
.board-col .chooser-icon .chooser-panel {
  max-width: 208px;
}

.card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 10px;
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  cursor: grab;
}

.card:active {
  cursor: grabbing;
}

.card:hover {
  background: var(--surface-raised);
}

.card.sortable-ghost {
  opacity: 0.45;
  border-style: dashed;
}

/* Checkbox and key share the card's first line: the checkbox cannot live
   inside the anchor, and it must not cost the card a second line. */
.card-head {
  display: flex;
  align-items: center;
  gap: 7px;
}

.card-link {
  display: block;
  color: inherit;
  text-decoration: none;
}

.card-title {
  font-size: var(--text-sm);
  line-height: 1.35;
}

.card-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}

.card-meta .row-labels {
  max-width: 100%;
}

/* ── Issue detail: human matter left, machine props right ──────────────── */

.issue {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
}

.issue-main {
  min-width: 0;
  padding: 20px;
  overflow-y: auto;
}

/* The scroll container stays full-width so its scrollbar sits at the column edge
   next to the sidebar; the reading blocks center inside it, so a wide monitor
   splits the leftover space on both sides instead of one void on the right. */
.issue-main > * {
  max-width: 1000px;
  margin-inline: auto;
}

.issue-title {
  margin: 0 auto 12px;
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.3;
}

.issue-props {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px;
  overflow-y: auto;
  border-left: 1px solid var(--rule);
  background: var(--surface-sunken);
}

.prop {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* The rail's pickers sit one <form> deep, and a block container leaves an
   inline-flex .chooser at shrink-to-fit, so the trigger's width: 100% would
   resolve against a box the width of its own text. */
.prop .input,
.prop .chooser {
  width: 100%;
}

.prop-value {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.prop-chips {
  flex-wrap: wrap;
}

.prop-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.prop-head-link {
  font-size: var(--text-xs);
  color: var(--text-faint);
  text-decoration: none;
}

.prop-head-link:hover {
  color: var(--text);
  text-decoration: underline;
}

.label-chip-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 6px;
}

.label-chip-item {
  display: inline-flex;
  align-items: center;
  min-width: 0;
  max-width: 100%;
}

.label-chip-item form {
  display: contents;
}

.prop-meta {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px dashed var(--rule);
}

.member-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (width <= 900px) {
  .issue {
    min-height: auto;
    grid-template-columns: minmax(0, 1fr);
  }

  /* One page scroll on narrow screens; the split-scroll only makes sense wide. */
  .issue-main,
  .issue-props {
    overflow-y: visible;
  }

  .issue-props {
    border-left: 0;
    border-bottom: 1px solid var(--rule);

    /* Properties above the history: triage-and-reply without scrolling past it */
    order: -1;
  }
}

/* Wide-viewport-only button labels collapse to their icon at phone width.
   Visually hidden, not display:none — role="status" still announces. */
@media (width <= 640px) {
  .btn-label-wide {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* ── Sub-issues and relations: the issue's place in the plan ───────────── */

.blocked-banner {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 12px;
  margin: 0 auto 14px;
  padding: 8px 12px;
  border: 1px solid var(--accent-strong);
  border-left-width: 3px;
  background: var(--accent-wash);
  font-size: var(--text-sm);
}

.blocked-banner-label {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-weight: 700;
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-strong);
  white-space: nowrap;
}

.blocked-banner-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.blocked-banner-issue {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  color: var(--text);
  text-decoration: none;
}

.blocked-banner-issue:hover .blocked-banner-title {
  text-decoration: underline;
}

.blocked-banner-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sub-progress {
  font-size: var(--text-xs);
  color: var(--text-soft);
  white-space: nowrap;
}

.pane-lead .sub-progress {
  margin-left: auto;
}

.sub-meter {
  align-self: center;
  width: 72px;
  height: 4px;
  appearance: none;
  border: none;
  background: var(--surface-raised);
}

.sub-meter::-webkit-progress-bar {
  background: var(--surface-raised);
}

.sub-meter::-webkit-progress-value {
  background: var(--accent);
}

.sub-meter::-moz-progress-bar {
  background: var(--accent);
}

/* The count says it all on phones; the bar would burst the group head */
@media (width <= 640px) {
  .sub-meter {
    display: none;
  }
}

.quick-add {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}

.quick-add > .field-error {
  flex-basis: 100%;
}

.quick-add-title {
  flex: 1 1 220px;
  min-width: 0;
}

.quick-add-key {
  flex: 0 1 110px;
  min-width: 0;
}

.quick-add-option {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--text-sm);
  color: var(--text-soft);
  white-space: nowrap;
}

.relation-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.relation {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  border-bottom: 1px solid var(--rule);
  font-size: var(--text-base);
}

.relation-kind {
  flex: none;
  min-width: 92px;
  font-size: var(--text-xs);
  color: var(--text-soft);
}

.relation-blocked .relation-kind {
  color: var(--accent-strong);
  font-weight: 700;
}

.relation-issue {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex: 1;
  min-width: 0;
  color: var(--text);
  text-decoration: none;
}

.relation-issue:hover .relation-title {
  text-decoration: underline;
}

.relation-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Links: titled URLs, the PR bridge ─────────────────────────────────── */

.link-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.link-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  border-bottom: 1px solid var(--rule);
  font-size: var(--text-base);
}

.link-row > .ic {
  flex: none;
  color: var(--text-soft);
}

.link-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  text-decoration: none;
}

.link-title:hover {
  text-decoration: underline;
}

.link-host {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.quick-add-url {
  flex: 2 1 240px;
  min-width: 0;
}

/* ── Attachments: inline images and file chips ─────────────────────────── */

.attachment-list {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 8px;
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
}

.attachment {
  display: flex;
  align-items: flex-start;
  gap: 2px;
  min-width: 0;
  max-width: 100%;
}

.attachment-image img {
  display: block;
  max-width: min(320px, 100%);
  max-height: 220px;
  border: 1px solid var(--rule-strong);
}

.attachment-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  padding: 3px 8px;
  border: 1px solid var(--rule-strong);
  background: var(--surface-raised);
  color: var(--text);
  text-decoration: none;
  font-size: var(--text-xs);
}

.attachment-chip:hover {
  border-color: var(--accent);
}

.attachment-chip > .ic {
  flex: none;
  color: var(--text-soft);
}

.attachment-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attachment-size {
  color: var(--text-faint);
  white-space: nowrap;
}

/* ── Attaching: a themed trigger and the files not yet submitted ───────── */

.attach,
.attach-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.attach-form {
  gap: 12px;
  margin-top: 10px;
}

.attach-trigger {
  position: relative;
}

/* Invisible rather than hidden, and lying on the trigger rather than beside it:
   the picker, the keyboard and the validation bubble all still have to come
   from the real control. */
.attach-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.attach-trigger:has(.attach-input:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* Holds nothing but hidden inputs, so it must not take a row of the column. */
.attach-uploaded {
  display: contents;
}

.attach-pending {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  max-width: 100%;
  list-style: none;
  margin: 0;
  padding: 0;
}

.attach-pending[hidden] {
  display: none;
}

/* No fill, so a pending file reads lighter than the attached chips it sits
   beside — and so .btn-text:hover still reveals the remove button. */
.attach-pending-file {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 0 2px 0 8px;
  border: 1px solid var(--rule);
  font-size: var(--text-xs);
}

.attach-pending-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attach-pending-size {
  color: var(--text-faint);
  white-space: nowrap;
}

.attach-pending-file .attach-remove {
  align-self: center;
}

.attach-over {
  outline: 1px dashed var(--accent);
  outline-offset: 3px;
}

.section-empty {
  margin: 8px 0 0;
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.prop-parent {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
  font-size: var(--text-sm);
  color: var(--text);
  text-decoration: none;
}

.prop-parent:hover .prop-parent-title {
  text-decoration: underline;
}

.prop-parent-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Rendered Markdown (the one sanitized pipeline) ────────────────────── */

.prose {
  max-width: 68ch;
}

.prose > :first-child {
  margin-top: 0;
}

.prose h1,
.prose h2,
.prose h3,
.prose h4,
.prose h5,
.prose h6 {
  margin: 18px 0 6px;
  font-size: var(--text-base);
  font-weight: 700;
}

.prose h1 {
  font-size: var(--text-md);
}

.prose p,
.prose ul,
.prose ol,
.prose table {
  margin: 0 0 10px;
}

.prose a {
  color: var(--accent-strong);
}

.prose code {
  font-family: var(--font-mono);
  font-size: var(--text-inline);
  background: var(--surface-sunken);
  border: 1px solid var(--rule);
  padding: 0 3px;
}

.prose pre {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  background: var(--surface-sunken);
  border: 1px solid var(--rule);
  padding: 10px 12px;
  overflow-x: auto;
}

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

.prose blockquote {
  margin: 0 0 10px;
  padding-left: 12px;
  border-left: 2px solid var(--rule-strong);
  color: var(--text-soft);
}

/* Wide tables (agents paste these constantly) scroll inside themselves,
   never the page */
.prose table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
}

.prose th,
.prose td {
  border: 1px solid var(--rule);
  padding: 4px 8px;
  text-align: left;
}

.prose hr {
  border: 0;
  border-top: 1px dashed var(--rule-strong);
}

.prose img {
  max-width: 100%;
}

/* Task lists: the checkbox is the marker, so it takes the marker's place in
   the indent rather than sitting beside a bullet. */
.prose li:has(> input[type="checkbox"]) {
  list-style: none;
}

.prose input[type="checkbox"] {
  margin: 0 6px 0 -1.4em;
  accent-color: var(--accent);
}

.prose-empty {
  margin: 0 auto;
  color: var(--text-faint);
}

/* ── Issue page: a wide reading column, a spec spine, a tabbed record ───── */

/* Surfaces that are themselves a bounded reading column — the centered
   .issue-main, the 40% drawer — let prose fill them; everything else keeps the
   global 68ch, which is what bounds it there. */
.issue-main .prose,
.drawer-body .prose {
  max-width: none;
}

.issue-desc {
  margin: 0 auto 4px;
  padding-left: 18px;
  border-left: 2px solid var(--rule);
}

.issue-desc .prose > :first-child {
  margin-top: 0;
}

.issue-desc .prose > p:first-child {
  line-height: 1.6;
}

/* Top-level sections are accent landmarks; h3 stays a subordinate heading so a
   description's own hierarchy survives instead of flattening to one level. */
.issue-desc .prose h1,
.issue-desc .prose h2 {
  margin: 22px 0 7px;
  padding-bottom: 3px;
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-strong);
  border-bottom: 1px solid var(--rule);
}

.issue-desc .prose h3 {
  margin: 16px 0 5px;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text);
}

.issue-desc .prose li {
  margin: 4px 0;
}

.issue-desc .prose li::marker {
  color: var(--rule-strong);
}

/* The accreting record — comments, activity, links, sub-issues, relations,
   attachments — under one sticky tab strip. Panels ship in the HTML; the tabs
   controller reveals one at a time (JS-required). */
.issue-record {
  margin-top: 20px;
}

.tabs {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  gap: 2px;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  background: var(--surface);
  border-bottom: 1px solid var(--rule-strong);
}

.tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex-shrink: 0;
  padding: 10px 12px 9px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--text-soft);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}

.tab:hover {
  color: var(--text);
}

.tab[aria-selected="true"] {
  color: var(--text);
  border-bottom-color: var(--accent);
}

.tab:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

.tab-count {
  padding: 0 5px;
  border: 1px solid var(--rule);
  font-size: var(--text-xs);
  line-height: 16px;
  color: var(--text-faint);
}

.tab[aria-selected="true"] .tab-count {
  color: var(--accent-strong);
  border-color: var(--accent-strong);
}

.pane {
  padding-top: 12px;
}

.pane[hidden] {
  display: none;
}

.pane-lead {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 8px;
}

/* ── The Markdown editor: toolbar, tabs, slash menu ────────────────────── */

.mdtabs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}

.mdtabs .btn.active {
  color: var(--text);
  background: var(--surface-raised);
}

.md-tools {
  display: flex;
  align-items: center;
  gap: 2px;
  padding-inline-start: 6px;
}

.md-tools[hidden] {
  display: none;
}

/* The mode pair travels together when the row wraps; a flexible spacer would
   strand Preview on the next line. */
.md-modes {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-inline-start: auto;
}

/* 24px is the floor for a target, and on a phone these four are the only path
   to bold, italic, a link and the structures there is no key for. */
.md-tool {
  min-width: 24px;
  min-height: 24px;
  padding: 4px 7px;
}

.md-glyph {
  font-size: var(--text-base);
  line-height: 14px;
}

.md-preview {
  min-height: 120px;
  padding: 10px 12px;
  border: 1px solid var(--rule);
  background: var(--surface);
}

/* No family and no size: a description is human matter and takes the body
   register (ADR 0014). */
.md-source {
  line-height: 1.6;
}

.md-anchor {
  position: relative;
}

.md-anchor .input {
  width: 100%;
}

.issue-form {
  max-width: 560px;
}

/* ── Mentions: members called into the thread by handle ────────────────── */

.mention {
  background: var(--accent-wash);
  color: var(--text);
  padding: 0 3px;
  border-radius: 2px;
}

/* Agent mentions print in agent ink, like every agent trace */
.mention-agent {
  font-family: var(--font-mono);
  font-size: var(--text-inline);
  background: var(--agent-bg);
  color: var(--agent-fg);
  border: 1px solid var(--agent-border);
}

/* Both menus anchor to the same textarea and a writer sees them under one
   field, so they are one surface with one definition. */
.mention-menu,
.md-menu {
  position: absolute;
  inset-inline: 0;
  top: calc(100% + 2px);
  z-index: 30;
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--rule-strong);
  background: var(--surface-raised);
}

.mention-options,
.md-menu {
  list-style: none;
  margin: 0;
  padding: 0;
}

.mention-option,
.md-option {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 6px 10px;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
}

/* The keyboard cursor, in the treatment .chooser-option already uses: the wash
   alone is far too faint to read as a cursor. */
.mention-option:hover,
.mention-option.active,
.md-option:hover,
.md-option.active {
  background: var(--surface-selected);
  box-shadow: inset 2px 0 0 var(--accent);
}

.md-option-syntax {
  margin-inline-start: auto;
  color: var(--text-faint);
  font-size: var(--text-xs);
}

/* The styleguide's sample stands in the flow; only the real menu anchors. */
.sg-md-menu {
  position: static;
  max-width: 280px;
}

@media (pointer: coarse) {
  .mention-option,
  .md-option {
    padding-block: 10px;
  }

  /* Matched to .chooser-icon's trigger: the app's floor for a glyph-only
     control on a finger, not the 24px minimum. */
  .md-tool {
    padding: 10px;
  }
}

.mention-none {
  margin: 0;
  padding: 6px 10px;
  font-size: var(--text-sm);
  color: var(--text-faint);
}

/* ── Comments: the conversation, attributed like everything else ───────── */

.comment-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.comment {
  padding: 10px 0;
  border-bottom: 1px solid var(--rule);
}

.comment-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: var(--text-sm);
}

.comment-head time {
  font-size: var(--text-xs);
  color: var(--text-faint);
  white-space: nowrap;
}

.comment-edited {
  font-size: var(--text-xs);
  font-style: italic;
  color: var(--text-faint);
}

.comment-body {
  margin-top: 6px;
  overflow-wrap: break-word;
}

/* Agent comments print in mono: the attribution language of the product */
.comment-agent .comment-body {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}

.comment-tombstone {
  margin: 0;
  font-size: var(--text-sm);
  font-style: italic;
  color: var(--text-faint);
}

.comments-empty {
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.comment-form {
  margin-top: 12px;
}

/* ── Activity: the attributed history of every issue ───────────────────── */

.act-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.act {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--rule);
  font-size: var(--text-sm);
}

.act-who {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  min-width: 0;
  max-width: 45%;
}

.act-text {
  flex: 1;
  min-width: 0;
  color: var(--text-soft);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

/* Agent entries print in mono: the attribution language of the product */
.act-agent .act-text {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.act time {
  font-size: var(--text-xs);
  color: var(--text-faint);
  white-space: nowrap;
}

/* ── Triage: the dispatch queue — accept routes to human, agent, or backlog ── */

.triage-item {
  padding: 10px 20px 12px;
  border-bottom: 1px solid var(--rule);
}

.triage-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  min-height: 26px;
}

.triage-row .row-title {
  font-weight: 600;
}

.triage-reporter {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  font-size: var(--text-sm);
  color: var(--text-soft);
}

.triage-reporter time {
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.triage-flag {
  border-color: var(--accent);
  background: var(--accent-wash);
  white-space: nowrap;
}

.triage-actions {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.triage-more summary {
  list-style: none;
}

.triage-more summary::-webkit-details-marker {
  display: none;
}

.triage-more[open] summary {
  border-color: var(--text);
  color: var(--text);
}

.triage-form {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.triage-question {
  flex: 1 1 260px;
  min-width: 0;
  resize: vertical;
}

/* ── Inbox: the personal feed — agent work groups per issue ────────────── */

.inbox-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.inbox-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
  min-height: 40px;
  border-bottom: 1px solid var(--rule);
  font-size: var(--text-sm);
}

.inbox-row:hover {
  background: var(--surface-sunken);
}

.inbox-row form {
  display: contents;
}

.inbox-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.inbox-unread .inbox-dot {
  background: var(--accent);
}

.inbox-who {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  max-width: 30%;
}

.inbox-text {
  color: var(--text-soft);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Agent-actor rows print in mono: the attribution language of the product */
.inbox-agent .inbox-text,
.inbox-group .inbox-text {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.inbox-issue {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.inbox-issue:hover .inbox-issue-title {
  text-decoration: underline;
}

.inbox-issue-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.inbox-row > time,
.inbox-fold summary > time {
  margin-left: auto;
  font-size: var(--text-xs);
  color: var(--text-faint);
  white-space: nowrap;
}

/* The agent group: one row per issue, the action list folds out */
.inbox-group {
  align-items: flex-start;
}

.inbox-fold {
  flex: 1;
  min-width: 0;
}

.inbox-fold summary {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  cursor: pointer;
  list-style: none;
}

.inbox-fold summary::-webkit-details-marker {
  display: none;
}

.inbox-fold:not([open]) .group-caret {
  transform: rotate(-90deg);
}

.inbox-group-read {
  margin-top: 7px;
}

.inbox-actions {
  list-style: none;
  margin: 0 0 8px;
  padding: 0 0 0 17px;
  border-left: 1px solid var(--rule);
}

.inbox-action {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.inbox-action-who {
  flex-shrink: 0;
}

.inbox-action-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--agent-text);
  text-decoration: none;
}

.inbox-action-text:hover {
  text-decoration: underline;
}

.inbox-action time {
  font-size: var(--text-xs);
  color: var(--text-faint);
  white-space: nowrap;
}

.inbox-channels {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 20px;
}

.inbox-email {
  display: contents;
}

.inbox-email-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  color: var(--text-soft);
  cursor: pointer;
}

.inbox-email-toggle input {
  accent-color: var(--accent);
  margin: 0;
}

.inbox-push {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.inbox-push-prompt[hidden] {
  display: none;
}

.inbox-push-prompt {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--rule-strong);
  border-left: 2px solid var(--accent);
  background: var(--surface-raised);
  border-radius: 3px;
}

.inbox-push-prompt-text {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  color: var(--text-soft);
}

.inbox-push-prompt-text svg {
  flex-shrink: 0;
  color: var(--accent);
}

.inbox-push-unsupported {
  font-size: var(--text-sm);
  color: var(--text-faint);
}

@media (width <= 640px) {
  .inbox-row > time,
  .inbox-fold summary > time {
    display: none;
  }
}

/* ── Projects: cross-team deliverable containers ───────────────────────── */

.project-head {
  padding: 16px 20px;
  border-bottom: 1px solid var(--rule-strong);
}

.project-name {
  margin: 0 0 12px;
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.3;
}

.project-props {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 10px 28px;
}

.project-props .prop {
  min-width: 120px;
}

.project-head .prose {
  max-width: 72ch;
  margin-top: 14px;
}

.project-row {
  grid-template-columns: minmax(0, 1fr);
}

/* The meta is sized to its content and anchored to the row's right edge, so
   every cell after the bar has to hold a floor: a Project with no lead, or a
   summary shorter than its neighbours', would otherwise pull the bar out of
   line with the rows above it. */
.project-row-meta .sub-progress {
  min-width: 17ch;
}

.project-row-lead {
  min-width: 20px;
}

.project-legend {
  color: var(--text-faint);
  font-size: var(--text-xs);
}

.project-legend-item {
  white-space: nowrap;
}

/* The summary always precedes the legend, so the separator belongs to every
   item rather than only to the joins between them. */
.project-legend-item::before {
  content: "· ";
}

.overdue-flag {
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--accent-strong);
  text-transform: uppercase;
}

/* Stacked <progress> layers segment the bar by category without inline
   styles (the CSP forbids them): each layer paints its cumulative count,
   larger sums sit lower, and only the difference shows through. */
.cat-meter {
  position: relative;
  width: 120px;
  height: 5px;
  background: var(--surface-raised);
}

.cat-meter-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  appearance: none;
  border: none;
  background: none;
}

.cat-meter-layer::-webkit-progress-bar {
  background: transparent;
}

.cat-meter-layer[data-category="done"]::-webkit-progress-value {
  background: var(--palette-green);
}

.cat-meter-layer[data-category="in_progress"]::-webkit-progress-value {
  background: var(--palette-amber);
}

.cat-meter-layer[data-category="todo"]::-webkit-progress-value {
  background: var(--palette-blue);
}

.cat-meter-layer[data-category="backlog"]::-webkit-progress-value {
  background: var(--palette-gray);
}

.cat-meter-layer[data-category="triage"]::-webkit-progress-value {
  background: var(--palette-orange);
}

.cat-meter-layer[data-category="done"]::-moz-progress-bar {
  background: var(--palette-green);
}

.cat-meter-layer[data-category="in_progress"]::-moz-progress-bar {
  background: var(--palette-amber);
}

.cat-meter-layer[data-category="todo"]::-moz-progress-bar {
  background: var(--palette-blue);
}

.cat-meter-layer[data-category="backlog"]::-moz-progress-bar {
  background: var(--palette-gray);
}

.cat-meter-layer[data-category="triage"]::-moz-progress-bar {
  background: var(--palette-orange);
}

/* ── Cycles: per-team time-boxes ───────────────────────────────────────── */

.cycle-head {
  padding: 16px 20px;
  border-bottom: 1px solid var(--rule-strong);
}

.cycle-head-top {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

.cycle-name {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.3;
}

.cycle-props {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 10px 28px;
}

.cycle-props .prop {
  min-width: 120px;
}

.cycle-points {
  color: var(--text-faint);
}

.cycle-points::before {
  content: "· ";
}

.cycle-status {
  padding: 1px 6px;
  border: 1px solid var(--rule-strong);
  color: var(--text-soft);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.cycle-status[data-status="active"] {
  border-color: var(--accent-strong);
  color: var(--accent-strong);
}

.cycle-status[data-status="past"] {
  color: var(--text-faint);
}

/* ── Trash: deleted, not canceled ──────────────────────────────────────── */

.trash-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 20px;
  border-bottom: 1px solid var(--accent-strong);
  background: var(--accent-wash);
}

/* ── Trust package: export, deletion, the read-only grace lock ─────────── */

.grace-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 20px;
  border-bottom: 1px solid var(--accent-strong);
  background: var(--accent-wash);
}

.grace-banner-text {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  color: var(--text);
}

.grace-banner .btn {
  flex-shrink: 0;
  white-space: nowrap;
}

.export-status-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}

.export-status {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.export-status-ready {
  color: var(--palette-green);
}

.export-status-pending {
  color: var(--text-soft);
}

.export-status-failed {
  color: var(--palette-red);
}

.export-when {
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.danger-zone {
  border: 1px solid var(--accent-strong);
  padding: 16px;
  background: var(--surface-sunken);
}

.danger-zone .group-head {
  padding-inline: 0;
}

.danger-form {
  max-width: 360px;
}

/* ── Styleguide chrome ─────────────────────────────────────────────────── */

.sg {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.sg-section > h2 {
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--rule-strong);
  padding-bottom: 6px;
  margin: 0 0 12px;
}

/* Board columns divide their pane, and the styleguide's pane is the page. Two
   samples across a wide monitor would show the component at a density no board
   reaches, on the surface the sweep panel's own size is judged against. */
.sg-board {
  max-width: 720px;
}

.sg-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

/* Under the width of the longest timezone label in either theme, so the sample
   documenting the ellipsis renders one at any viewport. */
.sg-narrow {
  width: 200px;
}

.sg-themes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 12px;
}

.sg-pane {
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-body);
  border: 1px solid var(--rule);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sg-pane-name {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.sg-swatch {
  width: 130px;
}

.sg-swatch .sw {
  height: 40px;
  border: 1px solid var(--rule);
}

.sg-swatch code {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  color: var(--text-soft);
}

.sw-surface {
  background: var(--surface);
}

.sw-surface-sunken {
  background: var(--surface-sunken);
}

.sw-surface-raised {
  background: var(--surface-raised);
}

.sw-surface-selected {
  background: var(--surface-selected);
}

.sw-text {
  background: var(--text);
}

.sw-text-soft {
  background: var(--text-soft);
}

.sw-text-faint {
  background: var(--text-faint);
}

.sw-rule {
  background: var(--rule);
}

.sw-rule-strong {
  background: var(--rule-strong);
}

.sw-accent {
  background: var(--accent);
}

.sw-accent-strong {
  background: var(--accent-strong);
}

.sw-accent-wash {
  background: var(--accent-wash);
}

.sw-text-on-accent {
  background: var(--text-on-accent);
}

.sw-agent-text {
  background: var(--agent-text);
}

.sw-lamp-ok {
  background: var(--lamp-ok);
}

.sw-palette-gray {
  background: var(--palette-gray);
}

.sw-palette-red {
  background: var(--palette-red);
}

.sw-palette-orange {
  background: var(--palette-orange);
}

.sw-palette-amber {
  background: var(--palette-amber);
}

.sw-palette-green {
  background: var(--palette-green);
}

.sw-palette-teal {
  background: var(--palette-teal);
}

.sw-palette-blue {
  background: var(--palette-blue);
}

.sw-palette-purple {
  background: var(--palette-purple);
}

.sg-icon {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.sg-icon code {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-soft);
}

.sg-type-sample {
  margin: 0;
}

.sg-type-sample .note {
  color: var(--text-faint);
  font-size: var(--text-xs);
}

.sg-scale {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}

.sg-step {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 3px 0;
  border-bottom: 1px solid var(--rule);
}

.sg-step code {
  flex: none;
  width: 92px;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  color: var(--text-faint);
}

.sg-step-micro {
  font-size: var(--text-micro);
}

.sg-step-xs {
  font-size: var(--text-xs);
}

.sg-step-sm {
  font-size: var(--text-sm);
}

.sg-step-base {
  font-size: var(--text-base);
}

.sg-step-md {
  font-size: var(--text-md);
}

.sg-step-lg {
  font-size: var(--text-lg);
}

.sg-step-xl {
  font-size: var(--text-xl);
}

.sg-step-section {
  font-size: var(--text-section);
}

.sg-step-title {
  font-size: var(--text-title);
}

.sg-step-hero {
  font-size: var(--text-hero);
}

.sg-step-inline {
  font-size: var(--text-inline);
}

/* ── Responsive: usable to tablet, sidebar becomes a drawer at phone width ── */

.nav-toggle {
  display: none;
  position: fixed;
  right: 14px;
  bottom: 14px;
  z-index: 30;
  width: 42px;
  height: 42px;
  place-items: center;
  padding: 0;
  border: 1px solid var(--rule-strong);
  background: var(--surface-raised);
  color: var(--text);
  cursor: pointer;
}

/* ── Members & Agents: the roster, agents under their accountable Owners ── */

.member-list {
  list-style: none;
  margin: 0;
  padding: 0 20px;
}

.member-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 3px 0;
  border-bottom: 1px solid var(--rule);
}

.member-agent-row {
  padding-left: 28px;
}

.member-agent-link {
  display: inline-flex;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.member-agent-link:hover .agent-name {
  text-decoration: underline;
}

.member-handle,
.member-email {
  min-width: 0;
  overflow: hidden;
  font-size: var(--text-xs);
  color: var(--text-faint);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.member-role {
  font-size: var(--text-xs);
  padding: 0 5px;
  line-height: 16px;
  border: 1px solid var(--rule-strong);
  color: var(--text-faint);
}

/* Phone: the identity strings stop ellipsizing each other away and each claims
   its own line. .row-actions is one flex item, so a pair too wide for the line
   wraps whole rather than splitting in two. */
@media (width <= 640px) {
  .member-row {
    flex-wrap: wrap;
  }

  .member-handle,
  .member-email {
    order: 1;
    flex-basis: 100%;
  }

  .member-row .row-actions {
    order: 2;
  }
}

.member-archive {
  margin-top: 20px;
}

.member-archive-summary {
  cursor: pointer;
}

.members .settings-note {
  margin: 6px 0 0;
  padding: 0 20px;
}

.members .empty {
  margin: 16px 20px;
}

/* ── Invitations: admin-issued, email-bound, single-use ────────────────── */

.invite-form {
  max-width: none;
}

.invite-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}

.invite-field-name {
  flex: 1 1 200px;
}

.invite-field-email {
  flex: 1 1 260px;
}

.invite-list {
  list-style: none;
  margin: 0 0 8px;
  padding: 0;
}

.invite-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 36px;
  padding: 3px 0;
  border-bottom: 1px solid var(--rule);
}

.invite-name,
.invite-email {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The address is secondary only once a name carries the identity — on a
   nameless invite it is the only thing naming the person. */
.invite-row:has(.invite-name) .invite-email {
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.invite-expiry {
  font-size: var(--text-xs);
  color: var(--text-faint);
  white-space: nowrap;
}

/* Phone: role, expiry and two buttons already fill the row, so the identity
   claims its own lines rather than collapsing to nothing. */
@media (width <= 640px) {
  .invite-row {
    flex-wrap: wrap;
  }

  .invite-name,
  .invite-email {
    flex-basis: 100%;
  }
}

.nav-item .avatar {
  width: 16px;
  height: 16px;
}

.profile {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  padding: 24px 20px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.profile .group-head,
.profile .settings-note {
  padding-inline: 0;
}

.profile-head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.profile-head .agent-mark {
  font-size: var(--text-base);
  line-height: 26px;
  padding: 0 10px;
}

.profile-head .agent-dot {
  width: 10px;
  height: 10px;
}

.profile-props {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}

.profile-teams {
  flex-wrap: wrap;
  gap: 4px 12px;
}

.profile-team {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-size: var(--text-sm);
  color: inherit;
  text-decoration: none;
}

.profile-team:hover {
  text-decoration: underline;
}

.check-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 0;
  font-size: var(--text-sm);
  cursor: pointer;
}

.mention-handle {
  margin-left: auto;
  font-size: var(--text-xs);
  color: var(--text-faint);
}

/* ── API keys: shown once, mono forever ────────────────────────────────── */

.key-reveal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin: 12px 0;
  padding: 12px 14px;
  border: 1px solid var(--accent-strong);
  background: var(--accent-wash);
}

.key-reveal-title {
  flex-basis: 100%;
  margin: 0;
  font-weight: 700;
}

.key-token {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  word-break: break-all;
  user-select: all;
}

.key-reveal-note {
  flex-basis: 100%;
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-soft);
}

.mcp-snippet {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin: 8px 0;
  padding: 10px 14px;
  border: 1px solid var(--rule);
}

.key-list {
  list-style: none;
  margin: 8px 0;
  padding: 0;
}

.key-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 32px;
  border-bottom: 1px solid var(--rule);
}

/* ── Keyboard: ⌘K palette, shortcut reference, focus cursor, key hints ───── */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
}

.overlay:not([hidden]) {
  display: flex;
  justify-content: center;
}

.overlay-scrim {
  position: absolute;
  inset: 0;
  background: var(--scrim);
}

.palette {
  align-items: flex-start;
  padding: 12vh 16px 16px;
}

.shortcut-overlay {
  align-items: center;
  padding: 16px;
}

.palette-panel,
.overlay-panel {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--surface-raised);
  border: 1px solid var(--rule-strong);
}

.palette-panel {
  width: min(560px, 100%);
  max-height: 70vh;
}

.palette-field {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--rule);
}

.palette-input {
  flex: 1;
  border: 0;
  padding: 0;
  background: none;
  font-size: var(--text-md);
}

.palette-input:focus {
  outline: none;
}

.palette-results {
  overflow-y: auto;
  padding: 6px;
}

.palette-group + .palette-group {
  margin-top: 6px;
}

.palette-group-head {
  padding: 6px 8px 4px;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.palette-cmd[hidden] {
  display: none;
}

.palette-cmd {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  cursor: pointer;
  color: var(--text);
}

.palette-cmd-label {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.palette-cmd-hint {
  flex: none;
}

.palette-cmd.active {
  background: var(--surface-selected);
  box-shadow: inset 2px 0 0 var(--accent);
}

.palette-search {
  color: var(--text-soft);
}

.palette-search .ic {
  color: var(--text-faint);
}

.shortcut-panel {
  width: min(680px, 100%);
  max-height: 84vh;
  overflow-y: auto;
}

.overlay-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--rule);
}

.overlay-title {
  margin: 0;
  font-size: var(--text-md);
  font-weight: 700;
}

.shortcut-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 8px 28px;
  padding: 16px;
}

.shortcut-group-head {
  margin: 0 0 6px;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.shortcut-list {
  margin: 0 0 12px;
}

.shortcut-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 4px 0;
  border-bottom: 1px solid var(--rule);
}

.shortcut-keys {
  flex: none;
  display: flex;
  gap: 3px;
  min-width: 64px;
}

.shortcut-desc {
  margin: 0;
  color: var(--text-soft);
}

/* j/k cursor over list / triage / inbox rows */
.kbd-cursor {
  background: var(--surface-selected);
  box-shadow: inset 3px 0 0 var(--accent);
}

/* Key hints that ride on labels and buttons */
.btn-kbd {
  margin-inline-start: 6px;
}

.prop-hint {
  margin-inline-start: 4px;
}

.kbd-hint {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 7px;
  padding: 0 0 10px;
  margin-bottom: 10px;
  border: 0;
  border-bottom: 1px dashed var(--rule);
  background: none;
  font: inherit;
  font-size: var(--text-xs);
  color: var(--text-faint);
  text-align: start;
  cursor: pointer;
}

.kbd-hint:hover {
  color: var(--text-soft);
}

/* ── Two-factor: the second door, machine-precise ──────────────────────── */

.settings-title .ic {
  vertical-align: -3px;
  color: var(--text-soft);
}

.two-factor-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  margin-bottom: 24px;
}

.two-factor-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  font-size: var(--text-sm);
  font-weight: 600;
  border: 1px solid var(--lamp-ok);
  color: var(--lamp-ok);
}

.two-factor-recovery-count {
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.two-factor-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 320px;
}

.two-factor-input {
  max-width: 240px;
}

.two-factor-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.btn-danger {
  color: var(--palette-red);
  border-color: var(--palette-red);
  align-self: flex-start;
}

.two-factor-empty {
  align-items: flex-start;
  text-align: start;
}

.enroll-card {
  display: flex;
  flex-direction: column;
  gap: 24px;
  max-width: 420px;
  margin-bottom: 24px;
}

.enroll-step {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 12px;
}

.enroll-step-num {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text-on-accent);
  background: var(--accent);
}

.enroll-step-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.enroll-step-title {
  font-weight: 600;
}

.enroll-step-note {
  font-size: var(--text-sm);
  color: var(--text-soft);
}

.qr-plate {
  width: min(200px, 100%);
  padding: 12px;
  margin: 4px 0 8px;
  color: var(--qr-ink);
  background: var(--qr-bg);
  border: 1px solid var(--rule);
}

.qr-plate svg {
  display: block;
  width: 100%;
  height: auto;
}

.enroll-secret-label {
  font-size: var(--text-sm);
  color: var(--text-soft);
}

.enroll-secret {
  font-size: var(--text-base);
  letter-spacing: 0.08em;
  word-break: break-all;
  user-select: all;
  color: var(--text);
}

.recovery-codes {
  max-width: 420px;
  padding: 16px;
  border: 1px solid var(--accent-strong);
  background: var(--accent-wash);
}

.recovery-code-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 20px;
  margin: 0 0 14px;
  padding-left: 22px;
}

.recovery-code {
  font-size: var(--text-base);
  letter-spacing: 0.06em;
  user-select: all;
}

.recovery-codes-warning {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 14px;
  font-size: var(--text-sm);
  color: var(--text-soft);
}

@media (width <= 640px) {
  .recovery-code-list {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (width <= 640px) {
  /* The row cannot wrap, and the stamp cannot shrink; the message can. */
  .ticker time {
    display: none;
  }

  .shortcut-groups {
    grid-template-columns: 1fr;
  }

  .app {
    grid-template-columns: minmax(0, 1fr);
  }

  .side {
    display: none;
  }

  .nav-toggle {
    display: grid;
  }

  .app.nav-open .side {
    display: flex;
    position: fixed;
    inset: 0 auto 0 0;
    width: min(280px, 84vw);
    z-index: 20;
    border-right: 1px solid var(--rule-strong);
  }
}

/* ── Quick View: the drawer a row or a card opens over the pane (ADR 0017) */

/* The drawer passes over the board; it never pushes it. It held a share of the
   desk until MACH-68, and re-dividing the board was the larger half of the
   motion — the columns reflowing under a panel that was only arriving, which
   read as the board doing the animating and the drawer merely showing up. So
   the track keeps nothing at any width and the panel travels over the pane
   instead of beside it. Nothing here reflows, which is also why this reads as
   one movement rather than two. */
.drawer {
  flex: none;
  width: 0;
}

/* The frame is what slides, not the panel inside it. A transition needs a
   previous style to leave, and the panel has none: it ships in the frame's
   response, so it is a new element in the very task that opens the drawer, and
   the browser resolves it straight to the open transform — no start value, no
   slide. The frame is already on the page: Turbo replaces a frame's children
   and keeps the frame, so this element is styled long before the panel arrives,
   and a swap lands inside one that is already open, which is what keeps
   swapping issues still. It is sized against the desk rather than against a
   track, so a long description holds one width for the whole crossing. */
.drawer > turbo-frame {
  position: absolute;
  inset: 0 0 0 auto;
  z-index: 35; /* over .nav-toggle (30), under the chooser sheet (40) */
  width: 40%;
  visibility: hidden;
  transform: translateX(100%);

  /* `visibility` carries the a11y state: it waits out the exit, and its delay
     is one of the transitions reduced motion drops, so the drawer is simply
     hidden the moment it closes there. */
  transition:
    transform var(--dur-travel) var(--ease-travel),
    visibility 0s linear var(--dur-travel);
}

.drawer-panel {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--rule-strong);
  background: var(--surface-raised);
}

/* Only the take-over mode below needs it, and only there does it size to
   anything: a tap on the strip the panel leaves has to land on a surface of
   its own, because the pixels under it belong to the row it would open. */
.drawer-scrim {
  position: absolute;
  inset: 0;
  z-index: 34;
  width: 0;
  background: var(--scrim);
  opacity: 0;
  transition: opacity var(--dur-travel) var(--ease-travel);
}

/* A swap keeps the issue you were reading on screen for the whole round trip,
   which is the one state where the drawer can show the wrong record. The dim
   waits out --delay-busy before it starts, though, or it reports nothing and
   costs a flash: a swap off a warm server lands in tens of milliseconds, and
   --ease is steep enough that 20ms of it is already down to 0.73 and 50ms to
   0.60 — a dip that deep, that brief, and that dependent on latency is the
   panel flickering rather than an answer being fetched. Coming back is
   immediate: .drawer-panel carries no transition of its own, so the moment
   busy clears the panel is opaque again with no second fade to sit out. */
.drawer:has(> turbo-frame[busy]) .drawer-panel {
  opacity: 0.55;
  transition: opacity var(--dur-fast) var(--ease) var(--delay-busy);
}

.drawer[data-open] > turbo-frame {
  visibility: visible;
  transform: translateX(0);
  transition:
    transform var(--dur-travel) var(--ease-travel),
    visibility 0s;
}

/* The row or card the drawer is reading. aria-current carries it to assistive
   tech as well, and the inset bar is the treatment .row.selected already uses
   for "this one", over the same surface the panel itself paints. */
.row[aria-current],
.card[aria-current] {
  background: var(--surface-raised);
  box-shadow: inset 2px 0 0 var(--accent);
}

.drawer-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--rule-strong);
}

/* The Workflow State's name is the only elastic thing on this line: at 40% of
   a narrow pane, a control that shrinks wraps its own label instead. */
.drawer-head .row-key,
.drawer-head .btn {
  flex: none;
  white-space: nowrap;
}

.drawer-state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: var(--text-xs);
  color: var(--text-soft);
}

.drawer-state-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.drawer-body {
  flex: 1;
  min-height: 0;
  padding: 14px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--rule-strong) transparent;
}

.drawer-title {
  margin: 0 0 12px;
  font-size: var(--text-md);
  font-weight: 700;
  line-height: 1.3;
}

/* Label and value share a row here rather than stacking as the issue page's
   rail does: the rail is a form and this is a reading of one. */
.drawer-props {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 7px 12px;
  margin: 16px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}

.drawer-props dd {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 6px;
  margin: 0;
  min-width: 0;
  font-size: var(--text-sm);
}

.drawer-foot {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 8px;
  padding: 8px 12px;
  border-top: 1px solid var(--rule);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

/* 40% stops being a readable panel before the desk stops being a desk: below
   ~1086px it is under 340px, and the head's own contents no longer fit. The
   drawer passes over the pane at every width now, so what changes here is only
   how much it covers: nearly all of it, leaving 44px of "outside" — a finger's
   worth, the only way out on a phone, which has no Escape key, and the reason
   the scrim is sized here. */
@media (width <= 1100px) {
  .drawer > turbo-frame {
    width: min(420px, 100% - 44px);
  }

  .drawer[data-open] .drawer-scrim {
    width: auto;
    opacity: 1;
  }

  /* 14px of glyph clears no finger, and on a phone this is the reliable exit. */
  .drawer-close {
    padding: 10px;
  }
}

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

/* ── Landing (signed-out marketing surface) ────────────────────────────────
   The landing is also the product's speed statement: it reuses the same
   tokens and component atoms so it renders correctly under both instruments
   and looks like the tool, not a generic marketing page. */

.landing {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.landing-top {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 16px clamp(16px, 5vw, 48px);
  border-bottom: 1px solid var(--rule);
}

.landing-brand {
  text-decoration: none;
  color: inherit;
}

.landing-top-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}

/* Language switcher: a hairline segmented control, no JS */
.locale-switch {
  display: inline-flex;
  border: 1px solid var(--rule-strong);
}

.locale-opt {
  font: inherit;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  padding: 5px 9px;
  border: none;
  background: none;
  color: var(--text-soft);
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}

.locale-opt + .locale-opt {
  border-left: 1px solid var(--rule-strong);
}

.locale-opt:hover {
  color: var(--text);
}

.locale-opt.is-active {
  background: var(--accent-wash);
  color: var(--text);
}

.landing-main {
  flex: 1;
  width: min(1080px, 100%);
  margin: 0 auto;
  padding: 0 clamp(16px, 5vw, 48px);
}

.landing-eyebrow {
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-strong);
  margin: 0 0 10px;
}

/* Hero */
.landing-hero {
  padding: clamp(40px, 8vw, 88px) 0 clamp(28px, 5vw, 56px);
  border-bottom: 1px solid var(--rule);
}

.landing-hero-title {
  margin: 0;
  max-width: 18ch;
  font-size: var(--text-hero);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.01em;
}

.landing-hero-body {
  margin: 20px 0 0;
  max-width: 60ch;
  font-size: var(--text-md);
  color: var(--text-soft);
}

.landing-hero-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 28px;
}

.landing-cta {
  font-size: var(--text-md);
  padding: 10px 20px;
}

.landing-hero-note {
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.landing-shots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: 20px;
  margin-top: clamp(32px, 5vw, 56px);
}

/* Rendered board preview: a theme island built from real board atoms */
.landing-shot {
  margin: 0;
  min-width: 0;
}

.landing-shot-frame {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--rule-strong);
  overflow: hidden;
}

.landing-shot-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--rule);
}

.landing-shot-crumb {
  font-size: var(--text-sm);
  color: var(--text-soft);
}

.landing-shot-instrument {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.landing-shot-ticker {
  margin: 0;
}

.landing-shot-board {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: var(--rule);
  border-top: 1px solid var(--rule);
}

.landing-shot-col {
  background: var(--surface);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.landing-shot-col-head {
  display: flex;
  align-items: center;
  gap: 6px;
}

.landing-shot-col-name {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.landing-shot-col-head .board-count {
  margin-left: auto;
}

.landing-shot-card {
  cursor: default;
}

/* Sections */
.landing-section {
  padding: clamp(40px, 7vw, 80px) 0;
  border-bottom: 1px solid var(--rule);
}

.landing-section-head {
  max-width: 62ch;
}

.landing-section-title {
  margin: 0;
  font-size: var(--text-section);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.landing-section-lead {
  margin: 14px 0 0;
  font-size: var(--text-md);
  color: var(--text-soft);
}

/* Wedge: alternating copy + real-component demo */
.landing-wedge {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: clamp(28px, 4vw, 44px);
}

.landing-wedge-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(20px, 4vw, 48px);
  align-items: center;
  padding: clamp(20px, 3vw, 32px) 0;
}

.landing-wedge-row + .landing-wedge-row {
  border-top: 1px solid var(--rule);
}

.landing-wedge-title {
  margin: 0 0 8px;
  font-size: var(--text-lg);
  font-weight: 700;
}

.landing-wedge-copy p {
  margin: 0;
  max-width: 46ch;
  color: var(--text-soft);
}

.landing-wedge-demo {
  min-width: 0;
  background: var(--surface-sunken);
  border: 1px solid var(--rule);
  padding: 14px;
}

.landing-wedge-demo .act-list,
.landing-wedge-demo .triage-item {
  margin: 0;
}

.landing-wedge-demo .ticker + .ticker {
  margin-top: 6px;
}

/* MCP one-liner snippet */
.landing-snippet {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.landing-snippet-label {
  font-size: var(--text-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.landing-snippet-code {
  margin: 0;
  padding: 12px;
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  color: var(--text);
  font-size: var(--text-sm);
  line-height: 1.6;
}

/* Core loop grid */
.landing-core {
  list-style: none;
  margin: clamp(28px, 4vw, 44px) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}

.landing-core-item {
  background: var(--surface);
  padding: 20px;
}

.landing-core-item-title {
  margin: 0 0 6px;
  font-size: var(--text-md);
  font-weight: 700;
}

.landing-core-item-body {
  margin: 0;
  font-size: var(--text-base);
  color: var(--text-soft);
}

/* No lock-in */
.landing-lockin-demo {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: clamp(24px, 3vw, 36px);
  padding: 16px;
  background: var(--surface-sunken);
  border: 1px solid var(--rule);
}

.landing-lockin-file {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);
  color: var(--text);
}

.landing-lockin-note {
  color: var(--text-soft);
  font-size: var(--text-base);
}

/* Two instruments */
.landing-instrument-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px;
  margin-top: clamp(28px, 4vw, 44px);
}

.landing-instrument {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.landing-instrument .tp-preview {
  padding: 14px;
}

.landing-instrument-name {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.landing-instrument-label {
  font-weight: 700;
}

.landing-instrument-tag {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

/* Final call to action */
.landing-final {
  text-align: center;
  padding: clamp(56px, 9vw, 104px) 0;
}

.landing-final-title {
  margin: 0;
  font-size: var(--text-title);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.landing-final-body {
  margin: 14px auto 28px;
  max-width: 48ch;
  color: var(--text-soft);
  font-size: var(--text-md);
}

.landing-final-legal {
  margin: 20px 0 0;
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.landing-final-legal a,
.landing-foot-links a,
.legal-cross a {
  color: var(--accent-strong);
}

/* Footer */
.landing-foot {
  border-top: 1px solid var(--rule);
  padding: clamp(28px, 4vw, 44px) clamp(16px, 5vw, 48px);
}

.landing-foot-main {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  flex-wrap: wrap;
  width: min(1080px, 100%);
  margin: 0 auto;
}

.landing-foot-tagline {
  margin: 8px 0 0;
  max-width: 34ch;
  font-size: var(--text-sm);
  color: var(--text-soft);
}

.landing-foot-links {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
}

.landing-foot-links a {
  text-decoration: none;
  font-size: var(--text-base);
}

.landing-foot-links a:hover {
  text-decoration: underline;
}

.landing-foot-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}

.landing-foot-rights {
  width: min(1080px, 100%);
  margin: 20px auto 0;
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  color: var(--text-faint);
}

/* Legal pages (ToS + privacy) */
.legal {
  max-width: 68ch;
  padding: clamp(40px, 7vw, 72px) 0 clamp(48px, 8vw, 88px);
}

.legal-title {
  margin: 8px 0 0;
  font-size: var(--text-title);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.legal-updated {
  margin: 8px 0 0;
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.legal-intro {
  margin: 20px 0 0;
  font-size: var(--text-md);
  color: var(--text-soft);
}

.legal-section {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid var(--rule);
}

.legal-section-title {
  margin: 0 0 8px;
  font-size: var(--text-lg);
  font-weight: 700;
}

.legal-section p {
  margin: 0;
  color: var(--text-soft);
}

.legal-cross {
  margin-top: 32px;
  font-size: var(--text-base);
  color: var(--text-faint);
}

@media (width <= 720px) {
  .landing-wedge-row {
    grid-template-columns: minmax(0, 1fr);
  }

  .landing-wedge-flip .landing-wedge-copy {
    order: -1;
  }
}

@media (width <= 560px) {
  .landing-signin {
    display: none;
  }
}
