// Civic Modern — Component library.
// Every component references window.tokens so brand changes flow through in one place.

// ─────────────────────────────────────────────────────────────
// BUTTONS
// ─────────────────────────────────────────────────────────────
function Button({ variant = 'primary', size = 'md', children, iconBefore, iconAfter, disabled, style, ...rest }) {
  const t = window.tokens;
  const pad = size === 'sm' ? '6px 12px' : size === 'lg' ? '12px 22px' : '9px 16px';
  const fs  = size === 'sm' ? 13 : size === 'lg' ? 15 : 14;

  const variants = {
    primary: { bg: t.color.action, fg: '#fff', border: 'transparent' },
    secondary: { bg: 'transparent', fg: t.color.text, border: t.color.strong },
    tertiary: { bg: 'transparent', fg: t.color.text, border: 'transparent' },
    ghost: { bg: 'transparent', fg: t.color.text, border: 'transparent' },
    link: { bg: 'transparent', fg: t.color.action, border: 'transparent' },
    destructive: { bg: t.color.err, fg: '#fff', border: 'transparent' },
    danger: { bg: t.color.err, fg: '#fff', border: 'transparent' },
  };
  const v = variants[variant] || variants.primary;

  return (
    <button
      disabled={disabled}
      className="cm-btn"
      data-variant={variant}
      style={{
        display: 'inline-flex',
        alignItems: 'center',
        gap: 6,
        background: v.bg,
        color: v.fg,
        border: `1px solid ${v.border}`,
        borderRadius: t.radius.sm,
        padding: variant === 'link' ? '4px 2px' : pad,
        fontSize: fs,
        fontFamily: t.font.sans,
        fontWeight: 500,
        letterSpacing: -0.1,
        cursor: disabled ? 'not-allowed' : 'pointer',
        opacity: disabled ? 0.5 : 1,
        whiteSpace: 'nowrap',
        '--cm-bg': v.bg,
        '--cm-fg': v.fg,
        '--cm-border': v.border,
        ...style,
      }}
      {...rest}
    >
      {iconBefore}
      {children}
      {iconAfter}
    </button>
  );
}

// ─────────────────────────────────────────────────────────────
// PILL / STATUS
// ─────────────────────────────────────────────────────────────
function Pill({ tone = 'neutral', variant = 'light', children, style }) {
  const t = window.tokens;
  const tones = {
    neutral: { light: { bg: t.color.surfaceHi, fg: t.color.body }, dark: { bg: t.color.text, fg: '#fff' } },
    action:  { light: { bg: t.color.actionSoft, fg: t.color.action }, dark: { bg: t.color.action, fg: '#fff' } },
    ok:      { light: { bg: t.color.okLight, fg: t.color.ok }, dark: { bg: t.color.ok, fg: '#fff' } },
    info:    { light: { bg: t.color.bpLight, fg: t.color.bp }, dark: { bg: t.color.bp, fg: '#fff' } },
    warn:    { light: { bg: t.color.warnLight, fg: t.color.warn }, dark: { bg: t.color.warn, fg: '#fff' } },
    err:     { light: { bg: t.color.errLight, fg: t.color.err }, dark: { bg: t.color.err, fg: '#fff' } },
  };
  const v = (tones[tone] || tones.neutral)[variant] || (tones[tone] || tones.neutral).light;
  return (
    <span style={{
      display: 'inline-flex',
      alignItems: 'center',
      gap: 6,
      padding: '4px 10px',
      background: v.bg,
      color: v.fg,
      fontSize: 12,
      fontWeight: 500,
      borderRadius: t.radius.pill,
      ...style,
    }}>
      {children}
    </span>
  );
}

