// Saddle Alert — shared components
const { useState, useEffect, useRef, useMemo } = React;

// ---------- Icons (minimal, original line icons) ----------
const Icon = ({ name, size = 18, stroke = 1.7 }) => {
  const s = size;
  const common = {
    width: s, height: s, viewBox: '0 0 24 24',
    fill: 'none', stroke: 'currentColor', strokeWidth: stroke,
    strokeLinecap: 'round', strokeLinejoin: 'round',
  };
  switch (name) {
    case 'feed':
      return <svg {...common}><path d="M4 6h16M4 12h16M4 18h10" /></svg>;
    case 'bell':
      return <svg {...common}><path d="M6 8a6 6 0 0 1 12 0c0 7 3 7 3 9H3c0-2 3-2 3-9Z" /><path d="M10 21a2 2 0 0 0 4 0" /></svg>;
    case 'plus':
      return <svg {...common}><path d="M12 5v14M5 12h14" /></svg>;
    case 'settings':
      return <svg {...common}><circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1Z" /></svg>;
    case 'search':
      return <svg {...common}><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>;
    case 'check':
      return <svg {...common}><path d="m5 12 5 5 9-11" /></svg>;
    case 'x':
      return <svg {...common}><path d="M6 6l12 12M18 6 6 18" /></svg>;
    case 'chevron-right':
      return <svg {...common}><path d="m9 6 6 6-6 6" /></svg>;
    case 'chevron-left':
      return <svg {...common}><path d="m15 6-6 6 6 6" /></svg>;
    case 'chevron-down':
      return <svg {...common}><path d="m6 9 6 6 6-6" /></svg>;
    case 'dot':
      return <svg {...common}><circle cx="12" cy="12" r="3" fill="currentColor" /></svg>;
    case 'external':
      return <svg {...common}><path d="M14 4h6v6" /><path d="M20 4 10 14" /><path d="M19 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h5" /></svg>;
    case 'trash':
      return <svg {...common}><path d="M4 7h16" /><path d="M10 11v6M14 11v6" /><path d="M6 7v13a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V7" /><path d="M9 7V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v3" /></svg>;
    case 'edit':
      return <svg {...common}><path d="M12 20h9" /><path d="M16.5 3.5a2.1 2.1 0 1 1 3 3L7 19l-4 1 1-4Z" /></svg>;
    case 'filter':
      return <svg {...common}><path d="M3 5h18M6 12h12M10 19h4" /></svg>;
    case 'sort':
      return <svg {...common}><path d="M7 4v16M3 8l4-4 4 4" /><path d="M17 20V4M21 16l-4 4-4-4" /></svg>;
    case 'refresh':
      return <svg {...common}><path d="M21 12a9 9 0 1 1-2.64-6.36" /><path d="M21 3v6h-6" /></svg>;
    case 'more-horizontal':
      return <svg {...common}><circle cx="5" cy="12" r="1" fill="currentColor" /><circle cx="12" cy="12" r="1" fill="currentColor" /><circle cx="19" cy="12" r="1" fill="currentColor" /></svg>;
    case 'spinner':
      return <svg {...common}><circle cx="12" cy="12" r="8" opacity="0.25" /><path d="M20 12a8 8 0 0 0-8-8" /></svg>;
    default: return null;
  }
};

