/* ==========================================================================
   OUR LIST - app layer
   --------------------------------------------------------------------------
   Sits on top of pulse-core.css and reuses its tokens. Every value here is a
   token or derived from one: no raw hex, no magic spacing, so re-theming
   stays a one-file job.

   Mobile first throughout. The phone is the real device; the desktop rules
   are the afterthought, not the other way round.
   ========================================================================== */

.pulse-main {
  max-width: 900px;
  margin-inline: auto;
  padding-bottom: calc(96px + env(safe-area-inset-bottom));
}
/* Board and table are wide working surfaces; give them the room Trello would. */
.pulse-main--wide { max-width: 1280px; }

/* A single view with nothing open reads best as one comfortable column, and a
   detail opened from the board or table gets the same treatment. */
.list-pane--solo,
.list-solo {
  max-width: 680px;
  margin-inline: auto;
}

/* Pulse hides .pulse-split__back on desktop because ITS detail always sits
   beside a visible list. The solo detail (opened from the board or the table)
   has no list beside it, so without this override the back button exists but
   is invisible above 960px and there is no way out of an item. Found live by
   Vasso; the automated gates missed it because a programmatic click works on
   a display:none element, so from now on gates assert computed visibility. */
.list-solo .pulse-split__back {
  display: inline-flex;
}

.pulse-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.list-boot { display: grid; gap: var(--pulse-space-sm); padding-top: var(--pulse-space-md); }

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */
.list-head {
  position: relative;
  padding: var(--pulse-space-lg) 0 var(--pulse-space-md);
}
.list-head__title {
  margin: 0;
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--pulse-text);
}
/* The opening note carries the tone of the whole thing, so it gets real
   breathing room and a soft ground rather than being squeezed into fine print. */
.list-head__intro {
  margin: var(--pulse-space-sm) 0 0;
  padding: var(--pulse-space-sm) var(--pulse-space-md);
  background: var(--pulse-brand-soft);
  border-left: 3px solid var(--pulse-brand);
  border-radius: var(--pulse-radius-s);
  color: var(--pulse-text-muted);
  font-size: 0.95rem;
  line-height: 1.55;
}
.list-head__count {
  margin: var(--pulse-space-sm) 0 0;
  font-weight: 600;
  color: var(--pulse-text-muted);
  font-size: 0.9rem;
}
.list-head__seen {
  margin: var(--pulse-space-2xs) 0 0;
  font-size: 0.8rem;
  color: var(--pulse-text-faint);
}
.list-head__edit {
  position: absolute;
  top: var(--pulse-space-lg);
  right: 0;
  min-height: var(--pulse-touch-target);
  padding: 0 var(--pulse-space-sm);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-s);
  background: var(--pulse-surface);
  color: var(--pulse-text-muted);
  font: inherit;
  font-size: 0.82rem;
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   Toolbar: filter bar + sort + view switch
   -------------------------------------------------------------------------- */
/* Static by default. On a phone the bar is taller than a third of the viewport,
   so pinning it eats the reading room the list needs; it scrolls away with the
   page instead. Pull-to-refresh and the header sync line still bring it back by
   scrolling up. Sticky returns once the screen has room to spare. */
.list-toolbar {
  position: static;
  padding: var(--pulse-space-xs) 0;
  background: var(--pulse-bg);
  border-bottom: 1px solid var(--pulse-border);
}
@media (min-width: 640px) {
  .list-toolbar {
    position: sticky;
    top: 0;
    z-index: 5;
  }
}

/* The vendored Pulse filter bar (assets/pulse/filters.js). Everything visual
   comes from .pulse-filterbar in pulse-core.css; this is only the glue that
   sits it in the toolbar and hides the one control the board cannot use. */
.list-filterbar {
  /* The multi-select panels are absolutely positioned against their own
     control, which on a phone can push them past the right edge. Contain them
     against the bar instead (see the narrow-screen rule below). */
  position: relative;
}
/* The bar's controls are 36px in Pulse, which is under the 44px this app holds
   itself to on a touch screen. */
.list-filterbar .pulse-filter__control {
  min-height: var(--pulse-touch-target);
}
/* 16px is the iOS Safari threshold below which focusing an input zooms the
   page. The bar's search box inherits the smaller Pulse control size, so it is
   set back up here, the same way the form fields and the note box are. */
.list-filterbar input {
  font-size: 16px;
}
/* On the board the five columns ARE the stage, so the stage control steps out
   of the way. The anchor is STRUCTURAL, not the module-generated id: the stage
   facet is this app's only select-widget facet, so "the facet wrapper holding
   a select" identifies it across every repaint the bar does (it rebuilds its
   facet DOM wholesale on each change, which is also why a JS-added class
   cannot serve here). The separator in front of it goes too, or two dividers
   would sit side by side. */
.list-filterbar.is-board .pulse-filter:has(select),
.list-filterbar.is-board .pulse-filterbar__sep:has(+ .pulse-filter select) {
  display: none;
}
@media (max-width: 560px) {
  .list-filterbar .pulse-multiselect { position: static; }
  .list-filterbar .pulse-multiselect__panel {
    left: 0;
    right: 0;
    min-width: 0;
  }
}
.list-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pulse-space-sm);
  margin-top: var(--pulse-space-xs);
}
.list-sort { flex: 1 1 auto; min-width: 0; }
.list-sort select { width: 100%; min-height: var(--pulse-touch-target); }
.list-view { flex: none; margin-left: auto; }
/* Once there is room the sort control takes its natural width instead of
   stretching across the page. */
@media (min-width: 640px) {
  .list-sort { flex: 0 1 auto; }
  .list-sort select { width: auto; min-width: 230px; }
}

/* --------------------------------------------------------------------------
   Project header
   Shown only when the Category facet is narrowed to exactly one category, so
   the page is about that one project. The accent stripe is the category's own
   tone, handed in as --_tone, which is the same colour its pills already use.
   -------------------------------------------------------------------------- */
