code:
/**
 * Copyright (c) 2020 Aleksej Komarov
 * SPDX-License-Identifier: MIT
 */

body {
	background-size: 50%;
	background-attachment: fixed;
}

em {
  font-style: normal;
  font-weight: bold;
}

img {
  margin: 0;
  padding: 0;
  line-height: 1;
  -ms-interpolation-mode: nearest-neighbor;
  image-rendering: pixelated;
}

img.icon {
  height: 1em;
  min-height: 16px;
  width: auto;
  vertical-align: bottom;
}

a {
  color: #397ea5;
}

a.visited {
  color: #7c00e6;
}

a:visited {
  color: #7c00e6;
}

a.popt {
  text-decoration: none;
}

/* POPUPS */

.popup {
  position: fixed;
  top: 50%;
  left: 50%;
  background: #ddd;
}

.popup .close {
  position: absolute;
  background: #aaa;
  top: 0;
  right: 0;
  color: #333;
  text-decoration: none;
  z-index: 2;
  padding: 0 10px;
  height: 30px;
  line-height: 30px;
}

.popup .close:hover {
  background: #999;
}

.popup .head {
  background: #999;
  color: #ddd;
  padding: 0 10px;
  height: 30px;
  line-height: 30px;
  text-transform: uppercase;
  font-size: 0.9em;
  font-weight: bold;
  border-bottom: 2px solid green;
}

.popup input {
  border: 1px solid #999;
  background: #fff;
  margin: 0;
  padding: 5px;
  outline: none;
  color: #333;
}

.popup input[type=text]:hover,
.popup input[type=text]:active,
.popup input[type=text]:focus {
  border-color: green;
}

.popup input[type=submit] {
  padding: 5px 10px;
  background: #999;
  color: #ddd;
  text-transform: uppercase;
  font-size: 0.9em;
  font-weight: bold;
}

.popup input[type=submit]:hover,
.popup input[type=submit]:focus,
.popup input[type=submit]:active {
  background: #aaa;
  cursor: pointer;
}

.changeFont {
  padding: 10px;
}

.changeFont a {
  display: block;
  text-decoration: none;
  padding: 3px;
  color: #333;
}

.changeFont a:hover {
  background: #ccc;
}

.highlightPopup {
  padding: 10px;
  text-align: center;
}

.highlightPopup input[type=text] {
  display: block;
  width: 215px;
  text-align: left;
  margin-top: 5px;
}

.highlightPopup input.highlightColor {
  background-color: #FFFF00;
}

.highlightPopup input.highlightTermSubmit {
  margin-top: 5px;
}

/* ADMIN CONTEXT MENU */

.contextMenu {
  background-color: #ddd;
  position: fixed;
  margin: 2px;
  width: 150px;
}

.contextMenu a {
  display: block;
  padding: 2px 5px;
  text-decoration: none;
  color: #333;
}

.contextMenu a:hover {
  background-color: #ccc;
}

/* ADMIN FILTER MESSAGES MENU */

.filterMessages {
  padding: 5px;
}

.filterMessages div {
  padding: 2px 0;
}

.filterMessages input {
}

.filterMessages label {
}

.icon-stack {
  height: 1em;
  line-height: 1em;
  width: 1em;
  vertical-align: middle;
  margin-top: -2px;
}

/*****************************************
*
* OUTPUT ACTUALLY RELATED TO MESSAGES
*
******************************************/

/* MOTD */

.motd {
  color: #a4bad6;
  font-family: Verdana, sans-serif;
  white-space: normal;
}

.motd h1,
.motd h2,
.motd h3,
.motd h4,
.motd h5,
.motd h6 {
  color: #a4bad6;
  text-decoration: underline;
}

.motd a,
.motd a:link,
.motd a:visited,
.motd a:active,
.motd a:hover {
  color: #a4bad6;
}

/* ADD HERE FOR BOLD */

.bold,
.name,
.prefix,
.ooc,
.looc,
.adminooc,
.admin,
.medal,
.yell {
  font-weight: bold;
}

/* ADD HERE FOR ITALIC */

.italic, .italics {
  font-style: italic;
}

/* OUTPUT COLORS */

.highlight {
  background: yellow;
}

h1, h2, h3, h4, h5, h6 {
  color: #a4bad6;
  font-family: Georgia, Verdana, sans-serif;
}

h1.alert, h2.alert {
  color: #a4bad6;
}

em {
  font-style: normal;
  font-weight: bold;
}

.ooc {
  font-weight: bold;
}

.adminobserverooc {
  color: #0099cc;
  font-weight: bold;
}

.adminooc {
  color: #3d5bc3;
  font-weight: bold;
}

.adminsay {
  color: #ff4500;
  font-weight: bold;
}

.admin {
  color: #5975da;
  font-weight: bold;
}

.name {
  font-weight: bold;
}

.say, .emote, .infoplain, .oocplain, .warningplain {
}

.deadsay {
  color: #e2c1ff;
}

.binarysay {
  color: #1e90ff;
}

.binarysay a {
  color: #00ff00;
}

.binarysay a:active, .binarysay a:visited {
  color: #88ff88;
}

/* RADIO COLORS */
/* IF YOU CHANGE THIS KEEP IT IN SYNC WITH TGUI CONSTANTS */

.radio {
  color: #1ecc43;
}

.sciradio {
  color: #c68cfa;
}

.comradio {
  color: #fcdf03;
}

.secradio {
  color: #dd3535;
}

.medradio {
  color: #57b8f0;
}

.engradio {
  color: #f37746;
}

.suppradio {
  color: #b88646;
}

.servradio {
  color: #6ca729;
}

.syndradio {
  color: #8f4a4b;
}

.gangradio {
  color: #ac2ea1;
}

.centcomradio {
  color: #2681a5;
}

.aiprivradio {
  color: #d65d95;
}

.redteamradio {
  color: #ff4444;
}

.blueteamradio {
  color: #3434fd;
}

.greenteamradio {
  color: #34fd34;
}

.yellowteamradio {
  color: #fdfd34;
}

.yell {
  font-weight: bold;
}

.alert {
  color: #d82020;
  text-shadow: 0 0 1px #e72525;
}

.userlove	{
  color: #ff57cd;
  text-shadow: 0 0 6px #e72b8f;
  font-style: italic;
  font-size: 110%;
}

.love	{
  color: #ff45c7;
  font-style: italic;
  text-shadow: 0 0 6px #cc77ee;
}

.horny	{
  color: #ff4591;
  font-style: italic;
  text-shadow: 0 0 3px #9b4e77;
}

