/* Misc extras — Toasts, NotificationDrawer, KeyboardCheatsheet, FilterPopover */

/* ─── Toasts ─── */
function ToastStack({ toasts, onDismiss }) {
  return (
    <div style={{
      position: 'fixed', right: 20, bottom: 20,
      display: 'flex', flexDirection: 'column-reverse', gap: 8,
      zIndex: 300, pointerEvents: 'none',
    }}>
      {toasts.map(t => (
        <div key={t.id} className="slide-in-r" style={{
          background: 'rgb(var(--surface))',
          border: '1px solid rgb(var(--rule))',
          borderLeft: `3px solid ${toneToColour(t.tone)}`,
          borderRadius: 10,
          boxShadow: 'var(--sh-md)',
          padding: '10px 14px',
          minWidth: 280, maxWidth: 360,
          display: 'flex', alignItems: 'flex-start', gap: 10,
          pointerEvents: 'auto',
        }}>
          <span style={{
            fontSize: 14, color: toneToColour(t.tone),
            background: toneToSoft(t.tone),
            width: 26, height: 26, borderRadius: 8,
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            flexShrink: 0,
          }}>{toneToIcon(t.tone)}</span>
          <div style={{ flex: 1, minWidth: 0 }}>
            {t.title && <div style={{ fontSize: 13, fontWeight: 600, color: 'rgb(var(--ink))' }}>{t.title}</div>}
            <div style={{ fontSize: 12.5, color: 'rgb(var(--ink-2))', marginTop: t.title ? 2 : 0 }}>{t.body}</div>
          </div>
          <button onClick={() => onDismiss(t.id)} style={{
            fontSize: 16, color: 'rgb(var(--muted))', padding: '0 4px', borderRadius: 4, lineHeight: 1,
          }}>×</button>
        </div>
      ))}
    </div>
  );
}
const toneToColour = tone => ({
  success: 'rgb(var(--forest))', error: 'rgb(var(--brick))',
  info: 'rgb(var(--accent))', warn: 'rgb(var(--warm))',
}[tone] || 'rgb(var(--accent))');
const toneToSoft = tone => ({
  success: 'rgb(var(--forest-soft))', error: 'rgb(var(--brick-soft))',
  info: 'rgb(var(--accent-soft))', warn: 'rgb(var(--warm-soft))',
}[tone] || 'rgb(var(--accent-soft))');
const toneToIcon = tone => ({
  success: '✓', error: '!', info: 'i', warn: '⚠',
}[tone] || 'i');

