Skip to content

Instantly share code, notes, and snippets.

@andrewsteinmeyer
Last active March 4, 2026 03:45
Show Gist options
  • Select an option

  • Save andrewsteinmeyer/929f1f3cb274a55ae50e9b19feb37426 to your computer and use it in GitHub Desktop.

Select an option

Save andrewsteinmeyer/929f1f3cb274a55ae50e9b19feb37426 to your computer and use it in GitHub Desktop.
Contour Health — Patient Symptom Tracking Mockup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Journey Pediatrics — Symptom Tracker</title>
<script>
// Inline loader for Chart.js + annotation plugin with fallback
(function(){
function loadScript(url){return new Promise(function(ok,fail){var s=document.createElement('script');s.src=url;s.onload=ok;s.onerror=fail;document.head.appendChild(s);})}
var cdns=[
['https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js','https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js'],
['https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation@3.0.1/dist/chartjs-plugin-annotation.min.js','https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/3.0.1/chartjs-plugin-annotation.min.js']
];
function loadWithFallback(pair){return loadScript(pair[0]).catch(function(){return loadScript(pair[1])})}
window._chartsReady=loadWithFallback(cdns[0]).then(function(){return loadWithFallback(cdns[1]).catch(function(){console.warn('Annotation plugin unavailable')})});
})();
</script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
/* ============ WHITE-LABEL BRANDING VARS ============ */
:root {
--brand-name: "Journey Pediatrics";
--brand-primary: #5BC5C2;
--brand-primary-light: #8ED9D6;
--brand-primary-dark: #3FA9A6;
--brand-secondary: #D4886B;
--brand-accent: #D4886B;
--brand-bg: #FAFAFA;
--brand-surface: #FFFFFF;
--brand-text: #2C3E50;
--brand-text-secondary: #6B7280;
--brand-border: #E5E7EB;
--brand-success: #10B981;
--brand-warning: #F59E0B;
--brand-danger: #EF4444;
--brand-trad-med: #6B7280;
--brand-func-med: #6B7280;
--radius: 12px;
--radius-sm: 8px;
--shadow: 0 1px 3px rgba(0,0,0,.06), 0 4px 12px rgba(0,0,0,.04);
--shadow-lg: 0 4px 24px rgba(0,0,0,.08);
--font: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
/* ============ RESET & BASE ============ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 15px; }
body { font-family: var(--font); color: var(--brand-text); background: var(--brand-bg); line-height: 1.6; min-height: 100vh; }
a { color: var(--brand-primary); text-decoration: none; }
button { cursor: pointer; font-family: var(--font); }
/* ============ LOGIN SCREEN ============ */
#login-screen {
min-height: 100vh; display: flex; align-items: center; justify-content: center;
background: linear-gradient(135deg, var(--brand-secondary) 0%, var(--brand-primary-dark) 50%, var(--brand-primary) 100%);
padding: 20px;
}
.login-card {
background: var(--brand-surface); border-radius: 16px; padding: 48px 40px;
max-width: 420px; width: 100%; box-shadow: 0 20px 60px rgba(0,0,0,.2);
}
.login-logo { text-align: center; margin-bottom: 32px; }
.login-logo svg { width: 48px; height: 48px; margin-bottom: 12px; }
.login-logo h1 { font-size: 1.5rem; font-weight: 700; color: var(--brand-secondary); }
.login-logo p { font-size: .85rem; color: var(--brand-text-secondary); margin-top: 4px; }
.form-group { margin-bottom: 20px; }
.form-group label { display: block; font-size: .8rem; font-weight: 600; color: var(--brand-text-secondary); margin-bottom: 6px; text-transform: uppercase; letter-spacing: .5px; }
.form-group input {
width: 100%; padding: 12px 14px; border: 1.5px solid var(--brand-border); border-radius: var(--radius-sm);
font-size: .95rem; transition: border .2s; background: var(--brand-bg);
}
.form-group input:focus { outline: none; border-color: var(--brand-primary); box-shadow: 0 0 0 3px rgba(11,122,117,.12); }
.btn-primary {
width: 100%; padding: 13px; background: var(--brand-primary); color: #fff; border: none;
border-radius: var(--radius-sm); font-size: 1rem; font-weight: 600; transition: background .2s;
}
.btn-primary:hover { background: var(--brand-primary-dark); }
.hipaa-badge {
display: flex; align-items: center; gap: 8px; margin-top: 24px; padding: 12px;
background: #EBF7F0; border-radius: var(--radius-sm); font-size: .78rem; color: var(--brand-success);
}
.hipaa-badge svg { flex-shrink: 0; }
.login-footer { text-align: center; margin-top: 20px; font-size: .75rem; color: var(--brand-text-secondary); }
/* ============ APP SHELL ============ */
#app { display: none; }
.topbar {
background: var(--brand-surface); border-bottom: 1px solid var(--brand-border);
padding: 0 32px; height: 64px; display: flex; align-items: center; justify-content: space-between;
position: sticky; top: 0; z-index: 100; box-shadow: 0 1px 4px rgba(0,0,0,.03);
}
.topbar-brand { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 1.1rem; color: var(--brand-secondary); }
.topbar-brand svg { width: 32px; height: 32px; }
.topbar-right { display: flex; align-items: center; gap: 20px; }
.topbar-user { display: flex; align-items: center; gap: 8px; font-size: .85rem; color: var(--brand-text-secondary); }
.avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--brand-primary); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: .8rem; }
/* Nav tabs */
.nav-tabs {
display: flex; gap: 4px; padding: 0 32px; background: var(--brand-surface);
border-bottom: 1px solid var(--brand-border);
}
.nav-tab {
padding: 12px 20px; border: none; background: none; font-size: .88rem; font-weight: 500;
color: var(--brand-text-secondary); border-bottom: 2.5px solid transparent; transition: all .2s;
}
.nav-tab:hover { color: var(--brand-primary); }
.nav-tab.active { color: var(--brand-primary); border-bottom-color: var(--brand-primary); }
/* Main content */
.main { max-width: 1280px; margin: 0 auto; padding: 28px 32px; }
.tab-content { display: none; }
.tab-content.active { display: block; }
/* Patient selector */
.patient-bar { display: flex; align-items: center; gap: 16px; margin-bottom: 24px; flex-wrap: wrap; }
.patient-select {
padding: 10px 14px; border: 1.5px solid var(--brand-border); border-radius: var(--radius-sm);
font-size: .9rem; background: var(--brand-surface); min-width: 300px; color: var(--brand-text);
}
.patient-badge {
display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px;
background: #E6F4F1; border-radius: 20px; font-size: .82rem; color: var(--brand-primary-dark); font-weight: 500;
}
/* Summary cards */
.summary-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin-bottom: 28px; }
.summary-card {
background: var(--brand-surface); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow);
border-left: 4px solid var(--brand-primary);
}
.summary-card.trend-down { border-left-color: var(--brand-success); }
.summary-card.trend-up { border-left-color: var(--brand-danger); }
.summary-card.milestone { border-left-color: var(--brand-accent); }
.summary-card h3 { font-size: .78rem; text-transform: uppercase; letter-spacing: .5px; color: var(--brand-text-secondary); margin-bottom: 8px; }
.summary-card .value { font-size: 2rem; font-weight: 700; color: var(--brand-text); }
.summary-card .sub { font-size: .82rem; color: var(--brand-text-secondary); margin-top: 4px; }
.trend-badge { display: inline-flex; align-items: center; gap: 3px; font-size: .78rem; font-weight: 600; padding: 2px 8px; border-radius: 10px; }
.trend-badge.good { background: #E6F9F0; color: var(--brand-success); }
.trend-badge.bad { background: #FDECEC; color: var(--brand-danger); }
/* Chart section */
.chart-section {
background: var(--brand-surface); border-radius: var(--radius); padding: 28px; box-shadow: var(--shadow); margin-bottom: 28px;
}
.chart-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 20px; flex-wrap: wrap; gap: 12px; }
.chart-header h2 { font-size: 1.2rem; font-weight: 700; }
.chart-header p { font-size: .85rem; color: var(--brand-text-secondary); margin-top: 2px; }
.chart-toggles { display: flex; flex-wrap: wrap; gap: 10px; }
.chart-toggle { display: flex; align-items: center; gap: 6px; font-size: .82rem; cursor: pointer; user-select: none; }
.chart-toggle input { accent-color: var(--brand-primary); }
.chart-toggle .dot { width: 10px; height: 10px; border-radius: 50%; }
.chart-wrap { position: relative; height: 380px; }
.chart-legend-custom { display: flex; gap: 20px; margin-top: 16px; flex-wrap: wrap; justify-content: center; }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: .78rem; color: var(--brand-text-secondary); }
.legend-line { width: 24px; height: 3px; border-radius: 2px; }
.legend-dash { width: 24px; height: 0; border-top: 2.5px dashed; }
.phase-labels { display: flex; margin-top: 8px; font-size: .75rem; font-weight: 600; text-transform: uppercase; letter-spacing: .5px; }
.phase-label { text-align: center; padding: 6px 0; border-radius: 6px; }
.phase-trad { flex: 8; background: #FFF3EB; color: var(--brand-trad-med); }
.phase-func { flex: 10; background: #E6F9F0; color: var(--brand-func-med); margin-left: 4px; }
/* Notifications */
.notif-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px; }
.notif-card {
background: var(--brand-surface); border-radius: var(--radius); padding: 20px; box-shadow: var(--shadow);
border-left: 4px solid; display: flex; gap: 14px; align-items: flex-start;
}
.notif-card.green { border-left-color: var(--brand-success); }
.notif-card.yellow { border-left-color: var(--brand-warning); }
.notif-card.red { border-left-color: var(--brand-danger); }
.notif-icon { width: 38px; height: 38px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 1.1rem; }
.notif-card.green .notif-icon { background: #E6F9F0; }
.notif-card.yellow .notif-icon { background: #FFF8E6; }
.notif-card.red .notif-icon { background: #FDECEC; }
.notif-body h4 { font-size: .92rem; font-weight: 600; margin-bottom: 4px; }
.notif-body p { font-size: .82rem; color: var(--brand-text-secondary); }
.notif-time { font-size: .72rem; color: var(--brand-text-secondary); margin-top: 6px; }
/* Resources */
.resources-section h2 { font-size: 1.15rem; font-weight: 700; margin-bottom: 16px; }
.resources-section h2 span { color: var(--brand-primary); }
.resource-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; margin-bottom: 36px; }
.resource-card {
background: var(--brand-surface); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow);
transition: transform .2s, box-shadow .2s;
}
.resource-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.resource-img { height: 140px; background: linear-gradient(135deg, var(--brand-accent), var(--brand-primary)); display: flex; align-items: center; justify-content: center; font-size: 2.5rem; }
.resource-card-body { padding: 18px; }
.resource-card-body h4 { font-size: .95rem; font-weight: 600; margin-bottom: 6px; }
.resource-card-body p { font-size: .82rem; color: var(--brand-text-secondary); margin-bottom: 10px; }
.resource-link { font-size: .82rem; font-weight: 600; color: var(--brand-primary); }
/* Responsive */
@media (max-width: 768px) {
.topbar { padding: 0 16px; }
.nav-tabs { padding: 0 16px; overflow-x: auto; }
.main { padding: 20px 16px; }
.chart-wrap { height: 280px; }
.patient-select { min-width: 100%; }
.login-card { padding: 32px 24px; }
}
</style>
</head>
<body>
<!-- ======== LOGIN SCREEN ======== -->
<div id="login-screen">
<div class="login-card">
<div class="login-logo">
<svg width="80" height="80" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="48" fill="#FBF9F7" stroke="#D8896A" stroke-width="2"/><path d="M50 20c-8 0-15 6-18 14-2 5-1 10 2 14l16 22 16-22c3-4 4-9 2-14-3-8-10-14-18-14z" fill="#6CC5C3" opacity=".85"/><path d="M50 20c-4 0-8 2-11 5 3-1 7-1 11 1s8-1 11-1c-3-3-7-5-11-5z" fill="#D8896A" opacity=".7"/><ellipse cx="44" cy="38" rx="2.5" ry="3" fill="#fff"/><ellipse cx="56" cy="38" rx="2.5" ry="3" fill="#fff"/><path d="M46 46c2 2 6 2 8 0" stroke="#fff" stroke-width="1.5" stroke-linecap="round"/></svg>
<h1>Journey Pediatrics</h1>
<p>Contour™ Symptom Tracker</p>
</div>
<form id="login-form">
<div class="form-group">
<label>Email Address</label>
<input type="email" placeholder="provider@journeypeds.com" value="demo@journeypeds.com">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" placeholder="••••••••" value="password">
</div>
<button type="submit" class="btn-primary">Sign In Securely</button>
</form>
<div class="hipaa-badge">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M12 2L3 7v5c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-9-5z" fill="#2E9E6A" opacity=".2" stroke="#2E9E6A" stroke-width="1.5"/><path d="M9 12l2 2 4-4" stroke="#2E9E6A" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
<span>HIPAA-compliant • 256-bit AES encryption • SOC 2 Type II certified</span>
</div>
<div class="login-footer">Protected health information is encrypted at rest and in transit.</div>
</div>
</div>
<!-- ======== APP ======== -->
<div id="app">
<!-- Topbar -->
<div class="topbar">
<div class="topbar-brand">
<svg width="32" height="32" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="48" fill="#FBF9F7" stroke="#D8896A" stroke-width="2"/><path d="M50 20c-8 0-15 6-18 14-2 5-1 10 2 14l16 22 16-22c3-4 4-9 2-14-3-8-10-14-18-14z" fill="#6CC5C3" opacity=".85"/><path d="M50 20c-4 0-8 2-11 5 3-1 7-1 11 1s8-1 11-1c-3-3-7-5-11-5z" fill="#D8896A" opacity=".7"/><ellipse cx="44" cy="38" rx="2.5" ry="3" fill="#fff"/><ellipse cx="56" cy="38" rx="2.5" ry="3" fill="#fff"/><path d="M46 46c2 2 6 2 8 0" stroke="#fff" stroke-width="1.5" stroke-linecap="round"/></svg>
Journey Pediatrics
</div>
<div class="topbar-right">
<div class="topbar-user">
<div class="avatar">DM</div>
<span>Dr. Martinez</span>
</div>
</div>
</div>
<!-- Nav -->
<div class="nav-tabs">
<button class="nav-tab active" data-tab="dashboard">Dashboard</button>
<button class="nav-tab" data-tab="timeline">Symptom Timeline</button>
<button class="nav-tab" data-tab="notifications">Notifications</button>
<button class="nav-tab" data-tab="resources">Resources</button>
</div>
<div class="main">
<!-- ===== DASHBOARD ===== -->
<div class="tab-content active" id="tab-dashboard">
<div class="patient-bar">
<select class="patient-select">
<option>Emma R., age 8 — Dr. Martinez (Functional Medicine)</option>
<option>Liam T., age 5 — Dr. Chen (General Pediatrics)</option>
<option>Sofia K., age 11 — Dr. Martinez (Functional Medicine)</option>
<option>Noah P., age 3 — Dr. Williams (Allergy/Immunology)</option>
</select>
<span class="patient-badge">🟢 Active Patient</span>
</div>
<div class="summary-cards">
<div class="summary-card trend-down">
<h3>Active Symptoms</h3>
<div class="value">2</div>
<div class="sub"><span class="trend-badge good">↓ 67%</span> from 6 months ago</div>
</div>
<div class="summary-card trend-down">
<h3>Severity Trend</h3>
<div class="value">Mild</div>
<div class="sub"><span class="trend-badge good">↓ Improving</span> 3-month avg: 1.8/10</div>
</div>
<div class="summary-card milestone">
<h3>Days Since Last Flare-Up</h3>
<div class="value">47</div>
<div class="sub">🎉 New personal record!</div>
</div>
<div class="summary-card">
<h3>Treatment Adherence</h3>
<div class="value">94%</div>
<div class="sub">Current protocol: 4 supplements</div>
</div>
</div>
<!-- Inline chart preview -->
<div class="chart-section">
<div class="chart-header">
<div>
<h2>Symptom Overview — Emma R.</h2>
<p>18-month severity trend • Composite score across all tracked symptoms</p>
</div>
</div>
<div class="chart-wrap"><canvas id="overview-chart"></canvas></div>
<!-- treatment start marker shown via chart annotation -->
</div>
</div>
<!-- ===== SYMPTOM TIMELINE ===== -->
<div class="tab-content" id="tab-timeline">
<div class="chart-section">
<div class="chart-header">
<div>
<h2>Detailed Symptom Timeline — Emma R.</h2>
<p>Individual symptom tracking with treatment markers • Sep 2024 – Feb 2026</p>
</div>
<div class="chart-toggles">
<label class="chart-toggle"><input type="checkbox" checked data-symptom="0"><span class="dot" style="background:#D94F4F"></span> GI / Gut Issues</label>
<label class="chart-toggle"><input type="checkbox" checked data-symptom="1"><span class="dot" style="background:#E5A100"></span> Skin Rashes</label>
<label class="chart-toggle"><input type="checkbox" checked data-symptom="2"><span class="dot" style="background:#7B61FF"></span> Behavioral</label>
<label class="chart-toggle"><input type="checkbox" checked data-symptom="3"><span class="dot" style="background:#2196F3"></span> Sleep Disruption</label>
</div>
</div>
<div class="chart-wrap"><canvas id="detail-chart"></canvas></div>
<!-- treatment start marker shown via chart annotation -->
</div>
</div>
<!-- ===== NOTIFICATIONS ===== -->
<div class="tab-content" id="tab-notifications">
<h2 style="font-size:1.2rem;font-weight:700;margin-bottom:20px;">Notifications & Milestones</h2>
<div class="notif-grid">
<div class="notif-card green">
<div class="notif-icon">🎉</div>
<div class="notif-body">
<h4>No severe episodes in 47 days!</h4>
<p>Emma has reached a new milestone — the longest streak without a severe symptom flare since tracking began.</p>
<div class="notif-time">2 hours ago</div>
</div>
</div>
<div class="notif-card green">
<div class="notif-icon">😴</div>
<div class="notif-body">
<h4>Sleep quality improved 80%</h4>
<p>Average sleep score increased from 3.2 to 8.6 over the past 3 months. Magnesium glycinate protocol appears effective.</p>
<div class="notif-time">1 day ago</div>
</div>
</div>
<div class="notif-card yellow">
<div class="notif-icon">📝</div>
<div class="notif-body">
<h4>New symptom logged — review recommended</h4>
<p>Parent reported mild nasal congestion (severity 2/10). May be seasonal — not matching previous patterns.</p>
<div class="notif-time">2 days ago</div>
</div>
</div>
<div class="notif-card green">
<div class="notif-icon">📉</div>
<div class="notif-body">
<h4>GI symptoms at all-time low</h4>
<p>Gut-related symptoms have decreased 90% since starting the elimination diet and probiotic protocol.</p>
<div class="notif-time">5 days ago</div>
</div>
</div>
<div class="notif-card red">
<div class="notif-icon">⚠️</div>
<div class="notif-body">
<h4>Supplement reorder reminder</h4>
<p>Omega-3 supply estimated to run out in 5 days. Send refill reminder to family?</p>
<div class="notif-time">1 week ago</div>
</div>
</div>
<div class="notif-card green">
<div class="notif-icon">🏆</div>
<div class="notif-body">
<h4>Treatment plan 6-month review due</h4>
<p>Emma's functional medicine protocol has been active for 10 months. Data suggests strong positive response — consider documenting as case study.</p>
<div class="notif-time">1 week ago</div>
</div>
</div>
</div>
</div>
<!-- ===== RESOURCES ===== -->
<div class="tab-content" id="tab-resources">
<div class="resources-section">
<h2>🧴 <span>Recommended Products</span></h2>
<p style="color:var(--brand-text-secondary);font-size:.85rem;margin:-10px 0 20px;">Practitioner-selected supplements for Emma's current protocol</p>
<div class="resource-grid">
<div class="resource-card">
<div class="resource-img" style="background:linear-gradient(135deg,#0B9A6A,#62B6CB)">🦠</div>
<div class="resource-card-body">
<h4>MegaSporeBiotic™ Probiotics</h4>
<p>Spore-based probiotic for gut barrier support. Clinically studied for pediatric GI health. Take 1 capsule daily with food.</p>
<a href="#" class="resource-link">View Details →</a>
</div>
</div>
<div class="resource-card">
<div class="resource-img" style="background:linear-gradient(135deg,#7B61FF,#62B6CB)">🧠</div>
<div class="resource-card-body">
<h4>Kids Magnesium Glycinate</h4>
<p>Highly absorbable magnesium for calm nervous system support and better sleep quality. 100mg chewable tablets.</p>
<a href="#" class="resource-link">View Details →</a>
</div>
</div>
<div class="resource-card">
<div class="resource-img" style="background:linear-gradient(135deg,#E5A100,#D97236)">🐟</div>
<div class="resource-card-body">
<h4>Nordic Naturals Omega-3 Gummies</h4>
<p>Kid-friendly omega-3 fatty acids for brain health, inflammation support, and skin wellness. Strawberry flavor.</p>
<a href="#" class="resource-link">View Details →</a>
</div>
</div>
<div class="resource-card">
<div class="resource-img" style="background:linear-gradient(135deg,#D94F4F,#E5A100)">🍎</div>
<div class="resource-card-body">
<h4>Elimination Diet Starter Kit</h4>
<p>Family-friendly guide and meal plans for identifying food sensitivities. Includes shopping lists and kid-approved recipes.</p>
<a href="#" class="resource-link">View Details →</a>
</div>
</div>
</div>
<h2>📚 <span>Educational Resources</span></h2>
<p style="color:var(--brand-text-secondary);font-size:.85rem;margin:-10px 0 20px;">Articles and guides to help your family understand the healing journey</p>
<div class="resource-grid">
<div class="resource-card">
<div class="resource-img" style="background:linear-gradient(135deg,#1B4965,#0B7A75)">📖</div>
<div class="resource-card-body">
<h4>Understanding the Gut-Brain Connection</h4>
<p>How your child's digestive health affects mood, behavior, and sleep — and what you can do about it.</p>
<a href="#" class="resource-link">Read Article →</a>
</div>
</div>
<div class="resource-card">
<div class="resource-img" style="background:linear-gradient(135deg,#065A57,#0FA3A3)">🔬</div>
<div class="resource-card-body">
<h4>Functional vs. Traditional: A Comparison</h4>
<p>A balanced look at how functional medicine approaches complement conventional pediatric care.</p>
<a href="#" class="resource-link">Read Article →</a>
</div>
</div>
<div class="resource-card">
<div class="resource-img" style="background:linear-gradient(135deg,#2E9E6A,#62B6CB)">🥦</div>
<div class="resource-card-body">
<h4>Elimination Diet Protocol Guide</h4>
<p>Step-by-step instructions for safely conducting an elimination diet with your child. Includes reintroduction phases.</p>
<a href="#" class="resource-link">Read Protocol →</a>
</div>
</div>
<div class="resource-card">
<div class="resource-img" style="background:linear-gradient(135deg,#7B61FF,#1B4965)">💤</div>
<div class="resource-card-body">
<h4>Sleep Hygiene for Kids</h4>
<p>Evidence-based strategies for improving your child's sleep quality naturally, without medication dependency.</p>
<a href="#" class="resource-link">Read Guide →</a>
</div>
</div>
</div>
</div>
</div>
</div><!-- .main -->
</div><!-- #app -->
<script>
// ============ LOGIN ============
document.getElementById('login-form').addEventListener('submit', e => {
e.preventDefault();
document.getElementById('login-screen').style.display = 'none';
document.getElementById('app').style.display = 'block';
(window._chartsReady||Promise.resolve()).then(function(){initCharts()}).catch(function(){initCharts()});
});
// ============ TAB NAV ============
document.querySelectorAll('.nav-tab').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('.nav-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
document.getElementById('tab-' + tab.dataset.tab).classList.add('active');
});
});
// ============ CHART DATA ============
const months = ['Sep 24','Oct 24','Nov 24','Dec 24','Jan 25','Feb 25','Mar 25','Apr 25','May 25','Jun 25','Jul 25','Aug 25','Sep 25','Oct 25','Nov 25','Dec 25','Jan 26','Feb 26'];
// Symptom data: high first 8 months, dramatic drop after month 9
const gi = [8.5, 7.8, 8.2, 9.0, 8.7, 8.0, 8.5, 7.5, 6.0, 4.2, 3.0, 2.2, 1.5, 1.0, 0.8, 0.5, 0.4, 0.3];
const skin = [7.0, 7.5, 6.8, 7.2, 8.0, 7.8, 7.0, 6.5, 5.5, 3.8, 2.8, 2.0, 1.2, 0.8, 0.6, 0.5, 0.3, 0.2];
const behavioral = [6.5, 7.0, 7.5, 8.0, 7.5, 8.2, 7.8, 7.0, 5.0, 3.5, 2.5, 1.8, 1.2, 0.8, 0.5, 0.4, 0.3, 0.2];
const sleep = [7.2, 8.0, 7.5, 8.5, 8.0, 7.5, 8.0, 7.2, 5.8, 4.0, 2.8, 1.5, 1.0, 0.8, 0.5, 0.3, 0.2, 0.2];
// Composite average
const composite = months.map((_, i) => +((gi[i] + skin[i] + behavioral[i] + sleep[i]) / 4).toFixed(1));
// Treatment start annotation — single vertical line at May 2025 (index 8)
function treatmentAnnotations() {
return {
treatmentStart: {
type: 'line', xMin: 8, xMax: 8,
borderColor: '#0B9A6A', borderWidth: 2.5, borderDash: [6, 4],
label: {
display: true,
content: '🥦 Cut gluten from diet — May 2025',
position: 'start',
backgroundColor: '#0B9A6A',
color: '#fff',
font: { size: 11, weight: '600' },
padding: { x: 8, y: 5 },
borderRadius: 6
}
}
};
}
function initCharts() {
// Overview chart (composite)
new Chart(document.getElementById('overview-chart'), {
type: 'line',
data: {
labels: months,
datasets: [{
label: 'Composite Severity',
data: composite,
borderColor: '#0B7A75',
backgroundColor: ctx => {
const g = ctx.chart.ctx.createLinearGradient(0, 0, 0, 350);
g.addColorStop(0, 'rgba(11,122,117,.25)'); g.addColorStop(1, 'rgba(11,122,117,.01)');
return g;
},
fill: true, tension: .4, borderWidth: 3, pointRadius: 4, pointBackgroundColor: '#fff',
pointBorderColor: '#0B7A75', pointBorderWidth: 2, pointHoverRadius: 7,
}]
},
options: {
responsive: true, maintainAspectRatio: false,
scales: {
y: { min: 0, max: 10, title: { display: true, text: 'Severity (0–10)', font: {size: 12} }, grid: { color: '#EEF2F4' }},
x: { grid: { display: false }}
},
plugins: {
legend: { display: false },
annotation: { annotations: treatmentAnnotations() },
tooltip: { backgroundColor: '#1A2B3C', titleFont: {size: 13}, bodyFont: {size: 12}, padding: 12, cornerRadius: 8 }
}
}
});
// Detail chart (individual symptoms)
const detailChart = new Chart(document.getElementById('detail-chart'), {
type: 'line',
data: {
labels: months,
datasets: [
{ label: 'GI / Gut Issues', data: gi, borderColor: '#D94F4F', backgroundColor: 'rgba(217,79,79,.08)', fill: true, tension: .4, borderWidth: 2.5, pointRadius: 3, pointBackgroundColor: '#fff', pointBorderColor: '#D94F4F', pointBorderWidth: 2 },
{ label: 'Skin Rashes', data: skin, borderColor: '#E5A100', backgroundColor: 'rgba(229,161,0,.08)', fill: true, tension: .4, borderWidth: 2.5, pointRadius: 3, pointBackgroundColor: '#fff', pointBorderColor: '#E5A100', pointBorderWidth: 2 },
{ label: 'Behavioral', data: behavioral, borderColor: '#7B61FF', backgroundColor: 'rgba(123,97,255,.08)', fill: true, tension: .4, borderWidth: 2.5, pointRadius: 3, pointBackgroundColor: '#fff', pointBorderColor: '#7B61FF', pointBorderWidth: 2 },
{ label: 'Sleep Disruption', data: sleep, borderColor: '#2196F3', backgroundColor: 'rgba(33,150,243,.08)', fill: true, tension: .4, borderWidth: 2.5, pointRadius: 3, pointBackgroundColor: '#fff', pointBorderColor: '#2196F3', pointBorderWidth: 2 },
]
},
options: {
responsive: true, maintainAspectRatio: false,
scales: {
y: { min: 0, max: 10, title: { display: true, text: 'Severity (0–10)', font: {size: 12} }, grid: { color: '#EEF2F4' }},
x: { grid: { display: false }}
},
plugins: {
legend: { display: false },
annotation: { annotations: treatmentAnnotations() },
tooltip: { mode: 'index', intersect: false, backgroundColor: '#1A2B3C', titleFont: {size: 13}, bodyFont: {size: 12}, padding: 12, cornerRadius: 8 }
},
interaction: { mode: 'index', intersect: false }
}
});
// Toggle symptom lines
document.querySelectorAll('[data-symptom]').forEach(cb => {
cb.addEventListener('change', () => {
const idx = +cb.dataset.symptom;
detailChart.data.datasets[idx].hidden = !cb.checked;
detailChart.update();
});
});
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment