diff --git a/stygia/CHANGELOG.md b/stygia/CHANGELOG.md
new file mode 100644
index 0000000000..4cff71a9b6
--- /dev/null
+++ b/stygia/CHANGELOG.md
@@ -0,0 +1,78 @@
+# Changelog
+
+## 2.1.1 — 2026-08-21
+
+Modal and field-editor polish: datepicker/timepicker, jQuery UI dialogs, Bootstrap overlays.
+
+### Editors and overlays
+
+- Fix calendar trigger: ship `img/b_calendar.png` (host JS path) and paint via SVG mask
+- Modernize `#ui-datepicker-div`: circular day selection, Inter chrome, roomier padding
+- Rebuild `.ui-timepicker-div` as CSS grid (no float label hack); compact time input + green sliders
+- Theme `.ui-widget-overlay`, dialog close via `close.svg`, stronger buttonpane layout
+- New `scss/_modals.scss`: Bootstrap modal shell, `#enum_editor`, GIS editor, inline `.cEdit` overflow
+- RTL overrides for picker chevrons, time grid, dialog close, calendar trigger
+
+## 2.1.0 — 2026-08-21
+
+Usability and design polish: 20 targeted improvements plus a visual QA pass (login, tabs, typed cells, chrome).
+
+### Design system
+
+- Expose Sass tokens as `--stygia-*` CSS custom properties on `:root` (`scss/_tokens.scss`)
+- Inter 300 bundled; body stays 400, paragraphs/labels use 300, headings 500 — reserve 600 for lockups
+- Optional system font: **FiraCode Nerd Font** (Propo for UI, Mono for SQL) when installed; otherwise Inter / JetBrains Mono
+- Stronger muted/disabled text; denser-but-breathing type rhythm
+- Login: river-mark badge + `phpMyAdmin · STYGIA` lockup, single centered column, glow, `prefers-reduced-motion`
+- Sidebar lockup is CSS-only so phpMyAdmin’s leftover `
)
+ > div:not(.container):not(.modal_form) {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ margin-bottom: 0.35rem;
+ }
+
+ #pmalogo {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ padding: 0;
+ margin: 0 0 0.25rem;
+ text-align: center;
+ }
+
+ // Welcome heading (not the brand lockup)
+ div.container > h1 {
+ display: block;
+ width: 100%;
+ text-align: center;
+ margin-left: auto;
+ margin-right: auto;
+ }
+
+ // Brand lockup: mark badge + CSS wordmark (host
![]()
fully hidden)
+ a.logo {
+ display: flex !important;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ max-width: 320px;
+ height: auto;
+ min-height: 88px;
+ margin: 0 auto 0.75rem;
+ padding: 0;
+ background: none !important;
+ background-image: none !important;
+ text-decoration: none !important;
+ position: relative;
+ font-size: 0;
+ line-height: 0;
+ animation: stygia-login-fade 0.5s ease-out both;
+
+ &::before {
+ content: "";
+ display: block;
+ width: 56px;
+ height: 56px;
+ margin-bottom: 0.65rem;
+ background: url("../img/logo-login.svg") no-repeat center / contain;
+ filter: drop-shadow(0 0 18px rgba($accent-green, 0.22));
+ }
+
+ &::after {
+ content: "phpMyAdmin · STYGIA";
+ display: block;
+ font-size: 0.95rem;
+ font-weight: 600;
+ letter-spacing: -0.02em;
+ line-height: 1.3;
+ white-space: nowrap;
+ background: linear-gradient(
+ 90deg,
+ $accent-green 0 1.7ch,
+ $text-primary 1.7ch 8.4ch,
+ $text-muted 8.4ch 9.5ch,
+ lighten($accent-green, 12%) 9.5ch 100%
+ );
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ -webkit-text-fill-color: transparent;
+ }
+
+ img,
+ #imLogo {
+ position: absolute !important;
+ width: 1px !important;
+ height: 1px !important;
+ padding: 0 !important;
+ margin: -1px !important;
+ overflow: hidden !important;
+ clip: rect(0, 0, 0, 0) !important;
+ white-space: nowrap !important;
+ border: 0 !important;
+ opacity: 0 !important;
+ visibility: hidden !important;
+ pointer-events: none !important;
+ color: transparent !important;
+ font-size: 0 !important;
+ max-height: none !important;
+ }
+ }
+
+ // Welcome + form share one column
+ div.container {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ width: $login-col;
+ max-width: 100%;
+ margin: 0 auto;
+ padding: 0;
+ text-align: left;
+ animation: stygia-login-rise 0.55s ease-out 0.06s both;
+ }
+
+ // Welcome — secondary to the brand, centered in the column
+ h1 {
+ order: 0;
+ width: 100%;
+ margin: 0 0 1.25rem;
+ padding: 0;
+ font-size: 0.95rem;
+ font-weight: 500;
+ letter-spacing: -0.01em;
+ color: $text-muted;
+ text-align: center;
+ line-height: 1.4;
+ }
+
+ .card {
+ width: 100%;
+ background: $bg-surface;
+ border: 1px solid $border-default;
+ border-radius: $border-radius-lg;
+ box-shadow:
+ $shadow-lg,
+ 0 0 0 1px rgba($accent-green, 0.04),
+ $shadow-green;
+ overflow: hidden;
+ }
+
+ .card-header {
+ background: linear-gradient(180deg, $bg-surface-2 0%, $bg-surface 100%);
+ border-bottom: 1px solid $border-default;
+ text-align: center;
+ font-weight: $font-weight-semibold;
+ letter-spacing: -0.02em;
+ font-size: 0.95rem;
+ color: $text-primary;
+ padding: 1rem 1.25rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+
+ // Hide the odd clock/compass glyph if PMA injects an icon next to "Log in"
+ .icon,
+ img,
+ .ic_b_login,
+ .ic_s_loggoff {
+ display: none !important;
+ }
+ }
+
+ .card-body {
+ padding: 1.5rem 1.5rem 1.25rem;
+ }
+
+ .card-footer {
+ background: $bg-surface;
+ border-top: 1px solid $border-default;
+ padding: 1rem 1.5rem 1.25rem;
+ }
+
+ .row,
+ .mb-3,
+ .form-group {
+ margin-bottom: 1rem !important;
+ }
+
+ label,
+ .form-label,
+ .col-form-label {
+ color: $text-secondary;
+ font-weight: 500;
+ font-size: 0.8rem;
+ letter-spacing: 0.02em;
+ text-transform: none;
+ margin-bottom: 0.4rem;
+ display: block;
+ text-align: left;
+ }
+
+ input[type="text"],
+ input[type="password"],
+ select,
+ .form-control,
+ .form-select {
+ width: 100%;
+ max-width: 100%;
+ margin: 0 0 0.15rem;
+ padding: 0.65rem 0.85rem;
+ min-height: 2.5rem;
+ background: $bg-body;
+ border: 1px solid $border-strong;
+ border-radius: $border-radius-sm;
+ color: $text-primary;
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
+
+ &:hover {
+ border-color: $border-stronger;
+ }
+
+ &:focus {
+ border-color: $accent-green;
+ box-shadow: $input-focus-box-shadow;
+ outline: none;
+ background: $bg-body;
+ }
+ }
+
+ select,
+ .form-select {
+ appearance: none;
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23b0b0b0' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
+ background-repeat: no-repeat;
+ background-position: right 0.75rem center;
+ background-size: 12px;
+ padding-right: 2.25rem;
+ }
+
+ .btn-primary,
+ input[type="submit"],
+ button[type="submit"] {
+ width: 100%;
+ border-radius: $border-radius-pill;
+ padding: 0.65rem 1.5rem;
+ min-height: 2.6rem;
+ font-weight: 600;
+ letter-spacing: 0.01em;
+ background: $accent-green-deep;
+ border-color: $accent-green-deep;
+ color: $text-white;
+ transition: background 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
+
+ &:hover {
+ background: $accent-green-deep-hover;
+ border-color: $accent-green-deep-hover;
+ transform: translateY(-1px);
+ box-shadow: $shadow-green;
+ color: $text-white;
+ }
+
+ &:active {
+ transform: translateY(0);
+ }
+ }
+
+ // Language / footer links under the card
+ .card + *,
+ > p,
+ .footer {
+ margin-top: 1.25rem;
+ text-align: center;
+ color: $text-muted;
+ font-size: 0.8rem;
+
+ a {
+ color: $text-secondary;
+
+ &:hover {
+ color: $accent-green;
+ }
+ }
+ }
+}
+
+#login_form .card-footer {
+ text-align: stretch;
+
+ .btn,
+ input[type="submit"] {
+ width: 100%;
+ }
+}
+
+@keyframes stygia-login-fade {
+ from {
+ opacity: 0;
+ transform: translateY(-6px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes stygia-login-rise {
+ from {
+ opacity: 0;
+ transform: translateY(12px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ body#loginform {
+ a.logo,
+ div.container {
+ animation: none;
+ }
+
+ .btn-primary:hover,
+ input[type="submit"]:hover,
+ button[type="submit"]:hover {
+ transform: none;
+ }
+ }
+}
diff --git a/stygia/scss/_modals.scss b/stygia/scss/_modals.scss
new file mode 100644
index 0000000000..29a05e20bc
--- /dev/null
+++ b/stygia/scss/_modals.scss
@@ -0,0 +1,263 @@
+// ============================================================
+// Stygia — Bootstrap modals + field editors (ENUM, GIS, inline)
+// ============================================================
+
+// --- Bootstrap modal shell ---
+.modal-content {
+ background-color: $bg-surface;
+ border: 1px solid $border-default;
+ border-radius: $border-radius-lg;
+ box-shadow: $shadow-lg;
+ color: $text-primary;
+}
+
+.modal-header {
+ background: $bg-surface-2;
+ border-bottom: 1px solid $border-default;
+ padding: 0.75rem 1rem;
+ border-radius: $border-radius-lg $border-radius-lg 0 0;
+
+ .modal-title {
+ font-weight: 500;
+ font-size: $h3-font-size;
+ color: $text-primary;
+ }
+}
+
+.modal-body {
+ padding: 1rem;
+ color: $text-primary;
+ background: $bg-surface;
+}
+
+.modal-footer {
+ background: $bg-surface;
+ border-top: 1px solid $border-default;
+ padding: 0.65rem 1rem;
+ gap: 0.5rem;
+ border-radius: 0 0 $border-radius-lg $border-radius-lg;
+}
+
+.modal-backdrop {
+ background-color: #000;
+
+ &.show {
+ opacity: 0.72;
+ }
+}
+
+.btn-close {
+ filter: invert(0.85) grayscale(1);
+ opacity: 0.7;
+
+ &:hover {
+ opacity: 1;
+ }
+
+ &:focus {
+ box-shadow: $shadow-focus;
+ opacity: 1;
+ }
+}
+
+// Dense tables inside modal bodies (index dialog, etc.)
+.modal-body {
+ table {
+ color: $text-primary;
+ }
+
+ .CodeMirror {
+ border: 1px solid $border-default;
+ border-radius: $border-radius-sm;
+ }
+}
+
+// --- ENUM / SET editor (#enum_editor injected into #enumEditorModal) ---
+p.enum_notice {
+ margin: 0.35rem 0.15rem 0.65rem;
+ font-size: 0.8rem;
+ color: $text-muted;
+ font-weight: 300;
+}
+
+#enum_editor {
+ p {
+ margin-top: 0;
+ font-style: italic;
+ color: $text-secondary;
+ font-size: 0.85rem;
+ font-weight: 300;
+ }
+
+ .values {
+ width: 100%;
+ background: $bg-surface-2;
+ border: 1px solid $border-default;
+ border-radius: $border-radius-sm;
+ padding: 0.5rem;
+ max-height: 220px;
+ overflow-y: auto;
+
+ td.drop {
+ width: 1.8em;
+ cursor: pointer;
+ vertical-align: middle;
+ color: $text-muted;
+
+ &:hover {
+ color: $color-danger;
+ }
+ }
+
+ input {
+ margin: 0.15em 0;
+ padding-right: 2em;
+ width: 100%;
+ min-height: 1.85rem;
+ }
+
+ img {
+ vertical-align: middle;
+ }
+
+ tr:hover td {
+ background: $bg-hover;
+ }
+ }
+
+ .add {
+ width: 100%;
+ margin-top: 0.65rem;
+
+ td {
+ vertical-align: middle;
+ width: 50%;
+ padding: 0;
+ padding-inline-start: 0.75em;
+ }
+ }
+
+ input.add_value {
+ margin: 0;
+ margin-inline-end: 0.4em;
+ }
+}
+
+#enum_editor_output textarea {
+ width: 100%;
+ margin: 1em 0 0;
+ font-family: $font-family-monospace;
+ min-height: 4rem;
+}
+
+.enum_hint {
+ position: relative;
+
+ a {
+ position: absolute;
+ inset-inline-start: 81%;
+ bottom: 0.35em;
+ }
+}
+
+// --- GIS editor ---
+#gisEditorModal {
+ .modal-body {
+ min-height: 12rem;
+ }
+}
+
+#gis_editor {
+ color: $text-primary;
+
+ label {
+ color: $text-secondary;
+ font-size: 0.8rem;
+ font-weight: 400;
+ }
+
+ select,
+ input[type="text"],
+ input[type="number"] {
+ min-height: 1.85rem;
+ }
+
+ // Visualization / map canvas area
+ #placeholder,
+ .gis_canvas,
+ .ol-viewport,
+ canvas {
+ background: $bg-surface;
+ border: 1px solid $border-default;
+ border-radius: $border-radius-sm;
+ }
+
+ #visualization {
+ background: $bg-surface;
+ border: 1px solid $border-default;
+ border-radius: $border-radius-sm;
+ padding: 0.5rem;
+ margin: 0.75rem 0;
+ }
+
+ textarea,
+ #gis_data_textarea,
+ .gis_data {
+ font-family: $font-family-monospace;
+ font-size: 0.8rem;
+ }
+
+ .form-check-label {
+ color: $text-primary;
+ }
+}
+
+// GIS data editor form (loaded into #gis_editor)
+#gis_data_editor_form,
+form[name="gis_data"] {
+ .card,
+ fieldset {
+ background: $bg-surface;
+ border-color: $border-default;
+ }
+}
+
+// --- Inline cell editor (browse) — keep datepicker visible ---
+.cEdit {
+ overflow: visible;
+
+ .edit_area {
+ overflow: visible;
+ box-shadow: $shadow-md;
+ }
+
+ // Datepicker is repositioned relative inside .cEdit by host JS
+ #ui-datepicker-div,
+ .ui-datepicker {
+ position: relative;
+ }
+
+ img.ui-datepicker-trigger {
+ vertical-align: middle;
+ }
+
+ input[type="text"].datefield,
+ input[type="text"].datetimefield,
+ input[type="text"].timefield {
+ font-family: $font-family-monospace;
+ font-variant-numeric: tabular-nums;
+ min-height: 1.85rem;
+ padding: 0.25rem 0.5rem;
+ }
+}
+
+// Preview SQL / index dialog body polish
+#previewSqlModal .modal-body,
+#indexDialogModal .modal-body,
+#previewSqlConfirmModal .modal-body {
+ .CodeMirror,
+ pre,
+ code {
+ font-family: $font-family-monospace;
+ }
+}
diff --git a/stygia/scss/_nav.scss b/stygia/scss/_nav.scss
new file mode 100644
index 0000000000..91bca42bfa
--- /dev/null
+++ b/stygia/scss/_nav.scss
@@ -0,0 +1,129 @@
+// ============================================================
+// Stygia — Nav pills & tabs
+// Feel like tabs (underline), not primary CTA pills
+// ============================================================
+
+.nav-pills {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0;
+ border-bottom: 1px solid $border-default;
+ margin-bottom: 0;
+ padding: 0;
+
+ .nav-item {
+ margin: 0;
+ }
+
+ .nav-link {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.4em;
+ margin: 0;
+ padding: 0.55rem 0.9rem;
+ font-weight: 400;
+ font-size: 0.875rem;
+ line-height: 1.3;
+ color: $text-secondary;
+ background: transparent;
+ border: 0;
+ border-bottom: 2px solid transparent;
+ border-radius: 0;
+ white-space: nowrap;
+ transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
+
+ .icon {
+ width: 14px !important;
+ height: 14px !important;
+ min-width: 14px !important;
+ min-height: 14px !important;
+ margin: 0;
+ background-color: $text-muted;
+ flex-shrink: 0;
+ }
+
+ &:hover,
+ &:focus {
+ color: $text-primary;
+ background: $bg-hover;
+ border-bottom-color: $border-strong;
+
+ .icon {
+ background-color: $text-primary;
+ }
+ }
+
+ &.active {
+ color: $accent-green;
+ background: transparent;
+ border-bottom-color: $accent-green;
+ font-weight: 500;
+
+ .icon {
+ background-color: $accent-green;
+ }
+ }
+ }
+}
+
+.nav-tabs {
+ border-bottom: 1px solid $border-default;
+ font-weight: 400;
+
+ .nav-link {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.4em;
+ margin-bottom: -1px;
+ padding: 0.5rem 0.85rem;
+ font-weight: 400;
+ color: $text-secondary;
+ background: transparent;
+ border: 1px solid transparent;
+ border-top-left-radius: $border-radius-sm;
+ border-top-right-radius: $border-radius-sm;
+
+ .icon {
+ width: 14px !important;
+ height: 14px !important;
+ min-width: 14px !important;
+ min-height: 14px !important;
+ margin: 0;
+ background-color: $text-muted;
+ }
+
+ &:hover,
+ &:focus {
+ color: $text-primary;
+ background: $bg-hover;
+ border-color: $border-default $border-default $border-default;
+
+ .icon {
+ background-color: $text-primary;
+ }
+ }
+
+ &.active {
+ color: $accent-green;
+ background: $bg-surface;
+ border-color: $border-default $border-default $bg-surface;
+ font-weight: 500;
+
+ .icon {
+ background-color: $accent-green;
+ }
+ }
+ }
+}
+
+// Top menu = same tab language
+#topmenucontainer {
+ .nav-pills {
+ border-bottom: 0;
+ }
+
+ .navbar-nav.nav-pills,
+ .nav.nav-pills {
+ width: 100%;
+ }
+}
diff --git a/stygia/scss/_navbar.scss b/stygia/scss/_navbar.scss
new file mode 100644
index 0000000000..ced80d68b6
--- /dev/null
+++ b/stygia/scss/_navbar.scss
@@ -0,0 +1,329 @@
+// ============================================================
+// Stygia — Navbar
+// ============================================================
+
+#floating_menubar {
+ z-index: 99;
+ position: sticky;
+ top: 0;
+ background: $bg-body;
+}
+
+.navbar {
+ background: $bg-body;
+ border-bottom: 1px solid $border-default;
+ padding: 0 1rem;
+ min-height: $navbar-height;
+
+ .navbar-collapse {
+ padding: 0;
+ }
+}
+
+.navbar.bg-light {
+ background: $bg-body;
+ border-bottom: 1px solid $border-default;
+}
+
+.navbar-nav {
+ font-weight: 400;
+ gap: 0;
+
+ .nav-link {
+ color: $text-secondary;
+ padding: 0.45rem 0.75rem;
+ font-size: 0.875em;
+ font-weight: 400;
+ min-height: 36px;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.35em;
+ transition: color 0.15s ease, background 0.15s ease;
+
+ .icon {
+ width: 14px;
+ height: 14px;
+ margin: 0;
+ background-color: $text-muted;
+ }
+
+ &:hover,
+ &:focus {
+ color: $text-primary;
+ background: $bg-hover;
+
+ .icon {
+ background-color: $text-primary;
+ }
+ }
+ }
+}
+
+.navbar-nav .icon {
+ margin-right: 0;
+ vertical-align: middle;
+}
+
+.navbar-nav .nav-item {
+ background: transparent;
+ border: none;
+ border-bottom: 2px solid transparent;
+ border-radius: 0;
+ padding: 0;
+
+ .nav-link {
+ color: $text-secondary;
+ padding: 0.45rem 0.75rem;
+ font-size: 0.875em;
+ font-weight: 400;
+ transition: color 0.15s ease, background 0.15s ease;
+
+ &:hover {
+ background: $bg-hover;
+ color: $text-primary;
+ }
+ }
+
+ &.active {
+ background: transparent;
+
+ .nav-link {
+ color: $accent-green;
+ border-bottom: 2px solid $accent-green;
+ font-weight: 500;
+ background: transparent;
+
+ .icon {
+ background-color: $accent-green;
+ }
+ }
+ }
+}
+
+.navbar-brand {
+ color: $text-primary;
+ &:hover {
+ color: $accent-green;
+ }
+}
+
+.navbar-toggler {
+ border-color: $border-default;
+ color: $text-secondary;
+ padding: 0.35rem 0.5rem;
+ min-width: 36px;
+ min-height: 36px;
+
+ .navbar-toggler-icon {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(180, 180, 180, 1)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
+ }
+
+ &:hover {
+ color: $text-primary;
+ background: $bg-hover;
+ }
+}
+
+.nav-link {
+ color: $text-secondary;
+
+ &:hover {
+ color: $text-primary;
+ }
+}
+
+// Breadcrumb navbar
+.breadcrumb-navbar {
+ background: $bg-surface;
+ border-bottom: 1px solid $border-default;
+ padding: 6px 1rem;
+ margin-bottom: 0;
+ border-radius: 0;
+ min-height: $breadcrumb-height;
+ position: sticky;
+ top: $navbar-height;
+ z-index: 98;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 0.25rem 0.5rem;
+
+ .breadcrumb-item {
+ color: $text-secondary;
+ font-size: 0.85em;
+ line-height: 1.4;
+
+ a {
+ color: $text-secondary;
+ text-decoration: none;
+ transition: color 0.15s ease;
+ padding: 0.15rem 0;
+
+ &:hover {
+ color: $accent-green;
+ text-decoration: none;
+ }
+ }
+
+ &.active {
+ color: $text-primary;
+ font-weight: 500;
+ }
+
+ + .breadcrumb-item::before {
+ color: $text-muted;
+ }
+ }
+
+ .breadcrumb-comment {
+ color: $text-muted;
+ font-size: 0.85em;
+ font-style: italic;
+ }
+}
+
+// Top menu container
+#topmenucontainer {
+ padding: 0 1em;
+ width: 100%;
+ border-bottom: 1px solid $border-default;
+ background: $bg-body;
+
+ .menucontainer {
+ padding: 0;
+ text-align: left;
+ }
+
+ ul,
+ li {
+ text-align: left;
+ }
+}
+
+// Page nav icons (top-right toolbar)
+#page_nav_icons {
+ position: fixed;
+ top: 0;
+ right: 0;
+ z-index: 100;
+ margin: 0 !important;
+ padding: 0 8px !important;
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 2px;
+ min-height: $navbar-height;
+ height: $navbar-height;
+ background: $bg-body;
+ border-bottom: 1px solid $border-default;
+ border-left: 1px solid $border-default;
+ box-sizing: border-box;
+
+ // Neutralize Bootstrap row/col spacing that throws off icon alignment
+ &.row {
+ --bs-gutter-x: 0;
+ --bs-gutter-y: 0;
+ }
+
+ > .col-12 {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 2px;
+ width: auto;
+ padding: 0;
+ margin: 0;
+ flex: 0 0 auto;
+ }
+
+ .dropdown-toggle {
+ color: $text-secondary;
+ border-color: $border-strong;
+ background: transparent;
+ padding: 0;
+ font-size: 0.8em;
+ width: 28px;
+ height: 28px;
+ min-width: 28px;
+ min-height: 28px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: $border-radius-sm;
+ line-height: 1;
+
+ &:hover,
+ &:focus-visible {
+ color: $text-primary;
+ background: $bg-hover;
+ }
+
+ .icon {
+ margin: 0;
+ width: 14px;
+ height: 14px;
+ min-width: 14px;
+ min-height: 14px;
+ padding: 0;
+ }
+ }
+
+ // Chrome controls only — do not style dropdown links/spans
+ #goto_pagetop,
+ #lock_page_icon,
+ #page_settings_icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 28px;
+ height: 28px;
+ min-width: 28px;
+ min-height: 28px;
+ padding: 0;
+ margin: 0;
+ line-height: 0;
+ vertical-align: middle;
+ border-radius: $border-radius-sm;
+ color: $text-secondary;
+ box-sizing: border-box;
+ text-decoration: none;
+ transition: color 0.15s ease, background-color 0.15s ease;
+
+ &:hover,
+ &:focus-visible {
+ color: $text-primary;
+ background: $bg-hover;
+ text-decoration: none;
+ }
+
+ .icon {
+ display: block;
+ width: 14px !important;
+ height: 14px !important;
+ min-width: 14px !important;
+ min-height: 14px !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ box-sizing: border-box;
+ vertical-align: middle;
+ background-color: $text-secondary;
+ background-origin: padding-box;
+ border-radius: 0;
+ }
+
+ &:hover .icon,
+ &:focus-visible .icon {
+ background-color: $text-primary;
+ }
+ }
+}
+
+#page_settings_icon {
+ cursor: pointer;
+ display: none;
+}
+
+#lock_page_icon:empty {
+ display: none;
+}
diff --git a/stygia/scss/_navigation.scss b/stygia/scss/_navigation.scss
new file mode 100644
index 0000000000..8b91eb8dfe
--- /dev/null
+++ b/stygia/scss/_navigation.scss
@@ -0,0 +1,791 @@
+// ============================================================
+// Stygia — Navigation Sidebar
+// Green left border active indicator
+// ============================================================
+
+#pma_navigation {
+ width: $navi-width;
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100vh;
+ background: $bg-surface;
+ color: $navi-color;
+ z-index: 800;
+ border-right: 1px solid $border-default;
+ display: flex;
+ flex-direction: column;
+
+ ul {
+ margin: 0;
+ }
+
+ form {
+ margin: 0;
+ padding: 0;
+ display: inline;
+ }
+
+ select {
+ select_server,
+ lightm_db {
+ width: 100%;
+ }
+ }
+
+ div {
+ &.pageselector {
+ text-align: left;
+ margin: 0;
+ padding: 4px 10px;
+ }
+ }
+
+ #pmalogo {
+ text-align: left;
+ padding: 12px 12px 10px;
+ border: 0;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+
+ // Single CSS lockup: mark + wordmark. Host may inject
![]()
(PNG)
+ // or fall back to
phpMyAdmin
— both must stay invisible.
+ a,
+ a[href] {
+ display: inline-flex !important;
+ align-items: center;
+ gap: 8px;
+ width: auto !important;
+ max-width: 100%;
+ height: 28px;
+ min-height: 28px;
+ padding: 0;
+ margin: 0;
+ background: none !important;
+ background-image: none !important;
+ overflow: visible;
+ text-decoration: none !important;
+ position: relative;
+ font-size: 0; // kill any leaked host text metrics
+ line-height: 0;
+
+ &::before {
+ content: "";
+ display: block;
+ flex-shrink: 0;
+ width: 24px;
+ height: 24px;
+ background: url("../img/logo-mark.svg") no-repeat center / contain;
+ }
+
+ &::after {
+ content: "phpMyAdmin · Stygia";
+ display: block;
+ font-size: 13px;
+ font-weight: 600;
+ letter-spacing: -0.02em;
+ line-height: 24px;
+ white-space: nowrap;
+ color: $text-primary;
+ // php accent + Stygia mint via clipped gradient on the wordmark
+ background: linear-gradient(
+ 90deg,
+ $accent-green 0 1.7ch,
+ $text-primary 1.7ch 8.4ch,
+ $text-muted 8.4ch 9.5ch,
+ lighten($accent-green, 12%) 9.5ch 100%
+ );
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ -webkit-text-fill-color: transparent;
+ }
+
+ img,
+ h1,
+ #imgpmalogo {
+ position: absolute !important;
+ width: 1px !important;
+ height: 1px !important;
+ padding: 0 !important;
+ margin: -1px !important;
+ overflow: hidden !important;
+ clip: rect(0, 0, 0, 0) !important;
+ white-space: nowrap !important;
+ border: 0 !important;
+ opacity: 0 !important;
+ visibility: hidden !important;
+ pointer-events: none !important;
+ color: transparent !important;
+ font-size: 0 !important;
+ }
+ }
+
+ // Bare h1 if host renders without a wrapping link
+ > h1 {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ margin: 0;
+ font-size: 0;
+ line-height: 0;
+ color: transparent;
+
+ &::before {
+ content: "";
+ display: block;
+ width: 24px;
+ height: 24px;
+ background: url("../img/logo-mark.svg") no-repeat center / contain;
+ }
+
+ &::after {
+ content: "phpMyAdmin · Stygia";
+ font-size: 13px;
+ font-weight: 600;
+ letter-spacing: -0.02em;
+ line-height: 24px;
+ white-space: nowrap;
+ background: linear-gradient(
+ 90deg,
+ $accent-green 0 1.7ch,
+ $text-primary 1.7ch 8.4ch,
+ $text-muted 8.4ch 9.5ch,
+ lighten($accent-green, 12%) 9.5ch 100%
+ );
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ -webkit-text-fill-color: transparent;
+ }
+ }
+ }
+
+ #serverChoice,
+ #databaseList,
+ div.pageselector.dbselector {
+ text-align: left;
+ padding: 5px 10px 0;
+ border: 0;
+ }
+
+ #navipanellinks {
+ text-align: left;
+ padding: 6px 10px;
+ border: 0;
+ border-bottom: 1px solid $border-default;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 2px;
+
+ a {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 28px;
+ height: 28px;
+ min-width: 28px;
+ min-height: 28px;
+ padding: 0;
+ margin: 0;
+ color: $text-secondary;
+ border: 0;
+ border-radius: $border-radius-sm;
+ background: transparent;
+ box-sizing: border-box;
+ transition: color 0.15s ease, background 0.15s ease;
+
+ &:hover {
+ color: $text-primary;
+ background: $bg-hover;
+ text-decoration: none;
+ }
+ }
+
+ .icon {
+ margin: 0 !important;
+ width: 14px !important;
+ height: 14px !important;
+ min-width: 14px !important;
+ min-height: 14px !important;
+ background-color: $text-secondary;
+ }
+
+ a:hover .icon {
+ background-color: $text-primary;
+ }
+ }
+
+ #serverChoice select {
+ width: 80%;
+ }
+}
+
+// --- Drag & Drop / SQL Import Overlay ---
+.pma_drop_handler {
+ position: absolute;
+ bottom: 40px;
+ left: 8px;
+ right: 8px;
+ background: $bg-surface-2;
+ color: $text-secondary;
+ text-align: center;
+ padding: 12px;
+ font-size: 0.8em;
+ border: 1px dashed $border-strong;
+ border-radius: $border-radius-sm;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.2s ease;
+ z-index: 10;
+}
+
+.pma_sql_import_status {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: $bg-surface-2;
+ border-top: 1px solid $border-default;
+ padding: 0;
+ z-index: 10;
+ max-height: 0;
+ overflow: hidden;
+ transition: max-height 0.3s ease;
+
+ h2 {
+ font-size: 0.8em;
+ font-weight: 500;
+ color: $text-secondary;
+ padding: 6px 10px;
+ margin: 0;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+
+ .close,
+ .minimize {
+ cursor: pointer;
+ color: $text-secondary;
+ font-size: 1em;
+
+ &:hover {
+ color: $text-primary;
+ }
+ }
+ }
+}
+
+// Show drag handler when dragging over
+#pma_navigation.dragover .pma_drop_handler {
+ opacity: 1;
+ pointer-events: auto;
+}
+
+// Show import status when there are imports
+#pma_navigation.has-imports .pma_sql_import_status {
+ max-height: 200px;
+ overflow: auto;
+}
+
+#pma_navigation_header {
+ overflow: hidden;
+}
+
+#pma_navigation_content {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+
+ .dropdown-menu {
+ box-shadow: $shadow-md, $shadow-green;
+ }
+
+ > img.throbber {
+ display: block;
+ margin: 0.5em auto;
+ width: 20px;
+ height: 20px;
+ background: url("../img/spinner.svg") center / contain no-repeat;
+ border: 0;
+ }
+}
+
+#pma_navigation_select_database {
+ text-align: left;
+ padding: 0;
+ border: 0;
+ margin: 0;
+}
+
+#pma_navigation_db_select {
+ margin-top: 0.5em;
+ padding: 0 10px;
+
+ select {
+ background: $bg-surface;
+ border-radius: $border-radius-sm;
+ border: 1px solid $border-strong;
+ color: $text-primary;
+ padding: 0.4rem 0.5rem;
+ margin: 0;
+ width: 92%;
+ font-size: 1.11em;
+
+ &:focus {
+ border-color: $accent-green;
+ box-shadow: $input-focus-box-shadow;
+ }
+ }
+}
+
+#pma_navigation_tree_content {
+ width: 100%;
+ overflow: hidden;
+ overflow-y: auto;
+ position: absolute;
+ height: 100%;
+
+ a.hover_show_full {
+ position: relative;
+ z-index: 100;
+ vertical-align: sub;
+ }
+}
+
+#pma_navigation_tree {
+ margin: 0;
+ margin-left: 5px;
+ overflow: hidden;
+ color: $text-secondary;
+ flex: 1 1 auto;
+ min-height: 0;
+ height: auto;
+ position: relative;
+
+ a {
+ color: $text-secondary;
+ padding-left: 0;
+ text-decoration: none;
+ transition: color 0.15s ease, background-color 0.15s ease;
+
+ &:hover {
+ color: $text-primary;
+ text-decoration: none;
+ }
+ }
+
+ ul {
+ clear: both;
+ padding: 0;
+ list-style-type: none;
+ margin: 0;
+
+ ul {
+ position: relative;
+ }
+ }
+
+ li {
+ margin-bottom: 0;
+ color: $text-secondary;
+
+ // Only the hovered/selected *row* — not every descendant link
+ &.activePointer,
+ &.selected {
+ color: $text-primary;
+ background-color: rgba($accent-green, 0.06);
+ border-radius: 0;
+ border-left: 0;
+ padding-left: 0;
+ box-shadow: inset 2px 0 0 $accent-green;
+
+ // Nested tree under a selected DB stays neutral (readable grey)
+ > .list_container,
+ > ul {
+ background: $navi-background;
+ box-shadow: none;
+ color: $text-secondary;
+
+ > li {
+ background: transparent;
+ box-shadow: none;
+ }
+
+ a {
+ color: $text-secondary;
+
+ &:hover {
+ color: $text-primary;
+ }
+ }
+ }
+
+ // Direct label of this row only
+ > a {
+ color: $accent-green;
+ }
+ }
+
+ // Nested selected/hovered rows still get the accent
+ .list_container li.activePointer,
+ .list_container li.selected,
+ ul li.activePointer,
+ ul li.selected {
+ background-color: rgba($accent-green, 0.06);
+ box-shadow: inset 2px 0 0 $accent-green;
+
+ > a {
+ color: $accent-green;
+ }
+ }
+
+ .dbItemControls {
+ padding-right: 4px;
+ float: right;
+ display: flex;
+ align-items: center;
+ gap: 2px;
+ }
+
+ .navItemControls {
+ display: none;
+ padding-right: 4px;
+ float: right;
+ align-items: center;
+ gap: 2px;
+
+ a,
+ .icon {
+ min-width: 28px;
+ min-height: 28px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: $border-radius-sm;
+ }
+ }
+
+ &.activePointer .navItemControls,
+ &:focus-within .navItemControls {
+ display: flex;
+ opacity: 0.85;
+
+ &:hover,
+ &:focus-within {
+ opacity: 1;
+ }
+
+ a:hover,
+ a:focus-visible {
+ background: $bg-hover;
+ opacity: 1;
+ }
+ }
+ }
+
+ li {
+ white-space: nowrap;
+ clear: both;
+ min-height: 16px;
+
+ &.fast_filter {
+ white-space: normal;
+ clear: both;
+ min-height: 28px;
+ overflow: visible;
+ }
+ }
+
+ img {
+ margin: 0;
+ }
+
+ i {
+ display: block;
+ }
+
+ div {
+ &.block {
+ position: relative;
+ width: 1.5em;
+ height: 1.5em;
+ min-width: 16px;
+ min-height: 16px;
+ float: left;
+
+ &.double {
+ width: 2.5em;
+ }
+
+ i,
+ b {
+ width: 1.5em;
+ height: 1.7em;
+ min-width: 16px;
+ min-height: 8px;
+ position: absolute;
+ bottom: 0.7em;
+ left: 0.75em;
+ z-index: 0;
+ }
+
+ i {
+ display: block;
+ border-left: 1px solid $border-default;
+ border-bottom: 1px solid $border-default;
+ position: relative;
+ z-index: 0;
+
+ &.first {
+ border-left: 0;
+ }
+ }
+
+ b {
+ display: block;
+ height: 0.75em;
+ bottom: -0.5rem;
+ left: 0.75em;
+ border-left: 1px solid $border-default;
+ }
+
+ a,
+ u {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ z-index: 10;
+ }
+
+ a + a {
+ left: 100%;
+ }
+
+ &.double {
+ a,
+ u {
+ left: 33%;
+ }
+ a + a {
+ left: 85%;
+ }
+ }
+
+ img {
+ position: relative;
+ top: -0.6em;
+ left: 0;
+ margin-left: -7px;
+ }
+ }
+
+ &.throbber img {
+ top: 2px;
+ left: 2px;
+ }
+ }
+
+ li {
+ &.last > ul {
+ background: none;
+ }
+
+ > {
+ a,
+ i {
+ line-height: 1.5em;
+ height: 1.5em;
+ padding-left: 0.3em;
+ }
+ }
+ }
+
+ .list_container {
+ border-left: 1px solid $border-default;
+ margin-left: 0.5em;
+ padding-left: 0.5em;
+
+ li.last.database {
+ margin-bottom: 0 !important;
+ }
+ }
+
+ .last > .list_container {
+ border-left: 0 solid $border-default;
+ }
+}
+
+// Fast filter — full width of sidebar, clear button inside the field
+li.fast_filter {
+ position: relative;
+ padding: 6px 8px;
+ margin: 0;
+ border-left: 0;
+ list-style: none;
+ white-space: normal;
+ overflow: visible;
+ max-width: 100%;
+ box-sizing: border-box;
+
+ input,
+ input[type="text"] {
+ font-size: 0.75rem;
+ min-height: 28px;
+ width: 100%;
+ max-width: 100%;
+ margin: 0 !important;
+ padding: 0.35rem 1.75rem 0.35rem 0.5rem;
+ box-sizing: border-box;
+ }
+
+ .searchClauseClear {
+ position: absolute;
+ right: 12px;
+ top: 50%;
+ transform: translateY(-50%);
+ border: 0;
+ background: transparent;
+ font-weight: bold;
+ color: $color-danger;
+ font-size: 1rem;
+ line-height: 1;
+ min-width: 24px;
+ min-height: 24px;
+ padding: 0;
+ cursor: pointer;
+ z-index: 2;
+ }
+
+ .searchClauseClear:hover {
+ background-color: transparent;
+ border-color: transparent;
+ color: lighten($color-danger, 8%);
+ }
+
+ &.db_fast_filter {
+ border: 0;
+ margin-left: 0;
+ padding: 6px 8px;
+ }
+}
+
+#navigation_controls_outer {
+ min-height: 36px !important;
+ padding: 4px 8px;
+ clear: both;
+
+ &.activePointer {
+ background-color: transparent !important;
+ box-shadow: none !important;
+ }
+}
+
+#navigation_controls {
+ float: none;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ padding: 0;
+ flex-wrap: wrap;
+
+ a,
+ .icon {
+ min-width: 32px;
+ min-height: 32px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: $border-radius-sm;
+ }
+
+ select,
+ .pageselector {
+ margin: 0;
+ }
+}
+
+// Resize handler
+#pma_navigation_resizer {
+ width: 3px;
+ height: 100%;
+ background-color: $border-default;
+ cursor: col-resize;
+ position: fixed;
+ top: 0;
+ left: $navi-width;
+ z-index: 801;
+}
+
+#pma_navigation_collapser {
+ width: 20px;
+ height: 35px;
+ line-height: 35px;
+ background: $bg-surface-2;
+ color: $text-secondary;
+ font-weight: 500;
+ position: fixed;
+ top: 0;
+ left: $navi-width;
+ text-align: center;
+ cursor: pointer;
+ z-index: 800;
+ border: 1px solid $border-default;
+ border-left: 0;
+ border-radius: 0 $border-radius-sm $border-radius-sm 0;
+ transition: background 0.15s ease, color 0.15s ease;
+
+ &:hover {
+ background: $bg-hover;
+ color: $text-primary;
+ }
+}
+
+// --- Recent / Favorites Quick Access ---
+#recentFavoriteTablesWrapper {
+ padding: 0 8px;
+ margin-bottom: 8px;
+
+ .btn-outline-secondary {
+ color: $text-secondary;
+ border-color: $border-strong;
+ background: transparent;
+ font-size: 0.8em;
+ padding: 3px 10px;
+ border-radius: 9999px;
+
+ &:hover {
+ color: $text-primary;
+ background: $bg-hover;
+ border-color: $border-strong;
+ }
+
+ &.show {
+ color: $text-primary;
+ background: $bg-hover;
+ }
+ }
+
+ .dropdown-menu {
+ background: $bg-surface-2;
+ border: 1px solid $border-default;
+ border-radius: $border-radius-sm;
+ padding: 4px 0;
+ font-size: 0.85em;
+
+ .dropdown-item {
+ color: $text-secondary;
+ padding: 4px 12px;
+
+ &:hover {
+ background: $bg-hover;
+ color: $text-primary;
+ }
+ }
+ }
+}
diff --git a/stygia/scss/_print.scss b/stygia/scss/_print.scss
new file mode 100644
index 0000000000..5e732a0397
--- /dev/null
+++ b/stygia/scss/_print.scss
@@ -0,0 +1,118 @@
+// ============================================================
+// Stygia — Print Styles
+// ============================================================
+
+@media print {
+ .hide {
+ display: none;
+ }
+
+ // Standard CSS
+ body,
+ table,
+ th,
+ td {
+ color: #000;
+ background-color: #fff;
+ font-size: 12px;
+ }
+
+ // Remove link decoration
+ a:link {
+ color: #000;
+ text-decoration: none;
+ }
+
+ // Remove image borders
+ img {
+ border: 0;
+ }
+
+ // Table specific
+ table,
+ th,
+ td {
+ border: 0.1em solid #000;
+ background-color: #fff;
+ }
+
+ table {
+ border-collapse: collapse;
+ border-spacing: 0.2em;
+ }
+
+ thead {
+ border-collapse: collapse;
+ border-spacing: 0.2em;
+ border: 0.1em solid #000;
+ font-weight: 900;
+ }
+
+ th,
+ td {
+ padding: 0.2em;
+ }
+
+ thead th {
+ font-weight: bold;
+ background-color: #e5e5e5;
+ border: 0.1em solid #000;
+ }
+
+ // Position the main content
+ #page_content {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 95%;
+ float: none;
+ }
+
+ .sqlOuter {
+ color: black;
+ background-color: #fff;
+ }
+
+ // Hide buttons in print
+ .cDrop,
+ .cEdit,
+ .cList,
+ .cCpy,
+ .cPointer {
+ display: none;
+ }
+
+ table tbody:first-of-type tr {
+ &:nth-child(odd) {
+ background: #fff;
+ th {
+ background: #fff;
+ }
+ }
+
+ &:nth-child(even) {
+ background: #dfdfdf;
+ th {
+ background: #dfdfdf;
+ }
+ }
+ }
+
+ .column_attribute {
+ font-size: 100%;
+ }
+
+ // Navigation and console
+ #pma_navigation,
+ #pma_console_container,
+ #floating_menubar,
+ .navbar {
+ display: none !important;
+ }
+
+ // Adjust main content for print
+ #page_content {
+ margin-left: 0;
+ width: 100%;
+ }
+}
diff --git a/stygia/scss/_profiling.scss b/stygia/scss/_profiling.scss
new file mode 100644
index 0000000000..c81f946505
--- /dev/null
+++ b/stygia/scss/_profiling.scss
@@ -0,0 +1,298 @@
+// ============================================================
+// Stygia — SQL Profiling (tables + chart panel)
+// Chart slice colors come from Chart.js host defaults; we polish
+// layout, tables, and the canvas presentation only.
+// ============================================================
+
+// Sortable headers (tablesorter) — used by profiling tables
+th.header {
+ cursor: pointer;
+ color: $text-secondary;
+ user-select: none;
+
+ &:hover {
+ color: $text-primary;
+ text-decoration: none;
+ }
+
+ .sorticon {
+ width: 14px;
+ height: 14px;
+ margin-left: 0.35rem;
+ display: inline-block;
+ vertical-align: middle;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: contain;
+ opacity: 0.35;
+ }
+}
+
+th.headerSortUp .sorticon {
+ background-image: url("../img/sort-desc.svg");
+ opacity: 0.85;
+}
+
+th.headerSortDown {
+ .sorticon {
+ background-image: url("../img/sort-asc.svg");
+ opacity: 0.85;
+ }
+
+ &:hover .sorticon {
+ background-image: url("../img/sort-desc.svg");
+ }
+}
+
+th.headerSortUp:hover .sorticon {
+ background-image: url("../img/sort-asc.svg");
+}
+
+// Full-bleed profiling block inside Bootstrap .container
+.container:has(#profiletable),
+.container:has(#profilingChartCanvas) {
+ max-width: 100%;
+ padding-inline: 0;
+}
+
+.card:has(#profiletable),
+.card:has(#profilingChartCanvas) {
+ margin-top: 1rem;
+ overflow: hidden;
+
+ > .card-header {
+ font-weight: 500;
+ letter-spacing: 0.02em;
+ }
+
+ .card-body {
+ padding: 1.1rem 1.15rem 1.25rem;
+ }
+
+ // Three panels: detail | summary | chart
+ .card-body > .row {
+ display: grid;
+ grid-template-columns: minmax(200px, 0.85fr) minmax(260px, 1.2fr) minmax(240px, 0.95fr);
+ gap: 1.25rem;
+ align-items: start;
+
+ > .col {
+ width: auto;
+ max-width: none;
+ flex: none;
+ padding: 0;
+ min-width: 0;
+ }
+
+ @media (max-width: 1200px) {
+ grid-template-columns: 1fr 1fr;
+
+ > .col:has(#profilingChartCanvas) {
+ grid-column: 1 / -1;
+ }
+ }
+
+ @media (max-width: 768px) {
+ grid-template-columns: 1fr;
+ }
+ }
+
+ h3 {
+ display: flex;
+ align-items: center;
+ gap: 0.4rem;
+ margin: 0 0 0.7rem;
+ padding: 0;
+ font-size: 0.72rem;
+ font-weight: 500;
+ line-height: 1.3;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ color: $text-muted;
+
+ .icon {
+ width: 14px;
+ height: 14px;
+ opacity: 0.7;
+ }
+
+ a {
+ display: inline-flex;
+ color: $text-muted;
+
+ &:hover {
+ color: $accent-green;
+ }
+ }
+ }
+}
+
+@mixin profiling-table {
+ width: 100%;
+ margin: 0;
+ font-size: 0.8125rem;
+ border: 1px solid $border-default;
+ border-radius: $border-radius-sm;
+ border-collapse: separate;
+ border-spacing: 0;
+ overflow: hidden;
+ background: $bg-surface;
+
+ thead th {
+ position: relative;
+ padding: 0.5rem 0.65rem;
+ font-size: 0.68rem;
+ font-weight: 500;
+ letter-spacing: 0.05em;
+ text-transform: uppercase;
+ white-space: nowrap;
+ color: $text-muted;
+ background: $bg-surface-2;
+ border-bottom: 1px solid $border-strong;
+ border-right: 1px solid $border-default;
+ vertical-align: middle;
+
+ &:last-child {
+ border-right: 0;
+ }
+
+ &.header {
+ color: $text-secondary;
+ }
+ }
+
+ tbody {
+ tr {
+ transition: background-color 0.12s ease;
+
+ &:hover {
+ background: rgba($accent-green, 0.06);
+ }
+
+ &:last-child td {
+ border-bottom: 0;
+ }
+ }
+
+ td {
+ padding: 0.38rem 0.65rem;
+ border-bottom: 1px solid $border-default;
+ border-right: 1px solid rgba($border-default, 0.6);
+ vertical-align: middle;
+ color: $text-primary;
+ line-height: 1.35;
+
+ &:last-child {
+ border-right: 0;
+ }
+ }
+ }
+
+ // Times / counts — never wrap "281 µs"
+ td.text-end {
+ white-space: nowrap;
+ font-family: $font-family-monospace;
+ font-size: 0.75rem;
+ font-variant-numeric: tabular-nums;
+ font-weight: 400;
+ letter-spacing: 0.01em;
+ color: $odp-whiskey;
+ }
+
+ .rawvalue {
+ display: none !important;
+ }
+}
+
+#profiletable {
+ @include profiling-table;
+
+ // Order
+ tbody td:nth-child(1) {
+ width: 1%;
+ white-space: nowrap;
+ font-variant-numeric: tabular-nums;
+ font-family: $font-family-monospace;
+ font-size: 0.75rem;
+ color: $text-muted;
+ text-align: end;
+ }
+
+ // State
+ tbody td:nth-child(2) {
+ color: $text-primary;
+ white-space: nowrap;
+ }
+}
+
+#profilesummarytable {
+ @include profiling-table;
+
+ // State name
+ tbody td:nth-child(1) {
+ white-space: nowrap;
+ color: $text-primary;
+ font-weight: 400;
+ }
+
+ // % Time — scannable accent
+ tbody td:nth-child(3) {
+ white-space: nowrap;
+ font-family: $font-family-monospace;
+ font-variant-numeric: tabular-nums;
+ font-size: 0.75rem;
+ font-weight: 500;
+ color: $accent-green;
+ }
+
+ // Calls
+ tbody td:nth-child(4) {
+ white-space: nowrap;
+ font-variant-numeric: tabular-nums;
+ font-family: $font-family-monospace;
+ font-size: 0.75rem;
+ color: $text-secondary;
+ }
+}
+
+.col:has(#profiletable),
+.col:has(#profilesummarytable) {
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+// Chart panel — modern frame around host Chart.js canvas
+.col:has(#profilingChartCanvas),
+.col:has(#queryProfilingCanvas) {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ justify-content: flex-start;
+ min-height: 280px;
+ padding: 1rem 1rem 1.1rem;
+ background:
+ radial-gradient(ellipse 80% 60% at 50% 35%, rgba($accent-green, 0.06), transparent 65%),
+ $bg-surface-2;
+ border: 1px solid $border-default;
+ border-radius: $border-radius;
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
+}
+
+#profilingChartCanvas,
+#queryProfilingCanvas {
+ display: block;
+ width: 100% !important;
+ max-width: 100%;
+ height: auto !important;
+ margin: 0 auto;
+ // Soften Chart.js default rainbow toward Stygia dark UI
+ filter: saturate(0.7) brightness(0.9) contrast(1.04);
+}
+
+// Query stats pie (same Chart.js default look)
+#query-statistics-chart {
+ display: block;
+ max-width: 100%;
+ height: auto !important;
+ filter: saturate(0.7) brightness(0.9) contrast(1.04);
+}
diff --git a/stygia/scss/_reboot.scss b/stygia/scss/_reboot.scss
new file mode 100644
index 0000000000..3f9878d974
--- /dev/null
+++ b/stygia/scss/_reboot.scss
@@ -0,0 +1,182 @@
+// ============================================================
+// Stygia — Reboot / Base Element Overrides
+// ============================================================
+
+body {
+ text-align: left;
+ background: var(--stygia-bg-body, #{$bg-body});
+ color: var(--stygia-text-primary, #{$text-primary});
+ color-scheme: dark;
+ font-weight: 400;
+ line-height: 1.5;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+p,
+.card-text,
+.form-text,
+small,
+.small {
+ font-weight: 300;
+ color: $text-secondary;
+}
+
+label,
+.form-label,
+.col-form-label {
+ font-weight: 400;
+}
+
+h1 {
+ font-weight: 500;
+ letter-spacing: -0.02em;
+ color: $text-primary;
+ margin: 0.5rem 0 0.75rem;
+}
+
+h2 {
+ font-weight: 500;
+ color: $text-primary;
+ padding: 0.35rem 0;
+ font-size: $h2-font-size;
+ letter-spacing: -0.015em;
+}
+
+h3,
+h4,
+h5,
+h6 {
+ font-weight: 500;
+ letter-spacing: -0.01em;
+}
+
+strong,
+b {
+ font-weight: 500;
+}
+
+input,
+select {
+ font-size: 1em;
+}
+
+textarea {
+ font-family: $font-family-monospace;
+ font-size: 1em;
+}
+
+a {
+ color: var(--stygia-accent, #{$accent-green});
+ transition: color 0.15s ease;
+
+ &:hover {
+ color: var(--stygia-accent-light, #{$accent-green-light});
+ }
+}
+
+code {
+ color: $accent-green-light;
+ background: rgba($accent-green, 0.1);
+ padding: 0.15em 0.3em;
+ border-radius: 4px;
+ font-size: 0.875em;
+}
+
+hr {
+ color: $border-default;
+ background-color: $border-default;
+ border: 0;
+ height: 1px;
+ margin: 1rem 0;
+}
+
+::selection {
+ background: rgba($accent-green, 0.25);
+ color: $text-primary;
+}
+
+::placeholder {
+ color: $text-muted;
+}
+
+:focus-visible {
+ outline: 2px solid var(--stygia-accent, #{$accent-green});
+ outline-offset: 2px;
+}
+
+:focus:not(:focus-visible) {
+ outline: none;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+
+ #pma_console_container {
+ transition: none !important;
+
+ &.expanded {
+ max-height: 60vh;
+ }
+ }
+}
+
+@media (prefers-contrast: more) {
+ :focus-visible {
+ outline-width: 3px;
+ }
+
+ .table,
+ .table th,
+ .table td {
+ border-color: $border-stronger;
+ }
+
+ a {
+ text-decoration: underline;
+ }
+}
+
+@media (forced-colors: active) {
+ :focus-visible {
+ outline: 3px solid Highlight;
+ }
+
+ .icon {
+ forced-color-adjust: auto;
+ }
+}
+
+.dropdown-menu {
+ box-shadow: $shadow-md, $shadow-green;
+}
+
+.skip-link {
+ position: absolute;
+ top: -40px;
+ left: 0;
+ background: $accent-green-deep;
+ color: $text-white;
+ padding: 8px 16px;
+ z-index: 10000;
+ text-decoration: none;
+ border-radius: 0 0 $border-radius-sm 0;
+ font-weight: 500;
+
+ &:focus {
+ top: 0;
+ }
+}
+
+@keyframes stygia-spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
diff --git a/stygia/scss/_rtl-overrides.scss b/stygia/scss/_rtl-overrides.scss
new file mode 100644
index 0000000000..ded30ad0d7
--- /dev/null
+++ b/stygia/scss/_rtl-overrides.scss
@@ -0,0 +1,150 @@
+// ============================================================
+// Stygia — RTL overrides applied AFTER rtlcss(theme.css)
+// Keep this lean: only rules rtlcss cannot infer correctly.
+// ============================================================
+
+@import "variables";
+
+// SQL / code stay LTR even in RTL UI
+#sqlquery,
+#sql_query_edit,
+.CodeMirror,
+.result_query .sqlOuter,
+textarea.codemirror-textarea {
+ direction: ltr !important;
+ text-align: left !important;
+}
+
+// Do NOT force all inputs to LTR (comments / localized text need RTL)
+
+#page_nav_icons {
+ left: 0;
+ right: auto;
+ border-left: 0;
+ border-right: 1px solid $border-default;
+}
+
+#pma_console_container {
+ left: 0;
+ right: auto;
+ width: 100%;
+}
+
+#pma_console {
+ margin-left: 0;
+ margin-right: $navi-width;
+}
+
+// Tree block connectors use absolute left; nudge for RTL
+#pma_navigation_tree div.block {
+ float: right;
+
+ i,
+ b {
+ left: auto;
+ right: 0.75em;
+ border-left: 0;
+ border-right: 1px solid $border-default;
+ }
+
+ b {
+ right: 0.75em;
+ }
+
+ a,
+ u {
+ left: auto;
+ right: 50%;
+ }
+
+ a + a {
+ left: auto;
+ right: 100%;
+ }
+
+ &.double {
+ a,
+ u {
+ left: auto;
+ right: 33%;
+ }
+
+ a + a {
+ left: auto;
+ right: 85%;
+ }
+ }
+
+ img {
+ left: auto;
+ right: 0;
+ margin-left: 0;
+ margin-right: -7px;
+ }
+}
+
+#pma_navigation_tree .list_container {
+ border-left: 0;
+ border-right: 1px solid $border-default;
+}
+
+// Selected accent bar already flipped by rtlcss for box-shadow; ensure nested reset
+#pma_navigation_tree li.activePointer > .list_container,
+#pma_navigation_tree li.selected > .list_container {
+ box-shadow: none;
+}
+
+.ic_select_all_arrow[dir="rtl"] {
+ transform: scaleX(-1);
+}
+
+// Date/time picker — grid + chrome that rtlcss cannot infer
+.ui-timepicker-div dl {
+ text-align: right;
+}
+
+.ui-datepicker {
+ .ui-datepicker-prev {
+ left: auto;
+ right: 0;
+
+ &,
+ &.ui-state-hover,
+ &.ui-datepicker-prev-hover {
+ left: auto;
+ right: 0;
+ }
+
+ span.ui-icon {
+ -webkit-mask-image: url("../img/chevron-right.svg");
+ mask-image: url("../img/chevron-right.svg");
+ }
+ }
+
+ .ui-datepicker-next {
+ right: auto;
+ left: 0;
+
+ &,
+ &.ui-state-hover,
+ &.ui-datepicker-next-hover {
+ right: auto;
+ left: 0;
+ }
+
+ span.ui-icon {
+ -webkit-mask-image: url("../img/chevron-left.svg");
+ mask-image: url("../img/chevron-left.svg");
+ }
+ }
+}
+
+.ui-dialog .ui-dialog-titlebar-close {
+ right: auto;
+ left: 0.65rem;
+}
+
+img.ui-datepicker-trigger {
+ margin-inline-start: 0;
+ margin-inline-end: 0.35rem;
+}
diff --git a/stygia/scss/_tables.scss b/stygia/scss/_tables.scss
new file mode 100644
index 0000000000..22c9ced06e
--- /dev/null
+++ b/stygia/scss/_tables.scss
@@ -0,0 +1,338 @@
+// ============================================================
+// Stygia — Tables
+// ============================================================
+
+.table {
+ caption-side: top;
+ color: $text-primary;
+ font-weight: 400;
+
+ th,
+ td {
+ vertical-align: middle;
+ color: $text-primary;
+ line-height: 1.45;
+ font-weight: 400;
+
+ > span:empty::before {
+ content: "\200b";
+ }
+ }
+
+ th {
+ color: $th-color;
+ font-weight: 500;
+ font-size: 0.8125rem;
+ }
+
+ td {
+ touch-action: manipulation;
+ }
+
+ td.value,
+ .value {
+ font-family: $font-family-monospace;
+ font-size: 0.8125rem;
+ font-weight: 400;
+ color: $text-primary;
+ letter-spacing: 0.01em;
+ }
+
+ thead th {
+ border-right: 1px solid $border-default;
+ background: $bg-surface-2;
+ border-bottom: 1px solid $border-strong;
+ }
+
+ caption {
+ background-color: $th-background;
+ font-weight: 500;
+ text-align: center;
+ color: $text-primary;
+ padding: 0.55rem;
+ border-radius: $border-radius-sm $border-radius-sm 0 0;
+ }
+
+ .cell-selected {
+ outline: 1px solid $accent-green;
+ outline-offset: -1px;
+
+ &.with-bg-color {
+ background-color: $browse-marker-background;
+ }
+ }
+
+ tbody tr.marked,
+ tbody tr.marked:hover,
+ tbody tr.selected,
+ tbody tr.selected:hover {
+ background: $browse-marker-background !important;
+ color: $browse-marker-color;
+ }
+
+ // Nested header rows (FK / relation editors)
+ thead tr + tr th {
+ font-weight: 400;
+ font-size: 0.75rem;
+ color: $text-muted;
+ text-transform: none;
+ letter-spacing: 0;
+ background: $bg-surface;
+ }
+}
+
+.table-hover {
+ tbody tr {
+ &:hover > * {
+ background: $browse-pointer-background;
+ color: $browse-pointer-color;
+ box-shadow: none;
+ }
+ }
+}
+
+.table-striped {
+ > tbody > tr:nth-of-type(#{$table-striped-order}) > * {
+ background-color: $table-striped-bg;
+ box-shadow: none;
+ }
+
+ > tbody > tr:nth-of-type(#{$table-striped-order}) > th {
+ color: $th-color;
+ }
+}
+
+@media only screen and (width >= 768px) {
+ .table th.position-sticky {
+ top: $sticky-offset;
+ z-index: 2;
+ box-shadow: 0 1px 0 $border-default;
+ }
+}
+
+.navigation {
+ margin: 0.9em 0;
+ border-radius: $border-radius;
+ background: $bg-surface-2;
+ border: 1px solid $border-default;
+ padding: 0.25rem 0.45rem;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 0.35rem;
+
+ td {
+ margin: 0;
+ padding: 0;
+ vertical-align: middle;
+ white-space: nowrap;
+ }
+}
+
+// Foreign key / relation editors
+table.relationalTable,
+#relationalTable,
+table#foreign_keys,
+.card table.table {
+ width: 100%;
+ border-collapse: separate;
+ border-spacing: 0;
+
+ th,
+ td {
+ padding: 0.55rem 0.65rem;
+ vertical-align: top;
+ border-color: $border-default;
+ }
+
+ input[type="text"],
+ select {
+ width: 100%;
+ max-width: 100%;
+ min-height: 2rem;
+ font-weight: 400;
+ }
+
+ label {
+ font-weight: 400;
+ font-size: 0.75rem;
+ color: $text-muted;
+ text-transform: none;
+ letter-spacing: 0;
+ }
+}
+
+// Soften shouting ON DELETE / ON UPDATE labels inside FK editors
+.card-body,
+#relationalTable,
+table.relationalTable {
+ td {
+ strong,
+ b,
+ label {
+ font-weight: 400;
+ color: $text-secondary;
+ font-size: 0.75rem;
+ letter-spacing: 0.02em;
+ }
+ }
+}
+
+// "+ Add constraint" / "+ Add column" as quiet actions, not orphan footers
+.card-footer {
+ a,
+ .add_foreign_key,
+ a[href*="foreign"] {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.35em;
+ font-weight: 400;
+ font-size: 0.875rem;
+ color: $accent-green;
+ text-decoration: none;
+ padding: 0.25rem 0;
+
+ &:hover {
+ color: $accent-green-light;
+ text-decoration: underline;
+ }
+ }
+}
+
+.card:has(table) {
+ .card-footer {
+ padding: 0.65rem 1rem;
+ min-height: auto;
+ background: $bg-surface-2;
+ }
+
+ .card-header {
+ font-weight: 500;
+ font-size: 0.9rem;
+ }
+}
+
+// --- Browse row actions: round icon-only 3D chips ---
+// Edit / Copy / Delete in `.table_results` + bulk `mult_submit` bar.
+$row-action-size: 1.7rem;
+
+@mixin row-action-chip($glow) {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: $row-action-size;
+ height: $row-action-size;
+ min-width: $row-action-size;
+ min-height: $row-action-size;
+ padding: 0;
+ margin: 0 0.12rem;
+ border-radius: 50%;
+ font-size: 0;
+ line-height: 0;
+ letter-spacing: 0;
+ color: transparent;
+ text-decoration: none !important;
+ vertical-align: middle;
+ cursor: pointer;
+ background:
+ linear-gradient(145deg, lighten($bg-surface-3, 4%), $bg-surface-2 45%, darken($bg-surface-2, 3%));
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ box-shadow:
+ inset 0 1px 0 rgba(255, 255, 255, 0.1),
+ inset 0 -1px 1px rgba(0, 0, 0, 0.35),
+ 0 1px 2px rgba(0, 0, 0, 0.45),
+ 0 2px 7px rgba($glow, 0.2);
+ transition:
+ box-shadow 0.18s ease,
+ transform 0.15s ease,
+ border-color 0.15s ease,
+ background 0.15s ease;
+
+ > .text-nowrap,
+ .text-nowrap {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0;
+ line-height: 0;
+ width: 100%;
+ height: 100%;
+ }
+
+ .icon {
+ margin: 0;
+ width: 13px;
+ height: 13px;
+ background-color: $text-secondary;
+ flex-shrink: 0;
+ }
+
+ &:hover,
+ &:focus-visible {
+ color: transparent;
+ text-decoration: none !important;
+ transform: translateY(-1px);
+ border-color: rgba($glow, 0.35);
+ background:
+ linear-gradient(145deg, lighten($bg-surface-3, 7%), $bg-surface-3 50%, $bg-surface-2);
+ box-shadow:
+ inset 0 1px 0 rgba(255, 255, 255, 0.14),
+ inset 0 -1px 1px rgba(0, 0, 0, 0.4),
+ 0 2px 4px rgba(0, 0, 0, 0.5),
+ 0 4px 14px rgba($glow, 0.48),
+ 0 0 0 1px rgba($glow, 0.22);
+
+ .icon {
+ background-color: $text-primary;
+ }
+ }
+
+ &:active {
+ transform: translateY(0);
+ box-shadow:
+ inset 0 1px 2px rgba(0, 0, 0, 0.45),
+ inset 0 -1px 0 rgba(255, 255, 255, 0.04),
+ 0 1px 3px rgba($glow, 0.28);
+ }
+}
+
+.table_results td.d-print-none {
+ padding-left: 0.28rem;
+ padding-right: 0.28rem;
+ white-space: nowrap;
+
+ a:has(.ic_b_edit) {
+ @include row-action-chip($color-info);
+ }
+
+ a:has(.ic_b_insrow) {
+ @include row-action-chip($accent-green);
+ }
+
+ a.delete_row,
+ a:has(.ic_b_drop) {
+ @include row-action-chip(darken($color-danger, 8%));
+ }
+}
+
+// Bulk “With selected” Edit / Copy / Delete
+button.mult_submit:has(.ic_b_edit) {
+ @include row-action-chip($color-info);
+}
+
+button.mult_submit:has(.ic_b_insrow) {
+ @include row-action-chip($accent-green);
+}
+
+button.mult_submit:has(.ic_b_drop) {
+ @include row-action-chip(darken($color-danger, 8%));
+}
+
+button.mult_submit:has(.ic_b_edit, .ic_b_insrow, .ic_b_drop) {
+ &.btn,
+ &.btn-link {
+ --bs-btn-padding-x: 0;
+ --bs-btn-padding-y: 0;
+ text-decoration: none !important;
+ }
+}
diff --git a/stygia/scss/_tokens.scss b/stygia/scss/_tokens.scss
new file mode 100644
index 0000000000..67a44a9f5f
--- /dev/null
+++ b/stygia/scss/_tokens.scss
@@ -0,0 +1,69 @@
+// ============================================================
+// Stygia — CSS custom properties (runtime-inspectable tokens)
+// Sourced from Sass variables in _variables.scss
+// ============================================================
+
+:root {
+ color-scheme: dark;
+
+ // Accent
+ --stygia-accent: #{$accent-green};
+ --stygia-accent-dark: #{$accent-green-dark};
+ --stygia-accent-light: #{$accent-green-light};
+ --stygia-accent-deep: #{$accent-green-deep};
+ --stygia-accent-deep-hover: #{$accent-green-deep-hover};
+
+ // Surfaces
+ --stygia-bg-body: #{$bg-body};
+ --stygia-bg-surface: #{$bg-surface};
+ --stygia-bg-surface-2: #{$bg-surface-2};
+ --stygia-bg-surface-3: #{$bg-surface-3};
+ --stygia-bg-surface-4: #{$bg-surface-4};
+ --stygia-bg-popover: #{$bg-popover};
+ --stygia-bg-hover: #{$bg-hover};
+ --stygia-bg-active: #{$bg-active};
+ --stygia-bg-selected: #{$bg-selected};
+
+ // Text
+ --stygia-text-primary: #{$text-primary};
+ --stygia-text-secondary: #{$text-secondary};
+ --stygia-text-muted: #{$text-muted};
+ --stygia-text-disabled: #{$text-disabled};
+
+ // Borders
+ --stygia-border-default: #{$border-default};
+ --stygia-border-strong: #{$border-strong};
+ --stygia-border-stronger: #{$border-stronger};
+
+ // Semantic
+ --stygia-success: #{$color-success};
+ --stygia-danger: #{$color-danger};
+ --stygia-warning: #{$color-warning};
+ --stygia-info: #{$color-info};
+ --stygia-string: #{$color-string};
+ --stygia-number: #{$color-number};
+
+ // One Dark Pro data-type tokens
+ --stygia-odp-chalky: #{$odp-chalky};
+ --stygia-odp-coral: #{$odp-coral};
+ --stygia-odp-green: #{$odp-green};
+ --stygia-odp-whiskey: #{$odp-whiskey};
+ --stygia-odp-malibu: #{$odp-malibu};
+ --stygia-odp-purple: #{$odp-purple};
+ --stygia-odp-fountain: #{$odp-fountain-blue};
+ --stygia-odp-comment: #{$odp-light-dark};
+
+ // Shadows
+ --stygia-shadow-sm: #{$shadow-sm};
+ --stygia-shadow-md: #{$shadow-md};
+ --stygia-shadow-lg: #{$shadow-lg};
+ --stygia-shadow-focus: #{$shadow-focus};
+
+ // Layout
+ --stygia-navi-width: #{$navi-width};
+ --stygia-navbar-height: #{$navbar-height};
+ --stygia-breadcrumb-height: #{$breadcrumb-height};
+ --stygia-radius: #{$border-radius};
+ --stygia-radius-sm: #{$border-radius-sm};
+ --stygia-radius-lg: #{$border-radius-lg};
+}
diff --git a/stygia/scss/_variables.scss b/stygia/scss/_variables.scss
new file mode 100644
index 0000000000..4eaafcf64f
--- /dev/null
+++ b/stygia/scss/_variables.scss
@@ -0,0 +1,401 @@
+// ============================================================
+// Stygia Theme — Design Tokens
+// Dark theme with deep green accent palette
+// ============================================================
+
+// --- Accent color palette (Stygia deep green) ---
+$accent-green: #3ecf8e;
+$accent-green-dark: #2db87a;
+$accent-green-light: #7ee0b3;
+$accent-green-deep: #006239;
+$accent-green-deep-hover: #004529;
+
+// Backgrounds — three distinct elevation levels
+$bg-body: #121212;
+$bg-surface: #1a1a1a;
+$bg-surface-2: #222222;
+$bg-surface-3: #2a2a2a;
+$bg-surface-4: #333333;
+$bg-popover: #242424;
+
+// Translucent surfaces (for hover/active states)
+$bg-hover: rgba(255, 255, 255, 0.05);
+$bg-active: rgba(255, 255, 255, 0.08);
+$bg-selected: rgba(62, 207, 142, 0.10);
+
+// Text — WCAG AA on #121212 / #1a1a1a (bumped for scannability)
+$text-white: #fafafa;
+$text-primary: $text-white;
+$text-secondary: #c8c8c8;
+$text-muted: #b0b0b0;
+$text-disabled: #949494;
+
+// Borders — dark theme hierarchy
+$border-default: #2e2e2e;
+$border-strong: #3d3d3d;
+$border-stronger: #4a4a4a;
+$border-subtle: rgba(255, 255, 255, 0.06);
+$border-translucent: rgba(255, 255, 255, 0.08);
+
+// Semantic UI colors — distinct from primary accent
+$color-success: #5dd39e;
+$color-danger: #f07178;
+$color-warning: #f5a623;
+$color-info: #4ecdc4;
+
+// One Dark Pro (zhuangtongfa / Binaryify) — classic token palette
+// https://github.com/Binaryify/OneDark-Pro
+$odp-chalky: #e5c07b;
+$odp-coral: #e06c75;
+$odp-dark: #5c6370;
+$odp-fountain-blue: #56b6c2;
+$odp-green: #98c379;
+$odp-malibu: #61afef;
+$odp-purple: #c678dd;
+$odp-whiskey: #d19a66;
+$odp-light-white: #abb2bf;
+$odp-light-dark: #7f848e;
+
+// Code / cell values (aligned with One Dark Pro)
+$color-string: $odp-green;
+$color-number: $odp-whiskey;
+$color-type: $odp-chalky;
+$color-keyword: $odp-purple;
+$color-function: $odp-malibu;
+$color-operator: $odp-fountain-blue;
+$color-comment: $odp-light-dark;
+$color-null: $odp-dark;
+
+// Shadows — close-range, higher opacity for dark mode
+$shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
+$shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35);
+$shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45);
+$shadow-focus: 0 0 0 2px rgba(62, 207, 142, 0.28);
+$shadow-green: 0 8px 24px rgba(0, 98, 57, 0.18);
+
+// phpMyAdmin layout variables
+$navi-width: 240px;
+$navi-color: $text-primary;
+$navi-background: $bg-surface;
+$navi-right-gradient: $bg-surface-2;
+$navi-pointer-color: $text-primary;
+$navi-pointer-background: $bg-hover;
+
+$main-color: $text-primary;
+$browse-pointer-color: $text-primary;
+$browse-pointer-background: rgba($accent-green, 0.08);
+$browse-marker-color: $accent-green;
+$browse-marker-background: rgba($accent-green, 0.14);
+
+$border: 0;
+$th-background: $bg-surface;
+$th-color: $text-secondary;
+$bg-one: $bg-surface;
+$bg-two: $bg-surface-2;
+
+// --- Bootstrap Overrides ---
+
+$body-bg: $bg-body;
+$body-color: $text-primary;
+
+$link-color: $accent-green;
+$link-decoration: none;
+$link-hover-color: $accent-green-light;
+$link-hover-decoration: underline;
+
+// UI: local FiraCode Nerd Font trial (system font). Propo for UI, Mono for SQL.
+// Falls back to Inter / JetBrains if FiraCode NF is not installed.
+$font-family-base: "FiraCode Nerd Font Propo", "FiraCode Nerd Font", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+$font-family-monospace: "FiraCode Nerd Font Mono", "FiraCode Nerd Font", "JetBrains Mono", "Cascadia Code", "Fira Code", Menlo, Consolas, monospace;
+$font-size-base: 0.875rem;
+$font-weight-lighter: 300;
+$font-weight-light: 300;
+$font-weight-normal: 400;
+$font-weight-medium: 500;
+$font-weight-semibold: 500;
+$font-weight-bold: 600;
+$line-height-base: 1.5;
+
+$h1-font-size: 1.375rem;
+$h2-font-size: 1.125rem;
+$h3-font-size: 1rem;
+$h1-font-weight: 500;
+$h2-font-weight: 500;
+$h3-font-weight: 500;
+
+$border-radius: 8px;
+$border-radius-sm: 6px;
+$border-radius-lg: 12px;
+$border-radius-xl: 16px;
+$border-radius-pill: 9999px;
+
+$table-cell-padding-y: 0.55rem;
+$table-cell-padding-x: 0.75rem;
+$table-cell-padding-y-sm: 0.3rem;
+$table-cell-padding-x-sm: 0.5rem;
+$table-bg: transparent;
+$table-head-bg: $bg-surface;
+$table-head-color: $text-secondary;
+$table-striped-order: even;
+$table-striped-bg: rgba(255, 255, 255, 0.045);
+$table-hover-bg: rgba($accent-green, 0.07);
+$table-border-color: $border-default;
+$table-border-width: 1px;
+$table-caption-color: $text-secondary;
+$table-color: $text-primary;
+
+$enable-gradients: false;
+$enable-shadows: false;
+$enable-transitions: true;
+
+$primary: $accent-green;
+$secondary: $bg-surface-4;
+$success: $color-success;
+$danger: $color-danger;
+$warning: $color-warning;
+$info: $color-info;
+
+// Remap Bootstrap "light" utilities so .bg-light / .table-light stay dark
+$white: $text-white;
+$gray-100: $bg-surface-4;
+$gray-200: $bg-surface-3;
+$gray-300: $border-stronger;
+$gray-400: $text-disabled;
+$gray-500: $text-muted;
+$gray-600: $text-secondary;
+$gray-700: $bg-surface-2;
+$gray-800: $bg-surface;
+$gray-900: $bg-body;
+$black: #000;
+
+$light: $bg-surface-2;
+$dark: $bg-body;
+
+$primary-text-emphasis: $accent-green-light;
+$secondary-text-emphasis: $text-secondary;
+$success-text-emphasis: $color-success;
+$info-text-emphasis: $color-info;
+$warning-text-emphasis: $color-warning;
+$danger-text-emphasis: $color-danger;
+$light-text-emphasis: $text-primary;
+$dark-text-emphasis: $text-primary;
+
+$primary-bg-subtle: rgba($accent-green, 0.12);
+$secondary-bg-subtle: $bg-surface-2;
+$success-bg-subtle: rgba($color-success, 0.12);
+$info-bg-subtle: rgba($color-info, 0.12);
+$warning-bg-subtle: rgba($color-warning, 0.14);
+$danger-bg-subtle: rgba($color-danger, 0.12);
+$light-bg-subtle: $bg-surface;
+$dark-bg-subtle: $bg-body;
+
+$btn-border-radius: $border-radius-sm;
+$btn-line-height: 1.5;
+$btn-padding-y: 0.4rem;
+$btn-padding-x: 0.85rem;
+$btn-font-weight: 500;
+
+$btn-primary-color: $text-white;
+$btn-primary-bg: $accent-green-deep;
+$btn-primary-border-color: $accent-green-deep;
+$btn-primary-hover-color: $text-white;
+$btn-primary-hover-bg: $accent-green-deep-hover;
+$btn-primary-hover-border-color: $accent-green-deep-hover;
+$btn-primary-active-color: $text-white;
+$btn-primary-active-bg: darken($accent-green-deep, 3%);
+$btn-primary-active-border-color: darken($accent-green-deep, 3%);
+
+$btn-secondary-color: $text-primary;
+$btn-secondary-bg: transparent;
+$btn-secondary-border-color: $border-strong;
+$btn-secondary-hover-color: $text-primary;
+$btn-secondary-hover-bg: $bg-hover;
+$btn-secondary-hover-border-color: $border-stronger;
+$btn-secondary-active-color: $text-primary;
+$btn-secondary-active-bg: $bg-active;
+$btn-secondary-active-border-color: $border-stronger;
+
+$btn-danger-color: $text-white;
+$btn-danger-bg: $color-danger;
+$btn-danger-border-color: $color-danger;
+
+$btn-link-color: $accent-green;
+$btn-link-hover-color: $accent-green-light;
+$btn-link-decoration: none;
+$btn-link-hover-decoration: underline;
+
+$btn-disabled-color: $text-disabled;
+$btn-disabled-bg: $bg-surface-2;
+$btn-disabled-border-color: $border-default;
+
+$dropdown-bg: $bg-popover;
+$dropdown-border-color: $border-default;
+$dropdown-color: $text-primary;
+$dropdown-hover-bg: $bg-hover;
+$dropdown-hover-color: $text-primary;
+$dropdown-padding-y: 0.25rem;
+$dropdown-padding-x: 0.5rem;
+$dropdown-item-padding-y: 0.375rem;
+$dropdown-item-padding-x: 0.75rem;
+$dropdown-box-shadow: $shadow-md, $shadow-green;
+
+$input-bg: $bg-surface;
+$input-border-color: $border-strong;
+$input-color: $text-primary;
+$input-focus-border-color: $accent-green;
+$input-focus-bg: $bg-surface;
+$input-focus-box-shadow: 0 0 0 2px rgba($accent-green, 0.18);
+$input-placeholder-color: $text-muted;
+$input-disabled-bg: $bg-surface-2;
+$input-disabled-color: $text-disabled;
+$input-disabled-border-color: $border-default;
+
+$form-check-input-bg: $bg-surface-2;
+$form-check-input-border-color: $border-strong;
+$form-check-input-checked-bg-color: $accent-green;
+$form-check-input-checked-border-color: $accent-green;
+
+$form-select-bg: $bg-surface;
+$form-select-border-color: $border-strong;
+$form-select-color: $text-primary;
+$form-select-focus-border-color: $accent-green;
+
+$form-text-color: $text-secondary;
+
+$nav-tabs-border-color: $border-default;
+$nav-tabs-link-hover-bg: transparent;
+$nav-tabs-link-hover-border-color: transparent transparent $border-strong;
+$nav-tabs-link-active-bg: transparent;
+$nav-tabs-link-active-color: $accent-green;
+$nav-tabs-link-active-border-color: transparent transparent $accent-green;
+$nav-link-color: $text-secondary;
+$nav-link-hover-color: $text-primary;
+$nav-link-active-color: $accent-green;
+$nav-link-font-weight: 400;
+
+// Pills used as top menu — restyle as underline tabs (not green CTA pills)
+$nav-pills-border-radius: 0;
+$nav-pills-link-active-color: $accent-green;
+$nav-pills-link-active-bg: transparent;
+
+$enable-caret: false;
+$navbar-padding-y: 0;
+$navbar-padding-x: 0;
+$navbar-dark-color: $text-secondary;
+$navbar-dark-hover-color: $text-primary;
+$navbar-dark-active-color: $accent-green;
+$navbar-dark-disabled-color: $text-disabled;
+$navbar-bg: $bg-body;
+$navbar-brand-color: $text-primary;
+$navbar-height: 38px;
+$breadcrumb-height: 36px;
+$sticky-offset: calc(#{$navbar-height} + #{$breadcrumb-height});
+
+$pagination-color: $text-secondary;
+$pagination-bg: $bg-surface;
+$pagination-border-color: $border-default;
+$pagination-hover-color: $text-primary;
+$pagination-hover-bg: $bg-hover;
+$pagination-hover-border-color: $border-strong;
+$pagination-active-color: $text-primary;
+$pagination-active-bg: $accent-green-deep;
+$pagination-active-border-color: $accent-green-deep;
+$pagination-disabled-color: $text-disabled;
+$pagination-disabled-bg: $bg-surface-2;
+$pagination-disabled-border-color: $border-default;
+
+$card-bg: $bg-surface;
+$card-border-color: $border-default;
+$card-cap-bg: transparent;
+$card-cap-color: $text-primary;
+$card-color: $text-primary;
+$card-border-radius: $border-radius-lg;
+$card-border-width: 1px;
+$card-img-height: 16vh;
+
+$accordion-bg: $bg-surface;
+$accordion-border-color: $border-default;
+$accordion-button-color: $text-primary;
+$accordion-button-active-color: $accent-green;
+$accordion-button-active-bg: $bg-surface-2;
+$accordion-button-focus-border-color: $accent-green;
+$accordion-button-focus-box-shadow: 0 0 0 2px rgba($accent-green, 0.18);
+$accordion-button-padding-y: 0.75rem;
+$accordion-button-padding-x: 1rem;
+
+$breadcrumb-navbar-padding-y: 0.5rem;
+$breadcrumb-navbar-padding-x: 1.8rem;
+$breadcrumb-navbar-margin-bottom: 0;
+$breadcrumb-navbar-bg: $bg-surface;
+$breadcrumb-navbar-bg-dark: $bg-surface;
+$breadcrumb-bg: transparent;
+$breadcrumb-color: $text-secondary;
+$breadcrumb-active-color: $text-primary;
+$breadcrumb-divider-color: $text-muted;
+$breadcrumb-link-color: $text-secondary;
+$breadcrumb-link-hover-color: $accent-green;
+$breadcrumb-divider: quote("\00bb");
+
+$modal-content-bg: $bg-surface;
+$modal-content-border-color: $border-default;
+$modal-content-border-radius: $border-radius-lg;
+$modal-header-bg: $bg-surface;
+$modal-header-border-color: $border-default;
+$modal-header-color: $text-primary;
+$modal-body-color: $text-primary;
+$modal-footer-bg: transparent;
+$modal-backdrop-bg: rgba(0, 0, 0, 0.72);
+$modal-inner-padding: 1rem;
+$modal-footer-margin-between: 0.5rem;
+$modal-header-padding-y: 0.75rem;
+
+$alert-bg: transparent;
+$alert-border-width: 0;
+$alert-border-radius: $border-radius;
+$alert-margin-bottom: 0.75em;
+
+$alert-success-color: $color-success;
+$alert-success-bg: rgba($color-success, 0.14);
+$alert-success-border-color: $color-success;
+
+$alert-danger-color: $color-danger;
+$alert-danger-bg: rgba($color-danger, 0.14);
+$alert-danger-border-color: $color-danger;
+
+$alert-warning-color: $color-warning;
+$alert-warning-bg: rgba($color-warning, 0.14);
+$alert-warning-border-color: $color-warning;
+
+$alert-info-color: $color-info;
+$alert-info-bg: rgba($color-info, 0.14);
+$alert-info-border-color: $color-info;
+
+$list-group-bg: transparent;
+$list-group-border-color: $border-default;
+$list-group-color: $text-primary;
+$list-group-hover-bg: $bg-hover;
+$list-group-hover-color: $text-primary;
+$list-group-active-bg: $bg-active;
+$list-group-active-color: $text-primary;
+$list-group-item-padding-x: 0.75rem;
+$list-group-item-padding-y: 0.5rem;
+
+$toast-background-color: $bg-popover;
+$toast-color: $text-primary;
+$toast-border-color: $border-default;
+
+$tooltip-bg: $bg-surface-4;
+$tooltip-color: $text-primary;
+
+$btn-close-color: $text-secondary;
+$btn-close-hover-color: $text-primary;
+
+$label-margin-bottom: 0.25rem;
+$form-label-color: $text-secondary;
+
+$spinner-color: $accent-green;
+
+$badge-color: $bg-body;
+$badge-bg: $accent-green;
+
+$transition-base: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
diff --git a/stygia/scss/theme.scss b/stygia/scss/theme.scss
new file mode 100644
index 0000000000..2ea4bd13a1
--- /dev/null
+++ b/stygia/scss/theme.scss
@@ -0,0 +1,30 @@
+// ============================================================
+// Stygia — Dark phpMyAdmin Theme
+// Inspired by the mythological river Styx
+// ============================================================
+
+@import "variables";
+@import "bootstrap/scss/bootstrap";
+@import "tokens";
+@import "fonts";
+@import "icons";
+@import "common";
+@import "layout";
+@import "login";
+@import "navigation";
+@import "tables";
+@import "profiling";
+@import "datatypes";
+@import "buttons";
+@import "forms";
+@import "navbar";
+@import "nav";
+@import "card";
+@import "alert";
+@import "codemirror";
+@import "console";
+@import "designer";
+@import "jquery-ui";
+@import "modals";
+@import "reboot";
+@import "print";
diff --git a/stygia/theme.json b/stygia/theme.json
new file mode 100644
index 0000000000..5518714e9a
--- /dev/null
+++ b/stygia/theme.json
@@ -0,0 +1,9 @@
+{
+ "name": "Stygia",
+ "version": "2.1.1",
+ "description": "A dark, elegant theme for phpMyAdmin inspired by the mythological river Styx. Deep green accent, One Dark Pro typed cells, accessible contrast, RTL, and a dense modern UI.",
+ "author": "Horacio Dominguez",
+ "url": "https://github.com/horaciodominguez/stygia",
+ "supports": ["6.0"],
+ "colorModes": ["dark"]
+}