// ─────────────────────────────────────────────────────────────
// INPUT / TEXTAREA / SELECT / CHECKBOX / RADIO / SWITCH
// ─────────────────────────────────────────────────────────────
function Field({ label, help, error, children, style }) {
  const t = window.tokens;
  return (
    <label style={{ display: 'block', ...style }}>
      {label && <div style={{ fontSize: 15, fontWeight: 500, color: t.color.text, marginBottom: 8, textTransform: 'capitalize' }}>{label}</div>}
      {help && <div style={{ fontSize: 12, color: t.color.muted, marginBottom: 8 }}>{help}</div>}
      {children}
      {error && (
        <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, color: t.color.err, marginTop: 6 }}>
          <FluentIcon name="error_circle" size={14} weight="filled" />
          {error}
        </div>
      )}
    </label>
  );
}

function Input({ invalid, style, ...rest }) {
  const t = window.tokens;
  return (
    <input
      className="cm-input"
      data-invalid={invalid ? 'true' : 'false'}
      style={{
        width: '100%',
        background: t.color.bg,
        border: invalid ? `2px solid ${t.color.err}` : `1px solid ${t.color.strong}`,
        borderRadius: t.radius.sm,
        padding: invalid ? '9px 13px' : '10px 14px',
        fontSize: 15,
        fontFamily: t.font.sans,
        color: t.color.text,
        outline: 'none',
        ...style,
      }}
      {...rest}
    />
  );
}

function Textarea({ style, rows = 4, ...rest }) {
  const t = window.tokens;
  return (
    <textarea
      rows={rows}
      className="cm-textarea"
      style={{
        width: '100%',
        background: t.color.bg,
        border: `1px solid ${t.color.strong}`,
        borderRadius: t.radius.sm,
        padding: '10px 14px',
        fontSize: 15,
        fontFamily: t.font.sans,
        color: t.color.text,
        outline: 'none',
        resize: 'vertical',
        lineHeight: 1.5,
        ...style,
      }}
      {...rest}
    />
  );
}

function Select({ children, style, ...rest }) {
  const t = window.tokens;
  return (
    <select
      className="cm-select"
      style={{
        width: '100%',
        background: t.color.bg,
        border: `1px solid ${t.color.strong}`,
        borderRadius: t.radius.sm,
        padding: '10px 14px',
        fontSize: 15,
        fontFamily: t.font.sans,
        color: t.color.text,
        outline: 'none',
        appearance: 'none',
        backgroundImage: `linear-gradient(45deg, transparent 50%, ${t.color.muted} 50%), linear-gradient(135deg, ${t.color.muted} 50%, transparent 50%)`,
        backgroundPosition: `calc(100% - 16px) 50%, calc(100% - 11px) 50%`,
        backgroundSize: '5px 5px, 5px 5px',
        backgroundRepeat: 'no-repeat',
        paddingRight: 34,
        ...style,
      }}
      {...rest}
    >
      {children}
    </select>
  );
}

function Checkbox({ checked, label, onChange, size = 'md', disabled = false }) {
  const t = window.tokens;
  const sm = size === 'sm';
  const box = sm ? 16 : 20;
  const tick = sm ? 10 : 12;
  const fontSize = sm ? 14 : 15;
  const gap = sm ? 10 : 12;
  const stroke = sm ? 1.6 : 1.8;
  const borderColor = disabled ? t.color.hair : (checked ? t.color.action : t.color.strong);
  const fillColor = disabled
    ? (checked ? t.color.dim : t.color.surface)
    : (checked ? t.color.action : t.color.bg);
  return (
    <label className="cm-check-label" style={{ display: 'inline-flex', alignItems: 'center', gap, cursor: disabled ? 'not-allowed' : 'pointer', fontSize, color: disabled ? t.color.muted : t.color.text, opacity: disabled ? 0.6 : 1 }}>
      <span className="cm-check-box" data-checked={checked ? 'true' : 'false'} data-disabled={disabled ? 'true' : 'false'} style={{
        width: box, height: box,
        borderRadius: sm ? 3 : 4,
        border: `1.5px solid ${borderColor}`,
        background: fillColor,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        transition: 'all 120ms ease',
        flexShrink: 0,
      }}>
        {checked && (
          <svg width={tick} height={tick} viewBox="0 0 10 10" fill="none">
            <path d="M2 5.2 L4.2 7.4 L8 3" stroke="#fff" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        )}
      </span>
      <input className="cm-check-native" type="checkbox" checked={checked} onChange={onChange} disabled={disabled} style={{ position: 'absolute', opacity: 0, pointerEvents: 'none', width: 1, height: 1 }} />
      {label}
    </label>
  );
}

