/* Skyhearth Codex — entry treatments
 * Three visual directions for a single gated Codex entry, each driven by two
 * independent flags: `seen` (stats) and `triggerKnown` (the secret trigger).
 *   tier 0 Rumored      = !seen && !triggerKnown
 *   tier 1 Discovered   = seen
 *   tier 2 Trigger known= triggerKnown
 * Art is element-icon based (identities/art deferred per handoff §10). */
/* global CX_ELEM, VERDICT_META, AVAIL_META, restLabel, timeAwakePct, triggerLore */

const pad2 = (n) => String(n).padStart(2, '0');
function tierOf(seen, tk) { return tk ? 2 : seen ? 1 : 0; }
// 2x2 reveal — `seen` and `tk` (triggerKnown) are INDEPENDENT axes:
//   seen → the realized stat record (role, niche, distribution, rest/food/bond/life, ledger)
//   tk   → the secret trigger.  Identity (which veins / art / name / class) shows once EITHER is true.
// "Told, not seen" (tk && !seen) knows the recipe but not the record — the stat block stays sealed.
function revLabel(seen, tk) {
  return (seen && tk) ? 'TRIGGER KNOWN' : tk ? 'TOLD, NOT SEEN' : seen ? 'DISCOVERED' : 'RUMORED';
}

// element composite — overlapping inked icons on a plate -----------------------
function ElComposite({ els, size = 92, ghost = false }) {
  // Rumored (tier 0): no vein art may leak — render a neutral unformed silhouette.
  if (ghost) {
    return (
      <div style={{ width:size, height:size, position:'relative', display:'flex', alignItems:'center', justifyContent:'center' }}>
        <img src="assets/drift-mote.png" alt="" style={{ width:size*0.92, height:size*0.92, objectFit:'contain',
          filter:'url(#sh-dropwhite) grayscale(1) brightness(0)', opacity:0.12 }} />
      </div>
    );
  }
  if (!els.length) {
    return <div style={{ width:size, height:size, display:'flex', alignItems:'center', justifyContent:'center',
      fontFamily:'IM Fell English SC, serif', fontSize:size*0.5, color:'var(--ink-faded)' }}>※</div>;
  }
  const step = els.length > 1 ? Math.min(26, size*0.28) : 0;
  const w = size + step * (els.length - 1);
  return (
    <div style={{ position:'relative', width:w, height:size }}>
      {els.map((e, i) => (
        <img key={e} src={CX_ELEM[e].icon} alt="" style={{
          position:'absolute', left:i*step, top:0, width:size, height:size, objectFit:'contain',
          filter: 'url(#sh-dropwhite) drop-shadow(0 3px 7px rgba(74,54,38,0.4))',
          opacity: 1,
        }} />
      ))}
    </div>
  );
}

// form portrait — real adult artwork when discovered, element composite otherwise
// Pures + duals carry `f.art` (canonical R2 illustration). Rumored (ghost) always
// falls back to the neutral silhouette — no identity may leak before discovery.
function FormPortrait({ f, size = 92, ghost = false }) {
  if (!ghost && f && f.art) {
    return (
      <img src={f.art.src} alt="" style={{ width:size, height:size, objectFit:'contain',
        filter:'url(#sh-dropwhite) drop-shadow(0 3px 8px rgba(74,54,38,0.42))' }} />
    );
  }
  return <ElComposite els={f ? f.elements : []} size={size} ghost={ghost} />;
}

// element glyph chip ----------------------------------------------------------
function ElChip({ e, val }) {
  const m = CX_ELEM[e];
  return (
    <span style={{ display:'inline-flex', alignItems:'center', gap:5, fontFamily:'JetBrains Mono, monospace', fontSize:12.5 }}>
      <span style={{ width:18, height:18, borderRadius:'50%', display:'inline-flex', alignItems:'center', justifyContent:'center',
        border:`1.5px solid ${m.color}`, color:m.color, fontFamily:'IM Fell English SC, serif', fontSize:13 }}>{m.glyph}</span>
      <span style={{ color:'var(--ink)' }}>{m.name}</span>
      {val != null && <span style={{ color:m.color, fontWeight:600 }}>+{val}</span>}
    </span>
  );
}

