/* HaloScape Feedback Hub — components (HaloScape editorial language) */
/* global React, window */

const { useState, useMemo, useEffect, useRef } = React;

// ---------- Icons ----------
const Icon = ({ size = 16, sw = 1.8, fill, children, style, className }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={fill || "none"}
       stroke="currentColor" strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round"
       style={style} className={className}>
    {children}
  </svg>
);
const IChevUp    = (p) => <Icon {...p}><polyline points="18 15 12 9 6 15"/></Icon>;
const IChevDown  = (p) => <Icon {...p}><polyline points="6 9 12 15 18 9"/></Icon>;
const IChevLeft  = (p) => <Icon {...p}><polyline points="15 18 9 12 15 6"/></Icon>;
const IChevRight = (p) => <Icon {...p}><polyline points="9 18 15 12 9 6"/></Icon>;
const ISearch    = (p) => <Icon {...p}><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></Icon>;
const IAttach    = (p) => <Icon {...p}><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></Icon>;
const ICheck     = (p) => <Icon {...p}><polyline points="20 6 9 17 4 12"/></Icon>;
const IX         = (p) => <Icon {...p}><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></Icon>;
const IShield    = (p) => <Icon {...p}><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></Icon>;
const IPlus      = (p) => <Icon {...p}><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></Icon>;
const ITrash     = (p) => <Icon {...p}><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/><path d="M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2"/></Icon>;
const IArrowRight= (p) => <Icon {...p}><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></Icon>;
const ISparkle   = (p) => <Icon {...p}><path d="M12 2l2.09 6.26L20 10l-5.91 1.74L12 18l-2.09-6.26L4 10l5.91-1.74z"/></Icon>;
const IBug       = (p) => <Icon {...p}><rect x="8" y="6" width="8" height="14" rx="4"/><path d="M8 10H5M19 10h-3M8 14H4M20 14h-4M8 18H5M19 18h-3M9 6V4a3 3 0 0 1 6 0v2"/></Icon>;
const IChat      = (p) => <Icon {...p}><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></Icon>;

// ---------- StatusChip ----------
function StatusChip({ status, adminMode }) {
  if (!status || status === 'open') return null;
  // Public view: only show Shipped
  if (!adminMode && status !== 'shipped') return null;
  const map = {
    planned:  { cls: 'chip-planned',  label: 'Planned' },
    progress: { cls: 'chip-progress', label: 'In Progress' },
    shipped:  { cls: 'chip-shipped',  label: 'Shipped' },
    pending:  { cls: 'chip-pending',  label: 'Pending' },
    declined: { cls: 'chip-declined', label: 'Declined' },
  };
  const s = map[status]; if (!s) return null;
  return <span className={`chip ${s.cls}`}><span className="chip-dot"/>{s.label}</span>;
}

// ---------- Top Nav ----------
function TopNav({ boards, currentBoardId, onPick, adminMode, setAdminMode, page, setPage, pendingCount, onAddBoard, onRemoveBoard }) {
  const [addingTab, setAddingTab] = useState(false);
  const [newTabName, setNewTabName] = useState('');
  const [showSignOutConfirm, setShowSignOutConfirm] = useState(false);
  const inputRef = useRef(null);
  useEffect(() => { if (addingTab && inputRef.current) inputRef.current.focus(); }, [addingTab]);

  const publicBoards = adminMode ? boards : boards.filter(b => b.id !== 'bugs');

  const submitAdd = () => {
    const v = newTabName.trim();
    if (v) onAddBoard(v);
    setNewTabName(''); setAddingTab(false);
  };

  return (
    <header className="nav">
      <div className="nav-inner">
        <a className="brand" onClick={() => setPage('hub')}>
          <img src="assets/wordmark-black.png" alt="HaloScape" className="brand-wordmark"/>
        </a>

        <nav className="nav-links">
          {publicBoards.map(b => (
            <button
              key={b.id}
              className={`nav-link ${page === 'hub' && currentBoardId === b.id ? 'on' : ''}`}
              onClick={() => onPick(b.id)}>
              {b.name}
              {adminMode && (
                <span
                  className="nav-tab-remove"
                  onClick={e => { e.stopPropagation(); if (confirm(`Remove "${b.name}" tab?`)) onRemoveBoard(b.id); }}
                  title="Remove tab">
                  <IX size={9} sw={2.8}/>
                </span>
              )}
            </button>
          ))}
          {adminMode && (
            addingTab ? (
              <input
                ref={inputRef}
                value={newTabName}
                placeholder="Tab name…"
                onChange={e => setNewTabName(e.target.value)}
                onBlur={submitAdd}
                onKeyDown={e => {
                  if (e.key === 'Enter') submitAdd();
                  if (e.key === 'Escape') { setAddingTab(false); setNewTabName(''); }
                }}
                style={{height:'32px', padding:'0 12px', fontSize:'13px', borderRadius:'20px', border:'1px solid var(--hairline)', background:'var(--bg)', color:'var(--fg-1)', outline:'none', minWidth:'110px', fontFamily:'inherit'}}
              />
            ) : (
              <button className="nav-link" onClick={() => setAddingTab(true)} title="Add tab" style={{padding:'6px 10px'}}>
                <IPlus size={14} sw={2.4}/>
              </button>
            )
          )}
          {adminMode && (
            <>
              <span className="nav-sep"/>
              <button
                className={`nav-link ${page === 'moderation' ? 'on' : ''}`}
                onClick={() => setPage('moderation')}>
                Moderation
                {pendingCount > 0 && <span className="nav-badge">{pendingCount}</span>}
              </button>
              <button
                className={`nav-link ${page === 'bugs' ? 'on' : ''}`}
                onClick={() => setPage('bugs')}>
                Bug Reports
              </button>
            </>
          )}
        </nav>

        <div className="nav-right">
          {adminMode && (
            <div style={{display:'flex',alignItems:'center',gap:'6px'}}>
              <span style={{
                display:'flex',alignItems:'center',gap:'5px',
                padding:'5px 12px',borderRadius:'20px',
                background:'#1a1a1a',color:'#fff',
                fontSize:'11px',fontWeight:'600',letterSpacing:'0.05em',
                userSelect:'none',
              }}>
                <IShield size={11} sw={2.2}/>
                ADMIN
              </span>
              <button
                onClick={() => setShowSignOutConfirm(true)}
                title="Sign out"
                style={{
                  display:'flex',alignItems:'center',justifyContent:'center',
                  width:'28px',height:'28px',borderRadius:'50%',
                  border:'none',background:'transparent',
                  cursor:'pointer',color:'var(--fg-3)',
                }}>
                <IX size={13} sw={2.4}/>
              </button>
            </div>
          )}
        </div>
      </div>

      {showSignOutConfirm && ReactDOM.createPortal(
        <div style={{position:'fixed',inset:0,background:'rgba(0,0,0,0.4)',zIndex:9999,display:'flex',alignItems:'center',justifyContent:'center'}}
             onClick={() => setShowSignOutConfirm(false)}>
          <div style={{background:'var(--bg)',borderRadius:'20px',padding:'32px',width:'340px',boxShadow:'0 12px 48px rgba(0,0,0,0.22)'}}
               onClick={e => e.stopPropagation()}>
            <div style={{fontWeight:'700',fontSize:'17px',marginBottom:'10px',color:'var(--fg-1)'}}>Sign out of admin?</div>
            <div style={{fontSize:'14px',color:'var(--fg-3)',marginBottom:'28px',lineHeight:'1.5'}}>Your admin session will end and access will be removed.</div>
            <div style={{display:'flex',gap:'8px',justifyContent:'flex-end'}}>
              <button onClick={() => setShowSignOutConfirm(false)}
                style={{padding:'9px 18px',borderRadius:'20px',border:'1px solid var(--hairline)',background:'transparent',cursor:'pointer',fontSize:'13px',color:'var(--fg-2)',fontFamily:'inherit'}}>
                Cancel
              </button>
              <button onClick={() => { setShowSignOutConfirm(false); setAdminMode(false); }}
                style={{padding:'9px 18px',borderRadius:'20px',border:'none',background:'#1a1a1a',color:'#fff',cursor:'pointer',fontSize:'13px',fontWeight:'600',fontFamily:'inherit'}}>
                Sign out
              </button>
            </div>
          </div>
        </div>,
        document.body
      )}
    </header>
  );
}

