ONOS-4359: continued work on theming UI
- topo view: map and instance panel re-theming.

Change-Id: I8e5b0eda61b78b7d54593d84efccb16c54c1611e
(cherry picked from commit 2d147f6)
diff --git a/web/gui/src/main/webapp/app/fw/svg/glyphData.js b/web/gui/src/main/webapp/app/fw/svg/glyphData.js
index dfb8084..7cb5387 100644
--- a/web/gui/src/main/webapp/app/fw/svg/glyphData.js
+++ b/web/gui/src/main/webapp/app/fw/svg/glyphData.js
@@ -127,6 +127,11 @@
         glyphDataSet = {
             _viewbox: '0 0 110 110',
 
+            uiAttached: 'M91.9,16.7H18.1A5.3,5.3,0,0,0,12.8,22V68' +
+            'a5.3,5.3,0,0,0,5.3,5.3H91.9A5.3,5.3,0,0,0,97.2,68V22' +
+            'A5.3,5.3,0,0,0,91.9,16.7ZM91.6,65.2H18.4V22.3H91.6V65.2Z' +
+            'M71.5,87.5h3.8v5.9h-40.6v-5.9h3.8v-1.7h5.4v-9.7h22.3v9.7h5.3v1.7z',
+
             // Small dot
             unknown: 'M35,40a5,5,0,0,1,5-5h30a5,5,0,0,1,5,5v30a5,5,0,0,1-5,5' +
             'h-30a5,5,0,0,1-5-5z',
@@ -525,11 +530,6 @@
         badgeDataSet = {
             _viewbox: '0 0 10 10',
 
-            uiAttached: 'M2,2.5a.5,.5,0,0,1,.5-.5h5a.5,.5,0,0,1,.5,.5v3' +
-            'a.5,.5,0,0,1-.5,.5h-5a.5,.5,0,0,1-.5-.5zM2.5,2.8a.3,.3,0,0,1,' +
-            '.3-.3h4.4a.3,.3,0,0,1,.3,.3v2.4a.3,.3,0,0,1-.3,.3h-4.4' +
-            'a.3,.3,0,0,1-.3-.3zM2,6.55h6l1,1.45h-8z',
-
             checkMark: 'M8.6,3.4L4.4,7.7L1.4,4.7L2.5,3.6L4.4,5.5L7.5,2.3L8.6,3.4Z',
 
             xMark: 'M7.8,6.7L6.7,7.8,5,6.1,3.3,7.8,2.2,6.7,3.9,5,2.2,3.3,3.3,' +
diff --git a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
index 1cbdcf9..c83b3cc 100644
--- a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
+++ b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
@@ -159,12 +159,13 @@
 
     // --- Ordinal scales for 7 values.
 
-    //               blue       brown      brick red  sea green  purple     dark teal  lime
-    var lightNorm = ['#3E5780', '#78533B', '#CB4D28', '#018D61', '#8A2979', '#006D73', '#56AF00'],
-        lightMute = ['#A8B8CC', '#CCB3A8', '#FFC2BD', '#96D6BF', '#D19FCE', '#8FCCCA', '#CAEAA4'],
-
-        darkNorm  = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'],
-        darkMute  = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'];
+    // Colors per Mojo-Design's color palette..
+    //               blue       lt blue    red        lt red     dk grey    lt grey    steel
+    var lightNorm = ['#5b99d2', '#66cef6', '#d05a55', '#db7773', '#716b6b', '#aeada8', '#7e9aa8'],
+        lightMute = ['#a8cceb', '#a8e9fd', '#f1a7a7', '#f8c9c9', '#b9b5b5', '#d7d6d4', '#bdcdd5'],
+        // TODO: dark theme
+        darkNorm = ['#5b99d2', '#66cef6', '#d05a55', '#db7773', '#716b6b', '#aeada8', '#7e9aa8'],
+        darkMute = ['#a8cceb', '#a8e9fd', '#f1a7a7', '#f8c9c9', '#b9b5b5', '#d7d6d4', '#bdcdd5'];
 
     var colors= {
         light: {
@@ -215,7 +216,7 @@
                     dom.forEach(function (id, i) {
                         var x = i * 20,
                             y = k * 20,
-                            f = get(id, muted, theme);
+                            f = getColor(id, muted, theme);
                         g.append('circle').attr({
                             cx: x,
                             cy: y,
diff --git a/web/gui/src/main/webapp/app/fw/widget/toolbar.js b/web/gui/src/main/webapp/app/fw/widget/toolbar.js
index 3fe4497..87252ab 100644
--- a/web/gui/src/main/webapp/app/fw/widget/toolbar.js
+++ b/web/gui/src/main/webapp/app/fw/widget/toolbar.js
@@ -110,7 +110,8 @@
         }
 
         function adjustWidth(btnWidth) {
-            if (fs.noPxStyle(currentRow, 'width') >= maxWidth) {
+            // 0.1 fudge for rounding error
+            if (fs.noPxStyle(currentRow, 'width') + 0.1 >= maxWidth) {
                 tbWidth += btnWidth;
                 maxWidth = tbWidth;
             }
diff --git a/web/gui/src/main/webapp/app/view/topo/topo-theme.css b/web/gui/src/main/webapp/app/view/topo/topo-theme.css
index 587fcf6..052ef61 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo-theme.css
+++ b/web/gui/src/main/webapp/app/view/topo/topo-theme.css
@@ -21,40 +21,25 @@
 /* --- Base SVG Layer --- */
 
 .light #ov-topo svg {
-    background-color: #fff;
-}
-.dark #ov-topo svg {
-    background-color: #2b2b2b;
+    background-color: #f4f4f4;
 }
 
 /* --- "No Devices" Layer --- */
 
 .light #ov-topo svg .noDevsBird {
-    fill: #ecd;
-}
-.dark #ov-topo svg .noDevsBird {
-    fill: #683434;
+    fill: #db7773;
 }
 
 .light #ov-topo svg #topo-noDevsLayer text {
-    fill: #dde;
-}
-.dark #ov-topo svg #topo-noDevsLayer text {
-    fill: #3b3b4f;
+    fill: #7e9aa8;
 }
 
 /* --- Topo Map --- */
 
-#ov-topo svg #topo-map {
-    stroke-width: 2px;
-    fill: transparent;
-}
-
 .light #ov-topo svg #topo-map {
-    stroke: #ddd;
-}
-.dark #ov-topo svg #topo-map {
-    stroke: #444;
+    stroke-width: 2px;
+    stroke: #f4f4f4;
+    fill: #e5e5e6;
 }
 
 /* --- general topo-panel styling --- */