// minimal §6 ledger — diverging bars + NET vs GATE ----------------------------
function LedgerBars({ f, compact }) {
  const d = f.d;
  const parts = [
    { k:'bonus', v:d.effBonus, label:'Bonus' },
    { k:'rest',  v:d.restV,    label:'Rest'  },
    { k:'life',  v:d.lifeV,    label:'Life'  },
    { k:'food',  v:d.foodV,    label:'Food'  },
    { k:'bond',  v:d.bondV,    label:'Bond'  },
  ];
  const max = 34;
  const vm = VERDICT_META[d.verdict];
  return (
    <div className="col" style={{ gap:5 }}>
      {!compact && <div className="label" style={{ marginBottom:1 }}>BALANCE LEDGER · NET {d.net} vs GATE {d.gate}</div>}
      {parts.map(p => {
        const pct = Math.min(100, Math.abs(p.v)/max*100);
        const pos = p.v >= 0;
        return (
          <div key={p.k} className="row" style={{ gap:7, fontFamily:'JetBrains Mono, monospace', fontSize:10.5 }}>
            <span style={{ width:38, color:'var(--ink-faded)', textTransform:'uppercase', letterSpacing:'0.08em' }}>{p.label}</span>
            <div style={{ position:'relative', flex:1, height:9, background:'var(--ink-trace)' }}>
              <div style={{ position:'absolute', left:'50%', top:0, bottom:0, width:1, background:'var(--ink-ghost)' }} />
              <div style={{ position:'absolute', top:0, bottom:0,
                left: pos ? '50%' : `${50 - pct/2}%`, width:`${pct/2}%`,
                background: pos ? 'var(--ok)' : 'var(--crit)', opacity:0.78 }} />
            </div>
            <span style={{ width:24, textAlign:'right', color: pos ? 'var(--ok)' : 'var(--crit)' }}>{pos?'+':''}{p.v}</span>
          </div>
        );
      })}
      <div className="row" style={{ gap:7, marginTop:2 }}>
        <span className="stamp" style={{ fontSize:9, padding:'2px 7px 1px', transform:'rotate(-1.5deg)', borderColor:vm.color, color:vm.color, background:'transparent' }}>{vm.label.toUpperCase()}</span>
        {!compact && <span className="label" style={{ color:'var(--ink-faded)', textTransform:'none', letterSpacing:0 }}>{vm.note}</span>}
      </div>
    </div>
  );
}

// requirements vs effects — the clear breakdown (Direction A) -----------------
function GroupHead({ children }) {
  return <div className="row" style={{ gap:6, alignItems:'center', margin:'2px 0 5px' }}>
    <span className="label label-ink" style={{ fontSize:9.5 }}>{children}</span>
    <span className="leader" style={{ margin:0 }} />
  </div>;
}
function KV({ k, v, accent }) {
  return (
    <div className="row" style={{ padding:'2.5px 0' }}>
      <span className="label" style={{ fontSize:9 }}>{k}</span>
      <span className="leader" />
      <span style={{ fontFamily:'JetBrains Mono, monospace', fontSize:11.5, color:accent||'var(--ink)' }}>{v}</span>
    </div>
  );
}
function ReqEffect({ f }) {
  const av = AVAIL_META[f.avail];
  const gv = window.GATE_VALUE[f.gate];
  const bonusStr = f.elements.length
    ? f.elements.map(e => `${CX_ELEM[e].glyph}+${f.d.dist[e]}`).join('  ')
    : 'spread 4 / 4 / 4 / 4';
  return (
    <div className="col" style={{ gap:9 }}>
      <div>
        <GroupHead>REQUIREMENTS</GroupHead>
        <KV k="Trigger gate" v={`${f.gate[0].toUpperCase()+f.gate.slice(1)} · diff ${gv}`} />
        <KV k="Availability" v={av.label} accent={av.color} />
        <KV k="Class" v={`${window.plabel(f.profile)}${f.variant!=='std' && f.variant!=='only' ? ' · '+f.variant : ''}`} />
      </div>
      <div>
        <GroupHead>EFFECTS · ON ASCEND</GroupHead>
        <KV k="Ascend bonus" v={bonusStr} accent="var(--stamp-amber)" />
        <KV k="Sleep" v={restLabel(f.rest)} />
        <KV k="Lifespan" v={`${f.life} days`} />
        <KV k="Appetite" v={f.food[0].toUpperCase()+f.food.slice(1)} />
        <KV k="Bond decay" v={f.bond[0].toUpperCase()+f.bond.slice(1)} />
      </div>
    </div>
  );
}

