/* Poppins — a free geometric sans that closely matches the ClickUp reference (Gilroy).
   Bundled locally (../fonts) so it works offline and keeps the app self-contained. */
@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 300; font-display: swap; src: url('../fonts/poppins-300.woff2') format('woff2'); }
@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/poppins-400.woff2') format('woff2'); }
@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/poppins-500.woff2') format('woff2'); }
@font-face { font-family: 'Poppins'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/poppins-600.woff2') format('woff2'); }

:root {
  --sidebar-w: 300px;
  --row-h: 36px;
  --group-h: 32px;
  --header-h: 52px;
  --day-w-day: 42px;
  --day-w-week: 22px;
  --day-w-month: 7px;
  --day-w-quarter: 2.4px;

  --bg: #f6f7f9;
  --panel: #ffffff;
  --border: #e2e5ea;
  --border-strong: #cbd0d8;
  --text: #1f2430;
  --text-dim: #6b7280;
  --text-faint: #9aa1ac;
  --accent: #774ACB; /* violet — full scale (light/dark/tint) lives in gantt-colors.css */
  --accent-contrast: #ffffff;
  --danger: #e0503c;
  --weekend: #eef0f4;
  /* Three-step grey ladder, dark → light: date-header band, row hover, category headers.
     Each step is deliberately subtle but distinct. */
  --header-band: #f0f3f7;     /* dark   — date header (a tiny step darker than before) */
  --row-hover: #f3f5f9;       /* medium — sidebar row hover */
  --section-header: #f7f9fb;  /* light  — category header rows */
  --today: #774ACB; /* today line + highlighted header date follow the accent */
  --shadow: 0 6px 24px rgba(20, 24, 34, .12);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: 'Poppins', -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--text);
  background: var(--bg);
  font-size: 13px;
}

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

.app {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

/* ---------- Toolbar (redesign 7e) ---------- */
/* Single row, no wrap: identity left, floating add cluster centered by the two
   flex spacers, view + utility right. */
.toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  flex: 0 0 auto;
  flex-wrap: nowrap;
}
.tb-spacer { flex: 1; }
.tb-left, .tb-right { display: flex; align-items: center; gap: 12px; flex: none; }
.tb-right { gap: 8px; }
.tb-divider { width: 1px; height: 26px; background: var(--border); flex: none; }

/* Wordmark: logo tile L5d + product name */
.tb-wordmark { display: flex; align-items: center; gap: 9px; }
.tb-logo { flex: none; display: block; }
.tb-wordmark-text {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -.01em;
  white-space: nowrap;
}

/* Timeline switcher (native select dressed as the spec box) + rename pencil */
.tb-project { display: flex; align-items: center; gap: 4px; }
.tb-switcher {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 8px 10px 8px 12px;
  background: var(--panel);
  cursor: pointer;
  color: var(--text-faint); /* icon + chevron */
}
.tb-switcher select {
  appearance: none;
  -webkit-appearance: none;
  border: none;
  background: transparent;
  padding: 0;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text);
  max-width: 280px;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
  cursor: pointer;
  outline: none;
}
/* Inline rename: the input lives INSIDE the switcher box (icon + chevron stay put);
   the box itself signals edit mode with an accent border. */
.tb-rename-input {
  border: none;
  background: transparent;
  padding: 0;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text);
  max-width: 280px;
  outline: none;
}
.tb-switcher.editing { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-tint); cursor: text; }
.tb-switcher.editing .tb-chev { opacity: .35; }
.tb-iconbtn {
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--text-faint);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex: none;
  padding: 0;
}
.tb-iconbtn:hover { background: var(--accent-tint); color: var(--accent); }
.tb-morebtn { color: var(--text-dim); }

/* Floating add-action cluster — no border, no background box (defining feature of 7e) */
.tb-add-cluster { display: flex; align-items: center; gap: 2px; flex: none; }
.tb-add {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 7px 10px;
  border: none;
  border-radius: 7px;
  background: transparent;
  font-size: 11.5px;
  font-weight: 500;
  color: #4b5563;
  white-space: nowrap;
  cursor: pointer;
  transition: background .1s;
}
.tb-add-ic { display: flex; color: var(--text-dim); }
.tb-add:hover { background: var(--accent-tint); }
.tb-add:hover .tb-add-ic { color: var(--accent); }

/* Ghost buttons (Date Range, Day ▾, Today, Export) */
.tb-ghost {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 8px 13px;
  background: var(--panel);
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  cursor: pointer;
}
.tb-ghost:hover { background: #f7f8fa; }
.tb-strong { font-weight: 600; }
.tb-chev { color: var(--text-faint); flex: none; }

/* Weekends toggle */
.tb-weekends { display: flex; align-items: center; gap: 9px; }
.tb-weekends > span { font-size: 13px; font-weight: 500; color: #4b5563; white-space: nowrap; }
.tb-switch {
  position: relative;
  width: 36px;
  height: 20px;
  border: none;
  border-radius: 20px;
  background: #d8dbe0;
  cursor: pointer;
  padding: 0;
  flex: none;
  transition: background .12s;
}
.tb-switch[aria-checked="true"] { background: var(--accent); }
.tb-switch-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .25);
  transition: left .12s;
}
.tb-switch[aria-checked="true"] .tb-switch-knob { left: 18px; }

