/* Modern CSS with Light/Dark Mode - ShopeeFood style: light sky-blue accent, clean white UI */

:root {
    /* Light mode colors */
    --bg-primary: #ffffff;
    --bg-secondary: #f2f8fd;
    --bg-card: #ffffff;
    --text-primary: #1a2530;
    --text-secondary: #64748b;
    --text-muted: #a3b1c2;
    --border-color: #e3edf7;
    --accent-color: #2F9BFF;
    --accent-hover: #1c7ed6;
    --success-color: #22c55e;
    --warning-color: #f5a623;
    --danger-color: #ef4444;
    --info-color: #3b82f6;
    --radius-card: 16px;
    --radius-btn: 10px;
    --radius-pill: 999px;
    --shadow-sm: 0 2px 6px rgba(20,60,100,0.06);
    --shadow-md: 0 8px 20px rgba(20,60,100,0.08);
    --shadow-lg: 0 16px 40px rgba(20,60,100,0.14);
    --gradient-primary: linear-gradient(135deg, #07264a 0%, #12599a 55%, #4db5ff 100%);
    --gradient-accent: linear-gradient(135deg, #4db5ff 0%, #2178dd 100%);
    --gradient-success: linear-gradient(135deg, #34d399 0%, #10b981 100%);
    --gradient-warning: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
    --gradient-danger: linear-gradient(135deg, #f87171 0%, #ef4444 100%);
}

[data-theme="dark"] {
    /* Dark mode colors */
    --bg-primary: #0a1420;
    --bg-secondary: #101c2c;
    --bg-card: #142235;
    --text-primary: #ffffff;
    --text-secondary: #93a5bb;
    --text-muted: #5f7286;
    --border-color: #1f3245;
    --accent-color: #4db8ff;
    --accent-hover: #6ec6ff;
    --success-color: #22c55e;
    --warning-color: #fbbf24;
    --danger-color: #f87171;
    --info-color: #60a5fa;
    --shadow-sm: 0 2px 6px rgba(0,0,0,0.35);
    --shadow-md: 0 8px 20px rgba(0,0,0,0.45);
    --shadow-lg: 0 16px 40px rgba(0,0,0,0.55);
    --gradient-primary: linear-gradient(135deg, #030a14 0%, #0c3560 55%, #2f8fe0 100%);
    --gradient-accent: linear-gradient(135deg, #4db8ff 0%, #2178dd 100%);
    --gradient-success: linear-gradient(135deg, #34d399 0%, #10b981 100%);
    --gradient-warning: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
    --gradient-danger: linear-gradient(135deg, #f87171 0%, #ef4444 100%);
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    /* "hidden" here turns the page into its own scroll container, which
       silently stops position: sticky working anywhere inside it - that is
       what kept the mobile top bar from pinning. "clip" trims the same
       sideways overflow without creating that container; the hidden line
       stays first as the fallback for browsers without clip. */
    overflow-x: hidden;
    overflow-x: clip;
    width: 100%;
}

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background-color: var(--bg-primary);
    background-image: radial-gradient(circle at 100% 0%, rgba(47,155,255,0.06) 0%, transparent 45%);
    color: var(--text-primary);
    line-height: 1.6;
    transition: background-color 0.3s ease, color 0.3s ease;
}

h1, h2, h3, h4, h5, h6 {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-weight: 800;
    letter-spacing: -0.02em;
}

.nav-brand, .card-title {
    font-weight: 700;
}

.admin-title, .dashboard-title {
    font-weight: 700;
}

/* Quantity Selector with +/- buttons */
.quantity-selector {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.quantity-controls {
    display: flex;
    align-items: center;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    overflow: hidden;
    background: var(--bg-card);
}

.quantity-btn {
    background: var(--bg-secondary);
    border: none;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease;
    color: var(--text-primary);
    font-size: 1rem;
}

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

.quantity-input {
    border: none;
    width: 60px;
    height: 36px;
    text-align: center;
    background: var(--bg-card);
    color: var(--text-primary);
    font-size: 1rem;
    outline: none;
}

.quantity-input:focus {
    background: var(--bg-primary);
}

.product-actions {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.stock-badge {
    align-self: flex-start;
}

/* Theme Toggle */
.theme-toggle {
    position: fixed;
    top: 20px;
    right: 20px;
    z-index: 1000;
    background: var(--gradient-accent);
    border: none;
    border-radius: 50px;
    padding: 12px 20px;
    color: white;
    cursor: pointer;
    font-size: 14px;
    font-weight: 600;
    box-shadow: var(--shadow-md);
    transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
    display: flex;
    align-items: center;
    gap: 8px;
}

.theme-toggle:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

.theme-toggle:active {
    transform: translateY(0);
}

/* Navigation */
.navbar {
    background: color-mix(in srgb, var(--bg-card) 88%, transparent);
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
    border-bottom: 1px solid var(--border-color);
    padding: 1rem 0;
    box-shadow: var(--shadow-sm);
    position: sticky;
    top: 0;
    z-index: 100;
    transition: background 0.2s ease, box-shadow 0.2s ease;
}

.nav-container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 2rem;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    gap: 2.5rem;
}

.nav-brand {
    font-size: 1.5rem;
    font-weight: 500;
    background: var(--gradient-accent);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    text-decoration: none;
}

.nav-links {
    display: flex;
    gap: 2rem;
    list-style: none;
}

.nav-link {
    color: var(--text-secondary);
    text-decoration: none;
    font-weight: 500;
    transition: color 0.3s ease;
    position: relative;
}

.nav-link:hover {
    color: var(--accent-color);
}

.nav-link::after {
    content: '';
    position: absolute;
    bottom: -5px;
    left: 0;
    width: 0;
    height: 2px;
    background: var(--gradient-accent);
    transition: width 0.3s ease;
}

.nav-link:hover::after {
    width: 100%;
}

/* Container */
.container {
    /* .main-area is a column flex container, and an auto horizontal margin
       stops a flex item from stretching - without an explicit width this box
       collapsed to its content instead of growing to max-width, which left a
       wide screen mostly empty. */
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem;
}

/* Cards */
.card {
    background: var(--bg-card);
    border-radius: var(--radius-card);
    padding: 0.5rem;
    box-shadow: var(--shadow-md);
    border: 1px solid var(--border-color);
    transition: transform 0.25s ease, box-shadow 0.25s ease;
    margin-bottom: 2rem;
}

.card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
}

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

.card-title {
    font-size: 1.5rem;
    font-weight: 500;
    color: var(--text-primary);
    margin: 0;
}

/* Buttons */
.btn {
    padding: 13px 26px;
    border: none;
    border-radius: var(--radius-btn);
    font-weight: 600;
    font-size: 14px;
    cursor: pointer;
    transition: transform 0.25s ease, box-shadow 0.25s ease, background 0.25s ease;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    position: relative;
    overflow: hidden;
}

.btn::before {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
    transition: left 0.5s ease;
}

.btn:hover::before {
    left: 100%;
}

.btn-primary {
    background: var(--gradient-accent);
    color: white;
    box-shadow: 0 4px 14px rgba(47,155,255,0.32);
}

.btn-primary:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

.btn-secondary {
    background: var(--bg-secondary);
    color: var(--text-primary);
    border: 1px solid var(--border-color);
}

.btn-secondary:hover {
    background: var(--border-color);
    transform: translateY(-2px);
}

.btn-success {
    background: var(--gradient-success);
    color: var(--bg-primary);
}

.btn-warning {
    background: var(--gradient-warning);
    color: var(--bg-primary);
}

.btn-danger {
    background: var(--gradient-danger);
    color: white;
}

.btn-outline {
    background: transparent;
    border: 2px solid var(--accent-color);
    color: var(--accent-color);
}

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

/* Forms */
.form-group {
    margin-bottom: 1.5rem;
}

.form-label {
    display: block;
    margin-bottom: 0.5rem;
    font-weight: 600;
    color: var(--text-primary);
}

.form-control {
    width: 100%;
    padding: 12px 16px;
    border: 2px solid var(--border-color);
    border-radius: 14px;
    font-size: 14px;
    background: var(--bg-primary);
    color: var(--text-primary);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.form-control:focus {
    outline: none;
    border-color: var(--accent-color);
    box-shadow: 0 0 0 3px rgba(47, 155, 255, 0.14);
}

.form-control::placeholder {
    color: var(--text-muted);
}

/* Range inputs */
input[type="range"] {
    width: 100%;
    height: 6px;
    border-radius: 3px;
    background: var(--border-color);
    outline: none;
    -webkit-appearance: none;
}

input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--gradient-accent);
    cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

input[type="range"]::-webkit-slider-thumb:hover {
    transform: scale(1.2);
    box-shadow: var(--shadow-md);
}

input[type="range"]::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--gradient-accent);
    cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

/* Tables */
.table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 1rem;
}

.table th,
.table td {
    padding: 1rem;
    text-align: left;
    border-bottom: 1px solid var(--border-color);
}

.table th {
    background: var(--bg-secondary);
    font-weight: 600;
    color: var(--text-primary);
}

.table tbody tr:hover {
    background: var(--bg-secondary);
}

/* Alerts */
.alert {
    padding: 1rem 1.5rem;
    border-radius: 8px;
    margin-bottom: 1rem;
    border-left: 4px solid;
    display: flex;
    align-items: center;
    gap: 1rem;
}

.alert-success {
    background: rgba(6, 255, 165, 0.1);
    border-left-color: var(--success-color);
    color: var(--success-color);
}

.alert-warning {
    background: rgba(255, 190, 11, 0.1);
    border-left-color: var(--warning-color);
    color: var(--warning-color);
}

.alert-danger {
    background: rgba(251, 86, 7, 0.1);
    border-left-color: var(--danger-color);
    color: var(--danger-color);
}

.alert-info {
    background: rgba(58, 134, 255, 0.1);
    border-left-color: var(--info-color);
    color: var(--info-color);
}

/* Grid */
.grid {
    display: grid;
    gap: 2rem;
}

.grid-cols-1 { grid-template-columns: repeat(1, 1fr); }
.grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
.grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid-cols-4 { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 768px) {
    .grid-cols-2,
    .grid-cols-3,
    .grid-cols-4 {
        grid-template-columns: 1fr;
    }
    
    .nav-links {
        display: none;
    }
    
    .container {
        padding: 1rem;
    }
    
    .page-header {
        padding: 2rem 0 !important;
        margin: -1rem -1rem 1rem -1rem !important;
    }
    
    .card {
        padding: 1.5rem;
    }
    
    .theme-toggle {
        top: 2px;
        right: 10px;
        padding: 2px 6px;
        font-size: 12px;
    }
}

/* Animations */
@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.fade-in {
    animation: fadeIn 0.5s ease-out;
}

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

.pulse {
    animation: pulse 2s infinite;
}

/* Stock Indicator Classes */
.stock-indicator {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 1rem;
}

.stock-indicator i {
    font-size: 1.5rem;
    color: white;
}

.stock-success {
    background: var(--gradient-success);
}

.stock-danger {
    background: var(--gradient-danger);
}

.stock-text-success {
    color: var(--success-color);
    font-weight: 600;
}

.stock-text-danger {
    color: var(--danger-color);
    font-weight: 600;
}

/* Loading spinner */
.spinner {
    width: 40px;
    height: 40px;
    border: 4px solid var(--border-color);
    border-top: 4px solid var(--accent-color);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* Product cards */
.product-card {
    background: var(--bg-card);
    border-radius: var(--radius-card);
    overflow: hidden;
    box-shadow: var(--shadow-md);
    transition: transform 0.35s ease, box-shadow 0.35s ease;
    border: 1px solid var(--border-color);
}

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

.product-card > a {
    display: block;
    overflow: hidden;
}

.product-image {
    width: 100%;
    height: 200px;
    /* contain, not cover: a tall can/bottle photo cropped to fill this box
       was losing its label and top/bottom - showing the whole image and
       letting it shrink to fit keeps the product actually recognisable. */
    object-fit: contain;
    background: var(--bg-secondary);
    display: block;
    transition: transform 0.5s ease;
}

.product-card:hover .product-image {
    transform: scale(1.08);
}

.product-info {
    padding: 1.5rem;
}

.product-title {
    font-size: 1.15rem;
    font-weight: 600;
    margin-bottom: 0.5rem;
    color: var(--text-primary);
}

.product-price {
    font-size: 1.4rem;
    font-weight: 800;
    color: var(--accent-color);
    margin-bottom: 1rem;
}

/* Status badges */
.badge {
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    font-size: 16px;
    font-weight: 400;
    text-transform: uppercase;
    white-space: nowrap;
}

.badge-success {
    background: var(--gradient-success);
    color: var(--bg-primary);
}

.badge-warning {
    background: var(--gradient-warning);
    color: var(--bg-primary);
}

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

.badge-info {
    background: var(--gradient-accent);
    color: white;
}

/* ===== Onboarding welcome flow (first visit only) ===== */
.onboarding-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 6000;
    background: var(--bg-primary);
    overflow: hidden;
    opacity: 1;
    transition: opacity 0.3s ease;
}

html.show-onboarding .onboarding-overlay {
    display: block;
    cursor: pointer;
}

html.show-onboarding body {
    overflow: hidden;
}



/* Was one of four panels inside a sliding track; now the only thing on
   screen, so it fills it. */
.onboarding-slide {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
}

.onboarding-slide-cover {
    background: var(--gradient-primary);
    align-items: center;
    justify-content: center;
    position: relative;
    cursor: pointer;
}

.onboarding-cover-brand {
    font-size: 2.1rem;
    font-weight: 800;
    color: white;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    justify-content: center;
}

.onboarding-cover-brand span {
    color: #7ec8ff;
}


@keyframes onboardingPulse {
    0%, 100% { opacity: 0.5; }
    50% { opacity: 1; }
}

.onboarding-cover-version {
    position: absolute;
    bottom: 2rem;
    left: 0;
    right: 0;
    text-align: center;
    color: rgba(255,255,255,0.4);
    font-size: 0.75rem;
}












@media (min-width: 700px) {
}

/* Product card call-to-action pair ("thêm giỏ" + "mua ngay")
   ------------------------------------------------------------------
   The quantity stepper and the icon-only cart button must always share one
   row, with "Mua ngay" on its own row below. This used to be flexbox with
   flex-wrap - which meant the row's fate depended on every child's computed
   width adding up correctly, and the exact number that tips it over varies
   by device: a bigger font-scale setting, a browser's own number-input
   spinner, slightly different sub-pixel rounding, all pushed the cart
   button onto its own third row despite fitting on desktop/headless
   testing. A 2-column CSS grid makes the row split structural instead of
   arithmetic: the cart button's column is exactly as wide as the button,
   the stepper's column takes the rest, and nothing can ever wrap to a
   different row because there is no wrapping mechanism involved at all. */
.product-cta {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.5rem;
    width: 100%;
}

.product-cta .btn {
    min-width: 0;          /* allow shrinking; flex/grid items default to min-content */
    justify-content: center;
    gap: 0.35rem;
    padding: 10px 8px;
    font-size: 0.85rem;
    white-space: nowrap;   /* short labels; wrapping was the defect */
}

.product-cta .quantity-selector {
    grid-column: 1;
    grid-row: 1;
    min-width: 0;
    margin-bottom: 0;
}

.product-cta .btn-cart {
    grid-column: 2;
    grid-row: 1;
    width: 40px;
    padding: 0;
    min-height: 38px;      /* square even when it is the tallest thing in the row */
}

.product-cta .quantity-controls {
    width: 100%;
    min-width: 0;
}

.product-cta .quantity-btn {
    width: 30px;
    height: 36px;
    flex: 0 0 30px;
}

.product-cta .quantity-input {
    width: auto;
    min-width: 0;
    flex: 1 1 auto;
    font-size: 0.9rem;
    /* the native up/down spinner is dead weight in a stepper that already
       has its own +/- buttons, and its width isn't consistent across
       browsers - remove it so it never eats into the row's budget */
    -moz-appearance: textfield;
}

.product-cta .quantity-input::-webkit-outer-spin-button,
.product-cta .quantity-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.product-cta .btn-buy {
    grid-column: 1 / -1;   /* its own full-width row below the stepper */
    grid-row: 2;
}

@media (max-width: 768px) {
    .product-cta {
        gap: 0.4rem;
    }

    .product-cta .btn {
        padding: 0 6px;
        font-size: 0.78rem;
        min-height: 36px;
    }

    /* At two cards per row there is about 150px to share between the stepper
       and the cart button, so both shrink; the grid guarantees they still
       never end up on different rows. */
    .product-cta .btn-cart {
        width: 34px;
    }

    .product-cta .quantity-btn {
        width: 26px;
        flex: 0 0 26px;
    }

    .product-cta .quantity-input {
        font-size: 0.8rem;
    }
}

/* Catalogue grid
   ------------------------------------------------------------------
   The products page pairs a 300px filter sidebar with the card grid, so it
   has noticeably less room than the other pages - and it used a hard-coded
   two-column grid, which on a desktop screen produced two ~390px cards and
   left the rest of the row empty. Sizing by column width instead of column
   count lets the same grid be 2-up on a tablet, 3-up on a laptop and 4-up on
   a wide monitor without another breakpoint. */
.grid-products {
    grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
    gap: 1.5rem;
}

/* Swiggy-style catalogue header
   ------------------------------------------------------------------
   A tab strip, a full-width search bar and a scrollable chip row, the
   pattern the Swiggy app uses. Every colour here comes from the existing
   tokens, so the theme (and dark mode) is unchanged. */

/* Tabs: one per catalogue type, icon above label, accent underline when
   active. Horizontally scrollable so more tabs can be added later without
   the row wrapping. */
.sw-tabs {
    display: flex;
    gap: 0.25rem;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 1.25rem;
    overflow-x: auto;
    scrollbar-width: none;
}

.sw-tabs::-webkit-scrollbar {
    display: none;
}

.sw-tab {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.45rem;
    padding: 0.75rem 1.5rem 0;
    text-decoration: none;
    color: var(--text-secondary);
    border-bottom: 3px solid transparent;
    transition: color 0.2s ease, border-color 0.2s ease;
}

.sw-tab-icon {
    width: 54px;
    height: 54px;
    border-radius: var(--radius-card);
    display: grid;
    place-items: center;
    font-size: 1.35rem;
    background: var(--bg-secondary);
    color: var(--text-secondary);
    transition: background 0.2s ease, color 0.2s ease;
}

.sw-tab-label {
    font-size: 0.85rem;
    font-weight: 600;
    padding-bottom: 0.65rem;
    white-space: nowrap;
}

.sw-tab:hover {
    color: var(--text-primary);
}

.sw-tab.active {
    color: var(--accent-color);
    border-bottom-color: var(--accent-color);
}

.sw-tab.active .sw-tab-icon {
    background: var(--gradient-accent);
    color: white;
    box-shadow: var(--shadow-sm);
}

/* Search row: the search field and the filter button sit together, the way
   Swiggy pairs its search bar with the veg toggle. */
.sw-searchbar {
    display: flex;
    gap: 0.75rem;
    align-items: center;
    margin-bottom: 1rem;
}

.sw-search {
    flex: 1;
    /* the flex item itself needs this, not just the input inside it -
       without it the box refuses to shrink and pushes the filter button
       past the container edge on a narrow phone */
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-pill);
    padding: 0.65rem 1.15rem;
    box-shadow: var(--shadow-sm);
}

.sw-search i {
    color: var(--text-muted);
}

.sw-search input {
    flex: 1;
    min-width: 0;
    border: 0;
    outline: 0;
    background: transparent;
    font-size: 0.95rem;
    color: var(--text-primary);
    font-family: inherit;
}

.sw-search input::placeholder {
    color: var(--text-muted);
}

.sw-filter-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-pill);
    padding: 0.65rem 1.15rem;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-primary);
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    font-family: inherit;
}

.sw-filter-btn:hover {
    border-color: var(--accent-color);
    color: var(--accent-color);
}

/* Sort chips - a horizontal, scrollable row like Swiggy's filter pills. */
.sw-chips {
    display: flex;
    gap: 0.6rem;
    overflow-x: auto;
    padding-bottom: 0.35rem;
    margin-bottom: 1.5rem;
    scrollbar-width: none;
}

.sw-chips::-webkit-scrollbar {
    display: none;
}

.sw-chip {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-pill);
    padding: 0.45rem 0.95rem;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-secondary);
    text-decoration: none;
    white-space: nowrap;
    box-shadow: var(--shadow-sm);
}