@@ -62,30 +47,18 @@
 .light .topo-p svg .glyph {
     fill: #222;
 }
-.dark .topo-p svg .glyph {
-    fill: #ddd;
-}
 
 .light .topo-p svg .glyph.overlay {
     fill: #fff;
 }
-.dark .topo-p svg .glyph.overlay {
-    fill: #222;
-}
 
 .light .topo-p h2 {
     color: black;
 }
-.dark .topo-p h2 {
-    color: #ddd;
-}
 
 .light .topo-p h3 {
     color: black;
 }
-.dark .topo-p h3 {
-    color: #ddd;
-}
 
 .topo-p td.label {
     /* works for both light and dark themes ... */
@@ -98,85 +71,70 @@
     background-color: #ccc;
     color: #ccc;
 }
-.dark .topo-p hr {
-    background-color: #888;
-    color: #888;
-}
 
 /* --- Topo Instance Panel --- */
 
 #topo-p-instance svg rect {
-    stroke-width: 3.5;
+    stroke-width: 0;
 }
 #topo-p-instance .online svg rect {
     opacity: 1;
 }
 .light #topo-p-instance svg rect {
-    fill: #ccc;
-    stroke: #aaa;
+    fill: #fbfbfb;
 }
+/* body of an instance */
 .light #topo-p-instance .online svg rect {
-    fill: #9cf;
-    stroke: #555;
-}
-.dark #topo-p-instance svg rect {
-    fill: #666;
-    stroke: #222;
-}
-.dark #topo-p-instance .online svg rect {
-    fill: #9cf;
-    stroke: #999;
+    fill: #fbfbfb;
 }
 
 
 #topo-p-instance svg .glyph {
-    fill: #888;
-    fill-rule: evenodd;
+    fill: #fff;
 }
 #topo-p-instance .online svg .glyph {
-    fill: #000;
+    fill: #fff;
 }
 
 
+/* offline */
 #topo-p-instance svg .badgeIcon {
-    fill-rule: evenodd;
     opacity: 0.4;
 }
 .light #topo-p-instance svg .badgeIcon {
-    fill: #777;
-}
-.dark #topo-p-instance svg .badgeIcon {
-    fill: #555;
+    fill: #939598;
 }
 
+/* online */
 #topo-p-instance .online svg .badgeIcon {
     opacity: 1.0;
 }
 .light #topo-p-instance .online svg .badgeIcon {
-    fill: #fff;
+    fill: #939598;
 }
-.dark #topo-p-instance .online svg .badgeIcon {
-    fill: #fff;
+.light #topo-p-instance .online svg .badgeIcon.bird {
+    fill: #ffffff;
+}
+
+#topo-p-instance svg .readyBadge {
+    visibility: hidden;
+}
+#topo-p-instance .ready svg .readyBadge {
+    visibility: visible;
 }
 
 #topo-p-instance svg text {
-    text-anchor: middle;
-    opacity: 0.3;
+    text-anchor: left;
+    opacity: 0.5;
 }
 #topo-p-instance .online svg text {
     opacity: 1.0;
 }
 .light #topo-p-instance svg text {
-    fill: #444;
+    fill: #3c3a3a;
 }
 .light #topo-p-instance .online svg text {
-    fill: #eee;
-}
-.dark #topo-p-instance svg text {
-    fill: #aaa;
-}
-.dark #topo-p-instance .online svg text {
-    fill: #ccc;
+    fill: #3c3a3a;
 }
 
 #topo-p-instance .onosInst.mastership {
@@ -188,15 +146,10 @@
 .light #topo-p-instance .onosInst.mastership.affinity svg rect {
     filter: url(#blue-glow);
 }
-.dark #topo-p-instance .onosInst.mastership.affinity svg rect {
-    filter: url(#yellow-glow);
-}
+
 .light.firefox #topo-p-instance .onosInst.mastership.affinity svg rect {
     filter: url("data:image/svg+xml;utf8, <svg xmlns = \'http://www.w3.org/2000/svg\'><filter x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\" id=\"blue-glow\"><feColorMatrix type=\"matrix\" values=\"0 0 0 0  0 0 0 0 0  0 0 0 0 0  0.7 0 0 0 1  0 \"></feColorMatrix><feGaussianBlur stdDeviation=\"3\" result=\"coloredBlur\"></feGaussianBlur><feMerge><feMergeNode in=\"coloredBlur\"></feMergeNode><feMergeNode in=\"SourceGraphic\"></feMergeNode></feMerge></filter></svg>#blue-glow");
 }
