/* HTMLHELD Tasks - minimal stylesheet (v0.1). */

:root {
  --bg: #f5f6f8;
  --surface: #ffffff;
  --surface-2: #f0f2f5;
  --border: #d8dadf;
  --border-strong: #b3b8c1;
  --text: #1a1d23;
  --text-soft: #5e6366;
  --accent: #005faf;
  --accent-soft: #e6f0fa;
  --danger: #b22a2a;
  --danger-soft: #fdeaea;
  --success: #1f7a3c;
  --success-soft: #e6f4eb;
  --warning: #b97a00;
  --warning-soft: #fdf2da;
  --shadow: 0 1px 2px rgba(15, 19, 26, 0.08), 0 2px 8px rgba(15, 19, 26, 0.04);
  /* v0.8.1 calm-by-default palette (Jovana feedback: "tone it down"): only URGENT
     and BLOCKED carry visible color. Everything else uses neutral gray. Per-board
     brand color is dropped from headers/tiles/badges so multi-board views read as
     one uniform surface. --surface-2 is a subtle 2-tone step for row-hover +
     column-badge fills. */
  --calm-urgent-soft: #f7ecec;
  --calm-urgent-accent: #c98080;
  --calm-urgent-text: #8a3a3a;
  --calm-done-opacity: 0.62;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
}

/* Topbar -------------------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 10px 24px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.topbar-brand a {
  color: var(--text);
  font-weight: 600;
  font-size: 15px;
}

.topbar-nav {
  flex: 1;
  display: flex;
  gap: 4px;
}

.topbar-nav-link {
  padding: 6px 12px;
  border-radius: 6px;
  color: var(--text-soft);
}

.topbar-nav-link:hover {
  background: var(--accent-soft);
  text-decoration: none;
}

.topbar-nav-link.active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.topbar-user {
  display: flex;
  align-items: center;
  gap: 10px;
}

.topbar-user-name {
  font-weight: 600;
}

.topbar-user-role {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.role-admin {
  background: var(--accent-soft);
  color: var(--accent);
}

.role-member {
  background: var(--success-soft);
  color: var(--success);
}

.logout-form {
  margin: 0;
}

/* v0.5.1 language switch: explicit DE / EN segmented control so the affordance is
   immediately readable. Both options are always visible; the active one is
   highlighted + disabled (button click prevented + accessible state announced). */
.locale-switch {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
  margin: 0;
  padding: 0;
  background: var(--surface);
  line-height: 1;
}

.locale-option {
  background: transparent;
  border: 0;
  padding: 5px 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-soft);
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}

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

.locale-option:hover:not(:disabled) {
  background: var(--accent-soft);
  color: var(--accent);
}

.locale-option.is-active,
.locale-option:disabled {
  background: var(--accent);
  color: #fff;
  cursor: default;
  opacity: 1;
}

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

.btn-link {
  background: none;
  border: 0;
  padding: 0;
  color: var(--text-soft);
  cursor: pointer;
}

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

/* App shell + main + flash --------------------------------- */

/* v0.5: .app-shell wraps .main + the side-panel aside in a flex row.
   v0.6: panel moved from right to left (Jovana's request). Border swapped from
   border-left -> border-right. Template child order swapped so panel renders first.
   On login + change-password (no panel rendered) the shell holds a single child,
   so the layout stays identical to pre-v0.5. */
.app-shell {
  display: flex;
  align-items: flex-start;
  gap: 0;
  width: 100%;
}

.main {
  max-width: 1200px;
  margin: 0 auto;
  padding: 32px 24px;
  flex: 1 1 auto;
  min-width: 0;
}

.flash {
  padding: 10px 14px;
  border-radius: 6px;
  margin-bottom: 16px;
  border: 1px solid transparent;
}

.flash-error {
  background: var(--danger-soft);
  border-color: var(--danger);
  color: var(--danger);
}

.flash-success {
  background: var(--success-soft);
  border-color: var(--success);
  color: var(--success);
}

