/* ════════════════════════════════════════════════════════════════════════ 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; }