anycoder-75441bba / index.html
caustino's picture
Upload folder using huggingface_hub
d1aae9a verified
Raw History Blame Contribute Delete
30.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>RIGOR-PRS-Secure++ | Electrochemical Genotyping Interface</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=Fira+Code:wght@400;600&display=swap" rel="stylesheet"> <style> /* Modern CSS Reset & Custom Properties */ :root { --primary-color: #0a192f; --secondary-color: #64ffda; --accent-color: #00a8cc; --warning-color: #ff6b6b; --success-color: #4ecdc4; --text-primary: #e6f1ff; --text-secondary: #8892b0; --bg-primary: #0a192f; --bg-secondary: #112240; --bg-tertiary: #172a45; --border-color: #233554; --gradient-primary: linear-gradient(135deg, #0a192f 0%, #112240 100%); --gradient-accent: linear-gradient(135deg, #64ffda 0%, #00a8cc 100%); --shadow-primary: 0 10px 30px -15px rgba(100, 255, 218, 0.2); --shadow-heavy: 0 20px 50px -20px rgba(0, 0, 0, 0.5); --glass-bg: rgba(17, 34, 64, 0.7); --glass-border: rgba(100, 255, 218, 0.1); --terminal-bg: #0d1117; --terminal-text: #58a6ff; } * { margin: 0; padding: 0; box-sizing: border-box; } html { scroll-behavior: smooth; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; background: var(--bg-primary); color: var(--text-primary); line-height: 1.6; overflow-x: hidden; } /* Typography */ h1, h2, h3, h4 { font-weight: 700; line-height: 1.2; } h1 { font-size: clamp(2rem, 5vw, 3.5rem); background: var(--gradient-accent); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } h2 { font-size: clamp(1.5rem, 3vw, 2.5rem); color: var(--secondary-color); } h3 { font-size: clamp(1.2rem, 2vw, 1.8rem); color: var(--text-primary); } h4 { font-size: 1.1rem; color: var(--text-secondary); } p, li { color: var(--text-secondary); } /* Header & Navigation */ header { position: fixed; top: 0; width: 100%; background: var(--glass-bg); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-bottom: 1px solid var(--glass-border); z-index: 1000; padding: 1rem 0; transition: all 0.3s ease; } .header-container { max-width: 1400px; margin: 0 auto; padding: 0 2rem; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem; } .logo-section { display: flex; align-items: center; gap: 1rem; } .logo { width: 40px; height: 40px; background: var(--gradient-accent); border-radius: 8px; display: flex; align-items: center; justify-content: center; font-weight: bold; color: var(--primary-color); } .brand-text { display: flex; flex-direction: column; } .brand-name { font-size: 1.2rem; font-weight: 700; color: var(--secondary-color); } .brand-tagline { font-size: 0.8rem; color: var(--text-secondary); } .anycoder-link { background: var(--gradient-accent); padding: 0.5rem 1rem; border-radius: 20px; text-decoration: none; color: var(--primary-color); font-weight: 600; font-size: 0.9rem; transition: transform 0.3s ease, box-shadow 0.3s ease; box-shadow: var(--shadow-primary); } .anycoder-link:hover { transform: translateY(-2px); box-shadow: 0 15px 35px -15px rgba(100, 255, 218, 0.3); } /* Main Container */ .container { max-width: 1400px; margin: 0 auto; padding: 6rem 2rem 2rem; } /* Hero Section */ .hero { text-align: center; padding: 4rem 0; position: relative; } /* Section Cards */ .section { background: var(--glass-bg); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border: 1px solid var(--glass-border); border-radius: 16px; padding: 2rem; margin: 2rem 0; box-shadow: var(--shadow-heavy); transition: transform 0.3s ease, box-shadow 0.3s ease; } .section:hover { transform: translateY(-5px); box-shadow: 0 25px 60px -20px rgba(100, 255, 218, 0.15); } .section-header { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.5rem; padding-bottom: 1rem; border-bottom: 1px solid var(--border-color); } .section-icon { width: 50px; height: 50px; background: var(--gradient-accent); border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 1.5rem; color: var(--primary-color); } /* Buttons */ .btn { background: var(--gradient-accent); color: var(--primary-color); border: none; padding: 0.75rem 1.5rem; border-radius: 8px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; display: inline-flex; align-items: center; gap: 0.5rem; text-decoration: none; font-size: 1rem; } .btn:hover { transform: translateY(-2px); box-shadow: 0 10px 25px -10px rgba(100, 255, 218, 0.4); } .btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; } .btn-secondary { background: var(--bg-tertiary); color: var(--secondary-color); border: 1px solid var(--border-color); } /* Hardware Interface */ .hardware-interface { display: grid; grid-template-columns: 300px 1fr; gap: 2rem; } @media (max-width: 900px) { .hardware-interface { grid-template-columns: 1fr; } } .device-panel { background: var(--bg-tertiary); border-radius: 12px; padding: 1.5rem; border: 1px solid var(--border-color); } .status-row { display: flex; justify-content: space-between; margin-bottom: 0.8rem; font-size: 0.9rem; } .status-value { color: var(--secondary-color); font-family: 'Fira Code', monospace; } /* Electrode Grid */ .electrode-grid-container { background: #000; border-radius: 8px; padding: 1rem; border: 1px solid var(--border-color); position: relative; } .electrode-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 4px; aspect-ratio: 4/3; } .electrode { background: #1a1a1a; border-radius: 2px; transition: all 0.2s ease; position: relative; } .electrode:hover { border: 1px solid #fff; z-index: 10; } .electrode.active-scan { background: #f1c40f; box-shadow: 0 0 10px #f1c40f; } .electrode.ref-detected { background: var(--success-color); } .electrode.alt-detected { background: var(--warning-color); } .electrode.qc-pass { background: var(--accent-color); } /* Terminal/Console */ .terminal-window { background: var(--terminal-bg); border-radius: 8px; border: 1px solid #30363d; font-family: 'Fira Code', monospace; margin-top: 2rem; overflow: hidden; display: flex; flex-direction: column; } .terminal-header { background: #161b22; padding: 0.5rem 1rem; border-bottom: 1px solid #30363d; display: flex; justify-content: space-between; align-items: center; } .terminal-title { font-size: 0.85rem; color: #8b949e; } .terminal-body { height: 200px; overflow-y: auto; padding: 1rem; font-size: 0.85rem; color: var(--text-secondary); } .log-entry { margin-bottom: 0.25rem; word-break: break-all; } .log-tx { color: var(--secondary-color); } .log-rx { color: var(--accent-color); } .log-sys { color: var(--warning-color); font-style: italic; } /* Voltammetry Chart */ .chart-container { width: 100%; height: 200px; background: var(--bg-tertiary); border-radius: 8px; margin-top: 1rem; position: relative; border: 1px solid var(--border-color); } canvas { width: 100%; height: 100%; } /* Manufacturing Visualization (New) */ .manufacturing-line { display: flex; justify-content: space-between; align-items: center; position: relative; padding: 2rem 0; overflow-x: auto; } .mfg-step { display: flex; flex-direction: column; align-items: center; z-index: 2; min-width: 100px; } .mfg-icon { width: 60px; height: 60px; background: var(--bg-secondary); border: 2px solid var(--border-color); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; color: var(--text-secondary); margin-bottom: 0.5rem; transition: all 0.5s ease; } .mfg-step.active .mfg-icon { border-color: var(--secondary-color); background: var(--gradient-accent); color: var(--primary-color); box-shadow: 0 0 15px var(--secondary-color); } .mfg-label { font-size: 0.8rem; text-align: center; } .mfg-track { position: absolute; top: 50%; left: 0; width: 100%; height: 4px; background: var(--bg-tertiary); transform: translateY(-50%); z-index: 1; } .mfg-progress { height: 100%; background: var(--gradient-accent); width: 0%; transition: width 0.5s ease; } /* Blockchain Section (New) */ .blockchain-viz { display: flex; flex-direction: column; gap: 1rem; } .chain-step { display: flex; align-items: center; gap: 1rem; background: var(--bg-secondary); padding: 1rem; border-radius: 8px; border-left: 4px solid var(--border-color); opacity: 0.5; transition: all 0.3s ease; } .chain-step.active { opacity: 1; border-left-color: var(--secondary-color); background: rgba(100, 255, 218, 0.05); } .chain-step i { font-size: 1.2rem; width: 30px; text-align: center; } .hash-display { font-family: 'Fira Code', monospace; font-size: 0.8rem; color: var(--accent-color); word-break: break-all; } /* Upload Zone */ .upload-zone { border: 2px dashed var(--border-color); border-radius: 12px; padding: 3rem; text-align: center; cursor: pointer; transition: all 0.3s ease; } .upload-zone:hover { border-color: var(--secondary-color); background: rgba(100, 255, 218, 0.02); } .file-list { margin-top: 1rem; display: flex; flex-direction: column; gap: 0.5rem; } .file-item { background: var(--bg-secondary); padding: 0.75rem; border-radius: 6px; display: flex; align-items: center; justify-content: space-between; } /* Results & Tables */ .results-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.5rem; margin: 2rem 0; } .result-card { background: var(--bg-secondary); border-radius: 12px; padding: 1.5rem; border-left: 4px solid var(--accent-color); transition: transform 0.3s ease; } .result-value { font-size: 2rem; font-weight: 700; color: var(--secondary-color); margin: 0.5rem 0; } .data-table { width: 100%; border-collapse: collapse; margin: 1rem 0; border-radius: 8px; overflow: hidden; } .data-table th { background: var(--bg-tertiary); padding: 1rem; text-align: left; font-weight: 600; color: var(--secondary-color); border-bottom: 1px solid var(--border-color); } .data-table td { padding: 0.75rem 1rem; border-bottom: 1px solid var(--border-color); } .data-table tr:hover { background: rgba(100, 255, 218, 0.05); } /* Accessibility & Utilities */ .accessibility-controls { position: fixed; bottom: 2rem; right: 2rem; background: var(--glass-bg); backdrop-filter: blur(10px); border: 1px solid var(--glass-border); border-radius: 12px; padding: 1rem; display: flex; flex-direction: column; gap: 0.5rem; z-index: 999; } .accessibility-btn { width: 40px; height: 40px; border: none; background: var(--bg-secondary); color: var(--text-primary); border-radius: 8px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; } .accessibility-btn:hover, .accessibility-btn.active { background: var(--secondary-color); color: var(--primary-color); } /* Animations */ @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } } .spinner { width: 40px; height: 40px; border: 4px solid var(--border-color); border-top: 4px solid var(--secondary-color); border-radius: 50%; animation: spin 1s linear infinite; margin: 2rem auto; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .fade-in { animation: fadeIn 0.5s ease-in; } @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } /* Scrollbar */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: var(--bg-primary); } ::-webkit-scrollbar-thumb { background: var(--secondary-color); border-radius: 4px; } </style> </head> <body> <!-- Header --> <header role="banner"> <div class="header-container"> <div class="logo-section"> <div class="logo" aria-hidden="true">RIGOR</div> <div class="brand-text"> <div class="brand-name">RIGOR-PRS-Secure++</div> <div class="brand-tagline">Electrochemical Genotyping & PRS Platform</div> </div> </div> <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link" aria-label="Built with anycoder - Visit Hugging Face Space"> <i class="fas fa-rocket" aria-hidden="true"></i> Built with anycoder </a> </div> </header> <!-- Main Container --> <main class="container" role="main"> <!-- Hero --> <section class="hero" aria-labelledby="main-title"> <h1 id="main-title">Hardware-Integrated Genetic Analysis</h1> <p class="hero-subtitle">Direct USB-C interface to 96-electrode electrochemical cartridges with real-time voltammetry and post-quantum evidence hashing.</p> </section> <!-- SECTION 1: Hardware Interface --> <section class="section fade-in" aria-labelledby="hardware-title"> <div class="section-header"> <div class="section-icon" aria-hidden="true"> <i class="fas fa-microchip"></i> </div> <div> <h2 id="hardware-title">1. Electrochemical Reader Interface</h2> <p>Phase 2: USB-C Device Detection & Multiplexer Control</p> </div> </div> <div class="hardware-interface"> <!-- Left: Device Controls --> <div class="device-panel"> <h3>Device Status</h3> <div style="height: 1rem;"></div> <div class="status-row"> <span>Connection:</span> <span class="status-value" id="hw-conn-status" style="color: var(--warning-color)">Disconnected</span> </div> <div class="status-row"> <span>Port:</span> <span class="status-value" id="hw-port">--</span> </div> <div class="status-row"> <span>MCU:</span> <span class="status-value">RP2040</span> </div> <div class="status-row"> <span>Firmware:</span> <span class="status-value">v1.2.3</span> </div> <hr style="border: 0; border-top: 1px solid var(--border-color); margin: 1.5rem 0;"> <h3>Real-time Telemetry</h3> <div style="height: 1rem;"></div> <div class="status-row"> <span>Supply Voltage:</span> <span class="status-value" id="hw-voltage">0.00 V</span> </div> <div class="status-row"> <span>Current:</span> <span class="status-value" id="hw-current">0.00 mA</span> </div> <div class="status-row"> <span>Temp (NTC):</span> <span class="status-value" id="hw-temp">-- °C</span> </div> <div style="margin-top: 2rem;"> <button class="btn" id="btn-connect" onclick="toggleConnection()" style="width: 100%; justify-content: center;"> <i class="fas fa-plug"></i> Connect Reader </button> <button class="btn btn-secondary" id="btn-start-hw-test" onclick="startHardwareTest()" disabled style="width: 100%; justify-content: center; margin-top: 1rem;"> <i class="fas fa-play"></i> Start Cartridge Scan </button> </div> </div> <!-- Right: Grid & Charts --> <div> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem;"> <h4>96-Electrode Array (ADG731 Mux)</h4> <span style="font-size: 0.8rem; color: var(--text-secondary);">Spatial Multiplexing Map</span> </div> <div class="electrode-grid-container"> <div class="electrode-grid" id="electrode-grid"> <!-- Generated by JS --> </div> </div> <div class="chart-container"> <canvas id="voltammetryChart"></canvas> <div style="position: absolute; top: 10px; left: 10px; font-size: 0.8rem; color: var(--text-secondary); background: rgba(10,25,47,0.8); padding: 2px 5px; border-radius: 4px;"> SWV Signal (Current vs Potential) </div> </div> </div> </div> <!-- API Terminal --> <div class="terminal-window"> <div class="terminal-header"> <span class="terminal-title"><i class="fas fa-terminal"></i> API CONSOLE (CDC-ACM)</span> <i class="fas fa-wifi" style="color: var(--success-color); opacity: 0;"></i> </div> <div class="terminal-body" id="terminal-output"> <div class="log-entry log-sys">System ready. Waiting for USB-C device enumeration...</div> </div> </div> </section> <!-- SECTION 2: Manufacturing Visualization --> <section class="section fade-in" aria-labelledby="mfg-title"> <div class="section-header"> <div class="section-icon" aria-hidden="true"> <i class="fas fa-industry"></i> </div> <div> <h2 id="mfg-title">2. Roll-to-Roll Manufacturing (FIG. 9)</h2> <p>Visualizing the cartridge production line: 15 m/min web speed</p> </div> </div> <div class="manufacturing-line"> <div class="mfg-track"> <div class="mfg-progress" id="mfg-progress-bar"></div> </div> <div class="mfg-step" id="step-0"> <div class="mfg-icon"><i class="fas fa-file"></i></div> <div class="mfg-label">PET Stock</div> </div> <div class="mfg-step" id="step-1"> <div class="mfg-icon"><i class="fas fa-print"></i></div> <div class="mfg-label">Gravure Carbon</div> </div> <div class="mfg-step" id="step-2"> <div class="mfg-icon"><i class="fas fa-temperature-high"></i></div> <div class="mfg-label">IR Dry</div> </div> <div class="mfg-step" id="step-3"> <div class="mfg-icon"><i class="fas fa-mask"></i></div> <div class="mfg-label">Screen Ag/AgCl</div> </div> <div class="mfg-step" id="step-4"> <div class="mfg-icon"><i class="fas fa-sun"></i></div> <div class="mfg-label">UV Cure</div> </div> <div class="mfg-step" id="step-5"> <div class="mfg-icon"><i class="fas fa-bolt"></i></div> <div class="mfg-label">Laser Ablate</div> </div> <div class="mfg-step" id="step-6"> <div class="mfg-icon"><i class="fas fa-layer-group"></i></div> <div class="mfg-label">Laminate</div> </div> <div class="mfg-step" id="step-7"> <div class="mfg-icon"><i class="fas fa-cut"></i></div> <div class="mfg-label">Die-Cut</div> </div> </div> <div style="margin-top: 1rem; text-align: center;"> <button class="btn btn-secondary" onclick="runManufacturingSim()"> <i class="fas fa-play-circle"></i> Simulate Production Batch </button> <p id="mfg-status" style="margin-top: 0.5rem; font-size: 0.9rem; font-family: 'Fira Code';">Status: Idle</p> </div> </section> <!-- File Upload Section (Fallback/Software Mode) --> <section class="section fade-in" aria-labelledby="upload-title"> <div class="section-header"> <div class="section-icon" aria-hidden="true"> <i class="fas fa-upload"></i> </div> <div> <h2 id="upload-title">3. Software Mode: Encrypted Ingestion</h2> <p>Upload VCF or PLINK files if hardware is unavailable</p> </div> </div> <div class="upload-zone" id="upload-zone" role="button" tabindex="0" aria-label="Drag and drop files here or click to browse"> <div class="upload-icon" aria-hidden="true" style="font-size: 3rem; color: var(--secondary-color); margin-bottom: 1rem;"> <i class="fas fa-dna"></i> </div> <h3>Drop Genotype Files Here</h3> <p>Supports VCF, PLINK binary (.bed/.bim/.fam)</p> <button class="btn" onclick="document.getElementById('file-input').click()" style="margin-top: 1rem;"> <i class="fas fa-folder-open"></i> Browse Files </button> <input type="file" id="file-input" class="file-input" multiple accept=".vcf,.vcf.gz,.bed,.bim,.fam" style="display: none;"> </div> <div class="file-list" id="file-list" aria-live="polite"></div> <button class="btn" id="process-btn" onclick="startProcessing()" disabled style="margin-top: 1rem; width: 100%; justify-content: center;"> <i class="fas fa-cogs"></i> Process Software Data </button> </section> <!-- SECTION 3: Blockchain Evidence Anchoring --> <section class="section fade-in" id="blockchain-section" aria-labelledby="bc-title" style="display: none;"> <div class="section-header"> <div class="section-icon" aria-hidden="true"> <i class="fas fa-link"></i> </div> <div> <h2 id="bc-title">4. Quantum-Resistant Blockchain Anchoring</h2> <p>Post-Quantum Cryptography (Dilithium) & Hyperledger Fabric</p> </div> </div> <div class="blockchain-viz"> <!-- Step A --> <div class="chain-step" id="bc-step-a"> <i class="fas fa-file-contract"></i> <div> <h4>Step A: Prepare Evidence Packet</h4> <p style="font-size: 0.9rem;">UID + Timestamp + Hash(Genotype Vector)</p> <div class="hash-display" id="bc-packet-hash">Calculating...</div> </div> </div> <!-- Step B --> <div class="chain-step" id="bc-step-b"> <i class="fas fa-key"></i> <div> <h4>Step B: Lattice-Based Signing (Dilithium)</h4> <p style="font-size: 0.9rem;">Signing with Private Key (Post-Quantum Secure)</p> <div class="spinner" id="bc-spinner" style="width: 20px; height: 20px; margin: 0.5rem 0; border-width: 2px;"></div> </div> </div> <!-- Step C --> <div class="chain-step" id="bc-step-c"> <i class="fas fa-network-wired"></i> <div> <h4>Step C: Submit to Hyperledger Fabric</h4> <p style="font-size: 0.9rem;">Broadcasting transaction to permissioned nodes</p> </div> </div> <!-- Result --> <div class="chain-step active" id="bc-result" style="display: none; border-left-color: var(--success-color);"> <i class="fas fa-check-circle" style="color: var(--success-color);"></i> <div> <h4 style="color: var(--success-color);">Evidence Anchored Successfully</h4> <p style="font-size: 0.9rem;">TXID: <span id="bc-txid" class="hash-display"></span></p> <button class="btn btn-secondary" style="margin-top: 0.5rem; padding: 0.5rem;" onclick="downloadCertificate()"> <i class="fas fa-download"></i> Download JSON-LD Certificate </button> </div> </div> <button id="btn-start-bc" class="btn" onclick="startBlockchainProcess()" style="margin-top: 1rem; align-self: flex-start;"> <i class="fas fa-shield-alt"></i> Sign & Anchor Evidence </button> </div> </section> <!-- Results Section --> <section class="section fade-in" id="results-section" aria-labelledby="results-title" style="display: none;"> <div class="section-header"> <div class="section-icon" aria-hidden="true"> <i class="fas fa-chart-line"></i> </div> <div> <h2 id="results-title">5. Analysis Results</h2> <p>Polygenic Risk Scores & Evidence Authentication</p> </div> </div> <div class="results-grid"> <div class="result-card"> <div class="result-label">Raw PRS Score</div> <div class="result-value" id="raw-score">0.00</div> <small>Sum of weighted risk alleles</small> </div> <div class="result-card"> <div class="result-label">Z-Score</div> <div class="result-value" id="z-score">0.00</div> <small>Std dev from mean</small> </div> <div class="result-card"> <div class="result-label">Percentile</div> <div class="result-value" id="percentile">0th</div> <small>Population rank</small> </div> <div class="result-card"> <div class="result-label">Blockchain TXID</div> <div class="result-value" style="font-size: 1rem; word-break: break-all;" id="res-txid">Pending...</div> <small>Dilithium Signed</small> </div> </div> <h3>Genotype Vector</h3> <div class="table-container" style="overflow-x: auto;"> <table class="data-table" id="variant-table"> <thead> <tr> <th scope="col">SNP ID</th> <th scope="col">Chr</th> <th scope="col">Genotype</th> <th scope="col">Signal (µA)</th> <th scope="col">Confidence</th> </tr> </thead> <tbody id="variant-table-body"> <!-- Populated by JS --> </tbody> </table> </div> </section> </main> <!-- Accessibility Controls --> <div class="accessibility-controls" role="group" aria-label="Accessibility controls"> <button class="accessibility-btn" id="high-contrast-btn" onclick="toggleHighContrast()" title="Toggle high contrast mode" aria-label="Toggle high contrast mode"> <i class="fas fa-adjust"></i> </button> <button class="accessibility-btn" onclick="increaseFontSize()" title="Increase font size" aria-label="Increase font size"> <i class="fas fa-search-plus"></i> </button> <button class="accessibility-btn" onclick="decreaseFontSize()" title="Decrease font size" aria-label="Decrease font size"> <i class="fas fa-search-minus"></i> </button> </div> <script> // --- CONSTANTS & STATE --- const GRID_SIZE = 96; let isConnected = false; let isScanning = false; let scanInterval; let chartAnimationId; let genotypeData = []; // Store for blockchain // --- INITIALIZATION --- document.addEventListener('DOMContentLoaded', () => { initGrid(); initChart(); initFileUpload(); logToTerminal('SYS', 'Application initialized. Waiting for device...'); }); // --- HARDWARE SIMULATION --- function toggleConnection() { const btn = document.getElementById('btn-connect'); const statusLabel = document.getElementById('hw-conn-status'); const portLabel = document.getElementById('hw-port'); const testBtn = document.getElementById('btn-start-hw-test'); if (!isConnected) { // Simulate Connection btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Connecting...'; btn.disabled = true; logToTerminal('TX', 'CONNECT {"timeout": 5000}'); setTimeout(() => { isConnected = true; btn.innerHTML = '<i class="fas fa-eject"></i
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RIGOR-PRS-Secure++ | Electrochemical Genotyping Interface</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=Fira+Code:wght@400;600&display=swap" rel="stylesheet">
<style>
/* Modern CSS Reset & Custom Properties */
:root {
--primary-color: #0a192f;
--secondary-color: #64ffda;
--accent-color: #00a8cc;
--warning-color: #ff6b6b;
--success-color: #4ecdc4;
--text-primary: #e6f1ff;
--text-secondary: #8892b0;
--bg-primary: #0a192f;
--bg-secondary: #112240;
--bg-tertiary: #172a45;
--border-color: #233554;
--gradient-primary: linear-gradient(135deg, #0a192f 0%, #112240 100%);
--gradient-accent: linear-gradient(135deg, #64ffda 0%, #00a8cc 100%);
--shadow-primary: 0 10px 30px -15px rgba(100, 255, 218, 0.2);
--shadow-heavy: 0 20px 50px -20px rgba(0, 0, 0, 0.5);
--glass-bg: rgba(17, 34, 64, 0.7);
--glass-border: rgba(100, 255, 218, 0.1);
--terminal-bg: #0d1117;
--terminal-text: #58a6ff;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
overflow-x: hidden;
}
/* Typography */
h1, h2, h3, h4 {
font-weight: 700;
line-height: 1.2;
}
h1 {
font-size: clamp(2rem, 5vw, 3.5rem);
background: var(--gradient-accent);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
h2 {
font-size: clamp(1.5rem, 3vw, 2.5rem);
color: var(--secondary-color);
}
h3 {
font-size: clamp(1.2rem, 2vw, 1.8rem);
color: var(--text-primary);
}
h4 {
font-size: 1.1rem;
color: var(--text-secondary);
}
p, li {
color: var(--text-secondary);
}
/* Header & Navigation */
header {
position: fixed;
top: 0;
width: 100%;
background: var(--glass-bg);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-bottom: 1px solid var(--glass-border);
z-index: 1000;
padding: 1rem 0;
transition: all 0.3s ease;
}