// fc-icons.jsx, OnWeight bespoke combat-sport icon system.
//
// SYSTEM (research-grounded, Olympic-pictogram tradition):
// • 64-unit grid, 8-unit safe margin → 48-unit live area. Optical, not mechanical.
// • Equipment-led marks: each sport reads through its signature gear, not a figure
//   in motion (more legible at small size, fewer anatomy pitfalls).
// • One line language. Every mark is a clean outline at one constant stroke weight.
//   Gear you wear/hold (glove, jacket, belt) reads as a closed outline; equipment
//   that ENCLOSES the athlete (cage, ring, mask, headgear) reads as an open keyline.
// • One accent only. Brand red marks the single signature detail per icon (the
//   laces, the rank bar, the crack), at the same weight as the ink, never two.
// • Corner radius is generous and consistent (rounded terminals), matching the
//   Balanced product theme.
//
// Every icon renders into a 64×64 viewBox and inherits two colours so it works in
// positive, negative, duotone and single-tone, flexibility without a border.

const ICON_VB = 64;
const LINE_SW = 4;            // the single constant stroke weight
const DETAIL_SW = 3;          // secondary interior detail (mesh, tassels, inner ring)

// shared stroke props. _WMUL is the optical-weight multiplier SportGlyph sets per
// render size: full weight at hero/spec sizes, lighter at list/picker sizes so the
// marks sit with the app's hairlines and light type instead of out-weighing them.
let _WMUL = 1;
const _ln = (c, w = LINE_SW) => ({ fill: 'none', stroke: c, strokeWidth: +(w * _WMUL).toFixed(3), strokeLinecap: 'round', strokeLinejoin: 'round', vectorEffect: 'non-scaling-stroke' });

