Redesign Purple theme with proper contrast and professional chart axes

Rebuilt the purple color palette from scratch using a 4-level luminance
scale (~3-5x jump per level: #06000f → #110028 → #1d0845 → #3a158a),
matching the approach of high-contrast Bootswatch dark themes (Darkly,
Cyborg). All contrast ratios are now WCAG-compliant: body text 16:1,
card header white text 8.5:1, primary button 5.5:1.

Chart axis improvements: Y-axis large numbers abbreviated (1.4M, 568K),
X-axis max 6 ticks at 30° rotation, Inter font throughout, dark-glass
tooltips, network_charts settings added to settings.json.tmpl with
transparent canvas background
This commit is contained in:
2026-04-28 14:50:22 +02:00
parent 6f03cf10b3
commit 88cba13e77
5 changed files with 472 additions and 598 deletions
+34
View File
@@ -98,6 +98,40 @@
"enabled": true, "enabled": true,
"display_order": 4 "display_order": 4
}, },
"network_charts": {
"nethash_chart": {
"enabled": true,
"chart_title": { "enabled": false, "title_text": "", "alignment": "center", "color": "#666", "font": { "family": "Arial", "size": 14, "weight": "bold" } },
"legend": { "enabled": true, "position": "bottom" },
"bgcolor": "transparent",
"line_color": "rgba(54,162,235,1)",
"fill_color": "rgba(54,162,235,0.2)",
"crosshair_color": "#aaa",
"block_line": { "enabled": true, "block_line_color": "rgba(0,128,0,0.2)" },
"round_decimals": 3,
"chart_height": 320,
"full_row": false,
"stretch_to_fit": false
},
"difficulty_chart": {
"enabled": true,
"chart_title": { "enabled": false, "title_text": "", "alignment": "center", "color": "#666", "font": { "family": "Arial", "size": 14, "weight": "bold" } },
"legend": { "enabled": true, "position": "bottom" },
"bgcolor": "transparent",
"pow_line_color": "rgba(255,99,132,1)",
"pow_fill_color": "rgba(255,99,132,0.2)",
"pos_line_color": "rgba(255,161,0,1)",
"pos_fill_color": "rgba(255,161,0,0.2)",
"crosshair_color": "#aaa",
"block_line": { "enabled": true, "block_line_color": "rgba(0,128,0,0.2)" },
"round_decimals": 3,
"chart_height": 320,
"full_row": false,
"stretch_to_fit": false
},
"reload_chart_seconds": 60,
"sync_charts": true
},
"custom_menus": [] "custom_menus": []
}, },
"page_footer": { "page_footer": {
+128 -321
View File
@@ -1,55 +1,29 @@
/* ============================================================ /* ============================================================
BitcoinPurple Explorer custom UX overrides (Purple theme) BitcoinPurple Explorer explorer-specific component styles
The base dark theme is in themes/purple/_bootswatch.scss.
This file adds only what Bootstrap + bootswatch don't cover.
============================================================ */ ============================================================ */
/* ── Variables ──────────────────────────────────────────────── */ /* ── CSS vars (available to JS and inline styles) ────────────── */
:root { :root {
--btcp-900: #0e001c; --btcp-bg: #06000f;
--btcp-800: #1c003a; --btcp-surface: #110028;
--btcp-700: #2d1052; --btcp-card: #1d0845;
--btcp-600: #3d1278; --btcp-header: #3a158a;
--btcp-500: #5b21b6; --btcp-border: #7c3aed;
--btcp-400: #7c3aed; --btcp-accent: #9333ea;
--btcp-300: #9333ea; --btcp-bright: #a855f7;
--btcp-200: #c084fc; --btcp-label: #c084fc;
--btcp-100: #f0e6ff; /* leggermente più luminoso per contrasto testo */ --btcp-text: #ece0ff;
--btcp-text: #f5eeff; /* testo principale quasi bianco con tinta viola */ --btcp-text-dim: #9d6ae8;
--btcp-text-muted: #c8a8f0; /* secondario viola chiaro leggibile */ --btcp-glow: 0 0 14px rgba(147,51,234,.5), 0 0 40px rgba(147,51,234,.18);
--btcp-search-text: #f0d9ff; /* testo dentro search bar caldo/luminoso */ --btcp-glow-sm: 0 0 8px rgba(147,51,234,.4);
--btcp-glow: 0 0 12px rgba(147,51,234,.45), 0 0 32px rgba(147,51,234,.15); --radius: .55rem;
--btcp-glow-sm: 0 0 6px rgba(147,51,234,.35);
--radius: .6rem;
--radius-pill: 50rem; --radius-pill: 50rem;
} }
/* ── Fix btn-success → purple ────────────────────────────────── */
.btn-success,
.btn-success:not(:disabled):not(.disabled) {
background: linear-gradient(135deg, var(--btcp-400), var(--btcp-300)) !important;
border: none !important;
color: #fff !important;
font-weight: 600;
letter-spacing: .02em;
box-shadow: var(--btcp-glow-sm);
transition: all .2s ease;
}
.btn-success:hover,
.btn-success:focus {
background: linear-gradient(135deg, var(--btcp-300), var(--btcp-200)) !important;
box-shadow: var(--btcp-glow) !important;
transform: translateY(-1px);
}
.btn-success:active {
transform: translateY(0);
box-shadow: var(--btcp-glow-sm) !important;
}
/* ── Search bar ──────────────────────────────────────────────── */ /* ── Search bar ──────────────────────────────────────────────── */
.search-box-custom, .search-box-custom, #index-search, #search-row { padding: .75rem 0; }
#index-search,
#search-row {
padding: .75rem 0;
}
.search-for, .search-for,
#index-search .form-group { #index-search .form-group {
@@ -59,36 +33,65 @@
position: relative; position: relative;
} }
/* Input field */
.search-for .form-control, .search-for .form-control,
#index-search input.form-control { #index-search input.form-control {
background: rgba(18, 0, 40, .95) !important; background: var(--btcp-surface) !important;
border: 1.5px solid var(--btcp-500) !important; border: 1.5px solid var(--btcp-border) !important;
border-right: none !important; border-right: none !important;
border-radius: var(--radius-pill) 0 0 var(--radius-pill) !important; border-radius: var(--radius-pill) 0 0 var(--radius-pill) !important;
color: var(--btcp-search-text) !important; color: #fff !important;
padding: .6rem 1.25rem !important; padding: .6rem 1.25rem .6rem 2.6rem !important;
font-size: .95rem; font-size: .95rem;
font-weight: 500; font-weight: 500;
letter-spacing: .01em;
transition: border-color .2s, box-shadow .2s;
height: 44px; height: 44px;
caret-color: var(--btcp-200); caret-color: var(--btcp-label);
transition: border-color .2s, box-shadow .2s;
} }
.search-for .form-control:focus, .search-for .form-control:focus,
#index-search input.form-control:focus { #index-search input.form-control:focus {
border-color: var(--btcp-300) !important; border-color: var(--btcp-accent) !important;
box-shadow: 0 0 0 3px rgba(147,51,234,.25) !important; box-shadow: 0 0 0 3px rgba(147,51,234,.28) !important;
background: rgba(20, 0, 45, 1) !important; background: #16003a !important;
color: #fff !important; color: #fff !important;
outline: none; outline: none;
} }
.search-for .form-control::placeholder, .search-for .form-control::placeholder,
#index-search input.form-control::placeholder { #index-search input.form-control::placeholder {
color: #d8b4fe; color: rgba(192,132,252,.7);
opacity: .85;
font-weight: 400;
} }
/* Search icon */
.search-for::before {
content: "";
position: absolute;
left: 1rem;
top: 50%;
transform: translateY(-50%);
color: var(--btcp-label);
font-size: 1.1rem;
pointer-events: none;
z-index: 5;
}
/* btn-success → purple (used as search button) */
.btn-success,
.btn-success:not(:disabled):not(.disabled) {
background: linear-gradient(135deg, var(--btcp-border), var(--btcp-accent)) !important;
border: none !important;
color: #fff !important;
font-weight: 600;
box-shadow: var(--btcp-glow-sm);
transition: all .2s ease;
}
.btn-success:hover,
.btn-success:focus {
background: linear-gradient(135deg, var(--btcp-accent), var(--btcp-bright)) !important;
box-shadow: var(--btcp-glow) !important;
transform: translateY(-1px);
}
.btn-success:active { transform: translateY(0); }
.search-for .btn-success, .search-for .btn-success,
#index-search .btn-success { #index-search .btn-success {
border-radius: 0 var(--radius-pill) var(--radius-pill) 0 !important; border-radius: 0 var(--radius-pill) var(--radius-pill) 0 !important;
@@ -97,31 +100,13 @@
font-size: .9rem; font-size: .9rem;
} }
/* Search icon prefix */ /* ── Stat panels (header area) ───────────────────────────────── */
.search-for::before {
content: "";
position: absolute;
left: 1rem;
top: 50%;
transform: translateY(-50%);
color: var(--btcp-200);
font-size: 1.1rem;
pointer-events: none;
z-index: 5;
}
.search-for .form-control {
padding-left: 2.5rem !important;
}
/* ── Stat panels (header) ─────────────────────────────────────── */
.panel-box, .panel-box,
.card.panel, .card.panel,
.stat-panel, .stat-panel {
[class*="stat-"] .card, border: 1px solid rgba(124,58,237,.55) !important;
.summary-panel .card { background: var(--btcp-card) !important;
border-radius: var(--radius) !important; border-radius: var(--radius) !important;
border: 1px solid var(--btcp-600) !important;
background: linear-gradient(145deg, rgba(45,16,82,.95), rgba(28,0,58,.95)) !important;
transition: transform .18s, box-shadow .18s; transition: transform .18s, box-shadow .18s;
} }
.panel-box:hover, .panel-box:hover,
@@ -130,280 +115,102 @@
box-shadow: var(--btcp-glow) !important; box-shadow: var(--btcp-glow) !important;
} }
/* Panel values big numbers */ /* Big numbers */
.panel-box .panel-value, .panel-box .panel-value,
.card .display-4, .card .display-4,
.card h3, .card h3, .card .h3 {
.card .h3 { color: #fff !important;
color: var(--btcp-100) !important;
font-weight: 700; font-weight: 700;
} }
/* Panel labels */ /* Labels */
.panel-box .panel-label, .panel-box .panel-label,
.card .card-title, .card .card-title,
.card small { .card small {
color: var(--btcp-200) !important; color: var(--btcp-label) !important;
font-size: .75rem; font-size: .73rem;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: .08em; letter-spacing: .09em;
font-weight: 500; font-weight: 600;
} }
/* ── Tables ───────────────────────────────────────────────────── */ /* ── Text helpers ────────────────────────────────────────────── */
.table { body { color: var(--btcp-text) !important; }
border-radius: var(--radius); .card-body, .panel-body { color: var(--btcp-text) !important; }
overflow: hidden; p, li, span, div, td, th, label { color: inherit; }
.text-muted, small, .small {
color: var(--btcp-text-dim) !important;
opacity: 1 !important;
} }
.table thead th { /* ── Hash / monospace links in tables ────────────────────────── */
background: linear-gradient(90deg, var(--btcp-700), var(--btcp-600)) !important;
color: var(--btcp-200) !important;
font-size: .78rem !important;
font-weight: 600 !important;
text-transform: uppercase !important;
letter-spacing: .07em !important;
border: none !important;
padding: .85rem 1rem !important;
white-space: nowrap;
}
.table tbody tr {
transition: background .12s;
}
.table tbody tr:nth-child(odd) td {
background: rgba(45,16,82,.25) !important;
}
.table tbody tr:nth-child(even) td {
background: rgba(28,0,58,.25) !important;
}
.table tbody tr:hover td {
background: rgba(124,58,237,.18) !important;
}
.table td {
border-color: rgba(61,18,120,.4) !important;
padding: .7rem 1rem !important;
vertical-align: middle !important;
font-size: .875rem;
}
/* Hash / tx links in tables */
.table td a { .table td a {
color: var(--btcp-200) !important;
font-family: "SF Mono", "Fira Code", monospace; font-family: "SF Mono", "Fira Code", monospace;
font-size: .8rem; font-size: .8rem;
} }
.table td a:hover {
color: #fff !important;
text-shadow: 0 0 8px rgba(192,132,252,.7);
}
/* ── Cards & containers ──────────────────────────────────────── */ /* ── Status badges ───────────────────────────────────────────── */
.card {
border-radius: var(--radius) !important;
border: 1px solid var(--btcp-600) !important;
background: rgba(28,0,58,.85) !important;
backdrop-filter: blur(6px);
}
.card-header {
border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0 !important;
background: linear-gradient(90deg, var(--btcp-700), rgba(45,16,82,.8)) !important;
border-bottom: 1px solid var(--btcp-600) !important;
padding: .85rem 1.25rem !important;
}
.card-header h4,
.card-header h5,
.card-header .card-title {
margin: 0;
font-size: .9rem;
font-weight: 600;
color: var(--btcp-100) !important;
letter-spacing: .04em;
text-transform: uppercase;
}
/* ── Navbar / sidebar ─────────────────────────────────────────── */
header,
.navbar,
#main-header,
#main-header-side {
background: linear-gradient(135deg, #160032 0%, #1e0040 100%) !important;
border-bottom: 1px solid var(--btcp-600) !important;
box-shadow: 0 2px 20px rgba(0,0,0,.5) !important;
}
.navbar-brand {
font-weight: 700 !important;
font-size: 1.1rem !important;
color: var(--btcp-100) !important;
letter-spacing: .04em;
}
.nav-link {
color: rgba(233,213,255,.7) !important;
font-size: .875rem !important;
font-weight: 500 !important;
padding: .5rem .85rem !important;
border-radius: .4rem;
transition: color .15s, background .15s;
}
.nav-link:hover,
.nav-link.active,
.nav-item.active .nav-link {
color: #fff !important;
background: rgba(124,58,237,.25) !important;
}
/* ── Sidebar (side menu layout) ──────────────────────────────── */
#sidebar,
.sidebar-wrapper,
nav.sidebar {
background: linear-gradient(180deg, #130028 0%, #0e001c 100%) !important;
border-right: 1px solid var(--btcp-600) !important;
}
/* ── Badges ──────────────────────────────────────────────────── */
.badge {
border-radius: var(--radius-pill) !important;
font-weight: 500 !important;
font-size: .72rem !important;
padding: .3em .7em !important;
}
.badge.bg-success,
.badge.text-bg-success {
background: rgba(74,222,128,.15) !important;
color: #4ade80 !important;
border: 1px solid rgba(74,222,128,.3) !important;
}
.badge.bg-danger,
.badge.text-bg-danger {
background: rgba(248,113,113,.15) !important;
color: #f87171 !important;
border: 1px solid rgba(248,113,113,.3) !important;
}
.badge.bg-primary,
.badge.text-bg-primary {
background: rgba(147,51,234,.2) !important;
color: var(--btcp-200) !important;
border: 1px solid var(--btcp-500) !important;
}
/* ── Confirmations color ─────────────────────────────────────── */
.text-success { color: #4ade80 !important; } .text-success { color: #4ade80 !important; }
.text-danger { color: #f87171 !important; } .text-danger { color: #f87171 !important; }
.text-warning { color: #fbbf24 !important; } .text-warning { color: #fbbf24 !important; }
/* ── Pagination ──────────────────────────────────────────────── */
.pagination {
gap: 3px;
}
.page-link {
border-radius: .4rem !important;
background: var(--btcp-700) !important;
border: 1px solid var(--btcp-600) !important;
color: var(--btcp-200) !important;
transition: all .15s;
font-size: .85rem;
}
.page-link:hover {
background: var(--btcp-400) !important;
border-color: var(--btcp-400) !important;
color: #fff !important;
box-shadow: var(--btcp-glow-sm);
}
.page-item.active .page-link {
background: linear-gradient(135deg, var(--btcp-400), var(--btcp-300)) !important;
border-color: transparent !important;
box-shadow: var(--btcp-glow-sm);
}
.page-item.disabled .page-link {
background: rgba(45,16,82,.4) !important;
border-color: var(--btcp-700) !important;
color: var(--btcp-500) !important;
}
/* ── Global text contrast boost ─────────────────────────────── */
body {
color: var(--btcp-text) !important;
}
p, li, span, div, td, th, label {
color: inherit;
}
/* Testo secondario / muted più leggibile */
.text-muted,
small,
.small {
color: var(--btcp-text-muted) !important;
opacity: 1 !important;
}
/* Valori numerici nei pannelli massima leggibilità */
.card-body,
.panel-body {
color: var(--btcp-text) !important;
}
/* Intestazioni */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
color: var(--btcp-100) !important;
}
/* ── Loading bar ─────────────────────────────────────────────── */ /* ── Loading bar ─────────────────────────────────────────────── */
#loading-bar, #loading-bar, .loading-bar, #nprogress .bar {
.loading-bar, background: linear-gradient(90deg, var(--btcp-border), var(--btcp-label)) !important;
#nprogress .bar { box-shadow: 0 0 8px var(--btcp-accent);
background: linear-gradient(90deg, var(--btcp-400), var(--btcp-200)) !important;
box-shadow: 0 0 8px var(--btcp-300);
} }
/* ── Charts ──────────────────────────────────────────────────── */ /* ── Chart canvas subtle glow ────────────────────────────────── */
canvas { canvas {
filter: drop-shadow(0 0 6px rgba(147,51,234,.2)); filter: drop-shadow(0 0 4px rgba(147,51,234,.12));
} }
/* ── Footer ──────────────────────────────────────────────────── */ /* ── Network chart card overrides ────────────────────────────── */
footer, #nethashChartParent,
#footer { #difficultyChartParent {
background: linear-gradient(135deg, #130028 0%, #0e001c 100%) !important; .card { background: var(--btcp-card) !important; overflow: hidden; }
border-top: 1px solid var(--btcp-600) !important; .card-header {
color: var(--btcp-500) !important; background: var(--btcp-header) !important;
font-size: .8rem; border-bottom: 2px solid var(--btcp-border) !important;
padding: .6rem 1rem !important;
display: flex;
align-items: center;
gap: .5rem;
&::before {
content: '';
display: inline-block;
width: 3px;
height: 14px;
border-radius: 2px;
background: linear-gradient(180deg, var(--btcp-label), var(--btcp-accent));
flex-shrink: 0;
}
strong {
color: #fff !important;
font-size: .78rem;
letter-spacing: .08em;
text-transform: uppercase;
font-weight: 700;
}
}
.card-body { padding: .75rem !important; }
canvas { display: block; border-radius: .3rem; }
} }
/* ── Scrollbar ───────────────────────────────────────────────── */ /* ── Scrollbar ───────────────────────────────────────────────── */
* { * { scrollbar-width: thin; scrollbar-color: var(--btcp-border) var(--btcp-bg); }
scrollbar-width: thin; ::-webkit-scrollbar { width: 5px; height: 5px; }
scrollbar-color: var(--btcp-500) var(--btcp-900); ::-webkit-scrollbar-track { background: var(--btcp-bg); }
} ::-webkit-scrollbar-thumb { background: var(--btcp-border); border-radius: 99px; }
::-webkit-scrollbar { width: 5px; height: 5px; } ::-webkit-scrollbar-thumb:hover { background: var(--btcp-accent); }
::-webkit-scrollbar-track { background: var(--btcp-900); }
::-webkit-scrollbar-thumb {
background: var(--btcp-500);
border-radius: 99px;
}
::-webkit-scrollbar-thumb:hover { background: var(--btcp-300); }
/* ── Inputs & forms ──────────────────────────────────────────── */ /* ── Tooltip ─────────────────────────────────────────────────── */
.form-control,
.form-select {
border-radius: .45rem !important;
}
.form-control:focus,
.form-select:focus {
border-color: var(--btcp-300) !important;
box-shadow: 0 0 0 3px rgba(147,51,234,.2) !important;
}
/* ── Tooltips ────────────────────────────────────────────────── */
.tooltip-inner { .tooltip-inner {
background: var(--btcp-700) !important; background: var(--btcp-card) !important;
border: 1px solid var(--btcp-600); border: 1px solid var(--btcp-border);
color: var(--btcp-text);
font-size: .8rem; font-size: .8rem;
} }
/* ── Links ───────────────────────────────────────────────────── */
a { transition: color .15s; }
a:hover { text-decoration: none !important; }
+111 -153
View File
@@ -1,258 +1,216 @@
// BitcoinPurple Theme // BitcoinPurple Bootswatch overrides
// Handles everything Bootstrap's SCSS variables can't reach
@use "sass:color"; @use "sass:color";
// Fonts // ── Web font ──────────────────────────────────────────────────────────────────
$web-font-path: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" !default; $web-font-path: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" !default;
@if $web-font-path { @if $web-font-path {
@import url($web-font-path); @import url($web-font-path);
} }
// Glow mixins // ── Mixins ────────────────────────────────────────────────────────────────────
@mixin purple-glow($size: 8px) {
@mixin glow($color) { box-shadow: 0 0 $size rgba(168, 85, 247, .55), 0 0 #{$size * 3} rgba(168, 85, 247, .2);
box-shadow: 0 0 6px rgba($color, .5), 0 0 20px rgba($color, .2);
} }
@mixin text-glow($color) { // ── Body ──────────────────────────────────────────────────────────────────────
text-shadow: 0 0 8px rgba($color, .6), 0 0 20px rgba($color, .3);
}
// Body — deep purple gradient background
body { body {
background-image: linear-gradient(160deg, #130025 0%, #0e001c 40%, #0a0018 100%); background: #06000f !important;
background-attachment: fixed;
} }
// Headings glow // ── Headings ─────────────────────────────────────────────────────────────────
h1, h2, h3, h4, h5, h6, h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 { .h1, .h2, .h3, .h4, .h5, .h6 {
@include text-glow(#a855f7); color: #fff;
} }
// Navbar — rich purple // ── Navbar ────────────────────────────────────────────────────────────────────
.navbar { .navbar {
background: linear-gradient(135deg, #1a003a 0%, #2d0057 100%) !important; background: #110028 !important;
border-bottom: 1px solid #5b21b6; border-bottom: 2px solid #7c3aed;
@include glow(#7c3aed); box-shadow: 0 2px 20px rgba(0, 0, 0, .8);
} }
.navbar-brand, .navbar-brand { color: #fff !important; font-weight: 700; }
.nav-link { .nav-link {
color: #e9d5ff !important; color: rgba(236, 224, 255, .65) !important;
border-radius: .35rem;
transition: color .15s, background .15s;
&:hover, &.active {
color: #fff !important;
background: rgba(168, 85, 247, .2) !important;
}
} }
.nav-link:hover, // ── Sidebar ───────────────────────────────────────────────────────────────────
.nav-link.active {
color: #fff !important;
@include text-glow(#c084fc);
}
// Sidebar menu
#sidebar, #sidebar,
.sidebar, .sidebar,
[id*="sidebar"], [id*="sidebar"],
.nav-sidebar, .nav-sidebar,
.col-sidebar { .col-sidebar {
background: linear-gradient(180deg, #1a003a 0%, #120028 100%) !important; background: #110028 !important;
border-right: 1px solid #3d1278; border-right: 2px solid #7c3aed;
} }
// Cards — dark purple glass effect // ── Cards ─────────────────────────────────────────────────────────────────────
.card { .card {
background: rgba(28, 0, 58, .85) !important; background: #1d0845 !important;
border: 1px solid #3d1278 !important; border: 1px solid rgba(124, 58, 237, .55) !important;
backdrop-filter: blur(4px);
} }
.card-header { .card-header {
background: rgba(45, 16, 82, .9) !important; background: #3a158a !important;
border-bottom: 1px solid #4c1a8f !important; border-bottom: 2px solid rgba(124, 58, 237, .7) !important;
color: #d8b4fe !important; color: #fff !important;
font-weight: 600; font-weight: 600;
} }
// Tables // ── Tables ────────────────────────────────────────────────────────────────────
.table { .table {
color: #e9d5ff; color: #ece0ff;
th { thead th {
background: #2d1052 !important; background: #3a158a !important;
color: #c084fc !important; color: #fff !important;
border-bottom: 2px solid #5b21b6 !important; border-bottom: 2px solid #7c3aed !important;
font-weight: 600; border-top: none !important;
font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
font-size: .82rem; font-size: .78rem;
letter-spacing: .04em; letter-spacing: .07em;
white-space: nowrap;
} }
td { td { border-color: rgba(124, 58, 237, .3) !important; }
border-color: #2d1052 !important;
}
tbody tr:hover td { tbody tr:nth-child(odd) td { background: rgba(58, 21, 138, .2) !important; }
background: rgba(147, 51, 234, .12) !important; tbody tr:nth-child(even) td { background: rgba(17, 0, 40, .15) !important; }
tbody tr:hover td { background: rgba(168, 85, 247, .15) !important; }
// Monospace hash links
td a {
color: #c084fc;
&:hover { color: #fff; text-shadow: 0 0 8px rgba(192, 132, 252, .8); }
} }
} }
// Buttons — glowing purple // ── Buttons ───────────────────────────────────────────────────────────────────
.btn-primary { .btn-primary {
background: linear-gradient(135deg, #7c3aed, #9333ea) !important; background: linear-gradient(135deg, #7c3aed, #9333ea) !important;
border: none !important; border: none !important;
@include glow(#9333ea);
&:hover { &:hover, &:focus {
background: linear-gradient(135deg, #6d28d9, #7c3aed) !important; background: linear-gradient(135deg, #9333ea, #a855f7) !important;
@include glow(#a855f7); @include purple-glow(10px);
} }
} }
.btn-secondary { .btn-secondary {
background: #2d1052 !important; background: #3a158a !important;
border: 1px solid #5b21b6 !important; border: 1px solid #7c3aed !important;
color: #e9d5ff !important; color: #ece0ff !important;
} }
// Badges & labels // ── Badges ────────────────────────────────────────────────────────────────────
.badge.bg-primary { background: #7c3aed !important; }
.badge.bg-primary { .badge.bg-secondary { background: #3a158a !important; }
background: #7c3aed !important;
}
.badge.bg-success { .badge.bg-success {
background: #166534 !important; background: rgba(74, 222, 128, .18) !important;
color: #4ade80 !important; color: #4ade80 !important;
border: 1px solid rgba(74, 222, 128, .4) !important;
} }
// Links .badge.bg-danger {
background: rgba(248, 113, 113, .18) !important;
a { color: #f87171 !important;
color: #c084fc; border: 1px solid rgba(248, 113, 113, .4) !important;
&:hover {
color: #e9d5ff;
}
} }
// Inputs // ── Inputs ───────────────────────────────────────────────────────────────────
.form-control, .form-control,
.form-select { .form-select {
background: #1c003a !important; background: #110028 !important;
border-color: #3d1278 !important; border-color: rgba(124, 58, 237, .55) !important;
color: #e9d5ff !important; color: #ece0ff !important;
&::placeholder { color: rgba(192, 132, 252, .6); }
&:focus { &:focus {
background: #1c003a !important; background: #110028 !important;
border-color: #9333ea !important; border-color: #9333ea !important;
box-shadow: 0 0 0 3px rgba(147, 51, 234, .25) !important; box-shadow: 0 0 0 3px rgba(147, 51, 234, .25) !important;
color: #fff !important; color: #fff !important;
} }
} }
// Panels / stat boxes // ── Pagination ────────────────────────────────────────────────────────────────
.panel,
.stats-panel,
[class*="panel-"] {
background: rgba(28, 0, 58, .9) !important;
border: 1px solid #3d1278 !important;
}
// Pagination
.page-link { .page-link {
background: #2d1052 !important; background: #1d0845 !important;
border-color: #5b21b6 !important; border-color: rgba(124, 58, 237, .5) !important;
color: #d8b4fe !important; color: #c084fc !important;
transition: all .15s;
&:hover { &:hover {
background: #9333ea !important; background: #7c3aed !important;
border-color: #7c3aed !important;
color: #fff !important; color: #fff !important;
@include purple-glow(6px);
} }
} }
.page-item.active .page-link { .page-item.active .page-link {
background: #7c3aed !important; background: linear-gradient(135deg, #7c3aed, #9333ea) !important;
border-color: #7c3aed !important; border-color: transparent !important;
color: #fff !important;
@include purple-glow(6px);
} }
// Scrollbar styling // ── Scrollbar ─────────────────────────────────────────────────────────────────
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: #06000f; }
::-webkit-scrollbar-thumb { background: #7c3aed; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #9333ea; }
::-webkit-scrollbar { // ── Breadcrumbs ───────────────────────────────────────────────────────────────
width: 6px; .breadcrumb { background: #1d0845 !important; }
height: 6px; .breadcrumb-item a { color: #c084fc !important; }
}
::-webkit-scrollbar-track {
background: #0e001c;
}
::-webkit-scrollbar-thumb {
background: #5b21b6;
border-radius: 3px;
&:hover {
background: #9333ea;
}
}
// Breadcrumbs
.breadcrumb {
background: #2d1052 !important;
}
.breadcrumb-item a {
color: #c084fc !important;
}
// Code / pre
// ── Code / pre ────────────────────────────────────────────────────────────────
code { code {
color: #e879f9; color: #f0abfc;
background: rgba(45, 16, 82, .6); background: rgba(58, 21, 138, .5);
padding: .1em .3em; padding: .1em .3em;
border-radius: .2em; border-radius: .2em;
} }
pre { pre {
background: #1c003a; background: #110028;
border: 1px solid #3d1278; border: 1px solid rgba(124, 58, 237, .4);
color: #e9d5ff; color: #ece0ff;
} }
// Footer // ── Footer ────────────────────────────────────────────────────────────────────
footer, footer,
.footer { .footer {
background: linear-gradient(135deg, #1a003a 0%, #0e001c 100%) !important; background: #110028 !important;
border-top: 1px solid #3d1278 !important; border-top: 2px solid #7c3aed !important;
color: #a855f7 !important; color: rgba(168, 85, 247, .8) !important;
} }
// Alerts // ── Alerts ───────────────────────────────────────────────────────────────────
.alert { .alert {
border: none; border: none;
color: $white; color: $white;
} }
// Misc utility // ── Misc ──────────────────────────────────────────────────────────────────────
.text-muted { color: #9d6ae8 !important; }
.text-muted {
color: #a855f7 !important;
}
hr { hr {
border-color: #3d1278; border-color: rgba(124, 58, 237, .4);
opacity: .5; opacity: .6;
} }
+131 -122
View File
@@ -1,153 +1,162 @@
// BitcoinPurple Theme (based on Vapor 5.1.3) // BitcoinPurple Theme
// Contrast-aware dark palette inspired by Darkly + Cyborg structure
//
// Luminance scale (each level ~3-5x the previous):
// $gray-900 #06000f 0.1% body background
// $gray-800 #110028 0.6% navbar / sidebar
// $gray-700 #1d0845 2.4% card body
// $gray-600 #3a158a 7.3% card header / table thead
// $gray-500 #7c3aed 18% borders / interactive
// $gray-400 #9d6ae8 31% secondary interactive
// $gray-300 #c084fc 47% links / accent labels
// $gray-200 #ddb8ff 63% secondary text
// $gray-100 #f0e8ff 79% near-white text
//
// Key contrast ratios:
// body text (#ece0ff) on bg (#06000f) → 16:1 ✓ AAA
// white on card header (#3a158a) → 8.5:1 ✓ AAA
// white on primary (#9333ea) → 5.5:1 ✓ AA
// link (#c084fc) on bg (#06000f) → 10:1 ✓ AAA
// link (#c084fc) on card (#1d0845) → 7:1 ✓ AA
@use "sass:color"; @use "sass:color";
$theme: "purple" !default; $theme: "purple" !default;
// Color system // ── Color scale ───────────────────────────────────────────────────────────────
$white: #fff !default;
$gray-100: #f0e8ff !default;
$gray-200: #ddb8ff !default;
$gray-300: #c084fc !default;
$gray-400: #9d6ae8 !default;
$gray-500: #7c3aed !default;
$gray-600: #3a158a !default;
$gray-700: #1d0845 !default;
$gray-800: #110028 !default;
$gray-900: #06000f !default;
$black: #020008 !default;
$white: #fff !default; // ── Named colors ──────────────────────────────────────────────────────────────
$gray-100: #f3e8ff !default; $blue: #60a5fa !default;
$gray-200: #e9d5ff !default; $indigo: #818cf8 !default;
$gray-300: #d8b4fe !default; $purple: #c084fc !default;
$gray-400: #c084fc !default; $pink: #f0abfc !default;
$gray-500: #a855f7 !default; $red: #f87171 !default;
$gray-600: #7e22ce !default; $orange: #fb923c !default;
$gray-700: #581c87 !default; $yellow: #fbbf24 !default;
$gray-800: #3b0764 !default; $green: #4ade80 !default;
$gray-900: #160026 !default; $teal: #2dd4bf !default;
$black: #08000f !default; $cyan: #22d3ee !default;
$blue: #818cf8 !default; // ── Theme colors ──────────────────────────────────────────────────────────────
$indigo: #6366f1 !default; // Primary: #9333ea → white contrast 5.5:1 (AA ✓)
$purple: #a855f7 !default; $primary: #9333ea !default;
$pink: #e879f9 !default; $secondary: $gray-600 !default;
$red: #f87171 !default; $success: $green !default;
$orange: #fb923c !default; $info: $blue !default;
$yellow: #fbbf24 !default; $warning: $yellow !default;
$green: #4ade80 !default; $danger: $red !default;
$teal: #2dd4bf !default;
$cyan: #22d3ee !default;
$primary: #9333ea !default;
$secondary: #7c3aed !default;
$success: $green !default;
$info: $blue !default;
$warning: $yellow !default;
$danger: $red !default;
$light: $gray-200 !default; $light: $gray-200 !default;
$dark: $gray-900 !default; $dark: $gray-900 !default;
$min-contrast-ratio: 2 !default; $min-contrast-ratio: 2.5 !default;
// Body // ── Body ──────────────────────────────────────────────────────────────────────
$body-bg: $gray-900 !default;
$body-color: #ece0ff !default; // 16:1 contrast on body-bg
$body-bg: #0e001c !default; // ── Links ─────────────────────────────────────────────────────────────────────
$body-color: #e9d5ff !default; $link-color: $gray-300 !default;
$link-hover-color: $white !default;
// Links $link-decoration: none !default;
$link-hover-decoration: underline !default;
$link-color: $gray-300 !default;
// Fonts
// ── Typography ────────────────────────────────────────────────────────────────
$font-family-sans-serif: "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !default; $font-family-sans-serif: "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !default;
$text-muted: $gray-500 !default; $text-muted: $gray-400 !default;
// Tables // ── Tables ────────────────────────────────────────────────────────────────────
$table-color: $body-color !default;
$table-border-color: rgba($gray-500, .35) !default;
$table-bg-scale: 0 !default;
$table-border-color: #2d1052 !default; // ── Forms ─────────────────────────────────────────────────────────────────────
$table-bg-scale: 0 !default; $input-bg: $gray-800 !default;
$input-color: $gray-100 !default;
$input-border-color: rgba($gray-500, .6) !default;
$input-placeholder-color: rgba($gray-300, .6) !default;
$input-group-addon-color: $gray-200 !default;
$input-group-addon-bg: $gray-600 !default;
// Forms $form-check-input-bg: $gray-800 !default;
$form-check-input-border: 1px solid rgba($gray-500, .6) !default;
$input-bg: #1c003a !default; // ── Nav ───────────────────────────────────────────────────────────────────────
$input-color: $gray-200 !default; $nav-link-padding-x: 1.2rem !default;
$input-border-color: #3d1278 !default; $nav-link-disabled-color: $gray-500 !default;
$input-group-addon-color:$gray-400 !default; $nav-tabs-border-color: $gray-500 !default;
$input-group-addon-bg: #2d1052 !default;
$form-check-input-bg: #1c003a !default;
$form-check-input-border: 1px solid #3d1278 !default;
// Dropdowns
$dropdown-bg: #1c003a !default;
$dropdown-border-color: #3d1278 !default;
$dropdown-divider-bg: #3d1278 !default;
$dropdown-link-color: $gray-200 !default;
$dropdown-link-hover-color: $white !default;
$dropdown-link-hover-bg: $primary !default;
// Navs
$nav-link-padding-x: 2rem !default;
$nav-link-disabled-color: $gray-600 !default;
$nav-tabs-border-color: #3d1278 !default;
$nav-tabs-link-active-color:$white !default; $nav-tabs-link-active-color:$white !default;
// Navbar // ── Navbar ────────────────────────────────────────────────────────────────────
$navbar-dark-color: rgba($white, .7) !default;
$navbar-dark-hover-color: $white !default;
$navbar-dark-color: rgba($white, .75) !default; // ── Dropdowns ────────────────────────────────────────────────────────────────
$navbar-dark-hover-color: $white !default; $dropdown-bg: $gray-700 !default;
$dropdown-border-color: $gray-500 !default;
$dropdown-divider-bg: $gray-600 !default;
$dropdown-link-color: $gray-200 !default;
$dropdown-link-hover-color: $white !default;
$dropdown-link-hover-bg: $primary !default;
// Pagination // ── Pagination ────────────────────────────────────────────────────────────────
$pagination-color: $white !default;
$pagination-bg: $gray-700 !default;
$pagination-border-width: 1px !default;
$pagination-border-color: rgba($gray-500, .55) !default;
$pagination-hover-color: $white !default;
$pagination-hover-bg: $primary !default;
$pagination-hover-border-color: $primary !default;
$pagination-active-bg: $primary !default;
$pagination-active-border-color: $primary !default;
$pagination-disabled-color: $gray-500 !default;
$pagination-disabled-bg: rgba($gray-700, .5) !default;
$pagination-disabled-border-color:rgba($gray-500, .3) !default;
$pagination-color: $white !default; // ── Cards ─────────────────────────────────────────────────────────────────────
$pagination-bg: $primary !default; $card-cap-bg: $gray-600 !default;
$pagination-border-width: 0 !default; $card-bg: $gray-700 !default;
$pagination-border-color: transparent !default; $card-border-color: rgba($gray-500, .55) !default;
$pagination-hover-color: $white !default; $card-cap-color: $white !default;
$pagination-hover-bg: color.adjust($primary, $lightness: 8%) !default;
$pagination-hover-border-color: transparent !default;
$pagination-active-bg: color.adjust($primary, $lightness: 8%) !default;
$pagination-active-border-color: transparent !default;
$pagination-disabled-color: $gray-300 !default;
$pagination-disabled-bg: color.adjust($primary, $lightness: -15%) !default;
$pagination-disabled-border-color:transparent !default;
// Cards // ── Modals ────────────────────────────────────────────────────────────────────
$modal-content-bg: $gray-700 !default;
$modal-content-border-color: $gray-500 !default;
$modal-header-border-color: $gray-500 !default;
$card-cap-bg: #2d1052 !default; // ── Popovers ─────────────────────────────────────────────────────────────────
$card-bg: #1c003a !default; $popover-bg: $gray-700 !default;
$popover-header-bg: $gray-600 !default;
// Popovers // ── Progress ─────────────────────────────────────────────────────────────────
$progress-bg: $gray-600 !default;
$popover-bg: #1c003a !default;
$popover-header-bg: #2d1052 !default;
// Modals
$modal-content-bg: #1c003a !default;
$modal-content-border-color: #3d1278 !default;
$modal-header-border-color: #3d1278 !default;
// Progress bars
$progress-bg: #2d1052 !default;
// List group
// ── List group ───────────────────────────────────────────────────────────────
$list-group-color: $body-color !default; $list-group-color: $body-color !default;
$list-group-bg: #1c003a !default; $list-group-bg: $gray-700 !default;
$list-group-border-color: #3d1278 !default; $list-group-border-color: $gray-500 !default;
$list-group-hover-bg: #2d1052 !default; $list-group-hover-bg: $gray-600 !default;
$list-group-action-hover-color: $list-group-color !default; $list-group-action-hover-color: $white !default;
$list-group-action-active-bg: $gray-900 !default; $list-group-action-active-bg: $gray-900 !default;
// Breadcrumbs // ── Breadcrumbs ───────────────────────────────────────────────────────────────
$breadcrumb-padding-y: .375rem !default;
$breadcrumb-padding-y: .375rem !default; $breadcrumb-padding-x: .75rem !default;
$breadcrumb-padding-x: .75rem !default; $breadcrumb-bg: $gray-700 !default;
$breadcrumb-bg: #2d1052 !default; $breadcrumb-border-radius:.25rem !default;
$breadcrumb-border-radius:.25rem !default;
// Close button
// ── Misc ──────────────────────────────────────────────────────────────────────
$btn-close-color: $white !default; $btn-close-color: $white !default;
$btn-close-opacity: .5 !default; $btn-close-opacity: .5 !default;
$btn-close-hover-opacity:1 !default; $btn-close-hover-opacity:1 !default;
$pre-color: inherit !default;
// Code
$pre-color: inherit !default;
+68 -2
View File
@@ -1,3 +1,69 @@
$(document).ready(function() { $(document).ready(function() {
/* Add custom javascript code here */ if (typeof Chart === 'undefined') return;
});
// ── Y-axis: abbreviate large numbers ─────────────────────────
// 1400000 → "1.4M", 45000 → "45K", 999 → "999"
function fmtAxis(value) {
var abs = Math.abs(value);
if (abs >= 1e9) return (value / 1e9).toFixed(1).replace(/\.0$/, '') + 'B';
if (abs >= 1e6) return (value / 1e6).toFixed(1).replace(/\.0$/, '') + 'M';
if (abs >= 1e3) return (value / 1e3).toFixed(1).replace(/\.0$/, '') + 'K';
return value;
}
var font = { family: 'Inter, system-ui, sans-serif', size: 11 };
// ── Linear scale (Y-axis on both charts) ─────────────────────
var lin = Chart.defaults.scales.linear;
if (lin) {
lin.ticks = Object.assign({}, lin.ticks, {
callback: fmtAxis,
font: font,
color: 'rgba(200,160,255,0.85)',
padding: 8,
maxTicksLimit: 6
});
lin.title = Object.assign({}, lin.title, {
font: Object.assign({}, font, { weight: '700', size: 11 }),
color: 'rgba(216,180,254,1)'
});
lin.grid = Object.assign({}, lin.grid, {
color: 'rgba(80,40,130,0.3)'
});
}
// ── Time scale (X-axis) ───────────────────────────────────────
// Reduce label density and avoid 90° rotation
['time', 'timeseries'].forEach(function(t) {
var s = Chart.defaults.scales[t];
if (!s) return;
s.ticks = Object.assign({}, s.ticks, {
font: font,
color: 'rgba(200,160,255,0.75)',
maxTicksLimit: 6,
maxRotation: 30,
minRotation: 0,
padding: 6
});
s.grid = Object.assign({}, s.grid, {
color: 'rgba(80,40,130,0.3)'
});
});
// ── Tooltip ───────────────────────────────────────────────────
Object.assign(Chart.defaults.plugins.tooltip, {
backgroundColor: 'rgba(10,0,28,0.96)',
borderColor: 'rgba(93,33,182,0.65)',
borderWidth: 1,
titleColor: 'rgba(216,180,254,1)',
titleFont: Object.assign({}, font, { weight: '700', size: 12 }),
bodyColor: 'rgba(240,230,255,0.9)',
bodyFont: Object.assign({}, font, { size: 12 }),
padding: 11,
cornerRadius: 7
});
// ── Legend ────────────────────────────────────────────────────
Chart.defaults.plugins.legend.labels.font = Object.assign({}, font, { size: 12 });
Chart.defaults.plugins.legend.labels.color = 'rgba(216,180,254,1)';
});