Files
Warracker/frontend/style.css
T
sassanix 47a42fb388 feat: Add currency controls, owner role, OIDC-only mode & key enhancements
This major update introduces several significant new features, critical bug fixes, and key enhancements across the application, focusing on user customization, administration, and system stability.
New Features
Currency Position Control: Allows users to choose whether the currency symbol appears on the left or right of numbers. This setting is applied universally across the app, including warranty cards and forms, and is saved per-user.
Super-Admin (Owner) Role: Implements an immutable Owner role for the primary administrator, who cannot be deleted or demoted. A secure ownership transfer process has been added to the admin settings.
OIDC-Only Login Mode: Adds a site-wide setting to enforce OIDC-only authentication, which hides the traditional username/password login form to streamline SSO environments.
Product Age Tracking & Sorting: Displays the age of a product (e.g., "2 years, 3 months") on warranty cards and adds a new "Sort by Age" option to organize items by their purchase date.
Global View Photo Access: Permits users to view product photos on warranties shared in global view, while ensuring other sensitive documents like invoices remain private to the owner.
Persistent View Scope: The application now remembers the user's last selected view (Global or Personal) and automatically loads the appropriate data on page refresh for a seamless experience.
Export Debug Tools: Introduces a comprehensive debugging system, including a new debug page and API endpoint, to help administrators troubleshoot and verify warranty exports.
Key Enhancements
About Page Redesign: A complete visual overhaul of the "About" page with a modern, card-based layout, prominent community links, and improved branding.
Flexible Apprise Notifications: Admins can now configure Apprise notifications to be a single global summary or sent as per-user messages. Additionally, the scope can be set to include warranties from all users or only the admin's warranties.
Larger Product Photo Thumbnails: Increased the size of product photo thumbnails in all views (grid, list, and table) for better product visibility.
Smart Currency Default: The "Add Warranty" form now intelligently defaults to the user's preferred currency setting, rather than always using USD.
Bug Fixes
Critical OIDC & Proxy Fixes: Resolved two major OIDC issues: a RecursionError with gevent workers and incorrect http:// callback URLs when behind an HTTPS reverse proxy, enabling reliable OIDC login.
Critical User Preferences Persistence: Fixed a bug where user settings for currency symbol and date format were not being saved correctly to the database.
Apprise & Notification Settings: Corrected an issue preventing user notification channel and Apprise timing settings from saving. The Apprise message format is now standardized, and the admin UI has been cleaned up.
CSV Import Currency: Ensured that warranties imported via CSV correctly use the user's preferred currency instead of defaulting to USD.
Maintenance & Refactoring
Authentication System Refactoring: Migrated all authentication-related routes from app.py into a dedicated Flask Blueprint (auth_routes.py) to improve code organization and maintainability.
Legacy Code Cleanup: Removed over 290 lines of orphaned and commented-out legacy OIDC code from the main application file.
2025-06-15 23:26:23 -03:00

4005 lines
85 KiB
CSS