.sw-chip:hover {
    border-color: var(--accent-color);
    color: var(--accent-color);
}

/* The selected chip is filled rather than ticked: at this size a check mark
   crowds the label and shifts the text, while a solid fill reads instantly. */
.sw-chip.active {
    border-color: var(--accent-color);
    background: var(--accent-color);
    color: #fff;
}

.sw-chip.active:hover {
    border-color: var(--accent-hover);
    background: var(--accent-hover);
    color: #fff;
}

.sw-result-count {
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin-bottom: 1rem;
}

/* A badge laid over the product image, like Swiggy's discount flash. */
.sw-media {
    position: relative;
    display: block;
    overflow: hidden;
}

.sw-media .sw-badge {
    position: absolute;
    left: 0.6rem;
    bottom: 0.6rem;
    padding: 0.25rem 0.6rem;
    border-radius: var(--radius-pill);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: white;
    background: var(--success-color);
    box-shadow: var(--shadow-sm);
}

.sw-media .sw-badge.is-out {
    background: var(--danger-color);
}

/* "Đặc biệt": top-right, so it never collides with the daily-dish badge
   (top-left) or the stock badge (bottom-left). A violet distinct from the
   site's other badge colors (green/amber/red/blue) so it reads as its own
   category rather than a stock or freshness signal. */
