/* ============================================================================
   MATRIA, screens, part 2.
   Answer, KnowledgeMapScreen, ConnectedWomen, MythsHistories, FromMatria,
   SourceDetail, Explore, Paths, Sanctuary, Suggest.
   ============================================================================ */

function TopBar({title, onBack, dark, right}){
  return (
    <div className="pad" style={{display:'flex',alignItems:'center',justifyContent:'space-between',paddingTop:6,flex:'none',height:34}}>
      <button onClick={onBack} aria-label="Back" style={{background:'none',border:'none',padding:0,cursor:'pointer',color:dark?'var(--ctext)':'var(--ink)'}}><Icon name="back" size={22}/></button>
      {title? <span className="label">{title}</span> : <span/>}
      {right||<span style={{width:22}}/>}
    </div>
  );
}

/* 8, Answer (editorial card + explore deeper) */
function Answer({ctx}){
  const D=window.MATRIA;
  const S=useMStore();
  const q=ctx.q;
  const saved=S.isSaved(q.id);
  const [sourcesOpen,setSourcesOpen]=React.useState(false);
  return (
    <div className="screen dark matria-dark answer-screen">
      <StatusBar/>
      <div className="answer-toolbar pad">
        <button type="button" className="answer-toolbar__btn" onClick={()=>ctx.back()} aria-label="Back">
          <Icon name="back" size={18}/>
        </button>
        <div className="answer-toolbar__actions">
          <button type="button" className="answer-toolbar__btn" onClick={()=>S.toggleSaved(q.id,q.text)} aria-label={saved?'Remove bookmark':'Save answer'}>
            <Icon name="bookmark" size={18} stroke={saved?2.2:1.4}/>
          </button>
          <button type="button" className="answer-toolbar__btn" onClick={()=>ctx.nav('FromMatria')} aria-label="More options">
            <Icon name="more" size={18}/>
          </button>
        </div>
      </div>
      <div className="s-body pad answer-screen__body">
        <div className="answer-screen__question-block">
          <div className="label answer-screen__eyebrow">Your question</div>
          <h1 className="answer-question">{q.text}</h1>
        </div>
        <div className="answer-screen__reflection-intro">
          <div className="label answer-screen__eyebrow">From Matria</div>
          <p className="answer-screen__editorial-note">Editorial reading of the archive. Open any woman below for sources.</p>
        </div>
        <AnswerEditorialCard q={q} onOpenSources={()=>setSourcesOpen(true)}/>
        <AnswerExploreDeeper ctx={ctx}/>
      </div>
      {sourcesOpen && <AnswerSourcesSheet q={q} onClose={()=>setSourcesOpen(false)} onOpen={id=>{setSourcesOpen(false);ctx.openSource(id);}}/>}
      <TabBar active="Ask" onNav={ctx.nav}/>
    </div>
  );
}

function MapPreview({q, onOpen, onOpenNode}){
  const D=window.MATRIA;
  const nodeIds=(q.nodes||[]).slice(0,9);
  const women=(q.women||[]).slice(0,3).map(id=>D.get(id)).filter(Boolean);
  const slideCount=1+women.length;
  const trackRef=React.useRef(null);
  const [active,setActive]=React.useState(0);
  function syncActive(){
    const el=trackRef.current;
    if(!el||!el.children.length) return;
    const pad=24;
    let best=0,bestDist=Infinity;
    [...el.children].forEach((child,i)=>{
      const dist=Math.abs(child.offsetLeft-el.scrollLeft-pad);
      if(dist<bestDist){bestDist=dist;best=i;}
    });
    setActive(best);
  }
  React.useEffect(()=>{
    const el=trackRef.current;
    if(!el) return;
    syncActive();
    el.addEventListener('scroll',syncActive,{passive:true});
    return ()=>el.removeEventListener('scroll',syncActive);
  },[slideCount]);
  return (
    <div className="answer-map-carousel" aria-roledescription="carousel" aria-label="Knowledge map and lineage">
      <div className="answer-map-carousel__track" ref={trackRef}>
        <div className="answer-map-carousel__slide">
          <button type="button" className="answer-map-preview" onClick={onOpen} aria-label="Open knowledge map">
            <img className="answer-map-preview__bg" src="uploads/matria-constellation-bg.png" alt="" aria-hidden="true"/>
            <span className="answer-map-preview__veil" aria-hidden="true"/>
            <div className="answer-map-preview__map" aria-hidden="true">
              <KnowledgeMap question={q.text} nodeIds={nodeIds} variant="preview"/>
            </div>
            <span className="answer-map-preview__label">Knowledge Map</span>
            <span className="answer-map-preview__cta">Open map <Icon name="chevron" size={13}/></span>
          </button>
        </div>
        {women.map(n=>(
          <div key={n.id} className="answer-map-carousel__slide">
            <button type="button" className="answer-map-node" onClick={()=>onOpenNode(n.id)} aria-label={'Open source for '+n.title}>
              <img className="answer-map-node__bg" src="uploads/matria-constellation-bg.png" alt="" aria-hidden="true"/>
              <span className="answer-map-node__veil" aria-hidden="true"/>
              <div className="answer-map-node__portrait">
                <Portrait pic={n.pic} id={n.id} name={n.title} size={56}/>
              </div>
              <div className="answer-map-node__copy">
                <span className="answer-map-node__name">{n.title}</span>
                <span className="answer-map-node__role">{n.role||D.TYPES[n.type].label}</span>
              </div>
              <span className="answer-map-node__cta">Open source <Icon name="chevron" size={13}/></span>
            </button>
          </div>
        ))}
      </div>
      {slideCount>1 && (
        <div className="answer-map-carousel__foot" aria-hidden="true">
          <div className="answer-map-carousel__dots">
            {Array.from({length:slideCount}).map((_,i)=><i key={i} className={i===active?'on':''}/>)}
          </div>
          <span className="answer-map-carousel__count">{active+1} of {slideCount}</span>
        </div>
      )}
    </div>
  );
}

function reflectionLeadAndBody(text){
  if(!text) return {lead:'',body:[]};
  const sentences=text.match(/[^.!?]+[.!?]+(?:\s|$)|[^.!?]+$/g)||[text];
  const lead=sentences.slice(0,2).join(' ').trim();
  const rest=sentences.slice(2);
  const body=[];
  for(let i=0;i<rest.length;i+=2) body.push(rest.slice(i,i+2).join(' ').trim());
  return {lead,body:body.filter(Boolean)};
}

function answerSourceIds(q){
  return [...new Set([...(q.women||[]), ...(q.myths||[]), ...(q.ideas||[])])];
}

function answerSourceLine(q){
  const D=window.MATRIA;
  const sources=answerSourceIds(q).map(id=>D.get(id)).filter(Boolean);
  const names=sources.slice(0,2).map(n=>n.title);
  const more=Math.max(0,sources.length-2);
  if(!names.length) return 'Archive sources';
  return more? names.join(' • ')+' • +'+more+' more' : names.join(' • ');
}

function AnswerEditorialCard({q, onOpenSources, compact, readOnly}){
  const D=window.MATRIA;
  const {lead,body}=reflectionLeadAndBody(reflectionText(q));
  const women=(q.women||[]).map(id=>D.get(id)).filter(n=>n&&n.type==='person').slice(0,2);
  return (
    <article className={'answer-card'+(compact?' answer-card--compact':'')}>
      <span className="answer-card__quote-mark" aria-hidden="true">&ldquo;</span>
      {lead && <p className="answer-card__lead">{lead}</p>}
      {body.length>0 && (
        <div className="answer-card__rule" aria-hidden="true">
          <span className="answer-card__rule-line"/>
          <Icon name="explore" size={11}/>
          <span className="answer-card__rule-line"/>
        </div>
      )}
      {body.map((p,i)=><p key={i} className="answer-card__body">{p}</p>)}
      <button type="button" className="answer-card__sources" onClick={readOnly?undefined:onOpenSources} disabled={readOnly} aria-disabled={readOnly}>
        <div className="answer-card__avatars">
          {women.map(n=>(
            <span key={n.id} className="answer-card__avatar"><Portrait pic={n.pic} id={n.id} name={n.title} size={28}/></span>
          ))}
        </div>
        <div className="answer-card__source-copy">
          <span className="answer-card__source-label">Sourced from the archive</span>
          <span className="answer-card__source-names">{answerSourceLine(q)}</span>
        </div>
        <span className="answer-card__source-chevron"><Icon name="chevron" size={15}/></span>
      </button>
    </article>
  );
}

function AnswerExploreDeeper({ctx}){
  return (
    <div className="answer-deeper">
      <p className="answer-deeper__prompt"><Icon name="explore" size={13}/>Would you like to explore this deeper?</p>
      <div className="hscroll answer-deeper__pills">
        <button type="button" className="answer-deeper__pill" onClick={()=>ctx.nav('Letters')}>
          <Icon name="letters" size={15}/><span>Related letters</span>
        </button>
        <button type="button" className="answer-deeper__pill" onClick={()=>ctx.openQuestionMap()}>
          <Icon name="constellation" size={15}/><span>Explore map</span>
        </button>
        <button type="button" className="answer-deeper__pill" onClick={()=>ctx.nav('Ask')}>
          <Icon name="plus" size={15}/><span>Ask a follow-up</span>
        </button>
      </div>
    </div>
  );
}

function AnswerSourcesSheet({q, onClose, onOpen}){
  const D=window.MATRIA;
  const sourceNodes=answerSourceIds(q).map(D.get).filter(n=>n&&n.sources);
  return (
    <div className="sheet-backdrop" onClick={onClose}>
      <div className="sheet" onClick={e=>e.stopPropagation()}>
        <div className="sheet-handle"/>
        <div className="sheet-head">
          <div>
            <div className="label">Sources · {sourceNodes.length}</div>
            <div style={{fontSize:10.5,color:'var(--ctext-faint)',marginTop:3}}>Every answer is drawn only from the archive.</div>
          </div>
          <button type="button" className="sheet-close" onClick={onClose}>✕</button>
        </div>
        <div className="sheet-scroll">
          {sourceNodes.map((n,i)=>(
            <div key={n.id} style={{display:'flex',alignItems:'center',gap:13,padding:'12px 0',borderBottom:i<sourceNodes.length-1?'1px solid var(--line-dark)':'none',cursor:'pointer'}} onClick={()=>onOpen(n.id)}>
              {n.type==='person'
                ? <Portrait pic={n.pic} id={n.id} name={n.title} size={38}/>
                : <TypeMedallion type={n.type} conceptId={n.id} size={38}/>}
              <div style={{flex:1,minWidth:0}}>
                <div style={{fontFamily:'var(--font-display)',fontSize:14.5,color:'var(--ctext)',fontWeight:600}}>{n.title}</div>
                <div style={{fontSize:11,color:'var(--ctext-soft)',marginTop:2,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{n.sources[0]}</div>
              </div>
              <span style={{color:'var(--ctext-faint)'}}><Icon name="chevron" size={14}/></span>
            </div>
          ))}
        </div>
        <div className="sheet-foot">
          <button type="button" className="btn btn-ghost-dark" style={{height:42,fontSize:13}} onClick={onClose}>Close</button>
        </div>
      </div>
    </div>
  );
}

function reflectionText(q){
  if(q && q._authored && q.reflection) return q.reflection;
  const D=window.MATRIA;
  const women=(q.women||[]).map(id=>D.get(id)).filter(Boolean).slice(0,2);
  const ideas=(q.ideas||[]).map(id=>D.get(id)?.title).filter(Boolean).slice(0,3);
  const names=women.map(n=>n.title).join(women.length>1?' and ':'');
  const ideaText=ideas.length ? ideas.map(s=>s.toLowerCase()).join(', ').replace(/, ([^,]*)$/, ' and $1') : 'this question';
  if(!names) return q.reflection;
  return `Almost no question is asked alone. In the archive, ${names} ${women.length===1?'is':'are'} among the voices turning toward ${ideaText}. They do not resolve the question for you. They keep you company inside it, with sources you can open.`;
}

function reflectionParagraphs(text){
  if(!text) return [];
  const sentences=text.match(/[^.!?]+[.!?]+(?:\s|$)|[^.!?]+$/g)||[text];
  const paras=[];
  for(let i=0;i<sentences.length;i+=2){
    paras.push(sentences.slice(i,i+2).join(' ').trim());
  }
  return paras.filter(Boolean);
}

function ReflectionCopy({q, style, className=''}){
  const text=reflectionText(q);
  const paras=reflectionParagraphs(text);
  return (
    <div className={'answer-reflection '+className} style={style}>
      {paras.map((p,i)=>(
        <p key={i} className={'answer-reflection__p'+(i===0?' answer-reflection__p--lead':'')}>{p}</p>
      ))}
    </div>
  );
}

function carryText(q){
  if(q && q._authored && q.carry) return q.carry;
  return 'What changes if you live alongside this question today, instead of forcing it to be solved?';
}

function practiceText(q){
  if(q && q._authored && q.practice) return q.practice;
  if(!q || /Take ten slow breaths with this question/i.test(q.practice||'')){
    return 'Choose one source named in this answer. Open it, read its context and source line, then write one sentence about what it changes in the question.';
  }
  return q.practice;
}

function nodeHasVerbatimQuote(n){
  return !!(n && n._quoteCleared==='cleared' && n.quotes && n.quotes.length);
}

function NodeVoicePanel({n, dark}){
  if(!n) return null;
  const verbatim=nodeHasVerbatimQuote(n);
  const matriaVoice=n.context;
  const ink=dark?'var(--ctext)':'var(--ink)';
  const soft=dark?'var(--ctext-soft)':'var(--ink-soft)';
  const faint=dark?'var(--ctext-faint)':'var(--ink-faint)';
  if(!verbatim && !matriaVoice){
    return <p className="bodytext" style={{fontStyle:'italic',color:soft}}>No sourced line is shown here yet. Open About, or read her works directly.</p>;
  }
  return <>
    {verbatim && <>
      <div className="label">In her words</div>
      <p className="meta voice-tab-note" style={{color:faint}}>Short attributed line from a published source.</p>
      {n.quotes.map(q=><p key={q} className="quote-text" style={{color:ink,margin:'0 0 10px'}}>{q}</p>)}
      {n.sources && n.sources[0] && <p className="meta" style={{color:faint,margin:'0 0 14px'}}>{n.sources[0]}</p>}
    </>}
    {matriaVoice && <>
      <div className="label" style={{marginTop:verbatim?14:0}}>From Matria</div>
      <p className="meta voice-tab-note" style={{color:faint}}>Editorial reading of the archive, not a verbatim quotation.</p>
      <p className="bodytext" style={{color:dark?'var(--ctext)':undefined}}>{n.context}</p>
    </>}
  </>;
}

/* 9, Knowledge Map screen */
function KnowledgeMapScreen({ctx}){
  const D=window.MATRIA;
  const q=ctx.q;
  const anchor=ctx.mapAnchor;
  const anchored=anchor&&D.mapNodesFor?D.mapNodesFor(anchor):null;
  const center=anchored?anchored.center:q.text;
  const ringIds=anchored?anchored.nodes.slice(0,9):q.nodes.slice(0,9);
  const mapKey=anchor||q.id;
  const [filter,setFilter]=useState({});
  const [showFilter,setShowFilter]=useState(false);
  const [legend,setLegend]=useState(false);
  const [traceOpen,setTraceOpen]=useState(true);
  return (
    <div className="screen dark matria-dark">
      <StatusBar/>
      <div className="pad" style={{display:'flex',alignItems:'flex-start',justifyContent:'space-between',paddingTop:6,flex:'none'}}>
        <div style={{display:'flex',gap:10,alignItems:'flex-start'}}>
          <button onClick={()=>ctx.back()} style={{background:'none',border:'none',padding:0,marginTop:4,cursor:'pointer',color:'var(--ctext)'}}><Icon name="back" size={22}/></button>
          <div>
            <h1 className="title">Knowledge Map</h1>
            <p className="lead" style={{marginTop:4,maxWidth:200}}>Women carrying themes across time. Tap once to focus, tap again to open.</p>
          </div>
        </div>
        <span style={{color:'var(--gold)',marginTop:4}}><Icon name="bell" size={20}/></span>
      </div>
      <div className="kmap-stage">
        <ConstellationBackground dim={0.42}/>
        <KnowledgeMap key={mapKey} question={center} nodeIds={ringIds} onOpenNode={ctx.openNode}
          variant="mobile" filterState={filter} onFilterChange={k=>setFilter(f=>({...f,[k]:!f[k]}))} legendOpen={legend} onLegendClose={()=>setLegend(false)} traceOpen={traceOpen}/>
        <p className="kmap-hint" style={{top:6}}>Tap a woman to open · Threads show shared themes · drag · pinch or +/− to zoom</p>
        {showFilter && <FilterPanel types={D.TYPES} state={filter} onChange={k=>setFilter(f=>({...f,[k]:!f[k]}))} onClose={()=>setShowFilter(false)}/>}
        {!showFilter && !legend && (
          <div className="kmap-toolbelt" aria-label="Knowledge Map tools">
            <button className="kmap-tool" onClick={()=>ctx.nav('ArchivePrimer')} aria-label="How the Knowledge Map works"><Icon name="journal" size={16}/><span>Guide</span></button>
            <button className={'kmap-tool'+(traceOpen?' kmap-tool--on':'')} onClick={()=>setTraceOpen(t=>!t)} aria-label="Toggle connection threads" aria-pressed={traceOpen}><Icon name="paths" size={17}/><span>Threads</span></button>
            <button className="kmap-tool" onClick={()=>setShowFilter(true)} aria-label="Filter map nodes"><Icon name="filter" size={17}/><span>Filter</span></button>
            <button className="kmap-tool" onClick={()=>setLegend(l=>!l)} aria-label="Open map legend"><Icon name="legend" size={17}/><span>Legend</span></button>
          </div>
        )}
      </div>
    </div>
  );
}

/* Your Constellation, a private, growing map of the women you follow, with the
   real connections among them revealed. The retention artifact. */
function YourConstellation({ctx}){
  const D=window.MATRIA; const S=useMStore();
  const follows=S.get().follows.filter(id=>D.get(id));
  const [filter,setFilter]=useState({});
  const [legend,setLegend]=useState(false);
  const [traceOpen,setTraceOpen]=useState(true);
  if(follows.length===0){
    return (
      <div className="screen dark has-constellation-bg">
        <ConstellationBackground dim={0.76}/>
        <StatusBar/>
        <TopBar onBack={()=>ctx.back()} dark/>
        <div className="s-body pad constellation-foreground" style={{display:'flex',flexDirection:'column',alignItems:'center',textAlign:'center',paddingTop:10}}>
          <div className="constellation-empty-art" aria-hidden="true">
            <span className="constellation-empty-art__glow"/>
            <img className="constellation-empty-art__planet" src="uploads/matria-constellation-planet.png" alt=""/>
          </div>
          <h1 className="title" style={{marginTop:18}}>Your constellation<br/>is still dark.</h1>
          <p className="bodytext" style={{margin:'14px auto 0',maxWidth:250,color:'var(--ctext-soft)'}}>Follow a woman, tap Follow Lineage on any source, and she joins your sky. As you gather them, the threads between them appear.</p>
          <div style={{flex:1,minHeight:16}}/>
          <button className="btn btn-tan" style={{width:'100%',marginBottom:'calc(16px + env(safe-area-inset-bottom))'}} onClick={()=>ctx.nav('Explore')}>Find a woman to follow</button>
        </div>
      </div>
    );
  }
  const vis=new Set(follows);
  const women=follows.filter(id=>D.get(id).type==='person').length;
  const threads=D.linksFor(follows).length + (D.RELATIONS||[]).filter(r=>vis.has(r.a)&&vis.has(r.b)).length;
  return (
    <div className="screen dark has-constellation-bg" style={{display:'flex',flexDirection:'column'}}>
      <ConstellationBackground dim={0.68}/>
      <StatusBar/>
      <div className="pad constellation-foreground" style={{display:'flex',alignItems:'flex-start',justifyContent:'space-between',paddingTop:6,flex:'none'}}>
        <div style={{display:'flex',gap:10,alignItems:'flex-start'}}>
          <button onClick={()=>ctx.back()} style={{background:'none',border:'none',padding:0,marginTop:4,cursor:'pointer',color:'var(--ctext)'}}><Icon name="back" size={22}/></button>
          <div>
            <h1 className="title">Your Constellation</h1>
            <p className="lead" style={{marginTop:4,maxWidth:230}}>{women} {women===1?'woman':'women'} you follow{threads>0?', '+threads+(threads===1?' thread':' threads')+' between them':''}. It grows as you gather them.</p>
          </div>
        </div>
      </div>
      <div className="constellation-foreground" style={{flex:1,position:'relative',minHeight:0,display:'flex',flexDirection:'column'}}>
        <div className="kmap-stage">
          <KnowledgeMap question={"Your\nconstellation"} nodeIds={follows} onOpenNode={ctx.openSource}
            variant="mobile" filterState={filter} onFilterChange={k=>setFilter(f=>({...f,[k]:!f[k]}))} legendOpen={legend} onLegendClose={()=>setLegend(false)} traceOpen={traceOpen}/>
          <p className="kmap-hint" style={{top:6}}>Tap a woman to open · Threads show shared themes · drag · pinch or +/− to zoom</p>
          {!legend && (
            <div className="kmap-toolbelt" aria-label="Constellation tools">
              <button className="kmap-tool" onClick={()=>ctx.nav('Explore')} aria-label="Add women to your constellation"><Icon name="plus" size={17}/><span>Add</span></button>
              <button className={'kmap-tool'+(traceOpen?' kmap-tool--on':'')} onClick={()=>setTraceOpen(t=>!t)} aria-label="Toggle connection threads" aria-pressed={traceOpen}><Icon name="paths" size={17}/><span>Threads</span></button>
              <button className="kmap-tool" onClick={()=>setLegend(l=>!l)} aria-label="Open constellation legend"><Icon name="legend" size={17}/><span>Legend</span></button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

/* 10, Connected Women */
function ConnectedWomen({ctx}){
  const D=window.MATRIA; const q=ctx.q;
  const cats={All:()=>true, Writers:n=>/Writer|Poet/.test(n.role), Thinkers:n=>/thinker|theorist|Scholar|Philosopher|scholar/.test(n.role), Leaders:n=>n.type==='political'||/activist|Activist/.test(n.role), Scientists:n=>/Astronomer|scientist/.test(n.role)};
  const [cat,setCat]=useState('All');
  const women=q.women.map(D.get).filter(n=>n&&cats[cat](n));
  return (
    <div className="screen dark matria-dark">
      <StatusBar/>
      <div className="s-body" style={{paddingBottom:8}}>
        <div className="pad matria-section" style={{paddingTop:8}}>
          <div style={{display:'flex',alignItems:'flex-start',justifyContent:'space-between'}}>
            <button onClick={()=>ctx.back()} style={{background:'none',border:'none',padding:0,marginTop:6,cursor:'pointer',color:'var(--ink)'}}><Icon name="back" size={20}/></button>
            <div style={{flex:1,marginLeft:12}}>
              <h1 className="title">Connected Women</h1>
              <p className="lead" style={{marginTop:6}}>Women in conversation with this question.</p>
            </div>
          </div>
          <div className="chip-row section-controls">
            {Object.keys(cats).map(c=><button key={c} className={'chip'+(c===cat?' on':'')} onClick={()=>setCat(c)}>{c}</button>)}
          </div>
          <div className="matria-list matria-section__content">
          {women.map(n=>(
            <div key={n.id} className="lrow" style={{padding:10}} onClick={()=>ctx.openSource(n.id)}>
              <Portrait pic={n.pic} id={n.id} name={n.title} size={52} round={false} radius={9}/>
              <div style={{flex:1}}>
                <div className="section-title" style={{fontFamily:'var(--font-display)',fontSize:15.5,color:'var(--ink)',fontWeight:600}}>{n.title}</div>
                <div className="meta" style={{color:'var(--ink-soft)',marginTop:2}}>{n.role}</div>
                <div className="meta" style={{fontSize:11,color:'var(--ink-faint)',marginTop:1}}>{n.region} · {n.period}</div>
              </div>
            </div>
          ))}
          </div>
        </div>
        <div className="scrollfade"/>
      </div>
      <TabBar active="Explore" onNav={ctx.nav}/>
    </div>
  );
}

/* 11, Myths & Histories */
function MythsHistories({ctx}){
  const D=window.MATRIA; const q=ctx.q;
  const tabs={Myths:n=>n.type==='myth', History:n=>n.type==='history', Movements:n=>n.type==='political', Cultures:n=>n.type==='tradition'};
  const [tab,setTab]=useState('Myths');
  const list=(tab==='Myths'?q.myths:Object.keys(D.NODES).filter(id=>tabs[tab](D.NODES[id]))).map(D.get).filter(Boolean);
  return (
    <div className="screen dark matria-dark">
      <StatusBar/>
      <div className="s-body" style={{paddingBottom:8}}>
        <div className="pad matria-section" style={{paddingTop:8}}>
          <div style={{display:'flex',alignItems:'flex-start',justifyContent:'space-between'}}>
            <button onClick={()=>ctx.back()} style={{background:'none',border:'none',padding:0,marginTop:6,cursor:'pointer',color:'var(--ink)'}}><Icon name="back" size={20}/></button>
            <div style={{flex:1,marginLeft:12}}>
              <h1 className="title">Myths & Histories</h1>
              <p className="lead" style={{marginTop:6}}>Stories and traditions that speak to this theme.</p>
            </div>
          </div>
          <div className="chip-row section-controls">
            {Object.keys(tabs).map(c=><button key={c} className={'chip'+(c===tab?' on':'')} onClick={()=>setTab(c)}>{c}</button>)}
          </div>
          <div className="matria-list matria-section__content">
          {list.map(n=>(
            <div key={n.id} className="lrow" style={{padding:10}} onClick={()=>ctx.openNode(n.id)}>
              {n.art
                ? <img src={n.art} alt="" style={{width:52,height:52,borderRadius:'50%',flex:'none',objectFit:'cover',display:'block',border:'1px solid var(--line-gold)'}}/>
                : <TypeMedallion type={n.type} conceptId={n.id} size={52}/>}
              <div style={{flex:1}}>
                <div className="section-title" style={{fontFamily:'var(--font-display)',fontSize:15.5,color:'var(--ink)',fontWeight:600}}>{n.title}</div>
                <div className="meta" style={{color:'var(--ink-soft)',marginTop:2,lineHeight:1.3}}>{n.role}</div>
              </div>
            </div>
          ))}
          </div>
        </div>
        <div className="scrollfade"/>
      </div>
      <TabBar active="Explore" onNav={ctx.nav}/>
    </div>
  );
}

/* 12, From Matria (full response) */
function FromMatria({ctx}){
  const q=ctx.q; const D=window.MATRIA; const S=useMStore();
  const [sheet,setSheet]=useState(false);
  const [flash,setFlash]=useState('');
  const saved=S.isSaved(q.id), done=S.isPracticeDone(q.id);
  function share(){
    const text=q.text+'\n\n'+reflectionText(q)+'\n\nA question to carry: '+carryText(q)+'\n\nMatria';
    const ok=()=>{setFlash('Copied ✓');setTimeout(()=>setFlash(''),1600);};
    if(navigator.share){
      navigator.share({title:'Matria',text}).then(()=>{setFlash('Shared ✓');setTimeout(()=>setFlash(''),1600);}).catch(err=>{ if(err && err.name!=='AbortError') copyFallback(text, ok); });
    } else copyFallback(text, ok);
  }
  function copyFallback(text, done){
    if(navigator.clipboard){ navigator.clipboard.writeText(text).then(done).catch(()=>legacyCopy(text, done)); }
    else legacyCopy(text, done);
  }
  function legacyCopy(text, done){
    const ta=document.createElement('textarea'); ta.value=text; ta.style.position='fixed'; ta.style.opacity='0';
    document.body.appendChild(ta); ta.select();
    try{ document.execCommand('copy'); done(); }catch(e){ setFlash('Long-press to copy'); setTimeout(()=>setFlash(''),1800); }
    document.body.removeChild(ta);
  }
  return (
    <div className="screen dark matria-dark">
      <StatusBar/>
      <TopBar onBack={()=>ctx.back()} dark/>
      <div className="s-body pad" style={{paddingTop:6}}>
        <h1 className="title">From Matria</h1>
        <p className="answer-screen__editorial-note" style={{marginTop:8}}>Practice, pathways and the full editorial reading.</p>
        <AnswerEditorialCard q={q} onOpenSources={()=>setSheet(true)}/>
        <hr className="rule" style={{margin:'18px 0 14px'}}/>
        {(()=>{const f=window.MATRIA_FRAGMENTS.forQuestion(q.id); if(!f) return null; return (
          <React.Fragment>
            <div className="label" style={{marginBottom:10}}>In conversation with</div>
            <div className="dcard" style={{padding:'14px 15px 15px'}}>
              {!f.verified && <div className="label" style={{fontSize:8.5,marginBottom:8,color:'var(--gold)'}}>From Matria · not verbatim</div>}
              <FragmentQuote f={f} size={15.5} dark/>
              <div style={{display:'flex',alignItems:'center',gap:9,marginTop:9,flexWrap:'wrap'}}>
                <span className="meta">{f.speaker_or_source}</span>
                <span className="tag" style={{height:20,fontSize:8.5}}>{f.context_label}</span>
              </div>
              <button onClick={()=>ctx.openFragment(f.id)} style={{width:'100%',height:44,marginTop:14,background:'rgba(200,160,100,.1)',border:'1px solid var(--line-gold)',borderRadius:12,color:'var(--gold)',fontSize:13,fontWeight:700,fontFamily:'var(--font-body)',cursor:'pointer',display:'flex',alignItems:'center',justifyContent:'center',gap:8}}>
                Read this fragment <Icon name="arrow" size={16}/>
              </button>
            </div>
            <hr className="rule" style={{margin:'14px 0 14px'}}/>
          </React.Fragment>);})()}
        <div className="label" style={{marginBottom:11}}>Ideas in Conversation</div>
        <div style={{display:'flex',flexWrap:'wrap',gap:9}}>
          {q.ideas.map(id=>{const n=D.get(id);return <span key={id} className="tag" style={{cursor:'pointer'}} onClick={()=>ctx.openNode(id)}>{n.title}</span>;})}
        </div>
        <hr className="rule" style={{margin:'18px 0 14px'}}/>
        <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:8}}>
          <div className="label">A Practice</div>
          <button onClick={()=>S.togglePractice(q.id)} style={{background:done?'rgba(76,168,160,.16)':'none',border:'1px solid '+(done?'rgba(76,168,160,.5)':'var(--line-gold)'),borderRadius:14,color:done?'#7ac4bd':'var(--gold)',fontSize:10.5,padding:'4px 11px',cursor:'pointer',fontFamily:'var(--font-body)',display:'flex',alignItems:'center',gap:5}}>
            {done&&<Icon name="check" size={11} stroke={2.2}/>}{done?'Completed':'Mark complete'}
          </button>
        </div>
        <p className="bodytext">{practiceText(q)}</p>
        <hr className="rule" style={{margin:'18px 0 14px'}}/>
        <PracticePathways ctx={ctx}/>
        <hr className="rule" style={{margin:'18px 0 14px'}}/>
        <div className="label" style={{marginBottom:8}}>A Question to Carry</div>
        <p className="bodytext">{carryText(q)}</p>
        <hr className="rule" style={{margin:'18px 0 0'}}/>
      </div>
      <div className="pad" style={{flex:'none',borderTop:'1px solid var(--line-dark)',display:'flex',gap:6,padding:'9px 14px 11px',position:'relative'}}>
        {[[saved?'Saved':'Save','save',()=>S.toggleSaved(q.id,q.text),saved],['Journal','journal',()=>ctx.nav('Journal'),false],[flash||'Share','share',share,!!flash],['Sources','sources',()=>setSheet(true),false]].map(([l,ic,fn,on])=>(
          <button key={ic} onClick={fn} style={{flex:1,display:'flex',flexDirection:'column',alignItems:'center',gap:5,
            color:on?'var(--gold)':'var(--ctext-soft)',cursor:'pointer',background:on?'rgba(200,160,100,.09)':'none',
            border:'none',borderRadius:12,padding:'7px 0 6px',fontFamily:'var(--font-body)',transition:'background .2s,color .2s',WebkitTapHighlightColor:'transparent'}}>
            <Icon name={ic} size={19}/><span style={{fontSize:9.5,fontWeight:600}}>{l}</span>
          </button>
        ))}
      </div>
      {sheet && <AnswerSourcesSheet q={q} onClose={()=>setSheet(false)} onOpen={id=>{setSheet(false);ctx.openSource(id);}}/>}
    </div>
  );
}

/* 13, Source Detail (tabbed) */
/* natural phrasing for a documented relation, from this woman's point of view.
   out = true means she is the subject (a), false means she is the object (b). */
function relPhrase(rel, otherName, out){
  switch(rel){
    case 'read': return out? 'Read '+otherName : otherName+' read her';
    case 'wrote-about': return out? 'Wrote about '+otherName : otherName+' wrote about her';
    case 'corresponded-with': return 'Corresponded with '+otherName;
    case 'translated': return out? 'Translated '+otherName : otherName+' translated her';
    case 'cites': return out? 'Cites '+otherName : otherName+' cites her';
    case 'same-movement': return 'Shared a movement with '+otherName;
    case 'mentored': return out? 'Mentored '+otherName : otherName+' mentored her';
    default: return out? rel.replace(/-/g,' ')+' '+otherName : otherName+' '+rel.replace(/-/g,' ')+' her';
  }
}

function SourceDetail({ctx}){
  const D=window.MATRIA; const n=D.get(ctx.nodeId)||D.get('lorde');
  const rels=(D.relationsFor?D.relationsFor(n.id):[]);
  const S=useMStore(); const followed=S.isFollowed(n.id);
  const [tab,setTab]=useState('About');
  const tabs=['About','Works','Voice'];
  return (
    <div className="screen matria-cream">
      <StatusBar/>
      <TopBar onBack={()=>ctx.back()} right={
        <button onClick={()=>S.toggleFollow(n.id)} style={{background:'none',border:'none',padding:0,cursor:'pointer',color:followed?'var(--gold-line)':'var(--ink)'}}>
          <Icon name="bookmark" size={18} stroke={followed?2.4:1.6}/>
        </button>}/>
      <div className="s-body pad" style={{paddingTop:6}}>
        <h1 className="title" style={{color:'var(--ink)',marginBottom:14}}>{n.type==='person'||n.type==='political'?'Author Page':'Source Detail'}</h1>
        <div style={{display:'flex',gap:15,alignItems:'flex-start'}}>
          {n.type==='person'
            ? <div className="source-detail-portrait">
                <Portrait pic={n.pic} id={n.id} name={n.title} size={100} round={false} radius={12} collage/>
              </div>
            : <TypeMedallion type={n.type} conceptId={n.id} size={92}/>}
          <div style={{paddingTop:4}}>
            <div className="section-title" style={{fontFamily:'var(--font-display)',fontSize:21,color:'var(--ink)',fontWeight:600,lineHeight:1.1}}>{n.title}</div>
            <div className="meta" style={{color:'var(--ink-soft)',margin:'6px 0 3px'}}>{n.role}</div>
            <div className="meta" style={{color:'var(--ink-soft)'}}>{n.region} · {n.period}</div>
          </div>
        </div>
        <div style={{display:'flex',gap:22,marginTop:18,borderBottom:'1px solid var(--line-cream)'}}>
          {tabs.map(t=>(
            <span key={t} onClick={()=>setTab(t)} style={{fontSize:13,paddingBottom:9,cursor:'pointer',
              color:t===tab?'var(--ink)':'var(--ink-faint)',fontWeight:t===tab?700:400,
              borderBottom:t===tab?'2px solid var(--gold-line)':'2px solid transparent',marginBottom:-1}}>{t}</span>
          ))}
        </div>
        <div style={{paddingTop:14}}>
          {tab==='About' && <>
            <div className="label" style={{marginBottom:8}}>About</div>
            <p className="bodytext">{n.description}</p>
            {n.themes && <>
              <div className="label" style={{margin:'16px 0 9px'}}>Themes</div>
              <div style={{display:'flex',flexWrap:'wrap',gap:8}}>{n.themes.map(t=><span key={t} className="tag">{t}</span>)}</div>
            </>}
            {n.sources && <>
              <div className="label" style={{margin:'16px 0 7px'}}>Source</div>
              {n.works? n.works.map(w=><p key={w} style={{fontSize:13,color:'var(--ink)',margin:'0 0 4px'}}>{w}</p>) : n.sources.map(s=><p key={s} style={{fontSize:13,color:'var(--ink)',margin:'0 0 4px'}}>{s}</p>)}
            </>}
          </>}
          {tab==='Works' && <><div className="label" style={{marginBottom:8}}>Works</div>{n.works&&n.works.length ? n.works.map(w=><p key={w} style={{fontSize:13.5,color:'var(--ink)',margin:'0 0 7px'}}>{w}</p>) : <p className="bodytext" style={{fontStyle:'italic',color:'var(--ink-soft)'}}>No verified work is listed for this entry yet.</p>}</>}
          {tab==='Voice' && <div style={{paddingTop:2}}><NodeVoicePanel n={n}/></div>}
        </div>
        {rels.length>0 && <>
          <div className="label" style={{margin:'20px 0 4px'}}>In her own hands</div>
          <p style={{fontSize:11,color:'var(--ink-faint)',margin:'0 0 9px',fontStyle:'italic'}}>Documented connections, with sources.</p>
          <div style={{display:'flex',flexDirection:'column',gap:8}}>
            {rels.map((r,i)=>{
              const out=r.a===n.id; const other=D.get(out?r.b:r.a); if(!other) return null;
              return (
                <div key={i} className="lrow" style={{padding:'10px 12px'}} onClick={()=>ctx.openSource(other.id)}>
                  <TypeMedallion type={other.type} conceptId={other.id} size={34}/>
                  <div style={{flex:1,minWidth:0}}>
                    <div style={{fontSize:13.5,color:'var(--ink)',fontWeight:600}}>{relPhrase(r.rel,other.title,out)}</div>
                    <div style={{fontSize:10.5,color:'var(--ink-faint)',marginTop:2,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{r.source} · {r.evidence}</div>
                  </div>
                  <span style={{color:'var(--ink-faint)'}}><Icon name="chevron" size={14}/></span>
                </div>
              );
            })}
          </div>
        </>}
        <button className="btn btn-ghost-dark" style={{width:'100%',margin:'18px 0 6px',border:'1px solid var(--line-gold)',color:'var(--gold-line)'}} onClick={()=>ctx.openMapForNode(n.id)}>View in Knowledge Map</button>
        <button className="btn btn-navy" style={{width:'100%',margin:'0 0 10px',height:46}} onClick={()=>S.toggleFollow(n.id)}>{followed?'Following ✓':'Follow Lineage'}</button>
      </div>
    </div>
  );
}

/* Explore tab, enter the archive by node type */
function ExploreDestArt({kind}){
  const stroke='rgba(201,143,106,.34)';
  const faint='rgba(201,143,106,.18)';
  if(kind==='primer') return (
    <span className="explore-dest-card__art" aria-hidden="true">
      <svg width="92" height="72" viewBox="0 0 92 72" fill="none">
        <path d="M58 54V34c0-8 6-14 14-14" stroke={stroke} strokeWidth=".9"/>
        <path d="M58 54c-4-10-8-16-14-20M44 34c6 4 10 10 14 20" stroke={faint} strokeWidth=".8"/>
        <path d="M30 58h34" stroke={faint} strokeWidth=".8"/>
        <rect x="22" y="42" width="24" height="16" rx="2" stroke={stroke} strokeWidth=".9"/>
        <path d="M26 46h16M26 50h11" stroke={faint} strokeWidth=".7"/>
      </svg>
    </span>
  );
  if(kind==='reading') return (
    <span className="explore-dest-card__art" aria-hidden="true">
      <svg width="92" height="72" viewBox="0 0 92 72" fill="none">
        <path d="M52 58c0-16 4-28 12-36" stroke={stroke} strokeWidth=".9"/>
        <path d="M64 22c-4 6-6 14-6 24" stroke={faint} strokeWidth=".8"/>
        <ellipse cx="58" cy="54" rx="10" ry="5" stroke={stroke} strokeWidth=".85"/>
        <path d="M48 54h20" stroke={faint} strokeWidth=".7"/>
        <circle cx="66" cy="18" r="2.2" fill="rgba(201,143,106,.28)"/>
        <circle cx="72" cy="26" r="1.6" fill="rgba(201,143,106,.2)"/>
      </svg>
    </span>
  );
  if(kind==='atlas') return (
    <span className="explore-dest-card__art" aria-hidden="true">
      <svg width="92" height="72" viewBox="0 0 92 72" fill="none">
        <circle cx="58" cy="36" r="18" stroke={stroke} strokeWidth=".85"/>
        <circle cx="58" cy="36" r="11" stroke={faint} strokeWidth=".7"/>
        <path d="M58 18v36M40 36h36" stroke={faint} strokeWidth=".65"/>
        <circle cx="52" cy="30" r="1.2" fill="rgba(201,143,106,.35)"/>
        <circle cx="64" cy="42" r="1.2" fill="rgba(201,143,106,.28)"/>
        <path d="M46 52l6-8 5 4 8-10" stroke={stroke} strokeWidth=".8"/>
      </svg>
    </span>
  );
  return (
    <span className="explore-dest-card__art" aria-hidden="true">
      <svg width="92" height="72" viewBox="0 0 92 72" fill="none">
        <path d="M48 58c0-22 8-34 20-42" stroke={stroke} strokeWidth=".9"/>
        <path d="M68 16c6 8 8 18 6 30" stroke={faint} strokeWidth=".8"/>
        <path d="M42 58h30" stroke={faint} strokeWidth=".7"/>
        <path d="M54 46c4-6 10-10 18-12" stroke={stroke} strokeWidth=".85"/>
        <circle cx="70" cy="24" r="2" fill="rgba(201,143,106,.24)"/>
      </svg>
    </span>
  );
}

function ExploreSlotIcon({kind}){
  const g={
    primer:<Icon name="journal" size={18}/>,
    reading:<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.1" strokeLinecap="round"><path d="M6 4l6 16M18 4L12 20"/><circle cx="6" cy="4" r="1.2"/><circle cx="18" cy="4" r="1.2"/></svg>,
    atlas:<TypeGlyph type="tradition" size={18}/>,
    paths:<Icon name="paths" size={18}/>,
  };
  return <span className="explore-dest-card__slot">{g[kind]}</span>;
}

const EXPLORE_DESTINATIONS=[
  {key:'primer', title:'How the archive works', meta:'Ancient myths to modern science. How lineage, notes and search fit together.', art:'primer', icon:'primer', go:'ArchivePrimer'},
  {key:'reading', title:'The Reading Room', meta:'Every author we read. New readings every two months.', art:'reading', icon:'reading', go:'ReadingRoom'},
  {key:'atlas', title:'Practice Atlas', meta:'80 practices, labelled by evidence.', art:'atlas', icon:'atlas', go:'PracticeAtlas'},
  {key:'paths', title:'Guided Paths', meta:'Constellations curated through the archive.', art:'paths', icon:'paths', go:'Paths'},
];

function Explore({ctx}){
  const D=window.MATRIA;
  const browseRef=React.useRef(null);
  const [q,setQ]=useState('');
  const query=q.trim().toLowerCase();
  const showBrowse=query.length<2;
  const results = query.length>=2
    ? Object.values(D.NODES).filter(n=>n.title.toLowerCase().includes(query) || (n.role||'').toLowerCase().includes(query)).slice(0,8)
    : [];
  const counts={};Object.values(D.NODES).forEach(n=>counts[n.type]=(counts[n.type]||0)+1);
  const plural={person:'Women',myth:'Myths',political:'Political figures',history:'Historical events',science:'Scientific discoveries',tradition:'Cultural traditions',idea:'Philosophical ideas'};
  return (
    <div className="screen dark matria-dark explore-screen">
      <StatusBar/>
      <div className="s-body explore-screen__body matria-flow">
        <div className="pad explore-screen__head matria-section">
          <div className="explore-screen__title-row">
            <h1 className="matria-title">Explore</h1>
            <span className="explore-screen__glyph" aria-hidden="true"><Icon name="explore" size={17}/></span>
          </div>
          <p className="matria-lead">Search a name, or enter the archive by kind of knowledge.</p>
          <div className="explore-search">
            <span className="explore-search__icon" aria-hidden="true"><Icon name="search" size={16} stroke={1.4}/></span>
            <input className="explore-search__input" value={q} onChange={e=>setQ(e.target.value)} name="archive-search" aria-label="Search the archive" autoComplete="off" placeholder="Search a woman, a myth, a theme…"/>
            <button type="button" className="explore-search__filter" aria-label="Browse archive by kind" onClick={()=>browseRef.current&&browseRef.current.scrollIntoView({behavior:'smooth',block:'start'})}>
              <Icon name="filter" size={16} stroke={1.2}/>
            </button>
          </div>
          {results.length>0 && <div className="explore-results matria-section__content">
            {results.map(n=>(
              <div key={n.id} className="lrow explore-result" onClick={()=>ctx.openSource(n.id)}>
                {n.type==='person'
                  ? <Portrait pic={n.pic} id={n.id} name={n.title} size={34}/>
                  : <TypeMedallion type={n.type} conceptId={n.id} size={34}/>}
                <div className="explore-result__copy">
                  <div className="explore-dest-card__title">{n.title}</div>
                  <div className="explore-dest-card__meta">{n.role||D.TYPES[n.type].label}{n.region?' · '+n.region:''}</div>
                </div>
                <span className="explore-dest-card__chev"><Icon name="chevron" size={14}/></span>
              </div>
            ))}
          </div>}
          {query.length>=2 && results.length===0 && <p className="explore-empty matria-section__content">No one by that name in the archive yet. You can suggest her.</p>}
        </div>
        {showBrowse && <>
          <div className="pad explore-screen__ways matria-section">
            <div className="matria-rule" aria-hidden="true">
              <Icon name="plus" size={9} stroke={1.5}/>
              <span className="matria-section-label">Ways to explore</span>
              <Icon name="explore" size={9} stroke={1.2}/>
            </div>
            <div className="explore-dest-list matria-section__content">
              {EXPLORE_DESTINATIONS.map(d=>(
                <button key={d.key} type="button" className="explore-dest-card" onClick={()=>ctx.nav(d.go)}>
                  <ExploreSlotIcon kind={d.icon}/>
                  <div className="explore-dest-card__copy">
                    <div className="explore-dest-card__title">{d.title}</div>
                    <div className="explore-dest-card__meta">{d.meta}</div>
                  </div>
                  <ExploreDestArt kind={d.art}/>
                  <span className="explore-dest-card__chev"><Icon name="chevron" size={15}/></span>
                </button>
              ))}
            </div>
            <button type="button" className="explore-reassure" onClick={()=>ctx.nav('Ask')}>
              <span className="explore-reassure__glyph" aria-hidden="true"><Icon name="explore" size={18}/></span>
              <span className="explore-reassure__copy">
                <span className="explore-reassure__line">The archive is vast.</span>
                <span className="explore-reassure__line">You are not alone in it.</span>
              </span>
              <span className="explore-reassure__cta">Start exploring <Icon name="arrow" size={13}/></span>
            </button>
          </div>
          <div className="pad explore-screen__browse matria-section" id="explore-browse" ref={browseRef}>
            <div className="matria-rule" aria-hidden="true">
              <span className="matria-section-label">Browse the archive</span>
            </div>
            <div className="explore-browse-list matria-section__content">
              {Object.entries(D.TYPES).map(([k])=>(
                <button key={k} type="button" className="explore-browse-row lrow" onClick={()=>ctx.nav(k==='person'?'ConnectedWomen':'MythsHistories')}>
                  <TypeMedallion type={k} size={36}/>
                  <div className="explore-dest-card__copy">
                    <div className="explore-dest-card__title">{plural[k]}</div>
                    <div className="explore-dest-card__meta">{counts[k]} {counts[k]===1?'entry':'entries'} in the archive</div>
                  </div>
                  <span className="explore-dest-card__chev"><Icon name="chevron" size={14}/></span>
                </button>
              ))}
            </div>
            <div className="matria-rule explore-screen__threads-rule" aria-hidden="true">
              <span className="matria-section-label">Threads</span>
            </div>
            <div className="explore-threads matria-section__content">
              {Object.values(D.THREADS).map(th=>{
                const threadQuestion={womb:'mother_01',water:'migration_02',weaving:'care_03',fire:'anger_01'}[th.id] || 'care_02';
                return (
                <button key={th.id} type="button" className="explore-thread-card dcard" onClick={()=>{ctx.setQuestion(threadQuestion);ctx.openQuestionMap();}}>
                  <div className="explore-dest-card__title" style={{color:'var(--gold)'}}>{th.name}</div>
                  <div className="explore-dest-card__meta">{th.subtitle}</div>
                </button>
              );})}
            </div>
          </div>
        </>}
        <div className="scrollfade"/>
      </div>
      <TabBar active="Explore" onNav={ctx.nav}/>
    </div>
  );
}

/* Paths tab, guided constellations + Suggest a name */
function Paths({ctx}){
  const paths=[
    ['science','Women Who Mapped the Universe','Astronomy, observation and erased labour.','work_05'],
    ['idea','The Invisible Infrastructure of Care','How care quietly holds the world together.','care_03'],
    ['tradition','Exile, Language and Belonging','Migration, memory and the work of return.','migration_02'],
    ['myth','Myths of Feminine Power','Goddesses, monsters and reclaimed force.','power_10'],
    ['person','Birth, Darkness and Creation','Origin stories told from the mother.','mother_01'],
  ];
  return (
    <div className="screen dark matria-dark">
      <StatusBar/>
      <div className="s-body" style={{paddingBottom:8}}>
        <div className="pad" style={{paddingTop:8}}>
          <h1 className="title display-title">Paths</h1>
          <p className="lead" style={{marginTop:6}}>Guided constellations through the archive.</p>
        </div>
        <div className="pad" style={{marginTop:14,display:'flex',flexDirection:'column',gap:9}}>
          {paths.map(([g,t,d,qid])=>{
            const q=window.MATRIA.QUESTIONS[qid];
            return (
            <div key={t} className="lrow" style={{padding:'11px 13px'}} onClick={()=>{ctx.setQuestion(qid);ctx.openQuestionMap();}}>
              <TypeMedallion type={g} size={40}/>
              <div style={{flex:1}}>
                <div className="section-title" style={{fontFamily:'var(--font-display)',fontSize:14,color:'var(--ctext)',fontWeight:600,lineHeight:1.2}}>{t}</div>
                <div className="meta" style={{fontSize:10.5,marginTop:2}}>{d}</div>
                <div style={{fontSize:10,color:'rgba(200,160,100,.75)',marginTop:2}}>{q ? q.nodes.length+' archive entries' : 'Open map'}</div>
              </div>
              <span style={{color:'var(--ctext-soft)'}}><Icon name="chevron" size={15}/></span>
            </div>
          );})}
          <div className="lrow" style={{padding:'13px',borderStyle:'dashed',borderColor:'var(--line-gold)'}} onClick={()=>ctx.nav('Suggest')}>
            <span style={{width:40,height:40,flex:'none',borderRadius:9,background:'rgba(200,160,100,.1)',display:'flex',alignItems:'center',justifyContent:'center',color:'var(--gold)'}}><Icon name="plus" size={20}/></span>
            <div style={{flex:1}}>
              <div className="section-title" style={{fontFamily:'var(--font-display)',fontSize:14,color:'var(--ctext)',fontWeight:600}}>Suggest a name</div>
              <div className="meta" style={{fontSize:10.5,marginTop:2}}>Propose a woman for the archive.</div>
            </div>
            <span style={{color:'var(--ctext-soft)'}}><Icon name="chevron" size={15}/></span>
          </div>
        </div>
        <div className="scrollfade"/>
      </div>
      <TabBar active="Explore" onNav={ctx.nav}/>
    </div>
  );
}

/* Sanctuary */
function Sanctuary({ctx}){
  const S=useMStore(); const st=S.get();
  const items=[
    ['Saved Answers', st.saved.length+' saved', 'save', 'saved'],
    ['Saved Fragments', st.fragments.length+' fragments', 'bookmark', 'fragments'],
    ['Journal Reflections', st.journal.length+' entries', 'journal', 'journal'],
    ['Followed Lineages', st.follows.length+' followed', 'map', 'follows'],
    ['Completed Practices', st.practices.length+' completed', 'check', 'practices'],
  ];
  return (
    <div className="screen matria-cream">
      <StatusBar/>
      <div className="s-body" style={{paddingBottom:8}}>
        <div className="pad" style={{paddingTop:8}}>
          <h1 className="title display-title" style={{color:'var(--ink)'}}>Sanctuary</h1>
          <p className="lead" style={{marginTop:6}}>Your private space. Empty until you save something.</p>
        </div>
        <div className="pad" style={{marginTop:14,display:'flex',flexDirection:'column',gap:10}}>
          {!st.saved.length && !st.journal.length && !st.follows.length && !st.fragments.length && !st.practices.length && (
            <p className="lead sanctuary-empty-hint">Nothing saved yet. That is normal. Ask on Today, then save what stays with you.</p>
          )}
          <div className="sanctuary-constellation" onClick={()=>ctx.nav('YourConstellation')}>
            <span className="sanctuary-constellation__sky" aria-hidden="true"/>
            <span className="sanctuary-constellation__veil" aria-hidden="true"/>
            <span className="sanctuary-constellation__icon"><Icon name="star" size={20}/></span>
            <div className="sanctuary-constellation__body">
              <div className="sanctuary-constellation__title">Your Constellation</div>
              <div className="sanctuary-constellation__meta">{st.follows.length? st.follows.length+' women you follow, and the threads between them' : 'Follow women and watch your own sky take shape'}</div>
            </div>
            <span className="sanctuary-constellation__chevron"><Icon name="chevron" size={16}/></span>
          </div>
          <div className="lrow" onClick={()=>ctx.nav('ArchivePrimer')}>
            <span className="lrow__slot"><Icon name="journal" size={18}/></span>
            <div style={{flex:1}}>
              <div className="section-title" style={{fontFamily:'var(--font-display)',fontSize:15,color:'var(--ink)',fontWeight:600}}>How the archive works</div>
              <div className="meta" style={{fontSize:11,marginTop:1,lineHeight:1.35}}>Lineage, notes, myths and search, explained for readers.</div>
            </div>
            <span style={{color:'var(--ink-faint)'}}><Icon name="chevron" size={16}/></span>
          </div>
          {items.map(([t,s,ic,kind])=>(
            <div key={t} className="lrow" onClick={()=>ctx.openList(kind)}>
              <span className="lrow__slot"><Icon name={ic} size={18}/></span>
              <div style={{flex:1}}>
                <div className="section-title" style={{fontFamily:'var(--font-display)',fontSize:15,color:'var(--ink)',fontWeight:600}}>{t}</div>
                <div className="meta" style={{fontSize:11,color:'var(--ink-faint)',marginTop:1}}>{s}</div>
              </div>
              <span style={{color:'var(--ink-faint)'}}><Icon name="chevron" size={16}/></span>
            </div>
          ))}
          <div className="sanctuary-write-card" onClick={()=>ctx.nav('Journal')}>
            <span className="sanctuary-write-card__sprig" aria-hidden="true"><Sprig w={80} h={170} color="#a8895a"/></span>
            <div className="sanctuary-write-card__title">Continue Writing</div>
            <div className="sanctuary-write-card__meta">What did this awaken in you?</div>
          </div>
        </div>
        <div className="scrollfade"/>
      </div>
      <TabBar active="Sanctuary" onNav={ctx.nav}/>
    </div>
  );
}

/* iPad split view: Knowledge Map (left) + a live reading panel (right).
   Rendered full-viewport by App when the Knowledge Map is opened on a tablet,
   so it is not constrained by the phone-frame shell. Reuses the iPad map design
   wired to the live corpus. */
function MapReadingPanel({nodeId, q, ctx, onOpen}){
  const D=window.MATRIA; const n=nodeId&&D.get(nodeId);
  if(!n) return (
    <div className="reading-measure" style={{padding:'calc(46px + env(safe-area-inset-top)) 30px 30px',display:'flex',flexDirection:'column',height:'100%',margin:'0 auto'}}>
      <div className="label">From Matria</div>
      <h2 className="title" style={{margin:'10px 0 16px'}}>{q.text}</h2>
      <ReflectionCopy q={q} style={{color:'var(--ctext)'}}/>
      <div style={{flex:1}}/>
      <p style={{fontSize:12,color:'var(--ctext-soft)',fontStyle:'italic'}}>Tap a woman to read her source. Tap again to trace her lineage.</p>
    </div>
  );
  return (
    <div className="reading-measure" style={{padding:'calc(42px + env(safe-area-inset-top)) 28px 26px',overflowY:'auto',height:'100%',margin:'0 auto'}}>
      <div style={{display:'flex',gap:15,alignItems:'flex-start'}}>
        {n.type==='person'
          ? <div className="source-detail-portrait source-detail-portrait--dark">
              <Portrait pic={n.pic} id={n.id} name={n.title} size={84} round={false} radius={12} collage/>
            </div>
          : <TypeMedallion type={n.type} conceptId={n.id} size={84}/>}
        <div style={{paddingTop:2}}>
          <div className="label" style={{color:D.TYPES[n.type].color}}>{D.TYPES[n.type].label}</div>
          <div className="section-title" style={{fontFamily:'var(--font-display)',fontSize:22,color:'var(--ctext)',fontWeight:600,margin:'5px 0 4px',lineHeight:1.1}}>{n.title}</div>
          <div className="meta">{n.role}{n.period&&n.period!=='-'?' · '+n.period:''}</div>
        </div>
      </div>
      <p className="bodytext" style={{margin:'18px 0 0',color:'var(--ctext)'}}>{n.description}</p>
      <div style={{margin:'16px 0 0'}}><NodeVoicePanel n={n} dark/></div>
      {n.themes && <><div className="label" style={{margin:'18px 0 9px'}}>Themes</div>
        <div style={{display:'flex',flexWrap:'wrap',gap:8}}>{n.themes.map(t=><span key={t} className="tag">{t}</span>)}</div></>}
      {n.sources && <><div className="label" style={{margin:'18px 0 7px'}}>Sources</div>
        {n.sources.map(s=><p key={s} style={{fontSize:12.5,color:'var(--ctext)',margin:'0 0 5px',lineHeight:1.4}}>{s}</p>)}</>}
      {(()=>{ const rels=(D.relationsFor?D.relationsFor(n.id):[]); if(!rels.length) return null; return (
        <>
          <div className="label" style={{margin:'20px 0 4px'}}>In her own hands</div>
          <p style={{fontSize:11,color:'var(--ctext-faint)',margin:'0 0 9px',fontStyle:'italic'}}>Documented connections, with sources.</p>
          <div style={{display:'flex',flexDirection:'column',gap:8}}>
            {rels.map((r,i)=>{ const out=r.a===n.id; const other=D.get(out?r.b:r.a); if(!other) return null; return (
              <div key={i} onClick={()=>onOpen&&onOpen(other.id)} style={{display:'flex',alignItems:'center',gap:11,padding:'10px 12px',borderRadius:12,border:'1px solid var(--line-dark)',background:'rgba(255,255,255,.03)',cursor:'pointer'}}>
                <TypeMedallion type={other.type} conceptId={other.id} size={34}/>
                <div style={{flex:1,minWidth:0}}>
                  <div style={{fontSize:13,color:'var(--ctext)',fontWeight:600}}>{relPhrase(r.rel,other.title,out)}</div>
                  <div style={{fontSize:10.5,color:'var(--ctext-faint)',marginTop:2,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{r.source} · {r.evidence}</div>
                </div>
                <span style={{color:'var(--ctext-faint)'}}><Icon name="chevron" size={14}/></span>
              </div>
            );})}
          </div>
        </>
      );})()}
    </div>
  );
}

function MapFilterChips({types,state,onChange}){
  const anyOn = Object.values(state||{}).some(Boolean);
  return (
    <div style={{display:'flex',flexDirection:'column',gap:7,alignItems:'flex-end'}}>
      <div className="label" style={{fontSize:9}}>Filter</div>
      {Object.entries(types).map(([k,t])=>(
        <button key={k} className={'chip'+((!anyOn||state[k])?' on':'')} style={{height:26,fontSize:11}} onClick={()=>onChange(k)}>
          <span style={{width:7,height:7,borderRadius:'50%',background:t.color,marginRight:6,display:'inline-block'}}/>{t.label}
        </button>
      ))}
    </div>
  );
}

function IPadKnowledgeMap({ctx}){
  const D=window.MATRIA; const q=ctx.q;
  const anchor=ctx.mapAnchor;
  const anchored=anchor&&D.mapNodesFor?D.mapNodesFor(anchor):null;
  const center=anchored?anchored.center:q.text;
  const ringIds=anchored?anchored.nodes:q.nodes;
  const mapKey=anchor||q.id;
  const [readId,setReadId]=useState(null);
  const [filter,setFilter]=useState({});
  const [legend,setLegend]=useState(true);
  return (
    <div className="screen dark ipad-map-shell">
      <div className="ipad-map-stage">
        <div className="ipad-map-head">
          <button className="ipad-map-back" onClick={()=>ctx.back()} aria-label="Back"><Icon name="back" size={20}/></button>
          <div>
            <h1 className="title">Knowledge Map</h1>
            <p className="lead" style={{marginTop:3,maxWidth:340}}>{center.replace(/\n/g,' · ')}</p>
          </div>
        </div>
        <KnowledgeMap key={mapKey} question={center} nodeIds={ringIds} onOpenNode={setReadId}
          variant="ipad" filterState={filter} onFilterChange={k=>setFilter(f=>({...f,[k]:!f[k]}))} legendOpen={legend} onLegendClose={()=>setLegend(false)}/>
        <div style={{position:'absolute',right:18,top:'calc(env(safe-area-inset-top) + 18px)',zIndex:5}}>
          <MapFilterChips types={D.TYPES} state={filter} onChange={k=>setFilter(f=>({...f,[k]:!f[k]}))}/>
        </div>
        <p className="kmap-hint" style={{bottom:14}}>Tap a woman to open · Threads show shared themes · drag · pinch or +/− to zoom</p>
      </div>
      <div className="ipad-map-panel">
        <MapReadingPanel nodeId={readId} q={q} ctx={ctx} onOpen={setReadId}/>
      </div>
    </div>
  );
}

/* Reader-facing primer: lineage, notes, myths, search */
function ArchivePrimer({ctx}){
  const P=window.MATRIA_PRIMER;
  return (
    <div className="screen matria-cream">
      <StatusBar/>
      <TopBar onBack={()=>ctx.back()} title="Archive"/>
      <div className="s-body pad archive-primer">
        <h1 className="title display-title" style={{color:'var(--ink)'}}>{P.title}</h1>
        <p className="lead archive-primer__lead">Poetic in tone, sourced in practice. Read this once, then explore.</p>
        <div className="archive-primer__sections">
          {P.sections.map(s=>(
            <section key={s.id} className="archive-primer__section card card-pad">
              <div className="label" style={{marginBottom:8}}>{s.label}</div>
              <p className="bodytext" style={{margin:0}}>{s.body}</p>
            </section>
          ))}
        </div>
        <button className="btn btn-navy" style={{marginTop:16,height:48}} onClick={()=>ctx.nav('Explore')}>Enter the archive</button>
        <p className="archive-primer__foot">Questions without sources route to an honest empty state. Matria will not invent around them.</p>
      </div>
    </div>
  );
}

Object.assign(window,{TopBar,Answer,AnswerEditorialCard,AnswerExploreDeeper,AnswerSourcesSheet,MapPreview,KnowledgeMapScreen,YourConstellation,ConnectedWomen,MythsHistories,FromMatria,SourceDetail,Explore,Paths,Sanctuary,IPadKnowledgeMap,MapReadingPanel,MapFilterChips,ArchivePrimer});