// ── icon geometry. each: (ink, acc, detail) => <g/> ──────────────────────────
const ICONS = {
  // BOXING, the closed mitt. Signature: the laces (accent).
  boxing: (ink, acc) => (
    <g>
      <path d="M20 40 V24 a14 14 0 0 1 28 0 V40" {..._ln(ink)} />
      <path d="M20 25 a6 6 0 0 0 0 12" {..._ln(ink)} />
      <rect x="20" y="40" width="28" height="12" rx="4" {..._ln(ink)} />
      <path d="M34 43 V49" {..._ln(acc)} />
      <path d="M30 45.5 H38" {..._ln(acc)} />
    </g>
  ),
  // MMA, the octagon cage (keyline). Signature: the cage gate (accent).
  mma: (ink, acc) => (
    <g>
      <polygon points="52.3,40.4 40.4,52.3 23.6,52.3 11.7,40.4 11.7,23.6 23.6,11.7 40.4,11.7 52.3,23.6" {..._ln(ink)} />
      <path d="M27 52.3 H37" {..._ln(acc)} />
    </g>
  ),
  // MUAY THAI, the mongkhon headband. Signature: the bound prasart knot (accent) at
  // the front; pra jiad tassels splay OUTWARD, killing the "magnifier/handle" read.
  muaythai: (ink, acc, detail = true) => (
    <g>
      <ellipse cx="32" cy="30" rx="16" ry="14" {..._ln(ink)} />
      {detail && <path d="M21 42 L17 53 M43 42 L47 53" {..._ln(ink, DETAIL_SW)} />}
      <path d="M25 42.6 Q32 45.4 39 42.6" {..._ln(acc)} />
    </g>
  ),
  // BJJ, the tied belt: the wrap, a centre knot, and two tails fanning outward (the
  // karate/BJJ knot). Signature: the rank bar (accent) bound across the knot.
  bjj: (ink, acc) => (
    <g>
      <path d="M12 25 H52" {..._ln(ink)} />
      <rect x="27" y="20" width="10" height="10" rx="2.5" {..._ln(ink)} />
      <path d="M30 30 L21 52 M34 30 L43 52" {..._ln(ink)} />
      <path d="M28 25 H36" {..._ln(acc)} />
    </g>
  ),
  // JUDO, the heavy wrap jacket. Signature: the belt (accent).
  judo: (ink, acc, detail = true) => (
    <g>
      <path d="M16 14 L26 14 L32 25 L38 14 L48 14 L50 20 L42 24 L42 52 L22 52 L22 24 L14 20 Z" {..._ln(ink)} />
      {detail && <path d="M32 25 L32 52" {..._ln(ink)} />}
      <path d="M14 41 H50" {..._ln(acc)} />
    </g>
  ),
  // TAEKWONDO, the board break: the system's ONE sanctioned "signature moment"
  // (not equipment). Signature: the fracture (accent), confined within the boards.
  taekwondo: (ink, acc) => (
    <g>
      <path d="M11 19 L30 22 L30 45 L11 42 Z" {..._ln(ink)} />
      <path d="M53 19 L34 22 L34 45 L53 42 Z" {..._ln(ink)} />
      <path d="M32 21 L28 31 L36 36 L32 46" {..._ln(acc)} />
    </g>
  ),
  // WRESTLING, the ear-guard headgear (keyline). Dome + chin strap, with the red ear
  // cups as the signature; seen front-on, the chin strap kills the "headphones" read.
  wrestling: (ink, acc) => (
    <g>
      <circle cx="32" cy="29" r="15" {..._ln(ink)} />
      <path d="M19 39 Q32 50 45 39" {..._ln(ink)} />
      <ellipse cx="16.5" cy="30" rx="4" ry="6.5" fill={acc} />
      <ellipse cx="47.5" cy="30" rx="4" ry="6.5" fill={acc} />
    </g>
  ),

  // ── EXPANSION ──────────────────────────────────────────────────────────────
  // KARATE, the front fist (seiken). Signature: the wrist wrap (accent).
  karate: (ink, acc, detail = true) => (
    <g>
      <rect x="16" y="16" width="32" height="23" rx="6" {..._ln(ink)} />
      {detail && <path d="M24 16 V25 M32 16 V25 M40 16 V25" {..._ln(ink, DETAIL_SW)} />}
      <path d="M16 32 H48" {..._ln(ink)} />
      <path d="M16 42 H48" {..._ln(acc)} />
    </g>
  ),
  // KICKBOXING, the contoured shin guard, tapering to the ankle so its silhouette
  // reads apart from judo/sambo/karate. Signature: the two straps (accent).
  kickboxing: (ink, acc) => (
    <g>
      <path d="M20 14 Q20 11 24 11 H40 Q44 11 44 14 L40 45 Q39.5 48 35 48 H29 Q24.5 48 24 45 Z" {..._ln(ink)} />
      <path d="M22 22 H42 M25 34 H39" {..._ln(acc)} />
    </g>
  ),
  // SAMBO, the wrestling boot. Signature: the laces (accent).
  sambo: (ink, acc) => (
    <g>
      <path d="M24 13 L33 13 L33 37 L46 40 a3 3 0 0 1 2.5 3 V49 a2.5 2.5 0 0 1 -2.5 2.5 H17 a3 3 0 0 1 -3 -3 V42 a3 3 0 0 1 3 -3 h7 Z" {..._ln(ink)} />
      <path d="M24.5 20 H32 M24.5 28 H32" {..._ln(acc)} />
    </g>
  ),
  // SUMO, the dohyō: clay platform (square) with the ring inside (keyline). The
  // square+circle pairing escapes the generic-disc read. Signature: the shikiri lines.
  sumo: (ink, acc, detail = true) => (
    <g>
      <rect x="12.5" y="12.5" width="39" height="39" rx="5" {..._ln(ink)} />
      {detail && <circle cx="32" cy="32" r="13" {..._ln(ink, DETAIL_SW)} />}
      <path d="M26.5 29 H37.5 M26.5 36 H37.5" {..._ln(acc)} />
    </g>
  ),
  // FENCING, the mask (keyline front). Signature: the bib (accent).
  fencing: (ink, acc, detail = true) => (
    <g>
      <path d="M18 24 a14 15 0 0 1 28 0 V40 a8 8 0 0 1 -4 7 H22 a8 8 0 0 1 -4 -7 Z" {..._ln(ink)} />
      {detail && <path d="M26 15 V44 M32 13 V46 M38 15 V44" {..._ln(ink, DETAIL_SW)} />}
      <path d="M22 47 L22 53 a10 8 0 0 0 20 0 L42 47" {..._ln(acc)} />
    </g>
  ),
};

const SPORT_META = {
  boxing:     { label: 'Boxing',     sig: 'Closed mitt + laces' },
  mma:        { label: 'MMA',        sig: 'Octagon cage' },
  muaythai:   { label: 'Muay Thai',  sig: 'Mongkhon crown' },
  bjj:        { label: 'BJJ',        sig: 'Belt + rank bar' },
  judo:       { label: 'Judo',       sig: 'Wrap jacket + belt' },
  taekwondo:  { label: 'Taekwondo',  sig: 'Board break' },
  wrestling:  { label: 'Wrestling',  sig: 'Ear-guard headgear' },
  karate:     { label: 'Karate',     sig: 'Front fist (seiken)' },
  kickboxing: { label: 'Kickboxing', sig: 'Shin guard' },
  sambo:      { label: 'Sambo',      sig: 'Wrestling boot' },
  sumo:       { label: 'Sumo',       sig: 'Dohyō ring' },
  fencing:    { label: 'Fencing',    sig: 'Mesh mask' },
};

const CORE_SPORTS = ['boxing', 'mma', 'muaythai', 'bjj', 'judo', 'taekwondo', 'wrestling'];
const EXP_SPORTS = ['karate', 'kickboxing', 'sambo', 'sumo', 'fencing'];

