/* ── Design tokens ─────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* The browser's own [hidden] rule is display:none, but any author class setting
   display (e.g. .alert-banner { display: flex }) overrides it, leaving elements
   marked hidden fully visible. Restore the attribute's meaning app-wide. */
[hidden] { display: none !important; }

:root {
  /* ── Colour ────────────────────────────────────────────────────────────────
     The 2026 redesign palette. Cool greys throughout, replacing the earlier
     warm neutrals; the accent blue barely moved (#185FA5 → #1d5db8). The role
     names below are ours — the ramps they map onto are the handoff's. */

  /* Neutral ramp */
  --n-100: #ffffff;  --n-200: #eef0f3;  --n-300: #e0e3e8;
  --n-400: #c3c8d0;  --n-500: #9aa1ad;  --n-600: #6b7280;
  --n-700: #4b5563;  --n-800: #374151;  --n-900: #1f2937;

  /* Blue (accent) ramp */
  --a-100: #eff5fd;  --a-200: #dbeafe;  --a-300: #bcd6f7;
  --a-400: #7fb0ec;  --a-500: #3b82d6;  --a-600: #1d5db8;
  --a-700: #1a4b96;  --a-800: #163b74;  --a-900: #122c55;

  /* Green (accent-2) ramp */
  --g-100: #ecfdf5;  --g-200: #d1fae5;  --g-300: #a7ecca;
  --g-400: #5fd3a3;  --g-500: #10b981;  --g-600: #059669;
  --g-700: #047857;  --g-800: #065f46;  --g-900: #064e3b;

  --bg-page:       #f6f7f9;
  --bg-surface:    #ffffff;
  --bg-subtle:     #fbfbfc;
  --bg-hover:      var(--n-200);
  --bg-selected:   var(--a-100);
  --bg-info:       var(--a-200);
  --bg-success:    var(--g-200);
  --bg-warning:    #fde8c8;
  --bg-danger:     #fee2e2;

  --text-primary:  #111827;
  --text-secondary:var(--n-700);
  --text-tertiary: var(--n-600);
  --text-info:     var(--a-700);
  --text-success:  var(--g-700);
  --text-warning:  #92400e;
  --text-danger:   #b91c1c;

  --border:        #e5e7eb;
  /* Lighter than --border, for rules inside a card or list. Referenced in three
     places but never defined until now, which silently dropped those borders. */
  --border-subtle: var(--n-200);
  --border-md:     var(--n-300);
  --border-strong: var(--n-400);

  --accent:        #1d5db8;
  --accent-hover:  var(--a-700);

  /* Radius scale from the 2026 redesign handoff (6 / 10 / 14). */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 16px;

  --font:      'Hanken Grotesk', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;

  /* Shadow scale from the handoff. lg is for slide-overs and modals. */
  --shadow-sm: 0 1px 2px rgba(17,24,39,0.06);
  --shadow-md: 0 2px 8px rgba(17,24,39,0.08);
  --shadow-lg: 0 16px 40px rgba(17,24,39,0.18);

  /* ── Priority semantics ──────────────────────────────────────────────────
     From the handoff. Our domain names the top level Critical and the middle
     one Medium, where the design says Urgent and Normal; the colours carry
     over unchanged. */
  --pri-critical-bg: #FEE2E2;  --pri-critical-fg: #B91C1C;  --pri-critical-bar: #EF4444;
  --pri-high-bg:     #FDE8C8;  --pri-high-fg:     #92400E;  --pri-high-bar:     #F59E0B;
  --pri-medium-bg:   #DBEAFE;  --pri-medium-fg:   #1A4B96;  --pri-medium-bar:   #3B82D6;
  --pri-low-bg:      #EEF0F3;  --pri-low-fg:      #6B7280;  --pri-low-bar:      #C3C8D0;
}

/* Headings carry the handoff's tighter tracking. */
h1, h2, h3, h4, h5, h6 { letter-spacing: -0.02em; line-height: 1.12; }

/* Every interactive element gets a visible focus ring — the handoff is explicit
   that the browser default is never acceptable. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Quieter scrollbars throughout, per the handoff. */
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb {
  background: var(--border-md);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-track { background: transparent; }

html, body {
  height: 100%;
  font-family: var(--font);
  background: var(--bg-page);
  color: var(--text-primary);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* ── Shell layout ──────────────────────────────────────────────────────────── */
.shell {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

/* ── Sidebar ───────────────────────────────────────────────────────────────
   Three fixed regions: brand, a nav that scrolls on its own, and the user card
   pinned to the floor. The nav scrolls so a long board list can never push the
   user card off screen. */
.sidebar {
  width: 244px;
  flex-shrink: 0;
  background: var(--bg-page);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Same height, background and rule as .topbar, so the brand block and the page
   title read as one continuous white header strip across the top of the app
   rather than two separate panels meeting at a corner. */
.sidebar-logo {
  height: 56px;
  padding: 0 14px;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.logo-mark {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
/* The mark is a transparent PNG, so it needs its own white ground now that the
   sidebar sits on the tinted page colour. */
.logo-img {
  width: 34px; height: 34px;
  object-fit: contain;
  flex-shrink: 0;
  background: #ffffff;
  border-radius: var(--radius-sm);
  padding: 2px;
}
.logo-text {
  font-size: 13.5px; font-weight: 600;
  color: var(--text-primary); letter-spacing: -0.2px;
  line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.logo-sub {
  font-size: 11px; color: var(--text-tertiary); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding-bottom: 12px;
  /* A quiet scrollbar — the nav should not look like a scrolling region until
     it actually needs to be one. */
  scrollbar-width: thin;
  scrollbar-color: var(--border-md) transparent;
}
.sidebar-nav::-webkit-scrollbar { width: 8px; }
.sidebar-nav::-webkit-scrollbar-thumb {
  background: var(--border-md); border-radius: 8px;
  border: 2px solid var(--bg-page);
}
.sidebar-nav::-webkit-scrollbar-track { background: transparent; }

.nav-section {
  padding: 16px 20px 6px;
  font-size: 10px;
  font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 12px;
  margin: 2px 10px;
  border-radius: 8px;
  font-size: 13.5px;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.14s ease, color 0.14s ease;
  user-select: none;
  text-decoration: none;
}
.nav-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-item i {
  font-size: 18px; flex-shrink: 0;
  color: var(--text-tertiary);
  transition: color 0.14s ease;
}
.nav-item:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
  text-decoration: none;
}
.nav-item:hover i { color: var(--text-secondary); }
.nav-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.nav-item.active {
  background: var(--bg-surface);
  color: var(--text-primary);
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(17,24,39,0.06), 0 0 0 1px rgba(17,24,39,0.05);
}
.nav-item.active i { color: var(--accent); }
/* Marker sits flush against the sidebar edge, aligned to the item's margin. */
.nav-item.active::before {
  content: "";
  position: absolute;
  left: -10px; top: 50%;
  transform: translateY(-50%);
  width: 3px; height: 18px;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}

/* Count of boards, sitting at the end of the Boards row. */
.nav-count {
  margin-left: auto;
  flex-shrink: 0;
  font-size: 10.5px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-tertiary);
  background: var(--border);
  padding: 1px 7px;
  border-radius: 20px;
}
.nav-item.active .nav-count { color: var(--accent); background: var(--bg-info); }

/* Individual boards nested under the Boards nav item, with a guide rail so the
   nesting reads without relying on indentation alone. */
.nav-group { position: relative; margin: 2px 0 4px; }
.nav-group::before {
  content: "";
  position: absolute;
  left: 31px; top: 2px; bottom: 2px;
  width: 1px;
  background: var(--border-md);
}
.nav-item--sub {
  padding: 6px 12px 6px 34px;
  margin: 1px 10px;
  font-size: 12.5px;
  gap: 8px;
}
.nav-item--sub i { font-size: 9px; color: var(--border-strong); }
.nav-item--sub:hover i { color: var(--text-tertiary); }
.nav-item--sub.active { font-weight: 600; }
.nav-item--sub.active i { color: var(--accent); }
.nav-item--sub.active::before { height: 14px; }

/* The open board's own views, a step further in again. Their icons are real glyphs
   rather than the bullet the board links use, so the two levels stay distinguishable. */
.nav-item--view { padding-left: 46px; font-size: 12px; }
.nav-item--view i { font-size: 14px; color: var(--text-tertiary); }
.nav-item--view.active i { color: var(--accent); }

.nav-badge {
  margin-left: auto;
  background: var(--accent);
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 20px;
  line-height: 1.6;
}

/* User card, pinned to the floor of the sidebar. */
.sidebar-bottom { margin-top: auto; flex-shrink: 0; padding: 10px; }
.sidebar-user {
  padding: 9px 10px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  background: var(--bg-surface);
  box-shadow: 0 0 0 1px rgba(17,24,39,0.06);
  transition: box-shadow 0.14s ease, background 0.14s ease;
}
.sidebar-user:hover {
  background: var(--bg-surface);
  box-shadow: 0 1px 3px rgba(17,24,39,0.10), 0 0 0 1px rgba(17,24,39,0.12);
}
.user-avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; font-weight: 600;
  color: #fff;
  flex-shrink: 0;
}
/* A real photo replaces the initials disc, so it has to fill the same circle rather
   than sit letterboxed inside it. */
.user-avatar--photo { object-fit: cover; background: none; }
.user-id { min-width: 0; flex: 1; }
.user-name {
  font-size: 12.5px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.user-role { font-size: 11px; color: var(--text-tertiary); }
.user-signout {
  font-size: 16px; color: var(--text-tertiary); flex-shrink: 0;
  transition: color 0.14s ease;
}
.sidebar-user:hover .user-signout { color: var(--text-danger); }

/* ── Main area ─────────────────────────────────────────────────────────────── */
.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}

.topbar {
  padding: 0 24px;
  height: 56px;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}
.page-title { font-size: 16px; font-weight: 600; color: var(--text-primary); letter-spacing: -0.2px; }
.topbar-right { display: flex; align-items: center; gap: 8px; }

.content {
  flex: 1;
  overflow-y: auto;
  padding: 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* ── Buttons ───────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px;
  border-radius: var(--radius-md);
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  transition: background 0.13s, transform 0.1s;
  border: 1px solid transparent;
  font-family: var(--font);
  text-decoration: none;
}
.btn:active { transform: scale(0.97); }
.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
  border-color: var(--border-md);
}
.btn-ghost:hover { background: var(--bg-hover); color: var(--text-primary); text-decoration: none; }
.btn-primary {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 1px 3px rgba(24,95,165,0.3);
}
.btn-primary:hover { background: var(--accent-hover); text-decoration: none; }
.btn-success {
  background: var(--g-700);
  color: #fff;
  box-shadow: 0 1px 3px rgba(59,109,17,0.3);
}
.btn-success:hover { background: var(--g-800); }
.btn-danger {
  background: var(--text-danger);
  color: #fff;
}
.btn-danger:hover { background: #991b1b; }
.btn-sm { padding: 5px 10px; font-size: 12px; }
.btn-full { width: 100%; justify-content: center; }
.btn i { font-size: 15px; }

/* ── SLA summary cards ─────────────────────────────────────────────────────── */
.sla-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}
.sla-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px;
  box-shadow: var(--shadow-sm);
}
.sla-card-label {
  font-size: 11px;
  color: var(--text-secondary);
  display: flex; align-items: center; gap: 5px;
  margin-bottom: 8px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.sla-card-label i { font-size: 14px; }
.sla-card-value { font-size: 24px; font-weight: 600; color: var(--text-primary); letter-spacing: -0.5px; }
.sla-card-value.plan { font-size: 15px; margin-top: 2px; }
.sla-card-sub { font-size: 11px; color: var(--text-secondary); margin-top: 4px; }
.sla-bar-track { height: 5px; background: var(--bg-page); border-radius: 99px; margin-top: 10px; overflow: hidden; }
.sla-bar-fill  { height: 100%; border-radius: 99px; }
.sla-card-link { text-decoration: none; cursor: pointer; transition: box-shadow 0.15s, transform 0.1s; }
.sla-card-link:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.10); transform: translateY(-1px); }

/* ── Ticket list card ──────────────────────────────────────────────────────── */
.tickets-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
}
.tickets-head {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  gap: 12px;
  flex-wrap: wrap;
}
.tickets-head-title { font-size: 14px; font-weight: 600; color: var(--text-primary); }
.filter-pills { display: flex; gap: 6px; flex-wrap: wrap; }
.pill {
  font-size: 12px;
  padding: 4px 12px;
  border-radius: 99px;
  border: 1px solid var(--border-md);
  color: var(--text-secondary);
  cursor: pointer;
  transition: all 0.12s;
  font-weight: 500;
  text-decoration: none;
  background: none;
  font-family: var(--font);
}
.pill:hover { background: var(--bg-hover); text-decoration: none; color: var(--text-primary); }
.pill.active {
  background: var(--bg-info);
  color: var(--text-info);
  border-color: rgba(24,95,165,0.25);
}