-.dark.firefox #topo-p-instance .onosInst.mastership.affinity svg rect {
-    filter: url("data:image/svg+xml;utf8, <svg xmlns = \'http://www.w3.org/2000/svg\'><filter x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\" id=\"yellow-glow\"><feColorMatrix type=\"matrix\" values=\"0 0 0 0  1.0 0 0 0 0  1.0 0 0 0 0  0.3 0 0 0 1  0 \"></feColorMatrix><feGaussianBlur stdDeviation=\"3\" result=\"coloredBlur\"></feGaussianBlur><feMerge><feMergeNode in=\"coloredBlur\"></feMergeNode><feMergeNode in=\"SourceGraphic\"></feMergeNode></feMerge></filter></svg>#yellow-glow");
-}
 
 /* --- Topo Nodes --- */
 
@@ -213,19 +166,19 @@
     fill: #f90;
     filter: url(#blue-glow);
 }
-.dark #ov-topo svg .node.selected rect,
-.dark #ov-topo svg .node.selected circle {
-    fill: #f90;
-    filter: url(#yellow-glow);
-}
+/*.dark #ov-topo svg .node.selected rect,*/
+/*.dark #ov-topo svg .node.selected circle {*/
+    /*fill: #f90;*/
+    /*filter: url(#yellow-glow);*/
+/*}*/
 .light.firefox #ov-topo svg .node.selected rect,
 .light.firefox #ov-topo svg .node.selected circle {
     filter: url("data:image/svg+xml;utf8, <svg xmlns = \'http://www.w3.org/2000/svg\'><filter x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\" id=\"blue-glow\"><feColorMatrix type=\"matrix\" values=\"0 0 0 0  0 0 0 0 0  0 0 0 0 0  0.7 0 0 0 1  0 \"></feColorMatrix><feGaussianBlur stdDeviation=\"3\" result=\"coloredBlur\"></feGaussianBlur><feMerge><feMergeNode in=\"coloredBlur\"></feMergeNode><feMergeNode in=\"SourceGraphic\"></feMergeNode></feMerge></filter></svg>#blue-glow");
 }
-.dark.firefox #ov-topo svg .node.selected rect,
-.dark.firefox #ov-topo svg .node.selected circle {
-    filter: url("data:image/svg+xml;utf8, <svg xmlns = \'http://www.w3.org/2000/svg\'><filter x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\" id=\"yellow-glow\"><feColorMatrix type=\"matrix\" values=\"0 0 0 0  1.0 0 0 0 0  1.0 0 0 0 0  0.3 0 0 0 1  0 \"></feColorMatrix><feGaussianBlur stdDeviation=\"3\" result=\"coloredBlur\"></feGaussianBlur><feMerge><feMergeNode in=\"coloredBlur\"></feMergeNode><feMergeNode in=\"SourceGraphic\"></feMergeNode></feMerge></filter></svg>#yellow-glow");
-}
+/*.dark.firefox #ov-topo svg .node.selected rect,*/
+/*.dark.firefox #ov-topo svg .node.selected circle {*/
+    /*filter: url("data:image/svg+xml;utf8, <svg xmlns = \'http://www.w3.org/2000/svg\'><filter x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\" id=\"yellow-glow\"><feColorMatrix type=\"matrix\" values=\"0 0 0 0  1.0 0 0 0 0  1.0 0 0 0 0  0.3 0 0 0 1  0 \"></feColorMatrix><feGaussianBlur stdDeviation=\"3\" result=\"coloredBlur\"></feGaussianBlur><feMerge><feMergeNode in=\"coloredBlur\"></feMergeNode><feMergeNode in=\"SourceGraphic\"></feMergeNode></feMerge></filter></svg>#yellow-glow");*/
+/*}*/
 
 /* Device Nodes */
 
@@ -239,17 +192,11 @@
 .light #ov-topo svg .node.device.fixed rect {
     stroke: #aaa;
 }
-.dark #ov-topo svg .node.device.fixed rect {
-    stroke: #999;
-}
 
 /* note: device is offline without the 'online' class */
 .light #ov-topo svg .node.device {
     fill: #777;
 }
-.dark #ov-topo svg .node.device {
-    fill: #555;
-}
 
 .light #ov-topo svg .node.device rect {
     stroke: #666;
@@ -261,14 +208,10 @@
 .light #ov-topo svg .node.device.online {
     fill: #6e7fa3;
 }
-.dark #ov-topo svg .node.device.online {
-    fill: #4E5C7F;
-}
 
 /* note: device is offline without the 'online' class */
 #ov-topo svg .node.device text {
     fill: #bbb;
-    font: 10pt sans-serif;
 }
 
 #ov-topo svg .node.device.online text {
@@ -340,25 +283,15 @@
 .light #ov-topo svg .node.host text {
     fill: #846;
 }
-.dark #ov-topo svg .node.host text {
-    fill: #BB809D;
-}
 
 .light svg .node.host circle {
     stroke: #000;
     fill: #edb;
 }
-.dark svg .node.host circle {
-    stroke: #eee;
-    fill: #B2A180;
-}
 
 .light svg .node.host .svgIcon {
     fill: #444;
 }
-.dark svg .node.host .svgIcon {
-    fill: #222;
-}
 
 /* --- Topo Links --- */
 
@@ -374,25 +307,25 @@
 .light #ov-topo svg .link.enhanced {
     filter: url(#blue-glow);
 }
