/* ==========================================================================
   CSS Stylesheet - Construction Equipment Rental System
   Theme: Clean Light Mode with Accent Colors
   ========================================================================== */

/* Design Tokens (CSS Variables) */
:root {
    --primary-color: #4f46e5;       /* Indigo */
    --primary-light: #e0e7ff;
    --primary-hover: #4338ca;
    --accent-color: #0d9488;        /* Teal */
    --accent-light: #ccfbf1;
    --accent-hover: #0f766e;
    --success-color: #10b981;       /* Emerald */
    --success-light: #d1fae5;
    --danger-color: #ef4444;        /* Red */
    --danger-light: #fee2e2;
    --warning-color: #f59e0b;       /* Amber */
    --warning-light: #fef3c7;
    
    --bg-body: #f8fafc;             /* Slate 50 */
    --bg-card: #ffffff;
    --border-color: #e2e8f0;        /* Slate 200 */
    --text-main: #0f172a;           /* Slate 900 */
    --text-muted: #64748b;          /* Slate 500 */
    --text-light: #94a3b8;          /* Slate 400 */
    
    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -2px rgba(0, 0, 0, 0.08);
    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.08);
    
    --radius-sm: 6px;
    --radius-md: 12px;
    --radius-lg: 16px;
    
    --transition-fast: 0.15s ease;
    --transition-normal: 0.25s ease;
}

/* Reset and Global Styles */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Prompt', 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    background-color: var(--bg-body);
    background-image: 
        radial-gradient(rgba(148, 163, 184, 0.08) 1.5px, transparent 1.5px);
    background-size: 24px 24px;
    color: var(--text-main);
    line-height: 1.5;
    overflow-x: hidden;
}

/* App Container Layout */
.app-container {
    display: flex;
    min-height: 100vh;
    width: 100vw;
}

/* Sidebar Styling */
.sidebar {
    width: 280px;
    background-color: var(--bg-card);
    border-right: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    position: fixed;
    height: 100vh;
    z-index: 100;
}

.sidebar-brand {
    padding: 24px;
    display: flex;
    align-items: center;
    gap: 12px;
    border-bottom: 1px solid var(--border-color);
}

.brand-icon {
    background: linear-gradient(135deg, #3b82f6, #06b6d4);
    color: #ffffff;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
    transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.brand-icon:hover {
    transform: translateY(-2px) scale(1.05);
    box-shadow: 0 6px 16px rgba(59, 130, 246, 0.3);
}

.brand-icon i {
    width: 22px;
    height: 22px;
}

.brand-text h1 {
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--text-main);
    line-height: 1.2;
}

.brand-text span {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-weight: 500;
}

.sidebar-menu {
    padding: 20px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex-grow: 1;
    overflow-y: auto;
}

.menu-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    color: var(--text-muted);
    text-decoration: none;
    border-radius: var(--radius-md);
    font-weight: 500;
    font-size: 0.95rem;
    transition: var(--transition-fast);
}

.menu-item i {
    width: 20px;
    height: 20px;
}

.menu-item:hover {
    background-color: var(--bg-body);
    color: var(--primary-color);
}

.menu-item.active {
    background-color: var(--primary-light);
    color: var(--primary-color);
    font-weight: 600;
}

.sidebar-footer {
    padding: 20px 24px;
    border-top: 1px solid var(--border-color);
    font-size: 0.75rem;
    color: var(--text-light);
}

.sidebar-footer > span {
    display: block;
    margin-top: 4px;
    color: var(--success-color);
    font-weight: 500;
}

/* Main Content Area */
.main-content {
    margin-left: 280px;
    flex-grow: 1;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    width: calc(100% - 280px);
    position: relative;
}

.main-content::before {
    content: "";
    position: fixed;
    top: -10%;
    right: -10%;
    width: 50vw;
    height: 50vw;
    background: radial-gradient(circle, rgba(99, 102, 241, 0.06) 0%, rgba(255, 255, 255, 0) 70%);
    z-index: -1;
    pointer-events: none;
}

.main-content::after {
    content: "";
    position: fixed;
    bottom: -10%;
    left: 10%;
    width: 60vw;
    height: 60vw;
    background: radial-gradient(circle, rgba(13, 148, 136, 0.04) 0%, rgba(255, 255, 255, 0) 70%);
    z-index: -1;
    pointer-events: none;
}

/* Top Header */
.top-header {
    background-color: var(--bg-card);
    border-bottom: 1px solid var(--border-color);
    padding: 20px 32px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: sticky;
    top: 0;
    z-index: 90;
}

.header-title h2 {
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--text-main);
}

.current-date {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-top: 2px;
}

/* Base Button Styles */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 18px;
    font-size: 0.9rem;
    font-weight: 500;
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    cursor: pointer;
    transition: var(--transition-fast);
    font-family: inherit;
    text-decoration: none;
}

.btn i {
    width: 18px;
    height: 18px;
}

.btn-primary {
    background-color: var(--primary-color);
    color: #ffffff;
}

.btn-primary:hover {
    background-color: var(--primary-hover);
}

.btn-secondary {
    background-color: #ffffff;
    border-color: var(--border-color);
    color: var(--text-muted);
}

.btn-secondary:hover {
    background-color: var(--bg-body);
    color: var(--text-main);
}

.btn-accent {
    background-color: var(--accent-color);
    color: #ffffff;
}

.btn-accent:hover {
    background-color: var(--accent-hover);
}

.btn-success {
    background-color: var(--success-color);
    color: #ffffff;
}

.btn-success:hover {
    background-color: #059669;
}

.btn-danger {
    background-color: var(--danger-color);
    color: #ffffff;
}

.btn-danger:hover {
    background-color: #dc2626;
}

.btn-sm {
    padding: 6px 12px;
    font-size: 0.8rem;
    border-radius: var(--radius-sm);
}

.btn-sm i {
    width: 14px;
    height: 14px;
}

/* View Wrapper (SPA views container) */
.view-wrapper {
    padding: 32px;
    flex-grow: 1;
}

.content-view {
    display: none;
    animation: fadeIn 0.3s ease;
}

.content-view.active {
    display: block;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: translateY(0); }
}

/* Card Components */
.card {
    background-color: var(--bg-card);
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-sm);
    margin-bottom: 24px;
    overflow: hidden;
}

.card-header {
    padding: 20px 24px;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.card-header h3 {
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--text-main);
}

.card-body {
    padding: 24px;
}

/* Stats Dashboard Grid */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
    margin-bottom: 28px;
}

.stat-card {
    background-color: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    padding: 20px;
    display: flex;
    align-items: center;
    gap: 16px;
    box-shadow: var(--shadow-sm);
    transition: var(--transition-fast);
    cursor: pointer;
}

.stat-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
}

.stat-icon {
    width: 52px;
    height: 52px;
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
}

.stat-icon i {
    width: 24px;
    height: 24px;
}

.stat-icon.income {
    background-color: var(--success-light);
    color: var(--success-color);
}

.stat-icon.active-rent {
    background-color: var(--primary-light);
    color: var(--primary-color);
}

.stat-icon.total-prod {
    background-color: var(--accent-light);
    color: var(--accent-color);
}

.stat-icon.low-stock {
    background-color: var(--warning-light);
    color: var(--warning-color);
}

.stat-card.alert {
    border-color: #fcd34d;
}

.stat-info h3 {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-weight: 500;
}

.stat-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-main);
    margin-top: 2px;
}

/* Dashboard Charts & Alerts Layout */
.dashboard-grid {
    display: grid;
    grid-template-columns: 2fr 1.2fr;
    gap: 24px;
    margin-bottom: 24px;
}

.chart-container {
    position: relative;
    height: 280px;
    width: 100%;
}

/* Table Styling */
.table-responsive {
    overflow-x: auto;
    width: 100%;
}

.table {
    width: 100%;
    border-collapse: collapse;
    text-align: left;
}

.table th {
    background-color: var(--bg-body);
    padding: 14px 16px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-color);
}

.table td {
    padding: 16px;
    font-size: 0.9rem;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-main);
}

.table tbody tr:hover {
    background-color: #fafafa;
}

.min-table th, .min-table td {
    padding: 10px 12px;
    font-size: 0.85rem;
}

.empty-row-placeholder {
    text-align: center;
    color: var(--text-light);
    padding: 32px !important;
}

/* Low Stock Table Styles */
#table-low-stock th {
    white-space: nowrap !important;
    font-size: 0.88rem;
    font-weight: 700;
    padding: 12px 14px;
}

#table-low-stock td {
    white-space: nowrap !important;
    vertical-align: middle;
    padding: 12px 14px;
    font-size: 0.92rem;
}

#table-low-stock td:first-child {
    font-family: 'Outfit', monospace;
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--primary-color);
    letter-spacing: 0.5px;
}

/* Rentals Document Table Styles */
.rentals-table th {
    white-space: nowrap !important;
    font-size: 0.88rem;
    font-weight: 600;
    padding: 14px 16px;
}

.rentals-table td {
    white-space: nowrap !important;
    vertical-align: middle;
    padding: 14px 16px;
    font-size: 0.9rem;
}

/* Badges */
.badge {
    display: inline-flex;
    align-items: center;
    padding: 4px 8px;
    font-size: 0.75rem;
    font-weight: 600;
    border-radius: var(--radius-sm);
}

.badge-success {
    background-color: var(--success-light);
    color: var(--success-color);
}

.badge-warning {
    background-color: var(--warning-light);
    color: var(--warning-color);
}

.badge-primary {
    background-color: var(--primary-light);
    color: var(--primary-color);
}

.badge-danger {
    background-color: var(--danger-light);
    color: var(--danger-color);
}

/* View Header Bar (Search & Filter) */
.view-header-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 24px;
    gap: 20px;
}

.search-filter-group {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-grow: 1;
    max-width: 750px;
}

.search-filter-group .search-box {
    flex: 1;
}

.search-filter-group select {
    width: 180px;
    flex: 0 0 180px;
}

.search-box {
    position: relative;
    flex-grow: 1;
}

.search-box i, .search-box svg {
    position: absolute;
    right: 14px;
    left: auto;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-light);
    width: 18px;
    height: 18px;
    cursor: pointer;
    transition: color 0.15s;
    pointer-events: none; /* Make clicks pass through to input */
}

.search-box i:hover, .search-box svg:hover {
    color: var(--primary-color);
}

.search-box input {
    width: 100%;
    padding: 10px 42px 10px 14px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    font-family: inherit;
    font-size: 0.9rem;
    outline: none;
    transition: var(--transition-fast);
    background-color: var(--bg-card);
    color: var(--text-main);
}

.search-box input:focus {
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
}

/* Form Controls */
.form-control {
    width: 100%;
    padding: 10px 14px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    font-family: inherit;
    font-size: 0.9rem;
    outline: none;
    transition: var(--transition-fast);
    background-color: var(--bg-card);
    color: var(--text-main);
}

.form-control:focus {
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
}

/* Date fields are shown as วัน/เดือน/ปี by flatpickr's altInput (see
   js/dateDisplay.js). The calendar it opens is appended to <body>, so it
   needs to clear the modals it is opened from — those sit at z-index 9999. */
.flatpickr-calendar {
    z-index: 100000 !important;
}

.form-group {
    margin-bottom: 20px;
}

.form-group label {
    display: block;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text-muted);
    margin-bottom: 6px;
}

.form-row {
    display: flex;
    gap: 16px;
}

.col-6 { flex: 1; }
.col-4 { width: 33.33%; }
.col-8 { width: 66.66%; }

.required {
    color: var(--danger-color);
}

/* Sub-tabs inside view */
.sub-tabs {
    display: flex;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 24px;
    gap: 24px;
}

.sub-tab-btn {
    padding: 10px 4px;
    background: none;
    border: none;
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--text-muted);
    cursor: pointer;
    position: relative;
    transition: var(--transition-fast);
}

.sub-tab-btn:hover {
    color: var(--primary-color);
}

.sub-tab-btn.active {
    color: var(--primary-color);
    font-weight: 600;
}

.sub-tab-btn.active::after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 0;
    width: 100%;
    height: 2px;
    background-color: var(--primary-color);
}

.sub-tab-content {
    display: none;
}

.sub-tab-content.active {
    display: block;
}

/* Products Inventory Cards Grid */
.products-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 20px;
}

.product-card {
    background-color: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: var(--shadow-sm);
    transition: var(--transition-fast);
}

.product-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-md);
}

.product-card-body {
    padding: 20px;
    flex-grow: 1;
}

.product-cat {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--accent-color);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 6px;
    display: block;
}

.product-card-title {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--text-main);
    margin-bottom: 12px;
    line-height: 1.3;
}

.product-stock-bar {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px;
    background-color: var(--bg-body);
    border-radius: var(--radius-md);
    margin-bottom: 16px;
    font-size: 0.8rem;
}

