:root {
  --color-primary: #0F766E;
  --color-primary-dark: #0B5A54;
  --color-accent: #14E8D4;
  --color-bg: #F8FAFA;
  --color-surface: #FFFFFF;
  --color-text: #1E293B;
  --color-text-muted: #5B6B7A;
  --color-border: #E2E8E7;
  --color-primary-tint: #E6F7F5;
  --color-primary-tint-hover: #D2EFEB;
  --color-danger: #B91C1C;
  --color-danger-tint: #FDECEC;
  /* Epic accent — same violet pairing as the existing .badge--system /
     .badge--in-house tokens, reused rather than introducing a new hue. */
  --color-epic: #6D28D9;
  --color-epic-tint: #EFE6FB;
  --color-warning: #92400E;
  --color-warning-tint: #FEF3C7;

  --radius-sm: 8px;
  --radius-md: 12px;
  --shadow-card: 0 1px 2px rgba(15, 23, 42, 0.04), 0 4px 12px rgba(15, 23, 42, 0.06);
  --shadow-card-hover: 0 4px 8px rgba(15, 23, 42, 0.06), 0 12px 24px rgba(15, 23, 42, 0.08);
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--color-bg);
  color: var(--color-text);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--color-primary);
  text-decoration: none;
}

h1, h2, h3 {
  font-weight: 700;
  margin: 0 0 0.5em;
  letter-spacing: -0.01em;
}

p {
  margin: 0 0 1em;
  color: var(--color-text-muted);
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0.65em 1.4em;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.05s ease;
}

.btn--primary {
  background: var(--color-primary);
  color: #fff;
}

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

.btn--lg {
  padding: 0.85em 2em;
  font-size: 1.05rem;
}

.btn--sm {
  padding: 0.45em 1em;
  font-size: 0.85rem;
}

.btn--block {
  display: flex;
  width: 100%;
}

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

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

/* Public auth screens (login + root login) */
.public-body {
  min-height: 100vh;
  display: flex;
}

.auth-screen {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem 1.5rem;
}

.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 2.5rem 2rem;
  text-align: center;
}

.auth-card__wordmark {
  height: 38px;
  width: auto;
  margin: 0 auto 1.5rem;
  display: block;
}

.auth-card__title {
  font-size: 1.5rem;
  margin-bottom: 0.5rem;
}

.auth-card__subtitle {
  font-size: 0.95rem;
  margin-bottom: 1.75rem;
}