-.dark #ov-topo svg .link.selected,
-.dark #ov-topo svg .link.enhanced {
-    filter: url(#yellow-glow);
-}
+/*.dark #ov-topo svg .link.selected,*/
+/*.dark #ov-topo svg .link.enhanced {*/
+    /*filter: url(#yellow-glow);*/
+/*}*/
 .light.firefox #ov-topo svg .link.selected,
 .light.firefox #ov-topo svg .link.enhanced {
     filter: url("data:image/svg+xml;utf8, <svg xmlns = \'http://www.w3.org/2000/svg\'><filter x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\" id=\"blue-glow\"><feColorMatrix type=\"matrix\" values=\"0 0 0 0  0 0 0 0 0  0 0 0 0 0  0.7 0 0 0 1  0 \"></feColorMatrix><feGaussianBlur stdDeviation=\"3\" result=\"coloredBlur\"></feGaussianBlur><feMerge><feMergeNode in=\"coloredBlur\"></feMergeNode><feMergeNode in=\"SourceGraphic\"></feMergeNode></feMerge></filter></svg>#blue-glow");
 }
-.dark.firefox #ov-topo svg .link.selected,
-.dark.firefox #ov-topo svg .link.enhanced {
-    filter: url("data:image/svg+xml;utf8, <svg xmlns = \'http://www.w3.org/2000/svg\'><filter x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\" id=\"yellow-glow\"><feColorMatrix type=\"matrix\" values=\"0 0 0 0  1.0 0 0 0 0  1.0 0 0 0 0  0.3 0 0 0 1  0 \"></feColorMatrix><feGaussianBlur stdDeviation=\"3\" result=\"coloredBlur\"></feGaussianBlur><feMerge><feMergeNode in=\"coloredBlur\"></feMergeNode><feMergeNode in=\"SourceGraphic\"></feMergeNode></feMerge></filter></svg>#yellow-glow");
+/*.dark.firefox #ov-topo svg .link.selected,*/
+/*.dark.firefox #ov-topo svg .link.enhanced {*/
+    /*filter: url("data:image/svg+xml;utf8, <svg xmlns = \'http://www.w3.org/2000/svg\'><filter x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\" id=\"yellow-glow\"><feColorMatrix type=\"matrix\" values=\"0 0 0 0  1.0 0 0 0 0  1.0 0 0 0 0  0.3 0 0 0 1  0 \"></feColorMatrix><feGaussianBlur stdDeviation=\"3\" result=\"coloredBlur\"></feGaussianBlur><feMerge><feMergeNode in=\"coloredBlur\"></feMergeNode><feMergeNode in=\"SourceGraphic\"></feMergeNode></feMerge></filter></svg>#yellow-glow");*/
 
-}
+/*}*/
 
 #ov-topo svg .link.inactive {
     opacity: .5;
     stroke-dasharray: 8 4;
 }
-/* FIXME: Review for not-permitted links */
+/* TODO: Review for not-permitted links */
 #ov-topo svg .link.not-permitted {
     stroke: rgb(255,0,0);
     stroke-width: 5.0;
@@ -405,9 +338,6 @@
 .light #ov-topo svg .link.secondary {
     stroke: rgba(0,153,51,0.5);
 }
-.dark #ov-topo svg .link.secondary {
-    stroke: rgba(121,231,158,0.5);
-}
 
 /* Port traffic color visualization for Kbps, Mbps, and Gbps */
 
@@ -415,37 +345,21 @@
     stroke: rgb(0,153,51);
     stroke-width: 5.0;
 }
-.dark #ov-topo svg .link.secondary.port-traffic-Kbps {
-    stroke: rgb(98, 153, 118);
-    stroke-width: 5.0;
-}
 
 .light #ov-topo svg .link.secondary.port-traffic-Mbps {
     stroke: rgb(128,145,27);
     stroke-width: 6.5;
 }
-.dark #ov-topo svg .link.secondary.port-traffic-Mbps {
-    stroke: rgb(91, 109, 54);
-    stroke-width: 6.5;
-}
 
 .light #ov-topo svg .link.secondary.port-traffic-Gbps {
     stroke: rgb(255, 137, 3);
     stroke-width: 8.0;
 }
-.dark #ov-topo svg .link.secondary.port-traffic-Gbps {
-    stroke: rgb(174, 119, 55);
-    stroke-width: 8.0;
-}
 
 .light #ov-topo svg .link.secondary.port-traffic-Gbps-choked {
     stroke: rgb(183, 30, 21);
     stroke-width: 8.0;
 }
-.dark #ov-topo svg .link.secondary.port-traffic-Gbps-choked {
-    stroke: rgb(127, 40, 39);
-    stroke-width: 8.0;
-}
 
 
 
@@ -470,9 +384,6 @@
 .light #ov-topo svg .link.primary {
     stroke: #ffA300;
 }
-.dark #ov-topo svg .link.primary {
-    stroke: #D58E0F;
-}
 
 #ov-topo svg .link.secondary.optical {
     stroke-width: 4px;
@@ -480,9 +391,6 @@
 .light #ov-topo svg .link.secondary.optical {
     stroke: rgba(128,64,255,0.5);
 }
-.dark #ov-topo svg .link.secondary.optical {
-    stroke: rgba(164,139,215,0.5);
-}
 
 #ov-topo svg .link.primary.optical {
     stroke-width: 6px;
@@ -490,9 +398,6 @@
 .light #ov-topo svg .link.primary.optical {
     stroke: #74f;
 }
-.dark #ov-topo svg .link.primary.optical {
-    stroke: #7352CD;
-}
 
 /* Link Labels */
 #ov-topo svg .linkLabel rect {
@@ -501,16 +406,10 @@
 .light #ov-topo svg .linkLabel rect {
     fill: #eee;
 }
-.dark #ov-topo svg .linkLabel rect {
-    fill: #555;
-}
 
 .light #ov-topo svg .linkLabel text {
     fill: #444;
 }
-.dark #ov-topo svg .linkLabel text {
-    fill: #eee;
-}
 
 /* Port Labels */
 
@@ -520,16 +419,10 @@
 .light #ov-topo svg .portLabel rect {
     fill: #eee;
 }