/* ── Ticket rows ───────────────────────────────────────────────────────────── */
.ticket-row {
  display: flex;
  align-items: center;
  padding: 13px 18px;
  border-bottom: 1px solid var(--border);
  gap: 12px;
  cursor: pointer;
  transition: background 0.1s;
  text-decoration: none;
  color: inherit;
}
.ticket-row:last-child { border-bottom: none; }
.ticket-row:hover { background: var(--bg-hover); text-decoration: none; }

.priority-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.p-critical { background: var(--pri-critical-bar); }
.p-high     { background: var(--pri-high-bar); }
.p-medium   { background: var(--pri-medium-bar); }
.p-low      { background: var(--pri-low-bar); }

.ticket-id {
  font-size: 11.5px;
  font-weight: 500;
  color: var(--text-tertiary);
  width: 72px;
  flex-shrink: 0;
  font-family: var(--font-mono);
}
.ticket-info { flex: 1; min-width: 0; }
.ticket-subject {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ticket-meta { font-size: 11.5px; color: var(--text-secondary); margin-top: 2px; }

/* ── Badges ────────────────────────────────────────────────────────────────── */
.badge {
  font-size: 11px;
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 99px;
  white-space: nowrap;
  flex-shrink: 0;
}
.badge-open     { background: var(--bg-info);    color: var(--text-info); }
.badge-inprogress { background: var(--bg-warning); color: var(--text-warning); }
.badge-softclose { background: var(--bg-success); color: var(--text-success); }
.badge-closed   { background: var(--bg-subtle);   color: var(--text-secondary); border: 1px solid var(--border-md); }
.badge-danger   { background: var(--bg-danger);   color: var(--text-danger); }

/* ── Detail / three-column layout ─────────────────────────────────────────── */
.detail-shell {
  display: flex;
  gap: 0;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.detail-body {
  flex: 1;
  overflow-y: auto;
  padding: 0;
  min-width: 0;
}
/* Wider than a plain sidebar: this column now carries the activity timeline,
   which is unreadable in the 296px the panel used to be. */
.detail-panel {
  width: 400px;
  flex-shrink: 0;
  background: var(--bg-surface);
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.detail-panel-head {
  padding: 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.detail-tid  { font-size: 11px; color: var(--text-secondary); margin-bottom: 5px; font-family: var(--font-mono); }
.detail-title { font-size: 14px; font-weight: 600; color: var(--text-primary); line-height: 1.4; }
.detail-badges { display: flex; gap: 6px; margin-top: 10px; flex-wrap: wrap; }

.detail-meta {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 9px;
  flex-shrink: 0;
}
.meta-row { display: flex; justify-content: space-between; align-items: center; }
.meta-label { font-size: 12px; color: var(--text-secondary); display: flex; align-items: center; gap: 4px; }
.meta-label i { font-size: 13px; }
.meta-value { font-size: 12.5px; color: var(--text-primary); font-weight: 500; }

/* ── SLA gauges ────────────────────────────────────────────────────────────── */
.gauge-section {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.gauge-header {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 8px;
}
.gauge-label { font-size: 11px; font-weight: 500; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.05em; display: flex; align-items: center; gap: 3px; }
.gauge-label i { font-size: 12px; }
.gauge-value { font-size: 12px; font-weight: 600; }
.gauge-value.warn  { color: var(--text-danger); }
.gauge-value.ok    { color: var(--text-success); }
.gauge-value.amber { color: var(--text-warning); }
.gauge-track { height: 8px; background: var(--bg-page); border-radius: 99px; overflow: hidden; }
.gauge-fill  { height: 100%; border-radius: 99px; }
.gauge-fill-blue  { background: var(--a-500); }
.gauge-fill-amber { background: var(--pri-high-bar); }
.gauge-fill-red   { background: var(--pri-critical-bar); }
.gauge-fill-green { background: var(--g-600); }
.gauge-stats {
  display: flex; justify-content: space-between;
  margin-top: 6px;
  font-size: 11px;
  color: var(--text-secondary);
}

/* ── Timeline ──────────────────────────────────────────────────────────────── */
.timeline-wrap { flex: 1; overflow-y: auto; padding: 14px 16px; }
.timeline-heading {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.tl-item { display: flex; gap: 10px; margin-bottom: 16px; }
.tl-spine { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; }
.tl-dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--accent);
  margin-top: 3px;
  flex-shrink: 0;
}
.tl-dot.muted { background: var(--border-strong); }
.tl-dot.success { background: var(--g-600); }
.tl-dot.danger  { background: var(--pri-critical-bar); }
.tl-line { flex: 1; width: 1px; background: var(--border); margin-top: 4px; min-height: 10px; }
.tl-body { flex: 1; }
.tl-author { font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
.tl-role   { font-weight: 400; color: var(--text-secondary); }
.tl-msg    { font-size: 12.5px; color: var(--text-secondary); margin-top: 3px; line-height: 1.55; }
.tl-time   { font-size: 11px; color: var(--text-tertiary); margin-top: 4px; }

/* ── Reply / action box ────────────────────────────────────────────────────── */
.reply-box {
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg-subtle);
}
.reply-input {
  width: 100%;
  border: 1px solid var(--border-md);
  border-radius: var(--radius-md);
  padding: 9px 11px;
  font-size: 13px;
  color: var(--text-primary);
  background: var(--bg-surface);
  resize: none;
  font-family: var(--font);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.reply-input:focus {
  border-color: rgba(24,95,165,0.5);
  box-shadow: 0 0 0 3px rgba(24,95,165,0.1);
}
.reply-actions {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 8px;
  gap: 8px;
  flex-wrap: wrap;
}
.reply-hint { font-size: 11px; color: var(--text-tertiary); }
.reply-file-zone { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.reply-file-label {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11.5px; color: var(--accent); cursor: pointer; padding: 3px 8px;
  border: 1px dashed var(--border); border-radius: 5px; transition: background .15s;
}
.reply-file-label:hover { background: var(--bg-subtle); }
.reply-file-list { display: flex; flex-wrap: wrap; gap: 4px; }

/* ── Ticket description block ──────────────────────────────────────────────── */
/* ── Ticket hero (internal detail, centre column) ───────────────────────────
   The ticket's own identity — number, subject, state and the headline facts.
   Lives at the top of the centre column so it reads as the page's subject
   rather than as sidebar metadata. */
.ticket-hero {
  padding: 20px 22px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-surface);
  flex-shrink: 0;
}
.ticket-hero-top {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 10px;
}
.ticket-hero-num {
  font-family: var(--font-mono);
  font-size: 12.5px; font-weight: 600; color: var(--accent);
}
.ticket-hero-line {
  font-size: 12px; color: var(--text-secondary);
  padding-left: 10px; border-left: 1px solid var(--border-md);
}
.ticket-hero-badges { display: flex; gap: 6px; margin-left: auto; flex-wrap: wrap; }
.ticket-hero-title {
  font-size: 23px; font-weight: 600; line-height: 1.3;
  color: var(--text-primary);
  margin: 0 0 16px;
}

/* Headline facts as a stat row, not label:value rows — this is a header, and
   a header should scan horizontally. */
.ticket-facts { display: flex; flex-wrap: wrap; gap: 12px 30px; }
.ticket-fact { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.fact-label {
  font-size: 10px; font-weight: 600; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.fact-value {
  font-size: 13px; font-weight: 500; color: var(--text-primary);
  display: flex; align-items: center; gap: 6px;
}
.fact-value i { font-size: 14px; color: var(--text-tertiary); }
.fact-value.is-warning { color: var(--text-warning); }
.fact-value.is-muted {
  font-family: var(--font-mono); font-size: 12px;
  font-weight: 400; color: var(--text-tertiary);
}

/* Shared section wrapper for the right panel's stacked blocks. */
.panel-section {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.panel-section-title {
  font-size: 10px; font-weight: 600; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--text-tertiary);
  margin-bottom: 8px;
  display: flex; align-items: center; gap: 6px;
}

.ticket-description-block {
  padding: 16px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-page);
}
/* The description in a surface box of its own. pre-wrap matters: customers type
   line breaks and lists, and those were being collapsed into one run-on
   paragraph. Capped in height so a long one scrolls rather than pushing the
   checklist and the action buttons below the fold. */
.ticket-description-box {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-primary);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 260px;
  overflow-y: auto;
}
.ticket-description-block h3 {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.ticket-description-block p {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
}

/* ── Action banners (soft-close, etc.) ─────────────────────────────────────── */
.action-banner {
  margin: 14px 16px;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  font-size: 13px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.action-banner--success { background: var(--bg-success); border: 1px solid rgba(59,109,17,0.2); color: var(--text-success); }
.action-banner--info    { background: var(--bg-info);    border: 1px solid rgba(24,95,165,0.2); color: var(--text-info); }
.action-banner-title { font-weight: 600; display: flex; align-items: center; gap: 6px; }
.action-banner-actions { display: flex; gap: 8px; margin-top: 4px; }

/* ── Alert banner (top of content) ────────────────────────────────────────── */
.alert-banner {
  padding: 10px 14px;
  border-radius: var(--radius-md);
  font-size: 13px;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 8px;
}
.alert-banner--success { background: var(--bg-success); color: var(--text-success); border: 1px solid rgba(59,109,17,0.2); }
.alert-banner--error   { background: var(--bg-danger);  color: var(--text-danger);  border: 1px solid rgba(163,45,45,0.2); }

/* ── Empty state ───────────────────────────────────────────────────────────── */
.empty-state {
  padding: 48px 24px;
  text-align: center;
  color: var(--text-secondary);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.empty-state i { font-size: 36px; color: var(--text-tertiary); }
.empty-state p { font-size: 13px; }

/* ── New ticket form ───────────────────────────────────────────────────────── */
.form-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 24px;
  box-shadow: var(--shadow-sm);
  max-width: 720px;
}
.form-group { display: flex; flex-direction: column; gap: 5px; margin-bottom: 16px; }
.form-group label { font-size: 13px; font-weight: 500; color: var(--text-primary); }
.form-control {
  padding: 8px 11px;
  border: 1px solid var(--border-md);
  border-radius: var(--radius-md);
  font-size: 13px;
  width: 100%;
  font-family: var(--font);
  color: var(--text-primary);
  background: var(--bg-surface);
  transition: border-color 0.15s, box-shadow 0.15s;
  outline: none;
}
.form-control:focus {
  border-color: rgba(24,95,165,0.5);
  box-shadow: 0 0 0 3px rgba(24,95,165,0.1);
}
.form-control select, select.form-control {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236B6A65' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 30px;
}
.field-error { font-size: 11.5px; color: var(--text-danger); }
.form-row { display: flex; gap: 16px; }
.form-row .form-group { flex: 1; }
.form-actions { display: flex; gap: 10px; margin-top: 8px; }
.validation-summary-valid { display: none !important; }
.validation-summary-errors {
  display: block !important;
  background: var(--bg-danger);
  border: 1px solid rgba(163,45,45,0.2);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  margin-bottom: 16px;
  color: var(--text-danger);
  font-size: 13px;
}
.validation-summary-errors ul { list-style: none; margin: 0; padding: 0; }
.validation-summary-errors ul li + li { margin-top: 4px; }

/* ── Auth pages (login / accept invitation) ────────────────────────────────── */
.auth-page {
  display: flex; justify-content: center; align-items: center;
  min-height: 100vh; padding: 24px;
  background: var(--bg-page);
}
.auth-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  padding: 40px;
  width: 100%;
  max-width: 400px;
}
.auth-logo {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 28px;
}
.auth-card__title { font-size: 20px; font-weight: 600; letter-spacing: -0.3px; margin-bottom: 4px; }
.auth-card__subtitle { color: var(--text-secondary); font-size: 13px; margin-bottom: 24px; }
.auth-card__footer { margin-top: 20px; font-size: 12px; color: var(--text-secondary); line-height: 1.6; }

/* ── Kanban board ──────────────────────────────────────────────────────────── */
/* .content is not a flex column, so the wrap takes an explicit bounded height
   to give each column its own vertical scroll without touching global layout. */
.kanban-wrap {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  height: calc(100vh - 140px);
  padding-bottom: 8px;
  align-items: flex-start;
}

.kanban-column {
  flex: 0 0 300px;
  display: flex;
  flex-direction: column;
  max-height: 100%;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.kanban-column.kanban-backlog {
  border-style: dashed;
  border-color: var(--border-md);
}

.kanban-column-accent { height: 3px; background: var(--accent); flex-shrink: 0; }

.kanban-column-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 13px;
  font-size: 13px; font-weight: 600;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.kanban-column-head > span:first-child {
  flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kanban-column-heading {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 1px;
}
.kanban-column-name {
  display: flex; align-items: center; gap: 5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Sprint date range under the column name. */
.kanban-column-sub {
  display: flex; align-items: center; gap: 4px;
  font-size: 10.5px; font-weight: 400;
  color: var(--text-tertiary);
  white-space: nowrap;
}
.kanban-column-sub i { font-size: 11px; }
.kanban-active-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-success);
  flex-shrink: 0;
}
.kanban-column-count {
  flex-shrink: 0;
  background: var(--bg-hover);
  color: var(--text-secondary);
  border-radius: 99px;
  padding: 1px 8px;
  font-size: 11px; font-weight: 500;
}

.kanban-column-add {
  flex-shrink: 0;
  width: 20px; height: 20px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-tertiary);
  text-decoration: none;
}
.kanban-column-add i { font-size: 14px; }
.kanban-column-add:hover { background: var(--bg-hover); color: var(--accent); }

.kanban-column-body {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
  display: flex; flex-direction: column; gap: 8px;
  min-height: 80px;
}
.kanban-column-body.is-drop-target {
  background: var(--bg-selected);
  outline: 2px dashed var(--accent);
  outline-offset: -4px;
}

.kanban-card {
  display: block;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px;
  box-shadow: var(--shadow-sm);
  cursor: grab;
  text-decoration: none;
  color: inherit;
  transition: box-shadow .12s ease;
}
.kanban-card:hover { box-shadow: var(--shadow-md); }
.kanban-card:active { cursor: grabbing; }
.kanban-card.is-dragging { opacity: .45; }
.kanban-card.is-saving { opacity: .5; pointer-events: none; }

/* Chip row — priority, product line, then the key set hard right in mono. */
.kanban-card-top {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 7px; flex-wrap: wrap;
}
.kanban-card-num {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 500;
  color: var(--text-tertiary);
}

/* Priority pill. Semantics from the redesign handoff — a filled pill states the
   level outright, where the old 8px dot needed a tooltip to be read at all. */
.pri-pill {
  display: inline-flex; align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em;
  white-space: nowrap;
}
.pri--critical { background: var(--pri-critical-bg); color: var(--pri-critical-fg); }
.pri--high     { background: var(--pri-high-bg);     color: var(--pri-high-fg); }
.pri--medium   { background: var(--pri-medium-bg);   color: var(--pri-medium-fg); }
.pri--low      { background: var(--pri-low-bg);      color: var(--pri-low-fg); }

.chip {
  display: inline-flex; align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 10.5px; font-weight: 600;
  white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.chip--muted { background: var(--pri-low-bg); color: var(--pri-low-fg); }

.kanban-card-title {
  font-size: 13.5px; font-weight: 600; line-height: 1.35;
  text-wrap: pretty;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--text-primary);
  text-decoration: none;
}

/* Which customer the work is for. */
.kanban-card-customer {
  margin-top: 5px;
  font-size: 12px; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Checklist progress bar on the card face. */
.kanban-card-progress {
  display: flex; align-items: center; gap: 8px;
  margin-top: 8px;
}
.kcp-track {
  flex: 1; height: 6px; border-radius: 999px;
  background: var(--pri-low-bg); overflow: hidden;
}
.kcp-fill {
  height: 100%; border-radius: 999px;
  background: var(--accent);
  transition: width .3s ease;
}
.kcp-fill.is-done { background: var(--text-success); }
.kcp-label {
  font-size: 10.5px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-tertiary);
}

/* SLA chip, derived from the scheduled date. Red and amber, deliberately — the
   handoff's own notes reject the prototype's blue for this. */
.sla-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 10.5px; font-weight: 700;
  white-space: nowrap;
}
.sla-chip i { font-size: 12px; }
.sla--overdue { background: var(--pri-critical-bg); color: var(--pri-critical-fg); }
.sla--today   { background: var(--pri-high-bg);     color: var(--pri-high-fg); }
.sla--soon    { background: var(--pri-low-bg);      color: var(--pri-low-fg); }
.sla--later   { background: var(--pri-low-bg);      color: var(--pri-low-fg); }

/* An overdue card earns a border, so it is findable without reading chips. */
.kanban-card.is-overdue { border-color: var(--pri-high-bar); }

.kanban-card-signals {
  display: flex; align-items: center; gap: 5px;
  flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end;
}
.kanban-card-title:hover { color: var(--accent); text-decoration: underline; }

/* Assignee row and inline assign popover. */
.kanban-card-foot {
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--border);
  display: flex; align-items: center; gap: 6px;
  position: relative;
}
.kanban-assignee { flex: 1; min-width: 0; display: flex; align-items: center; }

.kanban-assign { position: relative; flex-shrink: 0; }
.kanban-assign-toggle {
  list-style: none; cursor: pointer;
  width: 24px; height: 24px; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-secondary);
}
.kanban-assign-toggle::-webkit-details-marker { display: none; }
.kanban-assign-toggle:hover { background: var(--bg-hover); color: var(--accent); }
.kanban-assign[open] .kanban-assign-toggle { background: var(--bg-selected); color: var(--accent); }

/* An absolutely-positioned child of a closed <details> still generates boxes in
   Chrome, so the popover must be hidden explicitly rather than relying on the
   element's default collapse behaviour. */
.kanban-assign:not([open]) .kanban-assign-form { display: none; }

/* Fixed, not absolute: the column body scrolls (overflow-y:auto) and would clip an
   absolutely-positioned popover, forcing the user to scroll to reach the fields.
   Fixed escapes that clipping; board.js places it against the toggle button. */
.kanban-assign-form {
  position: fixed; z-index: 100;
  width: 210px; padding: 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border-md);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
.kanban-assign-form label {
  display: block; margin-bottom: 3px;
  font-size: 10.5px; font-weight: 600;
  color: var(--text-tertiary); text-transform: uppercase; letter-spacing: .05em;
}
.kanban-assign-form select,
.kanban-assign-form input {
  width: 100%; margin-bottom: 8px; padding: 5px 7px;
  font-family: inherit; font-size: 12px;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface); color: var(--text-primary);
}
.kanban-assign-form select:focus,
.kanban-assign-form input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

/* ── Quick-create task popup ───────────────────────────────────────────────
   Same recipe as the assign popover above, including the explicit hide: an
   absolutely-positioned child of a closed <details> still generates boxes in
   Chrome. Wider, because it holds a people picker rather than a plain select. */
.kanban-quick-add:not([open]) .kanban-quick-add-form { display: none; }
.kanban-quick-add > summary { list-style: none; cursor: pointer; }
.kanban-quick-add > summary::-webkit-details-marker { display: none; }

.kanban-quick-add-form {
  position: fixed; z-index: 100;
  width: 260px; padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-md);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  /* Expanded, the form can outgrow a short viewport. Scroll inside it rather than
     letting it run off the bottom — board.js clamps the position, not the height. */
  max-height: calc(100vh - 32px);
  overflow-y: auto;
}
.kanban-quick-add-form label {
  display: block; margin-bottom: 3px;
  font-size: 10.5px; font-weight: 600;
  color: var(--text-tertiary); text-transform: uppercase; letter-spacing: .05em;
}
.kanban-quick-add-form input[type="text"],
.kanban-quick-add-form input[type="date"] {
  width: 100%; margin-bottom: 9px; padding: 6px 8px;
  font-family: inherit; font-size: 12.5px;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface); color: var(--text-primary);
}
.kanban-quick-add-form input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.kanban-quick-add-form .people-picker { margin-bottom: 9px; }
.kanban-quick-add-form textarea,
.kanban-quick-add-form select {
  width: 100%; margin-bottom: 9px; padding: 6px 8px;
  font-family: inherit; font-size: 12.5px;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface); color: var(--text-primary);
}
.kanban-quick-add-form textarea { resize: vertical; min-height: 54px; }
.kanban-quick-add-form select:focus,
.kanban-quick-add-form textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