.auth-card__footnote {
  margin: 1.25rem 0 0;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

.auth-card__error {
  background: var(--color-danger-tint);
  color: var(--color-danger);
  border-radius: var(--radius-sm);
  padding: 0.6em 1em;
  font-size: 0.85rem;
  margin-bottom: 1.25rem;
}

.auth-form {
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.auth-form__label {
  font-size: 0.85rem;
  font-weight: 600;
  margin-top: 0.75rem;
}

.auth-form__input {
  font-family: inherit;
  font-size: 0.95rem;
  padding: 0.6em 0.8em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
}

.auth-form__input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.auth-form .btn {
  margin-top: 1.5rem;
}

/* Authenticated app shell */
.app-body {
  min-height: 100vh;
}

.app-header {
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.app-header__inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0.9rem 1.5rem;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.app-header__brand {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  color: var(--color-text);
}

.app-header__logo-img {
  height: 30px;
  width: auto;
  display: block;
}

.app-header__divider {
  width: 1px;
  height: 22px;
  background: var(--color-border);
  flex-shrink: 0;
}

.app-header__name {
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
}

.app-header__user {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-left: auto;
}

.app-header__avatar {
  width: 32px;
  height: 32px;
  border-radius: 9999px;
  background: var(--color-primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  font-weight: 700;
  flex-shrink: 0;
}

.app-header__email {
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.app-header__logout-form {
  margin: 0;
}

/* Sidebar layout */
.app-layout {
  max-width: 1280px;
  margin: 0 auto;
  display: flex;
  align-items: flex-start;
}

.app-sidebar {
  width: 220px;
  flex-shrink: 0;
  padding: 1.5rem 1rem;
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 65px);
  border-right: 1px solid var(--color-border);
}

.app-sidebar__nav {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.app-sidebar__link {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6em 0.8em;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  font-size: 0.9rem;
  font-weight: 500;
  transition: background 0.15s ease, color 0.15s ease;
}

.app-sidebar__link svg {
  width: 18px;
  height: 18px;
}

.app-sidebar__link:hover {
  background: var(--color-primary-tint);
  color: var(--color-primary);
}

.app-sidebar__link.is-active {
  background: var(--color-primary-tint);
  color: var(--color-primary);
  font-weight: 600;
}

.app-main {
  flex: 1;
  padding: 2.5rem 2rem 4rem;
  min-width: 0;
}

.page-title {
  font-size: 1.5rem;
}

/* Empty states (no-access, coming-soon) */
.empty-state {
  max-width: 460px;
  margin: 3rem auto 0;
  text-align: center;
  padding: 2.5rem 2rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}

.empty-state__icon {
  width: 52px;
  height: 52px;
  margin: 0 auto 1.25rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: var(--color-primary-tint);
  color: var(--color-primary);
}

.empty-state__icon svg {
  width: 24px;
  height: 24px;
}

.empty-state__title {
  font-size: 1.15rem;
  margin-bottom: 0.5rem;
}

.empty-state__message {
  font-size: 0.9rem;
  margin: 0;
}

/* Buttons: outline variant (Sync now) */
.btn--outline {
  background: transparent;
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.btn--outline:hover {
  background: var(--color-primary-tint);
}

.btn--outline:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Users page */
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}

.page-subtitle {
  font-size: 0.9rem;
  margin: 0;
}

.banner {
  border-radius: var(--radius-sm);
  padding: 0.75em 1em;
  font-size: 0.85rem;
  margin-bottom: 1.25rem;
  display: flex;
  align-items: center;
}

/* Same fix as .modal-overlay[hidden]: display:flex above otherwise beats
   the browser's default [hidden] rule, so an empty/no-error banner with
   the `hidden` attribute would still render as a visible empty bar. */
.banner[hidden] {
  display: none;
}

.banner--error {
  background: var(--color-danger-tint);
  color: var(--color-danger);
}

/* Shared list-page toolbar (search + optional filter/checkbox) — used by
   every list page (Users, Clients, Projects, and any future one). There
   must be exactly one definition of this so a new page can never end up
   with a differently-named, possibly-divergent copy. */
.list-toolbar {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}

.list-toolbar__search {
  font-family: inherit;
  font-size: 0.9rem;
  padding: 0.55em 0.9em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  min-width: 260px;
  color: var(--color-text);
}

.list-toolbar__search:focus {
  outline: none;
  border-color: var(--color-primary);
}

.list-toolbar__select {
  font-family: inherit;
  font-size: 0.85rem;
  padding: 0.5em 0.75em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  background: var(--color-surface);
  min-width: 140px;
}

.list-toolbar__select:focus {
  outline: none;
  border-color: var(--color-primary);
}

/* Epic titles run longer than a phase/sprint name — a touch more room so
   the closed select doesn't truncate mid-word (Fix 3). */
.list-toolbar__select--wide {
  min-width: 190px;
  max-width: 220px;
}

.list-toolbar__filters {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.list-toolbar__checkbox {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-size: 0.9rem;
  color: var(--color-text-muted);
  cursor: pointer;
}

.table-wrapper {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  overflow-x: auto;
}

/* The Tasks tab's outline tree needs horizontal scroll as its fallback
   for a fixed-width row (Phase/Sprint/etc. columns) that doesn't fit the
   viewport — see .outline-row below. overflow-x: auto here is deliberate,
   unlike most .table-wrapper usages. */
.table-wrapper.outline-tree {
  overflow-x: auto;
}

/* Shared list-page table — the single source of styling for every data
   table in the app (header row, borders, row separators, hover state).
   A page-specific class (.users-table etc.) must never be reintroduced
   for this: reuse .data-table directly so every table is provably
   identical, not just visually similar. */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.data-table th {
  text-align: left;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  padding: 0.9em 1.25em;
  border-bottom: 1px solid var(--color-border);
}

/* Click-to-sort headers (public/js/tableSort.js) — flat list tables only,
   never the Tasks tree. */
.data-table th.is-sortable {
  cursor: pointer;
  user-select: none;
}

.data-table th.is-sortable:hover {
  color: var(--color-primary);
}

.data-table th.is-sorted-asc,
.data-table th.is-sorted-desc {
  color: var(--color-primary);
}

.sort-arrow {
  display: inline-block;
  margin-left: 0.4em;
  font-size: 0.7em;
}

.data-table td {
  padding: 0.85em 1.25em;
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}

.data-table__row:last-child td {
  border-bottom: none;
}

.data-table__row.is-clickable {
  cursor: pointer;
}

.data-table__row.is-clickable:hover td {
  background: var(--color-primary-tint);
}

.data-table__row.is-root {
  background: #F5F0FC;
}

.data-table__row.is-inactive,
.data-table__row.is-offboarded {
  opacity: 0.55;
}

/* Plain bold label (e.g. inside a name-link) */
.data-table__name {
  font-weight: 600;
}

/* Avatar + name side by side, applied directly to a <td> (Users page) */
.data-table__name-row {
  display: flex;
  align-items: center;
  gap: 0.7em;
  font-weight: 600;
  white-space: nowrap;
}

/* Anchor wrapping a name + secondary badge/chip. Side-by-side by default
   (Clients); .is-stacked switches to name-above-chip (Projects). */
.data-table__name-link {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  color: var(--color-text);
}

.data-table__name-link.is-stacked {
  display: block;
}

.data-table__secondary {
  display: block;
  margin-top: 0.15em;
}

.data-table__chevron-col {
  width: 40px;
  text-align: center;
}

.data-table__chevron {
  display: inline-flex;
  color: var(--color-text-muted);
}

.data-table__chevron svg {
  width: 18px;
  height: 18px;
}

.data-table__actions-col {
  width: 56px;
  text-align: center;
}

.data-table__empty {
  text-align: center;
  padding: 2.5em 1em;
  color: var(--color-text-muted);
}

.avatar-initials {
  width: 30px;
  height: 30px;
  border-radius: 9999px;
  background: var(--color-primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.72rem;
  font-weight: 700;
  flex-shrink: 0;
}

/* Badges */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.25em 0.7em;
  border-radius: 9999px;
  font-size: 0.78rem;
  font-weight: 600;
}

.badge--active {
  background: #E7F7EE;
  color: #15803D;
}

.badge--inactive {
  background: #EEF1F3;
  color: #5B6B7A;
}

.badge--system {
  background: #EFE6FB;
  color: #6D28D9;
}

/* Role cell */
.role-select {
  font-family: inherit;
  font-size: 0.87rem;
  padding: 0.4em 0.6em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  background: var(--color-surface);
}

.role-select:focus {
  outline: none;
  border-color: var(--color-primary);
}

.role-select:disabled {
  opacity: 0.6;
}

.role-static {
  color: var(--color-text-muted);
  font-size: 0.87rem;
}

.lock-icon {
  display: inline-flex;
  color: var(--color-text-muted);
}

.lock-icon svg {
  width: 16px;
  height: 16px;
}

/* Row "..." menu */
.row-menu {
  position: relative;
  display: inline-block;
}

.row-menu__trigger {
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  padding: 0.35em;
  border-radius: var(--radius-sm);
  display: inline-flex;
}

.row-menu__trigger:hover {
  background: var(--color-primary-tint);
  color: var(--color-primary);
}

.row-menu__trigger svg {
  width: 18px;
  height: 18px;
}

.row-menu__dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card-hover);
  min-width: 170px;
  z-index: 20;
  overflow: hidden;
}

.row-menu__dropdown.is-open {
  display: block;
}

/* Users page's row menu carries a longer item ("Mark as Service/Excluded
   Account") than the default 170px comfortably fits without wrapping to
   3 lines — scoped to this one dropdown rather than widening every
   .row-menu__dropdown in the app. */
.row-menu__dropdown--wide {
  min-width: 240px;
}

.row-menu__item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  padding: 0.65em 1em;
  font-family: inherit;
  font-size: 0.85rem;
  color: var(--color-text);
  cursor: pointer;
}

.row-menu__item:hover {
  background: var(--color-primary-tint);
  color: var(--color-primary);
}

/* Modals — z-index 71 deliberately sits above .drawer (61) and
   .drawer-backdrop (60): the people-picker modal (Owners/Collaborators
   "+ Add") opens *from inside* an already-open drawer, and at the old
   z-index 50 it rendered visually behind the drawer's own backdrop —
   every click meant for the modal actually landed on the backdrop
   instead, which closed the drawer instead of picking anyone. */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 71;
  padding: 1.5rem;
}

/* The class above sets display:flex unconditionally, which otherwise beats
   the browser's default `[hidden] { display: none }` rule (author styles
   always win over the user-agent stylesheet) — without this, the modal
   renders open regardless of the `hidden` attribute. */
.modal-overlay[hidden] {
  display: none;
}

.modal {
  width: 100%;
  max-width: 420px;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card-hover);
  padding: 1.75rem;
}

/* Notification target modal: name + URL + scope radios + a searchable
   project checklist need more breathing room than the default 420px
   modals (confirm dialogs, single-field pickers) elsewhere in the app. */
.modal--wide {
  max-width: 560px;
}

.modal h3 {
  font-size: 1.1rem;
  margin-bottom: 0.75rem;
}

.modal__body {
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

.assignments-list {
  margin: 0;
  padding-left: 1.1rem;
  color: var(--color-text);
  font-size: 0.9rem;
}

.modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.row-menu__item--danger {
  color: var(--color-danger);
}

.row-menu__item--danger:hover {
  background: var(--color-danger-tint);
  color: var(--color-danger);
}

/* Muted banner (e.g. offboarded notice) — same shape as .banner--error but
   neutral, not a warning. */
.banner--muted {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
}

/* Small monospace chip, used for Client ID everywhere it appears */
.chip {
  display: inline-flex;
  align-items: center;
  padding: 0.2em 0.6em;
  border-radius: 6px;
  background: var(--color-primary-tint);
  color: var(--color-primary);
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
}

.badge--in-house {
  background: #EFE6FB;
  color: #6D28D9;
}

/* Generic form styles — used by the client create/edit form and reusable
   by any future module's forms */
.form-card {
  max-width: 640px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 2rem;
}

.form-group {
  margin-bottom: 1.25rem;
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
}

.form-label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  margin-bottom: 0.4em;
}

.form-input,
.form-textarea,
.form-select {
  width: 100%;
  font-family: inherit;
  font-size: 0.9rem;
  padding: 0.6em 0.8em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  background: var(--color-surface);
}

.form-textarea {
  resize: vertical;
  min-height: 5em;
}

.form-input:focus,
.form-textarea:focus,
.form-select:focus {
  outline: none;
  border-color: var(--color-primary);
}

.form-input[readonly] {
  background: var(--color-bg);
  color: var(--color-text-muted);
}

.form-input.has-error,
.form-select.has-error {
  border-color: var(--color-danger);
}

/* Wrong-answer feedback for the delete-challenge inputs (see
   public/js/deleteChallenge.js) — a brief shake instead of a popup. */
@keyframes shake-input {
  10%, 90% { transform: translateX(-1px); }
  20%, 80% { transform: translateX(2px); }
  30%, 50%, 70% { transform: translateX(-4px); }
  40%, 60% { transform: translateX(4px); }
}
.shake-input {
  animation: shake-input 0.4s ease;
  border-color: var(--color-danger);
}
@media (prefers-reduced-motion: reduce) {
  .shake-input {
    animation: none;
  }
}

.form-hint {
  margin: 0.4em 0 0;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

.form-error {
  margin: 0.4em 0 0;
  font-size: 0.8rem;
  color: var(--color-danger);
}

/* Same shape as .form-error, matching the app's existing done/success
   green (see .badge--done) rather than introducing a new color token. */
.form-success {
  margin: 0.4em 0 0;
  font-size: 0.8rem;
  color: #15803D;
}

/* Informational callout — deliberately NOT styled like .banner--error
   (no red, no alarm framing): tinted with the app's own primary teal so
   it reads as "here's a tip" rather than "something's wrong". */
.info-callout {
  display: flex;
  align-items: flex-start;
  gap: 0.6em;
  margin: 0 0 1.25em;
  padding: 0.75em 1em;
  background: var(--color-primary-tint);
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  color: var(--color-text);
}

.info-callout svg {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin-top: 0.1em;
  color: var(--color-primary);
}

.form-checkbox {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-top: 1.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--color-border);
}

/* Client detail page */
.client-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}