.list-project {
  margin-top: var(--pulse-space-md);
  padding: var(--pulse-space-md);
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border);
  border-left: 4px solid var(--_tone);
  border-radius: var(--pulse-radius-l);
}
.list-project__head {
  display: flex;
  align-items: baseline;
  gap: var(--pulse-space-sm);
}
.list-project__name {
  margin: 0;
  min-width: 0;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--pulse-text);
  overflow-wrap: anywhere;
}
.list-project__when {
  margin-left: auto;
  flex: none;
  font-size: 0.85rem;
  color: var(--pulse-text-muted);
}
/* Written as a note, so the line breaks the owner typed are the line breaks
   she reads. A pasted booking link is the likeliest thing in here and would
   push the page sideways on a phone, hence the break-anywhere. */
.list-project__desc {
  margin: var(--pulse-space-xs) 0 0;
  color: var(--pulse-text-muted);
  font-size: 0.95rem;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.list-project__progress {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--pulse-space-sm);
  margin-top: var(--pulse-space-sm);
}
.list-project__count {
  flex: none;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--pulse-text-muted);
}
.list-project__bar {
  flex: 1;
  height: 6px;
  border-radius: 999px;
  background: var(--pulse-surface-sunken);
  overflow: hidden;
}
.list-project__bar > span {
  display: block;
  height: 100%;
  background: var(--_tone);
  border-radius: 999px;
}
/* The project's own controls, on their own row. They were trailing the progress
   bar, which held while Edit was the only one; with a way out of the project
   and a way to wrap it up beside it, three buttons were squeezing the bar down
   to a stub on a phone. Quiet type, full-size tap: they read as small without
   dropping under the touch target the rest of the app holds to. */
.list-project__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pulse-space-xs);
  margin-top: var(--pulse-space-sm);
}
.list-project__actions .list-btn {
  flex: none;
  padding: 0 var(--pulse-space-sm);
  font-size: 0.82rem;
}

/* Header freshness */
.list-head__fresh {
  margin: var(--pulse-space-2xs) 0 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--pulse-accent-strong);
}
/* The freshness line is now the way into the trail behind it, so it is a real
   button. The reset keeps it reading as the quiet line it always was; the
   dotted underline is the only thing that says it can be pressed, matching the
   sync line below it. */
button.list-head__fresh {
  display: block;
  min-height: var(--pulse-touch-target);
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--pulse-accent-strong);
  text-align: left;
  text-decoration: underline dotted;
  cursor: pointer;
}
/* With nothing new the same control is a plain way into the history, so it
   drops the accent colour and stops competing with the open-items count. */
button.list-head__fresh--quiet { color: var(--pulse-text-faint); font-weight: 400; }
button.list-head__fresh:hover { color: var(--pulse-accent); }
button.list-head__fresh:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: 2px; }

/* The trail itself. A quiet log under the line that counts it: plain sentences
   on the left, when it happened on the right, and nothing to press. */
.list-activity {
  margin-top: var(--pulse-space-xs);
  padding: var(--pulse-space-xs) var(--pulse-space-sm);
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-m);
}
.list-activity__rows { margin: 0; padding: 0; list-style: none; }
.list-activity__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--pulse-space-sm);
  padding: var(--pulse-space-2xs) 0;
  border-bottom: 1px solid var(--pulse-border);
  font-size: 0.85rem;
  line-height: 1.5;
}
.list-activity__row:last-child { border-bottom: 0; }
.list-activity__what { color: var(--pulse-text); overflow-wrap: anywhere; }
.list-activity__when {
  flex: none;
  color: var(--pulse-text-faint);
  font-size: 0.78rem;
  white-space: nowrap;
}
.list-activity__note {
  margin: 0;
  padding: var(--pulse-space-2xs) 0;
  color: var(--pulse-text-faint);
  font-size: 0.85rem;
}

/* --------------------------------------------------------------------------
   Offline banner
   The page is running on a board this phone saved earlier, because the first
   load could not reach the server. Amber rather than red: nothing is broken and
   nothing was lost, the page is just behind.
   -------------------------------------------------------------------------- */
.list-offline {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--pulse-space-sm);
  margin-top: var(--pulse-space-md);
  padding: var(--pulse-space-sm) var(--pulse-space-md);
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border);
  border-left: 4px solid var(--pulse-warning);
  border-radius: var(--pulse-radius-m);
}
.list-offline__text {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  color: var(--pulse-text-muted);
  font-size: 0.9rem;
  line-height: 1.5;
}
.list-offline__retry {
  flex: none;
  padding: 0 var(--pulse-space-md);
  font-size: 0.85rem;
}
.list-head__sync {
  display: inline-flex;
  align-items: flex-end;
  background: none;
  border: 0;
  height: auto;
  /* Small text, full-size tap: the visible line stays quiet but the target
     clears the 44px minimum like everything else. */
  min-height: var(--pulse-touch-target);
  padding: 12px 0 0;
  font: inherit;
  font-size: 0.78rem;
  color: var(--pulse-text-faint);
  text-decoration: underline dotted;
  cursor: pointer;
}
.list-head__sync:hover { color: var(--pulse-text-muted); }

/* The way into the removed items. Deliberately as quiet as the sync line above
   it: it is a door that should be findable without inviting a tap, because
   nothing behind it is part of the day-to-day list. Its own line rather than
   trailing the sync line, so neither wraps into the other on a phone. */
.list-head__archive {
  display: block;
  min-height: var(--pulse-touch-target);
  padding: var(--pulse-space-2xs) 0 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 0.78rem;
  color: var(--pulse-text-faint);
  text-align: left;
  text-decoration: underline dotted;
  cursor: pointer;
}
.list-head__archive:hover { color: var(--pulse-text-muted); }
.list-head__archive:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: 2px; }

/* Pull-to-refresh pill */
.list-ptr {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 10px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--pulse-toast-bg);
  color: var(--pulse-toast-text);
  font-size: 0.8rem;
  font-weight: 600;
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms linear;
}
.list-ptr.is-armed { background: var(--pulse-brand); }

