TLDR / index.html
caustino's picture
Update index.html
0b07206 verified
Raw
History Blame Contribute Delete
54.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HSPA/RIGOR Platform — Documentation Dashboard</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg-primary: #020617; --bg-secondary: #0f172a; --bg-tertiary: #1e293b;
--bg-glass: rgba(30,41,59,0.7); --border-subtle: rgba(148,163,184,0.12);
--border-medium: rgba(148,163,184,0.2); --text-primary: #f1f5f9;
--text-secondary: #94a3b8; --text-muted: #64748b;
--accent-blue: #3b82f6; --accent-green: #22c55e; --accent-amber: #f59e0b;
--accent-purple: #a855f7; --accent-rose: #f43f5e; --accent-cyan: #06b6d4;
--accent-emerald: #10b981; --accent-indigo: #6366f1;
--font-sans: 'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
--font-mono: 'JetBrains Mono','Fira Code',Consolas,monospace;
}
body { font-family: var(--font-sans); background: var(--bg-primary); color: var(--text-primary); min-height: 100vh; line-height: 1.6; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--bg-secondary); }
::-webkit-scrollbar-thumb { background: var(--bg-tertiary); border-radius: 4px; }
.glass { background: var(--bg-glass); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid var(--border-subtle); }
.hidden { display: none !important; }
.fade-in { animation: fadeIn 0.3s ease-out forwards; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.header { position: sticky; top: 0; z-index: 100; background: var(--bg-glass); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-bottom: 1px solid var(--border-subtle); }
.header-inner { max-width: 1400px; margin: 0 auto; padding: 12px 24px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.brand { display: flex; align-items: center; gap: 12px; }
.brand-icon { width: 40px; height: 40px; border-radius: 10px; background: linear-gradient(135deg, var(--accent-blue), var(--accent-cyan)); display: flex; align-items: center; justify-content: center; box-shadow: 0 0 20px rgba(59,130,246,0.15); font-weight: 800; font-size: 18px; color: white; }
.brand-text h1 { font-size: 17px; font-weight: 700; letter-spacing: -0.3px; }
.brand-text p { font-size: 11px; color: var(--text-secondary); margin-top: 1px; }
.sim-panel { display: flex; align-items: center; gap: 12px; }
.sim-progress { display: flex; align-items: center; gap: 8px; opacity: 0; transition: opacity 0.3s; }
.sim-progress.active { opacity: 1; }
.sim-percent { font-family: var(--font-mono); font-size: 12px; color: var(--accent-green); font-weight: 600; }
.sim-bar-bg { width: 120px; height: 6px; background: var(--bg-tertiary); border-radius: 3px; overflow: hidden; }
.sim-bar-fill { height: 100%; width: 0%; background: linear-gradient(90deg, var(--accent-green), var(--accent-emerald)); border-radius: 3px; transition: width 0.1s linear; }
.btn { display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; border-radius: 6px; font-size: 12px; font-weight: 600; border: none; cursor: pointer; transition: all 0.2s; font-family: var(--font-sans); }
.btn-green { background: rgba(34,197,94,0.85); color: white; }
.btn-green:hover { background: var(--accent-green); }
.btn-green:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-slate { background: var(--bg-tertiary); color: var(--text-secondary); border: 1px solid var(--border-medium); }
.btn-slate:hover { background: var(--text-muted); color: white; }
.nav-bar { background: rgba(15,23,42,0.6); border-bottom: 1px solid var(--border-subtle); }
.nav-inner { max-width: 1400px; margin: 0 auto; padding: 0 24px; display: flex; align-items: center; gap: 4px; }
.nav-tab { display: flex; align-items: center; gap: 6px; padding: 12px 16px; font-size: 12px; font-weight: 600; color: var(--text-muted); background: none; border: none; border-bottom: 2px solid transparent; cursor: pointer; transition: all 0.2s; white-space: nowrap; }
.nav-tab:hover { color: var(--text-secondary); background: rgba(255,255,255,0.03); }
.nav-tab.active { color: var(--accent-blue); border-bottom-color: var(--accent-blue); background: rgba(59,130,246,0.06); }
.nav-tab svg { width: 14px; height: 14px; }
.search-box { margin-left: auto; position: relative; }
.search-box input { width: 220px; padding: 7px 12px 7px 32px; background: var(--bg-tertiary); border: 1px solid var(--border-medium); border-radius: 6px; color: var(--text-primary); font-size: 12px; font-family: var(--font-sans); outline: none; transition: all 0.2s; }
.search-box input:focus { border-color: var(--accent-blue); box-shadow: 0 0 0 3px rgba(59,130,246,0.15); }
.search-box input::placeholder { color: var(--text-muted); }
.search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-muted); pointer-events: none; }
.main { max-width: 1400px; margin: 0 auto; padding: 24px; }
.stats-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin-bottom: 24px; }
.stat-card { padding: 20px; border-radius: 12px; text-align: center; transition: transform 0.2s, box-shadow 0.2s; }
.stat-card:hover { transform: translateY(-2px); }
.stat-icon { width: 36px; height: 36px; margin: 0 auto 10px; border-radius: 8px; display: flex; align-items: center; justify-content: center; }
.stat-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 6px; }
.stat-value { font-size: 28px; font-weight: 800; font-family: var(--font-mono); }
.stat-blue { background: rgba(59,130,246,0.08); border: 1px solid rgba(59,130,246,0.2); }
.stat-blue .stat-icon { background: rgba(59,130,246,0.15); color: var(--accent-blue); }
.stat-blue .stat-label { color: var(--accent-blue); } .stat-blue .stat-value { color: var(--accent-blue); }
.stat-green { background: rgba(34,197,94,0.08); border: 1px solid rgba(34,197,94,0.2); }
.stat-green .stat-icon { background: rgba(34,197,94,0.15); color: var(--accent-green); }
.stat-green .stat-label { color: var(--accent-green); } .stat-green .stat-value { color: var(--accent-green); }
.stat-amber { background: rgba(245,158,11,0.08); border: 1px solid rgba(245,158,11,0.2); }
.stat-amber .stat-icon { background: rgba(245,158,11,0.15); color: var(--accent-amber); }
.stat-amber .stat-label { color: var(--accent-amber); } .stat-amber .stat-value { color: var(--accent-amber); }
.stat-purple { background: rgba(168,85,247,0.08); border: 1px solid rgba(168,85,247,0.2); }
.stat-purple .stat-icon { background: rgba(168,85,247,0.15); color: var(--accent-purple); }
.stat-purple .stat-label { color: var(--accent-purple); } .stat-purple .stat-value { color: var(--accent-purple); }
.stat-rose { background: rgba(244,63,94,0.08); border: 1px solid rgba(244,63,94,0.2); }
.stat-rose .stat-icon { background: rgba(244,63,94,0.15); color: var(--accent-rose); }
.stat-rose .stat-label { color: var(--accent-rose); } .stat-rose .stat-value { color: var(--accent-rose); }
.overview-desc { padding: 24px; border-radius: 12px; margin-bottom: 24px; }
.overview-desc h2 { font-size: 16px; font-weight: 700; margin-bottom: 12px; }
.overview-desc p { font-size: 13px; color: var(--text-secondary); line-height: 1.7; margin-bottom: 16px; }
.overview-features { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.feature-card { padding: 16px; background: rgba(255,255,255,0.03); border-radius: 8px; border: 1px solid var(--border-subtle); }
.feature-card h3 { font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.feature-card p { font-size: 11px; color: var(--text-muted); line-height: 1.6; margin: 0; }
.volume-nav { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.volume-card { padding: 16px; border-radius: 12px; text-align: left; cursor: pointer; transition: all 0.2s; border: 1px solid transparent; }
.volume-card:hover { transform: translateY(-2px); filter: brightness(1.1); }
.volume-card .vol-icon { width: 32px; height: 32px; margin-bottom: 10px; }
.volume-card .vol-num { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; }
.volume-card .vol-name { font-size: 13px; font-weight: 600; line-height: 1.3; }
.volume-card .vol-count { font-size: 11px; margin-top: 4px; opacity: 0.7; }
.volume-section { border-radius: 12px; overflow: hidden; margin-bottom: 12px; transition: all 0.2s; }
.volume-header { width: 100%; display: flex; align-items: center; gap: 12px; padding: 16px 20px; background: none; border: none; color: var(--text-primary); font-size: 14px; font-weight: 600; cursor: pointer; text-align: left; transition: background 0.2s; }
.volume-header:hover { background: rgba(255,255,255,0.03); }
.volume-header .chevron { transition: transform 0.2s; color: var(--text-muted); flex-shrink: 0; }
.volume-header.expanded .chevron { transform: rotate(90deg); }
.volume-header .vol-badge { margin-left: auto; font-size: 11px; font-weight: 500; color: var(--text-muted); }
.volume-body { max-height: 0; overflow: hidden; transition: max-height 0.3s ease-out; }
.volume-body.open { max-height: 2000px; }
.figure-item { padding: 14px 20px 14px 52px; border-left: 2px solid var(--border-subtle); margin-left: 20px; cursor: pointer; transition: background 0.2s; position: relative; }
.figure-item:hover { background: rgba(255,255,255,0.03); }
.figure-item.active { background: rgba(255,255,255,0.05); }
.figure-item h4 { font-size: 13px; font-weight: 500; color: var(--text-primary); margin-bottom: 4px; }
.figure-item .fig-desc { font-size: 11px; color: var(--text-muted); line-height: 1.5; margin-bottom: 8px; }
.figure-item .fig-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.figure-item .fig-tag { padding: 2px 8px; border-radius: 4px; font-size: 10px; font-weight: 500; }
.figures-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.figure-card { padding: 16px; border-radius: 10px; cursor: pointer; transition: all 0.2s; border: 1px solid transparent; }
.figure-card:hover { transform: translateY(-2px); filter: brightness(1.08); }
.figure-card .fig-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px; }
.figure-card .fig-id { font-family: var(--font-mono); font-size: 11px; font-weight: 600; }
.figure-card .fig-vol { font-size: 10px; color: var(--text-muted); }
.figure-card h3 { font-size: 12px; font-weight: 600; line-height: 1.4; margin-bottom: 6px; }
.figure-card .fig-desc-short { font-size: 11px; color: var(--text-muted); line-height: 1.5; margin-bottom: 10px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tables-section { margin-bottom: 24px; }
.tables-section h2 { font-size: 16px; font-weight: 700; margin-bottom: 16px; }
.cc-tables-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.cc-table-item { padding: 12px; background: rgba(255,255,255,0.03); border-radius: 8px; border: 1px solid var(--border-subtle); transition: all 0.2s; }
.cc-table-item:hover { background: rgba(255,255,255,0.05); border-color: var(--border-medium); }
.cc-table-item .cc-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
.cc-table-item .cc-num { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); }
.cc-table-item .cc-cat { padding: 2px 6px; border-radius: 4px; font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.3px; }
.cc-table-item .cc-title { font-size: 12px; font-weight: 500; line-height: 1.4; }
.vol-tables-list { display: flex; flex-direction: column; gap: 10px; }
.vol-tables-item { padding: 12px 16px; background: rgba(255,255,255,0.02); border-radius: 8px; border: 1px solid var(--border-subtle); }
.vol-tables-item .vt-header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.vol-tables-item .vt-name { font-size: 13px; font-weight: 600; }
.vol-tables-item .vt-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.matrix-table-wrap { overflow-x: auto; margin-bottom: 24px; }
.matrix-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.matrix-table th { text-align: left; padding: 10px 12px; color: var(--text-muted); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; border-bottom: 1px solid var(--border-medium); }
.matrix-table td { padding: 10px 12px; border-bottom: 1px solid var(--border-subtle); vertical-align: top; }
.matrix-table tr:hover { background: rgba(255,255,255,0.02); }
.matrix-table .claim-num { font-family: var(--font-mono); font-weight: 700; color: var(--accent-blue); }
.matrix-table .fig-badge { display: inline-block; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 500; margin-right: 4px; margin-bottom: 2px; }
.matrix-note { text-align: center; font-size: 11px; color: var(--text-muted); padding: 12px; }
.footer { border-top: 1px solid var(--border-subtle); margin-top: 40px; padding: 16px 24px; }
.footer-inner { max-width: 1400px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; font-size: 11px; color: var(--text-muted); }
.footer-inner .version { font-family: var(--font-mono); }
.vol-blue { background: rgba(59,130,246,0.06); border-color: rgba(59,130,246,0.25); }
.vol-blue .vol-icon { color: var(--accent-blue); } .vol-blue .vol-num { color: var(--accent-blue); }
.vol-blue .fig-tag { background: rgba(59,130,246,0.15); color: #93c5fd; } .vol-blue .fig-id { color: var(--accent-blue); }
.vol-green { background: rgba(34,197,94,0.06); border-color: rgba(34,197,94,0.25); }
.vol-green .vol-icon { color: var(--accent-green); } .vol-green .vol-num { color: var(--accent-green); }
.vol-green .fig-tag { background: rgba(34,197,94,0.15); color: #86efac; } .vol-green .fig-id { color: var(--accent-green); }
.vol-amber { background: rgba(245,158,11,0.06); border-color: rgba(245,158,11,0.25); }
.vol-amber .vol-icon { color: var(--accent-amber); } .vol-amber .vol-num { color: var(--accent-amber); }
.vol-amber .fig-tag { background: rgba(245,158,11,0.15); color: #fcd34d; } .vol-amber .fig-id { color: var(--accent-amber); }
.vol-purple { background: rgba(168,85,247,0.06); border-color: rgba(168,85,247,0.25); }
.vol-purple .vol-icon { color: var(--accent-purple); } .vol-purple .vol-num { color: var(--accent-purple); }
.vol-purple .fig-tag { background: rgba(168,85,247,0.15); color: #d8b4fe; } .vol-purple .fig-id { color: var(--accent-purple); }
.vol-rose { background: rgba(244,63,94,0.06); border-color: rgba(244,63,94,0.25); }
.vol-rose .vol-icon { color: var(--accent-rose); } .vol-rose .vol-num { color: var(--accent-rose); }
.vol-rose .fig-tag { background: rgba(244,63,94,0.15); color: #fda4af; } .vol-rose .fig-id { color: var(--accent-rose); }
.vol-cyan { background: rgba(6,182,212,0.06); border-color: rgba(6,182,212,0.25); }
.vol-cyan .vol-icon { color: var(--accent-cyan); } .vol-cyan .vol-num { color: var(--accent-cyan); }
.vol-cyan .fig-tag { background: rgba(6,182,212,0.15); color: #67e8f9; } .vol-cyan .fig-id { color: var(--accent-cyan); }
.vol-emerald { background: rgba(16,185,129,0.06); border-color: rgba(16,185,129,0.25); }
.vol-emerald .vol-icon { color: var(--accent-emerald); } .vol-emerald .vol-num { color: var(--accent-emerald); }
.vol-emerald .fig-tag { background: rgba(16,185,129,0.15); color: #6ee7b7; } .vol-emerald .fig-id { color: var(--accent-emerald); }
.vol-indigo { background: rgba(99,102,241,0.06); border-color: rgba(99,102,241,0.25); }
.vol-indigo .vol-icon { color: var(--accent-indigo); } .vol-indigo .vol-num { color: var(--accent-indigo); }
.vol-indigo .fig-tag { background: rgba(99,102,241,0.15); color: #a5b4fc; } .vol-indigo .fig-id { color: var(--accent-indigo); }
.cat-IP { background: rgba(139,92,246,0.15); color: #c4b5fd; } .cat-Nav { background: rgba(148,163,184,0.15); color: #cbd5e1; }
.cat-Ref { background: rgba(100,116,139,0.15); color: #94a3b8; } .cat-Genomics { background: rgba(34,197,94,0.15); color: #86efac; }
.cat-Clinical { background: rgba(244,63,94,0.15); color: #fda4af; } .cat-QA { background: rgba(245,158,11,0.15); color: #fcd34d; }
.cat-Legal { background: rgba(59,130,246,0.15); color: #93c5fd; } .cat-Risk { background: rgba(249,115,22,0.15); color: #fdba74; }
.cat-Regulatory { background: rgba(239,68,68,0.15); color: #fca5a5; } .cat-Security { background: rgba(234,179,8,0.15); color: #fde047; }
.cat-Software { background: rgba(168,85,247,0.15); color: #d8b4fe; } .cat-Evidence { background: rgba(99,102,241,0.15); color: #a5b4fc; }
.cat-Ops { background: rgba(6,182,212,0.15); color: #67e8f9; } .cat-Privacy { background: rgba(236,72,153,0.15); color: #f9a8d4; }
.cat-DevOps { background: rgba(20,184,166,0.15); color: #5eead4; }
@media (max-width: 1024px) { .stats-grid { grid-template-columns: repeat(3, 1fr); } .figures-grid { grid-template-columns: repeat(2, 1fr); } .volume-nav { grid-template-columns: repeat(2, 1fr); } .cc-tables-grid { grid-template-columns: repeat(2, 1fr); } .overview-features { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .stats-grid { grid-template-columns: repeat(2, 1fr); } .figures-grid { grid-template-columns: 1fr; } .volume-nav { grid-template-columns: 1fr; } .cc-tables-grid { grid-template-columns: 1fr; } .header-inner { flex-wrap: wrap; } .search-box input { width: 160px; } .nav-inner { overflow-x: auto; } }
</style>
<base target="_blank">
</head>
<body>
<header class="header">
<div class="header-inner">
<div class="brand">
<div class="brand-icon">H</div>
<div class="brand-text">
<h1>HSPA/RIGOR Platform</h1>
<p>Patent- & Regulatory-Grade Documentation</p>
</div>
</div>
<div class="sim-panel">
<div class="sim-progress" id="simProgress">
<span class="sim-percent" id="simPercent">0%</span>
<div class="sim-bar-bg"><div class="sim-bar-fill" id="simBar"></div></div>
</div>
<button class="btn btn-green" id="btnSim" onclick="startSimulation()">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>
Simulate
</button>
<button class="btn btn-slate" onclick="resetSimulation()">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>
Reset
</button>
</div>
</div>
</header>
<nav class="nav-bar">
<div class="nav-inner">
<button class="nav-tab active" data-tab="overview" onclick="switchTab('overview')">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
Overview
</button>
<button class="nav-tab" data-tab="architecture" onclick="switchTab('architecture')">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></svg>
Volumes
</button>
<button class="nav-tab" data-tab="figures" onclick="switchTab('figures')">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="10" y1="9" x2="8" y2="9"/></svg>
Figures
</button>
<button class="nav-tab" data-tab="tables" onclick="switchTab('tables')">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"/><rect x="2" y="14" width="20" height="8" rx="2" ry="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg>
Tables
</button>
<button class="nav-tab" data-tab="matrix" onclick="switchTab('matrix')">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>
Cross-Ref
</button>
<div class="search-box">
<svg class="search-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input type="text" id="searchInput" placeholder="Search figures, tables..." oninput="handleSearch(this.value)">
</div>
</div>
</nav>
<main class="main" id="mainContent">
<div id="tab-overview" class="tab-content">
<div class="stats-grid">
<div class="stat-card stat-blue">
<div class="stat-icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></svg></div>
<div class="stat-label">Volumes</div><div class="stat-value">8</div>
</div>
<div class="stat-card stat-green">
<div class="stat-icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="10" y1="9" x2="8" y2="9"/></svg></div>
<div class="stat-label">Figures</div><div class="stat-value">50</div>
</div>
<div class="stat-card stat-amber">
<div class="stat-icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"/><rect x="2" y="14" width="20" height="8" rx="2" ry="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg></div>
<div class="stat-label">Tables</div><div class="stat-value">100</div>
</div>
<div class="stat-card stat-purple">
<div class="stat-icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg></div>
<div class="stat-label">Cross-Refs</div><div class="stat-value">28</div>
</div>
<div class="stat-card stat-rose">
<div class="stat-icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg></div>
<div class="stat-label">USPTO Claims</div><div class="stat-value">7</div>
</div>
</div>
<div class="overview-desc glass">
<h2>Platform Overview</h2>
<p>The <strong style="color:var(--accent-blue)">HSPA/RIGOR Platform</strong> (Hyper-Synchronous Processing Array / Reproducible Integrated Genomic Operations Repository) is a comprehensive, patent-grade documentation system for genomic processing, post-quantum cryptographic security, and regulatory compliance. Consistent numbering across USPTO, FDA, whitepaper, dissertation, and software documentation ensures complete traceability.</p>
<div class="overview-features">
<div class="feature-card">
<h3 style="color:var(--accent-blue)">Scientific Assimilation</h3>
<p>NLP-powered literature ingestion, NER, entity linking, and automated adapter generation for GWAS catalogs.</p>
</div>
<div class="feature-card">
<h3 style="color:var(--accent-green)">Genomic Processing</h3>
<p>PRS calculation (PRS-CS, LDpred2), LD correction, ancestry calibration, and population transferability analysis.</p>
</div>
<div class="feature-card">
<h3 style="color:var(--accent-amber)">Zero-Trust Security</h3>
<p>NIST PQC algorithms (ML-KEM, ML-DSA, SLH-DSA), Merkle DAG ledger, blockchain anchoring, and immutable audit trails.</p>
</div>
</div>
</div>
<div class="volume-nav" id="overviewVolumes"></div>
</div>
<div id="tab-architecture" class="tab-content hidden"></div>
<div id="tab-figures" class="tab-content hidden"></div>
<div id="tab-tables" class="tab-content hidden"></div>
<div id="tab-matrix" class="tab-content hidden"></div>
</main>
<footer class="footer">
<div class="footer-inner">
<span>HSPA/RIGOR Platform Documentation</span>
<span class="version">v2.0.0 | 16 July 2026</span>
</div>
</footer>
<script>
const volumes = [
{ id: "v1", title: "System Architecture", icon: "database", color: "blue",
children: [
{ id: "f1", title: "Overall HSPA/RIGOR Platform Architecture", tables: ["Table 1","Table 10","Table 72","Table 100"], desc: "Mermaid flowchart: External Inputs → SAE → Core Block → Security → Ledger → Outputs" },
{ id: "f2", title: "Scientific Assimilation Engine (SAE)", tables: ["Table 2","Table 3","Table 4"], desc: "Document → Section Splitter → Paragraph Splitter → Sentence Tokenizer → NER → Entity Linker → Triple Extractor → Knowledge Graph" },
{ id: "f3", title: "Core Computational Block", tables: ["Table 11","Table 15","Table 17","Table 21"], desc: "GWAS Summary Stats → QC → LD Reference Selection → PRS Method → Score → Calibration → Clinical Report" },
{ id: "f4", title: "NLP Processing Pipeline", tables: ["Table 2"], desc: "Raw Text → Pre-processing → Tokenization → POS Tagging → Dependency Parsing → Constituency Parsing → Relation Extraction → JSON-LD" },
{ id: "f5", title: "Named Entity Recognition Architecture", tables: ["Table 3"], desc: "Token Sequence → BioBERT Embeddings → BiLSTM → CRF Decoder → Entity Tags → Entity Linking → Knowledge Base" },
{ id: "f6", title: "Repository Resolution Engine", tables: ["Table 4","Table 75"], desc: "Recognized Entity → Repository Mapping → URL Template Resolution → External API → Local Cache → Standardized Schema" },
{ id: "f7", title: "Dependency Graph Construction", tables: ["Table 7","Table 8"], desc: "Extracted Triples → Node Deduplication + Edge Creation → Graph Database → Semantic Query Interface" },
{ id: "f8", title: "Automated Adapter Generator", tables: ["Table 5","Table 9"], desc: "Data Schema → Template Engine → Code Generation → Sandbox Testing → Deploy Adapter (or Error Feedback Loop)" },
{ id: "f9", title: "Pipeline Orchestration Controller", tables: ["Table 6","Table 96"], desc: "Scheduler → Workflow Parser → DAG Validator → Task Dispatcher → Completion Check → Cleanup & Log → Notification" },
{ id: "f10", title: "Runtime Service Topology", tables: ["Table 38","Table 40","Table 97"], desc: "API Gateway ↔ Auth Service → Orchestrator ↔ Event Queue → PRS Calculation → SET Ledger Node" }
]},
{ id: "v2", title: "Genomic Processing", icon: "activity", color: "green",
children: [
{ id: "f11", title: "GWAS Summary Statistics Import", tables: ["Table 11","Table 12","Table 13"], desc: "GWAS Catalog/FTP → Format Detection → Column Mapping/VCF Parser → Standard Schema → QC → GWAS Inventory DB" },
{ id: "f12", title: "Reference Genome Pipeline", tables: ["Table 14"], desc: "Reference FASTA → Indexing → Chromosome Splitting → Liftover Chain Storage → Build Registry → Reference Genome Catalog" },
{ id: "f13", title: "Variant Calling Pipeline", tables: ["Table 16"], desc: "Raw Reads (FASTQ) → Alignment (BWA/minimap2) → Duplicate Marking → BQSR → Variant Calling (GATK/DeepVariant) → Filtering → Cohort VCF → QC Metrics" },
{ id: "f14", title: "PRS Workflow", tables: ["Table 15","Table 17","Table 18"], desc: "GWAS Summary Statistics + LD Reference Panel → PRS Method Selection (PRS-CS/LDpred2) → Score Individuals → Ancestry Calibration → Clinical Report" },
{ id: "f15", title: "LD Correction Workflow", tables: ["Table 15","Table 18"], desc: "GWAS Summary Statistics → Match to LD Panel SNPs → Compute LD Matrix → Shrinkage/Regularization → Update Effect Sizes → Posterior Effect Sizes" },
{ id: "f16", title: "Ancestry PCA", tables: ["Table 19","Table 20"], desc: "Reference Genotypes → PCA → PC Loadings → Target Genotypes → Project onto Loadings → Population Assignment → Sample Projection Table" },
{ id: "f17", title: "PRS Calibration", tables: ["Table 21"], desc: "Raw PRS → Decile Binning → Observed Disease Rate + Predicted Risk → Calibration Curve → AUC/R² Metrics" },
{ id: "f18", title: "Population Transferability", tables: ["Table 22"], desc: "GWAS EUR → PRS Model → Score EUR Target + Score AFR Target → Performance Metrics → Transferability Report" }
]},
{ id: "v3", title: "Security", icon: "shield", color: "amber",
children: [
{ id: "f19", title: "Zero Trust Architecture", tables: ["Table 24","Table 91"], desc: "User/Service → Policy Enforcement Point → Policy Decision Point ↔ Policy Rules → Resource/API" },
{ id: "f20", title: "ML-KEM Key Exchange", tables: ["Table 25","Table 84"], desc: "ClientHello (ML-KEM-1024) → ServerHello + Encapsulated Key → Shared Secret (Kyber.CCAKEM.Decap) → Encrypted Application Data (AES-256-GCM)" },
{ id: "f21", title: "ML-DSA Signature Flow", tables: ["Table 26","Table 31"], desc: "Data Payload → Hash (SHA3-512) → ML-DSA.Sign → Signature → ML-DSA.Verify → Valid?" },
{ id: "f22", title: "Merkle DAG", tables: ["Table 28","Table 85"], desc: "GWAS Result + PRS Model + Calibration → Individual Hashes → Merkle Root → Batch Root" },
{ id: "f23", title: "Ledger Synchronization", tables: ["Table 29","Table 37"], desc: "Node A → New DAG Node (content-hash) → Node B → Verify & Store → ACK + Signature → Consistent State" },
{ id: "f24", title: "Blockchain Anchoring", tables: ["Table 27","Table 30"], desc: "Batch Root → SLH-DSA Sign (Off-chain) → Blockchain Transaction → Smart Contract Anchor → Immutable Timestamp Proof" }
]},
{ id: "v4", title: "Software", icon: "code", color: "purple",
children: [
{ id: "f25", title: "PostgreSQL Schema", tables: ["Table 32","Table 33","Table 34","Table 35","Table 36","Table 37","Table 86","Table 87"], desc: "ER Diagram: CASES ↔ EXHIBITS ↔ CLAIMS ↔ PRS_RUNS ↔ LEDGER_NODES" },
{ id: "f26", title: "Entity Relationship Diagram", tables: ["Table 32–37","Table 100"], desc: "CASE ↔ EXHIBIT ↔ CLAIM ↔ PRS_RUN ↔ LEDGER_NODE ↔ BLOCK" },
{ id: "f27", title: "API Architecture", tables: ["Table 38","Table 39","Table 88","Table 97"], desc: "Client → API Gateway → Auth Service + Pipeline Orchestrator + Query Service → PostgreSQL" },
{ id: "f28", title: "Authentication Flow", tables: ["Table 39","Table 91"], desc: "User → Frontend → Auth Service → JWT → API → Validate Token → Protected Resource" },
{ id: "f29", title: "React Dashboard", tables: ["Table 41"], desc: "Widget Registry + Active Cases + PRS Run Status + Report Viewer ↔ API Gateway → Backend Services" },
{ id: "f30", title: "Event Queue", tables: ["Table 40","Table 97"], desc: "Orchestrator → Message Queue → Ledger Sync Worker + Notification Service + Audit Log Writer" }
]},
{ id: "v5", title: "FDA & Regulatory", icon: "book", color: "rose",
children: [
{ id: "f31", title: "Risk Management (ISO 14971)", tables: ["Table 42","Table 43","Table 44","Table 81"], desc: "Risk Management Plan → Hazard Identification → Risk Estimation → Evaluation → Controls → Verification → Residual Risk → Post-Market Monitoring" },
{ id: "f32", title: "Hazard Controls", tables: ["Table 44","Table 82"], desc: "Hazard: Incorrect PRS → Checksum Verification + Sandbox Testing + Manual Review Flag → Effectiveness Verified → Residual Risk Low/Medium" },
{ id: "f33", title: "Traceability Matrix", tables: ["Table 45","Table 83"], desc: "User Need → Design Input → Design Output → Verification → Validation" },
{ id: "f34", title: "Verification Flow", tables: ["Table 46"], desc: "Test Case → Execute → Record Result → Compare to Expected → Pass/Fail → Defect Log → Fix → Re-execute" },
{ id: "f35", title: "Validation Workflow", tables: ["Table 47","Table 48"], desc: "Validation Protocol → Assemble Cohort → Execute PRS Pipeline → Compute Metrics → Acceptance Criteria? → Approve or Investigate" },
{ id: "f36", title: "Clinical Release Process", tables: ["Table 49","Table 61","Table 80"], desc: "Release Candidate → SBOM Review → Security Scan → Verification Results → Validation Results → IRB Approval → Release Checklist → Deploy or Fix" }
]},
{ id: "v6", title: "AI", icon: "eye", color: "cyan",
children: [
{ id: "f37", title: "Transformer Architecture", tables: ["Table 51","Table 52"], desc: "Input Tokens → Embedding + Positional Encoding → Encoder Layer ×N → Decoder Layer ×N → Linear Projection → Softmax → Output Probabilities" },
{ id: "f38", title: "Attention Blocks", tables: ["Table 52"], desc: "Q + K → MatMul → Scale → Optional Mask → Softmax → MatMul with V → Attention Output" },
{ id: "f39", title: "Reasoning Loop", tables: ["Table 53","Table 56"], desc: "Question → Answer → Core Block → Attention → Add & Norm → MLP → Add & Norm → Repeat ×4 → Output" },
{ id: "f40", title: "Training Pipeline", tables: ["Table 54","Table 55","Table 56"], desc: "Dataset → Preprocess → Forward Pass → Loss → Backward Pass → Optimizer → Log Metrics → Evaluation → Checkpoint → Save" }
]},
{ id: "v7", title: "Reproducibility", icon: "git", color: "emerald",
children: [
{ id: "f41", title: "Docker Build Graph", tables: ["Table 57","Table 58","Table 96"], desc: "Git Commit → Dockerfile → docker build → Docker Image → Container Registry → Pipeline Execution → PRS Output" },
{ id: "f42", title: "Provenance Manifest", tables: ["Table 60","Table 63","Table 79"], desc: "Input Data + Process + Output Artifact → Provenance Record → Provenance Graph Database (W3C PROV)" },
{ id: "f43", title: "Git Version Graph", tables: ["Table 59"], desc: "main branch → commits a1b2c3, d4e5f6 (v1.0.0), 7a8b9c, 0d1e2f (v2.0.0)" },
{ id: "f44", title: "Artifact Lineage", tables: ["Table 60","Table 65"], desc: "GWAS Raw Data + LD Panel → PRS Model → PRS Scores → Clinical Report → Lineage Records at each step" },
{ id: "f45", title: "Chain of Custody", tables: ["Table 64","Table 71","Table 89"], desc: "Artifact Created → Transfer to Custodian → Secure Storage → Transfer to Expert → Court Submission → Integrity Verification → Custody Log" }
]},
{ id: "v8", title: "Litigation Evidence", icon: "users", color: "indigo",
children: [
{ id: "f46", title: "Court Evidence Flow", tables: ["Table 66","Table 70","Table 71"], desc: "Scientific Artifact → Content Hash → ML-DSA Sign by Expert → Exhibit Attachment → Court Filing → Docket Number → Opposing Verification" },
{ id: "f47", title: "Daubert Workflow", tables: ["Table 68"], desc: "Proffered Evidence → Tested? → Peer Reviewed? → Known Error Rate? → Standards Exist? → General Acceptance? → Admissibility Decision" },
{ id: "f48", title: "Scientific Citation Network", tables: ["Table 69"], desc: "Expert Report → Cites GWAS Study A (Supports) + GWAS Study B (Contradicts) + Methodology Paper (Background)" },
{ id: "f49", title: "Evidence Provenance", tables: ["Table 63","Table 70","Table 89"], desc: "Raw Data → Processed Data → Analysis Results → Exhibit Produced → Provenance Records at each transformation" },
{ id: "f50", title: "Expert Report Assembly", tables: ["Table 67","Table 73"], desc: "Case Materials → Background → Methods (Data Sources + Pipeline) → Results → Expert Opinions → Signature & Verification → Final Filing" }
]}
];
const crossCuttingTables = [
{ id: "t72", num: "72", title: "USPTO Claim-to-Figure Matrix", category: "IP" },
{ id: "t73", num: "73", title: "Figure-to-Table Cross-Reference", category: "Nav" },
{ id: "t74", num: "74", title: "Acronym & Abbreviation Glossary", category: "Ref" },
{ id: "t75", num: "75", title: "SNP Annotation Dictionary", category: "Genomics" },
{ id: "t76", num: "76", title: "Variant Classification Matrix (ACMG/AMP)", category: "Genomics" },
{ id: "t77", num: "77", title: "Population Allele Frequency Table", category: "Genomics" },
{ id: "t78", num: "78", title: "Clinical Performance Metrics (Per Disease)", category: "Clinical" },
{ id: "t79", num: "79", title: "Reproducibility Manifest Schema Validation Log", category: "QA" },
{ id: "t80", num: "80", title: "SPDX License Inventory", category: "Legal" },
{ id: "t81", num: "81", title: "Risk Register (Project Risks)", category: "Risk" },
{ id: "t82", num: "82", title: "ISO 14971 Hazard Analysis Detail", category: "Risk" },
{ id: "t83", num: "83", title: "FDA Traceability Matrix (Full)", category: "Regulatory" },
{ id: "t84", num: "84", title: "Cryptographic Key Hierarchy", category: "Security" },
{ id: "t85", num: "85", title: "Merkle Node Definitions (Extended)", category: "Security" },
{ id: "t86", num: "86", title: "PostgreSQL Data Dictionary (All Columns)", category: "Software" },
{ id: "t87", num: "87", title: "PostgreSQL Index Inventory", category: "Software" },
{ id: "t88", num: "88", title: "API Request/Response Example Catalog", category: "Software" },
{ id: "t89", num: "89", title: "Evidence Chain Metadata (Detailed)", category: "Evidence" },
{ id: "t90", num: "90", title: "Long-Term Archive Storage Inventory", category: "Ops" },
{ id: "t91", num: "91", title: "User Access Audit Log", category: "Security" },
{ id: "t92", num: "92", title: "Data Anonymization/Pseudonymization Map", category: "Privacy" },
{ id: "t93", num: "93", title: "Cohort Phenotype Definitions", category: "Clinical" },
{ id: "t94", num: "94", title: "Data Transfer Agreement Log", category: "Legal" },
{ id: "t95", num: "95", title: "Computational Environment Specification", category: "Ops" },
{ id: "t96", num: "96", title: "Build & Deployment Log", category: "DevOps" },
{ id: "t97", num: "97", title: "Inter-Component Message Schema Catalog", category: "Software" },
{ id: "t98", num: "98", title: "Configuration Parameter Registry", category: "Ops" },
{ id: "t99", num: "99", title: "Glossary of Scientific Terms", category: "Ref" },
{ id: "t100", num: "100", title: "Master Figure-Table-Volume Index", category: "Nav" }
];
const roman = ["I","II","III","IV","V","VI","VII","VIII"];
const claimMatrix = [
{ claim: "1", element: "Scientific assimilation engine", figs: "FIG. 1, FIG. 2", support: "Overall architecture and SAE detail" },
{ claim: "2", element: "NLP processing pipeline with NER", figs: "FIG. 4, FIG. 5", support: "Pipeline and entity recognition architecture" },
{ claim: "3", element: "Automatic adapter generation", figs: "FIG. 8", support: "Adapter generator workflow" },
{ claim: "4", element: "Immutable ledger via Merkle DAG", figs: "FIG. 22, FIG. 24", support: "DAG construction and blockchain anchoring" },
{ claim: "5", element: "PRS calculation with LD correction", figs: "FIG. 14, FIG. 15", support: "PRS and LD correction workflows" },
{ claim: "6", element: "Zero-trust security with PQC", figs: "FIG. 19, FIG. 20, FIG. 21", support: "Architecture, key exchange, and signing" },
{ claim: "7", element: "Reproducibility via containers/provenance", figs: "FIG. 41, FIG. 42", support: "Docker build and provenance manifest" }
];
const svgs = {
database: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/></svg>`,
activity: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>`,
shield: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>`,
code: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>`,
book: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>`,
eye: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>`,
git: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>`,
users: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>`,
chevronRight: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>`
};
let currentTab = "overview", expanded = {}, selectedFigure = null, simInterval = null;
function renderOverviewVolumes() {
document.getElementById("overviewVolumes").innerHTML = volumes.map((v, i) => `
<div class="volume-card vol-${v.color}" onclick="navToVolume('${v.id}')">
<div class="vol-icon">${svgs[v.icon]}</div>
<div class="vol-num">Volume ${roman[i]}</div>
<div class="vol-name">${v.title}</div>
<div class="vol-count">${v.children.length} figures</div>
</div>
`).join("");
}
function renderVolumes() {
const container = document.getElementById("tab-architecture");
container.innerHTML = volumes.map((v, i) => {
const isOpen = expanded[v.id] || false;
return `<div class="volume-section vol-${v.color} glass">
<button class="volume-header ${isOpen ? 'expanded' : ''}" onclick="toggleVolume('${v.id}')">
<span class="chevron">${svgs.chevronRight}</span>
<span style="color:var(--accent-${v.color})">${svgs[v.icon]}</span>
<span>Volume ${roman[i]}${v.title}</span>
<span class="vol-badge">${v.children.length} figures</span>
</button>
<div class="volume-body ${isOpen ? 'open' : ''}" id="body-${v.id}">
${v.children.map(c => `
<div class="figure-item ${selectedFigure === c.id ? 'active' : ''}" onclick="selectFigure('${c.id}')">
<h4>${c.title}</h4>
<p class="fig-desc">${c.desc}</p>
<div class="fig-tags">${c.tables.map(t => `<span class="fig-tag">${t}</span>`).join('')}</div>
</div>
`).join('')}
</div>
</div>`;
}).join("");
}
function renderFigures() {
const allFigs = volumes.flatMap(v => v.children.map(c => ({...c, volColor: v.color, volTitle: v.title})));
const container = document.getElementById("tab-figures");
container.innerHTML = `<div class="figures-grid">${allFigs.map(f => `
<div class="figure-card vol-${f.volColor}" onclick="selectFigure('${f.id}')">
<div class="fig-header">
<span class="fig-id">${f.id.toUpperCase()}</span>
<span class="fig-vol">${f.volTitle}</span>
</div>
<h3>${f.title.replace(/^FIG\. \d+ — /, '')}</h3>
<p class="fig-desc-short">${f.desc}</p>
<div class="fig-tags">${f.tables.slice(0,3).map(t => `<span class="fig-tag">${t}</span>`).join('')}${f.tables.length > 3 ? '<span class="fig-tag">+' + (f.tables.length - 3) + '</span>' : ''}</div>
</div>
`).join('')}</div>`;
}
function renderTables() {
const container = document.getElementById("tab-tables");
container.innerHTML = `
<div class="tables-section">
<h2>Cross-Cutting Tables (72–100)</h2>
<div class="cc-tables-grid">${crossCuttingTables.map(t => `
<div class="cc-table-item">
<div class="cc-header">
<span class="cc-num">Table ${t.num}</span>
<span class="cc-cat cat-${t.category}">${t.category}</span>
</div>
<div class="cc-title">${t.title}</div>
</div>
`).join('')}</div>
</div>
<div class="tables-section">
<h2>Volume-Specific Tables</h2>
<div class="vol-tables-list">${volumes.map((v, i) => {
const allTables = [...new Set(v.children.flatMap(c => c.tables))];
return `<div class="vol-tables-item">
<div class="vt-header">
<span style="color:var(--accent-${v.color})">${svgs[v.icon]}</span>
<span class="vt-name">Volume ${roman[i]}${v.title}</span>
</div>
<div class="vt-tags">${allTables.map(t => `<span class="fig-tag" style="background:rgba(255,255,255,0.05);color:var(--text-secondary)">${t}</span>`).join('')}</div>
</div>`;
}).join('')}</div>
</div>`;
}
function renderMatrix() {
const container = document.getElementById("tab-matrix");
container.innerHTML = `
<div class="glass" style="padding:24px;border-radius:12px;margin-bottom:24px;">
<h2 style="font-size:16px;font-weight:700;margin-bottom:16px;">USPTO Claim-to-Figure Matrix (Table 72)</h2>
<div class="matrix-table-wrap">
<table class="matrix-table">
<thead><tr><th>Claim #</th><th>Claim Element</th><th>Figure(s)</th><th>Support</th></tr></thead>
<tbody>${claimMatrix.map(row => `
<tr>
<td class="claim-num">${row.claim}</td>
<td>${row.element}</td>
<td>${row.figs.split(', ').map(f => `<span class="fig-badge" style="background:rgba(59,130,246,0.1);color:#93c5fd;border:1px solid rgba(59,130,246,0.2)">${f}</span>`).join('')}</td>
<td style="color:var(--text-muted);font-size:11px;">${row.support}</td>
</tr>
`).join('')}</tbody>
</table>
</div>
</div>
<div class="glass" style="padding:24px;border-radius:12px;">
<h2 style="font-size:16px;font-weight:700;margin-bottom:16px;">Figure-to-Table Cross-Reference (Table 73)</h2>
<div class="matrix-table-wrap">
<table class="matrix-table">
<thead><tr><th>Figure</th><th>Title</th><th>Primary Tables</th></tr></thead>
<tbody>${volumes.flatMap(v => v.children.map(c => ({...c, volColor: v.color}))).slice(0,15).map(f => `
<tr>
<td><span style="font-family:var(--font-mono);font-size:11px;color:var(--accent-${f.volColor})">${f.id.toUpperCase()}</span></td>
<td style="font-size:11px;">${f.title.replace(/^FIG\. \d+ — /, '')}</td>
<td>${f.tables.slice(0,3).map(t => `<span class="fig-badge" style="background:rgba(255,255,255,0.05);color:var(--text-secondary);border:1px solid var(--border-subtle)">${t}</span>`).join('')}${f.tables.length > 3 ? '<span style="font-size:10px;color:var(--text-muted)">+' + (f.tables.length - 3) + '</span>' : ''}</td>
</tr>
`).join('')}</tbody>
</table>
</div>
<div class="matrix-note">Showing 15 of 50 figures — use Volumes tab for full listing</div>
</div>`;
}
function switchTab(tab) {
document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden'));
document.querySelectorAll('.nav-tab').forEach(el => el.classList.remove('active'));
document.getElementById('tab-' + tab).classList.remove('hidden');
document.querySelector('[data-tab="' + tab + '"]').classList.add('active');
currentTab = tab;
if (tab === 'architecture') renderVolumes();
if (tab === 'figures') renderFigures();
if (tab === 'tables') renderTables();
if (tab === 'matrix') renderMatrix();
document.getElementById('tab-' + tab).classList.add('fade-in');
setTimeout(() => document.getElementById('tab-' + tab).classList.remove('fade-in'), 300);
}
function toggleVolume(vid) {
expanded[vid] = !expanded[vid];
const btn = document.querySelector(`[onclick="toggleVolume('${vid}')"]`);
const body = document.getElementById('body-' + vid);
if (expanded[vid]) { btn.classList.add('expanded'); body.classList.add('open'); }
else { btn.classList.remove('expanded'); body.classList.remove('open'); }
}
function selectFigure(fid) {
selectedFigure = selectedFigure === fid ? null : fid;
if (currentTab === 'architecture') renderVolumes();
if (currentTab === 'figures') renderFigures();
}
function navToVolume(vid) {
expanded[vid] = true;
switchTab('architecture');
setTimeout(() => {
const el = document.getElementById('body-' + vid);
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
}, 100);
}
function handleSearch(q) {
q = q.toLowerCase();
if (!q) { if (currentTab === 'architecture') renderVolumes(); if (currentTab === 'figures') renderFigures(); return; }
if (currentTab === 'architecture') {
const filtered = volumes.map(v => ({...v, children: v.children.filter(c => c.title.toLowerCase().includes(q) || c.desc.toLowerCase().includes(q) || c.tables.some(t => t.toLowerCase().includes(q)))})).filter(v => v.children.length > 0 || v.title.toLowerCase().includes(q));
document.getElementById('tab-architecture').innerHTML = filtered.map((v, i) => {
const idx = volumes.findIndex(x => x.id === v.id);
return `<div class="volume-section vol-${v.color} glass">
<button class="volume-header expanded" onclick="toggleVolume('${v.id}')">
<span class="chevron" style="transform:rotate(90deg)">${svgs.chevronRight}</span>
<span style="color:var(--accent-${v.color})">${svgs[v.icon]}</span>
<span>Volume ${roman[idx]}${v.title}</span>
<span class="vol-badge">${v.children.length} matches</span>
</button>
<div class="volume-body open">
${v.children.map(c => `<div class="figure-item"><h4>${c.title}</h4><p class="fig-desc">${c.desc}</p><div class="fig-tags">${c.tables.map(t => `<span class="fig-tag">${t}</span>`).join('')}</div></div>`).join('')}
</div>
</div>`;
}).join('') || '<div style="text-align:center;padding:40px;color:var(--text-muted)">No results found</div>';
}
if (currentTab === 'figures') {
const all = volumes.flatMap(v => v.children.map(c => ({...c, volColor: v.color, volTitle: v.title})));
const filtered = all.filter(f => f.title.toLowerCase().includes(q) || f.desc.toLowerCase().includes(q) || f.tables.some(t => t.toLowerCase().includes(q)));
document.getElementById('tab-figures').innerHTML = filtered.length ? `<div class="figures-grid">${filtered.map(f => `
<div class="figure-card vol-${f.volColor}">
<div class="fig-header"><span class="fig-id">${f.id.toUpperCase()}</span><span class="fig-vol">${f.volTitle}</span></div>
<h3>${f.title.replace(/^FIG\. \d+ — /, '')}</h3>
<p class="fig-desc-short">${f.desc}</p>
<div class="fig-tags">${f.tables.slice(0,3).map(t => `<span class="fig-tag">${t}</span>`).join('')}${f.tables.length > 3 ? '<span class="fig-tag">+' + (f.tables.length - 3) + '</span>' : ''}</div>
</div>
`).join('')}</div>` : '<div style="text-align:center;padding:40px;color:var(--text-muted)">No figures found</div>';
}
}
function startSimulation() {
const btn = document.getElementById('btnSim');
const progress = document.getElementById('simProgress');
const bar = document.getElementById('simBar');
const pct = document.getElementById('simPercent');
btn.disabled = true;
progress.classList.add('active');
let p = 0;
simInterval = setInterval(() => {
p += 1.5;
if (p >= 100) { p = 100; clearInterval(simInterval); setTimeout(() => { btn.disabled = false; progress.classList.remove('active'); }, 800); }
bar.style.width = p + '%';
pct.textContent = Math.round(p) + '%';
}, 80);
}
function resetSimulation() {
clearInterval(simInterval);
document.getElementById('simBar').style.width = '0%';
document.getElementById('simPercent').textContent = '0%';
document.getElementById('simProgress').classList.remove('active');
document.getElementById('btnSim').disabled = false;
}
// Initialize
renderOverviewVolumes();
renderVolumes();
renderFigures();
renderTables();
renderMatrix();
</script>
</body>
</html>