.client-header__main {
  flex: 1;
  min-width: 0;
}

.client-header__meta {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}

.client-header__meta-item {
  font-size: 0.88rem;
  color: var(--color-text-muted);
}

.client-header__actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.detail-section {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 1.5rem 1.75rem;
  margin-bottom: 1.5rem;
}

.detail-section__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.detail-section__title {
  font-size: 1.05rem;
  margin: 0;
}

/* Same treatment as .project-header__meta-item's "Client: X" label —
   a small muted line, not an inline dash-joined suffix on the title. */
.detail-section__title-meta {
  font-size: 0.88rem;
  color: var(--color-text-muted);
  margin: 0.25rem 0 0;
}

.detail-section__body {
  margin: 1rem 0 0;
  white-space: pre-wrap;
}

.detail-section__note {
  font-size: 0.82rem;
  color: var(--color-text-muted);
  margin: 0.35rem 0 1.25rem;
}

.empty-state--inline {
  margin: 0;
  box-shadow: none;
  border-style: dashed;
}

.project-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.project-row {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.project-row__header {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75em 1em;
  background: var(--color-surface);
  border: none;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  text-align: left;
  color: var(--color-text);
}

.project-row__header svg {
  width: 18px;
  height: 18px;
  color: var(--color-text-muted);
  transition: transform 0.15s ease;
}

.project-row.is-open .project-row__header svg {
  transform: rotate(90deg);
}

.project-row__team {
  display: none;
  padding: 0 1em 0.75em;
}

.project-row.is-open .project-row__team {
  display: block;
}

.project-row__member {
  display: flex;
  justify-content: space-between;
  padding: 0.5em 0;
  font-size: 0.85rem;
  color: var(--color-text-muted);
  border-top: 1px solid var(--color-border);
}

/* Amber badge (Lite template) — teal already exists for Full via
   .badge--active, reused directly rather than adding a duplicate. */
.badge--lite {
  background: #FEF3C7;
  color: #92400E;
}

.badge--full {
  background: var(--color-primary-tint);
  color: var(--color-primary);
}

/* Mini progress bar */
.progress-cell {
  display: flex;
  align-items: center;
  gap: 0.6em;
}

.progress-bar {
  width: 80px;
  height: 6px;
  border-radius: 999px;
  background: var(--color-border);
  overflow: hidden;
  flex-shrink: 0;
}

.progress-bar__fill {
  height: 100%;
  background: var(--color-primary);
  border-radius: 999px;
}

.progress-text {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* Template picker (New project form) */
.template-picker {
  display: flex;
  gap: 1rem;
  margin-bottom: 1.75rem;
}

.template-card {
  position: relative;
  flex: 1;
  display: block;
  border: 2px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 1.25rem;
  cursor: pointer;
  background: var(--color-surface);
  transition: border-color 0.15s ease, background 0.15s ease;
}

.template-card:hover {
  border-color: var(--color-primary);
}

.template-card__radio {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.template-card__check {
  position: absolute;
  top: 1rem;
  right: 1rem;
  display: none;
  color: var(--color-primary);
}

.template-card__check svg {
  width: 20px;
  height: 20px;
}

/* :has() covers browsers without JS; .is-selected (toggled by
   public/js/project-form.js) makes the same state change independently
   verifiable and doesn't rely on :has() alone. */
.template-card:has(.template-card__radio:checked),
.template-card.is-selected {
  border-color: var(--color-primary);
  background: var(--color-primary-tint);
}

.template-card:has(.template-card__radio:checked) .template-card__check,
.template-card.is-selected .template-card__check {
  display: block;
}

.template-card__title {
  font-weight: 700;
  font-size: 1rem;
  margin-bottom: 0.4rem;
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.template-card__desc {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: 0.75rem;
}

.template-card__hierarchy {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
}

.template-card__suitable {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  font-style: italic;
  margin-top: 0.5rem;
}

.template-card__locked-note {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  margin: -1rem 0 1.75rem;
}

/* Project detail header — same shape as .client-header */
.project-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}

.project-header__main {
  flex: 1;
  min-width: 0;
}

.project-header__meta {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}

.project-header__meta-item {
  font-size: 0.88rem;
  color: var(--color-text-muted);
}

.project-header__actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

/* Tabs */
.tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
}

.tabs__link {
  padding: 0.75em 1em;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.tabs__link:hover {
  color: var(--color-primary);
}

.tabs__link.is-active {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
}

.detail-section__actions {
  margin: 1rem 0;
}

/* Contributors panel */
.contributor-list {
  display: flex;
  flex-direction: column;
}

.contributor-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.65em 0;
  border-top: 1px solid var(--color-border);
}

.contributor-row:first-child {
  border-top: none;
}

.contributor-row__info {
  display: flex;
  align-items: center;
  gap: 0.75em;
}

.contributor-row__name {
  font-weight: 600;
  font-size: 0.9rem;
}

.contributor-row__role {
  font-size: 0.78rem;
  color: var(--color-text-muted);
}

.contributor-row__remove {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 0.35em;
  border-radius: var(--radius-sm);
  display: inline-flex;
}

.contributor-row__remove svg {
  width: 16px;
  height: 16px;
}

.contributor-row__remove:hover {
  background: var(--color-danger-tint);
  color: var(--color-danger);
}

/* Notifications settings: target list */
.notification-target-list {
  display: flex;
  flex-direction: column;
}

.notification-target-row {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1em;
  padding: 0.9em 0;
  border-top: 1px solid var(--color-border);
}

.notification-target-row:first-child {
  border-top: none;
}

.notification-target-row__info {
  min-width: 0;
}

.notification-target-row__name {
  font-weight: 600;
  font-size: 0.95rem;
  margin-bottom: 0.35em;
}

.notification-target-row__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5em;
}

.notification-target-row__url {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  background: var(--color-bg);
  padding: 0.15em 0.5em;
  border-radius: var(--radius-sm);
}

.notification-target-row__projects {
  margin: 0.4em 0 0;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

.notification-target-row__actions {
  display: flex;
  align-items: center;
  gap: 0.5em;
  flex-shrink: 0;
}

.notification-target-row .target-test-result,
.notification-target-row .target-row-error {
  flex-basis: 100%;
  margin-top: 0.5em;
}

/* Notifications settings: searchable multi-select project checklist —
   same "search input filters a list" spirit as the app's other
   type-ahead pickers (public/js/timesheets.js), adapted to a checkbox
   list since this one needs multiple selections at once. */
.notification-target-project-list {
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  margin-top: 0.5em;
}

.notification-target-project-list__item {
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.5em 0.75em;
  font-size: 0.85rem;
  cursor: pointer;
  border-bottom: 1px solid var(--color-border);
}

.notification-target-project-list__item:last-child {
  border-bottom: none;
}

.notification-target-project-list__item:hover {
  background: var(--color-bg);
}

.notification-target-project-list__empty {
  margin: 0.5em 0 0;
  font-size: 0.82rem;
  color: var(--color-text-muted);
}

/* Phases panel */
.phase-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.phase-row {
  display: flex;
  align-items: center;
  gap: 0.75em;
  padding: 0.6em 0.75em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.phase-row.is-done {
  background: var(--color-primary-tint);
  border-color: var(--color-primary);
}

.phase-row__order {
  display: flex;
  flex-direction: column;
}

.phase-row__order-btn {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.phase-row__order-btn svg {
  width: 16px;
  height: 16px;
}

.phase-row__order-btn:hover:not(:disabled) {
  color: var(--color-primary);
}

.phase-row__order-btn:disabled {
  opacity: 0.3;
  cursor: default;
}

.phase-row__name {
  flex: 1;
  font-weight: 600;
  font-size: 0.9rem;
}

.phase-row__name-input {
  flex: 1;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  padding: 0.3em 0.5em;
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-sm);
  color: var(--color-text);
}

.phase-row__actions {
  display: flex;
  align-items: center;
  gap: 0.15em;
}

.phase-row__actions .row-menu__trigger svg {
  width: 16px;
  height: 16px;
}

/* Toggle switch (Sprints enabled) */
.toggle-switch {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 22px;
  flex-shrink: 0;
}

.toggle-switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.toggle-switch__slider {
  position: absolute;
  inset: 0;
  cursor: pointer;
  background: var(--color-border);
  border-radius: 999px;
  transition: background 0.15s ease;
}

.toggle-switch__slider::before {
  content: '';
  position: absolute;
  height: 16px;
  width: 16px;
  left: 3px;
  top: 3px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.15s ease;
}

.toggle-switch input:checked + .toggle-switch__slider {
  background: var(--color-primary);
}

.toggle-switch input:checked + .toggle-switch__slider::before {
  transform: translateX(18px);
}

.toggle-switch input:disabled + .toggle-switch__slider {
  opacity: 0.5;
  cursor: default;
}

/* Sprints panel */
.sprint-list {
  display: flex;
  flex-direction: column;
}

.sprint-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.65em 0;
  border-top: 1px solid var(--color-border);
}

.sprint-row:first-child {
  border-top: none;
}

.sprint-row__name {
  font-weight: 600;
  font-size: 0.9rem;
}

.sprint-row__dates {
  font-size: 0.78rem;
  color: var(--color-text-muted);
}

/* Task phase badges — same .badge base as everywhere else. todo/done
   intentionally reuse the exact inactive/active tokens (grey = neutral,
   green = complete); doing is new (no existing analog) but built from the
   same teal-tint pairing as .badge--full. */
.badge--todo {
  background: #EEF1F3;
  color: #5B6B7A;
}

.badge--doing {
  background: var(--color-primary-tint);
  color: var(--color-primary);
}

.badge--done {
  background: #E7F7EE;
  color: #15803D;
}

/* Overlapping avatar-initials stack (owners on a task/card) */
.avatar-stack {
  display: inline-flex;
}

.avatar-stack .avatar-initials {
  border: 2px solid var(--color-surface);
  margin-left: -10px;
}

.avatar-stack .avatar-initials:first-child {
  margin-left: 0;
}

/* Tasks tab — unified outline tree (Milestone → Epic → Task → Subtask on
   Full projects; Task → Subtask on Lite). Row actions live inline on the
   row itself, revealed on hover — see .outline-row__actions — instead of
   stacked buttons below each row. */
.outline-tree {
  padding: 0.5rem 0;
  /* .table-wrapper.outline-tree's overflow-x: auto forces overflow-y to
     compute as auto too (CSS pairs the two axes once either leaves
     "visible"), which would otherwise clip the last row's "..." dropdown
     (.row-menu__dropdown, opens downward past the row) against this
     container's own bottom edge. This reserves exactly enough room below
     the last row for the tallest dropdown (2 items) to render in full
     without being cut off, measured against the real component. */
  padding-bottom: 92px;
}

/* Fixed-width columns sized to the longest REAL Phase/Sprint values in
   use (see the column-width plan worked out with the user), not an
   arbitrary guess — Phase/Sprint must never truncate under normal
   conditions. Title/id/toggle are grouped into one sticky "pinned" unit
   (.outline-row__pinned below) that's the row's only flexible column;
   everything else lines up at the same horizontal position on every row
   regardless of row type or title length. If a row's fixed columns don't
   fit the viewport, the table-wrapper scrolls horizontally (min-width
   below) with the pinned group staying visible — never wrapped text,
   never mid-word truncation on Phase/Sprint. */
.outline-row {
  display: grid;
  grid-template-columns: minmax(240px, 1fr) 130px 120px 150px 64px 116px;
  align-items: center;
  column-gap: 0.65em;
  padding: 0.65em 1.25em;
  border-bottom: 1px solid var(--color-border);
  cursor: pointer;
  min-width: 960px;
}

.outline-row__pinned {
  display: flex;
  align-items: center;
  gap: 0.65em;
  min-width: 0;
  position: sticky;
  left: 0;
  /* Rows carry several different backgrounds (default, milestone/epic
     tint, hover, backlog tint) — inherit so the pinned group always
     matches whatever the row it belongs to is showing, instead of a
     fixed color that would mismatch and look like a seam once scrolled. */
  background: inherit;
}

/* The Progress tab's completion-rollup tree (views/partials/progress-
   node.ejs) reuses .outline-row/.outline-row__meta for its shared chrome
   (indentation, hover, id chip, toggle) but has its own simpler two-part
   row (id/title, then one progress-bar-or-badge cell) — it was never part
   of the Tasks-tab scattered-columns complaint this Grid rework fixes, so
   it keeps the original flex layout here instead of adopting the fixed
   Phase/Sprint/Tags/Assignee columns above. */
.outline-tree--progress .outline-row {
  display: flex;
  align-items: center;
  gap: 0.65em;
  min-width: 0;
}

.outline-row__meta {
  display: flex;
  align-items: center;
  gap: 0.6em;
  flex-shrink: 0;
}

.outline-row:hover {
  background: var(--color-primary-tint);
}

/* Parent task rows (have children) get a light teal wash so they stand
   out from their leaf children — milestone/epic rows below always carry
   their own tint regardless of children. */
.outline-row--has-children.outline-row--task {
  background: var(--color-primary-tint);
}

.outline-row--has-children.outline-row--task:hover {
  background: var(--color-primary-tint-hover);
}

.outline-row--milestone {
  background: var(--color-primary-tint);
  font-weight: 600;
}

.outline-row--milestone:hover {
  background: var(--color-primary-tint-hover);
}

.outline-row--epic {
  background: var(--color-epic-tint);
}

.outline-row--epic:hover {
  background: #E4D6F9;
}

.outline-row--level-1 {
  padding-left: 3.25em;
}

.outline-row--level-2 {
  padding-left: 5em;
}

.outline-row--level-3 {
  padding-left: 6.75em;
}

.outline-row--level-4 {
  padding-left: 8.5em;
}

.outline-row--level-5 {
  padding-left: 10.25em;
}

.outline-row__toggle-slot {
  width: 20px;
  flex-shrink: 0;
  display: flex;
}

.outline-row__toggle {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  transition: transform 0.15s ease;
}

.outline-row__toggle svg {
  width: 18px;
  height: 18px;
}

.outline-row.is-open .outline-row__toggle {
  transform: rotate(90deg);
}

.outline-row__id {
  flex-shrink: 0;
}

.chip--epic {
  background: var(--color-epic-tint);
  color: var(--color-epic);
}

.outline-row__title {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  font-size: 0.88rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Fixed-width columns (Phase/Sprint/Tags/Assignee) — always present in
   the DOM even when empty for a given row type, so the grid column they
   occupy stays aligned across every row. */
.outline-row__col {
  display: flex;
  align-items: center;
  min-width: 0;
  overflow: hidden;
}

.outline-row__col--tags {
  flex-wrap: nowrap;
}

.outline-row__col--tags .tag-chip-row {
  flex-wrap: nowrap;
  overflow: hidden;
}

.outline-row__completion {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* Sprint inheritance / Backlog-override pill on epic + task rows */
.sprint-pill {
  display: inline-flex;
  align-items: center;
  padding: 0.2em 0.6em;
  border-radius: 9999px;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}

.sprint-pill--inherited {
  background: var(--color-bg);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}

.sprint-pill--backlog {
  background: var(--color-warning-tint);
  color: var(--color-warning);
}

.outline-row--backlog {
  background: #FFFCF5;
}

.outline-row--backlog:hover {
  background: #FDF6E3;
}

/* Row actions: hidden until hover on desktop (mouse present), always
   visible on touch devices since there's no hover to reveal them. */
.outline-row__actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.35em;
  flex-shrink: 0;
  opacity: 0;
  transition: opacity 0.1s ease;
}

.outline-row:hover .outline-row__actions,
.outline-row__actions:focus-within {
  opacity: 1;
}

@media (hover: none) {
  .outline-row__actions {
    opacity: 1;
  }
}

.outline-row__add-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0.3em 0.65em;
  border-radius: 9999px;
  white-space: nowrap;
}

.outline-row__add-btn svg {
  width: 13px;
  height: 13px;
}

.outline-row__add-btn:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.outline-row__children {
  display: block;
}

.outline-row__children[hidden] {
  display: none;
}

/* Task detail slide-in drawer */
.drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  z-index: 60;
  display: none;
}

.drawer-backdrop.is-open {
  display: block;
}

.drawer {
  position: fixed;
  top: 0;
  right: 0;
  height: 100vh;
  width: 440px;
  max-width: 92vw;
  background: var(--color-surface);
  box-shadow: var(--shadow-card-hover);
  z-index: 61;
  transform: translateX(100%);
  transition: transform 0.2s ease;
  overflow-y: auto;
}

.drawer.is-open {
  transform: translateX(0);
}

.drawer__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  background: var(--color-surface);
}

