/* Work items — milestone tree.
 *
 * All classes are rd-prefixed so legacy .table/.badge/.card rules outside
 * the redesign aren't affected.
 */

@layer components {
  /* ------------------------------------------------------------------ */
  /* Page head (title area + meta line)                                 */
  /* ------------------------------------------------------------------ */
  .wi-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    margin: 0 0 14px;
    flex-wrap: wrap;
  }
  .wi-head-main .rd-meta {
    color: var(--rd-fg-muted);
    font-size: var(--rd-text-sm);
  }

  .wi-toolbar { margin-bottom: 14px; }

  /* ------------------------------------------------------------------ */
  /* Milestone card                                                     */
  /* ------------------------------------------------------------------ */
  .milestone-card {
    position: relative;
    background: var(--rd-bg-raised);
    border: 2px solid var(--pop-ink);
    border-radius: 0;
    box-shadow: var(--pop-shadow);
    margin-bottom: 12px;
  }
  .milestone-card .card-body.flush {
    padding: 0;
    overflow-x: auto;
    background: var(--rd-bg-raised);
    border-radius: 0;
  }
  .milestone-card[data-collapsed="true"] .card-body.flush {
    display: none;
  }

  /* Milestone header bar. Right padding matches the actions column's
     padding-right (.wi-col-actions) so the more-menu button in the
     header lines up vertically with the per-row more-menu buttons. */
  .milestone-head {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 8px 12px 20px;
    cursor: pointer;
    background: var(--rd-bg-raised);
    position: relative;
    border-bottom: 1px solid transparent;
    border-radius: 0;
    transition: background var(--rd-dur) var(--rd-ease);
  }
  .milestone-card[data-collapsed="true"] .milestone-head {
    border-radius: 0;
  }
  .milestone-head::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--rd-accent);
  }
  .milestone-card.loose .milestone-head::before {
    background: var(--rd-fg-faint);
  }
  .milestone-card:not(.loose) .milestone-head {
    border-bottom-color: var(--rd-border);
  }
  .milestone-card[data-collapsed="true"] .milestone-head {
    border-bottom-color: transparent;
  }
  .milestone-head:hover { background: var(--rd-bg-hover); }
  .milestone-head:focus-visible {
    outline: 2px solid var(--rd-accent);
    outline-offset: -2px;
  }

  .milestone-chevron {
    color: var(--rd-fg-subtle);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border: 0;
    padding: 0;
    background: transparent;
    cursor: pointer;
    border-radius: var(--rd-radius-sm);
    transition: transform var(--rd-dur) var(--rd-ease),
                background var(--rd-dur-fast) var(--rd-ease),
                color var(--rd-dur-fast) var(--rd-ease);
  }
  .milestone-chevron:hover { color: var(--rd-fg); background: var(--rd-bg-hover); }
  .milestone-chevron:focus-visible {
    outline: 2px solid var(--rd-accent);
    outline-offset: 2px;
  }
  .milestone-card[data-collapsed="true"] .milestone-chevron {
    transform: rotate(-90deg);
  }

  .milestone-head-main {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
    flex: 1 1 auto;
  }
  .milestone-title-row {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    flex-wrap: wrap;
  }
  .milestone-title {
    font-family: var(--rd-font-sans);
    font-size: var(--rd-text-base);
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: var(--rd-leading-snug);
    margin: 0;
    color: var(--rd-fg);
    min-width: 0;
    flex: 1 1 auto;
  }

  .milestone-title-edit {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
    min-width: 0;
  }
  .milestone-title-edit .inline-editable {
    flex: 1 1 auto;
    min-width: 0;
    display: block;
    padding: 2px 6px;
    margin: -2px -6px;
    border-radius: var(--rd-radius-sm);
    cursor: text;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: inherit;
    transition: background var(--rd-dur-fast) var(--rd-ease);
  }
  .milestone-title-edit .inline-editable:hover {
    background: var(--rd-bg-active);
  }
  .milestone-title-edit .inline-edit-input {
    appearance: none;
    flex: 1 1 auto;
    font-family: var(--rd-font-sans);
    font-size: var(--rd-text-base);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--rd-fg);
    background: var(--rd-bg-raised);
    border: 1px solid var(--rd-border-focus);
    border-radius: var(--rd-radius-sm);
    padding: 2px 6px;
    line-height: 1.2;
    height: 28px;
    min-width: 0;
    max-width: 100%;
  }
  .milestone-title-edit .inline-edit-input:focus {
    outline: none;
  }
  .milestone-title-edit .inline-save-indicator {
    margin-left: 6px;
    font-size: var(--rd-text-xs);
    color: var(--rd-fg-muted);
    white-space: nowrap;
  }
  .milestone-title-edit .inline-save-indicator.saved { color: var(--rd-success); }
  .milestone-title-edit .inline-save-indicator.error { color: var(--rd-danger); }
  .milestone-title-edit .inline-save-indicator.hidden { display: none; }

  .eyebrow {
    display: inline-block;
    font-size: var(--rd-text-2xs);
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--rd-fg-subtle);
    flex: 0 0 auto;
  }

  .milestone-meta {
    display: flex;
    align-items: center;
    gap: 14px;
    font-size: var(--rd-text-sm);
    color: var(--rd-fg-muted);
    flex-wrap: wrap;
  }
  .milestone-meta .m { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
  .milestone-meta .m svg { color: var(--rd-fg-subtle); flex: 0 0 auto; }
  .milestone-meta .num {
    font-family: var(--rd-font-mono);
    font-variant-numeric: tabular-nums;
    color: var(--rd-fg);
  }
  .milestone-meta .due-overdue { color: var(--rd-danger); }

  .milestone-right {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: 0 0 auto;
  }
  .milestone-progress {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--rd-fg-muted);
    font-size: var(--rd-text-xs);
  }
  .milestone-progress .count {
    font-family: var(--rd-font-mono);
    font-variant-numeric: tabular-nums;
    color: var(--rd-fg);
    font-weight: 500;
  }
  .milestone-progress .bar {
    width: 96px;
    height: 5px;
    border-radius: 0;
    background: var(--rd-bg-sunken);
    overflow: hidden;
  }
  .milestone-progress .fill {
    height: 100%;
    background: var(--rd-accent);
    border-radius: 0;
    transition: width var(--rd-dur) var(--rd-ease);
  }

  @media (max-width: 1280px) {
    .milestone-meta .m-value { display: none; }
  }
  @media (max-width: 1100px) {
    .milestone-progress .bar { display: none; }
    .milestone-right .rd-avs { display: none; }
    .milestone-meta .m-hours { display: none; }
  }
  @media (max-width: 900px) {
    .milestone-meta { gap: 10px; }
    .milestone-head { gap: 10px; padding: 10px 8px 10px 16px; }
    .milestone-right { gap: 8px; }
  }

  /* Phones: titles need room to wrap, and the right-hand badge cluster
     can't share the first line with the truncated title. The drag
     handle is absolute-positioned in the left gutter (see below), so
     the grid only needs one column for the title and a second row for
     the badge/menu/chevron cluster aligned to the right. */
  @media (max-width: 720px) {
    .milestone-head {
      display: grid;
      grid-template-columns: 1fr;
      align-items: start;
      row-gap: 6px;
    }
    .milestone-head-main { min-width: 0; }
    .milestone-title-edit .inline-editable {
      white-space: normal;
      overflow: visible;
      text-overflow: clip;
      word-break: break-word;
      display: inline;
    }
    .milestone-right {
      justify-content: flex-end;
      gap: 10px;
      padding-top: 2px;
    }
    .milestone-progress .count { font-size: var(--rd-text-xs); }
  }
  @media (max-width: 520px) {
    /* On the smallest phones the milestone progress count duplicates
       what the in-row "70 items" line already tells you. Drop it to
       reclaim row space for the status badge and menu. */
    .milestone-progress { display: none; }
  }

  /* ------------------------------------------------------------------ */
  /* Tree table                                                         */
  /* ------------------------------------------------------------------ */
  .tree-table {
    width: 100%;
    min-width: 100%;
    border-collapse: collapse;
    font-size: var(--rd-text-base);
    table-layout: fixed;
  }
  .tree-table tbody td {
    padding: 9px 14px;
    border-bottom: 1px solid var(--rd-border);
    color: var(--rd-fg);
    vertical-align: middle;
  }
  .tree-table-head th {
    padding: 8px 14px;
    border-bottom: 1px solid var(--rd-border);
    background: var(--rd-bg-sunken);
    color: var(--rd-fg-muted);
    font-size: var(--rd-text-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    text-align: left;
    vertical-align: middle;
    white-space: nowrap;
  }
  .tree-table-head th.col-hours,
  .tree-table-head th.col-dollars { text-align: right; }
  .tree-table-head th.col-actions { padding-left: 4px; padding-right: 8px; }
  .tree-table tbody tr:hover { background: var(--rd-bg-hover); }
  .tree-table tbody tr:last-child td { border-bottom: 0; }
  .tree-table tbody tr.is-done td { color: var(--rd-fg-muted); }
  .tree-table tbody tr.is-done .wi-title { text-decoration: line-through; }
  .tree-table tbody td:nth-child(3) { overflow: hidden; }

  /* Tree-collapse visibility is kept on its own class so it doesn't fight
     the `hidden` attribute, which list_filter_controller owns for search
     state. A row is hidden when either flag is set — except while a filter
     is active, when a row the filter chose to show overrides tree-collapse
     so nested matches surface regardless of their card's expand state. */
  .wi-row.wi-row-collapsed { display: none; }
  [data-list-filtering] .wi-row.wi-row-collapsed:not([hidden]) { display: table-row; }

  /* Date strings get clipped at the cell so they don't push the table
     wider than the column allocation. */
  .tree-table .wi-col-start,
  .tree-table .wi-col-due,
  .tree-table .wi-col-appetite,
  .tree-table .wi-col-hours,
  .tree-table .wi-col-dollars,
  .tree-table .wi-col-billable {
    overflow: hidden;
  }

  /* Status cell: clip at the cell boundary and truncate the badge with
     an ellipsis when a custom status name is longer than the column.
     The badge is forced to `inline-block` here because `inline-flex`
     (the default) clips its right padding when combined with
     overflow:hidden + text-overflow:ellipsis, leaving the badge
     looking broken. inline-block preserves padding while still
     ellipsizing the text. Only the wrapper carries `max-width: 100%`
     — chaining the percentage through the inline-editable's padding
     compounds and forces an ellipsis even when the badge fits. */
  .tree-table .wi-col-status-cell {
    overflow: hidden;
  }
  .tree-table .wi-col-status-cell .inline-editable-wrapper {
    max-width: 100%;
  }
  /* Override the base `.wi-row .inline-editable { max-width: 100% }`
     rule below — chained percentages through the inline-editable's
     padding compound and force the badge to ellipsize even when it
     would otherwise fit. The wrapper's max-width plus flex-shrink on
     the editable handle the cell-level cap on their own. */
  .tree-table .wi-col-status-cell .inline-editable {
    max-width: none;
  }
  .tree-table .wi-col-status-cell .rd-badge {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
  }

  /* Actions cell holds an icon cluster (sync indicator, expand-steps
     chevron, detail-panel toggle, more-menu trigger). The td itself
     stays a table-cell so its bottom border tracks the rest of the
     row; the cluster flex layout lives on an inner wrapper so the
     trailing more-menu doesn't wrap from inline-flow whitespace. */
  .tree-table .wi-col-actions {
    padding-left: 4px;
    padding-right: 8px;
  }
  .wi-actions-cluster {
    display: flex;
    align-items: center;
    justify-content: flex-end;
  }

  .tree-table .col-lead      { width: 56px; }
  .tree-table .col-type      { width: 80px; }
  /* col-title intentionally has no fixed width — under `table-layout:
     fixed` an unsized column absorbs leftover width, so the lead/type
     columns render at exactly their declared sizes instead of getting
     proportionally inflated. The 1080px media query reasserts a fixed
     title width on tablets where every column is already snug. */
  .tree-table .col-status    { width: 160px; }
  .tree-table .col-start     { width: 108px; }
  .tree-table .col-due       { width: 108px; }
  .tree-table .col-appetite  { width: 96px; }
  .tree-table .col-hours     { width: 72px; }
  .tree-table .col-dollars   { width: 96px; }
  .tree-table .col-billable  { width: 100px; }
  .tree-table .col-assignees { width: 104px; }
  /* col-actions holds (left-to-right): basecamp sync indicator (when
     present), expand-steps chevron (when the card has steps), the
     detail-panel toggle, and the more-menu button. Widened from 72px
     so the new sync + chev icons fit alongside the existing 26px
     buttons without crowding the assignees column. */
  .tree-table .col-actions   { width: 112px; }

  /* ------------------------------------------------------------------ */
  /* Responsive column trimming                                         */
  /*                                                                    */
  /* The full table is ~1320px wide and the .rd-app shell takes 232px   */
  /* for the sidebar above 900px plus 56px of page padding, so even     */
  /* large laptops can't fit every column without horizontal scroll.    */
  /* Below the desktop breakpoint we progressively hide the lower-      */
  /* priority inline-edit columns and tighten widths so the milestone   */
  /* card never scrolls horizontally. Hidden columns remain editable    */
  /* from the expanded detail panel and from the work-item focus        */
  /* overlay.                                                           */
  /* ------------------------------------------------------------------ */

  /* The four "planning" columns drop one at a time as the viewport
     tightens, in reverse-priority order (Appetite → Hours → Amount →
     Billing). Dropping them all at once on a single breakpoint left
     the title column absorbing hundreds of pixels of whitespace at
     typical laptop widths; staggering keeps as many columns visible
     as fit. Hidden columns remain editable in the detail panel and
     the focus overlay. */
  @media (max-width: 1620px) {
    .tree-table .col-appetite,
    .tree-table .wi-col-appetite { display: none; }
  }
  @media (max-width: 1520px) {
    .tree-table .col-hours,
    .tree-table .wi-col-hours { display: none; }
  }
  @media (max-width: 1440px) {
    .tree-table .col-dollars,
    .tree-table .wi-col-dollars { display: none; }
  }
  @media (max-width: 1340px) {
    .tree-table .col-billable,
    .tree-table .wi-col-billable { display: none; }
  }

  /* <= 1280px (small laptop / large tablet) — additionally drop start
     date and type pill so the table fits all the way down to a 1024px
     iPad with the sidebar still visible. */
  @media (max-width: 1280px) {
    .tree-table .col-start,
    .tree-table .wi-col-start,
    .tree-table .col-type,
    .tree-table .wi-col-type { display: none; }
  }

  /* <= 1080px (tablet) — tighten the title column width and row padding
     so the remaining columns sit comfortably without truncation. */
  @media (max-width: 1080px) {
    .tree-table .col-title { width: 220px; }
    .tree-table tbody td,
    .tree-table-head th { padding: 9px 10px; }
    .tree-table .wi-col-actions,
    .tree-table-head th.col-actions { padding-left: 2px; padding-right: 6px; }
  }

  /* <= 900px (sidebar collapses to off-canvas) — keep the same column
     set but tighten the date column. */
  @media (max-width: 900px) {
    .tree-table .col-due { width: 96px; }
    .tree-table .col-status { width: 130px; }
  }

  /* <= 720px (phone landscape) — drop assignees, let title flex,
     hide the drag handle (touch reorder is rare on phones). */
  @media (max-width: 720px) {
    .tree-table .col-assignees,
    .tree-table .wi-col-assignees { display: none; }
    .tree-table .col-lead { width: 48px; }
    .tree-table .col-title { width: auto; }
    .tree-table tbody td,
    .tree-table-head th { padding: 8px 8px; }
    .tree-table .wi-lead { --wi-depth-step: 12px; --wi-lead-pad: 6px; }
    .tree-table .wi-drag-handle { display: none; }
    /* Allow titles to wrap onto two lines. With status, dates, and the
       actions menu sharing the row, single-line truncation hides too
       much of the title at 320–420px. The cell padding stays small so
       two-line rows remain compact. We use overflow-wrap (only break
       if needed) instead of word-break (which would break mid-word
       even when the word would have fit). */
    .tree-table .wi-title,
    .tree-table .wi-row .wi-title.inline-editable {
      white-space: normal;
      overflow: visible;
      text-overflow: clip;
      overflow-wrap: break-word;
      word-break: normal;
      line-height: 1.3;
      display: block;
    }
    .tree-table .wi-title-cell-inner {
      align-items: flex-start;
    }
  }

  /* <= 520px (phone portrait) — last-resort trim. Status hides because
     it's still set by tapping into the detail panel; due date and the
     completion checkbox stay so people can scan their day. The
     per-row overflow menu also drops — every action it offers is
     reachable from the detail panel — but the detail-toggle button
     stays so the panel itself remains reachable. We trim the title
     cell's inline indicators for the same reason: room beats
     redundancy at this width. */
  @media (max-width: 520px) {
    .tree-table .col-status,
    .tree-table .wi-col-status-cell { display: none; }
    .tree-table .wi-more-container { display: none; }
    .tree-table .col-actions { width: 36px; }
    .tree-table .col-lead { width: 42px; }
    .tree-table .col-due { width: 80px; }
    .tree-table tbody td,
    .tree-table-head th { padding: 8px 6px; }
    .tree-table .wi-lead { --wi-depth-step: 10px; --wi-lead-pad: 4px; }
    .tree-table .wi-sync,
    .tree-table .wi-chev { display: none; }
  }

  .tree-table .wi-col-start,
  .tree-table .wi-col-due,
  .tree-table .wi-col-appetite,
  .tree-table .wi-col-hours,
  .tree-table .wi-col-dollars,
  .tree-table .wi-col-billable {
    white-space: nowrap;
  }

  /* Fill narrow data cells so empty ("—") values remain clickable.
     Without this the inline-editable span shrinks to the em-dash width
     and there's nowhere else in the cell to click to enter edit mode. */
  .tree-table .wi-col-start .inline-editable-wrapper,
  .tree-table .wi-col-due .inline-editable-wrapper,
  .tree-table .wi-col-appetite .inline-editable-wrapper,
  .tree-table .wi-col-hours .inline-editable-wrapper,
  .tree-table .wi-col-dollars .inline-editable-wrapper,
  .tree-table .wi-col-billable .inline-editable-wrapper {
    display: flex;
    width: 100%;
  }
  .tree-table .wi-col-start .inline-editable,
  .tree-table .wi-col-due .inline-editable,
  .tree-table .wi-col-appetite .inline-editable,
  .tree-table .wi-col-hours .inline-editable,
  .tree-table .wi-col-dollars .inline-editable,
  .tree-table .wi-col-billable .inline-editable {
    flex: 1 1 auto;
    min-height: 22px;
  }

  .tree-table .rd-num {
    font-family: var(--rd-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--rd-text-sm);
  }
  .tree-table .rd-muted { color: var(--rd-fg-muted); }

  /* Leading cell holds chevron + checkbox + optional tree-guide.
     Indent scales by `--wi-depth` (set inline by _wi_row.html.erb) and
     `--wi-depth-step`, which media queries trim on narrower viewports
     so step rows don't blow out the lead column. */
  .tree-table .wi-lead {
    --wi-depth-step: 16px;
    --wi-lead-pad: 6px;
    position: relative;
    padding-left: calc(var(--wi-lead-pad) + var(--wi-depth, 0) * var(--wi-depth-step));
    padding-right: 0;
    overflow: hidden;
  }
  .wi-lead-inner {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-wrap: nowrap;
  }
  .wi-lead-inner > * { flex: 0 0 auto; }

  /* Type cell holds the type badge. The list-tree toggle that expands
     a card's child steps now lives in the actions cell so it stays
     visible at viewports where the type column is hidden. */
  .tree-table .wi-col-type { padding-left: 2px; padding-right: 6px; }

  /* Tree guide line: vertical thread between depth 1 and depth 2 rows */
  .tree-guide {
    left: calc(var(--wi-lead-pad) + (var(--wi-depth, 1) - 1) * var(--wi-depth-step) - 10px);
    position: absolute;
    top: 0; bottom: 0;
    width: 1px;
    background: var(--rd-border);
  }

  /* List-tree toggle that expands/collapses a card's child steps.
     Lives in the actions cluster on the right so it sits with the
     other per-row affordances and stays visible when the type column
     drops on narrower viewports. */
  .wi-chev {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 26px;
    background: transparent;
    border: 0;
    padding: 0;
    color: var(--rd-fg-muted);
    border-radius: var(--rd-radius-sm);
    cursor: pointer;
    margin-right: 2px;
    vertical-align: middle;
  }
  .wi-chev:hover { color: var(--rd-fg); background: var(--rd-bg-hover); }
  .wi-chev[aria-expanded="true"] { color: var(--rd-fg); }

  /* Checkbox (interactive for Todo/Step/Meeting, static indicator for Card) */
  .wi-check {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border: 0;
    background: transparent;
    padding: 0;
    color: var(--rd-fg-muted);
    cursor: pointer;
  }
  .wi-check-static { cursor: default; }
  .wi-check:hover { color: var(--rd-fg); }
  .is-done .wi-check { color: var(--rd-success); }

  /* Type pill */
  .wi-type {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--rd-font-mono);
    font-size: var(--rd-text-2xs);
    letter-spacing: 0.05em;
    padding: 2px 6px 2px 5px;
    border-radius: var(--rd-radius-sm);
    background: var(--rd-bg-sunken);
    color: var(--rd-fg-muted);
  }
  .wi-type-card      { background: var(--rd-info-soft);    color: var(--rd-info); }
  .wi-type-step      { background: var(--rd-warn-soft);    color: var(--rd-warn); }
  .wi-type-meeting   { background: var(--rd-success-soft); color: var(--rd-success); }
  .wi-type-milestone { background: var(--rd-accent-soft);  color: var(--rd-accent); }

  /* Title cell */
  .wi-title-cell {
    cursor: pointer;
    overflow: hidden;
  }
  .wi-title-cell-inner {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    width: 100%;
  }
  .wi-title {
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1 1 auto;
  }
  .is-done .wi-title { font-weight: 400; color: var(--rd-fg-muted); }
  .wi-sync {
    color: var(--rd-fg-subtle);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 26px;
    flex: 0 0 auto;
    margin-right: 2px;
  }
  .wi-overdue-date { color: var(--rd-danger); }
  .wi-unassigned { font-size: var(--rd-text-xs); }

  /* ------------------------------------------------------------------ */
  /* Inline editing inside tree-table rows                              */
  /* ------------------------------------------------------------------ */
  .wi-row .inline-editable-wrapper {
    position: relative;
    display: inline-flex;
    align-items: center;
    max-width: 100%;
    min-width: 0;
  }
  .wi-title-edit {
    flex: 1 1 auto;
    min-width: 0;
  }
  .wi-row .inline-editable {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 4px;
    margin: -2px -4px;
    border-radius: var(--rd-radius-sm);
    cursor: pointer;
    max-width: 100%;
    min-width: 0;
    color: inherit;
    transition: background var(--rd-dur-fast) var(--rd-ease);
  }
  .wi-row .inline-editable:hover {
    background: var(--rd-bg-active);
  }
  .wi-row .wi-title.inline-editable {
    cursor: text;
    display: inline-block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .wi-row .inline-field-value {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .wi-row .inline-edit-input {
    appearance: none;
    font-family: var(--rd-font-sans);
    font-size: var(--rd-text-sm);
    color: var(--rd-fg);
    background: var(--rd-bg-raised);
    border: 1px solid var(--rd-border-focus);
    border-radius: var(--rd-radius-sm);
    padding: 2px 6px;
    line-height: 1.2;
    height: 24px;
    min-width: 0;
    max-width: 100%;
  }
  .wi-row .inline-edit-input:focus {
    outline: none;
  }
  .wi-row input[type="date"].inline-edit-input {
    font-family: var(--rd-font-mono);
    min-width: 130px;
  }
  .wi-row input[type="number"].inline-edit-input {
    font-family: var(--rd-font-mono);
    width: 70px;
  }
  .wi-row select.inline-edit-input {
    cursor: pointer;
    padding-right: 18px;
  }
  .wi-row .wi-title-edit .inline-edit-input {
    width: 100%;
  }
  .wi-row .inline-save-indicator {
    margin-left: 6px;
    font-size: var(--rd-text-xs);
    color: var(--rd-fg-muted);
    white-space: nowrap;
  }
  .wi-row .inline-save-indicator.saved  { color: var(--rd-success); }
  .wi-row .inline-save-indicator.error  { color: var(--rd-danger); }
  .wi-row .inline-save-indicator.hidden { display: none; }

  /* Inline assignee (used in the assignees column) */
  .wi-row .inline-assignee-wrapper {
    position: relative;
    display: inline-flex;
    align-items: center;
  }
  .wi-row .inline-assignee-trigger {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 6px;
    border: 0;
    background: transparent;
    color: var(--rd-fg-muted);
    font-size: var(--rd-text-xs);
    border-radius: var(--rd-radius-sm);
    cursor: pointer;
  }
  .wi-row .inline-assignee-trigger:hover {
    background: var(--rd-bg-active);
    color: var(--rd-fg);
  }
  .wi-row .inline-assignee-trigger.text-muted {
    color: var(--rd-fg-subtle);
  }
  /* Rendered in the top layer (popover="manual") so the dropdown escapes
     the assignees column's overflow:hidden. The controller positions it
     in viewport coordinates after open. The popover is rendered the same
     way whether it's anchored from the row or from the expanded view's
     rail, so these rules apply to both contexts. */
  .inline-assignee-dropdown[popover] {
    position: fixed;
    inset: unset;
    margin: 0;
    min-width: 220px;
    max-width: 260px;
    background: var(--rd-bg-raised);
    border: 2px solid var(--pop-ink);
    border-radius: 0;
    box-shadow: var(--pop-shadow);
    padding: 4px;
    z-index: 50;
    overflow: visible;
  }
  .inline-assignee-dropdown[popover].hidden { display: none; }
  .inline-assignee-dropdown[popover] .inline-assignee-search {
    padding: 0;
    border-bottom: 0;
  }
  .inline-assignee-dropdown[popover] .inline-assignee-search input {
    width: 100%;
    font-family: var(--rd-font-sans);
    font-size: var(--rd-text-sm);
    color: var(--rd-fg);
    background: var(--rd-bg-sunken);
    border: 1px solid var(--rd-border);
    border-radius: var(--rd-radius-sm);
    padding: 4px 8px;
    margin-bottom: 4px;
  }
  .inline-assignee-dropdown[popover] .inline-assignee-list {
    max-height: 220px;
    overflow-y: auto;
  }
  .inline-assignee-dropdown[popover] .inline-assignee-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 8px;
    font-family: var(--rd-font-sans);
    font-size: var(--rd-text-sm);
    color: var(--rd-fg);
    background: transparent;
    border: 0;
    border-radius: var(--rd-radius-sm);
    text-align: left;
    cursor: pointer;
    transition: background var(--rd-dur-fast) var(--rd-ease);
  }
  .inline-assignee-dropdown[popover] .inline-assignee-item:hover {
    background: var(--rd-bg-hover);
  }
  .inline-assignee-dropdown[popover] .inline-assignee-item.selected {
    background: var(--rd-accent-soft);
    color: var(--rd-fg);
  }
  .inline-assignee-dropdown[popover] .inline-assignee-check {
    width: 14px;
    height: 14px;
    flex: 0 0 auto;
    color: var(--rd-accent);
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .inline-assignee-dropdown[popover] .inline-assignee-check svg {
    width: 14px;
    height: 14px;
  }
  .inline-assignee-dropdown[popover] .inline-assignee-name {
    flex: 1 1 auto;
    font-size: var(--rd-text-sm);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .inline-assignee-dropdown[popover] .inline-assignee-empty,
  .inline-assignee-dropdown[popover] .inline-assignee-loading {
    padding: 8px 10px;
    text-align: center;
    font-size: var(--rd-text-sm);
    color: var(--rd-fg-muted);
  }

  /* Actions column (⋯ link) */
  .wi-more-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: 0;
    background: transparent;
    color: var(--rd-fg-muted);
    cursor: pointer;
    border-radius: var(--rd-radius-sm);
  }
  .wi-more-btn:hover { color: var(--rd-fg); background: var(--rd-bg-hover); }

  /* Milestone 3-dot dropdown wrapper (anchor for positioned menu) */
  .milestone-more {
    position: relative;
    display: inline-flex;
  }
  /* Chevron + more-menu cluster — 2px gap matches the spacing between
     adjacent action buttons in the per-row actions cell below. Using
     a sub-flex container isolates this gap from .milestone-right's
     larger inter-item gap. */
  .milestone-actions-cluster {
    display: flex;
    align-items: center;
    gap: 2px;
  }

  /* Card 3-dot popover wrapper (anchor for top-layer popover menu) */
  .wi-more-container {
    display: inline-flex;
  }

  /* ------------------------------------------------------------------ */
  /* Drag-to-reorder handles                                            */
  /* ------------------------------------------------------------------ */
  .wi-drag-handle,
  .milestone-drag-handle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    padding: 0;
    background: transparent;
    color: var(--rd-fg-faint);
    cursor: grab;
    opacity: 0;
    transition: opacity 80ms ease, color 80ms ease;
  }
  /* Drag handle is overlaid on the lead cell / milestone head's left
     gutter so it doesn't reserve layout space when invisible at rest,
     letting the lead column collapse tight around the circle indicator
     and the milestone title sit close to the accent rule. */
  .wi-drag-handle,
  .milestone-drag-handle {
    position: absolute;
    left: 2px;
    top: 50%;
    transform: translateY(-50%);
    width: 14px;
    height: 18px;
  }
  /* Milestone head has a 3px accent bar at its left edge — nudge the
     handle inward so it clears the bar instead of overlapping it. */
  .milestone-drag-handle { left: 6px; }

  /* Reveal handles on hover / focus-within of the affected row or head */
  .wi-row:hover .wi-drag-handle,
  .wi-row:focus-within .wi-drag-handle,
  .milestone-head:hover .milestone-drag-handle,
  .milestone-head:focus-within .milestone-drag-handle {
    opacity: 1;
    color: var(--rd-fg-muted);
  }

  .wi-drag-handle:active,
  .milestone-drag-handle:active { cursor: grabbing; }

  /* SortableJS classes — subtle visual feedback */
  .sortable-ghost {
    opacity: 0.35;
  }
  .sortable-chosen { background: var(--rd-bg-hover); }
  .sortable-drag { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); }

  /* Hide handle on the "Unassigned" bucket head (not draggable) */
  .milestone-card.loose .milestone-drag-handle { display: none; }
}