.flash-info {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

.flash-warning {
  background: var(--warning-soft);
  border-color: var(--warning);
  color: var(--warning);
}

/* Login + change-password ------------------------------- */

.page-login,
.page-change-password {
  background: linear-gradient(180deg, #ecf0f7 0%, #f5f6f8 100%);
  min-height: 100vh;
}

.page-login .main,
.page-change-password .main {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

.login-card {
  width: 100%;
  max-width: 400px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 32px 28px;
  box-shadow: var(--shadow);
  position: relative;
}

.login-lang-bar {
  position: absolute;
  top: 12px;
  right: 16px;
  display: flex;
  gap: 4px;
  align-items: center;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
}

.login-lang-link {
  color: var(--text-soft);
  padding: 2px 4px;
  border-radius: 4px;
}

.login-lang-link.active {
  color: var(--accent);
  background: var(--accent-soft);
  text-decoration: none;
}

.login-lang-link:hover {
  text-decoration: none;
  color: var(--accent);
}

.login-lang-sep {
  color: var(--border-strong);
}

.login-card h1 {
  margin: 0 0 4px;
  font-size: 22px;
}

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

.login-form {
  display: grid;
  gap: 14px;
}

.login-form label {
  display: grid;
  gap: 6px;
}

.login-form label span {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.login-form input {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
}

.login-form input:focus {
  border-color: var(--accent);
  outline: 2px solid var(--accent-soft);
  outline-offset: 0;
}

.btn-primary {
  margin-top: 4px;
  padding: 10px 14px;
  border: 0;
  border-radius: 6px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
}

.btn-primary:hover {
  background: #004a8a;
}

.login-footer {
  margin: 20px 0 0;
  color: var(--text-soft);
  font-size: 12px;
  text-align: center;
}

/* Home / boards grid ------------------------------------ */

.home-hero h1 {
  margin: 0 0 4px;
  font-size: 24px;
}

.home-sub {
  margin: 0 0 24px;
  color: var(--text-soft);
}

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

.board-tile {
  display: flex;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  color: var(--text);
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}

.board-tile:hover {
  text-decoration: none;
  transform: translateY(-1px);
  box-shadow: var(--shadow);
  border-color: var(--border-strong);
}

.board-tile-color {
  /* v0.8.1: dropped per-board tint. All tiles carry the same neutral spine so
     multi-board home page reads as one calm grid, not a rainbow. Inline
     --board-color style on the template becomes a dead attribute; kept in
     markup for future opt-in but ignored by CSS. */
  width: 8px;
  background: var(--border-strong);
}

.board-tile-body {
  padding: 16px 18px;
  flex: 1;
}

.board-tile-body h2 {
  margin: 0 0 4px;
  font-size: 16px;
  font-weight: 600;
}

.board-tile-body p {
  margin: 0;
  font-size: 13px;
  color: var(--text-soft);
}

/* Board detail (kanban) -------------------------------------------- */

.page-board .main {
  max-width: none;
  padding: 24px 32px;
}

/* Tasks list view (/tasks/all, /tasks/mine, /tasks/shared) ---------- */
/* Match kanban: full-width to the right edge so the dense list view
   (toolbar + chip rows + multi-column rows) can breathe instead of
   being clipped to the 1200px centered main column. v0.6.3 fix per
   Jovana feedback "looks very overwhelmed". */

.page-tasks .main {
  max-width: none;
  padding: 24px 32px;
}

/* v0.6 side panel (was right-panel in v0.5, moved to left in v0.6) ----------- */

.side-panel {
  flex: 0 0 280px;
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: 20px 18px;
  min-height: calc(100vh - 49px); /* topbar is ~49px tall */
  position: sticky;
  top: 0;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  gap: 16px;
  font-size: 13px;
}

.panel-section {
  border: 0;
}

.panel-section summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
}

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

.panel-section-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 4px;
  border-radius: 4px;
  color: var(--text-soft);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.panel-section-head:hover {
  background: var(--accent-soft);
  color: var(--accent);
}

.panel-section-caret {
  display: inline-block;
  transition: transform 0.15s ease;
  font-size: 14px;
  line-height: 1;
}

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

.panel-list {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.panel-subhead {
  margin-top: 10px;
  padding: 4px 8px;
  font-size: 11px;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.panel-item {
  display: flex;
  align-items: center;
}

.panel-item-link {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 10px;
  border-radius: 5px;
  color: var(--text);
  text-decoration: none;
  font-weight: 500;
}

.panel-item-link:hover {
  background: var(--accent-soft);
  color: var(--accent);
  text-decoration: none;
}

/* v0.5 legacy placeholder style (rows are now scaffold-clickable in v0.6) */
.panel-item.is-placeholder {
  padding: 6px 10px;
  color: var(--text-soft);
  opacity: 0.6;
  cursor: not-allowed;
  border-radius: 5px;
  gap: 8px;
}

.panel-item.is-placeholder:hover {
  background: transparent;
}

/* v0.6 scaffold rows: clickable but visually marked as "test phase" via a
   small TEST badge on the right. Hover behaves like is-live so the
   interactability cue is unambiguous. */
.panel-item.is-scaffold .panel-item-link {
  color: var(--text);
}

.panel-item-count-scaffold {
  background: var(--warning-soft);
  color: var(--warning);
  font-size: 9px;
  letter-spacing: 0.08em;
  font-weight: 700;
  padding: 1px 6px;
  text-transform: uppercase;
}

.panel-item-link:hover .panel-item-count-scaffold {
  background: var(--warning);
  color: #fff;
}

.panel-item-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.panel-item-count {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 600;
  background: var(--bg);
  color: var(--text-soft);
  padding: 1px 7px;
  border-radius: 9px;
  min-width: 22px;
  text-align: center;
}

.panel-item-link:hover .panel-item-count {
  background: var(--surface);
  color: var(--accent);
}

.panel-item-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--tag-color, var(--text-soft));
}

.panel-item-header {
  margin-bottom: 4px;
}

.panel-list-tags {
  margin-top: 2px;
}

/* Mobile/narrow: hide the panel below 900px so the kanban + boards fill the
   width. This is the v0.5 floor; full responsive (collapse-to-drawer) is a
   v0.5.1 follow-up if Jovana asks. */
@media (max-width: 900px) {
  .side-panel {
    display: none;
  }
}

/* v0.5 tasks list view -------------------------------------- */

.tasks-header {
  margin-bottom: 18px;
}

.tasks-header h1 {
  font-size: 22px;
  margin: 0 0 4px 0;
  display: flex;
  align-items: center;
  gap: 10px;
}

.tasks-tag-pill {
  display: inline-block;
  padding: 2px 10px;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 10px;
  font-size: 12px;
  font-weight: 600;
}

.tasks-sub {
  margin: 0;
  color: var(--text-soft);
  font-size: 13px;
}

.tasks-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tasks-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: var(--shadow);
  overflow: hidden;
}

/* v0.8.1 calm-by-default: /tasks list rows only surface urgent visibly, and
   only with the muted calm-urgent-accent. High/low sit flat with the rest so
   the eye scans for urgent-only, not for a priority-color-coded stripe. */
.tasks-row.priority-urgent {
  border-left: 3px solid var(--calm-urgent-accent);
}

.tasks-row.priority-high,
.tasks-row.priority-low {
  border-left: 3px solid transparent;
}

.tasks-row-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  color: var(--text);
  text-decoration: none;
  gap: 16px;
}

.tasks-row-link:hover {
  background: var(--accent-soft);
  text-decoration: none;
}

.tasks-row-main {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  flex: 1 1 auto;
}

.tasks-row-board {
  /* v0.8.1: neutral board badge (was per-board colored background with white
     text). Multi-board list reads as one calm surface; the board name still
     communicates origin via text. */
  flex: 0 0 auto;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--surface-2);
  color: var(--text-soft);
  border: 1px solid var(--border);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.tasks-row-title {
  font-weight: 500;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tasks-row-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  color: var(--text-soft);
  flex: 0 0 auto;
}

.tasks-row-priority {
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.tasks-empty {
  padding: 32px;
  text-align: center;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: 8px;
  color: var(--text-soft);
}

.board-header {
  display: flex;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 20px;
  box-shadow: var(--shadow);
}

.board-header-spine {
  /* v0.8.1: dropped per-board tint. See .board-tile-color comment. */
  width: 8px;
  background: var(--border-strong);
}

.board-header-body {
  padding: 16px 22px;
  flex: 1;
}

.board-back {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 6px;
}

.board-back:hover {
  color: var(--accent);
  text-decoration: none;
}

.board-header-body h1 {
  margin: 0;
  font-size: 22px;
}

.board-sub {
  margin: 4px 0 0;
  color: var(--text-soft);
  font-size: 13px;
}

.kanban {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(280px, 1fr);
  gap: 16px;
  align-items: start;
}

.kanban-column {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  min-height: 200px;
}

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

.kanban-column-head h2 {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-soft);
}

.kanban-column-count {
  background: var(--bg);
  border-radius: 999px;
  padding: 2px 10px;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-soft);
  border: 1px solid var(--border);
}

.kanban-cards {
  list-style: none;
  margin: 0;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
  min-height: 60px;
}

.kanban-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  cursor: grab;
  transition: box-shadow 0.08s ease, border-color 0.08s ease, transform 0.08s ease;
  border-left: 3px solid var(--border-strong);
}

.kanban-card:hover {
  box-shadow: var(--shadow);
  border-color: var(--border-strong);
}

/* v0.8.1: calm-by-default kanban card priority accents. Only URGENT shows a
   colored left border; high and low blend into the neutral default so
   mixed-priority columns do not read as a rainbow. Priority pill still shows
   the level in text for anyone who needs the detail. */
.kanban-card.priority-urgent {
  border-left-color: var(--calm-urgent-accent);
}
.kanban-card.priority-high,
.kanban-card.priority-normal,
.kanban-card.priority-low {
  border-left-color: var(--border-strong);
}

.kanban-card-ghost {
  opacity: 0.4;
  background: var(--accent-soft);
}

.kanban-card-dragging {
  transform: rotate(0.5deg);
  cursor: grabbing;
}

.kanban-card-title {
  font-weight: 600;
  font-size: 14px;
  line-height: 1.35;
}

.kanban-card-desc {
  margin-top: 4px;
  font-size: 12px;
  color: var(--text-soft);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.kanban-card-meta {
  margin-top: 8px;
  display: flex;
  gap: 8px;
  font-size: 11px;
  color: var(--text-soft);
  flex-wrap: wrap;
}

.kanban-card-assignee,
.kanban-card-due,
.kanban-card-priority {
  background: var(--bg);
  border-radius: 999px;
  padding: 1px 8px;
  border: 1px solid var(--border);
}

.kanban-card-priority {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
}

.kanban-add-card {
  display: flex;
  gap: 6px;
  padding: 10px;
  border-top: 1px solid var(--border);
  background: var(--bg);
  border-bottom-left-radius: 10px;
  border-bottom-right-radius: 10px;
}

.kanban-add-card input {
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 13px;
  background: var(--surface);
}

.kanban-add-card input:focus {
  outline: 2px solid var(--accent-soft);
  border-color: var(--accent);
}

.btn-add-card {
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  color: var(--accent);
  font-size: 12px;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 6px;
  cursor: pointer;
}

.btn-add-card:hover {
  background: var(--accent);
  color: #fff;
}

/* Card detail overlay --------------------------------------------- */

.card-detail-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 19, 26, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

.card-detail-overlay[hidden] {
  display: none;
}

.card-detail-panel {
  background: var(--surface);
  border-radius: 12px;
  width: min(640px, 92vw);
  max-height: 92vh;
  overflow: auto;
  padding: 24px;
  box-shadow: var(--shadow);
  position: relative;
}

.card-detail-close {
  position: absolute;
  top: 8px;
  right: 12px;
  background: none;
  border: 0;
  font-size: 22px;
  color: var(--text-soft);
  cursor: pointer;
  line-height: 1;
}

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

.card-detail-field {
  display: grid;
  gap: 4px;
  margin-bottom: 12px;
}

.card-detail-field span {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-soft);
}

.card-detail-field input,
.card-detail-field select,
.card-detail-field textarea {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  background: var(--surface);
  font: inherit;
}

.card-detail-field textarea {
  resize: vertical;
  min-height: 100px;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
}

.card-detail-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.card-detail-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.card-detail-actions > div {
  display: flex;
  gap: 8px;
}

.card-detail-delete {
  color: var(--danger);
}

.card-detail-delete:hover {
  color: var(--danger);
  text-decoration: underline;
}

body.modal-open {
  overflow: hidden;
}

/* v0.6 scaffold pages -------------------------------------------- */
/* Shared styles for /inbox, /replies, /comments/assigned, /mentions, /drafts.
   These are "test phase" surfaces: mock data + interactive client-side affordances
   (reveal reply panel, mark read, dismiss) so Jovana can navigate the full shape
   before the real schema lands. */

.scaffold-page {
  max-width: 760px;
}

.scaffold-header {
  margin-bottom: 22px;
}

.scaffold-test-phase {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  background: var(--warning-soft);
  color: var(--warning);
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}

.scaffold-test-badge {
  background: var(--warning);
  color: #fff;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.scaffold-header h1 {
  margin: 0 0 4px;
  font-size: 22px;
}

.scaffold-sub {
  margin: 0;
  color: var(--text-soft);
  font-size: 13px;
}

.scaffold-filters {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 12px 0 16px;
  flex-wrap: wrap;
}

.chip {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text-soft);
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}

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

.chip.is-active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

/* Generic feed row used by inbox + replies + comments + mentions */
.feed-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.feed-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  transition: border-color 0.12s, box-shadow 0.12s;
}

.feed-row.is-unread {
  border-color: var(--accent);
  background: linear-gradient(180deg, var(--accent-soft) 0%, var(--surface) 100%);
}

.feed-row.is-read-mock {
  opacity: 0.55;
}

.feed-row.is-dismissed {
  display: none;
}

.feed-row-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--text-soft);
  margin-bottom: 4px;
}

.feed-row-author {
  font-weight: 700;
  color: var(--text);
}

.feed-row-kind-pill {
  background: var(--bg);
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* v0.8.1 calm-by-default: feed row kind pills are neutral for everything
   except "due" (attention-worthy) and "assigned" (routing signal). The pill
   letters still identify the kind; color no longer competes for attention. */
.feed-row-kind-pill.kind-assigned { background: var(--accent-soft); color: var(--accent); }
.feed-row-kind-pill.kind-mention { background: var(--surface-2); color: var(--text-soft); }
.feed-row-kind-pill.kind-comment { background: var(--surface-2); color: var(--text-soft); }
.feed-row-kind-pill.kind-status { background: var(--surface-2); color: var(--text-soft); }
.feed-row-kind-pill.kind-due { background: var(--calm-urgent-soft); color: var(--calm-urgent-text); }

.feed-row-body {
  font-size: 13px;
  color: var(--text);
  margin: 4px 0 8px;
  line-height: 1.5;
}

.feed-row-body strong {
  font-weight: 600;
}

.feed-row-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.btn-soft {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-soft);
  padding: 3px 10px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}

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

.btn-soft.is-active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

.feed-row-reply {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.feed-row-reply.is-hidden { display: none; }

.feed-row-reply textarea {
  width: 100%;
  min-height: 60px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-family: inherit;
  font-size: 13px;
  resize: vertical;
}

.feed-row-reply-actions {
  display: flex;
  gap: 8px;
  align-items: center;
}

.btn-send {
  background: var(--accent);
  color: #fff;
  border: 0;
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.btn-send:hover {
  filter: brightness(0.95);
}

.scaffold-empty {
  text-align: center;
  padding: 40px 20px;
  color: var(--text-soft);
  font-size: 13px;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: 8px;
}

.scaffold-empty p { margin: 0 0 8px; }

.scaffold-section {
  margin-top: 24px;
}

.scaffold-section h2 {
  font-size: 14px;
  margin: 0 0 8px;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.draft-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.draft-row-body { flex: 1; }
.draft-row-title { font-weight: 600; font-size: 14px; }
.draft-row-snippet { color: var(--text-soft); font-size: 12px; margin-top: 2px; }
.draft-row-meta { font-size: 11px; color: var(--text-soft); }

/* Scaffold filter visibility + flash toast (v0.6.0) */
.feed-row.is-filtered-out { display: none; }

.scaffold-flash {
  position: absolute;
  right: 14px;
  bottom: 8px;
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 999px;
  box-shadow: 0 2px 6px rgba(0,0,0,0.18);
  pointer-events: none;
  opacity: 0;
  animation: scaffold-flash-anim 1.8s ease-in-out forwards;
}

.feed-row, .draft-row { position: relative; }

@keyframes scaffold-flash-anim {
  0%   { opacity: 0; transform: translateY(4px); }
  15%  { opacity: 1; transform: translateY(0); }
  85%  { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-4px); }
}

/* Task scaffold (v0.6.1) ---------------------------------------------------- */

.task-scaffold .scaffold-section { padding: 20px 22px; }

.task-create-form { display: flex; flex-direction: column; gap: 14px; }

.task-create-row {
  display: flex;
  gap: 14px;
  align-items: flex-end;
  flex-wrap: wrap;
}

.task-create-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 160px;
}
.task-create-field-grow { flex: 1 1 280px; }
.task-create-field > span {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.task-create-field input,
.task-create-field select {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 14px;
  background: var(--surface);
  color: var(--text);
}
.task-create-field input:focus,
.task-create-field select:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

.task-create-note {
  font-size: 12px;
  color: var(--text-soft);
  font-style: italic;
}

/* Task card detail */
.task-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.task-card-head { display: flex; }

.task-card-title {
  flex: 1;
  font-size: 18px;
  font-weight: 700;
  padding: 6px 8px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--text);
  width: 100%;
}
.task-card-title:hover { border-color: var(--border); }
.task-card-title:focus {
  border-color: var(--accent);
  outline: none;
  background: var(--surface);
}

.task-card-meta-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}

