/* ============================================================================
   TMS components — the replacements for the DevExtreme widgets.

     .tms-grid      → dxDataGrid
     .tms-modal     → dxPopup / DevExpress.ui.dialog
     .tms-select    → dxSelectBox / dxTagBox
     .tms-upload    → dxFileUploader
     .tms-editor    → dxHtmlEditor  (thin Quill chrome)
     .tms-toast     → DevExpress.ui.notify
     .tms-loader    → dxLoadPanel
     .tms-breakdown → the developer task checklist (new)
   ========================================================================== */

/* ============================================================================
   GRID
   ========================================================================== */
.tms-grid { display: flex; flex-direction: column; }

.tms-grid-toolbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px;
}
.tms-grid-search { position: relative; }
.tms-grid-search .tms-i {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  color: var(--tms-text-3); font-size: 15px; pointer-events: none;
}
.tms-grid-search input {
  height: 33px; width: 260px; padding: 0 11px 0 32px;
  background: var(--tms-surface); color: var(--tms-text);
  border: 1px solid var(--tms-border-strong); border-radius: var(--tms-r);
  font-size: var(--tms-fs-data);
}
.tms-grid-search input:focus {
  outline: none; border-color: var(--tms-accent); box-shadow: 0 0 0 3px var(--tms-accent-tint);
}

.tms-chip {
  display: inline-flex; align-items: center; gap: 6px; height: 29px; padding: 0 10px;
  background: var(--tms-surface); border: 1px solid var(--tms-border-strong);
  border-radius: 999px; font-size: var(--tms-fs-data); font-weight: 550; color: var(--tms-text-2);
  transition: border-color var(--tms-fast), color var(--tms-fast), background-color var(--tms-fast);
}
.tms-chip:hover { border-color: var(--tms-text-3); color: var(--tms-text); }
.tms-chip.is-on { background: var(--tms-accent-tint); border-color: var(--tms-accent-line); color: var(--tms-accent-dark); }
.tms-chip .tms-i { font-size: 13px; }

/* Client contacts. Amber rather than the accent so that selecting one does not look like
   selecting a teammate — the two have very different consequences on an internal note. */
/* Staff and client chips are told apart at rest, not only when selected — the whole point
   is to see WHO you are about to mention before you commit to it. Staff take the accent,
   clients take amber and a dashed edge, because mentioning a client has consequences a
   teammate mention does not. */
.tms-chip-staff  { border-color: var(--tms-accent-line); color: var(--tms-accent-dark); }
.tms-chip-client { border-style: dashed; border-color: var(--tms-warn-line); color: var(--tms-warn); }

.tms-chip-client::before {
  content: "◇"; margin-right: 4px; font-size: 9px; vertical-align: 1px;
}

/* Keyboard highlight. A ring rather than a fill so it reads as "this is where the cursor
   is" and not as "this one is already selected" — is-on already means selected. */
.tms-chip.is-active {
  box-shadow: 0 0 0 2px var(--tms-accent);
  border-color: var(--tms-accent);
}

/* While an "@..." is being typed the row is showing matches, not the default list. The
   tint says the set has changed underneath you — otherwise chips silently disappearing
   reads as them having been lost. */
.tms-mention-row.is-filtering {
  background: var(--tms-accent-tint); border-radius: var(--tms-r-sm);
  padding: 4px 6px; margin: 0 -6px;
}
.tms-chip-client.is-on {
  background: var(--tms-warn-tint); border-color: var(--tms-warn-line);
  color: var(--tms-warn); border-style: solid;
}

.tms-grid-scroll {
  background: var(--tms-surface); border: 1px solid var(--tms-border);
  border-radius: var(--tms-r-lg); overflow-x: auto; box-shadow: var(--tms-shadow-1);
}
.tms-grid-table { width: 100%; border-collapse: collapse; font-size: var(--tms-fs-data); }
.tms-grid-table thead th {
  position: sticky; top: 0; z-index: 2; background: var(--tms-surface);
  text-align: left; font-size: var(--tms-fs-micro); font-weight: 700;
  letter-spacing: .075em; text-transform: uppercase; color: var(--tms-text-3);
  padding: 9px 12px; border-bottom: 1px solid var(--tms-border); white-space: nowrap;
}
.tms-grid-table thead th.is-sortable { cursor: pointer; user-select: none; }
.tms-grid-table thead th.is-sortable:hover { color: var(--tms-text); }
.tms-grid-table thead th .tms-sort { opacity: 0; font-size: 10px; margin-left: 3px; }
.tms-grid-table thead th.is-sorted .tms-sort { opacity: 1; color: var(--tms-accent); }

.tms-grid-table tbody tr { border-bottom: 1px solid var(--tms-border); transition: background-color .12s; }
.tms-grid-table tbody tr:last-child { border-bottom: none; }
.tms-grid-table tbody tr.is-clickable { cursor: pointer; }
.tms-grid-table tbody tr:hover { background: var(--tms-surface-2); }
.tms-grid-table td { padding: 9px 12px; vertical-align: middle; }
.tms-grid-table td.tms-num { text-align: right; font-variant-numeric: tabular-nums; }

/* 3px severity stripe in the first cell — reads priority without reading text */
.tms-grid-table td.tms-stripe { padding: 0; width: 3px; }
.tms-stripe-bar { display: block; width: 3px; height: 38px; }
.tms-stripe-crit { background: var(--tms-danger); }
.tms-stripe-high { background: var(--tms-warn); }
.tms-stripe-med  { background: var(--tms-info); }
.tms-stripe-low  { background: var(--tms-border-strong); }

.tms-grid-empty { padding: 40px 20px; text-align: center; color: var(--tms-text-3); font-size: var(--tms-fs-data); }
.tms-grid-foot {
  display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  border-top: 1px solid var(--tms-border); font-size: var(--tms-fs-data); color: var(--tms-text-2);
}
.tms-grid-foot .tms-pager { margin-left: auto; display: flex; gap: 6px; align-items: center; }
.tms-grid-foot .tms-pager select { height: 27px; }