.drawer__close {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 0.35em;
  border-radius: var(--radius-sm);
  display: inline-flex;
}

.drawer__close svg {
  width: 18px;
  height: 18px;
}

.drawer__close:hover {
  background: var(--color-primary-tint);
  color: var(--color-primary);
}

.drawer__body {
  padding: 1.5rem;
}

.drawer__type-label {
  color: var(--color-text-muted);
  font-size: 0.85rem;
  font-weight: 600;
  margin-left: 0.5em;
}

.drawer__header-actions {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.drawer__footer {
  position: sticky;
  bottom: 0;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  padding: 1rem 1.5rem;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.75rem;
}

.form-label__optional {
  font-weight: 400;
  color: var(--color-text-muted);
  text-transform: none;
  letter-spacing: 0;
}

/* Removable chip input (Owners / Collaborators) */
.chip-input {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5em;
}

.chip-input__chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  background: var(--color-primary-tint);
  color: var(--color-primary);
  padding: 0.3em 0.5em 0.3em 0.75em;
  border-radius: 9999px;
  font-size: 0.82rem;
  font-weight: 600;
}

.chip-input__remove {
  background: transparent;
  border: none;
  color: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  padding: 0;
}

.chip-input__remove svg {
  width: 14px;
  height: 14px;
}