function Radio({ checked, label, onChange, size = 'md', disabled = false }) {
  const t = window.tokens;
  const sm = size === 'sm';
  const box = sm ? 16 : 20;
  const dot = sm ? 8 : 10;
  const fontSize = sm ? 14 : 15;
  const gap = sm ? 10 : 12;
  const borderColor = disabled ? t.color.hair : (checked ? t.color.action : t.color.strong);
  const dotColor = disabled ? t.color.dim : t.color.action;
  return (
    <label className="cm-check-label" style={{ display: 'inline-flex', alignItems: 'center', gap, cursor: disabled ? 'not-allowed' : 'pointer', fontSize, color: disabled ? t.color.muted : t.color.text, opacity: disabled ? 0.6 : 1 }}>
      <span className="cm-radio-box" data-checked={checked ? 'true' : 'false'} data-disabled={disabled ? 'true' : 'false'} style={{
        width: box, height: box, borderRadius: box / 2,
        border: `1.5px solid ${borderColor}`,
        background: disabled ? t.color.surface : t.color.bg,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        transition: 'border-color 120ms ease',
        flexShrink: 0,
      }}>
        {checked && <span style={{ width: dot, height: dot, borderRadius: dot / 2, background: dotColor }} />}
      </span>
      <input className="cm-check-native" type="radio" checked={checked} onChange={onChange} disabled={disabled} style={{ position: 'absolute', opacity: 0, pointerEvents: 'none', width: 1, height: 1 }} />
      {label}
    </label>
  );
}

function Switch({ checked, onChange, label }) {
  const t = window.tokens;
  return (
    <label className="cm-check-label" style={{ display: 'inline-flex', alignItems: 'center', gap: 10, cursor: 'pointer', fontSize: 14, color: t.color.text }}>
      <span className="cm-switch-track" data-checked={checked ? 'true' : 'false'} style={{
        width: 32, height: 18, borderRadius: 999,
        background: checked ? t.color.action : t.color.strong,
        position: 'relative',
        transition: 'background 120ms',
      }}>
        <span style={{
          position: 'absolute',
          top: 2, left: checked ? 16 : 2,
          width: 14, height: 14, borderRadius: 7, background: '#fff',
          boxShadow: '0 1px 2px rgba(0,0,0,0.15)',
          transition: 'left 140ms',
        }} />
      </span>
      <input className="cm-check-native" type="checkbox" checked={checked} onChange={onChange} style={{ position: 'absolute', opacity: 0, pointerEvents: 'none', width: 1, height: 1 }} />
      {label}
    </label>
  );
}

