// Pocket Marshal — History, Reference (source library), Settings tabs

// ---------- History ----------
function PMHistory({ theme, sessions, onOpen, onDelete }) {
  return (
    <div data-screen-label="History" style={{ maxWidth: 680, margin: '0 auto', padding: '24px 20px', boxSizing: 'border-box' }}>
      <h1 style={{ margin: '0 0 4px', fontSize: '1.6em', fontWeight: 800, color: theme.ink }}>History</h1>
      <p style={{ margin: '0 0 20px', color: theme.muted, fontWeight: 600, fontSize: '0.95em' }}>
        Every conversation is saved on this device.
      </p>
      {sessions.length === 0 && (
        <div style={{
          background: theme.paper, border: `2px dashed ${theme.line}`, borderRadius: 16,
          padding: '40px 24px', textAlign: 'center',
        }}>
          <div style={{ display: 'inline-block', opacity: 0.9 }}><MarshalAvatar styleKind={window.__pmAvatarKind === 'mascot' ? 'mascot' : 'badge'} size={56} /></div>
          <p style={{ margin: '14px 0 0', color: theme.muted, fontWeight: 600, lineHeight: 1.5 }}>
            No inspections yet. When you and I work through something, it'll show up here.
          </p>
        </div>
      )}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        {sessions.map((s) => (
          <div key={s.id} style={{
            display: 'flex', alignItems: 'center', gap: 6,
            background: theme.paper, border: `1.5px solid ${theme.line}`, borderRadius: 16,
          }}>
            <button onClick={() => onOpen(s.id)} style={{
              flex: 1, minWidth: 0, display: 'flex', alignItems: 'center', gap: 14,
              padding: '16px 4px 16px 18px', background: 'none', border: 'none',
              font: 'inherit', textAlign: 'left', cursor: 'pointer', minHeight: 64,
            }}>
              <span style={{ color: theme.chipIcon, display: 'grid', placeItems: 'center' }}><IconBuilding size={24} /></span>
              <span style={{ flex: 1, minWidth: 0 }}>
                <span style={{ display: '-webkit-box', WebkitBoxOrient: 'vertical', WebkitLineClamp: 2, fontWeight: 800, color: theme.ink, fontSize: '1.02em', overflow: 'hidden', lineHeight: 1.3 }}>
                  {s.title}
                </span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 7, flexWrap: 'wrap', marginTop: 3 }}>
                  {s.sample && (
                    <span style={{
                      fontSize: '0.66em', fontWeight: 900, letterSpacing: '0.09em', textTransform: 'uppercase',
                      color: theme.amberDark, background: theme.amberSoft,
                      border: `1px solid ${theme.citeBorder}`, borderRadius: 5, padding: '2px 6px', whiteSpace: 'nowrap',
                    }}>Sample</span>
                  )}
                  <span style={{ color: theme.muted, fontWeight: 600, fontSize: '0.85em' }}>
                    {pmTimeAgo(s.time)} · {s.messages.length} message{s.messages.length === 1 ? '' : 's'}
                  </span>
                </span>
              </span>
              <span style={{ color: theme.muted }}><IconChevron size={20} /></span>
            </button>
            <button onClick={() => onDelete(s.id)} aria-label={`Delete ${s.title}`} style={{
              width: 48, height: 48, marginRight: 6, borderRadius: 12, border: 'none',
              background: 'transparent', color: theme.muted, cursor: 'pointer',
              display: 'grid', placeItems: 'center', flexShrink: 0,
            }}><IconTrash size={20} /></button>
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- Reference: the source library ----------
const PM_LIBRARY = [
  {
    id: 'ffpc',
    title: 'Florida Fire Prevention Code',
    subtitle: 'Primary authority for all inspections · 8th Edition (2023)',
    badge: 'Official',
    icon: IconShieldCheck,
    accent: 'navy',
    volumes: PM_FFPC_VOLUMES,
    entries: [],
  },
  {
    id: 'ordinances',
    title: 'City of Winter Haven Ordinances',
    subtitle: 'Local amendments & requirements',
    icon: IconScroll,
    accent: 'amber',
    entries: [
      {
        id: 'wh-lanes', label: '§ 46-33 — Fire lanes & marking', meta: 'Local',
        body: 'Where fire lanes are required on commercial property, sign and curb marking specs, and how violations are enforced.',
        ask: 'About Winter Haven ordinance § 46-33 (fire lanes) — ',
      },
      {
        id: 'wh-knox', label: '§ 46-61 — Key boxes (Knox)', meta: 'Local',
        body: 'Buildings with fire alarm or suppression systems need an approved key box: mounting location, height, and required contents.',
        ask: 'About Winter Haven ordinance § 46-61 (Knox key boxes) — ',
      },
      {
        id: 'wh-burn', label: '§ 46-72 — Open burning', meta: 'Local',
        body: 'Permit requirements, setbacks, and prohibited materials for outdoor burning inside city limits.',
        ask: 'About Winter Haven ordinance § 46-72 (open burning) — ',
      },
    ],
  },
  {
    id: 'guide',
    title: 'Inspector 101: Guide to the Galaxy',
    subtitle: 'Internal guidance & best practices · Winter Haven Fire Marshal\u2019s Office',
    icon: IconCompass,
    accent: 'teal',
    badge: 'Internal',
    entries: [
      {
        id: 'g-roles', label: 'Roles & jurisdictions — who does what', meta: 'Section II',
        body: 'Authority flows from Ch. 633, Florida Statutes: the State Fire Marshal sets the standards, the local enforcing authority carries out inspections, and the AHJ has the final say. You\u2019re the boots on the ground — you document, recommend, and enforce through the chain of command.',
        ask: 'From the internal guide, about roles and jurisdictions (who does what) — ',
      },
      {
        id: 'g-entry', label: 'Right to inspect & refused entry', meta: 'Section III',
        body: 'You\u2019re carrying out a legal duty, not asking permission. If entry is refused and there\u2019s no immediate hazard: de-escalate, educate on your authority, leave peacefully, and start the administrative warrant process per department procedure.',
        ask: 'From the internal guide, about the right to inspect and refused entry — ',
      },
      {
        id: 'g-owners', label: 'Communicating with business owners', meta: 'Section V',
        body: 'Introduce yourself by name, title, and department; explain the scope before you start; deliver findings calmly and factually — conditions as observed, never assumptions. And remember these are businesses: schedule disruptive tests with their hours in mind.',
        ask: 'From the internal guide, about communicating with business owners — ',
      },
      {
        id: 'g-escalate', label: 'When to call the Fire Marshal first', meta: 'Section V.E',
        body: 'Before any formal enforcement — citations, stop-work orders, closures; on legal, liability, or code-interpretation disputes; when a warrant may be needed; or when things turn confrontational. Coordinating first keeps enforcement consistent and defensible.',
        ask: 'From the internal guide, about when to coordinate with the Fire Marshal before acting — ',
      },
      {
        id: 'g-gray', label: 'Gray area decision framework', meta: 'Sections II & V',
        body: 'Code ambiguity gets resolved through channels, not on the spot: check local amendments, raise it through supervisory review, and if it can\u2019t be settled locally it can go to the state\u2019s Fire Code Interpretation Committee (FCIC).',
        ask: 'From the internal guide, about handling gray areas and code interpretation disputes — ',
      },
      {
        id: 'g-matrix', label: 'Inspection frequency matrix', meta: 'Section III.D',
        body: 'High risk (licensed care, detention, large assembly, bars ≥100): annual. Moderate (assembly <300, Class A mercantile, schools): every 2 years. Standard (business, Class B/C mercantile, low-hazard storage): every 3. When in doubt, bump frequency upward.',
        ask: 'From the internal guide, about the inspection frequency matrix — ',
      },
    ],
  },
  {
    id: 'fbc',
    title: 'Florida Building Code',
    subtitle: 'Cross-reference for construction context — not inspection authority',
    badge: 'Context',
    icon: IconBuilding,
    accent: 'denim',
    volumes: PM_FBC_VOLUMES,
    link: { href: 'https://codes.iccsafe.org/codes/florida', label: 'Read the full code text free — Florida Building Commission / ICC' },
    entries: [],
  },
];

const PM_LIB_ACCENTS = (theme) => theme.dark ? {
  navy: { soft: '#1b3050', edge: '#34527e', icon: '#9fc3f0', pill: '#2e4a74', pillInk: '#fff8f0', label: '#9fc3f0' },
  amber: { soft: '#33231a', edge: '#5e3a20', icon: '#f08030', pill: '#d44a18', pillInk: '#fff8f0', label: '#f0a070' },
  teal: { soft: '#12302b', edge: '#23584f', icon: '#7fd4c5', pill: '#136a5e', pillInk: '#ffffff', label: '#7fd4c5' },
  denim: { soft: '#172a40', edge: '#2d4a6e', icon: '#7fa8d9', pill: '#2a5a9c', pillInk: '#fff8f0', label: '#7fa8d9' },
} : {
  navy: { soft: '#eaeef5', edge: '#c6d0e0', icon: '#0d1f38', pill: '#0d1f38', pillInk: '#fff8f0', label: '#33455f' },
  amber: { soft: '#fce7da', edge: '#eec4a8', icon: '#b03c12', pill: '#d44a18', pillInk: '#fff8f0', label: '#a8390f' },
  teal: { soft: '#e7f4f1', edge: '#bfe0d9', icon: '#136a5e', pill: '#136a5e', pillInk: '#ffffff', label: '#136a5e' },
  denim: { soft: '#e9f0f9', edge: '#c3d4ea', icon: '#2a5a9c', pill: '#2a5a9c', pillInk: '#ffffff', label: '#2a5a9c' },
};

// One volume of the FFPC: collapsible chapter list
function PMVolume({ vol, theme, a, forceOpen, openEntry, onEntry, onAsk, matchIds }) {
  const [open, setOpen] = React.useState(vol.id === 'vol1' || !!vol.startOpen);
  // Expand automatically when the chapter being opened belongs to this volume
  // (following a citation tap from a determination).
  const ownsEntry = !!openEntry && String(openEntry).indexOf(vol.id + '-') === 0;
  const isOpen = forceOpen || open || ownsEntry;
  const chapters = matchIds ? vol.chapters.filter((ch) => matchIds.has(vol.id + '-' + ch.n)) : vol.chapters;
  if (matchIds && chapters.length === 0) return null;
  const volShort = vol.short || (vol.id === 'vol1' ? 'NFPA 1-FL' : 'NFPA 101-FL');
  const askName = vol.askName || `the Florida Fire Prevention Code, ${volShort}`;
  return (
    <div style={{ borderTop: `1.5px solid ${theme.line}` }}>
      <button onClick={() => setOpen(!open)} aria-expanded={isOpen} style={{
        width: '100%', display: 'flex', alignItems: 'center', gap: 11, padding: '12px 16px 12px 20px',
        background: 'none', border: 'none', font: 'inherit', textAlign: 'left', cursor: 'pointer', minHeight: 54, boxSizing: 'border-box',
      }}>
        <span style={{ flex: 1, minWidth: 0 }}>
          <span style={{ display: 'block', fontWeight: 800, color: theme.ink, fontSize: '0.92em', lineHeight: 1.3 }}>{vol.title}</span>
          <span style={{ display: 'block', color: theme.muted, fontWeight: 600, fontSize: '0.78em', marginTop: 2 }}>{vol.sub}</span>
        </span>
        <span style={{ color: a.label, fontWeight: 750, fontSize: '0.72em', whiteSpace: 'nowrap' }}>{chapters.length} ch.</span>
        <span style={{ color: theme.muted, transform: isOpen ? 'rotate(90deg)' : 'none', transition: 'transform 0.15s', display: 'grid', placeItems: 'center' }}><IconChevron size={17} /></span>
      </button>
      {isOpen && chapters.map((ch) => {
        const eid = vol.id + '-' + ch.n;
        const chOpen = openEntry === eid;
        return (
          <div key={eid} style={{ borderTop: `1px solid ${theme.line}` }}>
            <button onClick={() => onEntry(chOpen ? null : eid)} style={{
              width: '100%', display: 'flex', alignItems: 'center', gap: 12, padding: '10px 16px 10px 20px',
              background: chOpen ? a.soft : 'none', border: 'none', font: 'inherit', textAlign: 'left', cursor: 'pointer', minHeight: 50, boxSizing: 'border-box',
            }}>
              <span style={{
                minWidth: 44, textAlign: 'center', background: chOpen ? theme.paper : a.soft, color: a.label,
                border: `1px solid ${a.edge}`, borderRadius: 7, padding: '3px 6px',
                fontWeight: 800, fontSize: '0.74em', whiteSpace: 'nowrap', flexShrink: 0,
              }}>Ch. {ch.n}</span>
              <span style={{ flex: 1, fontWeight: 700, color: theme.ink, fontSize: '0.93em', lineHeight: 1.3 }}>{ch.t}</span>
              <span style={{ color: theme.muted, transform: chOpen ? 'rotate(90deg)' : 'none', transition: 'transform 0.15s', display: 'grid', placeItems: 'center' }}><IconChevron size={16} /></span>
            </button>
            {chOpen && (
              <div style={{ padding: '10px 20px 15px 76px' }}>
                <p style={{ margin: '0 0 12px', color: theme.ink, lineHeight: 1.5, fontSize: '0.92em', textWrap: 'pretty' }}>{ch.s}</p>
                <button onClick={() => onAsk({ ask: `About ${askName}, Chapter ${ch.n} (${ch.t}) — ` })} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 8, minHeight: 44, padding: '0 16px',
                  background: theme.cta, color: theme.ctaInk, border: 'none', borderRadius: 12,
                  font: 'inherit', fontWeight: 700, fontSize: '0.88em', cursor: 'pointer',
                }}><IconChat size={17} /> Ask Marshal about this</button>
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

function PMSourceCard({ source, theme, open, onToggle, openEntry, onEntry, onAsk, matchIds }) {
  const a = PM_LIB_ACCENTS(theme)[source.accent];
  const Ic = source.icon;
  const entries = matchIds ? source.entries.filter((e) => matchIds.has(e.id)) : source.entries;
  return (
    <div style={{ background: theme.paper, border: `1.5px solid ${open ? a.edge : theme.line}`, borderRadius: 16, overflow: 'hidden', transition: 'border-color 0.15s' }}>
      <button onClick={onToggle} aria-expanded={open} style={{
        width: '100%', display: 'flex', alignItems: 'center', gap: 13, padding: '14px 16px',
        background: open ? a.soft : 'none', border: 'none', font: 'inherit', textAlign: 'left',
        cursor: 'pointer', minHeight: 72, transition: 'background 0.15s', boxSizing: 'border-box',
      }}>
        <span style={{
          width: 42, height: 42, borderRadius: source.accent === 'teal' ? '50%' : 12,
          background: open ? theme.paper : a.soft, color: a.icon,
          display: 'grid', placeItems: 'center', flexShrink: 0,
        }}><Ic size={23} /></span>
        <span style={{ flex: 1, minWidth: 0 }}>
          <span style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <span style={{ fontWeight: 800, color: theme.ink, fontSize: '1.02em', lineHeight: 1.25 }}>{source.title}</span>
            {source.badge && (
              <span style={{
                background: a.pill, color: a.pillInk, fontWeight: 800, fontSize: '0.64em',
                letterSpacing: '0.07em', textTransform: 'uppercase', padding: '3px 8px', borderRadius: 6, whiteSpace: 'nowrap',
              }}>{source.badge}</span>
            )}
          </span>
          <span style={{ display: 'block', color: theme.muted, fontWeight: 600, fontSize: '0.83em', marginTop: 3, lineHeight: 1.35, textWrap: 'pretty' }}>{source.subtitle}</span>
        </span>
        <span style={{ color: theme.muted, transform: open ? 'rotate(90deg)' : 'none', transition: 'transform 0.15s', display: 'grid', placeItems: 'center' }}><IconChevron size={19} /></span>
      </button>
      {open && source.volumes && (
        <div>
          {source.volumes.map((vol) => (
            <PMVolume key={vol.id} vol={vol} theme={theme} a={a} forceOpen={!!matchIds}
              openEntry={openEntry} onEntry={onEntry} onAsk={onAsk} matchIds={matchIds} />
          ))}
          <a href={(source.link && source.link.href) || 'https://www.myfloridacfo.com/division/sfm/bfp/florida-fire-prevention-code'} target="_blank" rel="noopener" style={{
            display: 'flex', alignItems: 'center', gap: 10, padding: '13px 16px 13px 20px', minHeight: 50, boxSizing: 'border-box',
            borderTop: `1.5px solid ${theme.line}`, background: a.soft,
            color: a.label, fontWeight: 750, fontSize: '0.85em', textDecoration: 'none', lineHeight: 1.35,
          }}>
            <IconBook size={18} />
            <span style={{ flex: 1 }}>{(source.link && source.link.label) || 'Read the full code text free — Florida State Fire Marshal / NFPA LiNK'}</span>
            <IconChevron size={16} />
          </a>
        </div>
      )}
      {open && !source.volumes && entries.map((e, i) => {
        const isOpen = openEntry === e.id;
        return (
          <div key={e.id} style={{ borderTop: `1.5px solid ${theme.line}` }}>
            <button onClick={() => onEntry(isOpen ? null : e.id)} style={{
              width: '100%', display: 'flex', alignItems: 'center', gap: 12, padding: '13px 16px 13px 20px',
              background: 'none', border: 'none', font: 'inherit', textAlign: 'left', cursor: 'pointer', minHeight: 54, boxSizing: 'border-box',
            }}>
              <span style={{ flex: 1, minWidth: 0 }}>
                <span style={{ display: 'block', fontWeight: 700, color: theme.ink, fontSize: '0.96em', lineHeight: 1.3 }}>{e.label}</span>
                {e.meta && (
                  <span style={{ display: 'block', color: a.label, fontWeight: 750, fontSize: '0.72em', letterSpacing: '0.03em', marginTop: 3 }}>{e.meta}</span>
                )}
              </span>
              <span style={{ color: theme.muted, transform: isOpen ? 'rotate(90deg)' : 'none', transition: 'transform 0.15s', display: 'grid', placeItems: 'center' }}><IconChevron size={17} /></span>
            </button>
            {isOpen && (
              <div style={{ padding: '0 20px 15px' }}>
                <p style={{ margin: '0 0 12px', color: theme.ink, lineHeight: 1.5, fontSize: '0.94em', textWrap: 'pretty' }}>{e.body}</p>
                <button onClick={() => onAsk(e)} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 8, minHeight: 44, padding: '0 16px',
                  background: theme.cta, color: theme.ctaInk, border: 'none', borderRadius: 12,
                  font: 'inherit', fontWeight: 700, fontSize: '0.9em', cursor: 'pointer',
                }}><IconChat size={18} /> Ask Marshal about this</button>
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

function PMReference({ theme, onAsk, searchSeed }) {
  const [q, setQ] = React.useState('');
  const [openSources, setOpenSources] = React.useState({ ffpc: true, ordinances: false, guide: false, fbc: false });
  const [openEntry, setOpenEntry] = React.useState(null);
  React.useEffect(() => {
    if (!searchSeed) return;
    if (searchSeed.entry) { setQ(''); setOpenEntry(searchSeed.entry); setOpenSources((cur) => ({ ...cur, ffpc: true })); }
    else if (searchSeed.q) { setQ(searchSeed.q); setOpenEntry(null); }
  }, [searchSeed && searchSeed.nonce]);

  const needle = q.trim().toLowerCase();
  // When searching: compute matching entry/chapter ids per source and force-open sources with hits
  const matches = needle ? PM_LIBRARY.map((src) => {
    const ids = new Set();
    if (src.volumes) {
      src.volumes.forEach((v) => v.chapters.forEach((ch) => {
        const hay = (src.title + ' ' + v.title + ' ch ' + ch.n + ' chapter ' + ch.n + ' ' + ch.t + ' ' + ch.s).toLowerCase();
        if (hay.includes(needle)) ids.add(v.id + '-' + ch.n);
      }));
    }
    src.entries.forEach((e) => {
      if ((src.title + ' ' + e.label + ' ' + (e.meta || '') + ' ' + e.body).toLowerCase().includes(needle)) ids.add(e.id);
    });
    return { id: src.id, ids };
  }) : null;
  const anyHits = matches ? matches.some((m) => m.ids.size > 0) : true;

  return (
    <div data-screen-label="Reference" style={{ maxWidth: 680, margin: '0 auto', padding: '24px 20px', boxSizing: 'border-box' }}>
      <h1 style={{ margin: '0 0 4px', fontSize: '1.6em', fontWeight: 800, color: theme.ink }}>Reference</h1>
      <p style={{ margin: '0 0 16px', color: theme.muted, fontWeight: 600, fontSize: '0.95em' }}>
        The sources behind every call Marshal makes.
      </p>

      {/* Search */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 10, background: theme.paper,
        border: `2px solid ${theme.line}`, borderRadius: 14, padding: '0 14px', marginBottom: 14, minHeight: 52,
      }}>
        <span style={{ color: theme.muted }}><IconSearch size={21} /></span>
        <input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search codes, topics, or keywords..."
          style={{ flex: 1, minWidth: 0, border: 'none', outline: 'none', background: 'transparent', font: 'inherit', fontSize: '1em', color: theme.ink, minHeight: 48 }} />
        {q && <button onClick={() => setQ('')} aria-label="Clear search" style={{ border: 'none', background: 'none', color: theme.muted, cursor: 'pointer', display: 'grid', placeItems: 'center', width: 36, height: 36 }}><IconX size={18} /></button>}
      </div>

      {/* Warm banner */}
      <div style={{
        display: 'flex', alignItems: 'flex-start', gap: 11,
        background: theme.bannerBg, border: `1.5px solid ${theme.citeBorder}`, borderRadius: 14,
        padding: '12px 14px', marginBottom: 18,
      }}>
        <span style={{ marginTop: 1, flexShrink: 0 }}><MarshalAvatar styleKind={window.__pmAvatarKind === 'mascot' ? 'mascot' : 'badge'} size={30} /></span>
        <p style={{ margin: 0, color: theme.bannerInk, fontWeight: 650, fontSize: '0.9em', lineHeight: 1.45, textWrap: 'pretty' }}>
          Marshal references all of these sources automatically — this library is here when you want to look something up yourself.
        </p>
      </div>

      {!anyHits && (
        <p style={{ color: theme.muted, fontWeight: 600, textAlign: 'center', padding: '24px 0' }}>
          Nothing here for "{q}" — try asking Marshal directly in Chat.
        </p>
      )}

      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        {PM_LIBRARY.map((src) => {
          const m = matches ? matches.find((x) => x.id === src.id) : null;
          if (m && m.ids.size === 0) return null;
          return (
            <PMSourceCard key={src.id} source={src} theme={theme}
              open={m ? true : !!openSources[src.id]}
              onToggle={() => setOpenSources((cur) => ({ ...cur, [src.id]: !cur[src.id] }))}
              openEntry={openEntry} onEntry={setOpenEntry}
              onAsk={onAsk} matchIds={m ? m.ids : null} />
          );
        })}
      </div>
    </div>
  );
}

// ---------- Settings ----------
// Everything on this device as one readable text file. Conversations live only
// in this browser's storage, which iOS can evict and "Clear browsing data" wipes.
function pmExportAll(sessions, who) {
  const L = [];
  L.push('POCKET MARSHAL — CONVERSATION EXPORT');
  if (who) L.push('Inspector: ' + who);
  L.push('Exported: ' + pmStamp(Date.now()));
  L.push('Conversations: ' + sessions.length);
  L.push('');
  L.push('This is a personal copy, not an official record. Verify every section in');
  L.push("your department's adopted edition before issuing a finding.");
  sessions.forEach((s) => {
    L.push('');
    L.push('='.repeat(64));
    L.push(s.title || 'Untitled');
    if (s.time) L.push(pmStamp(s.time));
    L.push('='.repeat(64));
    (s.messages || []).forEach((m) => {
      L.push('');
      if (m.role === 'user') {
        L.push('[INSPECTOR' + (m.at ? ' \u00b7 ' + pmStamp(m.at) : '') + ']');
        L.push(m.text || (m.photo ? '(photo attached)' : ''));
      } else {
        L.push('[MARSHAL' + (m.at ? ' \u00b7 ' + pmStamp(m.at) : '') + (m.model ? ' \u00b7 ' + m.model : '') + ']');
        if (m.verdict) L.push(pmVerdictToText(m.verdict, m.text, { at: m.at, model: m.model }));
        else L.push(typeof pmPlain === 'function' ? pmPlain(m.text) : (m.text || ''));
        if (m.rating) L.push('(Inspector marked this ' + (m.rating === 'up' ? 'correct' : 'questionable') + ')');
      }
    });
  });
  return L.join('\n');
}

function pmDownloadText(name, text) {
  try {
    const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = name;
    document.body.appendChild(a); a.click(); document.body.removeChild(a);
    setTimeout(() => URL.revokeObjectURL(url), 4000);
    return true;
  } catch (e) { return false; }
}

function PMSettings({ theme, t, setTweak, inspectorName, onNameChange, onClearHistory, sessionCount, stay, onStayChange, onLockNow, sessions }) {
  const [access, setAccess] = React.useState(() => { try { return localStorage.getItem('pm_access') || ''; } catch (e) { return ''; } });
  const card = { background: theme.paper, border: `1.5px solid ${theme.line}`, borderRadius: 16, padding: '18px 18px', marginBottom: 14 };
  const label = { display: 'block', fontWeight: 800, fontSize: '0.85em', letterSpacing: '0.05em', textTransform: 'uppercase', color: theme.emberDark, marginBottom: 10 };
  return (
    <div data-screen-label="Settings" style={{ maxWidth: 680, margin: '0 auto', padding: '24px 20px', boxSizing: 'border-box' }}>
      <h1 style={{ margin: '0 0 20px', fontSize: '1.6em', fontWeight: 800, color: theme.ink }}>Settings</h1>

      <div style={card}>
        <span style={label}>Appearance</span>
        <div style={{ display: 'flex', gap: 10 }}>
          {[{ v: 'light', l: 'Light', Ic: IconSun, d: 'Warm white — bright sun' }, { v: 'dark', l: 'Dark', Ic: IconMoon, d: 'Deep navy — low light' }].map(({ v, l, Ic, d }) => {
            const on = (t.mode || 'light') === v;
            return (
              <button key={v} onClick={() => setTweak('mode', v)} aria-pressed={on} style={{
                flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6,
                padding: '14px 10px', minHeight: 84, borderRadius: 14, cursor: 'pointer', font: 'inherit',
                background: on ? theme.navySoft : 'transparent',
                border: `2px solid ${on ? theme.focusRing : theme.line}`,
                color: theme.ink, transition: 'border-color 0.15s, background 0.15s',
              }}>
                <Ic size={24} style={{ color: on ? theme.heroAccent : theme.muted }} />
                <span style={{ fontWeight: 800, fontSize: '0.95em' }}>{l}</span>
                <span style={{ fontWeight: 600, fontSize: '0.74em', color: theme.muted }}>{d}</span>
              </button>
            );
          })}
        </div>
      </div>

      <div style={card}>
        <span style={label}>Inspector</span>
        <input value={inspectorName} onChange={(e) => onNameChange(e.target.value)} placeholder="Your name"
          style={{
            width: '100%', boxSizing: 'border-box', border: `2px solid ${theme.line}`, borderRadius: 12,
            padding: '12px 14px', font: 'inherit', fontSize: '1.05em', fontWeight: 700, color: theme.ink,
            background: 'transparent', outline: 'none', minHeight: 52,
          }} />
        <p style={{ margin: '10px 0 0', color: theme.muted, fontSize: '0.88em', fontWeight: 600 }}>
          City of Winter Haven Fire Department · Bureau of Fire Prevention
        </p>
      </div>

      <div style={card}>
        <span style={label}><IconShieldCheck size={14} style={{ verticalAlign: '-2px', marginRight: 4 }} />Department access code</span>
        <input value={access} onChange={(e) => setAccess(e.target.value)}
          onBlur={() => { try { localStorage.setItem('pm_access', access.trim()); } catch (err) { /* noop */ } }}
          placeholder="From your Fire Marshal" autoComplete="off" spellCheck="false"
          style={{
            width: '100%', boxSizing: 'border-box', border: `2px solid ${theme.line}`, borderRadius: 12,
            padding: '12px 14px', font: 'inherit', fontSize: '1.02em', fontWeight: 700, color: theme.ink,
            background: 'transparent', outline: 'none', minHeight: 52, letterSpacing: '0.02em',
          }} />
        <p style={{ margin: '10px 0 0', color: theme.muted, fontSize: '0.88em', fontWeight: 600, lineHeight: 1.45 }}>
          Identifies your department to Marshal. If answers stop coming through, check this first.
        </p>
      </div>

      <div style={card}>
        <span style={label}><IconBook size={14} style={{ verticalAlign: '-2px', marginRight: 4 }} />Where code citations open</span>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 9 }}>
          {[
            { v: 'free', l: 'NFPA free access', d: 'Read-only. Works without a subscription.' },
            { v: 'link', l: 'NFPA LiNK', d: "Full text. Only if your department subscribes." },
          ].map(({ v, l, d }) => {
            const on = (t.codeLink || 'free') === v;
            return (
              <button key={v} onClick={() => setTweak('codeLink', v)} style={{
                display: 'flex', alignItems: 'center', gap: 12, width: '100%', boxSizing: 'border-box',
                minHeight: 60, padding: '12px 14px', borderRadius: 13, cursor: 'pointer', font: 'inherit', textAlign: 'left',
                background: on ? theme.navySoft : 'transparent',
                border: `2px solid ${on ? theme.focusRing : theme.line}`,
              }}>
                <span aria-hidden="true" style={{
                  width: 21, height: 21, borderRadius: '50%', flexShrink: 0, display: 'grid', placeItems: 'center',
                  border: `2px solid ${on ? theme.focusRing : theme.line}`,
                }}>{on && <span style={{ width: 11, height: 11, borderRadius: '50%', background: theme.focusRing }}></span>}</span>
                <span style={{ flex: 1, minWidth: 0 }}>
                  <span style={{ display: 'block', fontWeight: 800, color: theme.ink, fontSize: '0.96em' }}>{l}</span>
                  <span style={{ display: 'block', color: theme.muted, fontWeight: 600, fontSize: '0.82em', marginTop: 2, lineHeight: 1.35 }}>{d}</span>
                </span>
              </button>
            );
          })}
        </div>
        <p style={{ margin: '10px 0 0', color: theme.muted, fontSize: '0.86em', fontWeight: 600, lineHeight: 1.45 }}>
          Tapping a citation copies it and opens NFPA in a new tab — paste it into their search. Chapter scope notes stay here in Reference.
        </p>
      </div>

      <div style={card}>
        <span style={label}><IconSun size={14} style={{ verticalAlign: '-2px', marginRight: 4 }} />Text size — sunlight mode</span>
        <input type="range" min="100" max="135" step="5" value={t.typeScale}
          onChange={(e) => setTweak('typeScale', Number(e.target.value))}
          style={{ width: '100%', accentColor: theme.navIndicator, height: 32 }} />
        <div style={{ display: 'flex', justifyContent: 'space-between', color: theme.muted, fontWeight: 700, fontSize: '0.82em' }}>
          <span>Standard</span><span>{t.typeScale}%</span><span>Bright sun</span>
        </div>
      </div>

      <div style={card}>
        <span style={label}>Security</span>
        <label style={{
          display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer', minHeight: 44,
          color: theme.ink, fontWeight: 650, fontSize: '0.95em',
        }}>
          <input type="checkbox" checked={!!stay} onChange={(e) => onStayChange(e.target.checked)}
            style={{ width: 20, height: 20, accentColor: theme.heroAccent, cursor: 'pointer' }} />
          Stay signed in on this device
        </label>
        <p style={{ margin: '4px 0 12px', color: theme.muted, fontSize: '0.85em', fontWeight: 600, lineHeight: 1.45 }}>
          When off, Pocket Marshal asks you to sign in each time it opens. Your conversations and settings stay saved either way.
        </p>
        <button onClick={onLockNow} style={{
          display: 'inline-flex', alignItems: 'center', gap: 8, minHeight: 48, padding: '0 16px',
          background: 'transparent', color: theme.ink, border: `2px solid ${theme.line}`,
          borderRadius: 12, font: 'inherit', fontWeight: 700, fontSize: '0.95em', cursor: 'pointer',
        }}><IconShieldCheck size={19} /> Sign out</button>
      </div>

      <div style={card}>
        <span style={label}>Data</span>
        <button onClick={onClearHistory} disabled={sessionCount === 0} style={{
          display: 'inline-flex', alignItems: 'center', gap: 8, minHeight: 48, padding: '0 16px',
          background: 'transparent', color: sessionCount ? theme.dangerInk : theme.muted, border: `2px solid ${sessionCount ? theme.dangerEdge : theme.line}`,
          borderRadius: 12, font: 'inherit', fontWeight: 700, fontSize: '0.95em', cursor: sessionCount ? 'pointer' : 'default',
        }}><IconTrash size={19} /> Clear my conversations{sessionCount ? ` (${sessionCount})` : ''}</button>
        <p style={{ margin: '10px 0 0', color: theme.muted, fontSize: '0.88em', fontWeight: 600, lineHeight: 1.45 }}>
          Stored only on this device. Clearing removes your conversations and puts the sample inspections back — handy before a demo.
        </p>

        <div style={{ borderTop: `1.5px solid ${theme.line}`, margin: '16px 0 0', paddingTop: 16 }}>
          <button onClick={() => {
            const list = sessions || [];
            if (!list.length) return;
            const stamp = new Date().toISOString().slice(0, 10);
            pmDownloadText('pocket-marshal-' + stamp + '.txt', pmExportAll(list, inspectorName));
          }} disabled={!sessionCount} style={{
            display: 'inline-flex', alignItems: 'center', gap: 8, minHeight: 48, padding: '0 16px',
            background: sessionCount ? theme.cta : 'transparent', color: sessionCount ? theme.ctaInk : theme.muted,
            border: sessionCount ? 'none' : `2px solid ${theme.line}`,
            borderRadius: 12, font: 'inherit', fontWeight: 700, fontSize: '0.95em',
            cursor: sessionCount ? 'pointer' : 'default',
          }}><IconScroll size={19} /> Back up all conversations</button>
          <p style={{ margin: '10px 0 0', color: theme.muted, fontSize: '0.88em', fontWeight: 600, lineHeight: 1.5, textWrap: 'pretty' }}>
            Saves everything to a text file you can email yourself or file with your records.
            <b style={{ color: theme.ink }}> Worth doing regularly:</b> phone storage isn't permanent — clearing
            browsing data, or leaving the app unused for a long stretch, can erase your history. Nothing is
            kept on our side, so a backup is the only copy.
          </p>
        </div>
      </div>

      <div style={{ ...card, display: 'flex', gap: 14, alignItems: 'flex-start' }}>
        <MarshalAvatar styleKind={window.__pmAvatarKind === 'mascot' ? 'mascot' : 'badge'} size={46} />
        <div>
          <div style={{ fontWeight: 800, color: theme.ink, marginBottom: 4 }}>About Marshal</div>
          <p style={{ margin: 0, color: theme.muted, fontSize: '0.92em', lineHeight: 1.55, fontWeight: 550 }}>
            Marshal is a decision-support companion for field inspections. It cites the Florida Fire
            Prevention Code (8th Edition), adopted NFPA standards, and local ordinances — but it is not
            the authority. The AHJ has the final say: when a call is borderline, escalate,
            and verify citations before writing a violation.
          </p>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { PMHistory, PMReference, PMSettings, PM_LIBRARY });