.chip-input__add {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  background: transparent;
  border: 1px dashed var(--color-border);
  color: var(--color-text-muted);
  padding: 0.3em 0.75em;
  border-radius: 9999px;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
}

.chip-input__add svg {
  width: 14px;
  height: 14px;
}

.chip-input__add:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

/* Epic drawer: Acceptance Criteria repeatable list */
.criteria-list {
  display: flex;
  flex-direction: column;
  gap: 0.4em;
  margin-bottom: 0.5em;
}

.criteria-row {
  display: flex;
  align-items: center;
  gap: 0.4em;
}

.criteria-row__input {
  flex: 1;
}

.criteria-row__move,
.criteria-row__remove {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  cursor: pointer;
}

.criteria-row__move svg,
.criteria-row__remove svg {
  width: 14px;
  height: 14px;
}

.criteria-row__move:hover,
.criteria-row__remove:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.criteria-row__move:disabled {
  opacity: 0.35;
  cursor: default;
}

.criteria-row__move:disabled:hover {
  border-color: var(--color-border);
  color: var(--color-text-muted);
}

/* Comments */
.comment-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-bottom: 1rem;
}

.comment {
  display: flex;
  gap: 0.75em;
}

.comment__delete {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  padding: 0.15em;
  flex-shrink: 0;
  align-self: flex-start;
}

.comment__delete:hover {
  color: var(--color-danger);
}

.comment__delete svg {
  width: 14px;
  height: 14px;
}

.comment__body {
  flex: 1;
  min-width: 0;
}

.comment__meta {
  display: flex;
  align-items: baseline;
  gap: 0.5em;
  margin-bottom: 0.15em;
}

.comment__author {
  font-weight: 600;
  font-size: 0.85rem;
}

.comment__time {
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.comment__text {
  font-size: 0.87rem;
  color: var(--color-text);
}

.comment-composer {
  display: flex;
  gap: 0.6em;
}

.comment-composer .form-input {
  flex: 1;
}

/* Board tab — Kanban */
.board {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  overflow-x: auto;
  padding-bottom: 0.5rem;
}

.board-column {
  flex: 1 1 0%;
  /* Small enough that 3-5 columns (the typical phase count) fit the
     available width and simply grow to fill it via flex-grow, rather
     than forcing .board's overflow-x scroll — that only kicks in once
     column-count * this min-width genuinely exceeds the viewport
     (roughly 7+ columns). */
  min-width: 200px;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 1rem;
}

.board-column__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.board-column__title {
  font-weight: 700;
  font-size: 0.9rem;
}

.board-column__count {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--color-text-muted);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  padding: 0.1em 0.65em;
  border-radius: 9999px;
}

.board-column__list {
  min-height: 40px;
}

.board-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card);
  padding: 0.5em 0.65em;
  margin-bottom: 0.5rem;
  cursor: grab;
}

.board-card:last-child {
  margin-bottom: 0;
}

