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
+11 -7000
View File
File diff suppressed because it is too large Load Diff
+458
View File
@@ -0,0 +1,458 @@
/* biome-ignore-all lint/style/noDescendingSpecificity: extracted brownfield layer preserves intentional selector ordering while the CSS split remains behavior-compatible */
/* =============================================================================
About And Report Layer
Owns about modal, report, and adjacent informational overlay presentation.
============================================================================= */
.about-modal {
max-width: 380px;
padding: 0;
overflow-y: auto;
text-align: center;
}
.about-header {
padding: 2rem 1.5rem 1.5rem;
background: var(--bg-tertiary);
border-bottom: 1px solid var(--border-primary);
}
.about-logo {
width: 64px;
height: 64px;
margin: 0 auto 1rem;
}
.about-logo img {
width: 64px;
height: 64px;
border-radius: 16px;
}
.about-header h2 {
font-size: 1.5rem;
font-weight: 700;
margin: 0 0 0.5rem;
color: var(--text-primary);
}
.about-tagline {
font-size: 0.875rem;
color: var(--text-secondary);
margin: 0;
line-height: 1.4;
}
.about-versions {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid var(--border-primary);
}
.about-version-row {
display: flex;
justify-content: center;
align-items: center;
gap: 0.75rem;
padding: 0.5rem 0;
}
.about-version-label {
font-size: 0.875rem;
color: var(--text-secondary);
}
.about-version-value {
font-size: 0.875rem;
font-weight: 600;
color: var(--text-primary);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
background: var(--bg-tertiary);
padding: 0.25rem 0.5rem;
border-radius: 4px;
}
a.about-version-link {
color: var(--accent-primary);
text-decoration: none;
transition: text-decoration 0.15s ease;
}
a.about-version-link:hover {
text-decoration: underline;
}
.about-update-section {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid var(--border-primary);
}
.about-update-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.625rem 1.25rem;
font-size: 0.875rem;
font-weight: 500;
border: 1px solid var(--border-primary);
border-radius: 8px;
background: var(--bg-secondary);
color: var(--text-primary);
cursor: pointer;
transition: all 0.2s ease;
width: 100%;
}
.about-update-btn:hover:not(:disabled) {
background: var(--bg-tertiary);
border-color: var(--accent);
color: var(--accent);
}
.about-update-btn:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.about-update-btn svg {
width: 16px;
height: 16px;
}
.spinner-small {
width: 16px;
height: 16px;
border: 2px solid var(--border-primary);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.about-update-result {
margin-top: 1rem;
padding: 0.75rem;
border-radius: 8px;
font-size: 0.875rem;
}
.about-update-result.up-to-date {
background: rgba(34, 197, 94, 0.1);
color: var(--success);
}
.about-update-result.update-available {
background: rgba(59, 130, 246, 0.1);
color: var(--accent);
}
.about-update-result.error {
background: rgba(239, 68, 68, 0.1);
color: var(--error);
}
.update-status-text {
display: block;
font-weight: 500;
}
.update-status-text strong {
font-weight: 700;
}
.update-download-link {
display: inline-block;
margin-left: 0.5rem;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
font-weight: 600;
background: var(--accent);
color: white;
border-radius: 4px;
text-decoration: none;
transition: background 0.2s ease;
}
.update-download-link:hover {
background: var(--accent-hover);
}
.about-links {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid var(--border-primary);
}
.about-link {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.625rem 1.25rem;
font-size: 0.875rem;
font-weight: 500;
border: 1px solid var(--border-primary);
border-radius: 8px;
background: var(--bg-secondary);
color: var(--text-primary);
text-decoration: none;
transition: all 0.2s ease;
}
.about-link:hover {
background: var(--bg-tertiary);
border-color: var(--text-secondary);
}
.about-link svg {
width: 18px;
height: 18px;
}
.about-footer {
padding: 1.25rem 1.5rem;
background: var(--bg-tertiary);
}
.about-copyright {
font-size: 0.75rem;
color: var(--text-secondary);
margin: 0 0 0.25rem;
}
.about-license {
font-size: 0.75rem;
color: var(--text-tertiary);
margin: 0;
}
/* Share dialog styles moved to styles/share-dialog.css */
.card-head-actions {
display: flex;
gap: 0.75rem;
align-items: center;
}
.dashboard-main-sections {
display: flex;
flex-direction: column;
}
.dashboard-schedules-section {
overflow: visible;
}
.dashboard-main-sections-swapped .dashboard-schedules-section {
order: 1;
}
.dashboard-main-sections-swapped .dashboard-overview-section {
order: 2;
}
.card-head-actions > button,
.edit-header > button.btn-nav {
min-height: 3rem;
padding: 0 1.15rem;
display: inline-flex;
align-items: center;
justify-content: center;
}
/* Shared schedule + mobile edit styles moved to styles/schedule-mobile-edit.css */
/* =============================================================================
Report Modal
============================================================================= */
.report-modal {
max-width: 520px;
padding: 1.5rem;
}
.report-modal-title {
font-size: 1.25rem;
margin: 0 0 0.25rem;
padding-right: 2rem;
}
.report-modal-desc {
color: var(--text-secondary);
font-size: 0.875rem;
margin: 0 0 1.25rem;
}
/* Person filter */
.report-person-filter {
margin-bottom: 1.25rem;
}
.report-person-filter .report-format-options {
min-height: 4.5rem;
align-content: flex-start;
}
.report-person-filter h4 {
font-size: 0.85rem;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--text-muted);
margin: 0 0 0.5rem;
}
.report-person-filter .report-format-option input[type="checkbox"] {
display: none;
}
/* Medication selection area */
.report-selection {
height: 280px;
overflow-y: auto;
border: 1px solid var(--border-primary);
border-radius: 10px;
padding: 0.75rem;
margin-bottom: 1.25rem;
background: color-mix(in srgb, var(--bg-secondary) 75%, var(--bg-tertiary));
}
.report-selection-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.5rem;
}
.report-selection-count {
font-size: 0.8rem;
color: var(--text-secondary);
font-weight: 500;
}
.report-group {
margin-bottom: 0.5rem;
}
.report-group-title {
font-size: 0.78rem;
font-weight: 700;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.04em;
margin: 0.5rem 0 0.35rem;
}
.report-med-list {
display: flex;
flex-direction: column;
gap: 0.2rem;
}
.report-med-item {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.4rem 0.5rem;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s ease;
}
.report-med-item:hover {
background: var(--accent-bg);
}
.report-med-item input[type="checkbox"] {
width: 16px;
height: 16px;
margin: 0;
padding: 0;
flex-shrink: 0;
accent-color: var(--accent);
cursor: pointer;
}
.report-med-name {
flex: 1;
min-width: 0;
font-size: 0.9rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.report-med-name.obsolete-name {
color: var(--text-secondary);
font-style: italic;
}
.report-med-generic {
color: var(--text-secondary);
font-size: 0.8rem;
}
/* Format selection */
.report-format {
margin-bottom: 1.25rem;
}
.report-format h4 {
font-size: 0.85rem;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--text-muted);
margin: 0 0 0.5rem;
}
.report-format-options {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.report-format-option {
display: flex;
align-items: center;
gap: 0.35rem;
padding: 0.45rem 0.85rem;
border: 1px solid var(--border-secondary);
border-radius: 8px;
cursor: pointer;
font-size: 0.85rem;
font-weight: 500;
color: var(--text-secondary);
background: transparent;
transition:
border-color 0.15s ease,
background 0.15s ease,
color 0.15s ease;
}
.report-format-option:hover {
border-color: var(--accent);
color: var(--text-primary);
background: var(--accent-bg);
}
.report-format-option.selected {
border-color: var(--accent);
background: var(--accent-bg);
color: var(--accent-light);
font-weight: 600;
}
.report-format-option input[type="radio"] {
display: none;
}
/* Actions */
.report-actions {
display: flex;
justify-content: flex-end;
gap: 0.75rem;
padding-top: 0.75rem;
border-top: 1px solid var(--border-primary);
}
File diff suppressed because it is too large Load Diff
+704
View File
@@ -0,0 +1,704 @@
/* =============================================================================
Auth And Profile Layer
Owns authentication, password reset, and profile/account presentation.
============================================================================= */
.auth-container {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: var(--bg-gradient);
padding: 1rem;
}
.auth-card {
background: var(--bg-secondary);
border: 1px solid var(--border-primary);
border-radius: 16px;
padding: 2.5rem;
width: 100%;
max-width: 420px;
box-shadow: 0 10px 40px var(--shadow);
}
.auth-title {
font-size: 2rem;
font-weight: 700;
text-align: center;
margin: 0 0 0.5rem 0;
color: var(--text-primary);
}
.auth-subtitle {
font-size: 1.25rem;
font-weight: 500;
text-align: center;
margin: 0 0 1.5rem 0;
color: var(--text-secondary);
}
.auth-info {
text-align: center;
color: var(--text-secondary);
margin-bottom: 1.5rem;
padding: 1rem;
background: var(--accent-bg);
border-radius: 8px;
font-size: 0.9rem;
}
.auth-form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.auth-error {
background: var(--danger-bg);
color: var(--danger);
padding: 0.75rem 1rem;
border-radius: 8px;
font-size: 0.9rem;
text-align: center;
}
.auth-success {
background: var(--success-bg);
color: var(--success);
padding: 0.75rem 1rem;
border-radius: 8px;
font-size: 0.9rem;
text-align: center;
}
.auth-submit {
margin-top: 0.5rem;
padding: 0.875rem;
font-size: 1rem;
font-weight: 600;
}
/* SSO Login Button */
.auth-sso {
margin-bottom: 1rem;
}
.sso-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
width: 100%;
background: var(--card-bg);
border: 1px solid var(--border-primary);
color: var(--text-primary);
transition: all 0.2s ease;
}
.sso-btn:hover {
background: var(--hover-bg);
border-color: var(--accent);
color: var(--accent);
}
.sso-icon {
width: 1.25rem;
height: 1.25rem;
flex-shrink: 0;
}
.auth-divider {
display: flex;
align-items: center;
gap: 1rem;
margin: 1.25rem 0;
color: var(--text-muted);
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.auth-divider::before,
.auth-divider::after {
content: "";
flex: 1;
height: 1px;
background: var(--border-primary);
}
.auth-form .checkbox-group {
margin-bottom: 0.5rem;
}
.auth-form .checkbox-label {
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
font-size: 0.9rem;
color: var(--text-secondary);
}
.auth-form .checkbox-label input[type="checkbox"] {
width: 1rem;
height: 1rem;
accent-color: var(--accent);
cursor: pointer;
}
/* Password Input with Toggle */
.password-input-wrapper {
position: relative;
display: flex;
align-items: center;
}
.password-input-wrapper input {
width: 100%;
padding-right: 2.5rem;
}
.password-toggle-btn {
position: absolute;
right: 0.5rem;
background: none;
border: none;
padding: 0.25rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-tertiary);
transition: color 0.15s ease;
}
.password-toggle-btn:hover {
color: var(--text-secondary);
}
.password-toggle-btn svg {
width: 1.25rem;
height: 1.25rem;
}
.auth-links {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.75rem;
margin-top: 1.5rem;
padding-top: 1.5rem;
border-top: 1px solid var(--border-primary);
}
.auth-link,
.auth-link-btn {
color: var(--accent);
text-decoration: none;
font-size: 0.9rem;
background: none;
border: none;
cursor: pointer;
padding: 0;
}
.auth-link:hover,
.auth-link-btn:hover {
text-decoration: underline;
color: var(--accent-light);
}
/* Profile Component */
.profile-container {
padding: 0;
}
.profile-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1.5rem;
padding-right: 2.5rem; /* Space for modal close button */
}
.profile-header h2 {
margin: 0;
font-size: 1.25rem;
}
.profile-role {
background: var(--accent-bg);
color: var(--accent);
padding: 0.25rem 0.75rem;
border-radius: 100px;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
}
.profile-info {
margin-bottom: 1.5rem;
padding: 1rem;
background: var(--bg-tertiary);
border-radius: 8px;
}
.profile-info p {
margin: 0;
color: var(--text-secondary);
}
.profile-form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.profile-form h3 {
margin: 0.5rem 0 0 0;
font-size: 1rem;
color: var(--text-secondary);
}
.profile-divider {
border: none;
border-top: 1px solid var(--border-primary);
margin: 0.5rem 0;
}
.profile-actions {
display: flex;
gap: 1rem;
margin-top: 0.5rem;
}
.profile-actions .btn {
flex: 1;
}
/* User Menu Dropdown in Header */
.user-menu {
position: relative;
}
.user-menu-btn {
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: none;
padding: 0;
cursor: pointer;
border-radius: 50%;
box-shadow: none;
}
.user-menu-btn:hover {
background: transparent;
}
.user-menu-btn .user-avatar {
width: 36px;
height: 36px;
background: var(--accent);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 0.9rem;
border: 2px solid transparent;
transition: border-color 150ms ease;
}
.user-menu-btn .user-avatar-img {
width: 36px;
height: 36px;
border-radius: 50%;
object-fit: cover;
border: 2px solid transparent;
transition: border-color 150ms ease;
}
.user-menu:hover .user-menu-btn .user-avatar,
.user-menu:hover .user-menu-btn .user-avatar-img {
border-color: var(--accent);
}
.user-dropdown {
position: absolute;
top: calc(100% + 0.75rem);
right: 0;
width: 260px;
background: rgba(15, 23, 42, 0.75);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 16px;
box-shadow:
0 16px 48px rgba(0, 0, 0, 0.5),
inset 0 0 0 1px rgba(255, 255, 255, 0.05);
opacity: 0;
visibility: hidden;
transform: translateY(-8px) scale(0.95);
transition: all 0.2s ease;
z-index: 1000;
overflow: hidden;
}
[data-theme="light"] .user-dropdown {
background: rgba(255, 255, 255, 0.75);
border: 1px solid rgba(0, 0, 0, 0.08);
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.15);
}
/* Only use hover on devices that support it (not touch) */
@media (hover: hover) and (pointer: fine) {
.user-menu:hover .user-dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0) scale(1);
}
}
/* Click-based open for all devices */
.user-menu.open .user-dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0) scale(1);
}
.dropdown-header {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.25rem;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, rgba(147, 51, 234, 0.1) 100%);
border-bottom: 1px solid var(--border-primary);
}
.dropdown-avatar {
width: 48px;
height: 48px;
background: var(--accent);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 1.25rem;
flex-shrink: 0;
}
.dropdown-avatar-img {
width: 48px;
height: 48px;
border-radius: 50%;
object-fit: cover;
flex-shrink: 0;
}
.dropdown-user-info {
display: flex;
flex-direction: column;
gap: 0.125rem;
min-width: 0;
}
.dropdown-username {
font-size: 1rem;
font-weight: 600;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.dropdown-role {
font-size: 0.75rem;
color: var(--text-secondary);
}
.dropdown-menu {
padding: 0.5rem;
}
.dropdown-item {
display: flex;
align-items: center;
gap: 0.875rem;
width: 100%;
padding: 0.75rem 1rem;
border: none;
background: none;
color: var(--text-primary);
font-size: 0.9rem;
cursor: pointer;
border-radius: 10px;
transition:
background 0.15s ease,
color 0.15s ease;
text-align: left;
}
.dropdown-item:hover {
background: rgba(59, 130, 246, 0.15);
color: var(--text-primary);
}
.dropdown-item:hover svg {
opacity: 1;
color: var(--accent);
}
/* Override danger button styles for dropdown items */
.dropdown-item.danger,
[data-theme="light"] .dropdown-item.danger {
background: none !important;
color: var(--text-primary);
border: none;
box-shadow: none;
}
.dropdown-item.danger:hover,
[data-theme="light"] .dropdown-item.danger:hover {
background: rgba(239, 68, 68, 0.15) !important;
color: var(--danger);
}
.dropdown-item svg {
width: 20px;
height: 20px;
flex-shrink: 0;
opacity: 0.7;
}
@media (max-width: 600px) {
.auth-card {
padding: 1.5rem;
}
.auth-title {
font-size: 1.75rem;
}
}
/* Profile Modal */
.profile-modal {
max-width: 420px;
padding: 0;
overflow-y: auto;
max-height: 90vh;
}
.profile-container {
padding: 0;
}
.profile-user-section {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.5rem;
background: var(--bg-tertiary);
border-bottom: 1px solid var(--border-primary);
}
.profile-avatar-wrapper {
position: relative;
}
.profile-avatar {
width: 64px;
height: 64px;
background: var(--text-tertiary);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 1.75rem;
flex-shrink: 0;
}
.profile-avatar-img {
width: 64px;
height: 64px;
border-radius: 50%;
object-fit: cover;
}
.profile-avatar-actions {
position: absolute;
bottom: -4px;
right: -4px;
display: flex;
gap: 0.25rem;
}
.avatar-btn {
width: 28px;
height: 28px;
min-width: 28px;
min-height: 28px;
border-radius: var(--btn-radius-round);
border: 2px solid var(--bg-secondary);
background: var(--bg-tertiary);
color: var(--text-primary);
font-size: 0.75rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
transition:
background 150ms ease,
color 150ms ease;
box-shadow: none;
}
.avatar-btn:hover {
background: var(--accent);
color: white;
}
.avatar-btn.danger:hover {
background: var(--danger);
}
.avatar-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.profile-username {
font-size: 1.25rem;
font-weight: 600;
color: var(--text-primary);
}
.profile-form {
padding: 1.5rem;
}
.profile-section {
margin-bottom: 1.5rem;
}
.profile-section-title {
font-size: 0.8rem;
font-weight: 600;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
margin: 0 0 1rem 0;
padding-bottom: 0;
}
.profile-form .form-group {
margin-bottom: 1rem;
}
.profile-form .form-group label {
display: block;
font-size: 0.85rem;
font-weight: 500;
margin-bottom: 0.375rem;
color: var(--text-primary);
}
.profile-form .form-group input {
width: 100%;
padding: 0.625rem 0.875rem;
border: 1px solid var(--border-primary);
border-radius: 8px;
background: var(--bg-input);
color: var(--text-primary);
font-size: 0.9rem;
transition: border-color 0.2s ease;
}
.profile-form .form-group input:focus {
outline: none;
border-color: var(--accent);
}
.profile-form .form-group input::placeholder {
color: var(--text-tertiary);
}
.profile-actions {
display: flex;
gap: 0.75rem;
justify-content: flex-end;
padding-top: 0;
margin-top: 0.5rem;
}
.profile-actions .btn {
padding: 0.5rem 1rem;
font-size: 0.875rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
}
.profile-actions .btn-ghost {
background: none;
border: 1px solid var(--border-primary);
color: var(--text-secondary);
}
.profile-actions .btn-ghost:hover {
background: var(--bg-tertiary);
color: var(--text-primary);
}
.profile-actions .btn-primary {
background: var(--accent);
border: none;
color: white;
}
.profile-actions .btn-primary:hover:not(:disabled) {
background: var(--accent-hover);
}
.profile-actions .btn-primary:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Profile danger zone */
.profile-danger-zone {
margin: 0 1.5rem 1.5rem;
padding-top: 1rem;
}
.profile-danger-zone .profile-section-title {
margin-bottom: 0.75rem;
}
.btn-danger {
background: #dc2626;
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 6px;
font-weight: 500;
cursor: pointer;
transition: background 0.15s ease;
}
.btn-danger:hover:not(:disabled) {
background: #b91c1c;
}
.btn-danger:disabled {
opacity: 0.5;
cursor: not-allowed;
}
+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;
}
@@ -1,5 +1,7 @@
/* =============================================================================
Refill Modal & History
Owns medication workflow overlays and history views that are intentionally
kept separate from broader app-surface styling.
============================================================================= */
.refill-modal {
max-width: 500px;
+770
View File
@@ -0,0 +1,770 @@
/* biome-ignore-all lint/style/noDescendingSpecificity: extracted brownfield layer preserves intentional selector ordering while the CSS split remains behavior-compatible */
/* =============================================================================
Modal And Detail Layer
Owns medication detail and other modal-heavy detail flows that compose on top
of the shared modal base styles.
============================================================================= */
/* Medication Detail Modal */
.modal-content.med-detail-modal {
padding: 0;
width: min(100vw - 1rem, 711px);
max-width: 711px;
max-height: 90vh;
background: var(--bg-primary);
overscroll-behavior: contain;
display: flex;
flex-direction: column;
overflow: visible;
}
.med-detail-modal .med-detail-body {
flex: 1;
min-height: 0;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
}
.med-detail-header {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
padding: 2rem 2rem 2rem;
margin-bottom: 0.5rem;
background: linear-gradient(135deg, var(--accent) 0%, var(--accent-light) 100%);
color: white;
border-radius: 12px 12px 0 0;
}
.med-detail-header h2 {
margin: 0;
font-size: 1.5rem;
text-align: center;
}
.med-detail-titles {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.25rem;
}
.med-generic-name {
font-size: 0.95rem;
color: rgba(255, 255, 255, 0.75);
font-weight: 400;
}
.med-taken-by {
font-size: 1rem;
color: white;
font-weight: 600;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
text-align: center;
}
.taken-by-badge {
font-size: 0.75rem;
color: var(--accent);
font-weight: 500;
margin-left: 0.35rem;
opacity: 0.85;
}
.taken-by-badge.clickable,
.taken-by-name.clickable {
cursor: pointer;
transition: opacity 0.15s;
}
.taken-by-badge.clickable:hover,
.taken-by-name.clickable:hover {
opacity: 1;
text-decoration: underline;
}
/* User Medications Modal */
.modal-content.user-meds-modal {
max-width: 500px;
width: 95%;
padding: 0;
border-radius: 16px;
overflow: hidden;
}
.user-meds-header {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.5rem 2rem;
background: linear-gradient(135deg, var(--accent) 0%, #1e5bb8 100%);
border-radius: 16px 16px 0 0;
}
.user-meds-header .user-avatar {
width: 50px;
min-width: 50px;
height: 50px;
min-height: 50px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
font-weight: 700;
color: white;
flex-shrink: 0;
}
.user-meds-header h2 {
margin: 0;
color: white;
font-size: 1.3rem;
}
.user-meds-list {
padding: 1rem;
max-height: 400px;
overflow-y: auto;
}
.user-med-item {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem;
border-radius: 8px;
transition: background 0.15s;
flex-wrap: wrap;
}
.user-med-item.clickable {
cursor: pointer;
}
.user-med-item.clickable:hover {
background: var(--accent-bg);
}
.user-med-info {
flex: 1;
min-width: 150px;
}
.user-med-name {
display: block;
font-weight: 600;
color: var(--text-primary);
white-space: nowrap;
}
.user-med-generic {
display: block;
font-size: 0.8rem;
color: var(--text-secondary);
}
.user-med-stats {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.25rem;
flex-shrink: 0;
}
.user-med-pills {
font-size: 0.85rem;
color: var(--text-secondary);
}
.user-med-intakes {
display: flex;
flex-direction: column;
gap: 0.15rem;
margin-top: 0.15rem;
}
.user-med-intake-item {
font-size: 0.78rem;
color: var(--text-secondary);
line-height: 1.3;
}
.user-meds-empty {
padding: 2rem;
text-align: center;
color: var(--text-secondary);
}
.user-meds-footer {
padding: 1rem 1.5rem;
border-top: 1px solid var(--border-primary);
display: flex;
justify-content: flex-start;
}
.med-detail-header .med-avatar-lg {
width: 100px;
height: 100px;
font-size: 2.5rem;
border: 3px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
}
.med-detail-body {
padding: 1.5rem 2rem 2rem;
background: var(--bg-primary);
}
.med-detail-section {
margin-bottom: 1.5rem;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--border-color);
}
.med-detail-section:last-child {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}
/* Notes content in modal - auto-sizing box */
.med-notes-content {
background: var(--bg-secondary);
padding: 0.75rem 1rem;
border-radius: 8px;
white-space: pre-wrap;
word-wrap: break-word;
line-height: 1.6;
max-height: 300px;
overflow-y: auto;
-webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */
font-size: 1rem;
}
/* Mobile: larger notes box with better touch scrolling */
@media (max-width: 600px) {
.med-notes-content {
min-height: 80px;
max-height: 200px;
font-size: 1rem;
padding: 1rem;
touch-action: pan-y; /* Enable vertical touch scrolling */
}
}
.med-detail-section h3 {
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-secondary);
margin: 0 0 0.75rem;
}
.med-detail-section h3.section-header-with-badge {
display: flex;
align-items: center;
gap: 0.75rem;
}
.med-detail-section h3 .status-chip.small {
font-size: 0.7rem;
padding: 0.2rem 0.5rem;
text-transform: none;
letter-spacing: normal;
}
.med-detail-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
}
.prescription-detail-grid .med-detail-item {
display: flex;
flex-direction: column;
align-items: start;
}
.med-detail-item {
background: var(--bg-secondary);
padding: 0.75rem;
border-radius: 8px;
}
.med-detail-item.full-width {
grid-column: 1 / -1;
}
.med-detail-label {
display: block;
font-size: 0.75rem;
color: var(--text-secondary);
margin-bottom: 0;
}
.med-detail-value {
font-size: 1.1rem;
font-weight: 600;
color: var(--text-primary);
}
.med-detail-value.success-text {
color: var(--success);
}
.med-detail-value.warning-text {
color: var(--warning);
}
.med-detail-value.danger-text {
color: var(--danger);
}
.med-detail-schedules {
display: grid;
grid-template-columns: auto auto 1fr auto auto auto;
gap: 0.45rem 0;
}
.med-schedule-row {
display: grid;
grid-column: 1 / -1;
grid-template-columns: subgrid;
align-items: center;
column-gap: 0.75rem;
}
.med-schedule-usage {
font-weight: 600;
color: var(--accent);
white-space: nowrap;
grid-column: 1;
}
.med-schedule-freq {
color: var(--text-secondary);
white-space: nowrap;
grid-column: 2;
}
.med-schedule-person {
color: var(--text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
grid-column: 4;
}
.med-schedule-time {
font-weight: 700;
white-space: nowrap;
color: var(--text-primary);
text-align: right;
grid-column: 5;
}
.med-schedule-bell {
color: var(--warning);
display: inline-flex;
align-items: center;
grid-column: 6;
}
[data-theme="light"] .med-schedule-bell {
color: #b45309;
}
@media (max-width: 700px) {
.med-detail-schedules {
grid-template-columns: 1fr;
}
.med-schedule-row {
grid-template-columns: 1fr;
row-gap: 0.25rem;
}
.med-schedule-usage,
.med-schedule-freq,
.med-schedule-person,
.med-schedule-time,
.med-schedule-bell {
grid-column: auto;
}
}
.med-detail-footer {
padding: 1rem 2rem 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
border-top: 1px solid var(--border-primary);
background: var(--bg-primary);
border-radius: 0 0 12px 12px;
flex-shrink: 0;
overflow: visible;
position: relative;
z-index: 1;
padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
margin: 0;
}
/* Mobile devices can report wide CSS viewports (e.g., 768px in device emulation).
Use input modality instead of width-only breakpoints so the modal still fills the handset viewport. */
@media (hover: none) and (pointer: coarse) and (max-width: 500px) {
.med-detail-overlay {
padding: 0.4rem;
align-items: stretch;
}
.modal-content.med-detail-modal {
width: calc(100vw - 0.8rem);
max-width: none;
max-height: calc(100dvh - 0.8rem);
margin: auto;
border-radius: 12px;
}
}
.med-detail-footer::before {
content: none;
}
.med-detail-footer::after {
content: none;
}
.med-detail-footer .footer-actions {
display: flex;
gap: 0.5rem;
margin-left: auto;
overflow: visible;
position: relative;
}
.med-detail-footer .tooltip-trigger {
position: relative;
z-index: 1;
}
.med-detail-footer button.icon-only {
padding: 0.5rem;
min-width: 2.75rem;
min-height: 2.75rem;
}
.med-detail-footer button.icon-stock-correction {
background: color-mix(in srgb, var(--warning) 26%, var(--bg-tertiary));
border: 1px solid color-mix(in srgb, var(--warning) 62%, var(--border-secondary));
color: #fef3c7;
box-shadow: none;
}
.med-detail-footer button.icon-stock-correction:hover {
background: color-mix(in srgb, var(--warning) 36%, var(--bg-tertiary));
border-color: color-mix(in srgb, var(--warning) 76%, var(--border-secondary));
box-shadow: 0 0 0 1px color-mix(in srgb, var(--warning) 32%, transparent);
}
[data-theme="light"] .med-detail-footer button.icon-stock-correction {
background: color-mix(in srgb, var(--warning) 22%, white);
border-color: color-mix(in srgb, var(--warning) 70%, var(--border-secondary));
color: #92400e;
}
[data-theme="light"] .med-detail-footer button.icon-stock-correction:hover {
background: color-mix(in srgb, var(--warning) 32%, white);
border-color: color-mix(in srgb, var(--warning) 82%, var(--border-secondary));
}
/* Clickable avatar wrapper */
.med-detail-avatar-wrapper {
position: relative;
display: inline-block;
}
.med-detail-avatar-wrapper.clickable {
cursor: pointer;
}
.med-detail-avatar-wrapper.clickable:hover .med-avatar-lg {
transform: scale(1.05);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
.med-detail-avatar-wrapper .expand-icon {
position: absolute;
bottom: -4px;
right: -4px;
background: rgba(0, 0, 0, 0.6);
color: white;
font-size: 0.9rem;
width: 1.5rem;
height: 1.5rem;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.2s;
}
.med-detail-avatar-wrapper.clickable:hover .expand-icon {
opacity: 1;
}
/* Image Lightbox */
.lightbox-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.9);
display: flex;
align-items: center;
justify-content: center;
z-index: 2000;
padding: 2rem;
animation: fadeIn 0.2s ease;
}
.lightbox-container {
position: relative;
display: inline-flex;
}
.lightbox-close {
position: absolute;
top: -0.5rem;
right: -0.5rem;
background: rgba(255, 255, 255, 0.15);
border: none;
color: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--btn-radius-round);
transition: background 150ms ease;
box-shadow: none;
padding: 0;
z-index: 1;
}
.lightbox-close:hover {
background: rgba(255, 255, 255, 0.35);
}
.lightbox-image {
max-width: 50vw;
max-height: 50vh;
object-fit: contain;
border-radius: 12px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
animation: zoomIn 0.3s ease;
}
/* Mobile: larger lightbox image */
@media (max-width: 768px) {
.lightbox-image {
max-width: 90vw;
max-height: 70vh;
}
}
@keyframes zoomIn {
from {
opacity: 0;
transform: scale(0.8);
}
to {
opacity: 1;
transform: scale(1);
}
}
/* Clickable rows */
.table-row.clickable {
cursor: pointer;
transition: background 0.15s;
}
.table-row.clickable:hover {
background: var(--bg-secondary);
}
/* Mobile adjustments for modal */
@media (max-width: 500px) {
.med-detail-overlay {
padding: 0.4rem;
align-items: stretch;
}
.modal-content {
max-height: 85vh;
border-radius: 12px 12px 0 0;
margin-top: auto;
}
.modal-content.med-detail-modal {
width: calc(100vw - 0.8rem);
max-width: none;
max-height: calc(100dvh - 0.8rem);
border-radius: 12px;
margin: auto;
}
.med-detail-header {
padding: 1.5rem 1.5rem 1rem;
}
.med-detail-header .med-avatar-lg {
width: 80px;
height: 80px;
font-size: 2rem;
}
.med-detail-body {
padding: 1rem 1.5rem 0;
}
.med-detail-footer {
padding: 1rem 1.5rem;
padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
flex-direction: column;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 0.75rem;
margin: 0;
}
.med-detail-footer > button {
flex: 0 0 auto;
width: min(100%, 560px);
}
.med-detail-footer .footer-actions {
flex: 0 0 auto;
width: 100%;
justify-content: center;
margin-left: 0;
}
.med-detail-footer button {
padding: 0.6rem 0.8rem;
font-size: 0.9rem;
}
.med-detail-grid {
gap: 0.5rem;
}
}
/* Hard mobile override for MedDetailModal: remove side frame and use full handset viewport. */
@media (max-width: 500px) {
.modal-overlay.med-detail-overlay {
padding: 0 !important;
align-items: stretch;
}
.modal-overlay.med-detail-overlay > .modal-content.med-detail-modal {
width: 100vw !important;
max-width: 100vw !important;
max-height: 100dvh !important;
height: 100dvh;
margin: 0 !important;
border-radius: 0 !important;
border-left: none;
border-right: none;
}
.modal-overlay.med-detail-overlay .med-detail-header {
padding-left: 1rem;
padding-right: 1rem;
}
.modal-overlay.med-detail-overlay .med-detail-body {
padding-left: 1rem;
padding-right: 1rem;
}
.modal-overlay.med-detail-overlay .med-detail-footer {
margin: 0;
padding-left: 1rem;
padding-right: 1rem;
position: relative;
z-index: 1;
}
}
/* Reminder icon indicator */
.reminder-icon.info-tooltip,
.notes-icon.info-tooltip,
.prescription-icon.info-tooltip {
width: auto;
height: auto;
margin: 0 !important;
padding: 0 !important;
font-size: 1em;
opacity: 0.9;
color: var(--info);
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 1;
vertical-align: baseline;
}
.prescription-icon.info-tooltip {
color: var(--success);
}
.reminder-icon.info-tooltip,
.blister-reminder-icon {
color: var(--warning);
}
[data-theme="light"] .reminder-icon.info-tooltip,
[data-theme="light"] .blister-reminder-icon {
color: #b45309; /* dark amber — ~4.5:1 on light backgrounds */
}
[data-theme="light"] .notes-icon.info-tooltip {
color: #1d4ed8; /* darker blue — strong contrast on light backgrounds */
}
[data-theme="light"] .prescription-icon.info-tooltip {
color: #047857; /* dark emerald — strong contrast on light backgrounds */
}
.reminder-icon.info-tooltip:hover,
.notes-icon.info-tooltip:hover,
.prescription-icon.info-tooltip:hover {
opacity: 1;
}
h3 .reminder-icon.info-tooltip {
font-size: 0.75em;
vertical-align: middle;
}
h3 .notes-icon.info-tooltip {
font-size: 0.8em;
vertical-align: middle;
}
h3 .notes-icon.notes-icon-static {
font-size: 0.8em;
vertical-align: middle;
color: var(--info);
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 1;
}
[data-theme="light"] h3 .notes-icon.notes-icon-static {
color: #1d4ed8;
}
+3 -1
View File
@@ -1,5 +1,7 @@
/* =============================================================================
Modal Base Styles
Modal Base Styles
Owns reusable overlay, container, animation, and shared modal primitives used
by the focused modal/domain layers.
============================================================================= */
.modal-overlay {
@@ -1,5 +1,7 @@
/* =============================================================================
Shared Schedule Page (Public)
Owns the shared schedule experience and the mobile-first public edit flow
outside the authenticated app-shell surface styles.
============================================================================= */
.shared-schedule-page {
min-height: 100vh;
File diff suppressed because it is too large Load Diff
+1
View File
@@ -1,5 +1,6 @@
/* =============================================================================
Share Dialog
Owns the focused sharing dialog flow and related share-specific form states.
============================================================================= */
.share-dialog-modal {
max-width: 480px;