// ---------- HERO (big editorial band) ----------
function Hero({ onPrimary, onBugReport, heroTitle, adminMode, onEditTitle }) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState('');
  const inputRef = useRef(null);
  useEffect(() => { if (editing && inputRef.current) inputRef.current.focus(); }, [editing]);

  const startEdit = () => { setDraft(heroTitle); setEditing(true); };
  const commitEdit = () => {
    const v = draft.trim();
    if (v && v !== heroTitle) onEditTitle(v);
    setEditing(false);
  };

  return (
    <section className="hero">
      <div className="hero-orb"/>
      <div className="hero-content">
        <h1 className="hero-title" style={{display:'flex', flexDirection:'column', gap:0}}>
          {editing ? (
            <textarea
              ref={inputRef}
              value={draft}
              onChange={e => setDraft(e.target.value)}
              onBlur={commitEdit}
              onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); commitEdit(); } if (e.key === 'Escape') setEditing(false); }}
              style={{font:'inherit', fontSize:'inherit', fontWeight:'inherit', letterSpacing:'inherit', lineHeight:'inherit', background:'transparent', border:'2px solid var(--fg-1)', borderRadius:'8px', padding:'4px 8px', resize:'none', width:'100%', color:'inherit', outline:'none', minHeight:'2em'}}
              rows={2}
            />
          ) : (
            <span style={{display:'flex', alignItems:'flex-start', gap:'10px'}}>
              {heroTitle}
              {adminMode && (
                <button onClick={startEdit} title="Edit title" style={{background:'none', border:'1px solid var(--hairline)', borderRadius:'6px', padding:'2px 8px', fontSize:'12px', color:'var(--fg-3)', cursor:'pointer', flexShrink:0, marginTop:'8px', fontFamily:'inherit'}}>
                  Edit
                </button>
              )}
            </span>
          )}
        </h1>
        <div className="hero-actions">
          <button className="btn btn-primary btn-lg" onClick={onPrimary}>
            Post feedback
          </button>
          <button className="btn btn-ghost-outline" onClick={onBugReport} style={{height:'48px', padding:'0 22px', fontSize:'15px', borderRadius:'var(--radius-pill)'}}>
            <IBug size={15} sw={2}/>
            Report a bug
          </button>
        </div>
      </div>
    </section>
  );
}

// ---------- Board tiles ----------
const BOARD_VISUALS = {
  feedback:        { visual: 'chat',     tint: 'teal'   },
  features:        { visual: 'sparkle',  tint: 'lime'   },
  'feature-requests':{ visual:'sparkle', tint:'lime'    },
  bugs:            { visual: 'bug',      tint: 'peach'  },
  'bug-reports':   { visual: 'bug',      tint: 'peach'  },
};
const DEFAULT_TINTS = ['violet','mint','peach','lime','teal','lilac'];

function BoardTile({ board, postCount, active, onPick, adminMode, onRemove, onRename, index }) {
  const key = board.id;
  const v = BOARD_VISUALS[key] || { visual: 'sparkle', tint: DEFAULT_TINTS[index % DEFAULT_TINTS.length] };
  const [editing, setEditing] = useState(false);
  const [name, setName] = useState(board.name);
  const inputRef = useRef(null);
  useEffect(() => { if (editing && inputRef.current) { inputRef.current.focus(); inputRef.current.select(); } }, [editing]);

  const commit = () => {
    const v = name.trim();
    if (v && v !== board.name) onRename(board.id, v);
    else setName(board.name);
    setEditing(false);
  };

  return (
    <div className={`board-tile tint-${v.tint} ${active ? 'active' : ''}`}
         onClick={() => !editing && onPick(board.id)}>
      <div className="board-tile-visual" data-visual={v.visual}>
        {v.visual === 'sparkle' && <ISparkle size={30} sw={1.6}/>}
        {v.visual === 'bug'     && <IBug     size={30} sw={1.6}/>}
        {v.visual === 'chat'    && <IChat    size={30} sw={1.6}/>}
      </div>
      <div className="board-tile-body">
        {editing ? (
          <input
            ref={inputRef}
            className="board-tile-name-input"
            value={name}
            onChange={(e) => setName(e.target.value)}
            onBlur={commit}
            onKeyDown={(e) => {
              if (e.key === 'Enter') commit();
              if (e.key === 'Escape') { setName(board.name); setEditing(false); }
            }}
            onClick={(e) => e.stopPropagation()}
          />
        ) : (
          <h3 className="board-tile-name"
              onDoubleClick={(e) => { if (adminMode) { e.stopPropagation(); setEditing(true); } }}>
            {board.name}
          </h3>
        )}
        <div className="board-tile-meta">
          <span>{postCount} {postCount === 1 ? 'post' : 'posts'}</span>
          <span className="board-tile-arrow">
            <IArrowRight size={15} sw={2}/>
          </span>
        </div>
      </div>
      {adminMode && (
        <button className="board-tile-remove"
                onClick={(e) => {
                  e.stopPropagation();
                  if (confirm(`Remove "${board.name}" and its posts?`)) onRemove(board.id);
                }}
                title="Remove channel">
          <ITrash size={13} sw={2}/>
        </button>
      )}
    </div>
  );
}

function BoardTiles({ boards, counts, currentId, onPick, adminMode, onRemove, onRename, onAdd }) {
  const [adding, setAdding] = useState(false);
  const [name, setName] = useState('');
  const inputRef = useRef(null);
  useEffect(() => { if (adding && inputRef.current) inputRef.current.focus(); }, [adding]);

  const submit = () => {
    const v = name.trim();
    if (v) onAdd(v);
    setName(''); setAdding(false);
  };

  return (
    <section className="tiles-section">
      <div className="section-head">
        <div>
          <div className="section-eyebrow">Channels</div>
          <h2 className="section-title">Where would you like to post?</h2>
        </div>
        {adminMode && !adding && (
          <button className="btn btn-ghost-outline" onClick={() => setAdding(true)}>
            <IPlus size={14} sw={2.2}/>
            New channel
          </button>
        )}
      </div>

      <div className="board-tiles">
        {boards.map((b, i) => (
          <BoardTile
            key={b.id}
            board={b}
            postCount={counts[b.id] || 0}
            active={b.id === currentId}
            onPick={onPick}
            adminMode={adminMode}
            onRemove={onRemove}
            onRename={onRename}
            index={i}
          />
        ))}
        {adding && (
          <div className="board-tile board-tile-add">
            <div className="board-tile-visual" data-visual="add">
              <IPlus size={28} sw={1.6}/>
            </div>
            <div className="board-tile-body">
              <input
                ref={inputRef}
                className="board-tile-name-input"
                value={name}
                placeholder="Channel name…"
                onChange={(e) => setName(e.target.value)}
                onBlur={submit}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') submit();
                  if (e.key === 'Escape') { setAdding(false); setName(''); }
                }}
              />
              <div className="board-tile-meta">
                <span>Press Enter to add</span>
              </div>
            </div>
          </div>
        )}
      </div>
    </section>
  );
}

// ---------- Submit form (HaloScape form style — labels above, white cards) ----------
const TINT_COLORS = {
  teal: '#8ED8DD', lime: '#D6ED68', peach: '#FFB89A',
  violet: '#C5B6F0', mint: '#9ED9B2', lilac: '#E4B3E8',
};