/* inline progress meter, used by the Breakdown column */
.tms-meter { display: inline-flex; align-items: center; gap: 6px; font-family: var(--tms-font-mono);
  font-size: 11.5px; color: var(--tms-text-2); font-variant-numeric: tabular-nums; }
.tms-meter-track { width: 38px; height: 5px; background: var(--tms-surface-3); border-radius: 999px; overflow: hidden; }
.tms-meter-fill  { display: block; height: 100%; background: var(--tms-accent); border-radius: 999px; }

/* ============================================================================
   MODAL — replaces dxPopup and DevExpress.ui.dialog.*
   ========================================================================== */
.tms-modal-backdrop {
  position: fixed; inset: 0; z-index: var(--tms-z-modal);
  background: rgba(26, 25, 34, .45);
  display: grid; place-items: center; padding: 24px;
  animation: tms-fade .16s var(--tms-ease);
}
:root[data-theme="dark"] .tms-modal-backdrop { background: rgba(0, 0, 0, .62); }

.tms-modal {
  background: var(--tms-surface); border: 1px solid var(--tms-border);
  border-radius: var(--tms-r-lg); box-shadow: var(--tms-shadow-3);
  width: 100%; max-width: 520px; max-height: calc(100vh - 48px);
  display: flex; flex-direction: column;
  animation: tms-pop .18s var(--tms-ease);
}
.tms-modal-sm { max-width: 400px; }
.tms-modal-lg { max-width: 860px; }
.tms-modal-xl { max-width: 1180px; }

.tms-modal-h {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px; border-bottom: 1px solid var(--tms-border); flex: none;
}
.tms-modal-h h2 { margin: 0; font-size: var(--tms-fs-sub); font-weight: 650; letter-spacing: -.015em; }
.tms-modal-x {
  margin-left: auto; width: 30px; height: 30px; display: grid; place-items: center;
  border-radius: var(--tms-r); color: var(--tms-text-3); font-size: 16px;
  transition: background-color var(--tms-fast), color var(--tms-fast);
}
.tms-modal-x:hover { background: var(--tms-surface-2); color: var(--tms-text); }

.tms-modal-b { padding: 18px; overflow-y: auto; flex: 1; }
.tms-modal-f {
  display: flex; align-items: center; gap: 8px; justify-content: flex-end;
  padding: 12px 18px; border-top: 1px solid var(--tms-border); flex: none;
}
.tms-modal-f .tms-left { margin-right: auto; }

@keyframes tms-fade { from { opacity: 0; } }
@keyframes tms-pop  { from { opacity: 0; transform: translateY(10px) scale(.985); } }

/* ============================================================================
   SELECT — replaces dxSelectBox and dxTagBox
   ========================================================================== */
.tms-select { position: relative; }
.tms-select-control {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  min-height: 40px; padding: 5px 32px 5px 10px; cursor: pointer;
  background: var(--tms-surface); border: 1px solid var(--tms-border-strong);
  border-radius: var(--tms-r); transition: border-color var(--tms-fast), box-shadow var(--tms-fast);
}
.tms-select.is-open .tms-select-control,
.tms-select-control:focus-visible {
  border-color: var(--tms-accent); box-shadow: 0 0 0 3px var(--tms-accent-tint); outline: none;
}
.tms-select.is-disabled .tms-select-control {
  background: var(--tms-surface-2); color: var(--tms-text-2); cursor: not-allowed;
}
.tms-select-placeholder { color: var(--tms-text-3); font-size: var(--tms-fs-body); }
.tms-select-value { font-size: var(--tms-fs-body); }
.tms-select-caret {
  position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
  color: var(--tms-text-3); font-size: 15px; pointer-events: none;
  transition: transform var(--tms-fast);
}
.tms-select.is-open .tms-select-caret { transform: translateY(-50%) rotate(180deg); }

/* chips inside a multi-select */
.tms-select-chip {
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 4px 0 8px;
  background: var(--tms-accent-tint); border: 1px solid var(--tms-accent-line);
  border-radius: var(--tms-r-sm); font-size: var(--tms-fs-cap); font-weight: 600;
  color: var(--tms-accent-dark); max-width: 100%;
}
.tms-select-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tms-select-chip button {
  width: 16px; height: 16px; display: grid; place-items: center;
  border-radius: 3px; color: inherit; opacity: .65; font-size: 11px;
}
.tms-select-chip button:hover { opacity: 1; background: rgba(0,0,0,.08); }

.tms-select-menu {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: var(--tms-z-dropdown);
  background: var(--tms-surface); border: 1px solid var(--tms-border-strong);
  border-radius: var(--tms-r); box-shadow: var(--tms-shadow-3);
  max-height: 280px; display: none; flex-direction: column; overflow: hidden;
}
.tms-select.is-open .tms-select-menu { display: flex; }
.tms-select.is-up .tms-select-menu { top: auto; bottom: calc(100% + 4px); }

.tms-select-search { padding: 8px; border-bottom: 1px solid var(--tms-border); flex: none; }
.tms-select-search input {
  width: 100%; height: 32px; padding: 0 10px;
  background: var(--tms-surface-2); color: var(--tms-text);
  border: 1px solid transparent; border-radius: var(--tms-r-sm); font-size: var(--tms-fs-data);
}
.tms-select-search input:focus { outline: none; border-color: var(--tms-accent); }

.tms-select-list { list-style: none; margin: 0; padding: 4px; overflow-y: auto; flex: 1; }
.tms-select-opt {
  display: flex; align-items: center; gap: 8px; padding: 7px 9px;
  border-radius: var(--tms-r-sm); font-size: var(--tms-fs-data); cursor: pointer;
}
.tms-select-opt:hover, .tms-select-opt.is-active { background: var(--tms-surface-2); }
.tms-select-opt.is-selected { color: var(--tms-accent-dark); font-weight: 600; }
.tms-select-opt.is-selected::after {
  content: "✓"; margin-left: auto; font-size: 12px; color: var(--tms-accent);
}

