# Diagrams and math

> Chart.js charts, KaTeX formulas and Mermaid diagrams in detail - chart and diagram types, math typesetting and the self-hosted, on-demand loading.

_Source: https://theme.docs.tbsch.de/post/2026-02-09-diagrams-and-math/ · As of: 2026-02-09_


*Chart.js* (charts), *KaTeX* (math) and *Mermaid* (diagrams) are **self-hosted**
and only loaded when the respective shortcode appears on the page - no
unnecessary JavaScript on pages without them. The
[shortcodes post](/post/2026-01-26-shortcodes/) introduces them in
brief; here we go into depth. Every example has two tabs: **Example** shows the
result, **Code** the source.

## Charts: the basics

The `chart` shortcode renders a canvas with
[*Chart.js*](https://www.chartjs.org/). The inner content is the chart's
**config as JSON** (`type` + `data`); an optional `title` sets the canvas'
accessible label. Axis, grid and text colours bind to the theme tokens and
**re-theme live** when you toggle dark mode; series without a colour of their own
are filled from the site's accent palette.

### Line chart

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-1-tab-0" aria-controls="tabs-1-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-1-tab-1" aria-controls="tabs-1-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-1-panel-0" aria-labelledby="tabs-1-tab-0" data-tab-index="0"><figure class="tb-chart" style="height:22rem">
  <canvas role="img" aria-label="Sessions per weekday"></canvas>
  <script type="application/json">
{
  "type": "line",
  "data": {
    "labels": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
    "datasets": [
      { "label": "Desktop", "data": [120, 132, 101, 134, 90, 60, 70], "tension": 0.35 },
      { "label": "Mobile",  "data": [220, 182, 191, 234, 210, 150, 160], "tension": 0.35 }
    ]
  }
}
</script>
</figure></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-1-panel-1" aria-labelledby="tabs-1-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;line&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;labels&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;Mon&#34;</span><span class="p">,</span> <span class="s2">&#34;Tue&#34;</span><span class="p">,</span> <span class="s2">&#34;Wed&#34;</span><span class="p">,</span> <span class="s2">&#34;Thu&#34;</span><span class="p">,</span> <span class="s2">&#34;Fri&#34;</span><span class="p">,</span> <span class="s2">&#34;Sat&#34;</span><span class="p">,</span> <span class="s2">&#34;Sun&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;datasets&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span> <span class="nt">&#34;label&#34;</span><span class="p">:</span> <span class="s2">&#34;Desktop&#34;</span><span class="p">,</span> <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mi">120</span><span class="p">,</span> <span class="mi">132</span><span class="p">,</span> <span class="mi">101</span><span class="p">,</span> <span class="mi">134</span><span class="p">,</span> <span class="mi">90</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="mi">70</span><span class="p">],</span> <span class="nt">&#34;tension&#34;</span><span class="p">:</span> <span class="mf">0.35</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span> <span class="nt">&#34;label&#34;</span><span class="p">:</span> <span class="s2">&#34;Mobile&#34;</span><span class="p">,</span>  <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mi">220</span><span class="p">,</span> <span class="mi">182</span><span class="p">,</span> <span class="mi">191</span><span class="p">,</span> <span class="mi">234</span><span class="p">,</span> <span class="mi">210</span><span class="p">,</span> <span class="mi">150</span><span class="p">,</span> <span class="mi">160</span><span class="p">],</span> <span class="nt">&#34;tension&#34;</span><span class="p">:</span> <span class="mf">0.35</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></div></div>
</div>


### Bar chart

Two datasets render as grouped bars; a legend is added automatically.

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-2-tab-0" aria-controls="tabs-2-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-2-tab-1" aria-controls="tabs-2-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-2-panel-0" aria-labelledby="tabs-2-tab-0" data-tab-index="0"><figure class="tb-chart" style="height:22rem">
  <canvas role="img" aria-label="Posts per quarter"></canvas>
  <script type="application/json">
{
  "type": "bar",
  "data": {
    "labels": ["Q1", "Q2", "Q3", "Q4"],
    "datasets": [
      { "label": "2025", "data": [42, 55, 48, 61] },
      { "label": "2026", "data": [51, 63, 59, 74] }
    ]
  }
}
</script>
</figure></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-2-panel-1" aria-labelledby="tabs-2-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;bar&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;labels&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;Q1&#34;</span><span class="p">,</span> <span class="s2">&#34;Q2&#34;</span><span class="p">,</span> <span class="s2">&#34;Q3&#34;</span><span class="p">,</span> <span class="s2">&#34;Q4&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;datasets&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span> <span class="nt">&#34;label&#34;</span><span class="p">:</span> <span class="s2">&#34;2025&#34;</span><span class="p">,</span> <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mi">42</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">48</span><span class="p">,</span> <span class="mi">61</span><span class="p">]</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span> <span class="nt">&#34;label&#34;</span><span class="p">:</span> <span class="s2">&#34;2026&#34;</span><span class="p">,</span> <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mi">51</span><span class="p">,</span> <span class="mi">63</span><span class="p">,</span> <span class="mi">59</span><span class="p">,</span> <span class="mi">74</span><span class="p">]</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></div></div>
</div>


### Doughnut chart

For a single series of proportions, give the dataset an explicit
`backgroundColor` array so each slice gets its own colour.

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-3-tab-0" aria-controls="tabs-3-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-3-tab-1" aria-controls="tabs-3-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-3-panel-0" aria-labelledby="tabs-3-tab-0" data-tab-index="0"><figure class="tb-chart" style="height:20rem">
  <canvas role="img" aria-label="Traffic sources"></canvas>
  <script type="application/json">
{
  "type": "doughnut",
  "data": {
    "labels": ["Organic", "Direct", "Social", "Referral"],
    "datasets": [
      { "data": [58, 22, 12, 8], "backgroundColor": ["#ff5d8f", "#f59e0b", "#8b5cf6", "#12a594"] }
    ]
  }
}
</script>
</figure></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-3-panel-1" aria-labelledby="tabs-3-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;doughnut&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;labels&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;Organic&#34;</span><span class="p">,</span> <span class="s2">&#34;Direct&#34;</span><span class="p">,</span> <span class="s2">&#34;Social&#34;</span><span class="p">,</span> <span class="s2">&#34;Referral&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;datasets&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span> <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mi">58</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">8</span><span class="p">],</span> <span class="nt">&#34;backgroundColor&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;#ff5d8f&#34;</span><span class="p">,</span> <span class="s2">&#34;#f59e0b&#34;</span><span class="p">,</span> <span class="s2">&#34;#8b5cf6&#34;</span><span class="p">,</span> <span class="s2">&#34;#12a594&#34;</span><span class="p">]</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></div></div>
</div>


### Radar chart

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-4-tab-0" aria-controls="tabs-4-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-4-tab-1" aria-controls="tabs-4-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-4-panel-0" aria-labelledby="tabs-4-tab-0" data-tab-index="0"><figure class="tb-chart" style="height:22rem">
  <canvas role="img" aria-label="Lighthouse: before vs. after"></canvas>
  <script type="application/json">
{
  "type": "radar",
  "data": {
    "labels": ["Performance", "Accessibility", "Best Practices", "SEO", "PWA"],
    "datasets": [
      { "label": "Before", "data": [72, 88, 80, 90, 40] },
      { "label": "After",  "data": [98, 100, 95, 100, 80] }
    ]
  }
}
</script>
</figure></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-4-panel-1" aria-labelledby="tabs-4-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;radar&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;labels&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;Performance&#34;</span><span class="p">,</span> <span class="s2">&#34;Accessibility&#34;</span><span class="p">,</span> <span class="s2">&#34;Best Practices&#34;</span><span class="p">,</span> <span class="s2">&#34;SEO&#34;</span><span class="p">,</span> <span class="s2">&#34;PWA&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;datasets&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span> <span class="nt">&#34;label&#34;</span><span class="p">:</span> <span class="s2">&#34;Before&#34;</span><span class="p">,</span> <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mi">72</span><span class="p">,</span> <span class="mi">88</span><span class="p">,</span> <span class="mi">80</span><span class="p">,</span> <span class="mi">90</span><span class="p">,</span> <span class="mi">40</span><span class="p">]</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span> <span class="nt">&#34;label&#34;</span><span class="p">:</span> <span class="s2">&#34;After&#34;</span><span class="p">,</span>  <span class="nt">&#34;data&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mi">98</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">95</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">80</span><span class="p">]</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></div></div>
</div>


## KaTeX: the basics

Place the marker shortcode `{{< katex >}}` on the page **once** - it loads
the *KaTeX* renderer. You then write the actual math right in the prose with
`$ ... $` (inline) or `$$ ... $$` (display); one marker covers the whole page.



<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-6-tab-0" aria-controls="tabs-6-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-6-tab-1" aria-controls="tabs-6-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-6-panel-0" aria-labelledby="tabs-6-tab-0" data-tab-index="0"><p>Inline: $E = mc^2$ sits in the middle of a sentence without blowing up the line
height. In display mode the formula is centred on its own line:</p>
$$
\int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}
$$</div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-6-panel-1" aria-labelledby="tabs-6-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl">Inline: <span class="s">$</span><span class="nb">E </span><span class="o">=</span><span class="nb"> mc^</span><span class="m">2</span><span class="s">$</span> in the middle of a sentence.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="sb">$$</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\int</span><span class="nb">_{</span><span class="o">-</span><span class="nv">\infty</span><span class="nb">}^{</span><span class="nv">\infty</span><span class="nb">} e^{</span><span class="o">-</span><span class="nb">x^</span><span class="m">2</span><span class="nb">}</span><span class="nv">\,</span><span class="nb">dx </span><span class="o">=</span><span class="nb"> </span><span class="nv">\sqrt</span><span class="nb">{</span><span class="nv">\pi</span><span class="nb">}
</span></span></span><span class="line"><span class="cl"><span class="s">$$</span>
</span></span></code></pre></div></div></div>
</div>


