Files
LT_Janitorial_Quality_Control/app/static/css/theme.css
T

300 lines
12 KiB
CSS

/* ════════════════════════════════════════════════════════════════════════
Janitorial QC — Global UI Theme
────────────────────────────────────────────────────────────────────────
Purpose: unify every signed-in page onto one polished design system by
retuning Bootstrap's own components. UI/UX only — no markup/route/JS change.
Design tokens (matching the app's premium pages: inspections/view,
templates/form_editor, etc.):
Font DM Sans
Accent #2563eb / hover #1d4ed8 / soft #eff6ff
Slate text #0f172a · heading #374151 · muted #64748b / #94a3b8
border #e2e8f0 / #cbd5e1 · surface #f8fafc / #f1f5f9 · page #eef0f4
Chrome navbar #1a1d23 (matches the dark card-headers on premium pages)
Green #16a34a Amber #f59e0b Danger #dc2626
Shape radius .85rem cards / .5rem controls · soft shadows
Load order: AFTER bootstrap.min.css, BEFORE page-level {% block extra_css %}
so any page's own styles still win.
════════════════════════════════════════════════════════════════════════ */
/* ── 1. Design tokens (retune Bootstrap CSS variables) ───────────────────── */
:root {
--bs-primary: #2563eb;
--bs-primary-rgb: 37, 99, 235;
--bs-success: #16a34a;
--bs-success-rgb: 22, 163, 74;
--bs-warning: #f59e0b;
--bs-warning-rgb: 245, 158, 11;
--bs-danger: #dc2626;
--bs-danger-rgb: 220, 38, 38;
--bs-link-color: #2563eb;
--bs-link-color-rgb: 37, 99, 235;
--bs-link-hover-color: #1d4ed8;
--bs-link-hover-color-rgb: 29, 78, 216;
--bs-body-color: #0f172a;
--bs-body-color-rgb: 15, 23, 42;
--bs-secondary-color: rgba(100, 116, 139, 1);
--bs-body-bg: #eef0f4;
--bs-border-color: #e2e8f0;
--bs-border-radius: .55rem;
--bs-border-radius-sm: .4rem;
--bs-border-radius-lg: .85rem;
--bs-border-radius-xl: 1rem;
--bs-body-font-family: 'DM Sans', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
--jqc-ink: #0f172a;
--jqc-heading: #374151;
--jqc-muted: #64748b;
--jqc-faint: #94a3b8;
--jqc-border: #e2e8f0;
--jqc-border-2: #cbd5e1;
--jqc-surface: #f8fafc;
--jqc-surface-2: #f1f5f9;
--jqc-accent: #2563eb;
--jqc-accent-700: #1d4ed8;
--jqc-accent-50: #eff6ff;
--jqc-navbar: #2563eb; /* bright blue top bar (matches the app accent) */
--jqc-shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 1px 3px rgba(15, 23, 42, .05);
--jqc-shadow-md: 0 4px 24px rgba(15, 23, 42, .10);
}
/* ── 2. Base typography ──────────────────────────────────────────────────── */
body {
font-family: var(--bs-body-font-family);
background-color: var(--bs-body-bg);
color: var(--jqc-ink);
-webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
font-family: var(--bs-body-font-family);
font-weight: 700;
letter-spacing: -.01em;
}
.text-muted { color: var(--jqc-muted) !important; }
a { text-underline-offset: 2px; }
/* ── 3. Navbar — bright blue chrome (app accent) ─────────────────────────── */
.navbar.bg-primary {
background-color: var(--jqc-navbar) !important;
border-bottom: 1px solid rgba(0, 0, 0, .08);
box-shadow: 0 1px 3px rgba(15, 23, 42, .12);
}
.navbar .navbar-brand {
font-weight: 700;
letter-spacing: -.01em;
}
.navbar-dark .navbar-nav .nav-link {
color: rgba(255, 255, 255, .85);
border-radius: 6px;
padding-inline: .7rem;
transition: background-color .15s, color .15s;
}
.navbar-dark .navbar-nav .nav-link:hover {
color: #fff;
background-color: rgba(255, 255, 255, .10);
}
.navbar-dark .navbar-nav .nav-link.active {
background-color: rgba(255, 255, 255, .20) !important;
box-shadow: inset 0 -2px 0 rgba(255, 255, 255, .65) !important;
color: #fff !important;
}
/* ── 4. Cards ────────────────────────────────────────────────────────────── */
.card {
border: 1px solid var(--jqc-border);
border-radius: var(--bs-border-radius-lg);
box-shadow: var(--jqc-shadow);
}
.card.shadow-sm { box-shadow: var(--jqc-shadow) !important; }
.card.shadow,
.card.shadow-lg { box-shadow: var(--jqc-shadow-md) !important; }
.card-header {
background-color: var(--jqc-surface);
border-bottom: 1px solid var(--jqc-border);
color: var(--jqc-heading);
font-weight: 600;
padding: .7rem 1rem;
}
.card-header.bg-light { background-color: var(--jqc-surface) !important; }
.card-header.bg-white { background-color: #fff !important; }
/* Colored stat cards (dashboard) — flatten + soften corners */
.card.text-white { border: none; }
.card.text-white .text-white-50 { color: rgba(255, 255, 255, .72) !important; }
/* ── 5. Buttons ──────────────────────────────────────────────────────────── */
.btn {
font-weight: 500;
border-radius: var(--bs-border-radius);
--bs-btn-focus-box-shadow: 0 0 0 .2rem rgba(37, 99, 235, .25);
}
.btn-primary {
--bs-btn-bg: var(--jqc-accent);
--bs-btn-border-color: var(--jqc-accent);
--bs-btn-hover-bg: var(--jqc-accent-700);
--bs-btn-hover-border-color: var(--jqc-accent-700);
--bs-btn-active-bg: var(--jqc-accent-700);
--bs-btn-active-border-color: var(--jqc-accent-700);
--bs-btn-disabled-bg: var(--jqc-accent);
--bs-btn-disabled-border-color: var(--jqc-accent);
}
.btn-outline-primary {
--bs-btn-color: var(--jqc-accent);
--bs-btn-border-color: var(--jqc-accent);
--bs-btn-hover-bg: var(--jqc-accent);
--bs-btn-hover-border-color: var(--jqc-accent);
--bs-btn-active-bg: var(--jqc-accent);
--bs-btn-active-border-color: var(--jqc-accent);
}
.btn-success {
--bs-btn-bg: var(--bs-success); --bs-btn-border-color: var(--bs-success);
--bs-btn-hover-bg: #15803d; --bs-btn-hover-border-color: #15803d;
--bs-btn-active-bg: #15803d; --bs-btn-active-border-color: #15803d;
--bs-btn-disabled-bg: var(--bs-success); --bs-btn-disabled-border-color: var(--bs-success);
}
.btn-danger {
--bs-btn-bg: var(--bs-danger); --bs-btn-border-color: var(--bs-danger);
--bs-btn-hover-bg: #b91c1c; --bs-btn-hover-border-color: #b91c1c;
--bs-btn-active-bg: #b91c1c; --bs-btn-active-border-color: #b91c1c;
--bs-btn-disabled-bg: var(--bs-danger); --bs-btn-disabled-border-color: var(--bs-danger);
}
.btn-warning {
--bs-btn-bg: var(--bs-warning); --bs-btn-border-color: var(--bs-warning);
--bs-btn-color: #422006; --bs-btn-hover-color: #422006;
--bs-btn-hover-bg: #d97706; --bs-btn-hover-border-color: #d97706;
--bs-btn-active-bg: #d97706; --bs-btn-active-border-color: #d97706;
}
.btn-outline-secondary {
--bs-btn-color: var(--jqc-muted);
--bs-btn-border-color: var(--jqc-border-2);
--bs-btn-hover-bg: var(--jqc-surface);
--bs-btn-hover-color: var(--jqc-accent);
--bs-btn-hover-border-color: var(--jqc-accent);
--bs-btn-active-bg: var(--jqc-surface-2);
--bs-btn-active-color: var(--jqc-ink);
--bs-btn-active-border-color: var(--jqc-border-2);
}
.btn-link { --bs-btn-color: var(--jqc-accent); --bs-btn-hover-color: var(--jqc-accent-700); text-decoration: none; }
/* ── 6. Forms ────────────────────────────────────────────────────────────── */
.form-label {
color: var(--jqc-heading);
font-weight: 500;
margin-bottom: .35rem;
}
.form-control, .form-select {
border-color: var(--jqc-border);
color: var(--jqc-ink);
border-radius: var(--bs-border-radius);
}
.form-control::placeholder { color: var(--jqc-faint); }
.form-control:focus, .form-select:focus {
border-color: var(--jqc-accent);
box-shadow: 0 0 0 .2rem rgba(37, 99, 235, .18);
}
.input-group-text {
background-color: var(--jqc-surface);
border-color: var(--jqc-border);
color: var(--jqc-muted);
}
.form-check-input:checked {
background-color: var(--jqc-accent);
border-color: var(--jqc-accent);
}
.form-check-input:focus {
border-color: var(--jqc-accent);
box-shadow: 0 0 0 .2rem rgba(37, 99, 235, .18);
}
/* ── 7. Tables ───────────────────────────────────────────────────────────── */
.table {
--bs-table-color: var(--jqc-ink);
--bs-table-border-color: var(--jqc-border);
border-color: var(--jqc-border);
margin-bottom: 0;
}
.table > thead th,
.table-light, .table-light > th, .table-light > td {
background-color: var(--jqc-surface-2);
color: var(--jqc-heading);
font-weight: 600;
border-bottom-color: var(--jqc-border);
}
.table > thead th {
text-transform: none;
font-size: .82rem;
letter-spacing: .01em;
padding-block: .6rem;
}
.table > tbody > tr { border-color: var(--jqc-border); }
.table-hover > tbody > tr:hover > * {
background-color: var(--jqc-surface);
--bs-table-bg-state: var(--jqc-surface);
}
/* Cards that wrap a flush table: clip corners so the table follows the radius */
.card > .table-responsive:last-child,
.card > .card-body.p-0 > .table-responsive,
.card > .card-body.p-0 > .table {
border-bottom-left-radius: var(--bs-border-radius-lg);
border-bottom-right-radius: var(--bs-border-radius-lg);
overflow: hidden;
}
/* ── 8. Badges ───────────────────────────────────────────────────────────── */
.badge {
font-weight: 600;
letter-spacing: .01em;
border-radius: .4rem;
padding: .35em .6em;
}
/* ── 9. Alerts ───────────────────────────────────────────────────────────── */
.alert {
border-radius: var(--bs-border-radius);
border-width: 1px;
}
/* ── 10. Dropdowns ───────────────────────────────────────────────────────── */
.dropdown-menu {
border: 1px solid var(--jqc-border);
border-radius: var(--bs-border-radius);
box-shadow: var(--jqc-shadow-md);
padding: .35rem;
--bs-dropdown-link-active-bg: var(--jqc-accent);
}
.dropdown-item {
border-radius: var(--bs-border-radius-sm);
padding: .45rem .7rem;
color: var(--jqc-ink);
}
.dropdown-item:hover, .dropdown-item:focus {
background-color: var(--jqc-surface);
color: var(--jqc-accent);
}
.dropdown-divider { border-top-color: var(--jqc-border); }
/* ── 11. Misc components ─────────────────────────────────────────────────── */
.page-link { color: var(--jqc-accent); }
.page-item.active .page-link {
background-color: var(--jqc-accent);
border-color: var(--jqc-accent);
}
.nav-tabs .nav-link.active { color: var(--jqc-accent); }
.list-group-item-action:hover { background-color: var(--jqc-surface); }
.modal-content { border: 1px solid var(--jqc-border); border-radius: var(--bs-border-radius-lg); }
.spinner-border.text-primary { color: var(--jqc-accent) !important; }
hr { color: var(--jqc-border-2); }
/* Notification dropdown (base.html) — align accent + hover */
.notif-item.unread { border-left-color: var(--jqc-accent) !important; background-color: var(--jqc-accent-50) !important; }
.notif-item:hover { background-color: var(--jqc-surface) !important; }
/* ── 12. Focus visibility (accessibility) ────────────────────────────────── */
:focus-visible { outline: 2px solid rgba(37, 99, 235, .45); outline-offset: 1px; }