/* ─── Notification slide-over ─── */
function NotificationDrawer({ open, onClose, onOpenTask }) {
  if (!open) return null;
  const items = [
    { id: 1, kind: 'mention',  user: userById(2), at: '11:05', taskId: 1, body: 'mentioned you in a comment',  preview: '@alex.harley — flagging that patient mentioned medication concerns. May need pharmacist…', unread: true },
    { id: 2, kind: 'assigned', user: userById(3), at: '10:42', taskId: 3, body: 'assigned you a task',          preview: 'Send assessment booking confirmation — Aldridge', unread: true },
    { id: 3, kind: 'comment',  user: userById(4), at: 'yesterday', taskId: 4, body: 'commented on your task',   preview: 'Held for 38 mins, line dropped. Re-trying first thing Tuesday.', unread: true },
    { id: 4, kind: 'status',   user: userById(1), at: 'yesterday', taskId: 6, body: 'moved task to Review',     preview: 'Q2 information governance audit — gather evidence', unread: false },
    { id: 5, kind: 'mention',  user: userById(6), at: '2d ago', taskId: 7, body: 'mentioned you in a comment',  preview: 'Letter ready for sign-off when you have a moment.', unread: false },
  ];
  const kindIcon = { mention: '@', assigned: '◉', comment: '💬', status: '↪' };
  const kindColour = { mention: 'rgb(var(--accent))', assigned: 'rgb(var(--forest))', comment: 'rgb(var(--navy))', status: 'rgb(var(--warm))' };

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.4)', backdropFilter: 'blur(4px)',
      display: 'flex', justifyContent: 'flex-end', zIndex: 200,
    }}>
      <div onClick={e => e.stopPropagation()} className="slide-in-r" style={{
        width: 400, height: '100vh', background: 'rgb(var(--surface))',
        borderLeft: '1px solid rgb(var(--rule))',
        display: 'flex', flexDirection: 'column',
        boxShadow: 'var(--sh-pop)',
      }}>
        <div style={{ padding: '14px 18px', borderBottom: '1px solid rgb(var(--rule))', display: 'flex', alignItems: 'center' }}>
          <div>
            <h3 style={{ margin: 0, fontSize: 15, fontWeight: 700 }}>Inbox</h3>
            <p style={{ margin: '2px 0 0', fontSize: 12, color: 'rgb(var(--muted))' }}>3 unread · mentions, replies, assignments</p>
          </div>
          <span style={{ flex: 1 }} />
          <button className="btn btn-ghost" style={{ fontSize: 11.5, padding: '4px 8px' }}>Mark all read</button>
          <button onClick={onClose} style={{ fontSize: 20, color: 'rgb(var(--muted))', padding: '0 6px', borderRadius: 6, lineHeight: 1 }}>×</button>
        </div>

        <div style={{ flex: 1, overflowY: 'auto' }}>
          {items.map(it => (
            <button key={it.id} onClick={() => { onOpenTask(it.taskId); onClose(); }} style={{
              display: 'grid', gridTemplateColumns: '36px 1fr auto', gap: 12,
              width: '100%', padding: '12px 18px', textAlign: 'left',
              borderBottom: '1px solid rgb(var(--rule) / 0.6)',
              background: it.unread ? 'rgb(var(--accent-soft) / 0.18)' : 'transparent',
              position: 'relative',
            }}
              onMouseEnter={e => e.currentTarget.style.background = 'rgb(var(--paper-2) / 0.6)'}
              onMouseLeave={e => e.currentTarget.style.background = it.unread ? 'rgb(var(--accent-soft) / 0.18)' : 'transparent'}>
              {it.unread && <span style={{ position: 'absolute', left: 4, top: '50%', transform: 'translateY(-50%)', width: 6, height: 6, background: 'rgb(var(--accent))', borderRadius: '50%' }} />}
              <span style={{ position: 'relative' }}>
                <Avatar user={it.user} size={32} />
                <span style={{
                  position: 'absolute', bottom: -2, right: -2,
                  width: 18, height: 18, borderRadius: '50%',
                  background: kindColour[it.kind],
                  color: 'white',
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: 10, fontWeight: 700,
                  boxShadow: '0 0 0 2px rgb(var(--surface))',
                }}>{kindIcon[it.kind]}</span>
              </span>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontSize: 13 }}>
                  <strong>{it.user.name}</strong>{' '}
                  <span style={{ color: 'rgb(var(--muted))' }}>{it.body}</span>
                </div>
                <div style={{ fontSize: 12, color: 'rgb(var(--ink-2))', marginTop: 3, overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical' }}>{it.preview}</div>
              </div>
              <span style={{ fontSize: 11, color: 'rgb(var(--muted))', whiteSpace: 'nowrap', paddingTop: 2 }}>{it.at}</span>
            </button>
          ))}
        </div>

        <div style={{ borderTop: '1px solid rgb(var(--rule))', padding: '10px 16px', background: 'rgb(var(--bg))', fontSize: 11.5, color: 'rgb(var(--muted))' }}>
          Push notifications · <span style={{ color: 'rgb(var(--forest))' }}>● enabled</span> · digest emails daily 07:30
        </div>
      </div>
    </div>
  );
}