.board-card__id {
  margin-bottom: 0.3em;
  padding: 0.12em 0.5em;
  font-size: 0.72rem;
}

.board-card__title {
  font-weight: 600;
  font-size: 0.8rem;
  line-height: 1.3;
  color: var(--color-text);
}

.board-card__footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 0.4em;
}

/* SortableJS drag-state hooks */
.board-card.sortable-ghost {
  opacity: 0.35;
}

.board-card.sortable-chosen {
  box-shadow: var(--shadow-card-hover);
}

.board-card.sortable-drag {
  box-shadow: var(--shadow-card-hover);
  transform: rotate(1.5deg);
}

@media (max-width: 768px) {
  .app-layout {
    flex-direction: column;
  }

  .form-row {
    grid-template-columns: 1fr;
  }

  .template-picker {
    flex-direction: column;
  }

  .board {
    flex-direction: column;
  }

  .board-column {
    min-width: 0;
  }

  .drawer {
    width: 100vw;
    max-width: 100vw;
  }

  .task-row--level-1 {
    padding-left: 2em;
  }

  .task-row--level-2 {
    padding-left: 2.75em;
  }

  .task-row--level-3 {
    padding-left: 3.5em;
  }

  .app-sidebar {
    width: 100%;
    min-height: auto;
    border-right: none;
    border-bottom: 1px solid var(--color-border);
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.25rem;
  }

  .app-sidebar__nav {
    flex-direction: row;
    flex-wrap: wrap;
  }

  .app-main {
    padding: 1.5rem 1.25rem 3rem;
  }
}

@media (max-width: 480px) {
  .app-header__inner {
    justify-content: center;
    text-align: center;
  }
}

/* Roadmap tab — milestone/epic Gantt. Bars are positioned with left/width
   percentages computed server-side from real dates; month columns use the
   same day-proportional math so a bar always lines up under the correct
   month regardless of that month's day count. */
.gantt {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  overflow-x: auto;
  padding-bottom: 0.5rem;
}

.gantt__header {
  display: flex;
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  background: var(--color-surface);
}

.gantt__label-col {
  width: 260px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.75em 1.25em;
}

.gantt__months {
  flex: 1;
  display: flex;
  min-width: 480px;
}

.gantt__month {
  flex-shrink: 0;
  text-align: center;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--color-text-muted);
  padding: 0.75em 0;
  border-left: 1px solid var(--color-border);
}

.gantt__row-group {
  border-bottom: 1px solid var(--color-border);
}

.gantt__row {
  display: flex;
  align-items: center;
  min-height: 48px;
}

.gantt__row + .gantt__row {
  border-top: 1px solid var(--color-border);
}

.gantt__toggle {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  transition: transform 0.15s ease;
  flex-shrink: 0;
}

.gantt__toggle svg {
  width: 16px;
  height: 16px;
}

.gantt__row-group.is-open .gantt__toggle {
  transform: rotate(90deg);
}

.gantt__label-id {
  flex-shrink: 0;
}

.gantt__label-title {
  font-weight: 600;
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gantt__epics .gantt__label-title {
  font-weight: 500;
  color: var(--color-text-muted);
}

.gantt__track {
  flex: 1;
  position: relative;
  min-width: 480px;
  height: 28px;
}

.gantt__bar {
  position: absolute;
  top: 0;
  height: 100%;
  border-radius: 6px;
  background: var(--color-primary-tint);
  overflow: hidden;
  display: flex;
  align-items: center;
}

.gantt__bar--milestone {
  background: var(--color-primary-tint);
  border: 1px solid var(--color-primary);
}

.gantt__bar--epic {
  background: var(--color-epic-tint);
  border: 1px solid var(--color-epic);
  height: 20px;
  top: 4px;
}

.gantt__bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--color-primary);
  opacity: 0.35;
}

.gantt__bar--epic .gantt__bar-fill {
  background: var(--color-epic);
}

.gantt__bar-label {
  position: relative;
  margin-left: 0.6em;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text);
  white-space: nowrap;
}

.gantt__epics {
  display: block;
}

.gantt__epics[hidden] {
  display: none;
}

/* Progress tab — overall completion stat, phase-distribution strip, and
   the completion rollup tree. Tree rows reuse .outline-row/.chip/.badge
   exactly as the Tasks tab does; only the two pieces below (the stat and
   the segmented bar) are new, built from existing tokens. */
.progress-stat {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}

.progress-stat__value {
  font-size: 2.25rem;
  font-weight: 700;
  color: var(--color-primary);
  letter-spacing: -0.02em;
}

.progress-stat__label {
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

/* Wider variant of the shared .progress-bar for the rollup tree, where
   fixed-width table-cell sizing doesn't apply. */
.progress-bar--tree {
  width: 130px;
}

.phase-distribution {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.phase-distribution__bar {
  display: flex;
  height: 10px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--color-border);
}

.phase-distribution__segment {
  height: 100%;
}

.phase-distribution__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
}

.phase-distribution__legend-item {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.phase-distribution__legend-dot {
  width: 9px;
  height: 9px;
  border-radius: 999px;
  flex-shrink: 0;
}

/* Excluded-account tag (User Management) — same violet pairing as
   .badge--in-house/.badge--system, reused rather than a new hue. */
.badge--excluded {
  background: var(--color-epic-tint);
  color: var(--color-epic);
}

/* My Work + User Management "hidden" rows: greyed out, same treatment as
   the existing inactive/offboarded rows. */
.data-table__row.is-hidden {
  opacity: 0.55;
}

/* ===== Tags ===== */

/* Solid-color pill, color set per-tag via inline style (background is
   dynamic, unlike every other chip/badge in the app) — white text reads
   reliably across the whole preset palette. */
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.22em 0.65em;
  border-radius: 9999px;
  font-size: 0.74rem;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  line-height: 1.3;
}

/* Compact variant for tree rows / board cards, where several chips sit
   next to a sprint pill and avatar stack without room to spare. */
.tag-chip--sm {
  padding: 0.12em 0.55em;
  font-size: 0.68rem;
}

.tag-chip__remove {
  background: transparent;
  border: none;
  color: inherit;
  opacity: 0.85;
  cursor: pointer;
  display: flex;
  align-items: center;
  padding: 0;
}

.tag-chip__remove:hover {
  opacity: 1;
}

.tag-chip__remove svg {
  width: 12px;
  height: 12px;
}

/* Wraps a row/card's tag chips so a long set never fights the title or
   the sprint pill for space — wraps onto its own line instead of
   squeezing everything else. */
.tag-chip-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3em;
}

/* Settings > Tags — list of the project's tags with edit/delete actions,
   same row shape as .phase-row / .sprint-row on the same tab. */
.tag-settings-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.tag-settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6em 0.9em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.tag-settings-row__actions {
  display: flex;
  align-items: center;
  gap: 0.25em;
}

/* Add/edit tag modal's color picker — a small preset palette, not a full
   color wheel, per spec. */
.color-swatch-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6em;
}

.color-swatch {
  width: 28px;
  height: 28px;
  border-radius: 9999px;
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
}

.color-swatch:hover {
  transform: scale(1.08);
}

.color-swatch.is-selected {
  border-color: var(--color-text);
  box-shadow: 0 0 0 2px var(--color-surface), 0 0 0 4px var(--color-text);
}

/* Drawer's "Add tag" control + the popover it opens — same trigger shape
   as .chip-input__add, and a dropdown positioned the same way as
   .row-menu__dropdown but left-aligned under its trigger instead of
   right-aligned. */
.tag-picker {
  position: relative;
  display: inline-block;
}