// ---------- Logo ----------
// Saddle Alert mark — handle-less bag with strap-loop tab and a slanted
// tassel charm. Clay (#C8541F) deliberately shifted off Hermès Pantone 1448C.
const SaddleMark = ({ size = 28 }) => {
  const CLAY = 'var(--clay, #C8541F)';
  const CREAM = 'var(--cream, #FFFCF6)';
  return (
    <svg width={size} height={size} viewBox="0 0 68 68" aria-label="Saddle Alert">
      {/* bag body: raised corners, top edge dips between them */}
      <path d="M11.5 16 C 13 14 16 13.5 18 15.5 C 22 20 26 22 34 22 C 42 22 46 20 50 15.5 C 52 13.5 55 14 56.5 16 L 58 58 C 58.2 62 56 64 53 64 L 15 64 C 12 64 9.8 62 10 58 Z"
            fill={CLAY} />
      {/* stitch line tracing the dip */}
      <path d="M14 18 C 20 22.5 26 24 34 24 C 42 24 48 22.5 54 18"
            fill="none" stroke={CREAM} strokeWidth="0.9" opacity="0.5"
            strokeDasharray="1.4 2.2" />
      {/* leather strap-loop tab at top-right corner */}
      <path d="M49 17 L 49 10 C 49 6.5 57 6.5 57 10 L 57 17"
            fill="none" stroke={CLAY} strokeWidth="1.6" strokeLinecap="round" />
      {/* split-ring through the tab */}
      <circle cx="53" cy="18.6" r="2.2" fill={CREAM} stroke={CLAY} strokeWidth="1.3" />
      {/* drop link */}
      <path d="M53 20.8 L 52 24" stroke={CLAY} strokeWidth="1.3" strokeLinecap="round" />
      {/* tassel charm — cream silhouette, clay accents inside the silhouette */}
      <g transform="translate(52 28) rotate(22)" fill={CREAM} stroke={CLAY}
         strokeWidth="1.2" strokeLinejoin="round" strokeLinecap="round">
        {/* leather cap (bell-shape) */}
        <path d="M -3.4 -1.4 C -3.4 -3.6 3.4 -3.6 3.4 -1.4 L 3.8 3.4 L -3.8 3.4 Z" />
        {/* binding band */}
        <rect x="-4.0" y="3.4" width="8.0" height="1.8" rx="0.4" />
        {/* strand skirt — single cream silhouette */}
        <path d="M -3.8 5.2 L 3.8 5.2 L 4.6 13.6 C 4.6 14.2 4.2 14.4 3.6 14.4 L -3.6 14.4 C -4.2 14.4 -4.6 14.2 -4.6 13.6 Z" />
        {/* strand divisions — clay inside the cream */}
        <g fill="none" stroke={CLAY} strokeWidth="0.7">
          <path d="M -2.6 5.5 L -2.9 13.8" />
          <path d="M -1.3 5.5 L -1.4 13.9" />
          <path d="M 0 5.5 L 0 14.0" />
          <path d="M 1.3 5.5 L 1.4 13.9" />
          <path d="M 2.6 5.5 L 2.9 13.8" />
        </g>
        {/* cap top crease */}
        <path d="M -1.6 -2.4 L 1.6 -2.4" stroke={CLAY} strokeWidth="0.9" fill="none" />
      </g>
    </svg>
  );
};

const Logo = ({ size = 18 }) => {
  // Pixel sizes lifted from the design: hero @72 pairs with 44px serif "Saddle"
  // and 10.5px tracked "TRACKER". Scale proportionally with the size prop.
  const markSize = Math.round(size * 1.9);
  const nameSize = Math.round(size * 2.2);
  const subSize = Math.max(8.5, size * 0.55);
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
      <SaddleMark size={markSize} />
      <div style={{ display: 'flex', flexDirection: 'column', lineHeight: 1 }}>
        <span style={{
          fontFamily: 'var(--font-serif)',
          fontStyle: 'italic',
          fontSize: nameSize,
          letterSpacing: '-0.01em',
          color: 'var(--ink)',
          whiteSpace: 'nowrap',
        }}>
          Saddle
        </span>
        <span style={{
          fontSize: subSize,
          letterSpacing: '0.28em',
          color: 'var(--ink-3)',
          textTransform: 'uppercase',
          marginTop: Math.max(3, size * 0.25),
        }}>
          Tracker
        </span>
      </div>
    </div>
  );
};