function SubmitForm({ boardName, boardTint, boardColor, onSubmit, innerRef, formTitle, adminMode, onEditFormTitle, titlePlaceholder, detailsPlaceholder, onEditTitlePlaceholder, onEditDetailsPlaceholder }) {
  const [title, setTitle] = useState('');
  const [details, setDetails] = useState('');
  const [editingTitle, setEditingTitle] = useState(false);
  const [titleDraft, setTitleDraft] = useState('');
  const [editingTitlePH, setEditingTitlePH] = useState(false);
  const [editingDetailsPH, setEditingDetailsPH] = useState(false);
  const [titlePHDraft, setTitlePHDraft] = useState('');
  const [detailsPHDraft, setDetailsPHDraft] = useState('');
  const taRef = useRef(null);
  const titleInputRef = useRef(null);
  useEffect(() => { if (editingTitle && titleInputRef.current) titleInputRef.current.focus(); }, [editingTitle]);

  useEffect(() => {
    if (taRef.current) {
      taRef.current.style.height = 'auto';
      taRef.current.style.height = Math.max(taRef.current.scrollHeight, 100) + 'px';
    }
  }, [details]);

  const submit = (e) => {
    e?.preventDefault();
    if (!title.trim() || !details.trim()) return;
    onSubmit({ title: title.trim(), details: details.trim() });
    setTitle(''); setDetails('');
  };

  const dotColor = boardColor || TINT_COLORS[boardTint] || '#CBD5E1';
  const defaultTitlePH = 'e.g. Battery drains quickly when the orb is animating';
  const defaultDetailsPH = "What's the context? What did you expect? Any details the team should know?";
  const activeTitlePH = titlePlaceholder || defaultTitlePH;
  const activeDetailsPH = detailsPlaceholder || defaultDetailsPH;

  return (
    <section className="submit-section" ref={innerRef}>
      <div className="section-head">
        <div>
          <div className="section-eyebrow submit-channel-eyebrow">
            <span className="submit-channel-dot" style={{background: dotColor}}/>
            Post to · {boardName}
          </div>
          {editingTitle ? (
            <input
              ref={titleInputRef}
              className="section-title"
              value={titleDraft}
              onChange={e => setTitleDraft(e.target.value)}
              onBlur={() => { if (titleDraft.trim()) onEditFormTitle(titleDraft.trim()); setEditingTitle(false); }}
              onKeyDown={e => { if (e.key === 'Enter') { if (titleDraft.trim()) onEditFormTitle(titleDraft.trim()); setEditingTitle(false); } if (e.key === 'Escape') setEditingTitle(false); }}
              style={{font:'inherit', fontSize:'inherit', fontWeight:'inherit', letterSpacing:'inherit', background:'transparent', border:'1px solid var(--hairline)', borderRadius:'6px', padding:'2px 8px', width:'100%', outline:'none'}}
            />
          ) : (
            <h2 className="section-title" style={{display:'flex', alignItems:'center', gap:'10px'}}>
              {formTitle || "Tell us what you're thinking"}
              {adminMode && (
                <button onClick={() => { setTitleDraft(formTitle || "Tell us what you're thinking"); setEditingTitle(true); }} style={{background:'none', border:'1px solid var(--hairline)', borderRadius:'6px', padding:'2px 8px', fontSize:'12px', color:'var(--fg-3)', cursor:'pointer', fontFamily:'inherit', flexShrink:0}}>
                  Edit heading
                </button>
              )}
              {adminMode && (
                <button onClick={() => { setTitlePHDraft(activeTitlePH); setDetailsPHDraft(activeDetailsPH); setEditingTitlePH(true); setEditingDetailsPH(true); }} style={{background:'none', border:'1px solid var(--hairline)', borderRadius:'6px', padding:'2px 8px', fontSize:'12px', color:'var(--fg-3)', cursor:'pointer', fontFamily:'inherit', flexShrink:0}}>
                  Edit fields
                </button>
              )}
            </h2>
          )}
        </div>
      </div>
      <form className="form-card" onSubmit={submit}>
        <div className="form-field">
          <label className="form-label">Short, descriptive title</label>
          {adminMode && editingTitlePH ? (
            <input
              className="form-input"
              value={titlePHDraft}
              autoFocus
              onChange={e => setTitlePHDraft(e.target.value)}
              onBlur={() => { onEditTitlePlaceholder(titlePHDraft); setEditingTitlePH(false); }}
              onKeyDown={e => { if (e.key === 'Enter') { onEditTitlePlaceholder(titlePHDraft); setEditingTitlePH(false); } if (e.key === 'Escape') setEditingTitlePH(false); }}
              style={{fontStyle:'italic', color:'var(--fg-3)'}}
            />
          ) : (
            <input
              className="form-input"
              placeholder={activeTitlePH}
              value={title}
              maxLength={300}
              onChange={e => setTitle(e.target.value)}
              onDoubleClick={() => { if (adminMode) { setTitlePHDraft(activeTitlePH); setEditingTitlePH(true); } }}
              required
            />
          )}
          {title.length > 260 && <div style={{fontSize:'11px', color: title.length >= 300 ? 'var(--danger)' : 'var(--fg-4)', textAlign:'right', marginTop:'4px'}}>{title.length}/300</div>}
        </div>

        <div className="form-field">
          <label className="form-label">Details</label>
          {adminMode && editingDetailsPH ? (
            <textarea
              className="form-textarea"
              value={detailsPHDraft}
              autoFocus
              onChange={e => setDetailsPHDraft(e.target.value)}
              onBlur={() => { onEditDetailsPlaceholder(detailsPHDraft); setEditingDetailsPH(false); }}
              onKeyDown={e => { if (e.key === 'Escape') setEditingDetailsPH(false); }}
              style={{fontStyle:'italic', color:'var(--fg-3)'}}
              rows={3}
            />
          ) : (
            <textarea
              ref={taRef}
              className="form-textarea"
              placeholder={activeDetailsPH}
              value={details}
              maxLength={3000}
              onChange={e => setDetails(e.target.value)}
              onDoubleClick={() => { if (adminMode) { setDetailsPHDraft(activeDetailsPH); setEditingDetailsPH(true); } }}
              required
            />
          )}
          {details.length > 2700 && <div style={{fontSize:'11px', color: details.length >= 3000 ? 'var(--danger)' : 'var(--fg-4)', textAlign:'right', marginTop:'4px'}}>{details.length}/3000</div>}
        </div>

        <div className="form-actions">
          <div className="form-note">
            Your post is <strong>anonymous</strong>. New posts appear after a brief review.
          </div>
          <button type="submit" className="btn btn-primary btn-pill" disabled={!title.trim() || !details.trim()}>
            Submit
            <IArrowRight size={14} sw={2.4}/>
          </button>
        </div>
      </form>
    </section>
  );
}

// ---------- Vote orb ----------
function VoteOrb({ voted, votes, onClick, size = 'sm' }) {
  const fmt = votes >= 1000 ? (votes/1000).toFixed(1)+'K' : votes;
  const cls = size === 'lg' ? 'vote vote-lg' : 'vote';
  return (
    <button
      className={`${cls} ${voted ? 'voted' : ''}`}
      onClick={onClick}
      title={voted ? 'Remove upvote' : 'Upvote'}>
      <span className="vote-halo"/>
      <IChevUp className="vote-arrow" size={size === 'lg' ? 20 : 13} sw={2.4}/>
      <span className="vote-count">{fmt}</span>
    </button>
  );
}

// ---------- Post Card (grid) ----------
function PostCard({ post, voted, onVote, onOpen, boardLabel, boardTint, adminMode }) {
  return (
    <article className={`post-card tint-${boardTint || 'teal'}`} onClick={() => onOpen && onOpen(post.id)} style={{cursor: onOpen ? 'pointer' : 'default'}}>
      <div className="post-card-top">
        <VoteOrb
          voted={voted}
          votes={post.votes}
          onClick={(e) => { e.stopPropagation(); onVote(post.id); }}
        />
        <div className="post-card-meta">
          <span className="post-card-board">{boardLabel}</span>
          {post.status && post.status !== 'open' && <StatusChip status={post.status} adminMode={adminMode}/>}
        </div>
      </div>
      <h3 className="post-card-title">{post.title}</h3>
      {post.details && <p className="post-card-desc">{post.details}</p>}
    </article>
  );
}

// ---------- List head (sort + search) ----------
function ListHead({ sort, setSort, query, setQuery, count, boardName }) {
  const SORT_LABELS = { trending: 'Trending', newest: 'Newest', top: 'Most voted' };
  return (
    <div className="list-head">
      <div>
        <div className="section-eyebrow">{boardName} · {count} {count === 1 ? 'post' : 'posts'}</div>
        <h2 className="section-title">What others are asking for</h2>
      </div>
      <div className="list-head-controls">
        <div className="sort-pill">
          <span className="sort-pill-label">Sort</span>
          <span className="sort-pill-value">{SORT_LABELS[sort]}</span>
          <IChevDown size={12} sw={2.2}/>
          <select
            value={sort}
            onChange={e => setSort(e.target.value)}
            style={{position:'absolute',inset:0,opacity:0,cursor:'pointer',width:'100%',height:'100%',appearance:'none',border:0,fontSize:'inherit'}}>
            <option value="trending">Trending</option>
            <option value="newest">Newest</option>
            <option value="top">Most voted</option>
          </select>
        </div>
        <div className="search-pill">
          <ISearch size={15}/>
          <input
            placeholder="Search posts…"
            value={query}
            onChange={e => setQuery(e.target.value)}/>
        </div>
      </div>
    </div>
  );
}