.tag-picker__popover {
  display: none;
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card-hover);
  min-width: 200px;
  max-height: 260px;
  overflow-y: auto;
  z-index: 30;
  padding: 0.4em;
}

.tag-picker__popover.is-open {
  display: block;
}

.tag-picker__option {
  display: flex;
  align-items: center;
  gap: 0.55em;
  width: 100%;
  background: transparent;
  border: none;
  padding: 0.5em 0.6em;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.85rem;
  color: var(--color-text);
  cursor: pointer;
  text-align: left;
}

.tag-picker__option:hover {
  background: var(--color-primary-tint);
}

.tag-picker__option-dot {
  width: 10px;
  height: 10px;
  border-radius: 9999px;
  flex-shrink: 0;
}

.tag-picker__empty {
  padding: 0.6em;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

/* Filter bar — Tags multi-select trigger reuses .list-toolbar__select's
   look via a real <button> (so it can show a "Tags (2)" count) plus the
   same popover/checklist shape as .tag-picker__popover above. */
.filter-select-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: inherit;
  font-size: 0.85rem;
  padding: 0.5em 0.75em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  background: var(--color-surface);
  cursor: pointer;
}

.filter-select-btn:hover {
  border-color: var(--color-primary);
}

.filter-select-btn svg {
  width: 15px;
  height: 15px;
  color: var(--color-text-muted);
}

.tag-filter-popover {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card-hover);
  min-width: 200px;
  z-index: 30;
  padding: 0.5em;
}

.tag-filter-popover.is-open {
  display: block;
}

.tag-filter-popover__option {
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.45em 0.5em;
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  cursor: pointer;
}

.tag-filter-popover__option:hover {
  background: var(--color-primary-tint);
}

.tag-filter-popover__option input {
  accent-color: var(--color-primary);
}

/* "More filters" — Milestone/Owner/Contributor grouped behind one button
   (Fix 3) instead of sitting inline on the bar; reuses .tag-filter-
   popover's positioning/shadow, just wider and laid out as stacked
   labeled fields instead of a checklist. */
.filter-more-popover {
  width: 220px;
  padding: 0.75em;
}

.filter-more-popover__field {
  display: flex;
  flex-direction: column;
  gap: 0.35em;
}

.filter-more-popover__field + .filter-more-popover__field {
  margin-top: 0.75em;
}

.filter-more-popover__label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
}

.filter-more-popover .list-toolbar__select {
  width: 100%;
  min-width: 0;
}

/* Due-date filter's custom range — a popover below the due-date select
   once "Custom range" is chosen, same positioning as .tag-picker__popover
   (its wrapper reuses the .tag-picker class), instead of expanding
   inline and shoving every filter after it out of position. */
.filter-date-range {
  display: none;
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  align-items: center;
  gap: 0.4em;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card-hover);
  padding: 0.6em;
  z-index: 30;
  white-space: nowrap;
}

.filter-date-range.is-open {
  display: flex;
}

.filter-date-range input {
  font-family: inherit;
  font-size: 0.85rem;
  padding: 0.5em 0.6em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
}

.filter-date-range__sep {
  color: var(--color-text-muted);
  font-size: 0.8rem;
}

/* ============================================================
   Timesheets module (Step 1 — static mockup, dummy data only)
   ============================================================ */

.ts-week-nav {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}

.ts-week-nav__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text-muted);
  cursor: pointer;
}

.ts-week-nav__arrow:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.ts-week-nav__arrow svg {
  width: 16px;
  height: 16px;
}

.ts-week-nav__label {
  font-size: 1rem;
  font-weight: 700;
  min-width: 220px;
  text-align: center;
}

/* Overdue-timesheet nudge — amber, not red (a reminder, not an error),
   reusing the existing warning tokens defined for sprint-pill/badge use. */
.banner--warning {
  background: var(--color-warning-tint);
  color: var(--color-warning);
}

.banner--warning a {
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
}

/* Toolbar row above the grid: Copy last week / Freeze week */
.ts-toolbar {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.ts-freeze-btn svg {
  width: 15px;
  height: 15px;
}

.ts-freeze-btn.is-frozen {
  background: var(--color-primary-tint);
  border-color: var(--color-primary-tint);
  color: var(--color-primary-dark);
  cursor: default;
}

.ts-freeze-btn.is-frozen:hover {
  background: var(--color-primary-tint);
}

/* Grid */
.ts-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.87rem;
}

.ts-table th,
.ts-table td {
  padding: 0.65em 0.6em;
  border-bottom: 1px solid var(--color-border);
  text-align: center;
  vertical-align: middle;
}

.ts-table thead th {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
  font-weight: 700;
}

.ts-table th.ts-col-project,
.ts-table td.ts-col-project {
  text-align: left;
  min-width: 220px;
}

.ts-table td.ts-col-total {
  font-weight: 700;
}

.ts-table th.ts-col-actions,
.ts-table td.ts-col-actions {
  width: 64px;
}

.ts-day-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3em;
}

.ts-day-header__label {
  white-space: nowrap;
}

.ts-day-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 9999px;
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
}

.ts-day-toggle:hover {
  background: var(--color-bg);
  color: var(--color-primary);
}

.ts-day-toggle svg {
  width: 13px;
  height: 13px;
}

.ts-day-toggle.is-active {
  background: var(--color-warning-tint);
  color: var(--color-warning);
}

.ts-table td.is-leave,
.ts-table th.is-leave {
  background: var(--color-bg);
}

.ts-leave-label {
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-warning);
}

.ts-row__project {
  font-weight: 600;
  font-size: 0.88rem;
}

.ts-row__task-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  margin-top: 0.3em;
  padding: 0.2em 0.6em;
  border-radius: 6px;
  background: var(--color-primary-tint);
  color: var(--color-primary);
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
  font-size: 0.78rem;
  font-weight: 600;
  border: none;
  cursor: pointer;
}

.ts-row__task-chip:hover {
  background: var(--color-primary-tint-hover);
}

.ts-row__task-chip--empty {
  background: var(--color-bg);
  color: var(--color-text-muted);
  font-family: inherit;
  font-weight: 500;
  border: 1px dashed var(--color-border);
}

.ts-hour-input {
  width: 48px;
  font-family: inherit;
  font-size: 0.85rem;
  text-align: center;
  padding: 0.4em 0.2em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  background: var(--color-surface);
}

.ts-hour-input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.ts-hour-input:disabled {
  background: var(--color-bg);
  color: var(--color-text-muted);
  cursor: not-allowed;
}

.ts-row__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.3em;
}

.ts-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
}

.ts-icon-btn:hover {
  background: var(--color-bg);
  color: var(--color-primary);
}

.ts-icon-btn--danger:hover {
  color: var(--color-danger);
}

.ts-icon-btn.is-active {
  color: var(--color-primary);
}

.ts-icon-btn svg {
  width: 15px;
  height: 15px;
}

.ts-note-row td {
  border-bottom: 1px solid var(--color-border);
  background: var(--color-bg);
  padding: 0.5em 0.6em 0.75em;
  text-align: left;
}

.ts-note-input {
  width: 100%;
  font-family: inherit;
  font-size: 0.83rem;
  padding: 0.5em 0.75em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  background: var(--color-surface);
}

.ts-note-input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.ts-note-text {
  font-size: 0.83rem;
  color: var(--color-text-muted);
  font-style: italic;
}

.ts-total-row td {
  font-weight: 700;
  background: var(--color-bg);
  border-top: 2px solid var(--color-border);
  border-bottom: none;
}

/* Fix 1 — icon-only "add project" control, teal accent to match the
   app's other primary actions (was a full-width dashed text button). */