// shared stat lines (legacy; kept for any caller) ------------------------------
function StatLines({ f }) {
  const rows = [
    ['Role', f.role],
    ['Rest', restLabel(f.rest) + ` · ${timeAwakePct(f.rest)}% awake`],
    ['Lifespan', f.life + ' days'],
    ['Food', f.food[0].toUpperCase()+f.food.slice(1)],
    ['Bond', f.bond[0].toUpperCase()+f.bond.slice(1)],
    ['R3 route', f.d.r3 ? `→ ${f.d.r3}` : '—'],
  ];
  return (
    <div className="col" style={{ gap:0 }}>
      {rows.map(([k,v]) => (
        <div key={k} className="row" style={{ padding:'3px 0', borderBottom:'1px dotted var(--ink-ghost)' }}>
          <span className="label">{k}</span>
          <span className="leader" />
          <span style={{ fontFamily:'JetBrains Mono, monospace', fontSize:11.5, color:'var(--ink)' }}>{v}</span>
        </div>
      ))}
    </div>
  );
}

// trigger block (tier 2) — diegetic lore framing + the hard conditions --------
function ElThresh({ el, val, forbid }) {
  const m = CX_ELEM[el];
  return (
    <span style={{ display:'inline-flex', alignItems:'center', gap:4, fontFamily:'JetBrains Mono, monospace', fontSize:11,
      padding:'2px 7px', border:`1px solid ${forbid?'var(--crit)':m.color}`, color:forbid?'var(--crit)':'var(--ink)' }}>
      <span style={{ color:forbid?'var(--crit)':m.color, fontFamily:'IM Fell English SC, serif' }}>{m.glyph}</span>
      {m.name} {forbid ? '= 0' : `\u2265 ${val}`}
    </span>
  );
}
function TriggerSlip({ f, known }) {
  if (!known) {
    return (
      <div className="crosshatch" style={{ border:'1.5px dashed var(--ink-faded)', padding:'10px 12px', background:'rgba(26,46,74,0.03)' }}>
        <div className="label" style={{ color:'var(--ink-faded)' }}>SECRET TRIGGER · SEALED</div>
        <div className="elite" style={{ fontSize:11, color:'var(--ink-faded)', marginTop:4, lineHeight:1.5 }}>
          Unknown. Achieve this form once, or find the soul who still remembers how it turns.
        </div>
      </div>
    );
  }
  const lore = triggerLore(f);
  const spec = window.triggerSpec(f);
  return (
    <div style={{ position:'relative', background:'var(--paper-light)', border:'1px solid var(--ink-faded)',
      padding:'11px 13px', boxShadow:'0 2px 8px rgba(74,54,38,0.18)' }}>
      <div className="label" style={{ color:'var(--stamp-amber)' }}>TRIGGER · KNOWN</div>
      <div className="fell" style={{ fontStyle:'italic', fontSize:14.5, lineHeight:1.4, color:'var(--ink)', margin:'5px 0 4px' }}>{lore.text}</div>
      <div className="elite" style={{ fontSize:10, color:'var(--sepia)', textAlign:'right', marginBottom:8 }}>— {lore.who}</div>
      {/* the hard conditions — element floors · lived history · caps */}
      <div className="col" style={{ gap:7, borderTop:'1px dotted var(--ink-ghost)', paddingTop:8 }}>
        {(spec.gates.length > 0 || spec.sum != null) && <React.Fragment>
          <div className="label" style={{ fontSize:9 }}>ELEMENT FLOORS</div>
          <div className="row" style={{ gap:6, flexWrap:'wrap' }}>
            {spec.gates.map(g => <ElThresh key={g.el} el={g.el} val={g.val} />)}
            {spec.sum != null && <span style={{ fontFamily:'JetBrains Mono, monospace', fontSize:11, padding:'2px 7px', border:'1px solid var(--ink-faded)' }}>all veins · Σ ≥ {spec.sum}</span>}
          </div>
        </React.Fragment>}
        {spec.events.length > 0 && <React.Fragment>
          <div className="label" style={{ fontSize:9, marginTop:2 }}>LIVED HISTORY</div>
          <ul style={{ margin:0, paddingLeft:16 }}>
            {spec.events.map((e,i) => <li key={i} className="elite" style={{ fontSize:11, color:'var(--ink)', lineHeight:1.5 }}>{e.text}</li>)}
          </ul>
        </React.Fragment>}
        {spec.caps.length > 0 && <React.Fragment>
          <div className="label" style={{ fontSize:9, marginTop:2, color:'var(--crit)' }}>CAPS · DODGE THE LEAK</div>
          <div className="row" style={{ gap:6, flexWrap:'wrap' }}>
            {spec.caps.map((c,i) => <span key={i} style={{ fontFamily:'JetBrains Mono, monospace', fontSize:10.5, padding:'2px 7px', border:'1px solid var(--crit)', color:'var(--crit)' }}>{c.text}</span>)}
          </div>
        </React.Fragment>}
      </div>
    </div>
  );
}