/* Confetti canvas. Above the page, under the dialogs (which sit in the browser
   top layer anyway), and transparent to every pointer event: a celebration
   that swallows a tap is not a celebration. Removed from the DOM entirely the
   moment the last piece dies, so there is nothing left compositing. */
.list-confetti {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 70;
}

/* Detail: connected items */
.list-deplinks { display: grid; gap: var(--pulse-space-xs); }
.list-deplink {
  display: block;
  width: 100%;
  text-align: left;
  min-height: var(--pulse-touch-target);
  height: auto;
  padding: var(--pulse-space-xs) var(--pulse-space-sm);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-m);
  background: var(--pulse-surface-sunken);
  color: var(--pulse-text);
  font: inherit;
  cursor: pointer;
  white-space: normal;
  overflow-wrap: anywhere;
}
.list-deplink:hover { border-color: var(--pulse-border-strong); background: var(--pulse-surface); }
.list-deplink__phrase {
  font-size: 0.76rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--pulse-text-faint);
  display: block;
}

/* --------------------------------------------------------------------------
   Parts
   A part is a row, not a card: it is one line of an item, and giving it a card
   of its own would make the list look twice as long as the work actually is.
   -------------------------------------------------------------------------- */
.list-parts {
  display: grid;
  gap: 2px;
  margin-top: var(--pulse-space-xs);
  padding-left: var(--pulse-space-2xs);
  border-left: 2px solid var(--pulse-border);
}
.list-part {
  display: flex;
  align-items: center;
  gap: var(--pulse-space-2xs);
  min-height: var(--pulse-touch-target);
  padding-right: var(--pulse-space-2xs);
  border-radius: var(--pulse-radius-m);
  cursor: pointer;
  overflow-wrap: anywhere;
}
.list-part:hover { background: var(--pulse-surface-sunken); }
.list-part:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: -2px; }
.list-part__title { flex: 1; min-width: 0; font-size: 0.92rem; }
.list-part--done { opacity: 0.62; }
.list-part--done .list-part__title { text-decoration: line-through; }

/* Same one-tap circle as a card, drawn smaller. The 44px tap area is kept and
   pulled back in with negative margins, so the target stays honest while the
   row stays a row. */
.list-part__tick {
  flex: none;
  width: var(--pulse-touch-target);
  height: var(--pulse-touch-target);
  margin: 0 calc(-1 * var(--pulse-space-2xs));
  border: 0;
  background: none;
  cursor: pointer;
  position: relative;
  border-radius: 50%;
}
.list-part__tick::before {
  content: '';
  position: absolute;
  inset: 13px;
  border: 2px solid var(--pulse-border-strong);
  border-radius: 50%;
  transition: border-color var(--pulse-transition), background var(--pulse-transition);
}
.list-part__tick:hover::before {
  border-color: var(--pulse-success);
  background: color-mix(in srgb, var(--pulse-success) 12%, var(--pulse-surface));
}
.list-part__tick:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: -8px; }
.list-part__tick--done {
  display: inline-grid;
  place-items: center;
  width: var(--pulse-touch-target);
  height: var(--pulse-touch-target);
  margin: 0 calc(-1 * var(--pulse-space-2xs));
  flex: none;
  color: var(--pulse-success);
  font-weight: 700;
}

/* Adding a part from the item it belongs to: one line, no dialog. */
.list-partform { display: flex; gap: var(--pulse-space-xs); margin-top: var(--pulse-space-sm); }
.list-partform__input {
  flex: 1;
  min-width: 0;
  min-height: var(--pulse-touch-target);
  padding: var(--pulse-space-xs) var(--pulse-space-sm);
  border: 1px solid var(--pulse-border-strong);
  border-radius: var(--pulse-radius-m);
  background: var(--pulse-surface);
  color: var(--pulse-text);
  font: inherit;
  font-size: 16px;   /* no iOS zoom on focus */
}
.list-partform__input:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: 1px; }

/* --------------------------------------------------------------------------
   Cards
   -------------------------------------------------------------------------- */
.list-cards { display: grid; gap: var(--pulse-space-sm); padding-top: var(--pulse-space-md); }

.list-card {
  display: flex;
  gap: var(--pulse-space-sm);
  align-items: flex-start;
  padding: var(--pulse-space-md);
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-l);
  box-shadow: var(--pulse-shadow-1);
  cursor: pointer;
  overflow-wrap: anywhere;
  transition: box-shadow var(--pulse-transition), border-color var(--pulse-transition);
}
.list-card__body { flex: 1; min-width: 0; }

/* The one-tap Sorted circle. A 44px touch target drawing a 26px ring, so the
   tap is easy and the visual stays quiet. */
.list-card__tick {
  flex: none;
  width: 44px;
  height: 44px;
  margin: -9px 0 0 -9px;
  border: 0;
  background: none;
  cursor: pointer;
  position: relative;
  border-radius: 50%;
}
.list-card__tick::before {
  content: '';
  position: absolute;
  inset: 9px;
  border: 2px solid var(--pulse-border-strong);
  border-radius: 50%;
  transition: border-color var(--pulse-transition), background var(--pulse-transition);
}
.list-card__tick:hover::before {
  border-color: var(--pulse-success);
  background: color-mix(in srgb, var(--pulse-success) 12%, var(--pulse-surface));
}
.list-card__tick:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: -4px; }
.list-card__tick--done {
  display: inline-grid;
  place-items: center;
  color: var(--pulse-success);
  font-weight: 700;
}

/* Whose an item is. Solid and inverted, deliberately unlike the soft tinted
   category pill beside it: a person and a category are different kinds of
   fact, and matching them would make the row read as two of the same tag. */
.list-who {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.6;
  white-space: nowrap;
  background: var(--_who, var(--list-who-both));
  color: var(--pulse-text-invert);
}

/* A category chip is a door into that project, wherever it is drawn: on a list
   card, a board card, a table row or the detail head. It keeps the pill styling
   the other chips have, and gains only what says it can be pressed. The focus
   ring is not optional here: the chip is reachable by keyboard, so it has to be
   visible when it is reached. */