.ts-add-project-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  margin-top: 1rem;
  background: var(--color-primary);
  border: none;
  color: #fff;
  border-radius: 9999px;
  cursor: pointer;
  box-shadow: var(--shadow-card);
}

.ts-add-project-btn:hover {
  background: var(--color-primary-dark);
}

.ts-add-project-btn svg {
  width: 16px;
  height: 16px;
}

/* Weekly grid grouped by project (Restructure) — a header row per
   project, its task rows nested directly beneath, collapsible. */
.ts-group-header {
  background: var(--color-bg);
}

.ts-group-header td {
  border-bottom: 1px solid var(--color-border);
}

.ts-group-header .ts-col-project {
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.ts-group-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
  flex-shrink: 0;
}

.ts-group-toggle:hover {
  background: var(--color-surface);
  color: var(--color-primary);
}

.ts-group-toggle svg {
  width: 15px;
  height: 15px;
}

.ts-group-header__name {
  font-weight: 700;
  font-size: 0.9rem;
}

.ts-group-add-task {
  color: var(--color-primary);
}

.ts-col-task {
  vertical-align: top;
  padding-top: 0.75em;
}

.ts-empty-state {
  padding: 2.5rem 1rem;
  text-align: center;
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

/* Type-ahead search popover — search input up top, live-filtered results
   below. Distinct from .tag-picker__popover (a plain static checklist)
   since this one is driven by free text against any part of the name/id,
   not a fixed option list. */
.ts-typeahead {
  position: relative;
  display: inline-block;
}

.ts-typeahead--block {
  display: block;
}

.ts-typeahead__popover {
  display: none;
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card-hover);
  width: 280px;
  z-index: 40;
  padding: 0.5em;
}

.ts-typeahead__popover.is-open {
  display: block;
}

.ts-typeahead__input {
  width: 100%;
  font-family: inherit;
  font-size: 0.85rem;
  padding: 0.5em 0.7em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  margin-bottom: 0.4em;
}

.ts-typeahead__input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.ts-typeahead__results {
  max-height: 220px;
  overflow-y: auto;
}

.ts-typeahead__option {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  padding: 0.5em 0.6em;
  border-radius: var(--radius-sm);
  font-family: inherit;
  cursor: pointer;
}

.ts-typeahead__option:hover {
  background: var(--color-primary-tint);
}

.ts-typeahead__option-id {
  display: block;
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
  font-size: 0.75rem;
  color: var(--color-primary);
  font-weight: 600;
}

.ts-typeahead__option-name {
  display: block;
  font-size: 0.83rem;
  color: var(--color-text);
  margin-top: 0.1em;
}

.ts-typeahead__empty {
  padding: 0.75em 0.6em;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

/* Fix 3 — quick-pick shortlist (recent/assigned tasks) shown above the
   full search inside a task picker's popover. */
.ts-typeahead__popover--task {
  width: 300px;
}

.ts-typeahead__quickpick:empty {
  display: none;
}

.ts-typeahead__section-label {
  padding: 0.3em 0.6em;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
}

.ts-typeahead__divider {
  height: 1px;
  background: var(--color-border);
  margin: 0.4em 0.2em;
}

/* Task drawer "Time logged" section (Timesheets integration) — reuses
   .ts-icon-btn for the edit/delete controls to match the weekly grid. */
.time-log-list {
  display: flex;
  flex-direction: column;
  margin-bottom: 0.75rem;
}

.time-log-item {
  display: flex;
  align-items: center;
  gap: 0.75em;
  padding: 0.5em 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 0.85rem;
}

.time-log-item:last-child {
  border-bottom: none;
}

.time-log-item__date {
  flex-shrink: 0;
  width: 64px;
  color: var(--color-text-muted);
}

.time-log-item__hours {
  flex-shrink: 0;
  width: 40px;
  font-weight: 700;
}

.time-log-item__note {
  flex: 1;
  min-width: 0;
  color: var(--color-text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.time-log-item__actions {
  display: flex;
  align-items: center;
  gap: 0.2em;
  flex-shrink: 0;
}

.time-log-item .form-input {
  font-size: 0.83rem;
  padding: 0.35em 0.5em;
}

.time-log-item .time-log-item__edit-hours {
  width: 60px;
  flex-shrink: 0;
}

.time-log-item .time-log-item__edit-note {
  flex: 1;
  min-width: 0;
}

.time-log-composer {
  display: flex;
  gap: 0.5em;
  flex-wrap: wrap;
}

.time-log-composer__hours {
  width: 80px;
  flex-shrink: 0;
}

.time-log-composer__date {
  width: 150px;
  flex-shrink: 0;
}

.time-log-composer__note {
  flex: 1;
  min-width: 140px;
}

.time-log-composer__hint {
  margin-top: 0.5em;
  font-size: 0.78rem;
  color: var(--color-text-muted);
}

/* Status badges — Timesheets team list. Reuses the danger tokens the
   same way badge--todo/doing/done reuse inactive/primary/green above. */
.badge--overdue {
  background: var(--color-danger-tint);
  color: var(--color-danger);
}

/* Generic multi-button page-header action group — same shape as
   .project-header__actions, just not scoped to the project page. */
.page-header__actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

/* Requires Timesheet checkbox — User management table */
.requires-ts-checkbox {
  width: 17px;
  height: 17px;
  accent-color: var(--color-primary);
  cursor: pointer;
}

/* ============================================================
   Progress tab enhancements (Step 1 — static mockup, dummy data)
   ============================================================ */

/* Chart.js needs a sized ancestor to fill via responsive:true —
   height is set here rather than on the canvas itself. */
.chart-card__canvas-wrap {
  position: relative;
  height: 260px;
}

.chart-card__canvas-wrap--workload {
  height: 230px;
}

/* Fix 7 — "As Owner" / "As Contributor" side by side (stacked on narrow
   viewports), each its own independent chart, same pattern as
   .overdue-upcoming-grid below. */
.team-workload-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
}

@media (max-width: 768px) {
  .team-workload-grid {
    grid-template-columns: 1fr;
  }
}

.team-workload-grid__label {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
  margin: 0 0 0.75rem;
}

.chart-card__empty {
  padding: 2.5rem 1rem;
  text-align: center;
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

/* Overdue & Upcoming — two lists side by side, each with its own count
   pill next to the heading. */
.overdue-upcoming-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
}

@media (max-width: 768px) {
  .overdue-upcoming-grid {
    grid-template-columns: 1fr;
  }
}

.overdue-upcoming-col__header {
  display: flex;
  align-items: center;
  gap: 0.6em;
  margin-bottom: 0.85rem;
}

.overdue-upcoming-col__title {
  font-size: 0.95rem;
  font-weight: 700;
}

/* Reuses the danger tokens the same way badge--overdue (Timesheets)
   already does — "due this week" gets the warning-tint counterpart. */
.badge--upcoming {
  background: var(--color-warning-tint);
  color: var(--color-warning);
}

.overdue-upcoming-item {
  display: flex;
  align-items: center;
  gap: 0.65em;
  padding: 0.55em 0;
  border-bottom: 1px solid var(--color-border);
}

.overdue-upcoming-item:last-child {
  border-bottom: none;
}

.overdue-upcoming-item__body {
  flex: 1;
  min-width: 0;
}

.overdue-upcoming-item__title {
  font-size: 0.85rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.overdue-upcoming-item__meta {
  font-size: 0.76rem;
  color: var(--color-text-muted);
  margin-top: 0.15em;
}

.overdue-upcoming-empty {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  padding: 0.4em 0;
}