.sw-media .sw-badge.is-special {
    top: 0.6rem;
    bottom: auto;
    left: auto;
    right: 0.6rem;
    background: #8b5cf6;
}

@media (max-width: 768px) {
    /* Narrow phones: the label would crowd out the search field, so the
       filter control shows just its icon (the aria-label carries the name). */
    .sw-filter-btn {
        padding: 0.65rem 0.85rem;
    }

    .sw-filter-btn .sw-filter-label {
        display: none;
    }

    .sw-tab {
        padding: 0.6rem 1.05rem 0;
    }

    .sw-tab-icon {
        width: 46px;
        height: 46px;
        font-size: 1.15rem;
    }

    .sw-tab-label {
        font-size: 0.78rem;
    }
}

/* Card cells all share the row height, so the price and the action row have
   to be pinned to the bottom - otherwise a two-line description pushes them
   down and the buttons zig-zag across the row. */
.grid-products .product-card {
    display: flex;
    flex-direction: column;
}

.grid-products .product-info {
    display: flex;
    flex-direction: column;
    flex: 1;
}

/* Descriptions vary a lot in length; clamp to two lines so every card gives
   the same amount of room to it. */
.grid-products .product-info > p {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 2.7em;
}

.grid-products .product-actions {
    margin-top: auto;
}