.stock-indicator {
    display: flex;
    justify-content: space-between;
}

.stock-progress-track {
    height: 6px;
    background-color: var(--border-color);
    border-radius: 3px;
    overflow: hidden;
}

.stock-progress-bar {
    height: 100%;
    background-color: var(--success-color);
    border-radius: 3px;
}

.stock-progress-bar.low {
    background-color: var(--danger-color);
}

.product-price-box {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: auto;
    border-top: 1px solid var(--border-color);
    padding-top: 14px;
}

.product-price-label {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.product-price-val {
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--primary-color);
}

.product-card-actions {
    background-color: var(--bg-body);
    padding: 12px 10px;
    border-top: 1px solid var(--border-color);
    display: flex;
    gap: 6px;
}

.product-card-actions button {
    flex: 1;
    padding: 6px 2px;
    font-size: 0.72rem;
    gap: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.product-card-actions button i {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}

/* Info Alerts */
.info-alert {
    display: flex;
    gap: 12px;
    padding: 14px;
    border-radius: var(--radius-md);
    margin-bottom: 20px;
    font-size: 0.85rem;
}

.info-alert p {
    margin: 0;
}

.info-alert.info {
    background-color: var(--primary-light);
    color: var(--primary-color);
}

.info-alert.success {
    background-color: var(--success-light);
    color: var(--success-color);
}

.info-alert.warning {
    background-color: var(--warning-light);
    color: var(--warning-color);
}

/* Dynamic Forms Page Layout */
.form-grid {
    display: grid;
    grid-template-columns: 1fr 1.2fr;
    gap: 24px;
    align-items: start;
}

.form-grid.text-layout {
    grid-template-columns: 1fr 1.5fr;
}

.select-search-group {
    display: flex;
    gap: 8px;
}

.select-search-group select {
    flex-grow: 1;
}

.select-item-row {
    display: flex;
    gap: 12px;
    align-items: flex-end;
    margin-bottom: 20px;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--border-color);
}

.flex-3 { flex: 2; }
.flex-1 { flex: 0 0 90px; }

.selected-items-table-wrapper {
    max-height: 220px;
    overflow-y: auto;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    margin-bottom: 20px;
}

.selected-items-table-wrapper table th {
    position: sticky;
    top: 0;
    background-color: var(--bg-body);
    z-index: 10;
}

.rental-billing-summary {
    background-color: var(--bg-body);
    border-radius: var(--radius-lg);
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 24px;
}

.billing-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.9rem;
    color: var(--text-muted);
}

.billing-row strong {
    color: var(--text-main);
    font-size: 1.05rem;
}

.deposit-label {
    margin-bottom: 0 !important;
}

.inline-input {
    width: 120px;
    padding: 6px 12px;
    text-align: right;
}

/**
 * The report filters' date pickers (รายงานการเช่า).
 *
 * flatpickr (dateDisplay.js) hides the native <input type="date"> and shows
 * a text altInput carrying d/m/Y — 10 characters, e.g. "31/12/2569" — copied
 * from the original input's class and inline style. These three fields had
 * a hardcoded 170px, which is a class-less, id-less target for the mobile
 * "make inputs larger" rule below: that rule matches by class, and it never
 * matched here even though the sibling filter dropdowns in the same row do
 * get it. On a phone the whole row's font grows via .form-control's mobile
 * rule but this box did not — full digits in a box that never widened to
 * match.
 */
/**
 * Sized to the date it holds. flatpickr (dateDisplay.js) shows d/m/Y —
 * "24/08/2026" measures about 76px at this font, so 140px leaves a
 * comfortable margin without the empty half a wider box gave it.
 *
 * Left-aligned on purpose: .inline-input pushes its content right, which
 * is right for a money field in a form but left a visible void beside a
 * short date, making the box read as longer than it was.
 */
.report-date-input {
    width: 140px;
    text-align: left;
}

/* Sample-data notice. Amber rather than red: nothing is wrong, but the
   figures on screen are not the shop's own and saying so has to survive
   being scrolled past every day until they clear it. */
.demo-banner {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 0 0 20px;
    padding: 12px 16px;
    background: #fffbeb;
    border: 1px solid #fcd34d;
    border-left: 4px solid #f59e0b;
    border-radius: var(--radius-md);
    color: #78350f;
}

.demo-banner-icon {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    color: #b45309;
}

.demo-banner-text {
    flex: 1;
    font-size: 0.88rem;
    line-height: 1.5;
    min-width: 0;
}

.demo-banner-sub {
    display: block;
    font-size: 0.8rem;
    opacity: 0.85;
}

#btn-clear-demo-data {
    flex-shrink: 0;
    background: #b45309;
    border-color: #b45309;
    color: #fff;
    white-space: nowrap;
}

#btn-clear-demo-data:hover {
    background: #92400e;
    border-color: #92400e;
}

@media (max-width: 768px) {
    .demo-banner {
        flex-direction: column;
        align-items: stretch;
        text-align: left;
    }
    #btn-clear-demo-data {
        width: 100%;
    }
}

.grand-total {
    font-size: 1.05rem;
    font-weight: 600;
}

.grand-total strong {
    font-size: 1.35rem;
    color: var(--success-color);
}

.form-actions-bar {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
}

/* Document Settings Live Preview */
.preview-card {
    position: sticky;
    top: 90px;
}

.invoice-preview {
    background-color: #ffffff;
    border: 1px dashed var(--text-light);
    border-radius: 4px;
    padding: 32px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.02);
    font-size: 0.75rem;
    color: #333333;
    
    /* Scoped variables for preview context to prevent dark mode values from leaking */
    --text-main: #111111 !important;
    --text-muted: #475569 !important;
    --text-light: #94a3b8 !important;
    --bg-body: #f8fafc !important;
    --bg-card: #ffffff !important;
    --border-color: #e2e8f0 !important;
    --primary-light: #e0e7ff !important;
    --success-light: #d1fae5 !important;
    --danger-light: #fee2e2 !important;
}

.invoice-preview-header {
    display: flex;
    justify-content: space-between;
    gap: 20px;
}

.preview-logo-box {
    font-size: 1.2rem;
    font-weight: 800;
    color: var(--primary-color);
    letter-spacing: 1px;
    text-align: right;
}

.preview-header-info {
    text-align: left;
    font-size: 0.7rem;
    color: var(--text-muted);
}

.preview-header-info h4 {
    font-size: 0.85rem;
    color: var(--text-main);
    margin-bottom: 4px;
}

.preview-divider {
    border: none;
    border-top: 1px dashed var(--border-color);
    margin: 16px 0;
}

.invoice-preview-body {
    display: flex;
    flex-direction: column;
}

.preview-title-box {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
}

.preview-title-box h5 {
    font-size: 0.8rem;
    font-weight: 700;
}

.preview-serial {
    color: var(--text-muted);
}

.preview-table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 16px;
}

.preview-table th {
    background-color: #f8fafc;
    border-bottom: 1px solid #e2e8f0;
    padding: 6px;
    text-align: left;
    font-size: 0.7rem;
}

.preview-table td {
    border-bottom: 1px solid #f1f5f9;
    padding: 6px;
    font-size: 0.7rem;
}

.preview-summary {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    margin-bottom: 16px;
}

.preview-terms-box {
    background-color: #f8fafc;
    padding: 10px;
    border-radius: 4px;
    font-size: 0.65rem;
}

.preview-terms-box h6 {
    font-weight: 600;
    margin-bottom: 4px;
}

.preview-terms-box p {
    white-space: pre-line;
    color: var(--text-muted);
}

/* Daily Report Dashboard */
.report-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid var(--border-color);
    padding: 24px;
}

.report-logo {
    font-size: 1.3rem;
    font-weight: 800;
    color: var(--primary-color);
}

.report-title {
    text-align: right;
}

.report-title h2 {
    font-size: 1.3rem;
    font-weight: 700;
}

.report-selected-date-label {
    font-size: 0.9rem;
    color: var(--text-muted);
}

.report-summary-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 24px;
}

.r-summary-card {
    background-color: var(--bg-body);
    border-radius: var(--radius-md);
    padding: 16px;
    border: 1px solid var(--border-color);
}

.r-summary-card span {
    font-size: 0.75rem;
    color: var(--text-muted);
    display: block;
    margin-bottom: 6px;
}

.r-summary-card h4 {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-main);
}

.r-summary-card.cashflow h4 {
    color: var(--success-color);
}

.report-divider {
    border: none;
    border-top: 1px dashed var(--border-color);
    margin: 24px 0;
}

.report-lists-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
}

.report-list-column h3 {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 12px;
    color: var(--text-main);
}

/* Modals Overlay Base */
.modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(15, 23, 42, 0.4); /* Slate 900 translucent */
    backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 200;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

.modal.active {
    opacity: 1;
    pointer-events: auto;
}

.modal-content {
    background-color: var(--bg-card);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    width: 90%;
    max-width: 600px;
    max-height: 85vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    transform: translateY(16px);
    transition: transform 0.2s ease;
}

.modal.active .modal-content {
    transform: translateY(0);
}

.invoice-modal-content {
    max-width: 800px;
}

.modal-header {
    padding: 20px 24px;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.modal-header h3 {
    font-size: 1.15rem;
    font-weight: 600;
}

.modal-close {
    background: none;
    border: none;
    font-size: 1.75rem;
    font-weight: 300;
    color: var(--text-muted);
    cursor: pointer;
    line-height: 1;
    transition: var(--transition-fast);
}

.modal-close:hover {
    color: var(--danger-color);
}

.modal-body {
    padding: 24px;
    overflow-y: auto;
}

.modal-footer {
    padding: 16px 24px;
    border-top: 1px solid var(--border-color);
    display: flex;
    justify-content: flex-end;
    gap: 12px;
}

.header-buttons {
    display: flex;
    align-items: center;
    gap: 16px;
}

/* Details Page styling inside modal */
.details-section {
    margin-bottom: 24px;
}

.details-section h4 {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--primary-color);
    margin-bottom: 10px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 6px;
}

.details-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    font-size: 0.9rem;
}

.details-item span {
    color: var(--text-muted);
    display: block;
    font-size: 0.8rem;
}

.details-item strong {
    color: var(--text-main);
}

.details-item.full-width {
    grid-column: span 2;
}

/* Return Confirmation Modal Elements */
.return-info-summary {
    background-color: var(--bg-body);
    border-radius: var(--radius-md);
    padding: 16px;
    font-size: 0.9rem;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.return-items-list-wrapper {
    margin-top: 20px;
    margin-bottom: 20px;
}

.return-items-list-wrapper h4 {
    font-size: 0.95rem;
    font-weight: 600;
    margin-bottom: 8px;
}

/* Printable Invoice Styles */
.printable-invoice-area {
    background-color: #ffffff;
    color: #111111;
    font-size: 0.95rem;
    line-height: 1.5;

    /* Scoped variables to prevent dark mode styles from leaking into printable invoice modal */
    --text-main: #111111 !important;
    --text-muted: #475569 !important;
    --text-light: #94a3b8 !important;
    --bg-body: #f8fafc !important;
    --bg-card: #ffffff !important;
    --border-color: #e2e8f0 !important;
    --primary-light: #e0e7ff !important;
    --success-light: #d1fae5 !important;
    --danger-light: #fee2e2 !important;
}

.invoice-header {
    display: flex;
    justify-content: space-between;
    gap: 32px;
}

.biz-logo {
    font-size: 2rem;
    font-weight: 800;
    color: var(--primary-color);
    letter-spacing: 1px;
    text-align: right;
}

.biz-info {
    text-align: left;
}

.biz-info h2 {
    font-size: 1.3rem;
    font-weight: 700;
    margin-bottom: 4px;
}

.biz-info p {
    font-size: 0.9rem;
    color: var(--text-muted);
}

.invoice-divider {
    border: none;
    border-top: 1px solid var(--text-light);
    margin: 20px 0;
}

.invoice-subheader {
    display: flex;
    justify-content: space-between;
    margin-bottom: 20px;
}

.bill-to h4 {
    font-size: 1.1rem;
    font-weight: 600;
    margin-bottom: 8px;
    color: var(--text-main);
}

.bill-to p {
    font-size: 0.95rem;
    margin-bottom: 2px;
}

.bill-meta {
    text-align: right;
}

.bill-meta h3 {
    font-size: 1.4rem;
    font-weight: 700;
    margin-bottom: 8px;
    color: var(--primary-color);
}

.bill-meta p {
    font-size: 0.95rem;
    margin-bottom: 2px;
}

.invoice-table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 24px;
}

.invoice-table th {
    border-top: 1.5px solid #000;
    border-bottom: 1.5px solid #000;
    padding: 10px 8px;
    font-weight: 600;
    font-size: 0.95rem;
    text-align: left;
}

