Spaces:
Sleeping
Sleeping
| <html lang="en" class="scroll-smooth"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>MedAI — COS30018 Multi‑Agent Clinical Reasoning</title> | |
| <meta name="description" content="Swinburne COS30018 MedAI — Multi‑Agent Clinical Reasoning System with Agentic RAG, safety rails, and rigorous evaluation." /> | |
| <link rel="icon" href="assets/logo.svg"> | |
| <!-- Tailwind (CDN) --> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script> | |
| // Ensure Tailwind is loaded before configuring | |
| if (typeof tailwind !== 'undefined') { | |
| tailwind.config = { | |
| darkMode: 'class', | |
| theme: { | |
| extend: { | |
| fontFamily: { inter: ['Inter', 'ui-sans-serif', 'system-ui'] }, | |
| boxShadow: { | |
| glow: '0 0 20px rgba(99,102,241,0.3), 0 0 40px rgba(99,102,241,0.2)' | |
| }, | |
| backgroundImage: { | |
| 'grid': 'linear-gradient(to right, rgba(255,255,255,0.06) 1px, transparent 1px), linear-gradient(to bottom, rgba(255,255,255,0.06) 1px, transparent 1px)' | |
| }, | |
| spacing: { | |
| '18': '4.5rem', | |
| '88': '22rem' | |
| } | |
| } | |
| } | |
| }; | |
| } else { | |
| console.warn('Tailwind CSS not loaded'); | |
| } | |
| </script> | |
| <!-- AOS (Animate On Scroll) --> | |
| <link href="https://unpkg.com/aos@2.3.4/dist/aos.css" rel="stylesheet" /> | |
| <script defer src="https://unpkg.com/aos@2.3.4/dist/aos.js"></script> | |
| <!-- Lucide Icons --> | |
| <script src="https://unpkg.com/lucide@latest"></script> | |
| <!-- Mermaid --> | |
| <script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script> | |
| <script> | |
| mermaid.initialize({ | |
| startOnLoad: true, | |
| theme: 'dark', | |
| securityLevel: 'loose', | |
| fontFamily: 'Inter, ui-sans-serif, system-ui', | |
| flowchart: { | |
| useMaxWidth: true, | |
| htmlLabels: true | |
| } | |
| }); | |
| </script> | |
| <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@400;500;600;700;800&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="assets/styles.css"> | |
| </head> | |
| <body class="bg-slate-950 text-slate-100 font-inter"> | |
| <!-- Background decoration --> | |
| <div class="fixed inset-0 -z-10 overflow-hidden pointer-events-none"> | |
| <div class="absolute -top-40 -left-40 w-[60rem] h-[60rem] rounded-full bg-gradient-to-tr from-indigo-500/30 via-blue-400/20 to-cyan-300/10 blur-3xl animate-pulse-slow"></div> | |
| <div class="absolute -bottom-40 -right-40 w-[60rem] h-[60rem] rounded-full bg-gradient-to-tr from-fuchsia-500/20 via-indigo-500/10 to-sky-400/10 blur-3xl animate-pulse-slow delay-700"></div> | |
| </div> | |
| <!-- Navbar --> | |
| <header class="sticky top-0 z-50 backdrop-blur supports-[backdrop-filter]:bg-slate-900/60 border-b border-white/10" role="banner"> | |
| <div class="max-w-7xl mx-auto px-4 py-3 flex items-center justify-between"> | |
| <div class="flex items-center gap-3"> | |
| <img src="assets/logo.svg" class="w-9 h-9" alt="MedAI logo" width="36" height="36" /> | |
| <span class="font-extrabold tracking-tight text-xl">MedAI</span> | |
| <span class="text-slate-400 hidden sm:inline" aria-label="Course code">• COS30018</span> | |
| </div> | |
| <nav class="hidden md:flex items-center gap-6 text-sm" role="navigation" aria-label="Main navigation"> | |
| <a href="#overview" class="link" aria-label="Go to Overview section">Overview</a> | |
| <a href="#capabilities" class="link" aria-label="Go to Capabilities section">Capabilities</a> | |
| <a href="#architecture" class="link" aria-label="Go to Architecture section">Architecture</a> | |
| <a href="#training" class="link" aria-label="Go to Training section">Training</a> | |
| <a href="#evaluation" class="link" aria-label="Go to Evaluation section">Evaluation</a> | |
| <a href="#team" class="link" aria-label="Go to Team section">Team</a> | |
| </nav> | |
| <div class="flex items-center gap-3"> | |
| <a href="https://medai-cos30018-medicaldiagnosissystem.hf.space/" target="_blank" rel="noopener noreferrer" class="btn-primary" aria-label="Open live application in new tab">Live App</a> | |
| <button id="themeToggle" aria-label="Toggle between light and dark theme" class="btn-icon" type="button"> | |
| <i data-lucide="sun-medium" class="icon" aria-hidden="true"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Hero --> | |
| <section class="relative" role="banner" aria-labelledby="hero-title"> | |
| <div class="max-w-7xl mx-auto px-4 py-16 lg:py-24"> | |
| <div class="grid lg:grid-cols-2 gap-12 items-center"> | |
| <div data-aos="fade-right" data-aos-duration="700"> | |
| <h1 id="hero-title" class="text-4xl lg:text-6xl font-extrabold leading-tight"> | |
| Multi‑Agent <span class="text-indigo-400">Clinical Reasoning</span> System | |
| </h1> | |
| <p class="mt-5 text-slate-300 text-lg max-w-2xl"> | |
| Safety‑first medical assistant coordinating Diagnostics, Pharmacology, and Triage agents via an MCP orchestrator, | |
| grounded by Agentic RAG over EMR/EHR and PubMed, and rigorously evaluated on MedMCQA and PubMedQA. | |
| </p> | |
| <div class="mt-8 flex flex-wrap gap-3" role="group" aria-label="Action buttons"> | |
| <a class="btn-secondary" href="https://huggingface.co/spaces/MedAI-COS30018/MedAI_Processing" target="_blank" rel="noopener noreferrer" aria-label="Open data processing application">Data Processing</a> | |
| <a class="btn-ghost" href="#architecture" aria-label="Scroll to architecture section">See Architecture</a> | |
| </div> | |
| <div class="mt-6 flex items-center gap-6 text-sm text-slate-400" role="contentinfo"> | |
| <span>Unit: COS30018 (Intelligent Systems)</span> | |
| <span aria-hidden="true">•</span> | |
| <span>School: Swinburne University of Technology</span> | |
| </div> | |
| </div> | |
| <div class="relative" data-aos="fade-left" data-aos-duration="700"> | |
| <div class="card glass shadow-glow" role="complementary" aria-labelledby="glance-title"> | |
| <div class="p-6"> | |
| <h3 id="glance-title" class="font-semibold text-slate-200 mb-3">At a Glance</h3> | |
| <ul class="space-y-2 text-slate-300" role="list"> | |
| <li>• 500k+ curated & synthetic cases</li> | |
| <li>• LoRA/QLoRA, Knowledge Distillation, GRPO</li> | |
| <li>• Agentic RAG (Node & Graph) with citations</li> | |
| <li>• Safety rails, HIL, uncertainty flags</li> | |
| <li>• HPC‑reproducible training</li> | |
| </ul> | |
| <div class="mt-6 flex gap-3" role="group" aria-label="External resources"> | |
| <a class="chip" href="https://huggingface.co/MedAI-COS30018/MedicalDiagnosisSystem" target="_blank" rel="noopener noreferrer" aria-label="Visit Live App">Live App</a> | |
| <a class="chip" href="https://huggingface.co/MedAI-COS30018" target="_blank" rel="noopener noreferrer" aria-label="Visit Hugging Face organization">HF Org</a> | |
| <a class="chip" href="https://huggingface.co/collections/MedAI-COS30018/finetuning-68bbe0b045db4ed5aac5e9a2" target="_blank" rel="noopener noreferrer" aria-label="View fine-tuning datasets">Finetune Datasets</a> | |
| <a class="chip" href="https://huggingface.co/collections/MedAI-COS30018/rag-68bbe244bfa8ce6132fd5242" target="_blank" rel="noopener noreferrer" aria-label="View RAG datasets">RAG Datasets</a> | |
| </div> | |
| </div> | |
| <div class="border-t border-white/10 p-4 text-xs text-slate-400"> | |
| <span>Phase 1 prototype: Multimodal + naïve‑RAG + MCP</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Overview --> | |
| <section id="overview" class="section"> | |
| <div class="container"> | |
| <div class="section-header" data-aos="fade-up"> | |
| <h2>Overview</h2> | |
| <p>Accuracy, traceability, and safety via multi‑agent orchestration and evidence‑grounded generation.</p> | |
| </div> | |
| <div class="grid md:grid-cols-3 gap-6"> | |
| <div class="feature" data-aos="zoom-in-up"> | |
| <i data-lucide="stethoscope" class="feature-icon"></i> | |
| <h3>Specialist Agents</h3> | |
| <p>Diagnostics (differentials + red flags), Pharmacology (DDIs, dosing), and Triage (urgency & disposition).</p> | |
| </div> | |
| <div class="feature" data-aos="zoom-in-up" data-aos-delay="100"> | |
| <i data-lucide="workflow" class="feature-icon"></i> | |
| <h3>Reasoning Orchestrator</h3> | |
| <p>MCP planner routes tasks, fuses evidence, and enforces self‑consistency with safe refusal and uncertainty flags.</p> | |
| </div> | |
| <div class="feature" data-aos="zoom-in-up" data-aos-delay="200"> | |
| <i data-lucide="library" class="feature-icon"></i> | |
| <h3>Agentic RAG</h3> | |
| <p>Graph & Node RAG over EMR/EHR + PubMed with section‑aware chunking, source allowlists, and citations.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Capabilities --> | |
| <section id="capabilities" class="section"> | |
| <div class="container"> | |
| <div class="section-header" data-aos="fade-up"> | |
| <h2>Core Capabilities</h2> | |
| <p>Modeling & optimization to drive accurate, inspectable clinical reasoning.</p> | |
| </div> | |
| <div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6"> | |
| <div class="card" data-tilt data-tilt-max="6"> | |
| <div class="card-body"> | |
| <h4 class="card-title">LoRA/QLoRA</h4> | |
| <p>Parameter‑efficient adapters let us fine‑tune 7–13B models on modest GPUs while retaining high performance.</p> | |
| </div> | |
| </div> | |
| <div class="card" data-tilt data-tilt-max="6"> | |
| <div class="card-body"> | |
| <h4 class="card-title">Knowledge Distillation</h4> | |
| <p>Teacher→Student compression to deliver fast, strong specialists with small runtime footprints.</p> | |
| </div> | |
| </div> | |
| <div class="card" data-tilt data-tilt-max="6"> | |
| <div class="card-body"> | |
| <h4 class="card-title">GRPO Reasoning</h4> | |
| <p>Reinforcement learning variant targeting multi‑step, self‑consistent reasoning with lower compute costs.</p> | |
| </div> | |
| </div> | |
| <div class="card" data-tilt data-tilt-max="6"> | |
| <div class="card-body"> | |
| <h4 class="card-title">QAC + Counterfactuals</h4> | |
| <p>Paraphrasing, chunking, and “what‑if” synthesis improve robustness across presentation styles.</p> | |
| </div> | |
| </div> | |
| <div class="card" data-tilt data-tilt-max="6"> | |
| <div class="card-body"> | |
| <h4 class="card-title">Safety Rails</h4> | |
| <p>Allowlists, section filters, and citation‑required answers reduce hallucinations and protect privacy.</p> | |
| </div> | |
| </div> | |
| <div class="card" data-tilt data-tilt-max="6"> | |
| <div class="card-body"> | |
| <h4 class="card-title">HPC Reproducibility</h4> | |
| <p>Deterministic seeds, LR scheduling, and checkpointing ensure auditability and consistent results.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Architecture --> | |
| <section id="architecture" class="section" aria-labelledby="architecture-title"> | |
| <div class="container"> | |
| <div class="section-header" data-aos="fade-up"> | |
| <h2 id="architecture-title">Architecture</h2> | |
| <p>Click tabs to switch between layers.</p> | |
| </div> | |
| <div class="tabs mb-6" role="tablist" aria-label="Architecture layers"> | |
| <button class="tab active" data-target="#arch-l1" role="tab" aria-selected="true" aria-controls="arch-l1" id="tab-l1">System Diagram</button> | |
| <button class="tab" data-target="#arch-l2" role="tab" aria-selected="false" aria-controls="arch-l2" id="tab-l2">RAG Internals</button> | |
| <button class="tab" data-target="#arch-l3" role="tab" aria-selected="false" aria-controls="arch-l3" id="tab-l3">Sequence Diagram</button> | |
| </div> | |
| <div id="arch-l1" class="diagram visible" role="tabpanel" aria-labelledby="tab-l1" aria-hidden="false" style="display: block;"> | |
| <pre class="mermaid" aria-label="System Architecture Diagram"> | |
| flowchart LR | |
| U(["Clinician UI / EMR"]) -->|"symptoms, meds, files"| MCP["MCP Orchestrator<br/>FastAPI routing, planning, safety, tracing"] | |
| MCP --> DX["Diagnostics Agent"] | |
| MCP --> RX["Pharmacology Agent"] | |
| subgraph RAG["Agentic RAG"] | |
| QR["Query Router"] --> RET["Retriever"] | |
| RET --> SR["Safety Rails"] | |
| end | |
| DX --> RAG | |
| RX --> RAG | |
| SR --> KB[("Med KB / PubMed")] | |
| SR --> EMR[("EMR/EHR summaries")] | |
| DX --> FUSE["Evidence Fusion + Self-Consistency"] | |
| RX --> FUSE | |
| FUSE --> OUT{{"Final Report<br/>summary, plan, citations, cautions"}} | |
| OUT --> QA["Evaluation & QA<br/>MedMCQA, PubMedQA, similarity audits"] | |
| </pre> | |
| </div> | |
| <div id="arch-l2" class="diagram" role="tabpanel" aria-labelledby="tab-l2" aria-hidden="true" style="display: none;"> | |
| <pre class="mermaid" aria-label="RAG Internals Architecture Diagram"> | |
| sequenceDiagram | |
| autonumber | |
| participant MCP as Orchestrator (MCP) | |
| participant QR as Query Router | |
| participant RW as Rewriter / Disambiguator | |
| participant RET as Retriever (vector + keyword) | |
| participant SR as Safety Rails | |
| participant LTM as VectorDB / LTM | |
| participant KB as Med KB (PubMed / Guidelines) | |
| participant EMR as EMR Summarizer | |
| participant EVID as Evidence Bundle | |
| MCP->>QR: Build query context (symptoms, vitals, meds, files, LTM hints) | |
| QR->>RW: Route + transform query | |
| alt Disambiguation needed | |
| RW->>RW: Expand synonyms / codes / abbreviations | |
| else Well-formed query | |
| RW-->>QR: Passthrough | |
| end | |
| RW->>RET: Search request (text + embedding) | |
| par Vector search | |
| RET->>LTM: kNN on embeddings (cosine) | |
| LTM-->>RET: top-k chunks + scores | |
| and Keyword filter | |
| RET->>KB: Keyword/BM25 filter | |
| KB-->>RET: filtered docs | |
| end | |
| RET->>SR: Candidate bundle {doc, section, score, source} | |
| SR->>SR: Apply allowlist, section filters, dedupe, PII scrub | |
| SR->>SR: Compute threshold τ and coverage/confidence | |
| alt Low similarity (score < τ) | |
| SR-->>MCP: Low-confidence → ask clarify / broaden search | |
| else Sufficient evidence | |
| SR-->>EVID: Vetted bundle | |
| note right of EVID: Citations + provenance map | |
| EVID->>LTM: Write traces (embeds, query, ids, similarity) | |
| opt EMR context needed | |
| QR->>EMR: Request patient summary (PHI-safe) | |
| EMR-->>EVID: Labs, meds, history snippet | |
| end | |
| EVID-->>MCP: Evidence bundle + citations | |
| end | |
| </pre> | |
| </div> | |
| <div id="arch-l3" class="diagram" role="tabpanel" aria-labelledby="tab-l3" aria-hidden="true" style="display: none;"> | |
| <pre class="mermaid" aria-label="Single Turn Sequence Diagram"> | |
| sequenceDiagram | |
| participant C as Clinician | |
| participant MCP as Orchestrator (MCP) | |
| participant RAG as RAG (Router→Retriever→Safety) | |
| participant AG as Agents (Dx/Rx/Triage) | |
| participant DB as VectorDB/LTM | |
| participant OUT as Evidence Fusion | |
| C->>MCP: case description | |
| MCP->>RAG: retrieve evidence | |
| RAG->>DB: similarity search | |
| DB-->>RAG: top-k docs | |
| RAG-->>MCP: evidence bundle + citations | |
| MCP->>AG: delegated tasks | |
| AG-->>OUT: candidate answers + rationales | |
| OUT-->>C: final report + citations + cautions | |
| OUT->>DB: write traces/embeddings | |
| </pre> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Training & Reproducibility --> | |
| <section id="training" class="section"> | |
| <div class="container"> | |
| <div class="section-header" data-aos="fade-up"> | |
| <h2>Data, Training & Reproducibility</h2> | |
| <p>From 500k+ cases to specialized, efficient agents.</p> | |
| </div> | |
| <div class="grid lg:grid-cols-2 gap-6"> | |
| <div class="card"> | |
| <div class="card-body"> | |
| <h4 class="card-title">Datasets & Augmentation</h4> | |
| <ul class="list"> | |
| <li>500k+ curated & synthetic clinical cases across specialties</li> | |
| <li>QAC paraphrasing & chunking, self‑consistency sampling</li> | |
| <li>Counterfactual case generation, back‑translation</li> | |
| </ul> | |
| <div class="mt-4 flex gap-3 flex-wrap"> | |
| <a class="chip" target="_blank" href="https://huggingface.co/collections/MedAI-COS30018/finetuning-68bbe0b045db4ed5aac5e9a2">Fine‑tuning Collection</a> | |
| <a class="chip" target="_blank" href="https://huggingface.co/collections/MedAI-COS30018/rag-68bbe244bfa8ce6132fd5242">RAG Collection</a> | |
| <a class="chip" target="_blank" href="https://huggingface.co/spaces/MedAI-COS30018/MedAI_Processing">Ingestion Pipeline</a> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-body"> | |
| <h4 class="card-title">Fine‑Tuning & KD</h4> | |
| <ul class="list"> | |
| <li>Teacher→Student Knowledge Distillation</li> | |
| <li>LoRA/QLoRA adapters, GRPO for reasoning</li> | |
| <li>HPC runs: deterministic seeds, LR schedules, checkpoints</li> | |
| </ul> | |
| <div class="mt-4 flex gap-3 flex-wrap"> | |
| <a class="chip" target="_blank" href="https://hackmd.io/@ngFNmXW1RVOfNb7b3NYBJg/instruction">KD Procedure</a> | |
| <a class="chip" target="_blank" href="https://hackmd.io/@ngFNmXW1RVOfNb7b3NYBJg/bench">Benchmarks Plan</a> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Evaluation --> | |
| <section id="evaluation" class="section"> | |
| <div class="container"> | |
| <div class="section-header" data-aos="fade-up"> | |
| <h2>Evaluation & Safety</h2> | |
| <p>Benchmarks, semantic audits, and runtime guards.</p> | |
| </div> | |
| <div class="grid lg:grid-cols-3 gap-6"> | |
| <div class="metric"> | |
| <div class="metric-value" data-count="500000">0</div> | |
| <div class="metric-label">Cases Curated</div> | |
| </div> | |
| <div class="metric"> | |
| <div class="metric-value" data-count="3">0</div> | |
| <div class="metric-label">Specialist Agents</div> | |
| </div> | |
| <div class="metric"> | |
| <div class="metric-value" data-count="2">0</div> | |
| <div class="metric-label">Benchmarks</div> | |
| </div> | |
| </div> | |
| <div class="mt-8 grid md:grid-cols-2 gap-6"> | |
| <div class="card"> | |
| <div class="card-body"> | |
| <h4 class="card-title">Benchmarks</h4> | |
| <p>MedMCQA (medical exam QA) and PubMedQA (research abstract QA). Complemented by semantic similarity audits with biomedical embeddings.</p> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-body"> | |
| <h4 class="card-title">Runtime Guards</h4> | |
| <p>Uncertainty prompts, refusal policies for out‑of‑scope, citation‑required answers, and HIL oversight to ensure safety.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Team --> | |
| <section id="team" class="section"> | |
| <div class="container"> | |
| <div class="section-header" data-aos="fade-up"> | |
| <h2>Team</h2> | |
| <div class="team-info"> | |
| <div class="university-info"> | |
| <span class="university-name">Swinburne University of Technology</span> | |
| <span class="course-code">COS30018</span> | |
| </div> | |
| <div class="team-members"> | |
| <div class="member-card" data-aos="zoom-in" data-aos-delay="100" title="Liam - Team Leader"> | |
| <div class="member-avatar">🎖️</div> | |
| <span class="member-name">Liam</span> | |
| <span class="member-role">Team Leader</span> | |
| </div> | |
| <div class="member-card" data-aos="zoom-in" data-aos-delay="200" title="Henry - Finetune + RAG"> | |
| <div class="member-avatar">🧪</div> | |
| <span class="member-name">Henry</span> | |
| <span class="member-role">LLM + RAG</span> | |
| </div> | |
| <div class="member-card" data-aos="zoom-in" data-aos-delay="300" title="Hai - RAG + APIs"> | |
| <div class="member-avatar">🔗</div> | |
| <span class="member-name">Hai</span> | |
| <span class="member-role">RAG + APIs</span> | |
| </div> | |
| <div class="member-card" data-aos="zoom-in" data-aos-delay="400" title="Dylan - Infra + Fullstack"> | |
| <div class="member-avatar">⚙️</div> | |
| <span class="member-name">Dylan</span> | |
| <span class="member-role">Infra + Fullstack</span> | |
| </div> | |
| <div class="member-card" data-aos="zoom-in" data-aos-delay="500" title="Vinh - Infra + Backend"> | |
| <div class="member-avatar">🔧</div> | |
| <span class="member-name">Vinh</span> | |
| <span class="member-role">Infra + Backend</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Footer --> | |
| <footer class="py-10 border-t border-white/10 text-center text-slate-400"> | |
| <div class="container"> | |
| <div class="flex justify-center gap-6 mb-3"> | |
| <a class="link" target="_blank" href="https://huggingface.co/MedAI-COS30018">HF Org</a> | |
| <a class="link" target="_blank" href="https://medai-cos30018-medicaldiagnosissystem.hf.space/">Live App</a> | |
| <a class="link" target="_blank" href="https://huggingface.co/spaces/MedAI-COS30018/MedAI_Processing">Data Processing</a> | |
| </div> | |
| <div class="text-xs">© 2025 Swinburne University · MedAI (COS30018). For research and educational use only.</div> | |
| </div> | |
| </footer> | |
| <script src="https://unpkg.com/vanilla-tilt@1.8.1/dist/vanilla-tilt.min.js"></script> | |
| <script src="assets/app.js"></script> | |
| <script> | |
| // Wait for all resources to load before initializing | |
| window.addEventListener('load', () => { | |
| // Initialize AOS if available | |
| if (typeof AOS !== 'undefined') { | |
| AOS.init({ | |
| duration: 700, | |
| once: true, | |
| offset: 100, | |
| easing: 'ease-in-out' | |
| }); | |
| } else { | |
| console.warn('AOS library not loaded'); | |
| } | |
| // Initialize Lucide icons if available | |
| if (typeof lucide !== 'undefined') { | |
| lucide.createIcons(); | |
| } else { | |
| console.warn('Lucide library not loaded'); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> | |