06/05 Optimize app

This commit is contained in:
2026-06-05 15:23:23 -04:00
parent db44d6057b
commit 9c9aa694c4
9 changed files with 781 additions and 19 deletions
+108
View File
@@ -198,8 +198,88 @@
.sb-overlay.on { display: block; }
@keyframes spin { to { transform: rotate(360deg); } }
/* ── Dark mode ─────────────────────────────────────────────────────── */
body.dark-mode {
--body-bg: #0f172a; --card-bg: #1e293b; --text: #e2e8f0;
--muted: #94a3b8; --border: #334155;
color-scheme: dark;
}
body.dark-mode #topbar { background: #1e293b; border-color: #334155; }
body.dark-mode .pfm-table tbody tr:hover { background: #263548; }
body.dark-mode .pfm-table th, body.dark-mode .pfm-table td { border-color: #334155; }
body.dark-mode .form-control, body.dark-mode .form-select {
background: #0f172a; border-color: #334155; color: #e2e8f0;
}
body.dark-mode .form-control:focus, body.dark-mode .form-select:focus {
background: #0f172a; border-color: #3b82f6; color: #e2e8f0;
box-shadow: 0 0 0 .2rem rgba(59,130,246,.25);
}
body.dark-mode .form-control::placeholder { color: #475569; }
body.dark-mode .form-check-input { background-color: #334155; border-color: #475569; }
body.dark-mode .form-check-input:checked { background-color: #3b82f6; border-color: #3b82f6; }
body.dark-mode .btn-outline-secondary { color: #94a3b8; border-color: #334155; }
body.dark-mode .btn-outline-secondary:hover,
body.dark-mode .btn-outline-secondary:focus { background: #334155; color: #e2e8f0; border-color: #334155; }
body.dark-mode .btn-outline-primary { color: #93c5fd; border-color: #1e40af; }
body.dark-mode .btn-outline-primary:hover { background: #1e40af; color: #fff; }
body.dark-mode .btn-outline-warning { color: #fcd34d; border-color: #92400e; }
body.dark-mode .btn-outline-warning:hover { background: #92400e; color: #fff; }
body.dark-mode .btn-outline-danger { color: #fca5a5; border-color: #991b1b; }
body.dark-mode .btn-outline-danger:hover { background: #991b1b; color: #fff; }
body.dark-mode .dropdown-menu { background: #1e293b; border-color: #334155; }
body.dark-mode .dropdown-item { color: #e2e8f0; }
body.dark-mode .dropdown-item:hover, body.dark-mode .dropdown-item:focus { background: #334155; color: #f1f5f9; }
body.dark-mode .dropdown-divider { border-color: #334155; }
body.dark-mode .modal-content { background: #1e293b; border-color: #334155; color: #e2e8f0; }
body.dark-mode .modal-header, body.dark-mode .modal-footer { border-color: #334155; }
body.dark-mode .modal-header .btn-close { filter: invert(1) grayscale(1); }
body.dark-mode .alert-warning { background: #451a03; border-color: #92400e; color: #fcd34d; }
body.dark-mode .alert-danger { background: #450a0a; border-color: #991b1b; color: #fca5a5; }
body.dark-mode .alert-success { background: #052e16; border-color: #166534; color: #86efac; }
body.dark-mode .alert-info { background: #0c1a2e; border-color: #1e40af; color: #93c5fd; }
body.dark-mode .progress { background: #334155; }
body.dark-mode .table { color: #e2e8f0; }
body.dark-mode .input-group-text { background: #334155; border-color: #334155; color: #94a3b8; }
body.dark-mode .badge-income { background: #064e3b; color: #6ee7b7; }
body.dark-mode .badge-expense { background: #450a0a; color: #fca5a5; }
body.dark-mode .badge-transfer { background: #1e3a5f; color: #93c5fd; }
body.dark-mode #kbd-modal kbd { background: #334155; border-color: #475569; color: #e2e8f0; }
body.dark-mode .report-tab { background: #1e293b; border-color: #334155; color: #94a3b8; }
body.dark-mode .report-tab:hover { background: #334155; color: #e2e8f0; }
body.dark-mode .report-tab.active { background: #e2e8f0; color: #0f172a; border-color: #e2e8f0; }
/* Override common hardcoded light backgrounds in component inline styles */
body.dark-mode [style*="background:#f8fafc"], body.dark-mode [style*="background: #f8fafc"],
body.dark-mode [style*="background:#f1f5f9"], body.dark-mode [style*="background: #f1f5f9"]
{ background: #263548 !important; }
body.dark-mode [style*="background:#eff6ff"], body.dark-mode [style*="background: #eff6ff"]
{ background: #1e3a5f !important; }
body.dark-mode [style*="background:#fef2f2"], body.dark-mode [style*="background: #fef2f2"]
{ background: #450a0a !important; }
body.dark-mode [style*="background:#f0fdf4"], body.dark-mode [style*="background: #f0fdf4"]
{ background: #052e16 !important; }
body.dark-mode [style*="background:#fff5e6"], body.dark-mode [style*="background:#fffbeb"]
{ background: #451a03 !important; }
/* Text color overrides for hardcoded darks */
body.dark-mode [style*="color:#0f172a"] { color: #e2e8f0 !important; }
body.dark-mode [style*="color:#1e293b"] { color: #94a3b8 !important; }
body.dark-mode [style*="color:#374151"] { color: #94a3b8 !important; }
/* Border overrides */
body.dark-mode [style*="border-bottom:1px solid #e2e8f0"],
body.dark-mode [style*="border-bottom: 1px solid #e2e8f0"] { border-color: #334155 !important; }
body.dark-mode [style*="border:1px solid #e2e8f0"],
body.dark-mode [style*="border: 1px solid #e2e8f0"] { border-color: #334155 !important; }
{% block extra_css %}{% endblock %}
</style>
<script>
/* Apply dark mode class to body before first paint to avoid flash */
(function(){ if(localStorage.getItem('pfm_dark')==='1') document.documentElement.setAttribute('data-pfm-dark','1'); })();
</script>
<style>
/* Instant pre-body dark (avoids FOUC) — matches body.dark-mode vars */
html[data-pfm-dark] body { --body-bg:#0f172a; --card-bg:#1e293b; --text:#e2e8f0; --muted:#94a3b8; --border:#334155; }
</style>
</head>
<body>
<div class="sb-overlay" id="sbOverlay"></div>
@@ -318,6 +398,11 @@
<span class="tb-title">{% block page_title %}{% endblock %}</span>
<div class="tb-right">
{% block topbar_actions %}{% endblock %}
<button id="dark-toggle" type="button" title="Toggle dark mode"
style="background:none;border:none;color:var(--muted);font-size:15px;padding:3px 6px;border-radius:6px;cursor:pointer;line-height:1;"
class="d-inline-flex align-items-center">
<i class="bi bi-moon-stars"></i>
</button>
<button type="button" data-bs-toggle="modal" data-bs-target="#kbd-modal"
title="Keyboard shortcuts (?)"
style="background:none;border:none;color:var(--muted);font-size:13px;padding:3px 6px;border-radius:6px;cursor:pointer;line-height:1;"
@@ -473,6 +558,29 @@
}
});
})();
// ── Dark mode toggle ─────────────────────────────────────────────────
(function () {
var DKEY = 'pfm_dark';
var body = document.body;
var btn = document.getElementById('dark-toggle');
function applyDark(on) {
body.classList.toggle('dark-mode', on);
document.documentElement.setAttribute('data-pfm-dark', on ? '1' : '0');
if (btn) btn.querySelector('i').className = on ? 'bi bi-sun' : 'bi bi-moon-stars';
}
// Initialise from storage
var saved = localStorage.getItem(DKEY) === '1';
applyDark(saved);
if (btn) btn.addEventListener('click', function () {
var next = !body.classList.contains('dark-mode');
localStorage.setItem(DKEY, next ? '1' : '0');
applyDark(next);
});
})();
</script>
{% block extra_js %}{% endblock %}
</body>