.invoice-table td {
    border-bottom: 1px solid #f1f5f9;
    padding: 12px 8px;
    font-size: 0.95rem;
}

.invoice-summary-section {
    display: flex;
    justify-content: space-between;
    margin-bottom: 32px;
    gap: 32px;
}

.bill-remarks-box {
    flex: 1.5;
    background-color: var(--bg-body);
    padding: 16px;
    border-radius: var(--radius-md);
    font-size: 0.9rem;
}

.bill-remarks-box p {
    margin-top: 4px;
    white-space: pre-line;
}

.bill-totals {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.total-row {
    display: flex;
    justify-content: space-between;
    font-size: 0.95rem;
}

.total-row.grand {
    font-size: 1.1rem;
    font-weight: 700;
}

.total-row.grand strong {
    font-size: 1.35rem;
    color: var(--success-color);
}

.invoice-terms {
    background-color: #fafafa;
    padding: 16px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    margin-bottom: 32px;
    font-size: 0.85rem;
}

.invoice-terms h4 {
    font-weight: 600;
    margin-bottom: 6px;
}

.invoice-terms p {
    white-space: pre-line;
    color: var(--text-muted);
}

.invoice-signatures {
    display: flex;
    justify-content: space-between;
    margin-top: 48px;
    padding: 0 16px;
}

.signature-box {
    text-align: center;
    width: 250px;
    font-size: 0.9rem;
}

.signature-box p:first-child {
    margin-bottom: 24px;
}

/* Print Stylesheet Overrides */
@media print {
    /**
     * The shop prints its customer documents on 9 x 11 inch continuous
     * two-ply stationery, not A4. The two differ enough to matter: 9in is
     * 19mm wider than A4 and 11in is 18mm shorter, so a page laid out for
     * A4 prints narrow with a band of waste down the side and risks
     * spilling onto a second form.
     *
     * Margins are tight because continuous stationery has its tractor
     * strip removed already and the usable area is the full sheet.
     */
    /**
     * No page margin at all: the documents carry their own.
     *
     * A margin declared here is only a request. Chromium drops it the
     * moment the print dialog's own Margins control is set to anything but
     * Default, which is why the band above the shop's name stayed wide
     * after it was reduced — the browser was using its figure, not this
     * one. Padding inside the document cannot be overridden that way, so
     * the layout is the same whatever the dialog is set to, which matters
     * on a dot matrix feeding continuous forms where a shifted top edge
     * walks every following sheet out of alignment.
     */
    @page {
        size: 9in 11in;
        margin: 0;
    }

    html, body {
        height: auto !important;
        overflow: visible !important;
        background: #ffffff !important;
        color: #000000 !important;
        font-size: 10.5pt !important;
    }

    /**
     * Every character on every printed document is black.
     *
     * The templates had grown a scatter of greys — #222 on an address, #333
     * on a subtitle, #555 on a date, #666 on an empty-state, var(--text-muted)
     * wherever a screen style leaked through. On a screen that is hierarchy.
     * On 9 x 11 two-ply carbon it is a lottery: the second copy takes its
     * ink from the pressure of the strike, so mid-grey text arrives faint on
     * the shop's own copy and sometimes not at all — and the greys had
     * settled on exactly the fields somebody later needs to read, the
     * address and the dates.
     *
     * Written as one blanket rule rather than by correcting each hex code,
     * because the failure mode of the second approach is missing one and
     * never knowing. `color` only: backgrounds, borders and rules are left
     * exactly as they are.
     */
    .printable-invoice-area, .printable-invoice-area *,
    #printable-slip-area, #printable-slip-area *,
    #printable-taxinv-area, #printable-taxinv-area *,
    .printable-taxinv-area, .printable-taxinv-area *,
    #printable-receipt-area, #printable-receipt-area *,
    .printable-receipt-area, .printable-receipt-area *,
    #printable-catalog-area, #printable-catalog-area *,
    #printable-barcode-area, #printable-barcode-area * {
        color: #000000 !important;
    }

    /**
     * No animation reaches the paper. This is not cosmetic — it is the only
     * way to win the cascade.
     *
     * .modal-content animates in from `transform: translateY(16px)`, and its
     * transition was still live when the page was printed, putting every
     * document 16px (4.2mm) down the form with nothing in the box model to
     * explain it. That is the gap above the tax invoice's header that
     * survived three wrong theories — margin collapse, stray padding, a
     * leftover transform — and the reason the fix for the third one did not
     * take.
     *
     * `transform: none !important` could not beat it. Transition
     * declarations sit at the very top of the CSS cascade, ABOVE author
     * !important (CSS Cascading 4 §6.6.1) — a running transition wins
     * against anything a stylesheet can say. So the transition itself has
     * to go, and then the ordinary rules apply.
     */
    *, *::before, *::after {
        transition: none !important;
        animation: none !important;
    }

    /**
     * Two-ply carbon takes its second copy from the pressure of the strike,
     * so a pale grey fill reproduces as nothing on the customer's sheet
     * while still costing ink on the first. Table headers and shaded rows
     * are given a rule instead of a wash.
     */
    #printable-slip-area thead tr,
    #printable-receipt-area thead tr,
    #printable-taxinv-area thead tr {
        background: transparent !important;
        border-top: 1.5px solid #000 !important;
        border-bottom: 1.5px solid #000 !important;
    }
    
    /* Hide everything on screen and prevent page breaks from hidden elements */
    body * {
        visibility: hidden;
        box-shadow: none !important;
    }

    /* The confetti canvas is not a .modal, so the per-document hide rules
       below would not catch it. It only exists for ~3.6s on a shop's very
       first login, but a tax invoice is a legal document and one with
       confetti on it is not worth the risk of leaving to chance. */
    #celebration-canvas,
    #festive-layer,
    .festive-corner {
        display: none !important;
    }

    body[data-festival] #current-view-title::after {
        content: none !important;
    }

    body.printing-invoice .app-container,
    body.printing-invoice .modal:not(#modal-invoice-detail),
    body.printing-invoice .sidebar-overlay,
    body.printing-report .app-container,
    body.printing-report .modal,
    body.printing-report .sidebar-overlay,
    body.printing-net-revenue .app-container,
    body.printing-net-revenue .modal,
    body.printing-net-revenue .sidebar-overlay,
    body.printing-catalog .app-container,
    body.printing-catalog .modal,
    body.printing-catalog .sidebar-overlay,
    body.printing-receipt .app-container,
    body.printing-receipt .modal:not(#modal-subscription-receipt),
    body.printing-receipt .sidebar-overlay,
    body.printing-taxinv .app-container,
    body.printing-taxinv .modal:not(#modal-tax-invoice-doc),
    body.printing-taxinv .sidebar-overlay,
    body.printing-cashreceipt .app-container,
    body.printing-cashreceipt .modal:not(#modal-cash-receipt),
    body.printing-cashreceipt .sidebar-overlay {
        display: none !important;
    }

    /* ใบเสร็จรับเงิน for a rental bill. Same mechanism as the two above;
       kept apart from .printing-receipt, which prints the SUBSCRIPTION
       receipt HJ Rental issues to the shop. */
    body.printing-cashreceipt #modal-cash-receipt,
    body.printing-cashreceipt #modal-cash-receipt .modal-content {
        position: static !important;
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        height: auto !important;
        overflow: visible !important;
        background: transparent !important;
        box-shadow: none !important;
        border: none !important;
        transform: none !important;
        padding: 0 !important;
        margin: 0 !important;
    }

    body.printing-cashreceipt #modal-cash-receipt .modal-header,
    body.printing-cashreceipt #modal-cash-receipt .modal-footer {
        display: none !important;
    }

    body.printing-cashreceipt .printable-receipt-area,
    body.printing-cashreceipt .printable-receipt-area * {
        visibility: visible;
    }

    body.printing-cashreceipt .printable-receipt-area {
        position: static !important;
        width: 100%;
        padding: 0;
    }

    /* On paper the sheet is the form, not a fixed centimetre count — let it
       take the printable height so the signatures sit at the foot. Its
       size and padding are set with the tax invoice's further down, since
       both are the same form. */

    /* ใบกำกับภาษี the shop issues to its rental customer — same mechanism as
       the invoice above: lift the one modal out and show only its
       printable area. */
    body.printing-taxinv #modal-tax-invoice-doc,
    body.printing-taxinv #modal-tax-invoice-doc .modal-content {
        position: static !important;
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        height: auto !important;
        overflow: visible !important;
        background: transparent !important;
        box-shadow: none !important;
        border: none !important;
        transform: none !important;
        padding: 0 !important;
        margin: 0 !important;
    }

    body.printing-taxinv #modal-tax-invoice-doc .modal-header,
    body.printing-taxinv #modal-tax-invoice-doc .modal-footer {
        display: none !important;
    }

    body.printing-taxinv .printable-taxinv-area,
    body.printing-taxinv .printable-taxinv-area * {
        visibility: visible;
    }

    /**
     * A tax invoice is one document; splitting it puts the totals, the
     * remarks and the signatures on a sheet with no header saying what they
     * belong to. The blocks below stay whole, and a long item list breaks
     * between rows rather than through them.
     */
    body.printing-taxinv .printable-taxinv-area table,
    body.printing-taxinv .printable-taxinv-area ol,
    body.printing-taxinv .printable-taxinv-area li {
        page-break-inside: avoid;
    }

    /**
     * On paper the sheet is the form, so the foot lands at the foot of the
     * form rather than a fixed centimetre count meant for the screen.
     *
     * Sized BELOW the usable height on purpose. It was set to exactly
     * 11in minus the page margin, which the modal's own 20px of padding
     * then pushed over the edge — emitting a second, entirely blank form
     * on every print, and on continuous stationery that is a wasted sheet
     * per customer. The padding is removed here as well, and the few
     * millimetres of slack absorb the rounding the browser does when it
     * scales the page.
     */
    body.printing-taxinv #modal-tax-invoice-doc .modal-body,
    body.printing-cashreceipt #modal-cash-receipt .modal-body {
        padding: 0 !important;
        overflow: visible !important;
    }

    /**
     * The dialog's own frame contributes nothing to the printed page.
     *
     * Worth naming the one that is easy to miss: .modal-content carries
     * `transform: translateY(16px)` as part of its open animation, which
     * shifts the document down the form without appearing as any margin or
     * padding. The rules further down already clear it; these zero the rest.
     */
    body.printing-taxinv #modal-tax-invoice-doc,
    body.printing-cashreceipt #modal-cash-receipt,
    body.printing-taxinv #modal-tax-invoice-doc .modal-content,
    body.printing-cashreceipt #modal-cash-receipt .modal-content {
        padding: 0 !important;
        margin: 0 !important;
        transform: none !important;
    }

    /**
     * 11in less the page margins, less a few millimetres of slack.
     *
     * The slack is what keeps the foot on this sheet: sized to the usable
     * height exactly, any rounding the browser does while scaling spills a
     * blank second form. It is deliberately small — every millimetre of it
     * is space the totals and signatures do not get to use, and this block
     * is meant to sit near the bottom edge.
     */
    /**
     * The sheet IS the form now, margins included. 10mm at the sides where
     * a printer's own unprintable strip lives, and 7mm at the foot so the
     * signatures finish near the bottom.
     *
     * 3mm at the head, down from 5mm, because the shop still read the top
     * as loose after the animation offset was found and removed. That is
     * about as far as it goes: a dot matrix loses the first millimetre or
     * two to where the head parks, so a document set flush to the edge
     * loses the top of its own letters. There is room to spend — the fixed
     * blocks use 667px of a 1011px form, the item grid absorbing the rest —
     * so this is a choice about how it looks, not a fight for space.
     */
    body.printing-taxinv .taxinv-sheet,
    body.printing-cashreceipt .receipt-sheet {
        box-sizing: border-box !important;
        min-height: 11in !important;
        padding: 3mm 10mm 7mm !important;
    }

    body.printing-taxinv .printable-taxinv-area tr {
        page-break-inside: avoid;
    }

    body.printing-taxinv .printable-taxinv-area {
        position: static !important;
        width: 100%;
        padding: 0;
        margin: 0;
        font-size: 10pt !important;
        line-height: 1.35 !important;
        page-break-inside: avoid !important;
        overflow: visible;
    }

    /* Subscription receipt / tax invoice — same mechanism as the invoice
       above: lift the one modal out of the overlay and let only its
       printable area become visible. */
    body.printing-receipt #modal-subscription-receipt,
    body.printing-receipt #modal-subscription-receipt .modal-content {
        position: static !important;
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        height: auto !important;
        overflow: visible !important;
        background: transparent !important;
        box-shadow: none !important;
        border: none !important;
        transform: none !important;
        padding: 0 !important;
        margin: 0 !important;
    }

    body.printing-receipt #modal-subscription-receipt .modal-header,
    body.printing-receipt #modal-subscription-receipt .modal-footer {
        display: none !important;
    }

    body.printing-receipt .printable-receipt-area,
    body.printing-receipt .printable-receipt-area * {
        visibility: visible;
    }

    body.printing-receipt .printable-receipt-area {
        position: static !important;
        width: 100%;
        padding: 0;
        margin: 0;
        font-size: 10pt !important;
        line-height: 1.35 !important;
        page-break-inside: avoid !important;
        overflow: visible;
    }
    
    /* Active printing of invoice */
    body.printing-invoice #modal-invoice-detail,
    body.printing-invoice #modal-invoice-detail .modal-content {
        position: static !important;
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        height: auto !important;
        overflow: visible !important;
        background: transparent !important;
        box-shadow: none !important;
        border: none !important;
        transform: none !important;
        padding: 0 !important;
        margin: 0 !important;
    }

    body.printing-invoice .printable-invoice-area,
    body.printing-invoice .printable-invoice-area * {
        visibility: visible;
    }

    /* Dot-matrix / continuous-form printers print by striking pins through
       a ribbon. At these small point sizes (8-9.5pt), a normal-weight
       stroke lays down too few pins to stay dark — no printer "darkness"
       setting fixes that, because the driver never sees a lighter line to
       darken, only a thinner one to strike. Bold hits more pins per glyph
       and comes through reliably regardless of ribbon wear. This is why
       the invoice table's header row (already font-weight: bold below)
       printed clearly while every other line did not — now the whole
       document gets the same treatment. */
    body.printing-invoice .printable-invoice-area,
    body.printing-invoice .printable-invoice-area * {
        font-weight: 700 !important;
    }

    body.printing-invoice .printable-invoice-area {
        position: static !important;
        width: 100%;
        /**
         * The inset this document prints with, which used to come from the
         * page margin. That margin is zero now so the document supplies it
         * itself.
         *
         * 6mm at the head, 10mm everywhere else. The shop asked for the
         * head only — there was more paper above the business name than the
         * document needed and none of the other three edges were wrong. The
         * 4mm comes off the padding, not off the 270mm height, so the sheet
         * occupies exactly what it did and still clears the form.
         *
         * `!important` is doing real work here and must not be dropped.
         * This element IS the dialog's .modal-body, and further down that
         * class is zeroed with `padding: 0 !important` to strip the frame
         * off every printed document. An important declaration beats a
         * non-important one whatever the specificity, so the first attempt
         * at this rule — the same 10mm without the keyword — lost silently
         * and the bill printed hard against the paper edge. It looked like
         * the padding was ignored because it was.
         */
        box-sizing: border-box;
        padding: 6mm 10mm 10mm !important;
        margin: 0;
        font-size: 9.5pt !important;
        line-height: 1.25 !important;
        page-break-inside: avoid !important;
        max-height: 100%;
        overflow: visible;

        display: flex !important;
        flex-direction: column !important;
        /**
         * 270mm — the figure this document printed at before the 9 x 11
         * work, restored.
         *
         * It was changed to a flat 11in on the reasoning that the sheet IS
         * the form now that the page carries no margin. That is true of the
         * space available and false of the space usable: at exactly the
         * page height there is no room left for the rounding the browser
         * does while scaling the page, and every bill came out on two
         * sheets with the second one blank. On continuous stationery that
         * is a wasted form per customer.
         *
         * 270mm against a 279.4mm form leaves 9.4mm of slack, which is what
         * the old A4 layout had (270mm inside 281mm of usable page) and why
         * it never did this.
         */
        height: 270mm !important;
        box-sizing: border-box !important;
    }

    body.printing-invoice h2 {
        font-size: 14pt !important;
    }
    body.printing-invoice h3 {
        font-size: 12pt !important;
    }
    body.printing-invoice h4 {
        font-size: 10pt !important;
    }
    body.printing-invoice p {
        margin: 1px 0 !important;
        font-size: 9.5pt !important;
    }
    
    body.printing-invoice .invoice-header {
        margin-bottom: 2px !important;
        align-items: flex-start !important;
    }
    body.printing-invoice #bill-logo-img {
        max-height: 95px !important;
        max-width: 250px !important;
    }
    body.printing-invoice .invoice-header h2 {
        font-size: 14pt !important;
    }
    body.printing-invoice .invoice-divider {
        margin: 4px 0 !important;
        border-top: 1px solid #000000 !important;
    }
    body.printing-invoice .invoice-subheader {
        margin-bottom: 6px !important;
    }
    body.printing-invoice .invoice-table {
        margin: 4px 0 !important;
    }
    body.printing-invoice .invoice-table th {
        padding: 4px 6px !important;
        font-size: 9.5pt !important;
        border-top: 1.5px solid #000000 !important;
        border-bottom: 1.5px solid #000000 !important;
        font-weight: bold !important;
    }
    body.printing-invoice .invoice-table td {
        padding: 3px 6px !important;
        font-size: 9pt !important;
        border-bottom: 1px solid #cccccc !important;
    }
    body.printing-invoice .invoice-summary-section {
        margin-top: auto !important; /* Push summary, terms, and signatures to the very bottom */
        margin-bottom: 6px !important;
        gap: 16px !important;
    }
    body.printing-invoice .bill-remarks-box {
        padding: 6px !important;
        font-size: 9pt !important;
        border: 1px solid #999999 !important;
    }
    body.printing-invoice #bill-qrcode-container {
        margin-top: 6px !important;
        padding-top: 4px !important;
        gap: 8px !important;
        border-top: 1px dashed #999999 !important;
    }
    body.printing-invoice #bill-qrcode-box {
        width: 65px !important;
        height: 65px !important;
        border: 1px solid #000000 !important;
        padding: 1px !important;
    }
    /**
     * The QR caption, which tells the customer what the code is for.
     *
     * Was 8pt/7pt with the explanation in grey — the smallest and faintest
     * text on the bill, on a document printed by dot matrix onto carbon.
     * Nobody was reading it on the second copy, which makes the QR beside
     * it useless to the person holding that copy.
     *
     * Its grey also survived the blanket "everything black" rule: this
     * selector carries !important AND more specificity, so it won. Worth
     * remembering — a blanket rule only sweeps up declarations that are not
     * already shouting.
     */
    body.printing-invoice #bill-qrcode-container strong {
        font-size: 10pt !important;
        color: #000000 !important;
    }
    body.printing-invoice #bill-qrcode-container span {
        font-size: 9pt !important;
        color: #000000 !important;
    }
    /**
     * The change-due / still-owed figure, in black on paper.
     *
     * Green for a refund and red for a debt is worth having on screen. On
     * the printed bill it is the single most important number and it was
     * coming out mid-tone — the shop's carbon copy got it faintest of all.
     *
     * Named with all three state classes because those carry !important in
     * the base stylesheet and outrank the blanket rule further up; this has
     * to beat them on specificity, not just repeat the instruction. The
     * background tint is left alone, as asked.
     */
    body.printing-invoice .net-balance-amount,
    body.printing-invoice .net-balance-amount.owe,
    body.printing-invoice .net-balance-amount.refund,
    body.printing-invoice .net-balance-amount.even {
        color: #000000 !important;
    }

    body.printing-invoice .bill-totals {
        gap: 2px !important;
        min-width: 220px !important;
    }
    body.printing-invoice .bill-totals .total-row {
        padding: 1px 0 !important;
        font-size: 9.5pt !important;
    }
    body.printing-invoice .bill-totals .total-row.grand {
        font-size: 10.5pt !important;
        font-weight: bold !important;
    }
    body.printing-invoice .bill-totals .total-row.grand strong {
        font-size: 11.5pt !important;
    }
    body.printing-invoice .bill-totals hr {
        margin: 2px 0 !important;
        border-top: 1px solid #000000 !important;
    }
    body.printing-invoice .invoice-terms {
        margin-bottom: 6px !important;
        padding: 4px 8px !important;
        font-size: 8pt !important;
        border: 1px solid #999999 !important;
        line-height: 1.25 !important;
    }
    body.printing-invoice .invoice-terms h4 {
        margin-bottom: 2px !important;
        font-size: 9pt !important;
    }
    body.printing-invoice .invoice-signatures {
        margin-top: 16px !important;
    }
    body.printing-invoice .signature-box {
        width: 180px !important;
        font-size: 9pt !important;
    }
    body.printing-invoice .signature-box p:first-child {
        margin-bottom: 16px !important;
    }
    
    /* Active printing of daily report */
    body.printing-report #printable-report-card,
    body.printing-report #printable-report-card * {
        visibility: visible;
    }
    
    body.printing-report #printable-report-card {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        padding: 0;
        margin: 0;
        border: none !important;
        box-shadow: none !important;
        background: #ffffff !important;
    }
    body.printing-report .report-header {
        padding: 12px 0 !important;
        border-bottom: 2px solid #000000 !important;
    }
    body.printing-report .report-summary-grid {
        margin-bottom: 16px !important;
        gap: 12px !important;
    }
    body.printing-report .r-summary-card {
        border: 1px solid #000000 !important;
        padding: 10px !important;
        background: #ffffff !important;
    }
    body.printing-report .table th,
    body.printing-report .table td {
        border-color: #000000 !important;
        padding: 6px 8px !important;
    }
    
    /* Active printing of net revenue report */
    body.printing-net-revenue #printable-net-revenue-card,
    body.printing-net-revenue #printable-net-revenue-card * {
        visibility: visible;
    }
    body.printing-net-revenue #printable-net-revenue-card {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        padding: 0;
        margin: 0;
        border: none !important;
        box-shadow: none !important;
        background: #ffffff !important;
    }
    body.printing-net-revenue .report-header {
        padding: 12px 0 !important;
        border-bottom: 2px solid #000000 !important;
    }
    body.printing-net-revenue .report-summary-grid {
        margin-bottom: 16px !important;
        gap: 12px !important;
    }
    body.printing-net-revenue .r-summary-card {
        border: 1px solid #000000 !important;
        padding: 10px !important;
        background: #ffffff !important;
    }
    body.printing-net-revenue .table th,
    body.printing-net-revenue .table td {
        border-color: #000000 !important;
        padding: 6px 8px !important;
    }
    
    /* Hide modal frames and scrollbars during print */
    .modal {
        background: none !important;
        position: absolute !important;
        overflow: visible !important;
        display: none !important;
    }
    body.printing-invoice #modal-invoice-detail {
        display: block !important;
    }
    .modal-content {
        box-shadow: none !important;
        border: none !important;
        overflow: visible !important;
        width: 100% !important;
        max-width: 100% !important;
        /**
         * The open animation must not reach the paper.
         *
         * .modal-content carries `transform: translateY(16px)` as the start
         * of its entry animation, and it was still applied at print time —
         * so every document printed 16px (4.2mm) further down the form than
         * its own padding said, with nothing in the box model to show for
         * it. That is the unexplained gap above the tax invoice's header
         * that survived three wrong theories; it was never a margin.
         *
         * Cleared here, on the shared selector, so it cannot come back for
         * a document that adds its own print block later and forgets. The
         * per-document rules above say the same thing and are now
         * belt-and-braces rather than the only defence.
         */
        transform: none !important;
    }
    .hide-on-print {
        display: none !important;
    }
    .modal-body {
        overflow: visible !important;
        padding: 0 !important;
    }
    
    /* Force high contrast colors */
    .total-row.grand strong {
        color: #000000 !important;
    }
    .biz-logo {
        color: #000000 !important;
    }
    .bill-meta h3 {
        color: #000000 !important;
    }

    /* Active printing of catalog */
    body.printing-catalog #printable-catalog-area,
    body.printing-catalog #printable-catalog-area * {
        visibility: visible;
    }
    body.printing-catalog #printable-catalog-area {
        display: block !important;
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        /**
         * 10mm all round, the same inset the bill and the slips carry.
         *
         * This was zero, which was invisible while the page supplied its own
         * margin and became the whole problem when the documents took their
         * margins over: the leaflet printed hard against all four paper
         * edges, with the product names starting in the unprintable strip
         * some printers keep at the side. Missed at the time because the
         * catalogue is reached from a different menu and nobody printed one
         * while the margins were being moved.
         */
        box-sizing: border-box;
        padding: 10mm;
        margin: 0;
        background: #ffffff !important;
        color: #000000 !important;
        overflow: visible;
    }
    /* Shop's own name, left, and large. On a leaflet the prices say what it
       costs and this says who to ring, so it is not small print. The logo
       and the "HJ RENTAL" wordmark that used to sit opposite are gone. */
    .catalog-header {
        margin-bottom: 6px;
    }
    .catalog-shop-info {
        text-align: left;
    }
    .catalog-shop-info h2 {
        font-size: 20pt;
        margin: 0 0 3px 0;
        line-height: 1.15;
    }
    .catalog-shop-info p {
        font-size: 11pt;
        margin: 2px 0;
    }
    .catalog-divider {
        border-top: 1.5px solid #000000;
        margin: 4px 0;
    }
    .catalog-title-banner {
        text-align: center;
        margin: 4px 0;
    }
    .catalog-title-banner h2 {
        font-size: 12pt;
        font-weight: bold;
        margin: 0 0 2px 0;
    }
    .catalog-title-banner p {
        font-size: 8pt;
        margin: 0;
    }
    /**
     * Each category is a three-across grid, filling the full page width,
     * and the next one starts immediately under the last.
     *
     * A previous attempt flowed the whole leaflet down three newspaper
     * columns, which packs perfectly on screen and falls apart on paper:
     * Chromium's paged multi-column put one narrow column on each sheet, so
     * a leaflet that should have been one page came out three, each with
     * two thirds of it blank. Multi-column and paged media do not get on;
     * a grid per category does.
     *
     * What is deliberately NOT here is `page-break-inside: avoid` on the
     * section. That was what left the gaps: a category that did not fit in
     * the remaining space was thrown whole onto the next sheet, and the
     * space it left behind stayed empty. A long category now simply runs to
     * the foot of the page and continues at the top of the next, which is
     * what the paper is for.
     */
    .catalog-container {
        width: 100%;
    }
    .catalog-category-section {
        /* Tight to the one above. The heading's own rule does the
           separating, so no margin is needed to say a new category began. */
        margin: 0 0 3px;
    }
    .catalog-category-title {
        font-size: 9.5pt;
        font-weight: bold;
        color: #000000;
        margin: 0 0 3px 0;
        border-bottom: 1.5px solid #000000;
        padding-bottom: 2px;
        text-align: left;
        /* A heading alone at the foot of a page helps nobody — it goes over
           with its items. The items themselves may split freely. */
        break-after: avoid;
        page-break-after: avoid;
    }
    .catalog-grid {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        column-gap: 18px;
        row-gap: 0;
        margin: 0 0 4px;
        width: 100%;
    }
    /* 9.5pt, up from 8.5. This is a leaflet a builder reads standing on a
       site, not a spreadsheet — and packing the categories tight bought the
       room to set it larger without costing a sheet. A single line still
       never splits across a page. */
    .catalog-item-compact {
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-bottom: 1px dashed #cccccc;
        padding: 3px 0;
        font-size: 9.5pt;
        page-break-inside: avoid !important;
        box-sizing: border-box;
    }
    .catalog-item-name-compact {
        font-weight: 500;
        color: #000000;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        padding-right: 6px;
    }
    .catalog-item-price-compact {
        font-weight: bold;
        color: #000000 !important;
        flex-shrink: 0;
    }
    .catalog-footer {
        margin-top: 8px;
        page-break-inside: avoid;
    }
    .catalog-terms-box {
        padding: 6px;
        font-size: 7.5pt;
        border: 1px solid #000000;
        line-height: 1.3;
        background: #fbfbfb;
    }

    /* Print Slip Styles */
    body.printing-slip .app-container,
    body.printing-slip .modal,
    body.printing-slip .sidebar-overlay {
        display: none !important;
    }
    
    body.printing-slip #printable-slip-area,
    body.printing-slip #printable-slip-area * {
        visibility: visible !important;
    }

    /* Same continuous-form dot-matrix printer as the invoice above — see
       the note there. Normal weight prints too faint to read regardless of
       the printer's own darkness setting; bold hits enough pins to come
       through reliably. */
    body.printing-slip #printable-slip-area,
    body.printing-slip #printable-slip-area * {
        font-weight: 700 !important;
    }

    body.printing-slip #printable-slip-area {
        display: flex !important;
        flex-direction: column !important;
        /* The page carries no margin of its own any more, so the slip
           supplies all of it — the same 10mm inset it has always printed
           with, and the same 270mm height as the bill above, which leaves
           the form the slack it needs to stay on one sheet. See the note
           there; this had the identical two-sheet fault. */
        height: 270mm !important;
        box-sizing: border-box !important;
        position: absolute !important;
        left: 0 !important;
        top: 0 !important;
        width: 100% !important;
        padding: 10mm !important;
        margin: 0 !important;
        background: #ffffff !important;
        color: #000000 !important;
    }
    body.printing-slip #slip-signatures {
        margin-top: auto !important;
    }

    /* Active printing of barcode sheet */
    body.printing-barcodes .app-container,
    body.printing-barcodes .modal,
    body.printing-barcodes .sidebar-overlay,
    body.printing-barcodes #printable-slip-area {
        display: none !important;
    }
    body.printing-barcodes #printable-barcode-area,
    body.printing-barcodes #printable-barcode-area * {
        visibility: visible !important;
    }
    body.printing-barcodes #printable-barcode-area {
        display: block !important;
        position: absolute !important;
        left: 0 !important;
        top: 0 !important;
        width: 100% !important;
        padding: 0 !important;
        margin: 0 !important;
        background: #ffffff !important;
        color: #000000 !important;
    }
}

