refactor: split frontend styles into layered modules

Split the large frontend shared stylesheet into focused layered CSS partials while preserving the stable global entrypoint and existing specialized stylesheet modules.
This commit is contained in:
Daniel Volz
2026-03-26 05:36:50 +01:00
committed by GitHub
parent f670a6355f
commit a1c7e0e62c
11 changed files with 7043 additions and 7001 deletions
+753
View File
@@ -0,0 +1,753 @@
/* biome-ignore-all lint/style/noDescendingSpecificity: legacy shared stylesheet relies on intentional cascade ordering across base and contextual selectors */
/* =============================================================================
Foundation Layer
Owns theme tokens, global element defaults, and app-wide primitives reused
across every MedAssist product surface.
============================================================================= */
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap");
:root {
--bg-primary: #0b1220;
--bg-secondary: #111827;
--bg-tertiary: #0d1424;
--bg-input: #0a1018;
--bg-gradient: radial-gradient(circle at 20% 20%, #1a2440, #0b1220 40%), #0b1220;
--border-primary: #1f2a3d;
--border-secondary: #2a3a4d;
--text-primary: #e5e7eb;
--text-secondary: #a3adc2;
--text-muted: #cbd5f5;
--accent: #2f86f6;
--accent-light: #7ca7ff;
--accent-bg: rgba(47, 134, 246, 0.1);
--success: #6ee7b7;
--success-bg: rgba(57, 217, 138, 0.12);
--danger: #fca5a5;
--danger-bg: rgba(255, 94, 94, 0.12);
--warning: #fcd34d;
--warning-bg: rgba(252, 211, 77, 0.12);
--info: #93c5fd;
--shadow: rgba(0, 0, 0, 0.25);
/* Button Design System */
--btn-radius: 10px;
--input-radius: 10px;
--btn-radius-round: 50%;
--btn-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
--btn-shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.2);
--btn-primary-bg: var(--accent);
--btn-primary-hover: #3d94ff;
--btn-ghost-hover: rgba(255, 255, 255, 0.08);
--btn-danger-text: #2f0a0a;
--btn-success-text: #0a2b1f;
--btn-obsolete-bg: linear-gradient(135deg, #f7d14a 0%, #f2b91a 100%);
--btn-obsolete-hover: linear-gradient(135deg, #f9db72 0%, #f5c73c 100%);
--btn-obsolete-text: #2b2205;
--btn-obsolete-border: #f8e38a;
--btn-obsolete-shadow: 0 6px 14px rgba(252, 211, 77, 0.28);
}
[data-theme="light"] {
--bg-primary: #f8fafc;
--bg-secondary: #ffffff;
--bg-tertiary: #f1f5f9;
--bg-input: #ffffff;
--bg-gradient: linear-gradient(135deg, #f0f4ff 0%, #e8f0fe 100%);
--border-primary: #e2e8f0;
--border-secondary: #cbd5e1;
--text-primary: #1e293b;
--text-secondary: #64748b;
--text-muted: #475569;
--accent: #2563eb;
--accent-light: #3b82f6;
--accent-bg: rgba(37, 99, 235, 0.1);
--success: #10b981;
--success-bg: rgba(16, 185, 129, 0.1);
--danger: #ef4444;
--danger-bg: rgba(239, 68, 68, 0.1);
--warning: #f59e0b;
--warning-bg: rgba(245, 158, 11, 0.1);
--info: #3b82f6;
--shadow: rgba(0, 0, 0, 0.08);
/* Button Design System */
--btn-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
--btn-shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.12);
--btn-primary-bg: var(--accent);
--btn-primary-hover: #1d4ed8;
--btn-ghost-hover: rgba(0, 0, 0, 0.06);
--btn-danger-text: #ffffff;
--btn-success-text: #ffffff;
--btn-obsolete-bg: linear-gradient(135deg, #f5b52c 0%, #f59e0b 100%);
--btn-obsolete-hover: linear-gradient(135deg, #f8c85b 0%, #f7ad2d 100%);
--btn-obsolete-text: #ffffff;
--btn-obsolete-border: #d48806;
--btn-obsolete-shadow: 0 6px 14px rgba(245, 158, 11, 0.22);
}
* {
box-sizing: border-box;
}
html {
overflow-x: hidden;
background: var(--bg-primary);
}
body {
margin: 0;
font-family: "Space Grotesk", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
background: var(--bg-gradient);
color: var(--text-primary);
min-height: 100vh;
overflow-x: hidden;
transition:
background 200ms ease,
color 200ms ease;
}
html.modal-open,
body.modal-open {
overflow: hidden !important;
}
.page {
max-width: 1200px;
margin: 0 auto;
padding: 2.5rem 1.5rem 1.5rem;
overflow-x: hidden;
}
.route-transition-mask {
position: fixed;
inset: 0;
background: var(--bg-primary);
opacity: 0;
pointer-events: none;
transition: opacity 140ms ease-out;
z-index: 1500;
}
.route-transition-mask.active {
transition: none;
opacity: 1;
pointer-events: none;
}
.hero {
background: linear-gradient(135deg, rgba(67, 106, 255, 0.08), rgba(115, 195, 255, 0.06));
border: 1px solid var(--border-primary);
border-radius: 16px;
padding: 1.25rem 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
gap: 1.5rem;
box-shadow: 0 8px 32px var(--shadow);
margin-bottom: 1.5rem;
transition:
background 200ms ease,
border-color 200ms ease;
}
[data-theme='"light"'] .hero {
background: linear-gradient(135deg, rgba(37, 99, 235, 0.06), rgba(59, 130, 246, 0.04));
}
.header-actions {
display: flex;
align-items: center;
gap: 0.75rem;
}
.icon-btn {
width: 40px;
height: 40px;
border-radius: var(--btn-radius-round);
background: transparent;
border: none;
cursor: pointer;
font-size: 1.2rem;
display: flex;
align-items: center;
justify-content: center;
transition:
background 150ms ease,
opacity 150ms ease;
padding: 0;
opacity: 0.7;
box-shadow: none;
}
.icon-btn:hover {
background: var(--btn-ghost-hover);
opacity: 1;
}
.icon-btn.active {
opacity: 1;
background: rgba(47, 134, 246, 0.15);
}
[data-theme="light"] .icon-btn:hover {
background: var(--btn-ghost-hover);
}
[data-theme="light"] .icon-btn.active {
background: rgba(47, 134, 246, 0.12);
}
/* =============================================================================
Theme Dropdown Menu
============================================================================= */
.theme-menu {
position: relative;
}
.theme-dropdown {
position: absolute;
top: calc(100% + 0.5rem);
right: 0;
min-width: 160px;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 12px;
box-shadow:
0 12px 32px rgba(0, 0, 0, 0.4),
inset 0 0 0 1px rgba(255, 255, 255, 0.05);
opacity: 0;
visibility: hidden;
transform: translateY(-6px) scale(0.95);
transition: all 0.2s ease;
z-index: 1000;
overflow: hidden;
padding: 0.375rem;
}
[data-theme="light"] .theme-dropdown {
background: rgba(255, 255, 255, 0.85);
border: 1px solid rgba(0, 0, 0, 0.08);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
}
.theme-menu.open .theme-dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0) scale(1);
}
.theme-dropdown-item {
display: flex;
align-items: center;
gap: 0.75rem;
width: 100%;
padding: 0.625rem 0.75rem;
border: none;
background: none;
color: var(--text-primary);
font-size: 0.875rem;
cursor: pointer;
border-radius: 8px;
transition: background 0.15s ease;
text-align: left;
box-shadow: none;
}
.theme-dropdown-item:hover {
background: rgba(59, 130, 246, 0.15);
}
.theme-dropdown-item.active {
color: var(--accent-primary);
}
.theme-dropdown-item svg {
width: 18px;
height: 18px;
flex-shrink: 0;
opacity: 0.7;
}
.theme-dropdown-item.active svg {
opacity: 1;
color: var(--accent-primary);
}
.theme-check {
margin-left: auto;
font-size: 0.8rem;
opacity: 0.8;
}
.hero-title {
display: flex;
align-items: center;
gap: 1rem;
}
.hero-logo {
width: 48px;
height: 48px;
}
.hero h1 {
margin: 0.15rem 0 0;
font-size: 1.6rem;
font-weight: 600;
}
.sub {
color: var(--text-secondary);
margin: 0;
}
.eyebrow {
letter-spacing: 0.06em;
text-transform: uppercase;
color: #7ca7ff;
font-size: 0.75rem;
margin: 0;
font-weight: 500;
}
/* Reminder status bar */
.reminder-status-bar {
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: 0.875rem 1rem;
background: var(--accent-bg);
border: 1px solid var(--border-primary);
border-radius: 10px;
margin-bottom: 1rem;
font-size: 0.85rem;
}
.reminder-status-header {
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
}
.reminder-status-icon {
color: var(--accent);
display: flex;
align-items: center;
flex-shrink: 0;
}
.reminder-status-title {
color: var(--text-primary);
font-weight: 500;
}
.reminder-status-badge {
padding: 0.25rem 0.6rem;
border-radius: 6px;
font-size: 0.75rem;
font-weight: 500;
}
.reminder-status-badge.success {
background: var(--success-bg);
color: var(--success);
}
.reminder-status-badge.warning {
background: var(--warning-bg);
color: var(--warning);
}
.reminder-status-badge.danger {
background: var(--danger-bg);
color: var(--danger);
}
.reminder-status-details {
display: flex;
flex-direction: column;
gap: 0.5rem;
padding-left: 1.75rem;
}
.reminder-status-row {
display: flex;
align-items: baseline;
gap: 0.5rem;
color: var(--text-secondary);
font-size: 0.8rem;
}
.reminder-status-label {
color: var(--text-muted);
flex-shrink: 0;
}
.reminder-status-value {
color: var(--text-primary);
}
.reminder-status-meta {
color: var(--text-muted);
font-size: 0.75rem;
padding: 0.1rem 0.4rem;
background: var(--bg-tertiary);
border-radius: 4px;
}
.reminder-med-name {
font-weight: 500;
color: var(--text-primary);
}
.reminder-taken-by {
color: var(--text-muted);
font-size: 0.85rem;
margin-left: 0.25rem;
margin-right: 0.4rem;
}
.reminder-date {
color: var(--text-secondary);
}
.reminder-days-left {
color: var(--warning);
font-size: 0.8rem;
}
.critical .reminder-days-left {
color: var(--danger);
}
.reminder-send-row {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.35rem;
padding-left: 1.75rem;
padding-top: 0.25rem;
}
.reminder-send-row .ghost {
font-size: 0.8rem;
padding: 0.25rem 0.75rem;
}
.reminder-send-result {
font-size: 0.8rem;
}
.reminder-send-result.success {
color: var(--success);
}
.reminder-send-result.error {
color: var(--danger);
}
.reminder-status-skeleton .reminder-status-title {
color: var(--text-secondary);
}
.reminder-status-skeleton-lines {
gap: 0.45rem;
}
.skeleton-line {
display: block;
height: 0.75rem;
border-radius: 999px;
position: relative;
overflow: hidden;
background: color-mix(in srgb, var(--bg-tertiary) 78%, transparent);
max-width: 100%;
}
.skeleton-line::after {
content: "";
position: absolute;
inset: 0;
transform: translateX(-100%);
background: linear-gradient(
90deg,
transparent 0%,
color-mix(in srgb, var(--text-muted) 30%, transparent) 45%,
transparent 100%
);
animation: reminderSkeletonSweep 1.1s linear infinite;
}
.skeleton-line-long {
width: min(540px, 96%);
}
.skeleton-line-medium {
width: min(420px, 82%);
}
.skeleton-line-short {
width: min(300px, 68%);
}
.skeleton-pill {
width: 110px;
height: 2.25rem;
border-radius: 10px;
}
.dashboard-card-skeleton {
display: flex;
flex-direction: column;
gap: 0.55rem;
padding: 0.35rem 0;
}
.dashboard-actions-skeleton {
align-items: center;
}
.page-loading-skeleton {
display: flex;
flex-direction: column;
gap: 1rem;
}
.skeleton-card {
display: flex;
flex-direction: column;
gap: 0.65rem;
padding: 0.25rem 0;
}
.shared-schedule-loading-skeleton .skeleton-card {
max-width: 540px;
margin: 0.75rem auto 0;
}
.screen-reader-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
@keyframes reminderSkeletonSweep {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
.med-link {
font-weight: 600;
text-decoration: underline;
text-decoration-style: dotted;
text-underline-offset: 2px;
}
.med-link.clickable {
cursor: pointer;
}
.med-link.clickable:hover {
color: var(--accent);
text-decoration-style: solid;
}
@media (max-width: 600px) {
.reminder-status-bar {
padding: 0.75rem;
}
.reminder-status-header {
flex-wrap: wrap;
}
.reminder-status-badge {
margin-left: 0;
margin-top: 0.25rem;
}
.reminder-status-details {
padding-left: 0;
}
.reminder-status-row {
flex-direction: column;
gap: 0.15rem;
}
.reminder-low-stock-list {
padding-left: 0;
}
.reminder-send-row {
padding-left: 0;
}
}
.tabs {
display: flex;
gap: 0.5rem;
}
.stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.75rem;
align-items: center;
}
.stat {
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 14px;
padding: 0.9rem;
}
.stat .label {
margin: 0;
color: #b7c2e5;
font-size: 0.9rem;
}
.stat .value {
margin: 0.25rem 0 0;
font-size: 1.4rem;
font-weight: 700;
}
.grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
margin-bottom: 1rem;
max-width: 100%;
overflow: hidden;
}
.card {
background: var(--bg-secondary);
border: 1px solid var(--border-primary);
border-radius: 14px;
padding: 1.25rem;
box-shadow: 0 14px 36px var(--shadow);
transition:
background 200ms ease,
border-color 200ms ease;
}
.card-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
margin-bottom: 1rem;
}
.card h2 {
margin: 0;
font-size: 1.2rem;
}
.card h2.clickable {
cursor: pointer;
transition: color 0.15s;
}
.card h2.clickable:hover {
color: var(--accent-light);
}
.edit-header {
display: flex;
align-items: center;
gap: 0.75rem;
}
.edit-header h2 {
margin: 0;
font-size: 1.1rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.schedule-full {
max-width: 100%;
}
.select-field.schedule-days-select,
.schedule-days-select {
background-color: var(--accent-bg);
border: 1px solid var(--accent);
color: var(--text-muted);
padding: 0.25rem 2rem 0.25rem 0.5rem;
border-radius: 6px;
font-size: 0.75rem;
cursor: pointer;
outline: none;
transition: all 150ms ease;
width: auto;
max-width: 100px;
flex-shrink: 0;
background-position: right 0.6rem center;
}
.select-field.schedule-days-select:hover,
.schedule-days-select:hover {
filter: brightness(1.15);
}
.select-field.schedule-days-select:focus,
.schedule-days-select:focus {
border-color: var(--accent-light);
}
.pill {
border: 1px solid var(--accent);
color: var(--text-muted);
background: var(--accent-bg);
padding: 0.35rem 0.7rem;
border-radius: 999px;
font-size: 0.85rem;
transition:
background 150ms ease,
border-color 150ms ease;
}
.pill.clickable {
cursor: pointer;
}
.pill.clickable:hover {
filter: brightness(1.1);
}
.pill.success {
border-color: var(--success);
background: var(--success-bg);
color: var(--success);
}
.pill.neutral {
border-color: var(--border-secondary);
background: rgba(255, 255, 255, 0.04);
color: var(--text-muted);
}
[data-theme='"light"'] .pill.neutral {
background: rgba(0, 0, 0, 0.04);
}
.tabs .pill {
cursor: pointer;
transition:
background 150ms ease,
border-color 150ms ease;
background: transparent;
border: 1px solid var(--border-secondary);
color: var(--text-muted);
box-shadow: none;
}
.tabs .pill:hover {
background: var(--btn-ghost-hover);
border-color: var(--accent);
}
.tabs .pill.primary {
background: var(--accent-bg);
border-color: var(--accent);
color: var(--text-primary);
}
.badges {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
margin-top: 0.6rem;
}
.meds .med-list {
display: flex;
flex-direction: column;
gap: 0.75rem;
}