### Fractions, roots, powers and indices

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-7-tab-0" aria-controls="tabs-7-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-7-tab-1" aria-controls="tabs-7-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-7-panel-0" aria-labelledby="tabs-7-tab-0" data-tab-index="0">$$
\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
\qquad
\sqrt[3]{x}
\qquad
a_{i,j}^{2}
$$</div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-7-panel-1" aria-labelledby="tabs-7-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="sb">$$</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\frac</span><span class="nb">{</span><span class="o">-</span><span class="nb">b </span><span class="nv">\pm</span><span class="nb"> </span><span class="nv">\sqrt</span><span class="nb">{b^</span><span class="m">2</span><span class="nb"> </span><span class="o">-</span><span class="nb"> </span><span class="m">4</span><span class="nb">ac}}{</span><span class="m">2</span><span class="nb">a}
</span></span></span><span class="line"><span class="cl"><span class="nv">\qquad</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\sqrt</span><span class="o">[</span><span class="m">3</span><span class="o">]</span><span class="nb">{x}
</span></span></span><span class="line"><span class="cl"><span class="nv">\qquad</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nb">a_{i,j}^{</span><span class="m">2</span><span class="nb">}
</span></span></span><span class="line"><span class="cl"><span class="s">$$</span>
</span></span></code></pre></div></div></div>
</div>