/* Barcode Printable Sheet Grid */
.barcode-print-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    padding: 15px;
    background: #ffffff;
}
.barcode-print-card {
    border: 1px dashed #aaaaaa;
    border-radius: 4px;
    padding: 8px;
    text-align: center;
    background: #ffffff;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    page-break-inside: avoid;
    height: 38mm; /* standard size */
}
.barcode-print-card .shop-name {
    font-size: 7pt;
    margin-bottom: 2px;
    text-transform: uppercase;
    font-weight: 500;
}
.barcode-print-card .prod-name {
    font-size: 8.5pt;
    font-weight: bold;
    color: #000000;
    margin-bottom: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 100%;
}
.barcode-print-card svg {
    max-width: 95%;
    max-height: 20mm;
}
.barcode-print-card .prod-price {
    font-size: 7.5pt;
    font-weight: 600;
    color: #333333;
    margin-top: 3px;
}

/* Searchable Dropdown */
.searchable-select-wrapper { position: relative; }
.searchable-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--bg-card);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-top: none;
    border-radius: 0 0 var(--radius-md) var(--radius-md);
    max-height: 220px;
    overflow-y: auto;
    z-index: 500;
    box-shadow: var(--shadow-md);
}
.searchable-dropdown .dropdown-item {
    padding: 10px 14px;
    cursor: pointer;
    font-size: 0.875rem;
    border-bottom: 1px solid var(--bg-body);
    transition: background 0.15s;
}
.searchable-dropdown .dropdown-item:hover, .searchable-dropdown .dropdown-item.active {
    background: var(--primary-light);
    color: var(--primary-color);
}
.searchable-dropdown .dropdown-item.no-results {
    color: var(--text-light);
    cursor: default;
}