/* "More options" — expands the popup in place rather than sending the user to a
   separate page and losing what they had already typed. */
.kanban-quick-more { margin: 2px 0 10px; }
.kanban-quick-more > summary {
  list-style: none; cursor: pointer;
  padding: 4px 0;
  font-size: 11.5px; font-weight: 600; color: var(--text-secondary);
  user-select: none;
}
.kanban-quick-more > summary::-webkit-details-marker { display: none; }
.kanban-quick-more > summary::before {
  content: "▸"; display: inline-block; width: 12px;
  transition: transform .12s ease;
}
.kanban-quick-more[open] > summary::before { transform: rotate(90deg); }
.kanban-quick-more > summary:hover { color: var(--accent); }
.kanban-quick-more[open] > summary { color: var(--accent); }

/* ── Editable record fields on the ticket detail page ──────────────────────
   The field IS the control. Each one is styled to read exactly as the value it
   replaced, so the page looks unchanged until you interact with it — no edit mode,
   no second copy of the layout to drift. Borders and background appear on hover and
   focus, which is what tells you it can be typed into. */

.hero-edit,
.hero-edit-title,
.planning-edit,
.meta-edit {
  font: inherit; color: inherit;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  transition: background .12s ease, border-color .12s ease;
}
.hero-edit:hover,
.hero-edit-title:hover,
.planning-edit:hover,
.meta-edit:hover {
  background: var(--bg-surface);
  border-color: var(--border-md);
}
.hero-edit:focus,
.hero-edit-title:focus,
.planning-edit:focus,
.meta-edit:focus {
  background: var(--bg-surface);
  outline: 2px solid var(--accent); outline-offset: -1px;
}

/* Read-only on a closed record: no affordance, because there is nothing to do. */
.hero-edit[disabled], .hero-edit-title[readonly],
.planning-edit[readonly], .meta-edit[disabled] {
  cursor: default;
}
.hero-edit[disabled]:hover, .hero-edit-title[readonly]:hover,
.planning-edit[readonly]:hover, .meta-edit[disabled]:hover {
  background: transparent; border-color: transparent;
}