.task-card-meta-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.task-card-meta-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.task-card-select,
.task-card-due {
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
  background: var(--surface);
  color: var(--text);
}

/* Status / priority pills row */
.status-pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.status-pill {
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--text-soft);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.status-pill:hover {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}
.status-pill.is-active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
/* v0.8.1: status/priority pill active states now all use the single --accent
   color instead of a 7-color rainbow. The active state still reads clearly
   (colored background vs neutral inactive) but multiple pills stop competing
   for attention. Urgent gets a distinct calm-urgent tint so the alert
   semantic survives. */
.status-pill.priority-urgent.is-active  {
  background: var(--calm-urgent-accent);
  border-color: var(--calm-urgent-accent);
}

.task-card-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.task-card-body-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.task-card-description {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 14px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  resize: vertical;
  min-height: 120px;
}
.task-card-description:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

.task-card-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.task-card-section-head {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0;
}

/* Thread (chat-style) */
.thread-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 320px;
  overflow-y: auto;
}
.thread-msg {
  background: var(--bg);
  border-left: 3px solid var(--border);
  border-radius: 0 6px 6px 0;
  padding: 8px 12px;
}
.thread-msg-self {
  border-left-color: var(--accent);
  background: var(--accent-soft);
}
.thread-msg-meta {
  display: flex;
  gap: 8px;
  align-items: baseline;
  font-size: 11px;
  color: var(--text-soft);
  margin-bottom: 4px;
}
.thread-msg-author {
  font-weight: 700;
  color: var(--text);
}
.thread-msg-time {}
.thread-msg-body {
  font-size: 13px;
  line-height: 1.45;
  color: var(--text);
  white-space: pre-wrap;
}

.thread-compose {
  display: flex;
  gap: 8px;
  align-items: flex-end;
}
.thread-compose-text {
  flex: 1;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  resize: vertical;
  min-height: 44px;
}
.thread-compose-text:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

/* Attachments */
.attach-dropzone {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 18px;
  border: 2px dashed var(--border);
  border-radius: 8px;
  color: var(--text-soft);
  font-size: 13px;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.attach-dropzone:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}
.attach-dropzone-icon { font-size: 18px; }

.attach-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.attach-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
}
.attach-icon { font-size: 16px; }
.attach-name { flex: 1; color: var(--text); }
.attach-size { color: var(--text-soft); font-size: 11px; }
.attach-remove { color: var(--text-soft); font-size: 12px; }
.attach-remove:hover { color: #dc2626; }

.task-card-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.task-card-actions-right { display: flex; gap: 8px; }

.task-card-delete {
  color: #dc2626;
  font-size: 13px;
}
.task-card-delete:hover { text-decoration: underline; }

.task-scaffold-feedback {
  margin-top: 16px;
  font-size: 12px;
  color: var(--text-soft);
  font-style: italic;
  text-align: center;
}

/* v0.6.2 tasks-list scaffold (test-phase /tasks/all + /tasks/mine) ----------- */

.page-tasks .scaffold-test-phase {
  margin-bottom: 14px;
}

.tasks-sub-mock-note {
  color: var(--text-soft);
  font-size: 12px;
  margin-left: 4px;
  font-style: italic;
}

.tasks-toolbar {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 12px 0 16px 0;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: var(--shadow);
}

.tasks-toolbar-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.tasks-filter-row {
  border-top: 1px dashed var(--border);
  padding-top: 8px;
}

.tasks-toolbar .tasks-filter-row:first-of-type {
  border-top: none;
  padding-top: 0;
}

.tasks-filter-label {
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-soft);
  margin-right: 2px;
}

.tasks-search {
  flex: 1 1 280px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  font-size: 14px;
  color: var(--text);
}

.tasks-search:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}

.tasks-sort-wrap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.tasks-sort-label {
  font-size: 12px;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}

.tasks-sort {
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
}

/* v0.6.4: filter chip active state. Border-color only (no tinted bg, no recolored text)
   so the chip row stays calm. The colored border edge plus is-active class is enough
   signal for "this filter is on"; the loud bg+text combo was compounding visual noise
   with the status-pill column and the priority pills on each row. */
/* v0.8.1: chip filter active states unified to a single accent border. The
   chips still read as "one of many is selected" via the border weight
   difference; per-chip color is decorative noise that competes with the row
   content below. */
.chip.status-chip-open.is-active,
.chip.status-chip-in_progress.is-active,
.chip.status-chip-on_hold.is-active,
.chip.status-chip-blocked.is-active,
.chip.status-chip-review.is-active,
.chip.status-chip-done.is-active,
.chip.priority-chip-urgent.is-active,
.chip.priority-chip-high.is-active,
.chip.priority-chip-normal.is-active,
.chip.priority-chip-low.is-active {
  border-color: var(--accent);
}

.tasks-bulk-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  margin-bottom: 12px;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: 8px;
  font-size: 13px;
  position: relative;
}

.tasks-bulk-bar.is-hidden {
  display: none;
}

.tasks-bulk-count {
  font-weight: 600;
  color: var(--accent);
  margin-right: 6px;
}

.btn-soft-danger {
  border-color: var(--danger);
  color: var(--danger);
}

.btn-soft-danger:hover {
  background: #fef2f2;
}

.tasks-bulk-flash {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  background: var(--text);
  color: #fff;
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 12px;
  animation: scaffold-flash-fade 1.8s ease-in-out forwards;
}

/* Tasks-list rows (extends v0.5 .tasks-row with the v0.6.2 scaffold shape) */

.tasks-list-scaffold {
  gap: 4px;
}

