/* ============================================================================
   GruvWishlist — Design System
   Light theme: cream backgrounds, dark olive green text, warm gold accents.
   ========================================================================== */

:root {
    /* Brand palette */
    --c-bg:        #F5F2E8;
    --c-surface:   #FFFFFF;
    --c-surface-2: #EFEBDD;
    --c-border:    rgba(30, 38, 1, 0.10);
    --c-border-strong: rgba(30, 38, 1, 0.20);

    --c-ink:       #1E2601;
    --c-ink-2:     #2C4001;
    --c-ink-mute:  #4A5236;
    --c-ink-dim:   #6E7559;

    --c-accent:    #405908;
    --c-accent-2:  #2C4001;
    --c-gold:      #A67F38;
    --c-gold-soft: #C9A35F;
    --c-gold-tint: rgba(166, 127, 56, 0.12);

    --c-danger:    #8A2A1F;
    --c-danger-tint: rgba(138, 42, 31, 0.10);
    --c-success:   #405908;

    /* Type scale (1.25 ratio) */
    --fs-xs:  0.75rem;
    --fs-sm:  0.875rem;
    --fs-md:  1rem;
    --fs-lg:  1.125rem;
    --fs-xl:  1.25rem;
    --fs-2xl: 1.563rem;
    --fs-3xl: 1.953rem;
    --fs-4xl: 2.441rem;

    /* Spacing scale */
    --sp-1: 0.25rem;
    --sp-2: 0.5rem;
    --sp-3: 0.75rem;
    --sp-4: 1rem;
    --sp-5: 1.25rem;
    --sp-6: 1.5rem;
    --sp-8: 2rem;
    --sp-10: 2.5rem;
    --sp-12: 3rem;
    --sp-16: 4rem;

    /* Radii + shadows */
    --r-sm: 4px;
    --r-md: 8px;
    --r-lg: 12px;
    --r-pill: 9999px;
    --shadow-1: 0 1px 2px rgba(10, 13, 0, 0.06), 0 1px 1px rgba(10, 13, 0, 0.04);
    --shadow-2: 0 4px 12px rgba(10, 13, 0, 0.08);
    --shadow-3: 0 8px 24px rgba(10, 13, 0, 0.12);

    /* Type families */
    --ff-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --ff-display: "Inter", var(--ff-sans);
    --ff-mono: ui-monospace, SFMono-Regular, Menlo, monospace;

    /* Layout */
    --header-height: 64px;
    --content-max: 1280px;

    /* Motion */
    --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* ---- Reset / base ---- */

*, *::before, *::after { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--c-bg);
    color: var(--c-ink);
    font-family: var(--ff-sans);
    font-size: var(--fs-md);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    /* Brand-tinted tap highlight on iOS / Android Chrome instead of the default
       translucent grey rectangle. Subtle gold matches the link hover state. */
    -webkit-tap-highlight-color: rgba(166, 127, 56, 0.20);
}

img { max-width: 100%; height: auto; display: block; }

a {
    color: var(--c-accent);
    text-decoration: none;
    transition: color 120ms var(--ease-out);
}
a:hover { color: var(--c-accent-2); text-decoration: underline; }

h1, h2, h3, h4, h5, h6 {
    font-family: var(--ff-display);
    color: var(--c-ink-2);
    margin: 0 0 var(--sp-3);
    line-height: 1.2;
    letter-spacing: -0.01em;
}
h1 { font-size: var(--fs-3xl); }
h2 { font-size: var(--fs-2xl); }
h3 { font-size: var(--fs-xl); }
h4 { font-size: var(--fs-lg); }

p { margin: 0 0 var(--sp-4); }
small { font-size: var(--fs-sm); color: var(--c-ink-mute); }

/* ---- Site header (used by Blazor MainLayout AND Razor Pages _Layout) ----
   Lives in global app.css rather than a scoped .razor.css file because the same
   class names are rendered both from the Blazor SiteHeader component AND from
   the Razor Pages _SiteHeader.cshtml partial. A scoped CSS file would only apply
   to the Blazor surface (Blazor injects a [b-xyz] attribute selector), leaving
   the Razor Pages unstyled. Header is layout chrome — its styles are
   conceptually global, not component-private. */
.site-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: var(--c-surface-2);
    border-bottom: 1px solid var(--c-border);
    backdrop-filter: blur(6px);
}