/* The subject, still the page's headline. */
.hero-edit-title {
  display: block; width: 100%;
  margin: 0 0 2px; padding: 2px 6px 2px 4px;
  margin-left: -4px;
}

/* Product line, sitting in the hero's top row where the plain text was. */
.hero-edit--line {
  padding: 2px 4px;
  font-size: 12px; color: var(--text-secondary);
  max-width: 220px;
}

/* Type and priority, shaped like the badges beside them. */
.hero-edit--badge {
  padding: 2px 6px;
  font-size: 11px; font-weight: 600;
  border-radius: 999px;
  -webkit-appearance: none; appearance: none;
}
.hero-edit--badge:hover, .hero-edit--badge:focus { border-radius: 999px; }

/* Description: the box itself, now typeable. Keeps the bordered look it already had. */
.ticket-description-edit {
  width: 100%; min-height: 88px; resize: vertical;
  font: inherit; color: inherit;
}

.planning-edit {
  width: 130px; padding: 2px 6px;
  font-size: 15px; font-weight: 600;
}

.meta-edit { width: 100%; padding: 2px 4px; font-size: 12px; }

/* Validation from the record form, shown where the description ends rather than
   floating at the top of a long page. */
.ticket-edit-errors {
  margin: 0 18px 12px; padding: 8px 10px;
  font-size: 12px; color: var(--text-danger);
  background: var(--bg-danger); border-radius: var(--radius-sm);
}
.ticket-edit-errors ul { margin: 0; padding-left: 16px; }
.kanban-card-meta {
  margin-top: 7px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 11px; color: var(--text-secondary);
}

/* ── Checklist on a board card ─────────────────────────────────────────────
   The summary is the 2/5 progress badge; opening it reveals the steps, which can
   be ticked, owned, and added without leaving the board. Expands inline rather
   than as a fixed popover — a list of steps wants the card's full width. */
.kanban-checklist-panel { margin-top: 7px; }
.kanban-checklist {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 6px;
  border-radius: 99px;
  font-size: 10.5px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap; cursor: pointer; list-style: none;
  background: var(--bg-subtle); color: var(--text-secondary);
}
.kanban-checklist::-webkit-details-marker { display: none; }
.kanban-checklist i { font-size: 11px; }
.kanban-checklist.is-done { background: var(--bg-success); color: var(--text-success); }
/* No steps yet: a quiet affordance, not a 0/0 badge on every card. */
.kanban-checklist.is-empty { background: none; color: var(--text-tertiary); padding: 1px 2px; }
.kanban-checklist.is-empty:hover { color: var(--accent); }

.kcl-body {
  margin-top: 7px; padding: 7px 8px;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface);
}
.kcl-track {
  height: 3px; margin-bottom: 7px; border-radius: 99px;
  background: var(--border-md); overflow: hidden;
}
.kcl-fill { height: 100%; border-radius: 99px; background: var(--accent); }
.kcl-fill.is-done { background: var(--text-success); }

.kcl-list { list-style: none; margin: 0; padding: 0; }
.kcl-row {
  display: flex; align-items: center; gap: 5px;
  padding: 3px 0;
}
.kcl-tick-form { flex-shrink: 0; line-height: 1; }
.kcl-tick {
  background: none; border: none; padding: 0; cursor: pointer;
  font-size: 15px; line-height: 1; color: var(--text-tertiary);
}
.kcl-tick:hover { color: var(--accent); }
.kcl-row.is-done .kcl-tick { color: var(--text-success); }

.kcl-text {
  flex: 1; min-width: 0;
  font-size: 11.5px; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kcl-row.is-done .kcl-text { text-decoration: line-through; color: var(--text-tertiary); }

.kcl-owner-form { flex-shrink: 0; }
.kcl-owner-form select {
  max-width: 78px;
  padding: 1px 3px;
  font-family: inherit; font-size: 10.5px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--bg-subtle); color: var(--text-secondary);
}

.kcl-add {
  display: flex; align-items: center; gap: 4px;
  margin-top: 6px; padding-top: 6px;
  border-top: 1px solid var(--border-subtle);
}
.kcl-add input[type="text"] { flex: 1; min-width: 0; }
.kcl-add input,
.kcl-add select {
  padding: 3px 5px;
  font-family: inherit; font-size: 11px;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface); color: var(--text-primary);
}
.kcl-add select { max-width: 62px; }
.kcl-add-btn {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; width: 22px; height: 22px;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-subtle); color: var(--text-secondary);
  cursor: pointer; font-size: 13px;
}
.kcl-add-btn:hover { background: var(--accent); color: #fff; border-color: var(--accent); }

.kcl-open {
  display: block; margin-top: 6px;
  font-size: 10.5px; color: var(--text-tertiary); text-decoration: none;
}
.kcl-open:hover { color: var(--accent); }

/* Bucket + sprint tags — always shown, whichever way the board is grouped. */
.kanban-card-tags {
  margin-top: 7px;
  display: flex; gap: 5px; flex-wrap: wrap;
}
.kanban-tag {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px;
  border-radius: 99px;
  font-size: 10.5px; font-weight: 500;
  white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.kanban-tag i { font-size: 11px; flex-shrink: 0; }
.kanban-tag--bucket { background: var(--bg-info);    color: var(--text-info); }
.kanban-tag--sprint { background: var(--bg-success); color: var(--text-success); }
.kanban-tag--board  { background: var(--bg-warning); color: var(--text-warning); }

/* ── Checklist panel (internal ticket detail) ──────────────────────────────
   Sits between the planning fields and the timeline. Capped in height with its
   own scroll so a long breakdown cannot squeeze the timeline out of the view. */
.checklist-block {
  flex-shrink: 0;
  padding: 12px 18px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-subtle);
  max-height: 42vh;
  overflow-y: auto;
}
.checklist-head {
  display: flex; align-items: center; gap: 7px;
  font-size: 10px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.checklist-head i { font-size: 13px; }
.checklist-title { letter-spacing: .07em; }
.checklist-count {
  margin-left: auto;
  font-size: 12px; font-weight: 700; letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
}
.checklist-count.is-done { color: var(--text-success); }

.checklist-track {
  margin-top: 8px; height: 4px; border-radius: 99px;
  background: var(--border-md); overflow: hidden;
}
.checklist-fill {
  height: 100%; border-radius: 99px;
  background: var(--accent);
  transition: width .2s ease;
}
.checklist-fill.is-done { background: var(--text-success); }

.checklist-list { list-style: none; margin: 10px 0 0; padding: 0; }
.checklist-row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.checklist-row:last-child { border-bottom: none; }

.checklist-tick-form { flex-shrink: 0; line-height: 1; margin-top: 1px; }
/* Circular checkbox from the redesign handoff: an empty ring that fills green
   with a white tick. Reads as a control, where the old square glyph read as an
   icon and gave no affordance that it could be clicked. */
.checklist-box {
  width: 19px; height: 19px;
  border-radius: 999px;
  border: 2px solid var(--border-strong);
  background: transparent;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0; flex-shrink: 0; cursor: pointer;
  transition: background .14s ease, border-color .14s ease;
}
.checklist-box i {
  font-size: 12px; color: #fff; opacity: 0;
  transition: opacity .14s ease;
}
.checklist-box:hover { border-color: var(--accent); }
.checklist-box.is-static { cursor: default; }
.checklist-box.is-done {
  background: var(--text-success);
  border-color: var(--text-success);
}
.checklist-box.is-done i { opacity: 1; }

.checklist-main { flex: 1; min-width: 0; }
.checklist-text { font-size: 13px; line-height: 1.4; word-break: break-word; }
.checklist-row.is-done .checklist-text {
  text-decoration: line-through;
  color: var(--text-tertiary);
}
.checklist-sub {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 2px;
  font-size: 11px; color: var(--text-secondary);
}
.checklist-owner.is-empty { color: var(--text-tertiary); }

.checklist-actions { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.checklist-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  background: none; border: none; border-radius: var(--radius-sm);
  cursor: pointer; color: var(--text-tertiary); font-size: 14px;
  list-style: none;
}
.checklist-icon-btn::-webkit-details-marker { display: none; }
.checklist-icon-btn:hover { background: var(--border-md); color: var(--text-primary); }

.checklist-menu { position: relative; }
.checklist-menu-body {
  position: absolute; right: 0; top: 24px; z-index: 40;
  width: 220px; padding: 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border-md); border-radius: var(--radius-md);
  box-shadow: 0 6px 20px rgba(0,0,0,.16);
}
.checklist-menu-body label {
  display: block; margin-bottom: 3px;
  font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.checklist-menu-body input,
.checklist-menu-body select {
  width: 100%; margin-bottom: 6px; padding: 5px 7px;
  font-family: inherit; font-size: 12px;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface); color: var(--text-primary);
}
.checklist-menu-body form + form { margin-top: 8px; }
.checklist-menu-sep { height: 1px; margin: 9px 0; background: var(--border); }
.checklist-danger { color: var(--text-danger); }

.checklist-add {
  display: flex; align-items: center; gap: 6px;
  margin-top: 10px;
}
.checklist-add input[type="text"] { flex: 1; min-width: 0; }
.checklist-add input,
.checklist-add select {
  padding: 5px 8px;
  font-family: inherit; font-size: 12px;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface); color: var(--text-primary);
}
.checklist-add select { max-width: 140px; }
.checklist-empty { margin-top: 8px; font-size: 12px; color: var(--text-tertiary); }

/* Column grouping toggle in the topbar. */
.group-toggle {
  display: inline-flex;
  border: 1px solid var(--border-md);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.group-toggle-btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 11px;
  font-family: inherit; font-size: 12.5px; font-weight: 500;
  background: var(--bg-surface);
  color: var(--text-secondary);
  border: none; cursor: pointer;
}
.group-toggle-btn + .group-toggle-btn { border-left: 1px solid var(--border-md); }
.group-toggle-btn:hover { background: var(--bg-hover); }
.group-toggle-btn.active { background: var(--accent); color: #fff; }
/* The planning switcher uses anchors rather than submit buttons — it navigates instead
   of re-posting a grouping — so the underline the global link rule adds has to go. */
a.group-toggle-btn, a.group-toggle-btn:hover { text-decoration: none; }

.kanban-empty-col {
  padding: 14px 8px;
  text-align: center;
  font-size: 11.5px;
  color: var(--text-tertiary);
}

/* ── Avatar stack (shared by the board cards and the ticket grid) ──────────── */
.avatars { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.avatars-name {
  font-size: 11.5px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.avatars.is-unassigned .avatars-name { color: var(--text-tertiary); font-style: italic; }

.avatar {
  width: 22px; height: 22px; flex-shrink: 0;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 9.5px; font-weight: 600; letter-spacing: .02em;
  color: #fff;
  /* Ring in the surface colour so overlapping avatars stay visually separate. */
  box-shadow: 0 0 0 1.5px var(--bg-surface);
}
.avatar--photo { object-fit: cover; background: var(--bg-hover); }
.avatar--empty { background: var(--bg-hover); color: var(--text-tertiary); }
.avatar--more { background: var(--border-strong); color: var(--text-primary); font-size: 9px; }
.avatar--xs { width: 18px; height: 18px; font-size: 8px; box-shadow: none; }

/* ── People picker ─────────────────────────────────────────────────────────
   A type-ahead over a real <select>, which stays the form control. Sits with the
   avatars because it is built entirely out of them. */

/* Hidden with position/opacity rather than display:none, so browser validation
   still fires and can still focus the field it is complaining about. */
.pp-native {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none;
}

.people-picker { position: relative; }

.pp-shell {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  min-height: 32px; padding: 4px 6px;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface);
}
.pp-shell:focus-within { outline: 2px solid var(--accent); outline-offset: -1px; }

.pp-tokens { display: contents; }
.pp-token {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 4px 2px 2px;
  background: var(--bg-selected); border-radius: 999px;
  font-size: 11.5px; color: var(--text-primary);
}
.pp-token-remove {
  border: 0; background: none; cursor: pointer;
  padding: 0 3px; line-height: 1;
  font-size: 13px; color: var(--text-tertiary);
}
.pp-token-remove:hover { color: var(--text-danger); }

.pp-input {
  flex: 1; min-width: 90px;
  border: 0; outline: none; background: none;
  font-family: inherit; font-size: 12.5px; color: var(--text-primary);
  padding: 3px 2px;
}

.pp-list {
  position: absolute; z-index: 110; left: 0; right: 0;
  margin: 3px 0 0; padding: 4px; list-style: none;
  max-height: 210px; overflow-y: auto;
  background: var(--bg-surface);
  border: 1px solid var(--border-md); border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
.pp-option {
  display: flex; align-items: center; gap: 7px;
  padding: 5px 6px; border-radius: var(--radius-sm);
  font-size: 12.5px; color: var(--text-primary); cursor: pointer;
}
.pp-option:hover,
.pp-option.is-active { background: var(--bg-selected); }

.avatar-stack { display: inline-flex; align-items: center; }
.avatar-stack .avatar + .avatar { margin-left: -7px; }
/* Later avatars sit under earlier ones, so the stack reads left-to-right. */
.avatar-stack .avatar:nth-child(1) { z-index: 4; }
.avatar-stack .avatar:nth-child(2) { z-index: 3; }
.avatar-stack .avatar:nth-child(3) { z-index: 2; }
.avatar-stack .avatar:nth-child(4) { z-index: 1; }
.avatar-stack:hover .avatar { margin-left: 1px; }
.avatar-stack .avatar { transition: margin-left .12s ease; }

/* ── Dashboard ─────────────────────────────────────────────────────────────── */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(165px, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}
.kpi {
  display: block;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-md);
  border-radius: var(--radius-lg);
  padding: 13px 15px;
  text-decoration: none; color: inherit;
  box-shadow: var(--shadow-sm);
  transition: box-shadow .12s;
}
a.kpi:hover { box-shadow: var(--shadow-md); }
.kpi--info    { border-left-color: var(--text-info); }
.kpi--danger  { border-left-color: var(--text-danger); }
.kpi--warning { border-left-color: var(--text-warning); }
.kpi--success { border-left-color: var(--text-success); }
.kpi-label {
  display: flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 500; color: var(--text-secondary);
}
.kpi-value { font-size: 27px; font-weight: 600; line-height: 1.2; margin: 4px 0 2px; }
.kpi-sub { font-size: 11px; color: var(--text-tertiary); }

.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}
.dash-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  display: flex; flex-direction: column;
  overflow: hidden;
}
.dash-card--wide { grid-column: span 2; }
@media (max-width: 900px) { .dash-card--wide { grid-column: span 1; } }

.dash-card-head {
  display: flex; align-items: baseline; gap: 8px;
  padding: 11px 15px;
  border-bottom: 1px solid var(--border);
}
.dash-card-title { font-size: 13px; font-weight: 600; }
.dash-card-note { font-size: 11px; color: var(--text-tertiary); margin-left: auto; }
.dash-card-body { padding: 14px 15px; flex: 1; }
.dash-card-body--flush { padding: 0; }

/* Opened vs closed columns */
/* stretch, not flex-end: a percentage height only resolves against a parent with a
   definite one. With flex-end each week shrank to its label, leaving .trend-bars a few
   pixels tall, so every bar collapsed to its 2px minimum and the chart read as empty. */
.trend { display: flex; align-items: stretch; gap: 5px; height: 140px; }
.trend-week {
  flex: 1; min-width: 0; height: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
}
/* min-height:0 lets this shrink inside the column; without it the label can push the
   plot area past the 140px and the bars scale against the wrong height. */
.trend-bars {
  flex: 1; min-height: 0; width: 100%;
  display: flex; align-items: flex-end; justify-content: center; gap: 2px;
}
.trend-bar { width: 44%; min-height: 2px; border-radius: 2px 2px 0 0; }
.trend-bar--opened { background: var(--accent); }
.trend-bar--closed { background: var(--text-success); }
.trend-label {
  font-size: 9.5px; color: var(--text-tertiary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.chart-legend {
  display: flex; gap: 14px; margin-top: 10px;
  font-size: 11.5px; color: var(--text-secondary);
}
.chart-legend .swatch {
  display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 4px;
}
.swatch--opened { background: var(--accent); }
.swatch--closed { background: var(--text-success); }

/* Horizontal bar rows */
.bar-row { display: flex; align-items: center; gap: 9px; margin-bottom: 8px; }
.bar-row:last-child { margin-bottom: 0; }
.bar-name {
  width: 96px; flex-shrink: 0; font-size: 11.5px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bar-track { flex: 1; height: 8px; background: var(--bg-hover); border-radius: 99px; overflow: hidden; }
.bar-fill { height: 100%; border-radius: 99px; min-width: 2px; }
.bar-value {
  width: 30px; text-align: right; flex-shrink: 0;
  font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums;
}

.stat-big { display: flex; align-items: baseline; gap: 5px; }
.stat-big-value { font-size: 32px; font-weight: 600; line-height: 1; }
.stat-big-unit { font-size: 13px; color: var(--text-secondary); }
.stat-caption { font-size: 11.5px; color: var(--text-tertiary); margin-top: 3px; }

.stat-split {
  display: flex; gap: 10px; margin: 14px 0;
  padding: 10px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border);
}
.stat-split > div { flex: 1; }
.stat-split-value { font-size: 18px; font-weight: 600; }
.stat-split-label { font-size: 11px; color: var(--text-tertiary); }

.hours-row {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 12.5px; padding: 3px 0; color: var(--text-secondary);
}
.hours-row strong { font-variant-numeric: tabular-nums; color: var(--text-primary); }
.hours-row.is-over strong { color: var(--text-danger); }
.hours-row.is-under strong { color: var(--text-success); }

.attn-row {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 15px;
  border-bottom: 1px solid var(--border);
  text-decoration: none; color: inherit; font-size: 12.5px;
}
.attn-row:last-child { border-bottom: none; }
.attn-row:hover { background: var(--bg-hover); }
/* Two stacked lines now — subject over customer — so the cell is a column rather than
   a single truncating line. Both lines truncate independently. */
.attn-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.attn-subject {
  font-weight: 500; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.attn-sub {
  font-size: 11.5px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.attn-meta { color: var(--text-secondary); font-size: 11.5px; white-space: nowrap; }
.attn-flag {
  color: var(--text-danger); font-size: 11px; font-weight: 600;
  white-space: nowrap; flex-shrink: 0;
}

.dash-footnote { font-size: 11px; color: var(--text-tertiary); padding: 2px 2px 16px; }

/* ── Data grid (All Tickets) ───────────────────────────────────────────────── */
.grid-filters {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 12px 14px;
  margin-bottom: 14px;
  display: flex; flex-direction: column; gap: 10px;
}
.grid-filter-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.grid-filter-row .form-control { flex: 1; min-width: 140px; font-size: 12.5px; padding: 6px 9px; }
.grid-filter-row select[multiple] { padding: 4px; min-width: 120px; flex: 0 0 auto; }
.grid-filter-label {
  font-size: 11px; font-weight: 600; color: var(--text-tertiary);
  text-transform: uppercase; letter-spacing: .05em;
}

.grid-meta { font-size: 12.5px; color: var(--text-secondary); margin-bottom: 8px; }

.grid-scroll {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: auto;
  max-height: calc(100vh - 330px);
}

.grid { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.grid thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border-md);
  padding: 9px 11px;
  text-align: left; font-weight: 600; white-space: nowrap;
  color: var(--text-secondary);
}
.grid tbody td {
  padding: 8px 11px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  vertical-align: middle;
}
.grid tbody tr:hover { background: var(--bg-hover); }
.grid tbody tr:last-child td { border-bottom: none; }
.grid .num { text-align: right; font-variant-numeric: tabular-nums; }
.grid .is-over { color: var(--text-danger); font-weight: 600; }

.grid-subject {
  max-width: 280px; overflow: hidden; text-overflow: ellipsis;
}
.grid-link {
  font-family: var(--font-mono); font-size: 11.5px;
  color: var(--accent); text-decoration: none;
}
.grid-link:hover { text-decoration: underline; }

.grid-sort { color: inherit; text-decoration: none; }
.grid-sort:hover { color: var(--accent); }
.grid-sort.is-active { color: var(--accent); }

.grid-pager {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 12px 0;
}

/* ══ Planning views ═══════════════════════════════════════════════════════════
   Sprint Planning, the Sprint Cockpit and the Timeline. All three reuse the
   board's vocabulary — the priority ramp, .avatar, .chip, .badge, .kpi and
   .dash-card — so only what is genuinely new to them is defined here. */

/* The sprint picker in the topbar, sized to match .group-toggle beside it. */
.plan-sprint-switch select {
  padding: 5px 10px;
  border: 1px solid var(--border-md);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: 12.5px;
}

/* ── Sprint Planning ───────────────────────────────────────────────────────── */
.plan-shell {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 440px;
  gap: 16px;
}
.plan-col, .plan-sprint, .plan-capacity {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
}
.plan-col-head {
  padding: 13px 16px;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 10px;
  flex-shrink: 0;
}
.plan-col-title { font-size: 13.5px; font-weight: 600; }
.plan-col-note { margin-left: auto; font-size: 11.5px; color: var(--text-tertiary); }
.plan-col-body {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 10px; display: flex; flex-direction: column; gap: 8px;
}

.plan-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
}
.plan-item:hover { border-color: var(--border-strong); }
.plan-item-bar { width: 3px; align-self: stretch; border-radius: 2px; flex-shrink: 0; }
.plan-item-bar.pri--critical { background: var(--pri-critical-bar); }
.plan-item-bar.pri--high     { background: var(--pri-high-bar); }
.plan-item-bar.pri--medium   { background: var(--pri-medium-bar); }
.plan-item-bar.pri--low      { background: var(--pri-low-bar); }
.plan-item-main { flex: 1; min-width: 0; }
.plan-item-top { display: flex; align-items: center; gap: 7px; margin-bottom: 3px; }
.plan-item-num { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-tertiary); }
.plan-item-title {
  display: block;
  font-size: 13px; font-weight: 500; color: var(--text-primary);
  text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.plan-item-title:hover { color: var(--accent); text-decoration: none; }
.plan-item-meta {
  font-size: 11px; color: var(--text-tertiary);
  display: flex; align-items: center; gap: 5px; margin-top: 2px;
}
.plan-dot { opacity: .6; }
.plan-hours {
  font-family: var(--font-mono); font-size: 11px; font-weight: 500;
  color: var(--text-info); background: var(--a-100);
  padding: 2px 8px; border-radius: 99px; white-space: nowrap; flex-shrink: 0;
}
/* An estimate is what capacity is computed from, so its absence is worth seeing. */
.plan-hours.is-missing { color: var(--text-tertiary); background: var(--n-200); }
.plan-item-action { flex-shrink: 0; display: flex; }
.plan-move-btn {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface); color: var(--text-secondary);
  cursor: pointer; transition: background .12s, color .12s, border-color .12s;
}
.plan-move-btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; }

