// HomePrimitives.jsx — primitives for the CVE Dashboard Home page kit.
// Lifted directly from frontend/src/App.js (the home view), normalized to
// match the same vocabulary the Reporting + Knowledge Base kits use.
//
// Exported on window.HOME for the assembly + docs files to consume.

const { useState: useHomeState } = React;

/* ── Tokens ──────────────────────────────────────────────────────
   Identical palette to Reporting + KB. Home adds purple (Archer)
   and teal (Ivanti) — both used as left-rail / title-glow colors
   on the right-side panel stack. */
const H_COLORS = {
  sky:       '#0EA5E9',
  skySoft:   '#7DD3FC',
  green:     '#10B981',
  amber:     '#F59E0B',
  amberSoft: '#FCD34D',
  red:       '#EF4444',
  redSoft:   '#FCA5A5',
  purple:    '#8B5CF6',
  teal:      '#0D9488',
};

/* Card chrome shared with the rest of the system. One chrome, every panel. */
const CARD_BG = 'linear-gradient(135deg, rgba(30,41,59,0.95) 0%, rgba(15,23,42,0.98) 100%)';
const CARD_BORDER = '1.5px solid rgba(14,165,233,0.12)';
const CARD_BORDER_HOVER = '1.5px solid rgba(14,165,233,0.35)';

/* ── StatCard ────────────────────────────────────────────────────
   Top-of-page metric tile. Color-coded by tone — sky for neutral
   counts, amber for "needs attention", red for critical. Top edge
   has a soft horizontal glow line in the same color. */
function StatCard({ label, value, tone = 'sky', mono = true }) {
  const c = H_COLORS[tone] || H_COLORS.sky;
  const isAccent = tone !== 'neutral';
  return (
    <div style={{
      position: 'relative', overflow: 'hidden',
      background: CARD_BG,
      border: isAccent ? `2px solid ${c}` : CARD_BORDER,
      borderRadius: 8, padding: 16,
      boxShadow: isAccent
        ? `0 4px 16px rgba(0,0,0,0.5), 0 0 20px ${withAlpha(c, 0.15)}, inset 0 1px 0 ${withAlpha(c, 0.15)}`
        : '0 4px 16px rgba(0,0,0,0.5)',
    }}>
      <div style={{
        position: 'absolute', top: 0, left: 0, right: 0, height: 2,
        background: `linear-gradient(90deg, transparent, ${c}, transparent)`,
        boxShadow: `0 0 8px ${withAlpha(c, 0.5)}`,
      }} />
      <div style={{
        fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 600,
        color: 'var(--fg-2)', textTransform: 'uppercase', letterSpacing: '0.1em',
        marginBottom: 4,
      }}>
        {label}
      </div>
      <div style={{
        fontFamily: mono ? 'var(--font-mono)' : 'var(--font-display)',
        fontSize: 24, fontWeight: 700, color: c,
        textShadow: isAccent ? `0 0 16px ${withAlpha(c, 0.4)}` : 'none',
        lineHeight: 1,
      }}>
        {value}
      </div>
    </div>
  );
}

/* ── HomeCard ────────────────────────────────────────────────────
   Same chrome as Reporting's KbCard but without a label slot —
   the home cards put their title inline above the body. Used as
   the wrapper for Quick Lookup, the filter row, and CVE rows. */
function HomeCard({ children, padding = 24, hover = true, leftRail, style }) {
  const [h, setH] = useHomeState(false);
  return (
    <div
      onMouseEnter={() => hover && setH(true)}
      onMouseLeave={() => setH(false)}
      style={{
        background: CARD_BG,
        border: h ? CARD_BORDER_HOVER : CARD_BORDER,
        borderLeft: leftRail ? `3px solid ${leftRail}` : (h ? CARD_BORDER_HOVER : CARD_BORDER).split(' ').slice(0).join(' '),
        borderRadius: 8,
        padding,
        transition: 'border-color 200ms ease, box-shadow 200ms ease',
        position: 'relative',
        ...style,
      }}
    >
      {children}
    </div>
  );
}