// ---------- Post Detail Modal ----------
function PostModal({ post, voted, onVote, onClose, boardLabel, boardTint, onComment, adminMode }) {
  const [commentText, setCommentText] = useState('');
  const [submitted, setSubmitted] = useState(false);

  const submitComment = () => {
    if (!commentText.trim()) return;
    onComment(post.id, commentText);
    setCommentText('');
    setSubmitted(true);
    setTimeout(() => setSubmitted(false), 2000);
  };

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = '';
    };
  }, [onClose]);

  if (!post) return null;
  const votesFmt = post.votes >= 1000 ? (post.votes/1000).toFixed(1)+'K' : post.votes;
  const statusLabel = {
    open: 'Open', planned: 'Planned', progress: 'In Progress', shipped: 'Shipped'
  }[post.status || 'open'] || 'Open';

  return (
    <div className="modal-scrim" onClick={onClose}>
      <div className={`modal tint-${boardTint || 'teal'}`} onClick={(e) => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose}><IX size={18} sw={2}/></button>

        <div className="modal-hero">
          <div className="modal-hero-orb"/>
          <div className="modal-hero-inner">
            <div className="detail-eyebrow">
              <span className="mark"/> {boardLabel}
            </div>
            <h1 className="modal-title">{post.title}</h1>
            <div className="detail-meta">
              {adminMode && <span className="anon">{post.email || 'No email provided'}</span>}
              {post.status && post.status !== 'open' && (
                <>
                  <span className="dot-sep"/>
                  <StatusChip status={post.status}/>
                </>
              )}
            </div>
          </div>
        </div>

        <div className="modal-body">
          <div className="modal-col-main">
            {post.details && (
              <div className="modal-section">
                <div className="section-eyebrow">The submission</div>
                <p className="modal-body-text">{post.details}</p>
              </div>
            )}
          </div>

          <aside className="modal-col-side">
            {!adminMode && (
              <div className="side-card">
                <div className="section-eyebrow">Signal</div>
                <div style={{display:'flex', alignItems:'center', gap:'14px', marginBottom:'12px'}}>
                  <VoteOrb voted={voted} votes={post.votes} onClick={() => onVote(post.id)}/>
                  <div>
                    <div style={{fontSize:'22px', fontWeight:'600', letterSpacing:'-0.02em', lineHeight:1}}>{votesFmt}</div>
                    <div style={{fontSize:'12px', color:'var(--fg-3)', marginTop:'3px'}}>upvotes</div>
                  </div>
                </div>
                <button className={`btn btn-pill btn-block ${voted ? 'btn-secondary' : 'btn-primary'}`} onClick={() => onVote(post.id)} style={{height:'36px', fontSize:'13px'}}>
                  {voted ? 'Remove upvote' : 'Upvote this'}
                </button>
                <div style={{borderTop:'1px solid var(--hairline)', marginTop:'14px', paddingTop:'2px'}}>
                  <div className="side-row">
                    <span className="side-k">Status</span>
                    <span className="side-v">{statusLabel}</span>
                  </div>
                  <div className="side-row">
                    <span className="side-k">Channel</span>
                    <span className="side-v">{boardLabel}</span>
                  </div>
                </div>
              </div>
            )}
            {adminMode && (
              <div className="side-card">
                <div className="side-row">
                  <span className="side-k">Status</span>
                  <span className="side-v">{statusLabel}</span>
                </div>
                <div className="side-row">
                  <span className="side-k">Channel</span>
                  <span className="side-v">{boardLabel}</span>
                </div>
                <div className="side-row">
                  <span className="side-k">Email</span>
                  {post.email
                    ? <span className="side-v" style={{fontSize:'13px', wordBreak:'break-all'}}>{post.email}</span>
                    : <span className="side-v" style={{color:'var(--fg-4)'}}>Not provided</span>
                  }
                </div>
              </div>
            )}
          </aside>
        </div>
      </div>
    </div>
  );
}