.site-header-inner {
    max-width: var(--content-max);
    margin: 0 auto;
    height: var(--header-height);
    padding: 0 var(--sp-6);
    display: flex;
    align-items: center;
    gap: var(--sp-6);
}

.brand {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    text-decoration: none;
    color: var(--c-ink-2);
    font-family: var(--ff-display);
    font-weight: 700;
    font-size: var(--fs-lg);
    letter-spacing: -0.01em;
    flex-shrink: 0;
}
.brand:hover { text-decoration: none; color: var(--c-accent); }

.brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--r-sm);
    background: var(--c-ink-2);
    color: var(--c-bg);
    font-size: var(--fs-sm);
    font-weight: 700;
    letter-spacing: 0;
}

.site-nav {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex: 1;
}

.site-nav-link {
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--r-sm);
    color: var(--c-ink-mute);
    font-size: var(--fs-md);
    font-weight: 500;
    text-decoration: none;
    transition: background 100ms var(--ease-out), color 100ms var(--ease-out);
}
.site-nav-link:hover { background: var(--c-bg); color: var(--c-ink-2); text-decoration: none; }
.site-nav-link.active { color: var(--c-accent-2); background: var(--c-bg); }

.site-header-right {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}

.hamburger {
    display: none;
    background: none;
    border: 1px solid var(--c-border-strong);
    border-radius: var(--r-sm);
    /* 12px padding x 2 + 20px content = 44px hit area — meets WCAG 2.5.5 + Apple HIG. */
    padding: 12px;
    cursor: pointer;
    flex-direction: column;
    gap: 4px;
    margin-left: auto;
    min-width: 44px;
    min-height: 44px;
}
.hamburger span {
    display: block;
    width: 18px;
    height: 2px;
    background: var(--c-ink-2);
    border-radius: 1px;
}
.hamburger:focus-visible { outline: 2px solid var(--c-gold); outline-offset: 2px; }

/* Mobile-only search form inside the open hamburger panel. */
.site-nav-search { display: none; }

@media (max-width: 768px) {
    .site-header-inner { gap: var(--sp-3); padding: 0 var(--sp-4); }
    .hamburger { display: inline-flex; }

    /* Hide the inline HeaderSearchBox (Blazor island) on mobile — the site-nav-search
       inside the hamburger panel takes over. Targeted directly (not via ::deep) since
       both the Blazor child component AND the bare .header-search-equivalent absence
       on Razor Pages are non-issues — the rule simply matches whatever .header-search
       exists in the DOM. */
    .site-header-right .header-search { display: none; }

    .site-nav {
        position: absolute;
        top: var(--header-height);
        left: 0;
        right: 0;
        background: var(--c-surface);
        border-bottom: 1px solid var(--c-border);
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        padding: var(--sp-2);
        max-height: 0;
        overflow: hidden;
        transition: max-height 200ms var(--ease-out);
    }
    .site-nav.open {
        max-height: 420px;
        padding-top: var(--sp-2);
        padding-bottom: var(--sp-2);
    }
    .site-nav-link { padding: var(--sp-3); border-radius: 0; min-height: 44px; display: flex; align-items: center; }

    .site-nav-search {
        display: flex;
        gap: var(--sp-2);
        padding: var(--sp-2);
        border-bottom: 1px solid var(--c-border);
        margin-bottom: var(--sp-1);
    }
    .site-nav-search input[type="search"] {
        flex: 1;
        font-size: 16px; /* iOS Safari focus-zoom guard. */
        min-width: 0;
    }
}

@media (max-width: 380px) {
    .brand-text { display: none; }
}

/* ---- Site footer (used by Blazor MainLayout AND Razor Pages _Layout) ----
   Promoted to global for the same reason as the header — same markup, two surfaces. */
.site-footer {
    background: var(--c-surface-2);
    border-top: 1px solid var(--c-border);
    margin-top: var(--sp-12);
}
.site-footer-inner {
    max-width: var(--content-max);
    margin: 0 auto;
    padding: var(--sp-6);
    text-align: center;
    color: var(--c-ink-mute);
}

/* ---- Layout container ---- */

/* Skip-to-content link — visible only on focus. WCAG 2.4.1 (bypass repetitive blocks).
   Positioned absolute so it doesn't reserve layout space when off-screen; transitions
   into view at top-left when a keyboard user tabs into the page. */