/* ── CardTitle ───────────────────────────────────────────────────
   Mono uppercase, glow color matches the card's identity (sky for
   neutral, amber for tickets, purple for Archer, teal for Ivanti). */
function CardTitle({ color = H_COLORS.sky, icon, children, action }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12, gap: 12 }}>
      <h3 style={{
        margin: 0,
        fontFamily: 'var(--font-mono)', fontSize: 14, fontWeight: 600,
        color, textTransform: 'uppercase', letterSpacing: '0.1em',
        textShadow: `0 0 12px ${withAlpha(color, 0.4)}`,
        display: 'flex', alignItems: 'center', gap: 8,
      }}>
        {icon && <HomeIcon name={icon} size={16} color={color} />}
        {children}
      </h3>
      {action}
    </div>
  );
}

/* ── HomeButton ──────────────────────────────────────────────────
   Wraps the four button variants the Home page uses, keeping the
   exact same tinted-fill / outlined treatment as the Reporting kit
   so all pages feel consistent. */
function HomeButton({ variant = 'neutral', icon, children, size = 'md', ...rest }) {
  const [hover, setHover] = useHomeState(false);
  const v = {
    primary: { bg: hover ? 'rgba(16,185,129,0.18)' : 'rgba(16,185,129,0.10)', bd: H_COLORS.green, fg: H_COLORS.green },
    neutral: { bg: hover ? 'rgba(14,165,233,0.10)' : 'transparent',          bd: 'rgba(14,165,233,0.5)', fg: H_COLORS.sky },
    subtle:  { bg: hover ? 'rgba(14,165,233,0.16)' : 'rgba(14,165,233,0.08)', bd: 'rgba(14,165,233,0.30)', fg: H_COLORS.sky },
    danger:  { bg: hover ? 'rgba(239,68,68,0.18)' : 'rgba(239,68,68,0.10)',  bd: 'rgba(239,68,68,0.5)', fg: H_COLORS.red },
    warning: { bg: hover ? 'rgba(245,158,11,0.18)' : 'rgba(245,158,11,0.10)', bd: 'rgba(245,158,11,0.5)', fg: H_COLORS.amber },
  }[variant];
  const padX = size === 'sm' ? 10 : 14;
  const padY = size === 'sm' ? 4 : 8;
  const fs = size === 'sm' ? 11 : 12;
  return (
    <button
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{
        display: 'inline-flex', alignItems: 'center', gap: 6,
        padding: `${padY}px ${padX}px`, borderRadius: 6,
        background: v.bg, border: `1px solid ${v.bd}`, color: v.fg,
        fontFamily: 'var(--font-mono)', fontSize: fs, fontWeight: 600,
        textTransform: 'uppercase', letterSpacing: '0.06em',
        cursor: 'pointer', transition: 'all 160ms ease', whiteSpace: 'nowrap',
      }}
      {...rest}
    >
      {icon && <HomeIcon name={icon} size={fs + 2} color={v.fg} />}
      {children}
    </button>
  );
}

/* ── SeverityBadge ───────────────────────────────────────────────
   Strong tinted-fill badge used in CVE rows. Critical/High/Medium/Low. */
function SeverityBadge({ level }) {
  const map = {
    Critical: { c: H_COLORS.red,   text: H_COLORS.redSoft },
    High:     { c: H_COLORS.amber, text: H_COLORS.amberSoft },
    Medium:   { c: H_COLORS.sky,   text: H_COLORS.skySoft },
    Low:      { c: H_COLORS.green, text: '#6EE7B7' },
  }[level] || { c: H_COLORS.sky, text: H_COLORS.skySoft };
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      background: `linear-gradient(135deg, ${withAlpha(map.c, 0.25)}, ${withAlpha(map.c, 0.20)})`,
      border: `2px solid ${map.c}`, borderRadius: 6,
      padding: '4px 10px',
      color: map.text, fontWeight: 700, fontSize: 11,
      textTransform: 'uppercase', letterSpacing: '0.05em',
      fontFamily: 'var(--font-mono)',
      textShadow: `0 0 8px ${withAlpha(map.c, 0.5)}`,
      boxShadow: `0 0 16px ${withAlpha(map.c, 0.25)}, 0 4px 8px rgba(0,0,0,0.4)`,
    }}>
      <span style={{
        display: 'inline-block', width: 6, height: 6, borderRadius: '50%',
        background: map.c, boxShadow: `0 0 8px ${map.c}`,
      }} />
      {level}
    </span>
  );
}

