// fs-views.jsx — section views for Short's Resort Field Station (SRFS)

/* ============ FRONTISPIECE (home) ============ */
function Frontispiece({ go, onSignIn, session, onSignOut }){
  const clock = useClock();
  return (
    <div className="view"><div className="sheet">
      <Folio left="Frontispiece" right={FS_SITE.abbr+" · No. 01"} />
      <div style={{display:'grid',gridTemplateColumns:'1.5fr 1fr',gap:'48px',alignItems:'center',marginBottom:'20px'}} className="land-grid">
        <div>
          <div className="eyebrow" style={{marginBottom:'18px'}}>A Hill Country Restoration · In the Open</div>
          <h1 className="disp" style={{fontSize:'clamp(40px,6.4vw,84px)'}}>Short&rsquo;s Resort<br/>Field Station</h1>
          <p className="deck" style={{marginTop:'22px'}}>
            A working record of putting one small tract above the Lampasas River back toward what the Hill Country can be —
            its seven sections, the instruments we build to tend them and every plan and line of code we use to do it.
          </p>
          <div style={{display:'flex',gap:'12px',marginTop:'30px',flexWrap:'wrap'}}>
            <button className="btn solid" onClick={()=>go('journal')}>Read the Field Journal <span className="arr">→</span></button>
            <button className="btn" onClick={()=>go('ii')}>Instruments &amp; Infrastructure <span className="arr">→</span></button>
          </div>
        </div>
        <div style={{display:'flex',justifyContent:'center'}}>
          <Seal house size={260} style={{filter:'drop-shadow(0 24px 40px #0000002e)'}}/>
        </div>
      </div>

      <div className="obs-banner" style={{marginTop:'34px'}}>
        <span className="d"></span>
        <span>Bench reading · Operational · Reservoir {FS_STATION.reservoir}% · {FS_STATION.shelves.filter(s=>s.st!=='Vacant').length} of 4 shelves active · {clock} local</span>
      </div>

      <div className="rule-ink"></div>
      <div className="eyebrow" style={{marginBottom:'18px'}}>The Station, in Five Sections</div>
      <div className="entries">
        {FS_SECTIONS.map(s=>(
          <div className="entry" key={s.id} onClick={()=>go(s.id)}>
            <div className="no">Section {s.no}</div>
            <h3>{s.title}</h3>
            <p>{s.blurb}</p>
            <div className="arr">Open →</div>
          </div>
        ))}
      </div>

      <div className="rule-hair"></div>
      <div style={{display:'flex',gap:'34px',alignItems:'center',flexWrap:'wrap',justifyContent:'center',padding:'10px 0'}}>
        <span className="eyebrow">Supported by</span>
        {FS_FUNDERS.map(f=>(
          <a key={f.k} href={f.url} target="_blank" rel="noopener" style={{display:'flex',alignItems:'center',gap:'12px',color:'var(--ink)'}}>
            <AgencyMark kind={f.mark} size={44}/>
            <div>
              <div className="zilla" style={{fontWeight:900,fontSize:'15px',textTransform:'uppercase',letterSpacing:'0.01em'}}>{f.k}</div>
              <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.1em',color:'var(--char)',opacity:.75,marginTop:'2px'}}>{f.short} ↗</div>
            </div>
          </a>
        ))}
      </div>

      <div className="rule-hair"></div>
      <div style={{textAlign:'center',padding:'4px 0 8px'}}>
        {session
          ? <span className="mono" style={{fontSize:'11px',letterSpacing:'0.14em',textTransform:'uppercase',color:'var(--char)'}}>Signed in · {session.role} &nbsp;·&nbsp; <a onClick={onSignOut} style={{cursor:'pointer'}}>Sign out</a></span>
          : <a onClick={onSignIn} className="mono" style={{fontSize:'11px',letterSpacing:'0.16em',textTransform:'uppercase',color:'var(--char)',cursor:'pointer',borderBottom:'1px solid var(--rule)',paddingBottom:'3px'}}>Operator sign-in</a>}
      </div>
    </div></div>
  );
}

/* ============ THE LAND ============ */
const FS_PLATES = [
  { id:'SR · M-01', file:'assets/plate-m01-sections.png', title:'Sections of the Property',
    cap:'The master reference — seven working sections, from the Western Headwaters Savanna down to the River Conservation Strip, each keyed to the care classes below.' },
  { id:'SR · M-02', file:'assets/plate-m02-tifton.png', title:'Tifton Replanting · Plan 1',
    cap:'Phase 1 of the replanting sequence: the property edge goes native first — windbreak, filter band and river shade — while the interior stays in Tifton 85 forage. Later phases work inward.' },
  { id:'SR · M-03', file:'assets/plate-m03-floodplain.png', title:'Flood Plain Map',
    cap:'FEMA 1% and 0.2% annual-chance flood hazard over the tract, adapted from the Lampasas CAD export of Nov 2025. Informational only — not for insurance determination.' },
];

function PlateFigure({ p, onOpen }){
  return (
    <figure className="plate-fig" onClick={()=>onOpen(p)}>
      <div className="plate-frame">
        <img src={p.file} alt={p.title+' — mapping plate'} loading="lazy"/>
        <span className="tag plate-tag">{p.id}</span>
        <span className="plate-zoom mono">Enlarge ⤢</span>
      </div>
      <figcaption>
        <div className="mono" style={{fontSize:'10px',letterSpacing:'0.18em',textTransform:'uppercase',color:'var(--oxblood)',marginBottom:'4px'}}>Plate {p.id.split('· ')[1]}</div>
        <div className="zilla" style={{fontWeight:900,fontSize:'19px',textTransform:'uppercase',lineHeight:1,marginBottom:'6px'}}>{p.title}</div>
        <p style={{fontFamily:'Newsreader',fontSize:'14.5px',lineHeight:1.4,color:'var(--char)'}}>{p.cap}</p>
      </figcaption>
    </figure>
  );
}