// ---------- Buttons ----------
const Btn = ({ kind = 'primary', size = 'md', icon, iconRight, children, onClick, disabled, loading, style, type, full }) => {
  const sizes = {
    sm: { padding: '6px 12px', fontSize: 13, h: 30, gap: 6 },
    md: { padding: '9px 16px', fontSize: 14, h: 38, gap: 8 },
    lg: { padding: '12px 20px', fontSize: 15, h: 46, gap: 8 },
  };
  const s = sizes[size];
  const kinds = {
    primary: { bg: 'var(--ink)', color: 'var(--bg)', border: 'transparent' },
    accent: { bg: 'var(--orange)', color: '#fff', border: 'transparent' },
    secondary: { bg: 'var(--bg-elev)', color: 'var(--ink)', border: 'var(--line-2)' },
    ghost: { bg: 'transparent', color: 'var(--ink)', border: 'transparent' },
    danger: { bg: 'transparent', color: 'var(--red)', border: 'var(--line-2)' },
  };
  const k = kinds[kind];
  return (
    <button
      type={type || 'button'}
      onClick={onClick}
      disabled={disabled || loading}
      style={{
        display: 'inline-flex',
        alignItems: 'center',
        justifyContent: 'center',
        gap: s.gap,
        padding: s.padding,
        height: s.h,
        fontSize: s.fontSize,
        fontWeight: 500,
        background: k.bg,
        color: k.color,
        border: `1px solid ${k.border}`,
        borderRadius: 8,
        opacity: (disabled || loading) ? 0.45 : 1,
        cursor: (disabled || loading) ? 'not-allowed' : 'pointer',
        transition: 'transform 0.06s ease, background 0.15s ease, opacity 0.15s ease',
        whiteSpace: 'nowrap',
        width: full ? '100%' : 'auto',
        ...style,
      }}
      onMouseDown={(e) => !disabled && (e.currentTarget.style.transform = 'translateY(1px)')}
      onMouseUp={(e) => (e.currentTarget.style.transform = '')}
      onMouseLeave={(e) => (e.currentTarget.style.transform = '')}
    >
      {(icon || loading) && (
        <span style={{ display: 'inline-flex', animation: loading ? 'obt-spin 0.9s linear infinite' : 'none' }}>
          <Icon name={loading ? 'spinner' : icon} size={s.fontSize + 2} />
        </span>
      )}
      {children}
      {iconRight && <Icon name={iconRight} size={s.fontSize + 2} />}
    </button>
  );
};

// ---------- Tag / Chip ----------
const Chip = ({ children, active, accent, onClick, color, removable, onRemove, size = 'md', style, title }) => {
  const sz = size === 'sm'
    ? { padding: '3px 9px', fontSize: 12, h: 22 }
    : { padding: '5px 12px', fontSize: 13, h: 28 };
  return (
    <span
      onClick={onClick}
      title={title}
      style={{
        display: 'inline-flex',
        alignItems: 'center',
        gap: 6,
        padding: sz.padding,
        height: sz.h,
        fontSize: sz.fontSize,
        fontWeight: 500,
        background: active ? (accent ? 'var(--orange-soft)' : 'var(--ink)') : 'var(--bg-elev)',
        color: active ? (accent ? 'var(--orange-2)' : 'var(--bg)') : 'var(--ink-2)',
        border: `1px solid ${active ? (accent ? 'var(--orange)' : 'var(--ink)') : 'var(--line-2)'}`,
        borderRadius: 999,
        cursor: onClick ? 'pointer' : 'default',
        transition: 'all 0.12s ease',
        userSelect: 'none',
        ...style,
      }}
    >
      {color && (
        <span style={{
          width: 10, height: 10, borderRadius: '50%',
          background: color, boxShadow: 'inset 0 0 0 1px rgba(0,0,0,0.15)',
          flexShrink: 0,
        }} />
      )}
      {children}
      {removable && (
        <span onClick={(e) => { e.stopPropagation(); onRemove && onRemove(); }} style={{ display: 'inline-flex', opacity: 0.6, marginLeft: 2 }}>
          <Icon name="x" size={12} />
        </span>
      )}
    </span>
  );
};

