Create an interactive labeled diagram of the neuromuscular junction showing: Motor neuron axon Axon terminal (synaptic bouton) Synaptic vesicles containing acetylcholine (ACh) Voltage-gated calcium (Ca²⁺) channels Synaptic cleft Basal lamina with acetylcholinesterase (AChE) Motor end plate (sarcolemma) Junctional folds Nicotinic acetylcholine (Nm) receptors Voltage-gated sodium (Na⁺) channels Skeletal muscle fiber Animation sequence: Action potential reaches the axon terminal. Voltage-gated Ca²⁺ channels open and Ca²⁺ enters the terminal. Synaptic vesicles fuse with the membrane and release ACh. ACh diffuses across the synaptic cleft. ACh binds to nicotinic (Nm) receptors on the motor end plate. Na⁺ influx produces an end-plate potential (EPP). If threshold is reached, voltage-gated Na⁺ channels open, generating a muscle action potential. Action potential spreads along the sarcolemma and into T-tubules. ACh is broken down by acetylcholinesterase into acetate and choline. Choline is taken back into the nerve terminal for ACh resynthesis. Interactive features: Hover over each structure to display its function. Step-by-step controls (Next/Previous). Play/Pause animation. Toggle labels on/off. Color-code ions: Ca²⁺ = Blue Na⁺ = Green ACh = Yellow Include a summary panel explaining excitation at the neuromuscular junction. Learning objectives: Understand the anatomy of the neuromuscular junction. Explain the sequence of events in neuromuscular transmission. Identify the role of acetylcholine, calcium, sodium, and acetylcholinesterase. Relate end-plate potential to muscle action potential generation.

Running Command

mkdir -p /tmp/workspace/nmj-diagram && ls /tmp/workspace/

Writing File

~/nmj-diagram/nmj_interactive.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neuromuscular Junction - Interactive Diagram</title>
<style>
  :root {
    --ca-color: #3b82f6;
    --na-color: #22c55e;
    --ach-color: #eab308;
    --ache-color: #f97316;
    --bg: #0f172a;
    --panel: #1e293b;
    --border: #334155;
    --text: #e2e8f0;
    --text-dim: #94a3b8;
    --accent: #7c3aed;
    --highlight: #06b6d4;
  }
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body {
    font-family: 'Segoe UI', system-ui, sans-serif;
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
  }
  header {
    background: linear-gradient(135deg, #1e1b4b, #312e81);
    padding: 16px 24px;
    display: flex;
    align-items: center;
    gap: 12px;
    border-bottom: 1px solid var(--border);
  }
  header h1 { font-size: 1.3rem; font-weight: 700; letter-spacing: 0.02em; }
  header span { font-size: 0.8rem; color: var(--text-dim); margin-left: auto; }
  .main-layout {
    display: flex;
    flex: 1;
    gap: 0;
    height: calc(100vh - 60px);
  }
  .diagram-area {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 16px;
    min-width: 0;
  }
  #nmj-svg {
    width: 100%;
    height: auto;
    max-height: 520px;
    flex-shrink: 0;
  }
  .controls {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 12px;
    padding: 10px 14px;
    background: var(--panel);
    border-radius: 10px;
    border: 1px solid var(--border);
  }
  .controls button {
    background: #334155;
    color: var(--text);
    border: 1px solid #475569;
    padding: 6px 14px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.82rem;
    transition: all 0.15s;
  }
  .controls button:hover { background: #475569; }
  .controls button.active { background: var(--accent); border-color: var(--accent); }
  .controls button:disabled { opacity: 0.35; cursor: not-allowed; }
  #step-counter {
    font-size: 0.8rem;
    color: var(--text-dim);
    margin-left: auto;
  }
  .step-bar {
    display: flex;
    gap: 4px;
    margin-top: 10px;
  }
  .step-dot {
    width: 26px;
    height: 6px;
    border-radius: 3px;
    background: #334155;
    cursor: pointer;
    transition: background 0.2s;
  }
  .step-dot.active { background: var(--accent); }
  .step-dot.done { background: #4ade80; }

  /* Right panel */
  .right-panel {
    width: 320px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    border-left: 1px solid var(--border);
    background: var(--panel);
    overflow-y: auto;
  }
  .panel-section {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
  }
  .panel-section h3 {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-dim);
    margin-bottom: 8px;
  }
  #step-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--highlight);
    margin-bottom: 6px;
  }
  #step-desc {
    font-size: 0.83rem;
    line-height: 1.55;
    color: var(--text);
  }
  #hover-box {
    min-height: 70px;
  }
  #hover-name {
    font-size: 0.95rem;
    font-weight: 700;
    color: #fbbf24;
    margin-bottom: 5px;
  }
  #hover-desc {
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--text-dim);
  }
  .legend-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
    font-size: 0.8rem;
  }
  .legend-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    flex-shrink: 0;
  }

  /* Summary panel */
  .summary-panel {
    padding: 14px 16px;
  }
  .summary-panel p {
    font-size: 0.78rem;
    line-height: 1.55;
    color: var(--text-dim);
    margin-bottom: 8px;
  }
  .obj-list {
    list-style: none;
  }
  .obj-list li {
    font-size: 0.76rem;
    color: var(--text-dim);
    padding: 4px 0 4px 16px;
    position: relative;
    border-bottom: 1px solid #1e293b;
    line-height: 1.45;
  }
  .obj-list li::before {
    content: '▸';
    position: absolute;
    left: 0;
    color: var(--accent);
  }

  /* SVG interactive */
  .nmj-label {
    font-size: 10px;
    font-family: 'Segoe UI', sans-serif;
    fill: #e2e8f0;
    pointer-events: none;
  }
  .nmj-label-box {
    fill: rgba(15,23,42,0.88);
    stroke: #334155;
    stroke-width: 0.8;
    rx: 3;
    ry: 3;
  }
  .struct-hit {
    fill: transparent;
    cursor: pointer;
    transition: opacity 0.2s;
  }
  .struct-hit:hover { fill: rgba(255,255,255,0.06); }
  .struct-hit.highlighted { fill: rgba(250,204,21,0.12); }

  /* Animations */
  @keyframes apulse {
    0% { stroke-dashoffset: 200; opacity: 0; }
    20% { opacity: 1; }
    100% { stroke-dashoffset: 0; opacity: 1; }
  }
  @keyframes caflowin {
    0% { opacity: 0; transform: translateY(-18px); }
    60% { opacity: 1; }
    100% { opacity: 1; transform: translateY(0); }
  }
  @keyframes vesicle-fuse {
    0% { transform: scale(1) translateY(0); opacity: 1; }
    50% { transform: scale(1.4) translateY(-6px); opacity: 0.8; }
    100% { transform: scale(0) translateY(-12px); opacity: 0; }
  }
  @keyframes ach-diffuse {
    0% { cy: 310; opacity: 0; r: 3; }
    30% { opacity: 1; }
    100% { cy: 365; opacity: 1; r: 3; }
  }
  @keyframes na-influx {
    0% { opacity: 0; transform: translateY(-10px); }
    100% { opacity: 1; transform: translateY(8px); }
  }
  @keyframes ep-flash {
    0%, 100% { fill-opacity: 0; }
    30%, 70% { fill-opacity: 0.35; }
  }
  @keyframes ap-spread {
    0% { stroke-dashoffset: 400; }
    100% { stroke-dashoffset: 0; }
  }
  @keyframes choline-uptake {
    0% { cx: 295; opacity: 1; }
    100% { cx: 230; opacity: 0; }
  }
  @keyframes fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
  }
  @keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-5px); }
  }
  .hidden { display: none !important; }
  .anim-layer { pointer-events: none; }

  /* Tooltip */
  #tooltip {
    position: fixed;
    background: #1e293b;
    border: 1px solid #7c3aed;
    border-radius: 8px;
    padding: 8px 12px;
    font-size: 0.78rem;
    color: #e2e8f0;
    max-width: 200px;
    pointer-events: none;
    z-index: 999;
    display: none;
    line-height: 1.45;
  }
  #tooltip strong { color: #fbbf24; display: block; margin-bottom: 3px; }

  @media (max-width: 768px) {
    .main-layout { flex-direction: column; height: auto; }
    .right-panel { width: 100%; border-left: none; border-top: 1px solid var(--border); }
  }