/* Group header inside a filtering select. Sticky so the team stays readable while
   scrolling a long list — the whole point of grouping is knowing where you are. */
.tms-select-group {
  position: sticky; top: 0; z-index: 2;
  padding: 0; margin: 6px 0 2px;
  cursor: default;
}
.tms-select-group:first-child { margin-top: 0; }

/* The header sits ON the scrolling list, so it needs a solid fill and a rule beneath it.
   Without both, the row passing underneath shows through and reads as a clipped name —
   which is exactly what it looked like before. */
.tms-select-group > span {
  display: block; padding: 6px 9px 5px;
  background: var(--tms-surface);
  border-bottom: 1px solid var(--tms-border);
  font-size: var(--tms-fs-micro); font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--tms-text-3);
}
.tms-select-none { padding: 16px 12px; text-align: center; color: var(--tms-text-3); font-size: var(--tms-fs-data); }

/* ============================================================================
   UPLOAD — replaces dxFileUploader
   ========================================================================== */
.tms-upload-zone {
  /* A <label> is display:inline by default, and padding on an inline box does not
     affect line height — the dashed border then bleeds over whatever sits above and
     the text breaks mid-word. It has to be a block. */
  display: block; width: 100%;
  border: 1.5px dashed var(--tms-border-strong); border-radius: var(--tms-r-lg);
  padding: 22px; text-align: center; color: var(--tms-text-3);
  font-size: var(--tms-fs-data); cursor: pointer;
  transition: border-color var(--tms-fast), background-color var(--tms-fast), color var(--tms-fast);
}
.tms-upload-zone:hover, .tms-upload-zone.is-over {
  border-color: var(--tms-accent-line); background: var(--tms-accent-tint); color: var(--tms-accent-dark);
}
.tms-upload-zone .tms-i { font-size: 19px; display: block; margin: 0 auto 7px; }
.tms-upload-zone b { color: var(--tms-accent); font-weight: 600; }

.tms-upload-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.tms-upload-item {
  display: flex; align-items: center; gap: 9px; padding: 8px 11px;
  background: var(--tms-surface-2); border: 1px solid var(--tms-border);
  border-radius: var(--tms-r); font-size: var(--tms-fs-data);
}
.tms-upload-item .tms-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tms-upload-item .tms-size { font-family: var(--tms-font-mono); font-size: 11.5px; color: var(--tms-text-3); }
.tms-upload-item.is-error { background: var(--tms-danger-tint); border-color: var(--tms-danger-line); color: var(--tms-danger); }
.tms-upload-item.is-done .tms-i { color: var(--tms-ok); }
.tms-upload-bar { width: 62px; height: 5px; background: var(--tms-surface-3); border-radius: 999px; overflow: hidden; }
.tms-upload-bar i { display: block; height: 100%; background: var(--tms-accent); transition: width .2s linear; }
.tms-upload-x {
  width: 22px; height: 22px; display: grid; place-items: center; border-radius: var(--tms-r-sm);
  color: var(--tms-text-3); font-size: 13px;
}
.tms-upload-x:hover { background: var(--tms-danger-tint); color: var(--tms-danger); }

/* attachment chip, for already-uploaded files */
.tms-att {
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
  background: var(--tms-surface-2); border: 1px solid var(--tms-border);
  border-radius: var(--tms-r); font-size: var(--tms-fs-cap); color: var(--tms-text-2);
  transition: border-color var(--tms-fast), color var(--tms-fast);
}
.tms-att:hover { border-color: var(--tms-border-strong); color: var(--tms-text); text-decoration: none; }

/* ============================================================================
   EDITOR — replaces dxHtmlEditor (Quill without the DevExtreme wrapper)
   ========================================================================== */
.tms-editor {
  background: var(--tms-surface); border: 1px solid var(--tms-border-strong);
  border-radius: var(--tms-r-lg); overflow: hidden;
}
.tms-editor .ql-toolbar.ql-snow {
  border: none; border-bottom: 1px solid var(--tms-border);
  background: var(--tms-surface-2); padding: 6px 8px;
}
.tms-editor .ql-container.ql-snow { border: none; font-family: var(--tms-font); font-size: 13.5px; }
.tms-editor .ql-editor { min-height: 92px; line-height: 1.62; color: var(--tms-text); }
.tms-editor .ql-editor.ql-blank::before { color: var(--tms-text-3); font-style: normal; }
.tms-editor .ql-snow .ql-stroke { stroke: var(--tms-text-2); }
.tms-editor .ql-snow .ql-fill   { fill: var(--tms-text-2); }
.tms-editor .ql-snow .ql-picker { color: var(--tms-text-2); }
.tms-editor .ql-snow button:hover .ql-stroke,
.tms-editor .ql-snow button.ql-active .ql-stroke { stroke: var(--tms-accent); }
.tms-editor .ql-snow button:hover .ql-fill,
.tms-editor .ql-snow button.ql-active .ql-fill { fill: var(--tms-accent); }

/* ============================================================================
   TOAST — replaces DevExpress.ui.notify
   ========================================================================== */
.tms-toasts {
  position: fixed; bottom: 20px; right: 20px; z-index: var(--tms-z-toast);
  display: flex; flex-direction: column; gap: 8px; pointer-events: none;
}
.tms-toast {
  display: flex; align-items: center; gap: 9px; pointer-events: auto;
  background: var(--tms-surface); border: 1px solid var(--tms-border-strong);
  border-left: 3px solid var(--tms-accent); border-radius: var(--tms-r);
  padding: 11px 15px; box-shadow: var(--tms-shadow-3);
  font-size: var(--tms-fs-data); font-weight: 550; max-width: 380px;
  animation: tms-toast-in .22s cubic-bezier(.2, .8, .3, 1);
}
.tms-toast.is-leaving { animation: tms-toast-out .18s var(--tms-ease) forwards; }
.tms-toast .tms-i { font-size: 15px; color: var(--tms-accent); }
.tms-toast-error   { border-left-color: var(--tms-danger); }
.tms-toast-error .tms-i { color: var(--tms-danger); }
.tms-toast-warning { border-left-color: var(--tms-warn); }
.tms-toast-warning .tms-i { color: var(--tms-warn); }
.tms-toast-info    { border-left-color: var(--tms-info); }
.tms-toast-info .tms-i { color: var(--tms-info); }