/* Customer page header
   ------------------------------------------------------------------
   The catalogue page moved to a flat header when it was rebuilt; cart,
   checkout, rooms and the order confirmation kept the old full-bleed
   gradient banner, so the customer site read as two different designs on a
   desktop screen. This is that same flat treatment, shared. */
.page-head,
.sw-header {
    background: var(--bg-card);
    border-bottom: 1px solid var(--border-color);
    padding: 1.75rem 0 1.35rem;
    margin: -2rem -2rem 1.75rem -2rem;
}

/* The catalogue header has no single inner wrapper, so each child forms the
   centred column itself - same width and gutters as .page-head .container. */
.sw-header > * {
    max-width: 1440px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 2rem;
    padding-right: 2rem;
}

@media (max-width: 768px) {
    .sw-header > * {
        padding-left: 1rem;
        padding-right: 1rem;
    }
}

.page-head .container {
    max-width: 1440px;
    margin: 0 auto;
    padding: 0 2rem;
}

.page-head h1 {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 0.25rem;
    letter-spacing: -0.01em;
}

.page-head p {
    color: var(--text-secondary);
    font-size: 0.9rem;
    margin: 0;
}

@media (max-width: 768px) {
    .page-head,
    .sw-header {
        margin: -1rem -1rem 1.25rem -1rem;
        padding: 1.25rem 0 1rem;
    }

    .page-head .container {
        padding: 0 1rem;
    }
}