.bling {
  color: #D5AD6D; /*if no support for background-clip*/
  text-shadow: 0 0 3px #D5AD6D;
  font-weight: bold;
  font-size: 110%;
  background: -webkit-linear-gradient(transparent, transparent),
  -webkit-linear-gradient(top, rgba(213,173,109,1) 0%, rgba(213,173,109,1) 26%, rgba(226,186,120,1) 35%, rgba(163,126,67,1) 45%, rgba(145,112,59,1) 61%, rgba(213,173,109,1) 100%);
  background: -o-linear-gradient(transparent, transparent);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.animatedpain {
  color: #BA55D3;
  text-shadow: 0 0 6px #c75be2;
  font-size: 110%;
  animation: pain 2500ms infinite;
}

@keyframes pain {
  0% {
    color: #BA55D3;
    text-shadow: 0 0 4px #c75be2;
  }

  50% {
    color: #cc00ff;
    text-shadow: 0 0 8px #ad37ca;
  }

  100% {
    color: #BA55D3;
    text-shadow: 0 0 4px #c75be2;
  }
}

.lowpain {
  color: #a4a562;
  text-shadow: 0 0 0px #a4a562;
}

.lowestpain {
  color: #a4a562;
  font-size: 85%;
  text-shadow: 0 0 0px #a4a562;
}

.artery {
  color: #9B5455;
  text-shadow: 0 0 3px #9B5455;
}

.infection {
  color: #77c72b;
  text-shadow: 0 0 3px #68af26;
}

.necrosis {
  color: #558d20;
  text-shadow: 0 0 6px #497a1a;
}

.dead {
  color: #b280df;
  text-shadow: 0 0 2px #b280df;
}

.flashinguserdanger {
  color: #BA55D3;
  text-shadow: 0 0 6px #c75be2;
  font-size: 125%;
  animation: userdanger 250ms infinite;
}

@keyframes userdanger {
  0% {
    color: #BA55D3;
    text-shadow: 0 0 6px #c75be2;
  }

  50% {
    color: #ff56ff;
    text-shadow: 0 0 8px #ff4aff;
  }

  100% {
    color: #BA55D3;
    text-shadow: 0 0 6px #c75be2;
  }
}

.userdanger {
  color: #BA55D3;
  text-shadow: 0 0 6px #c75be2;
  font-size: 110%;
}

.bolddanger {
  color: #c51e1e;
  text-shadow: 0 0 3px #a81010;
  font-weight: bold;
}

.danger {
  color: #c51e1e;
  text-shadow: 0 0 3px #a81010;
}

.flashingdanger {
  color: #c51e1e;
  font-weight: bold;
  text-shadow: 0 0 3px #ff4444;
  animation: danger 1000ms infinite;
}

@keyframes danger {
  0% {
    color: #ff4f4f;
    text-shadow: 0 0 4px #ff4444;
  }

  50% {
    color: #c51e1e;
    text-shadow: 0 0 3px #ff4444;
  }

  100% {
    color: #ff4f4f;
    text-shadow: 0 0 4px #ff4444;
  }
}

.tinydanger {
  color: #c51e1e;
  text-shadow: 0 0 3px #a81010;
  font-size: 85%;
}

.smalldanger {
  color: #c51e1e;
  text-shadow: 0 0 3px #a81010;
  font-size: 90%;
}

.warning {
  color: #c51e1e;
  text-shadow: 0 0 3px #a81010;
  font-style: italic;
}

.alertwarning {
  color: #FF0000;
  text-shadow: 0 0 3px #ff4747;
  font-weight: bold;
}

.boldwarning {
  color: #c51e1e;
  text-shadow: 0 0 3px #a81010;
  font-style: italic;
  font-weight: bold;
}

.announce {
  color: #c51e1e;
  font-weight: bold;
}

.boldannounce {
  color: #c51e1e;
  font-weight: bold;
}

.minorannounce {
  font-weight: bold;
  font-size: 185%;
}

.greenannounce {
  color: #059223;
  font-weight: bold;
}

.rose {
  color: #ff5050;
}

.info {
  color: #9ab0ff;
  text-shadow: 0 0 3px #86a0ff;
}

.notice {
  color: #6685f5;
  text-shadow: 0 0 3px #5c78dd;
}

.tinynotice {
  color: #6685f5;
  text-shadow: 0 0 3px #5c78dd;
  font-size: 85%;
}

.tinynoticeital {
  color: #6685f5;
  text-shadow: 0 0 3px #5c78dd;
  font-style: italic;
  font-size: 85%;
}

.smallnotice {
  color: #6685f5;
  text-shadow: 0 0 3px #5c78dd;
  font-size: 90%;
}

.smallnoticeital {
  color: #6685f5;
  text-shadow: 0 0 3px #5c78dd;
  font-style: italic;
  font-size: 90%;
}

.boldnotice {
  color: #6685f5;
  text-shadow: 0 0 3px #5c78dd;
  font-weight: bold;
}

.hear {
  color: #6685f5;
  font-style: italic;
}

.adminnotice {
  color: #6685f5;
}

.adminhelp {
  color: #ff0000;
  font-weight: bold;
}

.unconscious {
  color: #a4bad6;
  font-weight: bold;
}

.suicide {
  color: #ff5050;
  font-style: italic;
}

.green {
  color: #059223;
}

.red {
  color: #FF0000;
}

.blue {
  color: #215cff;
}

.nicegreen {
  color: #059223;
  text-shadow: 0 0 3px #1f8134;
}

.cult {
  color: #973e3b;
}

.cultitalic {
  color: #973e3b;
  font-style: italic;
}

.cultbold {
  color: #973e3b;
  font-style: italic;
  font-weight: bold;
}

.cultboldtalic {
  color: #973e3b;
  font-weight: bold;
  font-size: 185%;
}

.cultlarge {
  color: #973e3b;
  font-weight: bold;
  font-size: 185%;
}

.narsie {
  color: #973e3b;
  font-weight: bold;
  font-size: 925%;
}

.narsiesmall {
  color: #973e3b;
  font-weight: bold;
  font-size: 370%;
}

.colossus {
  color: #7F282A;
  font-size: 310%;
}

.hierophant {
  color: #b441ee;
  font-weight: bold;
  font-style: italic;
}

.hierophant_warning {
  color: #c56bf1;
  font-style: italic;
}

.purple {
  color: #9956d3;
}

.holoparasite {
  color: #88809c;
}

.revennotice {
  color: #c099e2;
}

.revenboldnotice {
  color: #c099e2;
  font-weight: bold;
}

.revenbignotice {
  color: #c099e2;
  font-weight: bold;
  font-size: 185%;
}

.revenminor {
  color: #823abb;
}

.revenwarning {
  color: #760fbb;
  font-style: italic;
}

.revendanger {
  color: #760fbb;
  font-weight: bold;
  font-size: 185%;
}

.deconversion_message {
  color: #a947ff;
  font-size: 185%;
  font-style: italic;
}

.ghostalert {
  color: #6600ff;
  font-style: italic;
  font-weight: bold;
}

.alien {
  color: #855d85;
}

.noticealien {
  color: #059223;
}

.alertalien {
  color: #059223;
  font-weight: bold;
}

.changeling {
  color: #059223;
  font-style: italic;
}

.alertsyndie {
  color: #FF0000;
  font-size: 185%;
  font-weight: bold;
}

.spider {
  color: #8800ff;
  font-weight: bold;
  font-size: 185%;
}

.interface {
  color: #750e75;
}

.sans {
  font-family: "Comic Sans MS", cursive, sans-serif;
}

.papyrus {
  font-family: "Papyrus", cursive, sans-serif;
}

.robot {
  font-family: "Courier New", cursive, sans-serif;
}

.tape_recorder {
  color: #FF0000;
  font-family: "Courier New", cursive, sans-serif;
}

.command_headset {
  font-weight: bold;
  font-size: 160%;
}

.small {
  font-size: 60%;
}

.big {
  font-size: 185%;
}

.reallybig {
  font-size: 245%;
}

.extremelybig {
  font-size: 310%;
}

.greentext {
  color: #059223;
  font-size: 185%;
}

.redtext {
  color: #c51e1e;
  font-size: 185%;
}

.clown {
  color: #ff70c1;
  font-size: 160%;
  font-family: "Comic Sans MS", cursive, sans-serif;
  font-weight: bold;
}

.singing {
  font-family: "Trebuchet MS", cursive, sans-serif;
  font-style: italic;
}

.his_grace {
  color: #15D512;
  font-family: "Courier New", cursive, sans-serif;
  font-style: italic;
}

.hypnophrase {
  color: #202020;
  font-weight: bold;
  animation: hypnocolor 1500ms infinite;
  animation-direction: alternate;
}

@keyframes hypnocolor {
  0% {
    color: #202020;
  }

  25% {
    color: #4b02ac;
  }

  50% {
    color: #9f41f1;
  }

  75% {
    color: #541c9c;
  }

  100% {
    color: #7adbf3;
  }
}

.phobia {
  color: #dd0000;
  font-weight: bold;
  animation: phobia 750ms infinite;
}

@keyframes phobia {
  0% {
    color: #f75a5a;
  }

  50% {
    color: #dd0000;
  }

  100% {
    color: #f75a5a;
  }
}

.icon {
  height: 1em;
  width: auto;
}

.bigicon {
  font-size: 2.5em;
}

.infobox {
  border: 1px ridge #383243;
  background: rgba(40, 40, 60, 0.5);
  margin: 2px 8px;
  padding: 8px 12px;
  max-width: 550px;
}

.infohr {
  border: 0;
  height: 1px;
  background-image: linear-gradient(to right, rgba(187, 187, 255, 0), rgba(187, 187, 255, 0.65), rgba(187, 187, 255, 0));
}

.memo {
  color: #638500;
  text-align: center;
}

.memoedit {
  text-align: center;
  font-size: 125%;
}

.abductor {
  color: #c204c2;
  font-style: italic;
}

.mind_control {
  color: #df3da9;
  font-size: 100%;
  font-weight: bold;
  font-style: italic;
}

.slime {
  color: #00CED1;
}

.drone {
  color: #848482;
}

.monkey {
  color: #975032;
}

.swarmer {
  color: #2C75FF;
}

.resonate {
  color: #298F85;
}

.monkeyhive {
  color: #a56408;
}

.monkeylead {
  color: #af6805;
  font-size: 80%;
}

.connectionClosed, .fatalError {
  background: red;
  color: white;
  padding: 5px;
}

.connectionClosed.restored {
  background: green;
}

.internal.boldnshit {
  color: #3d5bc3;
  font-weight: bold;
}

/* HELPER CLASSES */

.text-normal {
  font-weight: normal;
  font-style: normal;
}

.hidden {
  display: none;
  visibility: hidden;
}

.ml-1 {
  margin-left: 1em;
}

.ml-2 {
  margin-left: 2em;
}

.ml-3 {
  margin-left: 3em;
}


code:
/**
 * Copyright (c) 2020 Aleksej Komarov
 * SPDX-License-Identifier: MIT
 */

html, body {
  padding: 0;
  margin: 0;
  height: 100%;
  color: #000000;
}

body {
  background: #fff;
  font-family: Verdana, sans-serif;
  font-size: 13px;
  line-height: 1.2;
  overflow-x: hidden;
  overflow-y: scroll;
  word-wrap: break-word;
}

em {
  font-style: normal;
  font-weight: bold;
}

img {
  margin: 0;
  padding: 0;
  line-height: 1;
  -ms-interpolation-mode: nearest-neighbor;
  image-rendering: pixelated;
}

img.icon {
  height: 1em;
  min-height: 16px;
  width: auto;
  vertical-align: bottom;
}

a {
  color: #0000ff;
}

a.visited {
  color: #ff00ff;
}

a:visited {
  color: #ff00ff;
}

a.popt {
  text-decoration: none;
}

/* POPUPS */

.popup {
  position: fixed;
  top: 50%;
  left: 50%;
  background: #ddd;
}

.popup .close {
  position: absolute;
  background: #aaa;
  top: 0;
  right: 0;
  color: #333;
  text-decoration: none;
  z-index: 2;
  padding: 0 10px;
  height: 30px;
  line-height: 30px;
}

.popup .close:hover {
  background: #999;
}

.popup .head {
  background: #999;
  color: #ddd;
  padding: 0 10px;
  height: 30px;
  line-height: 30px;
  text-transform: uppercase;
  font-size: 0.9em;
  font-weight: bold;
  border-bottom: 2px solid green;
}

.popup input {
  border: 1px solid #999;
  background: #fff;
  margin: 0;
  padding: 5px;
  outline: none;
  color: #333;
}

.popup input[type=text]:hover,
.popup input[type=text]:active,
.popup input[type=text]:focus {
  border-color: green;
}

.popup input[type=submit] {
  padding: 5px 10px;
  background: #999;
  color: #ddd;
  text-transform: uppercase;
  font-size: 0.9em;
  font-weight: bold;
}

.popup input[type=submit]:hover,
.popup input[type=submit]:focus,
.popup input[type=submit]:active {
  background: #aaa;
  cursor: pointer;
}

.changeFont {
  padding: 10px;
}

.changeFont a {
  display: block;
  text-decoration: none;
  padding: 3px;
  color: #333;
}

.changeFont a:hover {
  background: #ccc;
}

.highlightPopup {
  padding: 10px;
  text-align: center;
}

.highlightPopup input[type=text] {
  display: block;
  width: 215px;
  text-align: left;
  margin-top: 5px;
}

.highlightPopup input.highlightColor {
  background-color: #FFFF00;
}

.highlightPopup input.highlightTermSubmit {
  margin-top: 5px;
}

/* ADMIN CONTEXT MENU */

.contextMenu {
  background-color: #ddd;
  position: fixed;
  margin: 2px;
  width: 150px;
}

.contextMenu a {
  display: block;
  padding: 2px 5px;
  text-decoration: none;
  color: #333;
}

.contextMenu a:hover {
  background-color: #ccc;
}

/* ADMIN FILTER MESSAGES MENU */

.filterMessages {
  padding: 5px;
}

.filterMessages div {
  padding: 2px 0;
}

.filterMessages input {
}

.filterMessages label {
}

.icon-stack {
  height: 1em;
  line-height: 1em;
  width: 1em;
  vertical-align: middle;
  margin-top: -2px;
}

/*****************************************
*
* OUTPUT ACTUALLY RELATED TO MESSAGES
*
******************************************/

/* MOTD */

.motd {
  color: #638500;
  font-family: Verdana, sans-serif;
  white-space: normal;
}

.motd h1,
.motd h2,
.motd h3,
.motd h4,
.motd h5,
.motd h6 {
  color: #638500;
  text-decoration: underline;
}

.motd a,
.motd a:link,
.motd a:visited,
.motd a:active,
.motd a:hover {
  color: #638500;
}

/* ADD HERE FOR BOLD */

.bold,
.name,
.prefix,
.ooc,
.looc,
.adminooc,
.admin,
.medal,
.yell {
  font-weight: bold;
}

/* ADD HERE FOR ITALIC */

.italic,
.italics {
  font-style: italic;
}

/* OUTPUT COLORS */

.highlight {
  background: yellow;
}

h1, h2, h3, h4, h5, h6 {
  color: #0000ff;
  font-family: Georgia, Verdana, sans-serif;
}

h1.alert, h2.alert {
  color: #000000;
}

em {
  font-style: normal;
  font-weight: bold;
}

.ooc {
  font-weight: bold;
}

.adminobserverooc {
  color: #0099cc;
  font-weight: bold;
}

.adminooc {
  color: #700038;
  font-weight: bold;
}

.adminsay {
  color: #ff4500;
  font-weight: bold;
}

.admin {
  color: #4473ff;
  font-weight: bold;
}

.name {
  font-weight: bold;
}

.say, .emote, .infoplain, .oocplain, .warningplain {
}

.deadsay {
  color: #5c00e6;
}

.binarysay {
  color: #20c20e;
  background-color: #000000;
  display: block;
}

.binarysay a {
  color: #00ff00;
}

.binarysay a:active,
.binarysay a:visited {
  color: #88ff88;
}

.radio {
  color: #008000;
}

.sciradio {
  color: #993399;
}

.comradio {
  color: #948f02;
}

.secradio {
  color: #a30000;
}

.medradio {
  color: #337296;
}

.engradio {
  color: #fb5613;
}

.suppradio {
  color: #a8732b;
}

.servradio {
  color: #6eaa2c;
}

.syndradio {
  color: #6d3f40;
}

.gangradio {
  color: #ac2ea1;
}

.centcomradio {
  color: #686868;
}

.aiprivradio {
  color: #ff00ff;
}

.redteamradio {
  color: #ff0000;
}

.blueteamradio {
  color: #0000ff;
}

.greenteamradio {
  color: #00ff00;
}

.yellowteamradio {
  color: #d1ba22;
}

.yell {
  font-weight: bold;
}

.alert {
  color: #ff0000;
  text-shadow: 0 0 1px #e72525;
}

h1.alert, h2.alert {
  color: #000000;
}

.userlove	{
  color: #ff57cd;
  font-size: 110%;
  font-style: italic;
  text-shadow: 0 0 6px #e72b8f;
}

.love	{
  color: #ff45c7;
  font-style: italic;
  text-shadow: 0 0 6px #cc77ee;
}

.horny	{
  color: #ff4591;
  font-style: italic;
  text-shadow: 0 0 3px #9b4e77;
}

.bling {
  color: #D5AD6D; /*if no support for background-clip*/
  text-shadow: 0 0 3px #D5AD6D;
  font-weight: bold;
  font-size: 110%;
  background: -webkit-linear-gradient(transparent, transparent),
  -webkit-linear-gradient(top, rgba(213,173,109,1) 0%, rgba(213,173,109,1) 26%, rgba(226,186,120,1) 35%, rgba(163,126,67,1) 45%, rgba(145,112,59,1) 61%, rgba(213,173,109,1) 100%);
  background: -o-linear-gradient(transparent, transparent);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.animatedpain {
  color: #BA55D3;
  text-shadow: 0 0 6px #c75be2;
  font-size: 110%;
  animation: pain 2500ms infinite;
}

@keyframes pain {
  0% {
    color: #BA55D3;
    text-shadow: 0 0 4px #c75be2;
  }

  50% {
    color: #cc00ff;
    text-shadow: 0 0 8px #ad37ca;
  }

  100% {
    color: #BA55D3;
    text-shadow: 0 0 4px #c75be2;
  }
}

.lowpain {
  color: #a4a562;
}

.lowestpain {
  color: #a4a562;
  font-size: 85%;
}

.artery {
  color: #9B5455;
  text-shadow: 0 0 3px #9B5455;
}

.infection {
  color: #77c72b;
  text-shadow: 0 0 3px #68af26;
}

.necrosis {
  color: #558d20;
  text-shadow: 0 0 6px #497a1a;
}

.dead {
  color: #b280df;
  text-shadow: 0 0 1px #b280df;
}

.flashinguserdanger {
  color: #BA55D3;
  text-shadow: 0 0 6px #c75be2;
  font-size: 125%;
  animation: userdanger 250ms infinite;
}

@keyframes userdanger {
  0% {
    color: #BA55D3;
    text-shadow: 0 0 6px #c75be2;
  }

  50% {
    color: #ff56ff;
    text-shadow: 0 0 8px #ff4aff;
  }

  100% {
    color: #BA55D3;
    text-shadow: 0 0 6px #c75be2;
  }
}

.userdanger {
  color: #BA55D3;
  text-shadow: 0 0 6px #c75be2;
  font-size: 110%;
}

.bolddanger {
  color: #ff0000;
  text-shadow: 0 0 3px #ff4747;
  font-weight: bold;
}

.danger {
  color: #ff0000;
  text-shadow: 0 0 3px #ff4747;
}

.flashingdanger {
  color: #c51e1e;
  font-weight: bold;
  text-shadow: 0 0 3px #ff4444;
  animation: danger 1000ms infinite;
}

@keyframes danger {
  0% {
    color: #ff4f4f;
    text-shadow: 0 0 4px #ff4444;
  }

  50% {
    color: #c51e1e;
    text-shadow: 0 0 3px #ff4444;
  }

  100% {
    color: #ff4f4f;
    text-shadow: 0 0 4px #ff4444;
  }
}

.tinydanger {
  color: #ff0000;
  text-shadow: 0 0 3px #ff4747;
  font-size: 85%;
}

.smalldanger {
  color: #ff0000;
  text-shadow: 0 0 3px #ff4747;
  font-size: 90%;
}

.warning {
  color: #ff0000;
  text-shadow: 0 0 3px #ff4747;
  font-style: italic;
}

.alertwarning {
  color: #FF0000;
  text-shadow: 0 0 3px #ff4747;
  font-weight: bold;
}

.boldwarning {
  color: #ff0000;
  text-shadow: 0 0 3px #ff4747;
  font-style: italic;
  font-weight: bold;
}

.announce {
  color: #228b22;
  font-weight: bold;
}

.boldannounce {
  color: #ff0000;
  font-weight: bold;
}

.minorannounce {
  font-weight: bold;
  font-size: 185%;
}

.greenannounce {
  color: #00ff00;
  font-weight: bold;
}

.rose {
  color: #ff5050;
}

.info {
  color: #0000CC;
  text-shadow: 0 0 3px #3e3eb1;
}

.notice {
  color: #000099;
  text-shadow: 0 0 3px #262697;
}

.tinynotice {
  color: #000099;
  text-shadow: 0 0 3px #262697;
  font-size: 85%;
}

.tinynoticeital {
  color: #000099;
  text-shadow: 0 0 3px #262697;
  font-style: italic;
  font-size: 85%;
}

.smallnotice {
  color: #000099;
  text-shadow: 0 0 3px #262697;
  font-size: 90%;
}

.smallnoticeital {
  color: #000099;
  text-shadow: 0 0 3px #262697;
  font-style: italic;
  font-size: 90%;
}

.boldnotice {
  color: #000099;
  text-shadow: 0 0 3px #262697;
  font-weight: bold;
}

.hear {
  color: #000099;
  font-style: italic;
}

.adminnotice {
  color: #0000ff;
}

.adminhelp {
  color: #ff0000;
  font-weight: bold;
}

.unconscious {
  color: #0000ff;
  font-weight: bold;
}

.suicide {
  color: #ff5050;
  font-style: italic;
}

.green {
  color: #03ff39;
}

.red {
  color: #FF0000;
}

.blue {
  color: #0000FF;
}

.nicegreen {
  color: #14a833;
  text-shadow: 0 0 3px #1f8134;
}

.cult {
  color: #973e3b;
}

.cultitalic {
  color: #973e3b;
  font-style: italic;
}

.cultbold {
  color: #973e3b;
  font-style: italic;
  font-weight: bold;
}

.cultboldtalic {
  color: #973e3b;
  font-weight: bold;
  font-size: 185%;
}

.cultlarge {
  color: #973e3b;
  font-weight: bold;
  font-size: 185%;
}

.narsie {
  color: #973e3b;
  font-weight: bold;
  font-size: 925%;
}

.narsiesmall {
  color: #973e3b;
  font-weight: bold;
  font-size: 370%;
}

.colossus {
  color: #7F282A;
  font-size: 310%;
}

.hierophant {
  color: #660099;
  font-weight: bold;
  font-style: italic;
}

.hierophant_warning {
  color: #660099;
  font-style: italic;
}

.purple {
  color: #5e2d79;
}

.holoparasite {
  color: #35333a;
}

.revennotice {
  color: #1d2953;
}

.revenboldnotice {
  color: #1d2953;
  font-weight: bold;
}

.revenbignotice {
  color: #1d2953;
  font-weight: bold;
  font-size: 185%;
}

.revenminor {
  color: #823abb;
}

.revenwarning {
  color: #760fbb;
  font-style: italic;
}

.revendanger {
  color: #760fbb;
  font-weight: bold;
  font-size: 185%;
}

.deconversion_message {
  color: #5000A0;
  font-size: 185%;
  font-style: italic;
}

.ghostalert {
  color: #5c00e6;
  font-style: italic;
  font-weight: bold;
}

.alien {
  color: #543354;
}

.noticealien {
  color: #00c000;
}

.alertalien {
  color: #00c000;
  font-weight: bold;
}

.changeling {
  color: #800080;
  font-style: italic;
}

.alertsyndie {
  color: #FF0000;
  font-size: 185%;
  font-weight: bold;
}

.spider {
  color: #4d004d;
  font-weight: bold;
  font-size: 185%;
}

.interface {
  color: #330033;
}

.sans {
  font-family: "Comic Sans MS", cursive, sans-serif;
}

.papyrus {
  font-family: "Papyrus", cursive, sans-serif;
}

.robot {
  font-family: "Courier New", cursive, sans-serif;
}

.tape_recorder {
  color: #800000;
  font-family: "Courier New", cursive, sans-serif;
}

.command_headset {
  font-weight: bold;
  font-size: 160%;
}

.small {
  font-size: 60%;
}

.big {
  font-size: 185%;
}

.reallybig {
  font-size: 245%;
}

.extremelybig {
  font-size: 310%;
}

.greentext {
  color: #00FF00;
  font-size: 185%;
}

.redtext {
  color: #FF0000;
  font-size: 185%;
}

.clown {
  color: #FF69Bf;
  font-size: 160%;
  font-family: "Comic Sans MS", cursive, sans-serif;
  font-weight: bold;
}

.singing {
  font-family: "Trebuchet MS", cursive, sans-serif;
  font-style: italic;
}

.his_grace {
  color: #15D512;
  font-family: "Courier New", cursive, sans-serif;
  font-style: italic;
}

.hypnophrase {
  color: #0d0d0d;
  font-weight: bold;
  animation: hypnocolor 1500ms infinite;
  animation-direction: alternate;
}

@keyframes hypnocolor {
  0% {
    color: #0d0d0d;
  }

  25% {
    color: #410194;
  }

  50% {
    color: #7f17d8;
  }

  75% {
    color: #410194;
  }

  100% {
    color: #3bb5d3;
  }
}

.phobia {
  color: #dd0000;
  font-weight: bold;
  animation: phobia 750ms infinite;
}

@keyframes phobia {
  0% {
    color: #0d0d0d;
  }

  50% {
    color: #dd0000;
  }

  100% {
    color: #0d0d0d;
  }
}

.icon {
  height: 1em;
  width: auto;
}

.bigicon {
  font-size: 2.5em;
}

.infobox {
  border: 1px ridge #383243;
  background: rgba(40, 40, 60, 0.5);
  margin: 2px 8px;
  padding: 8px 12px;
  max-width: 550px;
}

.infohr {
  border: 0;
  height: 1px;
  background-image: linear-gradient(to right, rgba(187, 187, 255, 0), rgba(187, 187, 255, 0.65), rgba(187, 187, 255, 0));
}

.memo {
  color: #638500;
  text-align: center;
}

.memoedit {
  text-align: center;
  font-size: 125%;
}

.abductor {
  color: #800080;
  font-style: italic;
}

.mind_control {
  color: #A00D6F;
  font-size: 100%;
  font-weight: bold;
  font-style: italic;
}

.slime {
  color: #00CED1;
}

.drone {
  color: #848482;
}

.monkey {
  color: #975032;
}

.swarmer {
  color: #2C75FF;
}

.resonate {
  color: #298F85;
}

.monkeyhive {
  color: #774704;
}

.monkeylead {
  color: #774704;
  font-size: 80%;
}

.connectionClosed,
.fatalError {
  background: red;
  color: white;
  padding: 5px;
}

.connectionClosed.restored {
  background: green;
}

.internal.boldnshit {
  color: blue;
  font-weight: bold;
}

/* HELPER CLASSES */

.text-normal {
  font-weight: normal;
  font-style: normal;
}

.hidden {
  display: none;
  visibility: hidden;
}

.ml-1 {
  margin-left: 1em;
}

.ml-2 {
  margin-left: 2em;
}

.ml-3 {
  margin-left: 3em;
}

repo_name: AnalWerewolf/sundown

license: mit


code:
/**
 * Copyright (c) 2020 Aleksej Komarov
 * SPDX-License-Identifier: MIT
 */

@use 'sass:meta';
@use 'sass:color';

@use '~tgui/styles/colors.scss';
@use '~tgui/styles/base.scss' with (
  $color-bg: #202020,
  $color-bg-section: color.adjust(#202020, $lightness: -5%),
  $color-bg-grad-spread: 0%,
);

// Core styles
@include meta.load-css('~tgui/styles/reset.scss');

// Atomic classes
@include meta.load-css('~tgui/styles/atomic/candystripe.scss');
@include meta.load-css('~tgui/styles/atomic/color.scss');
@include meta.load-css('~tgui/styles/atomic/debug-layout.scss');
@include meta.load-css('~tgui/styles/atomic/outline.scss');
@include meta.load-css('~tgui/styles/atomic/text.scss');

// Components
@include meta.load-css('~tgui/styles/components/BlockQuote.scss');
@include meta.load-css('~tgui/styles/components/Button.scss');
@include meta.load-css('~tgui/styles/components/ColorBox.scss');
@include meta.load-css('~tgui/styles/components/Dimmer.scss');
@include meta.load-css('~tgui/styles/components/Divider.scss');
@include meta.load-css('~tgui/styles/components/Dropdown.scss');
@include meta.load-css('~tgui/styles/components/Flex.scss');
@include meta.load-css('~tgui/styles/components/Input.scss');
@include meta.load-css('~tgui/styles/components/Knob.scss');
@include meta.load-css('~tgui/styles/components/LabeledList.scss');
@include meta.load-css('~tgui/styles/components/Modal.scss');
@include meta.load-css('~tgui/styles/components/NoticeBox.scss');
@include meta.load-css('~tgui/styles/components/NumberInput.scss');
@include meta.load-css('~tgui/styles/components/ProgressBar.scss');
@include meta.load-css('~tgui/styles/components/Section.scss');
@include meta.load-css('~tgui/styles/components/Slider.scss');
@include meta.load-css('~tgui/styles/components/Stack.scss');
@include meta.load-css('~tgui/styles/components/Table.scss');
@include meta.load-css('~tgui/styles/components/Tabs.scss');
@include meta.load-css('~tgui/styles/components/TextArea.scss');
@include meta.load-css('~tgui/styles/components/Tooltip.scss');

// Components specific to tgui-panel
@include meta.load-css('./components/Chat.scss');
@include meta.load-css('./components/Ping.scss');
@include meta.load-css('./components/Notifications.scss');

// Layouts
@include meta.load-css('~tgui/styles/layouts/Layout.scss');
// @include meta.load-css('~tgui/styles/layouts/TitleBar.scss');
@include meta.load-css('~tgui/styles/layouts/Window.scss');

// Goonchat styles
@include meta.load-css('./goon/chat-dark.scss');

// OS13 background
.Layout__content {
  background-image: url('../assets/chatbg.png');
  background-size: 50%;
  background-attachment: fixed;
  background-repeat: repeat;
}
.topimg {
  background-image: url('../assets/chatshadow.png');
  background-size: 50%;
  position: fixed;
  background-repeat: repeat-x;
  pointer-events: none;
  left: -5px;
  top: 35px;
  width: 100%;
}


code:
/**
 * Copyright (c) 2020 Aleksej Komarov
 * SPDX-License-Identifier: MIT
 */

@use 'sass:color';
@use 'sass:meta';

@use '~tgui/styles/colors.scss' with (
  $primary: #ffffff,
  $bg-lightness: -25%,
  $fg-lightness: -10%,
  $label: #3b3b3b,
  // Makes button look actually grey due to weird maths.
  $grey: #ffffff,
  // Commenting out color maps will adjust all colors based on the lightness
  // settings above, but will add extra 10KB to the theme.
  // $fg-map-keys: (),
  // $bg-map-keys: (),
);
@use '~tgui/styles/base.scss' with (
  $color-fg: #000000,
  $color-bg: #eeeeee,
  $color-bg-section: #ffffff,
  $color-bg-grad-spread: 0%,
);

// A fat warning to anyone who wants to use this: this only half works.
// It was made almost purely for the nuke ui, and requires a good amount of manual hacks to get it working as intended.
.theme-light {
  // Atomic classes
  @include meta.load-css('~tgui/styles/atomic/color.scss');

  // Components
  @include meta.load-css('~tgui/styles/components/Tabs.scss', $with: (
    'text-color': rgba(0, 0, 0, 0.5),
    'color-default': rgba(0, 0, 0, 1),
  ));
  @include meta.load-css('~tgui/styles/components/Section.scss');
  @include meta.load-css('~tgui/styles/components/Button.scss', $with: (
    'color-default': #bbbbbb,
    'color-disabled': #363636,
    'color-selected': #0668b8,
    'color-caution': #be6209,
    'color-danger': #9a9d00,
    'color-transparent-text': rgba(0, 0, 0, 0.5),
  ));
  @include meta.load-css('~tgui/styles/components/Input.scss', $with: (
    'border-color': colors.fg(colors.$label),
    'background-color': #ffffff,
  ));
  @include meta.load-css('~tgui/styles/components/NumberInput.scss');
  @include meta.load-css('~tgui/styles/components/TextArea.scss');
  @include meta.load-css('~tgui/styles/components/Knob.scss');
  @include meta.load-css('~tgui/styles/components/Slider.scss');
  @include meta.load-css('~tgui/styles/components/ProgressBar.scss');

  // Components specific to tgui-panel
  @include meta.load-css('../components/Chat.scss', $with: (
    'text-color': #000000,
  ));

  // Layouts
  @include meta.load-css('~tgui/styles/layouts/Layout.scss', $with: (
    'scrollbar-color-multiplier': -1,
  ));
  @include meta.load-css('~tgui/styles/layouts/Window.scss');
  @include meta.load-css('~tgui/styles/layouts/TitleBar.scss', $with: (
    'text-color': rgba(0, 0, 0, 0.75),
    'background-color': base.$color-bg,
    'shadow-color-core': rgba(0, 0, 0, 0.25),
  ));

  // Goonchat styles
  @include meta.load-css('../goon/chat-light.scss');
}


code:
/**
 * @file
 * @copyright 2020 Aleksej Komarov
 * @license MIT
 */

import { sendMessage } from 'tgui/backend';
import { storage } from 'common/storage';
import { createLogger } from 'tgui/logging';

const logger = createLogger('telemetry');

const MAX_CONNECTIONS_STORED = 10;

const connectionsMatch = (a, b) => (
  a.ckey === b.ckey
    && a.address === b.address
    && a.computer_id === b.computer_id
);

export const telemetryMiddleware = store => {
  let telemetry;
  let wasRequestedWithPayload;
  return next => action => {
    const { type, payload } = action;
    // Handle telemetry requests
    if (type === 'telemetry/request') {
      // Defer telemetry request until we have the actual telemetry
      if (!telemetry) {
        logger.debug('deferred');
        wasRequestedWithPayload = payload;
        return;
      }
      logger.debug('sending');
      const limits = payload?.limits || {};
      // Trim connections according to the server limit
      const connections = telemetry.connections
        .slice(0, limits.connections);
      sendMessage({
        type: 'telemetry',
        payload: {
          connections,
        },
      });
      return;
    }
    // Keep telemetry up to date
    if (type === 'backend/update') {
      next(action);
      (async () => {
        // Extract client data
        const client = payload?.config?.client;
        if (!client) {
          logger.error('backend/update payload is missing client data!');
          return;
        }
        // Load telemetry
        if (!telemetry) {
          telemetry = await storage.get('telemetry') || {};
          if (!telemetry.connections) {
            telemetry.connections = [];
          }
          logger.debug('retrieved telemetry from storage', telemetry);
        }
        // Append a connection record
        let telemetryMutated = false;
        const duplicateConnection = telemetry.connections
          .find(conn => connectionsMatch(conn, client));
        if (!duplicateConnection) {
          telemetryMutated = true;
          telemetry.connections.unshift(client);
          if (telemetry.connections.length > MAX_CONNECTIONS_STORED) {
            telemetry.connections.pop();
          }
        }
        // Save telemetry
        if (telemetryMutated) {
          logger.debug('saving telemetry to storage', telemetry);
          storage.set('telemetry', telemetry);
        }
        // Continue deferred telemetry requests
        if (wasRequestedWithPayload) {
          const payload = wasRequestedWithPayload;
          wasRequestedWithPayload = null;
          store.dispatch({
            type: 'telemetry/request',
            payload,
          });
        }
      })();
      return;
    }
    return next(action);
  };
};


code:
/**
 * @file
 * @copyright 2020 Aleksej Komarov
 * @license MIT
 */

export const THEMES = ['dark'];

const COLOR_DARK_BG = '#202020';
const COLOR_DARK_BG_DARKER = '#171717';
const COLOR_DARK_TEXT = '#a4bad6';

let setClientThemeTimer = null;

/**
 * Darkmode preference, originally by Kmc2000.
 *
 * This lets you switch client themes by using winset.
 *
 * If you change ANYTHING in interface/skin.dmf you need to change it here.
 *
 * There's no way round it. We're essentially changing the skin by hand.
 * It's painful but it works, and is the way Lummox suggested.
 */
export const setClientTheme = name => {
  // Transmit once for fast updates and again in a little while in case we won
  // the race against statbrowser init.
  clearInterval(setClientThemeTimer);
  Byond.command(`.output statbrowser:set_theme ${name}`);
  setClientThemeTimer = setTimeout(() => {
    Byond.command(`.output statbrowser:set_theme ${name}`);
  }, 1500);
  if (name === 'dark' || name === 'light') {
    Byond.winset({
      // Main windows
      'infowindow.background-color': COLOR_DARK_BG,
      'infowindow.text-color': COLOR_DARK_TEXT,
      'info.background-color': COLOR_DARK_BG,
      'info.text-color': COLOR_DARK_TEXT,
      'browseroutput.background-color': COLOR_DARK_BG,
      'browseroutput.text-color': COLOR_DARK_TEXT,
      'outputwindow.background-color': COLOR_DARK_BG,
      'outputwindow.text-color': COLOR_DARK_TEXT,
      'mainwindow.background-color': COLOR_DARK_BG,
      'split.background-color': COLOR_DARK_BG,
      // Buttons
      'changelog.background-color': '#494949',
      'changelog.text-color': COLOR_DARK_TEXT,
      'rules.background-color': '#494949',
      'rules.text-color': COLOR_DARK_TEXT,
      'wiki.background-color': '#494949',
      'wiki.text-color': COLOR_DARK_TEXT,
      'forum.background-color': '#494949',
      'forum.text-color': COLOR_DARK_TEXT,
      'github.background-color': '#3a3a3a',
      'github.text-color': COLOR_DARK_TEXT,
      'report-issue.background-color': '#492020',
      'report-issue.text-color': COLOR_DARK_TEXT,
      'discord.background-color': '#492020',
      'discord.text-color': COLOR_DARK_TEXT,
      'codebase.background-color': '#492020',
      'codebase.text-color': COLOR_DARK_TEXT,
      // Status and verb tabs
      'output.background-color': COLOR_DARK_BG_DARKER,
      'output.text-color': COLOR_DARK_TEXT,
      'statwindow.background-color': COLOR_DARK_BG_DARKER,
      'statwindow.text-color': COLOR_DARK_TEXT,
      'stat.background-color': COLOR_DARK_BG_DARKER,
      'stat.tab-background-color': COLOR_DARK_BG,
      'stat.text-color': COLOR_DARK_TEXT,
      'stat.tab-text-color': COLOR_DARK_TEXT,
      'stat.prefix-color': COLOR_DARK_TEXT,
      'stat.suffix-color': COLOR_DARK_TEXT,
      // Say, OOC, me Buttons etc.
      'saybutton.background-color': COLOR_DARK_BG,
      'saybutton.text-color': COLOR_DARK_TEXT,
      'oocbutton.background-color': COLOR_DARK_BG,
      'oocbutton.text-color': COLOR_DARK_TEXT,
      'mebutton.background-color': COLOR_DARK_BG,
      'mebutton.text-color': COLOR_DARK_TEXT,
      'asset_cache_browser.background-color': COLOR_DARK_BG,
      'asset_cache_browser.text-color': COLOR_DARK_TEXT,
      'tooltip.background-color': COLOR_DARK_BG,
      'tooltip.text-color': COLOR_DARK_TEXT,
    });
  }
};


code:
/**
 * CSS Object Model patches
 *
 * Adapted from: https://github.com/shawnbot/aight
 *
 * @file
 * @copyright 2020 Aleksej Komarov
 * @license MIT
 */

/* eslint-disable */
(function(Proto) {
  'use strict';

  if (typeof Proto.setAttribute !== 'undefined') {
    function toAttr(prop) {
      return prop.replace(/-[a-z]/g, function (bit) {
        return bit[1].toUpperCase();
      });
    }

    Proto.setProperty = function (prop, value) {
      var attr = toAttr(prop);
      if (!value) {
        return this.removeAttribute(attr);
      }
      var str = String(value);
      return this.setAttribute(attr, str);
    };

    Proto.getPropertyValue = function (prop) {
      var attr = toAttr(prop);
      return this.getAttribute(attr) || null;
    };

    Proto.removeProperty = function (prop) {
      var attr = toAttr(prop);
      var value = this.getAttribute(attr);
      this.removeAttribute(attr);
      return value;
    };
  }

})(CSSStyleDeclaration.prototype);


code:
/**
 * @file
 * @copyright 2013 Andrea Giammarchi, WebReflection
 * @license MIT
 */

/* eslint-disable */
(function(window){
  'use strict';
  /* jshint loopfunc: true, noempty: false*/
  // http://www.w3.org/TR/dom/#element

  function createDocumentFragment() {
    return document.createDocumentFragment();
  }

  function createElement(nodeName) {
    return document.createElement(nodeName);
  }

  function enoughArguments(length, name) {
    if (!length) throw new Error(
      'Failed to construct ' +
        name +
      ': 1 argument required, but only 0 present.'
    );
  }

  function mutationMacro(nodes) {
    if (nodes.length === 1) {
      return textNodeIfPrimitive(nodes[0]);
    }
    for (var
      fragment = createDocumentFragment(),
      list = slice.call(nodes),
      i = 0; i < nodes.length; i++
    ) {
      fragment.appendChild(textNodeIfPrimitive(list[i]));
    }
    return fragment;
  }

  function textNodeIfPrimitive(node) {
    return typeof node === 'object' ? node : document.createTextNode(node);
  }

  for(var
    head,
    property,
    TemporaryPrototype,
    TemporaryTokenList,
    wrapVerifyToken,
    document = window.document,
    hOP = Object.prototype.hasOwnProperty,
    defineProperty = Object.defineProperty || function (object, property, descriptor) {
      if (hOP.call(descriptor, 'value')) {
        object[property] = descriptor.value;
      } else {
        if (hOP.call(descriptor, 'get'))
          object.__defineGetter__(property, descriptor.get);
        if (hOP.call(descriptor, 'set'))
          object.__defineSetter__(property, descriptor.set);
      }
      return object;
    },
    indexOf = [].indexOf || function indexOf(value){
      var length = this.length;
      while(length--) {
        if (this[length] === value) {
          break;
        }
      }
      return length;
    },
    // http://www.w3.org/TR/domcore/#domtokenlist
    verifyToken = function (token) {
      if (!token) {
        throw 'SyntaxError';
      } else if (spaces.test(token)) {
        throw 'InvalidCharacterError';
      }
      return token;
    },
    DOMTokenList = function (node) {
      var
        noClassName = typeof node.className === 'undefined',
        className = noClassName ?
          (node.getAttribute('class') || '') : node.className,
        isSVG = noClassName || typeof className === 'object',
        value = (isSVG ?
          (noClassName ? className : className.baseVal) :
          className
        ).replace(trim, '')
      ;
      if (value.length) {
        properties.push.apply(
          this,
          value.split(spaces)
        );
      }
      this._isSVG = isSVG;
      this._ = node;
    },
    classListDescriptor = {
      get: function get() {
        return new DOMTokenList(this);
      },
      set: function(){}
    },
    trim = /^\s+|\s+$/g,
    spaces = /\s+/,
    SPACE = '\x20',
    CLASS_LIST = 'classList',
    toggle = function toggle(token, force) {
      if (this.contains(token)) {
        if (!force) {
          // force is not true (either false or omitted)
          this.remove(token);
        }
      } else if(force === undefined || force) {
        force = true;
        this.add(token);
      }
      return !!force;
    },
    DocumentFragmentPrototype = window.DocumentFragment && DocumentFragment.prototype,
    Node = window.Node,
    NodePrototype = (Node || Element).prototype,
    CharacterData = window.CharacterData || Node,
    CharacterDataPrototype = CharacterData && CharacterData.prototype,
    DocumentType = window.DocumentType,
    DocumentTypePrototype = DocumentType && DocumentType.prototype,
    ElementPrototype = (window.Element || Node || window.HTMLElement).prototype,
    HTMLSelectElement = window.HTMLSelectElement || createElement('select').constructor,
    selectRemove = HTMLSelectElement.prototype.remove,
    SVGElement = window.SVGElement,
    properties = [
      'matches', (
        ElementPrototype.matchesSelector ||
        ElementPrototype.webkitMatchesSelector ||
        ElementPrototype.khtmlMatchesSelector ||
        ElementPrototype.mozMatchesSelector ||
        ElementPrototype.msMatchesSelector ||
        ElementPrototype.oMatchesSelector ||
        function matches(selector) {
          var parentNode = this.parentNode;
          return !!parentNode && -1 < indexOf.call(
            parentNode.querySelectorAll(selector),
            this
          );
        }
      ),
      'closest', function closest(selector) {
        var parentNode = this, matches;
        while (
          // document has no .matches
          (matches = parentNode && parentNode.matches) &&
          !parentNode.matches(selector)
        ) {
          parentNode = parentNode.parentNode;
        }
        return matches ? parentNode : null;
      },
      'prepend', function prepend() {
        var firstChild = this.firstChild,
            node = mutationMacro(arguments);
        if (firstChild) {
          this.insertBefore(node, firstChild);
        } else {
          this.appendChild(node);
        }
      },
      'append', function append() {
        this.appendChild(mutationMacro(arguments));
      },
      'before', function before() {
        var parentNode = this.parentNode;
        if (parentNode) {
          parentNode.insertBefore(
            mutationMacro(arguments), this
          );
        }
      },
      'after', function after() {
        var parentNode = this.parentNode,
            nextSibling = this.nextSibling,
            node = mutationMacro(arguments);
        if (parentNode) {
          if (nextSibling) {
            parentNode.insertBefore(node, nextSibling);
          } else {
            parentNode.appendChild(node);
          }
        }
      },
      // https://dom.spec.whatwg.org/#dom-element-toggleattribute
      'toggleAttribute', function toggleAttribute(name, force) {
        var had = this.hasAttribute(name);
        if (1 < arguments.length) {
          if (had && !force)
            this.removeAttribute(name);
          else if (force && !had)
            this.setAttribute(name, "");
        }
        else if (had)
          this.removeAttribute(name);
        else
          this.setAttribute(name, "");
        return this.hasAttribute(name);
      },
      // WARNING - DEPRECATED - use .replaceWith() instead
      'replace', function replace() {
        this.replaceWith.apply(this, arguments);
      },
      'replaceWith', function replaceWith() {
        var parentNode = this.parentNode;
        if (parentNode) {
          parentNode.replaceChild(
            mutationMacro(arguments),
            this
          );
        }
      },
      'remove', function remove() {
        var parentNode = this.parentNode;
        if (parentNode) {
          parentNode.removeChild(this);
        }
      }
    ],
    slice = properties.slice,
    i = properties.length; i; i -= 2
  ) {
    property = properties[i - 2];
    if (!(property in ElementPrototype)) {
      ElementPrototype[property] = properties[i - 1];
    }
    // avoid unnecessary re-patch when the script is included
    // gazillion times without any reason whatsoever
    // https://github.com/WebReflection/dom4/pull/48
    if (property === 'remove' && !selectRemove._dom4) {
      // see https://github.com/WebReflection/dom4/issues/19
      (HTMLSelectElement.prototype[property] = function () {
        return 0 < arguments.length ?
          selectRemove.apply(this, arguments) :
          ElementPrototype.remove.call(this);
      })._dom4 = true;
    }
    // see https://github.com/WebReflection/dom4/issues/18
    if (/^(?:before|after|replace|replaceWith|remove)$/.test(property)) {
      if (CharacterData && !(property in CharacterDataPrototype)) {
        CharacterDataPrototype[property] = properties[i - 1];
      }
      if (DocumentType && !(property in DocumentTypePrototype)) {
        DocumentTypePrototype[property] = properties[i - 1];
      }
    }
    // see https://github.com/WebReflection/dom4/pull/26
    if (/^(?:append|prepend)$/.test(property)) {
      if (DocumentFragmentPrototype) {
        if (!(property in DocumentFragmentPrototype)) {
          DocumentFragmentPrototype[property] = properties[i - 1];
        }
      } else {
        try {
          createDocumentFragment().constructor.prototype[property] = properties[i - 1];
        } catch(o_O) {}
      }
    }
  }

  // most likely an IE9 only issue
  // see https://github.com/WebReflection/dom4/issues/6
  if (!createElement('a').matches('a')) {
    ElementPrototype[property] = function(matches){
      return function (selector) {
        return matches.call(
          this.parentNode ?
            this :
            createDocumentFragment().appendChild(this),
          selector
        );
      };
    }(ElementPrototype[property]);
  }

  // used to fix both old webkit and SVG
  DOMTokenList.prototype = {
    length: 0,
    add: function add() {
      for(var j = 0, token; j < arguments.length; j++) {
        token = arguments[j];
        if(!this.contains(token)) {
          properties.push.call(this, property);
        }
      }
      if (this._isSVG) {
        this._.setAttribute('class', '' + this);
      } else {
        this._.className = '' + this;
      }
    },
    contains: (function(indexOf){
      return function contains(token) {
        i = indexOf.call(this, property = verifyToken(token));
        return -1 < i;
      };
    }([].indexOf || function (token) {
      i = this.length;
      while(i-- && this[i] !== token){}
      return i;
    })),
    item: function item(i) {
      return this[i] || null;
    },
    remove: function remove() {
      for(var j = 0, token; j < arguments.length; j++) {
        token = arguments[j];
        if(this.contains(token)) {
          properties.splice.call(this, i, 1);
        }
      }
      if (this._isSVG) {
        this._.setAttribute('class', '' + this);
      } else {
        this._.className = '' + this;
      }
    },
    toggle: toggle,
    toString: function toString() {
      return properties.join.call(this, SPACE);
    }
  };

  if (SVGElement && !(CLASS_LIST in SVGElement.prototype)) {
    defineProperty(SVGElement.prototype, CLASS_LIST, classListDescriptor);
  }

  // http://www.w3.org/TR/dom/#domtokenlist
  // iOS 5.1 has completely screwed this property
  // classList in ElementPrototype is false
  // but it's actually there as getter
  if (!(CLASS_LIST in document.documentElement)) {
    defineProperty(ElementPrototype, CLASS_LIST, classListDescriptor);
  } else {
    // iOS 5.1 and Nokia ASHA do not support multiple add or remove
    // trying to detect and fix that in here
    TemporaryTokenList = createElement('div')[CLASS_LIST];
    TemporaryTokenList.add('a', 'b', 'a');
    if ('a\x20b' != TemporaryTokenList) {
      // no other way to reach original methods in iOS 5.1
      TemporaryPrototype = TemporaryTokenList.constructor.prototype;
      if (!('add' in TemporaryPrototype)) {
        // ASHA double fails in here
        TemporaryPrototype = window.TemporaryTokenList.prototype;
      }
      wrapVerifyToken = function (original) {
        return function () {
          var i = 0;
          while (i < arguments.length) {
            original.call(this, arguments[i++]);
          }
        };
      };
      TemporaryPrototype.add = wrapVerifyToken(TemporaryPrototype.add);
      TemporaryPrototype.remove = wrapVerifyToken(TemporaryPrototype.remove);
      // toggle is broken too ^_^ ... let's fix it
      TemporaryPrototype.toggle = toggle;
    }
  }

  if (!('contains' in NodePrototype)) {
    defineProperty(NodePrototype, 'contains', {
      value: function (el) {
        while (el && el !== this) el = el.parentNode;
        return this === el;
      }
    });
  }

  if (!('head' in document)) {
    defineProperty(document, 'head', {
      get: function () {
        return head || (
          head = document.getElementsByTagName('head')[0]
        );
      }
    });
  }

  // requestAnimationFrame partial polyfill
  (function () {
    for (var
      raf,
      rAF = window.requestAnimationFrame,
      cAF = window.cancelAnimationFrame,
      prefixes = ['o', 'ms', 'moz', 'webkit'],
      i = prefixes.length;
      !cAF && i--;
    ) {
      rAF = rAF || window[prefixes[i] + 'RequestAnimationFrame'];
      cAF = window[prefixes[i] + 'CancelAnimationFrame'] ||
            window[prefixes[i] + 'CancelRequestAnimationFrame'];
    }
    if (!cAF) {
      // some FF apparently implemented rAF but no cAF
      if (rAF) {
        raf = rAF;
        rAF = function (callback) {
          var goOn = true;
          raf(function () {
            if (goOn) callback.apply(this, arguments);
          });
          return function () {
            goOn = false;
          };
        };
        cAF = function (id) {
          id();
        };
      } else {
        rAF = function (callback) {
          return setTimeout(callback, 15, 15);
        };
        cAF = function (id) {
          clearTimeout(id);
        };
      }
    }
    window.requestAnimationFrame = rAF;
    window.cancelAnimationFrame = cAF;
  }());

  // http://www.w3.org/TR/dom/#customevent
  try{new window.CustomEvent('?');}catch(o_O){
    window.CustomEvent = function(
      eventName,
      defaultInitDict
    ){

      // the infamous substitute
      function CustomEvent(type, eventInitDict) {
        /*jshint eqnull:true */
        var event = document.createEvent(eventName);
        if (typeof type != 'string') {
          throw new Error('An event name must be provided');
        }
        if (eventName == 'Event') {
          event.initCustomEvent = initCustomEvent;
        }
        if (eventInitDict == null) {
          eventInitDict = defaultInitDict;
        }
        event.initCustomEvent(
          type,
          eventInitDict.bubbles,
          eventInitDict.cancelable,
          eventInitDict.detail
        );
        return event;
      }

      // attached at runtime
      function initCustomEvent(
        type, bubbles, cancelable, detail
      ) {
        /*jshint validthis:true*/
        this.initEvent(type, bubbles, cancelable);
        this.detail = detail;
      }

      // that's it
      return CustomEvent;
    }(
      // is this IE9 or IE10 ?
      // where CustomEvent is there
      // but not usable as construtor ?
      window.CustomEvent ?
        // use the CustomEvent interface in such case
        'CustomEvent' : 'Event',
        // otherwise the common compatible one
      {
        bubbles: false,
        cancelable: false,
        detail: null
      }
    );
  }

  // window.Event as constructor
  try { new Event('_'); } catch (o_O) {
    /* jshint -W022 */
    o_O = (function ($Event) {
      function Event(type, init) {
        enoughArguments(arguments.length, 'Event');
        var out = document.createEvent('Event');
        if (!init) init = {};
        out.initEvent(
          type,
          !!init.bubbles,
          !!init.cancelable
        );
        return out;
      }
      Event.prototype = $Event.prototype;
      return Event;
    }(window.Event || function Event() {}));
    defineProperty(window, 'Event', {value: o_O});
    // Android 4 gotcha
    if (Event !== o_O) Event = o_O;
  }

  // window.KeyboardEvent as constructor
  try { new KeyboardEvent('_', {}); } catch (o_O) {
    /* jshint -W022 */
    o_O = (function ($KeyboardEvent) {
      // code inspired by https://gist.github.com/termi/4654819
      var
        initType = 0,
        defaults = {
          char: '',
          key: '',
          location: 0,
          ctrlKey: false,
          shiftKey: false,
          altKey: false,
          metaKey: false,
          altGraphKey: false,
          repeat: false,
          locale: navigator.language,
          detail: 0,
          bubbles: false,
          cancelable: false,
          keyCode: 0,
          charCode: 0,
          which: 0
        },
        eventType
      ;
      try {
        var e = document.createEvent('KeyboardEvent');
        e.initKeyboardEvent(
          'keyup', false, false, window, '+', 3,
          true, false, true, false, false
        );
        initType = (
          (e.keyIdentifier || e.key) == '+' &&
          (e.keyLocation || e.location) == 3
        ) && (
          e.ctrlKey ? e.altKey ? 1 : 3 : e.shiftKey ? 2 : 4
        ) || 9;
      } catch(o_O) {}
      eventType = 0 < initType ? 'KeyboardEvent' : 'Event';

      function getModifier(init) {
        for (var
          out = [],
          keys = [
            'ctrlKey',
            'Control',
            'shiftKey',
            'Shift',
            'altKey',
            'Alt',
            'metaKey',
            'Meta',
            'altGraphKey',
            'AltGraph'
          ],
          i = 0; i < keys.length; i += 2
        ) {
          if (init[keys[i]])
            out.push(keys[i + 1]);
        }
        return out.join(' ');
      }

      function withDefaults(target, source) {
        for (var key in source) {
          if (
            source.hasOwnProperty(key) &&
            !source.hasOwnProperty.call(target, key)
          ) target[key] = source[key];
        }
        return target;
      }

      function withInitValues(key, out, init) {
        try {
          out[key] = init[key];
        } catch(o_O) {}
      }

      function KeyboardEvent(type, init) {
        enoughArguments(arguments.length, 'KeyboardEvent');
        init = withDefaults(init || {}, defaults);
        var
          out = document.createEvent(eventType),
          ctrlKey = init.ctrlKey,
          shiftKey = init.shiftKey,
          altKey = init.altKey,
          metaKey = init.metaKey,
          altGraphKey = init.altGraphKey,
          modifiers = initType > 3 ? getModifier(init) : null,
          key = String(init.key),
          chr = String(init.char),
          location = init.location,
          keyCode = init.keyCode || (
            (init.keyCode = key) &&
            key.charCodeAt(0)
          ) || 0,
          charCode = init.charCode || (
            (init.charCode = chr) &&
            chr.charCodeAt(0)
          ) || 0,
          bubbles = init.bubbles,
          cancelable = init.cancelable,
          repeat = init.repeat,
          locale = init.locale,
          view = init.view || window,
          args
        ;
        if (!init.which) init.which = init.keyCode;
        if ('initKeyEvent' in out) {
          out.initKeyEvent(
            type, bubbles, cancelable, view,
            ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode
          );
        } else if (0 < initType && 'initKeyboardEvent' in out) {
          args = [type, bubbles, cancelable, view];
          switch (initType) {
            case 1:
              args.push(key, location, ctrlKey, shiftKey, altKey, metaKey, altGraphKey);
              break;
            case 2:
              args.push(ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode);
              break;
            case 3:
              args.push(key, location, ctrlKey, altKey, shiftKey, metaKey, altGraphKey);
              break;
            case 4:
              args.push(key, location, modifiers, repeat, locale);
              break;
            default:
              args.push(char, key, location, modifiers, repeat, locale);
          }
          out.initKeyboardEvent.apply(out, args);
        } else {
          out.initEvent(type, bubbles, cancelable);
        }
        for (key in out) {
          if (defaults.hasOwnProperty(key) && out[key] !== init[key]) {
            withInitValues(key, out, init);
          }
        }
        return out;
      }
      KeyboardEvent.prototype = $KeyboardEvent.prototype;
      return KeyboardEvent;
    }(window.KeyboardEvent || function KeyboardEvent() {}));
    defineProperty(window, 'KeyboardEvent', {value: o_O});
    // Android 4 gotcha
    if (KeyboardEvent !== o_O) KeyboardEvent = o_O;
  }

  // window.MouseEvent as constructor
  try { new MouseEvent('_', {}); } catch (o_O) {
    /* jshint -W022 */
    o_O = (function ($MouseEvent) {
      function MouseEvent(type, init) {
        enoughArguments(arguments.length, 'MouseEvent');
        var out = document.createEvent('MouseEvent');
        if (!init) init = {};
        out.initMouseEvent(
          type,
          !!init.bubbles,
          !!init.cancelable,
          init.view || window,
          init.detail || 1,
          init.screenX || 0,
          init.screenY || 0,
          init.clientX || 0,
          init.clientY || 0,
          !!init.ctrlKey,
          !!init.altKey,
          !!init.shiftKey,
          !!init.metaKey,
          init.button || 0,
          init.relatedTarget || null
        );
        return out;
      }
      MouseEvent.prototype = $MouseEvent.prototype;
      return MouseEvent;
    }(window.MouseEvent || function MouseEvent() {}));
    defineProperty(window, 'MouseEvent', {value: o_O});
    // Android 4 gotcha
    if (MouseEvent !== o_O) MouseEvent = o_O;
  }

  if (!document.querySelectorAll('*').forEach) {
    (function () {
      function patch(what) {
        var querySelectorAll = what.querySelectorAll;
        what.querySelectorAll = function qSA(css) {
          var result = querySelectorAll.call(this, css);
          result.forEach = Array.prototype.forEach;
          return result;
        };
      }
      patch(document);
      patch(Element.prototype);
    }());
  }

  try {
    // https://drafts.csswg.org/selectors-4/#the-scope-pseudo
    document.querySelector(':scope *');
  } catch(o_O) {
    (function () {
      var dataScope = 'data-scope-' + (Math.random() * 1e9 >>> 0);
      var proto = Element.prototype;
      var querySelector = proto.querySelector;
      var querySelectorAll = proto.querySelectorAll;
      proto.querySelector = function qS(css) {
        return find(this, querySelector, css);
      };
      proto.querySelectorAll = function qSA(css) {
        return find(this, querySelectorAll, css);
      };
      function find(node, method, css) {
        node.setAttribute(dataScope, null);
        var result = method.call(
          node,
          String(css).replace(
            /(^|,\s*)(:scope([ >]|$))/g,
            function ($0, $1, $2, $3) {
              return $1 + '[' + dataScope + ']' + ($3 || ' ');
            }
          )
        );
        node.removeAttribute(dataScope);
        return result;
      }
    }());
  }
}(window));
(function (global){'use strict';

  // a WeakMap fallback for DOM nodes only used as key
  var DOMMap = global.WeakMap || (function () {

    var
      counter = 0,
      dispatched = false,
      drop = false,
      value
    ;

    function dispatch(key, ce, shouldDrop) {
      drop = shouldDrop;
      dispatched = false;
      value = undefined;
      key.dispatchEvent(ce);
    }

    function Handler(value) {
      this.value = value;
    }

    Handler.prototype.handleEvent = function handleEvent(e) {
      dispatched = true;
      if (drop) {
        e.currentTarget.removeEventListener(e.type, this, false);
      } else {
        value = this.value;
      }
    };

    function DOMMap() {
      counter++;  // make id clashing highly improbable
      this.__ce__ = new Event(('@DOMMap:' + counter) + Math.random());
    }

    DOMMap.prototype = {
      'constructor': DOMMap,
      'delete': function del(key) {
        return dispatch(key, this.__ce__, true), dispatched;
      },
      'get': function get(key) {
        dispatch(key, this.__ce__, false);
        var v = value;
        value = undefined;
        return v;
      },
      'has': function has(key) {
        return dispatch(key, this.__ce__, false), dispatched;
      },
      'set': function set(key, value) {
        dispatch(key, this.__ce__, true);
        key.addEventListener(this.__ce__.type, new Handler(value), false);
        return this;
      },
    };

    return DOMMap;

  }());

  function Dict() {}
  Dict.prototype = (Object.create || Object)(null);

  // https://dom.spec.whatwg.org/#interface-eventtarget

  function createEventListener(type, callback, options) {
    function eventListener(e) {
      if (eventListener.once) {
        e.currentTarget.removeEventListener(
          e.type,
          callback,
          eventListener
        );
        eventListener.removed = true;
      }
      if (eventListener.passive) {
        e.preventDefault = createEventListener.preventDefault;
      }
      if (typeof eventListener.callback === 'function') {
        /* jshint validthis: true */
        eventListener.callback.call(this, e);
      } else if (eventListener.callback) {
        eventListener.callback.handleEvent(e);
      }
      if (eventListener.passive) {
        delete e.preventDefault;
      }
    }
    eventListener.type = type;
    eventListener.callback = callback;
    eventListener.capture = !!options.capture;
    eventListener.passive = !!options.passive;
    eventListener.once = !!options.once;
    // currently pointless but specs say to use it, so ...
    eventListener.removed = false;
    return eventListener;
  }

  createEventListener.preventDefault = function preventDefault() {};

  var
    Event = global.CustomEvent,
    dE = global.dispatchEvent,
    aEL = global.addEventListener,
    rEL = global.removeEventListener,
    counter = 0,
    increment = function () { counter++; },
    indexOf = [].indexOf || function indexOf(value){
      var length = this.length;
      while(length--) {
        if (this[length] === value) {
          break;
        }
      }
      return length;
    },
    getListenerKey = function (options) {
      return ''.concat(
        options.capture ? '1' : '0',
        options.passive ? '1' : '0',
        options.once ? '1' : '0'
      );
    },
    augment
  ;

  try {
    aEL('_', increment, {once: true});
    dE(new Event('_'));
    dE(new Event('_'));
    rEL('_', increment, {once: true});
  } catch(o_O) {}

  if (counter !== 1) {
    (function () {
      var dm = new DOMMap();
      function createAEL(aEL) {
        return function addEventListener(type, handler, options) {
          if (options && typeof options !== 'boolean') {
            var
              info = dm.get(this),
              key = getListenerKey(options),
              i, tmp, wrap
            ;
            if (!info) dm.set(this, (info = new Dict()));
            if (!(type in info)) info[type] = {
              handler: [],
              wrap: []
            };
            tmp = info[type];
            i = indexOf.call(tmp.handler, handler);
            if (i < 0) {
              i = tmp.handler.push(handler) - 1;
              tmp.wrap[i] = (wrap = new Dict());
            } else {
              wrap = tmp.wrap[i];
            }
            if (!(key in wrap)) {
              wrap[key] = createEventListener(type, handler, options);
              aEL.call(this, type, wrap[key], wrap[key].capture);
            }
          } else {
            aEL.call(this, type, handler, options);
          }
        };
      }
      function createREL(rEL) {
        return function removeEventListener(type, handler, options) {
          if (options && typeof options !== 'boolean') {
            var
              info = dm.get(this),
              key, i, tmp, wrap
            ;
            if (info && (type in info)) {
              tmp = info[type];
              i = indexOf.call(tmp.handler, handler);
              if (-1 < i) {
                key = getListenerKey(options);
                wrap = tmp.wrap[i];
                if (key in wrap) {
                  rEL.call(this, type, wrap[key], wrap[key].capture);
                  delete wrap[key];
                  // return if there are other wraps
                  for (key in wrap) return;
                  // otherwise remove all the things
                  tmp.handler.splice(i, 1);
                  tmp.wrap.splice(i, 1);
                  // if there are no other handlers
                  if (tmp.handler.length === 0)
                    // drop the info[type] entirely
                    delete info[type];
                }
              }
            }
          } else {
            rEL.call(this, type, handler, options);
          }
        };
      }

      augment = function (Constructor) {
        if (!Constructor) return;
        var proto = Constructor.prototype;
        proto.addEventListener = createAEL(proto.addEventListener);
        proto.removeEventListener = createREL(proto.removeEventListener);
      };

      if (global.EventTarget) {
        augment(EventTarget);
      } else {
        augment(global.Text);
        augment(global.Element || global.HTMLElement);
        augment(global.HTMLDocument);
        augment(global.Window || {prototype:global});
        augment(global.XMLHttpRequest);
      }

    }());
  }

}(window));


code:
/**
 * @file
 * @copyright 2014 Alexander Farkas
 * @license MIT
 */

/* eslint-disable */
(function(window, document) {
/*jshint evil:true */
  /** version */
  var version = '3.7.3';

  /** Preset options */
  var options = window.html5 || {};

  /** Used to skip problem elements */
  var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;

  /** Not all elements can be cloned in IE **/
  var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;

  /** Detect whether the browser supports default html5 styles */
  var supportsHtml5Styles;

  /** Name of the expando, to work with multiple documents or to re-shiv one document */
  var expando = '_html5shiv';

  /** The id for the the documents expando */
  var expanID = 0;

  /** Cached data for each document */
  var expandoData = {};

  /** Detect whether the browser supports unknown elements */
  var supportsUnknownElements;

  (function() {
    try {
        var a = document.createElement('a');
        a.innerHTML = '<xyz></xyz>';
        //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
        supportsHtml5Styles = ('hidden' in a);

        supportsUnknownElements = a.childNodes.length == 1 || (function() {
          // assign a false positive if unable to shiv
          (document.createElement)('a');
          var frag = document.createDocumentFragment();
          return (
            typeof frag.cloneNode == 'undefined' ||
            typeof frag.createDocumentFragment == 'undefined' ||
            typeof frag.createElement == 'undefined'
          );
        }());
    } catch(e) {
      // assign a false positive if detection fails => unable to shiv
      supportsHtml5Styles = true;
      supportsUnknownElements = true;
    }

  }());

  /*--------------------------------------------------------------------------*/

  /**
   * Creates a style sheet with the given CSS text and adds it to the document.
   * @private
   * @param {Document} ownerDocument The document.
   * @param {String} cssText The CSS text.
   * @returns {StyleSheet} The style element.
   */
  function addStyleSheet(ownerDocument, cssText) {
    var p = ownerDocument.createElement('p'),
        parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;

    p.innerHTML = 'x<style>' + cssText + '</style>';
    return parent.insertBefore(p.lastChild, parent.firstChild);
  }

  /**
   * Returns the value of `html5.elements` as an array.
   * @private
   * @returns {Array} An array of shived element node names.
   */
  function getElements() {
    var elements = html5.elements;
    return typeof elements == 'string' ? elements.split(' ') : elements;
  }

  /**
   * Extends the built-in list of html5 elements
   * @memberOf html5
   * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
   * @param {Document} ownerDocument The context document.
   */
  function addElements(newElements, ownerDocument) {
    var elements = html5.elements;
    if(typeof elements != 'string'){
      elements = elements.join(' ');
    }
    if(typeof newElements != 'string'){
      newElements = newElements.join(' ');
    }
    html5.elements = elements +' '+ newElements;
    shivDocument(ownerDocument);
  }

   /**
   * Returns the data associated to the given document
   * @private
   * @param {Document} ownerDocument The document.
   * @returns {Object} An object of data.
   */
  function getExpandoData(ownerDocument) {
    var data = expandoData[ownerDocument[expando]];
    if (!data) {
        data = {};
        expanID++;
        ownerDocument[expando] = expanID;
        expandoData[expanID] = data;
    }
    return data;
  }

  /**
   * returns a shived element for the given nodeName and document
   * @memberOf html5
   * @param {String} nodeName name of the element
   * @param {Document|DocumentFragment} ownerDocument The context document.
   * @returns {Object} The shived element.
   */
  function createElement(nodeName, ownerDocument, data){
    if (!ownerDocument) {
        ownerDocument = document;
    }
    if(supportsUnknownElements){
        return ownerDocument.createElement(nodeName);
    }
    if (!data) {
        data = getExpandoData(ownerDocument);
    }
    var node;

    if (data.cache[nodeName]) {
        node = data.cache[nodeName].cloneNode();
    } else if (saveClones.test(nodeName)) {
        node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
    } else {
        node = data.createElem(nodeName);
    }

    // Avoid adding some elements to fragments in IE < 9 because
    // * Attributes like `name` or `type` cannot be set/changed once an element
    //   is inserted into a document/fragment
    // * Link elements with `src` attributes that are inaccessible, as with
    //   a 403 response, will cause the tab/window to crash
    // * Script elements appended to fragments will execute when their `src`
    //   or `text` property is set
    return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
  }

  /**
   * returns a shived DocumentFragment for the given document
   * @memberOf html5
   * @param {Document} ownerDocument The context document.
   * @returns {Object} The shived DocumentFragment.
   */
  function createDocumentFragment(ownerDocument, data){
    if (!ownerDocument) {
        ownerDocument = document;
    }
    if(supportsUnknownElements){
        return ownerDocument.createDocumentFragment();
    }
    data = data || getExpandoData(ownerDocument);
    var clone = data.frag.cloneNode(),
        i = 0,
        elems = getElements(),
        l = elems.length;
    for(;i<l;i++){
        clone.createElement(elems[i]);
    }
    return clone;
  }

  /**
   * Shivs the `createElement` and `createDocumentFragment` methods of the document.
   * @private
   * @param {Document|DocumentFragment} ownerDocument The document.
   * @param {Object} data of the document.
   */
  function shivMethods(ownerDocument, data) {
    if (!data.cache) {
        data.cache = {};
        data.createElem = ownerDocument.createElement;
        data.createFrag = ownerDocument.createDocumentFragment;
        data.frag = data.createFrag();
    }

    ownerDocument.createElement = function(nodeName) {
      //abort shiv
      if (!html5.shivMethods) {
          return data.createElem(nodeName);
      }
      return createElement(nodeName, ownerDocument, data);
    };

    ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
      'var n=f.cloneNode(),c=n.createElement;' +
      'h.shivMethods&&(' +
        // unroll the `createElement` calls
        getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
          data.createElem(nodeName);
          data.frag.createElement(nodeName);
          return 'c("' + nodeName + '")';
        }) +
      ');return n}'
    )(html5, data.frag);
  }

  /*--------------------------------------------------------------------------*/

  /**
   * Shivs the given document.
   * @memberOf html5
   * @param {Document} ownerDocument The document to shiv.
   * @returns {Document} The shived document.
   */
  function shivDocument(ownerDocument) {
    if (!ownerDocument) {
        ownerDocument = document;
    }
    var data = getExpandoData(ownerDocument);

    if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
      data.hasCSS = !!addStyleSheet(ownerDocument,
        // corrects block display not defined in IE6/7/8/9
        'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
        // adds styling not present in IE6/7/8/9
        'mark{background:#FF0;color:#000}' +
        // hides non-rendered elements
        'template{display:none}'
      );
    }
    if (!supportsUnknownElements) {
      shivMethods(ownerDocument, data);
    }
    return ownerDocument;
  }

  /*--------------------------------------------------------------------------*/

  /**
   * The `html5` object is exposed so that more elements can be shived and
   * existing shiving can be detected on iframes.
   * @type Object
   * @example
   *
   * // options can be changed before the script is included
   * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
   */
  var html5 = {

    /**
     * An array or space separated string of node names of the elements to shiv.
     * @memberOf html5
     * @type Array|String
     */
    'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',

    /**
     * current version of html5shiv
     */
    'version': version,

    /**
     * A flag to indicate that the HTML5 style sheet should be inserted.
     * @memberOf html5
     * @type Boolean
     */
    'shivCSS': (options.shivCSS !== false),

    /**
     * Is equal to true if a browser supports creating unknown/HTML5 elements
     * @memberOf html5
     * @type boolean
     */
    'supportsUnknownElements': supportsUnknownElements,

    /**
     * A flag to indicate that the document's `createElement` and `createDocumentFragment`
     * methods should be overwritten.
     * @memberOf html5
     * @type Boolean
     */
    'shivMethods': (options.shivMethods !== false),

    /**
     * A string to describe the type of `html5` object ("default" or "default print").
     * @memberOf html5
     * @type String
     */
    'type': 'default',

    // shivs the document according to the specified `html5` object options
    'shivDocument': shivDocument,

    //creates a shived element
    createElement: createElement,

    //creates a shived documentFragment
    createDocumentFragment: createDocumentFragment,

    //extends list of elements
    addElements: addElements
  };

  /*--------------------------------------------------------------------------*/

  // expose html5
  window.html5 = html5;

  // shiv the document
  shivDocument(document);

  if(typeof module == 'object' && module.exports){
    module.exports = html5;
  }

}(window, document));