<section class="apw-tcm-tool">
<div class="apw-wrap">
<h2>TCM Symptom Checklist & Differential Builder</h2>
<p class="apw-intro">
Select symptoms below to see which TCM patterns are most strongly represented.
</p>
<div class="apw-grid">
<div class="apw-left">
<div class="apw-card">
<h3>Head / Location</h3>
<label><input type="checkbox" data-pattern="shaoyang" data-score="3"> One-sided headache</label>
<label><input type="checkbox" data-pattern="shaoyang" data-score="2"> Temporal pain</label>
<label><input type="checkbox" data-pattern="liverYang" data-score="2"> Vertex headache</label>
<label><input type="checkbox" data-pattern="taiyang" data-score="2"> Occipital headache</label>
<label><input type="checkbox" data-pattern="yangming" data-score="2"> Frontal headache</label>
</div>
<div class="apw-card">
<h3>Headache Quality</h3>
<label><input type="checkbox" data-pattern="liverYang" data-score="3"> Pounding / throbbing</label>
<label><input type="checkbox" data-pattern="liverQi" data-score="2"> Distending pressure</label>
<label><input type="checkbox" data-pattern="dampPhlegm" data-score="3"> Heavy / foggy</label>
<label><input type="checkbox" data-pattern="bloodYinDef" data-score="3"> Dull / empty</label>
<label><input type="checkbox" data-pattern="bloodStasis" data-score="3"> Sharp / fixed pain</label>
</div>
<div class="apw-card">
<h3>Eyes</h3>
<label><input type="checkbox" data-pattern="bloodYinDef" data-score="2"> Dry eyes</label>
<label><input type="checkbox" data-pattern="bloodYinDef" data-score="2"> Floaters</label>
<label><input type="checkbox" data-pattern="liverYang" data-score="2"> Red eyes</label>
<label><input type="checkbox" data-pattern="bloodYinDef" data-score="1"> Blurry vision</label>
</div>
<div class="apw-card">
<h3>Ears</h3>
<label><input type="checkbox" data-pattern="shaoyang" data-score="3"> Ear fullness</label>
<label><input type="checkbox" data-pattern="shaoyang" data-score="3"> Muffled hearing</label>
<label><input type="checkbox" data-pattern="liverYang" data-score="2"> High-pitched tinnitus</label>
<label><input type="checkbox" data-pattern="kidneyDef" data-score="2"> Hearing loss</label>
</div>
<div class="apw-card">
<h3>Jaw / Neck / Muscular</h3>
<label><input type="checkbox" data-pattern="liverQi" data-score="2"> Jaw tension / clenching</label>
<label><input type="checkbox" data-pattern="shaoyang" data-score="2"> SCM tension</label>
<label><input type="checkbox" data-pattern="shaoyang" data-score="2"> Side-of-neck tightness</label>
<label><input type="checkbox" data-pattern="taiyang" data-score="2"> Suboccipital tension</label>
<label><input type="checkbox" data-pattern="bloodStasis" data-score="2"> Chronic fixed muscular pain</label>
</div>
<div class="apw-card">
<h3>Stress / Mood / Nervous System</h3>
<label><input type="checkbox" data-pattern="liverQi" data-score="3"> Stress</label>
<label><input type="checkbox" data-pattern="liverYang" data-score="2"> Irritability</label>
<label><input type="checkbox" data-pattern="shenDisturbance" data-score="2"> Anxiety</label>
<label><input type="checkbox" data-pattern="shenDisturbance" data-score="2"> Insomnia</label>
<label><input type="checkbox" data-pattern="liverQi" data-score="2"> Mood swings</label>
</div>
<div class="apw-card">
<h3>Fatigue / Deficiency / Dryness</h3>
<label><input type="checkbox" data-pattern="qiDef" data-score="2"> Fatigue</label>
<label><input type="checkbox" data-pattern="bloodYinDef" data-score="2"> General dryness</label>
<label><input type="checkbox" data-pattern="bloodYinDef" data-score="2"> Pale complexion</label>
<label><input type="checkbox" data-pattern="kidneyDef" data-score="2"> Low back weakness</label>
<label><input type="checkbox" data-pattern="bloodYinDef" data-score="1"> Dizziness</label>
</div>
<div class="apw-card">
<h3>Damp / Digestive</h3>
<label><input type="checkbox" data-pattern="dampPhlegm" data-score="3"> Brain fog</label>
<label><input type="checkbox" data-pattern="dampPhlegm" data-score="3"> Heaviness</label>
<label><input type="checkbox" data-pattern="dampPhlegm" data-score="2"> Sticky stools</label>
<label><input type="checkbox" data-pattern="qiDef" data-score="2"> Poor appetite</label>
<label><input type="checkbox" data-pattern="qiDef" data-score="2"> Bloating</label>
</div>
<div class="apw-actions">
<button type="button" id="apw-reset-btn">Reset</button>
</div>
</div>
<div class="apw-right">
<div class="apw-card apw-results">
<h3>Pattern Scores</h3>
<ul id="apw-score-list"></ul>
</div>
<div class="apw-card apw-results">
<h3>Evolving Differential</h3>
<ol id="apw-differential-list"></ol>
</div>
<div class="apw-card apw-results">
<h3>Interpretive Notes</h3>
<div id="apw-notes"></div>
</div>
</div>
</div>
</div>
</section>
<style>
.apw-tcm-tool {
--apw-green: #4d7c57;
--apw-green-dark: #35563c;
--apw-green-soft: #edf5ef;
--apw-border: #d7e4da;
--apw-text: #243127;
--apw-muted: #5c6b60;
--apw-white: #ffffff;
--apw-shadow: 0 8px 24px rgba(0,0,0,0.06);
font-family: Arial, Helvetica, sans-serif;
color: var(--apw-text);
background: #f7faf7;
padding: 32px 16px;
}
.apw-tcm-tool * {
box-sizing: border-box;
}
.apw-wrap {
max-width: 1200px;
margin: 0 auto;
}
.apw-tcm-tool h2 {
margin: 0 0 10px;
font-size: 2rem;
color: var(--apw-green-dark);
}
.apw-intro {
margin: 0 0 24px;
color: var(--apw-muted);
font-size: 1rem;
line-height: 1.5;
}
.apw-grid {
display: grid;
grid-template-columns: 1.4fr 0.9fr;
gap: 24px;
}
.apw-left,
.apw-right {
display: grid;
gap: 18px;
}
.apw-card {
background: var(--apw-white);
border: 1px solid var(--apw-border);
border-radius: 16px;
padding: 18px 18px 14px;
box-shadow: var(--apw-shadow);
}
.apw-card h3 {
margin: 0 0 14px;
font-size: 1.1rem;
color: var(--apw-green-dark);
}
.apw-card label {
display: block;
margin: 0 0 10px;
line-height: 1.45;
cursor: pointer;
color: var(--apw-text);
}
.apw-card input[type="checkbox"] {
margin-right: 10px;
transform: scale(1.1);
accent-color: var(--apw-green);
}
.apw-actions {
display: flex;
justify-content: flex-start;
}
#apw-reset-btn {
border: none;
background: var(--apw-green);
color: #fff;
padding: 12px 18px;
border-radius: 999px;
cursor: pointer;
font-size: 0.95rem;
transition: background 0.2s ease;
}
#apw-reset-btn:hover {
background: var(--apw-green-dark);
}
.apw-results ul,
.apw-results ol {
margin: 0;
padding-left: 20px;
}
.apw-results li {
margin-bottom: 10px;
line-height: 1.45;
}
.apw-score-badge {
display: inline-block;
margin-left: 8px;
background: var(--apw-green-soft);
color: var(--apw-green-dark);
border: 1px solid var(--apw-border);
border-radius: 999px;
padding: 2px 8px;
font-size: 0.85rem;
font-weight: bold;
}
#apw-notes {
color: var(--apw-muted);
line-height: 1.6;
}
.apw-note {
margin-bottom: 12px;
padding: 10px 12px;
background: var(--apw-green-soft);
border-left: 4px solid var(--apw-green);
border-radius: 10px;
}
@media (max-width: 900px) {
.apw-grid {
grid-template-columns: 1fr;
}
}
</style>
<script>
(function () {
const patternNames = {
shaoyang: "Shaoyang Disorder / GB-SJ Obstruction",
liverYang: "Liver Yang Rising",
liverQi: "Liver Qi Stagnation",
bloodYinDef: "Liver Blood / Yin Deficiency",
dampPhlegm: "Damp / Phlegm Accumulation",
bloodStasis: "Blood Stasis",
qiDef: "Qi Deficiency / Spleen Qi Deficiency",
kidneyDef: "Kidney Deficiency",
taiyang: "Taiyang Channel Pattern",
yangming: "Yangming Channel Pattern",
shenDisturbance: "Shen Disturbance"
};
const patternNotes = {
shaoyang: "Often rises to the top when symptoms cluster around the side of the head, ear, jaw, and lateral neck.",
liverYang: "Often associated with pounding headache quality, irritability, rising tension, and eye involvement.",
liverQi: "Frequently linked with stress, jaw clenching, distending pain, and constrained movement.",
bloodYinDef: "Consider when dryness, floaters, pale complexion, fatigue, or dull empty pain are present.",
dampPhlegm: "Often suggested by heaviness, fogginess, sticky stools, and cloudy thinking.",
bloodStasis: "More likely when pain is fixed, sharp, chronic, and localized.",
qiDef: "Often appears with fatigue, bloating, poor appetite, and low overall resilience.",
kidneyDef: "Can underlie chronicity, hearing issues, low back weakness, and deeper depletion patterns.",
taiyang: "Think occiput, suboccipitals, posterior neck, and more exterior tension patterns.",
yangming: "Think frontal symptoms, face, jaw, sinus, and digestive involvement.",
shenDisturbance: "Often contributes when sleep, anxiety, agitation, or nervous system overactivation are prominent."
};
const checkboxes = document.querySelectorAll('.apw-tcm-tool input[type="checkbox"]');
const scoreList = document.getElementById('apw-score-list');
const differentialList = document.getElementById('apw-differential-list');
const notesBox = document.getElementById('apw-notes');
const resetBtn = document.getElementById('apw-reset-btn');
function calculateScores() {
const scores = {};
Object.keys(patternNames).forEach(key => scores[key] = 0);
checkboxes.forEach(box => {
if (box.checked) {
const pattern = box.dataset.pattern;
const score = parseInt(box.dataset.score, 10) || 0;
if (scores.hasOwnProperty(pattern)) {
scores[pattern] += score;
}
}
});
return scores;
}
function render() {
const scores = calculateScores();
const ranked = Object.entries(scores)
.filter(([, score]) => score > 0)
.sort((a, b) => b[1] - a[1]);
scoreList.innerHTML = '';
differentialList.innerHTML = '';
notesBox.innerHTML = '';
if (ranked.length === 0) {
scoreList.innerHTML = '<li>No symptoms selected yet.</li>';
differentialList.innerHTML = '<li>Select symptoms to generate a differential.</li>';
notesBox.innerHTML = '<div class="apw-note">This tool is educational and pattern-based. It does not replace individualized clinical assessment.</div>';
return;
}
ranked.forEach(([pattern, score]) => {
const li = document.createElement('li');
li.innerHTML = `${patternNames[pattern]} <span class="apw-score-badge">${score}</span>`;
scoreList.appendChild(li);
});
ranked.slice(0, 5).forEach(([pattern, score], index) => {
const li = document.createElement('li');
let label = patternNames[pattern];
if (index === 0) label += ' — Primary';
if (index === 1) label += ' — Secondary';
if (index === 2) label += ' — Tertiary';
li.textContent = `${label} (${score})`;
differentialList.appendChild(li);
});
ranked.slice(0, 3).forEach(([pattern]) => {
const div = document.createElement('div');
div.className = 'apw-note';
div.textContent = patternNotes[pattern];
notesBox.appendChild(div);
});
}
checkboxes.forEach(box => {
box.addEventListener('change', render);
});
resetBtn.addEventListener('click', function () {
checkboxes.forEach(box => box.checked = false);
render();
});
render();
})();
</script>