### Sums, products, limits

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-8-tab-0" aria-controls="tabs-8-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-8-tab-1" aria-controls="tabs-8-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-8-panel-0" aria-labelledby="tabs-8-tab-0" data-tab-index="0">$$
\sum_{k=1}^{n} k = \frac{n(n+1)}{2}
\qquad
\prod_{i=1}^{n} i = n!
\qquad
\lim_{x \to 0} \frac{\sin x}{x} = 1
$$</div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-8-panel-1" aria-labelledby="tabs-8-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="sb">$$</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\sum</span><span class="nb">_{k</span><span class="o">=</span><span class="m">1</span><span class="nb">}^{n} k </span><span class="o">=</span><span class="nb"> </span><span class="nv">\frac</span><span class="nb">{n</span><span class="o">(</span><span class="nb">n</span><span class="o">+</span><span class="m">1</span><span class="o">)</span><span class="nb">}{</span><span class="m">2</span><span class="nb">}
</span></span></span><span class="line"><span class="cl"><span class="nv">\qquad</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\prod</span><span class="nb">_{i</span><span class="o">=</span><span class="m">1</span><span class="nb">}^{n} i </span><span class="o">=</span><span class="nb"> n</span><span class="o">!</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\qquad</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\lim</span><span class="nb">_{x </span><span class="nv">\to</span><span class="nb"> </span><span class="m">0</span><span class="nb">} </span><span class="nv">\frac</span><span class="nb">{</span><span class="nv">\sin</span><span class="nb"> x}{x} </span><span class="o">=</span><span class="nb"> </span><span class="m">1</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="s">$$</span>
</span></span></code></pre></div></div></div>
</div>


