*
{
box-sizing: border-box;
}
html
{
width: 100%;
height: 100%;
}
body
{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
color: var(--default-fg-color);
background-color: var(--body-bg-color);
font-family: var(--font-family);
}
hr
{
border: 0;
border-top: 1px solid var(--hr-color);
margin: 16px 0;
}
/* -- start common layout */
.section-title
{
color: var(--section-title-fg-color);
font-size: var(--font-base-size);
font-variant: small-caps;
padding: 20px 0 10px 0;
}
hr + .section-title,
.section-title:first-child
{
padding-top: 0px;
}
.section .t
{
color: var(--title-fg-color);
font-size: var(--font-base-size);
}
.section .s
{
color: var(--subtitle-fg-color);
font-size: calc(var(--font-base-size) - 4px);
padding-bottom: 4px;
}
.section .ts
{
font-size: calc(var(--font-base-size) - 4px);
}
.section a
{
font: inherit;
color: inherit;
text-decoration: none;
font-variant: proportional-nums;
}
.section a:hover
{
color: var(--section-link-fg-color);
}
.section-subtitle
{
color: var(--section-subtitle-fg-color);
font-size: calc(var(--font-base-size) - 4px);
}
.heading
{
color: var(--section-title-fg-color);
font-size: calc(var(--font-base-size) - 2px);
padding-bottom: 6px;
}
.cols
{
display: flex;
flex-wrap: wrap;
}
.cols > div
{
flex: 1
}
.ctrl
{
padding: 5px;
border-radius: 10px;
border: 1px solid transparent;
}
.ctrl:last-child,
.noctrl:last-child
{
flex: 1;
}
.noctrl
{
padding: 5px;
border: 1px solid transparent;
}
body.authenticated .ctrl:hover
{
padding: 10px;
margin: -5px;
background-color: var(--ctrl-bg-color-hover);
}
/* -- end common layout */
/* -- start overall layout -- */
#all
{
display: flex;
min-width: 100%;
height: 100%;
flex-direction: column;
background-color: var(--body-bg-color);
}
#nav
{
position: absolute;
display: flex;
width: 100%;
min-height: 64px;
max-height: 64px;
background-color: var(--nav-bg-color);
}
#panel
{
display: flex;
flex: 1;
height: 100%;
padding-top: 64px;
background-color: var(--nav-bg-color);
}
#select
{
display: flex;
min-width: 64px;
flex-direction: column;
background-color: var(--nav-bg-color);
}
#main
{
flex: 1;
height: 100%;
padding: 10px;
background-color: var(--body-bg-color);
overflow-y: scroll;
overscroll-behavior: contain;
border-top-left-radius: 20px;
}
#main-container
{
display: flex;
flex: 1;
}
#c1
{
display: flex;
flex-direction: column;
min-width: 330px;
width: 330px;
}
#general
{
display: flex;
flex-direction: column;
padding: 10px 5px;
}
#location
{
}
#c2
{
display: flex;
flex-direction: column;
flex: 5;
padding: 20px 15px 0 15px;
min-width: 420px;
}
#services
{
display: flex;
flex-direction: column;
}
#local-and-neighbor-devices
{
container-type: inline-size;
}
#c3
{
display: flex;
flex-direction: column;
flex: 4;
padding: 20px 0 0 5px;
container-type: inline-size;
}
#radio-and-antenna
{
display: flex;
flex-direction: column;
}
#mesh-summary
{
}
#tunnels
{
display: flex;
flex-direction: column;
}
#dhcp
{
display: flex;
flex-direction: column;
}
@container (width < 400px)
{
#dhcp .t
{
font-size: 12px;
}
#dhcp .ts
{
font-size: 10px;
}
}
/* -- end overall layout -- */
/* -- start nav layout -- */
.nav-node-name
{
color: var(--title-fg-color);
font-size: 24px;
font-weight: bold;
margin: auto 0 auto 20px;
}
#nav-status
{
color: var(--subtitle-fg-color);
font-size: calc(var(--font-base-size) - 4px);
padding: 8px 0 0 8px;
margin: auto 0;
}
/* -- end nav layout -- */
/* -- start general layout -- */
#general .radio-image
{
display: flex;
align-items: center;
justify-content: center;
height: 150px;
margin-bottom: 20px;
}
#general .t
{
font-size: var(--font-base-size);
color: var(--title-fg-color);
}
#general .s
{
color: var(--subtitle-fg-color);
font-size: calc(var(--font-base-size) - 4px);
padding-bottom: 6px;
}
#general .ts
{
font-size: calc(var(--font-base-size) - 4px);
}
.node-description
{
padding-bottom: 4px;
}
.node-description .t
{
font-size: var(--font-base-size);
}
#general .firmware
{
font-size: calc(var(--font-base-size) - 4px);
}
#general .firmware .s
{
padding-top: 2px;
}
#general .firmware .s a
{
color: inherit;
text-decoration: none;
}
#general .firmware .s a:hover
{
text-decoration: underline;
}
#general .firmware-status
{
position: relative;
top: -2px;
display: inline-block;
margin-left: 4px;
font-size: calc(var(--font-base-size) - 6px);
padding: 2px 5px;
border-radius: 5px;
color: var(--firmware-status-fg-color);
}
#general .firmware-status.uptodate
{
background-color: var(--firmware-status-bg-color-positive);
}
#general .firmware-status.uptodate::after
{
content: "Up to date";
}
#general .firmware-status.needupdate
{
background-color: var(--firmware-status-bg-color-negative);
}
#general .firmware-status.needupdate::after
{
content: "Update available";
}
#general .firmware-status.custom
{
background-color: var(--firmware-status-bg-color-other);
}
#general .firmware-status.custom::after
{
content: "Custom";
}
#health
{
padding: 20px 0;
font-size: calc(var(--font-base-size) - 2px);
}
/* -- end general layout -- */
/* -- start location layout -- */
#location .t
{
color: var(--title-fg-color);
font-size: var(--font-base-size);
}
#location .s
{
color: var(--subtitle-fg-color);
font-size: calc(var(--font-base-size) - 4px);
}
#location .location-image
{
pointer-events: none;
width: 300px;
height: 150px;
margin: 0 0 15px 10px;
}
#location .location-image iframe
{
border: 1px solid var(--hr-color);
filter: var(--map-filter);
}
/* -- end location layout -- */
/* -- start local and neighborhood devices layout -- */
@container (width < 450px)
{
#local-and-neighbor-devices .section
{
font-size: 12px;
}
#local-and-neighbor-devices .ts
{
font-size: 10px;
}
}
#local-and-neighbor-devices .stats
{
text-align: right;
min-width: 260px;
}
#local-and-neighbor-devices .status
{
padding: 2.5px 5px;
margin: -5px -5px;
}
body.authenticated #local-and-neighbor-devices .status.ctrl:hover
{
padding: 7.5px 10px;
margin: -10px -10px;
}
#local-and-neighbor-devices .excellent
{
color: var(--conn-fg-color-excellent);
}
#local-and-neighbor-devices .good
{
color: var(--conn-fg-color-good);
}
#local-and-neighbor-devices .okay
{
color: var(--conn-fg-color-okay);
}
#local-and-neighbor-devices .poor
{
color: var(--conn-fg-color-poor);
}
#local-and-neighbor-devices .bad
{
color: var(--conn-fg-color-bad);
}
#local-and-neighbor-devices .blocked
{
color: var(--conn-fg-color-idle);
text-decoration: line-through;
}
#local-and-neighbor-devices .idle
{
color: var(--conn-fg-color-idle);
}
#local-and-neighbor-devices .icon
{
display: inline-block;
width: 12px;
height: 12px;
margin-left: 4px;
background-position: center center;
background-repeat: no-repeat;
filter: var(--icon-filter);
}
/* -- end local and neighborhood devices layout -- */
/* -- start services layout -- */
#services .service,
#services .device
{
font-size: calc(var(--font-base-size) - 3px);
padding: 2px 0;
flex-basis: 50%;
}
#services .service .status
{
display: inline-block;
width: calc(var(--font-base-size) * 3 + 4px);
padding: 2px 0;
border-radius: 5px;
margin-right: 5px;
text-align: center;
font-size: calc(var(--font-base-size) - 6px);
color: var(--service-fg-color-status);
background-color: var(--service-bg-color-status-inactive);
}
#services .service .icon
{
position: relative;
display: inline-block;
top: 3px;
width: 14px;
height: 14px;
filter: var(--icon-filter);
}
#services .service .status.inactive
{
background-color: var(--service-bg-color-status-inactive);
}
#services .service .status.active
{
background-color: var(--service-bg-color-status-active);
}
#services .service .status.disabled
{
background-color: var(--service-bg-color-status-disabled);
}
#services .service .status.inactive::after
{
content: "inactive";
}
#services .service .status.active::after
{
content: "active";
}
#services .service .status.disabled::after
{
content: "disabled";
}
/* -- end services layout -- */
/* -- start icon layout -- */
#nav a
{
position: relative;
text-decoration: none;
}
#icon-logo
{
display: table-cell;
width: 64px;
height: 64px;
background: url("data:image/svg+xml,") center center no-repeat;
text-align: center;
vertical-align: bottom;
}
#icon-logo + div
{
position: absolute;
display: inline-block;
bottom: 0;
left: 8px;
font-family: inherit;
font-size: 13px;
font-weight: bold;
color: var(--logo-fg-color);
background-color: var(--nav-bg-color);
}
#icon-logo.animate
{
animation-name: logo-rotate;
animation-duration: 1s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
@keyframes logo-rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
#select .icon,
#select .icon:hover:active,
#login-icon .icon,
#logout-icon .icon
{
width: 32px;
height: 32px;
margin: 16px;
filter: var(--nav-icon-filter);
background-position: center center;
background-repeat: no-repeat;
}
#select .icon:hover,
#select .icon.true,
#login-icon:hover .icon,
#logout-icon:hover .icon
{
filter: var(--nav-icon-filter-select);
}
#nav:has(#changes:not(:empty)) #logout-icon .menu div:last-child
{
display: none;
}
/* -- end icon layout -- */
/* login start */
#login-icon,
#logout-icon
{
position: relative;
}
#login-icon .icon,
#logout-icon .icon
{
position: absolute;
top: 0;
pointer-events: none;
}
#login-icon label,
#logout-icon label
{
position: absolute;
top: 0;
right: 0;
}
#login-icon input,
#logout-icon input
{
width: 64px;
height: 64px;
opacity: 0;
}
#login-icon .menu,
#logout-icon .menu
{
display: none;
position: absolute;
top: 64px;
right: 0;
padding: 0 0 5px 5px;
text-align: right;
font-size: calc(var(--font-base-size) - 2px);
background-color: var(--nav-bg-color);
border-bottom-left-radius: 10px;
border-top: 1px solid var(--ctrl-modal-bg-tertiary-color);
z-index: 1;
}
#login-icon .menu > div,
#logout-icon .menu > div
{
padding: 12px 20px;
color: var(--title-fg-color);
cursor: pointer;
}
#login-icon:has(input:checked) .menu,
#logout-icon:has(input:checked) .menu
{
display: block;
}
#login-icon .menu > div:hover,
#logout-icon .menu > div:hover
{
color: var(--menu-fg-select-color);
}
#login-icon .menu a,
#logout-icon .menu a
{
color: inherit;
}
#login
{
font: inherit;
font-size: 16px;
padding: 50px;
color: var(--ctrl-modal-fg-color);
border-radius: 20px;
background-color: var(--ctrl-modal-bg-tertiary-color);
}
#login input {
color: inherit;
background-color: var(--ctrl-modal-textbox-bg-color);
margin: 0 10px;
outline: none;
}
#login button {
font: inherit;
font-size: 12px;
color: inherit;
background-color: var(--ctrl-modal-textbox-bg-color);
}
#login::backdrop
{
background-color: var(--ctrl-modal-backdrop-color);
}
/* login end */
/* messages start */
#messages
{
position: relative;
background-color: var(--message-bg-color);
padding: 10px;
border-radius: 10px;
z-index: 1;
}
#messages .section-title
{
color: var(--message-fg-color);
}
#messages .section > div
{
color: var(--message-fg-color);
padding: 0 0 4px 2px;
}
/* messages end */
/* tools start */
#tools
{
display: none;
}
/* tools end */
/* meshpage start */
#meshfilter
{
padding-top: 30px;
display: flex;
}
#meshfilter input
{
width: 300px;
outline: none;
font: inherit;
padding: 5px;
color: var(--ctrl-modal-fg-color);
background-color: var(--ctrl-modal-textbox-bg-color);
border: 1px solid var(--ctrl-modal-textbox-border-color);
}
#meshfilter button
{
padding: 5px 10px;
border: 1px solid var(--ctrl-modal-textbox-border-color);
background-color: transparent;
font: inherit;
color: var(--ctrl-modal-textbox-border-color);
}
#meshfilter button:hover
{
background-color: var(--meshpage-node-bg-color-hover);
}
#meshpage
{
padding: 40px 60px;
font-size: calc(var(--font-base-size) - 2px);
}
#meshpage .block
{
position: relative;
display: flex;
flex-flow: wrap;
padding: 40px 20px 30px 20px;
border-radius: 10px;
margin-bottom: 10px;
border-width: 2px;
border-style: solid;
}
#meshpage .block:empty
{
display: none;
}
#meshpage .block .label
{
position: absolute;
top: -1px;
left: -1px;
padding: 4px 10px;
font-size: calc(var(--font-base-size) - 2px);
text-transform: uppercase;
color: var(--body-bg-color);
border-top-left-radius: 10px;
border-bottom-right-radius: 10px;
}
#meshpage .node
{
width: 50%;
padding: 2px 20px;
border-radius: 10px;
}
#meshpage .node:hover
{
background-color: var(--meshpage-node-bg-color-hover);
}
#meshpage .node .etx
{
font-size: 10px;
color: var(--meshpage-etx-fg-color);
padding-left: 6px;
}
#meshpage .lanhosts
{
font-size: calc(var(--font-base-size) - 3px);
padding: 4px 0 6px 0;
}
#meshpage .host,
#meshpage .lanhost
{
display: flex;
}
#meshpage .host .name,
#meshpage .lanhost .name
{
flex: 1;
}
#meshpage .host .name a
{
text-decoration: none;
color: var(--meshpage-hostname-fg-color);
}
#meshpage .host .name a:hover
{
text-decoration: underline;
}
#meshpage .services
{
flex: 1;
font-size: calc(var(--font-base-size) - 3px);
}
#meshpage .service
{
white-space: nowrap;
}
#meshpage .service a,
#meshpage .service span
{
text-decoration: none;
color: inherit;
white-space: normal;
}
#meshpage .service a:hover
{
text-decoration: underline;
color: var(--meshpage-service-hover-fg-color);
}
#meshpage .service div
{
position: relative;
display: inline-block;
top: 2.5px;
width: 14px;
height: 14px;
margin: 0;
background: url('data:image/svg+xml;utf8,') center center no-repeat;
filter: var(--icon-filter);
}
.meshpage-help
{
display: none;
padding: 40px 120px 0 120px;
}
.meshpage-help.visible
{
display: block;
color: var(--ctrl-modal-fg-help-color);
font-size: calc(var(--font-base-size) - 4px);
}
.block1
{
border-color: var(--meshpage-block1-border-color);
}
.block2
{
border-color: var(--meshpage-block2-border-color);
}
.block3
{
border-color: var(--meshpage-block3-border-color);
}
.block5
{
border-color: var(--meshpage-block5-border-color);
}
.block10
{
border-color: var(--meshpage-block10-border-color);
}
.block1000
{
border-color: var(--meshpage-block1000-border-color);
}
.block1 .label
{
background-color: var(--meshpage-block1-border-color);
}
.block2 .label
{
background-color: var(--meshpage-block2-border-color);
}
.block3 .label
{
background-color: var(--meshpage-block3-border-color);
}
.block5 .label
{
background-color: var(--meshpage-block5-border-color);
}
.block10 .label
{
background-color: var(--meshpage-block10-border-color);
}
.block1000 .label
{
background-color: var(--meshpage-block1000-border-color);
}
#meshpage.filtering .service,
#meshpage.filtering .lanhost,
#meshpage.filtering .node,
#meshpage.filtering .block
{
display: none;
}
#meshpage.filtering .service.valid,
#meshpage.filtering .node:has(.service.valid),
#meshpage.filtering .node:has(.lanhost.valid),
#meshpage.filtering .node:has(.host.valid)
{
display: block;
}
#meshpage.filtering .lanhost:has(.service.valid),
#meshpage.filtering .lanhost.valid,
#meshpage.filtering .block:has(.service.valid),
#meshpage.filtering .block:has(.lanhost.valid),
#meshpage.filtering .block:has(.host.valid)
{
display: flex;
}
/* meshpage end
/* start icons */
.icon.status
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.mesh
{
background-image: url("data:image/svg+xml;utf8,") !important;
}
.icon.cloudmesh
{
background-image: url("data:image/svg+xml;utf8,") !important;
}
.icon.tools
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.login
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.login.authenticated
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.map
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.camera
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.phone
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.time
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.winlink,
.icon.mail
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.local
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.server
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.router,
.icon.switch
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.radio
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.video
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.chat
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.solar
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.battery
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.power
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.wiki
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.refresh
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.cloud
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.cloudup
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.clipboard
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.wifi
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.download
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.twoarrow
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.tool
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.signal
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.plane
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.bolt
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.updownarrow
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.globe
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.eye
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.warning
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.weather
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
.icon.plus
{
background-image: url('data:image/svg+xml;utf8,') !important;
}
/* end icons */