.skip-link {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 1000;
    padding: var(--sp-2) var(--sp-3);
    background: var(--c-accent);
    color: var(--c-surface);
    font-weight: 500;
    border-radius: var(--r-sm);
    text-decoration: none;
    transform: translateY(-200%);
    transition: transform 120ms var(--ease-out);
}
.skip-link:focus,
.skip-link:focus-visible {
    transform: translateY(0);
    outline: 2px solid var(--c-gold);
    outline-offset: 2px;
    color: var(--c-surface);
    text-decoration: none;
}

main {
    max-width: var(--content-max);
    margin: 0 auto;
    padding: var(--sp-6) var(--sp-6) var(--sp-12);
    min-height: calc(100vh - var(--header-height) - 80px);
}
/* Suppress focus outline on programmatically-focused elements. The `tabindex="-1"`
   convention means "not in the natural tab order, only .focus()-able by code" —
   used by:
     - <main id="main" tabindex="-1"> (skip-link target; Safari needs it for fragment-focus)
     - <h1> after Blazor's <FocusOnNavigate Selector="h1" /> (sets tabindex=-1 + .focus()
       on every navigation so screen readers announce the page heading)
     - <a aria-hidden="true" tabindex="-1"> thumbnail links in Wishlist cards
   Sighted users didn't press Tab to land on these — they're focused programmatically
   for accessibility-tool benefit. A visible focus ring around a block-level h1 or
   <main> renders as a full-width rectangle that looks like a layout bug. */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
    outline: none;
}

@media (max-width: 640px) {
    main { padding: var(--sp-4) var(--sp-4) var(--sp-8); }
}

section { margin-bottom: var(--sp-12); }

/* Section header: h2 on the left, "View all" link on the right. */
.section-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    flex-wrap: wrap;
}
.section-header h2 { margin: 0; }
.view-all {
    color: var(--c-ink-mute);
    text-decoration: none;
    font-size: var(--fs-sm);
    font-weight: 500;
    white-space: nowrap;
}
.view-all:hover { color: var(--c-gold); text-decoration: underline; }

/* ---- Card grid (responsive product cards) ----
   Auto-fits as many 200px-wide columns as fit, growing to fill the row.
   `auto-fit` (not `auto-fill`) is intentional — it collapses empty column
   tracks at the end of the last row so a partial row of cards stretches to
   the full width instead of leaving a phantom empty slot.
   Browse/Home/Wishlist all use this. */

.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--sp-4);
    margin-bottom: var(--sp-6);
}

/* Compact grid: tighter columns and gap for secondary rails (e.g. homepage DVD rail). */
.card-grid-compact {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--sp-3);
}

@media (max-width: 480px) {
    .card-grid {
        grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
        gap: var(--sp-3);
    }
    .card-grid-compact {
        grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    }
}

/* Mobile filter tweaks moved next to the .filters base block — see the
   @media (max-width: 640px) block right after the .filters definition. */

@media (max-width: 768px) {
    .search-filterbar select { font-size: 16px; }
}

/* DVD rail sits visually below the primary content. */
.dvd-rail-heading { color: var(--c-ink-mute); font-size: var(--fs-lg); }

/* Search page form (bigger than the header search box) and result tiles. */
.search-form {
    display: flex;
    gap: var(--sp-3);
    margin-bottom: var(--sp-3);
}
.search-form input[type="search"] {
    flex: 1;
    font-size: var(--fs-md);
}
.search-results {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    margin-bottom: var(--sp-6);
}
.search-hit {
    position: relative; /* anchor for the absolutely-positioned WishlistAddButton at top-right */
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    /* Reserve the right edge for the 32x32 wishlist button (offset 8px from the right) so
       the title/price can't run under it on narrow widths. 32 + 8 + 8 = 48px clearance. */
    padding: var(--sp-3) calc(var(--sp-2) + 40px) var(--sp-3) var(--sp-3);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    transition: border-color 100ms var(--ease-out), box-shadow 100ms var(--ease-out);
}
.search-hit:hover { border-color: var(--c-border-strong); box-shadow: var(--shadow-1); }
.search-hit-link {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    flex: 1;
    min-width: 0;
    color: inherit;
    text-decoration: none;
}
.search-hit-link:hover { color: inherit; text-decoration: none; }
.search-hit-thumb {
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-sm);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.search-hit-thumb img { width: 100%; height: 100%; object-fit: contain; }
.search-hit-body { min-width: 0; flex: 1; }
.search-hit-title { margin: 0 0 4px 0; font-size: var(--fs-md); color: var(--c-ink); }
.search-hit-meta { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); color: var(--c-ink-mute); flex-wrap: wrap; }
.search-hit-meta .vendor { color: var(--c-ink-dim); }
.search-hit-price { margin-left: auto; color: var(--c-ink-2); font-weight: 500; }