/* On a large monitor the 1200px cap leaves a lot of the screen unused, and
   it made the catalogue (which also spends 300px on its filter sidebar) look
   cramped next to the other pages. One shared width keeps every page's
   header and content aligned on the same column. */
@media (min-width: 1500px) {
    .main-area > .container {
        max-width: 1440px;
    }
}

/* Payment method picker (checkout) and the transfer panel (confirmation).
   ------------------------------------------------------------------ */
.pay-options {
    display: grid;
    gap: 0.6rem;
}

.pay-option {
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-btn);
    background: var(--bg-card);
    cursor: pointer;
}

.pay-option:hover {
    border-color: var(--accent-color);
}

/* the whole row reads as selected, not just the dot */
.pay-option:has(input:checked) {
    border-color: var(--accent-color);
    background: var(--bg-secondary);
}

.pay-option input {
    margin-top: 0.2rem;
    flex: 0 0 auto;
}

.pay-option strong {
    display: block;
    color: var(--text-primary);
    font-size: 0.95rem;
}

.pay-option small {
    color: var(--text-secondary);
    font-size: 0.82rem;
}

.pay-panel-body {
    display: flex;
    flex-wrap: wrap;
    gap: 1.75rem;
    padding: 1.5rem;
    align-items: flex-start;
}