/* ── StatusBadge ─────────────────────────────────────────────────
   Tone-coded text badge used for ticket statuses (Open / In Progress /
   Closed / Draft / Accepted). Smaller and lighter than SeverityBadge. */
function StatusBadge({ tone = 'sky', children, size = 'md' }) {
  const c = H_COLORS[tone] || H_COLORS.sky;
  const fs = size === 'sm' ? 10 : 11;
  const pad = size === 'sm' ? '3px 7px' : '4px 9px';
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      background: withAlpha(c, 0.18),
      border: `1px solid ${c}`, borderRadius: 4,
      padding: pad, color: c,
      fontFamily: 'var(--font-mono)', fontSize: fs, fontWeight: 600,
      textTransform: 'uppercase', letterSpacing: '0.05em',
      whiteSpace: 'nowrap',
    }}>
      <span style={{
        display: 'inline-block', width: 6, height: 6, borderRadius: '50%',
        background: c, boxShadow: `0 0 6px ${c}`,
      }} />
      {children}
    </span>
  );
}

/* ── HomeInput / HomeSelect ──────────────────────────────────────
   The intel-input look: dark fill + sky border on focus. */
function HomeInput({ icon, ...rest }) {
  const [focus, setFocus] = useHomeState(false);
  return (
    <div style={{ position: 'relative', flex: 1 }}>
      {icon && (
        <div style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', color: H_COLORS.sky }}>
          <HomeIcon name={icon} size={14} color={H_COLORS.sky} />
        </div>
      )}
      <input
        onFocus={() => setFocus(true)} onBlur={() => setFocus(false)}
        style={{
          width: '100%', boxSizing: 'border-box',
          background: 'rgba(15,23,42,0.85)',
          border: `1px solid ${focus ? H_COLORS.sky : 'rgba(14,165,233,0.25)'}`,
          borderRadius: 6,
          padding: icon ? '9px 12px 9px 34px' : '9px 12px',
          color: 'var(--fg-1)',
          fontFamily: 'var(--font-mono)', fontSize: 13,
          outline: 'none', transition: 'border-color 160ms ease',
          boxShadow: focus ? `0 0 0 3px ${withAlpha(H_COLORS.sky, 0.15)}` : 'none',
        }}
        {...rest}
      />
    </div>
  );
}

function HomeSelect({ value, onChange, options }) {
  return (
    <select value={value} onChange={onChange} style={{
      width: '100%', boxSizing: 'border-box',
      background: 'rgba(15,23,42,0.85)',
      border: '1px solid rgba(14,165,233,0.25)', borderRadius: 6,
      padding: '9px 12px', color: 'var(--fg-1)',
      fontFamily: 'var(--font-mono)', fontSize: 13,
      outline: 'none', appearance: 'none',
      backgroundImage: `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='%230EA5E9' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E")`,
      backgroundRepeat: 'no-repeat', backgroundPosition: 'right 12px center', paddingRight: 32,
    }}>
      {options.map(o => <option key={o} value={o}>{o}</option>)}
    </select>
  );
}

function FieldLabel({ icon, children }) {
  return (
    <label style={{
      display: 'flex', alignItems: 'center', gap: 6,
      fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 600,
      color: 'var(--fg-2)', textTransform: 'uppercase', letterSpacing: '0.08em',
      marginBottom: 8,
    }}>
      {icon && <HomeIcon name={icon} size={13} color="currentColor" />}
      {children}
    </label>
  );
}