// ---------- Region flags ----------
const RegionFlags = ({ code, size = 14 }) => {
  const flagCodes = [code === 'UK' ? 'gb' : String(code || '').toLowerCase()];
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 3, flexShrink: 0 }}>
      {flagCodes.filter(Boolean).map(flagCode => (
        <img
          key={flagCode}
          src={`https://flagcdn.com/w40/${flagCode}.png`}
          alt=""
          aria-hidden="true"
          style={{
            display: 'block',
            width: size,
            height: Math.round(size * 0.68),
            objectFit: 'cover',
            borderRadius: 1,
            boxShadow: '0 0 0 1px rgba(26, 23, 20, 0.12)',
          }}
        />
      ))}
    </span>
  );
};

// ---------- Region badge ----------
const RegionBadge = ({ code }) => {
  const r = window.DW_DATA.REGIONS.find(x => x.code === code);
  if (!r) return null;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '3px 8px',
      fontSize: 11.5,
      fontWeight: 500,
      letterSpacing: '0.04em',
      color: 'var(--ink-2)',
      background: 'var(--bg)',
      border: '1px solid var(--line-2)',
      borderRadius: 6,
      whiteSpace: 'nowrap',
    }} title={r.hint || r.name}>
      <RegionFlags code={code} size={13} />
      <span>{r.displayCode || code}</span>
    </span>
  );
};

// ---------- Status pill ----------
const StatusPill = ({ status }) => {
  const map = {
    live: { label: 'In stock', color: 'var(--green)', bg: '#E6F2EC', dot: true },
    sold: { label: 'Sold out', color: 'var(--ink-3)', bg: 'var(--bg)', dot: false },
    alert: { label: 'Matches alert', color: 'var(--orange-2)', bg: 'var(--orange-soft)', dot: false },
    priority: { label: 'Priority', color: '#fff', bg: 'var(--orange)', dot: false },
    verified: { label: 'Verified', color: 'var(--green)', bg: '#E6F2EC', dot: false },
    detailUnknown: { label: 'Detail unknown', color: 'var(--orange-2)', bg: 'var(--orange-soft)', dot: false },
    detailUnavailable: { label: 'Unavailable', color: 'var(--ink-3)', bg: 'var(--bg)', dot: false },
    detailFailed: { label: 'Detail failed', color: 'var(--red)', bg: '#FBEDEA', dot: false },
  };
  const m = map[status];
  if (!m) return null;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '3px 9px',
      fontSize: 11.5,
      fontWeight: 500,
      color: m.color,
      background: m.bg,
      borderRadius: 999,
      letterSpacing: '0.01em',
    }}>
      {m.dot && <span style={{
        width: 6, height: 6, borderRadius: '50%',
        background: m.color,
        boxShadow: `0 0 0 3px ${m.color}22`,
        animation: 'pulse 1.6s ease-in-out infinite',
      }} />}
      {m.label}
    </span>
  );
};

// ---------- Time ago ----------
function timeAgo(mins) {
  if (mins < 1) return 'just now';
  if (mins < 60) return `${Math.round(mins)} min ago`;
  const hrs = mins / 60;
  if (hrs < 24) return `${Math.round(hrs)} hr ago`;
  return `${Math.round(hrs / 24)} d ago`;
}

// ---------- Rarity badge ----------
const RarityBadge = ({ rarity, compact, score, basis }) => {
  if (!rarity || rarity === 'common') return null;
  const map = {
    rare: { label: 'Rare', char: '◆', color: '#7a3f1a', bg: 'var(--orange-soft)' },
    unicorn: { label: 'Unicorn', char: '★', color: '#fff', bg: 'var(--ink)' },
  };
  const m = map[rarity];
  if (!m) return null;
  const detail = basis
    ? `Based on captured history: this model/color appears in ${basis} listings for its category.`
    : 'Based on captured history for this model/color.';
  const title = score ? `${m.label} · rarity score ${score}/100. ${detail}` : `${m.label}. ${detail}`;
  return (
    <span title={title} aria-label={title} style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      padding: compact ? '2px 7px' : '3px 9px',
      fontSize: compact ? 10.5 : 11.5,
      fontWeight: 600,
      letterSpacing: '0.04em',
      color: m.color,
      background: m.bg,
      borderRadius: 4,
      textTransform: 'uppercase',
      fontFamily: 'var(--font-mono)',
    }}>
      <span style={{ fontSize: compact ? 9 : 10 }}>{m.char}</span>
      {m.label}
    </span>
  );
};