/* ─── Keyboard cheatsheet ─── */
function KeyboardCheatsheet({ open, onClose }) {
  if (!open) return null;
  const sections = [
    ['Navigation', [
      ['⌘ K', 'Open command palette'],
      ['G then D', 'Go to My Day'],
      ['G then I', 'Go to Inbox'],
      ['G then B', 'Go to Board view'],
      ['G then C', 'Go to Calendar view'],
    ]],
    ['Task', [
      ['C',       'Create new task'],
      ['E',       'Edit selected task title'],
      ['Space',   'Toggle complete'],
      ['1–4',     'Set priority (urgent → low)'],
      ['Shift+S', 'Change status'],
      ['Shift+A', 'Assign to me'],
    ]],
    ['Detail pane', [
      ['Esc',     'Close detail pane'],
      ['M',       'Focus comment composer'],
      ['T',       'Start / stop timer'],
      ['/',       'Slash command in composer'],
    ]],
    ['Workspace', [
      ['?',       'Show this cheatsheet'],
      [',',       'Open Tweaks'],
      ['N',       'Open Inbox'],
      ['B',       'Toggle detail pane'],
    ]],
  ];

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(15,23,42,0.5)', backdropFilter: 'blur(6px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 250, padding: 40,
    }}>
      <div onClick={e => e.stopPropagation()} className="fadein shadow-pop" style={{
        background: 'rgb(var(--surface))', border: '1px solid rgb(var(--rule))',
        borderRadius: 14, width: 720, maxHeight: '80vh',
        display: 'flex', flexDirection: 'column',
      }}>
        <div style={{ padding: '16px 24px', borderBottom: '1px solid rgb(var(--rule))', display: 'flex', alignItems: 'center' }}>
          <div>
            <h3 style={{ margin: 0, fontSize: 17, fontWeight: 700 }}>Keyboard shortcuts</h3>
            <p style={{ margin: '2px 0 0', fontSize: 12, color: 'rgb(var(--muted))' }}>Fly through Taskhub without touching a mouse.</p>
          </div>
          <span style={{ flex: 1 }} />
          <button onClick={onClose} className="btn btn-secondary" style={{ fontSize: 11 }}><kbd style={{ fontFamily: 'JetBrains Mono, monospace' }}>esc</kbd></button>
        </div>
        <div style={{ flex: 1, overflowY: 'auto', padding: '20px 24px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 28 }}>
          {sections.map(([head, items]) => (
            <div key={head}>
              <p style={{
                margin: '0 0 10px', fontSize: 11, fontWeight: 600,
                color: 'rgb(var(--accent))', textTransform: 'uppercase', letterSpacing: '0.06em',
              }}>{head}</p>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                {items.map(([key, label]) => (
                  <div key={key} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                    <span style={{ flex: 1, fontSize: 13, color: 'rgb(var(--ink-2))' }}>{label}</span>
                    <span style={{
                      fontFamily: 'JetBrains Mono, monospace', fontSize: 11,
                      padding: '3px 9px',
                      background: 'rgb(var(--paper-2))',
                      border: '1px solid rgb(var(--rule))',
                      borderRadius: 6,
                      color: 'rgb(var(--ink))', fontWeight: 600,
                    }}>{key}</span>
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ─── Filter popover ─── */
function FilterPopover({ filters, smartFilter, onTogglePriority, onSetSmart, onClose, onClear, anchorRef }) {
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 80 }}>
      <div onClick={e => e.stopPropagation()} className="fadein shadow-pop" style={{
        position: 'absolute', top: 96, right: 24,
        background: 'rgb(var(--surface))', border: '1px solid rgb(var(--rule))',
        borderRadius: 12, width: 320, padding: 16,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', marginBottom: 12 }}>
          <h4 style={{ margin: 0, fontSize: 14, fontWeight: 700 }}>Filters</h4>
          <span style={{ flex: 1 }} />
          <button onClick={onClear} className="btn-ghost" style={{ fontSize: 11.5 }}>Clear all</button>
        </div>

        <p style={{ margin: '0 0 8px', fontSize: 11, fontWeight: 600, letterSpacing: '0.04em', color: 'rgb(var(--muted))', textTransform: 'uppercase' }}>Quick filters</p>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 14 }}>
          {[['today','Today'],['week','This week'],['overdue','Overdue'],['unscheduled','Unscheduled']].map(([k, lbl]) => (
            <button key={k} onClick={() => onSetSmart(smartFilter === k ? null : k)} style={{
              padding: '5px 12px', fontSize: 12, fontWeight: 500,
              background: smartFilter === k ? 'rgb(var(--accent))' : 'rgb(var(--surface))',
              color: smartFilter === k ? 'white' : 'rgb(var(--ink-2))',
              border: '1px solid ' + (smartFilter === k ? 'rgb(var(--accent))' : 'rgb(var(--rule))'),
              borderRadius: 999,
            }}>{lbl}</button>
          ))}
        </div>

        <p style={{ margin: '0 0 8px', fontSize: 11, fontWeight: 600, letterSpacing: '0.04em', color: 'rgb(var(--muted))', textTransform: 'uppercase' }}>Priority</p>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          {[['urgent','Urgent'],['high','High'],['medium','Medium'],['low','Low']].map(([k, lbl]) => {
            const on = filters.priorities.includes(k);
            return (
              <button key={k} onClick={() => onTogglePriority(k)} style={{
                padding: '5px 12px', fontSize: 12, fontWeight: 500,
                display: 'inline-flex', alignItems: 'center', gap: 6,
                background: on ? 'rgb(var(--ink))' : 'rgb(var(--surface))',
                color: on ? 'white' : 'rgb(var(--ink-2))',
                border: '1px solid ' + (on ? 'rgb(var(--ink))' : 'rgb(var(--rule))'),
                borderRadius: 999,
              }}>
                <span className={`prio prio-${k}`} style={{ width: 7, height: 7 }} />{lbl}
              </button>
            );
          })}
        </div>
      </div>
    </div>
  );
}

/* ─── Activity ticker ─── */
function ActivityTicker() {
  const events = React.useMemo(() => [
    { who: userById(2), what: 'commented on', target: 'INT-2026-00104' },
    { who: userById(3), what: 'created',      target: 'INT-2026-00105' },
    { who: userById(1), what: 'moved',        target: 'COMP-2026-00007', to: 'In progress' },
    { who: userById(4), what: 'logged time on', target: 'BILL-2026-00078' },
    { who: userById(5), what: 'opened',       target: 'OPS-2026-00012' },
  ], []);
  const [idx, setIdx] = React.useState(0);
  React.useEffect(() => {
    const t = setInterval(() => setIdx(i => (i + 1) % events.length), 4000);
    return () => clearInterval(t);
  }, []);
  const e = events[idx];
  return (
    <div key={idx} className="fadein" style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      fontSize: 11.5, color: 'rgb(var(--muted))',
      padding: '4px 10px', background: 'rgb(var(--paper-2))', borderRadius: 999,
      whiteSpace: 'nowrap', maxWidth: 360, overflow: 'hidden', textOverflow: 'ellipsis',
    }}>
      <span style={{ width: 5, height: 5, background: 'rgb(var(--forest))', borderRadius: '50%', animation: 'pulse-dot 1.6s infinite', flexShrink: 0 }} />
      <Avatar user={e.who} size={16} />
      <span><strong style={{ color: 'rgb(var(--ink))', fontWeight: 600 }}>{e.who.name.split(' ')[0]}</strong> {e.what} <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: 'rgb(var(--ink-2))' }}>{e.target}</span>{e.to ? ` → ${e.to}` : ''}</span>
    </div>
  );
}

/* ─── Focus mode overlay ─── */
function FocusModeOverlay({ task, onClose, onComplete }) {
  if (!task) return null;
  const sp = spaceById(task.spaceId);
  const [seconds, setSeconds] = React.useState(0);
  React.useEffect(() => {
    const t = setInterval(() => setSeconds(s => s + 1), 1000);
    return () => clearInterval(t);
  }, []);
  const mins = Math.floor(seconds / 60), secs = seconds % 60;

  return (
    <div style={{
      position: 'fixed', inset: 0,
      background: 'radial-gradient(ellipse at top, rgb(var(--accent-soft)) 0%, rgb(var(--bg)) 60%)',
      display: 'flex', flexDirection: 'column',
      zIndex: 220,
    }} className="fadein">
      <div style={{ padding: '24px 32px', display: 'flex', alignItems: 'center' }}>
        <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
          <span style={{ width: 8, height: 8, background: 'rgb(var(--accent))', borderRadius: '50%', animation: 'pulse-dot 1.6s infinite' }} />
          <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'rgb(var(--accent))' }}>Focus mode</span>
        </div>
        <span style={{ flex: 1 }} />
        <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 28, fontWeight: 700, color: 'rgb(var(--ink))', letterSpacing: '-0.02em' }}>
          {String(mins).padStart(2, '0')}:{String(secs).padStart(2, '0')}
        </span>
        <span style={{ flex: 1 }} />
        <button onClick={onClose} className="btn btn-secondary" style={{ fontSize: 12.5 }}>Exit focus →</button>
      </div>

      <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 32 }}>
        <div style={{ maxWidth: 720, textAlign: 'center' }}>
          <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
            <span style={{ width: 10, height: 10, background: sp.colour, borderRadius: 3 }} />
            <span style={{ fontSize: 13, fontWeight: 600, color: sp.colour }}>{sp.name}</span>
            <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: 'rgb(var(--muted))' }}>{task.ticket}</span>
          </div>
          <h1 style={{
            margin: 0, fontSize: 42, fontWeight: 700, letterSpacing: '-0.03em',
            color: 'rgb(var(--ink))', lineHeight: 1.15,
          }}>{task.title}</h1>
          {task.description && (
            <p style={{ marginTop: 18, fontSize: 16, color: 'rgb(var(--ink-2))', lineHeight: 1.55 }}>
              {task.description.split('\n')[0]}
            </p>
          )}

          {(task.checklist || []).length > 0 && (
            <div style={{ marginTop: 28, textAlign: 'left', maxWidth: 480, marginInline: 'auto' }}>
              <p style={{ fontSize: 11, fontWeight: 600, color: 'rgb(var(--muted))', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 8 }}>Checklist</p>
              {task.checklist.map(c => (
                <div key={c.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '6px 0' }}>
                  <span style={{
                    width: 18, height: 18, borderRadius: 6,
                    background: c.done ? 'rgb(var(--forest))' : 'transparent',
                    border: '1.5px solid ' + (c.done ? 'rgb(var(--forest))' : 'rgb(var(--rule-2))'),
                    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                    color: 'white', fontSize: 11, fontWeight: 700,
                  }}>{c.done ? '✓' : ''}</span>
                  <span style={{ fontSize: 14, color: c.done ? 'rgb(var(--muted))' : 'rgb(var(--ink))', textDecoration: c.done ? 'line-through' : 'none' }}>{c.title}</span>
                </div>
              ))}
            </div>
          )}

          <div style={{ marginTop: 32, display: 'flex', gap: 10, justifyContent: 'center' }}>
            <button onClick={() => onComplete(task.id)} className="btn btn-accent" style={{ fontSize: 14, padding: '10px 18px' }}>Mark complete ✓</button>
            <button onClick={onClose} className="btn btn-secondary" style={{ fontSize: 13, padding: '10px 18px' }}>Next task →</button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ─── Quick-add row ─── */
function QuickAddRow({ onAdd, placeholder = 'Add a task and press Enter…' }) {
  const [v, setV] = React.useState('');
  const submit = () => {
    if (!v.trim()) return;
    onAdd(v.trim());
    setV('');
  };
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 8,
      padding: '8px 14px',
      background: 'rgb(var(--surface))',
      border: '1px dashed rgb(var(--rule-2))',
      borderRadius: 10,
      marginBottom: 10,
      transition: 'border-color .14s, background .14s',
    }}
      onMouseEnter={e => e.currentTarget.style.borderColor = 'rgb(var(--accent))'}
      onMouseLeave={e => e.currentTarget.style.borderColor = 'rgb(var(--rule-2))'}>
      <span style={{
        width: 18, height: 18, borderRadius: 6,
        border: '1.5px dashed rgb(var(--rule-2))', flexShrink: 0,
      }} />
      <input
        value={v}
        onChange={e => setV(e.target.value)}
        onKeyDown={e => e.key === 'Enter' && submit()}
        placeholder={placeholder}
        style={{
          flex: 1, padding: '4px 0', fontSize: 13.5, fontWeight: 500,
          border: 'none', outline: 'none', background: 'transparent',
        }}
      />
      <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: 'rgb(var(--muted))', padding: '2px 6px', background: 'rgb(var(--paper-2))', borderRadius: 4 }}>Enter</span>
    </div>
  );
}