-.dark #ov-topo svg .portLabel rect {
-    fill: #222;
-}
 
 .light #ov-topo svg .portLabel text {
     fill: #444;
 }
-.dark #ov-topo svg .portLabel text {
-    fill: #eee;
-}
 
 /* Number of Links Labels */
 
@@ -537,9 +430,6 @@
 .light #ov-topo text.numLinkText {
     fill: #444;
 }
-.dark #ov-topo text.numLinkText {
-    fill: #eee;
-}
 
 /* ------------------------------------------------- */
 /* Sprite Layer */
@@ -548,60 +438,31 @@
     stroke: #fda;
     fill: none;
 }
-.dark #ov-topo svg #topo-sprites .gold1 use {
-    stroke: #541;
-    fill: none;
-}
 .light #ov-topo svg #topo-sprites .gold1 text {
     fill: #eda;
 }
-.dark #ov-topo svg #topo-sprites .gold1 text {
-    fill: #543;
-}
 
 .light #ov-topo svg #topo-sprites .blue1 use {
     stroke: #bbd;
     fill: none;
 }
-.dark #ov-topo svg #topo-sprites .blue1 use {
-    stroke: #445;
-    fill: none;
-}
 .light #ov-topo svg #topo-sprites .blue1 text {
     fill: #cce;
 }
-.dark #ov-topo svg #topo-sprites .blue1 text {
-    fill: #446;
-}
 
 .light #ov-topo svg #topo-sprites .gray1 use {
     stroke: #ccc;
     fill: none;
 }
-.dark #ov-topo svg #topo-sprites .gray1 use {
-    stroke: #333;
-    fill: none;
-}
 .light #ov-topo svg #topo-sprites .gray1 text {
     fill: #ddd;
 }
-.dark #ov-topo svg #topo-sprites .gray1 text {
-    fill: #444;
-}
 
 /* fills */
 .light #ov-topo svg #topo-sprites use.fill-gray2 {
     fill: #eee;
 }
-.dark #ov-topo svg #topo-sprites use.fill-gray2 {
-    fill: #444;
-}
 
 .light #ov-topo svg #topo-sprites use.fill-blue2 {
     fill: #bce;
 }
-.dark #ov-topo svg #topo-sprites use.fill-blue2 {
-    fill: #447;
-}
-
-/* -- MISC -- */
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.css b/web/gui/src/main/webapp/app/view/topo/topo.css
index 5d6e040..7b2fb98 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.css
+++ b/web/gui/src/main/webapp/app/view/topo/topo.css
@@ -127,7 +127,8 @@
 /* --- Topo Instance Panel --- */
 
 #topo-p-instance {
-    height: 100px;
+    height: 85px;
+    padding: 10px;
 }
 
 #topo-p-instance div.onosInst {
@@ -140,15 +141,20 @@
 #topo-p-instance svg text.instTitle {
     font-size: 11pt;
     font-weight: bold;
+    font-variant: small-caps;
+    text-transform: uppercase;
 }
 #topo-p-instance svg text.instLabel {
-    font-size: 9pt;
-    font-style: italic;
+    font-size: 10pt;
 }
 
 
 /* --- Toolbar --- */
 
+#toolbar-topo-tbar {
+  padding: 6px;
+}
+
 #toolbar-topo-tbar .tbar-row.right {
     width: 100%;
 }
@@ -228,10 +234,6 @@
 
 /* -- MISC -- */
 
-.notReady .readyBadge {
-    visibility: hidden;
-}
-
 .map-list {
     padding: 10px;
 }
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.js b/web/gui/src/main/webapp/app/view/topo/topo.js
index 75155e8..fafbf3f 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -67,6 +67,9 @@
 
             E: [equalizeMasters, 'Equalize mastership roles'],
 
+            //-- instance color palette debug
+            // 9: function () { sus.cat7().testCard(svg); },
+
             // topology overlay selections
             F1: function () { ttbs.fnkey(0); },
             F2: function () { ttbs.fnkey(1); },
diff --git a/web/gui/src/main/webapp/app/view/topo/topoInst.js b/web/gui/src/main/webapp/app/view/topo/topoInst.js
index 1ee8dc7..1d0cbed 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoInst.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoInst.js
@@ -32,20 +32,7 @@
      */
 
     // configuration