// ---------- Moderation Page ----------
function ModerationPage({ posts, boards, onSet, onSetStatus, onOpen, onBack, adminMode }) {
  const [filter, setFilter] = useState(adminMode ? 'pending' : 'approved');
  const [boardFilter, setBoardFilter] = useState('all');

  const toggleExpand = (id) => {
    if (onOpen) onOpen(id);
  };

  const filtered = useMemo(() => {
    let rows = posts;
    if (!adminMode) rows = rows.filter(p => p.moderation === 'approved');
    else {
      if (filter === 'pending')  rows = rows.filter(p => p.moderation === 'pending' || !p.moderation);
      if (filter === 'approved') rows = rows.filter(p => p.moderation === 'approved');
      if (filter === 'declined') rows = rows.filter(p => p.moderation === 'declined');
    }
    if (boardFilter !== 'all') rows = rows.filter(p => p.boardId === boardFilter);
    return [...rows].sort((a,b) => new Date(b.createdAt) - new Date(a.createdAt));
  }, [posts, filter, boardFilter, adminMode]);

  const channelPosts = boardFilter === 'all' ? posts : posts.filter(p => p.boardId === boardFilter);
  const pendingCount   = posts.filter(p => p.moderation === 'pending' || !p.moderation).length;
  const approvedCount  = channelPosts.filter(p => p.moderation === 'approved').length;
  const declinedCount  = channelPosts.filter(p => p.moderation === 'declined').length;
  const pendingCountCh = channelPosts.filter(p => p.moderation === 'pending' || !p.moderation).length;
  const counts = { pending: pendingCountCh, approved: approvedCount, declined: declinedCount };

  const STATUS_OPTS = [
    { k: 'open',     label: 'None' },
    { k: 'planned',  label: 'Planned' },
    { k: 'progress', label: 'In Progress' },
    { k: 'shipped',  label: 'Shipped' },
  ];

  return (
    <div className="page-moderation">
      <section className="hero hero-compact">
        <div className="hero-orb"/>
        <div className="hero-content">
          <div className="hero-eyebrow">
            <span className="hero-eyebrow-dot"/>
            {adminMode ? 'Admin · Moderation queue' : 'Roadmap'}
          </div>
          <h1 className="hero-title">
            {adminMode
              ? <><em>{pendingCount}</em> {pendingCount === 1 ? 'post needs' : 'posts need'} a decision</>
              : 'See what we\'re working on'}
          </h1>
          <p className="hero-lede">
            {adminMode
              ? 'Approve to publish into the public hub, or decline to keep it internal. No email is ever sent to the submitter either way.'
              : 'Track the status of your feedback — from planned to shipped.'}
          </p>
        </div>
      </section>

      <div className="mod-channel-tabs-wrap">
        <div className="mod-channel-tabs">
          <button
            className={`mod-channel-tab ${boardFilter === 'all' ? 'on' : ''}`}
            onClick={() => setBoardFilter('all')}>
            All
            {pendingCount > 0 && <span className="mod-channel-badge">{pendingCount}</span>}
          </button>
          {boards.map(b => {
            const bPending = posts.filter(p => p.boardId === b.id && (p.moderation === 'pending' || !p.moderation)).length;
            return (
              <button
                key={b.id}
                className={`mod-channel-tab ${boardFilter === b.id ? 'on' : ''}`}
                onClick={() => setBoardFilter(b.id)}>
                {b.name}
                {bPending > 0 && <span className="mod-channel-badge">{bPending}</span>}
              </button>
            );
          })}
        </div>
      </div>

      {adminMode && (
        <div className="mod-controls">
          <div className="seg-pill">
            {['pending','approved','declined'].map(f => (
              <button key={f}
                      className={filter === f ? 'on' : ''}
                      onClick={() => setFilter(f)}>
                {f.charAt(0).toUpperCase()+f.slice(1)}
                <span className="seg-count">{counts[f]}</span>
              </button>
            ))}
          </div>
        </div>
      )}

      {filtered.length === 0 ? (
        <div className="empty-card">
          <div className="empty-big">Nothing to moderate here</div>
          <p>You're all caught up.</p>
        </div>
      ) : (
        <div className="mod-list">
          {filtered.map(p => {
            const board = boards.find(b => b.id === p.boardId);
            return (
              <article key={p.id} className="mod-row">
                <div className="mod-row-main" onClick={() => toggleExpand(p.id)} style={{cursor:'pointer'}}>
                  <div className="mod-row-meta">
                    <span className="mod-row-chan">{board?.name || '—'}</span>
                    <span className="mod-row-sep"/>
                    <span className="mod-row-date">{new Date(p.createdAt).toLocaleDateString(undefined, {month:'short', day:'numeric'})}</span>
                    <span className="mod-row-sep"/>
                    <span className="mod-row-votes">{p.votes} upvotes</span>
                    {p.moderation && p.moderation !== 'pending' && <StatusChip status={p.moderation}/>}
                  </div>
                  <h3 className="mod-row-title">{p.title}</h3>
                  {p.details && (
                    <p className="mod-row-desc">{p.details}</p>
                  )}
                  {adminMode && p.email && (
                    <span style={{fontSize:'12px',color:'var(--fg-4)',marginTop:'4px',display:'inline-block'}}>✉ {p.email}</span>
                  )}
                </div>
                {adminMode && (
                  <div className="mod-row-actions">
                    <div className="mod-action-group">
                      <div className="mod-action-label">Decision</div>
                      <div className="mod-action-buttons">
                        <button
                          className={`mod-btn mod-btn-approve ${p.moderation === 'approved' ? 'on' : ''}`}
                          onClick={() => onSet(p.id, p.moderation === 'approved' ? null : 'approved')}>
                          <ICheck size={14} sw={2.8}/> Approve
                        </button>
                        <button
                          className={`mod-btn mod-btn-decline ${p.moderation === 'declined' ? 'on' : ''}`}
                          onClick={() => onSet(p.id, p.moderation === 'declined' ? null : 'declined')}>
                          <IX size={14} sw={2.8}/> Decline
                        </button>
                      </div>
                    </div>
                    <div className="mod-action-group">
                      <div className="mod-action-label">Public status</div>
                      <div className="mod-status-seg">
                        {STATUS_OPTS.map(o => (
                          <button key={o.k}
                                  className={(p.status === o.k || (!p.status && o.k === 'open')) ? 'on' : ''}
                                  onClick={() => onSetStatus(p.id, o.k)}>
                            {o.label}
                          </button>
                        ))}
                      </div>
                    </div>
                  </div>
                )}
                {!adminMode && p.status && p.status !== 'open' && (
                  <div style={{padding:'12px 16px 12px 0'}}>
                    <StatusChip status={p.status} adminMode={false}/>
                  </div>
                )}
              </article>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ---------- Tweaks Panel ----------
function TweaksPanel({ tweaks, setTweaks, visible }) {
  if (!visible) return null;
  const set = (k, v) => setTweaks({ ...tweaks, [k]: v });
  return (
    <div className="tweaks">
      <div className="tweaks-head">
        <span className="dot"/> Tweaks
      </div>

      <div className="tweak-row">
        <div className="tweak-label">Theme</div>
        <div className="tweak-segment">
          <button className={tweaks.mode === 'light' ? 'on' : ''} onClick={() => set('mode','light')}>Light</button>
          <button className={tweaks.mode === 'dark' ? 'on' : ''} onClick={() => set('mode','dark')}>Dark</button>
        </div>
      </div>

      <div className="tweak-row">
        <div className="tweak-label">Accent</div>
        <div className="tweak-swatches">
          {['ink','halo','teal','plum'].map(c => (
            <div key={c} className={`tweak-swatch ${tweaks.accent === c ? 'on' : ''}`}
                 data-c={c} onClick={() => set('accent', c)} title={c}/>
          ))}
        </div>
      </div>

      <div className="tweak-row">
        <div className="tweak-label">Layout</div>
        <div className="tweak-segment">
          <button className={tweaks.layout === 'grid' ? 'on' : ''} onClick={() => set('layout','grid')}>Grid</button>
          <button className={tweaks.layout === 'list' ? 'on' : ''} onClick={() => set('layout','list')}>List</button>
        </div>
      </div>

      <div className="tweak-row">
        <div className="tweak-label">Admin moderation</div>
        <div className="tweak-segment">
          <button className={!tweaks.adminMode ? 'on' : ''} onClick={() => set('adminMode', false)}>Public</button>
          <button className={tweaks.adminMode ? 'on' : ''} onClick={() => set('adminMode', true)}>Admin</button>
        </div>
      </div>

      <div className="tweaks-hint">
        Admin unlocks the Moderation tab and channel management — add, rename, remove.
      </div>
    </div>
  );
}

// ---------- Email Capture Modal ----------
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function EmailCaptureModal({ onClose, onSubmit, isBugReport }) {
  const [email, setEmail] = useState('');
  const [sent, setSent] = useState(false);
  const [emailError, setEmailError] = useState('');

  const submit = () => {
    const v = email.trim();
    if (!v) { onClose(); return; }
    if (!EMAIL_RE.test(v)) { setEmailError('Please enter a valid email address.'); return; }
    setEmailError('');
    onSubmit(v);
    setSent(true);
    setTimeout(onClose, 1800);
  };

  return (
    <div className="email-modal-wrap" onClick={onClose}>
      <div className="email-modal" onClick={e => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose}><IX size={18} sw={2}/></button>
        <div className="email-modal-orb"/>
        {sent ? (
          <>
            <h2 className="email-modal-title">Got it — thanks!</h2>
            <p className="email-modal-sub">We'll let you know when your feedback ships.</p>
          </>
        ) : (
          <>
            <h2 className="email-modal-title">Want to stay in the loop?</h2>
            <p className="email-modal-sub">{!isBugReport && 'Your feedback will be shared anonymously. '}If you want to be notified about updates you can leave your email.</p>
            <div className="email-modal-row">
              <input
                className={`email-input ${emailError ? 'input-error' : ''}`}
                type="text"
                placeholder="you@example.com"
                value={email}
                onChange={e => { setEmail(e.target.value); if (emailError) setEmailError(''); }}
                onKeyDown={e => { if (e.key === 'Enter') submit(); }}
                autoFocus
              />
              <button className="btn btn-primary btn-pill" onClick={submit} style={{whiteSpace:'nowrap'}}>
                Notify me
              </button>
            </div>
            {emailError && <p className="email-error-msg">{emailError}</p>}
            <button className="email-modal-skip" onClick={onClose}>Skip — feedback submitted either way</button>
          </>
        )}
      </div>
    </div>
  );
}

// ---------- Bug Report Public Section ----------
function BugReportSection({ currentBoardId, onSubmit }) {
  const [open, setOpen] = useState(false);
  const [title, setTitle] = useState('');
  const [details, setDetails] = useState('');
  const [file, setFile] = useState(null);
  const fileRef = useRef(null);
  const taRef = useRef(null);

  useEffect(() => {
    if (taRef.current) {
      taRef.current.style.height = 'auto';
      taRef.current.style.height = Math.max(taRef.current.scrollHeight, 80) + 'px';
    }
  }, [details]);

  const submit = (e) => {
    e?.preventDefault();
    if (!title.trim()) return;
    onSubmit({ title: title.trim(), details: details.trim(), fileName: file?.name });
    setTitle(''); setDetails(''); setFile(null); setOpen(false);
  };

  return (
    <section className="bug-report-section">
      <div className="bug-report-head">
        <div className="bug-report-badge">
          <span className="bug-icon-dot"/>
          Report a bug
        </div>
        {!open && (
          <button className="btn btn-ghost-outline" style={{height:'34px', fontSize:'13px'}} onClick={() => setOpen(true)}>
            <IBug size={14} sw={2}/>
            Open report
          </button>
        )}
      </div>

      {!open ? (
        <p style={{fontSize:'14px', color:'var(--fg-3)', margin:0}}>
          Found something broken? Report it here — the team reviews every bug internally.
        </p>
      ) : (
        <form onSubmit={submit} style={{display:'flex', flexDirection:'column', gap:'16px'}}>
          <div className="form-field">
            <label className="form-label">What's broken?</label>
            <input className="form-input" placeholder="e.g. App crashes when opening sleep chart" value={title} onChange={e => setTitle(e.target.value)} required/>
          </div>
          <div className="form-field">
            <label className="form-label">Details <span className="form-optional">— steps to reproduce, device, version</span></label>
            <textarea ref={taRef} className="form-textarea" placeholder="Describe what happened and what you expected…" value={details} onChange={e => setDetails(e.target.value)}/>
          </div>
          <div className="form-field">
            <label className="form-label">Attach a file <span className="form-optional">— screenshot or recording, optional</span></label>
            <div style={{display:'flex', alignItems:'center', gap:'10px'}}>
              <button type="button" className="form-attach" onClick={() => fileRef.current?.click()}>
                <IAttach size={15}/>
                {file ? file.name : 'Choose file'}
              </button>
              {file && <button type="button" className="btn btn-ghost" style={{height:'32px', fontSize:'12px', padding:'0 10px'}} onClick={() => setFile(null)}>Remove</button>}
            </div>
            <input ref={fileRef} type="file" style={{display:'none'}} accept="image/*,video/*,.pdf" onChange={e => setFile(e.target.files[0] || null)}/>
          </div>
          <div className="form-actions">
            <button type="button" className="btn btn-ghost" onClick={() => { setOpen(false); setTitle(''); setDetails(''); setFile(null); }}>Cancel</button>
            <div className="form-note" style={{flex:1}}>Internal only — not visible to other users.</div>
            <button type="submit" className="btn btn-primary btn-pill" disabled={!title.trim()}>
              Submit bug <IArrowRight size={14} sw={2.4}/>
            </button>
          </div>
        </form>
      )}
    </section>
  );
}

// ---------- Bug Reports Admin Page ----------
function BugReportsPage({ posts, onSetStatus, onOpen, adminMode }) {
  const bugPosts = posts.filter(p => p.boardId === 'bugs');
  const [statusFilter, setStatusFilter] = useState('all');
  const [selectedBug, setSelectedBug] = useState(null);

  const STATUS_OPTS = [
    { k: 'open',     label: 'Open' },
    { k: 'planned',  label: 'Investigating' },
    { k: 'progress', label: 'In Progress' },
    { k: 'shipped',  label: 'Fixed' },
  ];

  const filtered = useMemo(() => {
    let rows = statusFilter === 'all' ? bugPosts
      : bugPosts.filter(p => statusFilter === 'open' ? (!p.status || p.status === 'open') : p.status === statusFilter);
    return [...rows].sort((a,b) => new Date(b.createdAt) - new Date(a.createdAt));
  }, [bugPosts, statusFilter]);

  const counts = { all: bugPosts.length };
  STATUS_OPTS.forEach(o => {
    counts[o.k] = o.k === 'open'
      ? bugPosts.filter(p => !p.status || p.status === 'open').length
      : bugPosts.filter(p => p.status === o.k).length;
  });

  if (selectedBug) {
    const attachments = selectedBug.attachments || [];
    const cleanDetails = selectedBug.details ? selectedBug.details.replace(/\n\nAttachment:.*$/s, '').trim() : '';
    const statusLabel = { open:'Open', planned:'Investigating', progress:'In Progress', shipped:'Fixed' }[selectedBug.status || 'open'] || 'Open';
    return (
      <div className="page-bugs">
        <div className="bug-detail-wrap">
          <button className="survey-back-btn" onClick={() => setSelectedBug(null)}><IChevLeft size={14} sw={2}/> All bugs</button>
          <div className="bug-detail-card">
            <div className="mod-row-meta" style={{marginBottom:'12px'}}>
              <span className="mod-row-date">{new Date(selectedBug.createdAt).toLocaleDateString(undefined, {month:'short', day:'numeric', year:'numeric'})}</span>
              <span className="mod-row-sep"/>
              <span className="mod-row-votes">{selectedBug.votes} upvotes</span>
              {selectedBug.status && <StatusChip status={selectedBug.status} adminMode={true}/>}
            </div>
            <h2 className="bug-detail-title">{selectedBug.title}</h2>
            {cleanDetails && <p className="bug-detail-body">{cleanDetails}</p>}
            {attachments.length > 0 && (
              <div className="bug-detail-section">
                <div className="section-eyebrow" style={{marginBottom:'8px'}}>Attachments</div>
                {attachments.map((att, i) => {
                  const name = typeof att === 'string' ? att : att.name;
                  const url  = typeof att === 'string' ? null : att.url;
                  const type = typeof att === 'string' ? '' : (att.type || '');
                  if (url && type.startsWith('image/')) {
                    return (
                      <div key={i} style={{marginBottom:'12px'}}>
                        <a href={url} target="_blank" rel="noopener">
                          <img src={url} alt={name} style={{maxWidth:'100%',borderRadius:'10px',display:'block',cursor:'pointer'}}/>
                        </a>
                        <span style={{fontSize:'12px',color:'var(--fg-4)',marginTop:'4px',display:'block'}}>{name}</span>
                      </div>
                    );
                  }
                  if (url && type.startsWith('video/')) {
                    return (
                      <div key={i} style={{marginBottom:'12px'}}>
                        <video src={url} controls style={{maxWidth:'100%',borderRadius:'10px',display:'block'}}/>
                        <span style={{fontSize:'12px',color:'var(--fg-4)',marginTop:'4px',display:'block'}}>{name}</span>
                      </div>
                    );
                  }
                  if (url) {
                    return (
                      <a key={i} href={url} target="_blank" rel="noopener"
                        style={{display:'flex',alignItems:'center',gap:'8px',padding:'10px 14px',borderRadius:'10px',border:'1px solid var(--hairline)',marginBottom:'8px',fontSize:'13px',color:'var(--fg-1)',textDecoration:'none'}}>
                        <IAttach size={14} sw={2} style={{flexShrink:0}}/>
                        <span style={{flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{name}</span>
                        <IArrowRight size={13} sw={2} style={{flexShrink:0,color:'var(--fg-4)'}}/>
                      </a>
                    );
                  }
                  return (
                    <div key={i} className="bug-attach-row">
                      <IAttach size={14} sw={2}/>
                      <span>{name}</span>
                    </div>
                  );
                })}
              </div>
            )}
            <div className="bug-detail-section">
              <div className="section-eyebrow" style={{marginBottom:'8px'}}>Submitter</div>
              <div className="bug-detail-meta-row">
                <span className="side-k">Email</span>
                {selectedBug.email
                  ? <span className="side-v" style={{fontSize:'14px'}}>{selectedBug.email}</span>
                  : <span className="side-v" style={{color:'var(--fg-4)'}}>Not provided</span>
                }
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="page-bugs">
      <section className="hero hero-compact">
        <div className="hero-orb"/>
        <div className="hero-content">
          <div className="hero-eyebrow">
            <span className="hero-eyebrow-dot"/>
            Admin · Bug Reports
          </div>
          <h1 className="hero-title" style={{fontSize:'44px'}}>
            <em style={{fontStyle:'normal'}}>{bugPosts.length}</em> bug {bugPosts.length === 1 ? 'report' : 'reports'}
          </h1>
          <p className="hero-lede" style={{fontSize:'15px', marginBottom:0}}>
            Internal only — never shown on the public hub. Track status and view details.
          </p>
        </div>
      </section>

      <div className="mod-controls">
        <div className="seg-pill">
          {[{k:'all',label:'All'}, ...STATUS_OPTS].map(f => (
            <button key={f.k} className={statusFilter === f.k ? 'on' : ''} onClick={() => setStatusFilter(f.k)}>
              {f.label}
              <span className="seg-count">{counts[f.k] || 0}</span>
            </button>
          ))}
        </div>
      </div>

      {filtered.length === 0 ? (
        <div className="empty-card">
          <div className="empty-big">No bugs here</div>
          <p>Bug reports will appear here when submitted.</p>
        </div>
      ) : (
        <div className="bugs-list">
          {filtered.map(p => (
            <article key={p.id} className="bug-row">
              <div className="bug-row-main" onClick={() => setSelectedBug(p)}>
                <div className="mod-row-meta">
                  <span className="mod-row-chan">Bug</span>
                  <span className="mod-row-sep"/>
                  <span className="mod-row-date">{new Date(p.createdAt).toLocaleDateString(undefined, {month:'short', day:'numeric'})}</span>
                  <span className="mod-row-sep"/>
                  <span className="mod-row-votes">{p.votes} upvotes</span>
                  <StatusChip status={p.status}/>
                </div>
                <h3 className="mod-row-title">{p.title}</h3>
                {p.details && <p className="mod-row-desc">{p.details}</p>}
              </div>
              {adminMode && (
                <div className="bug-row-actions">
                  <div className="mod-action-label">Status</div>
                  <div className="mod-status-seg">
                    {STATUS_OPTS.map(o => (
                      <button key={o.k}
                              className={(!p.status && o.k === 'open') || p.status === o.k ? 'on' : ''}
                              onClick={(e) => { e.stopPropagation(); onSetStatus(p.id, o.k); }}>
                        {o.label}
                      </button>
                    ))}
                  </div>
                </div>
              )}
            </article>
          ))}
        </div>
      )}
    </div>
  );
}

// ---------- Survey (multi-topic) ----------
function SurveyForm({ topic, onSubmit, onBack }) {
  const [step, setStep] = useState(1);
  const [score, setScore] = useState(null);
  const [text, setText] = useState('');

  const handleScore = (s) => { setScore(s); setTimeout(() => setStep(2), 280); };
  const handleSubmit = () => {
    onSubmit({ score, text, date: new Date().toISOString() });
    setStep(3);
  };

  if (step === 3) {
    return (
      <div className="survey-wrap">
        <div className="survey-card survey-done">
          <div className="survey-done-orb"/>
          <h2 className="survey-done-title">Thank you</h2>
          <p className="survey-done-sub">Your response helps us improve HaloScape.</p>
          <button className="btn btn-ghost" onClick={onBack} style={{marginTop:'16px'}}>← Back to surveys</button>
        </div>
      </div>
    );
  }

  return (
    <div className="survey-wrap">
      <button className="survey-back-btn" onClick={onBack}><IChevLeft size={14} sw={2}/> All surveys</button>
      <div className="survey-card">
        {step === 1 && (
          <>
            <div className="section-eyebrow">{topic.title}</div>
            <h2 className="survey-q">{topic.description}</h2>
            <div className="survey-scores">
              {[1,2,3,4,5].map(n => (
                <button key={n} className={`survey-score-btn ${score === n ? 'on' : ''}`} onClick={() => handleScore(n)}>{n}</button>
              ))}
            </div>
            <div className="survey-score-labels"><span>Not great</span><span>Excellent</span></div>
          </>
        )}
        {step === 2 && (
          <>
            <div className="survey-score-display">
              <span className="survey-score-big">{score}</span>
              <span className="survey-score-out">&thinsp;/ 5</span>
            </div>
            <h2 className="survey-q">What would make it better?</h2>
            <textarea className="survey-textarea" placeholder="Share any thoughts, big or small…" value={text} onChange={e => setText(e.target.value)} autoFocus rows={5}/>
            <div className="survey-actions">
              <button className="btn btn-ghost" onClick={handleSubmit}>Skip</button>
              <button className="btn btn-primary btn-pill" onClick={handleSubmit}>Submit <IArrowRight size={14} sw={2.4}/></button>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

function SurveyResponsesView({ topic, responses, onBack }) {
  const avg = responses.length ? (responses.reduce((a, r) => a + r.score, 0) / responses.length).toFixed(1) : '—';
  return (
    <div style={{maxWidth:'800px', margin:'0 auto', padding:'0 clamp(16px, 4vw, 32px) 64px'}}>
      <button className="survey-back-btn" onClick={onBack}><IChevLeft size={14} sw={2}/> All surveys</button>
      <div className="survey-admin">
        <div className="survey-admin-header">
          <div>
            <div className="section-eyebrow">Responses · {topic.title}</div>
            <h2 className="section-title" style={{fontSize:'36px'}}>{responses.length} {responses.length === 1 ? 'response' : 'responses'}</h2>
          </div>
          <div className="survey-avg">
            <div className="survey-avg-n">{avg}</div>
            <div className="survey-avg-l">avg score / 5</div>
          </div>
        </div>
        {responses.length === 0 ? (
          <div className="empty-card"><div className="empty-big">No responses yet</div><p>Responses will appear here.</p></div>
        ) : (
          <div className="survey-responses-list">
            {[...responses].reverse().map((r, i) => (
              <div key={i} className="survey-response-row">
                <div className="survey-response-score">{r.score}<span>/5</span></div>
                <div className="survey-response-body">
                  <p>{r.text || <em style={{color:'var(--fg-4)'}}>No comment</em>}</p>
                  <span className="survey-response-date">{new Date(r.date).toLocaleDateString(undefined, {month:'short',day:'numeric',hour:'2-digit',minute:'2-digit'})}</span>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

function SurveyPage({ adminMode, surveyData, onSubmit, onAddTopic, onRemoveTopic }) {
  const [activeTopic, setActiveTopic] = useState(null);
  const [viewingTopic, setViewingTopic] = useState(null);
  const [addingTopic, setAddingTopic] = useState(false);
  const [newTitle, setNewTitle] = useState('');
  const [newDesc, setNewDesc] = useState('');

  const { topics = [], responses = {}, completed = [] } = surveyData;

  if (activeTopic) {
    return (
      <SurveyForm
        topic={activeTopic}
        onSubmit={(data) => { onSubmit(activeTopic.id, data); setActiveTopic(null); }}
        onBack={() => setActiveTopic(null)}
      />
    );
  }

  if (adminMode && viewingTopic) {
    return (
      <SurveyResponsesView
        topic={viewingTopic}
        responses={responses[viewingTopic.id] || []}
        onBack={() => setViewingTopic(null)}
      />
    );
  }

  const submitNewTopic = () => {
    const t = newTitle.trim(), d = newDesc.trim();
    if (t) { onAddTopic({ title: t, description: d || 'Share your thoughts.' }); }
    setNewTitle(''); setNewDesc(''); setAddingTopic(false);
  };

  return (
    <div>
      <section className="hero hero-compact">
        <div className="hero-orb"/>
        <div className="hero-content">
          <h1 className="hero-title" style={{fontSize:'52px'}}>Tell us what you think</h1>
          <p className="hero-lede">Pick a topic below and share your experience. Takes under a minute.</p>
        </div>
      </section>

      <div className="survey-topics-section">
        <div className="survey-topics-grid">
          {topics.map(t => (
            <div key={t.id} className="survey-topic-card">
              {adminMode && (
                <button className="survey-topic-remove" onClick={() => { if (confirm(`Remove "${t.title}"?`)) onRemoveTopic(t.id); }} title="Remove">
                  <IX size={10} sw={2.8}/>
                </button>
              )}
              <h3 className="survey-topic-card-title">{t.title}</h3>
              <p className="survey-topic-card-desc">{t.description}</p>
              <div className="survey-topic-card-foot">
                {adminMode ? (
                  <button className="survey-responses-link" onClick={() => setViewingTopic(t)}>
                    {(responses[t.id] || []).length} responses →
                  </button>
                ) : completed.includes(t.id) ? (
                  <span className="survey-topic-completed"><ICheck size={12} sw={3}/> Completed</span>
                ) : (
                  <button className="btn btn-primary btn-pill" style={{height:'36px',fontSize:'13px',padding:'0 16px'}} onClick={() => setActiveTopic(t)}>
                    Take survey <IArrowRight size={13} sw={2.4}/>
                  </button>
                )}
              </div>
            </div>
          ))}

          {adminMode && (
            addingTopic ? (
              <div className="survey-topic-new-form">
                <input className="form-input" placeholder="Survey title…" value={newTitle} onChange={e => setNewTitle(e.target.value)} autoFocus style={{fontSize:'14px'}}/>
                <textarea className="form-textarea" placeholder="Question / description…" value={newDesc} onChange={e => setNewDesc(e.target.value)} rows={2} style={{fontSize:'13px'}}/>
                <div style={{display:'flex', gap:'8px', justifyContent:'flex-end'}}>
                  <button className="btn btn-ghost" style={{height:'34px',fontSize:'13px'}} onClick={() => { setAddingTopic(false); setNewTitle(''); setNewDesc(''); }}>Cancel</button>
                  <button className="btn btn-primary btn-pill" style={{height:'34px',fontSize:'13px'}} onClick={submitNewTopic} disabled={!newTitle.trim()}>Add</button>
                </div>
              </div>
            ) : (
              <button className="survey-topic-add-card" onClick={() => setAddingTopic(true)}>
                <IPlus size={20} sw={1.8}/>
                New survey
              </button>
            )
          )}
        </div>
      </div>
    </div>
  );
}

// ---------- Bug Report Modal ----------
function BugReportModal({ onClose, onSubmit }) {
  const [title, setTitle] = useState('');
  const [details, setDetails] = useState('');
  const [files, setFiles] = useState([]);
  const [uploading, setUploading] = useState(false);
  const [submitted, setSubmitted] = useState(false);
  const fileRef = useRef(null);
  const taRef = useRef(null);

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => { document.removeEventListener('keydown', onKey); document.body.style.overflow = ''; };
  }, [onClose]);

  useEffect(() => {
    if (taRef.current) {
      taRef.current.style.height = 'auto';
      taRef.current.style.height = Math.max(taRef.current.scrollHeight, 80) + 'px';
    }
  }, [details]);

  const addFiles = (e) => {
    const newFiles = Array.from(e.target.files);
    e.target.value = '';
    setFiles(prev => [...prev, ...newFiles.map(f => ({ name: f.name, file: f, type: f.type }))]);
  };
  const removeFile = (idx) => setFiles(prev => prev.filter((_, i) => i !== idx));

  const submit = async (e) => {
    e?.preventDefault();
    if (!title.trim() || uploading) return;
    setUploading(true);
    const uploaded = await Promise.all(files.map(async (f) => {
      try {
        const ref = window.storage.ref('bug-attachments/' + Date.now() + '-' + f.name);
        await ref.put(f.file);
        const url = await ref.getDownloadURL();
        return { name: f.name, url, type: f.type };
      } catch {
        return { name: f.name, type: f.type };
      }
    }));
    onSubmit({ title: title.trim(), details: details.trim(), files: uploaded });
    setSubmitted(true);
  };

  if (submitted) return (
    <div className="email-modal-wrap" onClick={onClose}>
      <div className="bug-modal" onClick={e => e.stopPropagation()} style={{textAlign:'center', padding:'48px 32px'}}>
        <div style={{fontSize:'40px', marginBottom:'16px'}}>✓</div>
        <h2 className="bug-modal-title" style={{marginBottom:'8px'}}>Report received</h2>
        <p className="bug-modal-sub" style={{marginBottom:'28px'}}>Thanks for letting us know. The team will look into it.</p>
        <button className="btn btn-primary btn-pill" onClick={onClose} style={{height:'44px', padding:'0 28px'}}>Done</button>
      </div>
    </div>
  );

  return (
    <div className="email-modal-wrap" onClick={onClose}>
      <div className="bug-modal" onClick={e => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose}><IX size={18} sw={2}/></button>
        <h2 className="bug-modal-title">Digital pest control!</h2>
        <p className="bug-modal-sub">The team reviews every report internally.</p>
        <form onSubmit={submit} style={{display:'flex',flexDirection:'column',gap:'16px'}}>
          <div className="form-field">
            <label className="form-label">What's bugging you?</label>
            <input className="form-input" placeholder="Explain the behaviour you noticed." value={title} onChange={e => setTitle(e.target.value)} required autoFocus/>
          </div>
          <div className="form-field">
            <label className="form-label">Details <span className="form-optional">— Your device, version and experience.</span></label>
            <textarea ref={taRef} className="form-textarea" placeholder="Describe what happened and what you expected…" value={details} onChange={e => setDetails(e.target.value)}/>
          </div>
          <div className="form-field">
            <label className="form-label">Attachments</label>
            <button type="button" className="form-attach" onClick={() => fileRef.current?.click()}>
              <IAttach size={15}/> Add files
            </button>
            <input ref={fileRef} type="file" style={{display:'none'}} accept="image/*,video/*,.pdf" multiple onChange={addFiles}/>
            {files.length > 0 && (
              <div style={{display:'flex',flexDirection:'column',gap:'6px',marginTop:'8px'}}>
                {files.map((f, i) => (
                  <div key={i} style={{display:'flex',alignItems:'center',gap:'8px',fontSize:'13px',color:'var(--fg-2)'}}>
                    <IAttach size={13} sw={2}/>
                    <span style={{flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{f.name}</span>
                    <button type="button" onClick={() => removeFile(i)} style={{background:'none',border:'0',cursor:'pointer',color:'var(--fg-4)',padding:'0',lineHeight:1}}>
                      <IX size={13} sw={2.5}/>
                    </button>
                  </div>
                ))}
              </div>
            )}
          </div>
          <div className="form-actions" style={{borderTop:'0', paddingTop:'4px'}}>
            <button type="button" className="btn btn-ghost" onClick={onClose} disabled={uploading}>Cancel</button>
            <button type="submit" className="btn btn-primary btn-pill" disabled={!title.trim() || uploading}>
              {uploading ? 'Uploading…' : <span>Submit bug <IArrowRight size={14} sw={2.4}/></span>}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

// ---------- Admin Login Modal (Ctrl+Shift+A to open) ----------
function AdminLoginModal({ onClose, onSuccess }) {
  const [email,    setEmail]    = useState('');
  const [password, setPassword] = useState('');
  const [error,    setError]    = useState('');
  const [loading,  setLoading]  = useState(false);

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => { document.removeEventListener('keydown', onKey); document.body.style.overflow = ''; };
  }, [onClose]);

  const submit = async (e) => {
    e?.preventDefault();
    if (!email.trim() || !password) return;
    setLoading(true);
    setError('');
    try {
      await window.auth.signInWithEmailAndPassword(email.trim(), password);
      onSuccess();
    } catch (err) {
      setError('Invalid email or password.');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="email-modal-wrap" onClick={onClose}>
      <div className="email-modal" onClick={e => e.stopPropagation()} style={{maxWidth:'360px'}}>
        <button className="modal-close" onClick={onClose}><IX size={18} sw={2}/></button>
        <div className="email-modal-orb"/>
        <h2 className="email-modal-title" style={{display:'flex',alignItems:'center',gap:'8px'}}>
          <IShield size={18} sw={2}/> Admin access
        </h2>
        <p className="email-modal-sub">Sign in to manage posts, boards, and survey responses.</p>
        <form onSubmit={submit} style={{display:'flex',flexDirection:'column',gap:'12px',marginTop:'4px'}}>
          <input
            className="email-input"
            type="email"
            placeholder="Admin email"
            value={email}
            onChange={e => { setEmail(e.target.value); setError(''); }}
            autoFocus
            required
          />
          <input
            className="email-input"
            type="password"
            placeholder="Password"
            value={password}
            onChange={e => { setPassword(e.target.value); setError(''); }}
            required
          />
          {error && <p style={{margin:0,fontSize:'13px',color:'var(--danger)'}}>{error}</p>}
          <button
            type="submit"
            className="btn btn-primary btn-pill"
            disabled={loading || !email.trim() || !password}
            style={{marginTop:'4px'}}>
            {loading ? 'Signing in…' : 'Sign in'}
          </button>
        </form>
      </div>
    </div>
  );
}

// ---------- Footer ----------
function Footer() {
  const [newsletterEmail, setNewsletterEmail] = useState('');
  const [newsletterState, setNewsletterState] = useState('idle'); // idle | loading | success | error

  const submitNewsletter = () => {
    const v = newsletterEmail.trim();
    if (!v || !v.includes('@')) return;
    setNewsletterState('loading');
    window.subscribeToMailchimp(v)
      .then(() => { setNewsletterState('success'); setNewsletterEmail(''); })
      .catch(() => setNewsletterState('error'));
  };

  return (
    <footer className="footer-new">
      {/* CTA band */}
      <div className="footer-cta">
        <h2 className="footer-cta-title">Join the movement.</h2>
        <div className="footer-cta-btns">
          <a className="footer-store-btn" href="https://apps.apple.com/nl/app/haloscape-ai-health-mate/id6467396064" target="_blank" rel="noopener">Download for iOS</a>
          <a className="footer-store-btn" href="https://play.google.com/store/apps/details?id=com.realworks.realhealth" target="_blank" rel="noopener">Download for Android</a>
        </div>
      </div>

      {/* Main footer row */}
      <div className="footer-main">
        <div className="footer-newsletter">
          <div className="footer-newsletter-title">Subscribe to our Newsletter</div>
          <div className="footer-newsletter-sub">Get health tips &amp; insights straight to your inbox.</div>
          {newsletterState === 'success' ? (
            <div style={{display:'flex',alignItems:'center',gap:'8px',marginTop:'12px',padding:'12px 16px',borderRadius:'12px',background:'rgba(255,255,255,0.1)'}}>
              <ICheck size={16} sw={2.5} style={{color:'#4ade80',flexShrink:0}}/>
              <span style={{fontSize:'14px',color:'#fff',fontWeight:'500'}}>You're subscribed!</span>
            </div>
          ) : (
            <>
              <div className="footer-newsletter-row">
                <input
                  className="footer-newsletter-input"
                  type="email"
                  placeholder="Enter your email"
                  value={newsletterEmail}
                  onChange={e => { setNewsletterEmail(e.target.value); if (newsletterState === 'error') setNewsletterState('idle'); }}
                  onKeyDown={e => e.key === 'Enter' && submitNewsletter()}
                  disabled={newsletterState === 'loading'}
                />
                <button className="footer-newsletter-btn" onClick={submitNewsletter} disabled={newsletterState === 'loading'}>
                  {newsletterState === 'loading' ? '…' : 'Submit'}
                </button>
              </div>
              {newsletterState === 'error' && <p style={{fontSize:'12px',color:'#E43D41',marginTop:'6px'}}>Something went wrong, please try again.</p>}
            </>
          )}
        </div>

        <div className="footer-center">
          <img src="assets/wordmark-footer.png" alt="HaloScape" className="footer-wordmark"/>
          <span className="footer-copy">© 2026 HaloScape. All rights reserved.</span>
        </div>

        <nav className="footer-nav-links">
          <a href="https://haloscape.health/" target="_blank" rel="noopener">Features</a>
          <a href="https://haloscape.health/about" target="_blank" rel="noopener">About</a>
          <a href="https://haloscape.health/halo-research" target="_blank" rel="noopener">HaloResearch</a>
          <a href="https://haloscape.health/blog" target="_blank" rel="noopener">HaloHub</a>
          <a href="https://haloscape.health/newsroom" target="_blank" rel="noopener">Newsroom</a>
          <a href="https://haloscape.health/faq" target="_blank" rel="noopener">FAQ</a>
        </nav>
      </div>

      {/* Social icons — desktop inline, mobile 2×2 grid */}
      <div className="footer-socials">
        <a href="https://x.com/haloscape" target="_blank" rel="noopener"><img src="assets/icon-x.png" alt="X"/></a>
        <a href="https://www.reddit.com/r/HaloScape/" target="_blank" rel="noopener"><img src="assets/icon-reddit.png" alt="Reddit"/></a>
        <a href="https://www.linkedin.com/company/haloscape/" target="_blank" rel="noopener"><img src="assets/icon-linkedin.png" alt="LinkedIn"/></a>
        <a href="https://www.instagram.com/haloscape.health" target="_blank" rel="noopener"><img src="assets/icon-instagram.png" alt="Instagram"/></a>
      </div>

      {/* Mobile-only nav links row */}
      <nav className="footer-nav-mobile">
        <a href="https://haloscape.health/" target="_blank" rel="noopener">Features</a>
        <a href="https://haloscape.health/about" target="_blank" rel="noopener">About</a>
        <a href="https://haloscape.health/halo-research" target="_blank" rel="noopener">HaloResearch</a>
        <a href="https://haloscape.health/blog" target="_blank" rel="noopener">HaloHub</a>
        <a href="https://haloscape.health/newsroom" target="_blank" rel="noopener">Newsroom</a>
        <a href="https://haloscape.health/faq" target="_blank" rel="noopener">FAQ</a>
      </nav>

      {/* Legal bar */}
      <div className="footer-legal">
        <a href="https://haloscape.health/legals/privacy-policy" target="_blank" rel="noopener">Privacy Policy</a>
        <span>·</span>
        <a href="https://haloscape.health/legals/terms-of-us" target="_blank" rel="noopener">Terms of Use</a>
        <span>·</span>
        <a href="https://haloscape.health/legals/cookies-policy" target="_blank" rel="noopener">Cookies Policy</a>
        <span>·</span>
        <a href="https://haloscape.health/legals/general-termsconditions" target="_blank" rel="noopener">General Terms &amp; Conditions</a>
        <span>·</span>
        <a href="https://haloscape.health/legals/disclaimer" target="_blank" rel="noopener">Disclaimer</a>
      </div>
    </footer>
  );
}

Object.assign(window, {
  TopNav, Hero, BoardTiles, SubmitForm, PostCard, ListHead, PostModal, ModerationPage,
  BugReportsPage, SurveyPage, EmailCaptureModal, BugReportModal,
  AdminLoginModal, TweaksPanel, Footer, StatusChip, VoteOrb,
  IChevUp, IChevDown, IChevLeft, IChevRight, ISearch, ICheck, IX, IPlus, ITrash, IArrowRight,
  ISparkle, IBug, IChat,
  BOARD_VISUALS, DEFAULT_TINTS
});