// ---------- Color swatch ----------
function normalizeColorName(value) {
  return String(value || '')
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .toLowerCase()
    .trim();
}

function findColorSwatch(name) {
  const key = normalizeColorName(name);
  if (!key) return null;
  const colors = window.DW_DATA.COLORS;
  return colors.find(c => normalizeColorName(c.name) === key) ||
    colors.find(c => key.includes(normalizeColorName(c.name))) ||
    colors.find(c => key.split(/[\/,]/).some(part => normalizeColorName(c.name) === part.trim())) ||
    null;
}

const ColorSwatch = ({ name, size = 14 }) => {
  const c = findColorSwatch(name);
  return (
    <span style={{
      display: 'inline-block',
      width: size, height: size,
      borderRadius: '50%',
      background: c ? c.swatch : '#ccc',
      boxShadow: 'inset 0 0 0 1px rgba(0,0,0,0.15)',
      verticalAlign: 'middle',
      flexShrink: 0,
    }} />
  );
};

const stockPriceSymbolFor = (currency) => (
  currency === 'USD' ? '$' : currency === 'GBP' ? '£' : '$'
);

const compactStockCurrencyPrefixFor = (currency) => {
  const code = String(currency || '').trim().toUpperCase();
  if (code === 'AUD') return 'A$';
  if (code === 'SGD') return 'S$';
  if (code === 'NZD') return 'NZ$';
  if (code === 'USD') return 'US$';
  if (code === 'GBP') return '£';
  return stockPriceSymbolFor(currency);
};

const formatStockMoney = (price, currency, fallback = 'Price unavailable') => {
  const hasPrice = typeof price === 'number' && Number.isFinite(price) && price > 0;
  return hasPrice
    ? `${compactStockCurrencyPrefixFor(currency)}${new Intl.NumberFormat('en-US').format(price)}`
    : fallback;
};