/* Inline single-row format filter (used on /new). Compact alternative to the
   full .filters block on /browse. Auto-submits on change via inline onchange,
   so the fieldset's aria-label tells screen readers to expect that. */
.format-filter {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
    margin-bottom: var(--sp-4);
}
.format-filter-group {
    border: 0;
    padding: 0;
    margin: 0;
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
}
.format-filter-label {
    color: var(--c-ink-mute);
    font-size: var(--fs-sm);
    padding: 0;
    margin: 0 var(--sp-1) 0 0;
    float: none;
    width: auto;
}
.format-filter label {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    margin: 0;
    font-size: var(--fs-sm);
    color: var(--c-ink);
    cursor: pointer;
}
.format-filter label input { margin: 0; }

/* ---- /search filterbar (unified format chips + sort dropdown) ----
   Parallel-shape groups so the Format chips and the Sort dropdown share the same vertical
   alignment, label color, and spacing. Both groups are <div role="group"> with a leading
   <span>/<label> caption — the previous fieldset/legend pattern caused the format group to
   render half a pixel out of alignment with the select because legends carry implicit
   baseline shift even when border:0. /new still uses the older .format-filter rules above. */
.search-filterbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-4);
    margin-bottom: var(--sp-4);
}
.search-filterbar-group {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-3);
    min-height: 32px; /* match select min-height so wrapping rows still align */
}
.search-filterbar-group--right {
    margin-left: auto;
}
.search-filterbar-label {
    color: var(--c-ink-mute);
    font-size: var(--fs-sm);
    margin: 0;
}
.search-filterbar-check {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    margin: 0;
    font-size: var(--fs-sm);
    color: var(--c-ink);
    cursor: pointer;
}
.search-filterbar-check input {
    margin: 0;
}
.search-filterbar select {
    font-size: var(--fs-sm);
    padding: 4px 8px;
    border: 1px solid var(--c-border);
    border-radius: var(--r-sm);
    background: var(--c-surface);
    color: var(--c-ink);
}

/* ---- Browse filters (top-of-page, horizontal) ---- */

.filters {
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    gap: var(--sp-4);
    padding: var(--sp-4);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    margin-bottom: var(--sp-6);
}
.filters label { display: flex; flex-direction: column; gap: var(--sp-1); margin: 0; }
.filters label.check { flex-direction: row; align-items: center; gap: var(--sp-2); }
.filters label.check input { margin: 0; }
.filters select, .filters input[type="text"], .filters input[type="search"], .filters input:not([type]) { min-width: 160px; }

/* Mobile override for the .filters block. MUST come AFTER the .filters base
   rules above (same specificity) so the cascade picks the mobile declarations
   on small viewports — an earlier draft put this rule higher in the file and
   was silently overridden by the desktop min-width: 160px declaration at every
   viewport. The visual fix only worked by accident because the labels were
   wider than 160px on tested phone sizes; narrower viewports (iPhone SE) would
   have regressed.

   IMPORTANT: the `flex: 1 1 140px` is INTENTIONALLY on the LABEL only, never
   on the controls. Labels are `flex-direction: column` flex containers; a
   `flex-basis: 140px` on a child select would set the COLUMN's main axis =
   VERTICAL, making selects 140px TALL (verified before this fix). Width on
   the controls fills naturally via the explicit width: 100%. */
@media (max-width: 640px) {
    .filters select,
    .filters input[type="text"],
    .filters input[type="search"],
    .filters input:not([type]) {
        min-width: 0;
        width: 100%;
    }
    .filters label { flex: 1 1 140px; }
}

.result-count {
    font-size: var(--fs-sm);
    color: var(--c-ink-mute);
    margin-bottom: var(--sp-3);
}

.pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-4);
    padding: var(--sp-4) 0;
}
.pager span { color: var(--c-ink-mute); }

/* ---- Product detail two-column ---- */

