JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://static.opentok.com/webrtc/v2.2/js/opentok.min.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/hmac-sha1.js"></script>
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Base64/0.3.0/base64.min.js"></script>
<script type="text/javascript">
    "use strict";
    jQuery.base64 = (function($) {
        var _PADCHAR = "=",
            _ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
            _VERSION = "1.0";

        function _getbyte64(s, i) {
            var idx = _ALPHA.indexOf(s.charAt(i));
            if (idx === -1) {
                throw "Cannot decode base64"
            }
            return idx
        }

        function _decode(s) {
            var pads = 0,
                i, b10, imax = s.length,
                x = [];
            s = String(s);
            if (imax === 0) {
                return s
            }
            if (imax % 4 !== 0) {
                throw "Cannot decode base64"
            }
            if (s.charAt(imax - 1) === _PADCHAR) {
                pads = 1;
                if (s.charAt(imax - 2) === _PADCHAR) {
                    pads = 2
                }
                imax -= 4
            }
            for (i = 0; i < imax; i += 4) {
                b10 = (_getbyte64(s, i) << 18) | (_getbyte64(s, i + 1) << 12) | (_getbyte64(s, i + 2) << 6) | _getbyte64(s, i + 3);
                x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255, b10 & 255))
            }
            switch (pads) {
                case 1:
                    b10 = (_getbyte64(s, i) << 18) | (_getbyte64(s, i + 1) << 12) | (_getbyte64(s, i + 2) << 6);
                    x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255));
                    break;
                case 2:
                    b10 = (_getbyte64(s, i) << 18) | (_getbyte64(s, i + 1) << 12);
                   ...

CSS

.video-grid {
    position:relative;
    width: 100%;
    height: 100%;
}
.video-block {
    position:absolute;
    width: 200px;
    height: 100px;
    left: 10px;
    top: 10px;
    background-color:black;
    box-shadow: 0 0 6px rgba(0, 0, 0, 0.4);
    display:block;
}
.video-panel {
    visibility: hidden;
    background-color:rgba(255, 255, 255, 0.5);
}
.withvideo .content-pane {
    width: 100%;
    height: 75%;
}
.withvideo .video-pane {
    width: 100%;
    height: 25%;
    visibility:visible;
}

JavaScript

// Initialize API key, session, and token...
      // Think of a session as a room, and a token as the key to get in to the room
      // Sessions and tokens are generated on your server and passed down to the client
      var apiKey = "45120062";
      var sessionId = "1_MX40NTEyMDA2Mn5-MTQyMDIyNDA2NDI5OX5La2dKNnpoY2wxazVFcHJKQnhkVjVtZzJ-fg";
      var secret = 'dcb6ceea722e2a6a8e078f7472fa591da2e8ae2c';
      // var token = "T1==cGFydG5lcl9pZD00NTEyMDA2MiZzaWc9YjU5MGVhODdlNWY5NGE2ZmE1YzJhYjNhNjM2Zjc1MmZhMjRkNThlNDpyb2xlPXB1Ymxpc2hlciZzZXNzaW9uX2lkPTFfTVg0ME5URXlNREEyTW41LU1UUXlNREl5TkRBMk5ESTVPWDVMYTJkS05ucG9ZMnd4YXpWRmNISktRbmhrVmpWdFp6Si1mZyZjcmVhdGVfdGltZT0xNDIwOTIzMTE1Jm5vbmNlPTAuNTg2NDI1MjY5NzMwMjcyMw==";

      //Token generation
      var secondsInDay = 86400;
      // Token Params
      var timeNow = Math.floor(Date.now() / 1000);
      var expire = timeNow + secondsInDay;
      var role = "publisher";
      var rand = Math.floor(Math.random() * 999999);
      var data = "bob" + rand;

      TB.setLogLevel(TB.DEBUG);

      // Calculation
      data = escape(data);

      var dataString = "session_id=" + sessionId + "&create_time=" + timeNow + "&expire_time=" + expire + "&role=" + role + "&connection_data=" + data + "&nonce=" + rand;

      // Encryption
      var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA1, secret);
      hmac.update(dataString);
      hash = hmac.finalize();

      preCoded = "partner_id=" + apiKey + "&sig=" + hash + ":" + dataString;
      token = "T1==" + $.base64.encode(preCoded)

      /* Video Conference Plugin using ENYO */
      var blanc = {};
      enyo.kind({
          name: "videoOption",
          kind: "blanc.videoOption"
      });
      enyo.kind({
          name: "Media",
          kind: "FittableRows",
          handlers: {
              onVideoChanged: "videoChanged"
          },
          classes: "content",
          components: [{
              kind: "Panels",
              classes: "content-panel",
       ...