.tasks-list-scaffold .tasks-row {
  display: flex;
  align-items: stretch;
  padding: 0;
  position: relative;
}

.tasks-list-scaffold .tasks-row.is-filtered-out {
  display: none;
}

.tasks-list-scaffold .tasks-row.is-dismissed {
  opacity: 0;
  transform: translateX(40px);
  transition: opacity 0.22s ease-out, transform 0.22s ease-out;
}

.tasks-list-scaffold .tasks-row.is-mock {
  border-style: dashed;
}

.tasks-row-select {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  border-right: 1px solid var(--border);
  background: var(--bg);
  cursor: pointer;
}

.tasks-row-select input[type="checkbox"] {
  width: 16px;
  height: 16px;
  cursor: pointer;
}

.tasks-row-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 14px;
  min-width: 0;
}

.tasks-row-mock-badge {
  display: inline-block;
  padding: 1px 6px;
  background: transparent;
  color: var(--text-soft);
  border: 1px dashed var(--border);
  border-radius: 8px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-style: italic;
}

.tasks-row-title-link {
  color: var(--text);
  text-decoration: none;
  font-weight: 500;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tasks-row-title-link:hover {
  color: var(--accent);
  text-decoration: underline;
}

.tasks-list-scaffold .tasks-row-meta {
  flex-wrap: wrap;
  row-gap: 6px;
}

/* v0.6.4: calm status pill. Colored dot signals state; bg + text stay neutral.
   Only BLOCKED gets a faint red text/border because it is the only state that
   should grab attention in a flat list. DONE gets soft text so finished work
   visually recedes. Linear/Notion/GitHub pattern. */
.status-pill-small {
  padding: 2px 8px 2px 7px;
  font-size: 11px;
  font-weight: 500;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  letter-spacing: 0.01em;
  text-transform: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.status-pill-small::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-soft);
  flex: 0 0 7px;
}

.status-pill-small:hover {
  border-color: var(--accent);
}

/* v0.8.1: small status pill leading dot desaturated. Only BLOCKED keeps a
   subtle calm-urgent tint (it is the actionable-alert semantic). The rest
   read as neutral gray dots so the pill's TEXT communicates the state, not
   a mini-rainbow. */
.status-pill-small.status-open::before,
.status-pill-small.status-in_progress::before,
.status-pill-small.status-on_hold::before,
.status-pill-small.status-review::before,
.status-pill-small.status-done::before        { background: var(--text-soft); }
.status-pill-small.status-blocked::before     { background: var(--calm-urgent-accent); }

.status-pill-small.status-blocked {
  color: var(--calm-urgent-text);
  border-color: var(--calm-urgent-soft);
}

.status-pill-small.status-done {
  color: var(--text-soft);
}

/* v0.6.4: only URGENT keeps the loud red treatment because it is the
   actionable alert. High = subtle amber text + neutral border. Low = quiet
   gray. Normal is hidden by the template (only renders if != 'normal'). */
.priority-pill {
  padding: 1px 6px;
  border-radius: 8px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-soft);
}

.priority-pill.priority-urgent {
  background: var(--calm-urgent-soft);
  color: var(--calm-urgent-text);
  border-color: var(--calm-urgent-soft);
}
.priority-pill.priority-high {
  color: var(--text-soft);
  border-color: var(--border);
}
.priority-pill.priority-low {
  color: var(--text-soft);
}

.tasks-row-assignee {
  font-weight: 500;
  color: var(--text);
}

.tasks-row-due {
  color: var(--text-soft);
  font-size: 11px;
}

.tasks-row-tag {
  padding: 1px 8px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 11px;
  color: var(--text-soft);
}

.tasks-row-counter {
  font-size: 11px;
  color: var(--text-soft);
  padding: 1px 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.tasks-row-counter-attach::before {
  content: "ATT ";
  font-weight: 700;
  font-size: 9px;
  letter-spacing: 0.04em;
  margin-right: 2px;
}

.tasks-row-counter-thread::before {
  content: "CMT ";
  font-weight: 700;
  font-size: 9px;
  letter-spacing: 0.04em;
  margin-right: 2px;
}

/* v0.6.4: row tinting removed. Rows stay on var(--surface); the colored
   status pill carries all the state signal. Tinted rows compounded the visual
   noise with the pills and made the list feel "overwhelming" (Jovana). */

.tasks-empty-filtered {
  padding: 24px;
  text-align: center;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: 8px;
  color: var(--text-soft);
  margin-top: 10px;
}

.tasks-empty-filtered.is-hidden {
  display: none;
}

@media (max-width: 720px) {
  .tasks-row-meta {
    width: 100%;
  }
  .tasks-row-select {
    padding: 0 8px;
  }
}

/* v0.7.0 view-mode toggle (List | Kanban segmented control) ----------------
   Two-option segmented control rendered as <a> tags so SSR view state is
   bookmarkable + linkable (no JS swap; the URL controls the rendered view).
   Calm aesthetic: neutral surface for inactive, var(--accent-soft) for active. */
.tasks-view-switch {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface);
  margin-right: auto;
}
.tasks-view-switch .view-option {
  display: inline-block;
  padding: 6px 14px;
  font-size: 13px;
  color: var(--text-soft);
  text-decoration: none;
  border-right: 1px solid var(--border);
  background: var(--surface);
  transition: background 0.12s ease, color 0.12s ease;
}
.tasks-view-switch .view-option:last-child {
  border-right: none;
}
.tasks-view-switch .view-option:hover {
  background: var(--accent-soft);
  color: var(--text);
}
.tasks-view-switch .view-option.is-active {
  background: var(--accent-soft);
  color: var(--text);
  font-weight: 600;
}

/* v0.7.0 kanban view (6-column status board on /tasks/* surfaces) ----------
   Horizontal flex of 6 columns. Each column is fixed width (300px) and
   scrolls horizontally on narrow viewports. Each card uses the same calm
   aesthetic as the list view: neutral surface + colored border-left edge
   tied to status (so cards in the same column visually echo their column's
   header dot). */
.tasks-kanban {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  padding-bottom: 12px;
  align-items: flex-start;
}
.kanban-column {
  flex: 0 0 300px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 280px);
  min-height: 200px;
}
.kanban-column-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  border-radius: 10px 10px 0 0;
  position: sticky;
  top: 0;
  z-index: 1;
}
.kanban-column-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--text-soft);
  flex: 0 0 9px;
}
/* v0.8.1 calm-by-default: kanban column header dots are neutral by default;
   only blocked gets the muted calm-urgent accent so operators can scan for
   the one status that needs attention without a rainbow competing for it. */
