/* RecordField — the categorical corpus field.
   Source: index.html lines 114–122 (.grid197 / .cell / .legend / .lg) and the
   register data + isolate behavior at lines 431–480.

   Encoding rules this component enforces:
     · fills, never outlines
     · source groups ordered largest-first so the ramp reads as volume
     · isolation dims to 13% — it never removes cells, so the denominator stays
     · the container is role="img" with a full aria-label, and a text fallback
       renders when there is nothing to draw

   Selection works on hover, focus AND click. Click locks; Escape clears. */
function RecordField({ registers = [], ariaLabel }) {
  const [hovered, setHovered] = React.useState(null);
  const [locked, setLocked] = React.useState(null);
  const active = locked || hovered;

  React.useEffect(() => {
    function onKey(e) { if (e.key === 'Escape') setLocked(null); }
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, []);

  const total = registers.reduce((sum, r) => sum + r.n, 0);
  const label = ariaLabel || `${total} prototype ALERG keyword matches by source group: ` +
    registers.map((r) => `${r.n} ${r.label}`).join(', ') + '.';

  if (!total) {
    return (
      <p className="src">
        Source-group data unavailable — the full breakdown is in the ALERG case file.
      </p>
    );
  }

  const cells = [];
  registers.forEach((r) => {
    for (let i = 0; i < r.n; i++) {
      cells.push(
        <span
          key={`${r.k}-${i}`}
          className={`cell${active && r.k === active ? ' on' : ''}`}
          style={{ background: r.c }}
          title={r.label}
        />
      );
    }
  });

  return (
    <React.Fragment>
      <div className={`grid197${active ? ' focused' : ''}`} role="img" aria-label={label}>
        {cells}
      </div>
      <div className="legend">
        {registers.map((r) => (
          <button
            key={r.k}
            type="button"
            className="lg"
            aria-pressed={locked === r.k}
            aria-label={`Isolate ${r.label}, ${r.n} prototype matches`}
            onClick={() => setLocked(locked === r.k ? null : r.k)}
            onMouseEnter={() => setHovered(r.k)}
            onFocus={() => setHovered(r.k)}
            onMouseLeave={() => setHovered(null)}
            onBlur={() => setHovered(null)}
          >
            <span className="sw" style={{ background: r.c }} />
            {r.label} <span className="n">{r.n}</span>
          </button>
        ))}
      </div>
    </React.Fragment>
  );
}

/* The eight source groups of the ALERG prototype, scanned 2026-07-15. Total 197.
   Colors resolve from the --reg-* tokens so the encoding follows the palette
   and the active theme; the hex values are fallbacks only. */
RecordField.ALERG_REGISTERS = [
  { k: 'minutes', label: 'Council agendas & minutes', n: 70, c: 'var(--reg-1, #14572f)' },
  { k: 'boards',  label: 'Boards & hearings',         n: 44, c: 'var(--reg-2, #166534)' },
  { k: 'legis',   label: 'Council legislation',       n: 39, c: 'var(--reg-3, #3f8f52)' },
  { k: 'press',   label: 'City press releases',       n: 13, c: 'var(--reg-4, #6aa876)' },
  { k: 'edgar',   label: 'SEC EDGAR (local)',         n: 6,  c: 'var(--reg-5, #8fb597)' },
  { k: 'schools', label: 'Schools board',             n: 5,  c: 'var(--reg-6, #b3cdb8)' },
  { k: 'auditor', label: 'County auditor property',   n: 4,  c: 'var(--reg-7, #a8781f)' },
  { k: 'other',   label: '7 other source groups',     n: 16, c: 'var(--reg-8, #cfd8c9)' }
];

window.RecordField = RecordField;