.product-detail {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    column-gap: var(--sp-8);
    align-items: start;
}
@media (max-width: 768px) {
    .product-detail { grid-template-columns: 1fr; column-gap: var(--sp-6); }
}
.product-images img { width: 100%; border-radius: var(--r-lg); border: 1px solid var(--c-border); background: var(--c-surface); }

/* On narrow viewports the portrait 2:3 product hero would otherwise consume the entire
   first scroll of the page. Cap height + let width auto so it sits as a focused product
   shot, centred, with breathing room below for the buy CTA + price chart. The HTML
   width/height attributes on the <img> are preserved so the browser still reserves
   CLS-safe layout space before the image bytes arrive. */
@media (max-width: 768px) {
    .product-images img {
        width: auto;
        max-width: 100%;
        max-height: 60vh;
        margin: 0 auto;
    }
}
.product-info { display: flex; flex-direction: column; gap: var(--sp-4); }
.product-meta { color: var(--c-ink-mute); font-size: var(--fs-sm); margin: 0; }
.price-row { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.price-row.big { font-size: var(--fs-xl); }
.product-description { color: var(--c-ink-mute); line-height: 1.6; }
.product-description :is(p, ul, ol) { margin-bottom: var(--sp-3); }
/* About is a sibling of .product-detail, sitting full-width below it.
   Tight margin-top + zeroed h2 top margin keeps it visually close to the
   end of the right column (the price chart) while letting the prose
   span the entire content width. The global section { margin-bottom }
   still applies so anything after About gets normal spacing. */
.product-about { margin: var(--sp-3) 0 0 0; }
.product-about > :first-child { margin-top: 0; }

/* Syncfusion chart wrapper — see ProductDetail.razor. Lets the chart force Width 100%
   on the inner SVG without overflowing the layout grid on narrow viewports. */
.chart-scroll {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Long-form static pages (privacy, terms, etc.) — readable measure + comfortable spacing. */
.static-page {
    max-width: 70ch;
    margin: var(--sp-6) auto;
    padding: 0 var(--sp-4);
    color: var(--c-ink);
    line-height: 1.6;
}
.static-page h1 { margin-top: 0; }
.static-page h2 { margin-top: var(--sp-6); }
.static-page h3 { margin-top: var(--sp-4); }
.static-page-meta { color: var(--c-ink-mute); font-size: var(--fs-sm); }
.static-page :is(ul, ol) { padding-left: 1.5em; }
.static-page li { margin-bottom: var(--sp-1); }

/* ---- Auth / Account pages (Razor Pages) ----
   The Identity flow pages (Login, Manage, Logout, ExternalLogin, AccessDenied) share
   _Layout.cshtml which renders the standard site header + footer. Per-page content
   uses these classes to match the rest of the design system — replacing the prior
   inline styles which were both rule-violating (no inline CSS) and visually
   inconsistent with the Blazor pages. */
.auth-page {
    max-width: 480px;
    margin: var(--sp-6) auto;
    padding: 0 var(--sp-4);
    color: var(--c-ink);
    line-height: 1.6;
}
.auth-page-wide { max-width: 640px; }
.auth-page h1 { margin-top: 0; }
.auth-page h2 { margin-top: var(--sp-6); }

.auth-provider-form {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    margin-top: var(--sp-4);
}
.auth-provider-button {
    /* Full-width sign-in buttons stack vertically on every viewport. The .gw-btn-lg
       padding from the design system gives them ~48px height which doubles as a
       comfortable touch target on mobile. */
    width: 100%;
}

.auth-error {
    padding: var(--sp-3) var(--sp-4);
    background: var(--c-danger-tint);
    color: var(--c-danger);
    border: 1px solid var(--c-danger);
    border-radius: var(--r-md);
}

.auth-banner {
    margin: var(--sp-4) 0;
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--r-md);
    border: 1px solid var(--c-border-strong);
}
.auth-banner-error {
    background: var(--c-danger-tint);
    color: var(--c-danger);
    border-color: var(--c-danger);
}
.auth-banner-success {
    background: rgba(64, 89, 8, 0.10);
    color: var(--c-success);
    border-color: var(--c-success);
}

.auth-section { margin-top: var(--sp-8); }

.auth-provider-list {
    list-style: none;
    padding: 0;
    margin: var(--sp-3) 0 0 0;
}
.auth-provider-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-3) 0;
    border-bottom: 1px solid var(--c-border);
}
.auth-provider-row:last-child { border-bottom: none; }
.auth-hint {
    font-style: italic;
    color: var(--c-ink-mute);
    margin-top: var(--sp-2);
}