.kanban-dot-open        { background: var(--text-soft); }
.kanban-dot-in_progress { background: var(--text-soft); }
.kanban-dot-on_hold     { background: var(--text-soft); }
.kanban-dot-blocked     { background: var(--calm-urgent-accent); }
.kanban-dot-review      { background: var(--text-soft); }
.kanban-dot-done        { background: var(--text-soft); }
.kanban-column-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: 0.01em;
  flex: 1 1 auto;
}
.kanban-column-count {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-soft);
  background: var(--bg);
  padding: 2px 8px;
  border-radius: 10px;
  border: 1px solid var(--border);
  min-width: 22px;
  text-align: center;
}
.kanban-cards {
  list-style: none;
  margin: 0;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
  flex: 1 1 auto;
}
.kanban-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: 8px;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.kanban-card:hover {
  border-color: var(--accent);
  box-shadow: 0 2px 6px rgba(0,0,0,0.04);
}
/* v0.8.1 calm-by-default: kanban card status left borders are neutral for
   all non-attention states. Only blocked gets calm-urgent-accent. Done keeps
   its subtle opacity fade so the eye deprioritises finished work. */
.kanban-card.status-card-open        { border-left-color: var(--border-strong); }
.kanban-card.status-card-in_progress { border-left-color: var(--border-strong); }
.kanban-card.status-card-on_hold     { border-left-color: var(--border-strong); }
.kanban-card.status-card-blocked     { border-left-color: var(--calm-urgent-accent); }
.kanban-card.status-card-review      { border-left-color: var(--border-strong); }
.kanban-card.status-card-done        { border-left-color: var(--border-strong); opacity: var(--calm-done-opacity); }
.kanban-card.is-mock {
  border-style: dashed;
}
.kanban-card.is-filtered-out {
  display: none;
}
.kanban-card-head {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
/* v0.8.1 calm-by-default: kanban card board tag drops the board-color tint.
   Uniform neutral chip on every card so multi-board cross-project views look
   coherent instead of confetti. The --board-color inline attribute is left
   in the template (harmless dead attribute) so a future opt-in can restore
   it with a single variable reference change. */
.kanban-card-board {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-soft);
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: transparent;
}
.kanban-card-title {
  margin: 0;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  line-height: 1.35;
}
.kanban-card-title-link {
  color: var(--text);
  text-decoration: none;
}
.kanban-card-title-link:hover {
  color: var(--accent);
  text-decoration: underline;
}
.kanban-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--text-soft);
}
.kanban-card-assignee::before {
  content: "@";
  color: var(--text-soft);
  margin-right: 1px;
}
.kanban-card-due::before {
  content: "due ";
  color: var(--text-soft);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-right: 2px;
}
.kanban-card-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  color: var(--text-soft);
}
.kanban-card-tag {
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text-soft);
  font-size: 10px;
  letter-spacing: 0.02em;
}
.kanban-card-counter {
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text-soft);
  font-size: 10px;
}
.kanban-column-empty {
  padding: 18px 12px;
  font-size: 12px;
  color: var(--text-soft);
  text-align: center;
  font-style: italic;
  border-top: 1px dashed var(--border);
}

/* In kanban mode the status filter chip row is redundant (the columns ARE
   the status filter); hide it via the toolbar's data-view-mode attribute so
   we do not need a JS branch. Priority chips + search + sort still apply.
   The data-filter-axis attribute on the filter row makes this selector robust
   to row reordering in the template. */
.tasks-toolbar[data-view-mode="kanban"] .tasks-filter-row[data-filter-axis="status"] {
  display: none;
}
/* In kanban mode the bulk-actions bar is also hidden because the kanban cards
   don't carry per-row checkboxes (bulk-select is a list-mode affordance only). */
.tasks-toolbar[data-view-mode="kanban"] ~ .tasks-bulk-bar {
  display: none !important;
}

@media (max-width: 900px) {
  .tasks-kanban {
    padding-bottom: 18px;
  }
  .kanban-column {
    flex: 0 0 280px;
  }
}

/* v0.8.0: board detail List | Kanban view toggle + flat list rendering.
   The segmented control mirrors .tasks-view-switch so both toggles read as
   one chrome family. The .board-list is a flat card list with a column
   badge on each row so the operator can still see the kanban column each
   card belongs to. Kanban view remains the default and preserves all the
   existing v0.4.0 drag-drop + card-detail-modal behavior unchanged. */
.board-view-switch {
  display: inline-flex;
  gap: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  margin: 0 0 16px 0;
  background: var(--surface);
  font-size: 13px;
}
.board-view-switch .view-option {
  padding: 6px 14px;
  text-decoration: none;
  color: var(--text-soft);
  border-right: 1px solid var(--border);
  transition: background 120ms, color 120ms;
  line-height: 1.4;
}
.board-view-switch .view-option:last-child {
  border-right: none;
}
.board-view-switch .view-option:hover {
  background: var(--surface-2);
  color: var(--text);
}
.board-view-switch .view-option.is-active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

/* Board list mode: a single flat ul of cards, each row carrying its column
   as a small pill badge. Rows still open the card-detail modal on click,
   handled by the v0.8.0 addition to kanban.js. */
.board-list {
  padding: 0 0 24px 0;
}
.board-list-cards {
  list-style: none;
  padding: 0;
  margin: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface);
}
.board-list-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 120ms;
}
.board-list-row:last-child {
  border-bottom: none;
}
.board-list-row:hover {
  background: var(--surface-2);
}
.board-list-row-main {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1 1 auto;
  min-width: 0;
}
.board-list-row-column {
  flex: 0 0 auto;
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--surface-2);
  color: var(--text-soft);
  border: 1px solid var(--border);
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
.board-list-row-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: 14px;
}
.board-list-row-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--text-soft);
}
.board-list-row-assignee,
.board-list-row-due {
  white-space: nowrap;
}
.board-list-row-priority {
  font-size: 11px;
}
.board-list-empty {
  text-align: center;
  color: var(--text-soft);
  padding: 40px 20px;
  font-style: italic;
}
/* v0.8.1 calm-by-default: only urgent gets a visible edge, and it uses the
   muted calm-urgent-accent instead of the loud --danger red. High/low/normal
   are all transparent so the eye is drawn to the one row that needs it. */
.board-list-row.priority-urgent {
  border-left: 3px solid var(--calm-urgent-accent);
}
.board-list-row.priority-high,
.board-list-row.priority-low,
.board-list-row.priority-normal {
  border-left: 3px solid transparent;
}

@media (max-width: 700px) {
  .board-list-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }
  .board-list-row-meta {
    align-self: flex-end;
  }
}

/* ==========================================================================
   v0.9.0 DESIGN LAYER - typography scale, dense board layout, collapsible nav
   Driven by Jovana's Planka-reference brief (2026-08-05): minimalism, density
   management, high-contrast functionality, legible at small scale for
   metadata-heavy boards.

   Appended as a cascade layer on purpose. app.css carries two competing
   .kanban-column definitions (L813 board view, L2149 tasks view) and the later
   one silently wins; rewriting them in place risks regressing whichever surface
   was relying on the accident. Everything below is last-in-file so it resolves
   both surfaces to one predictable result.
   ========================================================================== */