function LandView(){
  const [zoom,setZoom] = React.useState(null);
  React.useEffect(()=>{
    if(!zoom) return;
    const onKey = e=>{ if(e.key==='Escape') setZoom(null); };
    window.addEventListener('keydown',onKey);
    return ()=>window.removeEventListener('keydown',onKey);
  },[zoom]);
  return (
    <div className="view"><div className="sheet">
      <Folio left="Section 02 · The Land" right="Map Atlas · Field Station Plates" />
      <SectionHead no="02" title="The Land"
        deck="Seven restoration sections across the tract along the Lampasas — each held to a care class, from river frontage to upland field. The map atlas below is the working record of the ground." />

      <div className="eyebrow" style={{margin:'34px 0 16px'}}>Map Atlas · Field Station Plates</div>

      <div className="plate-lead">
        <PlateFigure p={FS_PLATES[0]} onOpen={setZoom}/>
      </div>
      <div className="plate-grid">
        <PlateFigure p={FS_PLATES[1]} onOpen={setZoom}/>
        <PlateFigure p={FS_PLATES[2]} onOpen={setZoom}/>
      </div>
      <div className="mono" style={{fontSize:'10px',letterSpacing:'0.14em',textTransform:'uppercase',color:'var(--char)',opacity:.65,margin:'6px 0 40px'}}>
        Plates drawn from the field plan of January 2026 · North up · grid 250 ft · internal documents, not surveys
      </div>

      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'40px',marginTop:'4px',borderTop:'2px solid var(--ink)',paddingTop:'30px'}} className="land-grid">
        <div>
          <div className="eyebrow" style={{marginBottom:'14px'}}>Restoration Sections</div>
          <div className="legend">
            {FS_LAND.map(s=>(
              <div className="lr" key={s.n}>
                <span className="sw" style={{background:s.c}}></span>
                <div>
                  <div className="nm">{s.n} · {s.nm} {s.ac!=='—' && <span className="mono" style={{fontSize:'10px',color:'var(--char)',opacity:.7}}>· {s.ac}</span>}</div>
                  <div className="ds">{s.ds}</div>
                </div>
              </div>
            ))}
          </div>
        </div>
        <div>
          <div className="note"><span className="k">Care Classes</span>
            Riparian &amp; hydrologic (teal), woody &amp; shelter (sage) and agricultural (ochre). The same atlas drives the maps in our manuals and the open GeoJSON under Instruments &amp; Infrastructure.
          </div>
          <div className="note" style={{marginTop:'16px'}}><span className="k">On the plates</span>
            Boundaries are managerial, not legal; acreages are as recorded in the plan of record. The flood plate is adapted from the Lampasas CAD web map and is informational only — never use it for an insurance determination.
          </div>
        </div>
      </div>

      {zoom && (
        <div className="plate-lightbox" onClick={()=>setZoom(null)}>
          <img src={zoom.file} alt={zoom.title+' — full plate'} onClick={e=>e.stopPropagation()}/>
          <button className="plate-close mono" onClick={()=>setZoom(null)}>Close ✕</button>
        </div>
      )}
    </div></div>
  );
}

/* ============ FIELD JOURNAL ============ */
function catName(id){ const c=FS_JOURNAL_CATS.find(x=>x.id===id); return c?c.t:''; }
function FeatureCard({ e, go }){
  return (
    <div onClick={()=>go('journal/'+e.slug)} className="feat"
      style={{border:'1.5px solid var(--ink)',background:'var(--paper)',padding:'26px',cursor:'pointer',display:'flex',flexDirection:'column',gap:'12px',minHeight:'280px',transition:'.18s'}}>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:'12px'}}>
        <span className="tag" style={{color:'var(--oxblood)',borderColor:'var(--oxblood)'}}><span className="sw" style={{background:'var(--oxblood)'}}></span>{catName(e.cat)}</span>
        <Seal dept={DEPT_BY[e.deptKey]} size={78} title={e.dept}/>
      </div>
      <div className="mono" style={{fontSize:'10px',letterSpacing:'0.18em',textTransform:'uppercase',color:'var(--char)',opacity:.7}}>{e.date} · {e.folio}</div>
      <h3 style={{fontFamily:'Zilla Slab',fontWeight:900,fontSize:'clamp(24px,2.7vw,34px)',lineHeight:0.98,textTransform:'uppercase',letterSpacing:'-0.01em',marginTop:'auto'}}>{e.title}</h3>
      <p style={{fontFamily:'Newsreader',fontStyle:'italic',fontSize:'16px',color:'var(--char)',lineHeight:1.4}}>{e.deck}</p>
      <div className="mono" style={{fontSize:'11px',letterSpacing:'0.14em',textTransform:'uppercase',color:'var(--oxblood)'}}>Read the dispatch →</div>
    </div>
  );
}
function JournalView({ go }){
  const featured = FS_JOURNAL.filter(e=>e.featured).slice(0,2);
  return (
    <div className="view"><div className="sheet">
      <Folio left="Section 01 · Field Journal" right={FS_JOURNAL.length+' entries on file'} />
      <SectionHead no="01" title="Field Journal"
        deck="A field desk, not a feed. The latest dispatches sit up top; everything else is filed by section below." />

      <div className="eyebrow" style={{margin:'34px 0 14px'}}>Latest Dispatches</div>
      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'16px'}} className="feat-grid">
        {featured.map(e=><FeatureCard key={e.slug} e={e} go={go}/>)}
      </div>

      {FS_JOURNAL_CATS.map(c=>{
        const items = FS_JOURNAL.filter(e=>e.cat===c.id);
        if(!items.length) return null;
        return (
          <div key={c.id} style={{marginTop:'46px'}}>
            <div style={{display:'flex',alignItems:'baseline',gap:'14px',borderBottom:'2px solid var(--ink)',paddingBottom:'10px',flexWrap:'wrap'}}>
              <h3 style={{fontFamily:'Zilla Slab',fontWeight:900,fontSize:'22px',textTransform:'uppercase',letterSpacing:'0.01em'}}>{c.t}</h3>
              <span style={{fontFamily:'Newsreader',fontStyle:'italic',fontSize:'14px',color:'var(--char)'}}>{c.d}</span>
              <span className="fol" style={{marginLeft:'auto'}}>{items.length} on file</span>
            </div>
            {items.map(e=>(
              <div className="lrow" key={e.slug} onClick={()=>go('journal/'+e.slug)}>
                <div className="ld">{e.date}<br/>{e.dept}</div>
                <div className="lt"><h3>{e.title}</h3><p>{e.deck}</p></div>
                <div className="lm">
                  <Seal dept={DEPT_BY[e.deptKey]} size={54} title={e.dept}/>
                  <span className="fol">{e.folio} · Read →</span>
                </div>
              </div>
            ))}
          </div>
        );
      })}
    </div></div>
  );
}
function SeedMixPlate(){
  const grasses = FS_SEEDMIX.filter(s=>s.t==='G');
  const forbs = FS_SEEDMIX.filter(s=>s.t==='F');
  const total = Math.round(FS_SEEDMIX.reduce((a,s)=>a+s.pct,0));
  const Col = ({title, list, c}) => (
    <div>
      <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.16em',textTransform:'uppercase',color:'var(--char)',padding:'10px 14px',borderBottom:'1px solid var(--rule)',display:'flex',justifyContent:'space-between'}}>
        <span><span style={{display:'inline-block',width:'8px',height:'8px',background:c,transform:'rotate(45deg)',marginRight:'8px'}}></span>{title}</span>
        <span>Blend %</span>
      </div>
      {list.map(s=>(
        <div key={s.lat} style={{display:'grid',gridTemplateColumns:'1fr auto',gap:'12px',padding:'8px 14px',borderTop:'1px solid var(--rule-soft)',alignItems:'baseline'}}>
          <div><div style={{fontFamily:'Newsreader',fontSize:'15px',lineHeight:1.2}}>{s.sp}</div><div className="mono" style={{fontSize:'9px',letterSpacing:'0.04em',fontStyle:'italic',color:'var(--char)',opacity:.7}}>{s.lat}</div></div>
          <div className="zilla" style={{fontWeight:900,fontSize:'16px'}}>{s.pct}</div>
        </div>
      ))}
    </div>
  );
  return (
    <div style={{border:'1.5px solid var(--ink)',margin:'22px 0',background:'var(--bone)'}}>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-end',gap:'12px',padding:'14px 16px',borderBottom:'2px solid var(--ink)'}}>
        <div><div className="mono" style={{fontSize:'10px',letterSpacing:'0.2em',textTransform:'uppercase',color:'var(--oxblood)'}}>Plate S·01</div><div className="zilla" style={{fontWeight:900,fontSize:'22px',textTransform:'uppercase',lineHeight:1,marginTop:'4px'}}>Native Seed Mix</div></div>
        <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.12em',textTransform:'uppercase',color:'var(--char)',textAlign:'right',opacity:.8}}>Designed by TPWD · PUB<br/>{FS_SEEDMIX.length} species · {total}% blend</div>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'0'}} className="seedcols">
        <div style={{borderRight:'1px solid var(--rule)'}}><Col title="Grasses" list={grasses} c="var(--sage-deep)"/></div>
        <Col title="Wildflowers & Legumes" list={forbs} c="var(--ochre-deep)"/>
      </div>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',gap:'12px',padding:'12px 16px',borderTop:'2px solid var(--ink)',flexWrap:'wrap'}}>
        <span className="mono" style={{fontSize:'10px',letterSpacing:'0.12em',textTransform:'uppercase',color:'var(--char)'}}>Total &middot; {total}% PLS blend</span>
        <span className="mono" style={{fontSize:'10px',letterSpacing:'0.1em',textTransform:'uppercase'}}>Seed · <a href={FS_SEED_PROVIDER.url} target="_blank" rel="noopener">{FS_SEED_PROVIDER.k}, {FS_SEED_PROVIDER.place} ↗</a></span>
      </div>
    </div>
  );
}