Object.assign(window, { ToastStack, NotificationDrawer, KeyboardCheatsheet, FilterPopover, ActivityTicker, FocusModeOverlay, QuickAddRow, TaskTooltip, TaskHoverArea });

/* ─── TaskTooltip — rich-content hover tooltip showing task details ─── */
function TaskHoverArea({ task, children, disabled = false }) {
  const [pos, setPos] = React.useState(null);
  const ref = React.useRef(null);
  const timerRef = React.useRef(null);
  const showT = React.useCallback(() => {
    if (disabled || !ref.current) return;
    clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => {
      if (!ref.current) return;
      const r = ref.current.getBoundingClientRect();
      const tw = 320, th = 260;
      let left = r.right + 10;
      let top  = r.top;
      if (left + tw > window.innerWidth - 12) left = Math.max(12, r.left - tw - 10);
      if (top + th > window.innerHeight - 12) top  = Math.max(12, window.innerHeight - th - 12);
      setPos({ left, top });
    }, 400);
  }, [disabled]);
  const hide = React.useCallback(() => {
    clearTimeout(timerRef.current);
    setPos(null);
  }, []);
  React.useEffect(() => () => clearTimeout(timerRef.current), []);

  return (
    <>
      <div ref={ref} onMouseEnter={showT} onMouseLeave={hide} style={{ display: 'block' }}>{children}</div>
      {pos && task && <TaskTooltip task={task} pos={pos} />}
    </>
  );
}