// ─────────────────────────────────────────────────────────────
// CARD / SURFACE
// ─────────────────────────────────────────────────────────────
function Card({ children, variant = 'default', pad = 20, style }) {
  const t = window.tokens;
  const variants = {
    default: { bg: t.color.bg, border: t.color.hair, shadow: 'none' },
    raised:  { bg: t.color.bg, border: t.color.strong, shadow: t.shadow.card },
    soft:    { bg: t.color.paper, border: t.color.hair, shadow: 'none' },
  };
  const v = variants[variant] || variants.default;
  return (
    <div style={{
      background: v.bg,
      border: `1px solid ${v.border}`,
      borderRadius: t.radius.lg,
      padding: pad,
      boxShadow: v.shadow,
      ...style,
    }}>
      {children}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// ALERT / CALLOUT
// ─────────────────────────────────────────────────────────────
function Alert({ tone = 'info', title, children, action, style }) {
  const t = window.tokens;
  const tones = {
    info:   { bg: t.color.bpLight,      fg: t.color.bp,     edge: '#D6E3F1',           icon: 'info' },
    action: { bg: t.color.actionSoft,   fg: t.color.action, edge: t.color.actionEdge,  icon: 'megaphone' },
    ok:     { bg: t.color.okLight,      fg: t.color.ok,     edge: '#CCE8D6',           icon: 'checkmark_circle' },
    warn:   { bg: t.color.warnLight,    fg: t.color.warn,   edge: '#ECDDB0',           icon: 'warning' },
    err:    { bg: t.color.errLight,     fg: t.color.err,    edge: '#F2C8C4',           icon: 'error_circle' },
  };
  const v = tones[tone];
  return (
    <div style={{
      background: v.bg,
      border: `1px solid ${v.edge}`,
      borderRadius: t.radius.lg,
      padding: '16px 18px',
      display: 'flex',
      alignItems: 'flex-start',
      gap: 12,
      ...style,
    }}>
      <div style={{ flexShrink: 0, color: v.fg, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', marginTop: 0 }}>
        <FluentIcon name={v.icon} size={24} weight="filled" />
      </div>
      <div style={{ flex: 1 }}>
        {title && <div style={{ fontSize: 14, fontWeight: 500, color: t.color.text, marginBottom: 3 }}>{title}</div>}
        <div style={{ fontSize: 13, color: t.color.body, lineHeight: 1.5 }}>{children}</div>
      </div>
      {action}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// TABS
// ─────────────────────────────────────────────────────────────
function Tabs({ items, active = 0, onChange }) {
  const t = window.tokens;
  return (
    <div style={{ display: 'flex', gap: 0, borderBottom: `1px solid ${t.color.hair}` }}>
      {items.map((it, i) => {
        const isActive = i === active;
        return (
          <button
            key={it}
            onClick={() => onChange && onChange(i)}
            className="cm-tab"
            data-active={isActive ? 'true' : 'false'}
            style={{
              padding: '12px 18px',
              background: 'transparent',
              border: 'none',
              borderBottom: `2px solid ${isActive ? t.color.action : 'transparent'}`,
              marginBottom: -1,
              fontSize: 14,
              fontWeight: 500,
              fontFamily: t.font.sans,
              color: isActive ? t.color.text : t.color.muted,
              textTransform: 'capitalize',
              cursor: 'pointer',
            }}
          >
            {it}
          </button>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// BREADCRUMBS
// ─────────────────────────────────────────────────────────────
function Breadcrumbs({ items }) {
  const t = window.tokens;
  return (
    <nav style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: t.color.muted }}>
      {items.map((it, i) => {
        const isLast = i === items.length - 1;
        return (
          <React.Fragment key={i}>
            {i > 0 && <span style={{ color: t.color.dim, fontFamily: t.font.mono, fontSize: 11 }}>&gt;</span>}
            {isLast ? (
              <span aria-current="page" style={{ color: t.color.text, fontWeight: 500 }}>{it}</span>
            ) : (
              <a href="#" className="cm-breadcrumb">{it}</a>
            )}
          </React.Fragment>
        );
      })}
    </nav>
  );
}

// ─────────────────────────────────────────────────────────────
// AVATAR
// ─────────────────────────────────────────────────────────────
function Avatar({ initials = 'RC', size = 28, src, alt }) {
  const t = window.tokens;
  const common = {
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
    width: size, height: size, borderRadius: size / 2,
    overflow: 'hidden',
    border: `1px solid ${t.color.hair}`,
    verticalAlign: 'middle',
  };
  if (src) {
    return (
      <span style={{ ...common, background: t.color.surfaceHi }}>
        <img src={src} alt={alt || initials} style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
      </span>
    );
  }
  return (
    <span style={{
      ...common,
      background: t.color.surfaceHi, color: t.color.text,
      fontSize: Math.max(10, size * 0.4), fontWeight: 500,
      fontFamily: t.font.sans,
    }}>
      {initials}
    </span>
  );
}

// ─────────────────────────────────────────────────────────────
// PROGRESS + STEPPER
// ─────────────────────────────────────────────────────────────
function Progress({ value = 40, label }) {
  const t = window.tokens;
  return (
    <div>
      {label && (
        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, color: t.color.muted, marginBottom: 6 }}>
          <span>{label}</span>
          <span style={{ fontFamily: t.font.mono }}>{value}%</span>
        </div>
      )}
      <div style={{ height: 4, background: t.color.surfaceHi, borderRadius: 2, overflow: 'hidden' }}>
        <div style={{ width: `${value}%`, height: '100%', background: t.color.action }} />
      </div>
    </div>
  );
}

function Stepper({ steps, current = 0 }) {
  const t = window.tokens;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 0 }}>
      {steps.map((s, i) => {
        const done = i < current;
        const active = i === current;
        return (
          <React.Fragment key={s}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexShrink: 0 }}>
              <span style={{
                width: 22, height: 22, borderRadius: 11,
                background: done ? t.color.action : active ? t.color.bg : t.color.bg,
                border: `1.5px solid ${done || active ? t.color.action : t.color.strong}`,
                color: done ? '#fff' : active ? t.color.action : t.color.muted,
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 11, fontWeight: 500, fontFamily: t.font.mono,
              }}>
                {done ? '✓' : i + 1}
              </span>
              <span style={{ fontSize: 13, fontWeight: active ? 500 : 400, color: active ? t.color.text : done ? t.color.body : t.color.muted }}>{s}</span>
            </div>
            {i < steps.length - 1 && <div style={{ flex: 1, height: 1, background: t.color.hair, margin: '0 16px', minWidth: 24 }} />}
          </React.Fragment>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// TABLE
// ─────────────────────────────────────────────────────────────
function DataTable({ columns, rows }) {
  const t = window.tokens;
  return (
    <div style={{ border: `1px solid ${t.color.hair}`, borderRadius: 4, overflow: 'hidden' }}>
      <div style={{
        display: 'grid',
        gridTemplateColumns: columns.map(c => c.width || '1fr').join(' '),
        padding: '12px 18px',
        background: t.color.paper,
        borderBottom: `1px solid ${t.color.hair}`,
      }}>
        {columns.map((c, i) => (
          <div key={i} style={{ fontSize: 11, fontWeight: 500, textTransform: 'uppercase', letterSpacing: 1.2, color: t.color.muted, fontFamily: t.font.mono }}>
            {c.label}
          </div>
        ))}
      </div>
      {rows.map((r, i) => (
        <div key={i} style={{
          display: 'grid',
          gridTemplateColumns: columns.map(c => c.width || '1fr').join(' '),
          padding: '14px 18px',
          borderBottom: i < rows.length - 1 ? `1px solid ${t.color.hair}` : 'none',
          alignItems: 'center',
          fontSize: 14,
          color: t.color.text,
        }}>
          {columns.map((c, j) => (
            <div key={j} style={{ color: j === 0 ? t.color.text : t.color.body, fontWeight: j === 0 ? 500 : 400 }}>
              {r[c.key]}
            </div>
          ))}
        </div>
      ))}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// COMPOSER (signature component)
// ─────────────────────────────────────────────────────────────
function Composer({
  placeholder = "Ask about a permit, license, payment, or record…",
  value,
  variant = 'full',
  buttonLabel,
  defaultValue,
}) {
  const t = window.tokens;
  const compact = variant === 'compact';
  const [focused, setFocused] = React.useState(false);
  const [text, setText] = React.useState(defaultValue ?? value ?? '');

  // When parent passes `value`, treat as controlled and sync on change.
  React.useEffect(() => {
    if (value !== undefined) setText(value);
  }, [value]);

  const borderColor = focused ? t.color.action : t.color.strong;
  const borderWidth = focused ? 2 : 1;
  const label = buttonLabel || (compact ? 'Send' : 'Get Started');

  if (compact) {
    return (
      <div style={{
        display: 'flex',
        alignItems: 'center',
        gap: 10,
        background: t.color.bg,
        border: `${borderWidth}px solid ${borderColor}`,
        borderRadius: t.radius.xl,
        padding: focused ? '7px 7px 7px 17px' : '8px 8px 8px 18px',
        transition: 'border-color 120ms ease, border-width 0s',
      }}>
        <input
          type="text"
          value={text}
          placeholder={placeholder}
          onChange={(e) => setText(e.target.value)}
          onFocus={() => setFocused(true)}
          onBlur={() => setFocused(false)}
          style={{
            flex: 1,
            minWidth: 0,
            background: 'transparent',
            border: 'none',
            outline: 'none',
            fontFamily: t.font.sans,
            fontSize: 15,
            lineHeight: 1.5,
            color: t.color.text,
            padding: '6px 0',
          }}
        />
        <Button variant="primary">{label}</Button>
      </div>
    );
  }

  return (
    <div style={{
      background: t.color.bg,
      border: `${borderWidth}px solid ${borderColor}`,
      borderRadius: t.radius.xl,
      padding: focused ? 17 : 18,
      transition: 'border-color 120ms ease, border-width 0s',
    }}>
      <textarea
        value={text}
        placeholder={placeholder}
        onChange={(e) => setText(e.target.value)}
        onFocus={() => setFocused(true)}
        onBlur={() => setFocused(false)}
        rows={2}
        style={{
          display: 'block',
          width: '100%',
          minHeight: 56,
          background: 'transparent',
          border: 'none',
          outline: 'none',
          resize: 'vertical',
          fontFamily: t.font.sans,
          fontSize: 17,
          lineHeight: 1.55,
          color: t.color.text,
          padding: 0,
        }}
      />
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 16, paddingTop: 16, borderTop: `1px solid ${t.color.hair}` }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16, fontSize: 13, color: t.color.muted }}>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
            <IconSlot label="attach" size={14} />
            Attach a document
          </span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
            <IconSlot label="mic" size={14} />
            Use voice
          </span>
        </div>
        <Button variant="primary">{label}</Button>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// SERVICE CARD
// ─────────────────────────────────────────────────────────────
function ServiceCard({ title, desc, cta = 'Start' }) {
  const t = window.tokens;
  return (
    <a className="cm-service-card" tabIndex={0} style={{
      display: 'block',
      padding: '20px 22px',
      border: `1px solid ${t.color.hair}`,
      borderRadius: t.radius.lg,
      background: t.color.bg,
      textDecoration: 'none',
      color: 'inherit',
      cursor: 'pointer',
    }}>
      <div style={{ fontSize: 15, color: t.color.text, fontWeight: 500, marginBottom: 6 }}>{title}</div>
      <div style={{ fontSize: 13, color: t.color.muted, lineHeight: 1.45, marginBottom: 14 }}>{desc}</div>
      <span style={{ fontSize: 13, color: t.color.action, display: 'inline-flex', gap: 4 }}>{cta} <span>→</span></span>
    </a>
  );
}

// ─────────────────────────────────────────────────────────────
// EMPTY STATE
// ─────────────────────────────────────────────────────────────
function EmptyState({ title, desc, action }) {
  const t = window.tokens;
  return (
    <div style={{
      padding: '40px 24px',
      textAlign: 'center',
      border: `1px dashed ${t.color.strong}`,
      borderRadius: t.radius.lg,
      background: t.color.paper,
    }}>
      <div style={{ width: 44, height: 44, borderRadius: 22, background: t.color.surfaceHi, margin: '0 auto 14px' }} />
      <div style={{ fontSize: 15, fontWeight: 500, color: t.color.text, marginBottom: 4 }}>{title}</div>
      <div style={{ fontSize: 13, color: t.color.muted, marginBottom: 16, maxWidth: 320, margin: '0 auto 16px' }}>{desc}</div>
      {action}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// FLUENT ICON
// Loads a Fluent UI System Icon SVG from unpkg at runtime.
// Icons are MIT-licensed by Microsoft (github.com/microsoft/fluentui-system-icons).
//
//   <FluentIcon name="home" />                  // 20, regular, currentColor
//   <FluentIcon name="calendar" size={24} />
//   <FluentIcon name="checkmark" weight="filled" />
//   <FluentIcon name="alert" size={16} color="#D63600" />
//
// Available sizes: 12, 16, 20, 24, 28, 32, 48. Available weights: 'regular' | 'filled'.
// Not every icon exists at every size — unpkg will 404 if missing. Fall back to 24.
// ─────────────────────────────────────────────────────────────
const FLUENT_ICON_VERSION = '1.1.275';
const __fluentIconCache = (window.__fluentIconBundle && typeof window.__fluentIconBundle === 'object')
  ? { ...window.__fluentIconBundle }
  : {};

function FluentIcon({ name, size = 20, weight = 'regular', color, style, title }) {
  const [svg, setSvg] = React.useState(null);
  const [failed, setFailed] = React.useState(false);

  // Resolve to nearest available native size. On ties, prefer the larger size
  // (so 14 → 16 rather than 12) — downscaling reads better than upscaling.
  const nativeSizes = [12, 16, 20, 24, 28, 32, 48];
  const nativeSize = nativeSizes.includes(size)
    ? size
    : nativeSizes.reduce((best, s) => {
        const dS = Math.abs(s - size);
        const dB = Math.abs(best - size);
        if (dS < dB) return s;
        if (dS === dB && s > best) return s;
        return best;
      }, 24);

  const key = `${name}_${nativeSize}_${weight}`;
  const url = `https://unpkg.com/@fluentui/svg-icons@${FLUENT_ICON_VERSION}/icons/${key}.svg`;

  React.useEffect(() => {
    let cancelled = false;
    if (__fluentIconCache[key]) {
      setSvg(__fluentIconCache[key]);
      setFailed(false);
      return;
    }
    setSvg(null);
    setFailed(false);
    fetch(url)
      .then((r) => r.ok ? r.text() : Promise.reject(r.status))
      .then((text) => {
        // Reject anything that isn't an SVG (e.g. an HTML auth page from a
        // network proxy). Without this guard the proxy's HTML lands inside
        // dangerouslySetInnerHTML and shows up as visible page text.
        if (!/^\s*<svg[\s>]/i.test(text)) {
          if (!cancelled) setFailed(true);
          return;
        }
        // Strip hard-coded fill so currentColor wins.
        const cleaned = text
          .replace(/<svg([^>]*)>/, (m, attrs) => {
            const noFill = attrs.replace(/\sfill="[^"]*"/gi, '');
            return `<svg${noFill} fill="currentColor">`;
          })
          .replace(/<path([^>]*)fill="[^"]*"/gi, '<path$1');
        __fluentIconCache[key] = cleaned;
        if (!cancelled) setSvg(cleaned);
      })
      .catch(() => { if (!cancelled) setFailed(true); });
    return () => { cancelled = true; };
  }, [key]);

  const wrap = {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    width: size,
    height: size,
    color: color || 'currentColor',
    flexShrink: 0,
    lineHeight: 0,
    ...style,
  };

  if (failed) {
    // Fall back to a hairline placeholder so the layout doesn't collapse.
    return (
      <span aria-label={title || name} title={title || name} style={{
        ...wrap,
        border: '1px dashed currentColor',
        borderRadius: 2,
        opacity: 0.35,
      }} />
    );
  }

  if (!svg) {
    return <span aria-hidden style={wrap} />;
  }

  // Scale the SVG to the requested display size.
  const scaled = svg.replace(/<svg([^>]*)>/, (m, attrs) => {
    const stripped = attrs
      .replace(/\swidth="[^"]*"/gi, '')
      .replace(/\sheight="[^"]*"/gi, '');
    return `<svg${stripped} width="${size}" height="${size}">`;
  });

  return (
    <span
      aria-label={title || name}
      role={title ? 'img' : undefined}
      title={title}
      style={wrap}
      dangerouslySetInnerHTML={{ __html: scaled }}
    />
  );
}

// ─────────────────────────────────────────────────────────────
// NAV ITEM
// A single navigation row with a leading Fluent icon and optional trailing badge.
// Works in sidebars, mobile drawers, account menus. Active items get a soft
// Action Orange background, bold label, and a filled icon.
//
//   <NavItem icon="home" label="Overview" />
//   <NavItem icon="document_text" label="Requests" active />
//   <NavItem icon="mail" label="Messages" badge={3} href="/messages" />
// ─────────────────────────────────────────────────────────────
function NavItem({
  icon,
  label,
  active = false,
  badge,
  href,
  onClick,
  size = 'md',
  iconWeight,
  style,
}) {
  const t = window.tokens;
  const padY = size === 'sm' ? 6 : 8;
  const padX = size === 'sm' ? 10 : 12;
  const iconSize = size === 'sm' ? 18 : 20;
  const fontSize = size === 'sm' ? 13 : 14;
  const weight = iconWeight || (active ? 'filled' : 'regular');

  const [hover, setHover] = React.useState(false);

  const inner = (
    <React.Fragment>
      <FluentIcon name={icon} size={iconSize} weight={weight} />
      <span style={{ flex: 1, textAlign: 'left' }}>{label}</span>
      {badge != null && (
        <span style={{
          display: 'inline-flex',
          alignItems: 'center',
          justifyContent: 'center',
          minWidth: 20,
          height: 20,
          padding: '0 6px',
          borderRadius: 10,
          background: active ? t.color.action : t.color.surfaceHi,
          color: active ? '#fff' : t.color.muted,
          fontFamily: t.font.mono,
          fontSize: 11,
          fontWeight: 500,
          letterSpacing: 0.2,
        }}>{badge}</span>
      )}
    </React.Fragment>
  );

  const baseStyle = {
    display: 'flex',
    alignItems: 'center',
    gap: 10,
    width: '100%',
    padding: `${padY}px ${padX}px`,
    borderRadius: t.radius.sm,
    background: active
      ? t.color.actionSoft
      : hover ? t.color.surfaceLo : 'transparent',
    color: active ? t.color.action : t.color.body,
    fontSize,
    fontFamily: t.font.sans,
    fontWeight: active ? 500 : 400,
    border: 'none',
    textDecoration: 'none',
    cursor: (href || onClick) ? 'pointer' : 'default',
    textAlign: 'left',
    transition: 'background 0.12s',
    ...style,
  };

  const handlers = {
    onMouseEnter: () => setHover(true),
    onMouseLeave: () => setHover(false),
  };

  if (href) {
    return (
      <a href={href} style={baseStyle} {...handlers}>{inner}</a>
    );
  }
  if (onClick) {
    return (
      <button type="button" onClick={onClick} style={baseStyle} {...handlers}>{inner}</button>
    );
  }
  return (
    <div style={baseStyle} {...handlers}>{inner}</div>
  );
}

// A simple grouping wrapper for NavItems — adds an optional eyebrow label.
function NavGroup({ label, children, style }) {
  const t = window.tokens;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 2, ...style }}>
      {label && (
        <div style={{
          padding: '6px 12px 4px',
          fontFamily: t.font.mono,
          fontSize: 10,
          letterSpacing: 1.4,
          textTransform: 'uppercase',
          color: t.color.dim,
          fontWeight: 500,
        }}>{label}</div>
      )}
      {children}
    </div>
  );
}

Object.assign(window, {
  Button, Pill, Field, Input, Textarea, Select, Checkbox, Radio, Switch,
  Card, Alert, Tabs, Breadcrumbs, Avatar, Progress, Stepper, DataTable,
  Composer, ServiceCard, EmptyState, FluentIcon, NavItem, NavGroup,
});