.list-chip--cat { cursor: pointer; }
.list-chip--cat:hover {
  border-color: color-mix(in srgb, var(--_status) 55%, var(--pulse-surface));
  background: color-mix(in srgb, var(--_status) 20%, var(--pulse-surface));
}
.list-chip--cat:focus-visible {
  outline: 2px solid var(--pulse-focus);
  outline-offset: 2px;
}

/* "New since you last looked" */
.list-new {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--pulse-accent-strong);
  background: var(--pulse-accent-soft);
  border-radius: 999px;
  padding: 1px 8px;
}
.list-new-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--pulse-accent);
  margin-right: 6px;
  vertical-align: 1px;
}

/* Dependency lines on a card */
.list-dep {
  margin-top: var(--pulse-space-2xs);
  font-size: 0.8rem;
  color: var(--pulse-text-faint);
  display: flex;
  align-items: center;
  gap: 5px;
}
.list-dep--holds { color: var(--pulse-warning); font-weight: 600; }
.list-dep wa-icon { font-size: 0.75rem; }

/* Finished items folded behind one line */
.list-done-tuck { margin-top: var(--pulse-space-md); }
.list-done-tuck summary {
  cursor: pointer;
  min-height: var(--pulse-touch-target);
  display: flex;
  align-items: center;
  font-weight: 600;
  color: var(--pulse-text-muted);
}
.list-done-tuck summary:hover { color: var(--pulse-text); }
.list-done-tuck .list-cards { padding-top: var(--pulse-space-xs); }
.list-card:hover { box-shadow: var(--pulse-shadow-2); border-color: var(--pulse-border-strong); }
.list-card:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: 2px; }
.list-card--done { opacity: 0.62; }
.list-card--done .list-card__title { text-decoration: line-through; }

/* His own items read differently at a glance, so a private one is never
   mistaken for something she has been asked for. */
.list-card--mine-only {
  border-style: dashed;
  background: color-mix(in srgb, var(--pulse-surface-sunken) 45%, var(--pulse-surface));
}

.list-card__top {
  display: flex;
  align-items: center;
  gap: var(--pulse-space-xs);
  flex-wrap: wrap;
  margin-bottom: var(--pulse-space-xs);
}
.list-card__title {
  margin: 0;
  font-size: 1.02rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--pulse-text);
}
.list-card__why {
  margin: var(--pulse-space-2xs) 0 0;
  color: var(--pulse-text-muted);
  font-size: 0.9rem;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
.list-card__foot {
  display: flex;
  align-items: center;
  gap: var(--pulse-space-xs);
  flex-wrap: wrap;
  margin-top: var(--pulse-space-sm);
}
.list-meta { font-size: 0.8rem; color: var(--pulse-text-faint); }

/* Timing. Amber for near or past, never red: a late item is a nudge, not an
   emergency, and red would undo the whole point of this board. */
.list-when {
  font-size: 0.8rem;
  font-weight: 700;
  white-space: nowrap;
  margin-left: auto;
}
.list-when--soft { color: var(--pulse-text-faint); }
.list-when--near { color: var(--pulse-warning); }
.list-when--late { color: var(--pulse-warning); }

/* --------------------------------------------------------------------------
   Board view
   -------------------------------------------------------------------------- */
.list-board { padding-top: var(--pulse-space-md); }
.list-kcard { cursor: pointer; }
.list-kcard .list-card__title { font-size: 0.92rem; }

/* Desktop board, Trello rules: the columns share the full width instead of
   sitting at their fixed 290px against a sea of empty page. Folded strips
   keep their slim 44px; the phone keeps the swipe-scroll of fixed columns. */
@media (min-width: 700px) {
  .list-board .pulse-column:not(.pulse-column--folded) {
    flex: 1 1 0;
    max-width: 420px;
  }
}

/* --------------------------------------------------------------------------
   Table view
   -------------------------------------------------------------------------- */
.list-table-wrap { margin-top: var(--pulse-space-md); }
/* Header cells are the sort control. The button resets the vendored form
   styling and inherits the pulse-table header typography. */
.list-th {
  background: none;
  border: 0;
  padding: 0;
  height: auto;
  min-height: var(--pulse-touch-target);
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}
.list-th:hover { color: var(--pulse-text); }
.list-table__what { font-weight: 600; }
.list-row { cursor: pointer; }
.list-row:hover td { background: color-mix(in srgb, var(--pulse-brand) 6%, var(--pulse-surface)); }
.list-row:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: -2px; }
.list-row--done { opacity: 0.62; }
.list-row--done .list-table__what { text-decoration: line-through; }
/* On a phone the table keeps its three load-bearing columns: what, whose
   turn, when. Category, notes and added re-appear with room. */
@media (max-width: 759px) {
  .list-table__hide-sm { display: none; }
}

/* --------------------------------------------------------------------------
   Detail
   -------------------------------------------------------------------------- */
.list-detail { padding-top: var(--pulse-space-md); }
/* Back and the link sit on one line: leaving and sharing are the two things
   that are about the page rather than about the item. */
.list-detail__nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pulse-space-sm);
  flex-wrap: wrap;
  margin-bottom: var(--pulse-space-sm);
}
.list-detail__copy { padding: 0 var(--pulse-space-sm); font-size: 0.85rem; }
/* The way out must read as a button, not as stray text: it is the single
   most-used control on the page. Pulse's quiet text-link styling stays for
   its own split layout; inside the detail nav it gets a real button body. */
.list-detail__nav .pulse-split__back {
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border-strong);
  border-radius: var(--pulse-radius-m);
  padding: 0 var(--pulse-space-md);
  font-weight: 700;
  color: var(--pulse-brand-strong);
  box-shadow: var(--pulse-shadow-1);
  transition: box-shadow var(--pulse-transition), border-color var(--pulse-transition);
}
.list-detail__nav .pulse-split__back:hover {
  box-shadow: var(--pulse-shadow-2);
  border-color: var(--pulse-brand);
}