### Greek letters and operators

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-9-tab-0" aria-controls="tabs-9-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-9-tab-1" aria-controls="tabs-9-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-9-panel-0" aria-labelledby="tabs-9-tab-0" data-tab-index="0">$$
\alpha,\ \beta,\ \gamma,\ \Delta,\ \Omega \qquad
\nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0} \qquad
x \in \mathbb{R},\ A \subseteq B
$$</div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-9-panel-1" aria-labelledby="tabs-9-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="sb">$$</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\alpha</span><span class="nb">,</span><span class="nv">\ \beta</span><span class="nb">,</span><span class="nv">\ \gamma</span><span class="nb">,</span><span class="nv">\ \Delta</span><span class="nb">,</span><span class="nv">\ \Omega</span><span class="nb"> </span><span class="nv">\qquad</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\nabla</span><span class="nb"> </span><span class="nv">\cdot</span><span class="nb"> </span><span class="nv">\vec</span><span class="nb">{E} </span><span class="o">=</span><span class="nb"> </span><span class="nv">\frac</span><span class="nb">{</span><span class="nv">\rho</span><span class="nb">}{</span><span class="nv">\varepsilon</span><span class="nb">_</span><span class="m">0</span><span class="nb">} </span><span class="nv">\qquad</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nb">x </span><span class="nv">\in</span><span class="nb"> </span><span class="nv">\mathbb</span><span class="nb">{R},</span><span class="nv">\ </span><span class="nb">A </span><span class="nv">\subseteq</span><span class="nb"> B
</span></span></span><span class="line"><span class="cl"><span class="s">$$</span>
</span></span></code></pre></div></div></div>
</div>


### Matrices

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-10-tab-0" aria-controls="tabs-10-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-10-tab-1" aria-controls="tabs-10-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-10-panel-0" aria-labelledby="tabs-10-tab-0" data-tab-index="0">$$
\begin{pmatrix} a & b \\ c & d \end{pmatrix}
\begin{pmatrix} x \\ y \end{pmatrix} =
\begin{pmatrix} ax + by \\ cx + dy \end{pmatrix}
$$</div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-10-panel-1" aria-labelledby="tabs-10-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="sb">$$</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\begin</span><span class="nb">{pmatrix} a &amp; b </span><span class="nv">\\</span><span class="nb"> c &amp; d </span><span class="nv">\end</span><span class="nb">{pmatrix}
</span></span></span><span class="line"><span class="cl"><span class="nv">\begin</span><span class="nb">{pmatrix} x </span><span class="nv">\\</span><span class="nb"> y </span><span class="nv">\end</span><span class="nb">{pmatrix} </span><span class="o">=</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\begin</span><span class="nb">{pmatrix} ax </span><span class="o">+</span><span class="nb"> by </span><span class="nv">\\</span><span class="nb"> cx </span><span class="o">+</span><span class="nb"> dy </span><span class="nv">\end</span><span class="nb">{pmatrix}
</span></span></span><span class="line"><span class="cl"><span class="s">$$</span>
</span></span></code></pre></div></div></div>
</div>


### Aligned multi-line and cases

Use `aligned` to line up on `&`, and `cases` for piecewise definitions:

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-11-tab-0" aria-controls="tabs-11-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-11-tab-1" aria-controls="tabs-11-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-11-panel-0" aria-labelledby="tabs-11-tab-0" data-tab-index="0">$$
\begin{aligned}
  f(x) &= (x+1)^2 \\
       &= x^2 + 2x + 1
\end{aligned}
\qquad
|x| =
\begin{cases}
  x,  & \text{if } x \ge 0 \\
  -x, & \text{otherwise}
\end{cases}
$$</div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-11-panel-1" aria-labelledby="tabs-11-tab-1" data-tab-index="1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="sb">$$</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\begin</span><span class="nb">{aligned}
</span></span></span><span class="line"><span class="cl"><span class="nb">  f</span><span class="o">(</span><span class="nb">x</span><span class="o">)</span><span class="nb"> &amp;</span><span class="o">=</span><span class="nb"> </span><span class="o">(</span><span class="nb">x</span><span class="o">+</span><span class="m">1</span><span class="o">)</span><span class="nb">^</span><span class="m">2</span><span class="nb"> </span><span class="nv">\\</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nb">       &amp;</span><span class="o">=</span><span class="nb"> x^</span><span class="m">2</span><span class="nb"> </span><span class="o">+</span><span class="nb"> </span><span class="m">2</span><span class="nb">x </span><span class="o">+</span><span class="nb"> </span><span class="m">1</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\end</span><span class="nb">{aligned}
</span></span></span><span class="line"><span class="cl"><span class="nv">\qquad</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nb">|x| </span><span class="o">=</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\begin</span><span class="nb">{cases}
</span></span></span><span class="line"><span class="cl"><span class="nb">  x,  &amp; </span><span class="nv">\text</span><span class="nb">{if } x </span><span class="nv">\ge</span><span class="nb"> </span><span class="m">0</span><span class="nb"> </span><span class="nv">\\</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nb">  </span><span class="o">-</span><span class="nb">x, &amp; </span><span class="nv">\text</span><span class="nb">{otherwise}
</span></span></span><span class="line"><span class="cl"><span class="nv">\end</span><span class="nb">{cases}
</span></span></span><span class="line"><span class="cl"><span class="s">$$</span>
</span></span></code></pre></div></div></div>
</div>