/* Buttons (modals & elsewhere — unchanged look) */
.btn {
  appearance: none;
  border: 1px solid var(--border-strong);
  background: var(--panel);
  color: var(--text);
  padding: 6px 12px;
  border-radius: 6px;
  cursor: pointer;
  font-weight: 500;
  white-space: nowrap;
}
.btn:hover { background: #f0f2f5; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.35; cursor: default; }
.btn:disabled:hover { background: var(--panel); }
.btn:disabled:active { transform: none; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
.btn-primary:hover { background: var(--accent-dark); }
.btn-danger { background: #fff; border-color: var(--danger); color: var(--danger); }
.btn-danger:hover { background: #fdecea; }
.btn-small { padding: 4px 8px; font-size: 12px; }

/* Dropdown menus */
.menu { position: relative; }
.menu-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(20, 24, 34, .14);
  display: none;
  flex-direction: column;
  min-width: 196px;
  padding: 6px;
  z-index: 100;
}
.menu-dropdown.open { display: flex; }
.menu-dropdown button {
  display: flex;
  align-items: center;
  gap: 10px;
  text-align: left;
  border: none;
  background: none;
  border-radius: 7px;
  padding: 8px 10px;
  font-size: 13px;
  font-weight: 400;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.menu-dropdown button:hover { background: #f0f2f5; }
.menu-dropdown button:disabled { color: #c7cbd1; cursor: default; }
.menu-dropdown button:disabled:hover { background: none; }
.menu-sep { height: 1px; background: var(--border); margin: 4px 2px; }

/* Meeting Schedule range picker — a small panel under the menu item, not a separate popup.
   The menu item highlights while its panel is open (mirrors #zoomDropdown button.active). */
#meetingScheduleBtn.active { background: var(--accent-tint); color: var(--accent); font-weight: 500; }
.mtg-range-panel { margin: 2px 8px 8px; background: #f7f8fa; border: 1px solid #e2e5ea; border-radius: 7px; padding: 10px 12px; }
.mtg-range-chips { display: flex; flex-wrap: wrap; gap: 6px; }
/* Chip/go rules carry the .menu-dropdown prefix: the generic `.menu-dropdown button` item
   styling (and its grey :hover) would otherwise out-rank them and repaint these controls. */
.menu-dropdown button.mtg-range-chip { padding: 5px 10px; border-radius: 14px; background: #fff; border: 1px solid #d7dbe1; font-size: 12px; color: #333; cursor: pointer; }
.menu-dropdown button.mtg-range-chip.sel,
.menu-dropdown button.mtg-range-chip.sel:hover { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); font-weight: 600; }
.mtg-range-custom { display: flex; align-items: center; gap: 6px; margin-top: 10px; font-size: 12px; color: #555; }
.mtg-range-custom input { border: 1px solid #d7dbe1; border-radius: 5px; padding: 4px 6px; font-size: 12px; }
/* display:flex above (and .menu-dropdown button's) outranks the UA [hidden] rule — restore
   hiding explicitly, same trap as the Time Off dropzone. */
.mtg-range-custom[hidden], .menu-dropdown button.mtg-range-go[hidden] { display: none; }
.menu-dropdown button.mtg-range-go,
.menu-dropdown button.mtg-range-go:hover { margin-top: 10px; width: 100%; justify-content: center; background: var(--accent); color: var(--accent-contrast); border: none; border-radius: 5px; padding: 7px 0; font-size: 12.5px; font-weight: 600; cursor: pointer; }
.tb-menu { width: 196px; min-width: 0; }
.tb-mi { display: flex; width: 16px; justify-content: center; color: var(--text-dim); flex: none; }
.menu-dropdown button:disabled .tb-mi { color: #c7cbd1; }
.tb-danger { color: #c0304a !important; }
.tb-danger .tb-mi { color: #c0304a; }
.tb-danger:hover { background: #fdecef !important; }
/* View dropdown rows hover lavender; the active row reads as selected (accent text, tinted) */
#zoomDropdown button:hover { background: var(--accent-tint); }
#zoomDropdown button.active { background: var(--accent-tint); color: var(--accent); font-weight: 500; }

/* Narrow windows: the bar never wraps — collapse lower-priority items step by step
   (wordmark text → add labels → Date Range/Today into the ⋮ menu → tighter paddings). */
.tb-narrow-row { display: none !important; }
@media (max-width: 1360px) {
  .tb-wordmark-text { display: none; }
}
@media (max-width: 1200px) {
  .tb-add-label { display: none; }          /* add cluster → icon-only (titles carry labels) */
  .tb-add { padding: 8px 9px; }
  .tb-switcher select { max-width: 170px; }
}
@media (max-width: 1000px) {
  #rangeBtn, #todayBtn { display: none; }   /* … they reappear as rows in the ⋮ menu */
  .tb-narrow-row { display: flex !important; }
  div.tb-narrow-row { display: block !important; } /* the separator */
  .tb-weekends > span { display: none; }    /* switch keeps its title tooltip */
  .toolbar { padding: 12px 14px; gap: 8px; }
  .tb-left { gap: 8px; }
  .tb-switcher select { max-width: 120px; }
}
@media (max-width: 840px) {
  .tb-switcher select { max-width: 88px; }
  .tb-add { padding: 8px 7px; }
  .tb-right { gap: 6px; }
  .toolbar { padding: 12px 10px; }
}

/* ---------- Toast (undo/redo feedback) ---------- */
#toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  background: #22262b;
  color: #fff;
  font-size: 13px;
  font-weight: 500;
  padding: 8px 16px;
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.25);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
  z-index: 300;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }


/* ---------- Grid scaffold ---------- */
.gantt-scroll {
  flex: 1 1 auto;
  overflow: auto;
  position: relative;
  background: var(--panel);
}
.gantt-grid {
  display: grid;
  grid-template-columns: var(--sidebar-w) max-content;
  grid-template-rows: var(--header-h) max-content max-content;
  width: max-content;
  min-width: 100%;
}

.corner {
  grid-column: 1;
  grid-row: 1;
  position: sticky;
  top: 0;
  left: 0;
  z-index: 40;
  background: var(--panel);
  border-top: 1px solid var(--border-strong); /* closes the outer frame at the top */
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
}

.header-row {
  grid-column: 2;
  grid-row: 1;
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--panel);
  border-top: 1px solid var(--border-strong); /* closes the outer frame at the top */
  border-bottom: 1px solid var(--border);
  height: var(--header-h);
}

.sidebar-col {
  grid-column: 1;
  grid-row: 2;
  position: sticky;
  left: 0;
  /* Above dragging bars/milestones (z-index 25) so a bar dragged left is hidden behind the
     frozen pane, not painted over it. Still below the header (30) and corner (40). */
  z-index: 28;
  background: var(--panel);
  border-right: 1px solid var(--border);
}

.chart-col {
  grid-column: 2;
  grid-row: 2;
  position: relative;
}
.chart-inner { position: relative; }

/* ---------- Header (date columns) ---------- */
.header-tier {
  position: relative;
  height: 26px;
  border-bottom: 1px solid var(--border);
}
.header-tier.tier-2 { height: 26px; border-bottom: none; }
/* Darker Monday marker that runs the full header height, continuous with the chart line. */
.header-week-line {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--border-strong);
  pointer-events: none;
}
/* Alternating grey band over the tier-1 period (weeks in day view, months in week view) —
   the darkest step of the grey ladder (header > hover > category). */
.header-band {
  position: absolute;
  top: 1px; /* sit just below the frame's top border so the line keeps full contrast/weight */
  bottom: 0;
  background: var(--header-band);
  pointer-events: none;
}
.header-cell {
  position: absolute;
  top: 0;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border-right: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-dim);
  overflow: hidden;
  white-space: nowrap;
}
.header-tier.tier-1 .header-cell { font-weight: 600; color: var(--text); justify-content: flex-start; padding-left: 6px; }
/* Day-view week labels: centered over the week span, not left-aligned. */
.header-tier.tier-1.tier-1-center .header-cell { justify-content: center; padding-left: 0; text-transform: uppercase; }
/* Week view: smaller cell text so the date range + "wk1" count fits comfortably. */
.header-tier.tier-2-small .header-cell { font-size: 10px; }
/* Sequential week count appended to week-view cells, e.g. "07/06 - 07/10 wk1". */
.wk-num { color: var(--text-faint); font-size: 9px; margin-left: 4px; }
.header-cell.weekend { background: var(--weekend); }
.header-cell.is-today-col { color: var(--today); font-weight: 600; }

/* ---------- Sidebar rows ---------- */
.sb-group {
  display: flex;
  align-items: center;
  gap: 6px;
  height: var(--group-h);
  padding: 0 8px 0 6px;
  border-bottom: 1px solid var(--border);
  background: var(--section-header);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .03em;
  cursor: grab;
  user-select: none;
}
.sb-group:active { cursor: grabbing; }
.sb-group .caret { transition: transform .15s; flex: none; font-size: 12px; }
.sb-group.collapsed .caret { transform: rotate(-90deg); }
.sb-group .grp-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sb-group .grp-add,
.sb-group .grp-edit { opacity: 0; color: var(--text-faint); flex: none; cursor: default; }
.sb-group:hover .grp-add,
.sb-group:hover .grp-edit { opacity: 1; }
.sb-group .grp-add {
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  padding: 0 3px;
  border-radius: 4px;
}
.sb-group .grp-add:hover, .sb-group .grp-edit:hover { color: var(--accent); }

.sb-row {
  display: flex;
  align-items: center;
  gap: 6px;
  height: var(--row-h);
  padding: 0 8px 0 20px;
  border-bottom: 1px solid var(--border);
  cursor: grab;
}
.sb-row:active { cursor: grabbing; }
.sb-row:hover { background: var(--row-hover); }
.sb-row.selected { background: var(--accent-tint); }

/* Drag-to-reorder feedback */
.sb-dragging { opacity: .4; }
.sb-drop-indicator {
  position: absolute;
  left: 2px;
  right: 2px;
  height: 2px;
  margin-top: -1px;
  background: var(--accent);
  border-radius: 2px;
  z-index: 26;
  pointer-events: none;
}
/* Drag-to-merge: the hovered row is the task the dragged one will become a phase of. */
.sb-row.sb-merge-target {
  background: var(--accent-tint);
  box-shadow: inset 0 0 0 2px var(--accent);
  border-radius: 6px;
}
/* Cross-task phase drag: band marking the task row a lifted phase pill will drop into.
   Sits behind the bars (inserted before barsLayer) with a see-through fill, so the target
   row's existing phases stay fully visible while dragging. */
.phase-drop-target {
  position: absolute;
  left: 0;
  z-index: 0;
  background: rgba(119, 74, 203, .10);
  box-shadow: inset 0 0 0 2px var(--accent);
  border-radius: 6px;
  pointer-events: none;
}
/* A phase pill mid-lift toward another task reads as detached (above bars, accent ring). */
.bar.phase-lifting { z-index: 40; box-shadow: 0 4px 14px rgba(20, 24, 34, .28), 0 0 0 2px var(--accent); }
.sb-row .task-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sb-row .avatars { display: flex; }
.sb-row .add-row {
  color: var(--text-faint);
}

.avatar {
  /* "Negative" style: white fill, initials + outline in the category color (set inline). */
  width: 18px; height: 18px;
  border-radius: 50%;
  background: #fff;
  color: var(--accent);
  font-size: 9px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  margin-left: -6px;
  border: 1.5px solid var(--accent);
  flex: none;
}
.avatar:first-child { margin-left: 0; }

/* Day/Week views drop the sidebar row lines to match the chart's column-only grid.
   Group headers keep their shaded background so categories stay distinct. */
#sidebarCol.no-row-lines .sb-row,
#sidebarCol.no-row-lines .sb-group { border-bottom: none; }
/* A Time Off lane row that isn't its team's last drops its divider, so a multi-person team
   reads as one bordered block instead of a stack of blank lines (PR#24). */
.sb-row.no-line { border-bottom: none; }

/* ---------- Chart area ---------- */
.bars-layer, .dep-layer { position: absolute; top: 0; left: 0; }
.dep-layer { pointer-events: none; overflow: visible; }

.grid-row-bg {
  position: absolute;
  left: 0; right: 0;
  border-bottom: 1px solid var(--border);
}
.grid-row-bg.no-hline { border-bottom: none; }
.grid-row-bg.group { background: var(--section-header); }
/* Time Off: alternating design teams pick up the category grey so teams separate at a glance. */
.grid-row-bg.shaded { background: var(--section-header); }
.sb-row.sb-shaded { background: var(--section-header); }
.sb-row.sb-shaded:hover { background: var(--row-hover); }
.grid-col-weekend {
  position: absolute;
  top: 0;
  background: var(--weekend);
}
.grid-col-line {
  position: absolute;
  top: 0;
  width: 1px;
  background: var(--border);
}
/* Week-start (Monday) boundary in day view — darker so weeks read at a glance. */
.grid-col-line.week-start { background: var(--border-strong); }
/* Outer frame edges closing the grid on the right and bottom (all zoom levels). */
.grid-col-line.grid-edge-right { background: var(--border-strong); }
.grid-col-line.grid-edge-bottom { left: 0; height: 1px; width: auto; background: var(--border-strong); }

.today-marker {
  position: absolute;
  top: 0;
  width: 2px;
  background: var(--today);
  /* No explicit z-index: the marker sits just before the bars layer in the DOM, so it
     paints on top of the grey background fills / grid lines but BEHIND the pills. */
  pointer-events: none;
}
.today-marker::after {
  content: "Today";
  position: absolute;
  top: 2px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--today);
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  padding: 1px 5px;
  border-radius: 4px;
  white-space: nowrap;
}

.bar {
  position: absolute;
  height: calc(var(--row-h) - 12px);
  top: 6px;
  /* Fully rounded (pill) start/end edges, like ClickUp. Large value clamps to half-height. */
  border-radius: 999px;
  display: flex;
  align-items: center;
  color: #fff;
  font-size: 11.5px;
  font-weight: 400;
  cursor: grab;
  box-shadow: 0 1px 2px rgba(0,0,0,.15);
  user-select: none;
  overflow: visible;
}
.bar:active { cursor: grabbing; }
.bar.dragging { opacity: .85; box-shadow: 0 4px 14px rgba(0,0,0,.28); z-index: 25; }
.bar .bar-label {
  padding: 0 8px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  pointer-events: none;
}
/* Very narrow pills (single-column spans in coarse zooms): tiny centered label, no side
   padding, so a two-letter initial fits instead of clipping to one. */
.bar.bar-tiny .bar-label {
  padding: 0 1px;
  font-size: 9px;
  letter-spacing: 0;
  text-align: center;
  text-overflow: clip;
}
/* Centered pill label (time-off name pills). */
.bar.bar-center .bar-label { text-align: center; }
/* Floating text phase (single-day time off): the label IS the marker — no pill fill,
   no shadow, text in the phase's own color. */
.bar.phase-floating {
  background: transparent !important;
  font-size: 11.5px; /* same as the pill labels */
  font-weight: 500;
  justify-content: center;
}
.bar.phase-floating:not(.selected) { box-shadow: none; }
.bar.phase-floating .bar-label { padding: 0; text-align: center; text-overflow: clip; }
.bar .handle {
  position: absolute;
  top: 0; bottom: 0;
  width: 8px;
  cursor: ew-resize;
  z-index: 2;
}
.bar .handle.left { left: -2px; }
.bar .handle.right { right: -2px; }
.bar .bar-avatars {
  display: flex;
  /* Ref B: the avatar sits closer to the pill's right edge, so the ring of pill colour
     around it reads as a thin border rather than a band. */
  padding-right: 3px;
  pointer-events: none;
}
.bar .due-flag {
  position: absolute;
  top: -8px;
  width: 10px;
  height: 16px;
  /* Ref B: nudged 3px left of dead-centre so the marker's tip meets the stroke of the
     assignee circle beneath it instead of overlapping its middle. */
  transform: translateX(calc(-50% - 3px));
  cursor: ew-resize;
  z-index: 3;
}
.bar .due-flag svg { width: 100%; height: 100%; filter: drop-shadow(0 1px 1px rgba(0,0,0,.3)); }

.milestone {
  position: absolute;
  width: 18px;
  height: 18px;
  transform: translateX(-50%);
  cursor: grab;
}
.milestone .ms-shape {
  display: block;
  width: 100%;
  height: 100%;
  /* drop-shadow (not box-shadow) so the depth traces the shape outline, not a box.
     Lighter than v1 per the marker-set-v2 handoff. */
  filter: drop-shadow(0 1px 1.5px rgba(0,0,0,.14));
}
.milestone:active { cursor: grabbing; }
.milestone.dragging .ms-shape { filter: drop-shadow(0 3px 5px rgba(0,0,0,.35)); }
.milestone.dragging { z-index: 25; }
/* Meeting/milestone glyphs get NO selection ring/halo — the lavender sidebar row is the
   selection indicator. (The ring read as a muddy grey halo on the grey marker set.) */
.ms-shape { overflow: visible; }
.ms-ring { display: none; }

/* Sidebar milestone glyph: same shape geometry, uniform size, inherits row text color (black) */
.ms-glyph {
  display: inline-block;
  vertical-align: -2px;
  margin-right: 5px;
  flex: none;
}

/* Selected bar (Batch W): full-strength fill (no opacity fade — that read as the color
   itself dimming), a thin white inset stroke on the piece, and a tighter translucent ring.
   The ring keys off --ring-color — the bar's HUE FAMILY medium, resolved in render.js —
   so all three shades of one family show the identical ring; a custom off-palette color
   rings in itself. */
.bar.selected {
  outline: none;
  box-shadow:
    0 0 0 1.5px #fff inset,
    0 1px 2px rgba(0,0,0,.15),
    0 0 0 2px color-mix(in srgb, var(--ring-color, var(--bar-color, var(--accent))) 30%, transparent);
  z-index: 5;
}

/* Bottom date bar: the header repeated after the last row so dates stay readable at the
   foot of a tall chart, with the tiers REVERSED (day numbers first, period label under
   them) so the pair reads outward from the chart in both directions. */
.footer-row {
  grid-column: 2;
  grid-row: 3;
  position: relative;
  background: var(--panel);
  border-top: 1px solid var(--border);
  height: var(--header-h);
}
.corner-bottom {
  grid-column: 1;
  grid-row: 3;
  position: sticky;
  left: 0;
  z-index: 20;
  top: auto;
  background: var(--panel);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border-strong); /* closes the outer frame at the bottom */
}
/* Reversed order puts the hairline between the tiers on the other one. */
.footer-row .header-tier.tier-1 { border-bottom: none; }
.footer-row .header-tier.tier-2 { border-bottom: 1px solid var(--border); }

/* Time Off pills sit in the tighter row height, so they get a shorter pill than a task
   bar (which reserves headroom for deliverable markers Time Off never has). */
.bar.bar-compact { height: 18px; font-size: 11px; }
.bar.bar-compact .bar-label { padding: 0 6px; }

/* ---------- Action-button tooltip (design 9a) ---------- */
.action-tip {
  position: fixed;
  z-index: 300;
  background: #1f2430;
  color: #d5dae3;
  font-size: 12px;
  font-weight: 400;
  padding: 5px 10px;
  border-radius: 6px;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(20, 24, 34, .18);
  pointer-events: none;
  opacity: 0;
  transition: opacity .1s ease;
}
.action-tip.show { opacity: 1; }

/* ---------- Hover summary tooltip (design 10e) ---------- */
/* Dark surface with a TASK ▸ phase ▸ deliverable hierarchy; each phase carries its real
   bar color on a left rule; dates sit inline right after their label. */
.tooltip {
  position: fixed;
  background: #1f2430;
  border-radius: 8px;
  padding: 14px 16px;
  /* Match #taskModal (460px) so long agenda lines wrap far less (PR#23). The flip/clamp
     logic in showTooltip measures the real rendered size, so no other change is needed. */
  max-width: 460px;
  z-index: 200;
  /* Pass clicks + native drags through by default so a tooltip never blocks the chart or a
     sidebar-row drop underneath it. Only a tooltip carrying a link opts into capturing the
     mouse (.tooltip.has-link) so that link stays reachable (PR#22). */
  pointer-events: none;
  box-shadow: 0 8px 30px rgba(20, 24, 34, .28);
  line-height: 1.45;
  font-size: 12px;
}
.tooltip.has-link { pointer-events: auto; }
/* Meeting/milestone tooltips render at ONE fixed width so hovering along a row of
   markers doesn't produce a differently-sized card each time. Task/phase/deliverable
   tooltips keep shrink-to-fit (max-width) — they carry short, uniform content. */
.tooltip:has(.tip-title-point) { width: 460px; box-sizing: border-box; }
/* Tooltip links: real contrast on the dark surface (default blue is unreadable), and wrap a
   long URL rather than blow out the tooltip's max-width. */
.tooltip a {
  color: #8ab4ff;
  text-decoration: underline;
  overflow-wrap: anywhere;
}
/* Task title — the top of the hierarchy */
.tooltip .tip-title {
  color: #fff;
  font-size: 12.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
}
/* Parent-task kicker above a single phase-bar summary */
.tooltip .tip-kicker {
  color: #8b93a3;
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.tooltip .tip-kicker-sub { margin-top: 3px; text-transform: none; letter-spacing: 0; font-weight: 400; }
/* Meta line: pipe-separated segments (range | days | wks); divider adds a hairline */
.tooltip .tip-metabar { color: #8b93a3; font-size: 12px; margin-top: 4px; }
.tooltip .tip-divider { padding-bottom: 10px; border-bottom: 1px solid rgba(255, 255, 255, .1); }
.tooltip .tip-pipe { color: rgba(255, 255, 255, .22); margin: 0 8px; }
/* Phase list */
.tooltip .tip-phases { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.tooltip .tip-phase { border-left: 2px solid #774acb; padding-left: 10px; }
.tooltip .tip-phase-solo { margin-top: 6px; }
.tooltip .tip-phase-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.tooltip .tip-phase-name { color: #eef0f3; font-size: 12.5px; font-weight: 600; }
.tooltip .tip-phase-title { color: #fff; font-size: 12.5px; font-weight: 600; }
.tooltip .tip-range { color: #8b93a3; font-size: 11.5px; }
/* Deliverable rows — name then date, inline, stuck to the text */
.tooltip .tip-dels { margin-top: 4px; }
.tooltip .tip-del { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-top: 3px; }
.tooltip .tip-del-name { color: #d5dae3; font-size: 12px; }
.tooltip .tip-date { color: #8b93a3; font-size: 11.5px; }
/* Notes — italic, above a top hairline */
.tooltip .tip-notes {
  color: #8b93a3;
  font-size: 12px;
  font-style: italic;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, .1);
}
/* Optional milestone/meeting name — a quiet subtitle right under the title. */
.tooltip .tip-subname {
  color: #cfd5e0;
  font-size: 12px;
  font-weight: 600;
  margin-top: 2px;
}
/* Meeting agenda: labelled, regular weight and full-strength text — deliberately NOT the
   italic/grey notes look, so agenda and notes read as different things at a glance. */
.tooltip .tip-agenda {
  color: #e8ebf1;
  font-size: 12px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, .1);
}
.tooltip .tip-agenda-label {
  color: #8b93a3;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  margin-bottom: 3px;
}
/* Range arrow glyph (inline SVG so it never emojifies) */
.tooltip .tip-arrow { width: 13px; height: 6px; vertical-align: middle; }

/* ---------- Modal ---------- */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(20,24,34,.4);
  display: flex; align-items: center; justify-content: center;
  z-index: 300;
}
.modal-backdrop[hidden] { display: none; }
.modal {
  position: relative;
  background: var(--panel);
  border-radius: 10px;
  padding: 20px 22px;
  width: 460px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  box-shadow: var(--shadow);
}
.modal-small { width: 340px; }
/* Explicit close (×) in the modal header — with backdrop-click-to-close removed, the only
   ways out are Cancel, the ×, or Save, so a stray click outside can't dismiss edits. */
.modal-x {
  position: absolute;
  top: 14px; right: 14px;
  width: 28px; height: 28px;
  border: none; background: none;
  border-radius: 8px;
  color: #9aa1ac;
  font-size: 20px; line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.modal-x:hover { background: #f0f2f5; color: var(--text); }
/* Section modal: wide enough for the full 9-swatch color row on one line. */
#catModal { width: 410px; }
.modal h2 { margin: 0 0 14px; font-size: 16px; }
.modal-note { margin: 0 0 12px; font-size: 12px; line-height: 1.5; color: var(--text-dim); }

/* Time Off modal: Import CSV / Add one entry tab strip. */
.timeoff-tabs { display: flex; gap: 4px; margin-bottom: 14px; border-bottom: 1px solid var(--border); }
.timeoff-tab { padding: 8px 4px; border: none; background: none; color: var(--text-faint);
  font-weight: 600; font-size: 13px; cursor: pointer; border-bottom: 2px solid transparent; }
.timeoff-tab.active { color: var(--accent); border-bottom-color: var(--accent); }

/* ---------- Time Off modal: dropzone + selected-file chip ---------- */
/* `display:flex` below outranks the UA [hidden] rule, so restore hiding explicitly. */
.timeoff-dropzone[hidden], .timeoff-file-chip[hidden] { display: none; }
.timeoff-dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
  padding: 26px 16px;
  border: 2px dashed var(--accent-light, #885DDF);
  background: var(--accent-tint, #F3EFFA);
  border-radius: 10px;
  color: var(--accent, #774ACB);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.timeoff-dropzone:hover,
.timeoff-dropzone:focus-visible,
.timeoff-dropzone.drag-over {
  border-color: var(--accent, #774ACB);
  background: color-mix(in srgb, var(--accent-tint, #F3EFFA) 60%, #ffffff);
  outline: none;
}
.timeoff-dropzone-label {
  font-size: 13.5px;
  font-weight: 600;
  color: #1f2430;
}

.timeoff-file-chip {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1.5px solid var(--accent, #774ACB);
  background: var(--accent-tint, #F3EFFA);
  border-radius: 10px;
  color: var(--accent, #774ACB);
}
.timeoff-file-chip-name {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  font-weight: 600;
  color: #1f2430;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.timeoff-file-chip-remove {
  flex: none;
  border: none;
  background: none;
  font-size: 18px;
  line-height: 1;
  color: #9aa1ac;
  cursor: pointer;
  padding: 0 2px;
}
.timeoff-file-chip-remove:hover { color: #1f2430; }

.timeoff-summary {
  font-size: 12.5px;
  color: #b0223f; /* only ever shown on parse error now */
}
.timeoff-summary:empty { display: none; }
.field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.field > span, .field > label { font-size: 12px; font-weight: 600; color: var(--text-dim); text-transform: uppercase; letter-spacing: .04em; }
/* Not labels — keep natural case/weight. */
.field-hint, .field > span.duration-readout { text-transform: none; letter-spacing: normal; }
.field > span.duration-readout { font-weight: 500; }
.field-hint { font-weight: 400; color: var(--text-faint); }
.field input[type=text], .field input[type=date], .field select, .field textarea {
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 7px 9px;
}
/* Textareas grow taller only — dragging wider used to push the box past its modal and force
   the whole popup into horizontal scroll, clipping labels (PR#22). Height resize stays. */
.field textarea { resize: vertical; }
.field input[type=color] {
  width: 100%; height: 34px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 2px;
}
.duration-readout { font-size: 12px; color: var(--text-dim); font-weight: 500; }
.field-row { display: flex; gap: 12px; }
/* min-width: 0 lets a field shrink below its input's intrinsic width — without it a pair
   of text inputs refuses to share a row in the narrower modals and forces an h-scrollbar
   (the event modal's Division/Show row was the visible casualty). */
.field-row .field { flex: 1; min-width: 0; }
.checkbox-field { flex-direction: row; align-items: center; gap: 8px; }
.checkbox-field input { width: 16px; height: 16px; }

.deliverable-list { display: flex; flex-direction: column; gap: 6px; }
.deliverable-entry { display: flex; flex-direction: column; gap: 4px; }
.deliverable-entry + .deliverable-entry { margin-top: 8px; }
.deliverable-row { display: flex; gap: 6px; align-items: center; }
/* Optional per-deliverable / per-phase note, tucked under its row as part of the item. */
.deliverable-entry .del-notes,
.phase-row .phase-notes {
  resize: vertical;
  font-family: inherit;
  line-height: 1.35;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 5px 8px;
  font-size: 12.5px;
  color: var(--text-dim);
}
.deliverable-row .del-name {
  flex: 1;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 6px 8px;
  min-width: 0;
}
.deliverable-row .del-date {
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 6px 6px;
  width: 142px;
  flex: none;
}
.deliverable-row .del-date.custom-date-only { flex: 1; width: auto; }
.deliverable-row .remove-deliverable {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  background: none;
  border-radius: 7px;
  color: var(--text-faint);
  cursor: pointer;
  padding: 0;
}
.deliverable-row .remove-deliverable:hover { background: #f0f2f5; color: var(--text); }
.add-deliverable-btn { align-self: flex-start; margin-top: 2px; }
/* Replace the browser's default focus ring (renders orange on some systems) with the
   app's accent border. */
.deliverable-row .del-name:focus, .deliverable-row .del-date:focus { outline: none; border-color: var(--accent); }

.phase-list { display: flex; flex-direction: column; gap: 8px; }
.phase-row {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: #fafbfc; /* same light grey as the category rows */
}
.phase-assignees {
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.phase-assignees-label { font-size: 11px; font-weight: 500; color: var(--text-faint); text-transform: uppercase; letter-spacing: .02em; }
/* Quiet add links (8a): read as links, not buttons — accent text, hover underline */
.add-link {
  display: flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: none;
  padding: 2px 0;
  color: var(--accent);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  align-self: flex-start;
  white-space: nowrap;
}
.add-link .add-plus { font-size: 15px; line-height: 1; }
.add-link:hover { color: var(--accent-dark); }

/* "Assign to" row: half-width search bar with the dependency control beside it
   (link / picker / chip, depending on state) */
/* Top-aligned: the dep column centers on the bar's FIRST line (34px control height), so
   the link/chip stays put as added member chips wrap the bar taller. */
.phase-assign-grid { display: flex; align-items: flex-start; gap: 14px; }
.phase-assign-grid > .multiselect { flex: 0 0 50%; max-width: 50%; }
.phase-dep-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; justify-content: center; min-height: 34px; }
.phase-dep-col .phase-dep-label { margin-top: 0; }
/* Full-width "Depends on" picker row that appears below the assign row while choosing */
.phase-dep-row { display: flex; flex-direction: column; gap: 6px; margin-top: 2px; }

/* Dependency chip (8e): single dependency shown as a tinted chip; × clears it */
.phase-dep-label { margin-top: 4px; }
.dep-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.dep-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--accent-tint);
  color: var(--accent);
  border-radius: 14px;
  padding: 4px 11px;
  font-size: 12.5px;
  font-weight: 500;
}
.dep-chip-x {
  border: none;
  background: none;
  color: var(--accent);
  opacity: .7;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0;
}
.dep-chip-x:hover { opacity: 1; }
.phase-row-top { display: flex; gap: 6px; align-items: center; }
/* #fPhases-prefixed for specificity: must outrank ".field input[type=color]" (used by
   the main task's single color-override field), which would otherwise also match here
   since the phases block itself sits inside an element with class="field". */
#fPhases .phase-row-top .phase-name {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 6px 8px;
}
/* Same focus treatment as the deliverable inputs: no browser default ring (renders
   orange on some systems), accent border instead. */
#fPhases .phase-row-top .phase-name:focus { outline: none; border-color: var(--accent); }
/* Placeholders match the multiselect "Search" treatment: grey italics */
.phase-name::placeholder, .del-name::placeholder { font-style: italic; color: var(--text-faint); }
#fPhases .phase-row-top .phase-color {
  width: 30px; height: 30px;
  flex: none;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 2px;
}
.phase-row-dates { display: flex; gap: 6px; align-items: center; }
#fPhases .phase-row-dates .phase-start, #fPhases .phase-row-dates .phase-end {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 6px 6px;
}
.phase-row-dates .phase-arrow { color: var(--text-faint); flex: none; }
.phase-deliverables {
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.phase-deliverables-label { font-size: 11px; font-weight: 500; color: var(--text-faint); text-transform: uppercase; letter-spacing: .02em; }
.phase-deliverable-list { display: flex; flex-direction: column; gap: 6px; }
.phase-deliverables .add-phase-deliverable-btn { align-self: flex-start; }

.range-quick { display: flex; gap: 6px; flex-wrap: wrap; }

/* ---------- Color swatch (Section + Color override pickers, phase trio) ---------- */
.swatch-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.phase-shade-picker { display: flex; gap: 4px; }
.swatch {
  width: 30px; height: 30px;
  flex: none;
  border-radius: 9.6px; /* ~32% of size */
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08);
  transition: transform .1s ease;
}
.swatch:hover { transform: scale(1.03); }
.swatch.is-selected { box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--accent); }
.swatch-check { width: 13px; height: 13px; opacity: 0; pointer-events: none; }
.swatch.is-selected .swatch-check { opacity: 1; }
.swatch-sm { width: 26px; height: 26px; border-radius: 8px; }
.swatch-sm.is-selected { box-shadow: 0 0 0 1.5px #fff, 0 0 0 3px var(--accent); }
.swatch-sm .swatch-check { width: 11px; height: 11px; }

/* Neutral icon button (phase "remove" trash) — common edit, not destructive styling. */
.icon-btn {
  flex: none;
  width: 30px; height: 30px;
  border: none; background: none;
  border-radius: 8px;
  color: #9aa1ac;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.icon-btn:hover { background: #f0f2f5; color: var(--text); }

.shape-picker { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.shape-group-label {
  font-size: 10px;
  font-weight: 500;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: .03em;
  flex: none;
}
.shape-group-label:not(:first-child) { margin-left: 8px; }
.shape-swatch {
  width: 32px; height: 32px;
  border: 2px solid var(--border-strong);
  border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  background: var(--panel);
  color: var(--text-dim); /* the inlined SVG uses currentColor */
}
.shape-swatch svg { display: block; }
.shape-swatch:hover { background: #f0f2f5; }
.shape-swatch.active { border-color: var(--accent); background: var(--accent-tint); color: var(--accent); }

/* Multi-select search picker (Assignees, Depends on) — selected items as chips + a search
   input that filters the dropdown list. */
.multiselect { position: relative; }
.ms-control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
  min-height: 34px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 5px 7px;
  background: var(--panel);
  cursor: text;
}
.ms-control:focus-within { border-color: var(--accent); }
.ms-chips { display: contents; }
.ms-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--accent-tint);
  color: var(--accent);
  font-weight: 500;
  border-radius: 20px;
  padding: 2px 6px 2px 10px;
  font-size: 12px;
  white-space: nowrap;
}
.ms-chip-x { border: none; background: none; color: var(--accent); cursor: pointer; font-size: 14px; line-height: 1; padding: 0; opacity: .8; }
.ms-chip-x:hover { opacity: 1; }
.ms-search {
  flex: 1;
  min-width: 90px;
  border: none !important;
  outline: none;
  padding: 2px !important;
  font-size: 13px;
  background: transparent;
}
.ms-search::placeholder { font-style: italic; color: var(--text-faint); }
/* Overlay dropdown: floats above the surrounding fields instead of pushing them down
   (the .multiselect wrapper is the position:relative anchor). */
.ms-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 50;
  max-height: 200px;
  overflow-y: auto;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--panel);
  padding: 4px;
  box-shadow: 0 8px 24px rgba(20, 24, 34, .14);
}
.ms-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 13px;
  user-select: none;
}
.ms-option:hover { background: #f0f2f5; }
.ms-optlabel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-avatar {
  flex: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  color: #fff; font-weight: 600; font-size: 9.5px;
  display: flex; align-items: center; justify-content: center;
}
/* Inline "Add <query> as team member" row in the Assign-to picker. */
.ms-option-addnew { background: var(--accent-tint); border-radius: 7px; padding: 8px 10px; }
.ms-option-addnew:hover { background: color-mix(in srgb, var(--accent-tint) 65%, #fff); }
.ms-add-icon { display: flex; flex: none; }
.ms-add-label { color: var(--accent); font-size: 13.5px; font-weight: 400; }
.ms-noresult { padding: 6px 8px; font-size: 12px; color: var(--text-faint); }
.ms-empty { color: var(--text-faint); font-size: 12px; }

.chip-picker { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  border: 1px solid var(--border-strong);
  border-radius: 20px;
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
  background: var(--panel);
  user-select: none;
}
.chip.active { background: var(--accent); border-color: var(--accent); color: #fff; }

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

/* ---------- Team Members roster ---------- */
.member-list { margin-bottom: 12px; }
.member-count { font-size: 12px; color: #9aa1ac; margin-bottom: 6px; }
.member-roster {
  max-height: 280px;
  overflow-y: auto;
  border: 1px solid #eef0f3;
  border-radius: 9px;
  padding: 2px 10px;
}
.member-row {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 48px;
  border-bottom: 1px solid #eef0f3;
}
.member-roster .member-row:last-child { border-bottom: none; }
.member-avatar {
  flex: none;
  width: 30px; height: 30px;
  border-radius: 50%;
  color: #fff; font-weight: 600; font-size: 12.6px;
  display: flex; align-items: center; justify-content: center;
}
.member-name-input {
  flex: 1; min-width: 0;
  border: none; background: none;
  font-size: 14px; color: #1f2430;
  padding: 4px 2px;
  border-bottom: 1px solid transparent;
}
.member-name-input:focus { outline: none; border-bottom-color: var(--accent); }
.member-remove { width: 28px; height: 28px; border-radius: 7px; }
.member-empty { color: var(--text-faint); font-size: 12px; padding: 8px 2px; }

.member-add-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.member-add-row input {
  flex: 1;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 9px 10px;
  font-size: 13px;
}
.member-add-btn {
  flex: none;
  width: 38px; height: 38px;
  border: none; border-radius: 8px;
  background: var(--accent); color: #fff;
  font-size: 22px; line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.member-add-btn:hover { background: var(--accent-dark); }

/* ---------- Empty state ---------- */
.empty-hint {
  position: absolute;
  color: var(--text-faint);
  font-size: 13px;
  padding: 8px;
  pointer-events: none;
}

/* ---------- Print / export ---------- */
/* Header block (project name · range · export date). Styled outside @media print so the
   PNG snapshot (which embeds this stylesheet) renders it identically to the PDF. */
/* One row across the top of the chart exports: big title upper-left, range beside it on
   the same baseline, italic stamp pushed hard right (the chart fills the page, so the
   stamp lives up here instead of a footer). Shown as flex while printing (PR#28). */
.print-header { display: none; margin: 0 0 10px; align-items: baseline; gap: 20px; }
.print-header .print-line1 { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; min-width: 0; }
.print-header .print-title { font-size: 34px; font-weight: 600; color: #1a1a1a; letter-spacing: -.015em; line-height: 1.1; }
.print-header .print-range { font-size: 13px; color: #9aa1ac; letter-spacing: .01em; }
.print-header .print-meta { font-size: 11px; color: #b6bcc6; letter-spacing: .02em; font-style: italic; margin-left: auto; white-space: nowrap; }

/* Mirrored date footer (exists only during PDF/PNG export): a clone of the header's two
   tiers as a third grid row, reversed — day numbers on top, week range at the very
   bottom. Overrides the cloned .header-row's sticky/row-1 placement. */
.export-footer-row {
  grid-row: 3;
  grid-column: 2;
  position: relative;
  z-index: auto;
  top: auto;
  background: var(--panel);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border-strong); /* closes the outer frame at the bottom */
  height: var(--header-h);
}
.export-footer-row .header-tier.tier-2 { border-bottom: 1px solid var(--border); }
.export-footer-row .header-tier.tier-1 { border-bottom: none; }
.export-footer-corner {
  grid-row: 3;
  grid-column: 1;
  background: var(--panel);
  border-right: 1px solid var(--border);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border-strong);
}

/* Sequence export (design 11a — date-spine timeline). Styled outside @media print (hidden
   by default, shown while printing) so an on-screen preview renders identically. The white
   card IS the page: events sorted chronologically down a single grey spine. */
.print-seq {
  display: none;
  width: 600px;
  margin: 0 auto;
  background: #fff;
  border: 1px solid #e6e8ec;
  border-radius: 12px;
  padding: 34px 40px 40px;
  color: #1f2430;
}
.print-seq .seq-title { font-size: 19px; font-weight: 600; letter-spacing: -.01em; }
.print-seq .seq-mode { font-style: italic; font-weight: 400; color: #9aa1ac; font-size: 16px; }
.print-seq .seq-sub { font-size: 11.5px; color: #9aa1ac; margin-top: 3px; letter-spacing: .01em; }
.print-seq .seq-body { position: relative; margin-top: 26px; }
/* The spine is positioned, so it intentionally paints OVER the markers' white halos. */
.print-seq .seq-spine { position: absolute; left: 64px; top: 6px; bottom: 22px; width: 2px; background: #e6e8ec; }
.print-seq .seq-rows { display: flex; flex-direction: column; gap: 19px; }
.print-seq .seq-row { display: flex; align-items: flex-start; }
/* Date column: grey for tasks, ink for milestones, category color (inline, 700) for
   deadlines, 700 ink for the closing milestone. */
.print-seq .seq-date { width: 52px; flex: none; text-align: right; padding-top: 1px; font-size: 11px; font-weight: 600; letter-spacing: .03em; color: #9aa1ac; }
.print-seq .seq-row.seq-milestone .seq-date { color: #3f4657; }
.print-seq .seq-row.seq-deadline .seq-date { font-weight: 700; }
.print-seq .seq-row.seq-final .seq-date { font-weight: 700; color: #3f4657; }
.print-seq .seq-dow { font-size: 8.5px; font-weight: 600; color: #b6bcc6; letter-spacing: .08em; line-height: 1.4; }
.print-seq .seq-marker { width: 26px; flex: none; display: flex; justify-content: center; padding-top: 3px; }
/* Milestone: real shape SVG (star or no-pole flag) in the item's real color — sits
   directly on top of the grey spine line. */
.print-seq .m-glyph { position: relative; display: inline-block; vertical-align: middle; margin-top: -2px; }
/* Deadline: filled diamond in the category color (background set inline per event). */
.print-seq .m-diamond { display: inline-block; position: relative; width: 10px; height: 10px; transform: rotate(45deg); }
/* Task start: hollow ring in the category color (border set inline per event). */
.print-seq .m-ring { display: inline-block; position: relative; width: 11px; height: 11px; border-radius: 50%; background: #fff; border: 2px solid; }
.print-seq .seq-content { flex: 1; min-width: 0; }
.print-seq .seq-kicker { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; }
.print-seq .seq-kicker-ms { color: #9aa1ac; }
.print-seq .seq-name { font-size: 13.5px; font-weight: 600; color: #1f2430; line-height: 1.35; margin-top: 1px; }
.print-seq .seq-row.seq-deadline .seq-name { font-weight: 700; }
.print-seq .seq-row.seq-final .seq-name { font-size: 14px; font-weight: 700; }
.print-seq .seq-owner { font-weight: 400; font-style: italic; color: #9aa1ac; font-size: 12px; }
.print-seq .seq-range { font-size: 12px; color: #6b7280; margin-top: 1px; }
.print-seq .seq-footer { font-size: 10.5px; color: #b6bcc6; letter-spacing: .02em; text-align: right; margin-top: 24px; font-style: italic; }

/* Meeting Schedule export — same .print-seq card chrome as Sequence (one family). One
   flat row per meeting (PR#32): a fixed date column, then the body — glyph + name inline
   and left-aligned, with the Agenda (checkbox per line) / Notes columns indented under it.
   Weeks flow continuously, separated by a small label rather than a page break.
   (--accent = #774ACB is the app's real purple token — used directly here since this is
   a print stylesheet, not the live UI where var(--accent) would apply.) */
.print-seq .mtg-weeklabel { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; color: #b6bcc6; padding: 16px 0 10px; }
.print-seq .mtg-weeklabel-first { padding-top: 4px; }
.print-seq .mtg { display: flex; border-top: 1px solid #eef0f3; padding: 14px 0 16px; }
.print-seq .mtg-datecol { width: 76px; flex: none; }
.print-seq .mtg-date { font-size: 17px; font-weight: 600; color: #1f2430; letter-spacing: -.01em; white-space: nowrap; }
.print-seq .mtg-dow { font-size: 8.5px; font-weight: 600; color: #b6bcc6; text-transform: uppercase; letter-spacing: .08em; white-space: nowrap; }
.print-seq .mtg-body { flex: 1; min-width: 0; }
.print-seq .mtg-name { display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: #774ACB; }
.print-seq .mtg-nametext { min-width: 0; }
/* The occurrence name sits inline after an em-dash, in Sentence case — it must opt out of
   the series name's uppercase and letter-spacing explicitly. */
.print-seq .mtg-subname { font-size: 11.5px; font-weight: 400; text-transform: none; letter-spacing: 0; color: #6b7280; }
.print-seq .mtg-glyph { display: block; flex: none; }
/* Indented to the NAME text (past the glyph), not the row edge. min-width:0 on both
   columns kills the min-content floor so a long unbreakable URL in Notes can't squeeze
   Agenda (PR#28). */
.print-seq .mtg-cols { display: flex; gap: 26px; margin-left: 22px; margin-top: 9px; }
.print-seq .mtg-col-agenda { flex: 1.2; min-width: 0; }
.print-seq .mtg-col-notes { flex: 1; min-width: 0; }
.print-seq .mtg-colhead { font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .14em; color: #9aa1ac; margin-bottom: 4px; }
.print-seq .mtg-agenda-item { display: flex; align-items: flex-start; gap: 9px; margin-top: 5px; font-size: 11.5px; line-height: 1.55; color: #3f4657; }
.print-seq .mtg-agenda-item .mtg-check { width: 13px; height: 13px; border: 1.5px solid #d4d8de; border-radius: 4px; background: #fcfcfd; margin-top: 3px; flex: none; display: block; }
/* One span per line (PR#28) so a wrapped line aligns under the text, not the checkbox. */
.print-seq .mtg-agenda-item span { flex: 1; min-width: 0; }
/* A typed blank line between agenda groups — space, not a checkbox row (PR#33). */
.print-seq .mtg-agenda-gap { height: 9px; }
.print-seq .mtg-agenda-item b, .print-seq .mtg-agenda-item strong { font-weight: 600; }
.print-seq .mtg-notes { font-size: 11.5px; line-height: 1.55; color: #3f4657; overflow-wrap: anywhere; }
/* overflow-wrap:anywhere alone does NOT break a long URL inside an <a> — break-all does. */
.print-seq .mtg-notes a, .print-seq .mtg-agenda-item a { word-break: break-all; }
.print-seq .mtg-empty { font-size: 11.5px; color: #b6bcc6; font-style: italic; }
/* Nothing on either side: one quiet line under the name instead of two empty columns. */
.print-seq .mtg-empty-row { margin-left: 22px; margin-top: 4px; }

/* Calendar export (PR#35) — a month grid in the same .print-seq card. Each week is one
   table row holding a CSS grid: day cells span the full row height as the background, and
   phase bars / point items are placed into lanes above them. The table exists so <thead>
   can repeat the weekday header at the top of every printed page. */
.print-cal .cal-month + .cal-month { margin-top: 26px; }
.print-cal .cal-table { width: 100%; table-layout: fixed; border-collapse: collapse; margin-top: 8px; }
.print-cal .cal-table th {
  font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em;
  color: #9aa1ac; text-align: left; padding: 0 0 5px 7px; font-family: inherit;
}
.print-cal .cal-table td { padding: 0; vertical-align: top; }
.print-cal .cal-week { display: grid; position: relative; }
/* Day cell = the background layer: it spans every row of the week so the column rules run
   the full height however tall the week grows. */
.print-cal .cal-cell { border: 1px solid #eceef2; margin: -0.5px 0 0 -0.5px; min-height: 46px; }
.print-cal .cal-cell-we { background: #fafbfc; }
.print-cal .cal-daynum { display: block; font-size: 9.5px; color: #9aa1ac; padding: 3px 0 0 7px; line-height: 1; }
.print-cal .cal-daynum-we { color: #c4cad3; }
/* Phase bar. The rounded cap is half the bar height (9.5px of 19px) — a true capsule end,
   deliberately far from the square week-clipped edge it has to be told apart from. */
.print-cal .cal-seg {
  position: relative; height: 19px; margin: 0 2px 2px 3px; display: flex; align-items: center;
  font-size: 10px; font-weight: 500; line-height: 1; overflow: hidden; box-sizing: border-box;
}
.print-cal .cal-seg span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Event box — the frame everything else hangs off: a SOLID fill in the event's own colour
   with white type, deliberately unlike anything else on the grid. It spans and clips like a
   bar but takes none of the phase-relationship marks (PR#36). */
.print-cal .cal-event {
  position: relative; display: flex; align-items: center; gap: 4px;
  min-height: 19px; margin: 0 2px 2px 3px; padding: 2px 4px; border-radius: 3px;
  color: #fff; font-size: 10px; font-weight: 600; line-height: 1.25;
  overflow: hidden; box-sizing: border-box;
}
.print-cal .cal-evglyph { display: block; flex: none; }
.print-cal .cal-event span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Point item = a soft tint chip (never bare text on white): 12% fill, glyph and label in the
   full-strength colour, wrapping to at most three clamped lines rather than ellipsizing. */
.print-cal .cal-point {
  position: relative; display: flex; align-items: flex-start; gap: 3px;
  margin: 0 2px 2px 3px; padding: 2px 4px; border-radius: 3px;
  font-size: 9.5px; line-height: 1.3; min-width: 0;
}
.print-cal .cal-glyph { display: block; flex: none; margin-top: 1px; }
.print-cal .cal-diamond { width: 8px; height: 8px; transform: rotate(45deg); flex: none; margin-top: 2px; }
.print-cal .cal-plabel {
  min-width: 0; font-weight: 600; line-height: 1.3;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
/* The occurrence name is its OWN line inside the chip, not inline after an em-dash. */
.print-cal .cal-sub { display: block; font-weight: 500; }

/* Task-list agenda. Styled outside @media print (hidden by default, shown while
   printing) so an on-screen preview renders identically to the printed page.
   Layout: left content · dotted leader · right-aligned date column. */
.print-list { display: none; color: #1a1a1a; font-size: 12px; max-width: 720px; }
.print-list .pl-title { font-size: 20px; font-weight: 600; margin: 0 0 2px; }
.print-list .pl-meta { font-size: 11px; color: #666; margin: 0 0 6px; }
.print-list .pl-cat {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  border-bottom: 1px solid #d8dbe0; padding-bottom: 4px; margin: 18px 0 8px;
}
.print-list .pl-dot { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.print-list .pl-task { margin: 0 0 10px; }
.print-list .pl-row { display: flex; align-items: baseline; gap: 8px; }
.print-list .pl-left { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.print-list .pl-fill { flex: 1; border-bottom: 1px dotted #c9cdd4; transform: translateY(-3px); min-width: 24px; }
.print-list .pl-dates { white-space: nowrap; color: #444; font-variant-numeric: tabular-nums; }
.print-list .pl-dates b { color: #1a1a1a; }
.print-list .pl-task-name { font-weight: 600; font-size: 12.5px; }
.print-list .pl-people { color: #777; font-style: italic; font-size: 11px; }
.print-list .pl-phase { margin-top: 2px; }
.print-list .pl-phase .pl-left { padding-left: 18px; }
.print-list .pl-phase-name { font-weight: 500; }
.print-list .pl-del { margin-top: 1px; color: #333; }
.print-list .pl-del .pl-left { padding-left: 18px; }
.print-list .pl-del-phase .pl-left { padding-left: 36px; }
.print-list .pl-notes { margin: 2px 0 0 18px; color: #666; font-style: italic; font-size: 11px; }

@media print {
  @page { size: landscape; margin: 8mm; }
  /* Print background colors/fills (bar & header colors) — off by default in browsers. */
  * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }
  body { background: #fff; }

  .print-header { display: flex; } /* flex, not block — margin-left:auto pushes the stamp right */
  .toolbar, .modal-backdrop, .tooltip, #toast, .sb-row .row-actions { display: none !important; }
  .gantt-scroll { overflow: visible; height: auto; }
  .gantt-grid { width: max-content; }
  /* Use relative (not static) so these stay positioning contexts: the header's month-shading
     band (.header-band, top:0/bottom:0) must size to the header height, not stretch down the
     whole grid and paint grey over the chart. z-index reset so nothing overlaps the chart. */
  .sidebar-col, .header-row, .corner { position: relative; z-index: auto; }
  .app { height: auto; }

  /* Shrink the full-width chart to fit the page with transform:scale — a pure visual scale, so
     rows and bars stay pixel-aligned (zoom rounds them independently and drifts). The scroller
     is clamped to the scaled footprint (overflow hidden) so the print engine sees the fitted
     size and never clips the right side. */
  body.printing .gantt-scroll {
    width: var(--print-w, auto);
    height: var(--print-h, auto);
    overflow: hidden;
  }
  body.printing .gantt-grid {
    transform: scale(var(--print-scale, 1));
    transform-origin: top left;
  }

  /* ----- Task-list agenda (portrait) — replaces the chart when printing the list.
     Visual styles live outside @media print; this block only swaps chart → list and
     controls page breaks. ----- */
  body.printing-list .gantt-scroll { display: none !important; }
  body.printing-list .print-list { display: block; }
  .print-list .pl-section { break-inside: auto; }
  .print-list .pl-task { break-inside: avoid; }

  /* ----- Sequence card (portrait) — replaces the chart when printing the sequence. ----- */
  body.printing-seq .gantt-scroll { display: none !important; }
  body.printing-seq .print-seq { display: block; }
  .print-seq .seq-row { break-inside: avoid; }

  /* ----- Calendar (portrait). A week row must never split across a page; months start a
     fresh page; the weekday header repeats via table-header-group. ----- */
  body.printing-cal .gantt-scroll { display: none !important; }
  body.printing-cal .print-seq {
    display: block; width: auto; max-width: none;
    margin: 0; padding: 0; border: none; border-radius: 0;
  }
  .print-cal .cal-table thead { display: table-header-group; }
  .print-cal .cal-weekrow { break-inside: avoid; page-break-inside: avoid; }
  .print-cal .cal-month + .cal-month { break-before: page; page-break-before: always; margin-top: 0; }

  /* ----- Meeting Schedule card (portrait) — mirrors printing-seq; its own class so
     Sequence and Meeting Schedule never both show. On paper the card chrome drops and
     content fills the page inside the 14mm @page margin (Sequence keeps its 600px card). ----- */
  body.printing-mtgsched .gantt-scroll { display: none !important; }
  body.printing-mtgsched .print-seq {
    display: block; width: auto; max-width: none;
    /* .app is a column flex container and .print-seq carries `margin: 0 auto` — auto
       cross-axis margins cancel the flex stretch, so width:auto alone left the card
       shrink-to-fit instead of filling the page box PR#28 asked for. */
    margin: 0;
    padding: 0; border: none; border-radius: 0;
  }
  .print-seq .mtg { break-inside: avoid; }
}

/* ============================================================
   Read-only viewer (view.html). Scoped under body.viewer: the shared renderer emits the
   builder's editing affordances (group +/✎, resize handles, grab cursors), so the viewer
   suppresses them here. viewer.js additionally strips draggable attributes after every
   render — CSS alone still leaves the native drag ghost.
   ============================================================ */

/* Timeline identity in the toolbar: static name + published date, replacing the switcher. */
.viewer-ident { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.viewer-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.viewer-published { font-size: 12px; color: var(--text-faint); white-space: nowrap; }

/* Editing affordances that the shared renderer emits regardless of mode. */
body.viewer .grp-add,
body.viewer .grp-edit { display: none; }
body.viewer .bar .handle { display: none; }

/* Neutral cursors: nothing in the viewer grabs, resizes, or edits. Bars and rows keep
   default so the only "interactive" feel is the hover tooltip. */
body.viewer .sb-group,
body.viewer .sb-group:active,
body.viewer .sb-row,
body.viewer .sb-row:active,
body.viewer .bar,
body.viewer .bar:active,
body.viewer .milestone { cursor: default; }
/* Collapsing sections IS available — keep the pointer on the group caret/name. */
body.viewer .sb-group { cursor: pointer; }
body.viewer .sb-row:hover { background: transparent; }
body.viewer .sb-row.sb-shaded:hover { background: var(--section-header); }

/* Honest empty/error state (missing ?t=, unknown slug, unreadable file). */
.viewer-message { display: flex; justify-content: center; padding: 96px 24px; }
/* display:flex would silently defeat the hidden attribute's UA display:none — keep it
   authoritative (the toolbar's controls are hidden the same way on the error page). */
.viewer-message[hidden] { display: none; }
body.viewer .tb-right[hidden] { display: none; }
.viewer-message-box {
  max-width: 480px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 28px 32px;
  text-align: center;
  box-shadow: var(--shadow);
}
.viewer-message-title { font-size: 16px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.viewer-message-body { font-size: 13px; color: var(--text-dim); }

/* ---------- Hosted builder (app.html) chrome ---------- */
/* Save-status chip: the one visible truth about persistence. Green=saved, amber=in
   flight, red=needs attention (click to retry). */
.save-status {
  font-size: 12.5px; font-weight: 600; padding: 4px 10px; border-radius: 999px;
  white-space: nowrap; user-select: none;
}
.save-status[data-state="saved"] { color: #1b7a4f; background: #e7f5ee; }
.save-status[data-state="dirty"], .save-status[data-state="saving"] { color: #8a6d00; background: #fdf6dd; }
.save-status[data-state="error"], .save-status[data-state="conflict"] { color: #b3261e; background: #fdecec; cursor: pointer; }
.share-toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.share-url-row { display: flex; align-items: center; gap: 8px; }
.share-url { flex: 1; overflow-wrap: anywhere; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; font-size: 12.5px; }

/* Quiet live-feed note (sharing paused / connection lost). Sits under the toolbar and never
   replaces the chart — the last rendered timeline stays readable underneath. */
.viewer-note {
  padding: 7px 16px; font-size: 12.5px; color: #8a6d00;
  background: #fffbe8; border-bottom: 1px solid #ecdca0;
}

/* ---------- EVENTS band (design ref: event-markers-13c.html) ---------- */
.sb-events-band {
  display: flex; align-items: flex-start; padding: 14px 0 0 14px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .1em; color: var(--text-faint);
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}
.event-marker {
  position: absolute; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center;
  cursor: grab; z-index: 4; user-select: none;
}
.event-marker:active { cursor: grabbing; }
.event-marker .event-label {
  font-size: 9.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  /* pre (not pre-line, Batch X): manual line breaks render as typed and the text NEVER
     auto-wraps beyond them — a title is exactly as many lines as she typed. A long title
     with no break runs wide by design; breaks are hers to place, always. */
  color: var(--text); line-height: 1.25; white-space: pre; text-align: center; margin-top: 6px;
  pointer-events: none;
}
.event-marker .event-bar { display: block; height: 8px; border-radius: 4px; }
.event-marker.selected .event-glyph, .event-marker.selected .event-bar {
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--bar-color, var(--accent)) 60%, transparent));
}
/* Viewer: events are display-only like everything else. */
body.viewer .event-marker { cursor: default; }

/* ---------- Dependency picker tree (Batch T) ---------- */
/* Category → Task → phases/deliverables, folded shut by default; searching auto-expands
   only the branches that still match. Single-select: clicking a leaf picks it. */
.dep-tree {
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #fff;
  margin-top: 6px;
  padding: 4px;
}
.dt-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  border: none;
  background: none;
  padding: 6px 8px;
  border-radius: 6px;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  text-align: left;
}
.dt-toggle:hover { background: #f0f2f5; }
.dt-cat-toggle {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-dim);
}
.dt-chev { flex: none; transition: transform .12s; color: var(--text-dim); }
.dt-toggle.open .dt-chev { transform: rotate(90deg); }
.dt-children { margin-left: 16px; }
.dt-leaf {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
}
.dt-leaf:hover { background: #f0f2f5; }
.dt-leaf .dt-flag { flex: none; color: var(--text-dim); }

/* Occurrence modal: four actions (Delete / Edit series / Cancel / Save) need more room
   than modal-small offers — widen it and let the row wrap rather than clip the Save. */
#occModal { width: 430px; }
#occModal .modal-actions { flex-wrap: wrap; row-gap: 8px; }

/* Event modal: two date fields plus the full 9-swatch color row need the same width the
   Section modal already claims for its swatch row — modal-small forced a horizontal
   scrollbar that hid the Marker picker past the right edge. */
#eventModal { width: 410px; }

/* ---------- Custom phase color (Batch W) ---------- */
/* 4th tile beside the family trio: dashed border, live-previews the current pick. */
.phase-shade-picker { position: relative; }
.swatch-custom { border: 1.5px dashed #fff; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .18); }
/* Popover: the full 9-family × 3-shade palette + the native-picker hand-off. */
.custom-color-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 90;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
  padding: 8px;
}
.ccp-grid {
  display: grid;
  grid-template-columns: repeat(9, 26px);
  gap: 4px;
  margin-bottom: 6px;
}