/* ── ResultBanner ────────────────────────────────────────────────
   Sub-card used in Quick Lookup to surface scan results.
   Tones: success (CVE addressed), warning (not found), error. */
function ResultBanner({ tone = 'success', icon, title, children }) {
  const map = {
    success: { c: H_COLORS.green, bg: 'rgba(16,185,129,0.10)', bd: 'rgba(16,185,129,0.30)' },
    warning: { c: H_COLORS.amber, bg: 'rgba(245,158,11,0.10)', bd: 'rgba(245,158,11,0.30)' },
    error:   { c: H_COLORS.red,   bg: 'rgba(239,68,68,0.10)',  bd: 'rgba(239,68,68,0.30)' },
  }[tone];
  return (
    <div style={{
      display: 'flex', alignItems: 'flex-start', gap: 12,
      padding: 16, borderRadius: 6,
      background: map.bg, border: `1px solid ${map.bd}`,
    }}>
      <div style={{ color: map.c, marginTop: 1 }}>
        <HomeIcon name={icon || tone} size={18} color={map.c} />
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 13, fontWeight: 600,
          color: map.c, marginBottom: children ? 8 : 0,
        }}>
          {title}
        </div>
        {children}
      </div>
    </div>
  );
}

/* ── BigStat ─────────────────────────────────────────────────────
   The centered "active count + label" shown at the top of each
   right-rail panel (Open Tickets · Archer · Ivanti). */
function BigStat({ value, label, color = H_COLORS.sky }) {
  return (
    <div style={{ textAlign: 'center', marginBottom: 12 }}>
      <div style={{
        fontFamily: 'var(--font-mono)', fontSize: 32, fontWeight: 700,
        color, textShadow: `0 0 16px ${withAlpha(color, 0.4)}`, lineHeight: 1,
      }}>
        {value}
      </div>
      <div style={{
        fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 600,
        color: 'var(--fg-2)', textTransform: 'uppercase', letterSpacing: '0.12em',
        marginTop: 6,
      }}>
        {label}
      </div>
    </div>
  );
}

/* ── MiniTicket ──────────────────────────────────────────────────
   Compact card shown inside the right-rail scrollable lists.
   Color-coded by category via the `tone` prop (amber/purple/teal). */
function MiniTicket({ keyText, cveId, vendor, status, tone = 'amber', summary, onEdit, onDelete }) {
  const c = H_COLORS[tone] || H_COLORS.amber;
  return (
    <div style={{
      background: 'linear-gradient(135deg, rgba(30,41,59,0.85), rgba(51,65,85,0.75))',
      border: `1px solid ${withAlpha(c, 0.25)}`, borderRadius: 6,
      padding: 10,
      boxShadow: '0 2px 6px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.03)',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 6, marginBottom: 4 }}>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 600, color: H_COLORS.sky }}>
          {keyText}
        </span>
        {(onEdit || onDelete) && (
          <div style={{ display: 'flex', gap: 4 }}>
            {onEdit && <button onClick={onEdit} style={iconBtn(H_COLORS.amber)}><HomeIcon name="edit" size={11} color="currentColor" /></button>}
            {onDelete && <button onClick={onDelete} style={iconBtn(H_COLORS.red)}><HomeIcon name="trash" size={11} color="currentColor" /></button>}
          </div>
        )}
      </div>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-1)', marginBottom: 2 }}>{cveId}</div>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-2)' }}>{vendor}</div>
      {summary && (
        <div style={{
          fontSize: 11, color: 'var(--fg-2)', marginTop: 4,
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          fontFamily: 'var(--font-display)',
        }}>{summary}</div>
      )}
      {status && (
        <div style={{ marginTop: 8 }}>
          <StatusBadge tone={tone} size="sm">{status}</StatusBadge>
        </div>
      )}
    </div>
  );
}