/* Center the Edit Warranty button in the status page details row */
.warranty-details-actions {
display: flex;
justify-content: center;
align-items: center;
margin-top: 15px;
}
/* Make the Edit Warranty button on the status page details row minimal: blue outline, no fill, only around text */
.edit-warranty-status-btn {
background: transparent !important;
color: var(--primary-color) !important;
border: 2px solid var(--primary-color) !important;
border-radius: 6px !important;
font-size: 1rem !important;
font-weight: 500;
padding: 4px 18px !important;
min-width: unset !important;
width: auto !important;
height: auto !important;
box-shadow: none !important;
transition: background 0.2s, color 0.2s, border-color 0.2s;
display: inline-block;
}
.edit-warranty-status-btn:hover, .edit-warranty-status-btn:focus {
background: var(--primary-color) !important;
color: #fff !important;
border-color: var(--primary-dark) !important;
}
/* ===== GLOBAL STYLES ===== */
:root[data-theme="light"] {
--bg-color: #f5f5f5;
--card-bg: #ffffff;
--text-color: #333333;
--border-color: #e0e0e0;
--modal-backdrop: rgba(0, 0, 0, 0.5);
--loading-backdrop: rgba(255, 255, 255, 0.8);
--shadow-color: rgba(0, 0, 0, 0.1);
--primary-color: #3498db;
--primary-rgb: 52, 152, 219;
--primary-dark: #2980b9;
--secondary-color: #2ecc71;
--danger-color: #e74c3c;
--warning-color: #f39c12;
--light-gray: #f5f5f5;
--medium-gray: #e0e0e0;
--dark-gray: #777777;
--white: #ffffff;
--shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
--border-radius: 8px;
--transition: all 0.3s ease;
/* New variables for details row */
--details-bg: #f8f9fa; /* Light background for details */
--details-text-color: var(--text-color);
--details-border-color: #dee2e6;
--notes-bg: #e9ecef; /* Slightly different background for notes */
/* Ensure warranty card title is white in table view light mode */
.table-view .warranty-title {
color: #FFFFFF; /* White text for better contrast */
}
/* Make action button icons white in table view light mode */
.table-view .product-name-header .action-btn i {
color: #FFFFFF; /* White icon color */
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root[data-theme="dark"] {
--bg-color: #1a1a1a;
--card-bg: #2d2d2d;
--text-color: #e0e0e0;
--border-color: #404040;
--modal-backdrop: rgba(0, 0, 0, 0.7);
--loading-backdrop: rgba(0, 0, 0, 0.8);
--shadow-color: rgba(0, 0, 0, 0.3);
--primary-color: #4dabf7;
--primary-rgb: 77, 171, 247;
--primary-dark: #339af0;
--secondary-color: #40c057;
--danger-color: #fa5252;
--warning-color: #ff922b;
--light-gray: #2d2d2d;
--medium-gray: #404040;
--dark-gray: #909090;
--white: #2d2d2d;
--modal-background: #2d2d2d;
--text-muted: #909090;
--input-background: #1a1a1a;
--border-radius: 8px; /* Added missing border radius for dark theme */
/* New variables for details row */
--details-bg: #2c3034; /* Darker background for details */
--details-text-color: var(--text-color);
--details-border-color: #454a4f;
--notes-bg: #343a40; /* Slightly different dark background for notes */
/* Ensure warranty card title is white in table view dark mode */
.table-view .warranty-title {
color: #FFFFFF; /* White text for better contrast */
}
/* Make action button icons white in table view dark mode */
.table-view .product-name-header .action-btn i {
color: #FFFFFF; /* White icon color */
}
/* Dark mode styles for tags */
.tag {
background-color: var(--medium-gray); /* e.g., #404040 */
color: var(--text-color); /* e.g., #e0e0e0 */
box-shadow: 0 1px 2px var(--shadow-color); /* Softer shadow for dark mode */
}
.tag .remove-tag {
background-color: rgba(255, 255, 255, 0.1); /* Light transparent background for the 'x' button */
color: var(--text-color); /* Light color for the 'x' icon */
}
.tag .remove-tag:hover {
background-color: rgba(255, 255, 255, 0.2); /* Slightly more opaque on hover */
}
/* Dark mode styles for filter select options */
.filter-select option,
.filter-select option:hover,
.filter-select option:focus {
background-color: var(--input-background);
color: var(--text-color);
}
/* Dark mode styles for filter select options - using !important to override browser defaults */
.filter-select option,
.filter-select option:hover,
.filter-select option:focus {
background-color: var(--input-background) !important;
color: var(--text-color) !important;
}
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: var(--text-color);
background-color: var(--bg-color);
padding: 0;
margin: 0;
z-index: 1000;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* ===== HEADER ===== */
header {
background-color: var(--card-bg);
box-shadow: var(--shadow);
padding: 20px 0;
margin-bottom: 30px;
}
header .container {
display: flex;
justify-content: space-between;
align-items: center;
}
.app-title {
display: flex;
align-items: center;
}
.app-title h1 {
color: var(--primary-color);
font-size: 2.2rem;
margin: 0;
}
.app-title i {
font-size: 2rem;
margin-right: 15px;
color: var(--primary-color);
}
/* ===== MAIN CONTENT ===== */
.main-content {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 30px;
}
@media (max-width: 768px) {
.main-content {
grid-template-columns: 1fr;
}
}
/* ===== FORM PANEL ===== */
.form-panel {
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--shadow);
padding: 25px;
}
/* Form Tabs */
.form-tabs {
display: flex;
margin-bottom: 20px;
position: relative;
border-bottom: 2px solid var(--medium-gray);
overflow: hidden;
}
.form-tabs::after {
display: none;
}
.form-tabs::before {
content: '';
position: absolute;
bottom: -2px;
height: 2px;
background-color: var(--secondary-color);
transition: all 0.3s ease;
width: 25%;
z-index: 1;
}
.form-tabs[data-step="0"]::before {
left: 0;
}
.form-tabs[data-step="1"]::before {
left: 25%;
}
.form-tabs[data-step="2"]::before {
left: 50%;
}
.form-tabs[data-step="3"]::before {
left: 75%;
}
.form-tab {
flex: 1;
text-align: center;
padding: 15px 10px;
cursor: pointer;
position: relative;
color: var(--dark-gray);
transition: color 0.3s ease;
box-sizing: border-box;
width: 25%; /* Ensure each tab is exactly 25% width */
}
.form-tab:hover {
color: var(--primary-color);
}
.form-tab.active {
color: var(--primary-color);
font-weight: 600;
}
.form-tab.completed {
color: var(--secondary-color);
}
.form-tab.completed::after {
content: '\f00c';
font-family: 'Font Awesome 5 Free';
font-weight: 900;
position: absolute;
top: 10px;
right: 10px;
font-size: 0.8rem;
}
.form-tab i {
margin-right: 5px;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
animation: fade-in 0.3s ease;
}
.tab-navigation {
display: flex;
justify-content: space-between;
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid var(--medium-gray);
}
.tab-navigation .btn {
min-width: 120px;
}
.tab-navigation .btn i {
margin-right: 5px;
}
.tab-navigation .btn:last-child i {
margin-right: 0;
margin-left: 5px;
}
input.invalid {
border-color: var(--danger-color);
box-shadow: 0 0 0 1px var(--danger-color);
animation: shake 0.3s ease;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
/* Progress indicator */
.form-tabs {
display: flex;
border-bottom: 2px solid var(--medium-gray);
margin-bottom: 20px;
position: relative;
}
.form-tabs::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
height: 2px;
background-color: var(--secondary-color);
transition: width 0.3s ease;
}
.form-tabs[data-step="0"]::after {
width: calc(100% / 3);
}
.form-tabs[data-step="1"]::after {
width: calc(200% / 3);
}
.form-tabs[data-step="2"]::after {
width: 100%;
}
@keyframes fade-in {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.form-panel h2 {
color: var(--primary-color);
margin-bottom: 20px;
font-size: 1.5rem;
padding-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: var(--text-color);
}
.form-control {
width: 100%;
padding: 12px;
border: 1px solid var(--medium-gray);
border-radius: var(--border-radius);
font-size: 1rem;
transition: var(--transition);
}
.form-control:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.25);
}
.file-input-wrapper {
position: relative;
overflow: hidden;
display: inline-block;
width: 100%;
}
.file-input-label {
display: block;
background-color: var(--primary-color);
color: var(--white);
text-align: center;
padding: 12px;
border-radius: var(--border-radius);
cursor: pointer;
transition: var(--transition);
}
.file-input-label:hover {
background-color: var(--primary-dark);
}
.file-input-label i {
margin-right: 8px;
}
.file-input {
position: absolute;
font-size: 100px;
opacity: 0;
right: 0;
top: 0;
cursor: pointer;
}
.file-name {
margin-top: 8px;
font-size: 0.9rem;
color: var(--dark-gray);
word-break: break-all;
}
.btn {
display: inline-block;
font-weight: 500;
text-align: center;
white-space: nowrap;
vertical-align: middle;
user-select: none;
border: none;
padding: 12px 25px;
font-size: 1rem;
line-height: 1.5;
border-radius: var(--border-radius);
transition: var(--transition);
cursor: pointer;
width: 100%;
}
.btn-primary {
color: var(--white);
background-color: var(--primary-color);
}
.btn-primary:hover {
background-color: var(--primary-dark);
}
.btn-secondary {
color: var(--white);
background-color: var(--secondary-color);
}
.btn-secondary:hover {
background-color: #27ae60;
}
.btn-danger {
color: var(--white);
background-color: var(--danger-color);
}
.btn-danger:hover {
background-color: #c0392b;
}
/* ===== WARRANTIES LIST ===== */
.warranties-panel {
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--shadow);
padding: 25px;
grid-column: 1 / -1; /* Make panel span full width */
}
.warranties-panel h2 {
color: var(--primary-color);
margin-bottom: 20px;
font-size: 1.5rem;
padding-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.refresh-btn {
background: none;
border: none;
color: var(--primary-color);
cursor: pointer;
font-size: 1.2rem;
transition: var(--transition);
}
.refresh-btn:hover {
transform: rotate(90deg);
}
.search-box {
display: flex;
align-items: center;
background-color: var(--search-bg);
border: 1px solid var(--border-color);
padding: 8px 15px;
width: 100%;
border-radius: 25px;
position: relative;
transition: all 0.3s ease;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
}
.search-box:focus-within {
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1);
border-color: var(--primary-color);
width: 100%;
}
.search-box.active-search {
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1);
border-color: var(--primary-color);
background-color: rgba(var(--primary-rgb), 0.05);
width: 100%;
}
.search-box i {
color: var(--text-muted);
font-size: 1rem;
margin-right: 10px;
display: flex;
align-items: center;
justify-content: center;
min-width: 20px;
position: static; /* Override any absolute positioning */
transform: none; /* Reset any transform */
left: auto; /* Reset any left positioning */
top: auto; /* Reset any top positioning */
}
.search-box.active-search i {
color: var(--primary-color);
animation: search-pulse 1.5s ease-in-out infinite;
}
@keyframes search-pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.search-box input {
border: none;
outline: none;
background: none;
width: 100%;
color: var(--text-color);
font-size: 0.95rem;
padding: 2px 0;
}
.search-box input::placeholder {
color: var(--text-muted);
opacity: 0.8;
}
.clear-search-btn {
background: none;
border: none;
outline: none;
cursor: pointer;
color: var(--text-muted);
font-size: 0.9rem;
opacity: 0.7;
transition: opacity 0.3s;
padding: 0;
margin-left: 5px;
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
}
.clear-search-btn:hover {
opacity: 1;
color: var(--primary-color);
}
.warranties-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
}
.warranty-card {
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--shadow);
overflow: hidden;
transition: var(--transition);
border: 1px solid var(--border-color);
display: flex;
flex-direction: column;
height: auto; /* Allow height to be determined by content */
}
.warranty-card:hover {
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.warranty-card.expired {
border-left: 4px solid var(--danger-color);
}
.warranty-card.expiring-soon {
border-left: 4px solid var(--warning-color);
}
.warranty-card.active {
border-left: 4px solid var(--secondary-color);
}
.warranty-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
background-color: rgba(0, 0, 0, 0.03);
border-bottom: 1px solid var(--border-color);
position: relative;
}
.warranty-title {
margin: 0;
font-size: 1.1rem;
font-weight: 600;
color: var(--text-color);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
}
.warranty-actions {
display: flex;
gap: 8px;
}
.action-btn {
background: none;
border: none;
font-size: 1rem;
cursor: pointer;
color: var(--dark-gray);
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: var(--transition);
}
.action-btn:hover {
background-color: rgba(0, 0, 0, 0.05);
}
.edit-btn:hover {
color: var(--primary-color);
}
.delete-btn:hover {
color: var(--danger-color);
}
.warranty-details {
padding: 15px;
flex-grow: 1;
display: flex;
flex-direction: column;
}
.warranty-details div {
margin-bottom: 8px;
font-size: 0.95rem;
}
.warranty-details span {
font-weight: 500;
color: var(--text-color);
}
.warranty-status {
display: inline-block;
padding: 4px 10px;
border-radius: 20px;
font-size: 0.85rem;
font-weight: 600;
margin: 10px 0;
/* This class is kept for backward compatibility but we're now using warranty-status-row */
display: none;
}
.status-active {
background-color: rgba(46, 204, 113, 0.15);
color: #27ae60;
}
.status-expired {
background-color: rgba(231, 76, 60, 0.15);
color: #c0392b;
}
.status-expiring {
background-color: rgba(241, 196, 15, 0.15);
color: #f39c12;
}
.serial-numbers {
margin-top: 10px;
margin-bottom: 15px;
}
.serial-numbers strong {
display: block;
margin-bottom: 5px;
font-size: 0.9rem;
}
.serial-numbers ul {
margin: 0;
padding-left: 20px;
font-size: 0.9rem;
}
.serial-numbers li {
margin-bottom: 3px;
}
/* ===== MODAL ===== */
.modal-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: none;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-backdrop.active {
display: flex; /* Shown when active */
}
/* Specific override for tag management modal to ensure proper centering */
#tagManagementModal.modal-backdrop {
display: none;
justify-content: center !important;
align-items: center !important;
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
background-color: rgba(0, 0, 0, 0.5) !important;
z-index: 1050 !important;
}
#tagManagementModal.modal-backdrop.active {
display: flex !important;
}
/* Ensure the inner modal content is properly sized */
#tagManagementModal .modal {
background-color: var(--modal-background, #ffffff) !important;
border-radius: 8px !important;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1) !important;
width: 90% !important;
max-width: 600px !important;
max-height: 90vh !important;
display: flex !important;
flex-direction: column !important;
animation: slide-in 0.3s ease !important;
position: relative !important;
overflow: hidden !important;
margin: 0 !important; /* Remove any conflicting margins */
}
/* Override conflicting styles from styles.css for tag management modal */
#tagManagementModal.modal-backdrop .modal {
position: relative !important; /* Override fixed positioning */
top: auto !important; /* Remove top positioning */
left: auto !important; /* Remove left positioning */
width: 90% !important; /* Set proper width */
height: auto !important; /* Set auto height */
background-color: var(--modal-background, #ffffff) !important;
margin: 0 !important; /* Remove conflicting margins */
}
@keyframes slide-in {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Serial number input styling */
.serial-number-input {
display: flex;
align-items: center;
margin-bottom: 10px;
gap: 10px;
}
.serial-number-input .form-control {
flex-grow: 1;
}
.serial-number-input .btn {
width: auto;
padding: 8px 10px;
}
.add-serial {
display: block;
width: 100%;
margin-top: 5px;
margin-bottom: 15px;
}
/* End serial number input styling */
.modal-header {
padding: 1rem;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--modal-background, #ffffff);
}
.modal-title {
margin: 0;
font-size: 1.25rem;
color: var(--text-color);
}
.close-btn {
background: none;
border: none;
font-size: 1.5rem;
color: var(--text-muted);
cursor: pointer;
padding: 0;
line-height: 1;
}
.close-btn:hover {
color: var(--text-color);
}
.modal-body {
padding: 1rem;
overflow-y: auto; /* Enable vertical scroll */
flex-grow: 1; /* Allow body to take available space */
background-color: var(--card-bg); /* Ensure background */
}
.modal-footer {
padding: 1rem;
border-top: 1px solid var(--border-color);
display: flex;
justify-content: flex-end;
gap: 0.5rem;
background-color: var(--modal-background, #ffffff);
}
.modal-footer .btn {
width: auto;
}
/* ===== TOAST NOTIFICATIONS ===== */
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 1001;
}
.toast {
min-width: 250px;
margin-bottom: 10px;
padding: 15px 20px;
border-radius: var(--border-radius);
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
display: flex;
align-items: center;
justify-content: space-between;
animation: slide-in 0.3s ease, fade-out 0.3s ease 2.7s forwards;
}
@keyframes slide-in {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes fade-out {
from { opacity: 1; }
to { opacity: 0; }
}
.toast-success {
background-color: var(--secondary-color);
color: var(--white);
}
.toast-error {
background-color: var(--danger-color);
color: var(--white);
}
.toast-warning {
background-color: #f39c12;
color: var(--white);
}
.toast-info {
background-color: var(--primary-color);
color: var(--white);
}
.toast-close {
background: none;
border: none;
color: var(--white);
opacity: 0.7;
cursor: pointer;
font-size: 1.2rem;
transition: var(--transition);
}
.toast-close:hover {
opacity: 1;
}
/* ===== LOADING SPINNER ===== */
.loading-spinner {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.loading-spinner:after {
content: " ";
display: block;
border-radius: 50%;
width: 0;
height: 0;
margin: 8px;
box-sizing: border-box;
border: 32px solid var(--primary-color);
border-color: var(--primary-color) transparent var(--primary-color) transparent;
animation: loading-spinner 1.2s infinite;
}
@keyframes loading-spinner {
0% { transform: rotate(0); animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); }
50% { transform: rotate(180deg); animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); }
100% { transform: rotate(360deg); }
}
.loading-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--loading-backdrop);
display: flex;
justify-content: center;
align-items: center;
z-index: 1002;
opacity: 0;
visibility: hidden;
transition: var(--transition);
}
.loading-container.active {
opacity: 1;
visibility: visible;
}
/* ===== EMPTY STATE ===== */
.empty-state {
text-align: center;
padding: 40px 20px;
color: var(--dark-gray);
}
.empty-state i {
font-size: 3rem;
margin-bottom: 15px;
opacity: 0.3;
}
.empty-state h3 {
font-size: 1.2rem;
margin-bottom: 10px;
}
.empty-state p {
font-size: 0.9rem;
}
/* ===== RESPONSIVE ADJUSTMENTS ===== */
@media (max-width: 768px) {
/* Header Responsive Styles */
header .container {
flex-wrap: wrap; /* Allow header items to wrap */
justify-content: center; /* Center items when wrapped */
gap: 15px; /* Add space between wrapped items */
padding: 10px 15px !important; /* Adjust padding for smaller screens */
}
header .app-title h1 {
font-size: 1.8rem !important; /* Slightly reduce title size */
}
header .app-title i {
font-size: 1.6rem !important; /* Slightly reduce icon size */
margin-right: 10px !important; /* Slightly reduce icon size */
}
header .nav-links {
order: 3; /* Push nav links to the bottom row when wrapped */
width: 100%; /* Make nav links take full width */
justify-content: center; /* Center nav links */
margin: 10px 0 0 0 !important; /* Add margin top, remove horizontal margin */
padding-bottom: 5px; /* Add some padding below nav links */
}
header .auth-buttons,
header .user-menu,
header .settings-container {
margin-left: 0 !important; /* Reset margins */
margin-right: 0 !important;
}
/* End Header Responsive Styles */
.main-content {
grid-template-columns: 1fr;
}
.form-panel, .warranties-panel {
margin-bottom: 20px;
}
.warranty-header {
flex-direction: column;
}
.warranty-actions {
margin-top: 10px;
}
.document-links-row {
flex-direction: column;
gap: 5px;
}
.invoice-link, .manual-link, .product-link, .notes-link {
width: 100%;
justify-content: center;
}
.search-box,
.search-box:focus-within,
.search-box.active-search {
width: 100%;
max-width: none;
}
}
/* ===== SETTINGS MENU ===== */
.settings-container {
position: relative;
z-index: 100;
}
/* Group for right-aligned header elements (User Menu, Auth, Settings) */
.header-right-group {
display: flex;
align-items: center;
gap: 10px; /* Adjust gap as needed */
}
.settings-btn {
background-color: var(--card-bg);
border: 1px solid var(--border-color);
color: var(--primary-color);
font-size: 1.2rem;
cursor: pointer;
transition: var(--transition);
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: var(--shadow);
}
.settings-btn:hover {
transform: rotate(30deg);
background-color: var(--primary-color);
color: var(--white);
}
.settings-menu {
position: absolute;
top: calc(100% + 10px);
right: 0;
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--shadow);
padding: 15px;
min-width: 220px;
z-index: 100;
display: none;
border: 1px solid var(--border-color);
}
.settings-menu.active {
display: block;
animation: slide-in-top 0.3s forwards;
}
@keyframes slide-in-top {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.settings-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid var(--border-color);
}
.settings-item:last-child {
border-bottom: none;
}
.settings-item span {
font-weight: 500;
color: var(--text-color);
}
/* Toggle Switch */
.toggle-switch {
position: relative;
display: inline-block;
width: 50px;
height: 24px;
margin-left: 10px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--medium-gray);
transition: var(--transition);
border-radius: 34px;
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
}
.toggle-slider:before {
position: absolute;
content: "";
height: 16px;
width: 16px;
left: 4px;
bottom: 4px;
background-color: var(--white);
transition: var(--transition);
border-radius: 50%;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
input:checked + .toggle-slider {
background-color: var(--primary-color);
}
input:checked + .toggle-slider:before {
transform: translateX(26px);
}
/* ===== UTILITIES ===== */
.text-danger {
color: var(--danger-color);
}
.text-warning {
color: #f39c12;
}
.text-success {
color: var(--secondary-color);
}
.text-center {
text-align: center;
}
.mt-10 {
margin-top: 10px;
}
.mt-20 {
margin-top: 20px;
}
.mb-10 {
margin-bottom: 10px;
}
.mb-20 {
margin-bottom: 20px;
}
/* Navigation Links */
.nav-links {
display: flex;
gap: 20px;
margin: 0 20px;
}
.nav-link {
text-decoration: none;
color: var(--text-color);
padding: 8px 12px;
border-radius: 4px;
transition: background-color 0.3s;
display: flex;
align-items: center;
gap: 8px;
}
.nav-link:hover {
background-color: rgba(0, 0, 0, 0.05);
}
.nav-link.active {
background-color: rgba(0, 0, 0, 0.05);
font-weight: 600;
}
.nav-link i {
font-size: 1rem;
}
/* Status Page Styles */
.status-content {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.status-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.status-card {
background-color: var(--card-bg);
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
transition: transform 0.3s, box-shadow 0.3s;
}
.status-card:hover {
transform: translateY(-5px);
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
}
.status-card[data-status="active"] .card-icon {
color: #4CAF50;
}
.status-card[data-status="expiring"] .card-icon {
color: #FF9800;
}
.status-card[data-status="expired"] .card-icon {
color: #F44336;
}
.status-card[data-status="total"] .card-icon {
color: #3498db;
}
.card-icon {
font-size: 2.5rem;
margin-right: 15px;
}
.card-content h3 {
margin: 0 0 5px 0;
font-size: 1rem;
color: var(--dark-gray);
}
.card-content .count {
font-size: 2rem;
font-weight: 700;
margin: 0;
color: var(--text-color);
}
.charts-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 30px;
margin-bottom: 30px;
}
.chart-card {
background-color: var(--card-bg);
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.chart-card h3 {
margin-top: 0;
margin-bottom: 15px;
font-size: 1.2rem;
color: var(--text-color);
}
.chart-container {
height: 300px;
position: relative;
}
.recent-expirations {
background-color: var(--card-bg);
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
}
.recent-expirations h3 {
margin-top: 0;
margin-bottom: 15px;
font-size: 1.2rem;
color: var(--text-color);
text-align: left;
}
.table-responsive {
overflow-x: auto;
width: 100%;
min-width: 0;
padding-right: 0;
}
#recentExpirationsTable {
table-layout: auto;
width: 100%;
border-collapse: separate;
border-spacing: 0;
border-right: none;
}
#recentExpirationsTable th,
#recentExpirationsTable td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid var(--border-color);
width: auto;
min-width: 120px;
max-width: none;
white-space: nowrap;
}
#recentExpirationsTable td {
white-space: normal;
}
#recentExpirationsTable tbody {
min-height: 250px; /* Ensure minimum height for the table body */
}
#recentExpirationsTable .no-data {
text-align: center;
color: var(--dark-gray);
padding: 50px 30px;
font-size: 1.2em;
}
#recentExpirationsTable .empty-row {
height: 250px; /* Fixed height for the empty row */
}
#recentExpirationsTable .empty-row td {
vertical-align: middle;
text-align: center;
}
/* Fix for the last column to ensure border extends fully */
#recentExpirationsTable tr {
position: relative;
}
#recentExpirationsTable tr:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background-color: var(--border-color);
z-index: 0;
}
#recentExpirationsTable .action-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: 4px;
background-color: var(--light-gray);
color: var(--text-color);
text-decoration: none;
transition: all 0.2s ease;
position: relative;
z-index: 1;
}
#recentExpirationsTable .action-btn:hover {
background-color: var(--primary-color);
color: white;
}
#recentExpirationsTable .edit-btn:hover {
background-color: var(--secondary-color);
}
#recentExpirationsTable .view-btn:hover {
background-color: var(--info-color);
}
@media (max-width: 768px) {
#recentExpirationsTable td:last-child {
padding: 8px;
}
}
/* Status styling */
.status-expired {
color: #F44336;
padding: 4px 8px;
border-radius: 4px;
background-color: rgba(244, 67, 54, 0.1);
display: inline-block;
}
.status-expiring {
color: #FF9800;
padding: 4px 8px;
border-radius: 4px;
background-color: rgba(255, 152, 0, 0.1);
display: inline-block;
}
.status-active {
color: #4CAF50;
padding: 4px 8px;
border-radius: 4px;
background-color: rgba(76, 175, 80, 0.1);
display: inline-block;
}
tr.status-expired {
background-color: rgba(244, 67, 54, 0.05);
}
tr.status-expiring {
background-color: rgba(255, 152, 0, 0.05);
}
@media (max-width: 768px) {
.status-cards {
grid-template-columns: repeat(2, 1fr);
}
.charts-container {
grid-template-columns: 1fr;
}
.chart-container {
height: 250px;
}
#recentExpirationsTable th:nth-child(2),
#recentExpirationsTable td:nth-child(2) {
display: none;
}
}
@media (max-width: 480px) {
.status-cards {
grid-template-columns: 1fr;
}
#recentExpirationsTable th:nth-child(3),
#recentExpirationsTable td:nth-child(3) {
display: none;
}
}
/* Error message on status page */
.error-message {
text-align: center;
padding: 40px 20px;
background-color: rgba(244, 67, 54, 0.05);
border-radius: 8px;
margin: 20px 0;
}
.error-message i {
font-size: 3rem;
color: #F44336;
margin-bottom: 15px;
}
.error-message h3 {
font-size: 1.5rem;
margin-bottom: 10px;
color: #F44336;
}
.error-message p {
color: var(--text-color);
margin-bottom: 10px;
}
.error-message p:last-child {
font-family: monospace;
background-color: rgba(0, 0, 0, 0.05);
padding: 10px;
border-radius: 4px;
max-width: 100%;
overflow-x: auto;
font-size: 0.9rem;
}
/* Fix for table alignment */
.recent-expirations table {
width: 100%;
margin: 0 auto;
}
.recent-expirations thead,
.recent-expirations tbody,
.recent-expirations tr,
.recent-expirations th,
.recent-expirations td {
display: revert;
text-align: left;
}
.settings-link {
display: flex;
align-items: center;
text-decoration: none;
color: var(--text-color);
padding: 5px 0;
transition: var(--transition);
width: 100%;
}
.settings-link i {
margin-right: 10px;
font-size: 1rem;
width: 20px;
text-align: center;
}
.settings-link:hover {
color: var(--primary-color);
}
.dashboard-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.dashboard-header h2 {
margin: 0;
font-size: 1.5rem;
color: var(--text-color);
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
margin-bottom: 15px;
}
.table-header h3 {
margin: 0;
font-size: 1.2rem;
color: var(--text-color);
}
.table-actions {
display: flex;
gap: 10px;
align-items: center;
}
.filter-options {
min-width: 150px;
}
.filter-select {
width: 100%;
padding: 8px 10px;
border-radius: var(--border-radius);
border: 1px solid var(--border-color);
background-color: var(--card-bg);
color: var(--text-color);
font-size: 0.9rem;
cursor: pointer;
transition: var(--transition);
}
.filter-select:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
}
.sortable {
cursor: pointer;
position: relative;
user-select: none;
}
.sortable i {
font-size: 0.8rem;
margin-left: 5px;
opacity: 0.5;
transition: var(--transition);
}
.sortable:hover i {
opacity: 1;
}
.sortable.sort-asc i:before {
content: "\f0de"; /* fa-sort-up */
}
.sortable.sort-desc i:before {
content: "\f0dd"; /* fa-sort-down */
}
/* Export button */
.export-btn {
background-color: var(--card-bg);
border: 1px solid var(--border-color);
color: var(--text-color);
padding: 6px 12px;
border-radius: var(--border-radius);
cursor: pointer;
display: flex;
align-items: center;
gap: 5px;
font-size: 0.9rem;
transition: var(--transition);
}
.export-btn:hover {
background-color: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
/* Animation for refresh button */
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.refresh-btn.loading i {
animation: spin 1s linear infinite;
}
/* Document links */
.document-link-container {
margin-top: 10px;
}
.document-links-row {
display: flex;
/* flex-wrap: wrap; */ /* Remove wrapping */
/* gap: 8px; */ /* Remove gap, use margin on items */
margin-top: 15px;
justify-content: flex-start;
flex-direction: row; /* Explicitly set row direction */
align-items: center; /* Align items vertically */
/* Add border and background for consistency */
padding: 10px 15px;
background-color: rgba(0, 0, 0, 0.03);
border-top: 1px solid var(--border-color);
}
.invoice-link, .manual-link, .product-link, .notes-link, .other-document-link { /* Added .notes-link here */
display: inline-flex; /* Remove !important */
align-items: center !important; /* Keep important if needed for vertical icon align */
color: var(--primary-color) !important; /* Keep appearance */
text-decoration: none !important; /* Keep appearance */
font-weight: 500 !important; /* Keep appearance */
padding: 5px 10px !important; /* Keep appearance */
background-color: var(--light-gray) !important; /* Keep appearance */
border-radius: var(--border-radius) !important; /* Keep appearance */
transition: var(--transition) !important; /* Keep appearance */
border: none !important; /* Keep appearance */
margin: 0 5px 0 0 !important; /* Add right margin for spacing, remove others */
white-space: nowrap !important; /* Keep appearance */
}
.invoice-link i, .manual-link i, .product-link i, .notes-link i, .other-document-link i { /* Added .notes-link here */
margin-right: 5px !important;
font-size: 1rem !important;
}
.invoice-link:hover, .manual-link:hover, .product-link:hover, .notes-link:hover, .other-document-link:hover {
text-decoration: none !important;
background-color: var(--medium-gray) !important;
color: var(--primary-dark) !important;
}
.validation-message {
color: var(--danger-color);
font-size: 0.85rem;
margin-top: 5px;
animation: fade-in 0.3s ease;
}
/* Improve the visual feedback for invalid inputs */
input.invalid {
border-color: var(--danger-color);
box-shadow: 0 0 0 2px rgba(231, 76, 60, 0.25);
background-color: rgba(231, 76, 60, 0.05);
}
/* Add a subtle shake animation for validation errors */
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
input.invalid {
animation: shake 0.4s ease-in-out;
}
.summary-container {
background-color: var(--light-gray);
border-radius: var(--border-radius);
padding: 20px;
margin-bottom: 20px;
}
.summary-section {
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid var(--medium-gray);
}
.summary-section:last-child {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}
.summary-section h4 {
color: var(--primary-color);
margin-bottom: 15px;
font-size: 1.1rem;
display: flex;
align-items: center;
}
.summary-section h4 i {
margin-right: 8px;
}
.summary-item {
display: flex;
margin-bottom: 10px;
}
.summary-label {
font-weight: 500;
width: 150px;
flex-shrink: 0;
}
.summary-value {
flex-grow: 1;
}
.summary-value ul {
margin: 0;
padding-left: 20px;
}
/* Filter controls */
.filter-controls {
margin-bottom: 20px;
background-color: var(--card-bg);
border-radius: var(--border-radius);
padding: 15px;
box-shadow: var(--shadow);
border: 1px solid var(--border-color);
}
/* --- Improved search bar and dropdown spacing --- */
.search-container {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
flex-wrap: wrap;
justify-content: flex-start;
}
.search-box {
flex: 2 1 320px;
display: flex;
align-items: center;
background-color: var(--input-background, #f5f5f5);
border: 1.5px solid var(--border-color);
border-radius: 25px;
padding: 0 16px;
height: 44px;
box-shadow: none;
transition: border-color 0.2s, box-shadow 0.2s;
min-width: 220px;
max-width: 500px;
}
.search-box:focus-within {
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.10);
}
.search-btn {
background: none;
border: none;
color: var(--text-muted);
font-size: 1.1rem;
margin-right: 8px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 0 4px;
transition: color 0.2s;
}
.search-btn:hover {
color: var(--primary-color);
}
.search-box input {
border: none;
outline: none;
background: none;
width: 100%;
color: var(--text-color);
font-size: 1rem;
padding: 8px 0;
}
.clear-search-btn {
background: none;
border: none;
outline: none;
cursor: pointer;
color: var(--text-muted);
font-size: 1.1rem;
margin-left: 6px;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 0 4px;
transition: color 0.2s;
}
.clear-search-btn:hover {
color: var(--primary-color);
}
.filter-options {
display: flex;
flex-wrap: wrap;
gap: 18px 24px;
align-items: center;
margin-top: 0;
margin-bottom: 0;
}
.filter-group {
display: flex;
flex-direction: column;
flex: 1 1 160px;
min-width: 140px;
max-width: 220px;
}
@media (max-width: 900px) {
.filter-options {
gap: 12px 8px;
}
.filter-group {
min-width: 120px;
max-width: 100%;
}
}
@media (max-width: 768px) {
.search-container {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
.search-box {
min-width: 0;
max-width: none;
width: 100%;
}
.filter-options {
flex-direction: column;
gap: 10px 0;
}
.filter-group {
width: 100%;
min-width: 0;
max-width: none;
}
}
.search-container {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
flex-wrap: wrap;
justify-content: flex-start;
}
.search-container .search-box {
flex: 1 1 220px;
}
.search-container .export-btn {
margin-top: 0;
align-self: center;
height: 42px;
flex-shrink: 0;
}
/* Style for the global Manage Tags button to match Export/Import */
#globalManageTagsBtn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 15px;
border-radius: var(--border-radius);
border: none;
background-color: var(--secondary-color);
color: white;
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
transition: var(--transition);
height: 40px;
align-self: center;
margin-top: 0;
min-width: 120px;
max-width: none;
white-space: nowrap;
}
#globalManageTagsBtn:hover {
background-color: #27ae60;
transform: translateY(-1px);
}
#globalManageTagsBtn i {
font-size: 0.9rem;
}
/* Override any conflicting search box styles */
.filter-controls .search-box {
position: relative;
margin-bottom: 0;
display: flex;
align-items: center;
}
.filter-controls .search-box i {
position: static;
left: auto;
top: auto;
transform: none;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
min-width: 20px;
color: var(--text-muted);
}
.filter-controls .search-box input {
border: none;
outline: none;
background: none;
width: 100%;
}
/* Responsive: Make search/btns stack on mobile */
@media (max-width: 768px) {
.search-container {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
#globalManageTagsBtn, .search-container .export-btn, .search-container .import-btn {
width: 100%;
min-width: 0;
max-width: none;
}
}
.filter-options {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
}
.filter-group {
display: flex;
flex-direction: column;
flex: 1;
min-width: 150px;
}
.filter-label {
font-size: 0.85rem;
margin-bottom: 5px;
color: var(--dark-gray);
font-weight: 500;
}
.filter-select {
padding: 8px 10px;
border-radius: var(--border-radius);
border: 1px solid var(--border-color);
background-color: var(--card-bg);
color: var(--text-color);
font-size: 0.9rem;
cursor: pointer;
transition: var(--transition);
appearance: none;
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right 10px center;
background-size: 1em;
padding-right: 30px;
}
.filter-select:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
}
.export-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 15px;
border-radius: var(--border-radius);
border: none;
background-color: var(--primary-color);
color: white;
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
transition: var(--transition);
height: 40px;
align-self: flex-end;
margin-top: auto;
}
.export-btn:hover {
background-color: var(--primary-dark);
transform: translateY(-1px);
}
.export-btn i {
font-size: 0.9rem;
}
/* Responsive filter controls */
@media (max-width: 768px) {
.filter-options {
flex-direction: column;
width: 100%;
gap: 15px;
}
.filter-group {
width: 100%;
}
.filter-select, .export-btn {
width: 100%;
}
.search-container {
flex-direction: row;
flex-wrap: wrap;
gap: 10px;
}
.search-container .search-box {
width: calc(100% - 110px);
min-width: 200px;
}
.search-container .export-btn {
height: 42px;
width: 100px;
}
@media (max-width: 480px) {
.search-container {
flex-direction: column;
gap: 10px;
}
.search-container .search-box {
width: 100%;
}
.search-container .export-btn {
width: 100%;
}
}
.export-btn {
margin-top: 5px;
}
}
/* View Switcher */
.view-switcher {
display: flex;
flex-direction: column;
flex-grow: 1; /* Allow this to take available space */
min-width: 120px; /* Minimum width for the 3 buttons */
}
.view-buttons {
display: flex;
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
overflow: hidden;
}
.view-btn {
background-color: var(--bg-color);
border: none;
color: var(--dark-gray);
padding: 8px 12px;
cursor: pointer;
transition: var(--transition);
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.view-btn:not(:last-child) {
border-right: 1px solid var(--border-color);
}
.view-btn:hover {
background-color: var(--light-gray);
color: var(--primary-color);
}
.view-btn.active {
background-color: var(--primary-color);
color: white;
}
/* Admin View Switcher - reuse the same styling pattern */
.admin-view-switcher {
display: flex;
flex-direction: column;
flex-grow: 1;
min-width: 120px;
margin-left: 15px; /* Add some spacing from the regular view switcher */
}
.admin-view-switcher .view-buttons {
display: flex;
border: 1px solid var(--primary-color);
border-radius: var(--border-radius);
overflow: hidden;
}
.admin-view-switcher .view-btn {
background-color: var(--bg-color);
border: none;
color: var(--primary-color);
padding: 8px 12px;
cursor: pointer;
transition: var(--transition);
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
}
.admin-view-switcher .view-btn:not(:last-child) {
border-right: 1px solid var(--primary-color);
}
.admin-view-switcher .view-btn:hover {
background-color: rgba(var(--primary-rgb), 0.1);
color: var(--primary-dark);
}
.admin-view-switcher .view-btn.active {
background-color: var(--primary-color);
color: white;
}
/* View-only placeholder for non-owned warranties in global view */
.action-btn-placeholder {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: transparent;
color: #666;
cursor: default;
opacity: 0.5;
}
.action-btn-placeholder:hover {
background-color: rgba(0, 0, 0, 0.05);
}
[data-theme="dark"] .action-btn-placeholder {
border-color: #555;
color: #999;
}
[data-theme="dark"] .action-btn-placeholder:hover {
background-color: rgba(255, 255, 255, 0.05);
}
/* User info styling for global view */
.warranty-info div:has(strong:contains("Owner")) {
background-color: rgba(var(--primary-rgb), 0.1);
border-left: 3px solid var(--primary-color);
padding: 4px 8px;
margin-bottom: 8px;
border-radius: 4px;
font-weight: 500;
}
/* Alternative approach for better browser support */
.warranty-info div strong:contains("Owner") {
color: var(--primary-color);
}
.warranty-info div:first-child:has(strong) {
background-color: rgba(var(--primary-rgb), 0.1);
border-left: 3px solid var(--primary-color);
padding: 4px 8px;
margin-bottom: 8px;
border-radius: 4px;
font-weight: 500;
}
/* Grid View (Default) */
.warranties-list.grid-view {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
grid-auto-flow: row dense; /* Optimize grid item placement */
}
/* Make cards in grid view dynamic height based on content */
.grid-view .warranty-card {
display: flex;
flex-direction: column;
height: auto; /* Allow height to be determined by content */
}
/* Ensure content is properly structured */
.warranty-content {
display: flex;
padding: 15px;
flex: 0 1 auto; /* Don't force flex grow, allow natural sizing */
}
/* Keep document links at the bottom */
.document-links-row {
display: flex;
gap: 10px;
padding: 10px 15px;
background-color: rgba(0, 0, 0, 0.03);
border-top: 1px solid var(--border-color);
}
/* List View */
.warranties-list.list-view {
display: flex;
flex-direction: column;
gap: 15px;
margin-top: 20px;
}
.list-view .warranty-card {
display: flex;
flex-direction: column;
margin-bottom: 15px;
}
.list-view .warranty-content {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.list-view .warranty-info {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.list-view .warranty-info > div {
margin-bottom: 0;
margin-right: 15px;
}
.list-view .warranty-card .tags-row {
display: flex;
flex-wrap: wrap;
padding: 12px 15px 12px;
margin-top: 0;
border-top: 1px solid var(--border-color);
width: 100%;
}
/* For list view, ensure tags are clearly visible */
.list-view .tag {
margin-top: 4px;
margin-bottom: 4px;
}
/* Table View */
.warranties-list.table-view {
display: table;
width: 100%;
border-collapse: collapse;
margin-top: 20px;
table-layout: fixed; /* Add fixed table layout for better column control */
}
.table-view .warranty-card {
display: table-row;
border: none;
border-bottom: 1px solid var(--border-color);
height: auto; /* Explicitly allow row height to adjust to content */
}
.table-view .warranty-card.expired {
border-left: none;
background-color: rgba(231, 76, 60, 0.05);
}
.table-view .warranty-card.expiring-soon {
border-left: none;
background-color: rgba(241, 196, 15, 0.05);
}
.table-view .warranty-card.active {
border-left: none;
background-color: rgba(46, 204, 113, 0.05);
}
/* Ensure proper display of content in table view */
.table-view .product-name-header {
display: table-cell;
vertical-align: middle;
padding: 12px 15px;
width: 25%; /* Increase width for product names */
max-width: none; /* Remove max-width constraint */
white-space: normal; /* Allow text to wrap */
word-break: break-word; /* Break long words if needed */
background-color: transparent; /* Remove background color in table view */
border-bottom: none;
color: inherit; /* Use default text color instead of white */
}
.table-view .warranty-content {
display: table-cell;
vertical-align: middle;
padding: 12px 15px;
width: 30%; /* Set width for warranty details */
}
.table-view .warranty-info {
display: flex;
flex-direction: column;
}
.table-view .warranty-header,
.table-view .warranty-details {
display: table-cell;
vertical-align: middle;
padding: 12px 15px;
}
.table-view .warranty-header {
width: 200px;
border-bottom: none;
background-color: transparent;
}
.table-view .warranty-status {
margin: 0;
}
/* Ensure the status row is properly displayed in table view */
.table-view .warranty-status-row {
display: table-cell;
vertical-align: middle;
padding: 12px 15px;
border-top: none;
text-align: center;
width: 15%; /* Adjust width for status column */
}
.table-view .document-links-row {
display: table-cell; /* Restore table-cell display */
vertical-align: middle; /* Restore vertical alignment */
padding: 12px 15px;
width: 20%; /* Set width for document links */
}
/* ADD: New rule for inner container */
.document-links-inner-container {
display: flex;
flex-direction: column;
justify-content: center; /* Vertically center the group */
align-items: center; /* Horizontally center the group */
height: 100%; /* Fill cell height */
gap: 5px; /* Space between links */
}
/* Specific styling for links in table view */
.table-view .document-links-row a {
white-space: nowrap !important;
overflow: hidden !important; /* Restore overflow hidden */
text-overflow: ellipsis !important; /* Restore text overflow */
max-width: 90% !important; /* Slightly narrower to ensure centering works */
font-size: 0.9rem !important; /* Slightly smaller font size */
padding: 4px 8px !important; /* Smaller padding */
text-align: left !important; /* Keep text left-aligned within the link */
width: auto; /* Allow natural width */
}
.table-view .document-links-row a:last-child {
/* margin-bottom: 0 !important; */ /* Not needed */
}
.table-view .serial-numbers {
margin: 0;
}
/* Table Headers */
.table-view-header {
display: none;
}
.table-view-header.visible {
display: table-header-group;
}
.table-view-header th {
text-align: left;
padding: 12px 15px;
background-color: var(--light-gray);
font-weight: 600;
color: var(--text-color);
border-bottom: 2px solid var(--border-color);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Set specific widths for table headers to match cells */
.table-view-header th:nth-child(1) {
width: 25%; /* Product column */
}
.table-view-header th:nth-child(2),
.table-view-header th:nth-child(3) {
width: 15%; /* Purchase date and expiration columns */
}
.table-view-header th:nth-child(4) {
width: 15%; /* Status column */
text-align: center; /* Center align status header */
}
.table-view-header th:nth-child(5) {
width: 20%; /* Actions column */
text-align: center; /* Center align actions header */
}
/* Responsive adjustments */
@media (max-width: 768px) {
.view-switcher {
width: 100%;
}
.admin-view-switcher {
margin-left: 0;
margin-top: 10px;
width: 100%;
}
/* Convert table view to card-like view on mobile */
.warranties-list.table-view {
display: block;
}
.table-view .warranty-card {
display: block;
margin-bottom: 20px;
border: 1px solid var(--border-color);
border-radius: 8px;
overflow: hidden;
}
.table-view-header {
display: none !important; /* Hide table headers on mobile */
}
.table-view .product-name-header {
display: flex;
width: 100%;
padding: 15px;
background-color: var(--secondary-color);
color: white;
border-bottom: 1px solid var(--border-color);
}
.table-view .warranty-card.expired .product-name-header {
background-color: var(--danger-color);
}
.table-view .warranty-card.expiring-soon .product-name-header {
background-color: var(--warning-color);
}
.table-view .product-name-header .warranty-title {
color: white;
font-size: 1.1rem;
}
.table-view .warranty-content,
.table-view .warranty-status-row,
.table-view .document-links-row {
display: block;
width: 100%;
padding: 12px 15px;
}
.table-view .warranty-status-row {
text-align: center;
justify-content: center;
padding-left: 20px;
padding-right: 20px;
}
.table-view .document-links-row {
display: block; /* Make it block for mobile card layout */
gap: 10px;
border-top: 1px solid var(--border-color);
background-color: rgba(0, 0, 0, 0.03);
padding: 12px 15px;
width: 100%;
}
/* Reset the block display for links on mobile */
/* This might need adjustment if the parent is no longer flex */
.table-view .document-links-row a {
display: inline-flex !important;
margin-bottom: 5px !important; /* Add back some margin */
max-width: none !important;
flex: 0 1 auto !important;
}
}
/* Price input styling */
.price-input-wrapper {
position: relative;
display: flex;
align-items: center;
}
/* Apply absolute positioning ONLY inside input wrappers */
.price-input-wrapper .currency-symbol {
position: absolute;
left: 12px;
color: var(--dark-gray);
font-weight: 500;
z-index: 1;
}
/* Currency symbol on the right side of input */
.price-input-wrapper.currency-right .currency-symbol {
left: auto;
right: 12px;
pointer-events: none; /* Prevent interference with input */
}
/* Default style for currency symbols (e.g., on cards) */
.currency-symbol {
display: inline; /* Ensure it stays inline */
margin-right: 0.2em; /* Add a small space after the symbol */
/* Remove absolute positioning properties if they were here */
}
/* Currency symbol on the right side of numbers */
.currency-symbol.currency-right {
margin-right: 0;
margin-left: 0.2em; /* Add space before the symbol when on the right */
}
.price-input-wrapper .form-control {
padding-left: 25px;
}
/* Adjust padding for right-positioned currency symbol */
.price-input-wrapper.currency-right .form-control {
padding-left: 12px;
padding-right: 25px;
}
/* Product name header at the top of cards */
.product-name-header {
width: 100%;
padding: 15px;
border-bottom: 1px solid var(--border-color);
text-align: left;
color: white;
transition: background-color 0.3s ease;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
}
/* Default color for active warranties */
.warranty-card .product-name-header {
background-color: var(--secondary-color);
}
/* Color for expiring soon warranties */
.warranty-card.expiring-soon .product-name-header {
background-color: var(--warning-color);
}
/* Color for expired warranties */
.warranty-card.expired .product-name-header {
background-color: var(--danger-color);
}
.product-name-header .warranty-title {
margin: 0;
font-size: 1.2rem;
font-weight: 600;
color: white;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: calc(100% - 80px); /* Make room for the action buttons */
flex: 1;
text-align: left;
padding-left: 5px;
}
.product-name-header .warranty-actions {
display: flex;
gap: 8px;
align-items: center;
}
.warranty-actions .action-btn {
background: none;
border: none;
font-size: 1rem;
cursor: pointer;
color: rgba(255, 255, 255, 0.8);
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.warranty-actions .action-btn:hover {
background-color: rgba(255, 255, 255, 0.2);
color: white;
}
.warranty-content {
display: flex;
padding: 15px;
flex: 1;
position: relative;
}
.warranty-info {
flex: 0 1 auto; /* Allow natural sizing */
display: flex;
flex-direction: column;
}
.warranty-info > div {
margin-bottom: 8px;
}
.warranty-info > div:last-child {
margin-bottom: 0;
}
/* Serial numbers section */
.serial-numbers {
margin-top: 10px;
}
.serial-numbers ul {
margin: 5px 0 0 0;
padding-left: 20px;
}
.serial-numbers li {
margin-bottom: 3px;
}
/* Update list view styles */
.list-view .warranty-card {
display: flex;
flex-direction: column;
margin-bottom: 15px;
}
.list-view .warranty-content {
display: flex;
flex-direction: row;
align-items: center;
}
.list-view .warranty-info {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.list-view .warranty-info > div {
margin-bottom: 0;
margin-right: 15px;
}
/* Document links row */
.document-links-row {
display: flex;
gap: 10px;
padding: 10px 15px;
background-color: rgba(0, 0, 0, 0.03);
border-top: 1px solid var(--border-color);
}
/* Responsive adjustments */
@media (max-width: 768px) {
.product-name-header {
padding: 12px 15px;
}
.product-name-header .warranty-title {
font-size: 1.1rem;
}
.warranty-content {
flex-direction: column;
}
.list-view .warranty-info {
flex-direction: column;
gap: 5px;
}
}
/* GitHub link styling */
.settings-link.github-link {
background-color: #24292e; /* GitHub's dark color */
color: white !important;
border-radius: 4px;
transition: all 0.3s ease;
display: flex;
align-items: center;
padding: 8px 12px;
margin: 0;
width: 100%;
box-sizing: border-box;
}
.settings-link.github-link:hover {
background-color: #2b3137; /* Slightly lighter on hover */
transform: translateY(-2px);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.settings-link.github-link i {
font-size: 1.2em;
margin-right: 8px;
}
/* Warranty status row styling */
.warranty-status-row {
display: flex;
justify-content: center;
padding: 8px 15px;
font-weight: 600;
border-top: 1px solid var(--border-color);
}
.warranty-status-row.status-active {
background-color: rgba(40, 167, 69, 0.1);
color: var(--success-color);
}
.warranty-status-row.status-expiring {
background-color: rgba(255, 193, 7, 0.1);
color: var(--warning-color);
}
.warranty-status-row.status-expired {
background-color: rgba(220, 53, 69, 0.1);
color: var(--danger-color);
}
/* List view status row styling */
.list-view .warranty-status-row {
text-align: center;
justify-content: center;
padding-left: 20px;
padding-right: 20px;
}
.table-view .product-name-header .warranty-title {
color: var(--text-color); /* Use default text color */
white-space: normal; /* Allow text to wrap */
overflow: visible; /* Show overflow text */
text-overflow: clip; /* Don't use ellipsis */
max-width: none; /* Remove max-width constraint */
font-size: 1rem; /* Slightly smaller font size for table view */
}
.table-view .product-name-header .warranty-actions {
position: static; /* Reset position */
margin-left: auto; /* Push to the right */
}
.table-view .warranty-actions .action-btn {
color: var(--text-color); /* Use default text color */
opacity: 0.7;
transition: opacity 0.2s ease;
}
.table-view .warranty-actions .action-btn:hover {
opacity: 1;
}
/* Improve warranty info display in table view */
.table-view .warranty-info > div {
margin-bottom: 4px;
font-size: 0.9rem;
}
.table-view .warranty-info > div:last-child {
margin-bottom: 0;
}
/* Improve serial numbers display in table view */
.table-view .serial-numbers {
margin-top: 5px;
}
.table-view .serial-numbers ul {
padding-left: 20px;
margin: 5px 0 0;
}
.table-view .serial-numbers li {
font-size: 0.85rem;
margin-bottom: 2px;
}
/* Edit Warranty Tabs */
.edit-tabs-nav {
display: flex;
border-bottom: 1px solid var(--border-color);
margin-bottom: 1.5rem;
overflow-x: auto;
padding-bottom: 1px;
}
.edit-tab-btn {
background: none;
border: none;
cursor: pointer;
font-weight: 500;
padding: 0.75rem 1rem;
position: relative;
color: var(--text-muted);
white-space: nowrap;
transition: color 0.2s ease;
}
.edit-tab-btn:hover {
color: var(--text-color);
}
.edit-tab-btn.active {
color: var(--primary-color);
}
.edit-tab-btn.active::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
width: 100%;
height: 2px;
background-color: var(--primary-color);
}
.edit-tab-btn i {
margin-right: 0.5rem;
}
.edit-tab-content {
display: none;
}
.edit-tab-content.active {
display: block;
animation: fadeIn 0.3s ease;
}
/* Completed Tab Indicator for Edit Form - simplified */
.edit-tab-btn.completed {
color: var(--primary-color);
}
/* Make the edit modal wider to accommodate the tabs better */
#editModal .modal {
max-width: 700px;
background-color: var(--modal-background, #ffffff);
}
@media (max-width: 768px) {
.document-links-row .notes-link,
.document-links-row .invoice-link,
.document-links-row .manual-link,
.document-links-row .product-link,
.document-links-row .other-document-link {
margin-right: 5px !important;
margin-left: 0 !important;
}
}
@media (max-width: 768px) {
.document-links-row {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
gap: 5px !important;
}
.invoice-link, .manual-link, .product-link, .notes-link, .other-document-link {
width: auto !important;
justify-content: center !important;
}
}
.edit-tab-content {
padding: 1rem 0;
}
.edit-tabs-nav {
position: sticky;
top: 0;
background-color: var(--modal-background, #ffffff);
z-index: 5;
padding-top: 1rem;
border-bottom: 1px solid var(--border-color);
}
/* Style for validation errors in the edit form */
#editWarrantyForm input.invalid {
border-color: var(--danger-color);
background-color: rgba(255, 0, 0, 0.03);
}
#editWarrantyForm input.invalid:focus {
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
/* Add animation for tab switching */
@keyframes editTabFade {
from { opacity: 0; transform: translateY(5px); }
to { opacity: 1; transform: translateY(0); }
}
.edit-tab-content.active {
animation: editTabFade 0.3s ease;
}
/* Edit modal dark mode styles */
:root[data-theme="dark"] #editModal .modal {
background-color: var(--modal-background);
}
:root[data-theme="dark"] #editModal .modal-header,
:root[data-theme="dark"] #editModal .modal-body,
:root[data-theme="dark"] #editModal .modal-footer,
:root[data-theme="dark"] .edit-tabs-nav {
background-color: var(--modal-background);
color: var(--text-color);
}
:root[data-theme="dark"] #editModal .form-control {
background-color: var(--input-background);
color: var(--text-color);
border-color: var(--border-color);
}
:root[data-theme="dark"] #editModal .form-control:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.25);
}
:root[data-theme="dark"] #editModal label {
color: var(--text-color);
}
:root[data-theme="dark"] .edit-tab-btn {
color: var(--text-muted);
}
:root[data-theme="dark"] .edit-tab-btn:hover {
color: var(--text-color);
}
:root[data-theme="dark"] .edit-tab-btn.active {
color: var(--primary-color);
}
:root[data-theme="dark"] .currency-symbol {
color: var(--text-color);
}
:root[data-theme="dark"] .file-input-label {
background-color: var(--input-background);
color: var(--text-color);
border: 1px solid var(--border-color);
}
:root[data-theme="dark"] .file-input-label:hover {
background-color: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
:root[data-theme="dark"] .file-name {
color: var(--text-muted);
}
:root[data-theme="dark"] #currentInvoice,
:root[data-theme="dark"] #currentManual {
color: var(--text-color);
}
:root[data-theme="dark"] #currentInvoice a,
:root[data-theme="dark"] #currentManual a {
color: var(--primary-color);
}
:root[data-theme="dark"] .serial-number-input {
margin-bottom: 10px;
}
:root[data-theme="dark"] .serial-number-input .form-control {
background-color: var(--input-background);
color: var(--text-color);
border-color: var(--border-color);
}
:root[data-theme="dark"] .modal-backdrop {
background-color: rgba(0, 0, 0, 0.7);
}
/* Tags styling in warranty cards */
.tag {
display: inline-flex;
align-items: center;
padding: 6px 10px;
border-radius: 16px;
font-size: 0.85rem;
font-weight: 500;
margin-right: 8px;
margin-bottom: 8px;
white-space: nowrap;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.tag .remove-tag {
margin-left: 6px;
cursor: pointer;
font-size: 1.1rem;
line-height: 1;
opacity: 0.7;
transition: opacity 0.2s ease, transform 0.2s ease;
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: rgba(0, 0, 0, 0.1);
}
.tag .remove-tag:hover {
opacity: 1;
transform: scale(1.2);
background-color: rgba(0, 0, 0, 0.2);
}
/* Make the remove-tag more prominent in the edit modal */
#editSelectedTags .tag .remove-tag {
font-weight: bold;
background-color: rgba(0, 0, 0, 0.2);
border-radius: 50%;
width: 22px;
height: 22px;
margin-left: 8px;
font-size: 1.2rem;
opacity: 0.8;
/* Prevent text selection */
user-select: none;
-webkit-user-select: none;
}
#editSelectedTags .tag .remove-tag:hover {
opacity: 1;
transform: scale(1.2);
background-color: rgba(0, 0, 0, 0.3);
}
/* Use a more obvious pointer cursor */
#editSelectedTags .tag .remove-tag {
cursor: pointer;
}
.warranty-card .tags-row {
display: flex;
flex-wrap: wrap;
margin-top: 10px;
padding: 12px 15px 12px;
border-top: 1px solid var(--border-color);
}
/* Tag styling for grid view */
.grid-view .warranty-card .tags-row {
padding: 12px 15px 12px;
}
/* Tag styling for list view */
.list-view .warranty-card .tags-row {
padding: 12px 15px 12px;
}
/* Tag styling for table view */
.table-view .warranty-card .tags-row {
display: table-cell;
vertical-align: middle;
padding: 12px 15px;
width: 20%;
border-top: none;
}
/* Add near other form styles */
.lifetime-label {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-weight: 500;
margin-bottom: 10px;
}
.lifetime-label input[type="checkbox"] {
width: 18px;
height: 18px;
cursor: pointer;
margin-right: 5px;
accent-color: var(--primary-color);
}
/* Style for the warranty duration fields container */
.duration-inputs {
display: flex;
gap: 15px; /* Adjust spacing between inputs */
align-items: flex-start; /* Align items to the top */
}
.duration-inputs > div {
flex: 1; /* Allow each input group to take equal space */
display: flex;
flex-direction: column; /* Stack input and label vertically */
align-items: center; /* Center items horizontally within their div */
}
.duration-inputs input[type="number"].form-control {
text-align: center; /* Center the number inside the input */
margin-bottom: 5px; /* Space between input and label */
/* Inherits padding, border, etc. from .form-control */
}
.duration-inputs small {
font-size: 0.85rem;
color: var(--dark-gray);
}
/* Style for the warranty duration group when hidden (due to lifetime checkbox) */
#warrantyDurationFields[style*="display: none"],
#editWarrantyDurationFields[style*="display: none"] {
opacity: 0.5;
transition: opacity 0.3s ease;
/* Optionally add height transition if needed */
/* max-height: 0; */
/* overflow: hidden; */
/* padding-top: 0; */
/* padding-bottom: 0; */
/* margin-bottom: 0; */
}
/* Add CSS for the tags cell in table view */
.table-view .tags-row-cell {
display: table-cell;
vertical-align: middle;
}
/* Style the new button */
.add-warranty-button-container {
/* grid-column: 1 / -1; /* REMOVED */
/* text-align: right; /* REMOVED */
/* margin-bottom: 20px; /* REMOVED */
/* No longer needs standalone styles here */
}
/* REMOVE this rule if button size is handled by btn-sm */
/* #showAddWarrantyBtn {
width: auto;
padding: 10px 20px;
} */
/* REMOVE this rule if icon margin is handled by btn-sm or FontAwesome defaults */
/* #showAddWarrantyBtn i {
margin-right: 8px;
} */
/* Forms */
/* ADD styles for Panel Header */
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
flex-wrap: wrap;
gap: 10px;
}
.panel-header h2 {
margin: 0;
font-size: 1.4rem;
color: var(--primary-color);
flex-grow: 1;
}
.panel-header-actions {
display: flex;
align-items: center;
gap: 10px;
flex-shrink: 0;
}
/* ===== RESPONSIVE ADJUSTMENTS ===== */
@media (max-width: 768px) {
header .container {
flex-wrap: wrap; /* Allow header items to wrap */
justify-content: center; /* Center items when wrapped */
gap: 15px; /* Add space between wrapped items */
padding: 10px 15px !important; /* Adjust padding for smaller screens */
}
header .app-title h1 {
font-size: 1.8rem !important; /* Slightly reduce title size */
}
header .app-title i {
font-size: 1.6rem !important; /* Slightly reduce icon size */
margin-right: 10px !important; /* Slightly reduce icon size */
}
header .nav-links {
order: 3; /* Push nav links to the bottom row when wrapped */
width: 100%; /* Make nav links take full width */
justify-content: center; /* Center nav links */
margin: 10px 0 0 0 !important; /* Add margin top, remove horizontal margin */
padding-bottom: 5px; /* Add some padding below nav links */
}
header .auth-buttons,
header .user-menu,
header .settings-container {
margin-left: 0 !important; /* Reset margins */
margin-right: 0 !important;
}
/* Adjust existing rules within the media query */
.main-content {
grid-template-columns: 1fr;
}
}
.warranty-notes {
background: #f8f9fa;
color: #333;
border-left: 4px solid var(--primary-color, #007bff);
padding: 8px 12px;
margin: 10px 0 0 0;
font-size: 0.97rem;
border-radius: 4px;
white-space: pre-line;
}
/* Custom style for View Notes button to match refined requirements */
.view-notes-btn {
display: block;
width: auto;
min-width: 120px;
max-width: 220px;
margin: 18px auto 0 auto;
background-color: #8fc98a;
color: var(--text-color);
border: 1.5px solid #7bb87a;
border-radius: 6px;
font-size: 0.98rem;
font-family: inherit;
font-weight: 500;
padding: 7px 18px;
box-shadow: none;
text-align: center;
transition: background 0.2s, color 0.2s, border 0.2s;
}
.view-notes-btn i {
margin-right: 7px;
}
.view-notes-btn:hover, .view-notes-btn:focus {
background-color: #7bb87a;
color: var(--text-color);
border-color: #6fa96a;
outline: none;
}
.notes-link {
display: inline-flex;
align-items: center !important;
color: var(--primary-color) !important;
text-decoration: none !important;
font-weight: 500 !important;
padding: 5px 10px !important;
background-color: var(--light-gray) !important;
border-radius: var(--border-radius) !important;
transition: var(--transition) !important;
border: none !important;
white-space: nowrap !important;
font-size: 1rem !important;
}
.notes-link i {
margin-right: 5px !important;
font-size: 1rem !important;
}
.notes-link:hover, .notes-link:focus {
text-decoration: none !important;
background-color: var(--medium-gray) !important;
color: var(--primary-dark) !important;
outline: none;
}
/* ADD: Specific overrides for grid and list view */
.grid-view .document-links-row,
.list-view .document-links-row {
flex-direction: row; /* Ensure horizontal layout */
flex-wrap: wrap; /* Allow wrapping if needed in these views */
align-items: center; /* Vertically align items if they wrap */
justify-content: flex-start; /* Align items to the start */
margin-top: 10px; /* Adjust top margin if needed */
padding: 10px 15px; /* Ensure padding is consistent */
background-color: rgba(0, 0, 0, 0.03); /* Ensure background */
border-top: 1px solid var(--border-color); /* Ensure border */
}
/* Force horizontal layout for links in grid/list views */
.grid-view .document-links-inner-container,
.list-view .document-links-inner-container {
flex-direction: row !important;
align-items: center !important;
justify-content: flex-start !important;
gap: 10px !important;
height: auto !important;
flex-wrap: wrap !important;
}
@media (max-width: 768px) {
.table-view .document-links-row .notes-link {
margin-right: 5px !important;
}
}
@media (max-width: 768px) {
.document-links-row .notes-link,
.document-links-row .invoice-link,
.document-links-row .manual-link,
.document-links-row .product-link {
margin-right: 5px !important;
margin-left: 0 !important;
}
}
@media (max-width: 768px) {
.notes-link {
width: 100% !important;
justify-content: center !important;
}
}
@media (max-width: 768px) {
.document-links-row {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
gap: 5px !important;
}
.invoice-link, .manual-link, .product-link, .notes-link {
width: auto !important;
justify-content: center !important;
}
}
/* Styling for the main row when details are expanded */
#recentExpirationsTable tr.details-expanded {
background-color: var(--medium-gray) !important; /* Use important to override existing hover or status colors if needed, or make more specific */
/* color: var(--primary-color); /* Optional: change text color of expanded row */
}
/* Styling for the new details row */
.warranty-details-row td {
padding: 20px !important; /* Ensure padding is applied */
background-color: var(--details-bg);
color: var(--details-text-color);
border-top: 1px solid var(--details-border-color);
border-bottom: 1px solid var(--details-border-color);
}
.warranty-details-content {
display: flex;
flex-wrap: wrap;
gap: 25px; /* Increased gap */
}
.warranty-details-content > div { /* Direct children divs (sections) */
flex: 1 1 280px; /* Allow wrapping with a minimum width */
padding: 10px;
}
.warranty-details-content h4 {
margin-top: 0;
margin-bottom: 12px;
font-size: 1.1rem;
color: var(--primary-color);
border-bottom: 1px solid var(--details-border-color);
padding-bottom: 8px;
}
.warranty-details-content p {
margin-bottom: 8px;
font-size: 0.95rem;
line-height: 1.5;
}
.warranty-details-content p strong {
color: var(--details-text-color);
margin-right: 5px;
}
.warranty-details-content a {
color: var(--primary-color);
text-decoration: none;
}
.warranty-details-content a:hover {
text-decoration: underline;
}
.warranty-details-content ul {
list-style-type: disc;
margin-left: 20px;
padding-left: 0;
}
.warranty-details-content li {
margin-bottom: 5px;
}
.warranty-details-content pre {
background-color: var(--notes-bg);
color: var(--details-text-color);
padding: 15px;
border-radius: var(--border-radius);
white-space: pre-wrap;
word-wrap: break-word;
font-family: monospace;
font-size: 0.9rem;
border: 1px solid var(--details-border-color);
}
/* ... existing code ... */
/* Ensure view document links in modals are styled consistently, especially in dark mode */
[data-theme="dark"] .view-document-link {
color: var(--primary-color); /* Or your specific dark mode link color variable */
text-decoration: underline;
}
[data-theme="dark"] .view-document-link:hover,
[data-theme="dark"] .view-document-link:focus {
color: var(--primary-light); /* Or a slightly lighter/different hover color */
text-decoration: none;
}
/* If the text-success class interferes, this can provide higher specificity */
[data-theme="dark"] .text-success .view-document-link {
color: var(--primary-color); /* Ensure override if text-success sets link color */
}
[data-theme="dark"] .text-success .view-document-link:hover,
[data-theme="dark"] .text-success .view-document-link:focus {
color: var(--primary-light);
}
.modal {
background-color: var(--modal-background, #ffffff);
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
width: 90%;
max-width: 600px;
max-height: 90vh;
display: flex;
flex-direction: column;
animation: slide-in 0.3s ease;
position: relative;
overflow: hidden; /* Changed from auto to hidden */
}
:root[data-theme="dark"] .modal-backdrop {
background-color: rgba(0, 0, 0, 0.7);
}
/* Dark mode styles for tag management modal */
:root[data-theme="dark"] #tagManagementModal .modal {
background-color: var(--modal-background) !important;
}
:root[data-theme="dark"] #tagManagementModal .modal-header,
:root[data-theme="dark"] #tagManagementModal .modal-body,
:root[data-theme="dark"] #tagManagementModal .modal-footer {
background-color: var(--modal-background) !important;
color: var(--text-color) !important;
}
:root[data-theme="dark"] #tagManagementModal .form-control {
background-color: var(--input-background) !important;
color: var(--text-color) !important;
border-color: var(--border-color) !important;
}
:root[data-theme="dark"] #tagManagementModal .form-control:focus {
border-color: var(--primary-color) !important;
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.25) !important;
}
:root[data-theme="dark"] #tagManagementModal label,
:root[data-theme="dark"] #tagManagementModal h4 {
color: var(--text-color) !important;
}
:root[data-theme="dark"] #tagManagementModal .existing-tag {
background-color: var(--card-bg) !important;
color: var(--text-color) !important;
}
/* Mobile responsive styles for tag management modal */
@media (max-width: 768px) {
#tagManagementModal.modal-backdrop {
padding: 10px !important;
}
#tagManagementModal .modal {
width: 95% !important;
max-width: none !important;
margin: 0 !important;
}
#tagManagementModal .modal-header,
#tagManagementModal .modal-body,
#tagManagementModal .modal-footer {
padding: 15px !important;
}
#tagManagementModal .tag-form {
flex-direction: column !important;
gap: 10px !important;
}
#tagManagementModal .tag-form input[type="color"] {
width: 100% !important;
height: 40px !important;
}
}
/* Fix CSS Syntax Error - Replace orphaned properties with stronger tag management modal overrides */
/* Override styles.css modal positioning specifically for tag management modal */
#tagManagementModal.modal-backdrop {
display: none !important;
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
background-color: rgba(0, 0, 0, 0.5) !important;
z-index: 1050 !important;
justify-content: center !important;
align-items: center !important;
overflow: auto !important;
}
#tagManagementModal.modal-backdrop.active {
display: flex !important;
}
/* Stronger override to center the tag management modal content */
#tagManagementModal .modal-content,
#tagManagementModal .modal {
position: static !important;
top: auto !important;
left: auto !important;
margin: 0 !important;
width: 90% !important;
max-width: 600px !important;
max-height: 90vh !important;
background-color: var(--modal-background, #ffffff) !important;
border-radius: 8px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2) !important;
overflow-y: auto !important;
display: flex !important;
flex-direction: column !important;
}
.filter-options {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
}
/* Style for the warranty duration group when hidden (due to lifetime checkbox) */
#warrantyDurationFields.hidden {
display: none;
}
/* Warranty Entry Method Styling */
.warranty-method-options {
display: flex !important;
flex-direction: row !important;
gap: 20px;
margin-top: 8px;
flex-wrap: wrap;
}
.warranty-method-options .radio-option {
display: flex !important;
flex-direction: row !important;
align-items: center;
cursor: pointer;
font-weight: normal;
margin: 0;
white-space: nowrap;
}
.warranty-method-options .radio-option input[type="radio"] {
margin-right: 8px;
cursor: pointer;
flex-shrink: 0;
}
.warranty-method-options .radio-option span {
user-select: none;
cursor: pointer;
}
/* Ensure both add and edit modal warranty methods display horizontally */
#warrantyEntryMethod .warranty-method-options,
#editWarrantyEntryMethod .warranty-method-options {
display: flex !important;
flex-direction: row !important;
gap: 20px;
flex-wrap: wrap;
align-items: center;
}
/* Mobile responsive - stack vertically only on very small screens if needed */
@media (max-width: 480px) {
.warranty-method-options {
flex-direction: column !important;
gap: 10px;
}
.warranty-method-options .radio-option {
justify-content: flex-start;
}
}
/* Powered by Warracker footer */
.warracker-footer {
margin-top: 50px;
padding: 20px;
text-align: center;
border-top: 1px solid #e0e0e0;
background-color: var(--card-bg) !important;
color: var(--text-color);
font-size: 0.9rem;
}
.warracker-footer a {
color: #3498db;
text-decoration: none;
font-weight: 500;
}
.warracker-footer a:hover {
color: #2980b9;
text-decoration: underline;
}
/* Dark theme styles */
[data-theme="dark"] .warracker-footer {
border-top-color: #444;
}
[data-theme="dark"] .warracker-footer a {
color: #4dabf7;
}
[data-theme="dark"] .warracker-footer a:hover {
color: #339af0;
}
/* Also support html.dark-mode for older implementations */
html.dark-mode .warracker-footer {
border-top-color: #444;
}
html.dark-mode .warracker-footer a {
color: #4dabf7;
}
html.dark-mode .warracker-footer a:hover {
color: #339af0;
}
@media (max-width: 768px) {
.warracker-footer {
margin-top: 30px;
padding: 15px;
font-size: 0.85rem;
}
}
/* ===== PRODUCT PHOTO STYLES ===== */
.product-photo-thumbnail {
position: absolute;
top: 8px;
right: 8px;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.product-photo-thumbnail img {
border: 2px solid var(--border-color);
border-radius: 8px;
object-fit: cover;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.product-photo-thumbnail img:hover {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.product-photo-thumbnail a {
display: block;
text-decoration: none;
}
.product-photo-thumbnail a:hover {
text-decoration: none;
}
.photo-preview {
margin-top: 10px;
text-align: center;
}
.photo-preview img {
border: 2px solid var(--border-color);
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* Grid view photo positioning */
.grid-view .product-photo-thumbnail img {
width: 80px;
height: 80px;
}
/* List view photo positioning */
.list-view .product-photo-thumbnail img {
width: 70px;
height: 70px;
}
/* Table view photo positioning */
.table-view .product-photo-thumbnail img {
width: 55px;
height: 55px;
}
/* Dark mode adjustments */
:root[data-theme="dark"] .product-photo-thumbnail img {
border-color: var(--border-color);
}
:root[data-theme="dark"] .photo-preview img {
border-color: var(--border-color);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
/* Mobile responsiveness */
@media (max-width: 768px) {
.grid-view .product-photo-thumbnail img,
.list-view .product-photo-thumbnail img {
width: 60px;
height: 60px;
}
.table-view .product-photo-thumbnail img {
width: 50px;
height: 50px;
}
.product-photo-thumbnail {
top: 6px;
right: 6px;
}
}