-    var instCfg = {
-            rectPad: 8,
-            nodeOx: 9,
-            nodeOy: 9,
-            nodeDim: 40,
-            birdOx: 19,
-            birdOy: 21,
-            birdDim: 21,
-            uiDy: 45,
-            titleDy: 30,
-            textYOff: 20,
-            textYSpc: 15
-        },
-        showLogicErrors = true,
+    var showLogicErrors = true,
         idIns = 'topo-p-instance',
         instOpts = {
             edge: 'left',
@@ -102,14 +89,6 @@
 
     // ==========================
 
-    function computeDim(self) {
-        var css = window.getComputedStyle(self);
-        return {
-            w: sus.stripPx(css.width),
-            h: sus.stripPx(css.height)
-        };
-    }
-
     function clickInst(d) {
         var el = d3.select(this),
             aff = el.classed('affinity');
@@ -139,28 +118,13 @@
         oiShowMaster = false;
     }
 
-    function instRectAttr(dim) {
-        var pad = instCfg.rectPad;
-        return {
-            x: pad,
-            y: pad,
-            width: dim.w - pad*2,
-            height: dim.h - pad*2,
-            rx: 6
-        };
-    }
-
-    function viewBox(dim) {
-        return '0 0 ' + dim.w + ' ' + dim.h;
-    }
-
     function attachUiBadge(svg) {
-        gs.addGlyph(svg, 'uiAttached', 24, true, [28, instCfg.uiDy])
+        gs.addGlyph(svg, 'uiAttached', 24, true, [14, 54])
             .classed('badgeIcon uiBadge', true);
     }
 
     function attachReadyBadge(svg) {
-        gs.addGlyph(svg, 'checkMark', 16, true, [12, instCfg.uiDy + 4])
+        gs.addGlyph(svg, 'checkMark', 16, true, [18, 40])
             .classed('badgeIcon readyBadge', true);
     }
 
@@ -171,24 +135,50 @@
     // ==============================
 
     function updateInstances() {
+        var rox = 5,
+            roy = 5,
+            rw = 160,
+            rhh = 30,
+            rbh = 45,
+            tx = 48,
+            instSvg = {
+                width: 170,
+                height: 85,
+                viewBox: '0 0 170 85'
+            },
+            headRect = {
+                x: rox,
+                y: roy,
+                width: rw,
+                height: rhh
+            },
+            bodyRect = {
+                x: rox,
+                y: roy + rhh,
+                width: rw,
+                height: rbh
+            },
+            titleAttr = {
+                class: 'instTitle',
+                x: tx,
+                y: 27
+            };
+
         var onoses = oiBox.el().selectAll('.onosInst')
-                .data(onosOrder, function (d) { return d.id; }),
-            instDim = {w:0,h:0},
-            c = instCfg;
+                .data(onosOrder, function (d) { return d.id; });
 
         function nSw(n) {
-            return '# Switches: ' + n;
+            return 'Switches: ' + n;
         }
 
         // operate on existing onos instances if necessary
         onoses.each(function (d) {
             var el = d3.select(this),
                 svg = el.select('svg');
-            instDim = computeDim(this);
 
             // update online state
             el.classed('online', d.online);
-            el.classed('notReady', !d.ready);
+            el.classed('ready', d.ready);
 
             // update ui-attached state
             svg.select('use.uiBadge').remove();
@@ -196,8 +186,6 @@
                 attachUiBadge(svg);
             }
 
-            attachReadyBadge(svg, d.ready);
-
             function updAttr(id, value) {
                 svg.select('text.instLabel.'+id).text(value);
             }
@@ -210,59 +198,39 @@
         // operate on new onos instances
         var entering = onoses.enter()
             .append('div')
-            .attr('class', 'onosInst')
+            .classed('onosInst', true)
             .classed('online', function (d) { return d.online; })
-            .classed('notReady', function (d) { return !d.ready; })
+            .classed('ready', function (d) { return d.ready; })
             .on('click', clickInst);
 
         entering.each(function (d) {
             var el = d3.select(this),
-                rectAttr,
-                svg;
-            instDim = computeDim(this);
-            rectAttr = instRectAttr(instDim);
+                svg = el.append('svg').attr(instSvg);
 
-            svg = el.append('svg').attr({
-                width: instDim.w,
-                height: instDim.h,
-                viewBox: viewBox(instDim)
-            });
+            svg.append('rect').attr(headRect);
+            svg.append('rect').attr(bodyRect);
 
-            svg.append('rect').attr(rectAttr);
+            gs.addGlyph(svg, 'bird', 20, false, [15, 10])
+                .classed('badgeIcon bird', true);
 
-            gs.addGlyph(svg, 'bird', 28, true, [14, 14])
-                .classed('badgeIcon', true);
+            attachReadyBadge(svg);
 
             if (d.uiAttached) {
                 attachUiBadge(svg);
             }
 
-            attachReadyBadge(svg);
-
-            var left = c.nodeOx + c.nodeDim,
-                len = rectAttr.width - left,
-                hlen = len / 2,
-                midline = hlen + left;
-
-            // title
             svg.append('text')
-                .attr({
-                    class: 'instTitle',
-                    x: midline,
-                    y: c.titleDy
-                })
+                .attr(titleAttr)
                 .text(d.id);
 
-            // a couple of attributes
-            var ty = c.titleDy + c.textYOff;
-
+            var ty = 55;
             function addAttr(id, label) {
                 svg.append('text').attr({
                     class: 'instLabel ' + id,
-                    x: midline,
+                    x: tx,
                     y: ty
                 }).text(label);
-                ty += c.textYSpc;
+                ty += 18;
             }
 
             addAttr('ip', d.ip);
@@ -279,8 +247,8 @@
         });
 
         // adjust the panel size appropriately...
-        oiBox.width(instDim.w * onosOrder.length);
-        oiBox.height(instDim.h);
+        oiBox.width(instSvg.width * onosOrder.length);
+        oiBox.height(instSvg.height);
 
         // remove any outgoing instances
         onoses.exit().remove();
diff --git a/web/gui/src/main/webapp/tests/app/fw/svg/glyph-spec.js b/web/gui/src/main/webapp/tests/app/fw/svg/glyph-spec.js
index a808c3d..00a18a0 100644
--- a/web/gui/src/main/webapp/tests/app/fw/svg/glyph-spec.js
+++ b/web/gui/src/main/webapp/tests/app/fw/svg/glyph-spec.js
@@ -89,7 +89,8 @@
             diamond: 'M.2,.5'
         },
         glyphIds = [
-            'unknown', 'node', 'switch', 'roadm', 'endstation', 'router',
+            'unknown', 'uiAttached',
+            'node', 'switch', 'roadm', 'endstation', 'router',
             'bgpSpeaker', 'chain', 'crown', 'lock', 'topo', 'refresh',
             'garbage',
             'flowTable', 'portTable', 'groupTable',
@@ -98,7 +99,7 @@
             'prevIntent', 'intentTraffic', 'allTraffic', 'flows', 'eqMaster'
         ],
         badgeIds = [
-            'uiAttached', 'checkMark', 'xMark', 'triangleUp', 'triangleDown',
+            'checkMark', 'xMark', 'triangleUp', 'triangleDown',
             'plus', 'minus', 'play', 'stop'
         ],
         spriteIds = [
diff --git a/web/gui/src/main/webapp/tests/app/fw/svg/svgUtil-spec.js b/web/gui/src/main/webapp/tests/app/fw/svg/svgUtil-spec.js
index 0a3433a..1e8970b 100644
--- a/web/gui/src/main/webapp/tests/app/fw/svg/svgUtil-spec.js
+++ b/web/gui/src/main/webapp/tests/app/fw/svg/svgUtil-spec.js
@@ -153,39 +153,40 @@
         ])).toBeTruthy();
     });
 