.auth-link-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

/* Danger zone — bordered card with brand danger colour to signal irreversible action. */
.auth-danger-zone {
    margin-top: var(--sp-12);
    padding: var(--sp-4);
    border: 1px solid var(--c-danger);
    border-radius: var(--r-md);
    background: var(--c-danger-tint);
}
.auth-danger-zone h2 {
    color: var(--c-danger);
    margin-top: 0;
}
.auth-danger-label {
    display: block;
    margin-bottom: var(--sp-2);
    color: var(--c-ink);
    font-size: var(--fs-md);
}
.auth-danger-input {
    width: 100%;
    max-width: 320px;
    /* iOS Safari focus-zoom guard — bump to 16px since this input is rendered on mobile. */
    font-size: 16px;
    margin-bottom: var(--sp-3);
    display: block;
}

/* Logout button in the standard header (Razor-Pages-rendered _SiteHeader). Inline-flex
   so the form wrapper doesn't add a paragraph-style margin around the button. */
.site-header-logout {
    margin: 0;
    padding: 0;
    display: inline-flex;
}

.site-footer-sep { color: var(--c-ink-mute); margin: 0 var(--sp-2); }

/* ---- Wishlist ---- */

.wishlist-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    overflow: hidden;
}
.wishlist-table th, .wishlist-table td {
    padding: var(--sp-3);
    text-align: left;
    border-bottom: 1px solid var(--c-border);
    vertical-align: middle;
}
.wishlist-table th { background: var(--c-surface-2); font-weight: 500; color: var(--c-ink-mute); font-size: var(--fs-sm); }
.wishlist-table tr:last-child td { border-bottom: none; }
.wishlist-table .meta { color: var(--c-ink-mute); font-size: var(--fs-xs); margin-top: 2px; }
.wishlist-table .oos { margin-left: var(--sp-2); color: var(--c-danger); font-size: var(--fs-xs); }
.wishlist-item-cell { display: flex; align-items: center; gap: var(--sp-3); }
.wishlist-thumb {
    flex: 0 0 auto;
    width: 56px;
    height: 56px;
    border-radius: var(--r-md);
    border: 1px solid var(--c-border);
    background: var(--c-surface-2);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.wishlist-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wishlist-thumb-placeholder { font-size: var(--fs-xs); color: var(--c-ink-mute); text-align: center; padding: 0 4px; }
.wishlist-item-text { min-width: 0; }

/* Mobile card layout — replaces the table at ≤640px. Same data, but each item
   becomes a stacked card so columns don't crush and the Remove button can be a
   comfortable touch target. The .wishlist-cards list is hidden on desktop; the
   table is hidden on mobile. Both surfaces share the same Remove handler so no
   state-sync concerns. */
.wishlist-cards {
    display: none;
}
@media (max-width: 640px) {
    .wishlist-table { display: none; }
    .wishlist-cards {
        display: flex;
        flex-direction: column;
        gap: var(--sp-3);
        list-style: none;
        margin: 0;
        padding: 0;
    }
}
.wishlist-card {
    display: flex;
    gap: var(--sp-3);
    padding: var(--sp-3);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
}
.wishlist-card-thumb {
    flex: 0 0 auto;
    width: 72px;
    height: 108px;
    border-radius: var(--r-sm);
    border: 1px solid var(--c-border);
    background: var(--c-surface-2);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.wishlist-card-thumb img { width: 100%; height: 100%; object-fit: cover; }
.wishlist-card-body { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; flex: 1; }
.wishlist-card-title {
    font-weight: 500;
    color: var(--c-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.wishlist-card-meta { font-size: var(--fs-xs); color: var(--c-ink-mute); }
.wishlist-card-price-row { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-1); }
.wishlist-card-price-row .oos { color: var(--c-danger); font-size: var(--fs-xs); }
.wishlist-card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: auto;
    padding-top: var(--sp-2);
    gap: var(--sp-2);
}
.wishlist-card-footer small { color: var(--c-ink-mute); }

/* ---- Buttons (extends Syncfusion's e-btn but works standalone) ---- */

.gw-btn,
button.gw-btn,
a.gw-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-4);
    border-radius: var(--r-md);
    border: 1px solid transparent;
    background: var(--c-surface);
    color: var(--c-ink);
    font-family: var(--ff-sans);
    font-size: var(--fs-md);
    font-weight: 500;
    line-height: 1.2;
    cursor: pointer;
    text-decoration: none;
    transition: background 120ms var(--ease-out), color 120ms var(--ease-out), box-shadow 120ms var(--ease-out);
}