function TaskTooltip({ task, pos }) {
  const sp = spaceById(task.spaceId);
  const st = statusById(task.statusId);
  const subs = (task.subtasks || []).length + (task.checklist || []).length;
  const done = (task.subtasks || []).filter(s => s.done).length + (task.checklist || []).filter(c => c.done).length;
  return ReactDOM.createPortal(
    <div className="fadein" style={{
      position: 'fixed', left: pos.left, top: pos.top,
      width: 320, padding: 14, zIndex: 400,
      background: 'rgb(var(--surface))', border: '1px solid rgb(var(--rule))',
      borderRadius: 12, boxShadow: 'var(--sh-pop)',
      pointerEvents: 'none',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}>
          <span style={{ width: 8, height: 8, background: sp.colour, borderRadius: 2 }} />
          <span style={{ fontSize: 11.5, fontWeight: 600, color: sp.colour }}>{sp.name}</span>
        </span>
        <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10.5, color: 'rgb(var(--muted))' }}>{task.ticket}</span>
        <span style={{ flex: 1 }} />
        <PriorityDot p={task.priority} />
      </div>
      <h4 style={{ margin: '0 0 8px', fontSize: 14, fontWeight: 600, color: 'rgb(var(--ink))', letterSpacing: '-0.01em', lineHeight: 1.3 }}>{task.title}</h4>

      {task.description && (
        <p style={{ margin: '0 0 10px', fontSize: 12, color: 'rgb(var(--ink-2))', lineHeight: 1.5,
          display: '-webkit-box', WebkitLineClamp: 3, WebkitBoxOrient: 'vertical', overflow: 'hidden',
        }}>{task.description.replace(/[*`]/g, '').slice(0, 180)}</p>
      )}

      <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '2px 8px', background: st.colour + '14', color: st.colour, fontSize: 10.5, fontWeight: 700, borderRadius: 999 }}>
          <span style={{ width: 5, height: 5, background: st.colour, borderRadius: '50%' }} />{st.title}
        </span>
        {task.dueDate && <DueChip iso={task.dueDate} />}
        {task.tags.map(id => <TagChip key={id} tag={tagById(id)} />)}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '4px 10px', fontSize: 11.5 }}>
        {task.assignees.length > 0 && <>
          <span style={{ color: 'rgb(var(--muted))', fontWeight: 600 }}>Assignees</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
            <AvatarStack ids={task.assignees} size={18} />
            <span style={{ color: 'rgb(var(--ink-2))', marginLeft: 4 }}>{task.assignees.map(id => userById(id)?.name.split(' ')[0]).join(', ')}</span>
          </span>
        </>}
        {task.clients.length > 0 && <>
          <span style={{ color: 'rgb(var(--muted))', fontWeight: 600 }}>Patients</span>
          <span style={{ color: 'rgb(var(--ink-2))' }}>{task.clients.map(id => clientById(id)?.name).join(', ')}</span>
        </>}
        {task.estimateMins > 0 && <>
          <span style={{ color: 'rgb(var(--muted))', fontWeight: 600 }}>Estimate</span>
          <span style={{ color: 'rgb(var(--ink-2))', fontFamily: 'JetBrains Mono, monospace' }}>{fmtMins(task.estimateMins)}{task.actualMins > 0 && ` · ${fmtMins(task.actualMins)} logged`}</span>
        </>}
        {subs > 0 && <>
          <span style={{ color: 'rgb(var(--muted))', fontWeight: 600 }}>Subtasks</span>
          <span style={{ color: 'rgb(var(--ink-2))', fontFamily: 'JetBrains Mono, monospace' }}>{done}/{subs} complete</span>
        </>}
        {task.comments.length > 0 && <>
          <span style={{ color: 'rgb(var(--muted))', fontWeight: 600 }}>Comments</span>
          <span style={{ color: 'rgb(var(--ink-2))' }}>{task.comments.length}</span>
        </>}
      </div>

      <p style={{ margin: '10px 0 0', fontSize: 10.5, color: 'rgb(var(--muted))', fontStyle: 'italic' }}>Click to select · double-click to open</p>
    </div>,
    document.body
  );
}
