/* ═══════════════════════════════════════════════════════════
   Granularity explorations — shared: styles, Icon, ContentPanel
═══════════════════════════════════════════════════════════ */
const { useState: useStateG } = React;
const GRAN = window.GRAN;

/* one-time scoped CSS (everything under .gx) */
if (!document.getElementById('gx-styles')) {
  const s = document.createElement('style');
  s.id = 'gx-styles';
  s.textContent = `
  .gx, .gx * { box-sizing: border-box; }
  .gx {
    --paper:#f7f9fc; --ink:#38414f; --blue:#3d6b8a; --l-blue:#7a9ab5;
    --muted:#4a5563; --rule:#cdd5de; --vpale:#dde4ec; --icon:#8898aa; --white:#fff;
    --disp:'IM Fell English',Georgia,serif; --body:'Cormorant Garamond',Georgia,serif; --sc:'Cormorant SC',Georgia,serif;
    font-family: var(--body); color: var(--ink); background: var(--paper);
    width:100%; height:100%; display:flex; flex-direction:column;
  }
  .gx .disp { font-family: var(--disp); }
  .gx .sc { font-family: var(--sc); text-transform: uppercase; letter-spacing: .14em; }
  .gx svg.glyph { overflow: visible; }

  /* artboard title strip */
  .gx-top { padding:18px 20px 14px; border-bottom:1px solid var(--rule); }
  .gx-kick { font-family:var(--sc); text-transform:uppercase; letter-spacing:.18em; font-size:11px; color:var(--blue); margin-bottom:6px; }
  .gx-h { font-family:var(--disp); font-size:24px; line-height:1.05; color:var(--ink); }
  .gx-note { font-size:13.5px; font-weight:500; color:var(--muted); line-height:1.45; margin-top:7px; }

  /* content panel */
  .gx-panel { flex:1; padding:18px 20px 22px; min-height:0; display:flex; flex-direction:column; }
  .gx-pscale { font-family:var(--sc); text-transform:uppercase; letter-spacing:.16em; font-size:11px; color:var(--blue); }
  .gx-pspan { font-family:var(--disp); font-size:30px; line-height:1.05; color:var(--ink); margin:6px 0 4px; }
  .gx-pgloss { font-size:15px; font-style:italic; font-weight:500; color:var(--muted); }

  /* resolution meter — visualises granularity falling off */
  .gx-res { display:flex; align-items:center; gap:10px; margin:14px 0 4px; }
  .gx-res-bar { flex:1; height:18px; display:flex; align-items:center; gap:2px; }
  .gx-res-tick { flex:1; background:var(--l-blue); border-radius:1px; opacity:.85; }
  .gx-res-label { font-family:var(--sc); text-transform:uppercase; letter-spacing:.1em; font-size:10px; color:var(--muted); white-space:nowrap; }

  .gx-rows { margin-top:14px; display:flex; flex-direction:column; gap:8px; overflow:hidden; }
  .gx-row { display:flex; gap:11px; align-items:flex-start; padding:10px 12px; background:var(--white);
            border:1px solid var(--vpale); border-left:3px solid var(--rule); border-radius:2px; }
  .gx-row.lens-auspice  { border-left-color:var(--blue); }
  .gx-row.lens-transit  { border-left-color:var(--l-blue); }
  .gx-row.lens-planning { border-left-color:#9aa9bb; }
  .gx-row-icn { color:var(--blue); margin-top:2px; }
  .gx-row-icn svg { width:15px; height:15px; }
  .gx-row-body { flex:1; min-width:0; }
  .gx-row-top { display:flex; justify-content:space-between; gap:10px; align-items:baseline; }
  .gx-row-label { font-family:var(--disp); font-size:16px; color:var(--ink); line-height:1.18; }
  .gx-row-time { font-family:var(--sc); text-transform:uppercase; letter-spacing:.06em; font-size:11px; color:var(--blue); white-space:nowrap; flex-shrink:0; }
  .gx-row-text { font-size:13.5px; font-weight:500; color:var(--muted); line-height:1.45; margin-top:3px; }
  .gx-lenschip { font-family:var(--sc); text-transform:uppercase; letter-spacing:.1em; font-size:9px;
                 color:var(--muted); border:1px solid var(--vpale); border-radius:2px; padding:2px 6px; }

  /* coarser levels: fewer, larger blocks */
  .gx-rows[data-grain="4"] .gx-row-label,
  .gx-rows[data-grain="5"] .gx-row-label,
  .gx-rows[data-grain="6"] .gx-row-label { font-size:18px; }
  .gx-rows[data-grain="5"] .gx-row, .gx-rows[data-grain="6"] .gx-row { padding:14px 14px; }
  .gx-rows[data-grain="6"] .gx-row-text { font-size:14.5px; }

  .gx-count { font-family:var(--sc); text-transform:uppercase; letter-spacing:.1em; font-size:10.5px; color:var(--muted); margin-top:auto; padding-top:14px; }
  .gx-count b { color:var(--blue); font-weight:400; }
  `;
  document.head.appendChild(s);
}

function GIcon({ id, cls, style }) {
  return <svg className={'glyph ' + (cls||'')} viewBox="0 0 16 16" style={style} aria-hidden="true"><use href={'#' + id} /></svg>;
}

/* resolution meter: many thin ticks (fine) → few fat ticks (coarse) */
const RES_TICKS = [40, 22, 13, 8, 5, 3, 2];
function ResolutionMeter({ idx }) {
  const n = RES_TICKS[idx];
  return (
    <div className="gx-res">
      <span className="gx-res-label">Fine</span>
      <div className="gx-res-bar">
        {Array.from({ length: n }).map((_, i) => (
          <span key={i} className="gx-res-tick" style={{ height: (6 + idx * 1.8) + 'px' }}></span>
        ))}
      </div>
      <span className="gx-res-label">Coarse</span>
    </div>
  );
}

/* shared content panel — the same data, reshaped by the chosen scale */
function ContentPanel({ level, showHead }) {
  return (
    <div className="gx-panel">
      {showHead !== false && (
        <div>
          <div className="gx-pscale">{level.scale} · {level.when}</div>
          <div className="gx-pspan">{level.span}</div>
          <div className="gx-pgloss">{level.gloss}</div>
        </div>
      )}
      <ResolutionMeter idx={level.idx} />
      <div className="gx-rows" data-grain={level.idx}>
        {level.rows.map((r, i) => (
          <div key={i} className={'gx-row lens-' + r.lens}>
            <span className="gx-row-icn"><GIcon id={r.icon} /></span>
            <div className="gx-row-body">
              <div className="gx-row-top">
                <span className="gx-row-label">{r.label}</span>
                {r.time && r.time !== '—' && <span className="gx-row-time">{r.time}</span>}
              </div>
              <div className="gx-row-text">{r.text}</div>
            </div>
          </div>
        ))}
      </div>
      <div className="gx-count">
        Resolution <b>{level.precision}</b> · {level.rows.length} {level.rows.length === 1 ? 'reading' : 'readings'}
      </div>
    </div>
  );
}

Object.assign(window, { GIcon, ResolutionMeter, ContentPanel });