/* Logo & Product Image Upload Areas */
.logo-upload-area, .product-img-upload-area {
    border: 2px dashed var(--border-color);
    border-radius: var(--radius-md);
    padding: 16px;
    text-align: center;
    cursor: pointer;
    background: var(--bg-body);
    min-height: 80px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color 0.2s;
}
.logo-upload-area:hover, .product-img-upload-area:hover {
    border-color: var(--primary-color);
}
.logo-upload-area span, .product-img-upload-area span {
    font-size: 0.8rem;
    color: var(--text-muted);
    display: block;
    margin-top: 4px;
}
.logo-upload-area i, .product-img-upload-area i {
    color: var(--text-light);
    width: 24px;
    height: 24px;
}

/* Net Balance Amount in Invoice */
.net-balance-amount {
    font-size: 1.35rem !important;
    padding: 6px 12px;
    border-radius: var(--radius-sm);
}
.net-balance-amount.owe { color: var(--danger-color) !important; background: var(--danger-light); }
.net-balance-amount.refund { color: var(--success-color) !important; background: var(--success-light); }
.net-balance-amount.even { color: var(--text-main) !important; }

/* Product card image */
/* Product photos were removed at the shop's request (they were stored as
   base64 in the row and dominated every backup). This header replaces the
   140px image strip: a slim coloured band carrying the product code and
   its stock state, so a wall of cards is still scannable at a glance
   without a single picture. */
.product-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 14px;
    background: linear-gradient(135deg, var(--primary-color), #4338ca);
    color: #fff;
}
.product-card-head.low {
    background: linear-gradient(135deg, #dc2626, #b91c1c);
}
.product-card-code {
    font-weight: 800;
    font-size: 0.9rem;
    letter-spacing: 0.4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The whole card opens the product's rental history, so it has to look
   pressable — otherwise nobody discovers the feature exists. */
.product-card.is-clickable {
    cursor: pointer;
}
.product-card.is-clickable:hover {
    border-color: var(--primary-color);
}

/* ---- Product rental-history modal ---- */
.prod-hist-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 1px;
    background: var(--border-color);
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 18px;
}
.prod-hist-stat {
    background: var(--bg-card);
    padding: 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.prod-hist-stat span {
    font-size: 0.72rem;
    color: var(--text-muted);
}
.prod-hist-stat strong {
    font-size: 0.95rem;
}
.prod-hist-heading {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.9rem;
    font-weight: 700;
    color: var(--text-main);
    margin: 0 0 10px 0;
}
.prod-hist-active-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    margin-bottom: 8px;
    border-radius: var(--radius-sm);
    background: rgba(234, 179, 8, 0.08);
    border-left: 3px solid var(--warning-color);
}
.prod-hist-active-row.overdue {
    background: rgba(220, 38, 38, 0.07);
    border-left-color: var(--danger-color);
}
/* A vertical rail down the timeline, so rentals and returns read as one
   sequence rather than a stack of unrelated rows. */
.prod-hist-event {
    display: flex;
    gap: 12px;
    padding: 9px 0 9px 4px;
    border-left: 2px solid var(--border-color);
    margin-left: 5px;
    padding-left: 16px;
    position: relative;
}
.prod-hist-dot {
    position: absolute;
    left: -6px;
    top: 14px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    border: 2px solid var(--bg-card);
}
.prod-hist-dot.rent { background: var(--warning-color); }
.prod-hist-dot.ret { background: var(--success-color); }

.product-card-status {
    flex-shrink: 0;
    font-size: 0.72rem;
    font-weight: 700;
    padding: 2px 9px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.22);
    white-space: nowrap;
}

/* Delete product button danger outline */
.btn-outline-danger {
    background: transparent;
    border: 1px solid var(--danger-color);
    color: var(--danger-color);
}
.btn-outline-danger:hover {
    background: var(--danger-color);
    color: #ffffff;
}

/* --- RESPONSIVE MOBILE STYLES --- */
@media (max-width: 992px) {
    #btn-toggle-sidebar {
        display: flex !important;
    }
    
    .sidebar {
        transform: translateX(-100%);
        transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        z-index: 10000;
        box-shadow: var(--shadow-lg);
    }
    
    .sidebar.open {
        transform: translateX(0);
    }
    
    /* Overlay background when sidebar is open */
    .sidebar-overlay {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0,0,0,0.4);
        z-index: 9999;
        display: none;
    }
    .sidebar-overlay.active {
        display: block;
    }
    
    .main-content {
        margin-left: 0;
        width: 100%;
    }
    
    .top-header {
        padding: 16px 20px;
    }
    
    .form-grid {
        grid-template-columns: 1fr;
    }
    
    .preview-card {
        position: static;
        margin-top: 24px;
    }
}

@media (max-width: 768px) {
    .stats-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    
    .report-summary-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    
    .report-lists-grid {
        grid-template-columns: 1fr;
    }
    
    .form-row {
        flex-direction: column;
        gap: 12px;
    }
    
    .form-row > [class*="col-"] {
        width: 100% !important;
        flex: none !important;
    }

    /* Stack search and filters on tablet/mobile & make inputs larger */
    .view-header-bar {
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
    }
    
    .search-filter-group {
        flex-direction: column;
        align-items: stretch;
        max-width: 100%;
        gap: 10px;
    }

    .search-box input {
        padding: 12px 42px 12px 16px !important;
        font-size: 1rem !important;
    }

    .search-box i, .search-box svg {
        width: 20px;
        height: 20px;
        right: 14px;
        left: auto;
    }

    .form-control,
    .searchable-select-wrapper input {
        font-size: 1rem !important;
        padding: 10px 14px !important;
    }

    .search-filter-group select {
        font-size: 1rem !important;
        padding: 10px 14px !important;
        width: 100% !important;
        flex: none !important;
    }

    /* Still sized to the date, just allowing for the larger mobile font
       rather than stretching to the full column width. */
    .report-date-input {
        width: 160px !important;
        flex: none !important;
    }
}

