diff --git a/.gitignore b/.gitignore
index 2985a47..cff3c37 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ fonts/EngraversGothic-Regular-webfont.*
fonts/kbd-custom.*
jsonl.min.js
jsonl.js
+*.sublime-workspace
*~
diff --git a/CONTRIB.md b/CONTRIB.md
index 1556c57..4964d36 100644
--- a/CONTRIB.md
+++ b/CONTRIB.md
@@ -27,5 +27,6 @@ The following third-party software packages were used in the creation of keyboar
* [URLON](https://github.com/vjeux/URLON) (URL Object Notation)
* [Jison](http://zaach.github.io/jison/) (JavaScript parser generator)
* [Hint.css](http://kushagragour.in/lab/hint/) (CSS-only tooltips)
+* [doT.js](http://olado.github.io/doT/) (fast micro-templating)
* [Font Awesome](http://fortawesome.github.io/Font-Awesome/)
* [C64 TrueType Font](http://style64.org/c64-truetype) font (by [Style64.org](https://www.style64.org))
diff --git a/css/kb.css b/css/kb.css
new file mode 100644
index 0000000..b9f247b
--- /dev/null
+++ b/css/kb.css
@@ -0,0 +1 @@
+@font-face{font-family:'engravers_gothic_fsregular';src:url("/fonts/EngraversGothic-Regular-webfont.eot");src:url("/fonts/EngraversGothic-Regular-webfont.eot?#iefix") format('embedded-opentype'),url("/fonts/EngraversGothic-Regular-webfont.woff") format('woff'),url("/fonts/EngraversGothic-Regular-webfont.ttf") format('truetype'),url("/fonts/EngraversGothic-Regular-webfont.svg#engravers_gothic_fsregular") format('svg');font-weight:'normal';font-style:'normal'}@font-face{font-family:'C64ProMono';src:url("/fonts/C64_Pro_Mono-STYLE.eot");src:url("/fonts/C64_Pro_Mono-STYLE.eot?#iefix") format('embedded-opentype'),url("/fonts/C64_Pro_Mono-STYLE.woff") format('woff'),url("/fonts/C64_Pro_Mono-STYLE.ttf") format('truetype'),url("/fonts/C64_Pro_Mono-STYLE.svg#C64ProMono") format('svg');font-weight:'normal';font-style:'normal'}@font-face{font-family:'C64Pro';src:url("/fonts/C64_Pro-STYLE.eot");src:url("/fonts/C64_Pro-STYLE.eot?#iefix") format('embedded-opentype'),url("/fonts/C64_Pro-STYLE.woff") format('woff'),url("/fonts/C64_Pro-STYLE.ttf") format('truetype'),url("/fonts/C64_Pro-STYLE.svg#C64Pro") format('svg');font-weight:'normal';font-style:'normal'}html,body{height:100%;font-family:"Segoe UI","Arial","Helvetica",sans-serif;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.body{margin:10px}.nav,.pagination,.carousel,.panel-title a{cursor:pointer}#wrap{min-height:100%;height:auto !important;height:100%;margin:0 auto -70px;padding:0 0 60px;}#footer{height:70px;background-color:#f5f5f5}#keyboard{padding:9px;position:relative;border:solid 1px #ddd;border-radius:6px;background-color:#eee;min-height:56px;box-sizing:content-box;margin-top:10px;margin-bottom:10px}#keyboard div{position:absolute;border-color:#000;box-sizing:border-box;background-clip:padding-box}#keyboard .hover .keyborder{border-color:#008000 !important;border-style:solid}#keyboard .selected .keyborder{border-color:#f00 !important;border-style:solid}#keyboard .ghosted{opacity:.5}.keylabel>div{display:table-cell;position:static !important}.keylabel3>div,.keylabel4>div,.keylabel6>div,.keylabel8>div{text-align:right}.keylabel7>div,.keylabel8>div{vertical-align:middle}.keylabel2>div,.keylabel4>div{vertical-align:bottom}.keylabel5,.keylabel6{top:100%;margin-top:-1px;font-size:10px !important;white-space:nowrap;overflow:hidden}.keylabel1.centerx-true>div,.keylabel2.centerx-true>div,.keylabel5.centerf-true>div,.keylabel7.centerx-true>div{text-align:center}.keylabel1.centery-true>div,.keylabel3.centery-true>div{vertical-align:middle}.keylabel.textsize1{font-size:8px;line-height:1em}.keylabel.textsize2{font-size:10px;line-height:1em}.keylabel.textsize3{font-size:12px;line-height:1em}.keylabel.textsize4{font-size:14px;line-height:1em}.keylabel.textsize5{font-size:16px;line-height:1em}.keylabel.textsize6{font-size:18px;line-height:1em}.keylabel.textsize7{font-size:20px;line-height:1em}.keylabel.textsize8{font-size:22px;line-height:1em}.keylabel.textsize9{font-size:24px;line-height:1em}.keylabels{font-family:"Helvetica","Arial",sans-serif}.keylabel hr{display:inline}.keylabel hr:before{position:relative;display:block;overflow:hidden;white-space:nowrap;content:"\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500\2500"}.SA .keylabels,.DSA .keylabels{font-family:'engravers_gothic_fsregular';}.DSA .keylabel5,.DSA .keylabel6,.SA .keylabel5,.SA .keylabel6{margin-top:-1px;font-size:9px !important}.DCS .keytop,.OEM .keytop{background:linear-gradient(to right,rgba(0,0,0,0) 0%,rgba(0,0,0,0.102) 40%,rgba(0,0,0,0.102) 60%,rgba(0,0,0,0) 100%);background-repeat:no-repeat}.DSA .keytop,.SA .keytop{background:radial-gradient(ellipse at center,rgba(0,0,0,0.102) 0%,rgba(0,0,0,0.102) 10%,rgba(0,0,0,0) 100%);background-repeat:no-repeat}.DCS.SPACE .keytop,.OEM.SPACE .keytop,.DSA.SPACE .keytop,.SA.SPACE .keytop{background:linear-gradient(to bottom,rgba(0,0,0,0.102) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0) 40%,rgba(0,0,0,0.102) 100%);background-repeat:no-repeat}.DSA.DISH .keytop,.DSA.HOMING .keytop,.SA.HOMING .keytop{background:radial-gradient(circle,rgba(0,0,0,0.11) 50%,rgba(0,0,0,0.039) 60%);background-repeat:no-repeat}.HOMING .keytop .keylabels{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAYAAABhYU3QAAAAGElEQVQI12P4//+/ODGYAUwwMAThwyA1ACUKJ4H2Fi17AAAAAElFTkSuQmCC");background-repeat:no-repeat;background-position:center 90%}.DSA.HOMING .keytop .keylabels,.SA.HOMING .keytop .keylabels{background-image:none}span.PETSCII{font-family:"C64ProMono";font-size:6px !important;border:solid 1px;letter-spacing:0;padding:0;margin:0}#swatches{list-style-type:none}.swatch{display:inline-block;position:relative;width:16px;height:32px;border:solid 1px #888;margin-right:-1px;margin-bottom:-6px;padding:0}#swatches.disabled .swatch{background-color:#ebebe4 !important}#swatches [data-hint]:after{white-space:nowrap}.swatch .highlight{display:none}.swatch.selected-bg .highlight.bg{display:block;z-index:100;width:6px;height:6px;border:solid 1px #000;background:#fff;opacity:.75;position:absolute;left:7px;top:23px}.swatch.selected-fg .highlight.fg{display:block;z-index:100;width:6px;height:6px;border:solid 1px #fff;background:#000;opacity:.75;position:absolute;left:1px;top:23px}.hidden{display:none}.error{border:solid 2px #d9534f}#selectionRectangle{position:absolute;border:dashed 2px #f00}#rotationCrosshairs{display:none;position:absolute;margin:0;padding:0;font-size:25px;line-height:23px;width:25px;height:25px;color:#000;text-shadow:-1px 0 #fff,0 1px #fff,1px 0 #fff,0 -1px #fff}#rawdata,#rawdata-error,#noteseditor{font-family:"Consolas","Courier New","Courier",monospace}#rawdata{width:100%}#rawdata-error{white-space:pre}#tab-content{border-left:1px solid #ddd;border-right:1px solid #ddd;border-bottom:1px solid #ddd;padding-top:15px;padding-bottom:15px;margin-left:0}#properties.row{padding-left:30px}.hint--rounded:after{width:300px}.hint:after,[data-hint]:after{white-space:pre-line}.hint:before,.hint:after,[data-hint]:before,[data-hint]:after{-webkit-transition:.1s ease;-moz-transition:.1s ease;transition:.1s ease}.modal-xl .modal-dialog{width:80vw}.modal-xxl .modal-dialog{width:90vw}.markdownDialog .modal-dialog{margin:30 auto}.markdownDialog .modal-header{height:55px}.markdownDialog .modal-footer{height:74px;margin-top:0}.markdownDialog .modal-body{padding-bottom:15px;height:calc(100vh - 205px) !important;overflow-y:auto !important}.drag-over{border:dotted 3px #f00 !important;box-sizing:border-box}@media print{html,body{overflow:hidden;height:100%;margin:0 !important;padding:0 !important}#wrap > .navbar,#wrap > .body > .btn-group,#keyboard ~ *,#keyboard + *,#footer,#helpDialog,#markdownDialog{display:none;margin:0 !important;padding:0 !important}div.body{margin:0 !important;padding:0 !important}a{color:#000;text-decoration:none}#keyboard{border:none;background-color:inherit !important;transform:scale(.75,.75);position:absolute !important;left:0;top:0;padding-left:0;padding-top:0}}.navbar-right{margin-right:0}.form-horizontal .form-inline,.form-horizontal > .form-group.form-group-sm > .form-outdent{margin-left:-15px}.form-horizontal .form-inline .form-group{margin-left:0;margin-right:0}.form-group{margin-bottom:2px}.form-control.input-sm,.input-group-sm > .form-control{height:26px;padding:2px}.input-group-sm > .input-group-btn > .btn{height:26px;padding:2px;min-width:16px}.input-group-sm > .input-group-addon{height:26px;padding:2px;min-width:16px}.form-horizontal .form-group-sm .checkbox{padding-top:3px;min-height:26px}#swap-colors{position:absolute;top:11px;left:200px;z-index:1}.color-name{display:inline-block;min-width:3em;font-size:10px;white-space:nowrap}/*# sourceMappingURL=kb.css.map */
\ No newline at end of file
diff --git a/css/kb.css.map b/css/kb.css.map
new file mode 100644
index 0000000..78583aa
--- /dev/null
+++ b/css/kb.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../kb.css"],"names":[],"mappings":"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","file":"kb.css"}
\ No newline at end of file
diff --git a/js/doT.min.js b/js/doT.min.js
new file mode 100644
index 0000000..8fe800e
--- /dev/null
+++ b/js/doT.min.js
@@ -0,0 +1,8 @@
+/* Laura Doktorova https://github.com/olado/doT */
+(function(){function p(b,a,d){return("string"===typeof a?a:a.toString()).replace(b.define||h,function(a,c,e,g){0===c.indexOf("def.")&&(c=c.substring(4));c in d||(":"===e?(b.defineParams&&g.replace(b.defineParams,function(a,b,l){d[c]={arg:b,text:l}}),c in d||(d[c]=g)):(new Function("def","def['"+c+"']="+g))(d));return""}).replace(b.use||h,function(a,c){b.useParams&&(c=c.replace(b.useParams,function(a,b,c,l){if(d[c]&&d[c].arg&&l)return a=(c+":"+l).replace(/'|\\/g,"_"),d.__exp=d.__exp||{},d.__exp[a]=
+d[c].text.replace(new RegExp("(^|[^\\w$])"+d[c].arg+"([^\\w$])","g"),"$1"+l+"$2"),b+"def.__exp['"+a+"']"}));var e=(new Function("def","return "+c))(d);return e?p(b,e,d):e})}function k(b){return b.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}var f={version:"1.0.3",templateSettings:{evaluate:/\{\{([\s\S]+?(\}?)+)\}\}/g,interpolate:/\{\{=([\s\S]+?)\}\}/g,encode:/\{\{!([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,useParams:/(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,
+define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,defineParams:/^\s*([\w$]+):([\s\S]+)/,conditional:/\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,varname:"it",strip:!0,append:!0,selfcontained:!1,doNotSkipEncoded:!1},template:void 0,compile:void 0},m;f.encodeHTMLSource=function(b){var a={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},d=b?/[&<>"'\/]/g:/&(?!#?\w+;)|<|>|"|'|\//g;return function(b){return b?
+b.toString().replace(d,function(b){return a[b]||b}):""}};m=function(){return this||(0,eval)("this")}();"undefined"!==typeof module&&module.exports?module.exports=f:"function"===typeof define&&define.amd?define(function(){return f}):m.doT=f;var r={start:"'+(",end:")+'",startencode:"'+encodeHTML("},s={start:"';out+=(",end:");out+='",startencode:"';out+=encodeHTML("},h=/$^/;f.template=function(b,a,d){a=a||f.templateSettings;var n=a.append?r:s,c,e=0,g;b=a.use||a.define?p(a,b,d||{}):b;b=("var out='"+(a.strip?
+b.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):b).replace(/'|\\/g,"\\$&").replace(a.interpolate||h,function(b,a){return n.start+k(a)+n.end}).replace(a.encode||h,function(b,a){c=!0;return n.startencode+k(a)+n.end}).replace(a.conditional||h,function(b,a,c){return a?c?"';}else if("+k(c)+"){out+='":"';}else{out+='":c?"';if("+k(c)+"){out+='":"';}out+='"}).replace(a.iterate||h,function(b,a,c,d){if(!a)return"';} } out+='";e+=1;g=d||"i"+e;a=k(a);return"';var arr"+
+e+"="+a+";if(arr"+e+"){var "+c+","+g+"=-1,l"+e+"=arr"+e+".length-1;while("+g+"
All rights reserved. (LICENSE)