// trait block — what the form DOES on ascend (§11.10–11.11). Part of "seen" knowledge.
function TraitSlip({ f, compact }) {
  const tr = f.trait || { kind:'none' };
  const km = ({
    active:  { label:'ACTIVE',  color:'var(--stamp-amber)' },
    passive: { label:'PASSIVE', color:'var(--ok)' },
  })[tr.kind] || { label:'—', color:'var(--ink-faded)' };
  if (tr.kind === 'none') {
    return (
      <div className="row" style={{ gap:7, alignItems:'baseline', padding:'1px 0' }}>
        <span className="label" style={{ fontSize:9 }}>TRAIT</span>
        <span className="leader" />
        <span className="elite" style={{ fontSize:10.5, color:'var(--ink-faded)', fontStyle:'italic' }}>characterful — its trigger &amp; reward-stats carry it</span>
      </div>
    );
  }
  return (
    <div style={{ border:'1px solid var(--ink-faded)', borderLeft:`3px solid ${km.color}`, background:'rgba(244,236,214,0.4)', padding:'8px 11px' }}>
      <div className="row" style={{ justifyContent:'space-between', alignItems:'baseline', gap:8 }}>
        <span className="fell" style={{ fontSize:15, color:'var(--ink)' }}>{tr.name}</span>
        <span className="row" style={{ gap:5, alignItems:'center', flexShrink:0 }}>
          {tr.nyi && <span className="stamp" style={{ fontSize:7.5, borderColor:'var(--crit)', color:'var(--crit)', padding:'1px 5px' }}>NYI</span>}
          {tr.town && <span className="stamp" style={{ fontSize:7.5, borderColor:'var(--ink-faded)', color:'var(--sepia)', padding:'1px 5px' }}>TOWN</span>}
          <span style={{ fontFamily:'Special Elite, monospace', fontSize:8.5, letterSpacing:'0.1em', color:km.color }}>{km.label}</span>
        </span>
      </div>
      <div className="elite" style={{ fontSize:11, color:'var(--ink)', lineHeight:1.45, marginTop:3 }}>{tr.text}</div>
      {!compact && tr.reg && <div style={{ fontFamily:'JetBrains Mono, monospace', fontSize:8.5, color:'var(--ink-faded)', marginTop:5 }}>{tr.scarce ? '⚑ scarce · ' : ''}{tr.reg}</div>}
    </div>
  );
}