const iconBtn = (color) => ({
  background: 'transparent', border: 'none', color: 'var(--fg-2)',
  cursor: 'pointer', padding: 2, display: 'inline-flex', alignItems: 'center',
  transition: 'color 120ms ease',
});

/* ── CVERow ──────────────────────────────────────────────────────
   The main "row" in the home feed. Collapsed = chevron · CVE-ID ·
   description · meta row (severity badge, vendor count, doc count,
   statuses). Expanded = full description + admin actions slot. */
function CVERow({ cveId, severity, description, vendorCount, docCount, statuses, expanded, onToggle, children }) {
  return (
    <div style={{
      background: CARD_BG, border: CARD_BORDER, borderRadius: 8,
      transition: 'border-color 200ms ease',
    }}>
      <button
        onClick={onToggle}
        style={{
          width: '100%', textAlign: 'left',
          background: 'transparent', border: 'none',
          padding: 24, cursor: 'pointer',
        }}
      >
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 6 }}>
          <span style={{
            display: 'inline-block', transform: expanded ? 'rotate(0)' : 'rotate(-90deg)',
            transition: 'transform 200ms ease', color: H_COLORS.sky,
          }}>
            <HomeIcon name="chevron" size={18} color={H_COLORS.sky} />
          </span>
          <h3 style={{
            margin: 0, fontFamily: 'var(--font-mono)', fontSize: 22, fontWeight: 700,
            color: H_COLORS.sky, letterSpacing: '-0.01em',
          }}>{cveId}</h3>
        </div>
        <div style={{ marginLeft: 30 }}>
          <p style={{
            margin: '0 0 8px 0',
            color: 'var(--fg-1)', fontSize: 13, lineHeight: 1.5,
            fontFamily: 'var(--font-display)',
            display: '-webkit-box', WebkitLineClamp: expanded ? 'unset' : 1,
            WebkitBoxOrient: 'vertical', overflow: 'hidden',
            textOverflow: 'ellipsis',
          }}>
            {description}
          </p>
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap' }}>
            <SeverityBadge level={severity} />
            <span style={metaText}>{vendorCount} vendor{vendorCount !== 1 ? 's' : ''}</span>
            <span style={{ ...metaText, display: 'inline-flex', alignItems: 'center', gap: 4 }}>
              <HomeIcon name="doc" size={11} color="currentColor" />
              {docCount} doc{docCount !== 1 ? 's' : ''}
            </span>
            <span style={metaText}>{statuses.join(', ')}</span>
          </div>
        </div>
      </button>
      {expanded && children && (
        <div style={{ padding: '0 24px 24px', marginLeft: 30 }}>
          {children}
        </div>
      )}
    </div>
  );
}

const metaText = {
  fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-2)',
};

/* ── VendorEntry ─────────────────────────────────────────────────
   Sub-card inside an expanded CVE row, one per vendor that filed
   the CVE. Holds vendor name, severity, status, doc count, and
   inline action buttons. */
function VendorEntry({ vendor, severity, status, docCount, children, onView, onEdit, onDelete }) {
  return (
    <div style={{
      background: 'linear-gradient(135deg, rgba(15,23,42,0.95) 0%, rgba(30,41,59,0.9) 100%)',
      border: '1.5px solid rgba(14,165,233,0.30)', borderRadius: 6,
      padding: 16, marginBottom: 12,
      boxShadow: '0 4px 12px rgba(0,0,0,0.4), inset 0 1px 0 rgba(14,165,233,0.08)',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 8 }}>
            <h4 style={{ margin: 0, fontFamily: 'var(--font-display)', fontSize: 15, fontWeight: 600, color: 'var(--fg-1)' }}>{vendor}</h4>
            <SeverityBadge level={severity} />
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 16, fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-2)' }}>
            <span>Status: <strong style={{ color: 'var(--fg-1)', fontWeight: 500 }}>{status}</strong></span>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
              <HomeIcon name="doc" size={13} color="currentColor" />
              {docCount} doc{docCount !== 1 ? 's' : ''}
            </span>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 6, flexShrink: 0 }}>
          {onView && <HomeButton variant="neutral" icon="eye" size="sm" onClick={onView}>View</HomeButton>}
          {onEdit && <HomeButton variant="warning" icon="edit" size="sm" onClick={onEdit} />}
          {onDelete && <HomeButton variant="danger" icon="trash" size="sm" onClick={onDelete} />}
        </div>
      </div>
      {children && (
        <div style={{ marginTop: 16, paddingTop: 16, borderTop: '1px solid rgba(14,165,233,0.20)' }}>
          {children}
        </div>
      )}
    </div>
  );
}

/* ── HomeIcon ────────────────────────────────────────────────────
   Inline SVGs covering every icon used on the home page so the kit
   has no external icon-font dependency. Keys mirror lucide-react names. */
function HomeIcon({ name, size = 16, color = 'currentColor' }) {
  const p = {
    width: size, height: size, viewBox: '0 0 24 24', fill: 'none',
    stroke: color, strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round',
    style: { display: 'inline-block', verticalAlign: 'middle' },
  };
  switch (name) {
    case 'search':   return <svg {...p}><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>;
    case 'filter':   return <svg {...p}><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/></svg>;
    case 'alert':    return <svg {...p}><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>;
    case 'check':
    case 'success':  return <svg {...p}><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>;
    case 'warning':  return <svg {...p}><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>;
    case 'error':
    case 'x':        return <svg {...p}><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>;
    case 'shield':   return <svg {...p}><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>;
    case 'activity': return <svg {...p}><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>;
    case 'doc':      return <svg {...p}><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>;
    case 'eye':      return <svg {...p}><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg>;
    case 'edit':     return <svg {...p}><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>;
    case 'trash':    return <svg {...p}><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>;
    case 'plus':     return <svg {...p}><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>;
    case 'refresh':  return <svg {...p}><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/><path d="M3 21v-5h5"/></svg>;
    case 'chevron':  return <svg {...p}><polyline points="6 9 12 15 18 9"/></svg>;
    case 'upload':   return <svg {...p}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>;
    case 'download': return <svg {...p}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>;
    case 'calendar': return <svg {...p}><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>;
    default:         return <svg {...p}><circle cx="12" cy="12" r="10"/></svg>;
  }
}

/* ── CalendarMini ────────────────────────────────────────────────
   Minimal calendar surface for the right rail. Static — accepts a
   `today` index and an optional `markedDays` map for severity dots. */
function CalendarMini({ month = 'April 2026', today = 26, markedDays = {} }) {
  const dows = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
  // April 2026 starts on Wednesday — empty cells for S/M/T
  const startOffset = 3;
  const daysInMonth = 30;
  const cells = [...Array(startOffset).fill(null), ...Array.from({ length: daysInMonth }, (_, i) => i + 1)];
  return (
    <div>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        marginBottom: 12,
      }}>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-1)', fontWeight: 600 }}>{month}</span>
        <div style={{ display: 'flex', gap: 4 }}>
          <button style={navBtn}>‹</button>
          <button style={navBtn}>›</button>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 2 }}>
        {dows.map((d, i) => (
          <div key={`dow-${i}`} style={{
            fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-disabled)',
            textAlign: 'center', padding: '4px 0', fontWeight: 600,
          }}>{d}</div>
        ))}
        {cells.map((day, i) => {
          if (day === null) return <div key={`empty-${i}`} />;
          const mark = markedDays[day];
          const isToday = day === today;
          return (
            <button key={`day-${day}`} style={{
              position: 'relative',
              padding: '6px 0', borderRadius: 4,
              background: isToday ? withAlpha(H_COLORS.sky, 0.20) : 'transparent',
              border: isToday ? `1px solid ${H_COLORS.sky}` : '1px solid transparent',
              color: isToday ? H_COLORS.sky : 'var(--fg-1)',
              fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: isToday ? 700 : 500,
              cursor: 'pointer', transition: 'background 120ms ease',
            }}>
              {day}
              {mark && (
                <span style={{
                  position: 'absolute', bottom: 2, left: '50%', transform: 'translateX(-50%)',
                  width: 4, height: 4, borderRadius: '50%',
                  background: H_COLORS[mark] || H_COLORS.amber,
                }} />
              )}
            </button>
          );
        })}
      </div>
    </div>
  );
}