@keyframes tms-toast-in  { from { opacity: 0; transform: translateY(8px); } }
@keyframes tms-toast-out { to   { opacity: 0; transform: translateX(12px); } }

/* ============================================================================
   LOADER — replaces dxLoadPanel
   ========================================================================== */
.tms-loader-host { position: relative; }
.tms-loader {
  position: absolute; inset: 0; z-index: 40;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  background: color-mix(in srgb, var(--tms-surface) 72%, transparent);
  font-size: var(--tms-fs-data); color: var(--tms-text-2);
}
.tms-loader.is-fixed { position: fixed; inset: 0; z-index: var(--tms-z-modal); }
/* display MUST be set: as a <span> this is inline by default, and an inline box
   ignores width/height — the spinner renders as a 2px vertical sliver. */
.tms-spinner {
  display: inline-block; flex: none;
  width: 26px; height: 26px; border-radius: 50%;
  border: 2.5px solid var(--tms-border-strong); border-top-color: var(--tms-accent);
  animation: tms-spin .7s linear infinite;
  vertical-align: middle;
}
.tms-spinner-center { display: block; margin: 0 auto 10px; }
@keyframes tms-spin { to { transform: rotate(360deg); } }

/* ============================================================================
   BREAKDOWN — the developer task checklist
   ========================================================================== */
.tms-breakdown {
  background: var(--tms-surface); border: 1px solid var(--tms-accent-line);
  border-radius: var(--tms-r-lg); box-shadow: var(--tms-shadow-1);
  margin: 16px 0; overflow: hidden;
}
.tms-bd-h {
  display: flex; align-items: center; gap: 10px; padding: 12px 15px;
  background: var(--tms-accent-tint); border-bottom: 1px solid var(--tms-accent-line);
}
.tms-bd-title {
  font-size: var(--tms-fs-data); font-weight: 700; letter-spacing: .045em;
  text-transform: uppercase; color: var(--tms-accent-dark);
}
.tms-bd-count {
  margin-left: auto; font-family: var(--tms-font-mono); font-size: var(--tms-fs-cap);
  font-weight: 600; color: var(--tms-accent-dark);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.tms-bd-ring { width: 26px; height: 26px; flex: none; transform: rotate(-90deg); }
.tms-bd-ring circle { fill: none; stroke-width: 3.2; }
.tms-bd-ring .tms-ring-bg { stroke: var(--tms-accent-line); opacity: .45; }
.tms-bd-ring .tms-ring-fg {
  stroke: var(--tms-accent); stroke-linecap: round;
  transition: stroke-dashoffset .4s var(--tms-ease);
}
.tms-bd-bar { height: 3px; background: var(--tms-surface-3); }
.tms-bd-bar i { display: block; height: 100%; background: var(--tms-accent); transition: width .4s var(--tms-ease); }

.tms-bd-list { list-style: none; margin: 0; padding: 4px 0; }
.tms-bd-item {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 8px 15px 8px 10px; position: relative; transition: background-color .12s;
}
.tms-bd-item:hover { background: var(--tms-surface-2); }
.tms-bd-item.is-dragging { opacity: .45; }

.tms-bd-grip {
  width: 14px; flex: none; color: var(--tms-text-3); opacity: 0; cursor: grab;
  font-size: 13px; line-height: 1.5; letter-spacing: -1px; padding-top: 1px;
  user-select: none; touch-action: none; transition: opacity .13s;
}
.tms-bd-item:hover .tms-bd-grip { opacity: .7; }

.tms-bd-box {
  width: 16px; height: 16px; flex: none; margin-top: 2px;
  border: 1.6px solid var(--tms-border-strong); border-radius: 4px;
  display: grid; place-items: center; color: transparent; font-size: 11px;
  background: var(--tms-surface);
  transition: background-color .16s, border-color .16s, color .16s;
}
.tms-bd-box:hover { border-color: var(--tms-accent); }

/* Text and its timestamp stack; the pair takes the space the text alone used to. */
.tms-bd-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }

/* When the step was added. Quiet by design — it is provenance, not the step itself. */
.tms-bd-when {
  font-size: 11px; color: var(--tms-text-3); line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tms-bd-item.is-done .tms-bd-when { opacity: .7; }

.tms-bd-text {
  min-width: 0; font-size: 13.5px; line-height: 1.5;
  position: relative; padding-right: 4px; transition: color .22s;
  overflow-wrap: anywhere;
}
/* The strike-through is a pseudo-element that draws across, not a text-decoration,
   so completing a task reads as an action rather than a re-render. */
.tms-bd-text::after {
  content: ""; position: absolute; left: 0; top: .72em; height: 1.4px; width: 0;
  background: currentColor; opacity: .85;
  transition: width var(--tms-slow) cubic-bezier(.35, 0, .2, 1);
}
.tms-bd-item.is-done .tms-bd-box { background: var(--tms-accent); border-color: var(--tms-accent); color: var(--tms-on-accent); }
.tms-bd-item.is-done .tms-bd-text { color: var(--tms-text-3); }
.tms-bd-item.is-done .tms-bd-text::after { width: 100%; }

.tms-bd-meta { display: flex; align-items: center; gap: 7px; flex: none; font-size: 11.5px; color: var(--tms-text-3); }
.tms-bd-est {
  font-family: var(--tms-font-mono); font-variant-numeric: tabular-nums;
  background: var(--tms-surface-2); border: 1px solid var(--tms-border);
  border-radius: var(--tms-r-sm); padding: 1px 5px;
}
.tms-bd-del {
  width: 22px; height: 22px; display: grid; place-items: center; border-radius: var(--tms-r-sm);
  color: var(--tms-text-3); font-size: 13px; opacity: 0;
  transition: opacity .13s, background-color .13s, color .13s;
}
.tms-bd-item:hover .tms-bd-del, .tms-bd-del:focus-visible { opacity: 1; }
.tms-bd-del:hover { background: var(--tms-danger-tint); color: var(--tms-danger); }

.tms-bd-empty { padding: 16px 15px; color: var(--tms-text-3); font-size: var(--tms-fs-data); font-style: italic; }
.tms-bd-add {
  display: flex; gap: 8px; padding: 11px 15px;
  border-top: 1px solid var(--tms-border); background: var(--tms-surface-2);
}
.tms-bd-add .tms-input { height: 34px; background: var(--tms-surface); }
.tms-bd-foot {
  display: flex; align-items: center; gap: 8px; padding: 9px 15px;
  border-top: 1px solid var(--tms-border); font-size: 11.5px; color: var(--tms-text-3);
}
.tms-bd-foot .tms-right { margin-left: auto; }

/* --------------------------------------------------------------------------
   Grid summary tiles

   A count strip above the toolbar: "shown / total" per facet, click to filter.
   Deliberately ~46px tall rather than a card grid — the tickets grid is the
   densest screen in the portal and every 50px here is a ticket row lost on
   every visit. The label sits UNDER the number so the tile needs no second
   line of chrome, and a 3px left bar carries the category colour instead of a
   full border.
   -------------------------------------------------------------------------- */
.tms-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(94px, 1fr));
  gap: 8px;
  margin: 0 0 10px;
}

.tms-tile {
  display: block;
  text-align: left;
  min-width: 0;
  padding: 6px 10px 7px;
  background: var(--tms-surface);
  border: 1px solid var(--tms-border);
  border-left: 3px solid var(--tms-accent-bar, var(--tms-border-strong));
  border-radius: 0;                 /* a single-sided accent bar and rounded corners fight */
  cursor: pointer;
  transition: background var(--tms-fast) var(--tms-ease),
              border-color var(--tms-fast) var(--tms-ease);
}

.tms-tile:hover { background: var(--tms-surface-2); }

.tms-tile:focus-visible {
  outline: 2px solid var(--tms-accent);
  outline-offset: 1px;
}

.tms-tile-v {
  display: block;
  font-family: var(--tms-font-mono);
  font-size: var(--tms-fs-sub);
  font-weight: 500;
  line-height: 1.25;
  color: var(--tms-text);
  white-space: nowrap;
}

.tms-tile-t {
  font-size: var(--tms-fs-cap);
  font-weight: 400;
  color: var(--tms-text-3);
}

.tms-tile-l {
  display: block;
  font-size: var(--tms-fs-micro);
  color: var(--tms-text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Accent bar per facet. Set as a variable so the border rule stays single. */
.tms-tile[data-accent="info"]     { --tms-accent-bar: var(--tms-info); }
.tms-tile[data-accent="progress"] { --tms-accent-bar: var(--tms-progress); }
.tms-tile[data-accent="danger"]   { --tms-accent-bar: var(--tms-danger); }
.tms-tile[data-accent="warn"]     { --tms-accent-bar: var(--tms-warn); }
.tms-tile[data-accent="ok"]       { --tms-accent-bar: var(--tms-ok); }

.tms-tile.is-on {
  background: var(--tms-accent-tint);
  border-color: var(--tms-accent-line);
  border-left-color: var(--tms-accent-bar, var(--tms-accent));
}

/* The tint is light in both themes, so the ink has to come from the accent
   family rather than inheriting --tms-text. */
.tms-tile.is-on .tms-tile-v { color: var(--tms-accent-dark); }
.tms-tile.is-on .tms-tile-t,
.tms-tile.is-on .tms-tile-l { color: var(--tms-accent-ink-2); }

/* --------------------------------------------------------------------------
   Grid group headings

   A full-width band between rows. Deliberately not sticky: several groups are
   visible at once in a dense grid, and stacking sticky bands eats the viewport.
   -------------------------------------------------------------------------- */
.tms-grid-table tbody tr.tms-grouprow { background: var(--tms-surface-2); }
.tms-grid-table tbody tr.tms-grouprow:hover { background: var(--tms-surface-2); }

.tms-grid-table tbody tr.tms-grouprow td {
  padding: 5px 12px;
  border-bottom: 1px solid var(--tms-border);
  border-top: 1px solid var(--tms-border);
}

.tms-groupname {
  font-size: var(--tms-fs-micro);
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--tms-text-2);
}

.tms-groupcount {
  margin-left: 8px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--tms-surface-3);
  color: var(--tms-text-3);
  font-family: var(--tms-font-mono);
  font-size: var(--tms-fs-micro);
}

/* --------------------------------------------------------------------------
   Fill column — the one free-text column that absorbs leftover table width.

   The table is table-layout:auto, so a cell normally grows to fit its content
   and text-overflow never triggers. The pair below is what makes ellipsis work
   at the real column edge: max-width:0 stops the cell contributing its content
   to the column's intrinsic width, and width:100% then claims whatever space
   the fixed-width columns leave over. The inner element does the truncating.

   The previous approach capped the subject at 46ch, which truncated at a fixed
   character count no matter how wide the column actually was.

   The width:100% claim lives on the th ONLY. Put it on the td as well and the
   cell drags the slack back every layout pass, which makes the resize handle a
   silent no-op — the column snaps back to full width the moment you let go.
   On the th it is a plain stylesheet declaration, so the inline width the resize
   gesture writes overrides it and the column can be dragged like any other.
   max-width is likewise kept off the th: it beats width in the cascade and would
   collapse a resized column to zero.
   -------------------------------------------------------------------------- */