// ── optical normalisation ────────────────────────────────────────────────────
// Measured geometry bbox [cx, cy, maxDimension] per glyph. SportGlyph recenters each
// to (32,32) and scales its max dimension to a common target, so every mark sits in
// the same spot at the same optical size. non-scaling-stroke (in _ln) keeps the 4u
// weight constant through the scale, so weight stays uniform across the set.
const NORM = {
  boxing: [31, 31, 42], mma: [32, 32, 40.6], muaythai: [32, 34.5, 37], bjj: [32, 36, 40],
  judo: [32, 33, 38], taekwondo: [32, 32.5, 42], wrestling: [32, 29.3, 39], karate: [32, 29, 32],
  kickboxing: [32, 29.5, 37], sambo: [31.3, 32.3, 38.5], sumo: [32, 32, 39], fencing: [32, 35, 52],
};
const NORM_TARGET = 42;

// ── renderer ─────────────────────────────────────────────────────────────────
// variant: 'duo' (ink + red) · 'mono' (single ink)
function SportGlyph({ name, size = 56, ink = 'var(--ink)', accent = 'var(--red)', variant = 'duo' }) {
  const fn = ICONS[name];
  if (!fn) return null;
  const realInk = ink, realAcc = variant === 'mono' ? ink : accent;
  const detail = size >= 22;   // shed interior strokes at small sizes for list legibility
  // optical weight: thin to sit with the app's hairline UI and light type. With
  // non-scaling-stroke the multiplier IS the rendered px width, so keep it low.
  _WMUL = size >= 56 ? 0.5 : size >= 38 ? 0.4 : size >= 22 ? 0.34 : 0.42;
  let inner = fn(realInk, realAcc, detail);
  const nm = NORM[name];
  if (nm) {
    const s = NORM_TARGET / nm[2];
    const tx = 32 - s * nm[0], ty = 32 - s * nm[1];
    inner = <g transform={`translate(${tx.toFixed(2)} ${ty.toFixed(2)}) scale(${s.toFixed(4)})`}>{inner}</g>;
  }
  return (
    <svg width={size} height={size} viewBox={`0 0 ${ICON_VB} ${ICON_VB}`} fill="none" role="img" aria-label={SPORT_META[name] ? SPORT_META[name].label : name}>
      {inner}
    </svg>
  );
}

// badge frame variants for the canvas
function IconBadge({ name, frame = 'tile', size = 56, badge = 88 }) {
  const styles = {
    tile:   { background: 'var(--paper)', border: '1px solid var(--rule)', borderRadius: 20, boxShadow: '0 1px 3px rgba(20,18,12,0.05), 0 8px 22px rgba(20,18,12,0.05)' },
    circle: { background: 'var(--paper)', border: '1px solid var(--rule)', borderRadius: '50%' },
    ink:    { background: 'var(--ink)', borderRadius: 20 },
    clay:   { background: 'var(--clay)', borderRadius: 20 },
  }[frame];
  const inverted = frame === 'ink';
  return (
    <div style={{ width: badge, height: badge, display: 'flex', alignItems: 'center', justifyContent: 'center', ...styles }}>
      <SportGlyph name={name} size={size} ink={inverted ? 'var(--paper)' : 'var(--ink)'} accent={inverted ? '#f0a08f' : 'var(--red)'} />
    </div>
  );
}

// grid-overlay construction proof (anatomy section)
function ConstructionTile({ name, size = 180 }) {
  const u = size / ICON_VB;
  const lines = [];
  for (let i = 1; i < 8; i++) lines.push(i * 8);
  return (
    <div style={{ position: 'relative', width: size, height: size, background: 'var(--paper)', border: '1px solid var(--rule)', borderRadius: 16, overflow: 'hidden' }}>
      <svg width={size} height={size} style={{ position: 'absolute', inset: 0 }}>
        {lines.map(p => <line key={'v'+p} x1={p*u} y1={0} x2={p*u} y2={size} stroke="var(--rule)" strokeWidth="0.5" opacity="0.6" />)}
        {lines.map(p => <line key={'h'+p} x1={0} y1={p*u} x2={size} y2={p*u} stroke="var(--rule)" strokeWidth="0.5" opacity="0.6" />)}
        <rect x={8*u} y={8*u} width={48*u} height={48*u} fill="none" stroke="var(--red)" strokeWidth="0.8" strokeDasharray="3 3" opacity="0.7" />
        <circle cx={size/2} cy={size/2} r={24*u} fill="none" stroke="var(--red)" strokeWidth="0.8" strokeDasharray="3 3" opacity="0.5" />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <SportGlyph name={name} size={size * 0.86} />
      </div>
    </div>
  );
}

Object.assign(window, { ICONS, SPORT_META, CORE_SPORTS, EXP_SPORTS, SportGlyph, IconBadge, ConstructionTile });