/* --------------------------------------------------------------------------
   Removed items
   A screen, not a panel: it replaces the toolbar and the views under the same
   header. Rows are plain surfaces rather than cards, because nothing here is
   draggable, tickable or openable; the only two things that can happen to one
   are the two buttons on it.
   -------------------------------------------------------------------------- */
.list-archive {
  padding-top: var(--pulse-space-md);
  max-width: 680px;
  margin-inline: auto;
}
.list-archive__nav { margin-bottom: var(--pulse-space-sm); }
/* Same real-button treatment as the detail nav, and for the same reason: it is
   the only way off this screen. The display rule is not optional, either.
   Pulse hides .pulse-split__back above 960px because ITS back button always
   sits beside a visible list, and without this the archive would have no exit
   on a desktop, which is the bug .list-solo already exists to fix. */
.list-archive__nav .pulse-split__back {
  display: inline-flex;
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border-strong);
  border-radius: var(--pulse-radius-m);
  padding: 0 var(--pulse-space-md);
  font-weight: 700;
  color: var(--pulse-brand-strong);
  box-shadow: var(--pulse-shadow-1);
  transition: box-shadow var(--pulse-transition), border-color var(--pulse-transition);
}
.list-archive__nav .pulse-split__back:hover {
  box-shadow: var(--pulse-shadow-2);
  border-color: var(--pulse-brand);
}
.list-archive__head { margin-bottom: var(--pulse-space-md); }
.list-archive__title {
  margin: 0;
  font-size: 1.35rem;
  line-height: 1.3;
  color: var(--pulse-text);
}
.list-archive__intro {
  margin: var(--pulse-space-2xs) 0 0;
  color: var(--pulse-text-muted);
  font-size: 0.9rem;
  line-height: 1.55;
}
.list-archive__row {
  display: grid;
  gap: var(--pulse-space-2xs);
  padding: var(--pulse-space-md);
  margin-bottom: var(--pulse-space-sm);
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-l);
}
.list-archive__name {
  margin: 0;
  font-weight: 600;
  line-height: 1.4;
  color: var(--pulse-text);
  overflow-wrap: anywhere;
}
.list-archive__meta {
  margin: 0;
  color: var(--pulse-text-faint);
  font-size: 0.82rem;
}
.list-archive__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pulse-space-xs);
  margin-top: var(--pulse-space-2xs);
}
/* Sized to their words rather than stretched across the row: two buttons that
   fill the width read as a choice between equals, and these two are not. */
.list-archive__actions .list-btn {
  flex: none;
  padding: 0 var(--pulse-space-md);
  font-size: 0.85rem;
}
.list-archive__note {
  margin: 0;
  padding: var(--pulse-space-sm) 0;
  color: var(--pulse-text-faint);
  font-size: 0.9rem;
}
.list-detail__head { margin-bottom: var(--pulse-space-md); }
.list-detail__title {
  margin: var(--pulse-space-2xs) 0 0;
  font-size: 1.35rem;
  line-height: 1.3;
  color: var(--pulse-text);
  overflow-wrap: anywhere;
}

.list-block {
  padding: var(--pulse-space-md);
  margin-bottom: var(--pulse-space-sm);
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-l);
}
.list-block--why {
  background: var(--pulse-brand-soft);
  border-color: color-mix(in srgb, var(--pulse-brand) 22%, var(--pulse-surface));
}
.list-block__head {
  margin: 0 0 var(--pulse-space-xs);
  font-size: 0.76rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--pulse-text-faint);
}
.list-block__body {
  margin: 0;
  line-height: 1.6;
  color: var(--pulse-text);
  overflow-wrap: anywhere;
}

/* Stage and person: full-width targets on a phone, side by side once there is
   room. Both blocks reuse this grid, so it has to hold three buttons and five
   without either wrapping to a stripe of unreadable stubs. */
.list-status { display: grid; gap: var(--pulse-space-xs); }
.list-status__btn {
  --_status: var(--pulse-text-muted);
  min-height: var(--pulse-touch-target);
  padding: 0 var(--pulse-space-md);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-m);
  background: var(--pulse-surface);
  color: var(--pulse-text-muted);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--pulse-transition), color var(--pulse-transition), border-color var(--pulse-transition);
}
.list-status__btn:hover { border-color: var(--pulse-border-strong); }
.list-status__btn.is-active {
  color: color-mix(in srgb, var(--_status) 80%, var(--pulse-text));
  background: color-mix(in srgb, var(--_status) 15%, var(--pulse-surface));
  border-color: color-mix(in srgb, var(--_status) 48%, var(--pulse-surface));
}

/* --------------------------------------------------------------------------
   Notes
   -------------------------------------------------------------------------- */
.list-notes { display: grid; gap: var(--pulse-space-xs); }
.list-note {
  position: relative;
  padding: var(--pulse-space-sm) var(--pulse-space-md);
  padding-right: calc(var(--pulse-space-md) + 20px);
  background: var(--pulse-surface-sunken);
  border-radius: var(--pulse-radius-m);
  overflow-wrap: anywhere;
}
.list-note--mine { background: var(--pulse-brand-soft); }
.list-note__meta { font-size: 0.75rem; color: var(--pulse-text-faint); margin-bottom: 2px; }
.list-note__body { line-height: 1.5; white-space: pre-wrap; }
.list-note__del {
  position: absolute;
  top: 4px; right: 4px;
  width: 28px; height: 28px;
  border: 0; border-radius: 50%;
  background: none;
  color: var(--pulse-text-faint);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}
.list-note__del:hover { color: var(--pulse-danger); background: var(--pulse-surface); }
.list-note-empty { margin: 0; color: var(--pulse-text-faint); font-size: 0.9rem; line-height: 1.5; }

.list-noteform { display: flex; gap: var(--pulse-space-xs); margin-top: var(--pulse-space-sm); }
.list-noteform__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--pulse-space-sm);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-m);
  background: var(--pulse-surface);
  color: var(--pulse-text);
  font: inherit;
  /* 16px minimum stops iOS Safari zooming the page on focus. */
  font-size: 16px;
  resize: vertical;
}
.list-noteform__input:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: 1px; }

