From 88646cb47166af72022f4486772c16c3b39fc567 Mon Sep 17 00:00:00 2001 From: Roy Hagland Date: Tue, 24 Feb 2026 14:45:56 +0100 Subject: [PATCH 1/3] Fix responssive layout and enable mobile layout --- DnsServerCore/www/css/main.css | 1968 ++++++++--- DnsServerCore/www/index.html | 5822 ++++++++++++++++++++++++-------- 2 files changed, 5902 insertions(+), 1888 deletions(-) diff --git a/DnsServerCore/www/css/main.css b/DnsServerCore/www/css/main.css index 51a6b98a..7036fc3b 100644 --- a/DnsServerCore/www/css/main.css +++ b/DnsServerCore/www/css/main.css @@ -1,75 +1,182 @@ -html, body { - height: 100% !important; - scrollbar-gutter: stable; +/* ============================================================ + ROOT VARIABLES — single source of truth for both themes + ============================================================ */ +:root { + --accent: #5b8dee; + --accent-dark: #3f6fd4; + --accent-text: #ffffff; + --bg-page: #f0f2f7; + --bg-surface: #ffffff; + --bg-surface-alt: #f7f9fc; + --bg-header: #5b8dee; + --bg-footer: #f0f2f7; + --border: #dde3ef; + --text-primary: #1c2338; + --text-secondary: #5a6480; + --text-muted: #8892aa; + --shadow-sm: 0 1px 4px rgba(0, 0, 0, .08); + --shadow-md: 0 3px 12px rgba(0, 0, 0, .10); + --shadow-lg: 0 6px 24px rgba(0, 0, 0, .12); + --radius: 8px; + --transition: 0.18s ease; } - body.modal-open { - padding-right: 0 !important; - } +html.dark-mode, +body.dark-mode { + color-scheme: dark; + --accent: #5b8dee; + --accent-dark: #3f6fd4; + --bg-page: #12141a; + --bg-surface: #1e2130; + --bg-surface-alt: #171a27; + --bg-header: #1a1d2e; + --bg-footer: #1a1d2e; + --border: #2d3348; + --text-primary: #e8ecf4; + --text-secondary: #9aa3bc; + --text-muted: #5e6785; + --shadow-sm: 0 1px 4px rgba(0, 0, 0, .3); + --shadow-md: 0 3px 12px rgba(0, 0, 0, .4); + --shadow-lg: 0 6px 24px rgba(0, 0, 0, .5); +} + +html.dark-mode, +html.dark-mode body { + background-color: var(--bg-page) !important; + color: var(--text-primary) !important; +} +/* ============================================================ + RESET / BASE + ============================================================ */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, body { - margin: 0px !important; - line-height: 1.42857143 !important; + height: 100%; + scrollbar-gutter: stable; + overflow-x: hidden; } -a { - color: #6699ff; +body { + margin: 0 !important; + line-height: 1.5 !important; + font-family: 'Segoe UI', 'Helvetica Neue', Arial, sans-serif; + background-color: var(--bg-page); + color: var(--text-primary); + transition: background-color var(--transition), color var(--transition); } - a:hover { - color: #6699ff; - } +body.modal-open { + padding-right: 0 !important; +} - a:visited { - color: #6699ff; - } +a { + color: var(--accent); +} + +a:hover, +a:visited { + color: var(--accent); +} th a { - color: black !important; + color: var(--text-primary) !important; } - th a:hover { - color: black; - text-decoration: none; - } +th a:hover { + color: var(--text-primary); + text-decoration: none; +} +/* ============================================================ + HEADER + ============================================================ */ #header { - background-color: #6699ff; - height: 32px; - margin-bottom: -32px; - box-shadow: 0px 1px 15px 0px #888888; + background-color: var(--bg-header); + height: 56px; + box-shadow: var(--shadow-md); width: 100%; - min-width: 970px; + position: fixed; + top: 0; + left: 0; + z-index: 1000; + transition: background-color var(--transition); } - #header .title { - margin: 0 auto; - color: #ffffff; - padding: 0px 15px 0px 15px; - } +#header .title { + margin: 0 auto; + color: var(--accent-text); + padding: 0 16px; + line-height: 56px; + padding-right: 220px; +} - #header .title img { - vertical-align: text-bottom; - } +#header .title img { + height: 36px; + width: auto; + vertical-align: middle; +} - #header .title .text { - font-size: 24px; - font-weight: 600; - font-family: Arial; - margin-left: 4px; - } +@keyframes shimmer { + 0% { + background-position: -200% center; + } - #header .menu { - float: right; - padding: 6px; + 100% { + background-position: 200% center; } +} - #header .menu .menu-title { - color: #ffffff; - font-family: Arial; - font-size: 16px; - } +#header .title .text { + font-size: 36px; + font-weight: 700; + letter-spacing: -0.5px; + margin-left: 8px; + vertical-align: middle; + line-height: 1; + background: linear-gradient(90deg, + #a0b4e8 0%, + #ffffff 40%, + #a0b4e8 60%, + #ffffff 80%, + #a0b4e8 100%); + background-size: 200% auto; + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + animation: shimmer 5s linear infinite; +} + +#header .menu { + position: absolute; + top: 0; + right: 16px; + height: 56px; + display: flex; + align-items: center; +} + +#header .menu .menu-title { + color: var(--accent-text); + font-size: 14px; + opacity: 0.9; + display: flex; + align-items: center; + gap: 4px; +} + +#header .menu .menu-title:hover { + opacity: 1; +} +/* ============================================================ + CONTENT WRAPPER + ============================================================ */ #content { min-height: 100%; } @@ -77,512 +184,1575 @@ th a { .container { margin-left: auto; margin-right: auto; - padding: 55px 15px 60px 15px; + padding: 76px 16px 72px; word-wrap: break-word; - min-width: 970px; } - .container .pageLogin { - display: none; - margin: auto; - width: 500px; - padding: 150px 0 0 0; - } - - .container .page { - display: none; - } - -.auto-resize-img { - max-width: 100%; - height: auto; - display: block; - margin-right: auto; - margin-left: auto; +.container .pageLogin { + display: none; + margin: auto; + width: 100%; + max-width: 460px; + padding: 100px 0 0; } -.center-iframe { - display: block; - margin-right: auto; - margin-left: auto; - max-width: 640px; - max-height: 480px; +.container .page { + display: none; } - .center-iframe iframe { - width: 100%; - height: 100%; - } - +/* ============================================================ + FOOTER + ============================================================ */ #footer { - background-color: rgb(243, 243, 243); - padding: 20px 0px 20px 0px; + background-color: var(--bg-footer); + padding: 18px 0; margin-top: -55px; - box-shadow: 0px 2px 15px 1px #888888; + box-shadow: 0 -1px 0 var(--border); clear: both; position: relative; height: 55px; - min-width: 970px; + transition: background-color var(--transition); + z-index: 0; } - #footer .content { - margin: 0 auto; - color: rgb(119,119,119); - font-family: Arial, sans-serif; - font-size: 11px; - font-weight: 600; - text-align: center; - } +#footer .content { + margin: 0 auto; + color: var(--text-muted); + font-size: 12px; + font-weight: 500; + text-align: center; +} + +#footer .content a { + color: var(--accent); + text-decoration: none; +} - #footer .content a { - color: #6699ff; - text-decoration: none; - } +#footer .content a:hover { + color: var(--accent-dark); +} - #footer .content a:hover { - color: #6699ff; - } +/* ============================================================ + RESPONSIVE CONTAINER WIDTHS + ============================================================ */ +@media (min-width: 768px) { + .container { + padding-left: 20px; + padding-right: 20px; + } +} @media (min-width: 992px) { - #header .title, .container, #footer .content { - width: 970px; + + #header .title, + .container, + #footer .content { + width: 960px; } } @media (min-width: 1200px) { - #header .title, .container, #footer .content { - width: 1170px; + + #header .title, + .container, + #footer .content { + width: 1160px; } } -.form-inline .form-group { - margin-right: 10px; - margin-bottom: 10px; -} +@media (min-width: 1400px) { -.AlertPlaceholder { - position: fixed; - width: 800px; - margin: auto; - left: 0; - right: 0; - top: 45px; - z-index: 1000; + #header .title, + .container, + #footer .content { + width: 1340px; + } } -.zone-list-pane { - float: left; - width: 24%; -} +@media (min-width: 1600px) { -.zones { - font-size: 14px; + #header .title, + .container, + #footer .content { + width: 1540px; + } } - .zones .zone { - padding: 4px; +@media (min-width: 1920px) { + + #header .title, + .container, + #footer .content { + width: 1820px; } +} -.zone-viewer-pane { - float: right; - width: 75%; - display: none; +/* ============================================================ + PANELS (Bootstrap overrides) + ============================================================ */ +.panel { + border-radius: var(--radius) !important; + border-color: var(--border) !important; + background-color: var(--bg-surface) !important; + box-shadow: var(--shadow-sm) !important; + transition: background-color var(--transition), border-color var(--transition); + overflow: hidden !important; } -.log-list-pane { - float: left; - width: 17%; +.panel.has-dropdown, +.panel:has(.dropdown-menu) { + overflow: visible !important; } -.logs { - font-size: 12px; +.panel-heading { + border-radius: var(--radius) var(--radius) 0 0 !important; + background-color: var(--bg-surface-alt) !important; + border-bottom-color: var(--border) !important; + color: var(--text-primary) !important; + padding: 10px 16px !important; + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + overflow: visible !important; } - .logs .log { - padding: 2px; - } +.panel-heading .pull-left, +.panel-heading .pull-right { + float: none !important; +} -.log-viewer-pane { - float: right; - width: 82%; - display: none; +.panel-heading .clearfix { + display: none !important; } -.query-logs tr:hover { - backdrop-filter: brightness(95%); +.panel-heading .panel-title { + margin: 0; + font-size: 14px; + font-weight: 600; } -.stats-panel { - height: 80px; - padding: 6px 0 6px 0; +.panel-body { + background-color: var(--bg-surface) !important; + color: var(--text-primary) !important; + overflow: visible !important; + border-radius: 0 0 var(--radius) var(--radius) !important; } - .stats-panel .total-queries { - background-color: rgba(102, 153, 255, 0.7); - color: #ffffff; - } +/* ============================================================ + TABS + ============================================================ */ +.nav-tabs { + border-bottom: 2px solid var(--accent) !important; + display: flex; + flex-wrap: nowrap; + overflow-x: auto; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + scrollbar-width: thin; + scrollbar-color: var(--border) transparent; +} - .stats-panel .no-error { - background-color: rgba(92, 184, 92, 0.7); - color: #ffffff; - } +.nav-tabs>li.pull-right { + float: none !important; + margin-left: auto !important; +} - .stats-panel .server-failure { - background-color: rgba(217, 83, 79, 0.7); - color: #ffffff; - } +.tab-content .nav-tabs { + z-index: 97; +} - .stats-panel .nxdomain { - background-color: rgba(120, 120, 120, 0.7); - color: #ffffff; - } +.nav-tabs::-webkit-scrollbar { + height: 4px; +} - .stats-panel .refused { - background-color: rgba(91, 192, 222, 0.7); - color: #ffffff; - } +.nav-tabs::-webkit-scrollbar-track { + background: transparent; +} - .stats-panel .auth-hit { - background-color: rgba(150, 150, 0, 0.7); - color: #ffffff; - } +.nav-tabs::-webkit-scrollbar-thumb { + background-color: var(--border); + border-radius: 4px; +} - .stats-panel .cache-hit { - background-color: rgba(111, 84, 153, 0.7); - color: #ffffff; - } +.nav-tabs::-webkit-scrollbar-thumb:hover { + background-color: var(--text-muted); +} - .stats-panel .blocked { - background-color: rgba(255, 165, 0, 0.7); - color: #ffffff; - } +.nav-tabs>li>a { + white-space: nowrap; + border-radius: var(--radius) var(--radius) 0 0 !important; + color: var(--text-secondary) !important; + border-color: transparent !important; + transition: background-color var(--transition), color var(--transition); + padding: 8px 14px !important; + font-size: 13px; + font-weight: 500; +} - .stats-panel .dropped { - background-color: rgba(30, 30, 30, 0.7); - color: #ffffff; - } +.nav-tabs>li>a:hover { + background-color: color-mix(in srgb, var(--accent) 10%, transparent) !important; + color: var(--accent) !important; + border-color: transparent !important; +} - .stats-panel .recursions { - background-color: rgba(23, 162, 184, 0.7); - color: #ffffff; - } +.nav-tabs>li.active>a, +.nav-tabs>li.active>a:hover, +.nav-tabs>li.active>a:focus { + background-color: var(--bg-surface) !important; + border-color: var(--accent) var(--accent) transparent !important; + color: var(--accent) !important; + font-weight: 600; +} - .stats-panel .clients { - background-color: rgba(51, 122, 183, 0.7); - color: #ffffff; - } +/* ============================================================ + FORMS & CONTROLS + ============================================================ */ +.form-control { + border-radius: var(--radius) !important; + border-color: var(--border) !important; + background-color: var(--bg-surface) !important; + color: var(--text-primary) !important; + box-shadow: none !important; + transition: border-color var(--transition), background-color var(--transition); +} - .stats-panel .stats-last-item { - margin-right: 0% !important; - } +select, +select.form-control { + border-radius: var(--radius) !important; +} - .stats-panel .stats-item { - width: 8.818%; - float: left; - padding: 4px; - margin-right: 0.3%; - } +.form-control:focus { + border-color: var(--accent) !important; + box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent) !important; +} - .stats-panel .stats-item .number { - font-size: 15px; - font-weight: bold; - } +.form-control[disabled], +.form-control[readonly] { + background-color: var(--bg-surface-alt) !important; + color: var(--text-muted) !important; +} - .stats-panel .stats-item .percentage { - font-size: 10px; - font-weight: bold; - } +.input-group-addon { + border-radius: var(--radius) !important; + background-color: var(--bg-surface-alt) !important; + border-color: var(--border) !important; + color: var(--text-secondary) !important; +} - .stats-panel .stats-item .title { - font-size: 12px; - font-weight: bold; - } +.form-inline .form-group { + margin-right: 10px; + margin-bottom: 10px; +} -.zone-stats-panel { - margin-bottom: 15px; +/* ============================================================ + BUTTONS + ============================================================ */ +.btn { + border-radius: var(--radius) !important; + font-weight: 500; + transition: all var(--transition) !important; + display: inline-flex; + align-items: center; + justify-content: center; + line-height: 1.5 !important; } - .zone-stats-panel .stats-last-item { - margin-right: 0% !important; - } +.btn-primary { + background-color: var(--accent) !important; + border-color: var(--accent-dark) !important; +} - .zone-stats-panel .stats-item { - width: 16.125%; - float: left; - padding: 6px 4px; - margin-right: 0.65%; - background-color: rgba(51, 122, 183, 0.7); - color: #ffffff; - } +.btn-primary:hover { + background-color: var(--accent-dark) !important; + border-color: var(--accent-dark) !important; + transform: translateY(-1px); + box-shadow: var(--shadow-md) !important; +} - .zone-stats-panel .stats-item .number { - font-size: 14px; - font-weight: bold; - padding: 6px 0; - } +.btn-default { + background-color: var(--bg-surface) !important; + border-color: var(--border) !important; + color: var(--text-primary) !important; +} - .zone-stats-panel .stats-item .title { - font-size: 12px; - font-weight: bold; - } +.btn-default:hover, +.btn-default.active { + background-color: var(--bg-surface-alt) !important; + border-color: var(--accent) !important; + color: var(--accent) !important; +} -.about p { - color: rgb(119, 119, 119); - text-align: center; +.btn-group[data-toggle="buttons"] { + display: inline-flex !important; + gap: 6px !important; } -.about h3 a { - color: rgb(51,51,51) !important; +.btn-group[data-toggle="buttons"] .btn { + padding: 6px 14px !important; + font-size: 13px !important; + font-weight: 500 !important; + line-height: 1.5 !important; + height: 34px !important; + border-radius: var(--radius) !important; + margin-left: 0 !important; + float: none !important; } -.cluster-node-dropdown { - margin-left: 4px; - padding: 2px 8px; - height: 28px; - max-width: 250px; +.btn-group[data-toggle="buttons"] .btn.active, +.btn-group[data-toggle="buttons"] .btn:active { + background-color: var(--accent) !important; + border-color: var(--accent-dark) !important; + color: #fff !important; } -.dark-mode { - scrollbar-width: thin; - scrollbar-color: #555 #2c2c2e; +.btn-group[data-toggle="buttons"] label.btn.active { + background-color: var(--accent) !important; + border-color: var(--accent-dark) !important; + color: #fff !important; + box-shadow: none !important; } - .dark-mode ::-webkit-scrollbar { - width: 12px; - height: 12px; - } +.btn-group:not([data-toggle="buttons"]) { + display: inline-block !important; +} - .dark-mode ::-webkit-scrollbar-track { - background: #2c2c2e; - } +/* ============================================================ + TABLES + ============================================================ */ +.table>thead>tr>th, +.table>tbody>tr>td, +.table>tfoot>tr>th, +.table>tfoot>tr>td { + border-top-color: var(--border) !important; + color: var(--text-primary); +} - .dark-mode ::-webkit-scrollbar-thumb { - background-color: #555; - border-radius: 6px; - border: 3px solid #2c2c2e; - } +.table>thead>tr>th { + font-weight: 600; + color: var(--text-secondary) !important; + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.5px; + background-color: var(--bg-surface-alt) !important; +} -body.dark-mode { - background-color: #1a1a1a !important; - color: #dcdcdc !important; +.table-bordered, +.table-bordered>thead>tr>th, +.table-bordered>tbody>tr>td { + border-color: var(--border) !important; } -.dark-mode th a, -.dark-mode th a:hover { - color: #dcdcdc !important; - text-decoration: none !important; +.table-hover>tbody>tr:hover { + background-color: color-mix(in srgb, var(--accent) 6%, var(--bg-surface)) !important; } -.dark-mode #header { - background-color: #2c2c2e !important; - box-shadow: 0px 1px 15px 0px #000 !important; +.table-striped>tbody>tr:nth-of-type(odd) { + background-color: var(--bg-surface-alt) !important; } -.dark-mode #footer { - background-color: #252525 !important; - color: #888888 !important; - box-shadow: 0px 2px 15px 1px #000 !important; +.query-logs tr:hover { + backdrop-filter: brightness(95%); } - .dark-mode #footer .content { - color: #888888 !important; - } +/* ============================================================ + ALERTS & NOTIFICATIONS + ============================================================ */ +.AlertPlaceholder { + position: fixed; + width: min(800px, calc(100% - 32px)); + margin: auto; + left: 0; + right: 0; + top: 66px; + z-index: 1000; +} -.dark-mode .about h1 { - color: #f0f0f0 !important; +/* ============================================================ + DROPDOWNS + ============================================================ */ +.dropdown-menu { + border-radius: var(--radius) !important; + border-color: var(--border) !important; + background-color: var(--bg-surface) !important; + box-shadow: var(--shadow-lg) !important; + padding: 6px 0 !important; } -.dark-mode .about p { - color: #a0a0a0 !important; +#mnuUser .dropdown-menu { + right: 0 !important; + left: auto !important; } -.dark-mode .about h3 a { - color: #f0f0f0 !important; +.dropdown-menu>li>a { + color: var(--text-primary) !important; + padding: 8px 18px !important; + font-size: 14px; + transition: background-color var(--transition); } -.dark-mode .panel, -.dark-mode .panel-default { - background-color: #2c2c2e !important; - border-color: #3a3a3c !important; +.dropdown-menu>li>a:hover, +.dropdown-menu>li>a:focus { + background-color: color-mix(in srgb, var(--accent) 10%, transparent) !important; + color: var(--accent) !important; } -.dark-mode .panel-heading { - background-color: #3a3a3c !important; - border-color: #4a4a4c !important; - color: #f5f5f7 !important; +.divider { + background-color: var(--border) !important; + margin: 4px 0 !important; } -.dark-mode .panel-body { - background-color: #252525 !important; - color: #dcdcdc !important; +/* ============================================================ + MODALS + ============================================================ */ +.modal-content { + border-radius: calc(var(--radius) * 1.5) !important; + border-color: var(--border) !important; + background-color: var(--bg-surface) !important; + box-shadow: var(--shadow-lg) !important; } -.dark-mode .navbar-default { - background-color: #2c2c2e !important; - border-color: #3a3a3c !important; +.modal-header { + border-bottom-color: var(--border) !important; + background-color: var(--bg-surface-alt) !important; + border-radius: calc(var(--radius) * 1.5) calc(var(--radius) * 1.5) 0 0 !important; + padding: 14px 20px !important; +} + +.modal-footer { + border-top-color: var(--border) !important; + background-color: var(--bg-surface-alt) !important; + border-radius: 0 0 calc(var(--radius) * 1.5) calc(var(--radius) * 1.5) !important; } -.dark-mode .dropdown-menu { - background-color: #2c2c2e !important; - border-color: #3a3a3c !important; +.modal-body { + color: var(--text-primary) !important; } - .dark-mode .dropdown-menu > li > a:hover, - .dark-mode .dropdown-menu > li > a:focus { - background-color: #3a3a3c !important; +/* ============================================================ + MODALS — RESPONSIVE + ============================================================ */ +@media (max-width: 767px) { + .modal-dialog { + width: auto !important; + max-width: calc(100vw - 20px) !important; + margin: 10px auto !important; } - .dark-mode .dropdown-menu li a { - color: #ffffff !important; + .modal-body { + max-height: 75vh !important; + overflow-y: auto !important; + padding: 12px !important; } -.dark-mode .divider { - background-color: #3a3a3c !important; -} + .modal-body .form-horizontal .col-sm-3, + .modal-body .form-horizontal .col-sm-4 { + text-align: left !important; + padding-bottom: 0 !important; + } -.dark-mode .nav-tabs { - border-bottom: 1px solid #007aff !important; -} + .modal-body .form-horizontal .col-sm-offset-3, + .modal-body .form-horizontal .col-sm-offset-4 { + margin-left: 0 !important; + } - .dark-mode .nav-tabs > li > a:hover { - border-color: #4a4a4c !important; - border-bottom-color: #007aff !important; - background-color: #3a3a3c; + .modal-body .form-group { + margin-bottom: 10px !important; } - .dark-mode .nav-tabs > li.active > a, - .dark-mode .nav-tabs > li.active > a:hover, - .dark-mode .nav-tabs > li.active > a:focus { - background-color: #252525; - border-color: #007aff !important; - color: #ffffff !important; - border-bottom-color: transparent !important; + .modal-footer .btn { + min-height: 38px !important; } +} -.dark-mode .table-hover > tbody > tr:hover { - background-color: #33373a !important; +/* ============================================================ + WELL / PRE + ============================================================ */ +.well { + background-color: var(--bg-surface-alt) !important; + border-color: var(--border) !important; + border-radius: var(--radius) !important; + box-shadow: none !important; + color: var(--text-primary) !important; } -.dark-mode .table-striped > tbody > tr:nth-of-type(odd) { - background-color: #28282a !important; +pre { + background-color: var(--bg-surface-alt) !important; + color: var(--text-primary) !important; + border: 1px solid var(--border) !important; + border-radius: var(--radius) !important; } -.dark-mode .table > thead > tr > th, -.dark-mode .table > tbody > tr > td, -.dark-mode .table > tfoot > tr > th, -.dark-mode .table > tfoot > tr > td { - border-top-color: #3a3a3c !important; +/* ============================================================ + STATS PANELS + ============================================================ */ +.stats-panel { + display: flex; + flex-wrap: wrap; + gap: 6px; + padding: 6px 0; } -.dark-mode .table-bordered, -.dark-mode .table-bordered > thead > tr > th, -.dark-mode .table-bordered > tbody > tr > td { - border-color: #3a3a3c !important; +.stats-panel .stats-item { + flex: 1 1 80px; + max-width: 160px; + min-width: 72px; + padding: 8px 6px; + border-radius: var(--radius); + transition: transform var(--transition), box-shadow var(--transition); } -.dark-mode .form-control { - background-color: #3a3a3c !important; - border-color: #4a4a4c !important; - color: #f5f5f7 !important; +.stats-panel .stats-item:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); } - .dark-mode .form-control[disabled], .dark-mode .form-control[readonly] { - background-color: #2c2c2e !important; - } +.stats-panel .stats-item .number { + font-size: 16px; + font-weight: 700; +} -.dark-mode .modal-content { - background-color: #2c2c2e !important; - border-color: #3a3a3c !important; +.stats-panel .stats-item .percentage { + font-size: 10px; + font-weight: 600; + opacity: 0.85; } -.dark-mode .modal-header { - border-bottom-color: #3a3a3c !important; +.stats-panel .stats-item .title { + font-size: 11px; + font-weight: 600; + opacity: 0.9; + margin-top: 2px; } -.dark-mode .modal-footer { - border-top-color: #3a3a3c !important; +.stats-panel .stats-last-item { + margin-right: 0 !important; } -.dark-mode .well { - background-color: #252525 !important; - border-color: #3a3a3c !important; +.stats-panel .total-queries { + background-color: rgba(91, 141, 238, 0.85); + color: #fff; } -.dark-mode pre { - background-color: #222 !important; - color: #dcdcdc !important; - border: 1px solid #4a4a4c !important; +.stats-panel .no-error { + background-color: rgba(72, 187, 120, 0.85); + color: #fff; } -.dark-mode .btn-default { - color: #f5f5f7 !important; - background-color: #3a3a3c !important; - border-color: #4a4a4c !important; +.stats-panel .server-failure { + background-color: rgba(220, 80, 72, 0.85); + color: #fff; } - .dark-mode .btn-default:hover, - .dark-mode .btn-default.active { - background-color: #4a4a4c !important; - border-color: #5a5a5c !important; - } +.stats-panel .nxdomain { + background-color: rgba(110, 116, 128, 0.85); + color: #fff; +} -.dark-mode .input-group-addon { - background-color: #3a3a3c !important; - border-color: #4a4a4c !important; +.stats-panel .refused { + background-color: rgba(58, 189, 220, 0.85); + color: #fff; } -.dark-mode .stats-panel .stats-item, -.dark-mode .zone-stats-panel .stats-item { - color: #fff !important; +.stats-panel .auth-hit { + background-color: rgba(195, 160, 0, 0.85); + color: #fff; } -.dark-mode .c3-axis-x text, -.dark-mode .c3-axis-y text, -.dark-mode .c3-legend-item { - fill: #dcdcdc !important; +.stats-panel .cache-hit { + background-color: rgba(130, 90, 200, 0.85); + color: #fff; } -.dark-mode .c3-grid line { - stroke: #4a4a4c !important; +.stats-panel .blocked { + background-color: rgba(240, 150, 30, 0.85); + color: #fff; } -.dark-mode input[type="datetime-local"] { - color-scheme: dark; +.stats-panel .dropped { + background-color: rgba(30, 30, 30, 0.70); + color: #fff; } - .dark-mode input[type="datetime-local"]::-webkit-calendar-picker-indicator { - filter: invert(1); - } +.stats-panel .recursions { + background-color: rgba(23, 162, 184, 0.85); + color: #fff; +} -.dark-mode .pager li > a { - background-color: #3a3a3c !important; - border-color: #4a4a4c !important; +.stats-panel .clients { + background-color: rgba(51, 122, 183, 0.85); + color: #fff; } - .dark-mode .pager li > a:hover { - background-color: #4a4a4c !important; - } +.zone-stats-panel { + display: flex; + flex-wrap: nowrap; + gap: 8px; + margin-bottom: 15px; +} -.dark-mode .pagination li:not(.active) a { - color: white; - background-color: #252525; - border: 1px solid #337ab7; +.zone-stats-panel .stats-item { + flex: 1 1 0; + min-width: 0; + padding: 10px 8px; + border-radius: var(--radius); + background-color: rgba(51, 122, 183, 0.80); + color: #fff; + transition: transform var(--transition), box-shadow var(--transition); } - .dark-mode .pagination li:not(.active) a:hover { - background-color: #33373a; - } +.zone-stats-panel .stats-item:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); +} -.dark-mode #dpCustomDayWiseStart, -.dark-mode #dpCustomDayWiseEnd, -.dark-mode #txtQueryLogStart, -.dark-mode #txtQueryLogEnd { - color-scheme: dark; +.zone-stats-panel .stats-last-item { + margin-right: 0 !important; +} + +.zone-stats-panel .stats-item .number { + font-size: 14px; + font-weight: 700; + padding: 4px 0; +} + +.zone-stats-panel .stats-item .title { + font-size: 12px; + font-weight: 600; +} + +/* ============================================================ + ZONE / LOG PANES + ============================================================ */ +.zone-list-pane { + float: left; + width: 24%; } - .dark-mode #dpCustomDayWiseStart::-webkit-calendar-picker-indicator, - .dark-mode #dpCustomDayWiseEnd::-webkit-calendar-picker-indicator, - .dark-mode #txtQueryLogStart::-webkit-calendar-picker-indicator, - .dark-mode #txtQueryLogEnd::-webkit-calendar-picker-indicator { - filter: invert(1); +.zones { + font-size: 14px; +} + +.zones .zone { + padding: 4px; +} + +.zone-viewer-pane { + float: right; + width: 75%; + display: none; +} + +.log-list-pane { + float: left; + width: 17%; +} + +.logs { + font-size: 12px; +} + +.logs .log { + padding: 2px; +} + +.log-viewer-pane { + float: right; + width: 82%; + display: none; +} + +@media (max-width: 767px) { + + .zone-list-pane, + .zone-viewer-pane, + .log-list-pane, + .log-viewer-pane { + float: none; + width: 100%; + } + + .zone-viewer-pane, + .log-viewer-pane { + display: block; + } +} + +/* ============================================================ + IMAGES & IFRAMES + ============================================================ */ +.auto-resize-img { + max-width: 100%; + height: auto; + display: block; + margin: 0 auto; +} + +.center-iframe { + display: block; + margin: 0 auto; + max-width: 640px; + max-height: 480px; +} + +.center-iframe iframe { + width: 100%; + height: 100%; +} + +/* ============================================================ + ABOUT PAGE + ============================================================ */ +.about p { + color: var(--text-secondary); + text-align: center; +} + +.about h3 a { + color: var(--text-primary) !important; +} + +/* ============================================================ + CLUSTER DROPDOWN + ============================================================ */ +.cluster-node-dropdown { + margin-left: 4px; + padding: 2px 8px; + height: 30px; + max-width: 250px; + border-radius: var(--radius) !important; +} + +/* ============================================================ + PAGINATION + ============================================================ */ +.pager li>a { + border-radius: var(--radius) !important; + background-color: var(--bg-surface) !important; + border-color: var(--border) !important; + color: var(--text-primary) !important; + transition: all var(--transition) !important; +} + +.pager li>a:hover { + background-color: var(--bg-surface-alt) !important; + border-color: var(--accent) !important; + color: var(--accent) !important; +} + +.pagination li:not(.active) a { + color: var(--text-primary); + background-color: var(--bg-surface); + border: 1px solid var(--border); + transition: all var(--transition); +} + +.pagination li:not(.active) a:hover { + background-color: var(--bg-surface-alt); + border-color: var(--accent); + color: var(--accent); +} + +.pagination>.active>a, +.pagination>.active>span { + background-color: var(--accent) !important; + border-color: var(--accent-dark) !important; +} + +/* ============================================================ + DATETIME INPUTS + ============================================================ */ +#dpCustomDayWiseStart, +#dpCustomDayWiseEnd, +#txtQueryLogStart, +#txtQueryLogEnd { + border-radius: var(--radius) !important; +} + +/* ============================================================ + ACTION BUTTON ROWS + ============================================================ */ +.form-inline.pull-right .btn, +.form-inline.pull-right .btn-group, +.form-inline.pull-right .form-control { + vertical-align: middle !important; + margin-top: 0 !important; + margin-bottom: 0 !important; + margin-left: 4px !important; +} + +/* ============================================================ + CHARTS (C3 / Chart.js) + ============================================================ */ +.c3-axis-x text, +.c3-axis-y text, +.c3-legend-item { + fill: var(--text-secondary) !important; +} + +.c3-grid line { + stroke: var(--border) !important; +} + +.c3-legend-item-tile { + stroke: rgba(255, 255, 255, 0.25) !important; + stroke-width: 1px !important; +} + +/* ============================================================ + SCROLLBARS + ============================================================ */ +html { + scrollbar-width: thin; + scrollbar-color: var(--border) transparent; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background-color: var(--border); + border-radius: 4px; + border: 2px solid transparent; + background-clip: padding-box; +} + +::-webkit-scrollbar-thumb:hover { + background-color: var(--text-muted); +} + +/* ============================================================ + DARK MODE — applied via html.dark-mode (anti-flash) + AND via body.dark-mode (JS toggle compatibility) + ============================================================ */ + +html.dark-mode body, +body.dark-mode { + background-color: var(--bg-page) !important; + color: var(--text-primary) !important; +} + +html.dark-mode { + background-color: var(--bg-page); +} + +html.dark-mode #header { + background-color: var(--bg-header) !important; + box-shadow: var(--shadow-md) !important; +} + +html.dark-mode #footer { + background-color: var(--bg-footer) !important; +} + +html.dark-mode #footer .content { + color: var(--text-muted) !important; +} + +body.dark-mode { + background-color: var(--bg-page) !important; +} + +.dark-mode .navbar-default { + background-color: var(--bg-surface) !important; + border-color: var(--border) !important; +} + +.dark-mode .about h1 { + color: var(--text-primary) !important; +} + +.dark-mode .about p { + color: var(--text-secondary) !important; +} + +.dark-mode .about h3 a { + color: var(--text-primary) !important; +} + +.dark-mode th a, +.dark-mode th a:hover { + color: var(--text-primary) !important; + text-decoration: none !important; +} + +.dark-mode input[type="datetime-local"] { + color-scheme: dark; +} + +.dark-mode input[type="datetime-local"]::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +.dark-mode #dpCustomDayWiseStart, +.dark-mode #dpCustomDayWiseEnd, +.dark-mode #txtQueryLogStart, +.dark-mode #txtQueryLogEnd { + color-scheme: dark; +} + +.dark-mode #dpCustomDayWiseStart::-webkit-calendar-picker-indicator, +.dark-mode #dpCustomDayWiseEnd::-webkit-calendar-picker-indicator, +.dark-mode #txtQueryLogStart::-webkit-calendar-picker-indicator, +.dark-mode #txtQueryLogEnd::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +.dark-mode .stats-panel .stats-item, +.dark-mode .zone-stats-panel .stats-item { + color: #fff !important; +} + +/* ============================================================ + RESPONSIVE TWEAKS + ============================================================ */ +@media (max-width: 575px) { + #header .title .text { + font-size: 26px; + } + + .container { + padding: 60px 12px 72px; + } + + .nav-tabs>li>a { + padding: 7px 10px !important; + font-size: 12px; + } + + .container .pageLogin { + padding-top: 60px; + } + + .stats-panel .stats-item { + flex: 0 0 calc(50% - 6px) !important; + max-width: calc(50% - 6px) !important; + } +} + +@media (max-width: 767px) { + .form-horizontal .control-label { + text-align: left !important; + } + + .form-horizontal .col-sm-offset-3 { + margin-left: 0; + } + + .table-responsive { + border: none !important; + overflow: visible !important; + } + + .AlertPlaceholder { + top: 56px; + } +} + +@media (max-width: 991px) { + .container { + padding-left: 14px; + padding-right: 14px; + } +} + +/* ============================================================ + MOBILE RESPONSIVE + ============================================================ */ + +@media (max-width: 767px) { + + .nav-tabs { + scrollbar-width: none !important; + } + + .nav-tabs::-webkit-scrollbar { + display: none !important; + } + + .container { + padding: 70px 8px 60px !important; + min-width: 0 !important; + width: 100% !important; + } + + #header { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + width: 100% !important; + z-index: 9999 !important; + } + + #header .title { + width: 100% !important; + padding: 0 8px !important; + padding-right: 150px !important; + overflow: hidden !important; + } + + #header .title .text { + font-size: 22px !important; + white-space: nowrap !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + max-width: 100% !important; + } + + #header .menu { + right: 4px !important; + max-width: 145px !important; + } + + #header .menu .menu-title { + font-size: 13px !important; + white-space: nowrap !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + max-width: 145px !important; + } + + #header .menu .menu-title { + font-size: 13px !important; + max-width: 120px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + #mnuUser .dropdown-menu { + right: 0 !important; + left: auto !important; + min-width: 170px !important; + } + + .panel { + border-radius: 6px !important; + } + + .panel-heading { + padding: 10px 12px !important; + flex-wrap: wrap !important; + gap: 6px !important; + } + + .nav-tabs>li>a { + padding: 10px 10px !important; + font-size: 12px !important; + min-height: 44px !important; + display: flex !important; + align-items: center !important; + white-space: nowrap !important; + } + + .btn-group[data-toggle="buttons"] { + flex-wrap: wrap !important; + gap: 4px !important; + } + + .btn-group[data-toggle="buttons"] .btn { + flex: 1 1 calc(33% - 4px) !important; + min-width: 0 !important; + font-size: 12px !important; + height: auto !important; + min-height: 44px !important; + padding: 6px 4px !important; + } + + #divDashboardMainChart { + position: relative !important; + height: 380px !important; + width: 100% !important; + min-height: 380px !important; + padding-bottom: 30px !important; + } + + #canvasDashboardMain { + height: 350px !important; + min-height: 350px !important; + width: 100% !important; + max-width: 100% !important; + } + + #mainPanelTabPaneDashboard [style*="float: left; width: 50%"], + #mainPanelTabPaneDashboard [style*="float: right; width: 50%"], + #mainPanelTabPaneDashboard [style*="float:left; width:50%"], + #mainPanelTabPaneDashboard [style*="float:right; width:50%"] { + float: none !important; + width: 100% !important; + padding-left: 0 !important; + padding-right: 0 !important; + } + + #divDashboardPie1Body, + #divDashboardPie2Body, + #divDashboardPie3Body { + overflow: hidden !important; + height: 320px !important; + padding: 8px !important; + position: relative !important; + border-radius: 0 0 var(--radius) var(--radius) !important; + } + + #canvasDashboardPie, + #canvasDashboardPie2, + #canvasDashboardPie3 { + max-width: 100% !important; + width: 100% !important; + height: 300px !important; + max-height: 300px !important; + display: block !important; + } + + .zone-stats-panel { + display: grid !important; + grid-template-columns: repeat(2, 1fr) !important; + gap: 6px !important; + flex-wrap: unset !important; + } + + .zone-stats-panel .stats-item { + flex: unset !important; + min-width: 0 !important; + height: auto !important; + min-height: 70px !important; + } + + .panel-heading[style*="height: 41px"] { + display: block !important; + overflow: hidden !important; + height: auto !important; + } + + .panel-heading[style*="height: 41px"] .pull-left, + .panel-heading[style*="height: 41px"] .pull-right { + float: left !important; + display: flex !important; + align-items: center !important; + } + + .panel-heading[style*="height: 41px"] .pull-right { + float: right !important; + } + + .form-inline .pull-right, + .form-inline>.pull-right { + float: none !important; + display: flex !important; + flex-wrap: wrap !important; + align-items: center !important; + gap: 6px !important; + justify-content: flex-end !important; + margin-bottom: 6px !important; + } + + .form-inline.pull-right { + float: none !important; + display: flex !important; + flex-wrap: wrap !important; + align-items: center !important; + gap: 6px !important; + justify-content: flex-end !important; + width: 100% !important; + margin-bottom: 6px !important; + } + + .panel-heading .form-inline.pull-right { + float: right !important; + width: auto !important; + margin-bottom: 0 !important; + flex-wrap: nowrap !important; + } + + .panel-heading[style*="height: 36px"], + .panel-heading[style*="height: 41px"] { + height: auto !important; + min-height: 36px !important; + } + + .cluster-node-dropdown { + order: 999 !important; + flex: 0 0 100% !important; + width: 100% !important; + max-width: 100% !important; + margin: 4px 0 0 0 !important; + padding-top: 8px !important; + border-top: 1px solid var(--border) !important; + } + + .form-inline.pull-right, + .form-inline>.pull-right, + #divEditZone .pull-right, + #divViewZones .pull-right .form-group { + flex-wrap: wrap !important; + } + + .nav-tabs:has(li.pull-right) { + position: relative !important; + padding-bottom: 44px !important; + flex-wrap: nowrap !important; + overflow-x: auto !important; + } + + .nav-tabs li.pull-right { + float: none !important; + position: absolute !important; + bottom: 0 !important; + left: 0 !important; + right: 0 !important; + width: 100% !important; + padding: 0 !important; + border-top: 1px solid var(--border) !important; + margin: 0 !important; + } + + .nav-tabs li.pull-right .cluster-node-dropdown { + order: unset !important; + flex: unset !important; + width: 100% !important; + max-width: 100% !important; + margin: 4px 0 0 0 !important; + padding-top: 0 !important; + border-top: none !important; + } + + .panel-heading .form-inline.pull-right { + flex-wrap: wrap !important; + } + + #divViewZones>.form-inline:first-child { + display: flex !important; + flex-direction: row !important; + justify-content: flex-end !important; + align-items: center !important; + gap: 6px !important; + margin-bottom: 8px !important; + } + + #divViewZones>.form-inline:first-child .pull-right { + float: none !important; + display: flex !important; + align-items: center !important; + gap: 6px !important; + width: 100% !important; + justify-content: flex-end !important; + margin-bottom: 0 !important; + } + + #divViewZones .form-inline:nth-child(2) { + display: flex !important; + flex-direction: column !important; + gap: 8px !important; + } + + #divViewZones .form-inline:nth-child(2) form.pull-left, + #divViewZones .form-inline:nth-child(2) form.pull-right { + float: none !important; + width: 100% !important; + display: flex !important; + flex-wrap: wrap !important; + align-items: center !important; + gap: 6px !important; + } + + #divViewZones .form-inline .form-group { + display: flex !important; + align-items: center !important; + gap: 6px !important; + flex-wrap: wrap !important; + margin: 0 !important; + } + + #txtZonesEdit { + width: 100% !important; + min-width: 0 !important; + flex: 1 !important; + } + + #txtZonesPageNumber { + width: 60px !important; + } + + #optZonesPerPage { + width: 70px !important; + } + + #tableZones { + display: block !important; + overflow-x: auto !important; + -webkit-overflow-scrolling: touch !important; + width: 100% !important; + } + + .pagination>li>a { + padding: 6px 10px !important; + font-size: 13px !important; + } + + .zone-list-pane, + .zone-viewer-pane, + .log-list-pane, + .log-viewer-pane { + float: none !important; + width: 100% !important; + } + + #divEditZone [style*="float: left"] { + float: none !important; + margin-bottom: 8px !important; + } + + #divEditZone [style*="float: right; padding: 2px 0px"] { + float: none !important; + display: flex !important; + flex-wrap: wrap !important; + gap: 6px !important; + width: 100% !important; + } + + #divEditZone [style*="float: right; padding: 2px 0px"]>.btn, + #divEditZone [style*="float: right; padding: 2px 0px"]>.btn-group { + flex: 1 1 calc(50% - 6px) !important; + width: auto !important; + min-width: 0 !important; + } + + #divEditZone [style*="float: right; padding: 2px 0px"]>.btn-group>.btn { + width: 100% !important; + } + + #divEditZone .form-inline.well .pull-left, + #divEditZone .form-inline.well .pull-right { + float: none !important; + display: flex !important; + flex-wrap: wrap !important; + gap: 6px !important; + width: 100% !important; + align-items: center !important; + } + + #txtEditZoneFilterName { + width: 100% !important; + min-width: 0 !important; + flex: 1 !important; + } + + #txtEditZoneFilterType { + width: 100px !important; + } + + #tableEditZone { + display: block !important; + overflow-x: auto !important; + -webkit-overflow-scrolling: touch !important; + width: 100% !important; + } + + #divQueryLogsTable .query-logs { + display: block !important; + overflow-x: auto !important; + -webkit-overflow-scrolling: touch !important; + width: 100% !important; + } + + #divQueryLogsTable .query-logs th:nth-child(10), + #divQueryLogsTable .query-logs td:nth-child(10) { + min-width: 300px !important; + } + + #tableEditZone th:nth-child(5), + #tableEditZone td:nth-child(5) { + min-width: 300px !important; + } + + .table-responsive { + overflow-x: auto !important; + -webkit-overflow-scrolling: touch !important; + } + + .table th, + .table td { + white-space: nowrap !important; + padding: 8px 12px !important; + } + + .table th { + font-size: 12px !important; + letter-spacing: 0.03em !important; + } + + #tableTopClients th, + #tableTopClients td, + #tableTopDomains th, + #tableTopDomains td, + #tableTopBlockedDomains th, + #tableTopBlockedDomains td { + padding: 6px 8px !important; + } + + #tableTopClients th:nth-child(1), + #tableTopClients td:nth-child(1), + #tableTopDomains th:nth-child(1), + #tableTopDomains td:nth-child(1), + #tableTopBlockedDomains th:nth-child(1), + #tableTopBlockedDomains td:nth-child(1) { + width: 100% !important; + white-space: normal !important; + word-break: break-all !important; + } + + #tableTopClients th:nth-child(2), + #tableTopClients td:nth-child(2), + #tableTopDomains th:nth-child(2), + #tableTopDomains td:nth-child(2), + #tableTopBlockedDomains th:nth-child(2), + #tableTopBlockedDomains td:nth-child(2) { + white-space: nowrap !important; + text-align: right !important; + padding-right: 6px !important; + } + + #tableTopClients th:nth-child(3), + #tableTopClients td:nth-child(3), + #tableTopDomains th:nth-child(3), + #tableTopDomains td:nth-child(3), + #tableTopBlockedDomains th:nth-child(3), + #tableTopBlockedDomains td:nth-child(3) { + width: 36px !important; + min-width: 36px !important; + padding: 4px 2px !important; + text-align: center !important; + } + + #tableAdminSessions th:nth-child(5), + #tableAdminSessions td:nth-child(5) { + min-width: 250px !important; + } + + #tableAdminUsers th:nth-child(2), + #tableAdminUsers td:nth-child(2) { + min-width: 130px !important; + } + + #tableAdminUsers th:nth-child(5), + #tableAdminUsers td:nth-child(5) { + min-width: 160px !important; + } + + #mainPanelTabPaneAdmin .table { + display: block !important; + overflow-x: auto !important; + -webkit-overflow-scrolling: touch !important; + width: 100% !important; + } + + #divDhcpLeases th:nth-child(2), + #divDhcpLeases td:nth-child(2) { + min-width: 140px !important; + } + + #divDhcpLeases .table, + #divDhcpViewScopes .table { + display: block !important; + overflow-x: auto !important; + -webkit-overflow-scrolling: touch !important; + width: 100% !important; + } + + #divDhcpViewScopes>div[style*="float: right"] { + float: none !important; + display: flex !important; + justify-content: flex-end !important; + margin-bottom: 6px !important; + } + + #divAdminClusterView .form-inline.pull-right .btn, + #divAdminClusterView .form-inline.pull-right .btn-group { + flex: 1 1 calc(50% - 6px) !important; + min-width: 0 !important; + } + + #divAdminClusterView .form-inline.pull-right .cluster-node-dropdown { + flex: 1 1 100% !important; + width: 100% !important; + } + + .btn { + min-height: 44px !important; + padding-left: 10px !important; + padding-right: 10px !important; + } + + [style*="float: right"]>.btn, + .pull-right>.btn { + min-height: 38px !important; + } + + .form-horizontal .control-label { + text-align: left !important; + padding-bottom: 4px !important; + } + + .col-sm-offset-3, + .col-sm-offset-1 { + margin-left: 0 !important; + } + + .container .pageLogin { + padding-top: 40px !important; + width: 100% !important; + max-width: 100% !important; + } + + .AlertPlaceholder { + top: 66px !important; + width: calc(100% - 16px) !important; + } + + #footer { + height: auto !important; + padding: 12px 0 !important; + margin-top: -40px !important; + } + + #divCustomDayWise span { + display: block !important; + margin-bottom: 6px !important; + } + + #divCustomDayWise input[type="datetime-local"] { + width: 100% !important; + } + + .cluster-node-dropdown { + max-width: 100% !important; + width: 100% !important; + margin: 4px 0 0 0 !important; + } +} + +@media (max-width: 480px) { + + #header .title .text { + font-size: 20px !important; + } + + .btn-group[data-toggle="buttons"] .btn { + flex: 1 1 calc(50% - 4px) !important; + } + + .nav-tabs>li>a { + padding: 10px 7px !important; + font-size: 11px !important; + } + + .zone-stats-panel .stats-item { + flex: 1 1 calc(50% - 8px) !important; } +} \ No newline at end of file diff --git a/DnsServerCore/www/index.html b/DnsServerCore/www/index.html index 5f5b75e2..6b907024 100644 --- a/DnsServerCore/www/index.html +++ b/DnsServerCore/www/index.html @@ -19,18 +19,132 @@ --> + + Technitium DNS Server + + + + @@ -48,10 +162,12 @@ - + +
-
+
- +
@@ -195,55 +357,64 @@

DNS Server

70
-
0%
+
0% +
No Error
5
-
0%
+
0%
Server Failure
5
-
0%
+
0% +
NX Domain
10
-
0%
+
0% +
Refused
10
-
0%
+
0% +
Authoritative
10
-
0%
+
+ 0%
Recursive
10
-
0%
+
0% +
Cached
10
-
0%
+
0% +
Blocked
5
-
0%
+
0% +
Dropped
@@ -254,26 +425,26 @@

DNS Server

-
+
-
+
-
+
-
+
@@ -302,12 +473,14 @@

DNS Server

-
10
+
10 +
Allow List
-
10
+
10 +
Block List
@@ -316,9 +489,13 @@

DNS Server

-
Top Clients
+
Top Clients +
- +
@@ -343,9 +520,13 @@

DNS Server

-
Top Domains
+
Top Domains +
- +
@@ -366,9 +547,13 @@

DNS Server

-
Top Blocked Domains
+
Top Blocked + Domains
- +
@@ -391,15 +576,21 @@

DNS Server

-
- +
+
- - + +
@@ -408,14 +599,17 @@

DNS Server

- - + +
- +
@@ -428,7 +622,9 @@

DNS Server

- +
@@ -439,10 +635,13 @@

DNS Server

@@ -452,14 +651,30 @@

DNS Server

- - - - - - - - + + + + + + + + @@ -473,10 +688,15 @@

DNS Server

@@ -492,79 +712,136 @@

DNS Server

- +
-

example.com

+

example.com

Primary - DNSSEC - Enabled - catalog -
Expiry: 01 Jan 2020 00:00:00
+ DNSSEC + Enabled + catalog +
+ Expiry: 01 Jan 2020 00:00:00
- - - - - + + + + + - +
-
+
- +
- +
- +
@@ -577,7 +854,9 @@

- +
@@ -590,10 +869,13 @@

@@ -603,11 +885,21 @@

#ZoneTypeDNSSECStatusSerialExpiryLast Modified# + Zone + Type + DNSSEC + Status + Serial + Expiry + Last + Modified
- - - - - + + + + + @@ -622,10 +914,15 @@

@@ -638,15 +935,19 @@

-
+
- +
- +
@@ -657,11 +958,21 @@

-
technitium.com
+
technitium.com
- - - + + +
@@ -676,16 +987,22 @@

-
+
- +
- - + +
@@ -696,12 +1013,25 @@

-
technitium.com
+
technitium.com
- - - - + + + +
@@ -716,16 +1046,22 @@

-
+
- +
- - + +
@@ -736,12 +1072,26 @@

-
technitium.com
+
technitium.com
- - - - + + + +
@@ -756,14 +1106,20 @@

-
-
+
+
- - + +
@@ -771,41 +1127,54 @@

#NameTypeTTLData# + Name + Type + TTL + Data +
- + - + + +
Installed AppsInstalled + Apps
Total Apps: 0
Total Apps: 0
-
+
- +
- @@ -839,7 +1208,8 @@

- @@ -850,40 +1220,56 @@

- +

- - - + + +
- -
+
-
+
+
- +
- - - - + + + + - + + +
NameScope Range/Subnet MaskNetwork/BroadcastInterfaceName + Scope + Range/Subnet MaskNetwork/Broadcast + Interface +
Total Leases: 0
Total Leases: 0
- +
-
Enable this option to allow DHCP server to find out if an IP address is already in use to prevent IP address conflict when some of the devices on the network have manually configured IP addresses.
+
+ Enable this option to allow DHCP server to find out + if an IP address is already in use to prevent IP + address conflict when some of the devices on the + network have manually configured IP addresses.
- +
- + milliseconds (default 1000)
-
The timeout interval to wait for an ping reply.
+
The timeout interval to wait + for an ping reply.
- +
- + (default 2)
-
The maximum number of ping requests to try.
-
- -
Warning! Ping check would work as expected only when you make sure that all the client devices with manually configured IP addresses on the network respond to a ping request. Devices running Microsoft Windows by default drop ping requests at host firewall and will cause this ping check to fail to detect in use IP addresses. It is recommended to not rely on this option and instead make sure that you exclude a range of addresses using Exclusions and manually assign IP addresses to your devices only in the excluded range.
+
The maximum number of ping + requests to try.
+
+ +
Warning! Ping check would work as + expected only when you make sure that all the client devices + with manually configured IP addresses on the network respond + to a ping request. Devices running Microsoft Windows by + default drop ping requests at host firewall and will cause + this ping check to fail to detect in use IP addresses. It is + recommended to not rely on this option and instead make sure + that you exclude a range of addresses using Exclusions and + manually assign IP addresses to your devices only in the + excluded range.
- +
- +
-
The domain name for this network to allow assigning a fully qualified domain name to clients. Use a domain name that you own or that is not in common use like 'home' or 'lan' so that you don't block out an existing domain name. (Option 15)
+
The domain name for this + network to allow assigning a fully qualified domain name + to clients. Use a domain name that you own or that is + not in common use like 'home' or 'lan' so that you don't + block out an existing domain name. (Option 15)
- +
- +
-
The list of domain names that the clients can use as a suffix when searching a domain name. (Option 119)
+
The list of domain names that + the clients can use as a suffix when searching a domain + name. (Option 119)
- +
-
Enable this option to allow the DHCP server to automatically update forward and reverse DNS entries for clients.
+
+ Enable this option to allow the DHCP server to + automatically update forward and reverse DNS entries + for clients.
-
Enable this option to allow the DHCP server to overwrite existing DNS A record matching the client domain name for dynamic leases.
+
+ Enable this option to allow the DHCP server to + overwrite existing DNS A record matching the client + domain name for dynamic leases.
- +
- + seconds (default 900/15m)
-
The TTL value of the DNS records updated for the above provided domain name.
+
The TTL value of the DNS + records updated for the above provided domain name. +
- +
- +
-
The default gateway IP address to be used by the clients. (Option 3)
+
The default gateway IP address + to be used by the clients. (Option 3)
- +
-
Enable this option to automatically use this DNS Server.
+
+ Enable this option to automatically use this DNS + Server.
- +
-
The DNS server IP addresses to be used by the clients. (Option 6)
+
The DNS server IP addresses to + be used by the clients. (Option 6)
- +
- +
-
The NBNS/WINS server IP addresses to be used by the clients. (Option 44)
+
The NBNS/WINS server IP + addresses to be used by the clients. (Option 44)
- +
- +
-
The Network Time Protocol (NTP) server IP addresses to be used by the clients. (Option 42)
+
The Network Time Protocol + (NTP) server IP addresses to be used by the clients. + (Option 42)
- +
- +
-
Enter NTP server domain names (e.g. pool.ntp.org) above that the DHCP server should automatically resolve and pass the resolved IP addresses to clients as NTP server option. (Option 42)
+
Enter NTP server domain names + (e.g. pool.ntp.org) above that the DHCP server should + automatically resolve and pass the resolved IP addresses + to clients as NTP server option. (Option 42)
- +
- +
- +
Destination Subnet Mask Router +
-
The static routes to be used by the clients for accessing specified destination networks. (Option 121)
+
The static routes to be used + by the clients for accessing specified destination + networks. (Option 121)
- +
- +
-
The IP address of next server (TFTP) to use in bootstrap by the clients. If not specified, the DHCP server's IP address is used. (siaddr)
+
The IP address of next server + (TFTP) to use in bootstrap by the clients. If not + specified, the DHCP server's IP address is used. + (siaddr)
- +
- +
-
The optional bootstrap server host name to be used by the clients to identify the TFTP server. (sname/Option 66)
+
The optional bootstrap server + host name to be used by the clients to identify the TFTP + server. (sname/Option 66)
- +
- +
-
The boot file name stored on the bootstrap TFTP server to be used by the clients. (file/Option 67)
+
The boot file name stored on + the bootstrap TFTP server to be used by the clients. + (file/Option 67)
- +
- +
- +
Vendor Class Identifier Vendor Specific Information +
-
The Vendor Specific Information (option 43) to be sent to the clients that match the Vendor Class Identifier (option 60) in the request. The Vendor Class Identifier can be empty string to match any identifier, or matched exactly, or match a substring, for example substring(vendor-class-identifier,0,9)=="PXEClient". The Vendor Specific Information must be either a colon (:) separated hex string or a normal hex string, for example 06:01:03:0A:04:00:50:58:45:09:14:00:00:11:52:61:73:70:62:65:72:72:79:20:50:69:20:42:6F:6F:74:FF OR 0601030A0400505845091400001152617370626572727920506920426F6F74FF.
+
The Vendor Specific + Information (option 43) to be sent to the clients that + match the Vendor Class Identifier (option 60) in the + request. The Vendor Class Identifier can be empty string + to match any identifier, or matched exactly, or match a + substring, for example + substring(vendor-class-identifier,0,9)=="PXEClient". + The Vendor Specific Information must be either a colon + (:) separated hex string or a normal hex string, for + example + 06:01:03:0A:04:00:50:58:45:09:14:00:00:11:52:61:73:70:62:65:72:72:79:20:50:69:20:42:6F:6F:74:FF + OR + 0601030A0400505845091400001152617370626572727920506920426F6F74FF. +
- +
- +
-
The Control And Provisioning of Wireless Access Points (CAPWAP) Access Controller IP addresses to be used by Wireless Termination Points to discover the Access Controllers to which it is to connect. (Option 138)
+
The Control And Provisioning + of Wireless Access Points (CAPWAP) Access Controller IP + addresses to be used by Wireless Termination Points to + discover the Access Controllers to which it is to + connect. (Option 138)
- +
- +
-
The TFTP Server Address or the VoIP Configuration Server Address. (Option 150)
+
The TFTP Server Address or the + VoIP Configuration Server Address. (Option 150)
- +
- +
- +
Code Hex Value +
-
This feature allows you to define DHCP options that are not yet directly supported. To add an option, use the DHCP option code defined for it and enter the value in either a colon (:) separated hex string or a normal hex string format, for example C0:A8:01:01 OR C0A80101.
+
This feature allows you to + define DHCP options that are not yet directly supported. + To add an option, use the DHCP option code defined for + it and enter the value in either a colon (:) separated + hex string or a normal hex string format, for example + C0:A8:01:01 OR C0A80101. +
- +
- +
- +
Starting Address Ending Address +
-
The IP address range that must be excluded or not assigned dynamically to any client by the DHCP server.
+
The IP address range that must + be excluded or not assigned dynamically to any client by + the DHCP server.
-
Note! Make sure to exclude address ranges if you plan to manually assign IP addresses to some of the devices or to assign reserved leases so that these IP addresses are not dynamically allocated in the first place.
+
Note! Make sure to exclude + address ranges if you plan to manually assign IP addresses + to some of the devices or to assign reserved leases so that + these IP addresses are not dynamically allocated in the + first place.
- +
-
Enable this option to stop dynamic IP address allocation and allocate only reserved IP addresses.
+
+ Enable this option to stop dynamic IP address + allocation and allocate only reserved IP addresses. +
-
Enable this option to stop dynamic IP address allocation for clients with locally administered MAC addresses. MAC address with 0x02 bit set in the first octet indicate a locally administered MAC address which usually means that the device is not using its original MAC address.
+
+ Enable this option to stop dynamic IP address + allocation for clients with locally administered MAC + addresses. MAC address with 0x02 bit set in the + first octet indicate a locally administered MAC + address which usually means that the device is not + using its original MAC address.
-
This option when enabled will always use the client's MAC address as the identifier to allocate lease instead of the Client Identifier (Option 61) provided by the client in the request. Some Linux distros use a custom Client Identifier instead of the device's MAC Address which can cause issues when the Virtual Machine (VM) in which the OS is installed is cloned causing both the original and cloned clients to get same IP allocated. There can be issues too when the same client changes its Client Identifier and starts getting a different IP address lease. Enabling the Ignore Client Identifier option will fix such issues. Changing this option may cause the existing clients to get a different IP lease on renewal.
+
This + option when enabled will always use the client's MAC + address as the identifier to allocate lease instead + of the Client Identifier (Option 61) provided by the + client in the request. Some Linux distros use a + custom Client Identifier instead of the device's MAC + Address which can cause issues when the Virtual + Machine (VM) in which the OS is installed is cloned + causing both the original and cloned clients to get + same IP allocated. There can be issues too when the + same client changes its Client Identifier and starts + getting a different IP address lease. Enabling the + Ignore Client Identifier option will fix such + issues. Changing this option may cause the existing + clients to get a different IP lease on renewal. +
- +
- +
- +
Host Name MAC Address IP Address Comments +
-
The reserved IP addresses to be assigned to specific clients based on their MAC address. Set a hostname to override the client's hostname.
+
The reserved IP addresses to + be assigned to specific clients based on their MAC + address. Set a hostname to override the client's + hostname.
- - + +
@@ -2727,15 +4545,30 @@

Edit Scope

-
+
@@ -2744,12 +4577,17 @@

Edit Scope

-
+
+
- - + +
@@ -2757,29 +4595,44 @@

Edit Scope

- - - - - + + + + + - + + +
UsernameSessionLast SeenRemote AddressUser AgentUsername + Session + Last + SeenRemote + AddressUser + Agent
-
+
+
- +
@@ -2787,30 +4640,47 @@

Edit Scope

- - - - - - + + + + + + - + + +
UsernameDisplay Name2FA StatusStatusRecent LoginPrevious LoginUsername + Display + Name2FA + StatusStatus + Recent + LoginPrevious + Login
-
+
+
- +
@@ -2818,28 +4688,37 @@

Edit Scope

- - + + - + + +
NameDescriptionName + Description +
-
+
- + @@ -2848,32 +4727,53 @@

Edit Scope

- + + +
SectionSection + User Permissions Group Permissions
-
+
+
- - - - - + + + + +
@@ -2881,21 +4781,39 @@

Edit Scope

- - - - - - - - + + + + + + + + - + + +
Node NameIP AddressURLTypeStateUp SinceLast SeenLast SyncedNode + NameIP + AddressURL + Type + State + Up + SinceLast + SeenLast + Synced
@@ -2904,19 +4822,29 @@

Edit Scope

-
+
-
+
@@ -2926,25 +4854,35 @@

Edit Scope

-
20171012
+
+ 20171012
- - + +
-
- +
+
-
+
-
+
+
@@ -2984,17 +4923,20 @@

Edit Scope

- +
- +
- +
@@ -3044,7 +4986,8 @@

Edit Scope

- +
@@ -3066,8 +5009,13 @@

Edit Scope

- - + +
@@ -3081,10 +5029,13 @@

Edit Scope

@@ -3114,14 +5065,21 @@

Edit Scope

- Found: 0 logs + Found: 0 + logs
@@ -3138,7 +5096,8 @@

Edit Scope

-
+
Technitium Logo @@ -3146,32 +5105,53 @@

Technitium DNS Server

Version

Server up since

- Copyright (C) 2025 Shreyas Zare (shreyas@technitium.com)
- This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.
+ Copyright (C) 2025 Shreyas Zare (shreyas@technitium.com)
+ This program comes with ABSOLUTELY NO WARRANTY. This is free software, and + you are welcome to redistribute it under certain conditions.

-

Source code available under GNU General Public License v3.0 on  GitHub

- -

What's New?

-

Read the change log to know what's new in this release.

- -

API Documentation

-

The DNS server HTTP API allows any 3rd party app or script to configure the DNS server. The HTTP API is used by this web console and thus all the actions that this web console does can be performed via the API. Read the HTTP API documentation for complete details.

- -

Help Topics

-

Read the latest online help topics which contains the DNS Server user manual and covers frequently asked questions.

+

Source code available under GNU General Public License v3.0 on  GitHub

+ +

What's New?

+

Read the change + log to know what's new in this release.

+ +

API Documentation

+

The DNS server HTTP API allows any 3rd party app or script to configure the + DNS server. The HTTP API is used by this web console and thus all the + actions that this web console does can be performed via the API. Read the HTTP API documentation for complete details.

+ +

Help Topics

+

Read the latest online help topics which contains the DNS Server + user manual and covers frequently asked questions.

Support

-

For support, send an email to support@technitium.com.

+

For support, send an email to support@technitium.com.

- Follow @technitium@mastodon.social on Mastodon.
- Checkout Technitium Blog. + Follow @technitium@mastodon.social on Mastodon.
+ Checkout Technitium + Blog.

- Join /r/technitium on Reddit. + Join /r/technitium on Reddit.

-

Donate

-

Make a contribution to Technitium and help making new software, updates, and features possible.

+

Donate

+

Make a contribution to Technitium and help making new software, updates, and + features possible.

Donate Now!

@@ -3193,7 +5173,8 @@

@@ -3285,7 +5287,8 @@
@@ -3370,7 +5384,8 @@ @@ -3487,7 +5524,8 @@