</style>
</head>
<body>

<header>
  <svg width="28" height="28" viewBox="0 0 28 28" fill="none">
    <circle cx="14" cy="14" r="13" fill="#4c1d95" stroke="#7c3aed" stroke-width="1.5"/>
    <path d="M6 14 Q10 8 14 14 Q18 20 22 14" stroke="#06b6d4" stroke-width="2" fill="none" stroke-linecap="round"/>
    <circle cx="22" cy="14" r="3" fill="#eab308"/>
  </svg>
  <h1>Neuromuscular Junction - Interactive Diagram</h1>
  <span>Hover structures · Step through animation</span>
</header>

<div class="main-layout">
  <div class="diagram-area">

    <!-- SVG Diagram -->
    <svg id="nmj-svg" viewBox="0 0 760 540" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <linearGradient id="axonGrad" x1="0%" y1="0%" x2="0%" y2="100%">
          <stop offset="0%" stop-color="#6d28d9"/>
          <stop offset="100%" stop-color="#4c1d95"/>
        </linearGradient>
        <linearGradient id="muscleGrad" x1="0%" y1="0%" x2="0%" y2="100%">
          <stop offset="0%" stop-color="#7f1d1d"/>
          <stop offset="50%" stop-color="#991b1b"/>
          <stop offset="100%" stop-color="#7f1d1d"/>
        </linearGradient>
        <linearGradient id="terminalGrad" x1="0%" y1="0%" x2="0%" y2="100%">
          <stop offset="0%" stop-color="#5b21b6"/>
          <stop offset="100%" stop-color="#3b0764"/>
        </linearGradient>
        <radialGradient id="vesGrad" cx="40%" cy="35%">
          <stop offset="0%" stop-color="#fef08a"/>
          <stop offset="100%" stop-color="#ca8a04"/>
        </radialGradient>
        <radialGradient id="vesGrad2" cx="40%" cy="35%">
          <stop offset="0%" stop-color="#fef08a" stop-opacity="0.4"/>
          <stop offset="100%" stop-color="#ca8a04" stop-opacity="0.4"/>
        </radialGradient>
        <filter id="glow">
          <feGaussianBlur stdDeviation="3" result="coloredBlur"/>
          <feMerge><feMergeNode in="coloredBlur"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
        <filter id="softglow">
          <feGaussianBlur stdDeviation="2" result="coloredBlur"/>
          <feMerge><feMergeNode in="coloredBlur"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
        <marker id="arrowBlue" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto">
          <path d="M0,0 L0,6 L8,3 z" fill="#3b82f6"/>
        </marker>
        <marker id="arrowGreen" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto">
          <path d="M0,0 L0,6 L8,3 z" fill="#22c55e"/>
        </marker>
        <marker id="arrowYellow" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto">
          <path d="M0,0 L0,6 L8,3 z" fill="#eab308"/>
        </marker>
      </defs>

      <!-- ===== BACKGROUND ===== -->
      <rect width="760" height="540" fill="#0f172a"/>

      <!-- Extracellular space label -->
      <text x="620" y="28" font-size="9" fill="#475569" font-style="italic">Extracellular Space</text>
      <text x="620" y="520" font-size="9" fill="#475569" font-style="italic">Intracellular (Sarcoplasm)</text>

      <!-- ===== MOTOR NEURON AXON ===== -->
      <!-- Myelin sheath sections -->
      <rect x="80" y="82" width="55" height="46" rx="22" fill="#d97706" opacity="0.35"/>
      <rect x="155" y="82" width="55" height="46" rx="22" fill="#d97706" opacity="0.35"/>
      <rect x="230" y="82" width="55" height="46" rx="22" fill="#d97706" opacity="0.35"/>
      <!-- Axon core -->
      <rect x="75" y="90" width="230" height="30" rx="15" fill="url(#axonGrad)" stroke="#7c3aed" stroke-width="1.5"/>
      <!-- Node of Ranvier labels -->
      <line x1="142" y1="90" x2="142" y2="120" stroke="#0f172a" stroke-width="3"/>
      <line x1="217" y1="90" x2="217" y2="120" stroke="#0f172a" stroke-width="3"/>

      <!-- Axon narrowing -->
      <path d="M305 92 Q330 95 340 105 Q350 115 345 125 L305 120 Z" fill="url(#axonGrad)" stroke="#7c3aed" stroke-width="1"/>

      <!-- ===== AXON TERMINAL (SYNAPTIC BOUTON) ===== -->
      <ellipse cx="390" cy="200" rx="115" ry="80" fill="url(#terminalGrad)" stroke="#7c3aed" stroke-width="2"/>
      <!-- Terminal membrane detail - bottom edge -->
      <path d="M275 200 Q280 276 390 278 Q500 276 505 200" fill="none" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="4,2"/>

      <!-- ===== VOLTAGE-GATED Ca2+ CHANNELS ===== -->
      <!-- Ca channels on axon terminal membrane (bottom) -->
      <g id="ca-channels">
        <rect x="308" y="266" width="10" height="20" rx="2" fill="#1e40af" stroke="#3b82f6" stroke-width="1.5"/>
        <rect x="356" y="268" width="10" height="20" rx="2" fill="#1e40af" stroke="#3b82f6" stroke-width="1.5"/>
        <rect x="404" y="268" width="10" height="20" rx="2" fill="#1e40af" stroke="#3b82f6" stroke-width="1.5"/>
        <rect x="452" y="266" width="10" height="20" rx="2" fill="#1e40af" stroke="#3b82f6" stroke-width="1.5"/>
      </g>

      <!-- ===== SYNAPTIC VESICLES ===== -->
      <g id="vesicles-static">
        <!-- Row 1 - near membrane -->
        <circle cx="320" cy="248" r="12" fill="url(#vesGrad)" stroke="#ca8a04" stroke-width="1.5"/>
        <circle cx="352" cy="244" r="11" fill="url(#vesGrad)" stroke="#ca8a04" stroke-width="1.5"/>
        <circle cx="384" cy="250" r="13" fill="url(#vesGrad)" stroke="#ca8a04" stroke-width="1.5"/>
        <circle cx="418" cy="245" r="11" fill="url(#vesGrad)" stroke="#ca8a04" stroke-width="1.5"/>
        <circle cx="450" cy="248" r="12" fill="url(#vesGrad)" stroke="#ca8a04" stroke-width="1.5"/>
        <!-- Row 2 -->
        <circle cx="334" cy="218" r="11" fill="url(#vesGrad2)" stroke="#ca8a04" stroke-width="1" opacity="0.7"/>
        <circle cx="368" cy="212" r="10" fill="url(#vesGrad2)" stroke="#ca8a04" stroke-width="1" opacity="0.7"/>
        <circle cx="402" cy="215" r="12" fill="url(#vesGrad2)" stroke="#ca8a04" stroke-width="1" opacity="0.7"/>
        <circle cx="436" cy="212" r="10" fill="url(#vesGrad2)" stroke="#ca8a04" stroke-width="1" opacity="0.7"/>
        <circle cx="464" cy="220" r="9" fill="url(#vesGrad2)" stroke="#ca8a04" stroke-width="1" opacity="0.7"/>
        <!-- Row 3 -->
        <circle cx="350" cy="183" r="9" fill="url(#vesGrad2)" stroke="#ca8a04" stroke-width="1" opacity="0.4"/>
        <circle cx="390" cy="178" r="10" fill="url(#vesGrad2)" stroke="#ca8a04" stroke-width="1" opacity="0.4"/>
        <circle cx="425" cy="180" r="9" fill="url(#vesGrad2)" stroke="#ca8a04" stroke-width="1" opacity="0.4"/>
      </g>

      <!-- ACh dots inside vesicles (tiny) -->
      <circle cx="320" cy="248" r="4" fill="#fef9c3" opacity="0.6"/>
      <circle cx="352" cy="244" r="4" fill="#fef9c3" opacity="0.6"/>
      <circle cx="384" cy="250" r="4" fill="#fef9c3" opacity="0.6"/>
      <circle cx="418" cy="245" r="4" fill="#fef9c3" opacity="0.6"/>
      <circle cx="450" cy="248" r="4" fill="#fef9c3" opacity="0.6"/>

      <!-- ===== SYNAPTIC CLEFT ===== -->
      <rect x="275" y="286" width="230" height="50" rx="0" fill="#0f172a" opacity="0.5"/>
      <!-- Cleft border lines -->
      <line x1="275" y1="286" x2="505" y2="286" stroke="#475569" stroke-width="1" stroke-dasharray="3,3"/>
      <line x1="275" y1="336" x2="505" y2="336" stroke="#475569" stroke-width="1" stroke-dasharray="3,3"/>
      <!-- Synaptic cleft label space -->

      <!-- ===== BASAL LAMINA ===== -->
      <!-- Thin line through cleft center -->
      <path d="M275 311 Q330 308 390 311 Q450 314 505 311" stroke="#78716c" stroke-width="2.5" fill="none" stroke-dasharray="6,3"/>

      <!-- AChE enzymes on basal lamina -->
      <g id="ache-enzymes">
        <g transform="translate(298,308)"><rect x="-6" y="-5" width="12" height="10" rx="3" fill="#7c2d12" stroke="#ea580c" stroke-width="1.2"/><text x="0" y="3" text-anchor="middle" font-size="7" fill="#fed7aa">AChE</text></g>
        <g transform="translate(344,311)"><rect x="-6" y="-5" width="12" height="10" rx="3" fill="#7c2d12" stroke="#ea580c" stroke-width="1.2"/><text x="0" y="3" text-anchor="middle" font-size="7" fill="#fed7aa">AChE</text></g>
        <g transform="translate(390,308)"><rect x="-6" y="-5" width="12" height="10" rx="3" fill="#7c2d12" stroke="#ea580c" stroke-width="1.2"/><text x="0" y="3" text-anchor="middle" font-size="7" fill="#fed7aa">AChE</text></g>
        <g transform="translate(436,311)"><rect x="-6" y="-5" width="12" height="10" rx="3" fill="#7c2d12" stroke="#ea580c" stroke-width="1.2"/><text x="0" y="3" text-anchor="middle" font-size="7" fill="#fed7aa">AChE</text></g>
        <g transform="translate(481,308)"><rect x="-6" y="-5" width="12" height="10" rx="3" fill="#7c2d12" stroke="#ea580c" stroke-width="1.2"/><text x="0" y="3" text-anchor="middle" font-size="7" fill="#fed7aa">AChE</text></g>
      </g>

      <!-- ===== MOTOR END PLATE / SARCOLEMMA ===== -->
      <!-- Main sarcolemma membrane -->
      <path d="M265 336 Q280 336 280 336 L505 336 Q520 336 520 336" stroke="#b45309" stroke-width="3" fill="none"/>
      <!-- Junctional folds -->
      <g id="j-folds">
        <path d="M292 336 L286 372 L298 372 L292 336" fill="#92400e" stroke="#d97706" stroke-width="1.2"/>
        <path d="M330 336 L324 378 L336 378 L330 336" fill="#92400e" stroke="#d97706" stroke-width="1.2"/>
        <path d="M368 336 L362 374 L374 374 L368 336" fill="#92400e" stroke="#d97706" stroke-width="1.2"/>
        <path d="M406 336 L400 376 L412 376 L406 336" fill="#92400e" stroke="#d97706" stroke-width="1.2"/>
        <path d="M444 336 L438 372 L450 372 L444 336" fill="#92400e" stroke="#d97706" stroke-width="1.2"/>
        <path d="M482 336 L476 370 L488 370 L482 336" fill="#92400e" stroke="#d97706" stroke-width="1.2"/>
      </g>

      <!-- ===== Nm RECEPTORS on motor end plate ===== -->
      <g id="nm-receptors">
        <g transform="translate(292,342)"><ellipse rx="8" ry="5" fill="#15803d" stroke="#4ade80" stroke-width="1.3"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="#dcfce7">Nm</text></g>
        <g transform="translate(316,342)"><ellipse rx="8" ry="5" fill="#15803d" stroke="#4ade80" stroke-width="1.3"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="#dcfce7">Nm</text></g>
        <g transform="translate(340,342)"><ellipse rx="8" ry="5" fill="#15803d" stroke="#4ade80" stroke-width="1.3"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="#dcfce7">Nm</text></g>
        <g transform="translate(364,342)"><ellipse rx="8" ry="5" fill="#15803d" stroke="#4ade80" stroke-width="1.3"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="#dcfce7">Nm</text></g>
        <g transform="translate(388,342)"><ellipse rx="8" ry="5" fill="#15803d" stroke="#4ade80" stroke-width="1.3"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="#dcfce7">Nm</text></g>
        <g transform="translate(412,342)"><ellipse rx="8" ry="5" fill="#15803d" stroke="#4ade80" stroke-width="1.3"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="#dcfce7">Nm</text></g>
        <g transform="translate(436,342)"><ellipse rx="8" ry="5" fill="#15803d" stroke="#4ade80" stroke-width="1.3"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="#dcfce7">Nm</text></g>
        <g transform="translate(460,342)"><ellipse rx="8" ry="5" fill="#15803d" stroke="#4ade80" stroke-width="1.3"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="#dcfce7">Nm</text></g>
        <g transform="translate(484,342)"><ellipse rx="8" ry="5" fill="#15803d" stroke="#4ade80" stroke-width="1.3"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="#dcfce7">Nm</text></g>
      </g>

      <!-- ===== VOLTAGE-GATED Na+ CHANNELS ===== -->
      <g id="na-channels">
        <rect x="303" y="349" width="8" height="16" rx="2" fill="#14532d" stroke="#22c55e" stroke-width="1.3"/>
        <rect x="355" y="349" width="8" height="16" rx="2" fill="#14532d" stroke="#22c55e" stroke-width="1.3"/>
        <rect x="407" y="349" width="8" height="16" rx="2" fill="#14532d" stroke="#22c55e" stroke-width="1.3"/>
        <rect x="459" y="349" width="8" height="16" rx="2" fill="#14532d" stroke="#22c55e" stroke-width="1.3"/>
      </g>

      <!-- ===== SKELETAL MUSCLE FIBER ===== -->
      <!-- Sarcoplasm background -->
      <rect x="265" y="336" width="260" height="155" fill="#450a0a" opacity="0.6"/>
      <!-- Myofibril striations -->
      <g opacity="0.3">
        <line x1="265" y1="395" x2="525" y2="395" stroke="#f87171" stroke-width="1.5"/>
        <line x1="265" y1="418" x2="525" y2="418" stroke="#fca5a5" stroke-width="0.8"/>
        <line x1="265" y1="430" x2="525" y2="430" stroke="#f87171" stroke-width="1.5"/>
        <line x1="265" y1="453" x2="525" y2="453" stroke="#fca5a5" stroke-width="0.8"/>
        <line x1="265" y1="465" x2="525" y2="465" stroke="#f87171" stroke-width="1.5"/>
        <line x1="265" y1="488" x2="525" y2="488" stroke="#fca5a5" stroke-width="0.8"/>
      </g>
      <!-- Muscle fiber border -->
      <rect x="265" y="336" width="260" height="155" fill="none" stroke="#b45309" stroke-width="2"/>

      <!-- T-tubules -->
      <line x1="340" y1="336" x2="340" y2="491" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="4,4" opacity="0.4"/>
      <line x1="450" y1="336" x2="450" y2="491" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="4,4" opacity="0.4"/>
      <text x="342" y="480" font-size="8" fill="#f59e0b" opacity="0.5">T-tubule</text>
      <text x="452" y="480" font-size="8" fill="#f59e0b" opacity="0.5">T-tubule</text>

      <!-- Nucleus -->
      <ellipse cx="395" cy="470" rx="28" ry="14" fill="#1d4ed8" opacity="0.4" stroke="#3b82f6" stroke-width="1"/>
      <text x="395" y="474" text-anchor="middle" font-size="8" fill="#bfdbfe">Nucleus</text>

      <!-- ===== INTERACTIVE HIT ZONES ===== -->
      <!-- Motor neuron axon -->
      <rect class="struct-hit" id="hit-axon" x="75" y="80" width="270" height="50" rx="15"
        data-name="Motor Neuron Axon"
        data-desc="A myelinated nerve fiber carrying electrical impulses (action potentials) from the motor neuron cell body in the spinal cord to the neuromuscular junction. Myelination speeds conduction via saltatory propagation at nodes of Ranvier."/>
      <!-- Axon terminal -->
      <ellipse class="struct-hit" id="hit-terminal" cx="390" cy="200" rx="115" ry="80"
        data-name="Axon Terminal (Synaptic Bouton)"
        data-desc="The expanded distal end of the motor neuron. Contains mitochondria (energy for ACh synthesis), synaptic vesicles loaded with ACh, and voltage-gated Ca²⁺ channels. Depolarization triggers exocytosis of ACh."/>
      <!-- Synaptic vesicles -->
      <ellipse class="struct-hit" id="hit-vesicles" cx="390" cy="230" rx="90" ry="50"
        data-name="Synaptic Vesicles (ACh)"
        data-desc="Membrane-bound spheres (~40 nm) storing acetylcholine. Each vesicle contains ~10,000 ACh molecules. Ca²⁺-triggered SNARE protein interactions cause vesicle fusion with the presynaptic membrane and quantal release of ACh into the cleft."/>
      <!-- Ca channels -->
      <rect class="struct-hit" id="hit-cachannels" x="300" y="258" width="165" height="34"
        data-name="Voltage-Gated Ca²⁺ Channels"
        data-desc="Clustered at active zones on the presynaptic membrane. Depolarization opens these channels, allowing Ca²⁺ to flood in (driven by the steep electrochemical gradient). The rise in intracellular Ca²⁺ activates synaptotagmin, triggering vesicle fusion and ACh release."/>
      <!-- Synaptic cleft -->
      <rect class="struct-hit" id="hit-cleft" x="275" y="286" width="230" height="50"
        data-name="Synaptic Cleft"
        data-desc="A 50-100 nm gap between the presynaptic axon terminal and the postsynaptic motor end plate. ACh diffuses across this space. The basal lamina traversing the cleft anchors AChE, which rapidly terminates signaling by hydrolyzing ACh."/>
      <!-- Basal lamina -->
      <rect class="struct-hit" id="hit-basal" x="275" y="300" width="230" height="24"
        data-name="Basal Lamina + AChE"
        data-desc="Extracellular matrix sheet traversing the synaptic cleft. Anchors acetylcholinesterase (AChE), which cleaves ACh into acetate and choline within microseconds, terminating the signal. Choline is recycled into the nerve terminal via high-affinity choline transporters (CHT1)."/>
      <!-- Sarcolemma/end plate -->
      <rect class="struct-hit" id="hit-sarco" x="265" y="328" width="260" height="20"
        data-name="Motor End Plate (Sarcolemma)"
        data-desc="The specialized region of the muscle fiber membrane apposed to the axon terminal. It is thrown into junctional folds that increase surface area, hosts dense clusters of nicotinic Nm receptors, and contains voltage-gated Na⁺ channels that generate the muscle action potential."/>
      <!-- Junctional folds -->
      <rect class="struct-hit" id="hit-folds" x="275" y="336" width="240" height="50"
        data-name="Junctional Folds"
        data-desc="Deep invaginations of the sarcolemma at the end plate. They increase the membrane surface area up to 10-fold, concentrating Nm receptors at their crests. Voltage-gated Na⁺ channels are concentrated at the depths of the folds, amplifying the end-plate potential into a full muscle action potential."/>
      <!-- Nm receptors -->
      <rect class="struct-hit" id="hit-nmr" x="275" y="336" width="225" height="16"
        data-name="Nicotinic (Nm) Acetylcholine Receptors"
        data-desc="Pentameric ligand-gated ion channels (α2βγδ or α2βεδ) at the postsynaptic membrane. Each receptor requires binding of 2 ACh molecules to open its central cation pore, permitting Na⁺ influx and K⁺ efflux. The net inward current generates the end-plate potential (EPP)."/>
      <!-- Na channels -->
      <rect class="struct-hit" id="hit-nachannels" x="295" y="349" width="175" height="20"
        data-name="Voltage-Gated Na⁺ Channels"
        data-desc="Nav1.4 channels concentrated at the depths of junctional folds. When the EPP depolarizes the adjacent sarcolemma to threshold (~-55 mV), these channels open, generating an all-or-none muscle action potential that propagates along the sarcolemma and down T-tubules to trigger excitation-contraction coupling."/>
      <!-- Muscle fiber -->
      <rect class="struct-hit" id="hit-muscle" x="265" y="380" width="260" height="110"
        data-name="Skeletal Muscle Fiber"
        data-desc="A multinucleated syncytium containing ordered myofibrils with thick (myosin) and thin (actin) filaments producing the characteristic striated pattern. The action potential propagating along its sarcolemma and into T-tubules triggers Ca²⁺ release from the sarcoplasmic reticulum, initiating the cross-bridge cycle and muscle contraction."/>

      <!-- ===== STATIC LABELS (visible by default) ===== -->
      <g id="labels-layer">
        <!-- Axon label -->
        <line x1="160" y1="80" x2="160" y2="55" stroke="#94a3b8" stroke-width="0.8"/>
        <rect x="110" y="40" width="100" height="16" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="160" y="51" text-anchor="middle" class="nmj-label">Motor Neuron Axon</text>

        <!-- Myelin label -->
        <line x1="108" y1="105" x2="80" y2="130" stroke="#94a3b8" stroke-width="0.8"/>
        <rect x="16" y="128" width="68" height="16" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="50" y="139" text-anchor="middle" class="nmj-label">Myelin Sheath</text>

        <!-- Terminal label -->
        <line x1="390" y1="125" x2="390" y2="100" stroke="#94a3b8" stroke-width="0.8"/>
        <rect x="310" y="84" width="160" height="16" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="390" y="95" text-anchor="middle" class="nmj-label">Axon Terminal (Synaptic Bouton)</text>

        <!-- Vesicle label -->
        <line x1="480" y1="245" x2="560" y2="230" stroke="#94a3b8" stroke-width="0.8"/>
        <rect x="555" y="220" width="100" height="30" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="605" y="233" text-anchor="middle" class="nmj-label">Synaptic Vesicles</text>
        <text x="605" y="244" text-anchor="middle" class="nmj-label" fill="#eab308">(ACh)</text>

        <!-- Ca channel label -->
        <line x1="462" y1="278" x2="540" y2="268" stroke="#3b82f6" stroke-width="0.8"/>
        <rect x="535" y="258" width="115" height="30" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="592" y="271" text-anchor="middle" class="nmj-label" fill="#60a5fa">VG Ca²⁺ Channels</text>
        <text x="592" y="282" text-anchor="middle" class="nmj-label" fill="#60a5fa">(Presynaptic)</text>

        <!-- Cleft label -->
        <line x1="270" y1="311" x2="210" y2="311" stroke="#94a3b8" stroke-width="0.8"/>
        <rect x="110" y="303" width="102" height="16" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="161" y="314" text-anchor="middle" class="nmj-label">Synaptic Cleft</text>

        <!-- Basal lamina / AChE label -->
        <line x1="270" y1="309" x2="210" y2="290" stroke="#94a3b8" stroke-width="0.8"/>
        <rect x="92" y="278" width="120" height="16" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="152" y="289" text-anchor="middle" class="nmj-label">Basal Lamina + AChE</text>

        <!-- Sarcolemma / End plate label -->
        <line x1="270" y1="337" x2="210" y2="352" stroke="#94a3b8" stroke-width="0.8"/>
        <rect x="98" y="344" width="115" height="16" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="155" y="355" text-anchor="middle" class="nmj-label">Motor End Plate</text>

        <!-- Junctional folds label -->
        <line x1="270" y1="360" x2="210" y2="374" stroke="#94a3b8" stroke-width="0.8"/>
        <rect x="104" y="366" width="108" height="16" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="158" y="377" text-anchor="middle" class="nmj-label">Junctional Folds</text>

        <!-- Nm receptor label -->
        <line x1="500" y1="342" x2="560" y2="342" stroke="#4ade80" stroke-width="0.8"/>
        <rect x="555" y="333" width="125" height="30" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="617" y="346" text-anchor="middle" class="nmj-label" fill="#4ade80">Nm ACh Receptors</text>
        <text x="617" y="357" text-anchor="middle" class="nmj-label" fill="#4ade80">(Postsynaptic)</text>

        <!-- Na channel label -->
        <line x1="500" y1="358" x2="560" y2="370" stroke="#22c55e" stroke-width="0.8"/>
        <rect x="555" y="362" width="120" height="30" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="615" y="375" text-anchor="middle" class="nmj-label" fill="#22c55e">VG Na⁺ Channels</text>
        <text x="615" y="386" text-anchor="middle" class="nmj-label" fill="#22c55e">(Sarcolemma)</text>

        <!-- Muscle fiber label -->
        <line x1="270" y1="430" x2="210" y2="430" stroke="#94a3b8" stroke-width="0.8"/>
        <rect x="98" y="422" width="115" height="16" rx="3" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="0.8"/>
        <text x="155" y="433" text-anchor="middle" class="nmj-label">Skeletal Muscle Fiber</text>
      </g>

      <!-- ===== ANIMATION LAYERS ===== -->
      <g id="anim-layer" class="anim-layer">

        <!-- Step 1: Action potential wave along axon -->
        <g id="anim-step1" class="hidden">
          <path id="ap-wave" d="M75 105 Q120 75 160 105 Q200 135 240 105 Q280 75 305 105"
            stroke="#f59e0b" stroke-width="3" fill="none"
            stroke-dasharray="200" stroke-dashoffset="200"
            filter="url(#glow)"
            style="animation: apulse 1.5s ease forwards;"/>
          <text x="180" y="72" text-anchor="middle" font-size="11" fill="#f59e0b" filter="url(#softglow)" style="animation: fade-in 0.5s 0.5s both">Action Potential →</text>
        </g>

        <!-- Step 2: Ca2+ ions entering -->
        <g id="anim-step2" class="hidden">
          <!-- Open Ca channel highlight -->
          <rect x="306" y="264" width="14" height="24" rx="2" fill="#1d4ed8" stroke="#60a5fa" stroke-width="2" filter="url(#softglow)"/>
          <rect x="354" y="266" width="14" height="24" rx="2" fill="#1d4ed8" stroke="#60a5fa" stroke-width="2" filter="url(#softglow)"/>
          <rect x="402" y="266" width="14" height="24" rx="2" fill="#1d4ed8" stroke="#60a5fa" stroke-width="2" filter="url(#softglow)"/>
          <rect x="450" y="264" width="14" height="24" rx="2" fill="#1d4ed8" stroke="#60a5fa" stroke-width="2" filter="url(#softglow)"/>
          <!-- Ca2+ ions entering (animated down) -->
          <circle cx="313" cy="260" r="5" fill="#3b82f6" stroke="#93c5fd" stroke-width="1" filter="url(#softglow)" style="animation: caflowin 1s 0.2s both;"/>
          <text x="313" y="264" text-anchor="middle" font-size="5" fill="white">Ca</text>
          <circle cx="361" cy="258" r="5" fill="#3b82f6" stroke="#93c5fd" stroke-width="1" filter="url(#softglow)" style="animation: caflowin 1s 0.4s both;"/>
          <text x="361" y="262" text-anchor="middle" font-size="5" fill="white">Ca</text>
          <circle cx="409" cy="260" r="5" fill="#3b82f6" stroke="#93c5fd" stroke-width="1" filter="url(#softglow)" style="animation: caflowin 1s 0.3s both;"/>
          <text x="409" y="264" text-anchor="middle" font-size="5" fill="white">Ca</text>
          <circle cx="457" cy="258" r="5" fill="#3b82f6" stroke="#93c5fd" stroke-width="1" filter="url(#softglow)" style="animation: caflowin 1s 0.5s both;"/>
          <text x="457" y="262" text-anchor="middle" font-size="5" fill="white">Ca</text>
          <text x="390" y="165" text-anchor="middle" font-size="10" fill="#60a5fa" style="animation: fade-in 0.3s both">Ca²⁺ influx</text>
        </g>

        <!-- Step 3: Vesicle fusion & ACh release -->
        <g id="anim-step3" class="hidden">
          <!-- Fusing vesicles -->
          <circle cx="320" cy="278" r="12" fill="#eab308" stroke="#ca8a04" stroke-width="1.5" opacity="0.9" style="animation: vesicle-fuse 0.8s 0.1s both;"/>
          <circle cx="384" cy="280" r="13" fill="#eab308" stroke="#ca8a04" stroke-width="1.5" opacity="0.9" style="animation: vesicle-fuse 0.8s 0.3s both;"/>
          <circle cx="448" cy="278" r="12" fill="#eab308" stroke="#ca8a04" stroke-width="1.5" opacity="0.9" style="animation: vesicle-fuse 0.8s 0.5s both;"/>
          <!-- ACh released dots -->
          <circle cx="315" cy="290" r="4" fill="#eab308" style="animation: ach-diffuse 1s 0.9s both;"/>
          <circle cx="330" cy="295" r="4" fill="#fef08a" style="animation: ach-diffuse 1s 1.0s both;"/>
          <circle cx="370" cy="288" r="4" fill="#eab308" style="animation: ach-diffuse 1s 0.7s both;"/>
          <circle cx="390" cy="292" r="4" fill="#fef08a" style="animation: ach-diffuse 1s 0.8s both;"/>
          <circle cx="420" cy="290" r="4" fill="#eab308" style="animation: ach-diffuse 1s 0.6s both;"/>
          <circle cx="445" cy="294" r="4" fill="#fef08a" style="animation: ach-diffuse 1s 1.1s both;"/>
          <text x="390" y="165" text-anchor="middle" font-size="10" fill="#eab308" style="animation: fade-in 0.5s both">Exocytosis of ACh</text>
        </g>

        <!-- Step 4: ACh diffusing in cleft -->
        <g id="anim-step4" class="hidden">
          <circle cx="310" cy="300" r="5" fill="#eab308" filter="url(#softglow)"><animate attributeName="cy" from="290" to="330" dur="1.2s" fill="freeze"/><animate attributeName="opacity" from="0" to="1" dur="0.3s" fill="freeze"/></circle>
          <circle cx="335" cy="305" r="5" fill="#fef08a" filter="url(#softglow)"><animate attributeName="cy" from="292" to="328" dur="1.0s" fill="freeze"/><animate attributeName="opacity" from="0" to="1" dur="0.3s" fill="freeze"/></circle>
          <circle cx="362" cy="300" r="5" fill="#eab308" filter="url(#softglow)"><animate attributeName="cy" from="288" to="330" dur="1.3s" fill="freeze"/><animate attributeName="opacity" from="0" to="1" dur="0.3s" fill="freeze"/></circle>
          <circle cx="390" cy="302" r="5" fill="#fef08a" filter="url(#softglow)"><animate attributeName="cy" from="290" to="332" dur="1.1s" fill="freeze"/><animate attributeName="opacity" from="0" to="1" dur="0.3s" fill="freeze"/></circle>
          <circle cx="416" cy="300" r="5" fill="#eab308" filter="url(#softglow)"><animate attributeName="cy" from="292" to="330" dur="1.2s" fill="freeze"/><animate attributeName="opacity" from="0" to="1" dur="0.3s" fill="freeze"/></circle>
          <circle cx="444" cy="302" r="5" fill="#fef08a" filter="url(#softglow)"><animate attributeName="cy" from="289" to="331" dur="1.0s" fill="freeze"/><animate attributeName="opacity" from="0" to="1" dur="0.3s" fill="freeze"/></circle>
          <circle cx="470" cy="300" r="5" fill="#eab308" filter="url(#softglow)"><animate attributeName="cy" from="291" to="329" dur="1.3s" fill="freeze"/><animate attributeName="opacity" from="0" to="1" dur="0.3s" fill="freeze"/></circle>
          <text x="390" y="165" text-anchor="middle" font-size="10" fill="#eab308" style="animation:fade-in 0.3s both">ACh diffuses across cleft</text>
        </g>

        <!-- Step 5: ACh binds Nm receptors -->
        <g id="anim-step5" class="hidden">
          <!-- Highlight receptors -->
          <g transform="translate(292,342)"><ellipse rx="10" ry="7" fill="#15803d" stroke="#86efac" stroke-width="2" filter="url(#softglow)"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="white">Nm</text></g>
          <g transform="translate(340,342)"><ellipse rx="10" ry="7" fill="#15803d" stroke="#86efac" stroke-width="2" filter="url(#softglow)"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="white">Nm</text></g>
          <g transform="translate(388,342)"><ellipse rx="10" ry="7" fill="#15803d" stroke="#86efac" stroke-width="2" filter="url(#softglow)"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="white">Nm</text></g>
          <g transform="translate(436,342)"><ellipse rx="10" ry="7" fill="#15803d" stroke="#86efac" stroke-width="2" filter="url(#softglow)"/><text x="0" y="2" text-anchor="middle" font-size="6" fill="white">Nm</text></g>
          <!-- ACh binding dots -->
          <circle cx="292" cy="337" r="4" fill="#eab308" filter="url(#softglow)" style="animation:fade-in 0.3s both"/>
          <circle cx="340" cy="337" r="4" fill="#eab308" filter="url(#softglow)" style="animation:fade-in 0.5s both"/>
          <circle cx="388" cy="337" r="4" fill="#eab308" filter="url(#softglow)" style="animation:fade-in 0.4s both"/>
          <circle cx="436" cy="337" r="4" fill="#eab308" filter="url(#softglow)" style="animation:fade-in 0.6s both"/>
          <text x="390" y="165" text-anchor="middle" font-size="10" fill="#86efac" style="animation:fade-in 0.3s both">ACh binds Nm receptors</text>
        </g>

        <!-- Step 6: Na+ influx - End plate potential -->
        <g id="anim-step6" class="hidden">
          <!-- End plate potential flash -->
          <rect x="265" y="336" width="260" height="40" fill="#22c55e" opacity="0" style="animation: ep-flash 1.5s forwards;"/>
          <!-- Na+ ions entering -->
          <circle cx="307" cy="352" r="5" fill="#22c55e" stroke="#86efac" stroke-width="1" filter="url(#softglow)" style="animation: na-influx 0.8s 0.2s both;"/>
          <text x="307" y="356" text-anchor="middle" font-size="5" fill="white">Na</text>
          <circle cx="359" cy="354" r="5" fill="#22c55e" stroke="#86efac" stroke-width="1" filter="url(#softglow)" style="animation: na-influx 0.8s 0.4s both;"/>
          <text x="359" y="358" text-anchor="middle" font-size="5" fill="white">Na</text>
          <circle cx="411" cy="352" r="5" fill="#22c55e" stroke="#86efac" stroke-width="1" filter="url(#softglow)" style="animation: na-influx 0.8s 0.3s both;"/>
          <text x="411" y="356" text-anchor="middle" font-size="5" fill="white">Na</text>
          <circle cx="463" cy="354" r="5" fill="#22c55e" stroke="#86efac" stroke-width="1" filter="url(#softglow)" style="animation: na-influx 0.8s 0.5s both;"/>
          <text x="463" y="358" text-anchor="middle" font-size="5" fill="white">Na</text>
          <text x="390" y="165" text-anchor="middle" font-size="10" fill="#22c55e" style="animation:fade-in 0.3s both">Na⁺ influx → End Plate Potential</text>
        </g>

        <!-- Step 7: Muscle action potential -->
        <g id="anim-step7" class="hidden">
          <!-- Bright sarcolemma flash -->
          <rect x="265" y="330" width="260" height="12" fill="#22c55e" opacity="0.7" filter="url(#softglow)"/>
          <!-- VG Na+ channels open indicator -->
          <rect x="301" y="347" width="12" height="20" rx="2" fill="#15803d" stroke="#4ade80" stroke-width="2" filter="url(#softglow)"/>
          <rect x="353" y="347" width="12" height="20" rx="2" fill="#15803d" stroke="#4ade80" stroke-width="2" filter="url(#softglow)"/>
          <rect x="405" y="347" width="12" height="20" rx="2" fill="#15803d" stroke="#4ade80" stroke-width="2" filter="url(#softglow)"/>
          <rect x="457" y="347" width="12" height="20" rx="2" fill="#15803d" stroke="#4ade80" stroke-width="2" filter="url(#softglow)"/>
          <text x="390" y="165" text-anchor="middle" font-size="10" fill="#4ade80" style="animation:fade-in 0.3s both">Muscle Action Potential!</text>
        </g>

        <!-- Step 8: AP spreads along sarcolemma + T-tubules -->
        <g id="anim-step8" class="hidden">
          <path d="M265 337 L525 337" stroke="#4ade80" stroke-width="4"
            stroke-dasharray="400" stroke-dashoffset="400" filter="url(#glow)"
            style="animation: ap-spread 1.2s ease forwards;"/>
          <!-- T-tubule propagation -->
          <line x1="340" y1="337" x2="340" y2="491" stroke="#4ade80" stroke-width="2.5"
            stroke-dasharray="200" stroke-dashoffset="200" filter="url(#softglow)"
            style="animation: ap-spread 1s 0.8s ease forwards;"/>
          <line x1="450" y1="337" x2="450" y2="491" stroke="#4ade80" stroke-width="2.5"
            stroke-dasharray="200" stroke-dashoffset="200" filter="url(#softglow)"
            style="animation: ap-spread 1s 1.0s ease forwards;"/>
          <text x="390" y="165" text-anchor="middle" font-size="10" fill="#4ade80" style="animation:fade-in 0.3s both">AP spreads → T-tubules</text>
        </g>

        <!-- Step 9: AChE breakdown -->
        <g id="anim-step9" class="hidden">
          <!-- AChE active flash -->
          <g transform="translate(298,308)"><rect x="-8" y="-6" width="16" height="12" rx="3" fill="#c2410c" stroke="#fb923c" stroke-width="2" filter="url(#softglow)"/><text x="0" y="3" text-anchor="middle" font-size="7" fill="white">AChE</text></g>
          <g transform="translate(344,311)"><rect x="-8" y="-6" width="16" height="12" rx="3" fill="#c2410c" stroke="#fb923c" stroke-width="2" filter="url(#softglow)"/><text x="0" y="3" text-anchor="middle" font-size="7" fill="white">AChE</text></g>
          <g transform="translate(390,308)"><rect x="-8" y="-6" width="16" height="12" rx="3" fill="#c2410c" stroke="#fb923c" stroke-width="2" filter="url(#softglow)"/><text x="0" y="3" text-anchor="middle" font-size="7" fill="white">AChE</text></g>
          <g transform="translate(436,311)"><rect x="-8" y="-6" width="16" height="12" rx="3" fill="#c2410c" stroke="#fb923c" stroke-width="2" filter="url(#softglow)"/><text x="0" y="3" text-anchor="middle" font-size="7" fill="white">AChE</text></g>
          <!-- Acetate products (orange) -->
          <circle cx="305" cy="315" r="3" fill="#f97316" style="animation:fade-in 0.5s both"/><text x="305" cy="315" font-size="6" fill="#fed7aa" y="313">Ac</text>
          <circle cx="355" cy="318" r="3" fill="#f97316" style="animation:fade-in 0.7s both"/><text x="355" font-size="6" fill="#fed7aa" y="316">Ac</text>
          <circle cx="400" cy="315" r="3" fill="#f97316" style="animation:fade-in 0.6s both"/><text x="400" font-size="6" fill="#fed7aa" y="313">Ac</text>
          <!-- Choline products (yellow-green) -->
          <circle cx="320" cy="310" r="3" fill="#a3e635" style="animation:fade-in 0.5s both"/>
          <circle cx="370" cy="313" r="3" fill="#a3e635" style="animation:fade-in 0.7s both"/>
          <circle cx="418" cy="310" r="3" fill="#a3e635" style="animation:fade-in 0.6s both"/>
          <text x="390" y="165" text-anchor="middle" font-size="10" fill="#fb923c" style="animation:fade-in 0.3s both">AChE cleaves ACh → Acetate + Choline</text>
        </g>

        <!-- Step 10: Choline reuptake -->
        <g id="anim-step10" class="hidden">
          <!-- Choline transporter indicator on terminal membrane -->
          <rect x="355" y="274" width="16" height="14" rx="3" fill="#4d7c0f" stroke="#a3e635" stroke-width="1.5" filter="url(#softglow)"/>
          <text x="363" y="283" text-anchor="middle" font-size="6" fill="#d9f99d">CHT1</text>
          <!-- Choline moving up into terminal -->
          <circle id="cho1" cx="320" cy="316" r="4" fill="#a3e635" filter="url(#softglow)"><animate attributeName="cy" from="316" to="278" dur="1.2s" fill="freeze"/><animate attributeName="opacity" from="1" to="0" dur="1.2s" fill="freeze"/></circle>
          <circle id="cho2" cx="360" cy="318" r="4" fill="#a3e635" filter="url(#softglow)"><animate attributeName="cy" from="318" to="278" dur="1.0s" begin="0.2s" fill="freeze"/><animate attributeName="opacity" from="1" to="0" dur="1.0s" begin="0.2s" fill="freeze"/></circle>
          <circle id="cho3" cx="400" cy="315" r="4" fill="#a3e635" filter="url(#softglow)"><animate attributeName="cy" from="315" to="278" dur="1.1s" begin="0.4s" fill="freeze"/><animate attributeName="opacity" from="1" to="0" dur="1.1s" begin="0.4s" fill="freeze"/></circle>
          <text x="390" y="165" text-anchor="middle" font-size="10" fill="#a3e635" style="animation:fade-in 0.3s both">Choline recycled → ACh resynthesis</text>
        </g>

      </g>
      <!-- End animation layer -->

      <!-- Ion color legend -->
      <g transform="translate(12, 455)">
        <rect x="0" y="0" width="115" height="72" rx="5" fill="rgba(15,23,42,0.88)" stroke="#334155" stroke-width="1"/>
        <text x="8" y="14" font-size="9" fill="#94a3b8" font-weight="bold">Ion Color Legend</text>
        <circle cx="14" cy="26" r="5" fill="#3b82f6"/><text x="22" y="30" font-size="9" fill="#93c5fd">Ca²⁺</text>
        <circle cx="14" cy="41" r="5" fill="#22c55e"/><text x="22" y="45" font-size="9" fill="#86efac">Na⁺</text>
        <circle cx="14" cy="56" r="5" fill="#eab308"/><text x="22" y="60" font-size="9" fill="#fef08a">ACh</text>
        <circle cx="66" cy="56" r="5" fill="#a3e635"/><text x="74" y="60" font-size="9" fill="#d9f99d">Choline</text>
      </g>

    </svg>

    <!-- Controls -->
    <div class="controls">
      <button id="btn-prev" onclick="prevStep()" disabled>◀ Prev</button>
      <button id="btn-playpause" onclick="togglePlay()">▶ Play</button>
      <button id="btn-next" onclick="nextStep()">Next ▶</button>
      <button id="btn-reset" onclick="resetAnim()">↺ Reset</button>
      <button id="btn-labels" onclick="toggleLabels()" class="active">Labels ON</button>
      <span id="step-counter">Step 0 / 10</span>
    </div>
    <div class="step-bar" id="step-bar"></div>
  </div>

  <!-- Right Panel -->
  <div class="right-panel">
    <div class="panel-section">
      <h3>Animation Step</h3>
      <div id="step-title">Ready</div>
      <div id="step-desc">Click <strong>Play</strong> or use <strong>Next</strong> to step through neuromuscular transmission. Hover over any structure in the diagram to see its function.</div>
    </div>

    <div class="panel-section">
      <h3>Structure Info (Hover)</h3>
      <div id="hover-box">
        <div id="hover-name">Hover over a structure...</div>
        <div id="hover-desc">Point to any highlighted region in the diagram to learn about its function at the NMJ.</div>
      </div>
    </div>

    <div class="panel-section">
      <h3>Ion Color Code</h3>
      <div class="legend-row"><div class="legend-dot" style="background:#3b82f6"></div>Ca²⁺ - Triggers vesicle fusion</div>
      <div class="legend-row"><div class="legend-dot" style="background:#22c55e"></div>Na⁺ - Generates action potential</div>
      <div class="legend-row"><div class="legend-dot" style="background:#eab308"></div>ACh - Neurotransmitter</div>
      <div class="legend-row"><div class="legend-dot" style="background:#a3e635"></div>Choline - Recycled precursor</div>
      <div class="legend-row"><div class="legend-dot" style="background:#f97316"></div>Acetate - ACh breakdown product</div>
    </div>

    <div class="panel-section summary-panel">
      <h3>Summary: Excitation at the NMJ</h3>
      <p>The neuromuscular junction is a specialized chemical synapse where a motor neuron commands a skeletal muscle fiber to contract. Transmission is mediated by acetylcholine (ACh) and involves a precise sequence of electrical and chemical events.</p>
      <p>The safety factor of the NMJ is high - a single nerve impulse releases far more ACh than needed to reach threshold, ensuring reliable muscle activation.</p>
      <h3 style="margin-top:10px">Learning Objectives</h3>
      <ul class="obj-list">
        <li>Identify all anatomical components of the NMJ and their spatial relationships</li>
        <li>Explain how an action potential in the motor nerve leads to Ca²⁺-mediated ACh release</li>
        <li>Describe how ACh generates an end-plate potential via Nm receptor activation</li>
        <li>Distinguish the EPP from a muscle action potential and explain how threshold is reached</li>
        <li>Explain how AChE terminates synaptic transmission and how choline is recycled</li>
        <li>Recognize clinical relevance: myasthenia gravis (anti-Nm antibodies), organophosphate poisoning (AChE inhibition), curare (Nm blockade), botulinum toxin (vesicle fusion blockade)</li>
      </ul>
    </div>
  </div>