function linkify(text){
  if(typeof text!=='string') return text;
  const parts=[]; let last=0, i=0, m;
  const re=/\[([^\]]+)\]\(([^)]+)\)|((?:https?:\/\/|www\.)[^\s)]+|[a-z0-9-]+(?:\.[a-z0-9-]+)*\.(?:com|org|gov|net|edu)(?:\/[^\s)]*)?)/gi;
  while((m=re.exec(text))){
    if(m.index>last) parts.push(text.slice(last,m.index));
    if(m[1]){ parts.push(<a key={i++} href={m[2]} target="_blank" rel="noopener">{m[1]}</a>); }
    else { const u=m[3], href=u.startsWith('http')?u:'https://'+u; parts.push(<a key={i++} href={href} target="_blank" rel="noopener">{u.replace(/^https?:\/\//,'')}</a>); }
    last=re.lastIndex;
  }
  if(last<text.length) parts.push(text.slice(last));
  return parts;
}
function Block({ b }){
  if(b.t==='p') return <p className={b.cls==='dropcap'?'dropcap':''}>{linkify(b.c)}</p>;
  if(b.t==='h3') return <h3>{b.c}</h3>;
  if(b.t==='note') return <div className="note"><span className="k">{b.k}</span>{linkify(b.c)}</div>;
  if(b.t==='seedmix') return <SeedMixPlate/>;
  if(b.t==='plate') return (
    <figure className={'entry-plate'+(b.wide?' wide':'')}>
      <img src={b.src} alt={b.alt||b.c} loading="lazy"/>
      <figcaption className="mono">
        <b>{b.k} · </b>{b.c}
      </figcaption>
    </figure>
  );
  if(b.t==='spec') return (
    <div style={{border:'1px solid var(--ink)',margin:'18px 0'}}>
      <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.18em',textTransform:'uppercase',background:'var(--ink)',color:'var(--bone)',padding:'9px 14px'}}>{b.k}</div>
      {b.rows.map((r,i)=>(
        <div key={i} style={{display:'grid',gridTemplateColumns:'240px 1fr',gap:'14px',padding:'10px 14px',borderTop:i?'1px solid var(--rule-soft)':'none'}} className="specrow">
          <span className="mono" style={{fontSize:'10px',letterSpacing:'0.1em',textTransform:'uppercase',color:'var(--char)'}}>{r[0]}</span>
          <span style={{fontFamily:'Newsreader',fontSize:'15px'}}>{r[1]}</span>
        </div>
      ))}
    </div>
  );
  if(b.t==='list') return <ul style={{listStyle:'none',margin:'6px 0 20px'}}>{b.c.map((li,i)=>(
    <li key={i} className="mono" style={{fontSize:'13px',letterSpacing:'0.03em',padding:'9px 0 9px 22px',borderTop:'1px solid var(--rule-soft)',position:'relative',lineHeight:1.5}}>
      <span style={{position:'absolute',left:'3px',top:'15px',width:'7px',height:'7px',background:'var(--ink)',transform:'rotate(45deg)'}}></span>{li}
    </li>))}</ul>;
  return null;
}
function JournalEntry({ slug, go }){
  const e = FS_JOURNAL.find(x=>x.slug===slug);
  if(!e) return <NotFound go={go}/>;
  const idx = FS_JOURNAL.indexOf(e);
  const prev = FS_JOURNAL[idx+1], next = FS_JOURNAL[idx-1];
  return (
    <div className="view"><div className="sheet">
      <Folio left={'Section 01 · '+e.folio} right="Field Journal" />
      <div className="entry-head">
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:'20px'}}>
          <div className="eyebrow">Field Entry {e.folio}</div>
          <Seal dept={DEPT_BY[e.deptKey]} size={116} title={e.dept}/>
        </div>
        <h1 className="disp" style={{fontSize:'clamp(34px,5vw,60px)',maxWidth:'20ch'}}>{e.title}</h1>
        <div className="byline">
          <span>{e.date}</span><span className="sep"></span>
          <span>{catName(e.cat)}</span><span className="sep"></span>
          <span>{e.dept}</span>
        </div>
        <p className="deck" style={{marginTop:'6px'}}>{e.deck}</p>
      </div>
      <div className="figplate"><span className="cap">{e.figcap}</span></div>
      <div className="prose" style={{marginTop:'26px'}}>
        {e.body.map((b,i)=><Block key={i} b={b}/>)}
      </div>
      <div className="rule-hair"></div>
      <div style={{display:'flex',justifyContent:'space-between',gap:'16px',flexWrap:'wrap'}}>
        <button className="btn" onClick={()=>go('journal')}>← All entries</button>
        <div style={{display:'flex',gap:'10px'}}>
          {prev && <button className="btn" onClick={()=>go('journal/'+prev.slug)}>← {prev.folio}</button>}
          {next && <button className="btn" onClick={()=>go('journal/'+next.slug)}>{next.folio} →</button>}
        </div>
      </div>
    </div></div>
  );
}

/* ============ INSTRUMENTS & INFRASTRUCTURE ============ */
function Bar({ v, lo, hi, c }){
  return (
    <div className="bar" title={v+'%RH'}>
      {lo>0 && <span style={{position:'absolute',left:lo+'%',top:'-3px',bottom:'-3px',width:'1.5px',background:'var(--ink)',opacity:.5}}></span>}
      {hi>0 && <span style={{position:'absolute',left:hi+'%',top:'-3px',bottom:'-3px',width:'1.5px',background:'var(--ink)',opacity:.5}}></span>}
      <i style={{width:Math.max(2,v)+'%',background:c}}></i>
    </div>
  );
}
function InstrumentsView({ go, session }){
  const clock = useClock();
  const S = FS_STATION;
  const active = S.shelves.filter(s=>s.st!=='Vacant');
  return (
    <div className="view"><div className="sheet">
      <Folio left="Section 03 · Instruments & Infrastructure" right="Built · In Progress · Planned" />
      <SectionHead no="03" title={<span>Instruments &amp;<br/>Infrastructure</span>}
        deck="The things we build to do the work — from the propagation bench to wildlife guzzlers — and the open software that runs them. Not inventions; a small-scale kit of parts a family holding can actually build and maintain." />

      {/* roadmap of builds */}
      <div className="eyebrow" style={{margin:'36px 0 14px'}}>The Builds</div>
      <div className="grid" style={{gridTemplateColumns:'repeat(3,1fr)',marginBottom:'8px'}}>
        {FS_II_ITEMS.map(it=>(
          <div className="card" key={it.k}>
            <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:'10px',marginBottom:'12px'}}>
              <span className="tag" style={{color:FS_II_STATUS[it.status],borderColor:FS_II_STATUS[it.status]}}><span className="sw" style={{background:FS_II_STATUS[it.status]}}></span>{it.status}</span>
              <Seal dept={DEPT_BY[it.dept]} size={88} title=""/>
            </div>
            <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.16em',color:'var(--char)',opacity:.6,marginBottom:'4px'}}>{it.k}</div>
            <h4>{it.t}</h4>
            <div className="cd" style={{marginTop:'8px'}}>{it.d}</div>
            {it.demo && <button className="btn" style={{marginTop:'16px'}} onClick={()=>{ const el=document.getElementById('flagship'); if(el) el.scrollIntoView({behavior:'smooth'}); }}>See it live ↓</button>}
          </div>
        ))}
      </div>

      {/* flagship: propagation unit live board */}
      <div id="flagship" className="rule-ink"></div>
      <div style={{display:'flex',alignItems:'center',gap:'14px',marginBottom:'14px',flexWrap:'wrap'}}>
        <Seal dept={DEPT_BY['forestry_liveoak_bold']} size={76}/>
        <div>
          <div className="eyebrow">Flagship · Built</div>
          <div className="zilla" style={{fontWeight:900,fontSize:'26px',textTransform:'uppercase',lineHeight:1}}>Propagation Unit No. 01</div>
        </div>
      </div>
      <div className="demo-module">
      <div className="demo-bar">
        <span className="dm-id">Propagation Unit · No. 01</span>
        <span className="dm-dots"><i></i><i></i><i></i></span>
        <span className="dm-tag">Live Board · Observation</span>
      </div>
      <div className="demo-body">
      <div className="obs-banner">
        <span className="d"></span>
        <span>{session ? 'Operator signed in ('+session.role+') — control is unlocked in the live interface.' : 'Observation Mode — readings are live-styled; control is reserved for operators.'}</span>
      </div>
      <div className="board">
        <div className="cell"><div className="k">Bench Status</div><div className="v" style={{fontSize:'26px'}}><span className="d" style={{background:FS_STAT_COLOR[S.rackStatus]}}></span>{S.rackStatus}</div><div className="n">All subsystems nominal</div></div>
        <div className="cell"><div className="k">Reservoir</div><div className="v">{S.reservoir}<small>%</small></div><div className="n">≈ {Math.round(S.reservoir/13)} days at current draw</div></div>
        <div className="cell"><div className="k">Active Shelves</div><div className="v">{active.length}<small>/4</small></div><div className="n">One bay available</div></div>
        <div className="cell"><div className="k">Local Time</div><div className="v" style={{fontSize:'30px'}}>{clock}</div><div className="n">Unit clock · 06/21/26</div></div>
      </div>
      <div style={{marginTop:'18px'}}>
        <div className="shelfline" style={{fontWeight:700,color:'var(--char)',borderTop:'2px solid var(--ink)'}}>
          <span>Bay</span><span>Specimen</span><span className="sh-hide">Moisture</span><span className="sh-hide">Temp</span><span>Status</span>
        </div>
        {S.shelves.map(s=>(
          <div className="shelfline" key={s.n}>
            <span className="sn">{s.n}</span>
            <span className="sp">{s.sp}<em>{s.tag}</em></span>
            <div className="sh-hide">{s.st==='Vacant'?<span style={{opacity:.4}}>—</span>:<Bar v={s.m} lo={s.lo} hi={s.hi} c={s.c}/>}</div>
            <span className="sh-hide">{s.st==='Vacant'?'—':s.t+'°F'}</span>
            <span className="stat"><span className="d" style={{background:s.c}}></span>{s.st}</span>
          </div>
        ))}
      </div>
      <div style={{display:'flex',gap:'12px',marginTop:'24px',flexWrap:'wrap'}}>
        <a className="btn solid" href="Propogation GUI.html" target="_blank" rel="noopener">Explore the rack &amp; dashboard — observation mode ↗</a>
      </div>
      <p className="mono" style={{fontSize:'11px',letterSpacing:'0.08em',color:'var(--char)',opacity:.7,marginTop:'14px'}}>
        Telemetry shown is a styled placeholder; a live feed follows once the controller API is online. Operators sign in from the foot of any page to take control.
      </p>
      </div>
      </div>

      {/* software / open source */}
      <div className="rule-ink"></div>
      <div className="eyebrow" style={{marginBottom:'8px'}}>The Software · Open Source</div>
      <div className="repo">
        <span className="tag" style={{background:'var(--ink)',color:'var(--bone)',border:'none'}}>REPO</span>
        <a className="path" href={'https://'+FS_REPO.path} target="_blank" rel="noopener">{FS_REPO.path} ↗</a>
        <div className="meta"><span>License · {FS_REPO.license}</span><span>{FS_REPO.lang}</span></div>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'1.1fr 1fr',gap:'40px',marginTop:'26px'}} className="land-grid">
        <div>
          {FS_MODULES.map(m=>(
            <div className="modrow" key={m.k}>
              <div className="mk-col"><span className="mk">{m.k}</span><span className="ml">{m.l}</span></div>
              <div><div className="mt">{m.t}</div><div className="md">{m.d}</div></div>
            </div>
          ))}
        </div>
        <div>
          <div className="codeblock">
            <div><span className="c"># get the station kit</span></div>
            <div><span className="p">git</span> clone https://{FS_REPO.path}</div>
            <div><span className="p">cd</span> propagation-unit</div>
            <div style={{marginTop:'8px'}}><span className="c"># serve the interface locally</span></div>
            <div><span className="p">npm</span> install <span className="c">&amp;&amp;</span> <span className="p">npm</span> run dev</div>
            <div style={{marginTop:'8px'}}><span className="c"># flash the controller</span></div>
            <div><span className="p">make</span> flash <span className="s">PORT</span>=/dev/ttyUSB0</div>
          </div>
          <div className="note"><span className="k">Restoration R&amp;D</span>
            Every bit of software we build — systems automation, wildlife monitoring, weather tracking and the restoration work itself — is free and open source. Very little of it is wholly new; we&rsquo;re fitting existing ideas and other open source projects together so a small restoration project can build at the scale it actually needs.
          </div>
        </div>
      </div>
    </div></div>
  );
}