// =============================================================================
// A · FIELD DOSSIER — census index-card, redaction & stamps
// =============================================================================
function DossierCard({ f, num, seen, triggerKnown, w = 340 }) {
  const t = tierOf(seen, triggerKnown);
  const av = AVAIL_META[f.avail];
  const Redact = ({ width }) => (
    <span style={{ display:'inline-block', height:11, width, background:'var(--ink)', opacity:0.82, borderRadius:1, verticalAlign:'middle' }} />
  );
  return (
    <div className="panel brackets" style={{ width:w, background:'var(--paper)', padding:'0 0 14px', position:'relative' }}>
      {/* header strip */}
      <div className="row" style={{ justifyContent:'space-between', alignItems:'flex-start', padding:'12px 14px 9px', borderBottom:'1.5px solid var(--ink)' }}>
        <div className="col" style={{ gap:2 }}>
          <span className="label" style={{ letterSpacing:'0.18em' }}>ADULT FORM · №{pad2(num)}</span>
          <span className="fell" style={{ fontSize:21, lineHeight:1 }}>{t>=1 ? f.slot : <Redact width={108} />}</span>
        </div>
        <span className="stamp" style={{ fontSize:9, borderColor:av.color, color:av.color }}>{t>=1 ? window.plabel(f.profile).toUpperCase() : 'CLASS ?'}</span>
      </div>

      {/* specimen well */}
      <div className="row" style={{ gap:12, padding:'12px 14px 4px' }}>
        <div style={{ position:'relative', width:96, height:96, border:'1.5px solid var(--ink-faded)', background:'rgba(255,255,255,0.18)',
          display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
          {t>=1
            ? <FormPortrait f={f} size={86} />
            : <>
                <FormPortrait f={f} size={70} ghost />
                <span style={{ position:'absolute', fontFamily:'IM Fell English SC, serif', fontSize:48, color:'var(--ink-faded)' }}>?</span>
              </>}
        </div>
        <div className="col" style={{ gap:6, flex:1, minWidth:0 }}>
          {t>=1
            ? <div className="col" style={{ gap:4 }}>
                {f.elements.length
                  ? f.elements.map(e => <ElChip key={e} e={e} val={seen ? f.d.dist[e] : null} />)
                  : <span className="elite" style={{ fontSize:11, color:'var(--sepia)' }}>all veins, in equal measure</span>}
                {seen && <div className="elite" style={{ fontSize:10.5, color:'var(--sepia)', marginTop:2 }}>niche · {f.d.niche.join(' / ') || 'none'}</div>}
              </div>
            : <div className="col" style={{ gap:7, paddingTop:4 }}>
                <Redact width="80%" /><Redact width="62%" /><Redact width="70%" />
              </div>}
        </div>
      </div>

      {/* record body — requirements vs effects */}
      <div style={{ padding:'8px 14px 0' }}>
        {seen
          ? <ReqEffect f={f} />
          : <div className="col" style={{ gap:9, padding:'6px 0' }}>
              {[88,72,80,64,76].map((wd,i)=>(
                <div key={i} className="row" style={{ gap:8 }}>
                  <span className="label" style={{ opacity:0.5 }}>{['GATE','BONUS','UPTIME','LIFE','BOND'][i]}</span>
                  <span className="leader" /><Redact width={wd*0.5} />
                </div>
              ))}
            </div>}
      </div>

      {/* ledger (seen only) */}
      {seen && <div style={{ padding:'10px 14px 0' }}><LedgerBars f={f} /></div>}

      {/* trait (seen only) — what it does on ascend */}
      {seen && <div style={{ padding:'10px 14px 0' }}><TraitSlip f={f} /></div>}

      {/* trigger */}
      <div style={{ padding:'10px 14px 0' }}><TriggerSlip f={f} known={t>=2} /></div>

      {/* tier flag */}
      <div style={{ position:'absolute', top:-11, right:14 }}>
        <span className="stamp stamp-amber" style={{ fontSize:9, transform:'rotate(2deg)', background:'var(--paper)' }}>
          {revLabel(seen, triggerKnown)}
        </span>
      </div>
    </div>
  );
}

window.CodexCards = { DossierCard, ElComposite, FormPortrait, ElChip, LedgerBars, StatLines, TriggerSlip, TraitSlip, tierOf, pad2 };