:root {
  /* Type stack. Inter when the OS or a future self-hosted @font-face provides
     it, otherwise the platform UI face. No Google Fonts request: the app serves
     German clients and an external font fetch is a GDPR question we do not need
     to open for a typeface the OS already ships an equivalent of. */
  --font-ui: "Inter", "Inter var", system-ui, -apple-system, BlinkMacSystemFont,
             "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* Type scale. Five steps, deliberately few. Each has ONE job so a glance can
     resolve hierarchy without reading. */
  --fs-page:    20px;   /* board / page H1                        */
  --fs-section: 15px;   /* section + board tile titles            */
  --fs-column:  12px;   /* kanban column header                   */
  --fs-card:    13px;   /* card title - the reading size          */
  --fs-meta:    11px;   /* dates, labels, assignees, counters      */
  --fs-micro:   10px;   /* badges, tag chips, uppercase microcopy */

  --fw-bold:    700;
  --fw-semi:    600;
  --fw-med:     500;
  --fw-reg:     400;

  --lh-tight:   1.3;    /* titles: compact, still readable        */
  --lh-meta:    1.25;   /* single-line metadata                   */

  /* Density tokens. Change these two to retune the whole board. */
  --kanban-col-w:   304px;
  --kanban-gap:     12px;
  --card-pad-y:     9px;
  --card-pad-x:     11px;

  --sidebar-w:      280px;
  --sidebar-w-collapsed: 52px;
}