</div>

<!-- Tooltip -->
<div id="tooltip"></div>

<script>
// === STEP DATA ===
const steps = [
  { title: "Ready", desc: "Resting state. The motor neuron membrane potential is ~-70 mV. Synaptic vesicles are loaded with ACh and docked at the active zone. Ca²⁺ channels are closed." },
  { title: "Step 1: Action Potential Arrives", desc: "An action potential (AP) generated at the motor neuron soma propagates along the myelinated axon via saltatory conduction at nodes of Ranvier. It reaches the axon terminal, depolarizing it to ~+40 mV." },
  { title: "Step 2: Ca²⁺ Channels Open", desc: "Depolarization of the axon terminal opens voltage-gated Ca²⁺ channels. Ca²⁺ rushes in down its steep electrochemical gradient (extracellular [Ca²⁺] ~2 mM vs. intracellular ~100 nM). Intraterminal Ca²⁺ rises 100-fold." },
  { title: "Step 3: Vesicle Fusion & ACh Release", desc: "Ca²⁺ binds synaptotagmin on docked synaptic vesicles. This activates SNARE proteins (synaptobrevin, syntaxin, SNAP-25), causing vesicle fusion with the presynaptic membrane. Each vesicle releases ~10,000 ACh molecules into the cleft (quantal release)." },
  { title: "Step 4: ACh Diffuses Across Cleft", desc: "ACh molecules diffuse freely across the 50-100 nm synaptic cleft within microseconds. The short distance ensures rapid and efficient ligand-receptor contact. Some ACh is immediately hydrolyzed by AChE in the basal lamina." },
  { title: "Step 5: ACh Binds Nm Receptors", desc: "ACh binds to nicotinic muscular (Nm) receptors on the motor end plate. Each receptor requires 2 ACh molecules to bind (at α-subunits) before its central ion channel opens. ~500 receptors open per vesicle released." },
  { title: "Step 6: Na⁺ Influx → End-Plate Potential", desc: "Opened Nm receptors permit Na⁺ influx (and K⁺ efflux). The net inward cation current depolarizes the end-plate membrane, generating an end-plate potential (EPP) of ~70 mV amplitude. The EPP is graded, not all-or-none." },
  { title: "Step 7: Muscle Action Potential Fires", desc: "The EPP depolarizes adjacent sarcolemma to threshold (~-55 mV). Voltage-gated Nav1.4 channels (concentrated in junctional fold depths) open, generating an all-or-none muscle action potential (+30 mV peak). This is the point of no return." },
  { title: "Step 8: AP Spreads Along Sarcolemma & T-Tubules", desc: "The muscle AP propagates in both directions along the sarcolemma. It dips into T-tubules, reaching the triads where it activates DHPR (Cav1.1) receptors. These mechanically gate RyR1 receptors on the sarcoplasmic reticulum, releasing Ca²⁺ → contraction." },
  { title: "Step 9: AChE Cleaves ACh", desc: "Acetylcholinesterase (AChE), anchored to the basal lamina via ColQ protein, hydrolyzes ACh into acetate and choline at a rate of ~25,000 molecules/second per enzyme. ACh is cleared from the cleft within ~1 ms, terminating receptor activation." },
  { title: "Step 10: Choline Reuptake & ACh Resynthesis", desc: "Choline (but not acetate) is taken back into the axon terminal via high-affinity choline transporter 1 (CHT1). Inside, choline acetyltransferase (ChAT) recombines choline with acetyl-CoA (from mitochondria) to regenerate ACh, which is then repackaged into vesicles by VAChT." }
];

let currentStep = 0;
let isPlaying = false;
let playInterval = null;
let labelsVisible = true;

// Build step dots
const bar = document.getElementById('step-bar');
for (let i = 0; i <= 10; i++) {
  const d = document.createElement('div');
  d.className = 'step-dot';
  d.title = steps[i] ? steps[i].title : '';
  d.onclick = () => goToStep(i);
  bar.appendChild(d);
}

function updateUI() {
  const s = steps[currentStep];
  document.getElementById('step-title').textContent = s.title;
  document.getElementById('step-desc').innerHTML = s.desc;
  document.getElementById('step-counter').textContent = `Step ${currentStep} / 10`;
  document.getElementById('btn-prev').disabled = currentStep === 0;
  document.getElementById('btn-next').disabled = currentStep === 10;

  // Update dots
  document.querySelectorAll('.step-dot').forEach((d, i) => {
    d.classList.remove('active', 'done');
    if (i === currentStep) d.classList.add('active');
    else if (i < currentStep) d.classList.add('done');
  });
}

function showAnimStep(step) {
  // Hide all animation groups first
  for (let i = 1; i <= 10; i++) {
    const el = document.getElementById('anim-step' + i);
    if (el) el.classList.add('hidden');
  }
  if (step > 0) {
    const el = document.getElementById('anim-step' + step);
    if (el) {
      el.classList.remove('hidden');
      // Force reflow to restart CSS animations
      el.querySelectorAll('[style*="animation"]').forEach(a => {
        const s = a.style.animation;
        a.style.animation = 'none';
        a.getBoundingClientRect();
        a.style.animation = s;
      });
      // Restart SVG animate elements
      el.querySelectorAll('animate').forEach(a => {
        try { a.beginElement(); } catch(e) {}
      });
    }
  }
}

function goToStep(step) {
  currentStep = Math.max(0, Math.min(10, step));
  showAnimStep(currentStep);
  updateUI();
}

function nextStep() {
  if (currentStep < 10) goToStep(currentStep + 1);
  else stopPlay();
}

function prevStep() {
  if (currentStep > 0) goToStep(currentStep - 1);
}

function resetAnim() {
  stopPlay();
  goToStep(0);
}

function togglePlay() {
  if (isPlaying) stopPlay();
  else startPlay();
}

function startPlay() {
  if (currentStep >= 10) goToStep(0);
  isPlaying = true;
  document.getElementById('btn-playpause').textContent = '⏸ Pause';
  document.getElementById('btn-playpause').classList.add('active');
  playInterval = setInterval(() => {
    if (currentStep < 10) {
      nextStep();
    } else {
      stopPlay();
    }
  }, 2800);
}

function stopPlay() {
  isPlaying = false;
  clearInterval(playInterval);
  document.getElementById('btn-playpause').textContent = '▶ Play';
  document.getElementById('btn-playpause').classList.remove('active');
}

function toggleLabels() {
  labelsVisible = !labelsVisible;
  const layer = document.getElementById('labels-layer');
  layer.style.display = labelsVisible ? '' : 'none';
  const btn = document.getElementById('btn-labels');
  btn.textContent = labelsVisible ? 'Labels ON' : 'Labels OFF';
  btn.classList.toggle('active', labelsVisible);
}

// === HOVER TOOLTIPS ===
const tooltip = document.getElementById('tooltip');
const hoverName = document.getElementById('hover-name');
const hoverDesc = document.getElementById('hover-desc');

document.querySelectorAll('.struct-hit').forEach(el => {
  el.addEventListener('mouseenter', function(e) {
    const name = this.dataset.name;
    const desc = this.dataset.desc;
    hoverName.textContent = name;
    hoverDesc.textContent = desc;
    tooltip.innerHTML = `<strong>${name}</strong>${desc}`;
    tooltip.style.display = 'block';
    this.classList.add('highlighted');
  });
  el.addEventListener('mousemove', function(e) {
    const x = e.clientX + 14;
    const y = e.clientY - 10;
    const tw = tooltip.offsetWidth;
    const th = tooltip.offsetHeight;
    tooltip.style.left = (x + tw > window.innerWidth ? e.clientX - tw - 14 : x) + 'px';
    tooltip.style.top = (y + th > window.innerHeight ? e.clientY - th - 10 : y) + 'px';
  });
  el.addEventListener('mouseleave', function() {
    tooltip.style.display = 'none';
    this.classList.remove('highlighted');
    hoverName.textContent = 'Hover over a structure...';
    hoverDesc.textContent = 'Point to any highlighted region in the diagram to learn about its function at the NMJ.';
  });
});

