// Homebrew Tab — D&D-Beyond-style item viewer + AI Forge (fuse/reforge)
const HB_RARITY_COLOR = {
  common:      '#6b6966',
  uncommon:    '#22c55e',
  rare:        '#3a8fd9',
  'very-rare': '#a05fd9',
  legendary:   '#c9a227',
  artifact:    '#e25822',
};
const HB_RARITY_ORDER = ['common','uncommon','rare','very-rare','legendary','artifact'];

// ── Tiny markdown renderer (no deps) ─────────────────────────────────────────
// Supports: # / ## / ### headings, **bold**, *italic*, ***bold-italic***,
// `code`, blockquotes (> ), bullet lists (- / *), horizontal rules (---).
// Tuned to render D&D-Beyond-style item blocks cleanly.
const renderMarkdown = (md) => {
  if (!md) return null;
  const lines = md.split('\n');
  const blocks = [];
  let i = 0;

  const inline = (s) => {
    // Order matters: triple → double → single asterisks; then code; then italic _.
    const parts = [];
    let rest = s;
    let key = 0;
    const re = /(\*\*\*([^*]+)\*\*\*)|(\*\*([^*]+)\*\*)|(\*([^*]+)\*)|(`([^`]+)`)/;
    while (rest) {
      const m = rest.match(re);
      if (!m) { parts.push(rest); break; }
      if (m.index > 0) parts.push(rest.slice(0, m.index));
      if (m[1]) parts.push(<strong key={key++}><em>{m[2]}</em></strong>);
      else if (m[3]) parts.push(<strong key={key++}>{m[4]}</strong>);
      else if (m[5]) parts.push(<em key={key++}>{m[6]}</em>);
      else if (m[7]) parts.push(<code key={key++} style={hbStyles.codeInline}>{m[8]}</code>);
      rest = rest.slice(m.index + m[0].length);
    }
    return parts;
  };

  while (i < lines.length) {
    const ln = lines[i];
    if (!ln.trim()) { i++; continue; }

    // Horizontal rule
    if (/^---+\s*$/.test(ln)) { blocks.push(<hr key={blocks.length} style={hbStyles.hr} />); i++; continue; }

    // Headings
    const hMatch = ln.match(/^(#{1,3})\s+(.*)$/);
    if (hMatch) {
      const level = hMatch[1].length;
      const text = hMatch[2];
      const styleMap = [hbStyles.h1, hbStyles.h2, hbStyles.h3];
      blocks.push(React.createElement(`h${level}`, { key: blocks.length, style: styleMap[level-1] }, inline(text)));
      i++; continue;
    }

    // Blockquote (consume consecutive > lines)
    if (/^>\s?/.test(ln)) {
      const buf = [];
      while (i < lines.length && /^>\s?/.test(lines[i])) {
        buf.push(lines[i].replace(/^>\s?/, ''));
        i++;
      }
      blocks.push(
        <blockquote key={blocks.length} style={hbStyles.quote}>
          {buf.map((b,j) => <div key={j}>{inline(b) || <br/>}</div>)}
        </blockquote>
      );
      continue;
    }

    // List
    if (/^[-*]\s+/.test(ln)) {
      const items = [];
      while (i < lines.length && /^[-*]\s+/.test(lines[i])) {
        items.push(lines[i].replace(/^[-*]\s+/, ''));
        i++;
      }
      blocks.push(
        <ul key={blocks.length} style={hbStyles.ul}>
          {items.map((it,j) => <li key={j} style={hbStyles.li}>{inline(it)}</li>)}
        </ul>
      );
      continue;
    }

    // Italic-only "subtitle" line directly under the title (e.g. *Weapon (longsword), rare*)
    if (/^\*[^*].*\*$/.test(ln) && !/\*\*/.test(ln)) {
      blocks.push(<p key={blocks.length} style={hbStyles.subtitle}>{inline(ln)}</p>);
      i++; continue;
    }

    // Paragraph (consume consecutive non-blank, non-special lines)
    const pBuf = [ln];
    i++;
    while (i < lines.length && lines[i].trim() && !/^(#|>|---|[-*]\s)/.test(lines[i])) {
      pBuf.push(lines[i]);
      i++;
    }
    blocks.push(<p key={blocks.length} style={hbStyles.p}>{inline(pBuf.join(' '))}</p>);
  }
  return blocks;
};

// ── Item Card (preview in list) ──────────────────────────────────────────────
const HBCard = ({ item, selected, onClick }) => {
  const rcol = HB_RARITY_COLOR[item.rarity] || '#6b6966';
  return (
    <div
      style={{...hbStyles.card, ...(selected ? hbStyles.cardActive : {}), borderLeftColor: rcol}}
      onClick={onClick}
    >
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:8}}>
        <div style={{flex:1,minWidth:0}}>
          <div style={hbStyles.cardName}>{item.name}</div>
          <div style={hbStyles.cardType}>{item.type}</div>
        </div>
      </div>
      <div style={{display:'flex',gap:6,marginTop:8,flexWrap:'wrap'}}>
        <span style={{...hbStyles.rarityChip, background: rcol+'22', color: rcol, borderColor: rcol+'55'}}>
          {item.rarity.replace('-',' ')}
        </span>
        {item.attunement && <span style={hbStyles.attuneChip}>attunement</span>}
        {(item.tags||[]).slice(0,3).map(t => (
          <span key={t} style={hbStyles.tagChip}>#{t}</span>
        ))}
      </div>
    </div>
  );
};

// ── Edit Modal — straight markdown editor for an existing item ───────────────
const EditItemModal = ({ item, onSave, onClose, onDelete }) => {
  const [md, setMd] = React.useState(item.markdown);
  const [meta, setMeta] = React.useState({
    name: item.name, type: item.type, rarity: item.rarity,
    attunement: !!item.attunement, tags: (item.tags||[]).join(', '),
    isPublic: item.isPublic !== false,
  });
  return (
    <div style={hbStyles.modalScrim} {...scrimDismiss(onClose)}>
      <div style={hbStyles.modalEdit} onClick={e=>e.stopPropagation()}>
        <div style={hbStyles.modalHeader}>
          <div style={{fontFamily:"'Cinzel',serif",fontSize:16,fontWeight:700,color:'#e8e6e3'}}>
            Edit Item
          </div>
          <button style={hbStyles.closeX} onClick={onClose}>✕</button>
        </div>
        <div style={{padding:18, display:'grid', gridTemplateColumns:'1fr 1fr', gap:18, overflow:'auto'}}>
          <div>
            <div style={hbStyles.formLabel}>Name<Req/></div>
            <input style={hbStyles.input} value={meta.name} onChange={e=>setMeta({...meta,name:e.target.value})}/>
            <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:10,marginTop:10}}>
              <div>
                <div style={hbStyles.formLabel}>Type</div>
                <input style={hbStyles.input} value={meta.type} onChange={e=>setMeta({...meta,type:e.target.value})}/>
              </div>
              <div>
                <div style={hbStyles.formLabel}>Rarity</div>
                <select style={hbStyles.select} value={meta.rarity} onChange={e=>setMeta({...meta,rarity:e.target.value})}>
                  {HB_RARITY_ORDER.map(r=><option key={r} value={r}>{r.replace('-',' ')}</option>)}
                </select>
              </div>
            </div>
            <label style={{display:'flex',alignItems:'center',gap:6,marginTop:10,fontSize:12,color:'#9a9793',cursor:'pointer'}}>
              <input type="checkbox" checked={meta.attunement} onChange={e=>setMeta({...meta,attunement:e.target.checked})} style={{accentColor:'var(--accent)'}}/>
              Requires attunement
            </label>
            <label style={{display:'flex',alignItems:'flex-start',gap:6,marginTop:10,fontSize:12,color:'#9a9793',cursor:'pointer'}}>
              <input type="checkbox" checked={meta.isPublic !== false} onChange={e=>setMeta({...meta, isPublic: e.target.checked})} style={{accentColor:'var(--accent)', marginTop:3}}/>
              <span><strong style={{color:'#e8e6e3'}}>Public</strong> — show in cross-campaign Homebrew Repository (uncheck to keep private to this campaign).</span>
            </label>
            <div style={{...hbStyles.formLabel,marginTop:10}}>Tags (comma-separated)</div>
            <input style={hbStyles.input} value={meta.tags} onChange={e=>setMeta({...meta,tags:e.target.value})}/>
            <div style={{...hbStyles.formLabel,marginTop:14}}>Markdown</div>
            <textarea
              style={{...hbStyles.textarea, minHeight:380, fontFamily:'monospace', fontSize:12, lineHeight:1.55}}
              value={md}
              onChange={e=>setMd(e.target.value)}
            />
          </div>
          <div style={{borderLeft:'1px solid #2a2a32',paddingLeft:18,minHeight:0,overflow:'auto'}}>
            <div style={{...hbStyles.formLabel, marginBottom:10}}>Preview</div>
            <div style={hbStyles.dndScroll}>
              {renderMarkdown(md)}
            </div>
          </div>
        </div>
        <div style={{padding:'12px 18px',borderTop:'1px solid #2a2a32',display:'flex',justifyContent:'space-between',alignItems:'center',background:'#16161b'}}>
          <button style={{...hbStyles.btnGhost,color:'#f87171',borderColor:'rgba(248,113,113,0.2)'}} onClick={onDelete}>Delete</button>
          <div style={{display:'flex',gap:8}}>
            <button style={hbStyles.btnGhost} onClick={onClose}>Cancel</button>
            <button style={hbStyles.btnPrimary} onClick={()=>onSave({...item, ...meta, tags: meta.tags.split(',').map(s=>s.trim()).filter(Boolean), markdown: md})}>Save</button>
          </div>
        </div>
      </div>
    </div>
  );
};

// ── Main Tab ─────────────────────────────────────────────────────────────────
const HomebrewTab = ({ campaign, isDM, user }) => {
  const [items, setItems] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [selectedId, setSelectedId] = React.useState(null);
  const [editing, setEditing] = React.useState(null);
  const [filter, setFilter] = React.useState('');
  const [rarityFilter, setRarityFilter] = React.useState('all');

  const refresh = React.useCallback(async () => {
    setLoading(true);
    try {
      const list = (await api.campaigns.homebrew.list(campaign.id)) || [];
      setItems(list);
      setSelectedId(curr => curr || list[0]?.id || null);
    } catch (err) {
      console.error('[HomebrewTab] load failed:', err);
    } finally {
      setLoading(false);
    }
  }, [campaign.id]);

  React.useEffect(() => { refresh(); }, [refresh]);

  const filtered = items.filter(it => {
    if (rarityFilter !== 'all' && it.rarity !== rarityFilter) return false;
    if (filter) {
      const q = filter.toLowerCase();
      return it.name.toLowerCase().includes(q) ||
             (it.tags||[]).some(t => t.toLowerCase().includes(q)) ||
             it.type.toLowerCase().includes(q);
    }
    return true;
  }).sort((a,b) => HB_RARITY_ORDER.indexOf(a.rarity) - HB_RARITY_ORDER.indexOf(b.rarity) || a.name.localeCompare(b.name));

  const selected = items.find(i => i.id === selectedId);

  const onSaveEdit = async (updated) => {
    const payload = {
      name: updated.name, type: updated.type, rarity: updated.rarity,
      attunement: !!updated.attunement, tags: updated.tags || [], markdown: updated.markdown || '',
      isPublic: updated.isPublic !== false,
    };
    try {
      if (items.find(i => i.id === updated.id)) {
        // existing item — PATCH
        await api.campaigns.homebrew.update(campaign.id, updated.id, payload);
      } else {
        // new item created via "+ Blank" — POST (id is a temporary client placeholder)
        const newId = await api.campaigns.homebrew.create(campaign.id, payload);
        setSelectedId(newId);
      }
      await refresh();
    } catch (err) {
      console.error('[HomebrewTab] save failed:', err);
      window.dialog.alert('Failed to save item: ' + (err.message || 'unknown error'));
    }
    setEditing(null);
  };

  const onDelete = async (id) => {
    if (!(await window.dialog.confirm({ title:'Delete item?', message:'Delete this item permanently?', danger:true, confirmLabel:'Delete' }))) return;
    try {
      await api.campaigns.homebrew.delete(campaign.id, id);
      await refresh();
      if (selectedId === id) setSelectedId(items.find(i => i.id !== id)?.id || null);
    } catch (err) {
      console.error('[HomebrewTab] delete failed:', err);
      window.dialog.alert('Failed to delete: ' + (err.message || 'unknown error'));
    }
    setEditing(null);
  };

  const onNewBlank = async () => {
    const payload = {
      name: 'New Item', type: 'Wondrous Item', rarity: 'common', attunement: false, tags: [],
      markdown: `# New Item\n*Wondrous item, common*\n\nA short flavor description.\n\n***Property.*** Mechanical effect.`,
    };
    try {
      const newId = await api.campaigns.homebrew.create(campaign.id, payload);
      await refresh();
      setSelectedId(newId);
      // Open editor on the freshly persisted item (refresh has just put it in items)
      setEditing({ id: newId, ...payload, authorId: user.id, authorName: user.name, createdAt: new Date().toISOString().slice(0,10) });
    } catch (err) {
      console.error('[HomebrewTab] new blank failed:', err);
      window.dialog.alert('Failed to create item: ' + (err.message || 'unknown error'));
    }
  };

  return (
    <div style={hbStyles.tab}>
      {/* LEFT — list */}
      <div style={hbStyles.leftCol}>
        <div style={hbStyles.leftHeader}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:10}}>
            <div style={{fontFamily:"'Cinzel',serif",fontSize:14,fontWeight:700,color:'#c9a227'}}>
              Homebrew Items
            </div>
            <div style={{fontSize:11,color:'#6b6966'}}>{items.length} total</div>
          </div>
          <input
            style={hbStyles.input}
            placeholder="Search by name, tag, type…"
            value={filter}
            onChange={e=>setFilter(e.target.value)}
          />
          <div style={{display:'flex',gap:4,marginTop:8,flexWrap:'wrap'}}>
            <button
              style={{...hbStyles.filterChip, ...(rarityFilter==='all'?hbStyles.filterChipActive:{})}}
              onClick={()=>setRarityFilter('all')}>all</button>
            {HB_RARITY_ORDER.map(r => (
              <button key={r}
                style={{...hbStyles.filterChip, ...(rarityFilter===r?{...hbStyles.filterChipActive, color: HB_RARITY_COLOR[r], borderColor: HB_RARITY_COLOR[r]+'88'}:{})}}
                onClick={()=>setRarityFilter(r)}>{r.replace('-',' ')}</button>
            ))}
          </div>
        </div>

        <div style={hbStyles.cardList}>
          {filtered.map(item => (
            <HBCard
              key={item.id}
              item={item}
              selected={selectedId === item.id}
              onClick={()=>setSelectedId(item.id)}
            />
          ))}
          {!filtered.length && (
            <div style={{padding:30,textAlign:'center',color:'#4a4a52',fontSize:12}}>
              No items match.
            </div>
          )}
        </div>

        {isDM && (
          <div style={hbStyles.leftFooter}>
            <button style={hbStyles.btnGhost} onClick={onNewBlank}>+ Blank</button>
          </div>
        )}
      </div>

      {/* RIGHT — preview */}
      <div style={hbStyles.rightCol}>
        {selected ? (
          <>
            <div style={hbStyles.rightHeader}>
              <div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap'}}>
                <span style={{...hbStyles.rarityChip, background: (HB_RARITY_COLOR[selected.rarity]||'#6b6966')+'22', color: HB_RARITY_COLOR[selected.rarity], borderColor: HB_RARITY_COLOR[selected.rarity]+'55'}}>
                  {selected.rarity.replace('-',' ')}
                </span>
                {selected.attunement && <span style={hbStyles.attuneChip}>requires attunement</span>}
                {(selected.tags||[]).map(t => (
                  <span key={t} style={hbStyles.tagChip}>#{t}</span>
                ))}
                <span style={{marginLeft:'auto',fontSize:11,color:'#6b6966'}}>
                  by {selected.authorName || '—'} · {selected.createdAt}
                </span>
              </div>
              {isDM && (
                <button style={hbStyles.btnGhost} onClick={()=>setEditing(selected)}>✎ Edit</button>
              )}
            </div>
            <div style={hbStyles.scrollArea}>
              <div style={hbStyles.dndScroll}>
                {renderMarkdown(selected.markdown)}
              </div>
              {(() => {
                // Backend stores forge provenance as JSON. Parse it; accept both the
                // current ForgeTab field names (crafter, assistant, …) and the legacy
                // mock names (crafterName, assistantName) for old rows.
                let m = null;
                try { m = JSON.parse(selected.forgeMetaJson || '{}'); } catch { m = null; }
                if (!m || Object.keys(m).length === 0) return null;
                const crafter = m.crafter || m.crafterName;
                const assistant = m.assistant || m.assistantName;
                if (!crafter && !m.fee && !m.roll) return null;
                return (
                <div style={{ marginTop:18, padding:'14px 16px', background:'#16161b', border:'1px solid #2a2a32', borderRadius:8, fontSize:12, color:'#9a9793' }}>
                  <div style={{ fontFamily:"'Cinzel',serif", fontSize:12, fontWeight:800, color:'#c9a227', textTransform:'uppercase', letterSpacing:'0.1em', marginBottom:8 }}>⚒ Forged at the Workshop</div>
                  <div style={{ display:'grid', gridTemplateColumns:'auto 1fr', gap:'4px 14px' }}>
                    {crafter && <><span style={{color:'#7a7873'}}>Crafter</span><span style={{color:'#e8e6e3'}}>{crafter}{assistant ? ` · with ${assistant}` : ''}</span></>}
                    {(m.cityName || m.guildName) && <><span style={{color:'#7a7873'}}>Location</span><span style={{color:'#e8e6e3'}}>{m.cityName || ''}{m.guildName ? ` (${m.guildName})` : ''}</span></>}
                    {m.facilityLevel && <><span style={{color:'#7a7873'}}>Facility</span><span style={{color:'#e8e6e3'}}>{m.facilityLevel} (+{m.facilityBonus})</span></>}
                    {m.fee != null && <><span style={{color:'#7a7873'}}>Fee paid</span><span style={{color:'#c9a227'}}>{m.fee} gp</span></>}
                    {m.roll && <><span style={{color:'#7a7873'}}>Roll</span><span style={{color:'#22c55e'}}>d20={m.roll.d20} + {m.roll.bonus} = {m.roll.total} vs DC {m.roll.dc}</span></>}
                    {(m.sourceItemIds||[]).length>0 && <><span style={{color:'#7a7873'}}>Source items</span><span style={{color:'#e8e6e3'}}>{m.sourceItemIds.length} consumed</span></>}
                    {(m.sourceMaterialIds||[]).length>0 && <><span style={{color:'#7a7873'}}>Materials</span><span style={{color:'#e8e6e3'}}>{m.sourceMaterialIds.length} used</span></>}
                  </div>
                  {m.narrative && <div style={{ marginTop:10, fontStyle:'italic', color:'#c5c3c0', lineHeight:1.55, borderTop:'1px solid #2a2a32', paddingTop:10 }}>"{m.narrative}"</div>}
                </div>
                );
              })()}
            </div>
          </>
        ) : (
          <div style={{display:'flex',alignItems:'center',justifyContent:'center',height:'100%',color:'#4a4a52',fontSize:13}}>
            Pick an item to view it.
          </div>
        )}
      </div>

      {editing && (
        <EditItemModal
          item={editing}
          onSave={onSaveEdit}
          onClose={()=>setEditing(null)}
          onDelete={()=>onDelete(editing.id)}
        />
      )}
    </div>
  );
};

