Added railroad diagrams building lib (#137)

Co-authored-by: Alexey Alexandrov <alalexandrov@gridgain.com>
diff --git a/_docs/_layouts/default.html b/_docs/_layouts/default.html
index 992df4a..4f23c1a 100644
--- a/_docs/_layouts/default.html
+++ b/_docs/_layouts/default.html
@@ -104,6 +104,7 @@
     </script>
 <script type='module' src='{{"assets/js/index.js?"|append: timestamp | relative_url}}' async crossorigin></script>
 <script type='module' src='{{"assets/js/versioning.js?"|append: timestamp | relative_url}}' async crossorigin></script>
+<script type='module' src='{{"assets/js/railroad-diagram.js?"|append: timestamp | relative_url}}' async></script>
 
 <link rel="stylesheet" href="{{'assets/css/styles.css?'|append: timestamp |relative_url}}" media="print" onload="this.media='all'">
 <noscript><link media="all" rel="stylesheet" href="{{'assets/css/styles.css?'|append: timestamp |relative_url}}"></noscript>
diff --git a/_docs/_sass/railroad-diagram.scss b/_docs/_sass/railroad-diagram.scss
new file mode 100644
index 0000000..245a817
--- /dev/null
+++ b/_docs/_sass/railroad-diagram.scss
@@ -0,0 +1,72 @@
+.diagram-container {
+
+  svg {
+    background-color: hsl(0, 0%, 100%);
+  }
+
+  path {
+    stroke-width: 2;
+    stroke: black;
+    fill: rgba(0, 0, 0, 0);
+  }
+
+  text {
+    font: bold 14px monospace;
+    text-anchor: middle;
+    white-space: pre;
+
+    &.diagram-text {
+      font-size: 12px;
+    }
+
+    &.diagram-arrow {
+      font-size: 16px;
+    }
+
+    &.label {
+      text-anchor: start;
+    }
+
+    &.comment {
+      font: italic 12px monospace;
+    }
+  }
+
+  g {
+    .non-terminal {
+      text {
+        /*font-style: italic;*/
+      }
+    }
+
+    a {
+      text {
+        fill: blue;
+      }
+    }
+  }
+
+  rect {
+    stroke-width: 2;
+    stroke: black;
+    fill: hsl(0, 0%, 100%);
+
+    &.group-box {
+      stroke: gray;
+      stroke-dasharray: 10 5;
+      fill: none;
+    }
+  }
+
+  path.diagram-text {
+    stroke-width: 2;
+    stroke: black;
+    fill: white;
+    cursor: help;
+  }
+
+  g.diagram-text:hover path.diagram-text {
+    fill: #eee;
+  }
+
+}
diff --git a/_docs/assets/css/styles.scss b/_docs/assets/css/styles.scss
index 078cb22..1eb1c53 100644
--- a/_docs/assets/css/styles.scss
+++ b/_docs/assets/css/styles.scss
@@ -10,6 +10,7 @@
 @import "left-nav";
 @import "right-nav";
 @import "footer";
+@import "railroad-diagram";
 
 @import "docs";
 
diff --git a/_docs/assets/js/railroad-diagram.js b/_docs/assets/js/railroad-diagram.js
new file mode 100644
index 0000000..a903c5b
--- /dev/null
+++ b/_docs/assets/js/railroad-diagram.js
@@ -0,0 +1,11 @@
+import rr, * as rrClass from "./railroad.js";
+Object.assign(window, rr);
+window.rrOptions = rrClass.Options;
+
+let elements = document.querySelectorAll('.diagram-container p');
+[].forEach.call(elements, function(el) {
+    let result = eval(el.innerHTML).format();
+    let diagramContainer = el.closest('.diagram-container');
+    diagramContainer.innerHTML = '';
+    result.addTo(diagramContainer);
+})
diff --git a/_docs/assets/js/railroad.js b/_docs/assets/js/railroad.js
new file mode 100644
index 0000000..d029475
--- /dev/null
+++ b/_docs/assets/js/railroad.js
@@ -0,0 +1,1420 @@
+"use strict";
+/*
+Railroad Diagrams
+by Tab Atkins Jr. (and others)
+http://xanthir.com
+http://twitter.com/tabatkins
+http://github.com/tabatkins/railroad-diagrams
+
+This document and all associated files in the github project are licensed under CC0: http://creativecommons.org/publicdomain/zero/1.0/
+This means you can reuse, remix, or otherwise appropriate this project for your own use WITHOUT RESTRICTION.
+(The actual legal meaning can be found at the above link.)
+Don't ask me for permission to use any part of this project, JUST USE IT.
+I would appreciate attribution, but that is not required by the license.
+*/
+
+// Export function versions of all the constructors.
+// Each class will add itself to this object.
+const funcs = {};
+export default funcs;
+
+export const Options = {
+	DEBUG: false, // if true, writes some debug information into attributes
+	VS: 8, // minimum vertical separation between things. For a 3px stroke, must be at least 4
+	AR: 10, // radius of arcs
+	DIAGRAM_CLASS: 'railroad-diagram', // class to put on the root <svg>
+	STROKE_ODD_PIXEL_LENGTH: true, // is the stroke width an odd (1px, 3px, etc) pixel length?
+	INTERNAL_ALIGNMENT: 'center', // how to align items when they have extra space. left/right/center
+	CHAR_WIDTH: 8.5, // width of each monospace character. play until you find the right value for your font
+	COMMENT_CHAR_WIDTH: 7, // comments are in smaller text by default
+};
+
+export const defaultCSS = `
+	svg {
+		background-color: hsl(30,20%,95%);
+	}
+	path {
+		stroke-width: 3;
+		stroke: black;
+		fill: rgba(0,0,0,0);
+	}
+	text {
+		font: bold 14px monospace;
+		text-anchor: middle;
+		white-space: pre;
+	}
+	text.diagram-text {
+		font-size: 12px;
+	}
+	text.diagram-arrow {
+		font-size: 16px;
+	}
+	text.label {
+		text-anchor: start;
+	}
+	text.comment {
+		font: italic 12px monospace;
+	}
+	g.non-terminal text {
+		/*font-style: italic;*/
+	}
+	rect {
+		stroke-width: 3;
+		stroke: black;
+		fill: hsl(120,100%,90%);
+	}
+	rect.group-box {
+		stroke: gray;
+		stroke-dasharray: 10 5;
+		fill: none;
+	}
+	path.diagram-text {
+		stroke-width: 3;
+		stroke: black;
+		fill: white;
+		cursor: help;
+	}
+	g.diagram-text:hover path.diagram-text {
+		fill: #eee;
+	}`;
+
+
+export class FakeSVG {
+	constructor(tagName, attrs, text) {
+		if(text) this.children = text;
+		else this.children = [];
+		this.tagName = tagName;
+		this.attrs = unnull(attrs, {});
+	}
+	format(x, y, width) {
+		// Virtual
+	}
+	addTo(parent) {
+		if(parent instanceof FakeSVG) {
+			parent.children.push(this);
+			return this;
+		} else {
+			var svg = this.toSVG();
+			parent.appendChild(svg);
+			return svg;
+		}
+	}
+	toSVG() {
+		var el = SVG(this.tagName, this.attrs);
+		if(typeof this.children == 'string') {
+			el.textContent = this.children;
+		} else {
+			this.children.forEach(function(e) {
+				el.appendChild(e.toSVG());
+			});
+		}
+		return el;
+	}
+	toString() {
+		var str = '<' + this.tagName;
+		var group = this.tagName == "g" || this.tagName == "svg";
+		for(var attr in this.attrs) {
+			str += ' ' + attr + '="' + (this.attrs[attr]+'').replace(/&/g, '&amp;').replace(/"/g, '&quot;') + '"';
+		}
+		str += '>';
+		if(group) str += "\n";
+		if(typeof this.children == 'string') {
+			str += escapeString(this.children);
+		} else {
+			this.children.forEach(function(e) {
+				str += e;
+			});
+		}
+		str += '</' + this.tagName + '>\n';
+		return str;
+	}
+	walk(cb) {
+		cb(this);
+	}
+}
+
+
+export class Path extends FakeSVG {
+	constructor(x,y) {
+		super('path');
+		this.attrs.d = "M"+x+' '+y;
+	}
+	m(x,y) {
+		this.attrs.d += 'm'+x+' '+y;
+		return this;
+	}
+	h(val) {
+		this.attrs.d += 'h'+val;
+		return this;
+	}
+	right(val) { return this.h(Math.max(0, val)); }
+	left(val) { return this.h(-Math.max(0, val)); }
+	v(val) {
+		this.attrs.d += 'v'+val;
+		return this;
+	}
+	down(val) { return this.v(Math.max(0, val)); }
+	up(val) { return this.v(-Math.max(0, val)); }
+	arc(sweep){
+		// 1/4 of a circle
+		var x = Options.AR;
+		var y = Options.AR;
+		if(sweep[0] == 'e' || sweep[1] == 'w') {
+			x *= -1;
+		}
+		if(sweep[0] == 's' || sweep[1] == 'n') {
+			y *= -1;
+		}
+		var cw;
+		if(sweep == 'ne' || sweep == 'es' || sweep == 'sw' || sweep == 'wn') {
+			cw = 1;
+		} else {
+			cw = 0;
+		}
+		this.attrs.d += "a"+Options.AR+" "+Options.AR+" 0 0 "+cw+' '+x+' '+y;
+		return this;
+	}
+	arc_8(start, dir) {
+		// 1/8 of a circle
+		const arc = Options.AR;
+		const s2 = 1/Math.sqrt(2) * arc;
+		const s2inv = (arc - s2);
+		let path = "a " + arc + " " + arc + " 0 0 " + (dir=='cw' ? "1" : "0") + " ";
+		const sd = start+dir;
+		const offset =
+			sd == 'ncw'   ? [s2, s2inv] :
+			sd == 'necw'  ? [s2inv, s2] :
+			sd == 'ecw'   ? [-s2inv, s2] :
+			sd == 'secw'  ? [-s2, s2inv] :
+			sd == 'scw'   ? [-s2, -s2inv] :
+			sd == 'swcw'  ? [-s2inv, -s2] :
+			sd == 'wcw'   ? [s2inv, -s2] :
+			sd == 'nwcw'  ? [s2, -s2inv] :
+			sd == 'nccw'  ? [-s2, s2inv] :
+			sd == 'nwccw' ? [-s2inv, s2] :
+			sd == 'wccw'  ? [s2inv, s2] :
+			sd == 'swccw' ? [s2, s2inv] :
+			sd == 'sccw'  ? [s2, -s2inv] :
+			sd == 'seccw' ? [s2inv, -s2] :
+			sd == 'eccw'  ? [-s2inv, -s2] :
+			sd == 'neccw' ? [-s2, -s2inv] : null
+		;
+		path += offset.join(" ");
+		this.attrs.d += path;
+		return this;
+	}
+	l(x, y) {
+		this.attrs.d += 'l'+x+' '+y;
+		return this;
+	}
+	format() {
+		// All paths in this library start/end horizontally.
+		// The extra .5 ensures a minor overlap, so there's no seams in bad rasterizers.
+		this.attrs.d += 'h.5';
+		return this;
+	}
+}
+
+
+export class DiagramMultiContainer extends FakeSVG {
+	constructor(tagName, items, attrs, text) {
+		super(tagName, attrs, text);
+		this.items = items.map(wrapString);
+	}
+	walk(cb) {
+		cb(this);
+		this.items.forEach(x=>x.walk(cb));
+	}
+}
+
+
+export class Diagram extends DiagramMultiContainer {
+	constructor(...items) {
+		super('svg', items, {class: Options.DIAGRAM_CLASS});
+		if(!(this.items[0] instanceof Start)) {
+			this.items.unshift(new Start());
+		}
+		if(!(this.items[this.items.length-1] instanceof End)) {
+			this.items.push(new End());
+		}
+		this.up = this.down = this.height = this.width = 0;
+		for(const item of this.items) {
+			this.width += item.width + (item.needsSpace?20:0);
+			this.up = Math.max(this.up, item.up - this.height);
+			this.height += item.height;
+			this.down = Math.max(this.down - item.height, item.down);
+		}
+		this.formatted = false;
+	}
+	format(paddingt, paddingr, paddingb, paddingl) {
+		paddingt = unnull(paddingt, 20);
+		paddingr = unnull(paddingr, paddingt, 20);
+		paddingb = unnull(paddingb, paddingt, 20);
+		paddingl = unnull(paddingl, paddingr, 20);
+		var x = paddingl;
+		var y = paddingt;
+		y += this.up;
+		var g = new FakeSVG('g', Options.STROKE_ODD_PIXEL_LENGTH ? {transform:'translate(.5 .5)'} : {});
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			if(item.needsSpace) {
+				new Path(x,y).h(10).addTo(g);
+				x += 10;
+			}
+			item.format(x, y, item.width).addTo(g);
+			x += item.width;
+			y += item.height;
+			if(item.needsSpace) {
+				new Path(x,y).h(10).addTo(g);
+				x += 10;
+			}
+		}
+		this.attrs.width = this.width + paddingl + paddingr;
+		this.attrs.height = this.up + this.height + this.down + paddingt + paddingb;
+		this.attrs.viewBox = "0 0 " + this.attrs.width + " " + this.attrs.height;
+		g.addTo(this);
+		this.formatted = true;
+		return this;
+	}
+	addTo(parent) {
+		if(!parent) {
+			var scriptTag = document.getElementsByTagName('script');
+			scriptTag = scriptTag[scriptTag.length - 1];
+			parent = scriptTag.parentNode;
+		}
+		return super.addTo.call(this, parent);
+	}
+	toSVG() {
+		if(!this.formatted) {
+			this.format();
+		}
+		return super.toSVG.call(this);
+	}
+	toString() {
+		if(!this.formatted) {
+			this.format();
+		}
+		return super.toString.call(this);
+	}
+	toStandalone(style) {
+		if(!this.formatted) {
+			this.format();
+		}
+		const s = new FakeSVG('style', {}, style || defaultCSS);
+		this.children.push(s);
+		this.attrs.xmlns = "http://www.w3.org/2000/svg";
+		this.attrs['xmlns:xlink'] = "http://www.w3.org/1999/xlink";
+		const result = super.toString.call(this);
+		this.children.pop();
+		delete this.attrs.xmlns;
+		return result;
+	}
+}
+funcs.Diagram = (...args)=>new Diagram(...args);
+
+
+export class ComplexDiagram extends FakeSVG {
+	constructor(...items) {
+		var diagram = new Diagram(...items);
+		diagram.items[0] = new Start({type:"complex"});
+		diagram.items[diagram.items.length-1] = new End({type:"complex"});
+		return diagram;
+	}
+}
+funcs.ComplexDiagram = (...args)=>new ComplexDiagram(...args);
+
+
+export class Sequence extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		var numberOfItems = this.items.length;
+		this.needsSpace = true;
+		this.up = this.down = this.height = this.width = 0;
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			this.width += item.width + (item.needsSpace?20:0);
+			this.up = Math.max(this.up, item.up - this.height);
+			this.height += item.height;
+			this.down = Math.max(this.down - item.height, item.down);
+		}
+		if(this.items[0].needsSpace) this.width -= 10;
+		if(this.items[this.items.length-1].needsSpace) this.width -= 10;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "sequence";
+		}
+	}
+	format(x,y,width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			if(item.needsSpace && i > 0) {
+				new Path(x,y).h(10).addTo(this);
+				x += 10;
+			}
+			item.format(x, y, item.width).addTo(this);
+			x += item.width;
+			y += item.height;
+			if(item.needsSpace && i < this.items.length-1) {
+				new Path(x,y).h(10).addTo(this);
+				x += 10;
+			}
+		}
+		return this;
+	}
+}
+funcs.Sequence = (...args)=>new Sequence(...args);
+
+
+export class Stack extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		if( items.length === 0 ) {
+			throw new RangeError("Stack() must have at least one child.");
+		}
+		this.width = Math.max.apply(null, this.items.map(function(e) { return e.width + (e.needsSpace?20:0); }));
+		//if(this.items[0].needsSpace) this.width -= 10;
+		//if(this.items[this.items.length-1].needsSpace) this.width -= 10;
+		if(this.items.length > 1){
+			this.width += Options.AR*2;
+		}
+		this.needsSpace = true;
+		this.up = this.items[0].up;
+		this.down = this.items[this.items.length-1].down;
+
+		this.height = 0;
+		var last = this.items.length - 1;
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			this.height += item.height;
+			if(i > 0) {
+				this.height += Math.max(Options.AR*2, item.up + Options.VS);
+			}
+			if(i < last) {
+				this.height += Math.max(Options.AR*2, item.down + Options.VS);
+			}
+		}
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "stack";
+		}
+	}
+	format(x,y,width) {
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		x += gaps[0];
+		var xInitial = x;
+		if(this.items.length > 1) {
+			new Path(x, y).h(Options.AR).addTo(this);
+			x += Options.AR;
+		}
+
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			var innerWidth = this.width - (this.items.length>1 ? Options.AR*2 : 0);
+			item.format(x, y, innerWidth).addTo(this);
+			x += innerWidth;
+			y += item.height;
+
+			if(i !== this.items.length-1) {
+				new Path(x, y)
+					.arc('ne').down(Math.max(0, item.down + Options.VS - Options.AR*2))
+					.arc('es').left(innerWidth)
+					.arc('nw').down(Math.max(0, this.items[i+1].up + Options.VS - Options.AR*2))
+					.arc('ws').addTo(this);
+				y += Math.max(item.down + Options.VS, Options.AR*2) + Math.max(this.items[i+1].up + Options.VS, Options.AR*2);
+				//y += Math.max(Options.AR*4, item.down + Options.VS*2 + this.items[i+1].up)
+				x = xInitial+Options.AR;
+			}
+
+		}
+
+		if(this.items.length > 1) {
+			new Path(x,y).h(Options.AR).addTo(this);
+			x += Options.AR;
+		}
+		new Path(x,y).h(gaps[1]).addTo(this);
+
+		return this;
+	}
+}
+funcs.Stack = (...args)=>new Stack(...args);
+
+
+export class OptionalSequence extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		if( items.length === 0 ) {
+			throw new RangeError("OptionalSequence() must have at least one child.");
+		}
+		if( items.length === 1 ) {
+			return new Sequence(items);
+		}
+		var arc = Options.AR;
+		this.needsSpace = false;
+		this.width = 0;
+		this.up = 0;
+		this.height = sum(this.items, function(x){return x.height});
+		this.down = this.items[0].down;
+		var heightSoFar = 0;
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			this.up = Math.max(this.up, Math.max(arc*2, item.up + Options.VS) - heightSoFar);
+			heightSoFar += item.height;
+			if(i > 0) {
+				this.down = Math.max(this.height + this.down, heightSoFar + Math.max(arc*2, item.down + Options.VS)) - this.height;
+			}
+			var itemWidth = (item.needsSpace?10:0) + item.width;
+			if(i === 0) {
+				this.width += arc + Math.max(itemWidth, arc);
+			} else {
+				this.width += arc*2 + Math.max(itemWidth, arc) + arc;
+			}
+		}
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "optseq";
+		}
+	}
+	format(x, y, width) {
+		var arc = Options.AR;
+		var gaps = determineGaps(width, this.width);
+		new Path(x, y).right(gaps[0]).addTo(this);
+		new Path(x + gaps[0] + this.width, y + this.height).right(gaps[1]).addTo(this);
+		x += gaps[0];
+		var upperLineY = y - this.up;
+		var last = this.items.length - 1;
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			var itemSpace = (item.needsSpace?10:0);
+			var itemWidth = item.width + itemSpace;
+			if(i === 0) {
+				// Upper skip
+				new Path(x,y)
+					.arc('se')
+					.up(y - upperLineY - arc*2)
+					.arc('wn')
+					.right(itemWidth - arc)
+					.arc('ne')
+					.down(y + item.height - upperLineY - arc*2)
+					.arc('ws')
+					.addTo(this);
+				// Straight line
+				new Path(x, y)
+					.right(itemSpace + arc)
+					.addTo(this);
+				item.format(x + itemSpace + arc, y, item.width).addTo(this);
+				x += itemWidth + arc;
+				y += item.height;
+				// x ends on the far side of the first element,
+				// where the next element's skip needs to begin
+			} else if(i < last) {
+				// Upper skip
+				new Path(x, upperLineY)
+					.right(arc*2 + Math.max(itemWidth, arc) + arc)
+					.arc('ne')
+					.down(y - upperLineY + item.height - arc*2)
+					.arc('ws')
+					.addTo(this);
+				// Straight line
+				new Path(x,y)
+					.right(arc*2)
+					.addTo(this);
+				item.format(x + arc*2, y, item.width).addTo(this);
+				new Path(x + item.width + arc*2, y + item.height)
+					.right(itemSpace + arc)
+					.addTo(this);
+				// Lower skip
+				new Path(x,y)
+					.arc('ne')
+					.down(item.height + Math.max(item.down + Options.VS, arc*2) - arc*2)
+					.arc('ws')
+					.right(itemWidth - arc)
+					.arc('se')
+					.up(item.down + Options.VS - arc*2)
+					.arc('wn')
+					.addTo(this);
+				x += arc*2 + Math.max(itemWidth, arc) + arc;
+				y += item.height;
+			} else {
+				// Straight line
+				new Path(x, y)
+					.right(arc*2)
+					.addTo(this);
+				item.format(x + arc*2, y, item.width).addTo(this);
+				new Path(x + arc*2 + item.width, y + item.height)
+					.right(itemSpace + arc)
+					.addTo(this);
+				// Lower skip
+				new Path(x,y)
+					.arc('ne')
+					.down(item.height + Math.max(item.down + Options.VS, arc*2) - arc*2)
+					.arc('ws')
+					.right(itemWidth - arc)
+					.arc('se')
+					.up(item.down + Options.VS - arc*2)
+					.arc('wn')
+					.addTo(this);
+			}
+		}
+		return this;
+	}
+}
+funcs.OptionalSequence = (...args)=>new OptionalSequence(...args);
+
+
+export class AlternatingSequence extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		if( items.length === 1 ) {
+			return new Sequence(items);
+		}
+		if( items.length !== 2 ) {
+			throw new RangeError("AlternatingSequence() must have one or two children.");
+		}
+		this.needsSpace = false;
+
+		const arc = Options.AR;
+		const vert = Options.VS;
+		const max = Math.max;
+		const first = this.items[0];
+		const second = this.items[1];
+
+		const arcX = 1 / Math.sqrt(2) * arc * 2;
+		const arcY = (1 - 1 / Math.sqrt(2)) * arc * 2;
+		const crossY = Math.max(arc, Options.VS);
+		const crossX = (crossY - arcY) + arcX;
+
+		const firstOut = max(arc + arc, crossY/2 + arc + arc, crossY/2 + vert + first.down);
+		this.up = firstOut + first.height + first.up;
+
+		const secondIn = max(arc + arc, crossY/2 + arc + arc, crossY/2 + vert + second.up);
+		this.down = secondIn + second.height + second.down;
+
+		this.height = 0;
+
+		const firstWidth = 2*(first.needsSpace?10:0) + first.width;
+		const secondWidth = 2*(second.needsSpace?10:0) + second.width;
+		this.width = 2*arc + max(firstWidth, crossX, secondWidth) + 2*arc;
+
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "altseq";
+		}
+	}
+	format(x, y, width) {
+		const arc = Options.AR;
+		const gaps = determineGaps(width, this.width);
+		new Path(x,y).right(gaps[0]).addTo(this);
+		x += gaps[0];
+		new Path(x+this.width, y).right(gaps[1]).addTo(this);
+		// bounding box
+		//new Path(x+gaps[0], y).up(this.up).right(this.width).down(this.up+this.down).left(this.width).up(this.down).addTo(this);
+		const first = this.items[0];
+		const second = this.items[1];
+
+		// top
+		const firstIn = this.up - first.up;
+		const firstOut = this.up - first.up - first.height;
+		new Path(x,y).arc('se').up(firstIn-2*arc).arc('wn').addTo(this);
+		first.format(x + 2*arc, y - firstIn, this.width - 4*arc).addTo(this);
+		new Path(x + this.width - 2*arc, y - firstOut).arc('ne').down(firstOut - 2*arc).arc('ws').addTo(this);
+
+		// bottom
+		const secondIn = this.down - second.down - second.height;
+		const secondOut = this.down - second.down;
+		new Path(x,y).arc('ne').down(secondIn - 2*arc).arc('ws').addTo(this);
+		second.format(x + 2*arc, y + secondIn, this.width - 4*arc).addTo(this);
+		new Path(x + this.width - 2*arc, y + secondOut).arc('se').up(secondOut - 2*arc).arc('wn').addTo(this);
+
+		// crossover
+		const arcX = 1 / Math.sqrt(2) * arc * 2;
+		const arcY = (1 - 1 / Math.sqrt(2)) * arc * 2;
+		const crossY = Math.max(arc, Options.VS);
+		const crossX = (crossY - arcY) + arcX;
+		const crossBar = (this.width - 4*arc - crossX)/2;
+		new Path(x+arc, y - crossY/2 - arc).arc('ws').right(crossBar)
+			.arc_8('n', 'cw').l(crossX - arcX, crossY - arcY).arc_8('sw', 'ccw')
+			.right(crossBar).arc('ne').addTo(this);
+		new Path(x+arc, y + crossY/2 + arc).arc('wn').right(crossBar)
+			.arc_8('s', 'ccw').l(crossX - arcX, -(crossY - arcY)).arc_8('nw', 'cw')
+			.right(crossBar).arc('se').addTo(this);
+
+		return this;
+	}
+}
+funcs.AlternatingSequence = (...args)=>new AlternatingSequence(...args);
+
+
+export class Choice extends DiagramMultiContainer {
+	constructor(normal, ...items) {
+		super('g', items);
+		if( typeof normal !== "number" || normal !== Math.floor(normal) ) {
+			throw new TypeError("The first argument of Choice() must be an integer.");
+		} else if(normal < 0 || normal >= items.length) {
+			throw new RangeError("The first argument of Choice() must be an index for one of the items.");
+		} else {
+			this.normal = normal;
+		}
+		var first = 0;
+		var last = items.length - 1;
+		this.width = Math.max.apply(null, this.items.map(function(el){return el.width})) + Options.AR*4;
+		this.height = this.items[normal].height;
+		this.up = this.items[first].up;
+		var arcs;
+		for(var i = first; i < normal; i++) {
+			if(i == normal-1) arcs = Options.AR*2;
+			else arcs = Options.AR;
+			this.up += Math.max(arcs, this.items[i].height + this.items[i].down + Options.VS + this.items[i+1].up);
+		}
+		this.down = this.items[last].down;
+		for(i = normal+1; i <= last; i++) {
+			if(i == normal+1) arcs = Options.AR*2;
+			else arcs = Options.AR;
+			this.down += Math.max(arcs, this.items[i-1].height + this.items[i-1].down + Options.VS + this.items[i].up);
+		}
+		this.down -= this.items[normal].height; // already counted in Choice.height
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "choice";
+		}
+	}
+	format(x,y,width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		var last = this.items.length -1;
+		var innerWidth = this.width - Options.AR*4;
+
+		// Do the elements that curve above
+		var distanceFromY;
+		for(var i = this.normal - 1; i >= 0; i--) {
+			let item = this.items[i];
+			if( i == this.normal - 1 ) {
+				distanceFromY = Math.max(Options.AR*2, this.items[this.normal].up + Options.VS + item.down + item.height);
+			}
+			new Path(x,y)
+				.arc('se')
+				.up(distanceFromY - Options.AR*2)
+				.arc('wn').addTo(this);
+			item.format(x+Options.AR*2,y - distanceFromY,innerWidth).addTo(this);
+			new Path(x+Options.AR*2+innerWidth, y-distanceFromY+item.height)
+				.arc('ne')
+				.down(distanceFromY - item.height + this.height - Options.AR*2)
+				.arc('ws').addTo(this);
+			distanceFromY += Math.max(Options.AR, item.up + Options.VS + (i === 0 ? 0 : this.items[i-1].down+this.items[i-1].height));
+		}
+
+		// Do the straight-line path.
+		new Path(x,y).right(Options.AR*2).addTo(this);
+		this.items[this.normal].format(x+Options.AR*2, y, innerWidth).addTo(this);
+		new Path(x+Options.AR*2+innerWidth, y+this.height).right(Options.AR*2).addTo(this);
+
+		// Do the elements that curve below
+		for(i = this.normal+1; i <= last; i++) {
+			let item = this.items[i];
+			if( i == this.normal + 1 ) {
+				distanceFromY = Math.max(Options.AR*2, this.height + this.items[this.normal].down + Options.VS + item.up);
+			}
+			new Path(x,y)
+				.arc('ne')
+				.down(distanceFromY - Options.AR*2)
+				.arc('ws').addTo(this);
+			item.format(x+Options.AR*2, y+distanceFromY, innerWidth).addTo(this);
+			new Path(x+Options.AR*2+innerWidth, y+distanceFromY+item.height)
+				.arc('se')
+				.up(distanceFromY - Options.AR*2 + item.height - this.height)
+				.arc('wn').addTo(this);
+			distanceFromY += Math.max(Options.AR, item.height + item.down + Options.VS + (i == last ? 0 : this.items[i+1].up));
+		}
+
+		return this;
+	}
+}
+funcs.Choice = (...args)=>new Choice(...args);
+
+
+export class HorizontalChoice extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		if( items.length === 0 ) {
+			throw new RangeError("HorizontalChoice() must have at least one child.");
+		}
+		if( items.length === 1) {
+			return new Sequence(items);
+		}
+		const allButLast = this.items.slice(0, -1);
+		const middles = this.items.slice(1, -1);
+		const first = this.items[0];
+		const last = this.items[this.items.length - 1];
+		this.needsSpace = false;
+
+		this.width = Options.AR; // starting track
+		this.width += Options.AR*2 * (this.items.length-1); // inbetween tracks
+		this.width += sum(this.items, x=>x.width + (x.needsSpace?20:0)); // items
+		this.width += (last.height > 0 ? Options.AR : 0); // needs space to curve up
+		this.width += Options.AR; //ending track
+
+		// Always exits at entrance height
+		this.height = 0;
+
+		// All but the last have a track running above them
+		this._upperTrack = Math.max(
+			Options.AR*2,
+			Options.VS,
+			max(allButLast, x=>x.up) + Options.VS
+		);
+		this.up = Math.max(this._upperTrack, last.up);
+
+		// All but the first have a track running below them
+		// Last either straight-lines or curves up, so has different calculation
+		this._lowerTrack = Math.max(
+			Options.VS,
+			max(middles, x=>x.height+Math.max(x.down+Options.VS, Options.AR*2)),
+			last.height + last.down + Options.VS
+		);
+		if(first.height < this._lowerTrack) {
+			// Make sure there's at least 2*AR room between first exit and lower track
+			this._lowerTrack = Math.max(this._lowerTrack, first.height + Options.AR*2);
+		}
+		this.down = Math.max(this._lowerTrack, first.height + first.down);
+
+
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "horizontalchoice";
+		}
+	}
+	format(x,y,width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		const first = this.items[0];
+		const last = this.items[this.items.length-1];
+		const allButFirst = this.items.slice(1);
+		const allButLast = this.items.slice(0, -1);
+
+		// upper track
+		var upperSpan = (sum(allButLast, x=>x.width+(x.needsSpace?20:0))
+			+ (this.items.length - 2) * Options.AR*2
+			- Options.AR
+		);
+		new Path(x,y)
+			.arc('se')
+			.v(-(this._upperTrack - Options.AR*2))
+			.arc('wn')
+			.h(upperSpan)
+			.addTo(this);
+
+		// lower track
+		var lowerSpan = (sum(allButFirst, x=>x.width+(x.needsSpace?20:0))
+			+ (this.items.length - 2) * Options.AR*2
+			+ (last.height > 0 ? Options.AR : 0)
+			- Options.AR
+		);
+		var lowerStart = x + Options.AR + first.width+(first.needsSpace?20:0) + Options.AR*2;
+		new Path(lowerStart, y+this._lowerTrack)
+			.h(lowerSpan)
+			.arc('se')
+			.v(-(this._lowerTrack - Options.AR*2))
+			.arc('wn')
+			.addTo(this);
+
+		// Items
+		for(const [i, item] of enumerate(this.items)) {
+			// input track
+			if(i === 0) {
+				new Path(x,y)
+					.h(Options.AR)
+					.addTo(this);
+				x += Options.AR;
+			} else {
+				new Path(x, y - this._upperTrack)
+					.arc('ne')
+					.v(this._upperTrack - Options.AR*2)
+					.arc('ws')
+					.addTo(this);
+				x += Options.AR*2;
+			}
+
+			// item
+			var itemWidth = item.width + (item.needsSpace?20:0);
+			item.format(x, y, itemWidth).addTo(this);
+			x += itemWidth;
+
+			// output track
+			if(i === this.items.length-1) {
+				if(item.height === 0) {
+					new Path(x,y)
+						.h(Options.AR)
+						.addTo(this);
+				} else {
+					new Path(x,y+item.height)
+					.arc('se')
+					.addTo(this);
+				}
+			} else if(i === 0 && item.height > this._lowerTrack) {
+				// Needs to arc up to meet the lower track, not down.
+				if(item.height - this._lowerTrack >= Options.AR*2) {
+					new Path(x, y+item.height)
+						.arc('se')
+						.v(this._lowerTrack - item.height + Options.AR*2)
+						.arc('wn')
+						.addTo(this);
+				} else {
+					// Not enough space to fit two arcs
+					// so just bail and draw a straight line for now.
+					new Path(x, y+item.height)
+						.l(Options.AR*2, this._lowerTrack - item.height)
+						.addTo(this);
+				}
+			} else {
+				new Path(x, y+item.height)
+					.arc('ne')
+					.v(this._lowerTrack - item.height - Options.AR*2)
+					.arc('ws')
+					.addTo(this);
+			}
+		}
+		return this;
+	}
+}
+funcs.HorizontalChoice = (...args)=>new HorizontalChoice(...args);
+
+
+export class MultipleChoice extends DiagramMultiContainer {
+	constructor(normal, type, ...items) {
+		super('g', items);
+		if( typeof normal !== "number" || normal !== Math.floor(normal) ) {
+			throw new TypeError("The first argument of MultipleChoice() must be an integer.");
+		} else if(normal < 0 || normal >= items.length) {
+			throw new RangeError("The first argument of MultipleChoice() must be an index for one of the items.");
+		} else {
+			this.normal = normal;
+		}
+		if( type != "any" && type != "all" ) {
+			throw new SyntaxError("The second argument of MultipleChoice must be 'any' or 'all'.");
+		} else {
+			this.type = type;
+		}
+		this.needsSpace = true;
+		this.innerWidth = max(this.items, function(x){return x.width});
+		this.width = 30 + Options.AR + this.innerWidth + Options.AR + 20;
+		this.up = this.items[0].up;
+		this.down = this.items[this.items.length-1].down;
+		this.height = this.items[normal].height;
+		for(var i = 0; i < this.items.length; i++) {
+			let item = this.items[i];
+			let minimum;
+			if(i == normal - 1 || i == normal + 1) minimum = 10 + Options.AR;
+			else minimum = Options.AR;
+			if(i < normal) {
+				this.up += Math.max(minimum, item.height + item.down + Options.VS + this.items[i+1].up);
+			} else if(i > normal) {
+				this.down += Math.max(minimum, item.up + Options.VS + this.items[i-1].down + this.items[i-1].height);
+			}
+		}
+		this.down -= this.items[normal].height; // already counted in this.height
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "multiplechoice";
+		}
+	}
+	format(x, y, width) {
+		var gaps = determineGaps(width, this.width);
+		new Path(x, y).right(gaps[0]).addTo(this);
+		new Path(x + gaps[0] + this.width, y + this.height).right(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		var normal = this.items[this.normal];
+
+		// Do the elements that curve above
+		var distanceFromY;
+		for(var i = this.normal - 1; i >= 0; i--) {
+			var item = this.items[i];
+			if( i == this.normal - 1 ) {
+				distanceFromY = Math.max(10 + Options.AR, normal.up + Options.VS + item.down + item.height);
+			}
+			new Path(x + 30,y)
+				.up(distanceFromY - Options.AR)
+				.arc('wn').addTo(this);
+			item.format(x + 30 + Options.AR, y - distanceFromY, this.innerWidth).addTo(this);
+			new Path(x + 30 + Options.AR + this.innerWidth, y - distanceFromY + item.height)
+				.arc('ne')
+				.down(distanceFromY - item.height + this.height - Options.AR - 10)
+				.addTo(this);
+			if(i !== 0) {
+				distanceFromY += Math.max(Options.AR, item.up + Options.VS + this.items[i-1].down + this.items[i-1].height);
+			}
+		}
+
+		new Path(x + 30, y).right(Options.AR).addTo(this);
+		normal.format(x + 30 + Options.AR, y, this.innerWidth).addTo(this);
+		new Path(x + 30 + Options.AR + this.innerWidth, y + this.height).right(Options.AR).addTo(this);
+
+		for(i = this.normal+1; i < this.items.length; i++) {
+			let item = this.items[i];
+			if(i == this.normal + 1) {
+				distanceFromY = Math.max(10+Options.AR, normal.height + normal.down + Options.VS + item.up);
+			}
+			new Path(x + 30, y)
+				.down(distanceFromY - Options.AR)
+				.arc('ws')
+				.addTo(this);
+			item.format(x + 30 + Options.AR, y + distanceFromY, this.innerWidth).addTo(this);
+			new Path(x + 30 + Options.AR + this.innerWidth, y + distanceFromY + item.height)
+				.arc('se')
+				.up(distanceFromY - Options.AR + item.height - normal.height)
+				.addTo(this);
+			if(i != this.items.length - 1) {
+				distanceFromY += Math.max(Options.AR, item.height + item.down + Options.VS + this.items[i+1].up);
+			}
+		}
+		var text = new FakeSVG('g', {"class": "diagram-text"}).addTo(this);
+		new FakeSVG('title', {}, (this.type=="any"?"take one or more branches, once each, in any order":"take all branches, once each, in any order")).addTo(text);
+		new FakeSVG('path', {
+			"d": "M "+(x+30)+" "+(y-10)+" h -26 a 4 4 0 0 0 -4 4 v 12 a 4 4 0 0 0 4 4 h 26 z",
+			"class": "diagram-text"
+			}).addTo(text);
+		new FakeSVG('text', {
+			"x": x + 15,
+			"y": y + 4,
+			"class": "diagram-text"
+			}, (this.type=="any"?"1+":"all")).addTo(text);
+		new FakeSVG('path', {
+			"d": "M "+(x+this.width-20)+" "+(y-10)+" h 16 a 4 4 0 0 1 4 4 v 12 a 4 4 0 0 1 -4 4 h -16 z",
+			"class": "diagram-text"
+			}).addTo(text);
+		new FakeSVG('path', {
+			"d": "M "+(x+this.width-13)+" "+(y-2)+" a 4 4 0 1 0 6 -1 m 2.75 -1 h -4 v 4 m 0 -3 h 2",
+			"style": "stroke-width: 1.75"
+			}).addTo(text);
+		return this;
+	}
+}
+funcs.MultipleChoice = (...args)=>new MultipleChoice(...args);
+
+
+export class Optional extends FakeSVG {
+	constructor(item, skip) {
+		if( skip === undefined )
+			return new Choice(1, new Skip(), item);
+		else if ( skip === "skip" )
+			return new Choice(0, new Skip(), item);
+		else
+			throw "Unknown value for Optional()'s 'skip' argument.";
+	}
+}
+funcs.Optional = (...args)=>new Optional(...args);
+
+
+export class OneOrMore extends FakeSVG {
+	constructor(item, rep) {
+		super('g');
+		rep = rep || (new Skip());
+		this.item = wrapString(item);
+		this.rep = wrapString(rep);
+		this.width = Math.max(this.item.width, this.rep.width) + Options.AR*2;
+		this.height = this.item.height;
+		this.up = this.item.up;
+		this.down = Math.max(Options.AR*2, this.item.down + Options.VS + this.rep.up + this.rep.height + this.rep.down);
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "oneormore";
+		}
+	}
+	format(x,y,width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		// Draw item
+		new Path(x,y).right(Options.AR).addTo(this);
+		this.item.format(x+Options.AR,y,this.width-Options.AR*2).addTo(this);
+		new Path(x+this.width-Options.AR,y+this.height).right(Options.AR).addTo(this);
+
+		// Draw repeat arc
+		var distanceFromY = Math.max(Options.AR*2, this.item.height+this.item.down+Options.VS+this.rep.up);
+		new Path(x+Options.AR,y).arc('nw').down(distanceFromY-Options.AR*2).arc('ws').addTo(this);
+		this.rep.format(x+Options.AR, y+distanceFromY, this.width - Options.AR*2).addTo(this);
+		new Path(x+this.width-Options.AR, y+distanceFromY+this.rep.height).arc('se').up(distanceFromY-Options.AR*2+this.rep.height-this.item.height).arc('en').addTo(this);
+
+		return this;
+	}
+	walk(cb) {
+		cb(this);
+		this.item.walk(cb);
+		this.rep.walk(cb);
+	}
+}
+funcs.OneOrMore = (...args)=>new OneOrMore(...args);
+
+
+export class ZeroOrMore extends FakeSVG {
+	constructor(item, rep, skip) {
+		return new Optional(new OneOrMore(item, rep), skip);
+	}
+}
+funcs.ZeroOrMore = (...args)=>new ZeroOrMore(...args);
+
+
+export class Group extends FakeSVG {
+	constructor(item, label) {
+		super('g');
+		this.item = wrapString(item);
+		this.label =
+			label instanceof FakeSVG
+			  ? label
+			: label
+			  ? new Comment(label)
+			  : undefined;
+
+		this.width = Math.max(
+			this.item.width + (this.item.needsSpace?20:0),
+			this.label ? this.label.width : 0,
+			Options.AR*2);
+		this.height = this.item.height;
+		this.boxUp = this.up = Math.max(this.item.up + Options.VS, Options.AR);
+		if(this.label) {
+			this.up += this.label.up + this.label.height + this.label.down;
+		}
+		this.down = Math.max(this.item.down + Options.VS, Options.AR);
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "group";
+		}
+	}
+	format(x, y, width) {
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		new FakeSVG('rect', {
+			x,
+			y:y-this.boxUp,
+			width:this.width,
+			height:this.boxUp + this.height + this.down,
+			rx: Options.AR,
+			ry: Options.AR,
+			'class':'group-box',
+		}).addTo(this);
+
+		this.item.format(x,y,this.width).addTo(this);
+		if(this.label) {
+			this.label.format(
+				x,
+				y-(this.boxUp+this.label.down+this.label.height),
+				this.label.width).addTo(this);
+		}
+
+		return this;
+	}
+	walk(cb) {
+		cb(this);
+		this.item.walk(cb);
+		this.label.walk(cb);
+	}
+}
+funcs.Group = (...args)=>new Group(...args);
+
+
+export class Start extends FakeSVG {
+	constructor({type="simple", label}={}) {
+		super('g');
+		this.width = 20;
+		this.height = 0;
+		this.up = 10;
+		this.down = 10;
+		this.type = type;
+		if(label) {
+			this.label = ""+label;
+			this.width = Math.max(20, this.label.length * Options.CHAR_WIDTH + 10);
+		}
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "start";
+		}
+	}
+	format(x,y) {
+		let path = new Path(x, y-10);
+		if (this.type === "complex") {
+			path.down(20)
+				.m(0, -10)
+				.right(this.width)
+				.addTo(this);
+		} else {
+			path.down(20)
+				.m(10, -20)
+				.down(20)
+				.m(-10, -10)
+				.right(this.width)
+				.addTo(this);
+		}
+		if(this.label) {
+			new FakeSVG('text', {x:x, y:y-15, style:"text-anchor:start"}, this.label).addTo(this);
+		}
+		return this;
+	}
+}
+funcs.Start = (...args)=>new Start(...args);
+
+
+export class End extends FakeSVG {
+	constructor({type="simple"}={}) {
+		super('path');
+		this.width = 20;
+		this.height = 0;
+		this.up = 10;
+		this.down = 10;
+		this.type = type;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "end";
+		}
+	}
+	format(x,y) {
+		if (this.type === "complex") {
+			this.attrs.d = 'M '+x+' '+y+' h 20 m 0 -10 v 20';
+		} else {
+			this.attrs.d = 'M '+x+' '+y+' h 20 m -10 -10 v 20 m 10 -20 v 20';
+		}
+		return this;
+	}
+}
+funcs.End = (...args)=>new End(...args);
+
+
+export class Terminal extends FakeSVG {
+	constructor(text, {href, title, cls}={}) {
+		super('g', {'class': ['terminal', cls].join(" ")});
+		this.text = ""+text;
+		this.href = href;
+		this.title = title;
+		this.cls = cls;
+		this.width = this.text.length * Options.CHAR_WIDTH + 20; /* Assume that each char is .5em, and that the em is 16px */
+		this.height = 0;
+		this.up = 11;
+		this.down = 11;
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "terminal";
+		}
+	}
+	format(x, y, width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		new FakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down, rx:10, ry:10}).addTo(this);
+		var text = new FakeSVG('text', {x:x+this.width/2, y:y+4}, this.text);
+		if(this.href)
+			new FakeSVG('a', {'xlink:href': this.href}, [text]).addTo(this);
+		else
+			text.addTo(this);
+		if(this.title)
+			new FakeSVG('title', {}, [this.title]).addTo(this);
+		return this;
+	}
+}
+funcs.Terminal = (...args)=>new Terminal(...args);
+
+
+export class NonTerminal extends FakeSVG {
+	constructor(text, {href, title, cls=""}={}) {
+		super('g', {'class': ['non-terminal', cls].join(" ")});
+		this.text = ""+text;
+		this.href = href;
+		this.title = title;
+		this.cls = cls;
+		this.width = this.text.length * Options.CHAR_WIDTH + 20;
+		this.height = 0;
+		this.up = 11;
+		this.down = 11;
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "nonterminal";
+		}
+	}
+	format(x, y, width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		new FakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down}).addTo(this);
+		var text = new FakeSVG('text', {x:x+this.width/2, y:y+4}, this.text);
+		if(this.href)
+			new FakeSVG('a', {'xlink:href': this.href}, [text]).addTo(this);
+		else
+			text.addTo(this);
+		if(this.title)
+			new FakeSVG('title', {}, [this.title]).addTo(this);
+		return this;
+	}
+}
+funcs.NonTerminal = (...args)=>new NonTerminal(...args);
+
+
+export class Comment extends FakeSVG {
+	constructor(text, {href, title, cls=""}={}) {
+		super('g', {'class': ['comment', cls].join(" ")});
+		this.text = ""+text;
+		this.href = href;
+		this.title = title;
+		this.cls = cls;
+		this.width = this.text.length * Options.COMMENT_CHAR_WIDTH + 10;
+		this.height = 0;
+		this.up = 8;
+		this.down = 8;
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "comment";
+		}
+	}
+	format(x, y, width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		var text = new FakeSVG('text', {x:x+this.width/2, y:y+5, class:'comment'}, this.text);
+		if(this.href)
+			new FakeSVG('a', {'xlink:href': this.href}, [text]).addTo(this);
+		else
+			text.addTo(this);
+		if(this.title)
+			new FakeSVG('title', {}, this.title).addTo(this);
+		return this;
+	}
+}
+funcs.Comment = (...args)=>new Comment(...args);
+
+
+export class Skip extends FakeSVG {
+	constructor() {
+		super('g');
+		this.width = 0;
+		this.height = 0;
+		this.up = 0;
+		this.down = 0;
+		this.needsSpace = false;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "skip";
+		}
+	}
+	format(x, y, width) {
+		new Path(x,y).right(width).addTo(this);
+		return this;
+	}
+}
+funcs.Skip = (...args)=>new Skip(...args);
+
+
+export class Block extends FakeSVG {
+	constructor({width=50, up=15, height=25, down=15, needsSpace=true}={}) {
+		super('g');
+		this.width = width;
+		this.height = height;
+		this.up = up;
+		this.down = down;
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "block";
+		}
+	}
+	format(x, y, width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		new FakeSVG('rect', {x:x, y:y-this.up, width:this.width, height:this.up+this.height+this.down}).addTo(this);
+		return this;
+	}
+}
+funcs.Block = (...args)=>new Block(...args);
+
+
+function unnull(...args) {
+	// Return the first value that isn't undefined.
+	// More correct than `v1 || v2 || v3` because falsey values will be returned.
+	return args.reduce(function(sofar, x) { return sofar !== undefined ? sofar : x; });
+}
+
+function determineGaps(outer, inner) {
+	var diff = outer - inner;
+	switch(Options.INTERNAL_ALIGNMENT) {
+		case 'left': return [0, diff];
+		case 'right': return [diff, 0];
+		default: return [diff/2, diff/2];
+	}
+}
+
+function wrapString(value) {
+		return value instanceof FakeSVG ? value : new Terminal(""+value);
+}
+
+function sum(iter, func) {
+	if(!func) func = function(x) { return x; };
+	return iter.map(func).reduce(function(a,b){return a+b}, 0);
+}
+
+function max(iter, func) {
+	if(!func) func = function(x) { return x; };
+	return Math.max.apply(null, iter.map(func));
+}
+
+function SVG(name, attrs, text) {
+	attrs = attrs || {};
+	text = text || '';
+	var el = document.createElementNS("http://www.w3.org/2000/svg",name);
+	for(var attr in attrs) {
+		if(attr === 'xlink:href')
+			el.setAttributeNS("http://www.w3.org/1999/xlink", 'href', attrs[attr]);
+		else
+			el.setAttribute(attr, attrs[attr]);
+	}
+	el.textContent = text;
+	return el;
+}
+
+function escapeString(string) {
+	// Escape markdown and HTML special characters
+	return string.replace(/[*_\`\[\]<&]/g, function(charString) {
+		return '&#' + charString.charCodeAt(0) + ';';
+	});
+}
+
+function* enumerate(iter) {
+	var count = 0;
+	for(const x of iter) {
+		yield [count, x];
+		count++;
+	}
+}
diff --git a/assets/css/styles.css b/assets/css/styles.css
index 590c1cd..af0a5bf 100644
--- a/assets/css/styles.css
+++ b/assets/css/styles.css
@@ -357,6 +357,30 @@
 
 @media (max-width: 570px) { body > footer .copyright__extra { display: none; } }
 
+.diagram-container svg { background-color: white; }
+
+.diagram-container path { stroke-width: 2; stroke: black; fill: rgba(0, 0, 0, 0); }
+
+.diagram-container text { font: bold 14px monospace; text-anchor: middle; white-space: pre; }
+
+.diagram-container text.diagram-text { font-size: 12px; }
+
+.diagram-container text.diagram-arrow { font-size: 16px; }
+
+.diagram-container text.label { text-anchor: start; }
+
+.diagram-container text.comment { font: italic 12px monospace; }
+
+.diagram-container g .non-terminal text { /*font-style: italic;*/ }
+
+.diagram-container rect { stroke-width: 2; stroke: black; fill: white; }
+
+.diagram-container rect.group-box { stroke: gray; stroke-dasharray: 10 5; fill: none; }
+
+.diagram-container path.diagram-text { stroke-width: 2; stroke: black; fill: white; cursor: help; }
+
+.diagram-container g.diagram-text:hover path.diagram-text { fill: #eee; }
+
 section.page-docs { display: grid; transition: grid-template-columns 0.15s; grid-template-columns: auto 1fr auto; grid-template-rows: 100%; grid-template-areas: 'left-nav content right-nav'; line-height: 20px; max-width: 1440px; margin: auto; width: 100%; }
 
 section.page-docs > article { border-left: 1px solid #eeeeee; background-color: #ffffff; padding: 0 50px 30px; grid-area: content; overflow: hidden; font-family: sans-serif; font-size: 16px; color: #545454; line-height: 1.6em; }
diff --git a/assets/css/styles.css.map b/assets/css/styles.css.map
index 42b2c93..ef19767 100644
--- a/assets/css/styles.css.map
+++ b/assets/css/styles.css.map
@@ -13,11 +13,12 @@
 		"_sass/left-nav.scss",
 		"_sass/right-nav.scss",
 		"_sass/footer.scss",
+		"_sass/railroad-diagram.scss",
 		"_sass/docs.scss",
 		"_sass/asciidoc-pygments.scss"
 	],
 	"sourcesContent": [
-		"@import \"variables\";\n@import \"header\";\n@import \"code\";\n@import \"rouge-base16-solarized\";\n@import \"text\";\n@import \"callouts\";\n@import \"layout\";\n@import \"left-nav\";\n@import \"right-nav\";\n@import \"footer\";\n\n@import \"docs\";\n\n@import \"asciidoc-pygments\";",
+		"@import \"variables\";\n@import \"header\";\n@import \"code\";\n@import \"rouge-base16-solarized\";\n@import \"text\";\n@import \"callouts\";\n@import \"layout\";\n@import \"left-nav\";\n@import \"right-nav\";\n@import \"footer\";\n@import 'railroad-diagram';\n\n@import \"docs\";\n\n@import \"asciidoc-pygments\";",
 		":root {\n    --gg-red: #ec1c24;\n    --gg-orange: #ec1c24;\n    --gg-orange-dark: #bc440b;\n    --gg-orange-filter: invert(47%) sepia(61%) saturate(1950%) hue-rotate(345deg) brightness(100%) contrast(95%);\n    --gg-dark-gray: #333333;\n    --orange-line-thickness: 3px;\n    --block-code-background: rgba(241, 241, 241, 20%);\n    --inline-code-background: rgba(241, 241, 241, 90%);\n    --padding-top: 25px; \n    --link-color: #ec1c24;\n    --body-background: #fcfcfc;\n}\n\n@font-face {\n    font-family: 'Open Sans';\n    font-weight: 300;\n    font-display: swap;\n    font-style: normal;\n}\n",
 		"header {\n\n    min-height: var(--header-height);\n    background: white;\n    box-shadow: 0 4px 10px 0 #eeeeee, 0 0 4px 0 #d5d5d5;\n    \n\n    z-index: 1;\n\n    #promotion-bar {\n        background-color: #333333;\n        padding: 8px;\n        \n        p {\n            font-size: 14px;\n            line-height: 1.4em;\n            font-weight: 600;\n            padding: 0;\n            margin: 0;\n\n            color: #f0f0f0;\n            text-align: center;\n\n            a {\n                color: #FCB903;\n            }\n        }\n    }\n\n\n    > .container {\n        display: grid;\n        grid-template-columns: auto auto 1fr auto auto auto;\n        grid-template-areas: 'left-toggle home nav ver api search lang';\n        grid-template-rows: 40px;\n        flex-direction: row;\n        align-items: center;\n        justify-content: flex-start;\n        padding: 12px 20px;\n        max-width: 1400px;\n        margin: 0 auto;\n    }\n\n    a:hover, button:hover {\n        opacity: 0.85;\n    }\n\n    li:hover .dropdown, a:focus + .dropdown {\n        display: block;\n    }\n\n    .dropdown-arrow {\n        margin-left: 5px;\n        margin-bottom: 3px;\n\n        width: 8px;\n        height: 4px;\n    }\n\n    nav > ul {\n        padding: 0;\n        margin: 0;\n        list-style: none;\n        display: inherit;\n    }\n\n    .dropdown {\n        display: none;\n        position: fixed;\n        top: calc(var(--header-height) - 12px);\n        width: auto;\n        background: white;\n        box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.24), 0 0 4px 0 rgba(0, 0, 0, 0.12);\n        border-radius: 4px;\n        padding-top: 10px;\n        padding-bottom: 12px;\n        z-index: 2;\n\n        \n\n        li {\n            display: flex;\n        }\n\n        a {\n            color: grey !important;\n            font-size: 16px;\n            padding-top: 5px;\n            padding-bottom: 4px;\n            &:hover {\n                color: var(--gg-orange) !important;\n            }\n        }\n    }\n\n    .menu {\n        border: none;\n        background: none;\n        width: 40px;\n        height: 40px;\n        margin-right: 12px;\n        cursor: pointer;\n        grid-area: left-toggle;\n\n        img {\n            width: 18px;\n            height: 12px;\n        }\n    }\n\n    .search-toggle, .top-nav-toggle, .github, .search-close {\n        background: none;\n        border: none;\n        padding: 0;\n        width: 36px;\n        height: 36px;\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        color: var(--gg-dark-gray);\n        font-size: 26px;\n    }\n    .search-toggle {\n        grid-area: search;\n    }\n    .top-nav-toggle {\n        grid-area: top-toggle;\n    }\n\n    .home {\n        \n        grid-area: home;\n        margin-right: auto;\n        img {\n            height: 36px;\n        }\n    }\n\n    #api-docs {\n        grid-area: api;\n        margin: 0;\n        // font-weight: 600;\n        display: flex;\n\n        > li {\n            list-style: none;\n            margin-right: 0.5em;\n            display: flex;\n        }\n\n        .dropdown {\n            padding: .5em 0;\n        }\n        \n        .dropdown-item-heading, a {\n            padding: 9px 14px;\n            color: var(--gg-dark-gray) !important;\n            text-decoration: none;\n            white-space: nowrap;\n\n            &.active {\n                border-radius: 3px;\n                background-color: #f0f0f0;\n            }\n        }\n\n        .dropdown-item {\n            a {\n                font-weight: normal;\n                display: block;\n                width: 100%;\n                min-width: 150px;\n\n                &:hover {\n                    background-color: #e9e9e9;\n                }\n            }\n        }\n\n        .dropdown-item-heading {\n            font-weight: bold;\n            color: grey !important;\n            border-bottom: 2px solid #e9e9e9;\n            padding-left: 0;\n        }\n\n    }\n    \n    #lang-selector {\n        li {\n            list-style: none;\n            display: flex;\n            padding: 9px 14px;\n\n\n            a {\n\n                display: flex;\n                color: #000000;\n                align-items: center;\n\n                \n                span {\n                    font-size: 10px;\n                    margin-left: 5px;\n                }\n\n\n                img {\n                    width: 25px;\n                }\n\n                \n            }\n\n            .dropdown {\n                margin-left: -70px;\n\n                .dropdown-item {\n                    padding: 0 1em;\n                    margin-bottom: 8px;\n\n                    &:hover {\n                        background-color: #e9e9e9;\n                    }\n\n                    a {\n                        span {\n                            font-size: 14px;\n                        }\n                        &:hover {\n                            color: #000000;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n\n    .search {\n        margin-left: auto;\n        margin-right: 20px;\n        grid-area: search;\n\n        input[type='search'] {\n            color: var(--gg-dark-gray);\n            \n            background: rgba(255, 255, 255, 0.8);\n            border: 1px solid #cccccc;\n            padding: 10px 15px;\n            font-family: inherit;\n            max-width: 148px;\n            height: 37px;\n            font-size: 14px;\n            -webkit-appearance: unset;\n            appearance: unset;\n\n            &[disabled] {\n                opacity: 0.5;\n                cursor: not-allowed;\n            }\n        }\n\n    }\n\n    #version-selector {\n        list-style: none;\n        grid-area: ver;\n        line-height: 28px;\n        border-radius: 0px;\n        margin-right: 10px;\n        border: none;\n        color: var(--gg-dark-gray);\n        \n        padding: 5px 16px 5px 10px;\n        white-space: nowrap;\n        font-size: 14px;\n        width: auto;\n        text-align: right;\n        background:  transparent url(\"/assets/images/arrow-down.svg\") no-repeat center right 5px;\n        box-sizing: border-box;\n        text-align-last: right;\n        -moz-appearance: none;\n        -webkit-appearance: none;\n        appearance: none;\n\n        direction: rtl;\n\n        option {\n            direction: ltr;\n        }\n        \n    }\n    \n         \n\n    &>nav {\n        grid-area: nav;\n        font-size: 18px;\n        display: flex;\n        flex-direction: row;\n        margin: 0 20px;\n\n        li {\n            list-style: none;\n            margin-right: 0.5em;\n            display: flex;\n        }\n\n        a {\n            padding: 9px 14px;\n            color: var(--gg-dark-gray) !important;\n            text-decoration: none;\n            white-space: nowrap;\n\n            &.active {\n                border-radius: 3px;\n                background-color: #f0f0f0;\n            }\n        }\n    }\n\n    #lang-selector {\n        grid-area: lang;\n    }\n\n\n    .search-close {\n        margin-right: 10px;\n    }\n\n\n    \n\n    @media (max-width: 600px) {\n        .search {\n            margin-right: 5px;\n            input[type='search'] {\n                max-width: 110px;\n            }\n        }\n    }\n\n    &:not(.narrow-header) {\n        .search-toggle, .top-nav-toggle, .search-close {\n            display: none;\n        }\n    }\n    &.narrow-header {\n        a.home {\n            top: 0;\n        }\n        &:not(.show-nav) {\n            nav {\n                display: none;\n            }\n        }\n        &.show-search {\n            .search-toggle, .home, .top-nav-toggle, .github, .menu {\n                display: none;\n            }\n            .search {\n                grid-column-start: home;\n                grid-column-end: github;\n                width: 100%;\n                display: flex;\n\n                input {\n                    max-width: initial;\n                    width: 100%;\n                }\n            }\n        }\n        &:not(.show-search) {\n            .search {\n                display: none;\n            }\n        }\n        nav {\n            flex-direction: column;\n            justify-content: stretch;\n\n            li {\n                display: flex;\n            }\n\n            a {\n                width: 100%;\n            }\n        }\n    }\n}\n.swiftype-widget {\n\n    .autocomplete {\n        background-color: white;\n        display: block;\n        list-style-type: none;\n        margin: 0;\n        padding: 0;\n        box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.37);\n        position: absolute;\n        border-radius: 3px;\n        text-align: left;\n        right: 75px !important;\n        min-width: 350px;\n\n        ul {\n\n            background-color: white;\n            display: block;\n            list-style-type: none;\n            margin: 0;\n            padding: 0;\n            border-radius: 3px;\n            text-align: left;\n            max-height: 70vh;\n            overflow: auto;\n\n            li {\n                border-top: 1px solid #e5e5e5;\n                border-bottom: 1px solid #fff;\n                cursor: pointer;\n                padding: 10px 8px;\n                font-size: 13px;\n                list-style-type: none;\n                background-image: none;\n                margin: 0;\n              }\n\n            li.active {\n                border-top: 1px solid #cccccc;\n                border-bottom: 1px solid #cccccc;\n                background-color: #f0f0f0;\n            }\n            \n            p {\n                font-size: 13px;\n                line-height: 16px;\n                margin: 0;\n                padding: 0;\n\n                &.url {\n                    font-size: 11px;\n                    color: #999;\n                }\n            }\n            \n            a {\n                font-size: 15px;\n            }\n            em {\n                font-weight: bold\n            }\n        }\n    }   \n}\nsection.hero {\n    background-image: url(../images/dev-internal-bg.jpg);\n    background-position: center;\n    background-position-x: left;\n    background-repeat: no-repeat;\n    background-size: cover;\n    display: grid;\n    grid-template-columns: 1fr auto;\n    grid-template-areas: 'title versions';\n    grid-template-rows: 60px;\n    align-items: center;\n    padding: 5px 30px;\n    flex: unset;\n    \n    \n    .title {\n        color: #f3f3f3;\n        text-transform: uppercase;\n        font-size: 22px;\n    }\n\n    select {\n        list-style: none;\n        \n        line-height: 28px;\n        border-radius: 3px;\n    \n        \n        color: #333333;\n        line-height: 24px;\n        padding: 5px 10px;\n        white-space: nowrap;\n        font-size: 14px;\n        background:  #f0f0f0 url(\"/assets/images/arrow-down.svg\") no-repeat center right 5px;\n    }\n}\n\n@media (max-width: 670px) {\n\n    \n    header > .container{\n        grid-template-columns: auto 1fr auto;\n        grid-template-areas: \n            'left-toggle home search'\n            'ver api lang';\n\n         //grid-template-columns: auto auto 1fr auto auto auto;\n         //grid-template-areas:\n         //    'left-toggle home spacer top-toggle search gh gg'\n         //    'nav         nav  nav    nav        nav    nav nav';\n    }\n\n    header #lang-selector li {\n        justify-content: flex-end;\n    }\n    \n}\n\n/* Angolia seach styles */\n\n\n.algolia-autocomplete .algolia-docsearch-suggestion--highlight {\n    color: #ffffff !important;\n    background: lighten(#ec1c24, 25%) !important;\n}\n\n\n.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl0 .algolia-docsearch-suggestion--highlight, .algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl1 .algolia-docsearch-suggestion--highlight, .algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight {\n    padding: 0 0 1px;\n    background: inherit !important;\n    box-shadow: inset 0 -2px 0 0 var(--link-color) !important;\n    color: inherit !important;\n}\n\n.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion.suggestion-layout-simple, .algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion:not(.suggestion-layout-simple) .algolia-docsearch-suggestion--content {\n    background: #f0f0f0 !important;\n}\n",
 		"pre, pre.rouge {\n    padding: 8px 15px;\n    background: var(--block-code-background) !important;\n    border-radius: 5px;\n    border: 1px solid #e5e5e5;\n    overflow-x: auto;\n    // So code copy button doesn't overflow\n    min-height: 36px;\n\tline-height: 18px;\n    color: #545454;\n}\n\ncode {\n    color: #545454;\n}\n\npre.rouge code {\n    background: none !important;\n}\n\npre.rouge .tok-err {\n  \tborder: none !important;\n  }\n\ncode-tabs.code-tabs__initialized {\n    display: block;\n    margin-bottom: 1.5em;\n\n    nav {\n        border-bottom: 1px solid #e0e0e0\n    }\n\n    nav button {\n        background: white;\n        color: inherit;\n        border: none;\n        padding: 0.7em 1em;\n        cursor: pointer;\n        transform: translateY(1px);\n\t\tfont-size: .9em;\n\n        &.active {\n            border-bottom: var(--orange-line-thickness) solid var(--link-color);\n        }\n\t\t&.grey {\n\t\t  color: grey;\n\t\t}\n    }\n\n    code-tab:not([hidden]) {\n        display: block;\n    }\n}\n\n*:not(pre) > code {\n    background: var(--inline-code-background);\n    padding: 0.1em 0.5em;\n    background-clip: padding-box;\n    border-radius: 3px;\n    color: #545454;\n    font-size: 90%\n}\n\n// Required for copy button positioning\n.listingblock .content {\n    position: relative;\n}\n\n.copy-to-clipboard-button {\n    margin: 0;\n    padding: 0;\n    width: 36px;\n    height: 36px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    background: none;\n    border: none;\n\n    position: absolute;\n    top: 0;\n    right: 0;\n    background: url('../images/copy-icon.svg') center center no-repeat;\n\n    &.copy-to-clipboard-button__success {\n        color: green;\n        background: none;\n        font-size: 20px;\n        font-weight: bold;\n    }\n\n    &:hover:not(.copy-to-clipboard-button__success) {\n        filter: var(--gg-orange-filter);\n    }\n}\n",
@@ -28,9 +29,10 @@
 		".left-nav {\n    padding: 10px 20px;\n    width: 289px;\n    overflow-y: auto;\n    top: calc(var(--header-height) + var(--promotion-bar-height));\n    height: calc(100vh - var(--header-height) - var(--promotion-bar-height));\n    font-family: 'Open Sans';\n    padding-top: var(--padding-top);\n    background-color: var(--body-background);\n\n    li {\n        list-style: none;\n    }    \n    a, button {\n        text-decoration: none;\n        color: #757575;\n        font-size: 16px;\n        display: inline-flex;\n        width: 100%;\n        margin: 2px 0;\n        padding: 0.25em 0.375em;\n        background: none;\n        border: none;\n        cursor: pointer;\n        font: inherit;\n        text-align: left;\n\n        &.active, &:hover {\n            color: var(--link-color);\n        }\n    }\n\n\t*:focus {\n\t   \t outline: none;\n\t}\n\n    .nav-group {\n        margin-left: 6px;\n        font-size: 14px;\n    }\n\n    nav {\n        border-left: 2px solid #dddddd;\n//        margin-top: 5px;\n        margin-bottom: 5px;\n\n        &.collapsed {\n            display: none;\n        }\n    }\n\n    nav > li > a, nav > li > button {\n        padding-left: 20px;\n        text-align: left;\n\n        &.active {\n            border-left: var(--orange-line-thickness) solid var(--active-color);\n            padding-left: calc(20px - var(--orange-line-thickness));\n        }\n    }\n\n    nav.sub_pages {\n        border: none;\n    }\n\n\tnav.sub_pages a, nav.sub_pages button {\n        padding-left: 32px;\n\n        &.active {\n            padding-left: calc(32px - var(--orange-line-thickness));\n        }\n\t}\n\n    .parent {\n        color: #393939;\n    }\n\n    .state-indicator {\n        margin-left: auto;\n        margin-top: 5px;\n        width: 6.2px;\n        height: 10px;\n        flex: 0 0 auto;\n        transition: transform 0.1s;\n        filter: invert(49%) sepia(4%) saturate(5%) hue-rotate(23deg) brightness(92%) contrast(90%);\n    }\n\n    button:hover .state-indicator,\n    button.current .state-indicator {\n        filter: invert(47%) sepia(61%) saturate(1950%) hue-rotate(345deg) brightness(100%) contrast(95%);\n    }\n\n    button.expanded .state-indicator {\n        transform: rotate(90deg);\n    }\n}\n",
 		".right-nav {\n    width: 289px;\n    padding: 12px 26px;\n    overflow-y: auto;\n    height: calc(100vh - var(--header-height));\n    top: var(--header-height);\n    position: -webkit-sticky;\n    position: sticky;\n    display: flex;\n    flex-direction: column;\n    font-family: 'Open sans';\n    padding-top: var(--padding-top);\n    background-color: #ffffff;\n    \n    h6 {\n        margin: 12px 0;\n        font-size: 16px;\n        font-weight: normal;\n    }\n\n    ul {\n        list-style: none;\n        padding: 0;\n        margin: 0;\n        // margin-bottom: auto;\n    }\n\n    li {\n        padding: 0;\n    }\n\n    a {\n        --border-width: 0px;\n        font-size: 14px;\n        color: #757575;\n        padding-left: calc(15px * var(--nesting-level) + 8px - var(--border-width));\n        margin: 0.3em 0;\n        display: inline-block;\n\n        &:hover {\n          color: var(--link-color);\n        }\n\n        &.active {\n            --border-width: var(--orange-line-thickness);\n            border-left: var(--border-width) solid var(--link-color);\n            color: #393939;\n        }\n    }\n\n    .sectlevel1 {\n        border-left: 2px solid #dddddd;\n    }\n\n    @for $i from 1 through 6 {\n        .sectlevel#{$i} {\n            --nesting-level: #{$i - 1};\n        }\n    }\n\n    .promo-nav {\n        bottom: 3rem;\n        left: 50%;\n        width: 90%;\n        max-width: 237px;\n        margin: auto 0 2rem;\n    }\n}\n@media (max-width: 1200px) {\n    .right-nav {\n        width: 230px;\n    }\n}\n\n\n@media (max-width: 800px) {\n    .right-nav {\n\n        .promo-nav {\n            width: 230px;\n            bottom: 0;\n\n            .right-ad {\n                display: none;\n            }\n        }\n    }        \n}\n",
 		"body > footer {\n    border-top: 2px solid #dddddd;\n    height: var(--footer-height);\n    font-size: 16px;\n    color: #393939;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n\n\n    @media (max-width: 570px) {\n        .copyright__extra {\n            display: none;\n        }\n    }\n}\n// .right-nav footer {\n//     font-size: 12px;\n//     padding: calc(var(--footer-gap) * 0.3) 0 5px;;\n//     text-align: left;\n//     margin: auto 0 0;\n\n//     a {\n//         margin: 0;\n//     }\n\n//     img {\n//         width: 70px;\n//     }\n\n//     .copyright {\n//         display: none;\n//     }\n// }\n",
+		".diagram-container {\n\n  svg {\n    background-color: hsl(0, 0%, 100%);\n  }\n\n  path {\n    stroke-width: 2;\n    stroke: black;\n    fill: rgba(0, 0, 0, 0);\n  }\n\n  text {\n    font: bold 14px monospace;\n    text-anchor: middle;\n    white-space: pre;\n\n    &.diagram-text {\n      font-size: 12px;\n    }\n\n    &.diagram-arrow {\n      font-size: 16px;\n    }\n\n    &.label {\n      text-anchor: start;\n    }\n\n    &.comment {\n      font: italic 12px monospace;\n    }\n  }\n\n  g {\n    .non-terminal {\n      text {\n        /*font-style: italic;*/\n      }\n    }\n  }\n\n  rect {\n    stroke-width: 2;\n    stroke: black;\n    fill: hsl(0, 0%, 100%);\n\n    &.group-box {\n      stroke: gray;\n      stroke-dasharray: 10 5;\n      fill: none;\n    }\n  }\n\n  path.diagram-text {\n    stroke-width: 2;\n    stroke: black;\n    fill: white;\n    cursor: help;\n  }\n\n  g.diagram-text:hover path.diagram-text {\n    fill: #eee;\n  }\n\n}",
 		"section.page-docs {\n    display: grid;\n    transition: grid-template-columns 0.15s;\n    grid-template-columns: auto 1fr auto;\n    grid-template-rows: 100%;\n    grid-template-areas: 'left-nav content right-nav';\n    line-height: 20px;\n    max-width: 1440px;\n    margin: auto;\n    width: 100%;\n\n    &>article {\n        // box-shadow: -1px 13px 20px 0 #696c70;\n        border-left: 1px solid #eeeeee;\n        background-color: #ffffff;\n        padding: 0 50px 30px;\n        grid-area: content;\n        overflow: hidden;\n        font-family: sans-serif;\n        font-size: 16px;\n        color: #545454;\n        line-height: 1.6em;\n\n        h1, h2, h3:not(.discrete), h4, h5, strong, th {\n            font-family: 'Open Sans';\n        }\n\n        li {\n            margin-bottom: 0.5em;\n\n            > p {\n                margin-top: 0;\n                margin-bottom: 0;\n            }\n        }\n\n        img {\n            max-width: 100%;\n            height: auto;\n        }\n\n        @media (max-width: 800px) {\n            padding-left: 15px;\n            padding-right: 15px\n        }\n    }\n\n    .edit-link {\n        position:relative;\n        top: 10px;\n        right:10px;\n        float: right;\n        padding-top: calc(var(--header-height) + var(--padding-top));\n        margin-top: calc((-1 * var(--header-height)));\n    }\n\n    h1, h2, h3:not(.discrete), h4, h5 {\n        margin-bottom: 0;\n\n        &[id] {\n            margin-top:  var(--margin-top);\n            margin-bottom: calc(var(--margin-top) * 0.5);\n            // padding-top: calc(var(--header-height) + var(--padding-top));\n            z-index: -1;\n        }\n    }\n\n\t.toc > ul {\n   \t\t margin: 0;\n\t}\n\n\n\t.content > .pygments.highlight {\n\t      margin-top: 0px;\n   \t}\n\n\t.title {\n\t  \tfont-style: italic;\n\t }\n\n    .checkmark:before {\n       content: ''; \n       background-image: url(\"data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='check-square' class='svg-inline--fa fa-check-square fa-w-14' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%2300a100' d='M400 480H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48v352c0 26.51-21.49 48-48 48zm-204.686-98.059l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.248-16.379-6.249-22.628 0L184 302.745l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.25 16.379 6.25 22.628.001z'%3E%3C/path%3E%3C/svg%3E\");\n       width: 15px;\n       height: 15px;\n       display: inline-block;\n       background-repeat: no-repeat;\n       visibility: visible;\n    }\n    .checkmark {\n        visibility: hidden;\n    }\n\n    .stretch {width: 100%;}\n    h1[id] {\n        --margin-top: 1em;\n    }\n    h2[id] {\n        --margin-top: 1.2em;\n    }\n\t.toc > h2 {\n\t  --margin-top: 1em;\n\t}\n\n    h3[id] {\n        --margin-top: 1.2em;\n    }\n    h4[id] {\n        --margin-top: 0.5em;\n    }\n    h5[id] {\n        --margin-top: 1.67em;\n    }\n    .imageblock .content, .image {\n        text-align: center;\n        display: block;\n    }\n    .imageblock, .image {\n        img:not([width]):not([height]) {\n            width: auto;\n            height: auto;\n            max-width: 100%;\n            max-height: 450px;\n        }\n    }\n\tstrong {\n\t  color: #757575;\n\t}\n\n\tth.valign-top,td.valign-top { \n\t\tvertical-align:top;\n\t}\n\n    table {\n        margin: 16px 0;\n    }\n\n    table tr td {\n      hyphens: auto;\n    }\n\n\ttable thead,table tfoot {\n\t\tbackground:#f7f8f7; \n\t  color: #757575;\n\t}\n\ttable tr.even,table tr.alt{background:#f8f8f7}\n    table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd),table.stripes-even tr:nth-of-type(even),table.stripes-hover tr:hover{background:#f8f8f7}\n\n}\n.copyright {\n    margin-top: 3em;\n    padding-top: 1em;\n    border-top: 1px solid #f0f0f0;\n    font-size: 0.9em;\n    line-height: 1.8em;\n    color: #757575;\n}\n\nbody.hide-left-nav {\n    .left-nav {\n        display: none;\n    }\n}\n\n.left-nav {\n    // top: 0;\n    bottom: 0;\n    position: -webkit-sticky;\n    position: sticky;\n}\n.left-nav {\n    // max-height: calc(100vh );\n    grid-area: left-nav;    \n}\n.right-nav {\n    grid-area: right-nav;\n}\n.left-nav__overlay {\n    display: none;\n    background: rgba(0, 0, 0, 0.50);\n    z-index: 1;\n    position: fixed;\n    top: var(--header-height);\n    bottom: 0;\n    left: 0;\n    right: 0;\n}\n\n\n#doc-feedback-btn {\n    background-color: #b02032 !important; // rgb(240, 0, 35) !important;\n    display: block;\n    font-weight: 400;\n    color: white;\n    text-align: center;\n    cursor: pointer;\n    user-select: none;\n    background-color: transparent;\n    border: 1px solid transparent;\n    padding: .375rem .75rem;\n    margin: 1rem auto;\n    font-size: 14px;\n    line-height: 1.5;\n    border-radius: .25rem;\n    transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;\n}\n\n@media (max-width: 990px) {\n    body:not(.hide-left-nav) {\n        .left-nav__overlay {\n            display: block;\n        }\n    }\n    nav.left-nav {\n        background: #fafafa;\n        grid-area: left-nav;\n        box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.24), 0 0 4px 0 rgba(0, 0, 0, 0.12);\n        min-height: calc(100vh - var(--header-height));\n        max-height: calc(100vh - var(--header-height));\n        position: fixed;\n        bottom: 0;\n        top: var(--header-height);\n        z-index: 2;\n    }\n    section.page-docs > article {\n        grid-column-start: left-nav;\n        grid-column-end: content;\n        grid-row: content;\n    }\n}\n@media (max-width: 800px) {\n    nav.right-nav {\n        display: block;\n        width: 100%;\n        height: 80px;\n\n        .toc-wrapper {\n            display: none;\n        }\n    }\n    section.page-docs {\n        display: block;\n    }\n}\n\n:target:before {\n    content: \"\";\n    display: block;\n    margin-top: calc(var(--header-height) * -1);\n    height: var(--header-height);\n    width: 1px;\n}\n@media (min-width: 600px) and  (max-width: 900px) {\n    :target:before {\n        content: \"\";\n        display: block;\n        width: 1px;\n        margin-top: -150px;\n        height: 150px;\n    }\n}\n",
 		"pre.pygments .hll { background-color: #ffffcc }\npre.pygments, pre.pygments code { background: #ffffff; }\npre.pygments .tok-c { color: #008000 } /* Comment */\npre.pygments .tok-err { border: 1px solid #FF0000 } /* Error */\npre.pygments .tok-k { color: #0000ff } /* Keyword */\npre.pygments .tok-ch { color: #008000 } /* Comment.Hashbang */\npre.pygments .tok-cm { color: #008000 } /* Comment.Multiline */\npre.pygments .tok-cp { color: #0000ff } /* Comment.Preproc */\npre.pygments .tok-cpf { color: #008000 } /* Comment.PreprocFile */\npre.pygments .tok-c1 { color: #008000 } /* Comment.Single */\npre.pygments .tok-cs { color: #008000 } /* Comment.Special */\npre.pygments .tok-ge { font-style: italic } /* Generic.Emph */\npre.pygments .tok-gh { font-weight: bold } /* Generic.Heading */\npre.pygments .tok-gp { font-weight: bold } /* Generic.Prompt */\npre.pygments .tok-gs { font-weight: bold } /* Generic.Strong */\npre.pygments .tok-gu { font-weight: bold } /* Generic.Subheading */\npre.pygments .tok-kc { color: #0000ff } /* Keyword.Constant */\npre.pygments .tok-kd { color: #0000ff } /* Keyword.Declaration */\npre.pygments .tok-kn { color: #0000ff } /* Keyword.Namespace */\npre.pygments .tok-kp { color: #0000ff } /* Keyword.Pseudo */\npre.pygments .tok-kr { color: #0000ff } /* Keyword.Reserved */\npre.pygments .tok-kt { color: #2b91af } /* Keyword.Type */\npre.pygments .tok-s { color: #a31515 } /* Literal.String */\npre.pygments .tok-nc { color: #2b91af } /* Name.Class */\npre.pygments .tok-ow { color: #0000ff } /* Operator.Word */\npre.pygments .tok-sa { color: #a31515 } /* Literal.String.Affix */\npre.pygments .tok-sb { color: #a31515 } /* Literal.String.Backtick */\npre.pygments .tok-sc { color: #a31515 } /* Literal.String.Char */\npre.pygments .tok-dl { color: #a31515 } /* Literal.String.Delimiter */\npre.pygments .tok-sd { color: #a31515 } /* Literal.String.Doc */\npre.pygments .tok-s2 { color: #a31515 } /* Literal.String.Double */\npre.pygments .tok-se { color: #a31515 } /* Literal.String.Escape */\npre.pygments .tok-sh { color: #a31515 } /* Literal.String.Heredoc */\npre.pygments .tok-si { color: #a31515 } /* Literal.String.Interpol */\npre.pygments .tok-sx { color: #a31515 } /* Literal.String.Other */\npre.pygments .tok-sr { color: #a31515 } /* Literal.String.Regex */\npre.pygments .tok-s1 { color: #a31515 } /* Literal.String.Single */\npre.pygments .tok-ss { color: #a31515 } /* Literal.String.Symbol */"
 	],
 	"names": [],
-	"mappings": "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"
+	"mappings": "CCAC,AAAD,IAAK,CAAC,EACF,QAAQ,CAAA,QAAC,EACT,WAAW,CAAA,QAAC,EACZ,gBAAgB,CAAA,QAAC,EACjB,kBAAkB,CAAA,yFAAC,EACnB,cAAc,CAAA,QAAC,EACf,uBAAuB,CAAA,IAAC,EACxB,uBAAuB,CAAA,yBAAC,EACxB,wBAAwB,CAAA,yBAAC,EACzB,aAAa,CAAA,KAAC,EACd,YAAY,CAAA,QAAC,EACb,iBAAiB,CAAA,QAAC,GACrB;;AAED,UAAU,GACN,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,GAAG,EAChB,YAAY,EAAE,IAAI,EAClB,UAAU,EAAE,MAAM;;AClBtB,AAAA,MAAM,CAAC,EAEH,UAAU,EAAE,oBAAoB,EAChC,UAAU,EAAE,KAAK,EACjB,UAAU,EAAE,uCAAuC,EAGnD,OAAO,EAAE,CAAC,GAiYb;;AAxYD,AASI,MATE,CASF,cAAc,CAAC,EACX,gBAAgB,EAAE,OAAO,EACzB,OAAO,EAAE,GAAG,GAgBf;;AA3BL,AAaQ,MAbF,CASF,cAAc,CAIV,CAAC,CAAC,EACE,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,KAAK,EAClB,WAAW,EAAE,GAAG,EAChB,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,CAAC,EAET,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,MAAM,GAKrB;;AA1BT,AAuBY,MAvBN,CASF,cAAc,CAIV,CAAC,CAUG,CAAC,CAAC,EACE,KAAK,EAAE,OAAO,GACjB;;AAzBb,AA8BI,MA9BE,GA8BA,UAAU,CAAC,EACT,OAAO,EAAE,IAAI,EACb,qBAAqB,EAAE,4BAA4B,EACnD,mBAAmB,EAAE,0CAA0C,EAC/D,kBAAkB,EAAE,IAAI,EACxB,cAAc,EAAE,GAAG,EACnB,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,UAAU,EAC3B,OAAO,EAAE,SAAS,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACjB;;AAzCL,AA2CI,MA3CE,CA2CF,CAAC,CAAC,KAAK,EA3CX,MAAM,CA2CO,MAAM,CAAC,KAAK,CAAC,EAClB,OAAO,EAAE,IAAI,GAChB;;AA7CL,AA+CI,MA/CE,CA+CF,EAAE,CAAC,KAAK,CAAC,SAAS,EA/CtB,MAAM,CA+CkB,CAAC,CAAC,KAAK,GAAG,SAAS,CAAC,EACpC,OAAO,EAAE,KAAK,GACjB;;AAjDL,AAmDI,MAnDE,CAmDF,eAAe,CAAC,EACZ,WAAW,EAAE,GAAG,EAChB,aAAa,EAAE,GAAG,EAElB,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,GAAG,GACd;;AAzDL,AA2DI,MA3DE,CA2DF,GAAG,GAAG,EAAE,CAAC,EACL,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,CAAC,EACT,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,OAAO,GACnB;;AAhEL,AAkEI,MAlEE,CAkEF,SAAS,CAAC,EACN,OAAO,EAAE,IAAI,EACb,QAAQ,EAAE,KAAK,EACf,GAAG,EAAE,iCAAiC,EACtC,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,KAAK,EACjB,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAC1E,aAAa,EAAE,GAAG,EAClB,WAAW,EAAE,IAAI,EACjB,cAAc,EAAE,IAAI,EACpB,OAAO,EAAE,CAAC,GAiBb;;AA7FL,AAgFQ,MAhFF,CAkEF,SAAS,CAcL,EAAE,CAAC,EACC,OAAO,EAAE,IAAI,GAChB;;AAlFT,AAoFQ,MApFF,CAkEF,SAAS,CAkBL,CAAC,CAAC,EACE,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,GAAG,EAChB,cAAc,EAAE,GAAG,GAItB;;AA5FT,AAyFY,MAzFN,CAkEF,SAAS,CAkBL,CAAC,CAKK,KAAK,CAAC,EACJ,KAAK,EAAE,gBAAgB,CAAC,UAAU,GACrC;;AA3Fb,AA+FI,MA/FE,CA+FF,KAAK,CAAC,EACF,MAAM,EAAE,IAAI,EACZ,UAAU,EAAE,IAAI,EAChB,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,YAAY,EAAE,IAAI,EAClB,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,WAAW,GAMzB;;AA5GL,AAwGQ,MAxGF,CA+FF,KAAK,CASD,GAAG,CAAC,EACA,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,GACf;;AA3GT,AA8GI,MA9GE,CA8GF,cAAc,EA9GlB,MAAM,CA8Gc,eAAe,EA9GnC,MAAM,CA8G+B,OAAO,EA9G5C,MAAM,CA8GwC,aAAa,CAAC,EACpD,UAAU,EAAE,IAAI,EAChB,MAAM,EAAE,IAAI,EACZ,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,OAAO,EAAE,WAAW,EACpB,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,IAAI,GAClB;;AAzHL,AA0HI,MA1HE,CA0HF,cAAc,CAAC,EACX,SAAS,EAAE,MAAM,GACpB;;AA5HL,AA6HI,MA7HE,CA6HF,eAAe,CAAC,EACZ,SAAS,EAAE,UAAU,GACxB;;AA/HL,AAiII,MAjIE,CAiIF,KAAK,CAAC,EAEF,SAAS,EAAE,IAAI,EACf,YAAY,EAAE,IAAI,GAIrB;;AAxIL,AAqIQ,MArIF,CAiIF,KAAK,CAID,GAAG,CAAC,EACA,MAAM,EAAE,IAAI,GACf;;AAvIT,AA0II,MA1IE,CA0IF,SAAS,CAAC,EACN,SAAS,EAAE,GAAG,EACd,MAAM,EAAE,CAAC,EAET,OAAO,EAAE,IAAI,GA4ChB;;AA1LL,AAgJQ,MAhJF,CA0IF,SAAS,GAMH,EAAE,CAAC,EACD,UAAU,EAAE,IAAI,EAChB,YAAY,EAAE,KAAK,EACnB,OAAO,EAAE,IAAI,GAChB;;AApJT,AAsJQ,MAtJF,CA0IF,SAAS,CAYL,SAAS,CAAC,EACN,OAAO,EAAE,MAAM,GAClB;;AAxJT,AA0JQ,MA1JF,CA0IF,SAAS,CAgBL,sBAAsB,EA1J9B,MAAM,CA0IF,SAAS,CAgBmB,CAAC,CAAC,EACtB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,mBAAmB,CAAC,UAAU,EACrC,eAAe,EAAE,IAAI,EACrB,WAAW,EAAE,MAAM,GAMtB;;AApKT,AAgKY,MAhKN,CA0IF,SAAS,CAgBL,sBAAsB,AAMjB,OAAO,EAhKpB,MAAM,CA0IF,SAAS,CAgBmB,CAAC,AAMpB,OAAO,CAAC,EACL,aAAa,EAAE,GAAG,EAClB,gBAAgB,EAAE,OAAO,GAC5B;;AAnKb,AAuKY,MAvKN,CA0IF,SAAS,CA4BL,cAAc,CACV,CAAC,CAAC,EACE,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,KAAK,EACd,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,KAAK,GAKnB;;AAhLb,AA6KgB,MA7KV,CA0IF,SAAS,CA4BL,cAAc,CACV,CAAC,CAMK,KAAK,CAAC,EACJ,gBAAgB,EAAE,OAAO,GAC5B;;AA/KjB,AAmLQ,MAnLF,CA0IF,SAAS,CAyCL,sBAAsB,CAAC,EACnB,WAAW,EAAE,IAAI,EACjB,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,iBAAiB,EAChC,YAAY,EAAE,CAAC,GAClB;;AAxLT,AA6LQ,MA7LF,CA4LF,cAAc,CACV,EAAE,CAAC,EACC,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,IAAI,EACb,OAAO,EAAE,QAAQ,GA4CpB;;AA5OT,AAmMY,MAnMN,CA4LF,cAAc,CACV,EAAE,CAME,CAAC,CAAC,EAEE,OAAO,EAAE,IAAI,EACb,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,MAAM,GActB;;AArNb,AA0MgB,MA1MV,CA4LF,cAAc,CACV,EAAE,CAME,CAAC,CAOG,IAAI,CAAC,EACD,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,GAAG,GACnB;;AA7MjB,AAgNgB,MAhNV,CA4LF,cAAc,CACV,EAAE,CAME,CAAC,CAaG,GAAG,CAAC,EACA,KAAK,EAAE,IAAI,GACd;;AAlNjB,AAuNY,MAvNN,CA4LF,cAAc,CACV,EAAE,CA0BE,SAAS,CAAC,EACN,WAAW,EAAE,KAAK,GAmBrB;;AA3Ob,AA0NgB,MA1NV,CA4LF,cAAc,CACV,EAAE,CA0BE,SAAS,CAGL,cAAc,CAAC,EACX,OAAO,EAAE,KAAK,EACd,aAAa,EAAE,GAAG,GAcrB;;AA1OjB,AA8NoB,MA9Nd,CA4LF,cAAc,CACV,EAAE,CA0BE,SAAS,CAGL,cAAc,CAIR,KAAK,CAAC,EACJ,gBAAgB,EAAE,OAAO,GAC5B;;AAhOrB,AAmOwB,MAnOlB,CA4LF,cAAc,CACV,EAAE,CA0BE,SAAS,CAGL,cAAc,CAQV,CAAC,CACG,IAAI,CAAC,EACD,SAAS,EAAE,IAAI,GAClB;;AArOzB,AAsOwB,MAtOlB,CA4LF,cAAc,CACV,EAAE,CA0BE,SAAS,CAGL,cAAc,CAQV,CAAC,CAIK,KAAK,CAAC,EACJ,KAAK,EAAE,OAAO,GACjB;;AAxOzB,AAgPI,MAhPE,CAgPF,OAAO,CAAC,EACJ,WAAW,EAAE,IAAI,EACjB,YAAY,EAAE,IAAI,EAClB,SAAS,EAAE,MAAM,GAqBpB;;AAxQL,AAqPQ,MArPF,CAgPF,OAAO,CAKH,KAAK,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,EAAe,EACjB,KAAK,EAAE,mBAAmB,EAE1B,UAAU,EAAE,wBAAwB,EACpC,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,SAAS,EAClB,WAAW,EAAE,OAAO,EACpB,SAAS,EAAE,KAAK,EAChB,MAAM,EAAE,IAAI,EACZ,SAAS,EAAE,IAAI,EACf,kBAAkB,EAAE,KAAK,EACzB,UAAU,EAAE,KAAK,GAMpB;;AAtQT,AAkQY,MAlQN,CAgPF,OAAO,CAKH,KAAK,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,EAaD,AAAA,QAAC,AAAA,EAAU,EACR,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,WAAW,GACtB;;AArQb,AA0QI,MA1QE,CA0QF,iBAAiB,CAAC,EACd,UAAU,EAAE,IAAI,EAChB,SAAS,EAAE,GAAG,EACd,WAAW,EAAE,IAAI,EACjB,aAAa,EAAE,GAAG,EAClB,YAAY,EAAE,IAAI,EAClB,MAAM,EAAE,IAAI,EACZ,KAAK,EAAE,mBAAmB,EAE1B,OAAO,EAAE,iBAAiB,EAC1B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,KAAK,EACjB,UAAU,EAAG,WAAW,CAAC,oCAAoC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EACxF,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,KAAK,EACtB,eAAe,EAAE,IAAI,EACrB,kBAAkB,EAAE,IAAI,EACxB,UAAU,EAAE,IAAI,EAEhB,SAAS,EAAE,GAAG,GAMjB;;AArSL,AAiSQ,MAjSF,CA0QF,iBAAiB,CAuBb,MAAM,CAAC,EACH,SAAS,EAAE,GAAG,GACjB;;AAnST,AAySI,MAzSE,GAySA,GAAG,CAAC,EACF,SAAS,EAAE,GAAG,EACd,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,EACb,cAAc,EAAE,GAAG,EACnB,MAAM,EAAE,MAAM,GAmBjB;;AAjUL,AAgTQ,MAhTF,GAySA,GAAG,CAOD,EAAE,CAAC,EACC,UAAU,EAAE,IAAI,EAChB,YAAY,EAAE,KAAK,EACnB,OAAO,EAAE,IAAI,GAChB;;AApTT,AAsTQ,MAtTF,GAySA,GAAG,CAaD,CAAC,CAAC,EACE,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,mBAAmB,CAAC,UAAU,EACrC,eAAe,EAAE,IAAI,EACrB,WAAW,EAAE,MAAM,GAMtB;;AAhUT,AA4TY,MA5TN,GAySA,GAAG,CAaD,CAAC,AAMI,OAAO,CAAC,EACL,aAAa,EAAE,GAAG,EAClB,gBAAgB,EAAE,OAAO,GAC5B;;AA/Tb,AAmUI,MAnUE,CAmUF,cAAc,CAAC,EACX,SAAS,EAAE,IAAI,GAClB;;AArUL,AAwUI,MAxUE,CAwUF,aAAa,CAAC,EACV,YAAY,EAAE,IAAI,GACrB;;AAKD,MAAM,mBACF,GAhVR,AAgVQ,MAhVF,CAgVE,OAAO,CAAC,EACJ,YAAY,EAAE,GAAG,GAIpB,CArVT,AAkVY,MAlVN,CAgVE,OAAO,CAEH,KAAK,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,EAAe,EACjB,SAAS,EAAE,KAAK,GACnB,EACJ;;AArVT,AAyVQ,MAzVF,CAwVD,GAAK,CAAA,cAAc,EAChB,cAAc,EAzVtB,MAAM,CAwVD,GAAK,CAAA,cAAc,EACA,eAAe,EAzVvC,MAAM,CAwVD,GAAK,CAAA,cAAc,EACiB,aAAa,CAAC,EAC3C,OAAO,EAAE,IAAI,GAChB;;AA3VT,AA8VQ,MA9VF,AA6VD,cAAc,CACX,CAAC,AAAA,KAAK,CAAC,EACH,GAAG,EAAE,CAAC,GACT;;AAhWT,AAkWY,MAlWN,AA6VD,cAAc,CAIV,GAAK,CAAA,SAAS,EACX,GAAG,CAAC,EACA,OAAO,EAAE,IAAI,GAChB;;AApWb,AAuWY,MAvWN,AA6VD,cAAc,AASV,YAAY,CACT,cAAc,EAvW1B,MAAM,AA6VD,cAAc,AASV,YAAY,CACO,KAAK,EAvWjC,MAAM,AA6VD,cAAc,AASV,YAAY,CACc,eAAe,EAvWlD,MAAM,AA6VD,cAAc,AASV,YAAY,CAC+B,OAAO,EAvW3D,MAAM,AA6VD,cAAc,AASV,YAAY,CACwC,KAAK,CAAC,EACnD,OAAO,EAAE,IAAI,GAChB;;AAzWb,AA0WY,MA1WN,AA6VD,cAAc,AASV,YAAY,CAIT,OAAO,CAAC,EACJ,iBAAiB,EAAE,IAAI,EACvB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,IAAI,EACX,OAAO,EAAE,IAAI,GAMhB;;AApXb,AAgXgB,MAhXV,AA6VD,cAAc,AASV,YAAY,CAIT,OAAO,CAMH,KAAK,CAAC,EACF,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,IAAI,GACd;;AAnXjB,AAuXY,MAvXN,AA6VD,cAAc,CAyBV,GAAK,CAAA,YAAY,EACd,OAAO,CAAC,EACJ,OAAO,EAAE,IAAI,GAChB;;AAzXb,AA2XQ,MA3XF,AA6VD,cAAc,CA8BX,GAAG,CAAC,EACA,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,OAAO,GAS3B;;AAtYT,AA+XY,MA/XN,AA6VD,cAAc,CA8BX,GAAG,CAIC,EAAE,CAAC,EACC,OAAO,EAAE,IAAI,GAChB;;AAjYb,AAmYY,MAnYN,AA6VD,cAAc,CA8BX,GAAG,CAQC,CAAC,CAAC,EACE,KAAK,EAAE,IAAI,GACd;;AAIb,AAEI,gBAFY,CAEZ,aAAa,CAAC,EACV,gBAAgB,EAAE,KAAK,EACvB,OAAO,EAAE,KAAK,EACd,eAAe,EAAE,IAAI,EACrB,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC,EACV,UAAU,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAChD,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,GAAG,EAClB,UAAU,EAAE,IAAI,EAChB,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,KAAK,GAkDnB;;AA/DL,AAeQ,gBAfQ,CAEZ,aAAa,CAaT,EAAE,CAAC,EAEC,gBAAgB,EAAE,KAAK,EACvB,OAAO,EAAE,KAAK,EACd,eAAe,EAAE,IAAI,EACrB,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC,EACV,aAAa,EAAE,GAAG,EAClB,UAAU,EAAE,IAAI,EAChB,UAAU,EAAE,IAAI,EAChB,QAAQ,EAAE,IAAI,GAqCjB;;AA9DT,AA2BY,gBA3BI,CAEZ,aAAa,CAaT,EAAE,CAYE,EAAE,CAAC,EACC,UAAU,EAAE,iBAAiB,EAC7B,aAAa,EAAE,cAAc,EAC7B,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAE,IAAI,EACf,eAAe,EAAE,IAAI,EACrB,gBAAgB,EAAE,IAAI,EACtB,MAAM,EAAE,CAAC,GACV;;AApCf,AAsCY,gBAtCI,CAEZ,aAAa,CAaT,EAAE,CAuBE,EAAE,AAAA,OAAO,CAAC,EACN,UAAU,EAAE,iBAAiB,EAC7B,aAAa,EAAE,iBAAiB,EAChC,gBAAgB,EAAE,OAAO,GAC5B;;AA1Cb,AA4CY,gBA5CI,CAEZ,aAAa,CAaT,EAAE,CA6BE,CAAC,CAAC,EACE,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,IAAI,EACjB,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC,GAMb;;AAtDb,AAkDgB,gBAlDA,CAEZ,aAAa,CAaT,EAAE,CA6BE,CAAC,AAMI,IAAI,CAAC,EACF,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,IAAI,GACd;;AArDjB,AAwDY,gBAxDI,CAEZ,aAAa,CAaT,EAAE,CAyCE,CAAC,CAAC,EACE,SAAS,EAAE,IAAI,GAClB;;AA1Db,AA2DY,gBA3DI,CAEZ,aAAa,CAaT,EAAE,CA4CE,EAAE,CAAC,EACC,WAAW,EAAE,IACjB,GAAC;;AAIb,AAAA,OAAO,AAAA,KAAK,CAAC,EACT,gBAAgB,EAAE,kCAAkC,EACpD,mBAAmB,EAAE,MAAM,EAC3B,qBAAqB,EAAE,IAAI,EAC3B,iBAAiB,EAAE,SAAS,EAC5B,eAAe,EAAE,KAAK,EACtB,OAAO,EAAE,IAAI,EACb,qBAAqB,EAAE,QAAQ,EAC/B,mBAAmB,EAAE,gBAAgB,EACrC,kBAAkB,EAAE,IAAI,EACxB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,KAAK,GAuBd;;AAnCD,AAeI,OAfG,AAAA,KAAK,CAeR,MAAM,CAAC,EACH,KAAK,EAAE,OAAO,EACd,cAAc,EAAE,SAAS,EACzB,SAAS,EAAE,IAAI,GAClB;;AAnBL,AAqBI,OArBG,AAAA,KAAK,CAqBR,MAAM,CAAC,EACH,UAAU,EAAE,IAAI,EAEhB,WAAW,EAAE,IAAI,EACjB,aAAa,EAAE,GAAG,EAGlB,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,IAAI,EACjB,OAAO,EAAE,QAAQ,EACjB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,IAAI,EACf,UAAU,EAAG,OAAO,CAAC,oCAAoC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GACvF;;AAGL,MAAM,mBAGF,GAAA,AAAA,MAAM,GAAG,UAAU,CAAA,EACf,qBAAqB,EAAE,aAAa,EACpC,mBAAmB,EACf,wCACc,GAMrB,CAED,AAAA,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EACrB,eAAe,EAAE,QAAQ,GAC5B,EAJA;;AAQL,0BAA0B;AAG1B,AAAA,qBAAqB,CAAC,wCAAwC,CAAC,EAC3D,KAAK,EAAE,kBAAkB,EACzB,UAAU,EAAU,OAAO,CAAO,UAAU,GAC/C;;AAGD,AAAA,qBAAqB,CAAC,8CAA8C,CAAC,mDAAmD,CAAC,wCAAwC,EAAE,qBAAqB,CAAC,8CAA8C,CAAC,mDAAmD,CAAC,wCAAwC,EAAE,qBAAqB,CAAC,mCAAmC,CAAC,wCAAwC,CAAC,EACra,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,kBAAkB,EAC9B,UAAU,EAAE,KAAK,CAAC,CAAC,CAAE,IAAG,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,UAAU,EACzD,KAAK,EAAE,kBAAkB,GAC5B;;AAED,AAAA,qBAAqB,CAAC,iBAAiB,CAAC,cAAc,AAAA,UAAU,CAAC,6BAA6B,AAAA,yBAAyB,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,cAAc,AAAA,UAAU,CAAC,6BAA6B,CAAA,GAAK,CAAA,yBAAyB,EAAE,sCAAsC,CAAC,EAC1R,UAAU,EAAE,kBAAkB,GACjC;;ACthBD,AAAA,GAAG,EAAE,GAAG,AAAA,MAAM,CAAC,EACX,OAAO,EAAE,QAAQ,EACjB,UAAU,EAAE,4BAA4B,CAAC,UAAU,EACnD,aAAa,EAAE,GAAG,EAClB,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,IAAI,EAEhB,UAAU,EAAE,IAAI,EACnB,WAAW,EAAE,IAAI,EACd,KAAK,EAAE,OAAO,GACjB;;AAED,AAAA,IAAI,CAAC,EACD,KAAK,EAAE,OAAO,GACjB;;AAED,AAAA,GAAG,AAAA,MAAM,CAAC,IAAI,CAAC,EACX,UAAU,EAAE,eAAe,GAC9B;;AAED,AAAA,GAAG,AAAA,MAAM,CAAC,QAAQ,CAAC,EAChB,MAAM,EAAE,eAAe,GACvB;;AAEH,AAAA,SAAS,AAAA,uBAAuB,CAAC,EAC7B,OAAO,EAAE,KAAK,EACd,aAAa,EAAE,KAAK,GA0BvB;;AA5BD,AAII,SAJK,AAAA,uBAAuB,CAI5B,GAAG,CAAC,EACA,aAAa,EAAE,iBACnB,GAAC;;AANL,AAQI,SARK,AAAA,uBAAuB,CAQ5B,GAAG,CAAC,MAAM,CAAC,EACP,UAAU,EAAE,KAAK,EACjB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,IAAI,EACZ,OAAO,EAAE,SAAS,EAClB,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,eAAe,EAChC,SAAS,EAAE,IAAI,GAQZ;;AAvBL,AAiBQ,SAjBC,AAAA,uBAAuB,CAQ5B,GAAG,CAAC,MAAM,AASL,OAAO,CAAC,EACL,aAAa,EAAE,4BAA4B,CAAC,KAAK,CAAC,iBAAiB,GACtE;;AAnBT,AAoBE,SApBO,AAAA,uBAAuB,CAQ5B,GAAG,CAAC,MAAM,AAYX,KAAK,CAAC,EACL,KAAK,EAAE,IAAI,GACZ;;AAtBH,AAyBI,SAzBK,AAAA,uBAAuB,CAyB5B,QAAQ,CAAA,GAAK,EAAA,AAAA,MAAC,AAAA,GAAS,EACnB,OAAO,EAAE,KAAK,GACjB;;AAGL,AAAA,CAAC,CAAC,GAAI,CAAA,GAAG,IAAI,IAAI,CAAC,EACd,UAAU,EAAE,6BAA6B,EACzC,OAAO,EAAE,WAAW,EACpB,eAAe,EAAE,WAAW,EAC5B,aAAa,EAAE,GAAG,EAClB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,GACf,GAAC;;AAGD,AAAA,aAAa,CAAC,QAAQ,CAAC,EACnB,QAAQ,EAAE,QAAQ,GACrB;;AAED,AAAA,yBAAyB,CAAC,EACtB,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,OAAO,EAAE,IAAI,EACb,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,IAAI,EAChB,MAAM,EAAE,IAAI,EAEZ,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,CAAC,EACN,KAAK,EAAE,CAAC,EACR,UAAU,EAAE,8BAA8B,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,GAYrE;;AA1BD,AAgBI,yBAhBqB,AAgBpB,kCAAkC,CAAC,EAChC,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,IAAI,EAChB,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,IAAI,GACpB;;AArBL,AAuBI,yBAvBqB,CAuBnB,KAAK,CAAA,GAAK,CAAA,kCAAkC,EAAE,EAC5C,MAAM,EAAE,uBAAuB,GAClC;;AC7FL,AAAA,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAI;;AACtC,AAAA,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,GAAI;;AACpC,AAAA,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC,EACxB,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,IAAI,CAAC,EACd,KAAK,EAAE,OAAO,EACd,gBAAgB,EAAE,OAAO,GAC1B;;AACD,AAAA,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,EAC5E,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,CAAC,EAC5B,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,CAAC,EAC5B,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,EACd,gBAAgB,EAAE,OAAO,EACzB,WAAW,EAAE,IAAI,GAClB;;AACD,AAAA,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,EAC5E,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,EAC5H,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,EAC5H,KAAK,EAAE,OAAO,GACf;;AACD,AAAA,UAAU,CAAC,GAAG,CAAC,EACb,KAAK,EAAE,OAAO,GACf;;AC5ED,AAAA,IAAI,CAAC,EACD,WAAW,EAAE,uBAAuB,GACvC;;AAED,AAAA,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACX,KAAK,EAAE,IAAI,EACX,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,WAAW,GAC3B;;AAED,AAAA,EAAE,CAAC,EACC,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,IAAI,GACpB;;AAED,AAAA,CAAC,CAAC,EACE,eAAe,EAAE,IAAI,EACrB,KAAK,EAAE,iBAAiB,GAC3B;;AAGD,AAAA,OAAO,CAAC,EACJ,KAAK,EAAE,OAAO,GACjB;;AAED,AAAA,KAAK,CAAC,EACF,eAAe,EAAE,QAAQ,GAqB5B;;AAtBD,AAGI,KAHC,CAGD,EAAE,EAHN,KAAK,CAGG,EAAE,CAAC,EACH,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,QAAQ,EACjB,aAAa,EAAE,GAAG,CAAC,KAAK,CAAC,OAAe,EACxC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,OAAe,GACxC;;AARL,AAUI,KAVC,CAUD,EAAE,CAAC,CAAC,AAAA,WAAW,CAAC,EACZ,UAAU,EAAE,KAAK,EACjB,aAAa,EAAE,KAAK,GASvB;;AArBL,AAcQ,KAdH,CAUD,EAAE,CAAC,CAAC,AAAA,WAAW,CAIT,WAAW,CAAC,EACV,UAAU,EAAE,OAAO,GACtB;;AAhBT,AAkBQ,KAlBH,CAUD,EAAE,CAAC,CAAC,AAAA,WAAW,CAQT,UAAU,CAAC,EACT,aAAa,EAAE,OAAO,GACzB;;AC7CT,AAAA,gBAAgB,CAAC,EACb,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,qBAAqB,EAC5C,UAAU,EAAE,yBAAyB,EACrC,KAAK,EAAE,mBAAmB,EAC1B,WAAW,EAAE,CAAC,EAEd,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,IAAI,EACb,aAAa,EAAE,IAAI,GAuDtB;;AA/DD,AAUC,gBAVe,CAUf,KAAK,CAAC,EACC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,IAAI,GAKjB;;AAjBF,AAcQ,gBAdQ,CAUf,KAAK,CAIE,EAAE,CAAC,EACC,KAAK,EAAE,IAAI,GACd;;AAhBT,AAmBI,gBAnBY,GAmBV,KAAK,CAAC,EACJ,UAAU,EAAE,GAAG,GAClB;;AArBL,AAuBI,gBAvBY,CAuBZ,KAAK,CAAC,EACF,gBAAgB,EAAE,mBAAmB,EACrC,iBAAiB,EAAE,SAAS,EAC5B,mBAAmB,EAAE,aAAa,EAClC,OAAO,EAAE,QAAQ,EACjB,eAAe,EAAE,GAAG,EACpB,KAAK,EAAE,KAAK,GAKf;;AAlCL,AA+BQ,gBA/BQ,CAuBZ,KAAK,CAQD,MAAM,CAAC,EACH,OAAO,EAAE,IAAI,GAChB;;AAjCT,AAoCI,gBApCY,AAoCX,KAAK,CAAC,EACH,cAAc,CAAA,QAAC,EACf,gBAAgB,CAAA,QAAC,EACjB,oBAAoB,CAAA,QAAC,EACrB,cAAc,CAAA,yqBAAC,GAClB;;AAzCL,AA2CI,gBA3CY,AA2CX,IAAI,CAAC,EACF,cAAc,CAAA,QAAC,EACf,gBAAgB,CAAA,QAAC,EACjB,oBAAoB,CAAA,QAAC,EACrB,cAAc,CAAA,2rCAAC,GAClB;;AAhDL,AAkDI,gBAlDY,AAkDX,QAAQ,EAlDb,gBAAgB,AAkDA,UAAU,CAAC,EACnB,cAAc,CAAA,QAAC,EACf,gBAAgB,CAAA,QAAC,EACjB,oBAAoB,CAAA,QAAC,EACrB,cAAc,CAAA,msCAAC,GAClB;;AAvDL,AAyDI,gBAzDY,AAyDX,QAAQ,CAAC,EACN,cAAc,CAAA,QAAC,EACf,gBAAgB,CAAA,QAAC,EACjB,oBAAoB,CAAA,QAAC,EACrB,cAAc,CAAA,4uBAAC,GAClB;;AC9DL,AAAA,IAAI,CAAC,EACD,eAAe,CAAA,KAAC,EAChB,sBAAsB,CAAA,KAAC,EACvB,eAAe,CAAA,MAAC,EAChB,YAAY,CAAA,KAAC,EAMb,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,IAAI,EACb,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,KAAK,EACjB,gBAAgB,EAAE,sBAAsB,EACxC,WAAW,EAAE,sBAAsB,GAKtC;;AArBD,AAkBI,IAlBA,GAkBE,OAAO,CAAC,EACN,IAAI,EAAE,CAAC,GACV;;AAEL,AAAA,MAAM,CAAC,EACH,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,CAAC,EACN,OAAO,EAAE,CAAC,GACb;;AACD,AAAA,IAAI,GAAG,MAAM,CAAC,EACV,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,GACnC;;AACD,AAAA,CAAC,CAAC,EACE,UAAU,EAAE,UAAU,GACzB;;AAED,MAAM,mBAEF,GAAA,AAAA,IAAI,CAAC,EACD,eAAe,CAAA,KAAC,GACnB,EAAA;;ACvCL,AAAA,SAAS,CAAC,EACN,OAAO,EAAE,SAAS,EAClB,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,IAAI,EAChB,GAAG,EAAE,wDAAwD,EAC7D,MAAM,EAAE,gEAAgE,EACxE,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,kBAAkB,EAC/B,gBAAgB,EAAE,sBAAsB,GAuF3C;;AA/FD,AAUI,SAVK,CAUL,EAAE,CAAC,EACC,UAAU,EAAE,IAAI,GACnB;;AAZL,AAaI,SAbK,CAaL,CAAC,EAbL,SAAS,CAaF,MAAM,CAAC,EACN,eAAe,EAAE,IAAI,EACrB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,KAAK,EACb,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,IAAI,EAChB,MAAM,EAAE,IAAI,EACZ,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,IAAI,GAKnB;;AA9BL,AA2BQ,SA3BC,CAaL,CAAC,AAcI,OAAO,EA3BhB,SAAS,CAaL,CAAC,CAce,KAAK,EA3BzB,SAAS,CAaF,MAAM,AAcJ,OAAO,EA3BhB,SAAS,CAaF,MAAM,CAcO,KAAK,CAAC,EACd,KAAK,EAAE,iBAAiB,GAC3B;;AA7BT,AAgCC,SAhCQ,CAgCR,CAAC,CAAC,KAAK,CAAC,EACH,OAAO,EAAE,IAAI,GACjB;;AAlCF,AAoCI,SApCK,CAoCL,UAAU,CAAC,EACP,WAAW,EAAE,GAAG,EAChB,SAAS,EAAE,IAAI,GAClB;;AAvCL,AAyCI,SAzCK,CAyCL,GAAG,CAAC,EACA,WAAW,EAAE,iBAAiB,EAE9B,aAAa,EAAE,GAAG,GAKrB;;AAjDL,AA8CQ,SA9CC,CAyCL,GAAG,AAKE,UAAU,CAAC,EACR,OAAO,EAAE,IAAI,GAChB;;AAhDT,AAmDI,SAnDK,CAmDL,GAAG,GAAG,EAAE,GAAG,CAAC,EAnDhB,SAAS,CAmDS,GAAG,GAAG,EAAE,GAAG,MAAM,CAAC,EAC5B,YAAY,EAAE,IAAI,EAClB,UAAU,EAAE,IAAI,GAMnB;;AA3DL,AAuDQ,SAvDC,CAmDL,GAAG,GAAG,EAAE,GAAG,CAAC,AAIP,OAAO,EAvDhB,SAAS,CAmDS,GAAG,GAAG,EAAE,GAAG,MAAM,AAI1B,OAAO,CAAC,EACL,WAAW,EAAE,4BAA4B,CAAC,KAAK,CAAC,mBAAmB,EACnE,YAAY,EAAE,yCAAyC,GAC1D;;AA1DT,AA6DI,SA7DK,CA6DL,GAAG,AAAA,UAAU,CAAC,EACV,MAAM,EAAE,IAAI,GACf;;AA/DL,AAiEC,SAjEQ,CAiER,GAAG,AAAA,UAAU,CAAC,CAAC,EAjEhB,SAAS,CAiES,GAAG,AAAA,UAAU,CAAC,MAAM,CAAC,EAC/B,YAAY,EAAE,IAAI,GAKxB;;AAvEF,AAoEQ,SApEC,CAiER,GAAG,AAAA,UAAU,CAAC,CAAC,AAGP,OAAO,EApEhB,SAAS,CAiES,GAAG,AAAA,UAAU,CAAC,MAAM,AAG7B,OAAO,CAAC,EACL,YAAY,EAAE,yCAAyC,GAC1D;;AAtET,AAyEI,SAzEK,CAyEL,OAAO,CAAC,EACJ,KAAK,EAAE,OAAO,GACjB;;AA3EL,AA6EI,SA7EK,CA6EL,gBAAgB,CAAC,EACb,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,GAAG,EACf,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,IAAI,EACZ,IAAI,EAAE,QAAQ,EACd,UAAU,EAAE,cAAc,EAC1B,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,YAAY,CAAC,iBAAiB,CAAC,eAAe,CAAC,aAAa,GAC7F;;AArFL,AAuFI,SAvFK,CAuFL,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAvFjC,SAAS,CAwFL,MAAM,AAAA,QAAQ,CAAC,gBAAgB,CAAC,EAC5B,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC,eAAe,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,aAAa,GACnG;;AA1FL,AA4FI,SA5FK,CA4FL,MAAM,AAAA,SAAS,CAAC,gBAAgB,CAAC,EAC7B,SAAS,EAAE,aAAa,GAC3B;;AC9FL,AAAA,UAAU,CAAC,EACP,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,SAAS,EAClB,UAAU,EAAE,IAAI,EAChB,MAAM,EAAE,kCAAkC,EAC1C,GAAG,EAAE,oBAAoB,EACzB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,IAAI,EACb,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,kBAAkB,EAC/B,gBAAgB,EAAE,OAAO,GAuD5B;;AAnED,AAcI,UAdM,CAcN,EAAE,CAAC,EACC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,MAAM,GACtB;;AAlBL,AAoBI,UApBM,CAoBN,EAAE,CAAC,EACC,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,CAAC,GAEZ;;AAzBL,AA2BI,UA3BM,CA2BN,EAAE,CAAC,EACC,OAAO,EAAE,CAAC,GACb;;AA7BL,AA+BI,UA/BM,CA+BN,CAAC,CAAC,EACE,cAAc,CAAA,IAAC,EACf,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,6DAA6D,EAC3E,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,YAAY,GAWxB;;AAhDL,AAuCQ,UAvCE,CA+BN,CAAC,CAQK,KAAK,CAAC,EACN,KAAK,EAAE,iBAAiB,GACzB;;AAzCT,AA2CQ,UA3CE,CA+BN,CAAC,AAYI,OAAO,CAAC,EACL,cAAc,CAAA,6BAAC,EACf,WAAW,EAAE,mBAAmB,CAAC,KAAK,CAAC,iBAAiB,EACxD,KAAK,EAAE,OAAO,GACjB;;AA/CT,AAkDI,UAlDM,CAkDN,WAAW,CAAC,EACR,WAAW,EAAE,iBAAiB,GACjC;;AApDL,AAuDQ,UAvDE,CAAV,WAAW,CAuDC,EACA,eAAe,CAAA,EAAC,GACnB;;AAzDT,AAuDQ,UAvDE,CAAV,WAAW,CAuDC,EACA,eAAe,CAAA,EAAC,GACnB;;AAzDT,AAuDQ,UAvDE,CAAV,WAAW,CAuDC,EACA,eAAe,CAAA,EAAC,GACnB;;AAzDT,AAuDQ,UAvDE,CAAV,WAAW,CAuDC,EACA,eAAe,CAAA,EAAC,GACnB;;AAzDT,AAuDQ,UAvDE,CAAV,WAAW,CAuDC,EACA,eAAe,CAAA,EAAC,GACnB;;AAzDT,AAuDQ,UAvDE,CAAV,WAAW,CAuDC,EACA,eAAe,CAAA,EAAC,GACnB;;AAzDT,AA4DI,UA5DM,CA4DN,UAAU,CAAC,EACP,MAAM,EAAE,IAAI,EACZ,IAAI,EAAE,GAAG,EACT,KAAK,EAAE,GAAG,EACV,SAAS,EAAE,KAAK,EAChB,MAAM,EAAE,WAAW,GACtB;;AAEL,MAAM,oBACF,GAAA,AAAA,UAAU,CAAC,EACP,KAAK,EAAE,KAAK,GACf,EAAA;;AAIL,MAAM,mBAGE,GAFJ,AAEI,UAFM,CAEN,UAAU,CAAC,EACP,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,CAAC,GAKZ,CATL,AAMQ,UANE,CAEN,UAAU,CAIN,SAAS,CAAC,EACN,OAAO,EAAE,IAAI,GAChB,EACJ;;ACrFT,AAAA,IAAI,GAAG,MAAM,CAAC,EACV,UAAU,EAAE,iBAAiB,EAC7B,MAAM,EAAE,oBAAoB,EAC5B,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,IAAI,EACb,eAAe,EAAE,aAAa,EAC9B,WAAW,EAAE,MAAM,GAQtB;;AALG,MAAM,mBACF,GAXR,AAWQ,IAXJ,GAAG,MAAM,CAWL,iBAAiB,CAAC,EACd,OAAO,EAAE,IAAI,GAChB,EAAA;;ACbT,AAEE,kBAFgB,CAEhB,GAAG,CAAC,EACF,gBAAgB,EAAE,KAAgB,GACnC;;AAJH,AAME,kBANgB,CAMhB,IAAI,CAAC,EACH,YAAY,EAAE,CAAC,EACf,MAAM,EAAE,KAAK,EACb,IAAI,EAAE,gBAAgB,GACvB;;AAVH,AAYE,kBAZgB,CAYhB,IAAI,CAAC,EACH,IAAI,EAAE,mBAAmB,EACzB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,GAAG,GAiBjB;;AAhCH,AAiBI,kBAjBc,CAYhB,IAAI,AAKD,aAAa,CAAC,EACb,SAAS,EAAE,IAAI,GAChB;;AAnBL,AAqBI,kBArBc,CAYhB,IAAI,AASD,cAAc,CAAC,EACd,SAAS,EAAE,IAAI,GAChB;;AAvBL,AAyBI,kBAzBc,CAYhB,IAAI,AAaD,MAAM,CAAC,EACN,WAAW,EAAE,KAAK,GACnB;;AA3BL,AA6BI,kBA7Bc,CAYhB,IAAI,AAiBD,QAAQ,CAAC,EACR,IAAI,EAAE,qBAAqB,GAC5B;;AA/BL,AAoCM,kBApCY,CAkChB,CAAC,CACC,aAAa,CACX,IAAI,CAAC,EACH,uBAAuB,EACxB;;AAtCP,AA0CE,kBA1CgB,CA0ChB,IAAI,CAAC,EACH,YAAY,EAAE,CAAC,EACf,MAAM,EAAE,KAAK,EACb,IAAI,EAAE,KAAgB,GAOvB;;AApDH,AA+CI,kBA/Cc,CA0ChB,IAAI,AAKD,UAAU,CAAC,EACV,MAAM,EAAE,IAAI,EACZ,gBAAgB,EAAE,IAAI,EACtB,IAAI,EAAE,IAAI,GACX;;AAnDL,AAsDE,kBAtDgB,CAsDhB,IAAI,AAAA,aAAa,CAAC,EAChB,YAAY,EAAE,CAAC,EACf,MAAM,EAAE,KAAK,EACb,IAAI,EAAE,KAAK,EACX,MAAM,EAAE,IAAI,GACb;;AA3DH,AA6DE,kBA7DgB,CA6DhB,CAAC,AAAA,aAAa,CAAC,KAAK,CAAC,IAAI,AAAA,aAAa,CAAC,EACrC,IAAI,EAAE,IAAI,GACX;;AC/DH,AAAA,OAAO,AAAA,UAAU,CAAC,EACd,OAAO,EAAE,IAAI,EACb,UAAU,EAAE,2BAA2B,EACvC,qBAAqB,EAAE,aAAa,EACpC,kBAAkB,EAAE,IAAI,EACxB,mBAAmB,EAAE,4BAA4B,EACjD,WAAW,EAAE,IAAI,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,IAAI,EACZ,KAAK,EAAE,IAAI,GA2Id;;AApJD,AAWI,OAXG,AAAA,UAAU,GAWX,OAAO,CAAC,EAEN,WAAW,EAAE,iBAAiB,EAC9B,gBAAgB,EAAE,OAAO,EACzB,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,OAAO,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,UAAU,EACvB,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,KAAK,GAwBrB;;AA7CL,AAuBQ,OAvBD,AAAA,UAAU,GAWX,OAAO,CAYL,EAAE,EAvBV,OAAO,AAAA,UAAU,GAWX,OAAO,CAYD,EAAE,EAvBd,OAAO,AAAA,UAAU,GAWX,OAAO,CAYG,EAAE,CAAA,GAAK,CAAA,SAAS,GAvBhC,OAAO,AAAA,UAAU,GAWX,OAAO,CAYsB,EAAE,EAvBrC,OAAO,AAAA,UAAU,GAWX,OAAO,CAY0B,EAAE,EAvBzC,OAAO,AAAA,UAAU,GAWX,OAAO,CAY8B,MAAM,EAvBjD,OAAO,AAAA,UAAU,GAWX,OAAO,CAYsC,EAAE,CAAC,EAC1C,WAAW,EAAE,WAAW,GAC3B;;AAzBT,AA2BQ,OA3BD,AAAA,UAAU,GAWX,OAAO,CAgBL,EAAE,CAAC,EACC,aAAa,EAAE,KAAK,GAMvB;;AAlCT,AA8BY,OA9BL,AAAA,UAAU,GAWX,OAAO,CAgBL,EAAE,GAGI,CAAC,CAAC,EACA,UAAU,EAAE,CAAC,EACb,aAAa,EAAE,CAAC,GACnB;;AAjCb,AAoCQ,OApCD,AAAA,UAAU,GAWX,OAAO,CAyBL,GAAG,CAAC,EACA,SAAS,EAAE,IAAI,EACf,MAAM,EAAE,IAAI,GACf;;AAED,MAAM,mBA9BV,GAXJ,AAWI,OAXG,AAAA,UAAU,GAWX,OAAO,CAAC,EA+BF,YAAY,EAAE,IAAI,EAClB,aAAa,EAAE,IACnB,GACH,EAAA;;AA7CL,AA+CI,OA/CG,AAAA,UAAU,CA+Cb,UAAU,CAAC,EACP,QAAQ,EAAC,QAAQ,EACjB,GAAG,EAAE,IAAI,EACT,KAAK,EAAC,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,+CAA+C,EAC5D,UAAU,EAAE,iCAAiC,GAChD;;AAtDL,AAwDI,OAxDG,AAAA,UAAU,CAwDb,EAAE,EAxDN,OAAO,AAAA,UAAU,CAwDT,EAAE,EAxDV,OAAO,AAAA,UAAU,CAwDL,EAAE,CAAA,GAAK,CAAA,SAAS,GAxD5B,OAAO,AAAA,UAAU,CAwDc,EAAE,EAxDjC,OAAO,AAAA,UAAU,CAwDkB,EAAE,CAAC,EAC9B,aAAa,EAAE,CAAC,GAQnB;;AAjEL,AA2DQ,OA3DD,AAAA,UAAU,CAwDb,EAAE,CAGG,AAAA,EAAC,AAAA,GA3DV,OAAO,AAAA,UAAU,CAwDT,EAAE,CAGD,AAAA,EAAC,AAAA,GA3DV,OAAO,AAAA,UAAU,CAwDL,EAAE,CAGL,AAAA,EAAC,AAAA,EAHI,GAAK,CAAA,SAAS,GAxD5B,OAAO,AAAA,UAAU,CAwDc,EAAE,CAGxB,AAAA,EAAC,AAAA,GA3DV,OAAO,AAAA,UAAU,CAwDkB,EAAE,CAG5B,AAAA,EAAC,AAAA,EAAI,EACF,UAAU,EAAG,iBAAiB,EAC9B,aAAa,EAAE,6BAA6B,EAE5C,OAAO,EAAE,EAAE,GACd;;AAhET,AAmEC,OAnEM,AAAA,UAAU,CAmEhB,IAAI,GAAG,EAAE,CAAC,EACL,MAAM,EAAE,CAAC,GACb;;AArEF,AAwEC,OAxEM,AAAA,UAAU,CAwEhB,QAAQ,GAAG,SAAS,AAAA,UAAU,CAAC,EACzB,UAAU,EAAE,GAAG,GACjB;;AA1EL,AA4EC,OA5EM,AAAA,UAAU,CA4EhB,MAAM,CAAC,EACJ,UAAU,EAAE,MAAM,GACnB;;AA9EH,AAgFI,OAhFG,AAAA,UAAU,CAgFb,UAAU,CAAC,MAAM,CAAC,EACf,OAAO,EAAE,EAAE,EACX,gBAAgB,EAAE,spBAAspB,EACxqB,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,OAAO,EAAE,YAAY,EACrB,iBAAiB,EAAE,SAAS,EAC5B,UAAU,EAAE,OAAO,GACrB;;AAxFL,AAyFI,OAzFG,AAAA,UAAU,CAyFb,UAAU,CAAC,EACP,UAAU,EAAE,MAAM,GACrB;;AA3FL,AA6FI,OA7FG,AAAA,UAAU,CA6Fb,QAAQ,CAAC,EAAC,KAAK,EAAE,IAAI,GAAG;;AA7F5B,AA8FI,OA9FG,AAAA,UAAU,CA8Fb,EAAE,CAAA,AAAA,EAAC,AAAA,EAAI,EACH,YAAY,CAAA,IAAC,GAChB;;AAhGL,AAiGI,OAjGG,AAAA,UAAU,CAiGb,EAAE,CAAA,AAAA,EAAC,AAAA,EAAI,EACH,YAAY,CAAA,MAAC,GAChB;;AAnGL,AAoGC,OApGM,AAAA,UAAU,CAoGhB,IAAI,GAAG,EAAE,CAAC,EACR,YAAY,CAAA,IAAC,GACd;;AAtGF,AAwGI,OAxGG,AAAA,UAAU,CAwGb,EAAE,CAAA,AAAA,EAAC,AAAA,EAAI,EACH,YAAY,CAAA,MAAC,GAChB;;AA1GL,AA2GI,OA3GG,AAAA,UAAU,CA2Gb,EAAE,CAAA,AAAA,EAAC,AAAA,EAAI,EACH,YAAY,CAAA,MAAC,GAChB;;AA7GL,AA8GI,OA9GG,AAAA,UAAU,CA8Gb,EAAE,CAAA,AAAA,EAAC,AAAA,EAAI,EACH,YAAY,CAAA,OAAC,GAChB;;AAhHL,AAiHI,OAjHG,AAAA,UAAU,CAiHb,WAAW,CAAC,QAAQ,EAjHxB,OAAO,AAAA,UAAU,CAiHS,MAAM,CAAC,EACzB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,KAAK,GACjB;;AApHL,AAsHQ,OAtHD,AAAA,UAAU,CAqHb,WAAW,CACP,GAAG,CAAA,GAAK,EAAA,AAAA,KAAC,AAAA,GAAO,GAAK,EAAA,AAAA,MAAC,AAAA,IAtH9B,OAAO,AAAA,UAAU,CAqHA,MAAM,CACf,GAAG,CAAA,GAAK,EAAA,AAAA,KAAC,AAAA,GAAO,GAAK,EAAA,AAAA,MAAC,AAAA,GAAS,EAC3B,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,SAAS,EAAE,IAAI,EACf,UAAU,EAAE,KAAK,GACpB;;AA3HT,AA6HC,OA7HM,AAAA,UAAU,CA6HhB,MAAM,CAAC,EACL,KAAK,EAAE,OAAO,GACf;;AA/HF,AAiIC,OAjIM,AAAA,UAAU,CAiIhB,EAAE,AAAA,WAAW,EAjId,OAAO,AAAA,UAAU,CAiIF,EAAE,AAAA,WAAW,CAAC,EAC3B,cAAc,EAAC,GAAG,GAClB;;AAnIF,AAqII,OArIG,AAAA,UAAU,CAqIb,KAAK,CAAC,EACF,MAAM,EAAE,MAAM,GACjB;;AAvIL,AAyII,OAzIG,AAAA,UAAU,CAyIb,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EACV,OAAO,EAAE,IAAI,GACd;;AA3IL,AA6IC,OA7IM,AAAA,UAAU,CA6IhB,KAAK,CAAC,KAAK,EA7IZ,OAAO,AAAA,UAAU,CA6IJ,KAAK,CAAC,KAAK,CAAC,EACvB,UAAU,EAAC,OAAO,EACjB,KAAK,EAAE,OAAO,GACf;;AAhJF,AAiJC,OAjJM,AAAA,UAAU,CAiJhB,KAAK,CAAC,EAAE,AAAA,KAAK,EAjJd,OAAO,AAAA,UAAU,CAiJF,KAAK,CAAC,EAAE,AAAA,IAAI,CAAA,EAAC,UAAU,EAAC,OAAO,GAAE;;AAjJhD,AAkJI,OAlJG,AAAA,UAAU,CAkJb,KAAK,AAAA,YAAY,CAAC,EAAE,EAlJxB,OAAO,AAAA,UAAU,CAkJQ,KAAK,AAAA,YAAY,CAAC,EAAE,CAAC,WAAY,CAAA,GAAG,GAlJ7D,OAAO,AAAA,UAAU,CAkJ8C,KAAK,AAAA,aAAa,CAAC,EAAE,CAAC,WAAY,CAAA,IAAI,GAlJrG,OAAO,AAAA,UAAU,CAkJsF,KAAK,AAAA,cAAc,CAAC,EAAE,CAAC,KAAK,CAAA,EAAC,UAAU,EAAC,OAAO,GAAE;;AAGxJ,AAAA,UAAU,CAAC,EACP,UAAU,EAAE,GAAG,EACf,WAAW,EAAE,GAAG,EAChB,UAAU,EAAE,iBAAiB,EAC7B,SAAS,EAAE,KAAK,EAChB,WAAW,EAAE,KAAK,EAClB,KAAK,EAAE,OAAO,GACjB;;AAED,AACI,IADA,AAAA,cAAc,CACd,SAAS,CAAC,EACN,OAAO,EAAE,IAAI,GAChB;;AAGL,AAAA,SAAS,CAAC,EAEN,MAAM,EAAE,CAAC,EACT,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,MAAM,GACnB;;AACD,AAAA,SAAS,CAAC,EAEN,SAAS,EAAE,QAAQ,GACtB;;AACD,AAAA,UAAU,CAAC,EACP,SAAS,EAAE,SAAS,GACvB;;AACD,AAAA,kBAAkB,CAAC,EACf,OAAO,EAAE,IAAI,EACb,UAAU,EAAE,kBAAmB,EAC/B,OAAO,EAAE,CAAC,EACV,QAAQ,EAAE,KAAK,EACf,GAAG,EAAE,oBAAoB,EACzB,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,CAAC,GACX;;AAGD,AAAA,iBAAiB,CAAC,EACd,gBAAgB,EAAE,kBAAkB,EACpC,OAAO,EAAE,KAAK,EACd,WAAW,EAAE,GAAG,EAChB,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,IAAI,EACjB,gBAAgB,EAAE,WAAW,EAC7B,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,GAAG,EAChB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,kHAAkH,GACjI;;AAED,MAAM,mBAEE,GADJ,AACI,IADA,CAAA,GAAK,CAAA,cAAc,EACnB,kBAAkB,CAAC,EACf,OAAO,EAAE,KAAK,GACjB,CAEL,AAAA,GAAG,AAAA,SAAS,CAAC,EACT,UAAU,EAAE,OAAO,EACnB,SAAS,EAAE,QAAQ,EACnB,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAC1E,UAAU,EAAE,kCAAkC,EAC9C,UAAU,EAAE,kCAAkC,EAC9C,QAAQ,EAAE,KAAK,EACf,MAAM,EAAE,CAAC,EACT,GAAG,EAAE,oBAAoB,EACzB,OAAO,EAAE,CAAC,GACb,CACD,AAAA,OAAO,AAAA,UAAU,GAAG,OAAO,CAAC,EACxB,iBAAiB,EAAE,QAAQ,EAC3B,eAAe,EAAE,OAAO,EACxB,QAAQ,EAAE,OAAO,GACpB,EAjBI;;AAmBT,MAAM,mBACF,GAAA,AAAA,GAAG,AAAA,UAAU,CAAC,EACV,OAAO,EAAE,KAAK,EACd,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,GAKf,CARD,AAKI,GALD,AAAA,UAAU,CAKT,YAAY,CAAC,EACT,OAAO,EAAE,IAAI,GAChB,CAEL,AAAA,OAAO,AAAA,UAAU,CAAC,EACd,OAAO,EAAE,KAAK,GACjB,EAHA;;CAMJ,AAAD,MAAO,CAAC,MAAM,CAAC,EACX,OAAO,EAAE,EAAE,EACX,OAAO,EAAE,KAAK,EACd,UAAU,EAAE,+BAA+B,EAC3C,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,GAAG,GACb;;AACD,MAAM,0CACF,IAAC,AAAD,MAAO,CAAC,MAAM,CAAC,EACX,OAAO,EAAE,EAAE,EACX,OAAO,EAAE,KAAK,EACd,KAAK,EAAE,GAAG,EACV,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,KAAK,GAChB,EAAA;;ACnQL,AAAA,GAAG,AAAA,SAAS,CAAC,IAAI,CAAC,EAAE,gBAAgB,EAAE,OAAQ,GAAE;;AAChD,AAAA,GAAG,AAAA,SAAS,EAAE,GAAG,AAAA,SAAS,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,OAAO,GAAI;;AACzD,AAAA,GAAG,AAAA,SAAS,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,aAAa;AACpD,AAAA,GAAG,AAAA,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,iBAAkB,GAAE;;AAAA,WAAW;AAC/D,AAAA,GAAG,AAAA,SAAS,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,aAAa;AACpD,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,sBAAsB;AAC9D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,uBAAuB;AAC/D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,qBAAqB;AAC7D,AAAA,GAAG,AAAA,SAAS,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,yBAAyB;AAClE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,oBAAoB;AAC5D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,qBAAqB;AAC7D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,MAAO,GAAE;;AAAA,kBAAkB;AAC9D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,IAAK,GAAE;;AAAA,qBAAqB;AAChE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,IAAK,GAAE;;AAAA,oBAAoB;AAC/D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,IAAK,GAAE;;AAAA,oBAAoB;AAC/D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,IAAK,GAAE;;AAAA,wBAAwB;AACnE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,sBAAsB;AAC9D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,yBAAyB;AACjE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,uBAAuB;AAC/D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,oBAAoB;AAC5D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,sBAAsB;AAC9D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,kBAAkB;AAC1D,AAAA,GAAG,AAAA,SAAS,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,oBAAoB;AAC3D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,gBAAgB;AACxD,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,mBAAmB;AAC3D,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,0BAA0B;AAClE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,6BAA6B;AACrE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,yBAAyB;AACjE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,8BAA8B;AACtE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,wBAAwB;AAChE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,2BAA2B;AACnE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,2BAA2B;AACnE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,4BAA4B;AACpE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,6BAA6B;AACrE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,0BAA0B;AAClE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,0BAA0B;AAClE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,2BAA2B;AACnE,AAAA,GAAG,AAAA,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAQ,GAAE;;AAAA,2BAA2B"
 }
\ No newline at end of file
diff --git a/assets/js/railroad-diagram.js b/assets/js/railroad-diagram.js
new file mode 100644
index 0000000..a903c5b
--- /dev/null
+++ b/assets/js/railroad-diagram.js
@@ -0,0 +1,11 @@
+import rr, * as rrClass from "./railroad.js";
+Object.assign(window, rr);
+window.rrOptions = rrClass.Options;
+
+let elements = document.querySelectorAll('.diagram-container p');
+[].forEach.call(elements, function(el) {
+    let result = eval(el.innerHTML).format();
+    let diagramContainer = el.closest('.diagram-container');
+    diagramContainer.innerHTML = '';
+    result.addTo(diagramContainer);
+})
diff --git a/assets/js/railroad.js b/assets/js/railroad.js
new file mode 100644
index 0000000..d029475
--- /dev/null
+++ b/assets/js/railroad.js
@@ -0,0 +1,1420 @@
+"use strict";
+/*
+Railroad Diagrams
+by Tab Atkins Jr. (and others)
+http://xanthir.com
+http://twitter.com/tabatkins
+http://github.com/tabatkins/railroad-diagrams
+
+This document and all associated files in the github project are licensed under CC0: http://creativecommons.org/publicdomain/zero/1.0/
+This means you can reuse, remix, or otherwise appropriate this project for your own use WITHOUT RESTRICTION.
+(The actual legal meaning can be found at the above link.)
+Don't ask me for permission to use any part of this project, JUST USE IT.
+I would appreciate attribution, but that is not required by the license.
+*/
+
+// Export function versions of all the constructors.
+// Each class will add itself to this object.
+const funcs = {};
+export default funcs;
+
+export const Options = {
+	DEBUG: false, // if true, writes some debug information into attributes
+	VS: 8, // minimum vertical separation between things. For a 3px stroke, must be at least 4
+	AR: 10, // radius of arcs
+	DIAGRAM_CLASS: 'railroad-diagram', // class to put on the root <svg>
+	STROKE_ODD_PIXEL_LENGTH: true, // is the stroke width an odd (1px, 3px, etc) pixel length?
+	INTERNAL_ALIGNMENT: 'center', // how to align items when they have extra space. left/right/center
+	CHAR_WIDTH: 8.5, // width of each monospace character. play until you find the right value for your font
+	COMMENT_CHAR_WIDTH: 7, // comments are in smaller text by default
+};
+
+export const defaultCSS = `
+	svg {
+		background-color: hsl(30,20%,95%);
+	}
+	path {
+		stroke-width: 3;
+		stroke: black;
+		fill: rgba(0,0,0,0);
+	}
+	text {
+		font: bold 14px monospace;
+		text-anchor: middle;
+		white-space: pre;
+	}
+	text.diagram-text {
+		font-size: 12px;
+	}
+	text.diagram-arrow {
+		font-size: 16px;
+	}
+	text.label {
+		text-anchor: start;
+	}
+	text.comment {
+		font: italic 12px monospace;
+	}
+	g.non-terminal text {
+		/*font-style: italic;*/
+	}
+	rect {
+		stroke-width: 3;
+		stroke: black;
+		fill: hsl(120,100%,90%);
+	}
+	rect.group-box {
+		stroke: gray;
+		stroke-dasharray: 10 5;
+		fill: none;
+	}
+	path.diagram-text {
+		stroke-width: 3;
+		stroke: black;
+		fill: white;
+		cursor: help;
+	}
+	g.diagram-text:hover path.diagram-text {
+		fill: #eee;
+	}`;
+
+
+export class FakeSVG {
+	constructor(tagName, attrs, text) {
+		if(text) this.children = text;
+		else this.children = [];
+		this.tagName = tagName;
+		this.attrs = unnull(attrs, {});
+	}
+	format(x, y, width) {
+		// Virtual
+	}
+	addTo(parent) {
+		if(parent instanceof FakeSVG) {
+			parent.children.push(this);
+			return this;
+		} else {
+			var svg = this.toSVG();
+			parent.appendChild(svg);
+			return svg;
+		}
+	}
+	toSVG() {
+		var el = SVG(this.tagName, this.attrs);
+		if(typeof this.children == 'string') {
+			el.textContent = this.children;
+		} else {
+			this.children.forEach(function(e) {
+				el.appendChild(e.toSVG());
+			});
+		}
+		return el;
+	}
+	toString() {
+		var str = '<' + this.tagName;
+		var group = this.tagName == "g" || this.tagName == "svg";
+		for(var attr in this.attrs) {
+			str += ' ' + attr + '="' + (this.attrs[attr]+'').replace(/&/g, '&amp;').replace(/"/g, '&quot;') + '"';
+		}
+		str += '>';
+		if(group) str += "\n";
+		if(typeof this.children == 'string') {
+			str += escapeString(this.children);
+		} else {
+			this.children.forEach(function(e) {
+				str += e;
+			});
+		}
+		str += '</' + this.tagName + '>\n';
+		return str;
+	}
+	walk(cb) {
+		cb(this);
+	}
+}
+
+
+export class Path extends FakeSVG {
+	constructor(x,y) {
+		super('path');
+		this.attrs.d = "M"+x+' '+y;
+	}
+	m(x,y) {
+		this.attrs.d += 'm'+x+' '+y;
+		return this;
+	}
+	h(val) {
+		this.attrs.d += 'h'+val;
+		return this;
+	}
+	right(val) { return this.h(Math.max(0, val)); }
+	left(val) { return this.h(-Math.max(0, val)); }
+	v(val) {
+		this.attrs.d += 'v'+val;
+		return this;
+	}
+	down(val) { return this.v(Math.max(0, val)); }
+	up(val) { return this.v(-Math.max(0, val)); }
+	arc(sweep){
+		// 1/4 of a circle
+		var x = Options.AR;
+		var y = Options.AR;
+		if(sweep[0] == 'e' || sweep[1] == 'w') {
+			x *= -1;
+		}
+		if(sweep[0] == 's' || sweep[1] == 'n') {
+			y *= -1;
+		}
+		var cw;
+		if(sweep == 'ne' || sweep == 'es' || sweep == 'sw' || sweep == 'wn') {
+			cw = 1;
+		} else {
+			cw = 0;
+		}
+		this.attrs.d += "a"+Options.AR+" "+Options.AR+" 0 0 "+cw+' '+x+' '+y;
+		return this;
+	}
+	arc_8(start, dir) {
+		// 1/8 of a circle
+		const arc = Options.AR;
+		const s2 = 1/Math.sqrt(2) * arc;
+		const s2inv = (arc - s2);
+		let path = "a " + arc + " " + arc + " 0 0 " + (dir=='cw' ? "1" : "0") + " ";
+		const sd = start+dir;
+		const offset =
+			sd == 'ncw'   ? [s2, s2inv] :
+			sd == 'necw'  ? [s2inv, s2] :
+			sd == 'ecw'   ? [-s2inv, s2] :
+			sd == 'secw'  ? [-s2, s2inv] :
+			sd == 'scw'   ? [-s2, -s2inv] :
+			sd == 'swcw'  ? [-s2inv, -s2] :
+			sd == 'wcw'   ? [s2inv, -s2] :
+			sd == 'nwcw'  ? [s2, -s2inv] :
+			sd == 'nccw'  ? [-s2, s2inv] :
+			sd == 'nwccw' ? [-s2inv, s2] :
+			sd == 'wccw'  ? [s2inv, s2] :
+			sd == 'swccw' ? [s2, s2inv] :
+			sd == 'sccw'  ? [s2, -s2inv] :
+			sd == 'seccw' ? [s2inv, -s2] :
+			sd == 'eccw'  ? [-s2inv, -s2] :
+			sd == 'neccw' ? [-s2, -s2inv] : null
+		;
+		path += offset.join(" ");
+		this.attrs.d += path;
+		return this;
+	}
+	l(x, y) {
+		this.attrs.d += 'l'+x+' '+y;
+		return this;
+	}
+	format() {
+		// All paths in this library start/end horizontally.
+		// The extra .5 ensures a minor overlap, so there's no seams in bad rasterizers.
+		this.attrs.d += 'h.5';
+		return this;
+	}
+}
+
+
+export class DiagramMultiContainer extends FakeSVG {
+	constructor(tagName, items, attrs, text) {
+		super(tagName, attrs, text);
+		this.items = items.map(wrapString);
+	}
+	walk(cb) {
+		cb(this);
+		this.items.forEach(x=>x.walk(cb));
+	}
+}
+
+
+export class Diagram extends DiagramMultiContainer {
+	constructor(...items) {
+		super('svg', items, {class: Options.DIAGRAM_CLASS});
+		if(!(this.items[0] instanceof Start)) {
+			this.items.unshift(new Start());
+		}
+		if(!(this.items[this.items.length-1] instanceof End)) {
+			this.items.push(new End());
+		}
+		this.up = this.down = this.height = this.width = 0;
+		for(const item of this.items) {
+			this.width += item.width + (item.needsSpace?20:0);
+			this.up = Math.max(this.up, item.up - this.height);
+			this.height += item.height;
+			this.down = Math.max(this.down - item.height, item.down);
+		}
+		this.formatted = false;
+	}
+	format(paddingt, paddingr, paddingb, paddingl) {
+		paddingt = unnull(paddingt, 20);
+		paddingr = unnull(paddingr, paddingt, 20);
+		paddingb = unnull(paddingb, paddingt, 20);
+		paddingl = unnull(paddingl, paddingr, 20);
+		var x = paddingl;
+		var y = paddingt;
+		y += this.up;
+		var g = new FakeSVG('g', Options.STROKE_ODD_PIXEL_LENGTH ? {transform:'translate(.5 .5)'} : {});
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			if(item.needsSpace) {
+				new Path(x,y).h(10).addTo(g);
+				x += 10;
+			}
+			item.format(x, y, item.width).addTo(g);
+			x += item.width;
+			y += item.height;
+			if(item.needsSpace) {
+				new Path(x,y).h(10).addTo(g);
+				x += 10;
+			}
+		}
+		this.attrs.width = this.width + paddingl + paddingr;
+		this.attrs.height = this.up + this.height + this.down + paddingt + paddingb;
+		this.attrs.viewBox = "0 0 " + this.attrs.width + " " + this.attrs.height;
+		g.addTo(this);
+		this.formatted = true;
+		return this;
+	}
+	addTo(parent) {
+		if(!parent) {
+			var scriptTag = document.getElementsByTagName('script');
+			scriptTag = scriptTag[scriptTag.length - 1];
+			parent = scriptTag.parentNode;
+		}
+		return super.addTo.call(this, parent);
+	}
+	toSVG() {
+		if(!this.formatted) {
+			this.format();
+		}
+		return super.toSVG.call(this);
+	}
+	toString() {
+		if(!this.formatted) {
+			this.format();
+		}
+		return super.toString.call(this);
+	}
+	toStandalone(style) {
+		if(!this.formatted) {
+			this.format();
+		}
+		const s = new FakeSVG('style', {}, style || defaultCSS);
+		this.children.push(s);
+		this.attrs.xmlns = "http://www.w3.org/2000/svg";
+		this.attrs['xmlns:xlink'] = "http://www.w3.org/1999/xlink";
+		const result = super.toString.call(this);
+		this.children.pop();
+		delete this.attrs.xmlns;
+		return result;
+	}
+}
+funcs.Diagram = (...args)=>new Diagram(...args);
+
+
+export class ComplexDiagram extends FakeSVG {
+	constructor(...items) {
+		var diagram = new Diagram(...items);
+		diagram.items[0] = new Start({type:"complex"});
+		diagram.items[diagram.items.length-1] = new End({type:"complex"});
+		return diagram;
+	}
+}
+funcs.ComplexDiagram = (...args)=>new ComplexDiagram(...args);
+
+
+export class Sequence extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		var numberOfItems = this.items.length;
+		this.needsSpace = true;
+		this.up = this.down = this.height = this.width = 0;
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			this.width += item.width + (item.needsSpace?20:0);
+			this.up = Math.max(this.up, item.up - this.height);
+			this.height += item.height;
+			this.down = Math.max(this.down - item.height, item.down);
+		}
+		if(this.items[0].needsSpace) this.width -= 10;
+		if(this.items[this.items.length-1].needsSpace) this.width -= 10;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "sequence";
+		}
+	}
+	format(x,y,width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			if(item.needsSpace && i > 0) {
+				new Path(x,y).h(10).addTo(this);
+				x += 10;
+			}
+			item.format(x, y, item.width).addTo(this);
+			x += item.width;
+			y += item.height;
+			if(item.needsSpace && i < this.items.length-1) {
+				new Path(x,y).h(10).addTo(this);
+				x += 10;
+			}
+		}
+		return this;
+	}
+}
+funcs.Sequence = (...args)=>new Sequence(...args);
+
+
+export class Stack extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		if( items.length === 0 ) {
+			throw new RangeError("Stack() must have at least one child.");
+		}
+		this.width = Math.max.apply(null, this.items.map(function(e) { return e.width + (e.needsSpace?20:0); }));
+		//if(this.items[0].needsSpace) this.width -= 10;
+		//if(this.items[this.items.length-1].needsSpace) this.width -= 10;
+		if(this.items.length > 1){
+			this.width += Options.AR*2;
+		}
+		this.needsSpace = true;
+		this.up = this.items[0].up;
+		this.down = this.items[this.items.length-1].down;
+
+		this.height = 0;
+		var last = this.items.length - 1;
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			this.height += item.height;
+			if(i > 0) {
+				this.height += Math.max(Options.AR*2, item.up + Options.VS);
+			}
+			if(i < last) {
+				this.height += Math.max(Options.AR*2, item.down + Options.VS);
+			}
+		}
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "stack";
+		}
+	}
+	format(x,y,width) {
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		x += gaps[0];
+		var xInitial = x;
+		if(this.items.length > 1) {
+			new Path(x, y).h(Options.AR).addTo(this);
+			x += Options.AR;
+		}
+
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			var innerWidth = this.width - (this.items.length>1 ? Options.AR*2 : 0);
+			item.format(x, y, innerWidth).addTo(this);
+			x += innerWidth;
+			y += item.height;
+
+			if(i !== this.items.length-1) {
+				new Path(x, y)
+					.arc('ne').down(Math.max(0, item.down + Options.VS - Options.AR*2))
+					.arc('es').left(innerWidth)
+					.arc('nw').down(Math.max(0, this.items[i+1].up + Options.VS - Options.AR*2))
+					.arc('ws').addTo(this);
+				y += Math.max(item.down + Options.VS, Options.AR*2) + Math.max(this.items[i+1].up + Options.VS, Options.AR*2);
+				//y += Math.max(Options.AR*4, item.down + Options.VS*2 + this.items[i+1].up)
+				x = xInitial+Options.AR;
+			}
+
+		}
+
+		if(this.items.length > 1) {
+			new Path(x,y).h(Options.AR).addTo(this);
+			x += Options.AR;
+		}
+		new Path(x,y).h(gaps[1]).addTo(this);
+
+		return this;
+	}
+}
+funcs.Stack = (...args)=>new Stack(...args);
+
+
+export class OptionalSequence extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		if( items.length === 0 ) {
+			throw new RangeError("OptionalSequence() must have at least one child.");
+		}
+		if( items.length === 1 ) {
+			return new Sequence(items);
+		}
+		var arc = Options.AR;
+		this.needsSpace = false;
+		this.width = 0;
+		this.up = 0;
+		this.height = sum(this.items, function(x){return x.height});
+		this.down = this.items[0].down;
+		var heightSoFar = 0;
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			this.up = Math.max(this.up, Math.max(arc*2, item.up + Options.VS) - heightSoFar);
+			heightSoFar += item.height;
+			if(i > 0) {
+				this.down = Math.max(this.height + this.down, heightSoFar + Math.max(arc*2, item.down + Options.VS)) - this.height;
+			}
+			var itemWidth = (item.needsSpace?10:0) + item.width;
+			if(i === 0) {
+				this.width += arc + Math.max(itemWidth, arc);
+			} else {
+				this.width += arc*2 + Math.max(itemWidth, arc) + arc;
+			}
+		}
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "optseq";
+		}
+	}
+	format(x, y, width) {
+		var arc = Options.AR;
+		var gaps = determineGaps(width, this.width);
+		new Path(x, y).right(gaps[0]).addTo(this);
+		new Path(x + gaps[0] + this.width, y + this.height).right(gaps[1]).addTo(this);
+		x += gaps[0];
+		var upperLineY = y - this.up;
+		var last = this.items.length - 1;
+		for(var i = 0; i < this.items.length; i++) {
+			var item = this.items[i];
+			var itemSpace = (item.needsSpace?10:0);
+			var itemWidth = item.width + itemSpace;
+			if(i === 0) {
+				// Upper skip
+				new Path(x,y)
+					.arc('se')
+					.up(y - upperLineY - arc*2)
+					.arc('wn')
+					.right(itemWidth - arc)
+					.arc('ne')
+					.down(y + item.height - upperLineY - arc*2)
+					.arc('ws')
+					.addTo(this);
+				// Straight line
+				new Path(x, y)
+					.right(itemSpace + arc)
+					.addTo(this);
+				item.format(x + itemSpace + arc, y, item.width).addTo(this);
+				x += itemWidth + arc;
+				y += item.height;
+				// x ends on the far side of the first element,
+				// where the next element's skip needs to begin
+			} else if(i < last) {
+				// Upper skip
+				new Path(x, upperLineY)
+					.right(arc*2 + Math.max(itemWidth, arc) + arc)
+					.arc('ne')
+					.down(y - upperLineY + item.height - arc*2)
+					.arc('ws')
+					.addTo(this);
+				// Straight line
+				new Path(x,y)
+					.right(arc*2)
+					.addTo(this);
+				item.format(x + arc*2, y, item.width).addTo(this);
+				new Path(x + item.width + arc*2, y + item.height)
+					.right(itemSpace + arc)
+					.addTo(this);
+				// Lower skip
+				new Path(x,y)
+					.arc('ne')
+					.down(item.height + Math.max(item.down + Options.VS, arc*2) - arc*2)
+					.arc('ws')
+					.right(itemWidth - arc)
+					.arc('se')
+					.up(item.down + Options.VS - arc*2)
+					.arc('wn')
+					.addTo(this);
+				x += arc*2 + Math.max(itemWidth, arc) + arc;
+				y += item.height;
+			} else {
+				// Straight line
+				new Path(x, y)
+					.right(arc*2)
+					.addTo(this);
+				item.format(x + arc*2, y, item.width).addTo(this);
+				new Path(x + arc*2 + item.width, y + item.height)
+					.right(itemSpace + arc)
+					.addTo(this);
+				// Lower skip
+				new Path(x,y)
+					.arc('ne')
+					.down(item.height + Math.max(item.down + Options.VS, arc*2) - arc*2)
+					.arc('ws')
+					.right(itemWidth - arc)
+					.arc('se')
+					.up(item.down + Options.VS - arc*2)
+					.arc('wn')
+					.addTo(this);
+			}
+		}
+		return this;
+	}
+}
+funcs.OptionalSequence = (...args)=>new OptionalSequence(...args);
+
+
+export class AlternatingSequence extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		if( items.length === 1 ) {
+			return new Sequence(items);
+		}
+		if( items.length !== 2 ) {
+			throw new RangeError("AlternatingSequence() must have one or two children.");
+		}
+		this.needsSpace = false;
+
+		const arc = Options.AR;
+		const vert = Options.VS;
+		const max = Math.max;
+		const first = this.items[0];
+		const second = this.items[1];
+
+		const arcX = 1 / Math.sqrt(2) * arc * 2;
+		const arcY = (1 - 1 / Math.sqrt(2)) * arc * 2;
+		const crossY = Math.max(arc, Options.VS);
+		const crossX = (crossY - arcY) + arcX;
+
+		const firstOut = max(arc + arc, crossY/2 + arc + arc, crossY/2 + vert + first.down);
+		this.up = firstOut + first.height + first.up;
+
+		const secondIn = max(arc + arc, crossY/2 + arc + arc, crossY/2 + vert + second.up);
+		this.down = secondIn + second.height + second.down;
+
+		this.height = 0;
+
+		const firstWidth = 2*(first.needsSpace?10:0) + first.width;
+		const secondWidth = 2*(second.needsSpace?10:0) + second.width;
+		this.width = 2*arc + max(firstWidth, crossX, secondWidth) + 2*arc;
+
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "altseq";
+		}
+	}
+	format(x, y, width) {
+		const arc = Options.AR;
+		const gaps = determineGaps(width, this.width);
+		new Path(x,y).right(gaps[0]).addTo(this);
+		x += gaps[0];
+		new Path(x+this.width, y).right(gaps[1]).addTo(this);
+		// bounding box
+		//new Path(x+gaps[0], y).up(this.up).right(this.width).down(this.up+this.down).left(this.width).up(this.down).addTo(this);
+		const first = this.items[0];
+		const second = this.items[1];
+
+		// top
+		const firstIn = this.up - first.up;
+		const firstOut = this.up - first.up - first.height;
+		new Path(x,y).arc('se').up(firstIn-2*arc).arc('wn').addTo(this);
+		first.format(x + 2*arc, y - firstIn, this.width - 4*arc).addTo(this);
+		new Path(x + this.width - 2*arc, y - firstOut).arc('ne').down(firstOut - 2*arc).arc('ws').addTo(this);
+
+		// bottom
+		const secondIn = this.down - second.down - second.height;
+		const secondOut = this.down - second.down;
+		new Path(x,y).arc('ne').down(secondIn - 2*arc).arc('ws').addTo(this);
+		second.format(x + 2*arc, y + secondIn, this.width - 4*arc).addTo(this);
+		new Path(x + this.width - 2*arc, y + secondOut).arc('se').up(secondOut - 2*arc).arc('wn').addTo(this);
+
+		// crossover
+		const arcX = 1 / Math.sqrt(2) * arc * 2;
+		const arcY = (1 - 1 / Math.sqrt(2)) * arc * 2;
+		const crossY = Math.max(arc, Options.VS);
+		const crossX = (crossY - arcY) + arcX;
+		const crossBar = (this.width - 4*arc - crossX)/2;
+		new Path(x+arc, y - crossY/2 - arc).arc('ws').right(crossBar)
+			.arc_8('n', 'cw').l(crossX - arcX, crossY - arcY).arc_8('sw', 'ccw')
+			.right(crossBar).arc('ne').addTo(this);
+		new Path(x+arc, y + crossY/2 + arc).arc('wn').right(crossBar)
+			.arc_8('s', 'ccw').l(crossX - arcX, -(crossY - arcY)).arc_8('nw', 'cw')
+			.right(crossBar).arc('se').addTo(this);
+
+		return this;
+	}
+}
+funcs.AlternatingSequence = (...args)=>new AlternatingSequence(...args);
+
+
+export class Choice extends DiagramMultiContainer {
+	constructor(normal, ...items) {
+		super('g', items);
+		if( typeof normal !== "number" || normal !== Math.floor(normal) ) {
+			throw new TypeError("The first argument of Choice() must be an integer.");
+		} else if(normal < 0 || normal >= items.length) {
+			throw new RangeError("The first argument of Choice() must be an index for one of the items.");
+		} else {
+			this.normal = normal;
+		}
+		var first = 0;
+		var last = items.length - 1;
+		this.width = Math.max.apply(null, this.items.map(function(el){return el.width})) + Options.AR*4;
+		this.height = this.items[normal].height;
+		this.up = this.items[first].up;
+		var arcs;
+		for(var i = first; i < normal; i++) {
+			if(i == normal-1) arcs = Options.AR*2;
+			else arcs = Options.AR;
+			this.up += Math.max(arcs, this.items[i].height + this.items[i].down + Options.VS + this.items[i+1].up);
+		}
+		this.down = this.items[last].down;
+		for(i = normal+1; i <= last; i++) {
+			if(i == normal+1) arcs = Options.AR*2;
+			else arcs = Options.AR;
+			this.down += Math.max(arcs, this.items[i-1].height + this.items[i-1].down + Options.VS + this.items[i].up);
+		}
+		this.down -= this.items[normal].height; // already counted in Choice.height
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "choice";
+		}
+	}
+	format(x,y,width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		var last = this.items.length -1;
+		var innerWidth = this.width - Options.AR*4;
+
+		// Do the elements that curve above
+		var distanceFromY;
+		for(var i = this.normal - 1; i >= 0; i--) {
+			let item = this.items[i];
+			if( i == this.normal - 1 ) {
+				distanceFromY = Math.max(Options.AR*2, this.items[this.normal].up + Options.VS + item.down + item.height);
+			}
+			new Path(x,y)
+				.arc('se')
+				.up(distanceFromY - Options.AR*2)
+				.arc('wn').addTo(this);
+			item.format(x+Options.AR*2,y - distanceFromY,innerWidth).addTo(this);
+			new Path(x+Options.AR*2+innerWidth, y-distanceFromY+item.height)
+				.arc('ne')
+				.down(distanceFromY - item.height + this.height - Options.AR*2)
+				.arc('ws').addTo(this);
+			distanceFromY += Math.max(Options.AR, item.up + Options.VS + (i === 0 ? 0 : this.items[i-1].down+this.items[i-1].height));
+		}
+
+		// Do the straight-line path.
+		new Path(x,y).right(Options.AR*2).addTo(this);
+		this.items[this.normal].format(x+Options.AR*2, y, innerWidth).addTo(this);
+		new Path(x+Options.AR*2+innerWidth, y+this.height).right(Options.AR*2).addTo(this);
+
+		// Do the elements that curve below
+		for(i = this.normal+1; i <= last; i++) {
+			let item = this.items[i];
+			if( i == this.normal + 1 ) {
+				distanceFromY = Math.max(Options.AR*2, this.height + this.items[this.normal].down + Options.VS + item.up);
+			}
+			new Path(x,y)
+				.arc('ne')
+				.down(distanceFromY - Options.AR*2)
+				.arc('ws').addTo(this);
+			item.format(x+Options.AR*2, y+distanceFromY, innerWidth).addTo(this);
+			new Path(x+Options.AR*2+innerWidth, y+distanceFromY+item.height)
+				.arc('se')
+				.up(distanceFromY - Options.AR*2 + item.height - this.height)
+				.arc('wn').addTo(this);
+			distanceFromY += Math.max(Options.AR, item.height + item.down + Options.VS + (i == last ? 0 : this.items[i+1].up));
+		}
+
+		return this;
+	}
+}
+funcs.Choice = (...args)=>new Choice(...args);
+
+
+export class HorizontalChoice extends DiagramMultiContainer {
+	constructor(...items) {
+		super('g', items);
+		if( items.length === 0 ) {
+			throw new RangeError("HorizontalChoice() must have at least one child.");
+		}
+		if( items.length === 1) {
+			return new Sequence(items);
+		}
+		const allButLast = this.items.slice(0, -1);
+		const middles = this.items.slice(1, -1);
+		const first = this.items[0];
+		const last = this.items[this.items.length - 1];
+		this.needsSpace = false;
+
+		this.width = Options.AR; // starting track
+		this.width += Options.AR*2 * (this.items.length-1); // inbetween tracks
+		this.width += sum(this.items, x=>x.width + (x.needsSpace?20:0)); // items
+		this.width += (last.height > 0 ? Options.AR : 0); // needs space to curve up
+		this.width += Options.AR; //ending track
+
+		// Always exits at entrance height
+		this.height = 0;
+
+		// All but the last have a track running above them
+		this._upperTrack = Math.max(
+			Options.AR*2,
+			Options.VS,
+			max(allButLast, x=>x.up) + Options.VS
+		);
+		this.up = Math.max(this._upperTrack, last.up);
+
+		// All but the first have a track running below them
+		// Last either straight-lines or curves up, so has different calculation
+		this._lowerTrack = Math.max(
+			Options.VS,
+			max(middles, x=>x.height+Math.max(x.down+Options.VS, Options.AR*2)),
+			last.height + last.down + Options.VS
+		);
+		if(first.height < this._lowerTrack) {
+			// Make sure there's at least 2*AR room between first exit and lower track
+			this._lowerTrack = Math.max(this._lowerTrack, first.height + Options.AR*2);
+		}
+		this.down = Math.max(this._lowerTrack, first.height + first.down);
+
+
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "horizontalchoice";
+		}
+	}
+	format(x,y,width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		const first = this.items[0];
+		const last = this.items[this.items.length-1];
+		const allButFirst = this.items.slice(1);
+		const allButLast = this.items.slice(0, -1);
+
+		// upper track
+		var upperSpan = (sum(allButLast, x=>x.width+(x.needsSpace?20:0))
+			+ (this.items.length - 2) * Options.AR*2
+			- Options.AR
+		);
+		new Path(x,y)
+			.arc('se')
+			.v(-(this._upperTrack - Options.AR*2))
+			.arc('wn')
+			.h(upperSpan)
+			.addTo(this);
+
+		// lower track
+		var lowerSpan = (sum(allButFirst, x=>x.width+(x.needsSpace?20:0))
+			+ (this.items.length - 2) * Options.AR*2
+			+ (last.height > 0 ? Options.AR : 0)
+			- Options.AR
+		);
+		var lowerStart = x + Options.AR + first.width+(first.needsSpace?20:0) + Options.AR*2;
+		new Path(lowerStart, y+this._lowerTrack)
+			.h(lowerSpan)
+			.arc('se')
+			.v(-(this._lowerTrack - Options.AR*2))
+			.arc('wn')
+			.addTo(this);
+
+		// Items
+		for(const [i, item] of enumerate(this.items)) {
+			// input track
+			if(i === 0) {
+				new Path(x,y)
+					.h(Options.AR)
+					.addTo(this);
+				x += Options.AR;
+			} else {
+				new Path(x, y - this._upperTrack)
+					.arc('ne')
+					.v(this._upperTrack - Options.AR*2)
+					.arc('ws')
+					.addTo(this);
+				x += Options.AR*2;
+			}
+
+			// item
+			var itemWidth = item.width + (item.needsSpace?20:0);
+			item.format(x, y, itemWidth).addTo(this);
+			x += itemWidth;
+
+			// output track
+			if(i === this.items.length-1) {
+				if(item.height === 0) {
+					new Path(x,y)
+						.h(Options.AR)
+						.addTo(this);
+				} else {
+					new Path(x,y+item.height)
+					.arc('se')
+					.addTo(this);
+				}
+			} else if(i === 0 && item.height > this._lowerTrack) {
+				// Needs to arc up to meet the lower track, not down.
+				if(item.height - this._lowerTrack >= Options.AR*2) {
+					new Path(x, y+item.height)
+						.arc('se')
+						.v(this._lowerTrack - item.height + Options.AR*2)
+						.arc('wn')
+						.addTo(this);
+				} else {
+					// Not enough space to fit two arcs
+					// so just bail and draw a straight line for now.
+					new Path(x, y+item.height)
+						.l(Options.AR*2, this._lowerTrack - item.height)
+						.addTo(this);
+				}
+			} else {
+				new Path(x, y+item.height)
+					.arc('ne')
+					.v(this._lowerTrack - item.height - Options.AR*2)
+					.arc('ws')
+					.addTo(this);
+			}
+		}
+		return this;
+	}
+}
+funcs.HorizontalChoice = (...args)=>new HorizontalChoice(...args);
+
+
+export class MultipleChoice extends DiagramMultiContainer {
+	constructor(normal, type, ...items) {
+		super('g', items);
+		if( typeof normal !== "number" || normal !== Math.floor(normal) ) {
+			throw new TypeError("The first argument of MultipleChoice() must be an integer.");
+		} else if(normal < 0 || normal >= items.length) {
+			throw new RangeError("The first argument of MultipleChoice() must be an index for one of the items.");
+		} else {
+			this.normal = normal;
+		}
+		if( type != "any" && type != "all" ) {
+			throw new SyntaxError("The second argument of MultipleChoice must be 'any' or 'all'.");
+		} else {
+			this.type = type;
+		}
+		this.needsSpace = true;
+		this.innerWidth = max(this.items, function(x){return x.width});
+		this.width = 30 + Options.AR + this.innerWidth + Options.AR + 20;
+		this.up = this.items[0].up;
+		this.down = this.items[this.items.length-1].down;
+		this.height = this.items[normal].height;
+		for(var i = 0; i < this.items.length; i++) {
+			let item = this.items[i];
+			let minimum;
+			if(i == normal - 1 || i == normal + 1) minimum = 10 + Options.AR;
+			else minimum = Options.AR;
+			if(i < normal) {
+				this.up += Math.max(minimum, item.height + item.down + Options.VS + this.items[i+1].up);
+			} else if(i > normal) {
+				this.down += Math.max(minimum, item.up + Options.VS + this.items[i-1].down + this.items[i-1].height);
+			}
+		}
+		this.down -= this.items[normal].height; // already counted in this.height
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "multiplechoice";
+		}
+	}
+	format(x, y, width) {
+		var gaps = determineGaps(width, this.width);
+		new Path(x, y).right(gaps[0]).addTo(this);
+		new Path(x + gaps[0] + this.width, y + this.height).right(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		var normal = this.items[this.normal];
+
+		// Do the elements that curve above
+		var distanceFromY;
+		for(var i = this.normal - 1; i >= 0; i--) {
+			var item = this.items[i];
+			if( i == this.normal - 1 ) {
+				distanceFromY = Math.max(10 + Options.AR, normal.up + Options.VS + item.down + item.height);
+			}
+			new Path(x + 30,y)
+				.up(distanceFromY - Options.AR)
+				.arc('wn').addTo(this);
+			item.format(x + 30 + Options.AR, y - distanceFromY, this.innerWidth).addTo(this);
+			new Path(x + 30 + Options.AR + this.innerWidth, y - distanceFromY + item.height)
+				.arc('ne')
+				.down(distanceFromY - item.height + this.height - Options.AR - 10)
+				.addTo(this);
+			if(i !== 0) {
+				distanceFromY += Math.max(Options.AR, item.up + Options.VS + this.items[i-1].down + this.items[i-1].height);
+			}
+		}
+
+		new Path(x + 30, y).right(Options.AR).addTo(this);
+		normal.format(x + 30 + Options.AR, y, this.innerWidth).addTo(this);
+		new Path(x + 30 + Options.AR + this.innerWidth, y + this.height).right(Options.AR).addTo(this);
+
+		for(i = this.normal+1; i < this.items.length; i++) {
+			let item = this.items[i];
+			if(i == this.normal + 1) {
+				distanceFromY = Math.max(10+Options.AR, normal.height + normal.down + Options.VS + item.up);
+			}
+			new Path(x + 30, y)
+				.down(distanceFromY - Options.AR)
+				.arc('ws')
+				.addTo(this);
+			item.format(x + 30 + Options.AR, y + distanceFromY, this.innerWidth).addTo(this);
+			new Path(x + 30 + Options.AR + this.innerWidth, y + distanceFromY + item.height)
+				.arc('se')
+				.up(distanceFromY - Options.AR + item.height - normal.height)
+				.addTo(this);
+			if(i != this.items.length - 1) {
+				distanceFromY += Math.max(Options.AR, item.height + item.down + Options.VS + this.items[i+1].up);
+			}
+		}
+		var text = new FakeSVG('g', {"class": "diagram-text"}).addTo(this);
+		new FakeSVG('title', {}, (this.type=="any"?"take one or more branches, once each, in any order":"take all branches, once each, in any order")).addTo(text);
+		new FakeSVG('path', {
+			"d": "M "+(x+30)+" "+(y-10)+" h -26 a 4 4 0 0 0 -4 4 v 12 a 4 4 0 0 0 4 4 h 26 z",
+			"class": "diagram-text"
+			}).addTo(text);
+		new FakeSVG('text', {
+			"x": x + 15,
+			"y": y + 4,
+			"class": "diagram-text"
+			}, (this.type=="any"?"1+":"all")).addTo(text);
+		new FakeSVG('path', {
+			"d": "M "+(x+this.width-20)+" "+(y-10)+" h 16 a 4 4 0 0 1 4 4 v 12 a 4 4 0 0 1 -4 4 h -16 z",
+			"class": "diagram-text"
+			}).addTo(text);
+		new FakeSVG('path', {
+			"d": "M "+(x+this.width-13)+" "+(y-2)+" a 4 4 0 1 0 6 -1 m 2.75 -1 h -4 v 4 m 0 -3 h 2",
+			"style": "stroke-width: 1.75"
+			}).addTo(text);
+		return this;
+	}
+}
+funcs.MultipleChoice = (...args)=>new MultipleChoice(...args);
+
+
+export class Optional extends FakeSVG {
+	constructor(item, skip) {
+		if( skip === undefined )
+			return new Choice(1, new Skip(), item);
+		else if ( skip === "skip" )
+			return new Choice(0, new Skip(), item);
+		else
+			throw "Unknown value for Optional()'s 'skip' argument.";
+	}
+}
+funcs.Optional = (...args)=>new Optional(...args);
+
+
+export class OneOrMore extends FakeSVG {
+	constructor(item, rep) {
+		super('g');
+		rep = rep || (new Skip());
+		this.item = wrapString(item);
+		this.rep = wrapString(rep);
+		this.width = Math.max(this.item.width, this.rep.width) + Options.AR*2;
+		this.height = this.item.height;
+		this.up = this.item.up;
+		this.down = Math.max(Options.AR*2, this.item.down + Options.VS + this.rep.up + this.rep.height + this.rep.down);
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "oneormore";
+		}
+	}
+	format(x,y,width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		// Draw item
+		new Path(x,y).right(Options.AR).addTo(this);
+		this.item.format(x+Options.AR,y,this.width-Options.AR*2).addTo(this);
+		new Path(x+this.width-Options.AR,y+this.height).right(Options.AR).addTo(this);
+
+		// Draw repeat arc
+		var distanceFromY = Math.max(Options.AR*2, this.item.height+this.item.down+Options.VS+this.rep.up);
+		new Path(x+Options.AR,y).arc('nw').down(distanceFromY-Options.AR*2).arc('ws').addTo(this);
+		this.rep.format(x+Options.AR, y+distanceFromY, this.width - Options.AR*2).addTo(this);
+		new Path(x+this.width-Options.AR, y+distanceFromY+this.rep.height).arc('se').up(distanceFromY-Options.AR*2+this.rep.height-this.item.height).arc('en').addTo(this);
+
+		return this;
+	}
+	walk(cb) {
+		cb(this);
+		this.item.walk(cb);
+		this.rep.walk(cb);
+	}
+}
+funcs.OneOrMore = (...args)=>new OneOrMore(...args);
+
+
+export class ZeroOrMore extends FakeSVG {
+	constructor(item, rep, skip) {
+		return new Optional(new OneOrMore(item, rep), skip);
+	}
+}
+funcs.ZeroOrMore = (...args)=>new ZeroOrMore(...args);
+
+
+export class Group extends FakeSVG {
+	constructor(item, label) {
+		super('g');
+		this.item = wrapString(item);
+		this.label =
+			label instanceof FakeSVG
+			  ? label
+			: label
+			  ? new Comment(label)
+			  : undefined;
+
+		this.width = Math.max(
+			this.item.width + (this.item.needsSpace?20:0),
+			this.label ? this.label.width : 0,
+			Options.AR*2);
+		this.height = this.item.height;
+		this.boxUp = this.up = Math.max(this.item.up + Options.VS, Options.AR);
+		if(this.label) {
+			this.up += this.label.up + this.label.height + this.label.down;
+		}
+		this.down = Math.max(this.item.down + Options.VS, Options.AR);
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "group";
+		}
+	}
+	format(x, y, width) {
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		new FakeSVG('rect', {
+			x,
+			y:y-this.boxUp,
+			width:this.width,
+			height:this.boxUp + this.height + this.down,
+			rx: Options.AR,
+			ry: Options.AR,
+			'class':'group-box',
+		}).addTo(this);
+
+		this.item.format(x,y,this.width).addTo(this);
+		if(this.label) {
+			this.label.format(
+				x,
+				y-(this.boxUp+this.label.down+this.label.height),
+				this.label.width).addTo(this);
+		}
+
+		return this;
+	}
+	walk(cb) {
+		cb(this);
+		this.item.walk(cb);
+		this.label.walk(cb);
+	}
+}
+funcs.Group = (...args)=>new Group(...args);
+
+
+export class Start extends FakeSVG {
+	constructor({type="simple", label}={}) {
+		super('g');
+		this.width = 20;
+		this.height = 0;
+		this.up = 10;
+		this.down = 10;
+		this.type = type;
+		if(label) {
+			this.label = ""+label;
+			this.width = Math.max(20, this.label.length * Options.CHAR_WIDTH + 10);
+		}
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "start";
+		}
+	}
+	format(x,y) {
+		let path = new Path(x, y-10);
+		if (this.type === "complex") {
+			path.down(20)
+				.m(0, -10)
+				.right(this.width)
+				.addTo(this);
+		} else {
+			path.down(20)
+				.m(10, -20)
+				.down(20)
+				.m(-10, -10)
+				.right(this.width)
+				.addTo(this);
+		}
+		if(this.label) {
+			new FakeSVG('text', {x:x, y:y-15, style:"text-anchor:start"}, this.label).addTo(this);
+		}
+		return this;
+	}
+}
+funcs.Start = (...args)=>new Start(...args);
+
+
+export class End extends FakeSVG {
+	constructor({type="simple"}={}) {
+		super('path');
+		this.width = 20;
+		this.height = 0;
+		this.up = 10;
+		this.down = 10;
+		this.type = type;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "end";
+		}
+	}
+	format(x,y) {
+		if (this.type === "complex") {
+			this.attrs.d = 'M '+x+' '+y+' h 20 m 0 -10 v 20';
+		} else {
+			this.attrs.d = 'M '+x+' '+y+' h 20 m -10 -10 v 20 m 10 -20 v 20';
+		}
+		return this;
+	}
+}
+funcs.End = (...args)=>new End(...args);
+
+
+export class Terminal extends FakeSVG {
+	constructor(text, {href, title, cls}={}) {
+		super('g', {'class': ['terminal', cls].join(" ")});
+		this.text = ""+text;
+		this.href = href;
+		this.title = title;
+		this.cls = cls;
+		this.width = this.text.length * Options.CHAR_WIDTH + 20; /* Assume that each char is .5em, and that the em is 16px */
+		this.height = 0;
+		this.up = 11;
+		this.down = 11;
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "terminal";
+		}
+	}
+	format(x, y, width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		new FakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down, rx:10, ry:10}).addTo(this);
+		var text = new FakeSVG('text', {x:x+this.width/2, y:y+4}, this.text);
+		if(this.href)
+			new FakeSVG('a', {'xlink:href': this.href}, [text]).addTo(this);
+		else
+			text.addTo(this);
+		if(this.title)
+			new FakeSVG('title', {}, [this.title]).addTo(this);
+		return this;
+	}
+}
+funcs.Terminal = (...args)=>new Terminal(...args);
+
+
+export class NonTerminal extends FakeSVG {
+	constructor(text, {href, title, cls=""}={}) {
+		super('g', {'class': ['non-terminal', cls].join(" ")});
+		this.text = ""+text;
+		this.href = href;
+		this.title = title;
+		this.cls = cls;
+		this.width = this.text.length * Options.CHAR_WIDTH + 20;
+		this.height = 0;
+		this.up = 11;
+		this.down = 11;
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "nonterminal";
+		}
+	}
+	format(x, y, width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		new FakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down}).addTo(this);
+		var text = new FakeSVG('text', {x:x+this.width/2, y:y+4}, this.text);
+		if(this.href)
+			new FakeSVG('a', {'xlink:href': this.href}, [text]).addTo(this);
+		else
+			text.addTo(this);
+		if(this.title)
+			new FakeSVG('title', {}, [this.title]).addTo(this);
+		return this;
+	}
+}
+funcs.NonTerminal = (...args)=>new NonTerminal(...args);
+
+
+export class Comment extends FakeSVG {
+	constructor(text, {href, title, cls=""}={}) {
+		super('g', {'class': ['comment', cls].join(" ")});
+		this.text = ""+text;
+		this.href = href;
+		this.title = title;
+		this.cls = cls;
+		this.width = this.text.length * Options.COMMENT_CHAR_WIDTH + 10;
+		this.height = 0;
+		this.up = 8;
+		this.down = 8;
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "comment";
+		}
+	}
+	format(x, y, width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y+this.height).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		var text = new FakeSVG('text', {x:x+this.width/2, y:y+5, class:'comment'}, this.text);
+		if(this.href)
+			new FakeSVG('a', {'xlink:href': this.href}, [text]).addTo(this);
+		else
+			text.addTo(this);
+		if(this.title)
+			new FakeSVG('title', {}, this.title).addTo(this);
+		return this;
+	}
+}
+funcs.Comment = (...args)=>new Comment(...args);
+
+
+export class Skip extends FakeSVG {
+	constructor() {
+		super('g');
+		this.width = 0;
+		this.height = 0;
+		this.up = 0;
+		this.down = 0;
+		this.needsSpace = false;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "skip";
+		}
+	}
+	format(x, y, width) {
+		new Path(x,y).right(width).addTo(this);
+		return this;
+	}
+}
+funcs.Skip = (...args)=>new Skip(...args);
+
+
+export class Block extends FakeSVG {
+	constructor({width=50, up=15, height=25, down=15, needsSpace=true}={}) {
+		super('g');
+		this.width = width;
+		this.height = height;
+		this.up = up;
+		this.down = down;
+		this.needsSpace = true;
+		if(Options.DEBUG) {
+			this.attrs['data-updown'] = this.up + " " + this.height + " " + this.down;
+			this.attrs['data-type'] = "block";
+		}
+	}
+	format(x, y, width) {
+		// Hook up the two sides if this is narrower than its stated width.
+		var gaps = determineGaps(width, this.width);
+		new Path(x,y).h(gaps[0]).addTo(this);
+		new Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
+		x += gaps[0];
+
+		new FakeSVG('rect', {x:x, y:y-this.up, width:this.width, height:this.up+this.height+this.down}).addTo(this);
+		return this;
+	}
+}
+funcs.Block = (...args)=>new Block(...args);
+
+
+function unnull(...args) {
+	// Return the first value that isn't undefined.
+	// More correct than `v1 || v2 || v3` because falsey values will be returned.
+	return args.reduce(function(sofar, x) { return sofar !== undefined ? sofar : x; });
+}
+
+function determineGaps(outer, inner) {
+	var diff = outer - inner;
+	switch(Options.INTERNAL_ALIGNMENT) {
+		case 'left': return [0, diff];
+		case 'right': return [diff, 0];
+		default: return [diff/2, diff/2];
+	}
+}
+
+function wrapString(value) {
+		return value instanceof FakeSVG ? value : new Terminal(""+value);
+}
+
+function sum(iter, func) {
+	if(!func) func = function(x) { return x; };
+	return iter.map(func).reduce(function(a,b){return a+b}, 0);
+}
+
+function max(iter, func) {
+	if(!func) func = function(x) { return x; };
+	return Math.max.apply(null, iter.map(func));
+}
+
+function SVG(name, attrs, text) {
+	attrs = attrs || {};
+	text = text || '';
+	var el = document.createElementNS("http://www.w3.org/2000/svg",name);
+	for(var attr in attrs) {
+		if(attr === 'xlink:href')
+			el.setAttributeNS("http://www.w3.org/1999/xlink", 'href', attrs[attr]);
+		else
+			el.setAttribute(attr, attrs[attr]);
+	}
+	el.textContent = text;
+	return el;
+}
+
+function escapeString(string) {
+	// Escape markdown and HTML special characters
+	return string.replace(/[*_\`\[\]<&]/g, function(charString) {
+		return '&#' + charString.charCodeAt(0) + ';';
+	});
+}
+
+function* enumerate(iter) {
+	var count = 0;
+	for(const x of iter) {
+		yield [count, x];
+		count++;
+	}
+}