html, body {
  font-family: var(--font-ui);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Metadata is where small-scale legibility is actually won: lining tabular
   figures so due dates and counters align down a column instead of jittering. */
.kanban-card-meta,
.kanban-card-due,
.kanban-column-count,
.kanban-card-count,
.panel-item-count,
.tasks-row-due,
.board-list-row-due,
.board-list-row-meta {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* --- Hierarchy: headers bold, card titles medium, meta light + muted ------ */

.board-header-body h1,
.page-tasks .main > h1,
.home-header h1 {
  font-size: var(--fs-page);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: -0.011em;   /* optical correction: large text needs less */
}

.kanban-column-head h2,
.kanban-column-title {
  font-size: var(--fs-column);
  font-weight: var(--fw-bold);
  line-height: var(--lh-meta);
  text-transform: uppercase;
  letter-spacing: 0.055em;    /* uppercase needs more, or it sets tight */
  color: var(--text-soft);
}

.kanban-card-title {
  font-size: var(--fs-card);
  font-weight: var(--fw-med);
  line-height: var(--lh-tight);
  letter-spacing: 0;
  color: var(--text);
}

.kanban-card-desc {
  font-size: var(--fs-meta);
  font-weight: var(--fw-reg);
  line-height: 1.4;
  color: var(--text-soft);
}

.kanban-card-meta {
  font-size: var(--fs-meta);
  font-weight: var(--fw-reg);
  line-height: var(--lh-meta);
  color: var(--text-soft);
}

.kanban-card-priority,
.panel-section-head,
.kanban-card-board {
  font-size: var(--fs-micro);
  font-weight: var(--fw-semi);
  letter-spacing: 0.05em;
}

/* Counters read as quiet numerals, not as buttons. */
.kanban-column-count,
.kanban-card-count {
  font-size: var(--fs-meta);
  font-weight: var(--fw-med);
  color: var(--text-soft);
  background: var(--surface-2);
  border: 0;
  padding: 1px 7px;
  border-radius: 999px;
  min-width: 20px;
  text-align: center;
}

/* --- Horizontal board flow ------------------------------------------------
   One rule set for BOTH surfaces (.kanban on /boards/{slug}, .tasks-kanban on
   /tasks/*). Fixed-width columns, board scrolls X, each column scrolls Y. */

.kanban,
.tasks-kanban {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  gap: var(--kanban-gap);
  align-items: flex-start;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 10px;
  /* Bleed to the viewport edge so the scroll runway is the full screen, then
     re-inset the content. Without this the 24px .main padding clips the last
     column mid-card and the board looks broken rather than scrollable. */
  margin-inline: calc(var(--main-pad-x, 24px) * -1);
  padding-inline: var(--main-pad-x, 24px);
  scroll-padding-left: var(--main-pad-x, 24px);
  scrollbar-width: thin;
  overscroll-behavior-x: contain;
}

.kanban > *,
.tasks-kanban > * { scroll-snap-align: start; }

.kanban-column {
  flex: 0 0 var(--kanban-col-w);
  width: var(--kanban-col-w);
  max-width: var(--kanban-col-w);
  display: flex;
  flex-direction: column;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  min-height: 120px;
  max-height: calc(100vh - 210px);
  overflow: hidden;   /* keeps the sticky header inside the rounded corner */
}

.kanban-column-head,
.kanban-column-header {
  flex: 0 0 auto;
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  padding: 9px 11px;
  border-radius: 10px 10px 0 0;
}

/* The vertical scroller. This is the element that makes a 200-card column
   usable while the board itself still scrolls sideways. */
.kanban-cards {
  flex: 1 1 auto;
  min-height: 40px;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 8px;
  gap: 7px;
  scrollbar-width: thin;
  overscroll-behavior-y: contain;
}

/* --- Card density --------------------------------------------------------
   Card is a flex column. Title and description sit at the top; the meta row is
   pushed to the bottom edge by margin-top:auto, so cards of different heights
   in the same column still line their metadata up along the bottom. */

.kanban-card {
  display: flex;
  flex-direction: column;
  padding: var(--card-pad-y) var(--card-pad-x);
  border-radius: 7px;
  background: var(--surface);
  min-height: 56px;
  gap: 3px;
  /* A card is a flex item in a column that scrolls. Flex items default to
     flex-shrink:1, so once a column holds more cards than fit, the browser
     shrinks each card's BOX below its content height while the content itself
     keeps its size - the text then paints outside the white background and the
     next card overlaps it. Observed on /tasks/all, OFFEN column, 10 cards
     (screenshot 2026-08-05). flex-shrink:0 is the fix: cards keep their content
     height and the column scrolls instead. */
  flex-shrink: 0;
}

.kanban-card-desc { margin-top: 2px; }

.kanban-card-meta {
  margin-top: auto;          /* pin to the bottom row */
  padding-top: 7px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  flex-wrap: nowrap;
  width: 100%;
}

/* Left cluster keeps assignee + due together; priority is pushed right by
   space-between. Truncate rather than wrap: a card must not grow because one
   assignee has a long name. */
.kanban-card-assignee,
.kanban-card-due {
  background: transparent;
  border: 0;
  padding: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.kanban-card-assignee { flex: 0 1 auto; }
.kanban-card-due      { flex: 0 0 auto; margin-left: 6px; }

.kanban-card-priority {
  flex: 0 0 auto;
  margin-left: auto;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 7px;
}

/* Nothing inside a card ever touches the border. */
.kanban-card > * { min-width: 0; }

/* --- Collapsible sidebar -------------------------------------------------- */

.side-panel {
  flex: 0 0 var(--sidebar-w);
  width: var(--sidebar-w);
  transition: flex-basis 0.16s ease, width 0.16s ease, padding 0.16s ease;
  position: relative;
}

.side-panel-toggle {
  position: absolute;
  top: 10px;
  right: 8px;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-soft);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 0;
  z-index: 3;
}

.side-panel-toggle:hover {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}

.side-panel-toggle-icon { transition: transform 0.16s ease; display: block; }

/* Collapsed: the rail keeps only the toggle. Content is hidden with
   visibility so it stays out of the tab order and off the screen reader. */
.app-shell.is-panel-collapsed .side-panel {
  flex-basis: var(--sidebar-w-collapsed);
  width: var(--sidebar-w-collapsed);
  padding-left: 8px;
  padding-right: 8px;
  overflow: hidden;
}

.app-shell.is-panel-collapsed .side-panel > *:not(.side-panel-toggle) {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.app-shell.is-panel-collapsed .side-panel-toggle {
  right: 50%;
  transform: translateX(50%);
}

.app-shell.is-panel-collapsed .side-panel-toggle-icon {
  transform: rotate(180deg);
}

/* No transition before JS has restored the stored state, so a collapsed
   sidebar does not visibly swing shut on every page load. */
.app-shell:not(.is-panel-ready) .side-panel,
.app-shell:not(.is-panel-ready) .side-panel-toggle-icon { transition: none; }

/* --- Narrow viewports ----------------------------------------------------- */

@media (max-width: 900px) {
  .side-panel-toggle { display: none; }
  .kanban-column { max-height: calc(100vh - 170px); }
}

@media (prefers-reduced-motion: reduce) {
  .side-panel,
  .side-panel-toggle-icon { transition: none; }
}

/* ==========================================================================
   v0.10.0 - comment threads + real feed pages
   Appended as a trailing block for the same reason the v0.9.0 layer was: the
   file above stays untouched, so reverting this release is a truncation rather
   than a diff hunt. Every value here reuses the v0.9.0 type/density variables,
   so the Test Lab sliders move this new surface too.
   ========================================================================== */

/* Card modal: comment thread ---------------------------------------------- */

.card-comments {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border, #e3e6ea);
}

.card-comments-heading {
  margin: 0 0 10px;
  font-size: var(--fs-section, 15px);
  font-weight: 600;
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.card-comments-count {
  font-size: var(--fs-meta, 11px);
  font-weight: 400;
  color: var(--text-muted, #6b7280);
  font-variant-numeric: tabular-nums;
}

.card-comments-list {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 320px;
  overflow-y: auto;
}

.card-comment {
  padding: 9px 11px;
  border: 1px solid var(--border, #e3e6ea);
  border-radius: 6px;
  background: var(--surface-2, #fafbfc);
}

.card-comment.is-deleted {
  opacity: 0.55;
  font-style: italic;
}

.card-comment-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 4px;
}

.card-comment-author {
  font-size: var(--fs-card, 13px);
  font-weight: 500;
}

.card-comment-time,
.card-comment-edited {
  font-size: var(--fs-micro, 10px);
  color: var(--text-muted, #6b7280);
  font-variant-numeric: tabular-nums;
}

.card-comment-delete {
  margin-left: auto;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  color: var(--text-muted, #6b7280);
  padding: 0 2px;
}

.card-comment-delete:hover { color: var(--danger, #d6342c); }

.card-comment-body {
  font-size: var(--fs-card, 13px);
  line-height: var(--lh-body, 1.45);
  white-space: pre-wrap;
  word-break: break-word;
}

.card-comments-empty {
  margin: 0 0 12px;
  font-size: var(--fs-meta, 11px);
  color: var(--text-muted, #6b7280);
}

.card-comment-compose textarea {
  width: 100%;
  box-sizing: border-box;
  font: inherit;
  font-size: var(--fs-card, 13px);
  padding: 8px 10px;
  border: 1px solid var(--border, #e3e6ea);
  border-radius: 6px;
  resize: vertical;
}

.card-comment-compose-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

.card-comment-hint {
  font-size: var(--fs-micro, 10px);
  color: var(--text-muted, #6b7280);
}

.card-comment-status {
  font-size: var(--fs-micro, 10px);
  color: var(--text-muted, #6b7280);
  margin-left: auto;
}

.card-comment-status.is-error,
.feed-row-reply-status.is-error { color: var(--danger, #d6342c); }

/* Feed pages -------------------------------------------------------------- */

.feed-page { max-width: 900px; }

.feed-header { margin-bottom: 14px; }

.feed-header h1 {
  margin: 0 0 4px;
  font-size: var(--fs-page, 20px);
  font-weight: 700;
}

.feed-sub {
  margin: 0;
  font-size: var(--fs-meta, 11px);
  color: var(--text-muted, #6b7280);
}

.feed-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

.feed-filters { display: flex; gap: 6px; }

.feed-filters .chip { text-decoration: none; }

.feed-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.feed-row {
  padding: 10px 12px;
  border: 1px solid var(--border, #e3e6ea);
  border-radius: 7px;
  background: var(--surface, #fff);
}

/* Unread is a left edge, not a background wash: the row stays readable and the
   marker survives whatever the density sliders do to padding. */
.feed-row.is-unread { border-left: 3px solid var(--accent, #0c60ab); }

.feed-row-meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  font-size: var(--fs-meta, 11px);
  color: var(--text-muted, #6b7280);
  margin-bottom: 3px;
}

.feed-row-author {
  font-weight: 500;
  color: var(--text, #1f2328);
}

.feed-row-kind-pill {
  font-size: var(--fs-micro, 10px);
  padding: 1px 6px;
  border-radius: 9px;
  border: 1px solid var(--border, #e3e6ea);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.feed-row-time { margin-left: auto; font-variant-numeric: tabular-nums; }

.feed-row-title {
  font-size: var(--fs-card, 13px);
  font-weight: 500;
  margin-bottom: 2px;
}

.feed-row-body {
  font-size: var(--fs-card, 13px);
  line-height: var(--lh-body, 1.45);
  white-space: pre-wrap;
  word-break: break-word;
  margin-bottom: 6px;
}

.feed-row-actions { display: flex; gap: 6px; flex-wrap: wrap; }

.feed-row-reply { margin-top: 8px; }

.feed-row-reply.is-hidden { display: none; }

.feed-row-reply textarea {
  width: 100%;
  box-sizing: border-box;
  font: inherit;
  font-size: var(--fs-card, 13px);
  padding: 8px 10px;
  border: 1px solid var(--border, #e3e6ea);
  border-radius: 6px;
  resize: vertical;
}

.feed-row-reply-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}

.feed-row-sent-note {
  margin-top: 6px;
  font-size: var(--fs-micro, 10px);
  color: var(--accent, #0c60ab);
}

.feed-empty {
  padding: 24px 0;
  font-size: var(--fs-meta, 11px);
  color: var(--text-muted, #6b7280);
}
