summaryrefslogtreecommitdiffstats
path: root/public/css
diff options
context:
space:
mode:
Diffstat (limited to 'public/css')
-rw-r--r--public/css/icinga/about.less99
-rw-r--r--public/css/icinga/animation.less366
-rw-r--r--public/css/icinga/audit.less363
-rw-r--r--public/css/icinga/badges.less22
-rw-r--r--public/css/icinga/base.less344
-rw-r--r--public/css/icinga/compat.less35
-rw-r--r--public/css/icinga/configmenu.less303
-rw-r--r--public/css/icinga/controls.less281
-rw-r--r--public/css/icinga/dev.less10
-rw-r--r--public/css/icinga/forms.less596
-rw-r--r--public/css/icinga/grid.less47
-rw-r--r--public/css/icinga/health.less69
-rw-r--r--public/css/icinga/layout-structure.less167
-rw-r--r--public/css/icinga/layout.less379
-rw-r--r--public/css/icinga/login-orbs.less104
-rw-r--r--public/css/icinga/login.less183
-rw-r--r--public/css/icinga/main.less452
-rw-r--r--public/css/icinga/menu.less554
-rw-r--r--public/css/icinga/mixins.less201
-rw-r--r--public/css/icinga/modal.less113
-rw-r--r--public/css/icinga/nav.less50
-rw-r--r--public/css/icinga/php-diff.less17
-rw-r--r--public/css/icinga/print.less39
-rw-r--r--public/css/icinga/responsive.less167
-rw-r--r--public/css/icinga/setup.less479
-rw-r--r--public/css/icinga/spinner.less42
-rw-r--r--public/css/icinga/tabs.less105
-rw-r--r--public/css/icinga/widgets.less643
-rw-r--r--public/css/modes/light.less4
-rw-r--r--public/css/modes/none.less4
-rw-r--r--public/css/modes/system.less4
-rw-r--r--public/css/pdf/pdfprint.less103
-rw-r--r--public/css/themes/Winter.less32
-rw-r--r--public/css/themes/colorblind.less29
-rw-r--r--public/css/themes/high-contrast.less250
-rw-r--r--public/css/vendor/normalize.css427
36 files changed, 7083 insertions, 0 deletions
diff --git a/public/css/icinga/about.less b/public/css/icinga/about.less
new file mode 100644
index 0000000..4ccaaf8
--- /dev/null
+++ b/public/css/icinga/about.less
@@ -0,0 +1,99 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+#about {
+ &.content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ section {
+ width: auto;
+
+ > * {
+ margin-bottom: 2em;
+ }
+ }
+
+ h2 {
+ margin: 0;
+ }
+
+ .name-value-table {
+ th {
+ width: 100%;
+ }
+
+ th,
+ td {
+ white-space: nowrap;
+
+ a {
+ color: @icinga-blue
+ }
+ }
+ }
+
+ section:not(:last-child),
+ .icinga-logo {
+ margin-bottom: 2em;
+ }
+
+ .external-links {
+ .rounded-corners();
+ border: 1px solid @gray-light;
+ display: flex;
+ padding: .5em 0;
+ overflow: hidden;
+
+ .col {
+ flex: 1 1 auto;
+ text-align: center;
+ font-size: 12/14em;
+ }
+
+ .col:not(:last-child) {
+ border-right: 1px solid @gray-light;
+ }
+
+ a {
+ display: block;
+ padding: .75em 1em;
+ margin: -7/12em 0;
+ }
+
+ a:hover {
+ text-decoration: none;
+ background: @gray-light;
+ }
+
+ i {
+ font-size: 2*14/12em;
+ opacity: .8;
+ margin-bottom: .25em;
+ display: block;
+
+ &:before {
+ margin-right: 0;
+ }
+ }
+ }
+
+ footer {
+ margin-top: auto;
+ align-self: stretch;
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+
+ a {
+ i {
+ font-size: 2em;
+ }
+
+ &:hover {
+ opacity: .6;
+ }
+ }
+ }
+}
diff --git a/public/css/icinga/animation.less b/public/css/icinga/animation.less
new file mode 100644
index 0000000..aad3ffb
--- /dev/null
+++ b/public/css/icinga/animation.less
@@ -0,0 +1,366 @@
+/*! Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+.animate(@animate) {
+ -moz-animation: @animate;
+ -o-animation: @animate;
+ -webkit-animation: @animate;
+ animation: @animate;
+}
+
+@-moz-keyframes spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@-webkit-keyframes spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@-o-keyframes spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@-ms-keyframes spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -moz-transform: rotate(0deg);
+ -o-transform: rotate(0deg);
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ -moz-transform: rotate(359deg);
+ -o-transform: rotate(359deg);
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+
+@-moz-keyframes move-vertical {
+ 0% {
+ -moz-transform: translate(0, 100%);
+ -o-transform: translate(0, 100%);
+ -webkit-transform: translate(0, 100%);
+ transform: translate(0, 100%);
+ }
+
+ 17% {
+ -moz-transform: translate(0, 66%);
+ -o-transform: translate(0, 66%);
+ -webkit-transform: translate(0, 66%);
+ transform: translate(0, 66%);
+ }
+
+ 33% {
+ -moz-transform: translate(0, 33%);
+ -o-transform: translate(0, 33%);
+ -webkit-transform: translate(0, 33%);
+ transform: translate(0, 33%);
+ }
+
+ 50% {
+ -moz-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0);
+ }
+
+ 67% {
+ -moz-transform: translate(0, -33%);
+ -o-transform: translate(0, -33%);
+ -webkit-transform: translate(0, -33%);
+ transform: translate(0, -33%);
+ }
+
+ 83% {
+ -moz-transform: translate(0, -66%);
+ -o-transform: translate(0, -66%);
+ -webkit-transform: translate(0, -66%);
+ transform: translate(0, -66%);
+ }
+
+ 100% {
+ -moz-transform: translate(0, -100%);
+ -o-transform: translate(0, -100%);
+ -webkit-transform: translate(0, -100%);
+ transform: translate(0, -100%);
+ }
+}
+@-webkit-keyframes move-vertical {
+ 0% {
+ -moz-transform: translate(0, 100%);
+ -o-transform: translate(0, 100%);
+ -webkit-transform: translate(0, 100%);
+ transform: translate(0, 100%);
+ }
+
+ 17% {
+ -moz-transform: translate(0, 66%);
+ -o-transform: translate(0, 66%);
+ -webkit-transform: translate(0, 66%);
+ transform: translate(0, 66%);
+ }
+
+ 33% {
+ -moz-transform: translate(0, 33%);
+ -o-transform: translate(0, 33%);
+ -webkit-transform: translate(0, 33%);
+ transform: translate(0, 33%);
+ }
+
+ 50% {
+ -moz-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0);
+ }
+
+ 67% {
+ -moz-transform: translate(0, -33%);
+ -o-transform: translate(0, -33%);
+ -webkit-transform: translate(0, -33%);
+ transform: translate(0, -33%);
+ }
+
+ 83% {
+ -moz-transform: translate(0, -66%);
+ -o-transform: translate(0, -66%);
+ -webkit-transform: translate(0, -66%);
+ transform: translate(0, -66%);
+ }
+
+ 100% {
+ -moz-transform: translate(0, -100%);
+ -o-transform: translate(0, -100%);
+ -webkit-transform: translate(0, -100%);
+ transform: translate(0, -100%);
+ }
+}
+@-o-keyframes move-vertical {
+ 0% {
+ -moz-transform: translate(0, 100%);
+ -o-transform: translate(0, 100%);
+ -webkit-transform: translate(0, 100%);
+ transform: translate(0, 100%);
+ }
+
+ 17% {
+ -moz-transform: translate(0, 66%);
+ -o-transform: translate(0, 66%);
+ -webkit-transform: translate(0, 66%);
+ transform: translate(0, 66%);
+ }
+
+ 33% {
+ -moz-transform: translate(0, 33%);
+ -o-transform: translate(0, 33%);
+ -webkit-transform: translate(0, 33%);
+ transform: translate(0, 33%);
+ }
+
+ 50% {
+ -moz-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0);
+ }
+
+ 67% {
+ -moz-transform: translate(0, -33%);
+ -o-transform: translate(0, -33%);
+ -webkit-transform: translate(0, -33%);
+ transform: translate(0, -33%);
+ }
+
+ 83% {
+ -moz-transform: translate(0, -66%);
+ -o-transform: translate(0, -66%);
+ -webkit-transform: translate(0, -66%);
+ transform: translate(0, -66%);
+ }
+
+ 100% {
+ -moz-transform: translate(0, -100%);
+ -o-transform: translate(0, -100%);
+ -webkit-transform: translate(0, -100%);
+ transform: translate(0, -100%);
+ }
+}
+@-ms-keyframes move-vertical {
+ 0% {
+ -moz-transform: translate(0, 100%);
+ -o-transform: translate(0, 100%);
+ -webkit-transform: translate(0, 100%);
+ transform: translate(0, 100%);
+ }
+
+ 17% {
+ -moz-transform: translate(0, 66%);
+ -o-transform: translate(0, 66%);
+ -webkit-transform: translate(0, 66%);
+ transform: translate(0, 66%);
+ }
+
+ 33% {
+ -moz-transform: translate(0, 33%);
+ -o-transform: translate(0, 33%);
+ -webkit-transform: translate(0, 33%);
+ transform: translate(0, 33%);
+ }
+
+ 50% {
+ -moz-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0);
+ }
+
+ 67% {
+ -moz-transform: translate(0, -33%);
+ -o-transform: translate(0, -33%);
+ -webkit-transform: translate(0, -33%);
+ transform: translate(0, -33%);
+ }
+
+ 83% {
+ -moz-transform: translate(0, -66%);
+ -o-transform: translate(0, -66%);
+ -webkit-transform: translate(0, -66%);
+ transform: translate(0, -66%);
+ }
+
+ 100% {
+ -moz-transform: translate(0, -100%);
+ -o-transform: translate(0, -100%);
+ -webkit-transform: translate(0, -100%);
+ transform: translate(0, -100%);
+ }
+}
+@keyframes move-vertical {
+ 0% {
+ -moz-transform: translate(0, 100%);
+ -o-transform: translate(0, 100%);
+ -webkit-transform: translate(0, 100%);
+ transform: translate(0, 100%);
+ }
+
+ 17% {
+ -moz-transform: translate(0, 66%);
+ -o-transform: translate(0, 66%);
+ -webkit-transform: translate(0, 66%);
+ transform: translate(0, 66%);
+ }
+
+ 33% {
+ -moz-transform: translate(0, 33%);
+ -o-transform: translate(0, 33%);
+ -webkit-transform: translate(0, 33%);
+ transform: translate(0, 33%);
+ }
+
+ 50% {
+ -moz-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ -webkit-transform: translate(0, 0);
+ transform: translate(0, 0);
+ }
+
+ 67% {
+ -moz-transform: translate(0, -33%);
+ -o-transform: translate(0, -33%);
+ -webkit-transform: translate(0, -33%);
+ transform: translate(0, -33%);
+ }
+
+ 83% {
+ -moz-transform: translate(0, -66%);
+ -o-transform: translate(0, -66%);
+ -webkit-transform: translate(0, -66%);
+ transform: translate(0, -66%);
+ }
+
+ 100% {
+ -moz-transform: translate(0, -100%);
+ -o-transform: translate(0, -100%);
+ -webkit-transform: translate(0, -100%);
+ transform: translate(0, -100%);
+ }
+}
+
+@keyframes blink {
+ 0% {
+ opacity: 0.2;
+ }
+
+ 20% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0.2;
+ }
+}
+
+@keyframes pulse {
+ 0% {
+ opacity: .5;
+ transform: scale(1);
+ }
+
+ 50% {
+ opacity: 1;
+ transform: scale(1.2);
+ }
+
+ 100% {
+ opacity: .5;
+ transform: scale(1);
+ }
+}
diff --git a/public/css/icinga/audit.less b/public/css/icinga/audit.less
new file mode 100644
index 0000000..23ab5b9
--- /dev/null
+++ b/public/css/icinga/audit.less
@@ -0,0 +1,363 @@
+// Style
+
+.privilege-audit-role-control {
+ list-style-type: none;
+
+ li {
+ .rounded-corners(3px);
+ border: 1px solid;
+ border-color: @low-sat-blue;
+
+ &.active {
+ border-color: @icinga-blue;
+ }
+ }
+}
+
+.privilege-audit {
+ &, ul, ol {
+ list-style-type: none;
+ }
+
+ .privilege-section > summary {
+ font-weight: @font-weight-bold;
+ border-bottom: 1px solid @gray-light;
+ }
+
+ .privilege-section > summary em,
+ .previews em,
+ .privilege-label em {
+ color: @text-color-light;
+ }
+ .privilege-section > summary em {
+ font-weight: normal;
+ }
+ .privilege-label em {
+ font-style: normal;
+ }
+
+ .icon {
+ color: @gray-light;
+
+ &.granted {
+ color: @color-granted;
+ }
+
+ &.refused {
+ color: @color-refused;
+ }
+
+ &.restricted {
+ color: @color-restricted;
+ }
+ }
+
+ .privilege-list > li {
+ .spacer {
+ opacity: 0;
+ .transition(opacity .5s ease-out);
+ }
+
+ &:hover .spacer {
+ .transition(opacity .25s .25s ease-in);
+ border: 0 dashed;
+ border-color: @gray-light;
+ border-top-width: .2em;
+ opacity: 1;
+ }
+ }
+
+ .vertical-line {
+ border: 0 solid;
+ border-left-width: 2px;
+
+ &.granted {
+ border-color: @color-granted;
+ }
+
+ &.refused {
+ border-color: @color-refused;
+ }
+ }
+
+ .connector {
+ border: 0 solid;
+ border-color: @gray-lighter;
+ border-bottom-width: 2px;
+
+ &.granted {
+ border-color: @color-granted;
+ }
+
+ &.refused {
+ border-color: @color-refused;
+ }
+
+ &:first-child {
+ border-width: 0 0 2px 2px;
+ border-bottom-left-radius: .5em;
+ }
+ }
+
+ .role {
+ .rounded-corners(1em);
+ border: 2px solid;
+ border-color: @gray-lighter;
+
+ &.granted {
+ border: 2px solid;
+ border-color: @color-granted;
+ }
+
+ &.refused {
+ border: 2px solid;
+ border-color: @color-refused;
+ }
+ }
+
+ .restriction {
+ font-family: @font-family-fixed;
+ background-color: @gray-lighter;
+ }
+}
+
+// Layout
+
+.privilege-audit-role-control {
+ display: inline-flex;
+ flex-wrap: wrap;
+
+ margin: 0 0 0 1em;
+ padding: 0;
+
+ li {
+ margin-top: @vertical-padding;
+
+ &:not(:first-child) {
+ margin-left: .5em;
+ }
+ }
+}
+
+.privilege-audit {
+ &, ul, ol {
+ margin: 0;
+ padding: 0;
+ }
+
+ .flex-overflow,
+ .privilege-list > li,
+ .inheritance-paths > ol {
+ display: flex;
+ }
+
+ .privilege-list > li {
+ margin-top: 1em;
+
+ > :last-child {
+ // This aids the usage of text-overflow:ellipsis in any of the children.
+ // It seems that to get this working while none of the children has a
+ // defined width, any flex item on the way up to the clipped container
+ // also must have a overflow value of "hidden".
+ // https://codepen.io/unthinkingly/pen/XMwJLG
+ overflow: hidden;
+ }
+
+ > details:last-child {
+ // The overflow above cuts off the outline of the summary otherwise
+ margin: -4px;
+ padding: 4px;
+ }
+ }
+
+ .privilege-section {
+ &:not(.collapsed) {
+ margin-bottom: 2em;
+ }
+ }
+
+ .privilege-section > summary {
+ display: flex;
+ align-items: baseline;
+ font-size: 1.167em;
+ margin: 0.556em 0 0.333em;
+
+ > :first-child {
+ flex: 3 1 auto;
+ min-width: 20em;
+ max-width: 40em / 1.167em; // privilege label width + spacer width / summary font-size
+ }
+
+ .audit-preview {
+ flex: 1 1 auto;
+
+ .icon:before {
+ width: 1.25em;
+ font-size: 1.25em / 1.167em; // privilege state icon font-size / summary font-size
+ }
+ }
+
+ em {
+ font-size: .857em;
+ }
+ }
+
+ h4,
+ .privilege-label {
+ flex-shrink: 0;
+ width: 20em;
+ margin: 0;
+ text-align: right;
+ }
+
+ ol + h4 {
+ margin-top: 1em;
+ }
+
+ .spacer {
+ flex: 20 1 auto;
+ min-width: 10em; // TODO: Mobile?
+ max-width: 18.8em; // 20em - (margin-left + margin-right)
+ margin: .6em;
+ }
+
+ .inheritance-paths,
+ .restrictions {
+ flex: 1 1 auto;
+
+ > summary {
+ line-height: 1;
+
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ > .icon:before {
+ width: 1.25em;
+ font-size: 1.25em;
+ }
+ }
+ }
+
+ .vertical-line {
+ margin-left: ~"calc(.75em - 1px)";
+ }
+
+ .connector {
+ flex: 1 1 auto;
+ width: 2em;
+ max-width: 2em;
+ min-width: 1em;
+ margin-bottom: ~"calc(1em - 1px)";
+
+ &:first-child {
+ margin-left: ~"calc(.75em - 1px)";
+ }
+
+ &.initiator {
+ z-index: 1;
+ margin-right: ~"calc(-.25em - 2px)";
+ }
+ }
+
+ .vertical-line + .connector {
+ min-width: ~"calc(.75em - 2px)";
+ width: ~"calc(.75em - 2px)";
+ flex-grow: 0;
+
+ &.initiator {
+ width: ~"calc(1em - 1px)";
+ }
+ }
+ .connector:first-child {
+ min-width: .75em;
+ width: .75em;
+ flex-grow: 0;
+
+ &.initiator {
+ width: 1em;
+ }
+ }
+
+ .role {
+ padding: .25em .5em .25em .5em;
+ line-height: 1;
+
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ .icon:before {
+ font-size: 1.25em;
+ }
+ }
+ .inheritance-paths .role {
+ min-width: 4em;
+ margin-top: .5em;
+ padding-left: .25em;
+ }
+ .restrictions .role {
+ display: inline-block;
+ }
+
+ .previews {
+ display: flex;
+ margin-top: .25em;
+
+ em {
+ // explicit margin + ((header icon width + its margin right) * 125% font-size)
+ margin: 0 1em 0 1em + ((1.25em + .2em) * 1.25em);
+ }
+ }
+
+ .links li:not(:last-child):after {
+ content: ",";
+ }
+
+ .restrictions > ul > li {
+ margin-top: .5em;
+
+ .role {
+ margin-left: 1.25em + .2em * 1.25em; // (header icon width + its margin right) * 125% font-size
+ margin-right: 1em;
+ }
+ }
+
+ .restriction {
+ font-size: .8em;
+ padding: .335em / .8em;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ .user-select(all);
+ }
+}
+
+#layout.minimal-layout,
+#layout.poor-layout {
+ .privilege-audit {
+ .privilege-section > summary > :first-child {
+ flex-grow: 99;
+ }
+
+ h4,
+ .privilege-label {
+ width: 12em;
+ }
+
+ .spacer {
+ flex: 0;
+ min-width: 0;
+ }
+ }
+}
+
+// Integrations
+
+.privilege-audit .collapsible {
+ .collapsible-control {
+ cursor: pointer;
+ .user-select(none);
+ }
+}
diff --git a/public/css/icinga/badges.less b/public/css/icinga/badges.less
new file mode 100644
index 0000000..eae95c2
--- /dev/null
+++ b/public/css/icinga/badges.less
@@ -0,0 +1,22 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+@badge-color: @body-bg-color;
+@badge-line-height: 1.2;
+@badge-padding: 0.25em;
+
+.badge {
+ .bg-stateful();
+ .rounded-corners();
+
+ background-color: @gray;
+ color: @badge-color;
+ display: inline-block;
+ font-family: @font-family-wide;
+ font-size: @font-size-small;
+ line-height: @badge-line-height;
+ min-width: 2em;
+ padding: @badge-padding;
+ text-align: center;
+ vertical-align: middle;
+ white-space: nowrap;
+}
diff --git a/public/css/icinga/base.less b/public/css/icinga/base.less
new file mode 100644
index 0000000..9ce5d7e
--- /dev/null
+++ b/public/css/icinga/base.less
@@ -0,0 +1,344 @@
+/*! Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+// Black colors
+@black: #535353;
+@white: #fff;
+
+// Gray colors
+@gray: #c4c4c4;
+@gray-semilight: #888;
+@gray-light: #5c5c5c;
+@gray-lighter: #4b4b4b;
+@gray-lightest: #3a3a3a;
+
+@disabled-gray: #9a9a9a;
+
+// State colors
+@color-ok: #44bb77;
+@color-up: @color-ok;
+@color-warning: #ffaa44;
+@color-warning-handled: #ffcc66;
+@color-critical: #ff5566;
+@color-critical-handled: #ff99aa;
+@color-critical-accentuated: darken(@color-critical, 10%);
+@color-down: @color-critical;
+@color-down-handled: @color-critical-handled;
+@color-unknown: #aa44ff;
+@color-unknown-handled: #cc77ff;
+@color-unreachable: @color-unknown;
+@color-unreachable-handled: @color-unknown-handled;
+@color-pending: #77aaff;
+
+// Icinga colors
+@icinga-blue: #00C3ED;
+@icinga-secondary: #EF4F98;
+@icinga-secondary-dark: darken(@icinga-secondary, 10%);
+@low-sat-blue: #404d72;
+@low-sat-blue-dark: #434374;
+@icinga-blue-light: fade(@icinga-blue, 50%);
+@icinga-blue-dark: #0081a6;
+
+// Notification colors
+@color-notification-error: @color-critical;
+@color-notification-info: @color-pending;
+@color-notification-success: @color-ok;
+@color-notification-warning: @color-warning;
+
+// Background color for <body>
+@body-bg-color: #282E39;
+@body-bg-color-transparent: fade(@body-bg-color, 0);
+
+// Text colors
+@text-color: @white;
+@text-color-inverted: @body-bg-color;
+@text-color-light: fade(@text-color, 75%);
+@text-color-on-icinga-blue: @body-bg-color;
+@light-text-bg-color: fade(@gray, 5%);
+
+// Text color on <a>
+@link-color: @text-color;
+
+@tr-active-color: fade(@icinga-blue, 25);
+@tr-hover-color: fade(@icinga-blue, 5);
+
+// Menu colors
+@menu-bg-color: #06062B;
+@menu-hover-bg-color: lighten(@menu-bg-color, 5%);
+@menu-search-hover-bg-color: @menu-hover-bg-color;
+@menu-active-bg-color: #181742;
+@menu-active-hover-bg-color: lighten(@menu-active-bg-color, 5%);
+@menu-color: #DBDBDB;
+@menu-active-color: @text-color;
+@menu-highlight-color: @icinga-blue;
+@menu-highlight-hover-bg-color: @icinga-blue-dark;
+@menu-2ndlvl-color: #c4c4c4;
+@menu-2ndlvl-highlight-bg-color: @tr-hover-color;
+@menu-2ndlvl-active-bg-color: @menu-highlight-color;
+@menu-2ndlvl-active-color: @text-color-inverted;
+@menu-2ndlvl-active-hover-bg-color: darken(@menu-2ndlvl-active-bg-color, 5%);
+@menu-2ndlvl-active-hover-color: @menu-2ndlvl-active-color;
+@menu-flyout-bg-color: @body-bg-color;
+@menu-flyout-color: @text-color;
+@tab-hover-bg-color: fade(@body-bg-color, 50%);
+
+// Form colors
+@form-info-bg-color: fade(@color-ok, 20%);
+@form-error-bg-color: fade(@color-critical, 30%);
+@form-warning-bg-color: fade(@color-warning, 40%);
+@login-box-background: fade(#0B0B2F, 30%);
+
+// Other colors
+@color-granted: #59cd59;
+@color-refused: #ee7373;
+@color-restricted: #dede7d;
+
+// Font families
+@font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+@font-family-fixed: "Liberation Mono", "Lucida Console", Courier, monospace;
+@font-family-wide: Tahoma, Verdana, sans-serif;
+
+// Font sizes
+@font-size: 0.750em; // 12px
+@font-size-small: 11/12em; // 11px
+@font-size-dashboard: 3.5em; // 56px
+@font-size-dashboard-small: 1.1em; // 17px
+@font-weight-bold: 600;
+
+// Set line-height w/o unit so that the line-height is dynamically calculated as font-size * line-height
+@line-height: 1.5;
+
+@table-column-padding: 0.333em; // 4px
+
+@vertical-padding: 0.5em; // 6px
+@horizontal-padding: 1em; // 12px
+
+@light-mode: {
+ @light-body-bg-color: #F5F9FA;
+
+ @iplWebLightRules();
+
+ :root {
+ --body-bg-color: @light-body-bg-color;
+ --body-bg-color-transparent: fade(@light-body-bg-color, 0);
+ --badge-color: #F5F9FA;
+ --text-color-inverted: #F5F9FA;
+ --text-color-on-icinga-blue: #F5F9FA;
+ --menu-flyout-bg-color: #F5F9FA;
+ --tab-hover-bg-color: fade(#F5F9FA, 50%);
+
+ --menu-color: #535353;
+ --menu-bg-color: #DEECF1;
+ --menu-hover-bg-color: darken(#DEECF1, 10%);
+ --menu-search-hover-bg-color: darken(#DEECF1, 10%);
+ --menu-active-bg-color: #EDF7FC;
+ --menu-active-hover-bg-color: darken(#EDF7FC, 20%);
+ --menu-highlight-hover-bg-color: darken(#EDF7FC, 20%);
+ --menu-2ndlvl-color: #676767;
+
+ --text-color: #535353;
+ --text-color-light: fade(#535353, 75%);
+ --light-text-bg-color: fade(#7F7F7F, 5%);
+ --link-color: #535353;
+ --menu-active-color: #535353;
+ --menu-flyout-color: #535353;
+
+ --low-sat-blue: #DEECF1;
+ --low-sat-blue-dark: #c0cccd;
+
+ --gray: #819398;
+ --gray-semilight: #94a5a6;
+ --gray-light: #d0d3da;
+ --gray-lighter: #e8ecef;
+ --gray-lightest: #F7F7F7;
+
+ // ipl-web overrides
+ --base-gray: var(--gray);
+ --base-gray-light: var(--gray-light);
+ --base-gray-lighter: var(--gray-lighter);
+
+ --default-text-color: var(--text-color);
+ --default-text-color-light: var(--text-color-light);
+ --default-text-color-inverted: var(--text-color-inverted);
+
+ --searchbar-bg: var(--low-sat-blue);
+
+ --search-logical-operator-bg: fade(#819398, 50%); // --gray
+ }
+};
+
+// ipl-web overrides
+@default-bg: @body-bg-color;
+
+@base-gray: @gray;
+@base-gray-light: @gray-light;
+@base-gray-lighter: @gray-lighter;
+@base-disabled: @disabled-gray;
+
+@base-primary-color: @icinga-blue;
+@base-primary-bg: @icinga-blue;
+
+@default-text-color: @text-color;
+@default-text-color-light: @text-color-light;
+
+@state-ok: @color-ok;
+@state-warning: @color-warning;
+@state-critical: @color-critical;
+@state-pending: @color-pending;
+@state-unknown: @color-unknown;
+
+@primary-button-hover-bg: @icinga-blue-dark;
+
+@searchbar-bg: @low-sat-blue;
+
+// Make padding not affect the final computed width of an element
+html {
+ box-sizing: border-box;
+}
+details > * {
+ // children somehow default to content-box no matter the inheritance
+ box-sizing: border-box;
+}
+*,
+*:before,
+*:after {
+ -webkit-box-sizing: inherit;
+ -moz-box-sizing: inherit;
+ box-sizing: inherit;
+}
+
+a {
+ // Reset defaults
+ color: inherit;
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+}
+
+:focus {
+ outline: 3px solid fade(@icinga-blue, 50%);
+ outline-offset: 1px;
+}
+
+// Default margin for block text
+blockquote, p, pre {
+ margin: 0 0 1em 0;
+}
+
+blockquote {
+ border-left: 5px solid @gray-lighter;
+ padding: 0.667em 0.333em;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-weight: @font-weight-bold;
+ margin: 0.556em 0 0.333em;
+}
+
+h1 {
+ border-bottom: 1px solid @gray-lighter;
+ font-size: 1.333em;
+}
+
+h2 {
+ font-size: 1.333em;
+}
+
+h3 {
+ font-size: 1.167em;
+}
+
+h4 {
+ font-size: 1em;
+}
+
+h5 {
+ font-size: @font-size-small;
+}
+
+h6 {
+ font-size: @font-size-small;
+ font-weight: normal;
+}
+
+pre {
+ .rounded-corners(.25em);
+ background-color: @gray-lighter;
+ font-family: @font-family-fixed;
+ font-size: @font-size-small;
+ padding: @vertical-padding @horizontal-padding;
+ white-space: pre-wrap;
+}
+
+td, th {
+ padding: @table-column-padding;
+}
+
+[class^="icon-"], [class*=" icon-"] {
+ // Smooth icons; ifont claims to have it, but it does not work in :before
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+
+ &:before {
+ margin-left: 0;
+ }
+}
+
+// Styles for when the page is loading. JS will remove this class once the document is ready
+.loading * {
+ // Disable all transition on page load
+ -webkit-transition: none !important;
+ -moz-transition: none !important;
+ -o-transition: none !important;
+ transition: none !important;
+}
+
+.container {
+ &:before,
+ > .content:before {
+ content: "";
+ display: block;
+
+ background: url(../img/icinga-loader.gif) no-repeat center center;
+ background-color: @body-bg-color;
+ background-size: 4em 4em;
+
+ opacity: 0;
+ z-index: -1;
+ pointer-events: none;
+ .transition(none);
+ }
+
+ &.impact,
+ > .content.impact {
+ overflow: hidden;
+ position: relative;
+
+ &:before {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+
+ opacity: .7;
+ z-index: 1000;
+ pointer-events: all;
+ .transition(opacity 1s 2s linear);
+ }
+ }
+
+ &.impact:before {
+ top: 2.5em;
+ }
+}
+
+@light-mode: {
+ .container {
+ &:before,
+ > .content:before {
+ background-image: url(../img/icinga-loader-light.gif)
+ }
+ }
+};
diff --git a/public/css/icinga/compat.less b/public/css/icinga/compat.less
new file mode 100644
index 0000000..d57a189
--- /dev/null
+++ b/public/css/icinga/compat.less
@@ -0,0 +1,35 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+@colorMainLayout: @icinga-blue;
+@colorMainBackground: @body-bg-color;
+@colorMainForeground: @text-color;
+@colorMainLink: @text-color;
+@colorSecondary: @gray-lightest;
+@colorGray: @gray-lightest;
+@colorLinkDefault: @text-color;
+@colorTextDefault: @text-color;
+@colorTextDarkDefault: @text-color;
+@colorOk: @color-ok;
+@colorWarning: #ffaa44;
+@colorWarningHandled: #ffcc66;
+@colorCritical: #ff5566;
+@colorCriticalHandled: #ff99aa;
+@colorUnknown: #aa44ff;
+@colorUnknownHandled: #cc77ff;
+@colorUnreachable: #aa44ff;
+@colorUnreachableHandled: #cc77ff;
+@colorPending: #77aaff;
+@colorInvalid: #999;
+@colorFormNotificationInfo: #77aaff;
+@colorFormNotificationWarning: #ffaa44;
+@colorFormNotificationError: #ff5566;
+@colorPetrol: @icinga-blue;
+@menu-2ndlvl-highlight-color: @menu-2ndlvl-active-color;
+
+table.action {
+ .common-table();
+}
+
+table.avp {
+ .name-value-table();
+}
diff --git a/public/css/icinga/configmenu.less b/public/css/icinga/configmenu.less
new file mode 100644
index 0000000..05e50e8
--- /dev/null
+++ b/public/css/icinga/configmenu.less
@@ -0,0 +1,303 @@
+#menu {
+ margin-bottom: 3em;
+}
+
+.sidebar-collapsed #menu {
+ margin-bottom: 8em;
+}
+
+#menu .config-menu {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background-color: @menu-bg-color;
+ margin-top: auto;
+
+ > ul {
+ display: flex;
+ flex-wrap: nowrap;
+ padding: 0;
+
+ > li {
+ > a {
+ padding: 0.5em 0.5em 0.5em 0.75em;
+ line-height: 2.167em;
+ white-space: nowrap;
+ text-decoration: none;
+
+ }
+
+ &:hover .nav-level-1 {
+ display: block;
+ }
+ }
+
+ li.active a:after {
+ display: none;
+ }
+
+ .user-nav-item {
+ width: 100%;
+ overflow: hidden; // necessary for .text-ellipsis of <a>
+
+ > a {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ &:not(.active):hover a,
+ &:not(.active) a:focus {
+ background: @menu-hover-bg-color;
+ }
+ }
+
+ .config-nav-item {
+ line-height: 2;
+ display: flex;
+ align-items: center;
+ position: relative;
+
+ > button {
+ background: none;
+ border: none;
+ display: block;
+ .rounded-corners();
+
+ > .state-badge {
+ position: absolute;
+ pointer-events: none;
+ }
+
+ .icon {
+ opacity: .8;
+ font-size: 1.25em;
+
+ &:before {
+ margin-right: 0;
+ }
+ }
+ }
+
+ &:hover > button {
+ background: fade(@menu-hover-bg-color, 25);
+
+ > .state-badge {
+ display: none;
+ }
+ }
+
+ button:focus {
+ background: fade(@menu-hover-bg-color, 25);
+ }
+
+ &.active > button {
+ color: @text-color-inverted;
+ background: @icinga-blue;
+ }
+ }
+
+ .state-badge {
+ line-height: 1.2;
+ padding: .25em;
+ font-family: @font-family-wide;
+ }
+ }
+
+ .nav-level-1 li {
+ &.badge-nav-item > a {
+ display: flex;
+ align-items: baseline;
+ width: 100%;
+
+ .state-badge {
+ margin-left: auto;
+ }
+ }
+ }
+
+ .nav-item-logout {
+ color: @color-critical;
+ border-top: 1px solid @gray-lighter;
+ }
+
+ .user-ball {
+ .ball();
+ .ball-size-l();
+ .ball-solid(@icinga-blue);
+
+ // icingadb-web/public/css/common.less: .user-ball
+ font-weight: bold;
+ text-transform: uppercase;
+
+ // compensate border vertically and add space to the right;
+ margin: -1px .2em -2px 0;
+ border: 1px solid @text-color-inverted;
+ font-style: normal;
+ line-height: 1.2;
+ }
+}
+
+#layout:not(.sidebar-collapsed) #menu .config-menu {
+ .user-nav-item {
+ > a {
+ padding-right: 4.75em;
+ }
+
+ &.active.selected + .config-nav-item {
+ > button {
+ color: @text-color-inverted;
+ }
+ }
+ }
+
+ .config-nav-item {
+ position: absolute;
+ right: 2.5em;
+ bottom: 0;
+ top: 0;
+
+ .state-badge {
+ left: -1em;
+ top: 0;
+ }
+ }
+
+ .flyout {
+ bottom: 100%;
+ right: -2em;
+ width: 15em;
+ }
+}
+
+.sidebar-collapsed #menu .config-menu {
+ ul {
+ flex-direction: column;
+
+ .user-ball {
+ margin-left: .25em * 1.5/2;
+ margin-right: .5em + .25em * 1.5/2;
+ width: 2em * 1.5/2 ;
+ height: 2em * 1.5/2;
+ font-size: 2/1.5em;
+ line-height: 1;
+ }
+
+ .config-nav-item {
+ padding-right: 0;
+ margin-bottom: 3em;
+
+ .icon {
+ font-size: 1.5em;
+ }
+
+ button {
+ position: relative;
+ width: 3em;
+ margin: .125em .5em;
+ padding: .5em .75em;
+
+ .state-badge {
+ right: -.25em;
+ bottom: -.25em;
+ font-size: .75em;
+
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 4em;
+ }
+ }
+ }
+ }
+
+ .flyout {
+ bottom: 0;
+ left: 100%;
+ width: 14em;
+
+ &:before {
+ left: -.6em;
+ bottom: 1em;
+ transform: rotate(135deg);
+ }
+ }
+}
+
+.flyout {
+ display: none;
+ position: absolute;
+ border: 1px solid @gray-lighter;
+ background: @body-bg-color;
+ box-shadow: 0 0 1em 0 rgba(0,0,0,.25);
+ z-index: 1;
+ .rounded-corners();
+
+ a {
+ font-size: 11/12em;
+ padding: 0.364em 0.545em 0.364em 2em;
+ line-height: 2;
+
+ &:hover {
+ text-decoration: none;
+ background: @menu-2ndlvl-highlight-bg-color;
+ }
+ }
+
+ h3 {
+ font-size: 10/12em;
+ color: @text-color-light;
+ letter-spacing: .1px;
+ padding: 0.364em 0.545em 0.364em 0.545em;
+ margin: 0;
+ }
+
+ .flyout-content {
+ overflow: auto;
+ // Partially escape to have ems calculated
+ max-height: calc(~"100vh - " 50/12em);
+ padding: .5em 0;
+ position: relative;
+ }
+
+ // Caret
+ &:before {
+ content: "";
+ display: block;
+ position: absolute;
+ transform: rotate(45deg);
+ background: @body-bg-color;
+ border-bottom: 1px solid @gray-lighter;
+ border-right: 1px solid @gray-lighter;
+ height: 1.1em;
+ width: 1.1em;
+ bottom: -.6em;
+ right: 2.5em;
+ }
+}
+
+// Prevent flyout to vanish on autorefresh
+#layout.config-flyout-open .config-nav-item {
+ .flyout {
+ display: block;
+ }
+
+ > button > .state-badge {
+ display: none;
+ }
+}
+
+#layout.minimal-layout .config-menu {
+ display: none;
+}
+
+#layout.minimal-layout #menu {
+ margin-bottom: 0;
+}
+
+#layout:not(.minimal-layout) #menu .primary-nav {
+ .user-nav-item,
+ .configuration-nav-item,
+ .system-nav-item {
+ display: none;
+ }
+}
diff --git a/public/css/icinga/controls.less b/public/css/icinga/controls.less
new file mode 100644
index 0000000..01cf152
--- /dev/null
+++ b/public/css/icinga/controls.less
@@ -0,0 +1,281 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+// TODO(el): Rename .filter to .filter-control
+
+// Hide auto sumbit info in controls
+.controls .autosubmit-info {
+ display: none;
+}
+
+
+// Backend selection control in user and group list views
+.backend-selection {
+ float: left;
+
+ .control-label-group, select {
+ display: inline-block;
+ }
+
+ select {
+ margin-left: .5em;
+ }
+}
+
+.controls input.search,
+input.search {
+ .transition(border 0.3s ease);
+ .transition(background-image 0.2s ease);
+
+ background-image: url(../img/icons/search_white.png);
+ background-repeat: no-repeat;
+ background-size: 1em 1em;
+ background-position: .25em center;
+ outline: none;
+ padding-left: 1.5em;
+ width: 20em;
+
+ &:focus {
+ background-image: url(../img/icons/search_icinga_blue.png);
+ }
+
+ &:focus:not([readonly]) {
+ border-color: @icinga-blue;
+ }
+}
+
+@light-mode: {
+ #menu input.search,
+ .controls input.search,
+ input.search {
+ background-image: url(../img/icons/search.png);
+ }
+};
+
+.backend-selection,
+.pagination-control,
+.selection-info,
+.sort-controls-container {
+ margin-bottom: 0.5em;
+}
+
+.filter {
+ // Display filter control on a new line
+ clear: both;
+ margin: .5em 0;
+
+ > a {
+ color: @icinga-blue;
+ padding: .5em;
+ line-height: 1;
+ }
+
+ > a > i {
+ text-align: center;
+ &:before {
+ margin-right: 0;
+ }
+ }
+
+ .form input {
+ padding: @vertical-padding @vertical-padding;
+ }
+}
+
+.controls .filter {
+ form .search {
+ height: 2em;
+ }
+}
+
+.controls .button-link {
+ height: 2em;
+}
+
+.limiter-control > select {
+ margin-left: .5em;
+}
+
+.pagination-control {
+ // Display the pagination-control on a new line
+ clear: both;
+ float: left;
+
+ li {
+ line-height: 1;
+
+ &.active {
+ border-bottom: 2px solid @icinga-blue;
+
+ > a,
+ > a:hover {
+ color: @icinga-blue;
+ /* Compensate border-bottom: 2px */
+ margin-bottom: -2px;
+ }
+
+ > a:hover {
+ background: none;
+ cursor: default;
+ text-decoration: none;
+ }
+ }
+
+ &.disabled {
+ color: @disabled-gray;
+ cursor: no-drop;
+ }
+
+ > a,
+ > span {
+ padding: 0.5em;
+ }
+ > a:hover {
+ background-color: @gray-lighter;
+ text-decoration: none;
+ }
+ }
+
+ .previous-page {
+ padding-left: 0;
+ }
+
+ .next-page {
+ padding-right: 0;
+ }
+}
+
+// Multi-selection info
+.selection-info {
+ float: right;
+ font-size: @font-size-small;
+
+ &:hover {
+ cursor: help;
+ }
+}
+
+.sort-control {
+ label {
+ width: auto;
+ margin-right: 0.5em;
+ }
+
+ select[name=sort] {
+ width: 12em;
+ margin-left: 0;
+ }
+
+ select[name=dir] {
+ width: 8em;
+ margin-left: 0;
+ }
+}
+
+.sort-controls-container {
+ clear: right;
+ float: right;
+ display: flex;
+
+ > *:not(:last-child) {
+ margin-right: .5em;
+ }
+}
+
+.sort-direction-control {
+ margin-left: 0.25em;
+ width: 1em;
+
+ .spinner {
+ line-height: 1;
+ }
+}
+
+.controls .icinga-controls {
+ .control-label-group {
+ margin-top: 0;
+ margin-bottom: 0;
+ line-height: 1.5em;
+ padding-top: 0.25em;
+ padding-bottom: 0.25em;
+ }
+
+ input,
+ select {
+ max-width: 16em;
+ }
+
+ select {
+ padding-right: 1.526em;
+ margin-top: 0;
+ margin-bottom: 0;
+ /* compensate inconsistent select height calculations */
+ line-height: 1;
+ max-height: 2em;
+ }
+}
+
+// Datetime picker colors
+
+// The less variables are essentially the official dark theme for the flatpickr
+@fp-calendarBackground: #3f4458;
+@fp-calendarBorderColor: darken(#3f4458, 50%);
+
+@fp-monthForeground: #fff;
+@fp-monthBackground: #3f4458;
+
+@fp-weekdaysBackground: transparent;
+@fp-weekdaysForeground: #fff;
+
+@fp-dayForeground: fadeout(white, 5%);
+@fp-dayHoverBackground: lighten(@fp-calendarBackground, 25%);
+
+@fp-todayColor: #eee;
+@fp-today_fg_color: #3f4458;
+
+@fp-selectedDayBackground: #80CBC4;
+
+.icinga-datetime-picker .flatpickr-day.today {
+ &:hover,
+ &:focus {
+ color: @fp-today_fg_color;
+ }
+}
+
+@light-mode: {
+ :root {
+ // These are actually the default colors for the flatpickr
+
+ @fp-dayForeground: #393939;
+ @fp-dayHoverBackground: #e6e6e6;
+
+ --fp-calendarBackground: #ffffff;
+ --fp-calendarBorderColor: @fp-dayHoverBackground;
+
+ --fp-arrowColor: fadeout(@fp-dayForeground, 40%);
+ --fp-arrow_hover_color: #f64747;
+
+ --fp-monthForeground: fadeout(black, 10%);
+ --fp-monthBackground: transparent;
+
+ --fp-weekdaysBackground: transparent;
+ --fp-weekdaysForeground: fadeout(black, 46%);
+ --fp-weekNumberForeground: fadeout(@fp-dayForeground, 70%);
+
+ --fp-dayForeground: @fp-dayForeground;
+ --fp-dayHoverBackground: @fp-dayHoverBackground;
+ --fp-disabledDayForeground: fadeout(@fp-dayForeground, 90%);
+ --fp-outsideRangeDayForeground: fadeout(@fp-dayForeground, 70%);
+ --fp-selectedDayBackground: #569FF7;
+ --fp-todayColor: #959ea9;
+
+ --fp-timeHoverBg: lighten(@fp-dayHoverBackground, 3);
+
+ --fp-hoverInvertedBg: fadeout(black, 95%);
+
+ --fp-numChooserSvgFillColor: fadeout(fadeout(black, 10%), 50%);
+ --fp-hoverNumChooserBg: fadeout(black, 90%);
+ --fp-numChooserBorderColor: fadeout(@fp-dayForeground, 85%);
+ }
+};
+
+// Datetime picker colors (end)
diff --git a/public/css/icinga/dev.less b/public/css/icinga/dev.less
new file mode 100644
index 0000000..a1e34be
--- /dev/null
+++ b/public/css/icinga/dev.less
@@ -0,0 +1,10 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+#fontsize-calc {
+ display: none;
+ width: 1000em;
+ height: 1em;
+ font-size: 1em;
+ position: absolute;
+ top: -2em;
+}
diff --git a/public/css/icinga/forms.less b/public/css/icinga/forms.less
new file mode 100644
index 0000000..00389ea
--- /dev/null
+++ b/public/css/icinga/forms.less
@@ -0,0 +1,596 @@
+/*! Icinga Web 2 | (c) 2019 Icinga Development Team | GPLv2+ */
+
+/**
+ Rules found in here are structured with two layers:
+
+ 1) form.icinga-form, that's what defines the general structure of our single/individual forms. It's not
+ supposed to be used for any other forms that are not the only content on the page (e.g. inline-forms)
+ 2) .icinga-controls, this defines the design of our controls. Any input that's part of a container with
+ this class gets our design applied
+ */
+
+// General form layout
+
+form.icinga-form {
+ max-width: 70em;
+ width: 80%;
+
+ .control-group {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: flex-start;
+
+ // Negative margin-right because every child gets 1em right but we can't exclude
+ // the last element as it's impossible to identify the last *visible* element
+ margin: 1em -1em 1em 0;
+
+ > fieldset {
+ > .control-group:first-of-type {
+ margin-top: 0;
+ }
+
+ > .control-group:last-of-type {
+ margin-bottom: 0;
+ }
+ }
+ }
+
+ .control-group > :not(.control-label-group) {
+ margin-right: 1em;
+ }
+
+ .form-controls {
+ display: flex;
+ justify-content: flex-end;
+ }
+
+ &.inline {
+ width: auto;
+
+ .control-group {
+ margin: 0;
+ align-items: center;
+
+ > :not(.control-label-group) {
+ margin-right: .5em;
+ }
+
+ &:last-child {
+ margin-right: -.5em;
+ }
+ }
+ }
+}
+
+form.inline {
+ display: inline-block;
+
+ fieldset {
+ display: inline-block;
+ vertical-align: top;
+ border: none;
+ }
+}
+
+// Minimal form layout
+
+#layout.minimal-layout,
+#layout.twocols:not(.wide-layout) {
+ form.icinga-form {
+ &:not(.inline) {
+ width: 100%;
+ }
+
+ .control-label-group {
+ text-align: left;
+ padding-bottom: 0;
+ padding-left: 0;
+ margin-bottom: 0;
+ }
+
+ .toggle-switch ~ .control-info:before {
+ margin-left: 0;
+ }
+
+ .errors {
+ margin: 0;
+ }
+ }
+}
+
+#layout.minimal-layout .icinga-form {
+ .form-controls {
+ input[type="submit"] {
+ width: 100%;
+
+ &:not(:last-child) {
+ margin-bottom: 1em;
+ }
+ }
+ }
+}
+
+// Label styles
+
+form.icinga-form .control-label-group {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ line-height: 1.1em;
+ padding: .5625em .5625em .5625em 0;
+ max-height: 2.5em;
+ text-align: right;
+ width: 14em;
+}
+
+form.icinga-form.inline .control-label-group {
+ width: auto;
+ line-height: 0.857em;
+}
+
+.icinga-controls fieldset {
+ margin: 0;
+ padding: 0;
+ border: none;
+
+ legend {
+ font-weight: bold;
+ font-size: 4/3em;
+ margin: 0.556em 0 0.333em;
+ }
+}
+
+.icinga-controls .control-info {
+ line-height: 2.25em;
+ opacity: .6;
+
+ &:before {
+ margin-right: 0;
+ }
+
+ &:hover {
+ opacity: 1;
+ }
+}
+
+form.icinga-form .control-group .control-info {
+ margin-left: -.5em;
+}
+form.icinga-form .control-group .toggle-switch ~ .control-info {
+ margin-left: 0;
+}
+
+// General input styles
+
+.icinga-controls {
+ input[type="text"],
+ input[type="password"],
+ input[type="number"],
+ input[type="datetime-local"],
+ input[type="date"],
+ input[type="time"],
+ input[type="file"],
+ textarea,
+ select {
+ background-color: @low-sat-blue;
+ }
+}
+
+form.icinga-form {
+ input[type="text"],
+ input[type="password"],
+ input[type="number"],
+ input[type="datetime-local"],
+ input[type="date"],
+ input[type="time"],
+ input[type="file"],
+ .control-group > fieldset,
+ textarea,
+ select {
+ flex: 1 1 auto;
+ width: 0;
+ }
+}
+
+.icinga-controls {
+ input:not([type="radio"]),
+ .toggle-switch,
+ button,
+ select,
+ textarea {
+ border: none;
+ .rounded-corners(.25em);
+ .appearance(none);
+ }
+}
+
+.icinga-controls {
+ input:not([type="checkbox"]),
+ .toggle-switch,
+ select,
+ textarea,
+ button,
+ .toggle-switch {
+ font-size: inherit;
+ padding: @vertical-padding;
+ }
+
+ input[type="radio"] {
+ margin-right: .25em;
+ }
+}
+
+form.icinga-form {
+ .control-group .toggle-switch,
+ .form-controls .toggle-switch {
+ margin-top: 0.5em*0.666666667;
+ margin-bottom: 0.5em*0.666666667;
+ }
+}
+
+form.icinga-form select:not([multiple]) {
+ // Compensate inconsistent select height calculations
+ line-height: 1em;
+ height: 2.25em;
+}
+
+// Remove native dropdown arrow in IE10+
+.icinga-controls select::-ms-expand {
+ display: none;
+ opacity: 0;
+}
+
+.icinga-controls select:not([multiple]) {
+ padding-right: 1.5625em;
+ background-image: url(../img/select-icon.svg);
+ background-repeat: no-repeat;
+ background-position: right center;
+ background-size: contain;
+}
+
+form.icinga-form select {
+ width: 0; // Prevent selects with long option values from exceeding the container
+}
+
+form.inline select {
+ width: auto;
+}
+
+
+// Specific input styles
+
+.link-button {
+ .action-link();
+ // Reset defaults
+ background: none;
+ border: none;
+ display: inline-block;
+ padding: 0;
+
+ text-align: left;
+}
+
+.icinga-controls {
+ input ~ .spinner,
+ button ~ .spinner,
+ select ~ .spinner,
+ textarea ~ .spinner {
+ line-height: normal;
+ padding: .5em 0;
+
+ &:before {
+ vertical-align: middle;
+ margin-left: .5em;
+ opacity: 0.4;
+ }
+ }
+}
+
+/* selects get their spinner specifically placed */
+.icinga-controls select:not([multiple]) + .spinner {
+ height: 2.25em;
+ margin: 0;
+
+ &:before {
+ margin-left: -3.75em;
+ }
+}
+
+form.icinga-form .form-controls {
+ .spinner {
+ order: -1;
+ }
+
+ .btn-primary {
+ order: 99;
+ }
+}
+
+// Button styles
+
+.icinga-controls {
+ button:not([type]),
+ button[type="submit"],
+ input[type="submit"],
+ input[type="submit"].btn-confirm {
+ .button();
+ }
+
+ input[type="submit"].btn-remove {
+ .button(@body-bg-color, @color-critical, @color-critical-accentuated);
+ }
+
+ input[type="submit"].btn-cancel {
+ .button(@body-bg-color, @gray, @black);
+ }
+
+ button.noscript-apply {
+ color: @gray;
+ background-color: @gray-lightest;
+ border-color: @gray;
+ border-width: 1px;
+ }
+
+ button[type="button"] {
+ background-color: @low-sat-blue;
+ }
+}
+
+form.icinga-form {
+ button[type="button"] {
+ line-height: normal;
+ }
+}
+
+form.inline {
+ :not([type="hidden"]) {
+ & ~ button:not([type]),
+ & ~ button[type="submit"],
+ & ~ input[type="submit"],
+ & ~ input[type="submit"].btn-confirm {
+ margin-left: @horizontal-padding;
+ }
+ }
+
+ button.noscript-apply {
+ margin-left: .5em;
+ padding: .1em;
+ }
+}
+
+// Toggle styles
+
+.icinga-controls .toggle-switch {
+ cursor: pointer;
+ position: relative;
+ display: inline-block;
+ height: 1.5em;
+ width: 2.625em;
+}
+
+.icinga-controls .toggle-switch .toggle-slider {
+ position: absolute;
+ left: 0;
+ top: 0;
+
+ display: inline-block;
+ background: @low-sat-blue;
+ border: 1px solid;
+ border-color: @low-sat-blue;
+ box-sizing: content-box;
+ border-radius: 1em;
+ height: 4/3em;
+ width: 8/3em;
+ vertical-align: middle;
+}
+
+.icinga-controls .toggle-switch .toggle-slider:before {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ background: @text-color-inverted;
+ border-radius: 1em;
+ border: 1px solid;
+ border-color: @low-sat-blue;
+ box-sizing: border-box;
+ content: "";
+ display: block;
+ height: 4/3em;
+ margin-left: 0;
+ width: 4/3em;
+
+ @transition: left .2s ease, margin .2s ease;
+ -webkit-transition: @transition;
+ -moz-transition: @transition;
+ -o-transition: @transition;
+ transition: @transition;
+}
+
+.icinga-controls input[type="checkbox"]:checked + .toggle-switch .toggle-slider {
+ background-color: @icinga-blue;
+ border: 1px solid;
+ border-color: @icinga-blue;
+}
+
+.icinga-controls input[type="checkbox"]:focus + .toggle-switch .toggle-slider {
+ box-shadow: 0 0 0 2px @body-bg-color, 0 0 0 4px @icinga-blue-light;
+}
+
+.icinga-controls input[type="checkbox"]:checked + .toggle-switch .toggle-slider:before {
+ border: 1px solid;
+ border-color: @icinga-blue;
+ left: 100%;
+ margin-left: -4/3em;
+}
+
+// Disabled inputs
+
+.icinga-controls .toggle-switch.disabled {
+ cursor: default;
+
+ & > .toggle-slider {
+ background-color: @gray-light;
+ border-color: @gray-light;
+
+ &:before {
+ background-color: @gray-lighter;
+ border-color: @gray-light;
+ }
+ }
+}
+
+form.icinga-form .control-group.disabled .control-label-group {
+ color: @disabled-gray;
+}
+
+.icinga-controls {
+ input[disabled],
+ select[disabled] {
+ background-color: @gray-lighter;
+ border-color: transparent;
+ }
+}
+
+// Errors and additional information
+
+form.icinga-form {
+ .form-notifications,
+ .form-description {
+ border-radius: .25em;
+ display: flex;
+ list-style: none;
+ align-items: center;
+ margin: 0 0 1em 0;
+ padding: .25em .5em;
+
+ ul {
+ list-style: none;
+ margin: 0;
+ padding: 0 .5em;
+ }
+
+ li {
+ list-style: none;
+ }
+
+ & .form-notification-icon,
+ & .form-description-icon {
+ font-size: 2em;
+ margin-left: .25em;
+ opacity: .4;
+ align-self: flex-start;
+ }
+ }
+
+ .form-notifications {
+ &.info {
+ background-color: @form-info-bg-color;
+ }
+
+ &.error {
+ background-color: @form-error-bg-color;
+ }
+
+ &.warning {
+ background-color: @form-warning-bg-color;
+ }
+ }
+
+ .form-description {
+ background-color: @light-text-bg-color;
+ }
+
+ .errors {
+ list-style: none;
+ display: block;
+ width: 100%;
+ margin: 0 0 0 15em;
+ padding: 0;
+
+ & > li {
+ margin: 0.5em;
+ color: #f56;
+ }
+ }
+}
+
+form.icinga-form .form-info {
+ color: @text-color-light;
+ font-size: @font-size-small;
+ list-style: none;
+ padding-left: 0;
+}
+
+// Placeholder styles
+
+.icinga-controls {
+ input::placeholder {
+ color: @disabled-gray;
+ font-style: italic;
+ opacity: 1;
+ }
+
+ input:-ms-input-placeholder {
+ color: @disabled-gray;
+ font-style: italic;
+ opacity: 1;
+ }
+}
+
+// Specific form styles
+
+.search.inline {
+ display: inline-block;
+}
+
+/* Flyover form styles */
+
+.flyover-content form:not(.inline):not([role="search"]) {
+ width: auto;
+}
+
+.flyover-content .control-label-group {
+ text-align: left;
+}
+
+.theme-mode-input {
+ display: none;
+
+ &:checked + img {
+ border-color: @icinga-blue;
+ border-radius: .25em;
+ }
+
+ & + img {
+ margin: 0 auto;
+ border: .25em solid transparent;
+ display: block;
+ width: 6em;
+ overflow: hidden;
+ box-shadow: 0 0 .25em 0 rgba(0,0,0,.4);
+ }
+
+ &[disabled] ~ img,
+ &[disabled] ~ span {
+ opacity: .25;
+ }
+
+ & ~ span {
+ display: block;
+ text-align: center;
+ }
+}
+
+#layout.minimal-layout .icinga-form {
+ .theme-mode {
+ .control-label-group {
+ width: 100%;
+ margin-bottom: .5em;
+ }
+
+ label:first-of-type {
+ margin-left: auto;
+ }
+ }
+}
diff --git a/public/css/icinga/grid.less b/public/css/icinga/grid.less
new file mode 100644
index 0000000..e061bc8
--- /dev/null
+++ b/public/css/icinga/grid.less
@@ -0,0 +1,47 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+.grid {
+ .clearfix();
+}
+
+[class^="col-"],
+[class*=" col-"] {
+ float: left;
+ // Fix that empty columns don't consume their width
+ min-height: 1px;
+}
+
+.controls {
+ [class^="col-"],
+ [class*=" col-"] {
+ padding: @vertical-padding / 2 0;
+ }
+}
+
+.col-1-2 {
+ width: 50%;
+}
+
+.col-1-3 {
+ width: 33.33%;
+}
+
+.col-2-3 {
+ width: 66.66%;
+}
+
+.col-3-3 {
+ width: 100%;
+}
+
+// TODO(el): Set proper breakpoints
+#layout.twocols,
+#layout.compact-layout,
+#layout.minimal-layout,
+#layout.poor-layout {
+ [class^="col-"],
+ [class*=" col-"] {
+ float: none;
+ width: 100%;
+ }
+}
diff --git a/public/css/icinga/health.less b/public/css/icinga/health.less
new file mode 100644
index 0000000..50cc11a
--- /dev/null
+++ b/public/css/icinga/health.less
@@ -0,0 +1,69 @@
+// Style
+
+.app-health {
+ header {
+ color: @text-color-light;
+
+ span {
+ color: @text-color;
+ }
+ }
+
+ span {
+ &.state-ok {
+ background-color: @color-ok;
+ }
+
+ &.state-warning {
+ background-color: @color-warning;
+ }
+
+ &.state-critical {
+ background-color: @color-critical;
+ }
+
+ &.state-unknown {
+ background-color: @color-unknown;
+ }
+ }
+
+ a {
+ font-weight: bold;
+ }
+
+ tbody tr, tr.active {
+ border: none;
+ }
+
+ tr:not(:last-child) td {
+ border: 0 solid;
+ border-color: @gray-light;
+ border-bottom-width: 1px;
+ }
+
+ section {
+ color: @text-color-light;
+ font-family: @font-family-fixed;
+ }
+}
+
+// Layout
+
+.app-health {
+ th {
+ width: 2.5em;
+ padding: .5em 1em 0 .5em;
+ vertical-align: top;
+ }
+
+ td {
+ padding: .5em 0;
+ }
+
+ section {
+ margin-top: .25em;
+ height: 3em;
+ overflow: hidden;
+ word-break: break-word;
+ }
+}
diff --git a/public/css/icinga/layout-structure.less b/public/css/icinga/layout-structure.less
new file mode 100644
index 0000000..b1ca8e6
--- /dev/null
+++ b/public/css/icinga/layout-structure.less
@@ -0,0 +1,167 @@
+/*! Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+html {
+ height: 100%;
+ font-family: 'default-layout';
+}
+
+body {
+ height: 100%;
+ overflow: hidden;
+}
+
+#layout {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+#content-wrapper {
+ flex: 1 1 auto;
+ display: flex;
+ height: 0;
+
+}
+
+#sidebar {
+ width: 16em;
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ z-index: 2;
+}
+
+#layout:not(.minimal-layout) #sidebar:after {
+ content: "";
+ display: block;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ width: 1em;
+ background: linear-gradient(to left, rgba(0,0,0,.1), rgba(0,0,0,0));
+ z-index: 0;
+ pointer-events: none;
+}
+
+#main {
+ flex: 1;
+ display: flex;
+ z-index: 1;
+}
+
+.iframe {
+ #header, #sidebar {
+ display: none;
+ }
+}
+
+#responsive-debug {
+ font-size: 0.9em;
+ font-family: Courier new, monospace;
+ padding: 0.5em;
+ width: 25em;
+ color: white;
+ height: 10em;
+ display: none;
+ position: fixed;
+ bottom: 0.5em;
+ right: 2em;
+ overflow: hidden;
+ z-index: 1000;
+ background: #333;
+ border-radius: 0.5em;
+ opacity: 0.9;
+}
+
+#layout.minimal-layout #responsive-debug {
+ font-size: 0.6em;
+}
+
+#layout.poor-layout #responsive-debug {
+ font-size: 0.7em;
+}
+
+#layout.compact-layout #responsive-debug {
+ font-size: 0.8em;
+}
+
+#layout.wide-layout #responsive-debug {
+ font-size: 1em;
+}
+
+/** Fullscreen layout **/
+#layout.fullscreen-layout {
+ #sidebar {
+ display: none;
+ }
+
+ .container .controls {
+ padding: 0;
+ }
+
+ .controls > ul.tabs {
+ margin-top: 0;
+ height: 1.5em;
+ font-size: 0.75em;
+ padding: 0.2em 0 0;
+ }
+
+ .controls > ul.tabs > li > a {
+ line-height: 1.5em;
+ }
+}
+
+.controls-separated,
+.container .controls.separated {
+ box-shadow: 0 3px 4px -4px rgba(0, 0, 0, 0.2);
+// border-bottom: 1px solid @gray-lightest;
+ padding-bottom: @horizontal-padding / 2
+}
+
+.hbox {
+ display: inline-block;
+}
+
+.hbox-item {
+ display: inline-block;
+ vertical-align: top;
+ margin-top: 0.5em;
+ margin-bottom: 0.25em;
+ margin-left: 1em;
+ margin-right: 1em;
+}
+
+.hbox-spacer {
+ display: inline-block;
+ vertical-align: top;
+ width: 2em;
+}
+
+/*
+ * Class to hide content from users but available for screen reader
+ * Based on: https://cloudfour.com/thinks/see-no-evil-hidden-content-and-accessibility/
+ */
+.sr-only {
+ border: 0;
+ clip: rect(0 0 0 0);
+ clip-path: polygon(0px 0px, 0px 0px, 0px 0px);
+ -webkit-clip-path: polygon(0px 0px, 0px 0px, 0px 0px);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: fixed; // absolute causes view port glitches in chrome (#4310)
+ width: 1px;
+ white-space: nowrap;
+}
+
+// Hide non-javascript elements if javascript is enabled
+html.js *.no-js {
+ .sr-only;
+}
+
+// Hide javascript elements if javascript is disabled
+html.no-js *.js {
+ .sr-only;
+}
diff --git a/public/css/icinga/layout.less b/public/css/icinga/layout.less
new file mode 100644
index 0000000..c37da79
--- /dev/null
+++ b/public/css/icinga/layout.less
@@ -0,0 +1,379 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+#footer {
+ bottom: 0;
+ right: 0;
+ left: 12em;
+ position: fixed;
+ z-index: 999;
+}
+
+#layout.minimal-layout #footer {
+ left: 0;
+}
+
+.sidebar-collapsed #footer {
+ left: 3em;
+}
+
+#guest-error {
+ background-color: @icinga-blue;
+ height: 100%;
+ overflow: auto;
+}
+
+#guest-error #icinga-logo {
+ .fadein();
+}
+
+#guest-error-message {
+ .fadein();
+ color: @body-bg-color;
+ font-size: 2em;
+}
+
+#header,
+#login,
+#content-wrapper {
+ font-size: @font-size;
+ line-height: @line-height;
+}
+
+#header-logo-container {
+ background: @menu-bg-color;
+ height: 6em;
+ padding: 1.25em;
+ width: 16em;
+}
+
+#header-logo,
+#mobile-menu-logo {
+ background-image: url('../img/icinga-logo.svg');
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: contain;
+ display: block;
+ height: 100%;
+ width: 100%;
+
+ &:focus {
+ opacity: .6;
+ outline: none;
+ }
+}
+
+#mobile-menu-logo {
+ width: 50%;
+ float: left;
+ height: 2em;
+ margin-top: .25em;
+ background-position: .75em center;
+}
+
+#mobile-menu-toggle .icon-cancel {
+ display: none;
+}
+
+#icinga-logo {
+ background-image: url('../img/icinga-logo-big.svg');
+ background-position: center bottom;
+ background-repeat: no-repeat;
+ background-size: contain; // Does not work in IE < 10
+ height: 177px;
+ margin-bottom: 2em;
+ width: 100%;
+
+ &.invert {
+ background-image: url('../img/icinga-logo-big-dark.svg');
+ }
+}
+
+#layout {
+ background-color: @body-bg-color;
+ color: @text-color;
+ font-family: @font-family;
+}
+
+#login {
+ overflow: auto;
+}
+
+@gutter: 1em;
+
+// x-column-layout
+#main {
+ .clearfix();
+
+ & > .container {
+ width: 0;
+ overflow: auto;
+ flex: 1 1 auto;
+ display: flex;
+ flex-direction: column;
+
+ &:empty {
+ display: none;
+ }
+
+ & > .content {
+ flex: 1 1 auto;
+ overflow: auto;
+ }
+
+ & > .controls {
+ > .tabs {
+ // Remove gutter for tabs
+ margin-left: -1 * @gutter;
+ margin-right: -1 * @gutter;
+ height: 2.5em;
+ }
+
+ .tabs:first-child:not(:last-child) {
+ margin-bottom: .5em;
+ }
+ }
+ }
+}
+
+// Not part of the above to relax specificity and to allow modules adjust this
+:not(.dashboard) > .container {
+ & > .controls {
+ padding-left: @gutter;
+ padding-right: @gutter;
+ }
+
+ & > .content {
+ padding: @gutter;
+ }
+}
+
+// Mobile menu
+#layout.minimal-layout #sidebar {
+ background-color: @menu-bg-color;
+}
+
+#mobile-menu-toggle {
+ color: @menu-color;
+ text-align: right;
+
+ > button {
+ background: none;
+ border: none;
+ font-size: 2em;
+ padding: 0 .5em;
+ line-height: 2;
+
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ appearance: none;
+ }
+
+ i:before {
+ margin-right: 0;
+ }
+}
+
+.container,
+.error-message,
+.modal-window {
+ // Don't outline containers and error messages when focused because they receive focus for accessibility only
+ // programmatically
+ outline: none;
+}
+
+.controls {
+ > .tabs {
+ overflow: hidden;
+ }
+}
+
+// Dashboard grid
+
+.dashboard {
+ letter-spacing: -0.417em;
+
+ > .container {
+ display: inline-block;
+ letter-spacing: normal;
+ vertical-align: top;
+ // Column width controlled by #layout
+ width: 100%;
+
+ &:last-of-type {
+ // See reponsive.less for gutters
+ padding-right: 0;
+ }
+ }
+}
+
+// Notification styles
+
+#notifications {
+ // Reset defaults
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+#notifications > li {
+ color: @text-color;
+ display: block;
+ line-height: 2.5em;
+ border-left: .5em solid @gray-light;
+ background: @body-bg-color;
+ margin-bottom: 1px;
+ box-shadow: 0 0 1em 0 rgba(0,0,0,0.25);
+
+ .icon {
+ padding: .5em;
+ width: 3em;
+ text-align: center;
+ }
+
+ &:hover {
+ cursor: pointer;
+ }
+
+ &.error {
+ border-color: @color-notification-error;
+ background: @color-notification-error;
+ color: @text-color-on-icinga-blue;
+
+ .icon {
+ color: @text-color-on-icinga-blue;
+ }
+ }
+
+ &.info {
+ border-color: @color-notification-info;
+
+ .icon {
+ color: @color-notification-info;
+ }
+ }
+
+ &.success {
+ border-color: @color-notification-success;
+
+ .icon {
+ color: @color-notification-success;
+ }
+ }
+
+ &.warning {
+ border-color: @color-notification-warning;
+ background: @color-notification-warning;
+ color: @text-color-inverted;
+
+ .icon {
+ color: @text-color-inverted;
+ }
+ }
+}
+
+// Collapsed sidebar
+#layout:not(.minimal-layout).sidebar-collapsed {
+ #header-logo-container {
+ height: 3em;
+ padding: 0.25em 0.125em;
+ width: 4em;
+ }
+
+ #header-logo {
+ background-image: url('../img/icinga-logo-compact.svg');
+ }
+
+ #sidebar {
+ width: 4em;
+ }
+
+ #open-sidebar {
+ display: inline;
+ }
+
+ #close-sidebar {
+ display: none;
+ }
+
+ #menu {
+ .nav-level-1 {
+ > .badge-nav-item > a {
+ position: relative;
+
+ > .badge {
+ position: absolute;
+ right: .5em;
+ bottom: .25em;
+ font-size: 75%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 4em;
+ }
+ }
+
+ > .nav-item.active > a > .badge {
+ display: unset;
+ }
+ }
+
+ img.icon {
+ margin: 0 1.25em -.25em 0.25em;
+ font-size: 1.5em;
+ }
+
+ .nav-item {
+ white-space: nowrap;
+ }
+
+ .nav-item.no-icon > a {
+ padding-left: .75em;
+ }
+
+ .nav-level-1 > .nav-item i {
+ font-size: 1.5em;
+ margin-right: .5em;
+ }
+
+ > .search-control {
+ height: 3.333em;
+ }
+ }
+
+ #search {
+ padding-left: 3.75em;
+ }
+
+ #search:focus {
+ background-color: @menu-bg-color;
+ border-radius: 0 .25em .25em 0;
+ box-shadow: 0 0 .25em 0 rgba(0, 0, 0, .2);
+ color: @menu-color;
+ width: 20em;
+ position: fixed;
+ z-index: 1;
+ }
+
+ .search-input {
+ font-size: 1.25em;
+ padding-right: .625em;
+ }
+
+ .search-reset {
+ display: none;
+ }
+
+ .skip-links {
+ a, button {
+ width: 20em;
+ }
+ }
+}
+
+@light-mode: {
+ #header-logo,
+ #mobile-menu-logo,
+ #about .icinga-logo {
+ filter: brightness(0.415) sepia(1) ~"saturate(0.1)" hue-rotate(144deg);
+ }
+};
diff --git a/public/css/icinga/login-orbs.less b/public/css/icinga/login-orbs.less
new file mode 100644
index 0000000..b0426dd
--- /dev/null
+++ b/public/css/icinga/login-orbs.less
@@ -0,0 +1,104 @@
+/*! Icinga Web 2 | (c) 2021 Icinga GmbH | GPLv2+ */
+
+#login {
+ background-image: none;
+
+ .login-form {
+ background: none;
+ box-shadow: none;
+ }
+}
+
+.orb {
+ display: block;
+ position: absolute;
+ pointer-events: none;
+ transform-origin: center center;
+}
+
+.orb img {
+ height: auto;
+ width: 100%;
+}
+
+#orb-analytics {
+ top: -19%;
+ width: 25%;
+ left: 22.5%;
+ z-index: 0;
+}
+
+#orb-analytics img {
+ opacity: .2;
+}
+
+#orb-automation {
+ bottom: -6%;
+ width: 60%;
+ left: 7%;
+ z-index: 0;
+ margin-left: -30%;
+ margin-bottom: -30%;
+}
+
+#orb-automation img {
+ opacity: .75;
+}
+
+#orb-cloud {
+ top: -6%;
+ width: 25%;
+ right: 4%;
+ z-index: 0;
+ margin-right: -12.5%;
+ margin-top: -12.5%;
+}
+
+#orb-cloud img {
+ opacity: .4;
+}
+
+#orb-notifactions {
+ top: 7%;
+ right: 46%;
+ width: 10%;
+ margin: -5%;
+}
+
+#orb-notifactions img {
+ opacity: .5;
+}
+
+#orb-metrics {
+ left: 5%;
+ top: 20%;
+ width: 35%;
+ margin: -17.5%;
+}
+
+#orb-metrics img {
+ opacity: .5;
+}
+
+#orb-icinga {
+ left: 50%;
+ top: 50%;
+ margin-top: -38.5em;
+ margin-left: -38em;
+ width: 75em;
+ z-index: 0;
+}
+
+#orb-icinga img {
+ opacity: .8;
+}
+
+#orb-infrastructure {
+ top: -36%;
+ left: -15%;
+ width: 30%;
+}
+
+#orb-infrastructure img {
+ opacity: .6;
+}
diff --git a/public/css/icinga/login.less b/public/css/icinga/login.less
new file mode 100644
index 0000000..b37dbd8
--- /dev/null
+++ b/public/css/icinga/login.less
@@ -0,0 +1,183 @@
+/*! Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+// Login page styles
+
+#login {
+ height: 100%;
+ background-color: @menu-bg-color;
+ background-image: url(../img/icingaweb2-background-orbs.jpg);
+ background-repeat: no-repeat;
+ background-size: cover;
+ text-align: center;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ .login-form {
+ width: 36em;
+ position: relative;
+ z-index: 10;
+ padding: 2em 6em;
+ background-color: @login-box-background;
+ .box-shadow(0, 0, 1em, 1em, @login-box-background);
+ }
+
+ #icinga-logo {
+ width: 100%;
+ max-width: 18em;
+ height: auto;
+ margin: 0 auto 2em auto;
+
+ &:after {
+ content: "";
+ display: block;
+ width: 100%;
+ padding-bottom: 35%;
+ }
+ }
+
+ .errors,
+ .form-errors {
+ list-style-type: none;
+ padding: 0.5em;
+ }
+
+ .errors {
+ background-color: @color-critical;
+ color: white;
+ }
+
+ .form-errors {
+ margin-top: 0;
+ padding: 0;
+ }
+
+ .form-errors,
+ .control-group {
+ &:not(:last-child) {
+ margin-bottom: 1em;
+ }
+ }
+
+ input[type=password],
+ input[type=text] {
+ display: block;
+ height: 2.5em;
+ margin: 0;
+ transition: none;
+ width: 100%;
+
+ &:focus {
+ .rounded-corners(3px);
+ border-radius: 0;
+ padding-bottom: 3px;
+ }
+ }
+
+ input[type="submit"]:focus {
+ outline: 3px solid;
+ outline-color: @icinga-blue-light;
+ }
+
+ input[type=submit] {
+ border-radius: .25em;
+ background: @icinga-secondary;
+ color: white;
+ border: none;
+ height: 2.5em;
+ margin: 0;
+ width: 100%;
+
+ &:hover {
+ background-color: @icinga-secondary-dark;
+ }
+ }
+
+ .config-note {
+ background-color: @color-critical;
+ margin: 0 auto 2em auto; // Center horizontally w/ bottom margin
+ max-width: 50%;
+ min-width: 24em;
+ padding: 1em;
+
+ a {
+ color: @text-color-inverted;
+ font-weight: bold;
+ }
+ }
+
+ .remember-me-box {
+ display: flex;
+ align-items: flex-start;
+
+ .toggle-switch {
+ margin-right: 1em;
+ }
+
+ .control-info {
+ line-height: 1.5;
+ margin-left: .5em;
+ }
+ }
+}
+
+#social {
+ position: fixed;
+ right: 1em; bottom: 1em;
+ letter-spacing: -.417em;
+ margin: 0;
+
+ > * {
+ letter-spacing: normal;
+ }
+
+ > li {
+ display: inline-block;
+
+ a {
+ display: block;
+ text-decoration: none;
+ -webkit-transform: scale(1, 1);
+ -moz-transform: scale(1, 1);
+ -ms-transform: scale(1, 1);
+ transform: scale(1, 1);
+ }
+
+ i {
+ font-size: 3em;
+ color: white;
+ text-shadow: 0 0 .5em #01507B;
+ }
+ }
+
+ > li a:hover {
+ -webkit-transform: scale(1.2, 1.2);
+ -moz-transform: scale(1.2, 1.2);
+ -ms-transform: scale(1.2, 1.2);
+ transform: scale(1.2, 1.2);
+ }
+
+ li:not(:last-child) {
+ margin-right: 2em;
+ }
+}
+
+#login-footer {
+ padding: .5em 0;
+
+ p {
+ margin-bottom: 0;
+ }
+
+ a {
+ text-decoration: underline;
+
+ &:hover {
+ opacity: .8;
+ }
+ }
+}
+
+.orb {
+ display: none;
+}
diff --git a/public/css/icinga/main.less b/public/css/icinga/main.less
new file mode 100644
index 0000000..bfe97d5
--- /dev/null
+++ b/public/css/icinga/main.less
@@ -0,0 +1,452 @@
+/*! Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+// Url for static ipl assets
+@iplWebAssets: "../lib/icinga/icinga-php-library";
+
+// Width for the name column--th--of name-value-table
+@name-value-table-name-width: 38/3em;
+
+.action-link {
+ color: @icinga-blue;
+}
+
+.error-message {
+ font-weight: @font-weight-bold;
+}
+
+.error-reason {
+ margin-top: 4em;
+}
+
+.large-icon {
+ font-size: 200%;
+}
+
+.content-centered {
+ margin: 0 auto;
+ text-align: center;
+}
+
+.icon-col {
+ text-align: center;
+ width: 1em;
+}
+
+.preformatted {
+ font-family: @font-family-fixed;
+ white-space: pre-wrap;
+}
+
+.markdown {
+ > * {
+ margin-left: 0;
+ margin-right: 0;
+ }
+
+ > *:last-child {
+ margin-bottom: 0;
+ }
+
+ img {
+ max-width: 100%;
+ height: auto;
+ }
+
+ a {
+ border-bottom: 1px @text-color-light dotted;
+
+ &:hover, &:focus {
+ border-bottom: 1px @text-color solid;
+ text-decoration: none;
+ }
+
+ img {
+ max-width: 32em;
+ }
+
+ &.with-thumbnail {
+ img {
+ padding: 1px;
+ }
+
+ &:hover, &:focus {
+ img {
+ padding: 0;
+ }
+ }
+ }
+ }
+
+ table {
+ border-collapse: collapse;
+
+ th {
+ text-align: left;
+ background-color: @gray-lighter;
+ }
+
+ &, th, td {
+ border: 1px solid @gray-light;
+ }
+ }
+}
+
+.no-wrap {
+ white-space: nowrap;
+}
+
+.pull-right {
+ float: right;
+}
+
+.text-right {
+ text-align: right;
+}
+
+.user-avatar {
+ height: 16px;
+ width: 16px;
+}
+
+.v-center {
+ > * {
+ vertical-align: middle;
+ }
+}
+
+.section {
+ margin-bottom: 2em;
+}
+
+a:hover > .icon-cancel {
+ color: @color-critical;
+}
+
+.icon-stateful {
+ .fg-stateful();
+}
+
+// Link styles
+
+.button-link {
+ .action-link();
+ .rounded-corners(3px);
+
+ background: @low-sat-blue;
+ display: inline-block;
+ padding: 0.25em 0.5em;
+
+ &:hover {
+ background: @low-sat-blue-dark;
+ text-decoration: none;
+ }
+}
+
+// List styles
+
+.comment-list {
+ margin: 0;
+
+ > dt {
+ border-bottom: 1px solid @gray-lighter;
+ margin-bottom: 0.25em;
+
+ &:hover {
+ background-color: @gray-lightest;
+
+ > .remove-action button:not(.spinner.active) {
+ visibility: visible;
+ }
+ }
+
+ > .remove-action button:not(.spinner.active) {
+ visibility: hidden;
+ }
+ }
+
+ > dd {
+ margin: 0 0 1em 0;
+ }
+}
+
+.comment-time {
+ color: @text-color-light;
+ font-size: @font-size-small;
+}
+
+.name-value-list {
+ > dd {
+ // Reset default margin
+ margin: 0;
+ }
+
+ > dt {
+ color: @text-color-light;
+ font-size: @font-size-small;
+ }
+}
+
+// Table styles
+
+.common-table {
+ width: 100%;
+
+ td, th {
+ padding-top: 1em;
+ }
+
+ td {
+ padding-bottom: 1em;
+ }
+
+ th {
+ text-align: left;
+ padding-bottom: 0.5em;
+ }
+
+ thead {
+ border-bottom: 1px solid @gray-light;
+ }
+
+ tbody tr {
+ border-bottom: 1px solid @gray-lightest;
+ border-left: 5px solid transparent;
+
+ &:last-child {
+ border-bottom: none;
+ }
+ }
+
+ tr[href].active {
+ background-color: @tr-active-color;
+ border-left-color: @icinga-blue;
+ }
+
+ tr[href]:hover {
+ background-color: @tr-hover-color;
+ cursor: pointer;
+ }
+}
+
+.name-value-table {
+ width: 100%;
+}
+
+.name-value-table > caption {
+ margin-top: .5em;
+ text-align: left;
+ font-weight: bold;
+}
+
+.name-value-table > tbody > tr > th {
+ color: @text-color-light;
+ // Reset default font-weight
+ font-weight: normal;
+ padding-left: 0;
+ text-align: left;
+ vertical-align: top;
+ width: @name-value-table-name-width;
+}
+
+/* Styles for centering content of unknown width and height both horizontally and vertically
+ *
+ * Example markup:
+ * <div class="centered-ghost">
+ * <div class="centered-content">
+ * <p>I'm centered.</p>
+ * </div>
+ * </div>
+ */
+
+.centered-content {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.centered-ghost {
+ height: 100%;
+ text-align: center;
+ letter-spacing: -0.417em; // Remove gap between content and ghost
+}
+
+.centered-ghost > * {
+ letter-spacing: normal;
+}
+
+.centered-ghost:after {
+ content: '';
+ display: inline-block;
+ height: 100%;
+ vertical-align: middle;
+}
+
+// Responsive iFrames
+
+.iframe-container {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ padding-bottom: 75%;
+ width: 100%;
+
+ & > iframe {
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 100%;
+ width: 100%;
+ }
+}
+
+// Collapsible Control
+#collapsible-control-ghost {
+ display: none;
+}
+
+.collapsible + .collapsible-control {
+ position: relative;
+ z-index: 1;
+
+ button {
+ .rounded-corners(50%);
+
+ float: right;
+ width: 2em;
+ height: 2em;
+ padding: 0;
+ margin-top: -1em;
+ margin-right: .25em;
+
+ background: @gray-lighter;
+ color: @gray;
+ border: none;
+ -webkit-box-shadow: 0 0 1/3em rgba(0,0,0,.3);
+ -moz-box-shadow: 0 0 1/3em rgba(0,0,0,.3);
+ box-shadow: 0 0 1/3em rgba(0,0,0,.3);
+
+ &:hover {
+ background: @gray-light;
+ }
+ }
+
+ button i:before {
+ margin-right: 0;
+ }
+}
+
+.collapsible[data-can-collapse]:not(.collapsed) + .collapsible-control button,
+.collapsible[data-can-collapse]:not(.collapsed) > .collapsible-control,
+details.collapsible[open] + .collapsible-control button,
+details.collapsible[open] > .collapsible-control {
+ i.expand-icon {
+ display: none;
+ }
+
+ i.collapse-icon {
+ display: inline;
+ }
+}
+
+.collapsible.collapsed + .collapsible-control button,
+.collapsible.collapsed > .collapsible-control,
+details.collapsible:not([open]) + .collapsible-control button,
+details.collapsible:not([open]) > .collapsible-control {
+ i.expand-icon {
+ display: inline;
+ }
+
+ i.collapse-icon {
+ display: none;
+ }
+}
+
+// Collapsibles
+
+.collapsible.collapsed:not(details) {
+ overflow: hidden;
+}
+
+.collapsible.collapsed:not([data-toggle-element], details) {
+ position: relative;
+
+ &:after {
+ content: "";
+ display: block;
+ height: 2em;
+ background: linear-gradient(@body-bg-color-transparent, @body-bg-color);
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ z-index: 1;
+
+ opacity: 1;
+ transition: opacity 2s 1s linear;
+ }
+}
+
+.role-memberships {
+ letter-spacing: -0.417em;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+
+ > li {
+ display: inline-block;
+ letter-spacing: normal;
+ margin: 0;
+ padding: 0 0.25em 0 0;
+
+ &:last-child {
+ padding-right: 0;
+ }
+ }
+}
+
+.module-dependencies {
+ .unmet-dependencies {
+ background-color: @color-warning;
+ color: @text-color-on-icinga-blue;
+ padding: .25em .5em;
+ margin-left: -.5em;
+ }
+
+ .name-value-table {
+ > caption {
+ font-weight: normal;
+ color: @text-color-light;
+ }
+
+ > tbody > tr > th {
+ font-weight: bold;
+ color: @text-color;
+ }
+
+ .missing {
+ color: @color-critical;
+ font-weight: bold;
+ }
+
+ td {
+ white-space: nowrap;
+
+ &.or-separator {
+ width: 100%;
+ transform: translate(0, 50%);
+ padding-left: 3em;
+
+ &::before {
+ content: "";
+ position: absolute;
+ height: 1.5em;
+ width: 1.5em;
+ left: 0.5em;
+ border-top: 3px solid @gray;
+ border-right: 3px solid @gray;
+ border-top-right-radius: .50em;
+ transform: rotate(45deg);
+ }
+ }
+ }
+ }
+}
diff --git a/public/css/icinga/menu.less b/public/css/icinga/menu.less
new file mode 100644
index 0000000..98650a2
--- /dev/null
+++ b/public/css/icinga/menu.less
@@ -0,0 +1,554 @@
+/*! Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+#menu [class^="icon-"],
+#menu [class*=" icon-"] {
+ &:before {
+ width: 1.5em;
+ }
+}
+
+@icon-width: 1.7em; // 1.5em width + 0.2em right margin
+
+#menu {
+ background-color: @menu-bg-color;
+ width: 100%;
+ flex: 1;
+ overflow: auto;
+ overflow-x: hidden;
+}
+
+#menu .nav-item {
+ vertical-align: middle;
+
+ > a {
+ position: relative;
+
+ &:focus {
+ outline: none;
+ }
+
+ &:hover {
+ text-decoration: none;
+ }
+ }
+}
+
+#layout:not(.sidebar-collapsed) #menu .nav-item > a:first-of-type {
+ // Respect overflowing content
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+#layout:not(.minimal-layout).sidebar-collapsed #menu .nav-level-1 > .nav-item {
+ overflow: hidden;
+}
+
+#layout:not(.minimal-layout).sidebar-collapsed #menu .nav-level-1 > .nav-item > a {
+ // Clip overflowing content
+ overflow: hidden;
+ width: 4em;
+}
+
+#menu .nav-level-1 > .nav-item {
+ line-height: 2.167em; // 26 px
+ color: @menu-color;
+
+ &.active {
+ color: @menu-active-color;
+
+ > a > .badge {
+ display: none;
+ }
+
+ background-color: @menu-active-bg-color;
+ }
+
+ &.no-icon > a {
+ padding-left: @icon-width + .75em;
+ }
+
+ > a {
+ padding: 0.5em 0.5em 0.5em .75em;
+ }
+
+ &.active:not(.selected) > a:focus,
+ &.active:not(.selected) > a:hover {
+ background-color: @menu-active-hover-bg-color;
+ }
+
+ &:not(.selected) > a:hover,
+ &:not(.selected) > a:focus {
+ background-color: @menu-hover-bg-color;
+ }
+
+ // Balance icon weight for non active menu items
+ &:not(.active) > a > i {
+ opacity: .8;
+ }
+
+ & > a > .icon-letter:before {
+ content: attr(data-letter);
+ font-family: @font-family;
+ font-weight: 800;
+ text-transform: uppercase;
+ }
+}
+
+#menu ul:not(.nav-level-2) > .selected > a {
+ background-color: @menu-highlight-color;
+ color: @text-color-inverted;
+
+ &:focus {
+ background-color: @menu-highlight-hover-bg-color;
+ }
+
+ &:after {
+ .transform(rotate(45deg));
+
+ position: absolute;
+ right: -.75em;
+
+ background-color: @body-bg-color;
+ box-shadow: 0 0 1em 0 rgba(0,0,0,0.6);
+ content: "";
+ display: block;
+ height: 1.25em;
+ margin-top: -1.75em;
+ width: 1.25em;
+ }
+}
+
+#menu .nav-level-2 > .nav-item {
+ // Collapse menu by default
+ display: none;
+ line-height: 1.833em; // 22px
+
+ > a {
+ color: @menu-2ndlvl-color;
+ font-size: @font-size-small;
+ padding: 0.364em 0.545em 0.364em 0.545em;
+
+ &:first-of-type {
+ padding-left: (@icon-width + .75em)/@font-size-small;
+ }
+ }
+
+ &.active {
+ overflow: hidden;
+ position: relative;
+ }
+
+ // Little caret on active level-2 item
+ &.active:after {
+ .transform(rotate(45deg));
+
+ background-color: @body-bg-color;
+ box-shadow: 0 0 1em 0 rgba(0,0,0,.6);
+ content: "";
+ display: block;
+ height: 1.25em;
+ width: 1.25em;
+ position: absolute;
+ top: .5em;
+ right: -.75em;
+ z-index: 3;
+ }
+
+ &.active > a {
+ color: @menu-2ndlvl-active-color;
+ background-color: @menu-2ndlvl-active-bg-color;
+
+ &:focus {
+ &:first-of-type,
+ &:first-of-type ~ a {
+ color: @menu-2ndlvl-active-hover-color;
+ background-color: @menu-2ndlvl-active-hover-bg-color;
+ }
+ }
+ }
+}
+
+.no-js #menu .nav-level-2 > .nav-item {
+ // Expand menu if JavaScript is disabled
+ display: block;
+}
+
+#layout:not(.sidebar-collapsed) {
+ #menu .nav-level-1 > .nav-item {
+ &.active {
+ .nav-level-2 > li {
+ // Expand menu if active
+ display: block;
+ }
+ }
+ }
+}
+
+#menu img.icon {
+ line-height: 1;
+ margin: 0 0.5em -.05em 0.25em;
+ width: 1em;
+}
+
+#menu img[src*="/img/icons/"] {
+ &:not([src$="tux.png"]):not([src$="win.png"]):not([src$="_white.png"]) {
+ -webkit-filter: invert(100%);
+ -moz-filter: invert(100%);
+ -ms-filter: invert(100%);
+ filter: invert(100%);
+ }
+}
+
+.nav-item:hover img.icon {
+ opacity: .6;
+}
+
+#menu input.search {
+ background: transparent url('../img/icons/search_white.png') no-repeat 1em center;
+ background-size: 1em auto;
+ border: none;
+ color: @menu-color;
+ line-height: 2.167em;
+ padding: .25em;
+ padding-left: @icon-width + .75em;
+ width: 100%;
+
+ &:focus::placeholder {
+ color: @menu-color;
+ }
+ &:focus::-ms-input-placeholder {
+ color: @menu-color;
+ }
+
+ &.active {
+ background-color: @menu-active-bg-color;
+ }
+
+ &:hover,
+ &:focus {
+ background-color: @menu-search-hover-bg-color;
+ }
+}
+
+// Badge offset correction
+#menu > nav > .nav-level-1 > .badge-nav-item > a > .badge {
+ margin-top: 0.2em;
+}
+
+#menu .nav-level-2 > .badge-nav-item > a > .badge {
+ margin-top: 0.2em;
+ margin-right: .5em
+}
+
+// Hovered menu
+#layout:not(.minimal-layout).sidebar-collapsed #menu .nav-level-1 > .nav-item.hover,
+#layout:not(.minimal-layout) #menu .nav-level-1 > .nav-item:not(.active).hover {
+ > .nav-level-2 {
+ background-color: @menu-flyout-bg-color;
+ border: 1px solid;
+ border-color: @gray-light;
+ border-radius: .25em;
+ box-shadow: 0 0 1em 0 rgba(0,0,0,.3);
+ padding: @vertical-padding 0;
+ width: 14em;
+ position: fixed;
+ z-index: 1;
+
+ &:after {
+ .transform(rotate(45deg));
+
+ background-color: @body-bg-color;
+ border-bottom: 1px solid @gray-light;
+ border-left: 1px solid @gray-light;
+ content: "";
+ display: block;
+ height: 1.1em;
+ width: 1.1em;
+ position: absolute;
+ top: 1em;
+ left: -.6em;
+ z-index: -1;
+ }
+ > .nav-item {
+ display: block;
+ padding-left: 0;
+ position: relative;
+
+ > a {
+ color: @menu-flyout-color;
+
+ &:first-of-type {
+ padding-left: 1.5em;
+ }
+ }
+
+ &:not(.active) {
+ a:hover, a:focus {
+ &:first-of-type,
+ &:first-of-type ~ a {
+ background-color: @menu-2ndlvl-highlight-bg-color;
+ }
+ }
+ }
+
+ &.active > a {
+ color: @menu-color;
+ }
+
+ // Hide activity caret when displayed as flyout
+ &:after {
+ display: none;
+ }
+ }
+ }
+
+ > a > .badge {
+ display: none;
+ }
+
+ img.icon {
+ opacity: .6;
+ }
+}
+
+#layout:not(.minimal-layout) #menu .nav-level-1 > .nav-item:not(.active).hover {
+ > .nav-level-2 {
+ // Position relative to parent
+ margin-left: 16em;
+ margin-top: -3.167em;
+ }
+}
+
+#layout:not(.minimal-layout).sidebar-collapsed #menu .nav-level-1 > .nav-item.hover {
+ > .nav-level-2 {
+ // Position relative to parent
+ margin-left: 4em;
+ margin-top: -3.333em;
+
+ > .badge-nav-item {
+ display: flex;
+
+ a:first-of-type {
+ flex: 1 1 auto;
+ width: 0;
+ }
+
+ a:first-of-type ~ a {
+ flex: 0;
+ width: auto;
+
+ &:hover,
+ &:focus {
+ .badge {
+ opacity: .6;
+ }
+ }
+ }
+ }
+ }
+}
+
+// Accessibility skip links
+.skip-links {
+ position: relative;
+ font-size: 1/.75em;
+
+ ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ li {
+ display: block;
+ a, button[type="submit"] {
+ background-color: @body-bg-color;
+ border: none;
+ left: -999px;
+ padding: @vertical-padding @horizontal-padding;
+ position: absolute;
+ width: 100%;
+ z-index: 1;
+ &:focus {
+ left: 0;
+ outline-offset: -3px;
+ }
+ }
+ button[type="submit"] {
+ text-align: left;
+ }
+ }
+ }
+}
+
+#sidebar.expanded {
+ #mobile-menu-toggle .icon-menu {
+ display: none;
+ }
+
+ #mobile-menu-toggle .icon-cancel {
+ display: inline-block;
+ }
+}
+
+.search-control {
+ position: relative;
+}
+
+.search-input:focus ~ .search-reset:hover {
+ background-color: @menu-active-hover-bg-color;
+}
+
+.search-reset {
+ background: none;
+ border: 0;
+ color: @menu-color;
+ cursor: pointer;
+ display: none;
+ height: 100%;
+ padding: 0;
+ user-select: none;
+ position: absolute;
+ right: 0;
+ top: 0;
+
+ &:focus,
+ &:hover {
+ background-color: @menu-search-hover-bg-color;
+ outline: none;
+ }
+}
+
+// Override forms.less
+input[type=text].search-input {
+ padding-right: 1.4em;
+ text-overflow: ellipsis;
+ transition: none;
+}
+
+.search-input:focus:-moz-placeholder { // FF 18-
+ color: @gray-light;
+}
+
+.search-input:focus::-moz-placeholder { // FF 19+
+ color: @gray-light;
+}
+
+.search-input:focus:-ms-input-placeholder {
+ color: @gray-light;
+}
+
+.search-input:focus::-webkit-input-placeholder {
+ color: @gray-light;
+}
+
+.search-input ~ .search-reset {
+ opacity: 0;
+}
+
+.search-input:valid ~ .search-reset {
+ display: block;
+ opacity: 1;
+}
+
+.search-input:invalid,
+.search-input:-moz-submit-invalid,
+.search-input:-moz-ui-invalid {
+ // Disable glow
+ box-shadow: none;
+}
+
+// Toggle sidebar button
+#toggle-sidebar {
+ font-size: 1/.75em;
+
+ // Reset button styles
+ background: none;
+ border: none;
+ padding: 0;
+ color: @text-color-light;
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ z-index: 3;
+ line-height: 2;
+
+ i {
+ background-color: @body-bg-color;
+ border-radius: .25em 0 0 .25em;
+ font-size: 1.125em;
+ width: 2em;
+ }
+
+ &:focus {
+ outline: none;
+ }
+
+ &:hover, &:focus {
+ i {
+ color: @menu-highlight-color;
+ }
+ }
+}
+
+html.no-js #toggle-sidebar {
+ display: none;
+}
+
+#layout.minimal-layout #toggle-sidebar {
+ display: none;
+}
+
+#open-sidebar {
+ display: none;
+}
+
+#open-sidebar:before,
+#close-sidebar:before {
+ width: 1.4em;
+ margin-right: 0;
+}
+
+#layout:not(.sidebar-collapsed) #menu .nav-level-1 > .nav-item.active .nav-level-2 > li {
+ &.nav-item:not(.badge-nav-item) {
+ &:not(.selected):not(.active) a:hover,
+ &:not(.selected):not(.active) a:focus {
+ background-color: @menu-2ndlvl-highlight-bg-color;
+ }
+ }
+}
+
+#layout:not(.sidebar-collapsed) #menu .nav-level-1 > .nav-item.active .nav-level-2 > li,
+#layout:not(.sidebar-collapsed) #menu .nav-level-1 > .nav-item:not(.active).hover .nav-level-2 > li {
+ &.badge-nav-item {
+ display: flex;
+ }
+
+ &.badge-nav-item a:first-of-type {
+ flex: 1 1 auto;
+ width: 0;
+ }
+
+ &.badge-nav-item a:first-of-type ~ a {
+ flex: 0;
+ width: auto;
+
+ &:hover,
+ &:focus {
+ .badge {
+ opacity: .6;
+ }
+ }
+ }
+}
+
+#layout:not(.sidebar-collapsed) #menu .nav-level-1 > .nav-item.active .nav-level-2 > li {
+ &.badge-nav-item:not(.selected) {
+ a:hover,
+ a:focus {
+ &:first-of-type,
+ &:first-of-type ~ a {
+ background-color: @menu-2ndlvl-highlight-bg-color;
+ }
+ }
+ }
+}
diff --git a/public/css/icinga/mixins.less b/public/css/icinga/mixins.less
new file mode 100644
index 0000000..6c55512
--- /dev/null
+++ b/public/css/icinga/mixins.less
@@ -0,0 +1,201 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+.button(
+ @background-color: @body-bg-color,
+ @border-font-color: @icinga-blue,
+ @color-dark: @icinga-blue-dark
+) {
+ .rounded-corners(3px);
+
+ display: inline-flex;
+ align-items: baseline;
+ background-color: @background-color;
+ border: 2px solid @border-font-color;
+ color: @border-font-color;
+ cursor: pointer;
+ line-height: normal;
+ outline: none;
+ padding: ~"calc(@{vertical-padding} - 2px)" @horizontal-padding;
+
+ @duration: 0.2s;
+ // The trailing semicolon is needed to be able to pass this as a css list
+ .transition(background @duration, border @duration ease, color @duration ease;);
+
+ &:focus,
+ &:hover,
+ &.btn-primary {
+ background-color: @border-font-color;
+ color: @background-color;
+ }
+
+ &.btn-primary:focus,
+ &.btn-primary:hover {
+ background-color: @color-dark;
+ border-color: @color-dark;
+ color: @background-color;
+ }
+
+ &:hover {
+ text-decoration: none;
+ }
+}
+
+.clearfix {
+ &:after {
+ content: "";
+ clear: both;
+ display: table;
+ }
+}
+
+.opacity(@opacity: 0.6) {
+ opacity: @opacity;
+}
+
+.transform(@transform) {
+ -webkit-transform: @transform;
+ -moz-transform: @transform;
+ -ms-transform: @transform;
+ -o-transform: @transform;
+ transform: @transform;
+}
+
+.user-select(@user-select) {
+ -webkit-user-select: @user-select;
+ -moz-user-select: @user-select;
+ -ms-user-select: @user-select;
+ user-select: @user-select;
+}
+
+.transition (@transition) {
+ -webkit-transition: @transition;
+ -moz-transition: @transition;
+ -o-transition: @transition;
+ transition: @transition;
+}
+
+// Fadein animation
+
+/* Chrome, WebKit */
+@-webkit-keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+/* FF < 16 */
+@-moz-keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+/* Opera < 12.1 */
+@-o-keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+@keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+.fadein() {
+ opacity: 0;
+
+ -webkit-animation: fadein 2s ease-in; /* Chrome, WebKit */
+ -moz-animation: fadein 2s ease-in; /* FF < 16 */
+ -o-animation: fadein 2s ease-in; /* Opera < 12.1 */
+ animation: fadein 2s ease-in;
+
+ // Make sure that after animation is done we remain at the last keyframe value (opacity: 1)
+ -webkit-animation-fill-mode: forwards;
+ -moz-animation-fill-mode: forwards;
+ -o-animation-fill-mode: forwards;
+ animation-fill-mode: forwards;
+}
+
+// Mixin for stateful foreground colors, e.g. text or icons
+.fg-stateful {
+ &.state-ok {
+ color: @color-ok;
+ }
+ &.state-up {
+ color: @color-up;
+ }
+ &.state-warning {
+ color: @color-warning;
+ &.handled {
+ color: @color-warning-handled;
+ }
+ }
+ &.state-critical {
+ color: @color-critical;
+ &.handled {
+ color: @color-critical-handled;
+ }
+ }
+ &.state-down {
+ color: @color-down;
+ &.handled {
+ color: @color-down-handled;
+ }
+ }
+ &.state-unreachable {
+ color: @color-unreachable;
+ &.handled {
+ color: @color-unreachable-handled;
+ }
+ }
+ &.state-unknown {
+ color: @color-unknown;
+ &.handled {
+ color: @color-unknown-handled;
+ }
+ }
+ &.state-pending {
+ color: @color-pending;
+ }
+}
+
+// Mixin for stateful background colors
+.bg-stateful {
+ &.state-ok {
+ background-color: @color-ok;
+ }
+ &.state-up {
+ background-color: @color-up;
+ }
+ &.state-warning {
+ background-color: @color-warning;
+ &.handled {
+ background-color: @color-warning-handled;
+ }
+ }
+ &.state-critical {
+ background-color: @color-critical;
+ &.handled {
+ background-color: @color-critical-handled;
+ }
+ }
+ &.state-down {
+ background-color: @color-down;
+ &.handled {
+ background-color: @color-down-handled;
+ }
+ }
+ &.state-unreachable {
+ background-color: @color-unreachable;
+ &.handled {
+ background-color: @color-unreachable-handled;
+ }
+ }
+ &.state-unknown {
+ background-color: @color-unknown;
+ &.handled {
+ background-color: @color-unknown-handled;
+ }
+ }
+ &.state-pending {
+ background-color: @color-pending;
+ }
+}
diff --git a/public/css/icinga/modal.less b/public/css/icinga/modal.less
new file mode 100644
index 0000000..3d497d6
--- /dev/null
+++ b/public/css/icinga/modal.less
@@ -0,0 +1,113 @@
+#layout > #modal {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ top: 0;
+
+ background-color: rgba(0, 0, 0, .6);
+ opacity: 0;
+ font-size: @font-size;
+ line-height: @line-height;
+ pointer-events: none;
+ transition: opacity .2s ease-in; // This is coupled with a `setTimout` in modal.js
+ z-index: 1000;
+
+ &.active {
+ opacity: 1;
+ pointer-events: auto;
+ }
+
+ > div {
+ height: 100%;
+ pointer-events: none;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+}
+
+#modal-content {
+ display: flex;
+ flex: 10;
+ flex-direction: column;
+ justify-content: stretch;
+
+ > .content {
+ padding: 1em;
+
+ > .icinga-form {
+ width: 100%;
+ }
+ }
+}
+
+#modal-ghost {
+ display: none;
+}
+
+.modal-area {
+ display: flex;
+ flex-direction: row;
+ flex-grow: 1;
+ justify-content: stretch;
+}
+
+.modal-header {
+ padding: .25em 0;
+ position: relative;
+ text-align: center;
+
+ > button {
+ position: absolute;
+ top: .75em;
+ right: 1em;
+
+ background-color: @gray;
+ border: none;
+ border-radius: 50%;
+ color: @text-color-inverted;
+ height: 1.5em;
+ line-height: 1em;
+ padding: 0;
+ text-align: center;
+ width: 1.5em;
+
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ appearance: none;
+ }
+
+ > button:hover {
+ opacity: .8;
+ }
+
+ > button > .icon-cancel:before {
+ margin-right: 0;
+ }
+}
+
+.modal-header h1 {
+ padding: .25em;
+ margin: 0;
+}
+
+.modal-window {
+ overflow: auto;
+ pointer-events: auto;
+
+ display: flex;
+ align-items: stretch;
+ flex-direction: column;
+
+ background-color: @body-bg-color;
+ border-radius: .5em;
+ box-shadow: 0 0 2em 0 rgba(0, 0, 0, .6);
+ flex: 1;
+ margin: 0 auto;
+ max-height: 80%;
+ min-height: 40vh;
+ max-width: 60em;
+}
diff --git a/public/css/icinga/nav.less b/public/css/icinga/nav.less
new file mode 100644
index 0000000..f7950f1
--- /dev/null
+++ b/public/css/icinga/nav.less
@@ -0,0 +1,50 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+.badge-nav-item {
+ > a {
+ .clearfix();
+
+ > .badge {
+ float: right;
+ }
+ }
+}
+
+.dropdown-nav-item > ul {
+ display: none;
+ position: absolute;
+}
+
+.dropdown-nav-item.active > ul,
+.dropdown-nav-item:hover > ul {
+ display: block;
+}
+
+.nav {
+ // Reset defaults
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+
+ li > a,
+ li > span {
+ // Rollover
+ display: block;
+ }
+}
+
+.nav .nav-item .icon:before {
+ width: 1.5em;
+}
+
+.tab-nav {
+ .clearfix();
+
+ > li {
+ float: left;
+ }
+}
+
+.primary-nav a {
+ font-weight: 500;
+}
diff --git a/public/css/icinga/php-diff.less b/public/css/icinga/php-diff.less
new file mode 100644
index 0000000..d8f6a80
--- /dev/null
+++ b/public/css/icinga/php-diff.less
@@ -0,0 +1,17 @@
+@diff-bg-color: transparent;
+@diff-text-color: @text-color;
+
+@diff-bg-color-ins-base: @color-up;
+@diff-bg-color-del-base: @color-down;
+@diff-bg-color-rep-base: @color-warning;
+
+@diff-border-color: @gray-light;
+
+@light-mode: {
+ :root {
+ --diff-bg-color: var(--body-bg-color);
+ --diff-text-color: var(--text-color);
+
+ --diff-border-color: var(--gray-light);
+ }
+};
diff --git a/public/css/icinga/print.less b/public/css/icinga/print.less
new file mode 100644
index 0000000..75d4728
--- /dev/null
+++ b/public/css/icinga/print.less
@@ -0,0 +1,39 @@
+/*! Icinga Web 2 | (c) 2015 Icinga GmbH | GPLv2+ */
+
+@media print {
+ #sidebar,
+ #migrate-popup, // Icinga DB Web
+ .controls,
+ .footer, // ipl
+ .dontprint, // Compat only, use dont-print instead
+ .dont-print {
+ display: none !important;
+ }
+
+ #main > .container {
+ overflow: visible !important;
+
+ > .content {
+ overflow: visible !important;
+ }
+ }
+
+ :root {
+ --body-bg-color: #fff !important;
+ --text-color: #535353 !important;
+ --text-color-light: #7F7F7F !important;
+ --tr-active-color: #fff !important;
+ --tr-hover-color: #fff !important;
+
+ // ipl-web overrides
+ --default-bg: #fff !important;
+ --default-text-color: #535353 !important;
+ --default-text-color-inverted: #fff !important;
+ }
+}
+
+@media not print {
+ .print-only {
+ display: none !important;
+ }
+}
diff --git a/public/css/icinga/responsive.less b/public/css/icinga/responsive.less
new file mode 100644
index 0000000..6d1cae8
--- /dev/null
+++ b/public/css/icinga/responsive.less
@@ -0,0 +1,167 @@
+/*! Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+// Not growing larger than 3840px at 1em=16px right now
+@media screen and (min-width: 240em) {
+ #header {
+ min-width: 240em;
+ }
+
+ #main {
+ width: 227em;
+ }
+}
+
+// More than 100em, usually 1600px at 1em=16px
+@media screen and (min-width: 100em) {
+ html {
+ font-family: 'wide-layout';
+ }
+}
+
+// Up to 1152px at 1em=16px
+@media screen and (max-width:72em) {
+ html {
+ font-family: 'compact-layout';
+ }
+}
+
+// Up to 752px at 1em=16px
+@media screen and (max-width: 47em) {
+ html {
+ font-family: 'poor-layout';
+ }
+}
+
+// Up to 576px at 1em=16px, should fit 320px devices
+@media screen and (max-width: 36em) {
+ html {
+ font-family: 'minimal-layout';
+ }
+}
+
+#layout.compact-layout {
+ font-size: 0.875em;
+}
+
+#layout.poor-layout {
+ font-size: 0.875em;
+
+ #layout.twocols {
+ #col1 {
+ display: none;
+ }
+
+ #main > .container {
+ width: 100%;
+ }
+ }
+
+ .dashboard > div.container {
+ width: 100%;
+ }
+}
+
+#layout:not(.minimal-layout) {
+ #mobile-menu-toggle {
+ display: none;
+ }
+}
+
+#layout.minimal-layout {
+ #sidebar {
+ width: 100%;
+ overflow: auto;
+ }
+
+ #header-logo-container {
+ width: auto;
+ height: 4em;
+ padding: 0;
+ background: inherit;
+ }
+
+ #header-logo {
+ float: left;
+ width: 9em;
+ height: 3em;
+ margin: .5em 1em;
+ background-position: left center;
+ }
+
+ #mobile-menu-toggle {
+ float: right;
+ }
+
+ #sidebar:not(.expanded) #menu {
+ display: none;
+ }
+
+ #menu {
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+ }
+
+ #content-wrapper {
+ flex-direction: column;
+ }
+
+ #main {
+ flex: 1 1 auto;
+ height: 0;
+ }
+
+ ul > .selected > a:after,
+ ul > .nav-item.active:after {
+ display: none;
+ }
+
+ .dashboard > div.container {
+ width: 100%;
+ }
+}
+
+// Dashboard
+
+.dashboard > .container {
+ padding-right: 0;
+ width: 100%;
+}
+
+#layout:not(.twocols).default-layout .dashboard > .container:not(:only-child) {
+ padding-right: @gutter;
+ width: 50%;
+}
+
+#layout:not(.twocols).wide-layout .dashboard > .container:not(:only-child) {
+ padding-right: @gutter;
+ width: 33.33%;
+}
+
+// Columns
+
+#layout.twocols #col2 {
+ border-left: 1px solid @gray-lighter;
+}
+
+#layout.twocols.wide-layout #col2 {
+ flex-grow: 2;
+}
+
+// Safe areas for iPhone X
+
+#header, #sidebar, #footer {
+ padding-left: constant(safe-area-inset-left);
+}
+
+#main, #footer {
+ padding-right: constant(safe-area-inset-right);
+}
+
+#layout.twocols #col2 {
+ border-left: 1px solid @gray-lighter;
+
+ &:empty {
+ display: flex;
+ }
+}
diff --git a/public/css/icinga/setup.less b/public/css/icinga/setup.less
new file mode 100644
index 0000000..c848bc7
--- /dev/null
+++ b/public/css/icinga/setup.less
@@ -0,0 +1,479 @@
+/*! Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+#setup-content-wrapper {
+ height: 0;
+ display: flex;
+ flex: 1 1 auto;
+ flex-direction: column;
+
+ > .setup-content {
+ height: 0;
+ overflow: auto;
+ flex: 1 1 auto;
+ }
+}
+
+.setup-header {
+ width: 100%;
+ height: 5.5em;
+ background-color: @icinga-blue;
+ text-align: center;
+
+ img {
+ width: 7.5em;
+ margin: 1.5em;
+ float: left;
+ }
+
+ form[name='setup_restart_form'] button {
+ background: none;
+ border: none;
+ color: #ffffff;
+ cursor: pointer;
+ outline: none;
+ font-size: 1.4em;
+ margin-right: 0.6em;
+ -moz-transform: scale(1, -1);
+ -webkit-transform: scale(1, -1);
+ -o-transform: scale(1, -1);
+ -ms-transform: scale(1, -1);
+ transform: scale(1, -1);
+ }
+
+ .progress-bar {
+ overflow: hidden;
+ padding-top: 1em;
+
+ .step {
+ float: left;
+
+ h1 {
+ margin: 0;
+ color: white;
+ font-size: 0.9em;
+ text-align: center;
+ border-bottom: none;
+ }
+
+ table {
+ margin-top: 0.3em;
+
+ td {
+ padding: 0;
+
+ &.left, &.right {
+ width: 50%;
+ }
+ }
+ }
+
+ div {
+ background-color: lightgrey;
+
+ &.line {
+ height: 0.4em;
+
+ &.left {
+ margin-left: 0.1em;
+ margin-right: -0.1em;
+ border-top-left-radius: 0.5em;
+ border-bottom-left-radius: 0.5em;
+ }
+
+ &.right {
+ margin-left: -0.1em;
+ margin-right: 0.1em;
+ border-top-right-radius: 0.5em;
+ border-bottom-right-radius: 0.5em;
+ }
+ }
+
+ &.bubble {
+ width: 1.2em;
+ height: 1.2em;
+ border-radius: 1.2em;
+
+ // Make sure that such a bubble overlays lines
+ position: relative;
+ z-index: 1337;
+ }
+
+ &.active {
+ background-color: white;
+ }
+
+ &.complete {
+ background-color: @color-ok;
+ }
+
+ &.visited {
+ background-color: #eee;
+ }
+ }
+ }
+ }
+}
+
+.setup-content {
+ padding: 1.5em 10em 0 10em;
+
+ h1 {
+ font-weight: bold;
+ }
+
+ form {
+ h2 {
+ font-size: 2.0em;
+ }
+ }
+}
+
+.setup-content .control-group > :not([hidden]) {
+ display: inline-block;
+ margin-right: 1em;
+}
+
+.setup-content div.buttons {
+ margin-top: 1.5em; // Yes, -top and -bottom, keep it like that...
+ margin-bottom: 1.5em;
+
+ .double {
+ position: absolute;
+ left: -1337px;
+ }
+
+ .control-button,
+ input[type="submit"] {
+ .button();
+ }
+
+ .control-button[disabled] {
+ background: none;
+ cursor: default;
+ color: @control-disabled-color;
+ border: 1px solid @control-disabled-color;
+
+ &:hover {
+ color: @control-disabled-color;
+ background: none;
+ border: 1px solid @control-disabled-color;
+ }
+ }
+
+ button.finish, a.button-like.login {
+ min-width: 25em;
+ }
+
+ .spinner {
+ margin-left: 1em;
+ }
+}
+
+.setup-content div.buttons + ul.hints {
+ margin-top: -1.5em;
+ margin-bottom: 1.5em;
+}
+
+form#setup_requirements {
+ margin-top: 2em;
+ padding-top: 0.5em;
+ border-top: 1px solid #888;
+
+ div.buttons div.requirements-refresh {
+ width: 25%;
+ float: right;
+ text-align: center;
+
+ a.button-like {
+ padding: 0.1em 0.4em;
+ }
+ }
+}
+
+.setup-content ul.requirements {
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+
+ li {
+ margin-bottom: 1em;
+
+ & > ul {
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+ }
+
+ div {
+ float: left;
+ padding-top: 0.4em;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ }
+
+ div.title {
+ width: 25%;
+
+ h2 {
+ padding: 0;
+ margin: 0 1em 0 0;
+ border-bottom: 0;
+ }
+ }
+
+ div.description {
+ width: 50%;
+ border-left: 0.4em solid transparent;
+ border-right: 0.4em solid transparent;
+
+ ul {
+ margin: 0;
+ padding-left: 1em;
+ list-style-type: square;
+ }
+ }
+
+ div.state {
+ width: 25%;
+ color: white;
+ padding: 0.4em;
+
+ &.fulfilled {
+ background-color: @color-ok;
+ }
+
+ &.not-available {
+ color: black;
+ background-color: #e8ec70;
+ }
+
+ &.missing {
+ background-color: @color-critical;
+ }
+ }
+ }
+}
+
+#setup_ldap_discovery_confirm table {
+ margin: 1em 0;
+ border-collapse: separate;
+ border-spacing: 1em 0.2em;
+}
+
+#setup_admin_account {
+ div.instructions {
+ width: 30.2em;
+ display: inline-block;
+ }
+
+ div.radiobox {
+ vertical-align: top;
+ display: inline-block;
+ padding: 0.9em 0.2em 0;
+ }
+}
+
+.setup-content {
+ div.summary {
+ font-size: 90%;
+
+ div.page {
+ float: left;
+ width: 25em;
+ min-height: 25em;
+ padding: 0 1em 1em;
+ margin: 1em 1.5em 1.5em;
+ border: 1px dashed lightgrey;
+
+ h2 {
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+
+ div.topic {
+ margin-left: 2em;
+
+ h3 {
+ font-size: 1em;
+ }
+
+ ul {
+ list-style-type: circle;
+ }
+
+ table {
+ border-spacing: 0.5em;
+ border-collapse: separate;
+ font-size: 0.9em;
+ margin-left: 2em;
+ }
+ }
+ }
+ }
+
+ form.summary {
+ clear: left;
+ }
+}
+
+#setup-finish {
+ h2 {
+ padding: 0.5em;
+ border-bottom: 0;
+ font-variant: normal;
+ font-weight: bold;
+ color: white;
+
+ &.success {
+ background-color: @color-ok;
+ }
+
+ &.failure {
+ background-color: @color-critical;
+ }
+ }
+
+ pre.log-output {
+ width: 66%;
+ height: 25em;
+ max-height: none;
+ }
+
+ div.buttons {
+ margin-top: 0;
+ text-align: center;
+
+ a {
+ padding: 0.5em;
+ }
+ }
+}
+
+.welcome-page {
+ margin-top: 3em;
+ text-align: center;
+
+ h2 {
+ font-size: 2.0em;
+ margin-bottom: 2em;
+ }
+
+ div.info {
+ padding: 0 1em;
+ background-color: #eee;
+ border: 1px solid lightgrey;
+ }
+
+ p.restart-warning {
+ color: coral;
+ font-weight: bold;
+ }
+
+ form ul.errors {
+ display: block;
+
+ list-style-type: none;
+ color: red;
+ }
+
+ div.note {
+ padding: 1em 1em 0;
+ margin: 3em auto 0;
+ text-align: left;
+ font-size: 0.9em;
+ border: 1px solid;
+ border-color: @gray-light;
+
+ h3 {
+ padding: 0.2em;
+ margin: -1em -1em 1em;
+ text-align: center;
+ color: @text-color;
+ background-color: @gray-lightest;
+ border: 1px solid;
+ border-color: @gray-light;
+ }
+
+ img {
+ float: right;
+ }
+
+ p {
+ margin: 2em 0 1em 0;
+
+ &:first-child {
+ margin-top: 1em;
+ }
+ }
+
+ div.code {
+ margin: 0 2em;
+
+ span {
+ display: block;
+ font-family: monospace;
+ }
+ }
+ }
+}
+
+#setup_monitoring_welcome {
+ .welcome-page;
+ margin-top: 0;
+ padding: 1em;
+
+ h2 {
+ margin-top: 0;
+ }
+}
+
+#setup_modules {
+ div.module {
+ float: left;
+ width: 15em;
+ height: 15em;
+ margin: 1em;
+ padding: 0.3em;
+ border: 1px solid;
+ border-color: @gray-semilight;
+ background-color: @gray-lightest;
+
+ .header {
+ height: 2.5em;
+ display: flex;
+ justify-content: space-between;
+ }
+
+ h3 {
+ margin: 0;
+ border: none;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ label {
+ cursor: pointer;
+ }
+ }
+
+ label.description {
+ display: inline-block;
+ width: 14.4em;
+ height: 12em;
+ overflow: auto;
+ cursor: pointer;
+ font-weight: normal;
+ }
+
+ input[type=checkbox] {
+ height: 10em;
+ float: right;
+ margin: 0;
+ }
+ }
+
+ div.buttons {
+ padding-top: 1em;
+ clear: both;
+ }
+}
diff --git a/public/css/icinga/spinner.less b/public/css/icinga/spinner.less
new file mode 100644
index 0000000..c1cf93e
--- /dev/null
+++ b/public/css/icinga/spinner.less
@@ -0,0 +1,42 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+.refresh-container-control > i:before {
+ margin: 0;
+}
+
+a.spinner.active > i,
+button.spinner.active > i,
+i.spinner.active {
+ &:before {
+ .animate(spin 2s infinite linear);
+
+ // icon-spin6
+ content: '\e874';
+ }
+
+ &.fa:before {
+ // fa spinner
+ content: '\f110';
+ }
+}
+
+div.spinner {
+ display: inline-block;
+ vertical-align: middle;
+
+ i {
+ visibility: hidden;
+
+ &.active {
+ visibility: visible;
+
+ &:before {
+ .animate(spin 2s infinite linear);
+ }
+ }
+
+ &:before {
+ margin: 0; // Disables wobbling
+ }
+ }
+}
diff --git a/public/css/icinga/tabs.less b/public/css/icinga/tabs.less
new file mode 100644
index 0000000..8103735
--- /dev/null
+++ b/public/css/icinga/tabs.less
@@ -0,0 +1,105 @@
+/*! Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+// Styles for tab navigation of containers
+
+.tabs {
+ background-color: @menu-bg-color;
+ letter-spacing: -0.417em;
+}
+
+.tabs > li {
+ display: inline-block;
+ letter-spacing: normal;
+}
+
+.tabs a {
+ padding: 0 1em;
+ line-height: 2.5em;
+
+ &:focus {
+ outline-offset: -0.5em;
+ }
+}
+
+.tabs > li {
+ &:not(:last-child) {
+ margin-right: 0.5em;
+ }
+
+ > a {
+ color: @menu-color;
+
+ &:hover {
+ text-decoration: none;
+ background: @tab-hover-bg-color;
+ }
+ }
+
+ &.active > a,
+ > a:focus {
+ background-color: @body-bg-color;
+ color: @text-color;
+ }
+}
+
+.tabs > .dropdown-nav-item > a,
+.tabs > li > .close-container-control,
+.tabs > li > .refresh-container-control {
+ text-align: center;
+ width: 3em;
+}
+
+.tabs > .dropdown-nav-item:hover > a,
+.tabs > .dropdown-nav-item > a:focus,
+.tabs > li > .close-container-control:focus,
+.tabs > li > .close-container-control:hover,
+.tabs > li > .refresh-container-control:focus,
+.tabs > li > .refresh-container-control:hover {
+ background-color: @body-bg-color;
+ color: @text-color;
+ text-decoration: none;
+}
+
+.tabs > .dropdown-nav-item > ul {
+ .box-shadow();
+ .rounded-corners(0 0 0.3em 0.3em);
+
+ background-color: @body-bg-color;
+ border: 1px solid;
+ border-color: @gray-light;
+ border-top: none;
+ margin-left: -1px;
+ min-width: 14em;
+ z-index: 10;
+}
+
+.tabs > .dropdown-nav-item > ul > li:hover > a {
+ background-color: @gray-lighter;
+ text-decoration: none;
+}
+
+// Dropdown tabs after the fourth title should be right-aligned
+.tabs > li:nth-child(n+5).dropdown-nav-item > ul {
+ transform: translate(~"calc(-100% + 3em)"); // -full width + tab width
+ margin-left: 1px;
+}
+
+// TODO(el): Rename display-on-hover and move it to main.less
+.display-on-hover {
+ font-size: @font-size-small;
+ left: -999em;
+ position: relative;
+}
+
+.dropdown-nav-item > ul > li > a:focus > .display-on-hover,
+.dropdown-nav-item > ul > li:hover > a > .display-on-hover {
+ position: static;
+}
+
+.tabs > li > .close-container-control {
+ display: none;
+}
+
+#layout.twocols .tabs > li > .close-container-control {
+ display: block;
+}
diff --git a/public/css/icinga/widgets.less b/public/css/icinga/widgets.less
new file mode 100644
index 0000000..654e7d5
--- /dev/null
+++ b/public/css/icinga/widgets.less
@@ -0,0 +1,643 @@
+/*! Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+#announcements > ul {
+ background-color: @body-bg-color;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+
+ > li {
+ border-bottom: 1px solid @gray-lighter;
+ line-height: 1.5em;
+ padding: 0.5em 1em 0.5em 3em;
+
+ position: relative;
+
+ &:before {
+ color: @icinga-blue;
+ content: "\e811";
+ font-family: 'ifont';
+
+ position: absolute;
+ left: 1.25em;
+ }
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ a {
+ color: @icinga-blue;
+ }
+
+ .message {
+ display: inline-block;
+ vertical-align: middle;
+ padding-right: 1.5em;
+ font-size: 7/6em;
+ }
+
+ p {
+ margin-bottom: 0;
+ }
+ }
+}
+
+.acknowledge-announcement-control,
+.application-state-acknowledge-message-control {
+ background: none;
+ border: none;
+ display: block;
+ margin-top: -0.75em;
+
+ position: absolute;
+ right: .75em;
+ top: 50%;
+}
+
+.application-state-acknowledge-message-control .link-button {
+ color: #fff;
+
+ &:hover .icon-cancel {
+ color: @icinga-blue;
+ }
+}
+
+#application-state-summary > div {
+ background-color: @color-critical;
+ color: @text-color-on-icinga-blue;
+ line-height: 1.5em;
+ padding: 0.5em 1em 0.5em 3em;
+
+ position: relative;
+
+ &:before {
+ content: "\e84d";
+ font-family: 'ifont';
+
+ position: absolute;
+ text-align: center;
+ left: .4em;
+ padding: .5em;
+ width: 3em;
+ top: 0;
+ }
+
+ > section {
+ margin-left: .5em;
+ }
+
+ > form .icon-cancel:before {
+ color: @text-color-on-icinga-blue;
+ }
+}
+
+.dashboard-link {
+ .clearfix();
+ display: block;
+ max-width: 100%;
+ vertical-align: middle;
+ padding: 1em;
+ width: 36em;
+
+ &:hover {
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+
+ -webkit-box-shadow: 0 0 0.5em 0 rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 0 0.5em 0 rgba(0, 0, 0, 0.2);
+ box-shadow: 0 0 0.5em 0 rgba(0, 0, 0, 0.2);
+
+ background-color: @tr-hover-color;
+ text-decoration: none;
+ }
+}
+
+.dashboard.content > .container {
+ overflow-x: auto;
+}
+
+.link-meta {
+ display: table-cell;
+ vertical-align: middle;
+}
+
+.link-label {
+ font-weight: @font-weight-bold;
+}
+
+.link-description {
+ color: @text-color-light;
+}
+
+.link-icon {
+ display: table-cell;
+ padding-right: .5em;
+ vertical-align: middle;
+ text-align: center;
+
+ > i {
+ font-size: 3em;
+ opacity: 0.7;
+ line-height: 1.5;
+
+ &:before {
+ min-width: 1.25em;
+ }
+ }
+
+ > img {
+ width: 3em;
+ height: 3em;
+ margin-right: .6em;
+ }
+}
+
+table.historycolorgrid {
+ font-size: 1.5em;
+}
+
+table.historycolorgrid th {
+ width: 1em;
+ height: 1em;
+ margin: 0.5em;
+ font-size: 0.55em;
+ font-weight: bold;
+}
+
+table.historycolorgrid td {
+ width: 1em;
+ height: 1em;
+ margin: 1em;
+}
+
+table.historycolorgrid td:hover {
+ opacity: 0.5;
+}
+
+table.historycolorgrid td.weekday {
+ font-size: 0.55em;
+ font-weight: bold;
+ width: 2.5em;
+ opacity: 1.0;
+}
+
+table.historycolorgrid a, table.historycolorgrid span {
+ .rounded-corners(0.2em);
+ margin: 0;
+ text-decoration: none;
+ display: block;
+ width: 1.1em;
+ height: 1.1em;
+}
+
+table.historycolorgrid a:hover {
+ text-decoration: none;
+}
+
+table.multiselect tr[href] td {
+ user-select: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+}
+
+#main div.filter {
+ form.editor {
+ input[type=text], select {
+ width: 12em;
+ height: 2em;
+ line-height: 1;
+ }
+
+ ul.tree li.active {
+ background-color: @gray-lightest;
+ }
+
+ button {
+ padding: .5em;
+ border: none;
+ background: none;
+ color: @text-color;
+
+ &:hover, &:focus {
+ color: @icinga-blue;
+ }
+ }
+
+ .buttons {
+ margin-left: 25em;
+ padding: .25em 0;
+ }
+
+ .buttons input:not(:last-child) {
+ margin-right:.5em;
+ }
+ }
+}
+
+form.role-form {
+ &.icinga-form .control-label-group {
+ width: 20em;
+ }
+
+ .control-label-group em {
+ color: @text-color-light;
+ font-style: normal;
+ }
+
+ .control-label > * {
+ display: inline-block;
+ }
+
+ summary {
+ border-bottom: 1px solid @gray-light;
+ .user-select(none);
+ cursor: pointer;
+
+ font-weight: @font-weight-bold;
+ margin: 0.556em 0 0.333em;
+ font-size: 1.167em;
+
+ display: flex;
+ align-items: baseline;
+ .privilege-preview {
+ flex: 1 1 auto;
+ }
+
+ > :first-child {
+ display: inline-block;
+ width: 20em / 1.167em; // element label width / summary font-size
+ }
+
+ > :nth-last-child(1),
+ > :nth-last-child(2) {
+ font-size: .75em;
+ opacity: .6;
+ }
+
+ .privilege-preview .icon {
+ &.granted {
+ color: @color-granted;
+ }
+
+ &.refused {
+ color: @color-refused;
+ }
+
+ &.restricted {
+ color: @color-restricted;
+ }
+ }
+ }
+
+ .collapsible {
+ summary em {
+ font-size: .857em;
+ font-weight: normal;
+ color: @text-color-light;
+ }
+
+ h4 {
+ display: inline-block;
+ width: 20em;
+ margin-top: 1.5em;
+ padding-right: .5625em;
+ text-align: right;
+
+ & ~ i {
+ display: inline-block;
+ width: 2.625em;
+ margin-right: 1em;
+ text-align: center;
+
+ &.icon-ok {
+ color: @color-granted;
+ }
+
+ &.icon-cancel {
+ color: @color-refused;
+ }
+ }
+ }
+ }
+}
+
+ul.tree select:first-of-type { /* ?? */
+ margin-bottom: 0.3em;
+ margin-left: 2em;
+}
+
+ul.tree {
+ padding: 0;
+ margin: 0;
+ padding-top: .5em;
+}
+
+ul.tree ul {
+ padding-left: 1em;
+}
+
+ul.tree li {
+ margin: 0;
+ list-style-type: none;
+ position: relative;
+ padding: 0;
+}
+
+ul.tree li .handle {
+ background-image: url('../img/tree/tree-minus.gif');
+ background-repeat: no-repeat;
+ display: inline-block;
+ position: absolute;
+ width: 1.5em;
+ height: 2em;
+ left: 0em;
+ background-position: center center;
+ z-index: 1;
+ cursor: pointer;
+}
+
+ul.tree li.collapsed > .handle {
+ background-image: url('../img/tree/tree-plus.gif');
+}
+
+ul.tree li.collapsed > ul {
+ display: none;
+}
+
+ul.tree li::before, ul.tree li::after {
+ content: '';
+ position: absolute;
+ right: auto;
+ left: -0.2em;
+ border-color: @gray-light;
+ border-style: dotted;
+ border-width: 0;
+}
+
+/* This is the left vertical line */
+ul.tree li::before {
+ border-left-width: 1px;
+ top: -.5em;
+ width: 1em;
+ height: 2.5em;
+ bottom: 1em;
+}
+
+/* This is the horizontal dash in front of each item */
+ul.tree li::after {
+ border-top-width: 1px;
+ top: 1em;
+ width: 2em;
+ height: 1em;
+}
+
+/* Stop left vertical line at "mid-height" after last nodes (at each level) */
+ul.tree li:last-child::before {
+ height: 1.5em;
+}
+
+/* No border for the root element - there must be only ONE root */
+ul.tree > li::before, ul.tree > li::after {
+ display: none;
+}
+
+/* No connector before (each) root element */
+ul.tree > ul > li::before, ul.tree > ul > li::after {
+ border: 0;
+}
+
+ul.tree li a {
+ display: inline-block;
+ line-height: 2em;
+ padding: 0 .5em;
+ text-decoration: none;
+ color: @gray;
+ background-repeat: no-repeat;
+ background-position: 0.8em 0.4em;
+}
+
+ul.tree li a.error {
+ color: @color-critical-handled;
+}
+
+ul.tree li a:hover {
+ color: @text-color;
+ text-decoration: underline;
+}
+
+ul.tree li a.error:hover {
+ color: @color-critical;
+}
+
+/* charts should grow as much as possible but never beyond the current viewport's size */
+.svg-container-responsive {
+ padding: 1.5em;
+ height: 80vh;
+}
+
+.tipsy .tipsy-inner {
+ // overwrite tooltip max width, we need them to grow bigger
+ font-family: @font-family;
+ font-size: @font-size-small;
+ max-width: 300px;
+ text-align: left;
+ background-color: rgba(0,0,0,0.8);
+}
+
+.progress-label span {
+ font-size: 1.5em;
+ .animate(blink 1.4s infinite both);
+
+ &:nth-child(2) {
+ animation-delay: .2s;
+ }
+
+ &:nth-child(3) {
+ animation-delay: .4s;
+ }
+}
+
+.flyover:not(.flyover-expanded) .flyover-content {
+ display: none;
+}
+
+.flyover {
+ position: relative;
+
+ .flyover-content {
+ background-color: @body-bg-color;
+ border: 1px solid;
+ border-color: @gray-lighter;
+ box-shadow: 0 0 .5em 0 rgba(0, 0, 0, 0.2);
+ position: absolute;
+ padding: @vertical-padding @horizontal-padding;
+ .rounded-corners();
+ }
+
+ &.flyover-arrow-top .flyover-content:before {
+ background: @body-bg-color;
+ border-left: 1px solid @gray-lighter;
+ border-top: 1px solid @gray-lighter;
+ content: "";
+ height: 1em;
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+ width: 1em;
+
+ position: absolute;
+ left: 6px;
+ top: -7px;
+ }
+
+ &.flyover-right .flyover-content {
+ left: auto;
+ right: 0;
+ }
+
+ &.flyover-arrow-top.flyover-right .flyover-content:before {
+ left: auto;
+ right: 6px;
+ }
+}
+
+.slice-state-ok {
+ stroke: @color-ok;
+ background: @color-ok;
+}
+
+.slice-state-warning-handled {
+ stroke: @color-warning-handled;
+ background: @color-warning-handled;
+}
+
+.slice-state-warning {
+ stroke: @color-warning;
+ background: @color-unreachable-handled;
+}
+
+.slice-state-critical-handled {
+ stroke: @color-critical-handled;
+ background: @color-critical-handled;
+}
+
+.slice-state-critical {
+ stroke: @color-critical;
+ background: @color-critical;
+}
+
+.slice-state-unknown-handled {
+ stroke: @color-unknown-handled;
+ background: @color-unknown-handled;
+}
+
+.slice-state-unknown {
+ stroke: @color-unknown;
+ background: @color-unknown;
+}
+
+.slice-state-unreachable-handled {
+ stroke: @color-unreachable-handled;
+ background: @color-unreachable-handled;
+}
+
+.slice-state-unreachable {
+ stroke: @color-unreachable;
+ background: @color-unreachable;
+}
+
+.slice-state-pending {
+ stroke: @color-pending;
+ background: @color-pending;
+}
+
+.slice-state-not-checked {
+ stroke: @gray-light;
+ background: @gray-light;
+}
+
+.donut {
+ width: 22em;
+ height: 22em;
+ min-width: 11.5em;
+ display: table;
+}
+
+.donut-graph {
+ width: 22em;
+ height: 22em;
+}
+
+.donut-label {
+ font-weight: bold;
+ fill: @text-color;
+}
+
+.donut-label {
+ margin-top: -12.5em;
+ text-align: center;
+}
+
+.donut-label-big {
+ color: @gray-light;
+ .fg-stateful();
+ font-size: 6em;
+ line-height: 0;
+ text-anchor: middle;
+ &:hover {
+ text-decoration: none;
+ }
+}
+
+.donut-label-small {
+ fill: @text-color;
+ font-size: 1.2em;
+ text-anchor: middle;
+ -moz-transform: translateY(0.35em);
+ -ms-transform: translateY(0.35em);
+ -webkit-transform: translateY(0.35em);
+ transform: translateY(0.35em);
+}
+
+.donut-container {
+ float: left;
+
+ &:not(:last-of-type) {
+ margin-right: 10em;
+ }
+}
+
+.dashboard .donut-container .donut-legend {
+ margin-left: auto;
+}
+
+.donut-legend {
+ width: 50%;
+ padding: 0;
+ margin-left: 18em;
+ list-style-type: none;
+
+ li {
+ vertical-align: middle;
+
+ &:not(:last-child) {
+ margin-bottom: .5em;
+ }
+
+ .badge {
+ font-weight: bold;
+ margin-right: .5em;
+ vertical-align: initial;
+ }
+ }
+}
+
+html.no-js .progress-label {
+ display: none;
+}
diff --git a/public/css/modes/light.less b/public/css/modes/light.less
new file mode 100644
index 0000000..7044007
--- /dev/null
+++ b/public/css/modes/light.less
@@ -0,0 +1,4 @@
+/* Icinga Web 2 | (c) 2021 Icinga GmbH | GPLv2+ */
+
+@enable-color-preference: 999999px;
+@prefer-light-color-scheme: 0px;
diff --git a/public/css/modes/none.less b/public/css/modes/none.less
new file mode 100644
index 0000000..05c618c
--- /dev/null
+++ b/public/css/modes/none.less
@@ -0,0 +1,4 @@
+/* Icinga Web 2 | (c) 2021 Icinga GmbH | GPLv2+ */
+
+@enable-color-preference: 999999px;
+@prefer-light-color-scheme: 999999px;
diff --git a/public/css/modes/system.less b/public/css/modes/system.less
new file mode 100644
index 0000000..07bd06a
--- /dev/null
+++ b/public/css/modes/system.less
@@ -0,0 +1,4 @@
+/* Icinga Web 2 | (c) 2021 Icinga GmbH | GPLv2+ */
+
+@enable-color-preference: 0px;
+@prefer-light-color-scheme: 999999px;
diff --git a/public/css/pdf/pdfprint.less b/public/css/pdf/pdfprint.less
new file mode 100644
index 0000000..2c68d37
--- /dev/null
+++ b/public/css/pdf/pdfprint.less
@@ -0,0 +1,103 @@
+/*! Icinga Web 2 | (c) 2014 Icinga GmbH | GPLv2+ */
+
+// Ensure styling is light, exports use a white background
+
+@gray: #7F7F7F;
+@gray-semilight: #A9A9A9;
+@gray-light: #C9C9C9;
+@gray-lighter: #EEEEEE;
+@gray-lightest: #F7F7F7;
+@icinga-blue: #0095BF;
+@low-sat-blue: #dae3e6;
+@low-sat-blue-dark: #becbcf;
+@body-bg-color: #fff;
+@text-color: @black;
+@text-color-light: @gray;
+@tr-active-color: @body-bg-color;
+@tr-hover-color: @body-bg-color;
+
+// Page layout
+
+@page {
+ margin: 1cm;
+}
+
+body {
+ font-family: sans-serif;
+ margin: 0;
+ padding-top: 37px; // ~ logo height in the header
+}
+
+.content {
+ font-size: 9pt;
+}
+
+#header,
+#footer {
+ position: fixed;
+ left: 0;
+ right: 0;
+ color: #aaa;
+ font-size: 0.9em;
+}
+
+#header {
+ top: 0;
+ border-bottom: 0.1pt solid #aaa;
+
+ .title {
+ text-align: left;
+ }
+
+ img {
+ margin-bottom: 3px;
+ }
+}
+
+#footer {
+ bottom: 0;
+ padding-top: 2em;
+}
+
+.content table {
+ margin-bottom: 3em;
+}
+
+#header table,
+#footer table {
+ width: 100%;
+ border-collapse: collapse;
+ border: none;
+}
+
+#header td,
+#header th,
+#footer td,
+#footer th {
+ padding: 0;
+ width: 50%;
+}
+
+.page-number {
+ padding-top: 0.5em;
+ border-top: 0.1pt solid #aaa;
+ text-align: center;
+}
+
+.page-number:before {
+ content: "Page " counter(page);
+}
+
+hr {
+ page-break-after: always;
+ border: 0;
+}
+
+// General style
+.state-icons,
+.overview-performance-data,
+.controls,
+.dontprint, // Compat only, use dont-print instead
+.dont-print {
+ display: none !important;
+}
diff --git a/public/css/themes/Winter.less b/public/css/themes/Winter.less
new file mode 100644
index 0000000..547d109
--- /dev/null
+++ b/public/css/themes/Winter.less
@@ -0,0 +1,32 @@
+/*! Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+@icinga-blue: #2b95ff;
+@control-color: @icinga-blue;
+
+@menu-2ndlvl-highlight-bg-color: transparent;
+
+.letitsnow {
+ background-image: url('../img/winter/snow1.png'), url('../img/winter/snow2.png'), url('../img/winter/snow3.png');
+ animation: ~"snow" 10s linear infinite;
+}
+
+#header-logo {
+ background-image: url('../img/winter/logo_icinga_big_winter.png');
+}
+
+/* Snow, from http://codepen.io/NickyCDK/pen/AIonk */
+#login, #header-logo-container, #main > .container > .controls > .tabs {
+ .letitsnow()
+}
+
+@keyframes ~"snow" {
+ 0% {background-position: 0px 0px, 0px 0px, 0px 0px;}
+ 50% {background-position: 500px 500px, 100px 200px, -100px 150px;}
+ 100% {background-position: 500px 1000px, 200px 400px, -100px 300px;}
+}
+
+#menu ul.nav-level-1 > .nav-item {
+ &:focus, &:hover {
+ .letitsnow()
+ }
+}
diff --git a/public/css/themes/colorblind.less b/public/css/themes/colorblind.less
new file mode 100644
index 0000000..c6df585
--- /dev/null
+++ b/public/css/themes/colorblind.less
@@ -0,0 +1,29 @@
+/*! Icinga Web 2 | (c) 2019 Icinga Development Team | GPLv2+ */
+
+@color-ok: fade(#77E08E, 25%);
+@color-critical: #FE5566;
+@color-critical-handled: fade(@color-critical, 33%);
+@color-warning: #B0A029;
+@color-warning-handled: fade(@color-warning, 33%);
+@color-unknown: #7791E0;
+@color-unknown-handled: fade(@color-unknown, 50%);
+@color-unreachable: @color-unknown;
+@color-unreachable-handled: @color-unknown-handled;
+@color-pending: fade(#FFFFFF, 75%);
+
+/* Adapt font color to match handled / unhandled states */
+.badge,
+.state-badge {
+ font-weight: bold;
+ color: @text-color !important;
+
+ &.handled,
+ &.state-up,
+ &.state-ok {
+ color: fade(@text-color, 75%) !important;
+ }
+}
+
+.processinfo .process > div.backend-running {
+ color: @text-color;
+}
diff --git a/public/css/themes/high-contrast.less b/public/css/themes/high-contrast.less
new file mode 100644
index 0000000..b22ffd5
--- /dev/null
+++ b/public/css/themes/high-contrast.less
@@ -0,0 +1,250 @@
+/*! Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+@icinga-blue: #006D8C;
+
+// Gray colors
+@gray: #7F7F7F;
+@gray-semilight: #A9A9A9;
+@gray-light: #C9C9C9;
+@gray-lighter: #EEEEEE;
+@gray-lightest: #F7F7F7;
+@disabled-gray: #9a9a9a;
+
+// State colors
+@color-ok: #006400;
+@color-critical: #EE0000;
+@color-critical-handled: #EE0000;
+@color-warning: #8B5A00;
+@color-warning-handled: #8B5A00;
+@color-unknown: #800080;
+@color-unknown-handled: #800080;
+@color-unreachable: #800080;
+@color-unreachable-handled: #800080;
+@color-pending: #0000EE;
+
+// Icinga colors
+@low-sat-blue: #dae3e6;
+@low-sat-blue-dark: #c0cccd;
+
+// Background color for <body>
+@body-bg-color: @white;
+
+@text-color: #191919;
+@text-color-light: #555555;
+
+@menu-highlight-color: white;
+@menu-2ndlvl-color: white;
+@menu-2ndlvl-highlight-color: white;
+@menu-2ndlvl-active-hover-color: @text-color;
+
+#menu ul.nav-level-1 > .nav-item > a {
+ &:focus, &:hover {
+ text-decoration: underline;
+ }
+}
+
+#menu ul.nav-level-1 > .nav-item.active > a,
+#menu .nav-level-1 > .nav-item.active:not(.selected) > a:hover {
+ color: @text-color;
+ background-color: @white;
+}
+
+#menu .nav-level-2 > .nav-item.active {
+ background-color: @white;
+
+ a {
+ color: @text-color;
+ }
+
+ > a:focus, > a:hover {
+ opacity: 1;
+ }
+}
+
+#menu .nav-level-2 > .nav-item > a {
+ &:hover, &:focus {
+ text-decoration: underline;
+ }
+}
+
+#menu ul:not(.nav-level-2) > .selected > a {
+ color: @text-color;
+}
+
+#menu .active > a {
+ text-decoration: underline;
+}
+
+.badge:not(.handled),
+.state-badge:not(.handled) {
+ &.state-warning {
+ border: 1px solid @color-warning;
+ }
+
+ &.state-critical,
+ &.state-down {
+ border: 1px solid @color-critical;
+ }
+
+ &.state-unreachable {
+ border: 1px solid @color-unreachable;
+ }
+
+ &.state-unknown {
+ border: 1px solid @color-unknown;
+ }
+
+ &.state-ok,
+ &.state-up {
+ border: 1px solid @color-ok;
+ }
+}
+
+.badge.handled,
+.badge.state-ok,
+.state-badge.handled,
+.state-badge.state-ok {
+ background-color: @body-bg-color !important;
+ color: @text-color !important;
+
+ &.state-warning {
+ border: 1px solid @color-warning-handled;
+ }
+
+ &.state-critical,
+ &.state-down {
+ border: 1px solid @color-critical-handled;
+ }
+
+ &.state-unreachable {
+ border: 1px solid @color-unreachable-handled;
+ }
+
+ &.state-unknown {
+ border: 1px solid @color-unknown-handled;
+ }
+}
+
+.boxview a:focus {
+ color: @text-color;
+ text-decoration: underline;
+}
+
+.icinga-module.module-monitoring {
+ @timeline-notification-color: #1650CF;
+ @timeline-hard-state-color: #A24600;
+ @timeline-comment-color: #346964;
+ @timeline-ack-color: #855D18;
+ @timeline-downtime-start-color: #515151;
+ @timeline-downtime-end-color: #5e5e2f;
+
+ // Unfortunately it does not suffice to only override the timeline colors here, because our less compiler seems to
+ // have the related style block in module.less already evaluated
+
+ .timeline-notification {
+ background-color: @timeline-notification-color;
+
+ &.extrapolated {
+ background-color: lighten(@timeline-notification-color, 20%);
+ }
+ }
+
+ .timeline-hard-state {
+ background-color: @timeline-hard-state-color;
+
+ &.extrapolated {
+ background-color: lighten(@timeline-hard-state-color, 20%);
+ }
+ }
+
+ .timeline-comment {
+ background-color: @timeline-comment-color;
+
+ &.extrapolated {
+ background-color: lighten(@timeline-comment-color, 20%);
+ }
+ }
+
+ .timeline-ack {
+ background-color: @timeline-ack-color;
+
+ &.extrapolated {
+ background-color: lighten(@timeline-ack-color, 20%);
+ }
+ }
+
+ .timeline-downtime-start {
+ background-color: @timeline-downtime-start-color;
+
+ &.extrapolated {
+ background-color: lighten(@timeline-downtime-start-color, 20%);
+ }
+ }
+
+ .timeline-downtime-end {
+ background-color: @timeline-downtime-end-color;
+
+ &.extrapolated {
+ background-color: lighten(@timeline-downtime-end-color, 20%);
+ }
+ }
+}
+
+.icinga-controls {
+ input:not([type="checkbox"]):not([type="radio"]),
+ .toggle-switch .toggle-slider:before,
+ .toggle-switch > .toggle-slider,
+ select,
+ textarea {
+ border: 1px solid @icinga-blue;
+ }
+
+ input[type="checkbox"]:not(:checked) + .toggle-switch .toggle-slider:before {
+ height: 1.166666667em;
+ width: 1.166666667em;
+ margin: 1px;
+ }
+}
+
+.search-suggestions {
+ input:not([type="checkbox"]):not([type="radio"]),
+ .toggle-switch .toggle-slider:before,
+ .toggle-switch > .toggle-slider,
+ select,
+ textarea {
+ border: none;
+ }
+}
+
+.icinga-module.module-icingadb .list-item.overdue {
+ background: none;
+
+ header > *:not(time),
+ .caption {
+ opacity: 1;
+ }
+}
+
+.controls input.search,
+input.search {
+ background-image: url(../img/icons/search.png);
+}
+
+.search-bar,
+.button-link,
+.view-mode-switcher > label {
+ border: 1px solid @icinga-blue;
+}
+
+// compensate for 1px border
+.filter-input-area {
+ padding: 1/12em !important;
+}
+
+.view-mode-switcher > label {
+ padding: (10/16)*.25em (10/16)*.5em !important;
+
+ &:not(:first-of-type) {
+ border-left: none;
+ }
+}
diff --git a/public/css/vendor/normalize.css b/public/css/vendor/normalize.css
new file mode 100644
index 0000000..458eea1
--- /dev/null
+++ b/public/css/vendor/normalize.css
@@ -0,0 +1,427 @@
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}