.plan-side { display: flex; flex-direction: column; gap: 16px; min-height: 0; }
.plan-sprint { flex-shrink: 0; border-color: var(--a-300); }
.plan-sprint.is-over { border-color: var(--pri-critical-bar); }
.plan-sprint-head { padding: 13px 16px; border-bottom: 1px solid var(--border); background: var(--a-100); }
.plan-sprint.is-over .plan-sprint-head { background: var(--bg-danger); }
.plan-sprint-title { display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 600; }
.plan-sprint-dates { margin-left: auto; font-size: 11.5px; font-weight: 500; color: var(--text-secondary); }
.plan-sprint-figures { display: flex; align-items: baseline; gap: 8px; margin-top: 8px; }
.plan-sprint-value { font-family: var(--font-mono); font-size: 22px; font-weight: 600; }
.plan-sprint-of { font-size: 12px; color: var(--text-secondary); }
.plan-sprint-figures .badge { margin-left: auto; }
.plan-bar-track { height: 7px; background: var(--n-200); border-radius: 99px; overflow: hidden; margin-top: 8px; }
.plan-bar-fill { height: 100%; background: var(--accent); border-radius: 99px; }
.plan-bar-fill.is-over { background: var(--pri-critical-bar); }
.plan-sprint-body {
  max-height: 320px; overflow-y: auto;
  padding: 10px; display: flex; flex-direction: column; gap: 7px;
}
.plan-drop-hint {
  border: 1.5px dashed var(--a-400); border-radius: var(--radius-md);
  padding: 14px; text-align: center;
  font-size: 12px; color: var(--text-info); background: var(--a-100);
}
.plan-planned {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 9px;
  border: 1px solid var(--border); border-radius: var(--radius-md);
}
.plan-planned-title {
  flex: 1; min-width: 0;
  font-size: 12.5px; font-weight: 500; color: var(--text-primary); text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.plan-planned-title:hover { color: var(--accent); text-decoration: none; }

.plan-capacity { flex: 1; min-height: 0; }
.plan-capacity-body { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 16px; }
.cap-row + .cap-row { margin-top: 13px; }
.cap-who { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.cap-name { font-size: 12.5px; }
.cap-figure {
  margin-left: auto;
  font-family: var(--font-mono); font-size: 11.5px; color: var(--text-secondary);
}
.cap-figure.is-over { color: var(--text-danger); font-weight: 500; }
.cap-track { height: 7px; background: var(--n-200); border-radius: 99px; overflow: hidden; }
.cap-fill { height: 100%; background: var(--g-600); border-radius: 99px; }
.cap-fill.is-tight { background: var(--accent); }
.cap-fill.is-over { background: var(--pri-critical-bar); }
.cap-note { font-size: 10.5px; color: var(--text-success); margin-top: 3px; }
.cap-note.is-over { color: var(--text-danger); }

/* ── Sprint Cockpit ────────────────────────────────────────────────────────── */
.cockpit-top {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 16px;
  flex-shrink: 0;
}
.cockpit-figures { display: grid; grid-template-rows: repeat(3, 1fr); gap: 12px; }
.cockpit-figures .kpi { margin: 0; }

.burndown { width: 100%; height: 210px; display: block; }
.bd-grid   { stroke: var(--border); stroke-width: 1; }
.bd-axis   { font-family: var(--font-mono); font-size: 9px; fill: var(--text-tertiary); }
.bd-ideal  { stroke: var(--border-strong); stroke-width: 1.5; stroke-dasharray: 4 4; }
.bd-actual {
  fill: none; stroke: var(--accent); stroke-width: 2.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.bd-today  { stroke: var(--pri-high-bar); stroke-width: 1.5; }
.bd-dot    { fill: var(--accent); stroke: var(--bg-surface); stroke-width: 2; }
.swatch--actual { background: var(--accent); }
.swatch--ideal  { background: var(--border-strong); }

.cockpit-lanes { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.lane-head, .lane {
  display: grid;
  grid-template-columns: 168px repeat(4, minmax(0, 1fr));
}
.lane-head {
  border-bottom: 1px solid var(--border);
  background: var(--bg-subtle);
  flex-shrink: 0;
}
.lane-head span {
  padding: 8px 12px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.lane-head span + span { border-left: 1px solid var(--border); }
.lane { border-bottom: 1px solid var(--border); min-height: 88px; }
.lane:last-child { border-bottom: none; }
.lane-who { padding: 12px 14px; display: flex; align-items: flex-start; gap: 9px; }
.lane-id { min-width: 0; }
.lane-name { font-size: 12.5px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lane-load { font-size: 10.5px; color: var(--text-tertiary); margin-top: 1px; }
.lane-load.is-over { color: var(--text-danger); }
.lane-track { height: 4px; width: 72px; background: var(--n-200); border-radius: 99px; overflow: hidden; margin-top: 5px; }
.lane-fill { height: 100%; background: var(--accent); border-radius: 99px; }
.lane-fill.is-over { background: var(--pri-critical-bar); }
.lane-cell {
  border-left: 1px solid var(--border);
  padding: 8px; display: flex; flex-direction: column; gap: 6px;
}
.lane-card {
  display: block;
  border: 1px solid var(--border); border-left-width: 3px;
  border-radius: var(--radius-sm);
  padding: 7px 9px;
  background: var(--bg-surface);
  text-decoration: none; color: inherit;
  box-shadow: var(--shadow-sm);
}
.lane-card:hover { border-color: var(--border-strong); border-left-color: inherit; text-decoration: none; }
.lane-card.pri--critical { border-left-color: var(--pri-critical-bar); }
.lane-card.pri--high     { border-left-color: var(--pri-high-bar); }
.lane-card.pri--medium   { border-left-color: var(--pri-medium-bar); }
.lane-card.pri--low      { border-left-color: var(--pri-low-bar); }
.lane-card.is-done { opacity: .7; }
.lane-card.is-done .lane-card-title {
  text-decoration: line-through;
  text-decoration-color: var(--border-strong);
}
.lane-card-title { display: block; font-size: 11.5px; font-weight: 500; line-height: 1.3; }
.lane-card-foot { display: flex; align-items: center; gap: 6px; margin-top: 5px; }
.lane-card-num { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-tertiary); }
.lane-card-hours {
  margin-left: auto;
  font-family: var(--font-mono); font-size: 9.5px; color: var(--text-tertiary);
}
.lane-card-foot .sla-chip { margin-left: auto; }
.lane-card-progress { display: flex; align-items: center; gap: 6px; margin-top: 5px; }
.lane-card-progress .kcp-track { flex: 1; }

/* ── Timeline ──────────────────────────────────────────────────────────────── */
.tl-wrap {
  flex: 1; min-height: 0; overflow: auto;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.tl-grid { min-width: 900px; }
.tl-row { display: grid; grid-template-columns: 186px minmax(0, 1fr); border-bottom: 1px solid var(--border); }
.tl-row:last-child { border-bottom: none; }
.tl-row--unassigned { background: var(--bg-subtle); }
.tl-gutter { padding: 12px 14px; display: flex; align-items: flex-start; gap: 9px; }
.tl-gutter--head {
  padding: 9px 14px; align-items: center;
  font-size: 10.5px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text-tertiary);
  background: var(--bg-subtle);
}
.tl-who { min-width: 0; }
.tl-name { font-size: 12.5px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tl-load { font-size: 10.5px; color: var(--text-tertiary); margin-top: 1px; }
.tl-load.is-over { color: var(--text-danger); }
.tl-load-track { height: 4px; width: 74px; background: var(--n-200); border-radius: 99px; overflow: hidden; margin-top: 5px; }
.tl-load-fill { height: 100%; background: var(--accent); border-radius: 99px; }
.tl-load-fill.is-over { background: var(--pri-critical-bar); }

/* The track is a positioning context for bars and a grid for the week guides. */
.tl-track { position: relative; display: grid; grid-template-columns: repeat(var(--tl-cols), 1fr); }
.tl-track--head { background: var(--bg-subtle); }
.tl-guide { border-left: 1px solid var(--border); }
/* Tints the whole current-week column behind its bars. Deliberately paler than the
   header's --bg-warning so bars sitting on it stay legible. */
.tl-guide.is-current { background: #fef8ee; }
.tl-week {
  padding: 9px 12px; border-left: 1px solid var(--border);
  font-size: 11px; color: var(--text-secondary); white-space: nowrap;
}
.tl-week.is-current { background: var(--bg-warning); color: var(--text-warning); font-weight: 600; }
.tl-row--sprints .tl-track { min-height: 32px; }
.tl-sprint {
  padding: 8px 12px;
  border-left: 2px solid var(--border-strong);
  font-size: 11px; font-weight: 600; color: var(--text-tertiary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tl-sprint.is-active {
  border-left-color: var(--a-500);
  background: var(--a-100);
  color: var(--text-info);
}

.tl-bar {
  position: absolute; height: 24px;
  display: flex; align-items: center; gap: 7px;
  padding: 0 9px;
  border-left: 3px solid;
  border-radius: var(--radius-sm);
  font-size: 11px; font-weight: 600;
  text-decoration: none;
  overflow: hidden;
}
.tl-bar:hover { text-decoration: none; filter: brightness(.96); }
.tl-bar.pri--critical { background: var(--pri-critical-bg); border-left-color: var(--pri-critical-bar); color: var(--pri-critical-fg); }
.tl-bar.pri--high     { background: var(--pri-high-bg);     border-left-color: var(--pri-high-bar);     color: var(--pri-high-fg); }
.tl-bar.pri--medium   { background: var(--pri-medium-bg);   border-left-color: var(--pri-medium-bar);   color: var(--pri-medium-fg); }
.tl-bar.pri--low      { background: var(--pri-low-bg);      border-left-color: var(--pri-low-bar);      color: var(--pri-low-fg); }
/* Unplaced work reads as an outline: it occupies the slot but nobody owns it yet. */
.tl-bar.is-unassigned { background: var(--bg-surface); border: 1.5px dashed var(--border-strong); border-left-width: 3px; }
.tl-bar.is-overdue { box-shadow: inset 0 0 0 1.5px var(--pri-critical-bar); }
.tl-bar-title { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tl-bar-hours { font-family: var(--font-mono); font-size: 9.5px; opacity: .85; flex-shrink: 0; }

/* ── Form section headings ─────────────────────────────────────────────────────
   Replaces the inline style the New Task form used to carry on its one Placement
   heading, now that the form has two sections to separate. */
.form-section-label {
  margin: 18px 0 10px;
  font-size: 10px; font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: .07em; text-transform: uppercase;
  display: flex; align-items: center; gap: 6px;
}
.form-section-label:first-of-type { margin-top: 0; }
.form-section-note {
  margin-left: auto;
  text-transform: none; letter-spacing: 0;
  font-size: 11px; font-weight: 500;
  color: var(--text-info);
  display: flex; align-items: center; gap: 4px;
}

/* ══ My Tasks ═════════════════════════════════════════════════════════════════
   Two layouts over one card set, modelled on Planner's My Tasks: a flat grid and a
   board whose columns come from the chosen grouping. Both live inside .kanban-wrap so
   board-filters.js drives them, which means the kanban's own wrap/column/card rules
   have to be neutralised rather than inherited. */

.mt-controls { display: flex; align-items: center; }
.mt-groupby {
  display: flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--text-secondary);
  border: 1px solid var(--border-md); border-radius: var(--radius-md);
  padding: 4px 10px;
}
.mt-groupby select {
  border: none; background: none; outline: none;
  font-family: var(--font); font-size: 12.5px; font-weight: 500;
  color: var(--text-primary); cursor: pointer;
}

/* A filtered-out card must not leave a gap where it was, in either layout. */
.mt-wrap .kanban-card.is-filtered-out { display: none; }

/* ── Grid layout ───────────────────────────────────────────────────────────────
   A table built from divs: each row has to stay a .kanban-card so the filter pane
   can hide it, and a display:none <tr> still holds its track in a real <table>.
   One shared column template keeps the header and the rows in step. */
.mt-wrap--grid { display: block; overflow: visible; gap: 0; }

.mt-table {
  /* check · name · board · customer · bucket · sprint · due · priority · status · look */
  --mt-cols: 34px minmax(200px, 2.2fr) minmax(140px, 1fr) minmax(130px, 1fr)
             minmax(100px, .8fr) minmax(100px, .8fr) 92px 108px 150px 40px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.mt-thead, .mt-tr {
  display: grid;
  grid-template-columns: var(--mt-cols);
  align-items: center;
  gap: 12px;
  padding: 0 16px;
}
.mt-thead {
  height: 40px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-subtle);
  font-size: 11px; font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: .04em; text-transform: uppercase;
}
.mt-tr {
  min-height: 46px;
  border-bottom: 1px solid var(--border-subtle);
  font-size: 13px;
}
.mt-tr:last-child { border-bottom: none; }
.mt-tr:hover { background: var(--bg-hover); }
/* Rows the filter pane has hidden must not hold their grid track. */
.mt-tr.is-filtered-out { display: none; }

.mt-td { min-width: 0; display: flex; align-items: center; gap: 7px; }
.mt-td--check { justify-content: center; color: var(--border-strong); }
.mt-td--check i { font-size: 17px; }
.mt-tr.is-done .mt-td--check { color: var(--accent); }

.mt-name {
  font-weight: 500; color: var(--text-primary); text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mt-name:hover { color: var(--accent); text-decoration: none; }
.mt-tr.is-done .mt-name {
  text-decoration: line-through;
  text-decoration-color: var(--border-strong);
  color: var(--text-secondary);
}

/* Plan badge: deterministic colour per board, matching the avatar helper's hash so a
   board reads the same here as its people do elsewhere. */
.mt-plan { display: flex; align-items: center; gap: 8px; min-width: 0; }
.mt-plan-badge {
  width: 22px; height: 22px; flex-shrink: 0;
  border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 9.5px; font-weight: 700; color: #fff;
  letter-spacing: .02em;
}
.mt-plan-badge--none { background: var(--n-300); color: var(--text-tertiary); }
.mt-plan-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mt-plan--none .mt-plan-name { color: var(--text-tertiary); }

.mt-cell-sub { color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mt-cell-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* An overdue date is outlined rather than merely coloured — the same treatment the
   board cards give it, so "late" looks the same wherever it appears. */
.mt-due-cell { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.mt-due-cell.is-late {
  color: var(--text-danger);
  background: var(--bg-danger);
  border: 1px solid var(--pri-critical-bar);
  border-radius: var(--radius-sm);
  padding: 1px 7px;
  font-weight: 500;
}

.mt-status-icon { font-size: 16px; color: var(--border-strong); flex-shrink: 0; }
.mt-status-icon.is-done { color: var(--accent); }

.mt-td--look { justify-content: center; }
.mt-look { color: var(--text-tertiary); display: inline-flex; }
.mt-look:hover { color: var(--accent); }

.mt-addnew {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 12px; padding: 8px 4px;
  font-size: 13px; font-weight: 500; color: var(--accent);
  text-decoration: none;
}
.mt-addnew:hover { text-decoration: none; color: var(--accent-hover); }

/* The grid sheds its least load-bearing columns before it starts truncating names.
   Each block hides one more and restates the track list to match what is left —
   a display:none cell leaves grid flow, so the two must always agree. */
@media (max-width: 1500px) {
  /* − sprint */
  .mt-table { --mt-cols: 34px minmax(200px, 2.2fr) minmax(140px, 1fr) minmax(130px, 1fr) minmax(100px, .8fr) 92px 104px 148px 40px; }
  .mt-td--sprint { display: none; }
}
@media (max-width: 1280px) {
  /* − bucket */
  .mt-table { --mt-cols: 34px minmax(190px, 2.2fr) minmax(130px, 1fr) minmax(120px, 1fr) 88px 100px 144px 40px; }
  .mt-td--bucket { display: none; }
}
@media (max-width: 1080px) {
  /* − customer, − status. Board stays: it is the grouping everything else hangs off. */
  .mt-table { --mt-cols: 34px minmax(180px, 2.4fr) minmax(120px, 1fr) 84px 96px 40px; }
  .mt-td--customer, .mt-td--status { display: none; }
}

/* ── Board layout ──────────────────────────────────────────────────────────────
   The board view renders the board pages' own markup and card, so it inherits their
   styling wholesale. Only the wrapper differs: My Tasks columns grow with their
   content and the page scrolls, rather than each column scrolling inside a fixed
   viewport height the way a dedicated board page does. */
.mt-wrap--board { display: block; overflow: visible; }
.mt-board {
  display: flex; gap: 14px;
  align-items: flex-start;
  overflow-x: auto;
  padding-bottom: 8px;
}
/* overflow too, not just max-height: the base column clips at its own bounds, so an
   expanding Completed panel toggled open but stayed invisible behind the clip. Here
   the column grows with its content and the page scrolls, Planner-style. */
.mt-board .kanban-column { max-height: none; overflow: visible; }
.mt-board .kanban-column-body { overflow: visible; }

/* ── Completed section ─────────────────────────────────────────────────────────
   Shared by the My Tasks board and every kanban column. Finished work, collapsed,
   shown for reference rather than for working on. */
.done-section { margin-top: 4px; }
.done-section > summary {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 4px;
  font-size: 12.5px; font-weight: 500; color: var(--text-secondary);
  cursor: pointer; list-style: none;
}
.done-section > summary::-webkit-details-marker { display: none; }
.done-section > summary:hover { color: var(--text-primary); }
.done-chev { font-size: 14px; transition: transform .15s; }
.done-section[open] > summary .done-chev { transform: rotate(90deg); }
.done-count { margin-left: auto; font-size: 11px; color: var(--text-tertiary); }
.done-body { display: flex; flex-direction: column; gap: 8px; padding-top: 4px; }


.tasklist-none {
  padding: 40px 24px; text-align: center; color: var(--text-secondary);
  display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.tasklist-none i { font-size: 30px; color: var(--text-tertiary); }
.tasklist-none p { font-size: 13px; }

/* ══ Calendar grouping ════════════════════════════════════════════════════════
   A month grid built from the board's own .kanban-* elements, so drag-and-drop and
   the filter pane work untouched. Everything below is layout: the kanban's column
   rules are overridden rather than replaced. */

/* The calendar's controls, on a line of their own. A bordered bar rather than a bare
   row, so the options read as a toolbar and the grid below reads as the calendar
   itself — the two were previously one undifferentiated strip. */
.cal-toolbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 14px;
  margin-bottom: 14px;
  flex-shrink: 0;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.cal-toolbar-nav { display: flex; align-items: center; gap: 8px; }
.cal-scale { margin-left: auto; }
/* Inside the wrap the flex gap already separates the toolbar from the grid; the margin
   would stack on top of it and open twice the space My Tasks needs versus the board. */
.cal-wrap > .cal-toolbar { margin-bottom: 0; }

/* The grid, as its own surface below the toolbar. Scrolls sideways itself rather than
   clipping: seven readable day columns do not fit a narrow window, and hiding the
   overflow would simply cut Thursday off. */
.cal-section {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 12px;
  overflow-x: auto;
}
/* The grid draws its own frame, which would double up inside the section. */
.cal-section .cal-grid { border: none; border-radius: var(--radius-md); }


.cal-month {
  font-size: 16px; font-weight: 600; letter-spacing: -0.02em;
  min-width: 168px;
}
.cal-nav {
  width: 28px; height: 28px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  color: var(--text-secondary); text-decoration: none;
}
.cal-nav:hover { background: var(--bg-hover); color: var(--text-primary); text-decoration: none; }
.cal-today {
  font-size: 12px; font-weight: 500; color: var(--text-secondary);
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  padding: 5px 11px; text-decoration: none;
}
.cal-today:hover { background: var(--bg-hover); color: var(--text-primary); text-decoration: none; }

/* The wrap is a kanban wrap, but stacked rather than scrolled sideways. */
/* A calendar stacks: toolbar, then grid, then the unscheduled tray. Every declaration
   here exists to undo .kanban-wrap, which lays its children out as a horizontal row of
   fixed-width columns — the wrong shape entirely for a calendar. */
.cal-wrap {
  display: flex; flex-direction: column; gap: 14px;
  flex: 1; min-height: 0;
  overflow-y: auto;
  overflow-x: visible;
  /* .kanban-wrap pins a viewport-relative height for its scrolling columns; the
     calendar sizes to the content area it sits in instead. */
  height: auto;
  align-items: stretch;
}
/* Children must fill the width rather than shrink to their content, which is what a
   flex row would otherwise do to them. */
.cal-wrap > * { width: 100%; }
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
/* Seven cells instead of thirty-five, so each can hold a real day's work rather than
   two cards and a scrollbar. */
.cal-grid--week .cal-cell { min-height: 460px; }

.cal-dow {
  background: var(--bg-subtle);
  padding: 8px 10px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text-tertiary);
  text-align: center;
}
.cal-dow.is-off { color: var(--border-strong); }

/* A day cell IS a .kanban-column, so the column rules have to be neutralised. */
.cal-cell {
  flex: none;
  background: var(--bg-surface);
  border: none;
  border-radius: 0;
  min-height: 122px;
  max-height: none;
  display: flex; flex-direction: column;
}
.cal-cell.is-outside { background: var(--bg-subtle); }
.cal-cell.is-outside .cal-daynum { color: var(--text-tertiary); }
.cal-cell.is-off { background: var(--bg-subtle); }
.cal-cell.is-today { box-shadow: inset 0 0 0 2px var(--accent); }

.cal-cell-head {
  padding: 6px 8px 4px;
  border-bottom: none;
  display: flex; align-items: center; gap: 6px;
  flex-shrink: 0;
}
.cal-daynum { font-size: 12px; font-weight: 600; color: var(--text-secondary); }
.cal-cell.is-today .cal-daynum {
  background: var(--accent); color: #fff;
  min-width: 20px; height: 20px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px;
}
/* Rendered only because board.js writes into it without checking it exists, and both
   scripts would throw or mis-tally without it. A day cell shows its handful of cards
   plainly enough that a number on top of them is noise, so it is hidden outright. */
.cal-cell .kanban-column-count { display: none; }

.cal-cell-body {
  flex: 1; min-height: 0;
  padding: 0 6px 6px;
  display: flex; flex-direction: column; gap: 4px;
  overflow-y: auto;
}
/* board.js appends "Drop cards here" to every empty droppable column. Across a month
   grid that is thirty-odd repetitions of the same hint, so it is suppressed here. */
.cal-wrap .kanban-empty-col { display: none; }

/* ── Completed panel inside a kanban column ───────────────────────────────────── */
.kanban-done { border-top: 1px solid var(--border); padding-top: 2px; }
/* On a real board the column scrolls, so the panel must not force it wider or taller —
   it simply becomes more content for that scroll. */
.kanban-done .done-body { max-height: none; }
.kanban-done > summary { padding: 8px 2px; }
/* Finished cards read as settled: quieter, struck through, and plainly not draggable. */
.kanban-done .kanban-card {
  opacity: .68;
  cursor: default;
  box-shadow: none;
}
.kanban-done .kanban-card:hover { opacity: .85; }
.kanban-done .kanban-card-title {
  text-decoration: line-through;
  text-decoration-color: var(--border-strong);
}
/* The controls on a finished card would all act on work that is already done. */
.kanban-done .kanban-assign,
.kanban-done .kanban-checklist-panel { display: none; }

/* ── Calendar card ─────────────────────────────────────────────────────────── */
.cal-card {
  padding: 5px 7px;
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--border-strong);
  background: var(--bg-surface);
  box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column; gap: 3px;
  cursor: grab;
}
.cal-card.pri--critical { border-left-color: var(--pri-critical-bar); }
.cal-card.pri--high     { border-left-color: var(--pri-high-bar); }
.cal-card.pri--medium   { border-left-color: var(--pri-medium-bar); }
.cal-card.pri--low      { border-left-color: var(--pri-low-bar); }
.cal-card.is-overdue { background: var(--bg-danger); }
.cal-card-title {
  font-size: 11.5px; font-weight: 500; line-height: 1.25;
  color: var(--text-primary); text-decoration: none;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.cal-card-title:hover { color: var(--accent); text-decoration: none; }
.cal-card-foot { display: flex; align-items: center; gap: 5px; }
.cal-card-board {
  font-size: 9.5px; color: var(--text-tertiary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cal-card-who { margin-left: auto; flex-shrink: 0; }
/* Names would not fit a day cell; the stack alone carries who owns the work. */
.cal-card-who .avatars-name { display: none; }

/* ── Unscheduled tray ──────────────────────────────────────────────────────── */
.cal-tray {
  flex: none;
  background: var(--bg-subtle);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  max-height: none;
}
.cal-tray-head { display: flex; align-items: center; gap: 8px; }
.cal-tray-hint { margin-left: auto; font-size: 11px; color: var(--text-tertiary); }
.cal-tray-body {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 6px;
  max-height: 190px;
}

@media (max-width: 1024px) {
  /* Seven readable columns do not fit; .cal-section scrolls sideways rather than
     crushing them, so only the grid's own minimum is needed here. */
  .cal-grid { min-width: 860px; }
}

/* ══ New Task dialog ══════════════════════════════════════════════════════════
   Raising a task should not cost you the page you were reading, so the form opens
   over it. The markup inside is the same partial the full page renders. */
.fdlg {
  /* margin:auto is what centres a modal <dialog>, and the global `* { margin: 0 }`
     reset at the top of this file strips it — which pinned the dialog to the top-left
     corner. Restored explicitly rather than by weakening the reset. */
  margin: auto;
  width: min(680px, calc(100vw - 32px));
  max-height: min(86vh, 900px);
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  background: var(--bg-surface);
  color: var(--text-primary);
  overflow: hidden;
}
.fdlg::backdrop { background: rgba(17, 24, 39, 0.45); }
.fdlg-head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-subtle);
}
.fdlg-title { font-size: 15px; font-weight: 600; letter-spacing: -0.02em; display: flex; align-items: center; gap: 8px; }
.fdlg-close {
  margin-left: auto;
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; border-radius: var(--radius-sm);
  color: var(--text-secondary); cursor: pointer;
}
.fdlg-close:hover { background: var(--bg-hover); color: var(--text-primary); }
.fdlg-body { padding: 18px; overflow-y: auto; max-height: calc(86vh - 56px); }
/* The form carries its own card chrome for the standalone page; inside the dialog the
   dialog IS the card, so that second frame has to go. */
.fdlg-body .form-card {
  max-width: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  background: transparent;
}
.fdlg-busy { padding: 28px; text-align: center; font-size: 13px; color: var(--text-secondary); }

/* Standalone-page width for the New Task form. A class rather than an inline style,
   so the dialog rule above can widen it to the dialog's own bounds. */
.form-card--newtask { max-width: 620px; }

/* ── Quick assign ──────────────────────────────────────────────────────────────
   The queue's per-row assign dialog: who, how long and when up front, with the
   placement fields folded away behind More details. */
.mt-assign { color: var(--accent); }
.mt-assign:hover { color: var(--accent-hover); }

.qa-form.form-card {
  border: none; border-radius: 0; box-shadow: none; padding: 0; background: transparent;
  max-width: none;
}
/* The record being assigned, so the dialog is never ambiguous about its subject. */
.qa-subject {
  padding: 10px 12px; margin-bottom: 16px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  display: flex; flex-direction: column; gap: 2px;
}
.qa-num { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-tertiary); }
.qa-title { font-size: 13.5px; font-weight: 600; line-height: 1.35; }
.qa-customer { font-size: 11.5px; color: var(--text-secondary); }

.qa-more { margin-top: 4px; border-top: 1px solid var(--border); padding-top: 10px; }
.qa-more > summary {
  cursor: pointer; list-style: none;
  font-size: 12.5px; font-weight: 500; color: var(--accent);
  padding: 4px 0; margin-bottom: 8px;
  display: flex; align-items: center; gap: 6px;
}
.qa-more > summary::-webkit-details-marker { display: none; }
/* A caret that turns, so the section reads as expandable before it is touched. */
.qa-more > summary::before {
  content: "\ea61"; font-family: "tabler-icons"; font-size: 14px;
  transition: transform .15s;
}
.qa-more[open] > summary::before { transform: rotate(90deg); }
.qa-more > summary:hover { color: var(--accent-hover); }

/* ── Scrollbar ─────────────────────────────────────────────────────────────── */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-md); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }

/* ── Responsive ────────────────────────────────────────────────────────────── */
@media (max-width: 1024px) {
  .detail-panel { display: none; }
  .sla-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Planning and the cockpit stack rather than squeeze: a 440px capacity panel and a
     burndown beside it both stop being readable well before the viewport does. */
  .plan-shell { grid-template-columns: minmax(0, 1fr); }
  .cockpit-top { grid-template-columns: minmax(0, 1fr); }
  .cockpit-figures { grid-template-rows: none; grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .sidebar { display: none; }
  .sla-row { grid-template-columns: 1fr; }
}

/* ── Admin screens ──────────────────────────────────────────────────────────
   Shared by the five configuration pages. One page per lookup table: a create
   row on top, then the table with an inline editor behind each name. */
.admin-page { display: flex; flex-direction: column; gap: 14px; }

.admin-intro {
  background: var(--bg-info);
  border-radius: var(--radius-md);
  padding: 12px 15px;
  font-size: 12.5px; line-height: 1.55;
  color: var(--text-info);
  max-width: 900px;
}
.admin-intro strong { font-weight: 700; }

.admin-create {
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 14px 16px;
}
.admin-field { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 130px; }
.admin-field--wide { flex-basis: 100%; }
.admin-field label,
.admin-edit-form label {
  font-size: 10px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.admin-check {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--text-secondary); white-space: nowrap;
}

.admin-create-panel > summary {
  display: inline-flex; align-items: center; gap: 6px;
  cursor: pointer; list-style: none; width: fit-content;
}
.admin-create-panel > summary::-webkit-details-marker { display: none; }
.admin-form-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin-top: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px;
}

.admin-table-wrap {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.admin-table { width: 100%; border-collapse: collapse; }
.admin-table th {
  text-align: left; padding: 10px 14px;
  font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-tertiary);
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border);
}
.admin-table td {
  padding: 11px 14px;
  font-size: 13px;
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: top;
}
.admin-table tr:last-child td { border-bottom: none; }
.admin-table .mono { font-family: var(--font-mono); font-size: 12px; }
.admin-table .muted { color: var(--text-tertiary); }
/* A retired row stays legible but visibly out of service. */
.admin-table tr.is-retired td { opacity: .58; }

.admin-edit > summary {
  cursor: pointer; font-weight: 600; list-style: none;
  color: var(--text-primary);
}
.admin-edit > summary::-webkit-details-marker { display: none; }
.admin-edit > summary:hover { color: var(--accent); }
.admin-edit[open] > summary { color: var(--accent); }
.admin-edit-form {
  display: flex; flex-direction: column; gap: 4px;
  margin-top: 10px; padding: 12px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  min-width: 260px;
}
.admin-edit-form .form-control { margin-bottom: 4px; }
.admin-edit-form button { margin-top: 8px; }

.admin-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.admin-danger { color: var(--text-danger); }
.admin-chips { display: flex; gap: 5px; flex-wrap: wrap; }

.swatch {
  display: inline-block; width: 12px; height: 12px;
  border-radius: 3px; margin-right: 6px;
  vertical-align: -1px;
  box-shadow: inset 0 0 0 1px rgba(17,24,39,.12);
}
.kcp-fill.is-over { background: var(--pri-critical-bar); }

/* ── Board filter pane (Planner-style) ─────────────────────────────────────
   A right-hand slide-out over the board, with collapsible facet groups. All the
   filtering happens in the browser — see wwwroot/js/board-filters.js. */

/* Toolbar: keyword box and the Filters button, beside the grouping toggle. */
.bf-search {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; min-width: 210px;
  border-bottom: 1px solid var(--border-md);
  color: var(--text-tertiary);
}
.bf-search input {
  flex: 1; border: 0; outline: none; background: none;
  font-family: inherit; font-size: 12.5px; color: var(--text-primary);
}
.bf-search:focus-within { border-bottom-color: var(--accent); }

.bf-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; cursor: pointer;
  font-family: inherit; font-size: 12.5px; font-weight: 500;
  color: var(--text-primary);
  background: var(--bg-surface);
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
}
.bf-toggle:hover { background: var(--bg-hover); }
.bf-toggle.is-active { border-color: var(--accent); color: var(--accent); }
.bf-toggle-count { font-weight: 600; }

/* Scrim: dims the board and gives a click-anywhere-to-close target. */
.bf-scrim {
  position: fixed; inset: 0; z-index: 190;
  background: rgba(15, 23, 42, .28);
}

.bf-pane {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 200;
  width: 340px; max-width: 92vw;
  display: flex; flex-direction: column;
  background: var(--bg-surface);
  border-left: 1px solid var(--border-md);
  box-shadow: var(--shadow-lg);
}

.bf-head {
  display: flex; align-items: center; gap: 10px;
  padding: 18px 16px 12px;
  border-bottom: 1px solid var(--border);
}
.bf-head h2 { flex: 1; margin: 0; font-size: 20px; font-weight: 600; }
.bf-clear {
  border: 0; background: none; cursor: pointer;
  font-family: inherit; font-size: 12.5px; color: var(--accent);
}
.bf-clear:hover { text-decoration: underline; }
.bf-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; cursor: pointer;
  border: 1px solid var(--border-md); border-radius: var(--radius-sm);
  background: var(--bg-surface); color: var(--text-secondary);
}
.bf-close:hover { background: var(--bg-hover); color: var(--text-primary); }

.bf-body { flex: 1; overflow-y: auto; padding: 6px 0 20px; }

/* Each facet group is a <details>, so collapsing needs no script. */
.bf-group { border-bottom: 1px solid var(--border); }
.bf-group > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 6px;
  padding: 13px 16px;
  font-size: 13.5px; font-weight: 500; color: var(--text-primary);
  background: var(--bg-subtle);
}
.bf-group > summary::-webkit-details-marker { display: none; }
.bf-chev {
  margin-left: auto; font-size: 15px; color: var(--text-tertiary);
  transition: transform .12s ease;
}
.bf-group[open] .bf-chev { transform: rotate(180deg); }
.bf-group > summary:hover { background: var(--bg-hover); }
.bf-count { color: var(--text-tertiary); font-size: 12.5px; }
.bf-group.has-selection > summary { color: var(--accent); }
.bf-group.has-selection .bf-count { color: var(--accent); font-weight: 600; }

.bf-options { padding: 4px 0 10px; }

/* The checkbox itself is hidden: the row is the control, and a tick on the right
   marks the selection — the same shape Planner uses. */
.bf-opt {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 16px; cursor: pointer;
  font-size: 13px; color: var(--text-primary);
}
.bf-opt:hover { background: var(--bg-hover); }
.bf-opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.bf-opt > span { flex: 1; }
.bf-opt > .ti-check { visibility: hidden; color: var(--accent); font-size: 16px; }
.bf-opt input:checked ~ .ti-check { visibility: visible; }
/* Keyboard focus has to land somewhere visible, since the input is hidden. */
.bf-opt input:focus-visible ~ span { outline: 2px solid var(--accent); outline-offset: 2px; }

.bf-person { display: flex; align-items: center; gap: 9px; }

/* A column emptied by filtering reads as "nothing matches", not as an empty bucket.
   It stays a drop target. */
.kanban-card.is-filtered-out { display: none; }
.kanban-column.is-filtered-empty { opacity: .55; }