.pay-qr {
    flex: 0 0 300px;
    max-width: 100%;
}

.pay-qr img {
    width: 100%;
    height: auto;
    border-radius: var(--radius-card);
    border: 1px solid var(--border-color);
    background: #fff;   /* the QR must stay on white to stay scannable */
}

.pay-info {
    flex: 1 1 280px;
    min-width: 0;
}

.pay-hint {
    color: var(--text-secondary);
    margin: 0 0 1rem;
    font-size: 0.92rem;
}

.pay-rows {
    margin: 0 0 1rem;
}

.pay-rows > div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.55rem 0;
    border-bottom: 1px solid var(--border-color);
}

.pay-rows dt {
    color: var(--text-secondary);
    font-size: 0.88rem;
}

.pay-rows dd {
    margin: 0;
    color: var(--text-primary);
    font-weight: 600;
    text-align: right;
    word-break: break-word;
}

.pay-amount {
    color: var(--accent-color);
    font-size: 1.05rem;
}

.pay-content {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 3px 8px;
    font-size: 0.9rem;
    letter-spacing: 0.02em;
}

.pay-warn {
    margin: 0;
    padding: 0.7rem 0.9rem;
    border-radius: var(--radius-btn);
    background: color-mix(in srgb, var(--warning-color) 12%, transparent);
    color: var(--text-primary);
    font-size: 0.87rem;
}