@media (max-width: 576px) {
    .stats-grid {
        grid-template-columns: 1fr;
    }
    
    .report-summary-grid {
        grid-template-columns: 1fr;
    }
}

/* Sync Status Indicator */
.sync-indicator {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.85rem;
    margin-right: 16px;
    color: var(--text-muted);
    background: var(--bg-card);
    padding: 6px 12px;
    border-radius: 9999px;
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-sm);
    transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.sync-indicator:hover {
    background-color: var(--bg-body);
    border-color: var(--text-light);
}

.sync-indicator .dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: #94a3b8;
    transition: background-color 0.3s, box-shadow 0.3s;
}

.sync-indicator .dot.syncing {
    background-color: #3b82f6;
    animation: sync-pulse 1s infinite alternate;
}

.sync-indicator .dot.success {
    background-color: #10b981;
    box-shadow: 0 0 8px rgba(16, 185, 129, 0.6);
}

.sync-indicator .dot.error {
    background-color: #ef4444;
    box-shadow: 0 0 8px rgba(239, 68, 68, 0.6);
}

@keyframes sync-pulse {
    from {
        transform: scale(0.8);
        opacity: 0.5;
        box-shadow: 0 0 0 rgba(59, 130, 246, 0.2);
    }
    to {
        transform: scale(1.2);
        opacity: 1;
        box-shadow: 0 0 8px rgba(59, 130, 246, 0.6);
    }
}

/* ==========================================================================
   Dark Mode variables
   ========================================================================== */
[data-theme="dark"] {
    --bg-body: #0f172a;             /* Slate 900 */
    --bg-card: #1e293b;             /* Slate 800 */
    --border-color: #334155;        /* Slate 700 */
    --text-main: #f8fafc;           /* Slate 50 */
    --text-muted: #94a3b8;          /* Slate 400 */
    --text-light: #475569;          /* Slate 600 */
    
    --primary-light: rgba(79, 70, 229, 0.15);
    --accent-light: rgba(13, 148, 136, 0.15);
    --success-light: rgba(16, 185, 129, 0.15);
    --danger-light: rgba(239, 68, 68, 0.15);
    --warning-light: rgba(245, 158, 11, 0.15);
    
    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -2px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -4px rgba(0, 0, 0, 0.5);
}

/* Apply Dark Mode background dot pattern override */
[data-theme="dark"] body {
    background-image: 
        radial-gradient(rgba(148, 163, 184, 0.05) 1.5px, transparent 1.5px);
}

/* Dark mode custom adjustments for charts, prints & date inputs */
[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator {
    filter: invert(1);
}

[data-theme="dark"] .btn-secondary {
    background-color: var(--bg-card);
    border-color: var(--border-color);
    color: var(--text-muted);
}
[data-theme="dark"] .btn-secondary:hover {
    background-color: var(--bg-body);
    color: var(--text-main);
}

[data-theme="dark"] .table tbody tr:hover {
    background-color: rgba(255, 255, 255, 0.05);
}

[data-theme="dark"] .searchable-dropdown .dropdown-item:hover,
[data-theme="dark"] .searchable-dropdown .dropdown-item.active {
    background-color: var(--primary-color);
    color: #ffffff;
}

/* Brand Logo Image Styles */
.brand-logo-img {
    transition: transform var(--transition-fast);
}
.brand-logo-img:hover {
    transform: scale(1.03);
}
[data-theme="dark"] .brand-logo-img img {
    filter: invert(1);
    mix-blend-mode: screen;
}

/* Excel Upload Zone */
.excel-upload-zone {
    border: 2px dashed var(--border-color);
    border-radius: var(--radius-md);
    padding: 30px;
    text-align: center;
    cursor: pointer;
    background: var(--bg-body);
    transition: all 0.2s;
    margin-bottom: 20px;
}
.excel-upload-zone:hover, .excel-upload-zone.dragover {
    border-color: var(--primary-color);
    background: var(--primary-light);
}

/* Import Preview Status & Row Colors */
.import-row-valid {
    color: var(--success-color);
    font-weight: 500;
}
.import-row-invalid {
    color: var(--danger-color);
    font-weight: 500;
}
.import-row-error-line {
    background-color: var(--danger-light) !important;
}

/* Sidebar Sync Indicator */
.sidebar-sync-indicator {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.75rem;
    margin-top: 6px;
    color: var(--text-light);
    cursor: pointer;
    transition: color 0.2s;
}

.sidebar-sync-indicator:hover {
    color: var(--text-main);
}

.sidebar-sync-indicator .dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: #94a3b8;
    display: inline-block;
    transition: background-color 0.3s, box-shadow 0.3s;
}

.sidebar-sync-indicator .dot.syncing {
    background-color: #3b82f6;
    animation: sync-pulse-mini 1s infinite alternate;
}

.sidebar-sync-indicator .dot.success {
    background-color: #10b981;
    box-shadow: 0 0 6px rgba(16, 185, 129, 0.4);
}

.sidebar-sync-indicator .dot.error {
    background-color: #ef4444;
    box-shadow: 0 0 6px rgba(239, 68, 68, 0.4);
}

@keyframes sync-pulse-mini {
    from {
        transform: scale(0.9);
        opacity: 0.6;
    }
    to {
        transform: scale(1.1);
        opacity: 1;
    }
}

/* ==========================================================================
   Welcome Greeting Modal Styles
   ========================================================================== */

.welcome-modal-content {
    background: rgba(255, 255, 255, 0.75) !important;
    backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    box-shadow: 0 20px 40px rgba(15, 23, 42, 0.15) !important;
}

[data-theme="dark"] .welcome-modal-content {
    background: rgba(30, 41, 59, 0.75) !important; /* Slate 800 */
    border: 1px solid rgba(255, 255, 255, 0.08) !important;
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4) !important;
}

.welcome-decor-1 {
    position: absolute;
    top: -40px;
    right: -40px;
    width: 120px;
    height: 120px;
    background: radial-gradient(circle, rgba(79, 70, 229, 0.12) 0%, rgba(255, 255, 255, 0) 70%);
    z-index: 1;
    pointer-events: none;
}

.welcome-decor-2 {
    position: absolute;
    bottom: -40px;
    left: -40px;
    width: 120px;
    height: 120px;
    background: radial-gradient(circle, rgba(13, 148, 136, 0.12) 0%, rgba(255, 255, 255, 0) 70%);
    z-index: 1;
    pointer-events: none;
}

[data-theme="dark"] .welcome-decor-1 {
    background: radial-gradient(circle, rgba(99, 102, 241, 0.15) 0%, rgba(0, 0, 0, 0) 70%);
}

[data-theme="dark"] .welcome-decor-2 {
    background: radial-gradient(circle, rgba(20, 184, 166, 0.15) 0%, rgba(0, 0, 0, 0) 70%);
}

.welcome-icon-wrapper {
    width: 80px;
    height: 80px;
    margin: 0 auto 24px auto;
    background: linear-gradient(135deg, var(--primary-color), var(--accent-color));
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 10px 25px rgba(79, 70, 229, 0.25);
    animation: welcomePulse 2s infinite alternate;
}

.welcome-icon-wrapper i {
    width: 36px;
    height: 36px;
    color: #ffffff;
}

.welcome-title {
    font-size: 1.8rem;
    font-weight: 700;
    margin-bottom: 12px;
    background: linear-gradient(135deg, var(--text-main), var(--primary-color));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    letter-spacing: -0.5px;
}

[data-theme="dark"] .welcome-title {
    background: linear-gradient(135deg, #ffffff, #a5b4fc);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.welcome-message {
    font-size: 1.1rem;
    color: var(--text-muted);
    margin-bottom: 32px;
    line-height: 1.6;
    font-weight: 400;
}

[data-theme="dark"] .welcome-message {
    color: var(--text-light);
}

/* The shop's own name on its first-run celebration. Sits between the title
   and the message, so it reads as "ยินดีต้อนรับ! / <ร้าน> / เริ่มใช้งานวันแรก". */
.welcome-shop-name {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--primary-color);
    margin: -8px 0 10px;
    line-height: 1.4;
    word-break: break-word;
}

[data-theme="dark"] .welcome-shop-name {
    color: #a5b4fc;
}

/**
 * The way into the warehouse screen.
 *
 * Gated by a body class rather than an inline style because permissions.js
 * rewrites `display` on every [data-requires-permission] element and sets
 * it to '' for anyone holding the right — an owner holds every right, so an
 * inline hide was being switched straight back on with the module off.
 * Two independent gates now compose properly: this rule answers "does this
 * deployment run a warehouse", permissions.js answers "may this person work
 * it", and either one hides the link.
 */
body:not(.warehouse-enabled) #nav-warehouse {
    display: none !important;
}

/* Everything else that only means something to a shop running a warehouse
   department — currently the front counter's "แจ้งคลัง" sub-tab, which
   announces a return to a yard a shop without the module does not have. */
body:not(.warehouse-enabled) .wh-only {
    display: none !important;
}

/* ============================================================
   OUTSTANDING-MONEY ALERTS (alerts.js)

   A bell in the header with a count on it. Everything it lists was
   already recorded somewhere the counter had to go and look for; this
   is the same money, where they cannot miss it.
   ============================================================ */

/* Sits on the corner of the bell, like a phone. Deliberately allowed to
   overhang the button — a badge tucked inside reads as part of the icon
   and stops being an interruption, which is the whole job. */
#alerts-count {
    position: absolute;
    top: -5px;
    right: -5px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--danger-color, #dc2626);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 18px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--bg-card, #fff);
    pointer-events: none;
}

#alerts-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: min(380px, calc(100vw - 32px));
    max-height: min(70vh, 520px);
    overflow-y: auto;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: var(--radius-md, 10px);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.16);
    z-index: 1200;
}

#alerts-panel .alerts-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border-color, #e5e7eb);
    position: sticky;
    top: 0;
    background: var(--bg-card, #fff);
}
#alerts-panel .alerts-head strong { flex: 1; font-size: 0.92rem; }
#alerts-panel .alerts-total {
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--danger-color, #dc2626);
    font-variant-numeric: tabular-nums;
}

/* One row per bill. A whole row is the target, not a link inside it —
   this is used in a hurry with a customer at the counter. */
.alert-row {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    width: 100%;
    padding: 11px 14px;
    border-bottom: 1px solid var(--border-color, #e5e7eb);
    background: none;
    border-left: none;
    border-right: none;
    border-top: none;
    text-align: left;
    cursor: pointer;
    font: inherit;
    color: inherit;
}
.alert-row:hover { background: var(--bg-body, #f8fafc); }
.alert-row:last-child { border-bottom: none; }
.alert-row .alert-icon { flex: 0 0 auto; font-size: 1rem; line-height: 1.35; }
.alert-row .alert-main { flex: 1; min-width: 0; }
.alert-row .alert-bill { font-weight: 700; font-size: 0.88rem; }
.alert-row .alert-why { font-size: 0.78rem; color: var(--text-muted, #64748b); margin-top: 2px; }
.alert-row .alert-amount {
    flex: 0 0 auto;
    font-weight: 700;
    font-size: 0.88rem;
    color: var(--danger-color, #dc2626);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.alerts-empty {
    padding: 28px 14px;
    text-align: center;
    color: var(--text-muted, #64748b);
    font-size: 0.9rem;
}

/* ============================================================
   SEASONAL DECORATION (festive.js)

   Built and removed entirely from JS; none of this exists in the DOM
   outside a festival window. Everything is pointer-events:none and lives
   below the modal layer (z-index 200), so it can decorate the screen
   without ever intercepting a click or covering a dialog.
   ============================================================ */

/* Drawn from the body attribute rather than appended to the title, because
   the view switcher rewrites that title's text on every menu change and
   took an appended element with it. A pseudo-element survives that. */
body[data-festival] #current-view-title::after {
    display: inline-block;
    margin-left: 10px;
    font-size: 1.1em;
    line-height: 1;
    vertical-align: -2px;
    /* A gentle sway rather than anything that pulls the eye off the title
       the ornament is attached to. */
    animation: festiveSway 3.6s ease-in-out infinite;
}

body[data-festival="christmas"] #current-view-title::after { content: "🎄"; }
body[data-festival="newyear"]   #current-view-title::after { content: "🎉"; }
body[data-festival="songkran"]  #current-view-title::after { content: "💦"; }

@keyframes festiveSway {
    0%, 100% { transform: rotate(-7deg); }
    50%      { transform: rotate(7deg); }
}

#festive-layer {
    position: fixed;
    inset: 0;
    z-index: 90;
    pointer-events: none;
    overflow: hidden;
}

/* Lives in the spare middle of the top header, in NORMAL FLOW — layout
   reserves its space, so it cannot cover a control at any window size.
   Measured alternatives that failed: floated bottom-left covered the
   ปฏิทิน/ตั้งค่า menu labels, bottom-right belongs to the calculator, and
   the sidebar footer had no room to give (it forced the nav to scroll). */
.festive-corner {
    flex: 0 0 auto;
    margin: 0 auto;
    font-size: 40px;
    line-height: 1;
    text-align: center;
    opacity: 0.9;
    filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.16));
    animation: festiveSway 5.5s ease-in-out infinite;
}

/* The header's spare width disappears on smaller screens, where the title
   and the action buttons need all of it. The header ornament beside the
   page title carries the season on its own there. */
@media (max-width: 1150px) {
    .festive-corner { display: none; }
}

/* The drifting bits. transform + opacity only, so this stays on the
   compositor and off the main thread for the days it runs. */
.festive-bit {
    position: absolute;
    top: -6%;
    line-height: 1;
    will-change: transform;
    animation-name: festiveDrift;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}

@keyframes festiveDrift {
    0%   { transform: translate3d(0, -10vh, 0) rotate(0deg); }
    100% { transform: translate3d(14px, 108vh, 0) rotate(300deg); }
}

@media (prefers-reduced-motion: reduce) {
    body[data-festival] #current-view-title::after,
    .festive-corner {
        animation: none;
    }
}

/**
 * Confetti burst for the first-run celebration.
 *
 * Above the modal so pieces fall in front of it, but click-through, so it
 * can never swallow the button underneath — the celebration must not be
 * able to trap someone out of their own system. Created and removed by
 * welcome.js; it does not exist in the DOM at rest.
 */
#celebration-canvas {
    position: fixed;
    inset: 0;
    z-index: 100001;
    pointer-events: none;
}

.welcome-btn {
    width: 100%;
    padding: 14px 20px;
    font-size: 1rem;
    font-weight: 600;
    border-radius: var(--radius-md);
    box-shadow: 0 8px 20px rgba(79, 70, 229, 0.18);
    transition: all 0.2s ease;
}

.welcome-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 12px 24px rgba(79, 70, 229, 0.28);
}

@keyframes welcomePulse {
    0% {
        transform: scale(1);
        box-shadow: 0 10px 25px rgba(79, 70, 229, 0.25);
    }
    100% {
        transform: scale(1.06);
        box-shadow: 0 12px 30px rgba(79, 70, 229, 0.4);
    }
}

/* Suspend Overlay */
.suspend-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(15, 23, 42, 0.45);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    z-index: 99999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    font-family: 'Prompt', 'Outfit', sans-serif;
}