## Mermaid: the basics

You describe the diagram as **text** between `{{< mermaid >}}` and
`{{< /mermaid >}}` - Mermaid renders it to SVG in the browser. The first
line picks the diagram type (`graph`/`flowchart`, `sequenceDiagram`,
`classDiagram`, …).

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-12-tab-0" aria-controls="tabs-12-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-12-tab-1" aria-controls="tabs-12-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-12-panel-0" aria-labelledby="tabs-12-tab-0" data-tab-index="0"><pre class="mermaid">
graph LR
  A[Markdown] --&gt; B{Render hook}
  B --&gt; C[WebP]
  B --&gt; D[Lightbox]
</pre></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-12-panel-1" aria-labelledby="tabs-12-tab-1" data-tab-index="1"><pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">graph LR
  A[Markdown] --&gt; B{Render hook}
  B --&gt; C[WebP]
  B --&gt; D[Lightbox]
</code></pre></div></div>
</div>


### Flow direction and node shapes

`graph`/`flowchart` supports the directions `TD` (top→down), `LR`, `RL` and
`BT`. The brackets around the node text set its shape: `[box]`, `(round)`,
`([stadium])`, `{diamond}`, `((circle))`.

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-13-tab-0" aria-controls="tabs-13-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-13-tab-1" aria-controls="tabs-13-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-13-panel-0" aria-labelledby="tabs-13-tab-0" data-tab-index="0"><pre class="mermaid">
flowchart TD
  Start([Start]) --&gt; Check{All green?}
  Check --&gt;|yes| Deploy[Deploy]
  Check --&gt;|no| Fix(Fix errors)
  Fix --&gt; Check
  Deploy --&gt; Done((Done))
</pre></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-13-panel-1" aria-labelledby="tabs-13-tab-1" data-tab-index="1"><pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">flowchart TD
  Start([Start]) --&gt; Check{All green?}
  Check --&gt;|yes| Deploy[Deploy]
  Check --&gt;|no| Fix(Fix errors)
  Fix --&gt; Check
  Deploy --&gt; Done((Done))
</code></pre></div></div>
</div>


### Sequence diagram

For interactions between participants - with activation bars and notes.

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-14-tab-0" aria-controls="tabs-14-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-14-tab-1" aria-controls="tabs-14-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-14-panel-0" aria-labelledby="tabs-14-tab-0" data-tab-index="0"><pre class="mermaid">
sequenceDiagram
  participant V as Visitor
  participant S as Server
  V-&gt;&gt;S: GET /post/...
  activate S
  S--&gt;&gt;V: HTML (pre-rendered)
  deactivate S
  Note over V: Apply dark mode (no flash)
</pre></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-14-panel-1" aria-labelledby="tabs-14-tab-1" data-tab-index="1"><pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">sequenceDiagram
  participant V as Visitor
  participant S as Server
  V-&gt;&gt;S: GET /post/...
  activate S
  S--&gt;&gt;V: HTML (pre-rendered)
  deactivate S
  Note over V: Apply dark mode (no flash)
</code></pre></div></div>
</div>


### Class diagram

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-15-tab-0" aria-controls="tabs-15-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-15-tab-1" aria-controls="tabs-15-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-15-panel-0" aria-labelledby="tabs-15-tab-0" data-tab-index="0"><pre class="mermaid">
classDiagram
  class Post {
    +string Title
    +Date Date
    +render() string
  }
  class Series {
    +string Name
  }
  Series &#34;1&#34; o-- &#34;*&#34; Post : contains
</pre></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-15-panel-1" aria-labelledby="tabs-15-tab-1" data-tab-index="1"><pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">classDiagram
  class Post {
    +string Title
    +Date Date
    +render() string
  }
  class Series {
    +string Name
  }
  Series &#34;1&#34; o-- &#34;*&#34; Post : contains
</code></pre></div></div>
</div>