// ---------- Stock row (used in feed) ----------
const StockRow = ({ item, onClick }) => {
  const [thumbHover, setThumbHover] = useState(false);
  const [previewPos, setPreviewPos] = useState({ top: 0, left: 0 });
  const swatch = findColorSwatch(item.color);
  const isSold = item.status === 'sold';
  const displayName = item.title || `${item.model} ${item.size || ''}`.trim();
  return (
    <div
      onClick={onClick}
      style={{
        display: 'grid',
        gridTemplateColumns: '52px 1fr auto',
        gap: 14,
        alignItems: 'center',
        padding: '14px 16px',
        background: 'var(--bg-elev)',
        border: '1px solid var(--line)',
        borderRadius: 12,
        cursor: 'pointer',
        transition: 'border-color 0.15s ease, transform 0.06s ease',
        position: 'relative',
        overflow: 'visible',
      }}
      onMouseEnter={(e) => e.currentTarget.style.borderColor = 'var(--line-2)'}
      onMouseLeave={(e) => {
        e.currentTarget.style.borderColor = 'var(--line)';
      }}
    >
      {item.match && (
        <div style={{
          position: 'absolute', left: 0, top: 0, bottom: 0, width: 3,
          background: 'var(--orange)',
        }} />
      )}
      {/* Color swatch as the visual */}
      <div
        onMouseEnter={(e) => {
          const rect = e.currentTarget.getBoundingClientRect();
          setPreviewPos({
            top: Math.max(12, rect.top - 10),
            left: Math.min(window.innerWidth - 232, rect.right + 10),
          });
          setThumbHover(true);
        }}
        onMouseLeave={() => setThumbHover(false)}
        title={item.imageUrl ? 'Hover to preview' : ''}
        style={{
        width: 52, height: 52, borderRadius: 8,
        background: swatch ? swatch.swatch : '#ccc',
        boxShadow: 'inset 0 0 0 1px rgba(0,0,0,0.1)',
        position: 'relative',
        overflow: 'hidden',
        opacity: isSold ? 0.4 : 1,
      }}>
        {item.imageUrl ? (
          <img
            src={item.imageUrl}
            alt={displayName}
            loading="lazy"
            style={{ width: '100%', height: '100%', objectFit: 'contain', background: '#fff' }}
          />
        ) : null}
        {!item.imageUrl && (
          <div style={{
            position: 'absolute',
            top: 6, left: '50%', transform: 'translateX(-50%)',
            width: 22, height: 3,
            background: item.hw === 'Gold' ? '#c9a45a' : item.hw === 'Rose Gold' ? '#d99c8e' : '#cfd2d4',
            borderRadius: 1,
            boxShadow: '0 0 0 1px rgba(0,0,0,0.1)',
          }} />
        )}
        {thumbHover && item.imageUrl && (
          <div style={{
            position: 'fixed',
            left: previewPos.left,
            top: previewPos.top,
            width: 210,
            height: 210,
            background: 'var(--bg-elev)',
            border: '1px solid var(--line-2)',
            borderRadius: 10,
            boxShadow: 'var(--shadow-md)',
            zIndex: 999,
            padding: 8,
            pointerEvents: 'none',
          }}>
            <img
              src={item.imageUrl}
              alt={`${displayName} preview`}
              style={{ width: '100%', height: '100%', objectFit: 'contain', borderRadius: 8, background: '#fff' }}
            />
          </div>
        )}
      </div>

      <div style={{ minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginBottom: 4 }}>
          <span style={{ fontFamily: 'var(--font-serif)', fontSize: 19, color: 'var(--ink)' }}>
            {displayName}
          </span>
          <RarityBadge rarity={item.rarity} score={item.rarityScore} basis={item.rarityBasis} compact />
          {item.category && item.category !== 'bags' && (
            <span style={{
              padding: '2px 7px',
              borderRadius: 999,
              background: 'var(--bg)',
              border: '1px solid var(--line-2)',
              color: 'var(--ink-3)',
              fontFamily: 'var(--font-mono)',
              fontSize: 10,
              letterSpacing: '0.04em',
              textTransform: 'uppercase',
            }}>
              {item.category === 'slg' ? 'SLG' : 'Charm'}
            </span>
          )}
          {item.isNew && (
            <span style={{
              padding: '2px 7px',
              borderRadius: 999,
              background: '#E6F2EC',
              color: 'var(--green)',
              fontFamily: 'var(--font-mono)',
              fontSize: 10,
              letterSpacing: '0.04em',
              textTransform: 'uppercase',
            }}>New</span>
          )}
          {item.match && <StatusPill status="alert" />}
        </div>
        <div style={{
          fontSize: 13, color: 'var(--ink-2)',
          display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 6,
        }}>
          <span>{item.leather}</span>
          <span style={{ color: 'var(--line-2)' }}>·</span>
          <span>{item.color}</span>
          {item.hw && item.hw !== 'Hardware' && (
            <>
              <span style={{ color: 'var(--line-2)' }}>·</span>
              <span>{item.hw}</span>
            </>
          )}
        </div>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 6 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <RegionBadge code={item.region} />
          <StatusPill status={item.status} />
        </div>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
          <span className="num" style={{ fontFamily: 'var(--font-serif)', fontSize: 18, color: 'var(--ink)' }}>
            {formatStockMoney(item.price, item.currency)}
          </span>
          <span className="mono" style={{ fontSize: 11, color: 'var(--ink-3)' }}>
            {timeAgo(item.ago)}
          </span>
        </div>
      </div>
    </div>
  );
};