.suspend-card {
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(25px) saturate(180%);
    -webkit-backdrop-filter: blur(25px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: var(--radius-lg);
    padding: 30px 24px;
    max-width: 480px;
    width: 100%;
    max-height: 95vh;
    overflow-y: auto;
    text-align: center;
    box-shadow: 0 20px 40px rgba(15, 23, 42, 0.15);
    animation: suspendSlideUp 0.35s cubic-bezier(0.16, 1, 0.3, 1);
    color: var(--text-main);
    position: relative;
}

[data-theme="dark"] .suspend-card {
    background: rgba(30, 41, 59, 0.85) !important;
    border: 1px solid rgba(255, 255, 255, 0.08) !important;
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4) !important;
    color: #ffffff !important;
}

.suspend-icon {
    width: 64px;
    height: 64px;
    color: var(--danger-color);
    margin-bottom: 16px;
}

.suspend-header h2 {
    font-size: 1.5rem;
    font-weight: 700;
    margin-bottom: 8px;
    color: #f1f5f9;
}

.suspend-header p {
    font-size: 0.9rem;
    color: var(--text-light);
    line-height: 1.5;
}

.license-info {
    background: #0f172a;
    padding: 12px;
    border-radius: var(--radius-md);
    margin: 20px 0;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.9rem;
    border: 1px solid #1e293b;
}

.license-info span {
    color: var(--text-muted);
}

.license-info strong {
    color: var(--primary-light);
    font-family: monospace;
    font-size: 1rem;
}

.qr-payment-area p {
    font-size: 0.95rem;
    margin-bottom: 12px;
    color: #f8fafc;
}

.qr-box {
    background: #ffffff;
    padding: 16px;
    border-radius: var(--radius-md);
    display: inline-block;
    margin-bottom: 12px;
    box-shadow: var(--shadow-sm);
}

.qr-box img {
    max-width: 200px;
    display: block;
}

.payment-note {
    font-size: 0.8rem;
    color: #38bdf8;
    display: block;
    margin-bottom: 24px;
}

@keyframes suspendSlideUp {
    from { transform: translateY(30px); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
}

/* Logistics Tasks Style */
.logistics-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px;
    border-radius: var(--radius-md);
    background: var(--bg-body);
    border: 1px solid var(--border-color);
    transition: all 0.2s ease;
}
.logistics-item:hover {
    border-color: var(--primary-color);
    transform: translateY(-1px);
    box-shadow: var(--shadow-sm);
}
.logistics-item.completed {
    opacity: 0.65;
}
.logistics-item.completed .logistics-text {
    text-decoration: line-through;
    color: var(--text-muted);
}
.logistics-text {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex-grow: 1;
    margin-left: 12px;
}
.logistics-title {
    font-weight: 600;
    font-size: 0.88rem;
    color: var(--text-main);
}
.logistics-meta {
    font-size: 0.78rem;
    color: var(--text-muted);
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.logistics-badge {
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
}
.logistics-badge.delivery {
    background: rgba(2, 132, 199, 0.15);
    color: #0284c7;
}
.logistics-badge.pickup {
    background: rgba(234, 88, 12, 0.15);
    color: #ea580c;
}

/* Expense Form & Table Styles */
.quick-expense-form-container label {
    font-weight: 500;
}
.expense-row-delete-btn {
    background: transparent;
    border: none;
    color: var(--danger-color);
    cursor: pointer;
    padding: 4px;
    border-radius: var(--radius-sm);
    transition: background 0.15s;
}
.expense-row-delete-btn:hover {
    background: var(--danger-light);
}

/* ===================== CALENDAR STYLES ===================== */
.calendar-nav-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    width: 100%;
    padding: 4px 0;
}
.calendar-nav-controls {
    display: flex;
    align-items: center;
    gap: 10px;
}
.cal-legend {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 0.78rem;
    color: var(--text-muted);
    font-weight: 500;
    flex-wrap: wrap;
}
.cal-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin-right: 2px;
    vertical-align: middle;
}
.calendar-wrapper {
    background: var(--card-bg);
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-color);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
}
.calendar-grid-header {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    background: linear-gradient(135deg, var(--primary-hover) 0%, var(--primary-color) 60%, #6366f1 100%);
    box-shadow: 0 4px 15px rgba(79, 70, 229, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.2);
    border-bottom: 2px solid rgba(79, 70, 229, 0.4);
}
.cal-day-name {
    text-align: center;
    padding: 12px 4px;
    font-size: 0.85rem;
    font-weight: 700;
    color: #ffffff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    letter-spacing: 0.03em;
    border-right: 1px solid rgba(255, 255, 255, 0.1);
}
.cal-day-name:last-child {
    border-right: none;
}
.calendar-grid-body {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    min-height: 480px;
}
.cal-day-cell {
    min-height: 90px;
    border-right: 1px solid var(--border-color);
    border-bottom: 1px solid var(--border-color);
    padding: 6px 4px 4px 4px;
    cursor: pointer;
    transition: background 0.15s;
    position: relative;
    overflow: hidden;
}
.cal-day-cell:hover {
    background: var(--bg-secondary);
}
.cal-day-cell.other-month {
    background: var(--bg-secondary);
    opacity: 0.55;
}
.cal-day-cell.today {
    background: rgba(37, 99, 235, 0.07);
}
.cal-day-cell.today .cal-day-num {
    background: var(--primary-color);
    color: #fff;
    border-radius: 50%;
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
}
.cal-day-cell:last-child,
.calendar-grid-body > .cal-day-cell:nth-child(7n) {
    border-right: none;
}
.cal-day-num {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-main);
    margin-bottom: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
}
.cal-day-cell.other-month .cal-day-num {
    color: var(--text-muted);
    font-weight: 400;
}
.cal-events-in-day {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.cal-event-pill {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 2px 5px;
    border-radius: 4px;
    font-size: 0.72rem;
    font-weight: 500;
    cursor: pointer;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
    transition: filter 0.15s, transform 0.1s;
}
.cal-event-pill:hover {
    filter: brightness(0.9);
    transform: scale(1.02);
}
.cal-event-pill.type-delivery {
    background: rgba(59, 130, 246, 0.18);
    color: #1d4ed8;
    border-left: 3px solid #3b82f6;
}
.cal-event-pill.type-pickup {
    background: rgba(234, 88, 12, 0.15);
    color: #c2410c;
    border-left: 3px solid #ea580c;
}
.cal-event-pill.type-appointment {
    background: rgba(139, 92, 246, 0.15);
    color: #6d28d9;
    border-left: 3px solid #8b5cf6;
}
.cal-event-pill.type-other {
    background: rgba(16, 185, 129, 0.15);
    color: #059669;
    border-left: 3px solid #10b981;
}
.cal-more-events {
    font-size: 0.7rem;
    color: var(--text-muted);
    font-weight: 500;
    padding: 1px 3px;
    cursor: pointer;
}
.cal-event-type-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 12px;
    font-size: 0.75rem;
    font-weight: 600;
}
.cal-event-type-badge.delivery { background: rgba(59,130,246,0.15); color: #1d4ed8; }
.cal-event-type-badge.pickup { background: rgba(234,88,12,0.15); color: #c2410c; }
.cal-event-type-badge.appointment { background: rgba(139,92,246,0.15); color: #6d28d9; }
.cal-event-type-badge.other { background: rgba(16,185,129,0.15); color: #059669; }

/* Dark mode calendar */
[data-theme="dark"] .cal-day-cell.today {
    background: rgba(99, 102, 241, 0.12);
}
[data-theme="dark"] .cal-event-pill.type-delivery {
    background: rgba(59, 130, 246, 0.25);
    color: #93c5fd;
}
[data-theme="dark"] .cal-event-pill.type-pickup {
    background: rgba(234, 88, 12, 0.22);
    color: #fdba74;
}
[data-theme="dark"] .cal-event-pill.type-appointment {
    background: rgba(139, 92, 246, 0.22);
    color: #c4b5fd;
}
[data-theme="dark"] .cal-event-pill.type-other {
    background: rgba(16, 185, 129, 0.22);
    color: #6ee7b7;
}

@media (max-width: 768px) {
    .calendar-nav-row {
        flex-direction: column;
        align-items: flex-start;
    }
    .cal-day-cell {
        min-height: 60px;
        padding: 3px 2px 2px 2px;
    }
    .cal-day-num { font-size: 0.75rem; width: 22px; height: 22px; }
    .cal-event-pill { font-size: 0.65rem; padding: 1px 3px; }
    .cal-legend { gap: 6px; }
}

/* Floating Calculator Button */
.floating-calc-btn {
    position: fixed;
    bottom: 24px;
    right: 24px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));
    color: #ffffff;
    border: none;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(99, 102, 241, 0.4);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    transition: transform 0.2s, box-shadow 0.2s;
}
.floating-calc-btn:hover {
    transform: scale(1.1);
    box-shadow: 0 6px 20px rgba(99, 102, 241, 0.6);
}
.floating-calc-btn i {
    width: 24px;
    height: 24px;
}

/* Calculator Widget Container */
.calc-widget {
    position: fixed;
    bottom: 90px;
    right: 24px;
    width: 280px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: 1000;
    overflow: hidden;
    font-family: 'Inter', 'Prompt', sans-serif;
    animation: slideUp 0.2s ease-out;
}
@keyframes slideUp {
    from { transform: translateY(10px); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
}

.calc-header {
    background: var(--bg-body);
    padding: 10px 14px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-main);
}
.calc-close-btn {
    background: transparent;
    border: none;
    color: var(--text-muted);
    font-size: 1.25rem;
    cursor: pointer;
    line-height: 1;
}
.calc-close-btn:hover {
    color: var(--danger-color);
}

.calc-display-wrapper {
    background: var(--bg-body);
    padding: 14px;
    text-align: right;
    border-bottom: 1px solid var(--border-color);
}
.calc-history {
    font-size: 0.75rem;
    color: var(--text-muted);
    min-height: 16px;
    word-break: break-all;
}
.calc-input {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-main);
    word-break: break-all;
    margin-top: 4px;
}

.calc-buttons {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1px;
    background: var(--border-color);
}
.calc-btn {
    background: var(--bg-card);
    border: none;
    padding: 14px;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-main);
    cursor: pointer;
    transition: background 0.15s;
}
.calc-btn:hover {
    background: var(--bg-body);
}
.calc-btn.op {
    background: var(--primary-light);
    color: var(--primary-color);
}
.calc-btn.op:hover {
    background: #e0e7ff;
}
.calc-btn.eq {
    background: var(--primary-color);
    color: #ffffff;
    grid-row: span 2;
}
.calc-btn.eq:hover {
    background: var(--primary-hover);
}
.calc-btn.zero {
    grid-column: span 2;
}