.gw-btn:hover { background: var(--c-surface-2); text-decoration: none; }
.gw-btn:focus-visible {
    outline: 2px solid var(--c-gold);
    outline-offset: 2px;
}

.gw-btn-primary {
    background: var(--c-accent);
    color: var(--c-surface);
    border-color: var(--c-accent);
}
.gw-btn-primary:hover { background: var(--c-accent-2); border-color: var(--c-accent-2); color: var(--c-surface); }

.gw-btn-gold {
    background: var(--c-gold);
    color: #FFFFFF;
    border-color: var(--c-gold);
}
.gw-btn-gold:hover { background: #8C6A2D; border-color: #8C6A2D; color: #FFFFFF; }

.gw-btn-ghost {
    background: transparent;
    border-color: var(--c-border-strong);
    color: var(--c-ink);
}
.gw-btn-ghost:hover { background: var(--c-surface-2); }

.gw-btn-danger {
    background: transparent;
    border-color: var(--c-danger);
    color: var(--c-danger);
}
.gw-btn-danger:hover { background: var(--c-danger-tint); }

.gw-btn-sm { padding: var(--sp-1) var(--sp-3); font-size: var(--fs-sm); }
.gw-btn-lg { padding: var(--sp-3) var(--sp-6); font-size: var(--fs-lg); }

/* ---- Form inputs ---- */

/* ---- Form inputs ----
   Note the `input:not([type])` clause: HTML5 defaults `<input>` to type=text when
   no attribute is present, but CSS `[type="text"]` requires the attribute to be
   EXPLICITLY set. Without this fallback, bare `<input>` elements (like the
   Browse Search box) render with browser-default styling (~21px tall, no padding)
   while siblings with explicit type=text get the design-system styling — same
   element, two different looks. Catching the implicit case keeps the cascade
   honest no matter how markup is written. */
input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="search"], input:not([type]), select, textarea {
    background: var(--c-surface);
    color: var(--c-ink);
    border: 1px solid var(--c-border-strong);
    border-radius: var(--r-md);
    padding: var(--sp-2) var(--sp-3);
    font-family: var(--ff-sans);
    font-size: var(--fs-md);
    transition: border-color 120ms var(--ease-out), box-shadow 120ms var(--ease-out);
}
input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-gold-tint);
}

label { font-size: var(--fs-sm); color: var(--c-ink-mute); display: block; margin-bottom: var(--sp-1); }

/* ---- Pills / badges ---- */

.gw-pill {
    display: inline-flex;
    align-items: center;
    padding: 2px var(--sp-2);
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    font-weight: 500;
    line-height: 1.4;
}
.gw-pill-gold { background: var(--c-gold-tint); color: #6E5424; }
.gw-pill-success { background: rgba(64, 89, 8, 0.12); color: var(--c-accent-2); }
.gw-pill-danger  { background: var(--c-danger-tint); color: var(--c-danger); }
.gw-pill-mute    { background: rgba(30, 38, 1, 0.06); color: var(--c-ink-mute); }

/* ---- Status message ---- */

.status-message {
    padding: var(--sp-3) var(--sp-4);
    background: var(--c-gold-tint);
    color: var(--c-ink-2);
    border: 1px solid var(--c-gold-soft);
    border-radius: var(--r-md);
    margin-bottom: var(--sp-4);
}

/* ---- Card surface ---- */

.gw-card {
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
}

/* ---- Validation ---- */

.valid.modified:not([type=checkbox]) { outline: 1px solid var(--c-success); }
.invalid { outline: 1px solid var(--c-danger); }
.validation-message { color: var(--c-danger); font-size: var(--fs-sm); }

/* ---- Blazor error UI (kept from template, retheme) ---- */

#blazor-error-ui {
    color: #FFFFFF;
    background: var(--c-danger);
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0,0,0,.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}
#blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: 0.75rem; top: 0.5rem; }

.blazor-error-boundary {
    background: var(--c-danger);
    padding: 1rem;
    color: #FFFFFF;
    border-radius: var(--r-md);
}
.blazor-error-boundary::after { content: "An error has occurred."; }