/* ============ R&D LIBRARY ============ */
function spImg(code, slot){ return 'assets/species/'+code.toLowerCase()+'-'+slot+'.jpg'; }
function SpeciesShelf({ go }){
  const [q,setQ] = React.useState('');
  const ql = q.trim().toLowerCase();
  const woody = FS_SPECIES.filter(s=>!ql || (s.common+' '+s.latin+' '+s.group+' '+s.role+' '+s.method).toLowerCase().includes(ql));
  const herb  = FS_LIB_SPECIES.filter(s=>!ql || (s.sp+' '+s.tag+' '+s.type+' '+s.sec+' '+s.method+' '+s.prov).toLowerCase().includes(ql));
  const total = FS_SPECIES.length + FS_LIB_SPECIES.length;
  const shownN = woody.length + herb.length;
  const herbGroups = [
    { t:'Grass', nm:'Grasses',                c:'var(--sage-deep)' },
    { t:'Forb',  nm:'Wildflowers & Legumes',  c:'var(--ochre-deep)' },
  ];
  return (
    <div>
      <div className="rule-ink"></div>
      <div style={{display:'flex',alignItems:'baseline',justifyContent:'space-between',gap:'16px',flexWrap:'wrap',marginBottom:'12px'}}>
        <div className="eyebrow">Species Notes</div>
        <span className="tag" style={{color:'var(--ochre-deep)',borderColor:'var(--ochre-deep)'}}><span className="sw" style={{background:'var(--ochre-deep)'}}></span>Pending NPSOT review</span>
      </div>
      <p className="prose" style={{maxWidth:'72ch',marginBottom:'16px'}}>These are the species we are focusing on for the restoration — the woody trees, shrubs and vines we grow on the propagation bench, plus the PUB grass-and-forb drill mix. The list is long, but it is <em>not</em> exhaustive; it is a working set, not the whole flora of the tract. Each opens as its own plate — for the woody species, the full propagation profile from our manual — and we&rsquo;re reconciling every note against NPSOT and USDA before it hardens.</p>
      <div style={{display:'flex',alignItems:'center',gap:'12px',margin:'0 0 20px',flexWrap:'wrap'}}>
        <input className="field" style={{margin:0,maxWidth:'360px'}} value={q} onChange={e=>setQ(e.target.value)}
          placeholder="Search species — common or Latin name…" aria-label="Search species"/>
        <span className="mono" style={{fontSize:'10px',letterSpacing:'0.14em',textTransform:'uppercase',color:'var(--char)',opacity:.7}}>{shownN} of {total} shown</span>
      </div>

      {FS_SP_GROUPS.map(g=>{
        const items = woody.filter(s=>s.group===g.id);
        if(!items.length) return null;
        return (
          <div key={g.id} style={{marginBottom:'22px'}}>
            <div style={{display:'flex',alignItems:'center',gap:'10px',padding:'8px 4px',borderBottom:'1px solid var(--ink)',marginBottom:'12px'}}>
              <span style={{width:'10px',height:'10px',background:'var(--river-deep)',transform:'rotate(45deg)'}}></span>
              <span className="mono" style={{fontSize:'10px',letterSpacing:'0.18em',textTransform:'uppercase'}}>{g.t}</span>
              <span className="mono" style={{marginLeft:'auto',fontSize:'10px',letterSpacing:'0.12em',color:'var(--char)',opacity:.6}}>{items.length}</span>
            </div>
            <div className="grid" style={{gridTemplateColumns:'1fr 1fr'}}>
              {items.map(s=>(
                <div className="card feat spcard" key={s.slug} onClick={()=>go('species/'+s.slug)} style={{display:'flex',gap:'14px',alignItems:'stretch',cursor:'pointer',padding:'0'}}>
                  <img src={spImg(s.code,'form')} alt={s.common} loading="lazy" style={{width:'104px',flex:'none',objectFit:'cover',borderRight:'1px solid var(--ink)',background:'var(--paper-3)'}}/>
                  <div style={{padding:'16px 16px 16px 2px',display:'flex',flexDirection:'column',gap:'4px',minWidth:0}}>
                    <div className="mono" style={{fontSize:'9px',letterSpacing:'0.16em',textTransform:'uppercase',color:'var(--char)',opacity:.6}}>Plate {s.code}</div>
                    <div style={{fontFamily:'Zilla Slab',fontWeight:900,fontSize:'19px',lineHeight:1,textTransform:'uppercase'}}>{s.common}</div>
                    <div style={{fontFamily:'Newsreader',fontStyle:'italic',fontSize:'14px',color:'var(--char)'}}>{s.latin}</div>
                    <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.06em',color:'var(--char)',opacity:.75,marginTop:'2px'}}>Difficulty {s.diff} · {s.method}</div>
                    <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.12em',textTransform:'uppercase',color:'var(--oxblood)',marginTop:'auto',paddingTop:'6px'}}>Open plate →</div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        );
      })}

      {herbGroups.map(g=>{
        const items = herb.filter(s=>s.type===g.t);
        if(!items.length) return null;
        return (
          <div key={g.t} style={{marginBottom:'22px'}}>
            <div style={{display:'flex',alignItems:'center',gap:'10px',padding:'8px 4px',borderBottom:'1px solid var(--ink)'}}>
              <span style={{width:'10px',height:'10px',background:g.c,transform:'rotate(45deg)'}}></span>
              <span className="mono" style={{fontSize:'10px',letterSpacing:'0.18em',textTransform:'uppercase'}}>{g.nm} <span style={{opacity:.6}}>· PUB seed mix</span></span>
              <span className="mono" style={{marginLeft:'auto',fontSize:'10px',letterSpacing:'0.12em',color:'var(--char)',opacity:.6}}>{items.length}</span>
            </div>
            {items.map(s=>(
              <div className="modrow feat" key={s.slug} onClick={()=>go('species/'+s.slug)} style={{gridTemplateColumns:'1.4fr 1fr 1fr',cursor:'pointer'}}>
                <div><div className="mt">{s.sp}</div><div className="md" style={{fontStyle:'italic'}}>{s.tag} · {s.sec}</div></div>
                <div className="sh-hide"><div style={{fontFamily:'Newsreader',fontSize:'15px'}}>{s.method}</div><div className="mono" style={{fontSize:'10px',letterSpacing:'0.06em',color:'var(--char)',opacity:.7,marginTop:'2px'}}>{s.treat}</div></div>
                <div style={{fontFamily:'Newsreader',fontStyle:'italic',fontSize:'14px',color:'var(--char)'}}>{s.prov}<span className="mono" style={{display:'block',fontStyle:'normal',fontSize:'9.5px',letterSpacing:'0.12em',textTransform:'uppercase',color:'var(--oxblood)',marginTop:'4px'}}>Open note →</span></div>
              </div>
            ))}
          </div>
        );
      })}

      {shownN===0 && <p className="prose" style={{fontStyle:'italic',color:'var(--char)'}}>No species match “{q}” — try a common name like “bluestem” or a genus like “Quercus.”</p>}
      <div className="note"><span className="k">Help us get it right</span>
        If you know Central Texas provenance and propagation better than our notes do — especially through <a href="https://npsot.org/" target="_blank" rel="noopener">NPSOT</a> — we&rsquo;d welcome the correction through the <a href={'https://'+FS_REPO.path} target="_blank" rel="noopener">repository</a>.
      </div>
    </div>
  );
}
function LibraryView({ go }){
  return (
    <div className="view"><div className="sheet">
      <Folio left="Section 04 · R&D Library" right="References · Species Notes" />
      <SectionHead no="04" title="R&D Library"
        deck="Good source material for Central Texas native propagation is harder to find than it should be. This is our working shelf — credited resources we lean on, and our own species notes as we build them out." />

      <div className="eyebrow" style={{margin:'36px 0 14px'}}>Resources &amp; References</div>
      <div className="grid" style={{gridTemplateColumns:'repeat(2,1fr)',marginBottom:'8px'}}>
        {FS_LIB_RESOURCES.map(r=>(
          <a className="card" key={r.t} href={r.url} target="_blank" rel="noopener" style={{color:'var(--ink)',display:'block'}}>
            <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.16em',textTransform:'uppercase',color:'var(--river-deep)',marginBottom:'6px'}}>{r.org}</div>
            <h4>{r.t}</h4>
            <div className="cd" style={{marginTop:'8px'}}>{r.d}</div>
            <div className="mono" style={{fontSize:'10px',letterSpacing:'0.14em',textTransform:'uppercase',color:'var(--char)',opacity:.7,marginTop:'14px'}}>Visit ↗</div>
          </a>
        ))}
      </div>

      <SpeciesShelf go={go}/>
    </div></div>
  );
}

/* ============ ABOUT ============ */
function AboutView({ go }){
  return (
    <div className="view"><div className="sheet">
      <Folio left="Section 05 · About" right="The Institution" />
      <SectionHead no="05" title="About the Station"
        deck="What this place is, who stands behind it, and who supports the work." />
      <div style={{display:'grid',gridTemplateColumns:'1.3fr 1fr',gap:'44px',marginTop:'34px'}} className="land-grid">
        <div className="prose" style={{maxWidth:'none'}}>
          <p className="lead">Short&rsquo;s Resort Field Station (SRFS) is the public face of a roughly 100-acre restoration on a tract above the Lampasas River in the Texas Hill Country.</p>
          <p>The name is a small joke — there is no resort, only a cabin, a river and seven sections of ground shaped by generations of working it — decades of grazing and, later, a hay monoculture that in time crowded out much of what had been native to it. It came into a family&rsquo;s keeping, and the choice was to tend it, in the open, and to organize the work like an institution so that it outlasts any one season.</p>

          <h3>How the land came to us</h3>
          <p>The tract — about 103 acres on the Lampasas — came into the family four generations ago. Our great-grandfather, known to everyone as &ldquo;Short,&rdquo; farmed wheat in Killeen, Texas, until the federal government took his farm in the 1940s to build what became Fort Hood. Displaced, he was granted this ground in Lampasas County and did here what he had always done: he grew wheat for seed, and by reputation some of the highest-quality wheat seed in the region.</p>
          <p>The land he took over was native trees and grasses over heavy cedar. Family accounts have ship-anchor chains strung between two tractors and dragged across the ground to pull every tree out by the roots. Cleared, it became a wheat farm and a steady income for years. In the early 1960s Short built the cabin down by the river with his children — our grandfather and great-aunts. The family home was across the road on separate acreage, where they raised goats and sheep and cut hay; the cabin was the other thing — somewhere to cool off in the Lampasas after a day in the fields. They named it, half in earnest, &ldquo;Short&rsquo;s Resort&rdquo; — the original hand-painted sign was the work of our great-aunts. It has never had running water or electricity; for years propane ran a refrigerator, a stove, a heater and a few lamps, and only remnants of those remain. The outhouse washed away in a flood long ago.</p>

          <h3>Fallow, then leased for grazing</h3>
          <p>When Short retired from farming he let the field go mostly fallow but kept cattle on it under lease. By the standards we hold now it was grazed harder than the ground could carry — the common practice of the day — and there was no fence holding the cattle off the river. The banks eroded, and so did the central drainage corridor; manure ran off, seasonal floods pushed through, and between them larger old trees went down while little new growth came up. Wild pig and white-tailed deer numbers ran unchecked on top of it. When Short passed and our grandfather took over, the land was kept much the same way for years, as it always had been.</p>
          <p>That began to change on a visit to work on the old cabin, when the state of the ground was plain enough to act on. We fenced a hundred feet off the river bank and around the cabin to keep the cattle off the water. It slowed the bank erosion; the overgrazing and the corridor washout on the agricultural plain continued.</p>

          <h3>The Tifton years, and the turn</h3>
          <p>Eventually the cattle came off entirely and our grandfather planted the field in Tifton 85 bermudagrass, on USDA advice at the time — a low-maintenance grass that could be cut for hay and carry a small, steady income. For nearly twenty years it was fertilized and cut and looked the part, but over time it built a monoculture across much of the property — an outcome no one intended — that pushed out the native grasses, shrubs and trees, and with them the dove, quail and raptors that had used the ground.</p>
          <p>Our grandfather passed in 2023 and the land came to my mother. I grew up coming to the cabin with my grandparents — camping, fishing and swimming in the cool Lampasas, and I took my first deer on this ground. Since 2023 I have been building the proposal now underway: clear the Tifton monoculture and return the ground to native trees, grasses and woody shrubs — to bring back the native birds and riparian woodland species, slow the erosion as far as we can and restore the oak prairie and river habitat this stretch of the Hill Country carried for most of its history. Four generations on, the cabin still stands, and the work is only the newest form of tending the same ground.</p>

          <h3>An institution, deliberately</h3>
          <p>The station is organized into departments — Forestry &amp; Fire, Water &amp; Power, Wildlife, Agriculture &amp; Grazing, Hospitality and the Office of the Steward — each with its own seal and section of responsibility. It is smaller than that sounds. But the structure is the point: it makes the work legible, hands it off cleanly and keeps the records honest.</p>
          <div className="note"><span className="k">On names</span>
            You will not find people&rsquo;s names here. The station speaks for the work, not for individuals — for privacy, and because the land does not care who did the planting, only that it was done well.
          </div>
          <h3>How it&rsquo;s supported</h3>
          <p>The restoration is supported by two specific grants. Cost-share comes through the USDA Natural Resources Conservation Service under the <a href={FS_FUNDERS[0].url} target="_blank" rel="noopener">Environmental Quality Incentives Program (NRCS EQIP)</a>, administered by the Lampasas County field office. Grassland conversion is supported by a <a href={FS_FUNDERS[1].url} target="_blank" rel="noopener">Texas Parks &amp; Wildlife Pastures for Upland Birds (PUB)</a> grant — which is turning our Tifton 85 hayfield back into native prairie. Public support leaves a public trail: practices and outcomes are posted in <a onClick={()=>go('journal')} style={{cursor:'pointer'}}>the Field Journal</a> as they&rsquo;re completed.</p>
        </div>
        <div>
          <div style={{display:'flex',justifyContent:'center',marginBottom:'22px'}}>
            <Seal dept={DEPT_BY['steward_star']} size={190}/>
          </div>
          <div className="eyebrow" style={{marginBottom:'12px',textAlign:'center'}}>Our Partners</div>
          <div style={{border:'1px solid var(--ink)',marginBottom:'26px'}}>
            {FS_FUNDERS.map(f=>(
              <a key={f.k} href={f.url} target="_blank" rel="noopener" style={{display:'flex',gap:'14px',alignItems:'center',padding:'14px 16px',borderTop:'1px solid var(--rule-soft)',color:'var(--ink)'}}>
                <AgencyMark kind={f.mark} size={46}/>
                <div>
                  <div className="zilla" style={{fontWeight:900,fontSize:'15px',textTransform:'uppercase'}}>{f.k}</div>
                  <div className="mono" style={{fontSize:'10px',letterSpacing:'0.08em',color:'var(--char)',opacity:.8,marginTop:'3px'}}>{f.program}</div>
                  <div className="mono" style={{fontSize:'9px',letterSpacing:'0.1em',color:'var(--char)',opacity:.6,marginTop:'2px'}}>{f.office} ↗</div>
                </div>
              </a>
            ))}
          </div>
          <div className="eyebrow" style={{marginBottom:'12px',textAlign:'center'}}>The Departments</div>
          <div className="legend">
            {FS_SEALS.DEPTS.map(d=>(
              <div className="lr" key={d.key} style={{gridTemplateColumns:'58px 1fr'}}>
                <Seal dept={d} size={54} title={d.nm}/>
                <div><div className="nm">{d.nm}</div><div className="ds mono" style={{fontStyle:'normal',fontSize:'10px',letterSpacing:'0.12em',textTransform:'uppercase'}}>Section {d.plate} · {d.code}</div></div>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div className="tl-wrap">
        <div className="eyebrow" style={{marginBottom:'6px'}}>A Land History</div>
        <p style={{fontFamily:'Newsreader',fontStyle:'italic',fontSize:'16px',color:'var(--char)',marginBottom:'26px',maxWidth:'640px'}}>Four generations on the same ground — and a project meant to outlast the people running it.</p>
        <ol className="tl">
          {FS_TIMELINE.map(e=>(
            <li className="tl-row" key={e.yr}>
              <div className="tl-yr">{e.yr}</div>
              <div className="tl-body">
                <div className="tl-t">{e.t}</div>
                <div className="tl-d">{e.d}</div>
              </div>
            </li>
          ))}
          <li className="tl-row tl-future">
            <div className="tl-yr">Onward</div>
            <div className="tl-body">
              <div className="tl-t">A multigenerational project</div>
              <div className="tl-d">Later phases work inward for years, and a restored grassland will want fire and care for lifetimes after. We are planting things we will not see finished — and handing the work forward.</div>
              <span className="tl-inf" aria-hidden="true">∞</span>
            </div>
          </li>
        </ol>
      </div>
    </div></div>
  );
}

/* ============ SUPPORT (buried) ============ */
function SupportView({ go }){
  return (
    <div className="view"><div className="sheet">
      <Folio left="Appendix · Get Involved" right="Unlisted" />
      <SectionHead no="—" title="Get Involved"
        deck="This page isn't linked from the main sections — if you found it, thank you for digging." />
      <div className="prose" style={{marginTop:'30px'}}>
        <p>The station mostly needs three things, in this order: <strong>people who use the open plans</strong> and tell us what broke, <strong>native seed and cuttings</strong> from local provenance and — a distant third — <strong>a little money</strong> toward materials the grants don&rsquo;t cover.</p>
        <p>If you want to help, the most useful thing is to take the <a onClick={()=>go('ii')} style={{cursor:'pointer'}}>open source and plans</a>, build something on your own ground and share what you learn. That&rsquo;s the whole point of doing this in the open.</p>
        <div className="note"><span className="k">Materials fund</span>
          There is a small materials fund for fencing, seed and sensor parts. It is intentionally low-key and not a priority — reach out through the repository if you&rsquo;d like to contribute.
        </div>
        <p><a href={'https://'+FS_REPO.path} target="_blank" rel="noopener">Open an issue or say hello on the repository ↗</a></p>
      </div>
    </div></div>
  );
}

function NotFound({ go }){
  return (
    <div className="view"><div className="sheet">
      <Folio left="—" right="Off the map" />
      <SectionHead no="—" title="Off the Map" deck="That page isn't in the atlas. Try the sections below." />
      <div style={{display:'flex',gap:'12px',marginTop:'24px',flexWrap:'wrap'}}>
        <button className="btn solid" onClick={()=>go('home')}>Frontispiece</button>
        <button className="btn" onClick={()=>go('journal')}>Field Journal</button>
      </div>
    </div></div>
  );
}

function creditCaption(c){
  if(!c) return null;
  const who = c.artist && c.artist.trim() ? c.artist : 'Unknown';
  return <span>{c.title} — {who} · {c.license} · <a href={c.source} target="_blank" rel="noopener">Wikimedia Commons ↗</a></span>;
}
function SpeciesPlate({ sp, go }){
  const idx = FS_SPECIES.indexOf(sp);
  const prev = FS_SPECIES[idx-1], next = FS_SPECIES[idx+1];
  const cr = (window.FS_CREDITS||{})[sp.code] || (window.FS_CREDITS||{})[String(sp.code).toLowerCase()] || {};
  const grp = (FS_SP_GROUPS.find(g=>g.id===sp.group)||{}).t || '';
  const quick = [['Difficulty',sp.diff],['Growth rate',sp.growth],['Drought',sp.drought],['Flood',sp.flood],['Wildlife',sp.wildlife],['Deer',sp.deer],['Method',sp.method],['Container',sp.container]];
  const site  = [['Primary',sp.sitePrimary],['Secondary',sp.siteSecondary],['Avoid',sp.siteAvoid],['Soils',sp.soils],['Hydrology',sp.hydrology]];
  const care  = [['Seed collection',sp.seed],['Stratification',sp.strat],['Propagation',sp.prop],['Container progression',sp.progression],['Nursery watering',sp.water],['Light',sp.light],['Outplanting',sp.outplant]];
  const Photo = ({ slot }) => {
    const c = cr[slot];
    if(!c) return null;
    return (
      <figure style={{margin:0,border:'1px solid var(--ink)',background:'var(--paper-3)'}}>
        <img src={spImg(sp.code,slot)} alt={sp.common+' — '+slot} loading="lazy" style={{width:'100%',aspectRatio:'4/3',objectFit:'cover',display:'block',borderBottom:'1px solid var(--ink)'}}/>
        <figcaption className="mono" style={{fontSize:'9px',letterSpacing:'0.06em',color:'var(--char)',padding:'8px 10px',lineHeight:1.5}}>
          <b style={{textTransform:'uppercase',letterSpacing:'0.14em',opacity:.7}}>{slot==='form'?'Form':'Detail'} · </b>{creditCaption(c)}
        </figcaption>
      </figure>
    );
  };
  const Rows = ({ data }) => (
    <div style={{border:'1px solid var(--ink)'}}>
      {data.map((r,i)=>(
        <div key={i} style={{display:'grid',gridTemplateColumns:'150px 1fr',gap:'14px',padding:'10px 14px',borderTop:i?'1px solid var(--rule-soft)':'none'}} className="specrow">
          <span className="mono" style={{fontSize:'9.5px',letterSpacing:'0.12em',textTransform:'uppercase',color:'var(--char)'}}>{r[0]}</span>
          <span style={{fontFamily:'Newsreader',fontSize:'15px',lineHeight:1.45}}>{r[1]}</span>
        </div>
      ))}
    </div>
  );
  return (
    <div className="view"><div className="sheet">
      <Folio left={'Plate '+sp.code+' · Propagation Manual'} right="R&D Library · Species" />
      <div className="entry-head">
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:'20px'}}>
          <div className="eyebrow">Species Plate {sp.code} · {grp}</div>
          <Seal dept={DEPT_BY['forestry_liveoak_bold']} size={96} title="Forestry & Fire"/>
        </div>
        <h1 className="disp" style={{fontSize:'clamp(34px,5vw,60px)'}}>{sp.common}</h1>
        <div className="byline">
          <span style={{fontStyle:'italic',fontFamily:'Newsreader',textTransform:'none',letterSpacing:0,fontSize:'17px'}}>{sp.latin}</span><span className="sep"></span>
          <span>Short&rsquo;s Resort Field Station</span>
        </div>
      </div>

      <div style={{display:'grid',gridTemplateColumns:(cr.form&&cr.detail)?'1fr 1fr':'1fr',gap:'14px',margin:'18px 0 8px'}} className="land-grid">
        <Photo slot="form"/>
        <Photo slot="detail"/>
      </div>

      <div style={{display:'grid',gridTemplateColumns:'1.25fr 1fr',gap:'36px',marginTop:'22px'}} className="land-grid">
        <div className="prose" style={{maxWidth:'none'}}>
          <h3>Restoration Role</h3>
          <p className="lead" style={{fontSize:'19px'}}>{sp.role}</p>
          <h3>Site Suitability</h3>
          <Rows data={site}/>
          <h3 style={{marginTop:'28px'}}>Propagation &amp; Care</h3>
          <Rows data={care}/>
          <h3 style={{marginTop:'28px'}}>Establishment Watering</h3>
          <ul style={{listStyle:'none',margin:'6px 0 8px'}}>
            {sp.establish.map((li,i)=>(
              <li key={i} className="mono" style={{fontSize:'13px',letterSpacing:'0.03em',padding:'8px 0 8px 22px',borderTop:'1px solid var(--rule-soft)',position:'relative',lineHeight:1.5}}>
                <span style={{position:'absolute',left:'3px',top:'14px',width:'7px',height:'7px',background:'var(--ink)',transform:'rotate(45deg)'}}></span>{li}
              </li>
            ))}
          </ul>
          <div className="note"><span className="k">Field notes</span>{sp.notes}</div>
        </div>
        <div>
          <div style={{border:'1px solid var(--ink)',position:'sticky',top:'86px'}}>
            <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.18em',textTransform:'uppercase',background:'var(--ink)',color:'var(--bone)',padding:'9px 14px'}}>Quick Reference</div>
            {quick.map((r,i)=>(
              <div key={i} style={{display:'grid',gridTemplateColumns:'1fr auto',gap:'10px',padding:'9px 14px',borderTop:i?'1px solid var(--rule-soft)':'none',alignItems:'baseline'}}>
                <span className="mono" style={{fontSize:'9.5px',letterSpacing:'0.12em',textTransform:'uppercase',color:'var(--char)'}}>{r[0]}</span>
                <span style={{fontFamily:'Zilla Slab',fontWeight:700,fontSize:'14px',textAlign:'right'}}>{r[1]}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div className="note" style={{marginTop:'26px'}}><span className="k">Sources</span>
        Propagation data from the Short&rsquo;s Resort Native Tree &amp; Shrub Propagation Manual (SR-PROP-01). Photographs via Wikimedia Commons under the licenses noted on each image; credit to the individual photographers above.
      </div>
      <div className="rule-hair"></div>
      <div style={{display:'flex',justifyContent:'space-between',gap:'16px',flexWrap:'wrap'}}>
        <button className="btn" onClick={()=>go('library')}>← R&amp;D Library</button>
        <div style={{display:'flex',gap:'10px'}}>
          {prev && <button className="btn" onClick={()=>go('species/'+prev.slug)}>← {prev.common}</button>}
          {next && <button className="btn" onClick={()=>go('species/'+next.slug)}>{next.common} →</button>}
        </div>
      </div>
    </div></div>
  );
}
function SpeciesPage({ slug, go }){
  const woody = (window.FS_SPECIES||[]).find(x=>x.slug===slug);
  if(woody) return <SpeciesPlate sp={woody} go={go}/>;
  const s = FS_LIB_SPECIES.find(x=>x.slug===slug);
  if(!s) return <NotFound go={go}/>;
  const idx = FS_LIB_SPECIES.indexOf(s);
  const prev = FS_LIB_SPECIES[idx-1], next = FS_LIB_SPECIES[idx+1];
  const spec = [['Section',s.sec],['Method',s.method],['Seed treatment',s.treat],['Provenance',s.prov]];
  return (
    <div className="view"><div className="sheet">
      <Folio left="Section 04 · Species Note" right="R&D Library" />
      <div className="entry-head">
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:'20px'}}>
          <div className="eyebrow">Specimen Note · {s.sec}</div>
          <Seal dept={DEPT_BY['forestry_liveoak_bold']} size={96} title="Forestry & Fire"/>
        </div>
        <h1 className="disp" style={{fontSize:'clamp(34px,5vw,58px)'}}>{s.sp}</h1>
        <div className="byline">
          <span style={{fontStyle:'italic',fontFamily:'Newsreader',textTransform:'none',letterSpacing:0,fontSize:'17px'}}>{s.tag}</span><span className="sep"></span>
          <span>Short&rsquo;s Resort Field Station</span>
        </div>
        <span className="tag" style={{color:'var(--ochre-deep)',borderColor:'var(--ochre-deep)',alignSelf:'flex-start'}}><span className="sw" style={{background:'var(--ochre-deep)'}}></span>Pending NPSOT review</span>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'1.3fr 1fr',gap:'36px',marginTop:'26px'}} className="land-grid">
        <div className="prose" style={{maxWidth:'none'}}>
          <p className="lead">{s.note}</p>
          <div className="note"><span className="k">Status</span>A working first pass, being reconciled against <a href="https://npsot.org/" target="_blank" rel="noopener">NPSOT</a> and <a href="https://plants.usda.gov/" target="_blank" rel="noopener">USDA PLANTS</a>. Corrections welcome through the <a href={'https://'+FS_REPO.path} target="_blank" rel="noopener">repository</a>.</div>
        </div>
        <div>
          <div style={{border:'1px solid var(--ink)'}}>
            <div className="mono" style={{fontSize:'9.5px',letterSpacing:'0.18em',textTransform:'uppercase',background:'var(--ink)',color:'var(--bone)',padding:'9px 14px'}}>Propagation Record</div>
            {spec.map((r,i)=>(
              <div key={i} style={{display:'grid',gridTemplateColumns:'120px 1fr',gap:'12px',padding:'10px 14px',borderTop:i?'1px solid var(--rule-soft)':'none'}}>
                <span className="mono" style={{fontSize:'9.5px',letterSpacing:'0.1em',textTransform:'uppercase',color:'var(--char)'}}>{r[0]}</span>
                <span style={{fontFamily:'Newsreader',fontSize:'15px'}}>{r[1]}</span>
              </div>
            ))}
          </div>
          <div className="mono" style={{fontSize:'10px',letterSpacing:'0.1em',color:'var(--char)',opacity:.7,marginTop:'12px',textAlign:'center'}}>Shareable page &middot; #/species/{s.slug}</div>
        </div>
      </div>
      <div className="rule-hair"></div>
      <div style={{display:'flex',justifyContent:'space-between',gap:'16px',flexWrap:'wrap'}}>
        <button className="btn" onClick={()=>go('library')}>← R&amp;D Library</button>
        <div style={{display:'flex',gap:'10px'}}>
          {prev && <button className="btn" onClick={()=>go('species/'+prev.slug)}>← {prev.sp}</button>}
          {next && <button className="btn" onClick={()=>go('species/'+next.slug)}>{next.sp} →</button>}
        </div>
      </div>
    </div></div>
  );
}

Object.assign(window, { Frontispiece, LandView, JournalView, JournalEntry, InstrumentsView, LibraryView, SpeciesPage, AboutView, SupportView, NotFound });