// Initialize
updateUI();
</script>
</body>
</html>
Running Command

ls -lh /tmp/workspace/nmj-diagram/ && wc -l /tmp/workspace/nmj-diagram/nmj_interactive.html

Your interactive NMJ diagram is ready to download and open in any browser:

nmj interactive

HTML File · HTML


What's inside (979 lines of HTML/SVG/CSS/JS)

Anatomy - All 11 structures drawn and labeled:

StructureVisual
Motor Neuron AxonPurple myelinated tube with nodes of Ranvier
Axon Terminal (Synaptic Bouton)Large dark-purple ellipse
Synaptic Vesicles (ACh)Yellow gradient spheres in 3 depth rows
VG Ca²⁺ ChannelsBlue rectangles on terminal base
Synaptic CleftLabeled gap with dimension context
Basal Lamina + AChEDashed line with orange AChE enzyme badges
Motor End Plate (Sarcolemma)Amber membrane line
Junctional FoldsBrown invaginations with depth
Nm ACh ReceptorsGreen ellipses at crest of folds
VG Na⁺ ChannelsGreen rectangles in fold depths
Skeletal Muscle FiberRed striated sarcoplasm with T-tubules and nucleus

10-Step Animation Sequence:

  1. Action potential wave propagates along axon (gold dash animation)
  2. Ca²⁺ channels open - blue ions appear
  3. Vesicle fusion - yellow vesicles burst and release ACh
  4. ACh dots drift across the cleft (SMIL <animate>)
  5. ACh binds Nm receptors - glowing highlights
  6. Na⁺ influx - green flash with end-plate potential indicator
  7. Muscle action potential fires - sarcolemma lights up
  8. AP spreads along sarcolemma and down T-tubules
  9. AChE cleaves ACh into acetate (orange) + choline (lime)
  10. Choline reuptake via CHT1 back into terminal

Interactive Features:

  • Hover over any structure - side panel updates with the full physiological description
  • Floating tooltip follows the cursor with structure name + function
  • Next / Prev buttons for step-by-step control
  • Play / Pause auto-advances every 2.8 seconds
  • Reset returns to resting state
  • Toggle Labels hides/shows all SVG callout labels
  • Step progress bar - clickable dots, color-coded (done = green, current = purple)
  • Ion color legend embedded in the diagram and the side panel
  • Summary panel + 6 learning objectives including clinical correlates (myasthenia gravis, organophosphates, curare, botulinum toxin)
This is a shared conversation. Sign in to Orris to start your own chat.