.tms-grid-table td.tms-cell-fill {
  max-width: 0;
}

.tms-grid-table th.tms-cell-fill {
  width: 100%;
}

/* Anything directly inside a fill cell truncates rather than widening it. */
.tms-grid-table td.tms-cell-fill > * {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Silent-refresh indicator on the tickets grid.

   Deliberately not a toast: a toast covers rows and pulls attention for
   something the user did not ask for. This sits in the toolbar, next to the
   data it describes, and stays until dismissed or superseded.
   -------------------------------------------------------------------------- */
.tms-sync {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--tms-fs-cap); color: var(--tms-text-3);
  padding: 0 4px; white-space: nowrap;
}
.tms-sync .tms-spinner { width: 12px; height: 12px; border-width: 2px; }

.tms-sync.is-new {
  color: var(--tms-accent-dark); font-weight: 600;
  background: var(--tms-accent-tint); border: 1px solid var(--tms-accent-line);
  border-radius: 999px; height: 26px; padding: 0 10px; cursor: pointer;
}
.tms-sync.is-new:hover { background: var(--tms-surface); }
.tms-sync.is-new .tms-i { font-size: 12px; }

/* ============================================================================
   PRIORITY MANAGER

   Ten ranks and a backlog. Pick a ticket, then pick where it goes — no drag,
   because moving between two different containers is the case drag handles
   worst, and pick-then-place works from the keyboard and on touch.
   ========================================================================== */
.tms-pm-slots {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 7px;
}
@media (max-width: 620px) { .tms-pm-slots { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.tms-pm-slot {
  text-align: left; min-height: 64px; padding: 7px 9px;
  background: var(--tms-surface-2); border: 1px solid var(--tms-border);
  border-radius: var(--tms-r); overflow: hidden;
  transition: border-color var(--tms-fast), background-color var(--tms-fast);
}
.tms-pm-slot.is-free { border-style: dashed; }
.tms-pm-slot:disabled { opacity: .6; cursor: not-allowed; }

/* Where the held ticket can actually go. Only vacant ranks light up — an occupied
   one would mean evicting its holder, which the server would reject anyway. */
.tms-pm-slot.is-target {
  border-style: solid; border-color: var(--tms-info);
  background: var(--tms-info-tint);
}
.tms-pm-slot.is-picked, .tms-pm-row.is-picked {
  border-color: var(--tms-accent); background: var(--tms-accent-tint);
}

.tms-pm-n {
  display: block; font-family: var(--tms-font-mono);
  font-size: var(--tms-fs-data); font-weight: 650; line-height: 1.1;
}
.tms-pm-t {
  display: block; font-size: var(--tms-fs-micro); color: var(--tms-text-3);
  margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tms-pm-t b { color: var(--tms-text-2); font-family: var(--tms-font-mono); }
.tms-pm-sub {
  display: block; font-size: var(--tms-fs-micro); color: var(--tms-text-3);
  margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tms-pm-lock {
  margin-left: 5px; font-size: 9.5px; text-transform: uppercase; letter-spacing: .04em;
  background: var(--tms-surface-3); color: var(--tms-text-3);
  border-radius: var(--tms-r-sm); padding: 0 4px;
}

.tms-pm-count {
  font-family: var(--tms-font-mono); font-size: var(--tms-fs-micro);
  background: var(--tms-surface-3); color: var(--tms-text-3);
  border-radius: 999px; padding: 1px 7px; font-weight: 400; letter-spacing: 0;
}

.tms-pm-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.tms-pm-row { border: 1px solid var(--tms-border); border-radius: var(--tms-r); background: var(--tms-surface-2); }
.tms-pm-pick {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 10px; text-align: left; font-size: var(--tms-fs-data);
}
.tms-pm-pick:disabled { opacity: .6; cursor: not-allowed; }
.tms-pm-id { flex: none; color: var(--tms-text-3); font-size: var(--tms-fs-cap); }
.tms-pm-ttl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Per-task assignee. The avatar is the control — click it to reassign; a "+" stands
   in when nobody is on the step yet, so an unassigned step is visibly actionable
   rather than just blank. */
.tms-bd-whobtn {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; padding: 0; line-height: 1;
}
.tms-bd-whobtn:disabled { cursor: default; }
.tms-bd-whobtn.is-empty {
  width: 22px; height: 22px;
  border: 1px dashed var(--tms-border-strong); color: var(--tms-text-3);
  font-size: 13px; background: var(--tms-surface);
}
.tms-bd-whobtn.is-empty:hover { border-color: var(--tms-accent); color: var(--tms-accent); }

/* The picker replaces the avatar in place, so the row does not jump when it opens. */
.tms-bd-who { display: inline-block; min-width: 170px; }
.tms-bd-who .tms-select-control { min-height: 28px; padding-top: 2px; padding-bottom: 2px; }


/* ---------------------------------------------------------------------------
   AI analysis panel
   --------------------------------------------------------------------------- */

.tms-ai-wait { padding: 40px 8px; text-align: center; }
.tms-ai-wait p { margin: 10px 0 0; }

.tms-ai-intro p { margin: 0 0 10px; }
.tms-ai-intro textarea { margin-top: 6px; resize: vertical; }

/* Said before the request is sent, and again on the result. Client data leaving the
   network is not a footnote. */
.tms-ai-note {
  margin-top: 14px; padding: 9px 11px;
  border-left: 3px solid var(--tms-warn);
  background: var(--tms-surface-2);
  border-radius: var(--tms-r-sm);
  font-size: var(--tms-fs-cap); color: var(--tms-text-2);
}

.tms-ai-head { margin: 0 0 6px; font-size: var(--tms-fs-sub); }
.tms-ai-sum { margin: 0 0 4px; color: var(--tms-text-2); }

.tms-ai-sec {
  margin: 20px 0 8px; font-size: var(--tms-fs-micro); font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; color: var(--tms-text-3);
}

.tms-ai-risk, .tms-ai-theme {
  padding: 10px 12px; margin-bottom: 8px;
  border: 1px solid var(--tms-border); border-radius: var(--tms-r-sm);
  background: var(--tms-surface);
}
.tms-ai-risk p, .tms-ai-theme p { margin: 6px 0 0; font-size: var(--tms-fs-data); color: var(--tms-text-2); }
.tms-ai-risk-h { display: flex; align-items: center; gap: 8px; }

.tms-ai-sev {
  padding: 1px 7px; border-radius: 999px;
  font-size: var(--tms-fs-micro); font-weight: 600; text-transform: uppercase;
}
.tms-ai-sev[data-sev="High"]   { background: var(--tms-danger-tint); color: var(--tms-danger); }
.tms-ai-sev[data-sev="Medium"] { background: var(--tms-warn-tint);   color: var(--tms-warn); }
.tms-ai-sev[data-sev="Low"]    { background: var(--tms-surface-2);   color: var(--tms-text-3); }

.tms-ai-count {
  margin-left: auto; padding: 1px 8px; border-radius: 999px;
  background: var(--tms-surface-2); font-size: var(--tms-fs-micro); color: var(--tms-text-2);
}

.tms-ai-ids { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.tms-ai-id {
  padding: 1px 7px; border-radius: var(--tms-r-sm);
  background: var(--tms-surface-2); border: 1px solid var(--tms-border);
  font-family: var(--tms-font-mono); font-size: var(--tms-fs-micro);
  color: var(--tms-accent-dark); text-decoration: none;
}
.tms-ai-id:hover { border-color: var(--tms-accent); }

.tms-ai-load-row {
  display: flex; align-items: baseline; gap: 10px;
  padding: 6px 2px; border-bottom: 1px solid var(--tms-border);
}
.tms-ai-load-row:last-child { border-bottom: 0; }
.tms-ai-load-n { min-width: 170px; font-weight: 600; font-size: var(--tms-fs-data); }
.tms-ai-load-c { font-family: var(--tms-font-mono); font-size: var(--tms-fs-data); color: var(--tms-text-2); }
.tms-ai-load-t { flex: 1; font-size: var(--tms-fs-cap); color: var(--tms-text-3); }

.tms-ai-rec { margin: 0; padding-left: 20px; }
.tms-ai-rec li { margin-bottom: 6px; font-size: var(--tms-fs-data); }


/* --- AI analysis: charts computed locally, never from the model --- */

.tms-ai-kpis { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 6px; }
.tms-ai-kpi {
  flex: 1 1 92px; padding: 8px 10px;
  border: 1px solid var(--tms-border); border-radius: var(--tms-r-sm);
  background: var(--tms-surface);
}
.tms-ai-kpi b {
  display: block; font-family: var(--tms-font-mono);
  font-size: var(--tms-fs-sub); line-height: 1.2;
}
.tms-ai-kpi span {
  display: block; margin-top: 2px;
  font-size: var(--tms-fs-micro); color: var(--tms-text-3);
}

.tms-ai-chart { margin-top: 14px; }
.tms-ai-chart-t {
  margin: 0 0 6px; font-size: var(--tms-fs-cap);
  font-weight: 600; color: var(--tms-text-2);
}

.tms-ai-bar-row { display: flex; align-items: center; gap: 8px; padding: 2px 0; }

/* Fixed label width so every bar starts at the same x — ragged baselines make lengths
   impossible to compare, which is the only thing a bar chart is for. */
.tms-ai-bar-l {
  flex: 0 0 150px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--tms-fs-cap); color: var(--tms-text-2);
}
.tms-ai-bar-t {
  flex: 1; height: 15px; border-radius: 3px;
  background: var(--tms-surface-2); overflow: hidden;
}
.tms-ai-bar-t > i {
  display: block; height: 100%; border-radius: 3px;
  background: var(--tms-accent); position: relative;
}
/* Overdue share, drawn inside its own bar rather than as a second chart. */
.tms-ai-bar-t > i > u {
  display: block; height: 100%;
  background: var(--tms-danger); text-decoration: none;
}
.tms-ai-bar-v {
  flex: 0 0 40px; text-align: right;
  font-family: var(--tms-font-mono); font-size: var(--tms-fs-cap); color: var(--tms-text-2);
}

.tms-ai-trend {
  padding: 1px 7px; border-radius: 999px;
  font-size: var(--tms-fs-micro); font-weight: 600; text-transform: uppercase;
}
.tms-ai-trend[data-trend="Worsening"] { background: var(--tms-danger-tint); color: var(--tms-danger); }
.tms-ai-trend[data-trend="Steady"]    { background: var(--tms-surface-2);   color: var(--tms-text-3); }
.tms-ai-trend[data-trend="Improving"] { background: var(--tms-ok-tint);     color: var(--tms-ok); }


/* --- Assignee picker rows --------------------------------------------------
   Two lines per person: who they are, and what they are already carrying. The
   decision being made is "who should get this", which a list of names alone
   cannot answer.
   -------------------------------------------------------------------------- */

/* Taller than the default menu: richer rows are worth less scrolling, not more. */
.tms-select-menu { max-height: 380px; }

.tms-select-opt:has(.tms-pick-main) { padding: 6px 9px; gap: 9px; }

.tms-pick-av {
  flex: 0 0 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  font-size: var(--tms-fs-micro); font-weight: 700; letter-spacing: .02em;
}

/* Six fixed tints, picked by team so a team reads as a block while scrolling.
   Deliberately low-saturation: these are wayfinding, not status, and must not
   compete with the overdue count beside them. */
.tms-pick-av[data-team="0"] { background: #DCE9F7; color: #2C5F8F; }
.tms-pick-av[data-team="1"] { background: #DEEEE4; color: #2A6B48; }
.tms-pick-av[data-team="2"] { background: #F3E3E9; color: #8C3F5C; }
.tms-pick-av[data-team="3"] { background: #EFE7D9; color: #7A5A2B; }
.tms-pick-av[data-team="4"] { background: #E4E2F2; color: #4B4589; }
.tms-pick-av[data-team="5"] { background: #DCEDEE; color: #2A6167; }

:root[data-theme="dark"] .tms-pick-av[data-team="0"] { background: #22374B; color: #9CC5EA; }
:root[data-theme="dark"] .tms-pick-av[data-team="1"] { background: #1F3B2E; color: #94CFAE; }
:root[data-theme="dark"] .tms-pick-av[data-team="2"] { background: #422836; color: #E2A2BC; }
:root[data-theme="dark"] .tms-pick-av[data-team="3"] { background: #3D3323; color: #DCBB84; }
:root[data-theme="dark"] .tms-pick-av[data-team="4"] { background: #2E2B4A; color: #B3ADE6; }
:root[data-theme="dark"] .tms-pick-av[data-team="5"] { background: #1F3A3D; color: #92C9CE; }


.tms-pick-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.tms-pick-n {
  font-size: var(--tms-fs-data); line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tms-pick-d {
  font-size: var(--tms-fs-micro); color: var(--tms-text-3); line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.tms-pick-load {
  flex: 0 0 auto; display: flex; flex-direction: column;
  align-items: flex-end; gap: 1px; text-align: right;
}
.tms-pick-open {
  font-family: var(--tms-font-mono); font-size: var(--tms-fs-micro); color: var(--tms-text-2);
}
.tms-pick-over {
  font-family: var(--tms-font-mono); font-size: var(--tms-fs-micro); color: var(--tms-danger);
}
.tms-pick-free { font-size: var(--tms-fs-micro); color: var(--tms-ok); }

/* The tick would collide with the workload column, and the row is already marked by its
   accent colour and weight. */
.tms-select-opt.is-selected:has(.tms-pick-main)::after { content: none; }

/* --------------------------------------------------------------------------
   Expander column and detail row

   The caret is a button of its own, so opening a row and clicking a row stay
   two separate gestures. The detail sits in a full-width cell under its own
   row, tinted a shade off the grid so the nesting reads at a glance.
   -------------------------------------------------------------------------- */
.tms-grid-table th.tms-expander-cell,
.tms-grid-table td.tms-expander-cell { width: 30px; padding: 0 0 0 8px; }

.tms-expander {
  width: 22px; height: 22px; padding: 0;
  display: grid; place-items: center;
  border: none; border-radius: 5px;
  background: transparent; color: var(--tms-text-3);
  cursor: pointer;
}
.tms-expander:hover { background: var(--tms-surface-3); color: var(--tms-accent); }

.tms-expander .tms-caret {
  font-size: 9px; line-height: 1;
  transition: transform .12s ease;
}
.tms-expander.is-open { color: var(--tms-accent); }
.tms-expander.is-open .tms-caret { transform: rotate(90deg); }

.tms-grid-table tbody tr.is-expanded { background: var(--tms-accent-tint); }
.tms-grid-table tbody tr.is-expanded:hover { background: var(--tms-accent-tint); }

.tms-grid-table tbody tr.tms-detail-row,
.tms-grid-table tbody tr.tms-detail-row:hover { background: var(--tms-surface-2); }
.tms-grid-table tbody tr.tms-detail-row > td {
  padding: 0;
  border-top: 1px solid var(--tms-accent-line);
  border-bottom: 1px solid var(--tms-border);
}

/* ===========================================================================
   The ported grid, wearing the portal's clothes.

   Its own palette is a set of --tms-* tokens, so nothing here collides with the
   portal's. Re-pointing them at the portal tokens is all it takes for the grid
   to follow the sidebar's teal, the shared badge colours and — because the
   portal tokens flip with data-theme — dark mode.
   ========================================================================== */
:root, html[data-theme="dark"] {
    --tms-bg: var(--bg);
    --tms-surface: var(--card);
    --tms-surface-2: var(--bg);
    --tms-surface-3: var(--track);
    /* the filter row and the row rules are quiet lines, not boxes */
    --tms-border: var(--line-soft);
    --tms-border-strong: var(--line);

    --tms-text: var(--ink);
    --tms-text-2: var(--muted);
    --tms-text-3: var(--faint);
    --tms-text-invert: #fff;

    --tms-accent: var(--accent);
    --tms-accent-dark: var(--accent-ink);
    --tms-accent-tint: var(--accent-soft);
    --tms-accent-line: color-mix(in srgb, var(--accent) 35%, transparent);
    --tms-accent-ink-2: var(--accent-ink);

    --tms-danger: var(--bad);   --tms-danger-tint: var(--bad-bg);
    --tms-danger-line: color-mix(in srgb, var(--bad) 32%, transparent);
    --tms-warn: var(--warn);    --tms-warn-tint: var(--warn-bg);
    --tms-warn-line: color-mix(in srgb, var(--warn) 32%, transparent);
    --tms-ok: var(--good);      --tms-ok-tint: var(--good-bg);
    --tms-ok-line: color-mix(in srgb, var(--good) 32%, transparent);
    --tms-info: var(--accent);  --tms-info-tint: var(--accent-soft);
    --tms-info-line: color-mix(in srgb, var(--accent) 32%, transparent);
    --tms-progress: var(--purple); --tms-progress-tint: var(--purple-bg);
    --tms-progress-line: color-mix(in srgb, var(--purple) 32%, transparent);

    --tms-shadow-1: var(--shadow);
    --tms-shadow-2: var(--shadow);
    --tms-shadow-3: var(--shadow-lg);

    --tms-font: "Segoe UI", system-ui, -apple-system, sans-serif;
    --tms-font-mono: Consolas, "Cascadia Mono", monospace;
}