// ── Styles ───────────────────────────────────────────────────────────────────
const hbStyles = {
  tab: {
    display:'grid',
    gridTemplateColumns:'320px 1fr',
    gap:0,
    height:'calc(100vh - 220px)',
    minHeight:500,
    background:'#16161b',
    border:'1px solid #2a2a32',
    borderRadius:8,
    overflow:'hidden',
    position:'relative',
  },
  leftCol: { display:'flex', flexDirection:'column', borderRight:'1px solid #2a2a32', minHeight:0, background:'#13131a' },
  leftHeader: { padding:'14px 14px 10px', borderBottom:'1px solid #2a2a32', flexShrink:0 },
  cardList: { flex:1, overflowY:'auto', padding:10, display:'flex', flexDirection:'column', gap:8 },
  leftFooter: { padding:10, borderTop:'1px solid #2a2a32', display:'flex', gap:6, flexShrink:0 },

  rightCol: { display:'flex', flexDirection:'column', minHeight:0, background:'#1a1a22' },
  rightHeader: {
    display:'flex', justifyContent:'space-between', alignItems:'center',
    padding:'12px 18px', borderBottom:'1px solid #2a2a32',
    background:'#16161b', flexShrink:0, gap:12,
  },
  scrollArea: { flex:1, overflowY:'auto', padding:'24px 28px' },

  card: {
    background:'#1c1c22',
    border:'1px solid #2a2a32',
    borderLeft:'3px solid #6b6966',
    borderRadius:6,
    padding:'10px 12px',
    cursor:'pointer',
    transition:'all 0.12s',
  },
  cardActive: {
    background:'#22222b',
    borderColor:'#3a3a42',
    boxShadow:'0 0 0 1px rgba(201,162,39,0.18)',
  },
  cardName: { fontFamily:"'Cinzel',serif", fontSize:13, fontWeight:700, color:'#e8e6e3', lineHeight:1.3 },
  cardType: { fontSize:11, color:'#9a9793', fontStyle:'italic', marginTop:2 },

  rarityChip: {
    fontSize:10, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.06em',
    padding:'2px 7px', borderRadius:3, border:'1px solid',
  },
  attuneChip: {
    fontSize:10, color:'#c9a227', background:'rgba(201,162,39,0.1)',
    border:'1px solid rgba(201,162,39,0.3)', padding:'2px 7px', borderRadius:3,
    fontStyle:'italic',
  },
  tagChip: {
    fontSize:10, color:'#7a7873', background:'#0d0d12',
    border:'1px solid #2a2a32', padding:'2px 6px', borderRadius:3,
  },

  filterChip: {
    fontSize:10, fontWeight:600, textTransform:'lowercase',
    background:'#0d0d12', color:'#7a7873',
    border:'1px solid #2a2a32', borderRadius:3,
    padding:'3px 7px', cursor:'pointer',
    fontFamily:"'Nunito',sans-serif",
  },
  filterChipActive: { background:'#1c1c22', color:'#e8e6e3', borderColor:'#4a4a52' },

  input: {
    width:'100%', background:'#0d0d12',
    border:'1px solid #2a2a32', borderRadius:4,
    padding:'6px 10px', color:'#e8e6e3',
    fontSize:12, fontFamily:"'Nunito',sans-serif",
  },
  select: {
    width:'100%', background:'#0d0d12',
    border:'1px solid #2a2a32', borderRadius:4,
    padding:'6px 10px', color:'#e8e6e3',
    fontSize:12, fontFamily:"'Nunito',sans-serif",
  },
  textarea: {
    width:'100%', background:'#0d0d12',
    border:'1px solid #2a2a32', borderRadius:4,
    padding:'8px 10px', color:'#e8e6e3',
    fontSize:13, lineHeight:1.5, resize:'vertical',
    fontFamily:"'Nunito',sans-serif",
  },
  formLabel: {
    fontSize:10, fontWeight:800, color:'#6b6966',
    textTransform:'uppercase', letterSpacing:'0.12em',
    marginBottom:6,
  },

  // D&D Beyond-ish item card
  dndScroll: {
    background:'#1c1c22',
    border:'1px solid #2a2a32',
    borderRadius:4,
    padding:'24px 28px',
    color:'#d6d3ce',
    fontFamily:"'Nunito',sans-serif",
    fontSize:14,
    lineHeight:1.65,
    boxShadow:'inset 0 1px 0 rgba(255,255,255,0.02)',
    position:'relative',
  },
  h1: {
    fontFamily:"'Cinzel',serif",
    fontSize:24, fontWeight:700, color:'#c9a227',
    marginBottom:4, letterSpacing:'0.01em',
    borderBottom:'2px solid rgba(201,162,39,0.4)',
    paddingBottom:6,
  },
  h2: {
    fontFamily:"'Cinzel',serif",
    fontSize:18, fontWeight:700, color:'#e8e6e3',
    marginTop:18, marginBottom:6,
  },
  h3: {
    fontFamily:"'Cinzel',serif",
    fontSize:15, fontWeight:700, color:'#c9a227',
    marginTop:14, marginBottom:4,
  },
  subtitle: {
    fontStyle:'italic', color:'#9a9793', fontSize:13,
    marginTop:0, marginBottom:14,
  },
  p: { marginTop:0, marginBottom:10 },
  ul: { marginTop:6, marginBottom:10, paddingLeft:22 },
  li: { marginBottom:4 },
  hr: { border:'none', borderTop:'1px solid #2a2a32', margin:'14px 0' },
  quote: {
    margin:'14px 0 0',
    paddingLeft:14,
    borderLeft:'3px solid rgba(201,162,39,0.4)',
    color:'#9a9793',
    fontStyle:'italic',
    fontSize:13,
    lineHeight:1.6,
  },
  codeInline: {
    background:'#0d0d12', border:'1px solid #2a2a32',
    borderRadius:3, padding:'1px 5px', fontFamily:'monospace', fontSize:12,
  },

  // Forge dock
  forgeDock: {
    position:'absolute',
    left:'50%', bottom:14, transform:'translateX(-50%)',
    background:'#1c1c22',
    border:'1px solid var(--accent)',
    borderRadius:8,
    padding:'10px 14px',
    boxShadow:'0 8px 32px rgba(0,0,0,0.5), 0 0 0 1px rgba(201,162,39,0.1)',
    display:'flex', alignItems:'center', gap:14,
    zIndex:50,
  },
  dockChip: {
    fontSize:10, padding:'2px 6px',
    background:'#0d0d12', border:'1px solid #2a2a32',
    borderRadius:3,
  },

  // Modals
  modalScrim: {
    position:'fixed', inset:0,
    background:'rgba(8,8,12,0.85)',
    display:'flex', alignItems:'center', justifyContent:'center',
    zIndex:200, padding:24, backdropFilter:'blur(2px)',
  },
  modalForge: {
    background:'#13131a',
    border:'1px solid #3a3a42',
    borderRadius:10,
    width:'100%', maxWidth:1100, height:'min(85vh, 760px)',
    display:'flex', flexDirection:'column',
    boxShadow:'0 20px 60px rgba(0,0,0,0.7)',
    overflow:'hidden',
  },
  modalEdit: {
    background:'#13131a',
    border:'1px solid #3a3a42',
    borderRadius:10,
    width:'100%', maxWidth:1100, height:'min(85vh, 760px)',
    display:'flex', flexDirection:'column',
    boxShadow:'0 20px 60px rgba(0,0,0,0.7)',
    overflow:'hidden',
  },
  modalHeader: {
    display:'flex', justifyContent:'space-between', alignItems:'center',
    padding:'14px 18px', borderBottom:'1px solid #2a2a32',
    background:'#16161b', flexShrink:0,
  },
  closeX: {
    background:'none', border:'none', color:'#6b6966', cursor:'pointer',
    fontSize:18, padding:4, lineHeight:1,
  },
  forgeBody: {
    display:'grid', gridTemplateColumns:'320px 1fr',
    flex:1, minHeight:0,
  },
  forgeLeft: {
    padding:18, borderRight:'1px solid #2a2a32',
    overflowY:'auto', display:'flex', flexDirection:'column',
  },
  forgePreview: {
    padding:18, overflowY:'auto', display:'flex', flexDirection:'column', minHeight:0,
  },
  forgeEmpty: {
    flex:1, display:'flex', flexDirection:'column',
    alignItems:'center', justifyContent:'center',
  },
  forgeFooter: {
    display:'flex', justifyContent:'space-between', alignItems:'center',
    paddingTop:14, marginTop:14, borderTop:'1px solid #2a2a32',
  },
  modePill: {
    flex:1, background:'#0d0d12', border:'1px solid #2a2a32',
    borderRadius:4, padding:'6px 10px', color:'#9a9793', cursor:'pointer',
    fontSize:12, fontWeight:600, fontFamily:"'Nunito',sans-serif",
  },
  modePillActive: {
    background:'rgba(201,162,39,0.12)', borderColor:'var(--gold)', color:'#e8e6e3',
  },
  sourcePill: {
    display:'flex', alignItems:'center', gap:8,
    background:'#0d0d12', border:'1px solid #2a2a32',
    borderRadius:4, padding:'6px 10px',
    fontSize:12, color:'#c5c3c0',
  },
  forgeBtn: {
    marginTop:'auto', paddingTop:18,
    background:'var(--accent)', color:'#fff',
    border:'none', borderRadius:5,
    padding:'10px 16px',
    fontSize:13, fontWeight:700, fontFamily:"'Cinzel',serif",
    letterSpacing:'0.04em', cursor:'pointer',
    boxShadow:'0 4px 12px rgba(197,48,48,0.3)',
  },

  btnPrimary: {
    background:'var(--accent)', color:'#fff', border:'none',
    borderRadius:4, padding:'7px 14px',
    fontSize:12, fontWeight:700, cursor:'pointer',
    fontFamily:"'Nunito',sans-serif",
  },
  btnGhost: {
    background:'transparent', color:'#9a9793',
    border:'1px solid #3a3a42', borderRadius:4,
    padding:'6px 12px', fontSize:12, cursor:'pointer',
    fontFamily:"'Nunito',sans-serif",
  },
};

// Pulse animation for forge spinner
if (!document.getElementById('hb-keyframes')) {
  const s = document.createElement('style');
  s.id = 'hb-keyframes';
  s.textContent = `@keyframes pulse { 0%,100% { opacity: 0.4; transform: scale(1); } 50% { opacity: 0.8; transform: scale(1.05); } }`;
  document.head.appendChild(s);
}

Object.assign(window, { HomebrewTab, hbStyles, renderMarkdown });