/* --------------------------------------------------------------------------
   Photos
   -------------------------------------------------------------------------- */
.list-photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: var(--pulse-space-xs);
}
.list-photos:empty { display: none; }
.list-photo { position: relative; }
.list-photo img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--pulse-radius-m);
  border: 1px solid var(--pulse-border);
  display: block;
  background: var(--pulse-surface-sunken);
  cursor: pointer;
}
/* A player has controls of its own and needs the width to show them, so audio
   and video break out of the square grid and take the whole row. The modifier
   stands alone on the tile: it is never combined with .list-attach, which is
   the add-a-file button below. */
.list-attach--wide { grid-column: 1 / -1; }
.list-photo audio,
.list-photo video {
  width: 100%;
  display: block;
  border-radius: var(--pulse-radius-m);
}
/* Video is accepted rather than courted: no poster, no thumbnail, and a cap on
   how much of the page one clip may take. */
.list-photo video {
  max-height: 320px;
  background: var(--pulse-surface-sunken);
}
.list-attach__label {
  margin-top: var(--pulse-space-2xs);
  font-size: 0.78rem;
  color: var(--pulse-text-faint);
  overflow-wrap: anywhere;
}
/* A button, not a link: attachments are fetched with the bearer token and
   handed over as a blob, so there is no URL to put in an href. It carries the
   real filename, which can be long, so it grows downwards and breaks anywhere
   rather than being held to a square and spilling out of it. */
.list-photo__file {
  display: grid;
  place-items: center;
  gap: 4px;
  width: 100%;
  height: auto;
  min-height: var(--pulse-touch-target);
  padding: var(--pulse-space-xs);
  border: 1px dashed var(--pulse-border-strong);
  border-radius: var(--pulse-radius-m);
  background: var(--pulse-surface);
  color: var(--pulse-text-muted);
  font: inherit;
  font-size: 0.78rem;
  text-align: center;
  /* A button computes nowrap from the vendored native styles, so the name would
     sit on one line and spill out of both sides of the tile. */
  white-space: normal;
  overflow-wrap: anywhere;
  text-decoration: none;
  cursor: pointer;
}
/* The label is a grid item, and centring gives it its max-content width, which
   is wider than the tile for anything longer than a word or two. Holding it to
   the tile is what actually makes the wrap above take effect. */
.list-photo__file > span { max-width: 100%; }
.list-photo__del {
  position: absolute;
  top: 4px; right: 4px;
  width: 26px; height: 26px;
  border: 0; border-radius: 50%;
  background: var(--pulse-surface);
  color: var(--pulse-text-muted);
  box-shadow: var(--pulse-shadow-1);
  cursor: pointer;
  line-height: 1;
}
.list-attach { margin-top: var(--pulse-space-sm); display: inline-flex; }
/* The input is a trigger, never a control anyone sees: the label is the button.
   The hidden attribute alone does not achieve that here, because Web Awesome's
   native.css carries input[type="file"] { display: block } and an author rule
   beats the browser's own rule for [hidden]. Without this line the native file
   picker renders beside the label and pushes the page sideways on a phone. */
.list-attach input[type="file"] { display: none; }

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.list-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--pulse-touch-target);
  padding: 0 var(--pulse-space-md);
  border-radius: var(--pulse-radius-m);
  border: 1px solid transparent;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-align: center;
}
.list-btn--primary { background: var(--pulse-brand); color: var(--pulse-text-invert); }
.list-btn--primary:hover { background: var(--pulse-brand-strong); }
.list-btn--ghost {
  background: var(--pulse-surface);
  border-color: var(--pulse-border-strong);
  color: var(--pulse-text);
}
.list-btn--quiet { background: none; color: var(--pulse-text-muted); }
.list-btn--quiet:hover { color: var(--pulse-danger); }

/* What you can do to an item, sitting under the nav at the top of the detail.
   It scrolls sideways on a phone rather than wrapping into three stacked rows
   that push the actual content off the screen: these are tools, and tools sit
   on a shelf. Edge-to-edge bleed so the row reads as scrollable. */
.list-owner {
  display: flex;
  gap: var(--pulse-space-sm);
  padding: var(--pulse-space-sm) 0;
  margin-bottom: var(--pulse-space-xs);
  border-bottom: 1px solid var(--pulse-border);
  overflow-x: auto;
  scrollbar-width: none;
}
.list-owner::-webkit-scrollbar { display: none; }
.list-owner .list-btn {
  flex: none;
  white-space: nowrap;
}
@media (min-width: 640px) {
  .list-owner { flex-wrap: wrap; overflow-x: visible; }
}

/* Add button. Sits above the home indicator on iOS. */
.list-fab {
  position: fixed;
  right: var(--pulse-space-md);
  bottom: calc(var(--pulse-space-md) + env(safe-area-inset-bottom));
  width: 56px; height: 56px;
  border: 0; border-radius: 50%;
  background: var(--pulse-brand);
  color: var(--pulse-text-invert);
  font-size: 1.8rem;
  line-height: 1;
  box-shadow: var(--pulse-shadow-2);
  cursor: pointer;
  z-index: 10;
}

/* --------------------------------------------------------------------------
   Dialog
   -------------------------------------------------------------------------- */
.list-dialog {
  width: min(560px, calc(100vw - 2 * var(--pulse-space-md)));
  padding: 0;
  border: 0;
  border-radius: var(--pulse-radius-l);
  background: var(--pulse-surface);
  color: var(--pulse-text);
}
/* The scrim is a token, not a raw rgb(): pulse-core already owns the concept
   (--pulse-scrim, the text colour at 64%), so the backdrop follows the theme's
   warm near-black instead of a cold literal black nothing else on the page
   uses. */
