// Shared editorial primitives used across all artboards.

function Eyebrow({ children, dirId = 'concours', color, style = {} }) {
  const d = DIRECTIONS[dirId];
  return (
    <div style={{
      fontFamily: d.type.mono,
      fontSize: 10,
      letterSpacing: '0.18em',
      textTransform: 'uppercase',
      fontWeight: 500,
      color: color || d.palette.mute,
      ...style,
    }}>{children}</div>
  );
}

function VolumeStamp({ vol = '001', issue = 'INDEX', date = 'SUMMER 2026', dirId = 'concours', color }) {
  const d = DIRECTIONS[dirId];
  const c = color || d.palette.paper;
  return (
    <div style={{
      textAlign: 'right', color: c, lineHeight: 1.05,
    }}>
      <div style={{
        fontFamily: d.type.display,
        fontWeight: d.type.displayWeight,
        fontSize: 28, letterSpacing: d.type.displayTracking,
      }}>{vol}</div>
      <div style={{
        fontFamily: d.type.mono, fontSize: 9, letterSpacing: '0.18em',
        textTransform: 'uppercase', marginTop: 4, opacity: 0.85,
      }}>{issue}</div>
      <div style={{
        fontFamily: d.type.mono, fontSize: 9, letterSpacing: '0.18em',
        textTransform: 'uppercase', marginTop: 1, opacity: 0.7,
      }}>{date}</div>
    </div>
  );
}

// A rule with a label sitting flush — used liberally for editorial dividers.
function RuleLabel({ children, dirId = 'concours', color }) {
  const d = DIRECTIONS[dirId];
  const c = color || d.palette.slate;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
      <div style={{
        fontFamily: d.type.mono, fontSize: 9, letterSpacing: '0.18em',
        textTransform: 'uppercase', color: c, whiteSpace: 'nowrap',
      }}>{children}</div>
      <div style={{ flex: 1, height: 1, background: c, opacity: 0.4 }} />
    </div>
  );
}

// Card frame used inside artboards — a paper "page" for the section.
function Page({ dirId = 'concours', bg, fg, padding = 32, children, style = {} }) {
  const d = DIRECTIONS[dirId];
  return (
    <div style={{
      width: '100%', height: '100%',
      background: bg || d.palette.paper,
      color: fg || d.palette.ink,
      padding,
      fontFamily: d.type.body,
      position: 'relative',
      overflow: 'hidden',
      ...style,
    }}>{children}</div>
  );
}

// Icon system — Lucide outline library, mapped to short semantic names.
// Lucide ships icon defs as [tag, attrs, children] tuples on the global
// `lucide` object (PascalCase keys). If a name isn't in Lucide we fall
// back to a hand-drawn shape in the same monoline style.

const ICON_MAP = {
  garage:      'Warehouse',
  car:         'CarFront',
  gauge:       'Gauge',
  wrench:      'Wrench',
  hammer:      'Gavel',         // auction hammer
  spark:       'Sparkles',
  road:        'Route',
  flag:        'Flag',
  bookmark:    'Bookmark',
  search:      'Search',
  filter:      'SlidersHorizontal',
  compass:     'Compass',
  archive:     'Archive',
  heart:       'Heart',
  share:       'Share2',
  add:         'Plus',
  arrow:       'ArrowRight',
  certificate: 'Award',
};

function Icon({ name, size = 22, color = 'currentColor', strokeWidth = 1.5, style = {} }) {
  const lucideName = ICON_MAP[name] || name;
  const L = (typeof window !== 'undefined') ? window.lucide : null;
  const def = L && (L[lucideName] || (L.icons && L.icons[lucideName]));
  if (!def) {
    // Lucide not ready yet (race on first paint) — render a hairline box so
    // layout doesn't jump, then it'll fill in on the next render pass.
    return <svg width={size} height={size} viewBox="0 0 24 24" style={style} />;
  }
  const [, , children] = def;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke={color} strokeWidth={strokeWidth}
      strokeLinecap="round" strokeLinejoin="round"
      style={style}>
      {children.map(([tag, a], i) => React.createElement(tag, { key: i, ...a }))}
    </svg>
  );
}

Object.assign(window, { Eyebrow, VolumeStamp, RuleLabel, Page, Icon, ICON_MAP });