### State diagram

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-16-tab-0" aria-controls="tabs-16-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-16-tab-1" aria-controls="tabs-16-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-16-panel-0" aria-labelledby="tabs-16-tab-0" data-tab-index="0"><pre class="mermaid">
stateDiagram-v2
  [*] --&gt; Draft
  Draft --&gt; Review: submit
  Review --&gt; Draft: changes
  Review --&gt; Published: approve
  Published --&gt; [*]
</pre></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-16-panel-1" aria-labelledby="tabs-16-tab-1" data-tab-index="1"><pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">stateDiagram-v2
  [*] --&gt; Draft
  Draft --&gt; Review: submit
  Review --&gt; Draft: changes
  Review --&gt; Published: approve
  Published --&gt; [*]
</code></pre></div></div>
</div>


### Gantt chart

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-17-tab-0" aria-controls="tabs-17-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-17-tab-1" aria-controls="tabs-17-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-17-panel-0" aria-labelledby="tabs-17-tab-0" data-tab-index="0"><pre class="mermaid">
gantt
  title Project roadmap
  dateFormat YYYY-MM-DD
  section Planning
    Concept        :done,    des1, 2026-01-01, 2026-01-07
    Draft          :active,  des2, 2026-01-08, 5d
  section Build
    Build          :         des3, after des2, 10d
    Test &amp; launch  :         des4, after des3, 4d
</pre></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-17-panel-1" aria-labelledby="tabs-17-tab-1" data-tab-index="1"><pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">gantt
  title Project roadmap
  dateFormat YYYY-MM-DD
  section Planning
    Concept        :done,    des1, 2026-01-01, 2026-01-07
    Draft          :active,  des2, 2026-01-08, 5d
  section Build
    Build          :         des3, after des2, 10d
    Test &amp; launch  :         des4, after des3, 4d
</code></pre></div></div>
</div>


### Pie chart

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-18-tab-0" aria-controls="tabs-18-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-18-tab-1" aria-controls="tabs-18-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-18-panel-0" aria-labelledby="tabs-18-tab-0" data-tab-index="0"><pre class="mermaid">
pie showData
  title Time per task
  &#34;Writing&#34;  : 45
  &#34;Tinkering&#34;: 35
  &#34;Cleanup&#34;  : 20
</pre></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-18-panel-1" aria-labelledby="tabs-18-tab-1" data-tab-index="1"><pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">pie showData
  title Time per task
  &#34;Writing&#34;  : 45
  &#34;Tinkering&#34;: 35
  &#34;Cleanup&#34;  : 20
</code></pre></div></div>
</div>


### ER diagram

<div class="tb-tab__container" data-tb-component="tabs">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-19-tab-0" aria-controls="tabs-19-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        Example
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-19-tab-1" aria-controls="tabs-19-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        Code
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-19-panel-0" aria-labelledby="tabs-19-tab-0" data-tab-index="0"><pre class="mermaid">
erDiagram
  CATEGORY ||--o{ POST : has
  POST     }o--o{ TAG  : tagged-with
</pre></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-19-panel-1" aria-labelledby="tabs-19-tab-1" data-tab-index="1"><pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">erDiagram
  CATEGORY ||--o{ POST : has
  POST     }o--o{ TAG  : tagged-with
</code></pre></div></div>
</div>


*Mermaid* automatically adopts the light or dark colour scheme and
**re-renders live** when you toggle dark mode - try the switch in the top right
while a diagram is visible.

## Under the hood

What both shortcodes take care of in the background - with no extra effort:

- **Self-hosted, no CDN.** Mermaid, KaTeX (fonts included) and Chart.js are
  vendored from npm into the theme and served from your own domain -
  GDPR-friendly, no third-party requests.
- **Only when needed.** The libraries land only on pages that use the `mermaid`,
  `katex` or `chart` shortcode (`.HasShortcode`). Pages without diagrams,
  formulas or charts load no extra JavaScript.
- **CSP-friendly.** The init scripts load as regular `<script src>` with
  subresource integrity and `defer`, not inline - a strict Content Security
  Policy without `unsafe-inline` stays possible.
- **Live dark mode.** A `MutationObserver` on `html.dark` re-renders the
  diagrams and re-themes the charts as soon as the colour scheme changes
  (Mermaid and Chart.js only theme at render time).
- **Stable sizes.** Mermaid measures text boxes at render time; the init waits
  for `document.fonts.ready` so diagrams are measured with the loaded font and
  don't jump in size between reloads.
- **Safe.** Mermaid runs with `securityLevel: "strict"`. KaTeX auto-render only
  processes the prose regions of the page and leaves code blocks untouched - so
  `$` signs in examples stay put.