@media (max-width: 640px) {
    .pay-panel-body {
        padding: 1rem;
        gap: 1.25rem;
    }

    .pay-qr {
        flex-basis: 100%;
    }
}

/* Site footer: a single line of contact detail. */
.site-footer {
    margin-top: auto;
    padding: 1.5rem 2rem;
    border-top: 1px solid var(--border-color);
    text-align: center;
    color: var(--text-secondary);
    font-size: 0.9rem;
}

.site-footer p {
    margin: 0;
}

.site-footer a {
    color: var(--accent-color);
    font-weight: 600;
    text-decoration: none;
}

.site-footer a:hover {
    text-decoration: underline;
}

/* Shown only once the browser confirms the site is installable - see the
   beforeinstallprompt handler in modern_base.html. Hidden by default so it
   never sits there doing nothing on a browser that cannot install it. */
.install-app-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.9rem;
    padding: 0.55rem 1.1rem;
    border: 1px solid var(--accent-color);
    border-radius: var(--radius-pill);
    background: var(--bg-card);
    color: var(--accent-color);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
}

.install-app-btn img {
    width: 20px;
    height: 20px;
    border-radius: 5px;
}

.install-app-btn:hover {
    background: var(--accent-color);
    color: #fff;
}

@media (hover: none), (pointer: coarse) {
    .install-app-btn:hover {
        background: var(--bg-card);
        color: var(--accent-color);
    }
}

/* Touch devices: no hover, real press feedback
   ===================================================================
   A phone has no pointer, so tapping something applies :hover and leaves it
   applied until you tap somewhere else. Every lift-and-shadow hover in this
   file therefore stuck to whatever you last touched - a button left sitting
   raised with a drop shadow, which is the "trail" behind taps. The gradient
   sweep on .btn had the same problem: it ran across on tap and then parked
   at the far edge.

   So: hover effects are switched off wherever there is no real pointer, and
   replaced with a press state that ends the moment the finger lifts. */
@media (hover: none), (pointer: coarse) {
    .btn:hover,
    .btn-primary:hover,
    .btn-secondary:hover,
    .card:hover,
    .product-card:hover,
    .theme-toggle:hover {
        transform: none;
    }

    /* Each of these keeps whatever shadow it has at rest. Spelled out rather
       than `inherit`, which would have pulled in the parent's shadow instead
       of the element's own. */
    .card:hover,
    .product-card:hover,
    .theme-toggle:hover {
        box-shadow: var(--shadow-md);
    }

    .btn-primary:hover {
        box-shadow: 0 4px 14px rgba(47, 155, 255, 0.32);
    }

    /* Colour was the half this block forgot. Tapping the outline cart button
       left it filled in solid blue until you tapped somewhere else, and the
       0.25s background transition made that look like a lagging effect. Each
       of these keeps its resting colours under a finger. */
    .btn-outline:hover {
        background: transparent;
        color: var(--accent-color);
    }

    /* resting values spelled out, never `inherit` - that would pull the
       parent's colours in rather than the element's own */
    .btn-secondary:hover,
    .quantity-btn:hover {
        background: var(--bg-secondary);
        color: var(--text-primary);
    }

    .sw-filter-btn:hover {
        background: var(--bg-card);
        border-color: var(--border-color);
        color: var(--text-primary);
    }

    .pay-option:hover {
        background: var(--bg-card);
        border-color: var(--border-color);
    }

    .sw-tab:hover,
    .nav-link:hover {
        color: var(--text-secondary);
    }

    .table tbody tr:hover {
        background: transparent;
    }

    .sw-chip:hover {
        background: var(--bg-card);
        border-color: var(--border-color);
        color: var(--text-secondary);
    }

    /* the selected chip keeps its filled look - that is state, not hover */
    .sw-chip.active:hover {
        background: var(--accent-color);
        border-color: var(--accent-color);
        color: #fff;
    }

    .product-card:hover .product-image {
        transform: none;
    }

    /* the sweep only ever looked right following a mouse across the button */
    .btn::before,
    .btn:hover::before {
        display: none;
    }

    /* Press feedback instead: it tracks the finger exactly, so nothing is
       left behind when the tap ends. Scale rather than translate, because a
       translate leaves a gap the parent has to repaint. */
    .btn:active,
    .quick-chip:active,
    .sw-chip:active,
    .pos-item:active,
    .orders-filter:active {
        transform: scale(0.97);
        transition-duration: 0.06s;
    }

    .product-card:active {
        transform: scale(0.995);
        transition-duration: 0.06s;
    }

    /* Android draws its own grey box over anything tapped, on top of the
       press state above; ours is enough. */
    a, button, .btn, .pos-item, .product-card, .sw-tab, label {
        -webkit-tap-highlight-color: transparent;
    }
}