-    it('should provide a certain shade of blue', function () {
-       expect(sus.cat7().getColor('foo', false, 'light')).toEqual('#3E5780');
+    it('should provide blue', function () {
+       expect(sus.cat7().getColor('foo', false, 'light')).toEqual('#5b99d2');
     });
 
-    it('should not matter what the ID really is for shade of blue', function () {
-       expect(sus.cat7().getColor('bar', false, 'light')).toEqual('#78533B');
+    it('should provide light blue', function () {
+       expect(sus.cat7().getColor('bar', false, 'light')).toEqual('#66cef6');
     });
 
-    it('should provide different shade of blue for muted', function () {
-        expect(sus.cat7().getColor('foo', true, 'light')).toEqual('#A8B8CC');
+    it('should provide paler shade of blue for muted', function () {
+        expect(sus.cat7().getColor('foo', true, 'light')).toEqual('#a8cceb');
     });
 
-
-    it('should provide an alternate (dark) shade of blue', function () {
-       expect(sus.cat7().getColor('foo', false, 'dark')).toEqual('#304860');
+    // TODO: dark theme required
+    xit('should provide an alternate (dark) shade of blue', function () {
+       expect(sus.cat7().getColor('foo', false, 'dark')).toEqual('#5b99d2');
     });
 
-    it('should provide an alternate (dark) shade of blue for muted', function () {
-        expect(sus.cat7().getColor('foo', true, 'dark')).toEqual('#304860');
+    // TODO: dark theme required
+    xit('should provide an alternate (dark) shade of blue for muted', function () {
+        expect(sus.cat7().getColor('foo', true, 'dark')).toEqual('#a8cceb');
     });
 
     it('should iterate across the colors', function () {
-        expect(sus.cat7().getColor('foo', false, 'light')).toEqual('#3E5780');
-        expect(sus.cat7().getColor('bar', false, 'light')).toEqual('#78533B');
-        expect(sus.cat7().getColor('baz', false, 'light')).toEqual('#CB4D28');
-        expect(sus.cat7().getColor('goo', false, 'light')).toEqual('#018D61');
-        expect(sus.cat7().getColor('zoo', false, 'light')).toEqual('#8A2979');
-        expect(sus.cat7().getColor('pip', false, 'light')).toEqual('#006D73');
-        expect(sus.cat7().getColor('sdh', false, 'light')).toEqual('#56AF00');
+        expect(sus.cat7().getColor('foo', false, 'light')).toEqual('#5b99d2');
+        expect(sus.cat7().getColor('bar', false, 'light')).toEqual('#66cef6');
+        expect(sus.cat7().getColor('baz', false, 'light')).toEqual('#d05a55');
+        expect(sus.cat7().getColor('goo', false, 'light')).toEqual('#db7773');
+        expect(sus.cat7().getColor('zoo', false, 'light')).toEqual('#716b6b');
+        expect(sus.cat7().getColor('pip', false, 'light')).toEqual('#aeada8');
+        expect(sus.cat7().getColor('sdh', false, 'light')).toEqual('#7e9aa8');
         // and cycle back to the first color for item #8
-        expect(sus.cat7().getColor('bri', false, 'light')).toEqual('#3E5780');
+        expect(sus.cat7().getColor('bri', false, 'light')).toEqual('#5b99d2');
         // and return the same color for the same ID
-        expect(sus.cat7().getColor('zoo', false, 'light')).toEqual('#8A2979');
+        expect(sus.cat7().getColor('zoo', false, 'light')).toEqual('#716b6b');
     });
 
     // === translate(), scale(), skewX(), rotate()
diff --git a/web/gui/src/test/_karma/ev/colors/scenario.json b/web/gui/src/test/_karma/ev/colors/scenario.json
index dd17828..d5d3afe 100644
--- a/web/gui/src/test/_karma/ev/colors/scenario.json
+++ b/web/gui/src/test/_karma/ev/colors/scenario.json
@@ -7,7 +7,7 @@
     "lastAuto": 29
   },
   "description": [
-    "Press '=' to load initial events.",
-    "Press '-' to fire further events."
+    "Press 'a' to load initial events.",
+    "Press 'n' to fire further events."
   ]
 }
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_10_updInst_7_offline.json b/web/gui/src/test/_karma/ev/mojo/ev_10_updInst_7_offline.json
new file mode 100644
index 0000000..774e929
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_10_updInst_7_offline.json
@@ -0,0 +1,11 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "222.222.222.222",
+    "ip": "222.222.222.222",
+    "online": false,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 0
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_11_updInst_6_offline.json b/web/gui/src/test/_karma/ev/mojo/ev_11_updInst_6_offline.json
new file mode 100644
index 0000000..07703af
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_11_updInst_6_offline.json
@@ -0,0 +1,11 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "ONOS-6",
+    "ip": "192.168.224.126",
+    "online": false,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 0
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_12_updInst_5_offline.json b/web/gui/src/test/_karma/ev/mojo/ev_12_updInst_5_offline.json
new file mode 100644
index 0000000..c223350
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_12_updInst_5_offline.json
@@ -0,0 +1,11 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "ONOS-5",
+    "ip": "192.168.56.105",
+    "online": false,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 0
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_13_updInst_4_offline.json b/web/gui/src/test/_karma/ev/mojo/ev_13_updInst_4_offline.json
new file mode 100644
index 0000000..7e2de40
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_13_updInst_4_offline.json
@@ -0,0 +1,11 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "ONOS-4",
+    "ip": "192.168.56.104",
+    "online": false,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 0
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_14_updInst_3_offline.json b/web/gui/src/test/_karma/ev/mojo/ev_14_updInst_3_offline.json
new file mode 100644
index 0000000..923aeb8
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_14_updInst_3_offline.json
@@ -0,0 +1,11 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "ONOS-3",
+    "ip": "192.168.56.103",
+    "online": false,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 0
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_15_updInst_2_offline.json b/web/gui/src/test/_karma/ev/mojo/ev_15_updInst_2_offline.json
new file mode 100644
index 0000000..268e60a
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_15_updInst_2_offline.json
@@ -0,0 +1,11 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "ONOS-2",
+    "ip": "192.168.56.102",
+    "online": false,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 0
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_16_updInst_1_offline.json b/web/gui/src/test/_karma/ev/mojo/ev_16_updInst_1_offline.json
new file mode 100644
index 0000000..d56e0a4
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_16_updInst_1_offline.json
@@ -0,0 +1,11 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "192.168.56.101",
+    "ip": "192.168.56.101",
+    "online": false,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 0
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_1_addInst_1.json b/web/gui/src/test/_karma/ev/mojo/ev_1_addInst_1.json
new file mode 100644
index 0000000..740595d
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_1_addInst_1.json
@@ -0,0 +1,11 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "192.168.56.101",
+    "ip": "192.168.56.101",
+    "online": true,
+    "ready": true,
+    "uiAttached": true,
+    "switches": 4
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_2_addInst_2.json b/web/gui/src/test/_karma/ev/mojo/ev_2_addInst_2.json
new file mode 100644
index 0000000..0380b88b
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_2_addInst_2.json
@@ -0,0 +1,11 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "ONOS-2",
+    "ip": "192.168.56.102",
+    "online": true,
+    "ready": true,
+    "uiAttached": false,
+    "switches": 3
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_3_addInst_3.json b/web/gui/src/test/_karma/ev/mojo/ev_3_addInst_3.json
new file mode 100644
index 0000000..093b85d
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_3_addInst_3.json
@@ -0,0 +1,11 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "ONOS-3",
+    "ip": "192.168.56.103",
+    "online": true,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 3
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_4_addInst_4.json b/web/gui/src/test/_karma/ev/mojo/ev_4_addInst_4.json
new file mode 100644
index 0000000..fb833dc
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_4_addInst_4.json
@@ -0,0 +1,11 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "ONOS-4",
+    "ip": "192.168.56.104",
+    "online": true,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 0
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_5_addInst_5.json b/web/gui/src/test/_karma/ev/mojo/ev_5_addInst_5.json
new file mode 100644
index 0000000..d525f39
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_5_addInst_5.json
@@ -0,0 +1,11 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "ONOS-5",
+    "ip": "192.168.56.105",
+    "online": true,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 17
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_6_addInst_6.json b/web/gui/src/test/_karma/ev/mojo/ev_6_addInst_6.json
new file mode 100644
index 0000000..ad5888e
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_6_addInst_6.json
@@ -0,0 +1,11 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "ONOS-6",
+    "ip": "192.168.224.126",
+    "online": true,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 0
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_7_addInst_7.json b/web/gui/src/test/_karma/ev/mojo/ev_7_addInst_7.json
new file mode 100644
index 0000000..bcc5d8e
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_7_addInst_7.json
@@ -0,0 +1,11 @@
+{
+  "event": "addInstance",
+  "payload": {
+    "id": "222.222.222.222",
+    "ip": "222.222.222.222",
+    "online": true,
+    "ready": false,
+    "uiAttached": false,
+    "switches": 6
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_8_updInst_1_noui.json b/web/gui/src/test/_karma/ev/mojo/ev_8_updInst_1_noui.json
new file mode 100644
index 0000000..4930db1
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_8_updInst_1_noui.json
@@ -0,0 +1,11 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "192.168.56.101",
+    "ip": "192.168.56.101",
+    "online": true,
+    "ready": true,
+    "uiAttached": false,
+    "switches": 3
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/ev_9_updInst_3_ready.json b/web/gui/src/test/_karma/ev/mojo/ev_9_updInst_3_ready.json
new file mode 100644
index 0000000..272bf3d
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/ev_9_updInst_3_ready.json
@@ -0,0 +1,11 @@
+{
+  "event": "updateInstance",
+  "payload": {
+    "id": "ONOS-3",
+    "ip": "192.168.56.103",
+    "online": true,
+    "ready": true,
+    "uiAttached": true,
+    "switches": 3
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/mojo/scenario.json b/web/gui/src/test/_karma/ev/mojo/scenario.json
new file mode 100644
index 0000000..a9a1e50
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/mojo/scenario.json
@@ -0,0 +1,13 @@
+{
+  "comments": [
+    "Tweaking Mojo Colors"
+  ],
+  "title": "Color-Tweaking Scenario for Mojo Palette",
+  "params": {
+    "lastAuto": 7
+  },
+  "description": [
+    "Press 'a' to load initial events.",
+    "Press 'n' to fire further events."
+  ]
+}