.list-dialog::backdrop { background: var(--pulse-scrim); }
.list-form { display: grid; gap: var(--pulse-space-sm); padding: var(--pulse-space-lg); }
.list-form__head { margin: 0; font-size: 1.15rem; }
.list-form__row { display: grid; gap: var(--pulse-space-sm); }
.list-form__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--pulse-space-sm);
  padding-top: var(--pulse-space-xs);
}
.list-field { display: grid; gap: var(--pulse-space-2xs); }
.list-field > span { font-size: 0.82rem; font-weight: 600; color: var(--pulse-text-muted); }
.list-field input,
.list-field select,
.list-field textarea {
  width: 100%;
  min-height: var(--pulse-touch-target);
  padding: var(--pulse-space-xs) var(--pulse-space-sm);
  border: 1px solid var(--pulse-border-strong);
  border-radius: var(--pulse-radius-m);
  background: var(--pulse-surface);
  color: var(--pulse-text);
  font: inherit;
  font-size: 16px;   /* no iOS zoom on focus */
}
.list-field textarea { resize: vertical; line-height: 1.5; }
/* A hint sitting under an ordinary field. Without this it would inherit the
   `.list-field > span` label rule above and read as a second label. */
.list-field > .list-field__hint {
  font-size: 0.78rem;
  font-weight: 400;
  color: var(--pulse-text-faint);
}

/* Checkbox row: the box sits beside its label with the hint under both. */
.list-field--check {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--pulse-space-2xs) var(--pulse-space-xs);
  min-height: var(--pulse-touch-target);
  cursor: pointer;
}
.list-field--check input { width: 20px; height: 20px; accent-color: var(--pulse-accent); }
.list-field--check > span { font-size: 0.82rem; font-weight: 600; color: var(--pulse-text-muted); }
.list-field--check .list-field__hint {
  grid-column: 2;
  font-size: 0.78rem;
  font-weight: 400;
  color: var(--pulse-text-faint);
}
.list-field input:focus-visible,
.list-field select:focus-visible,
.list-field textarea:focus-visible { outline: 2px solid var(--pulse-focus); outline-offset: 1px; }

/* The two ways to combine, as a real fieldset so the legend is read as the
   question the radios answer. */
.list-modes {
  display: grid;
  gap: var(--pulse-space-xs);
  margin: 0;
  padding: var(--pulse-space-sm);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-m);
}
.list-modes legend {
  padding: 0 var(--pulse-space-2xs);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--pulse-text-muted);
}
.list-modes input[type="radio"] { width: 20px; height: 20px; accent-color: var(--pulse-accent); }

/* The count that should give him pause before wrapping a project up. Amber,
   like every other "this is worth reading" line on the board, never red. */
.list-wrapup__warn {
  color: var(--pulse-warning);
  font-weight: 600;
}

/* Split: one field per part, stacked. */
.list-splits { display: grid; gap: var(--pulse-space-sm); }
/* A disabled checkbox still has to be legible: it is explaining the model, not
   waiting for an answer. */
.list-field--check input:disabled { accent-color: var(--pulse-text-muted); }
.list-field--check:has(input:disabled) { cursor: default; }

/* --------------------------------------------------------------------------
   Gate (no link, or a dead link)
   -------------------------------------------------------------------------- */
.list-gate {
  padding: var(--pulse-space-xl) var(--pulse-space-md);
  text-align: center;
  color: var(--pulse-text-muted);
  line-height: 1.6;
}
.list-gate h1 { color: var(--pulse-text); font-size: 1.35rem; margin-bottom: var(--pulse-space-sm); }

/* --------------------------------------------------------------------------
   Wider screens
   -------------------------------------------------------------------------- */