/* The entrance animation slides content up 20px on every page load. On a
   phone that reads as the whole page shuddering into place, and it runs on
   dozens of cards at once. Keep a plain fade there - no movement to smear. */
@media (max-width: 768px) {
    @keyframes fadeIn {
        from { opacity: 0; }
        to   { opacity: 1; }
    }

    .fade-in {
        animation-duration: 0.25s;
    }
}

/* Anyone who has asked their phone to reduce motion means it. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Splash spinner. The overlay used to be the cover of an intro carousel with
   a "tap to start" prompt; now it dismisses itself, so it shows progress
   instead of asking for a tap. */
.onboarding-cover-spinner {
    width: 34px;
    height: 34px;
    margin: 1.5rem auto 0;
    border: 3px solid rgba(255, 255, 255, 0.25);
    border-top-color: #fff;
    border-radius: 50%;
    animation: splash-spin 0.8s linear infinite;
}

@keyframes splash-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .onboarding-cover-spinner { animation-duration: 2.4s; }
}

/* Brand mark in the sidebar and mobile bar. It is the uploaded icon rather
   than a fixed glyph, so changing the logo on /admin/seo changes the header
   too - otherwise the tab and the header would show different marks. */
.brand-logo {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    object-fit: cover;
    vertical-align: -6px;
    flex-shrink: 0;
}

/* Fly-to-cart
   ------------------------------------------------------------------
   The cart link is in the sidebar, which on a phone is a closed drawer, so
   there is nothing on screen to fly to. The badge in the mobile bar is the
   visible stand-in; when neither is on screen the animation is skipped and
   only the badge count updates - a shape flying to nowhere is worse than no
   animation. */
.fly-item {
    position: fixed;
    z-index: 5000;
    pointer-events: none;
    border-radius: 50%;
    width: 22px;
    height: 22px;
    background: var(--gradient-accent);
    color: #fff;
    display: grid;
    place-items: center;
    font-size: 11px;
    box-shadow: var(--shadow-md);
    /* the curve makes it lift away first and drop into the cart, rather than
       sliding in a straight line */
    transition: transform 0.62s cubic-bezier(0.55, -0.35, 0.35, 1),
                opacity 0.62s ease;
}

.cart-bump {
    animation: cart-bump 0.42s ease;
}

@keyframes cart-bump {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.28); }
    60%  { transform: scale(0.94); }
    100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .fly-item { transition-duration: 0.01ms; }
    .cart-bump { animation: none; }
}

/* Cart button in the mobile bar. */
.topbar-cart {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 10px;
    background: var(--bg-secondary);
    color: var(--text-primary);
    text-decoration: none;
    flex-shrink: 0;
}

/* An explicit display always beats the hidden attribute, so anything that
   sets one has to opt back out. This badge showed a "0" on an empty cart
   because of it. */
[hidden] { display: none !important; }

.topbar-cart .cart-count {
    position: absolute;
    top: -5px;
    right: -5px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--danger-color);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    display: grid;
    place-items: center;
    border: 2px solid var(--bg-card);
}

/* Confirmation for an add that no longer reloads the page. */
.cart-toast {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translate(-50%, 16px);
    z-index: 5200;
    max-width: min(90vw, 420px);
    padding: 0.7rem 1.1rem;
    border-radius: var(--radius-pill);
    background: var(--text-primary);
    color: var(--bg-card);
    font-size: 0.875rem;
    font-weight: 600;
    box-shadow: var(--shadow-lg);
    opacity: 0;
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.cart-toast.show {
    opacity: 1;
    transform: translate(-50%, 0);
}

.cart-toast.is-error {
    background: var(--danger-color);
    color: #fff;
}

/* On a phone the toast covers part of a screen that is already tight, and the
   flying item plus the badge ticking up already say the tap worked. The text
   is for pointer-sized screens, where there is room for it. */
@media (max-width: 768px) {
    .cart-toast { display: none !important; }
}