// ---------- Section header ----------
const SectionHead = ({ title, subtitle, action }) => (
  <div style={{
    display: 'flex',
    alignItems: 'flex-end',
    justifyContent: 'space-between',
    gap: 16,
    margin: '4px 0 18px',
  }}>
    <div>
      <h1 style={{
        fontFamily: 'var(--font-serif)',
        fontSize: 'clamp(28px, 4vw, 38px)',
        fontWeight: 400,
        lineHeight: 1,
        margin: 0,
        letterSpacing: '-0.015em',
      }}>{title}</h1>
      {subtitle && (
        <div style={{ marginTop: 8, fontSize: 14, color: 'var(--ink-3)' }}>{subtitle}</div>
      )}
    </div>
    {action}
  </div>
);

// ---------- Field ----------
const Field = ({ label, hint, children, error, required }) => (
  <label style={{ display: 'block' }}>
    {label && (
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
        marginBottom: 8,
      }}>
        <span style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink)' }}>
          {label}
          {required && <span style={{ color: 'var(--red)', marginLeft: 3 }} aria-label="required">*</span>}
        </span>
        {hint && <span style={{ fontSize: 12, color: 'var(--ink-3)' }}>{hint}</span>}
      </div>
    )}
    {children}
    {error && <div style={{ fontSize: 12, color: 'var(--red)', marginTop: 6 }}>{error}</div>}
  </label>
);

// ---------- Input ----------
const TextInput = ({ value, onChange, placeholder, type, prefix, suffix, icon }) => (
  <div style={{
    display: 'flex', alignItems: 'center', gap: 8,
    background: 'var(--bg-elev)',
    border: '1px solid var(--line-2)',
    borderRadius: 8,
    padding: '0 12px',
    height: 42,
    transition: 'border-color 0.15s ease',
  }}>
    {icon && <span style={{ color: 'var(--ink-3)', display: 'inline-flex' }}><Icon name={icon} size={16} /></span>}
    {prefix && <span style={{ color: 'var(--ink-3)', fontSize: 14 }}>{prefix}</span>}
    <input
      type={type || 'text'}
      value={value}
      onChange={e => onChange(e.target.value)}
      placeholder={placeholder}
      style={{
        flex: 1,
        border: 'none',
        background: 'transparent',
        outline: 'none',
        padding: 0,
        fontSize: 14,
      }}
    />
    {suffix && <span style={{ color: 'var(--ink-3)', fontSize: 13 }}>{suffix}</span>}
  </div>
);

// ---------- Toggle ----------
const Toggle = ({ value, onChange, disabled }) => (
  <button
    type="button"
    onClick={() => !disabled && onChange(!value)}
    disabled={disabled}
    aria-pressed={Boolean(value)}
    style={{
      width: 38, height: 22,
      borderRadius: 999,
      background: value ? 'var(--orange)' : 'var(--line-2)',
      border: 'none',
      position: 'relative',
      cursor: disabled ? 'not-allowed' : 'pointer',
      transition: 'background 0.18s ease',
      padding: 0,
      opacity: disabled ? 0.55 : 1,
    }}
  >
    <span style={{
      position: 'absolute',
      top: 2, left: value ? 18 : 2,
      width: 18, height: 18,
      borderRadius: '50%',
      background: '#fff',
      boxShadow: '0 1px 2px rgba(0,0,0,0.15)',
      transition: 'left 0.18s ease',
    }} />
  </button>
);

// Inject animations
if (typeof document !== 'undefined' && !document.getElementById('dw-keyframes')) {
  const s = document.createElement('style');
  s.id = 'dw-keyframes';
  s.textContent = `
    @keyframes pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.45; }
    }
    @keyframes slideUp {
      from { opacity: 0; transform: translateY(8px); }
      to { opacity: 1; transform: translateY(0); }
    }
    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }
    @keyframes obt-spin {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }
  `;
  document.head.appendChild(s);
}

Object.assign(window, {
  Icon, Logo, Btn, Chip, RegionBadge, StatusPill, RarityBadge, ColorSwatch,
  StockRow, SectionHead, Field, TextInput, Toggle, timeAgo,
});