/* Input History & Auto-suggest Dropdown */
.input-history-dropdown {
    position: fixed;
    z-index: 100000;
    background: var(--bg-card, #ffffff);
    border: 1px solid var(--border-color, #e2e8f0);
    border-radius: var(--radius-md, 8px);
    box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
    max-height: 230px;
    overflow-y: auto;
    display: none;
    min-width: 200px;
    font-family: inherit;
}

.history-dropdown-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 12px;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted, #64748b);
    background: var(--bg-body, #f8fafc);
    border-bottom: 1px solid var(--border-color, #e2e8f0);
}

.history-clear-all-btn {
    background: transparent;
    border: none;
    color: var(--danger-color, #ef4444);
    font-size: 0.72rem;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
    font-weight: 500;
}

.history-clear-all-btn:hover {
    text-decoration: underline;
    background: var(--danger-light, #fee2e2);
}

.history-dropdown-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    cursor: pointer;
    font-size: 0.85rem;
    color: var(--text-main, #1e293b);
    border-bottom: 1px solid var(--border-color, #f1f5f9);
    transition: background 0.15s ease;
    gap: 8px;
}

.history-dropdown-item:last-child {
    border-bottom: none;
}

.history-dropdown-item:hover {
    background: var(--primary-light, #eff6ff);
    color: var(--primary-color, #2563eb);
}

.history-item-left {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    overflow: hidden;
}

.history-icon {
    width: 14px;
    height: 14px;
    opacity: 0.5;
    flex-shrink: 0;
}

.history-item-text {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.history-item-delete-btn {
    background: transparent;
    border: none;
    color: var(--text-muted, #94a3b8);
    font-size: 1.2rem;
    line-height: 1;
    padding: 0px 6px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.15s ease;
    flex-shrink: 0;
}

.history-item-delete-btn:hover {
    background: var(--danger-light, #fee2e2);
    color: var(--danger-color, #ef4444);
}

/* =====================================================
   Payment Polling & Success Banner Animations
   ===================================================== */
@keyframes slideDown {
    from { opacity: 0; transform: translateX(-50%) translateY(-20px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

@keyframes spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

.spin {
    animation: spin 1s linear infinite;
    display: inline-block;
}

#modal-master-admin {
    z-index: 100005 !important;
}

/* Highlight fully returned rows in return modal */
tr.fully-returned-row td {
    background-color: #d1fae5 !important; /* Emerald 100 (Prominent light green) */
    color: #065f46 !important; /* Emerald 800 (Dark green) */
}
tr.fully-returned-row input.form-control,
tr.fully-returned-row select.form-control {
    background-color: #d1fae5 !important; /* Emerald 100 */
    color: #065f46 !important;
    border-color: #a7f3d0 !important;
}

[data-theme="dark"] tr.fully-returned-row td {
    background-color: #064e3b !important; /* Emerald 900 (Dark green) */
    color: #a7f3d0 !important; /* Emerald 200 (Light green text) */
}
[data-theme="dark"] tr.fully-returned-row input.form-control,
[data-theme="dark"] tr.fully-returned-row select.form-control {
    background-color: #022c22 !important;
    color: #a7f3d0 !important;
    border-color: #064e3b !important;
}

/* ═══════════════════════════════════════════════════════════
   VERSION CHANGELOG MODAL
   ═══════════════════════════════════════════════════════════ */

.changelog-modal {
    max-width: 560px;
    max-height: 80vh;
}

.changelog-modal .modal-body {
    max-height: 60vh;
    overflow-y: auto;
    padding: 0 24px 24px;
}

.changelog-timeline {
    position: relative;
    padding-left: 24px;
}

.changelog-timeline::before {
    content: '';
    position: absolute;
    left: 6px;
    top: 8px;
    bottom: 8px;
    width: 2px;
    background: linear-gradient(to bottom, var(--primary-color, #3b82f6), var(--border-color, #e2e8f0));
    border-radius: 1px;
}

.changelog-entry {
    position: relative;
    margin-bottom: 20px;
}

.changelog-entry:last-child {
    margin-bottom: 0;
}

.changelog-dot {
    position: absolute;
    left: -21px;
    top: 12px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--border-color, #e2e8f0);
    border: 2px solid var(--bg-primary, #fff);
    z-index: 1;
}

.changelog-entry.latest .changelog-dot {
    background: var(--primary-color, #3b82f6);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
}

.changelog-card {
    background: var(--bg-secondary, #f8fafc);
    border: 1px solid var(--border-color, #e2e8f0);
    border-radius: 10px;
    padding: 14px 16px;
    transition: box-shadow 0.2s;
}

.changelog-entry.latest .changelog-card {
    border-color: var(--primary-color, #3b82f6);
    background: linear-gradient(135deg, rgba(59,130,246,0.04), rgba(59,130,246,0.01));
    box-shadow: 0 2px 8px rgba(59, 130, 246, 0.08);
}

.changelog-header {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}

.changelog-version {
    font-weight: 700;
    font-size: 1rem;
    color: var(--text-primary);
    font-family: 'Outfit', monospace;
}

.changelog-type-badge {
    font-size: 0.7rem;
    padding: 2px 8px;
    border-radius: 99px;
    font-weight: 600;
    letter-spacing: 0.3px;
}

.changelog-type-badge.type-major {
    background: linear-gradient(135deg, #fef3c7, #fde68a);
    color: #92400e;
}

.changelog-type-badge.type-minor {
    background: linear-gradient(135deg, #dbeafe, #bfdbfe);
    color: #1e40af;
}

.changelog-type-badge.type-patch {
    background: linear-gradient(135deg, #d1fae5, #a7f3d0);
    color: #065f46;
}

.changelog-latest-tag {
    font-size: 0.6rem;
    padding: 1px 6px;
    border-radius: 4px;
    background: var(--primary-color, #3b82f6);
    color: white;
    font-weight: 700;
    letter-spacing: 0.5px;
    animation: latestPulse 2s ease-in-out infinite;
}

@keyframes latestPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.7; }
}

.changelog-date {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.75rem;
    color: var(--text-secondary);
    margin-bottom: 8px;
}

.changelog-changes {
    list-style: none;
    padding: 0;
    margin: 0;
}

.changelog-changes li {
    position: relative;
    padding: 3px 0 3px 16px;
    font-size: 0.82rem;
    color: var(--text-primary);
    line-height: 1.5;
}

.changelog-changes li::before {
    content: '▸';
    position: absolute;
    left: 0;
    color: var(--primary-color, #3b82f6);
    font-weight: 700;
}

/* Version NEW badge in sidebar */
.version-new-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.55rem;
    padding: 1px 5px;
    border-radius: 4px;
    background: linear-gradient(135deg, #ef4444, #f97316);
    color: white;
    font-weight: 800;
    letter-spacing: 0.5px;
    animation: badgeBounce 1.5s ease-in-out infinite;
    line-height: 1.4;
}

@keyframes badgeBounce {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.1); }
}

/* Dark theme overrides */
[data-theme="dark"] .changelog-card {
    background: var(--bg-secondary, #1e293b);
}

[data-theme="dark"] .changelog-entry.latest .changelog-card {
    background: linear-gradient(135deg, rgba(59,130,246,0.1), rgba(59,130,246,0.03));
}

[data-theme="dark"] .changelog-type-badge.type-major {
    background: linear-gradient(135deg, #78350f, #92400e);
    color: #fde68a;
}

[data-theme="dark"] .changelog-type-badge.type-minor {
    background: linear-gradient(135deg, #1e3a5f, #1e40af);
    color: #bfdbfe;
}

[data-theme="dark"] .changelog-type-badge.type-patch {
    background: linear-gradient(135deg, #064e3b, #065f46);
    color: #a7f3d0;
}

/* ═══════════════════════════════════════════════════════════
   SETTINGS SUB-TABS & PASSWORD VISIBILITY TOGGLE
   ═══════════════════════════════════════════════════════════ */

.settings-sub-tabs {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 20px;
    border-bottom: 2px solid var(--border-color);
    padding-bottom: 8px;
}

.settings-sub-tabs .sub-tab-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    border-radius: var(--radius-md);
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    color: var(--text-muted);
    font-size: 0.88rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
}

.settings-sub-tabs .sub-tab-btn:hover {
    background: var(--bg-hover);
    color: var(--text-main);
    border-color: var(--primary-color);
}

.settings-sub-tabs .sub-tab-btn.active {
    background: var(--primary-color);
    color: #ffffff;
    border-color: var(--primary-color);
    box-shadow: 0 2px 8px rgba(59, 130, 246, 0.25);
}

.settings-tab-content {
    animation: fadeInTab 0.25s ease-in-out;
}

@keyframes fadeInTab {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: translateY(0); }
}

.btn-toggle-pin-visibility:hover {
    color: var(--primary-color) !important;
}

.btn-toggle-pin-visibility:focus {
    outline: none;
}

/* ═══════════════════════════════════════════════════════════
   REAL PRINT-LIKE INVOICE PREVIEW PAPER FRAME
   ═══════════════════════════════════════════════════════════ */
.invoice-preview-paper-frame {
    background: #ffffff !important;
    color: #0f172a !important;
    border: 2px solid #cbd5e1 !important;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08) !important;
    border-radius: 8px !important;
    padding: 28px 32px !important;
    max-width: 680px !important;
    margin: 0 auto !important;
    font-size: 0.95rem !important;
    line-height: 1.5 !important;
}

[data-theme="dark"] .invoice-preview-paper-frame {
    background: #ffffff !important;
    color: #0f172a !important;
    border-color: #94a3b8 !important;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3) !important;
}

[data-theme="dark"] .invoice-preview-paper-frame h4,
[data-theme="dark"] .invoice-preview-paper-frame h5,
[data-theme="dark"] .invoice-preview-paper-frame th,
[data-theme="dark"] .invoice-preview-paper-frame strong {
    color: #0f172a !important;
}

[data-theme="dark"] .invoice-preview-paper-frame p,
[data-theme="dark"] .invoice-preview-paper-frame td,
[data-theme="dark"] .invoice-preview-paper-frame span,
[data-theme="dark"] .invoice-preview-paper-frame div {
    color: #334155 !important;
}

/* ═══════════════════════════════════════════════════════════
   SECURITY & AUTHENTICATION ENFORCEMENT STYLES
   ═══════════════════════════════════════════════════════════ */

body:not(.authenticated) .app-container {
    filter: blur(20px) !important;
    pointer-events: none !important;
    user-select: none !important;
}

body:not(.authenticated) #modal-login-overlay {
    display: flex !important;
    opacity: 1 !important;
    visibility: visible !important;
    pointer-events: auto !important;
}

/**
 * Nothing is known yet.
 *
 * The rule above shows the login box the instant the page paints, because
 * `.authenticated` cannot be on the body before the session has been
 * checked — and that check is a network round trip. On every refresh of an
 * already-signed-in shop the login box therefore flashed up and vanished.
 *
 * `.auth-pending` is set on <html> by the very first inline script and
 * removed the moment the answer arrives, so the overlay is suppressed
 * during the one uncertain moment rather than shown on a guess. Failing
 * that request removes the class too, so nobody can be locked out by it.
 */
html.auth-pending body:not(.authenticated) #modal-login-overlay {
    display: none !important;
}

/* Something has to occupy the screen while we wait, or the shop stares at
   a blank page and wonders whether it loaded. */
html.auth-pending body:not(.authenticated) .app-container::after {
    content: "กำลังตรวจสอบการเข้าใช้งาน...";
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-body);
    color: var(--text-muted);
    font-size: 0.95rem;
    z-index: 9998;
}

@media print {
    body:not(.authenticated) * {
        display: none !important;
    }
    body:not(.authenticated)::after {
        content: "ACCESS DENIED - Authentication Required";
        font-size: 28px;
        font-weight: 700;
        text-align: center;
        display: block;
        padding: 80px 20px;
        color: #ef4444;
        font-family: sans-serif;
    }
}

/* Subscription lock — the shop is suspended or expired.
   The overlay (.suspend-overlay, z-index 99999) already covers the screen;
   this additionally makes the app behind it inert, so a stray click, a
   keyboard tab into a form, or a script-driven action cannot reach a
   business control while the renewal card is up. Mirrors how the login
   overlay locks the app for an unauthenticated user. */
body.subscription-locked .app-container {
    pointer-events: none !important;
    user-select: none !important;
    filter: blur(6px) !important;
}