@media (min-width: 560px) {
  .list-status { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .list-form__row { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 960px) {
  .list-head__title { font-size: 1.9rem; }
  .pulse-main { padding-bottom: var(--pulse-space-xl); }
}

/* --------------------------------------------------------------------------
   Sections: List, Talks, Calendar
   The one switcher above everything. The badge on Talks counts what still
   needs talking about; the badge on Calendar counts what is waiting for YOUR
   answer. Small, quiet numbers, never red.
   -------------------------------------------------------------------------- */
.list-sections { margin: var(--pulse-space-sm) 0 var(--pulse-space-xs); }
.list-sections .pulse-seg__btn { position: relative; }
.list-sections__badge {
  display: inline-block;
  margin-left: 6px;
  min-width: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--pulse-accent-soft);
  color: var(--pulse-text);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}

/* --------------------------------------------------------------------------
   Talks
   -------------------------------------------------------------------------- */
.list-talks__group { margin-bottom: var(--pulse-space-md); }
.list-group__head {
  display: flex;
  align-items: baseline;
  gap: var(--pulse-space-2xs);
  margin: var(--pulse-space-md) 0 0;
  font-size: 1rem;
  font-weight: 700;
  color: var(--pulse-text);
}
.list-group__count { font-size: 0.8rem; font-weight: 600; color: var(--pulse-text-faint); }
.list-talk { cursor: pointer; }
.list-talk__why {
  margin: var(--pulse-space-2xs) 0 0;
  color: var(--pulse-text-muted);
  font-size: 0.9rem;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.list-talk__meta {
  margin: var(--pulse-space-2xs) 0 0;
  color: var(--pulse-text-faint);
  font-size: 0.8rem;
}
.list-talk__raised {
  margin: var(--pulse-space-2xs) 0 0;
  color: var(--pulse-text-faint);
  font-size: 0.82rem;
}
.list-talk__links { display: grid; gap: var(--pulse-space-xs); }
.list-talk__link { display: flex; align-items: center; gap: var(--pulse-space-2xs); }
.list-talk__link .list-deplink { flex: 1; }
.list-talk__picker {
  display: flex;
  gap: var(--pulse-space-xs);
  margin-top: var(--pulse-space-sm);
}
.list-talk__picker select { flex: 1; min-width: 0; }
.list-talk__byrow { margin-bottom: var(--pulse-space-sm); }
.list-field--inline {
  display: flex;
  align-items: center;
  gap: var(--pulse-space-sm);
}
.list-field--inline input { max-width: 200px; }

/* Where we landed: the standing answer, tinted like the why block but its own
   colour family, because an outcome is a different kind of fact. */
.list-block--outcome {
  background: var(--pulse-accent-soft);
  border-color: color-mix(in srgb, var(--pulse-accent) 25%, var(--pulse-surface));
}
.list-block--outcome .list-btn { margin-top: var(--pulse-space-xs); }

.list-detail__tools {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pulse-space-xs);
  margin-top: var(--pulse-space-md);
}
.list-noteform--talk { flex-wrap: wrap; }
.list-noteform--talk .list-noteform__input { flex: 1 1 100%; }
.list-noteform__meeting { flex: 1; min-width: 0; }
.list-deplink--inline {
  display: inline;
  width: auto;
  padding: 0 2px;
  font-size: inherit;
}

/* --------------------------------------------------------------------------
   Calendar
   Colour per person is the whole legend. Proposed entries are dashed or
   hollow until they are answered: a proposal should look like one.
   -------------------------------------------------------------------------- */
.list-cal {
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border);
  border-radius: var(--pulse-radius-m);
  padding: var(--pulse-space-sm);
  margin-top: var(--pulse-space-sm);
}
.list-cal__nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--pulse-space-xs);
}
.list-cal__month { font-weight: 700; }
.list-cal__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.list-cal__dow {
  text-align: center;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--pulse-text-faint);
  padding: var(--pulse-space-2xs) 0;
}
.list-cal__day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-height: 44px;
  padding: 4px 0 6px;
  border: 1px solid transparent;
  border-radius: var(--pulse-radius-s);
  background: none;
  cursor: pointer;
  font: inherit;
  color: var(--pulse-text);
}
.list-cal__day:hover { background: var(--pulse-brand-soft); }
.list-cal__day.is-out { color: var(--pulse-text-faint); opacity: 0.55; }
.list-cal__day.is-today { border-color: var(--pulse-accent); }
.list-cal__day.is-selected { background: var(--pulse-accent-soft); }
.list-cal__num { font-size: 0.85rem; line-height: 1.2; }
.list-cal__dots { display: flex; gap: 3px; min-height: 6px; }
.list-cal__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--_who);
}
.list-cal__dot.is-proposed {
  background: transparent;
  border: 1.5px solid var(--_who);
}
.list-cal__list { margin-top: var(--pulse-space-sm); }
.list-cal__dayhead {
  margin: var(--pulse-space-sm) 0 var(--pulse-space-2xs);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--pulse-text-muted);
}
.list-cal__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--pulse-space-xs);
  padding: var(--pulse-space-xs) var(--pulse-space-sm);
  margin-bottom: var(--pulse-space-xs);
  background: var(--pulse-surface);
  border: 1px solid var(--pulse-border);
  border-left: 4px solid var(--_who);
  border-radius: var(--pulse-radius-s);
  cursor: pointer;
}
.list-cal__row.is-proposed { border-style: dashed; border-left-style: solid; }
.list-cal__row.is-declined { opacity: 0.55; }
.list-cal__time {
  font-size: 0.78rem;
  color: var(--pulse-text-faint);
  white-space: nowrap;
}
.list-cal__label { font-weight: 600; font-size: 0.92rem; }
.list-cal__chip {
  font-size: 0.72rem;
  font-weight: 600;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--pulse-brand-soft);
  color: var(--pulse-text-muted);
}
.list-cal__chip.is-asking { background: var(--pulse-accent-soft); color: var(--pulse-text); }
.list-cal__chip.is-declined { background: none; border: 1px solid var(--pulse-border); }
.list-cal__answers {
  display: flex;
  gap: var(--pulse-space-2xs);
  margin-left: auto;
}
.list-form__kinds { margin-bottom: var(--pulse-space-sm); }
.list-block--ask { border-color: color-mix(in srgb, var(--pulse-accent) 30%, var(--pulse-surface)); }

/* Talks drag: an empty group stays a real dropzone, and the board's ghost
   classes do the rest. */
.list-talks .list-cards { min-height: 28px; }
.list-talk { touch-action: pan-y; }

/* --------------------------------------------------------------------------
   Calendar: what an entry means for the person reading it
   The one line on this page written from the reader's side. Tones are the
   board's existing register: calm says nothing is needed, ask wants
   something from you, wait is on the other person, off is settled as a no.
   -------------------------------------------------------------------------- */
.list-cal__means {
  flex: 1 1 100%;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--pulse-text-muted);
}
.list-cal__means--ask { color: var(--pulse-warning); font-weight: 600; }
.list-cal__means--wait { color: var(--pulse-text-faint); }
.list-cal__means--off { color: var(--pulse-text-faint); font-style: italic; }

.list-cal__controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pulse-space-xs);
  align-items: center;
  justify-content: space-between;
  margin-top: var(--pulse-space-sm);
}
.list-cal__facets { flex-wrap: wrap; }
.list-cal__views { margin-left: auto; }

/* The calendar as a table: the same five answers across a whole month. */
.list-tablewrap {
  margin-top: var(--pulse-space-sm);
  overflow-x: auto;
}
.list-table--cal {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.list-table--cal th,
.list-table--cal td {
  text-align: left;
  padding: var(--pulse-space-xs) var(--pulse-space-sm);
  border-bottom: 1px solid var(--pulse-border);
  vertical-align: top;
}
.list-table--cal th {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--pulse-text-faint);
  white-space: nowrap;
}
.list-table--cal .list-table__row { cursor: pointer; }
.list-table--cal .list-table__row:hover td {
  background: color-mix(in srgb, var(--pulse-brand) 6%, var(--pulse-surface));
}
.list-table--cal .list-table__row:focus-visible {
  outline: 2px solid var(--pulse-focus);
  outline-offset: -2px;
}
.list-table__sub {
  display: block;
  font-size: 0.75rem;
  color: var(--pulse-text-faint);
}
.list-table--cal td.is-cover { font-weight: 600; }

/* A control that is absent says why; a question on the meaning block reads
   as a question. Both are quiet lines, not warnings. */
.list-cal__lock {
  margin: var(--pulse-space-xs) 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--pulse-text-faint);
}
.list-block--means .list-status { margin-top: var(--pulse-space-xs); }