const navBtn = {
  background: 'transparent', border: '1px solid rgba(14,165,233,0.25)',
  color: H_COLORS.sky, borderRadius: 4, width: 22, height: 22,
  fontFamily: 'var(--font-mono)', fontSize: 12, cursor: 'pointer',
  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
};

/* ── ArchiveSummary ──────────────────────────────────────────────
   The bar of state pills that lives at the top of the Ivanti card.
   Each pill shows an Ivanti workflow state + count, color-coded. */
function ArchiveSummary({ items, activeFilter, onSelect }) {
  return (
    <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 12 }}>
      {items.map(it => {
        const c = H_COLORS[it.tone] || H_COLORS.teal;
        const active = activeFilter === it.label;
        return (
          <button
            key={it.label}
            onClick={() => onSelect && onSelect(active ? null : it.label)}
            style={{
              flex: '1 1 60px',
              padding: '8px 10px',
              background: active ? withAlpha(c, 0.20) : withAlpha(c, 0.08),
              border: `1px solid ${active ? c : withAlpha(c, 0.30)}`,
              borderRadius: 4,
              cursor: 'pointer',
              fontFamily: 'var(--font-mono)',
            }}
          >
            <div style={{
              fontSize: 16, fontWeight: 700, color: c,
              textShadow: active ? `0 0 8px ${withAlpha(c, 0.5)}` : 'none', lineHeight: 1,
            }}>{it.count}</div>
            <div style={{
              fontSize: 9, color: 'var(--fg-2)', textTransform: 'uppercase',
              letterSpacing: '0.06em', marginTop: 4, fontWeight: 600,
            }}>{it.label}</div>
          </button>
        );
      })}
    </div>
  );
}

/* ── ScrollList ──────────────────────────────────────────────────
   Generic max-height scroll wrapper for the right-rail panels. */
function ScrollList({ maxHeight = 300, children }) {
  return (
    <div style={{
      maxHeight, overflowY: 'auto',
      display: 'flex', flexDirection: 'column', gap: 8,
      paddingRight: 4,
    }}>
      {children}
    </div>
  );
}

/* ── EmptyState ──────────────────────────────────────────────────
   Center-aligned check-circle + caption, used inside ScrollList
   when a panel has no items. */
function EmptyState({ icon = 'check', tone = 'green', children }) {
  const c = H_COLORS[tone] || H_COLORS.green;
  return (
    <div style={{ textAlign: 'center', padding: '24px 0' }}>
      <div style={{ display: 'inline-flex', marginBottom: 8 }}>
        <HomeIcon name={icon} size={32} color={c} />
      </div>
      <p style={{
        margin: 0, fontFamily: 'var(--font-mono)', fontSize: 12,
        color: 'var(--fg-2)', fontStyle: 'italic',
      }}>{children}</p>
    </div>
  );
}

/* ── helpers ─────────────────────────────────────────────────── */
function withAlpha(hex, a) {
  const h = hex.replace('#', '');
  const r = parseInt(h.slice(0, 2), 16);
  const g = parseInt(h.slice(2, 4), 16);
  const b = parseInt(h.slice(4, 6), 16);
  return `rgba(${r}, ${g}, ${b}, ${a})`;
}

window.HOME = {
  COLORS: H_COLORS,
  StatCard, HomeCard, CardTitle, HomeButton, SeverityBadge, StatusBadge,
  HomeInput, HomeSelect, FieldLabel, ResultBanner,
  BigStat, MiniTicket, CVERow, VendorEntry,
  HomeIcon, CalendarMini, ArchiveSummary, ScrollList, EmptyState,
  withAlpha,
};
