/*
 * ============================================================
 * 8KWALLS — MAIN STYLESHEET
 * Phase 0 — Design System Foundation
 * Version: 4.0.0
 *
 * This file is the single source of truth for all CSS tokens,
 * base resets, and global utility styles.
 * Every future phase appends component CSS to this file or
 * imports from it. Never override tokens in component CSS —
 * add a new token or request a change here.
 *
 * Agent decisions applied:
 *   ATLAS  — Accent darkened to #a8522a (WCAG AA pass, ~4.6:1)
 *   NOVA   — R2: var() wrappers throughout
 *   NOVA   — R3: --color-error-hover / --color-error-active added
 *   NOVA   — R4: Lucide icons self-hosted SVG (no CDN)
 *   NOVA   — R5: Geist self-hosted @font-face (no Google Fonts)
 *   NOVA   — R6: Shadow values tokenized
 *   NOVA   — R7: --z-modal-backdrop: 550 (50-unit buffer)
 *   NOVA   — C5: --color-scrim-card (was --color-scrim-light)
 *   NOVA   — C6: --color-accent-focus-ring / --color-error-focus-ring
 *   ECHO   — ER2: Geist Fallback @font-face for CLS mitigation
 *   ECHO   — ER3: Geist preload hint (in functions.php — noted here)
 *   MIRA   — MIR1: Hero height 50vw → 50vh (comment in hero section)
 *   MIRA   — MIR2: --text-input: 1rem (16px) — separate from --text-body
 *   MIRA   — MIR3: --btn-height-md raised to 44px universally
 *   MIRA   — MIR4: Modal bottom-sheet spec at max-width: 480px
 *
 * Pinned asset versions:
 *   Geist Variable Font:      v1.3.0
 *   JetBrains Mono Variable:  v2.304
 *   Lucide Icons:             v0.344.0
 *
 * WordPress namespace: wg-
 * No conflicts with: wp-*, Gutenberg blocks, WooCommerce
 * ============================================================
 */


/* ============================================================
   FONT FACE — Geist Variable (self-hosted)
   File: assets/fonts/Geist-Variable.woff2
   Source: https://github.com/vercel/geist-font/releases
   Version: 1.3.0 — update this comment on upgrade
   ============================================================ */

@font-face {
    font-family: 'Geist';
    src: url('../fonts/Geist-Variable.woff2') format('woff2-variations');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC,
                   U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074,
                   U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
                   U+FEFF, U+FFFD;
}

/* ============================================================
   FONT FACE — Geist Fallback (CLS mitigation)
   ECHO ER2: Prevents Cumulative Layout Shift from font-display: swap.
   Metric overrides calibrated to Geist Variable.
   This font is never rendered — it exists only to match Geist metrics
   so the system-ui fallback occupies identical space before swap.
   Verify values with `fontpie` CLI if Geist version changes.
   ============================================================ */

@font-face {
    font-family: 'Geist Fallback';
    src: local('Arial');
    ascent-override: 90%;
    descent-override: 22%;
    line-gap-override: 0%;
    size-adjust: 104%;
}

/* ============================================================
   FONT FACE — JetBrains Mono Variable (self-hosted)
   Used only on wallpaper detail pages (is_singular('wallpaper')).
   @font-face declared globally so browser defers fetch until
   the font-family is referenced in CSS. Preload hint is added
   conditionally via wp_resource_hints in functions.php.
   File: assets/fonts/JetBrainsMono-Variable.woff2
   Source: https://www.jetbrains.com/lp/mono/
   Version: 2.304 — update this comment on upgrade
   ============================================================ */

@font-face {
    font-family: 'JetBrains Mono';
    src: url('../fonts/JetBrainsMono-Variable.woff2') format('woff2-variations');
    font-weight: 100 800;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC,
                   U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074,
                   U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
                   U+FEFF, U+FFFD;
}


/* ============================================================
   ROOT — ALL DESIGN TOKENS
   All CSS custom properties live here and ONLY here.
   Never define --wg-* or --color-* tokens in component CSS.
   ============================================================ */

:root {

    /* ----------------------------------------------------------
       COLOR — BASE PALETTE
       ---------------------------------------------------------- */

    --color-bg:             #f8f7f4;   /* Page background, body */
    --color-surface:        #ffffff;   /* Cards, panels, modals, inputs */
    --color-surface-raised: #fdfcfa;   /* Dropdown menus, tooltips */
    --color-border:         #e8e5e0;   /* Input borders, dividers */
    --color-border-strong:  #d0ccc5;   /* Focus borders, active tabs */

    --color-text-primary:   #111010;   /* Headings, body text */
    --color-text-secondary: #6b6762;   /* Captions, meta, placeholder */
    --color-text-disabled:  #b5b0aa;   /* Disabled inputs, muted labels */
    --color-text-inverse:   #f8f7f4;   /* Text on dark surfaces */

    /* ----------------------------------------------------------
       COLOR — ACCENT (Warm Terracotta)
       ATLAS decision: darkened from #c2623f to #a8522a.
       #c2623f failed WCAG AA (3.1:1). #a8522a achieves ~4.6:1
       on #f8f7f4. Verified compliant for button labels and links.
       Interactive affordance only — never decorative.
       ---------------------------------------------------------- */

    --color-accent:               #a8522a;               /* Primary buttons, links, focus rings */
    --color-accent-hover:         #8e3f1e;               /* Primary button hover */
    --color-accent-active:        #743216;               /* Primary button pressed */
    --color-accent-subtle:        #f5ede9;               /* Badge fills, alert backgrounds */
    --color-accent-subtle-border: #e8cdc5;               /* Border on accent-subtle */

    /*
     * Focus ring: accent at 24% opacity.
     * NOVA C6: tokenized from inline rgba() value.
     * Used on: all interactive elements' focus outline.
     */
    --color-accent-focus-ring: rgba(168, 82, 42, 0.24);

    /* ----------------------------------------------------------
       COLOR — SEMANTIC
       ---------------------------------------------------------- */

    --color-success:        #2d7a4f;
    --color-success-subtle: #edf7f1;

    --color-error:          #c0392b;
    --color-error-hover:    #a83224;   /* NOVA R3: was orphaned hex in button spec */
    --color-error-active:   #8e2a1f;   /* NOVA R3: was orphaned hex in button spec */
    --color-error-subtle:   #fdf0ee;

    /* NOVA C6: tokenized focus ring for error state */
    --color-error-focus-ring: rgba(192, 57, 43, 0.20);

    --color-warning:        #b45309;
    --color-warning-subtle: #fef9ec;

    /* ----------------------------------------------------------
       COLOR — OVERLAY / SCRIM
       ---------------------------------------------------------- */

    /*
     * Card hover overlay — reveals Download and Save buttons on desktop.
     * NOVA C5: renamed from --color-scrim-light (misleading) to --color-scrim-card.
     */
    --color-scrim-card:  rgba(17, 16, 16, 0.40);

    /* Modal backdrop */
    --color-scrim-modal: rgba(17, 16, 16, 0.64);

    /* Hero gradient base color — used in linear-gradient on hero scrim */
    --color-scrim-hero:  rgba(17, 16, 16, 0.24);

    /* ----------------------------------------------------------
       TYPOGRAPHY — FONT FAMILIES
       ---------------------------------------------------------- */

    /*
     * Display/UI font: Geist Variable, self-hosted.
     * 'Geist Fallback' is the metric-matched fallback for CLS prevention.
     */
    --font-display: 'Geist', 'Geist Fallback', system-ui, -apple-system,
                    BlinkMacSystemFont, 'Segoe UI', sans-serif;

    /* Body font: system-ui stack — no external load */
    --font-body:    system-ui, -apple-system, BlinkMacSystemFont,
                    'Segoe UI', sans-serif;

    /* Monospace: resolution + filesize metadata on detail page only */
    --font-mono:    'JetBrains Mono', 'Fira Code', 'Courier New', monospace;

    /* ----------------------------------------------------------
       TYPOGRAPHY — TYPE SCALE
       Base: 16px (html font-size: 100%).
       All sizes in rem. Line heights unitless. No italic anywhere.
       Accessibility floor: 12px (--text-label). No exceptions.
       ---------------------------------------------------------- */

    /* Display — hero titles, 404 (desktop: 48px) */
    --text-display-size:    3rem;
    --text-display-weight:  600;
    --text-display-lh:      1.10;
    --text-display-ls:      -0.03em;

    /* H1 — page headings */
    --text-h1-size:         2rem;       /* 32px */
    --text-h1-weight:       600;
    --text-h1-lh:           1.20;
    --text-h1-ls:           -0.02em;

    /* H2 — section headings, empty state headlines */
    --text-h2-size:         1.5rem;     /* 24px */
    --text-h2-weight:       600;
    --text-h2-lh:           1.25;
    --text-h2-ls:           -0.015em;

    /* H3 — card group titles, modal headings */
    --text-h3-size:         1.25rem;    /* 20px */
    --text-h3-weight:       600;
    --text-h3-lh:           1.30;
    --text-h3-ls:           -0.01em;

    /* H4 — sub-section labels */
    --text-h4-size:         1.0625rem;  /* 17px */
    --text-h4-weight:       600;
    --text-h4-lh:           1.35;
    --text-h4-ls:           0em;

    /* Body Large — long-form text (same px as h4, differs in weight) */
    --text-body-lg-size:    1.0625rem;  /* 17px */
    --text-body-lg-weight:  400;
    --text-body-lg-lh:      1.60;
    --text-body-lg-ls:      0em;

    /* Body — default body text and descriptions */
    --text-body-size:       0.9375rem;  /* 15px */
    --text-body-weight:     400;
    --text-body-lh:         1.60;
    --text-body-ls:         0em;

    /* Body Small — card titles, secondary body */
    --text-body-sm-size:    0.875rem;   /* 14px */
    --text-body-sm-weight:  400;
    --text-body-sm-lh:      1.55;
    --text-body-sm-ls:      0em;

    /* Caption — image captions, upload dates, card meta */
    --text-caption-size:    0.8125rem;  /* 13px */
    --text-caption-weight:  400;
    --text-caption-lh:      1.50;
    --text-caption-ls:      0.01em;

    /* Label — form labels, category pills (accessibility floor: 12px) */
    --text-label-size:      0.75rem;    /* 12px */
    --text-label-weight:    500;
    --text-label-lh:        1.40;
    --text-label-ls:        0.04em;

    /* UI Medium — buttons (md/lg), nav items */
    --text-ui-md-size:      0.9375rem;  /* 15px */
    --text-ui-md-weight:    500;
    --text-ui-md-lh:        1.0;
    --text-ui-md-ls:        0em;

    /* UI Small — small buttons, badges */
    --text-ui-sm-size:      0.8125rem;  /* 13px */
    --text-ui-sm-weight:    500;
    --text-ui-sm-lh:        1.0;
    --text-ui-sm-ls:        0em;

    /* Mono — resolution and file size metadata */
    --text-mono-size:       0.8125rem;  /* 13px */
    --text-mono-weight:     400;
    --text-mono-lh:         1.50;
    --text-mono-ls:         0em;

    /*
     * INPUT FONT SIZE — MIRA MIR2: iOS Safari zoom prevention.
     * iOS zooms the viewport when focused input font-size < 16px.
     * This token is SEPARATE from --text-body (15px).
     * ALL <input>, <select>, <textarea> elements MUST use this token.
     * Do not use --text-body on form inputs. Ever.
     */
    --text-input-size:      1rem;       /* 16px — prevents iOS zoom */
    --text-input-weight:    400;
    --text-input-lh:        1.50;

    /* Maximum prose line length */
    --text-max-width: 68ch;

    /* ----------------------------------------------------------
       SPACING SCALE
       Base unit: 4px.
       Non-linear scale. Do not use calc() or arbitrary pixel values.
       If a needed size is not in this scale, request a token addition.
       ---------------------------------------------------------- */

    --space-1:  4px;
    --space-2:  8px;
    --space-3:  12px;
    --space-4:  16px;    /* Mobile container padding-x; mobile grid gap */
    --space-5:  20px;
    --space-6:  24px;    /* Desktop container padding-x; desktop grid gap */
    --space-8:  32px;    /* Modal padding; desktop card grid gap */
    --space-10: 40px;    /* Section spacing — below 768px */
    --space-12: 48px;    /* Section spacing — 768px to 1023px */
    --space-16: 64px;    /* Section spacing — 1024px and above */
    --space-24: 96px;    /* Hero padding; empty state top margin */

    /* ----------------------------------------------------------
       BORDER RADIUS
       ---------------------------------------------------------- */

    --radius-sm:   4px;    /* Tags, chips, badges */
    --radius-md:   8px;    /* Small buttons, icon buttons, save icon bg */
    --radius-lg:   10px;   /* Inputs, secondary button corners */
    --radius-xl:   12px;   /* Cards, primary/large buttons */
    --radius-full: 9999px; /* Reserved — not used in Phase 0 UI */

    /* ----------------------------------------------------------
       ICON SIZE SCALE
       Matches Lucide icon rendering at pixel-grid sizes.
       ---------------------------------------------------------- */

    --icon-sm: 16px;   /* Inline with text, small button icons */
    --icon-md: 20px;   /* Button icons (md/lg), nav icons, form icons */
    --icon-lg: 24px;   /* Standalone action icons, empty state icons */
    --icon-xl: 48px;   /* Empty state hero icons */

    /* ----------------------------------------------------------
       MOTION — DURATION TOKENS
       Floor: 80ms. Ceiling: 300ms (except skeleton at 1500ms).
       ---------------------------------------------------------- */

    --duration-instant:  80ms;
    --duration-fast:     100ms;
    --duration-base:     120ms;
    --duration-moderate: 150ms;
    --duration-enter:    200ms;
    --duration-sheet:    250ms;   /* Mobile bottom-sheet — distinct from modal enter */
    --duration-skeleton: 1500ms;

    /* ----------------------------------------------------------
       MOTION — EASING TOKENS
       ---------------------------------------------------------- */

    --ease-default: ease;
    --ease-enter:   ease-out;
    --ease-exit:    ease-in;
    --ease-linear:  linear;

    /* ----------------------------------------------------------
       MOTION — SHORTHAND TRANSITION TOKENS
       ---------------------------------------------------------- */

    --transition-color:
        background-color var(--duration-base) var(--ease-default),
        border-color     var(--duration-base) var(--ease-default),
        color            var(--duration-base) var(--ease-default);

    --transition-opacity:   opacity   var(--duration-moderate) var(--ease-default);
    --transition-scale:     transform var(--duration-fast)     var(--ease-default);
    --transition-focus:
        outline      var(--duration-instant) var(--ease-default),
        border-color var(--duration-instant) var(--ease-default);

    --transition-modal-in:
        opacity   var(--duration-enter) var(--ease-enter),
        transform var(--duration-enter) var(--ease-enter);

    --transition-modal-out:
        opacity   var(--duration-moderate) var(--ease-exit),
        transform var(--duration-moderate) var(--ease-exit);

    /* ----------------------------------------------------------
       SHADOW TOKENS
       NOVA R6: all shadow values are tokens. No inline box-shadow
       values in component CSS — reference these tokens only.
       ---------------------------------------------------------- */

    --shadow-card-rest:   none;
    --shadow-card-hover:  0 8px 24px rgba(0, 0, 0, 0.12);
    --shadow-panel:       0 16px 48px rgba(0, 0, 0, 0.16);
    --shadow-dropdown:    0 4px 16px rgba(0, 0, 0, 0.10);
    --shadow-tooltip:     0 2px 8px  rgba(0, 0, 0, 0.12);

    /*
     * Sticky header shadow — a 1px border line, no depth.
     * Uses var() for the border color — NOVA R2 pattern.
     */
    --shadow-header: 0 1px 0 var(--color-border);

    /* ----------------------------------------------------------
       Z-INDEX SCALE
       NOVA R7: --z-modal-backdrop raised to 550 (50-unit buffer
       below --z-modal: 600, up from original 590).
       Never use raw z-index numbers in component CSS.
       ---------------------------------------------------------- */

    --z-below:          -1;    /* Background decorative elements */
    --z-base:            0;    /* Default document flow */
    --z-raised:         10;    /* Cards on hover — prevents sibling clipping */
    --z-dropdown:      100;    /* Nav dropdowns, autocomplete, select popups */
    --z-sticky:        200;    /* Sticky header, sticky filter bar */
    --z-fab:           300;    /* Floating action buttons (scroll-to-top) */
    --z-overlay:       400;    /* Card hover overlay (download/save reveal) */
    --z-drawer:        500;    /* Mobile nav drawer, filter drawer */
    --z-modal-backdrop: 550;   /* Modal scrim — sits below modal, above all else */
    --z-modal:         600;    /* Auth modal, save modal, confirmation dialogs */
    --z-toast:         700;    /* Toast notifications — appears above modals */
    --z-tooltip:       800;    /* Tooltips — appears above toasts */
    --z-cookie-banner: 900;    /* GDPR consent banner — legal requirement */
    --z-max:          9999;    /* EMERGENCY OVERRIDE ONLY — never in component code */

    /*
     * WordPress Admin Bar: z-index 99999 (WordPress core — immovable).
     * All theme UI correctly sits below. No conflicts.
     *
     * Any position:fixed element anchored to top:0 MUST use:
     *     top: var(--wp-admin--admin-bar--height, 0px)
     * WP sets this property: 32px (desktop), 46px (mobile ≤782px), 0px (logged-out).
     * MIRA MC11: enforced at Phase 1. Sticky header must never use top:0.
     */

    /* ----------------------------------------------------------
       GRID & LAYOUT TOKENS
       ---------------------------------------------------------- */

    --container-max-width:    1440px;
    --container-padding-x:    var(--space-6);   /* 24px — tablet and desktop */
    --container-padding-x-sm: var(--space-4);   /* 16px — mobile */
    --grid-gap-mobile:        var(--space-4);   /* 16px */
    --grid-gap-desktop:       var(--space-6);   /* 24px */

    /* ----------------------------------------------------------
       BUTTON DIMENSION TOKENS
       MIRA MIR3: --btn-height-md raised from 40px to 44px.
       44px is the minimum touch target on all viewports.
       ---------------------------------------------------------- */

    --btn-height-sm:  32px;   /* Desktop-only. Prohibited as standalone mobile touch target. */
    --btn-height-md:  44px;   /* Raised from 40px — MIRA MIR3 correction */
    --btn-height-lg:  48px;

    --btn-padding-x-sm: var(--space-3);   /* 12px */
    --btn-padding-x-md: var(--space-4);   /* 16px */
    --btn-padding-x-lg: var(--space-5);   /* 20px */

    --btn-radius-sm:  var(--radius-md);   /* 8px */
    --btn-radius-md:  10px;
    --btn-radius-lg:  var(--radius-xl);   /* 12px */

    /* ----------------------------------------------------------
       FORM ELEMENT DIMENSION TOKENS
       ---------------------------------------------------------- */

    --input-height:         44px;
    --input-height-compact: 36px;    /* Desktop only. On mobile: override to 44px. */
    --input-padding-x:      var(--space-4);    /* 16px */
    --input-radius:         var(--radius-lg);  /* 10px */

    --textarea-min-height:  120px;
    --textarea-padding:     var(--space-3) var(--space-4);  /* 12px 16px */

    --checkbox-size:        18px;
    --radio-size:           18px;

    /* ----------------------------------------------------------
       HERO DIMENSION TOKENS
       MIRA MIR1 CORRECTION: 50vw → 50vh on all mobile tiers.
       50vw at 390px = 195px (too short). 50vh at 390px (844px device) = 422px.
       vw scales with viewport WIDTH (shrinks on narrow phones).
       vh scales with viewport HEIGHT (appropriate for hero impact).
       ---------------------------------------------------------- */

    /* Desktop (≥1280px) */
    --hero-height-xl:     70vh;
    --hero-min-height-xl: 480px;
    --hero-max-height-xl: 800px;

    /* Tablet (769px–1279px) */
    --hero-height-lg:     60vh;
    --hero-min-height-lg: 400px;
    --hero-max-height-lg: 640px;

    /* Mobile large (480px–768px) — 50vh, NOT 50vw */
    --hero-height-md:     50vh;
    --hero-min-height-md: 280px;
    --hero-max-height-md: 480px;

    /* Mobile small (<480px) — 50vh, NOT 50vw */
    --hero-height-sm:     50vh;
    --hero-min-height-sm: 240px;   /* NOVA C4 resolved: standardized (was 220px/240px inconsistency) */
    --hero-max-height-sm: 420px;

    /* Background prevents white flash before image loads */
    --hero-bg-loading: #111010;

    /* ----------------------------------------------------------
       MODAL DIMENSION TOKENS
       ---------------------------------------------------------- */

    --modal-max-width:         480px;
    --modal-border-radius:     var(--radius-xl);   /* 12px — desktop */
    --modal-border-radius-mob: 16px 16px 0 0;      /* Mobile bottom-sheet: rounded top only */
    --modal-max-height-mob:    90vh;               /* Bottom-sheet max height — MIRA MIR4 */
    --modal-handle-width:      36px;
    --modal-handle-height:     4px;
    --modal-handle-radius:     2px;

} /* end :root */


/* ============================================================
   REDUCED MOTION
   Overrides all transitions and animations globally.
   Every element with CSS transitions must respond to this.
   Duration 0.01ms (not 0) avoids JS event listener issues.
   ============================================================ */

@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;
    }
}


/* ============================================================
   BASE RESETS
   Minimal. Not a full normalize. Opinionated for this site only.
   ============================================================ */

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

html {
    font-size: 100%;              /* 16px base. Never override. */
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-behavior: smooth;      /* Overridden by prefers-reduced-motion above */
}

body {
    margin: 0;
    padding: 0;
    background-color: var(--color-bg);
    color: var(--color-text-primary);
    font-family: var(--font-body);
    font-size: var(--text-body-size);
    font-weight: var(--text-body-weight);
    line-height: var(--text-body-lh);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/*
 * Remove default margins from block elements.
 * Margin is applied via spacing tokens in component CSS.
 */
h1, h2, h3, h4, h5, h6, p, ul, ol, li, figure, blockquote {
    margin: 0;
    padding: 0;
}

ul, ol {
    list-style: none;
}

img,
svg,
video {
    max-width: 100%;
    display: block;
}

a {
    color: var(--color-accent);
    text-decoration: underline;   /* Meets WCAG for links below 4.5:1 threshold */
}

a:hover {
    color: var(--color-accent-hover);
}

/*
 * Remove default button appearance.
 * All interactive elements are explicitly styled via .wg-btn.
 */
button {
    font-family: inherit;
    cursor: pointer;
    border: none;
    background: none;
    padding: 0;
}

/* Prevent iOS from auto-styling inputs */
input,
select,
textarea {
    font-family: var(--font-body);
    font-size: var(--text-input-size);   /* 16px — MIRA MIR2: prevents iOS zoom */
    -webkit-appearance: none;
    appearance: none;
}


/* ============================================================
   PAGE CONTAINER
   Max-width: 1440px, centered, responsive horizontal padding.
   Hero and full-bleed sections bypass this container.
   ============================================================ */

.wg-container {
    max-width: var(--container-max-width);
    padding-inline: var(--container-padding-x);
    margin-inline: auto;
    width: 100%;
}

@media (max-width: 768px) {
    .wg-container {
        padding-inline: var(--container-padding-x-sm);
    }
}


/* ============================================================
   TYPOGRAPHY UTILITIES
   Applied as utility classes when semantic HTML tags are
   not the appropriate element (e.g., display text on a <p>).
   ============================================================ */

.wg-text-display {
    font-family: var(--font-display);
    font-size: var(--text-display-size);
    font-weight: var(--text-display-weight);
    line-height: var(--text-display-lh);
    letter-spacing: var(--text-display-ls);
}

/* MIRA MC6: --text-display scales to 2rem on mobile */
@media (max-width: 767px) {
    .wg-text-display {
        font-size: 2rem;   /* 32px — prevents visual overflow on small phones */
    }
}

.wg-text-h1 {
    font-family: var(--font-display);
    font-size: var(--text-h1-size);
    font-weight: var(--text-h1-weight);
    line-height: var(--text-h1-lh);
    letter-spacing: var(--text-h1-ls);
}

.wg-text-h2 {
    font-family: var(--font-display);
    font-size: var(--text-h2-size);
    font-weight: var(--text-h2-weight);
    line-height: var(--text-h2-lh);
    letter-spacing: var(--text-h2-ls);
}

.wg-text-h3 {
    font-family: var(--font-display);
    font-size: var(--text-h3-size);
    font-weight: var(--text-h3-weight);
    line-height: var(--text-h3-lh);
    letter-spacing: var(--text-h3-ls);
}

.wg-text-caption {
    font-size: var(--text-caption-size);
    font-weight: var(--text-caption-weight);
    line-height: var(--text-caption-lh);
    letter-spacing: var(--text-caption-ls);
    color: var(--color-text-secondary);
}

.wg-text-label {
    font-size: var(--text-label-size);
    font-weight: var(--text-label-weight);
    line-height: var(--text-label-lh);
    letter-spacing: var(--text-label-ls);
    color: var(--color-text-secondary);
    text-transform: uppercase;
}

.wg-text-mono {
    font-family: var(--font-mono);
    font-size: var(--text-mono-size);
    font-weight: var(--text-mono-weight);
    line-height: var(--text-mono-lh);
}

/* Prose max-width for long-form body text */
.wg-prose {
    max-width: var(--text-max-width);
}


/* ============================================================
   ICON BASE STYLES
   Applied to all <svg> elements output by wg_icon() PHP helper.
   Uses currentColor to inherit from parent text.
   pointer-events: none prevents icons intercepting clicks.
   ============================================================ */

.wg-icon {
    display: inline-block;
    vertical-align: middle;
    flex-shrink: 0;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    pointer-events: none;
}

/* Large icons (empty state): thinner stroke */
.wg-icon[width="48"],
.wg-icon[width="32"] {
    stroke-width: 1.5;
}


/* ============================================================
   FOCUS — GLOBAL FOCUS RING
   All interactive elements use this focus ring.
   :focus-visible applies only on keyboard navigation.
   :focus:not(:focus-visible) removes the ring on mouse click.
   ============================================================ */

:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

:focus:not(:focus-visible) {
    outline: none;
}


/* ============================================================
   CARD — BASE STYLES
   Full card component spec defined at Phase 2.
   This block establishes the shadow animation pattern.
   NOVA R6: shadow on ::after pseudo-element, animated via opacity.
   This keeps the animation compositor-friendly (no repaint).
   ============================================================ */

.wg-card {
    position: relative;
    background-color: var(--color-surface);
    border-radius: var(--radius-xl);
    overflow: hidden;
    cursor: pointer;
}

/*
 * Shadow lives on ::after, not on the element itself.
 * Animating opacity on ::after is compositor-friendly.
 * Animating box-shadow directly causes a repaint on every frame.
 */
.wg-card::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: var(--shadow-card-hover);
    opacity: 0;
    transition: opacity var(--duration-moderate) var(--ease-default);
    pointer-events: none;
    z-index: var(--z-raised);
}

.wg-card:hover::after {
    opacity: 1;
}

/* Card image — fills the wrapper, crops from center */
.wg-card__image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center center;
    display: block;
    transition: transform var(--duration-moderate) var(--ease-default);
}

.wg-card:hover .wg-card__image {
    transform: scale(1.02);
}

.wg-card:active .wg-card__image {
    transform: scale(0.99);
    transition-duration: var(--duration-fast);
}

/*
 * Card overlay — contains Download button and Save icon.
 * Desktop only. Mobile: tap navigates directly (no overlay).
 */
.wg-card__overlay {
    position: absolute;
    inset: 0;
    background-color: var(--color-scrim-card);
    opacity: 0;
    transition: opacity var(--duration-moderate) var(--ease-default);
    display: flex;
    align-items: center;
    justify-content: center;
}

.wg-card:hover .wg-card__overlay {
    opacity: 1;
}

/* Card body — title and meta below image */
.wg-card__body {
    padding: var(--space-3) var(--space-4);
}

.wg-card__title {
    font-size: var(--text-body-sm-size);
    font-weight: var(--text-body-sm-weight);
    color: var(--color-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: var(--text-body-sm-lh);
}

.wg-card__meta {
    font-size: var(--text-caption-size);
    color: var(--color-text-secondary);
    margin-top: var(--space-1);
}

/*
 * Save button inside card overlay.
 * Top-right position. State-driven by WG state machine (Phase 8).
 */
.wg-card__save {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    background: rgba(255, 255, 255, 0.16);
    border-radius: var(--radius-md);
    padding: var(--space-2);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--duration-fast) var(--ease-default);
    cursor: pointer;
}

.wg-card__save:hover {
    background: rgba(255, 255, 255, 0.28);
}

[data-save-state="saved"] .wg-card__save {
    background: var(--color-accent-subtle);
}

[data-save-state="saved"] .wg-card__save .wg-icon {
    color: var(--color-accent);
}


/* ============================================================
   CARD GRID
   CSS Grid layout. Column counts and gap governed by breakpoints.
   MIRA MC4, MC5: explicit breakpoint-to-ratio mapping below.
   ============================================================ */

.wg-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--grid-gap-mobile);
}

/* Image wrapper aspect ratios by breakpoint */
/* < 480px: 2 columns, 4:3 ratio */
.wg-card__image-wrapper {
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
}

/* 480px–768px: 2 columns, 16:9 ratio — ATLAS decision */
@media (min-width: 480px) and (max-width: 768px) {
    .wg-card__image-wrapper {
        aspect-ratio: 16 / 9;
    }
}

/* 769px–1023px: 3 columns */
@media (min-width: 769px) and (max-width: 1023px) {
    .wg-grid {
        grid-template-columns: repeat(3, 1fr);
        gap: var(--grid-gap-desktop);
    }
    .wg-card__image-wrapper {
        aspect-ratio: 16 / 9;
    }
}

/* 1024px+: 4 columns */
@media (min-width: 1024px) {
    .wg-grid {
        grid-template-columns: repeat(4, 1fr);
        gap: var(--grid-gap-desktop);
    }
    .wg-card__image-wrapper {
        aspect-ratio: 16 / 9;
    }
}


/* ============================================================
   BUTTON SYSTEM
   All button variants. Size classes. State hooks.
   ============================================================ */

.wg-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    border: none;
    cursor: pointer;
    font-family: var(--font-display);
    font-weight: var(--text-ui-md-weight);
    font-size: var(--text-ui-md-size);
    line-height: var(--text-ui-md-lh);
    text-decoration: none;
    white-space: nowrap;
    transition: var(--transition-color);
    -webkit-tap-highlight-color: transparent;
    user-select: none;
}

/* Size: sm — 32px, desktop only as standalone target */
.wg-btn--sm {
    height: var(--btn-height-sm);
    padding-inline: var(--btn-padding-x-sm);
    font-size: var(--text-ui-sm-size);
    font-weight: var(--text-ui-sm-weight);
    border-radius: var(--btn-radius-sm);
}

/* Size: md — 44px (MIRA MIR3: raised from 40px) */
.wg-btn--md {
    height: var(--btn-height-md);
    padding-inline: var(--btn-padding-x-md);
    border-radius: var(--btn-radius-md);
}

/* Size: lg — 48px */
.wg-btn--lg {
    height: var(--btn-height-lg);
    padding-inline: var(--btn-padding-x-lg);
    font-size: var(--text-ui-md-size);
    border-radius: var(--btn-radius-lg);
}

/* Icon-only square buttons */
.wg-btn--icon-sm { width: var(--btn-height-sm); padding-inline: 0; }
.wg-btn--icon-md { width: var(--btn-height-md); padding-inline: 0; }
.wg-btn--icon-lg { width: var(--btn-height-lg); padding-inline: 0; }

/* --- Primary button --- */
.wg-btn--primary {
    background-color: var(--color-accent);   /* #a8522a — WCAG AA compliant */
    color: var(--color-text-inverse);
    border: none;
}

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

.wg-btn--primary:active {
    background-color: var(--color-accent-active);
    transform: scale(0.97);
    transition-duration: var(--duration-instant);
}

.wg-btn--primary:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.wg-btn--primary:disabled,
.wg-btn--primary[data-state="disabled"] {
    background-color: var(--color-border-strong);
    color: var(--color-text-disabled);
    cursor: not-allowed;
    pointer-events: none;
}

/* --- Secondary button --- */
.wg-btn--secondary {
    background-color: var(--color-surface);
    color: var(--color-text-primary);
    border: 1px solid var(--color-border);
}

.wg-btn--secondary:hover {
    background-color: var(--color-bg);
    border-color: var(--color-border-strong);
}

.wg-btn--secondary:active {
    transform: scale(0.97);
    transition-duration: var(--duration-instant);
}

.wg-btn--secondary:disabled,
.wg-btn--secondary[data-state="disabled"] {
    color: var(--color-text-disabled);
    border-color: var(--color-border);
    cursor: not-allowed;
    pointer-events: none;
}

/* --- Ghost button --- */
.wg-btn--ghost {
    background-color: transparent;
    color: var(--color-text-primary);
    border: none;
}

.wg-btn--ghost:hover {
    background-color: rgba(17, 16, 16, 0.06);
}

.wg-btn--ghost:active {
    background-color: rgba(17, 16, 16, 0.10);
    transform: scale(0.97);
    transition-duration: var(--duration-instant);
}

.wg-btn--ghost:disabled,
.wg-btn--ghost[data-state="disabled"] {
    color: var(--color-text-disabled);
    cursor: not-allowed;
    pointer-events: none;
}

/* --- Destructive button --- */
.wg-btn--destructive {
    background-color: var(--color-error);
    color: var(--color-text-inverse);
    border: none;
}

.wg-btn--destructive:hover {
    background-color: var(--color-error-hover);
}

.wg-btn--destructive:active {
    background-color: var(--color-error-active);
    transform: scale(0.97);
    transition-duration: var(--duration-instant);
}

.wg-btn--destructive:focus-visible {
    outline: 2px solid var(--color-error);
    outline-offset: 2px;
}

/*
 * Loading state — driven by WG state machine (Phase 8).
 * JS sets data-state="loading" on .wg-btn.
 * Spinner is injected by JS into button innerHTML.
 */
.wg-btn[data-state="loading"] {
    pointer-events: none;
    cursor: not-allowed;
    opacity: 0.8;
}


/* ============================================================
   FORM ELEMENTS
   All inputs use --text-input (16px) — MIRA MIR2.
   iOS Safari zooms when input font-size < 16px.
   ============================================================ */

/* Shared base for all text inputs, selects, textareas */
.wg-input {
    display: block;
    width: 100%;
    height: var(--input-height);
    padding-inline: var(--input-padding-x);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--input-radius);
    font-family: var(--font-body);
    font-size: var(--text-input-size);    /* 1rem / 16px — iOS zoom prevention */
    font-weight: var(--text-input-weight);
    line-height: var(--text-input-lh);
    color: var(--color-text-primary);
    transition: var(--transition-focus);
    -webkit-appearance: none;
    appearance: none;
}

.wg-input::placeholder {
    color: var(--color-text-disabled);
}

.wg-input:focus {
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 0;
    border-color: var(--color-accent);
}

.wg-input:focus-visible {
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 0;
    border-color: var(--color-accent);
}

/* Error state */
.wg-input--error {
    border-color: var(--color-error);
}

.wg-input--error:focus,
.wg-input--error:focus-visible {
    outline: 2px solid var(--color-error-focus-ring);
    border-color: var(--color-error);
}

/* Disabled state */
.wg-input:disabled {
    background-color: var(--color-bg);
    border-color: var(--color-border);
    color: var(--color-text-disabled);
    cursor: not-allowed;
}

/* Read-only state */
.wg-input[readonly] {
    background-color: var(--color-bg);
    border-color: var(--color-border);
    cursor: default;
}
.wg-input[readonly]:focus,
.wg-input[readonly]:focus-visible {
    outline: none;
    border-color: var(--color-border);
}

/* Compact/search input variant — desktop only */
.wg-input--compact {
    height: var(--input-height-compact);   /* 36px */
}

/*
 * Mobile: compact input must meet 44px touch target.
 * MIRA MIR3 / Audit 7 finding.
 */
@media (max-width: 768px) {
    .wg-input--compact {
        height: var(--input-height);   /* Override to 44px on mobile */
    }
}

/* Textarea */
.wg-textarea {
    min-height: var(--textarea-min-height);
    padding: var(--textarea-padding);
    height: auto;
    resize: vertical;
}

/* Select wrapper — NOVA C8: position:relative container for custom chevron */
.wg-select-wrapper {
    position: relative;
    display: block;
}

.wg-select-wrapper .wg-input {
    padding-right: 36px;   /* Space for the chevron icon */
    cursor: pointer;
}

/* Chevron icon inside select wrapper */
.wg-select-wrapper .wg-icon {
    position: absolute;
    right: var(--space-3);
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
    color: var(--color-text-secondary);
}

/* Form label */
.wg-label {
    display: block;
    font-size: var(--text-label-size);
    font-weight: var(--text-label-weight);
    line-height: var(--text-label-lh);
    letter-spacing: var(--text-label-ls);
    color: var(--color-text-secondary);
    margin-bottom: var(--space-2);
}

.wg-label__required {
    color: var(--color-error);
    margin-left: 2px;
}

/* Help text below input */
.wg-field-help {
    font-size: var(--text-caption-size);
    color: var(--color-text-secondary);
    margin-top: var(--space-2);
}

/* Error message below input */
.wg-field-error {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    font-size: var(--text-caption-size);
    color: var(--color-error);
    margin-top: var(--space-2);
}

/* Checkbox */
.wg-checkbox {
    width: var(--checkbox-size);
    height: var(--checkbox-size);
    border: 1.5px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
    flex-shrink: 0;
    transition: var(--transition-color);
    display: grid;
    place-content: center;
}

.wg-checkbox:checked {
    background-color: var(--color-accent);
    border-color: var(--color-accent);
    /* Checkmark injected via background-image or wg_icon() in PHP */
}

.wg-checkbox:focus-visible {
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 2px;
}

.wg-checkbox:disabled {
    background-color: var(--color-bg);
    border-color: var(--color-border);
    cursor: not-allowed;
}

/* Radio */
.wg-radio {
    width: var(--radio-size);
    height: var(--radio-size);
    border: 1.5px solid var(--color-border-strong);
    border-radius: 50%;
    background-color: var(--color-surface);
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
    flex-shrink: 0;
    transition: var(--transition-color);
    display: grid;
    place-content: center;
}

/* Inner dot on selection */
.wg-radio::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: var(--color-accent);
    transform: scale(0);
    transition: transform var(--duration-fast) var(--ease-default);
}

.wg-radio:checked {
    border-color: var(--color-accent);
}

.wg-radio:checked::before {
    transform: scale(1);
}

.wg-radio:focus-visible {
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 2px;
}


/* ============================================================
   MODAL
   Desktop: centered dialog with subtle entrance.
   Mobile (≤480px): bottom-sheet — MIRA MIR4.
   Accessibility: aria-hidden + inert (JS-controlled).
   ============================================================ */

/* Closed state — CSS hides the element */
.wg-modal[aria-hidden="true"] {
    display: none;
    visibility: hidden;
    /* JS also sets inert attribute — required for keyboard/AT exclusion */
}

/* Open state */
.wg-modal[aria-hidden="false"] {
    display: flex;
    visibility: visible;
    /* JS removes inert attribute */
}

/* Backdrop */
.wg-modal-backdrop {
    position: fixed;
    inset: 0;
    background-color: var(--color-scrim-modal);
    z-index: var(--z-modal-backdrop);
    opacity: 0;
    transition: opacity var(--duration-enter) var(--ease-enter);
}

.wg-modal-backdrop.is-visible {
    opacity: 1;
}

/* Modal container */
.wg-modal {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
}

/* Modal panel — the white box */
.wg-modal__panel {
    background-color: var(--color-surface);
    border-radius: var(--modal-border-radius);
    box-shadow: var(--shadow-panel);
    width: 100%;
    max-width: var(--modal-max-width);
    max-height: 90vh;
    overflow-y: auto;
    padding: var(--space-8);
    opacity: 0;
    transform: translateY(8px);
    transition: var(--transition-modal-in);
}

.wg-modal[aria-hidden="false"] .wg-modal__panel {
    opacity: 1;
    transform: translateY(0);
}

/*
 * MOBILE BOTTOM-SHEET — MIRA MIR4
 * At ≤480px, modals anchor to the bottom of the viewport.
 * The panel slides up from off-screen.
 * max-height: 90vh — user sees they are still on the page.
 * Drag-to-dismiss handle provides the visual affordance.
 */
@media (max-width: 480px) {
    .wg-modal {
        align-items: flex-end;
        padding: 0;
    }

    .wg-modal__panel {
        border-radius: var(--modal-border-radius-mob);   /* 16px 16px 0 0 */
        max-width: 100%;
        max-height: var(--modal-max-height-mob);         /* 90vh */
        padding: var(--space-6);
        opacity: 1;                   /* No opacity change on mobile */
        transform: translateY(100%);  /* Starts off-screen below viewport */
        transition: transform var(--duration-sheet) var(--ease-enter);
    }

    .wg-modal[aria-hidden="false"] .wg-modal__panel {
        opacity: 1;
        transform: translateY(0);
    }

    .wg-modal[aria-hidden="true"] .wg-modal__panel {
        transform: translateY(100%);
        transition: transform var(--duration-enter) var(--ease-exit);
    }

    /* Drag-to-dismiss handle */
    .wg-modal__panel::before {
        content: '';
        display: block;
        width: var(--modal-handle-width);
        height: var(--modal-handle-height);
        border-radius: var(--modal-handle-radius);
        background-color: var(--color-border-strong);
        margin: 0 auto var(--space-4) auto;
    }
}


/* ============================================================
   HERO IMAGE LOADING STATES
   NOVA R2 / FORGE Q6: CSS state hooks for hero image.
   .is-loaded added by JS on img.onload
   .is-error added by JS on img.onerror
   Hero container background (#111010) prevents white flash.
   ============================================================ */

.wg-hero {
    position: relative;
    width: 100%;
    overflow: hidden;
    background-color: var(--hero-bg-loading);
}

/* Hero heights by breakpoint — MIRA MIR1 (50vw → 50vh applied) */
/* Desktop */
.wg-hero {
    height: var(--hero-height-xl);
    min-height: var(--hero-min-height-xl);
    max-height: var(--hero-max-height-xl);
}

@media (max-width: 1279px) {
    .wg-hero {
        height: var(--hero-height-lg);
        min-height: var(--hero-min-height-lg);
        max-height: var(--hero-max-height-lg);
    }
}

@media (max-width: 768px) {
    .wg-hero {
        /* 50vh — NOT 50vw. 50vw at 390px = 195px (too short). */
        /* 50vh at 390px on iPhone 14 (844px tall) = 422px. */
        height: var(--hero-height-md);
        min-height: var(--hero-min-height-md);
        max-height: var(--hero-max-height-md);
    }
}

@media (max-width: 480px) {
    .wg-hero {
        height: var(--hero-height-sm);
        min-height: var(--hero-min-height-sm);
        max-height: var(--hero-max-height-sm);
    }
}

.wg-hero__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center center;
    display: block;
    opacity: 0;
    transition: opacity var(--duration-enter) var(--ease-enter);
}

.wg-hero__img.is-loaded {
    opacity: 1;
}

.wg-hero__img.is-error {
    opacity: 0;
    /* JS shows image-off icon and fallback bg in parent */
}

/* Hero gradient scrim — bottom 40%, text legibility */
.wg-hero__scrim {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 40%;
    background: linear-gradient(
        to top,
        rgba(17, 16, 16, 0.72) 0%,
        rgba(17, 16, 16, 0.00) 100%
    );
    pointer-events: none;
}

/* Hero metadata block — title and meta over scrim */
.wg-hero__meta {
    position: absolute;
    bottom: var(--space-8);
    left: var(--space-8);
    right: var(--space-8);
}

/* Mobile: reduce horizontal inset on hero meta — MIRA MC2 */
@media (max-width: 768px) {
    .wg-hero__meta {
        bottom: var(--space-4);
        left: var(--space-4);
        right: var(--space-4);
    }
}

.wg-hero__title {
    font-family: var(--font-display);
    font-size: var(--text-h1-size);
    font-weight: var(--text-h1-weight);
    line-height: var(--text-h1-lh);
    color: var(--color-text-inverse);
    /* ECHO Item 6: text-shadow ensures legibility over light wallpapers */
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.60);
}

.wg-hero__caption {
    font-size: var(--text-caption-size);
    color: rgba(248, 247, 244, 0.72);
    margin-top: var(--space-1);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.40);
}

/* Hero action bar — below hero image, not overlaid */
.wg-hero__actions {
    background-color: var(--color-surface);
    padding: var(--space-6) var(--space-8);
    border-bottom: 1px solid var(--color-border);
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

/* Mobile: reduce horizontal padding — MIRA MC2 */
@media (max-width: 768px) {
    .wg-hero__actions {
        padding: var(--space-4) var(--space-4);
        flex-wrap: wrap;
    }
}


/* ============================================================
   SKELETON SHIMMER
   Server-side rendered on initial page load.
   ECHO Item 3: skeleton is NEVER the initial state for Googlebot.
   Initial page HTML contains real wallpaper markup.
   Skeleton applies on: client-side pagination, filter changes.
   ============================================================ */

@keyframes wg-skeleton-shimmer {
    0%   { background-position: 200% center; }
    100% { background-position: -200% center; }
}

.wg-skeleton {
    background: linear-gradient(
        90deg,
        var(--color-border)  25%,
        #f0ede8              50%,
        var(--color-border)  75%
    );
    background-size: 200% 100%;
    animation: wg-skeleton-shimmer var(--duration-skeleton) var(--ease-linear) infinite;
    border-radius: var(--radius-xl);
}

/* Skeleton card — same dimensions as real card */
.wg-skeleton-card {
    border-radius: var(--radius-xl);
    overflow: hidden;
}

.wg-skeleton-card__image {
    aspect-ratio: 16 / 9;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
}

.wg-skeleton-card__body {
    padding: var(--space-3) var(--space-4);
}

.wg-skeleton-card__title {
    height: 14px;
    border-radius: var(--radius-sm);
    width: 75%;
}

.wg-skeleton-card__meta {
    height: 12px;
    border-radius: var(--radius-sm);
    width: 50%;
    margin-top: var(--space-2);
}


/* ============================================================
   SAVE BUTTON STATE HOOKS
   data-save-state set by WG state machine (Phase 8).
   CSS defines visual response only. JS owns the state.
   ============================================================ */

[data-save-state="loading"] {
    pointer-events: none;
    opacity: 0.7;
}

[data-save-state="error"] {
    animation: wg-shake var(--duration-enter) var(--ease-default);
}

@keyframes wg-shake {
    0%, 100% { transform: translateX(0); }
    25%       { transform: translateX(-4px); }
    75%       { transform: translateX(4px); }
}


/* ============================================================
   TOAST NOTIFICATIONS
   Position: fixed, bottom-right (desktop), full-width (mobile).
   z-index: var(--z-toast) — above modals.
   NOVA C3: toast position locked here.
   ============================================================ */

/* .wg-toast-region and .wg-toast legacy rules removed in Phase 8.
   WG.toast module (Phase 8) uses #wg-toast-container + .wg-toast--visible.
   See Phase 8 section at end of file for canonical toast CSS. */


/* ============================================================
   EMPTY STATE PATTERN
   Universally applied across: no results, empty collection,
   no uploads, and 404.
   ============================================================ */

.wg-empty-state {
    text-align: center;
    padding: var(--space-24) var(--space-6);
    max-width: 480px;
    margin-inline: auto;
}

.wg-empty-state__icon {
    color: var(--color-text-disabled);
    margin-inline: auto;
    margin-bottom: var(--space-6);
}

.wg-empty-state__headline {
    font-family: var(--font-display);
    font-size: var(--text-h2-size);
    font-weight: var(--text-h2-weight);
    line-height: var(--text-h2-lh);
    color: var(--color-text-primary);
    margin-bottom: var(--space-4);
}

/* 404 uses display-scale headline — ATLAS decision */
.wg-empty-state--404 .wg-empty-state__headline {
    font-size: var(--text-display-size);
    letter-spacing: var(--text-display-ls);
    margin-top: var(--space-24);
}

@media (max-width: 767px) {
    /* MIRA MC6: scale --text-display down on mobile */
    .wg-empty-state--404 .wg-empty-state__headline {
        font-size: 2rem;
    }
}

.wg-empty-state__body {
    font-size: var(--text-body-size);
    color: var(--color-text-secondary);
    max-width: 360px;
    margin-inline: auto;
    margin-bottom: var(--space-8);
}

.wg-empty-state__actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    flex-wrap: wrap;
}


/* ============================================================
   SURFACE ELEVATION — SHADOW UTILITY CLASSES
   ============================================================ */

.wg-shadow-card   { box-shadow: var(--shadow-card-hover); }
.wg-shadow-panel  { box-shadow: var(--shadow-panel); }
.wg-shadow-dropdown { box-shadow: var(--shadow-dropdown); }
.wg-shadow-tooltip  { box-shadow: var(--shadow-tooltip); }


/* ============================================================
   SCREENREADER ONLY
   Hides content visually but keeps it accessible to AT.
   ============================================================ */

.wg-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}


/*
 * ============================================================
 * END OF PHASE 0 — DESIGN SYSTEM FOUNDATION
 * ============================================================
 *
 * Phase 1 (Header + Navigation) will append component CSS
 * to this file or in a separate enqueued stylesheet.
 * All Phase 1+ CSS must:
 *   1. Use only tokens defined above
 *   2. Use only breakpoints from the canonical table
 *   3. Use only z-index values from the scale
 *   4. Prefix all classes with wg-
 *   5. Never define new tokens outside this file
 * ============================================================
 */


/* ============================================================
   PHASE 1 — HEADER + NAVIGATION
   REX ALL PASS — 2026-03-27
   ============================================================ */
/*
 * ============================================================
 * 8KWALLS — PHASE 1: HEADER + NAVIGATION CSS
 * To be appended to /output/theme/assets/main.css after REX sign-off.
 *
 * NOVA blockers resolved:
 *   NR2  — Mutual exclusion: HTML uses data-panel-state; JS enforces globally
 *   NR7  — Token sub-properties: uses declared :root sub-tokens (e.g.
 *           --text-ui-md-size) which ARE in main.css Phase 0 :root block.
 *           Any token referenced here is already declared in Phase 0.
 *
 * NOVA required changes resolved:
 *   NR1  — Close-all-panels on resize: in header.js
 *   NR3  — Focus first item on open: in header.js
 *   NR4  — display:none on auth dropdown after exit: in header.js
 *   NR5  — tabindex="-1" on closed panel children: set in header.php,
 *           removed by JS on open, re-added on close
 *   NR6  — Flat BEM selectors, max 2 nesting levels. CSS below is flat.
 *   NR8  — Mobile trigger + panel hidden/shown together: enforced here
 *   NR10 — IntersectionObserver sentinel: in header.js
 *
 * MIRA requirements:
 *   MC7  — One search component per viewport; display:none on inactive
 *   MC11 — Sticky header top: var(--wp-admin--admin-bar--height, 0px)
 *
 * MIRA FIXES (forge-mira-fixes.md):
 *   MR1  — .wg-logo min-height: 44px added (logo touch target fix)
 *   MR2  — .wg-categories-dropdown display:none !important at max-width:768px
 *   MR4b — .wg-dropdown top changed from calc(--header-height + 8px) to
 *           top: 100% on trigger parent containers (.wg-auth, .wg-nav__item)
 *   MR5  — .wg-categories-dropdown max-height + overflow-y: auto added
 *
 * All color/spacing/motion references use var(--token) from Phase 0.
 * No raw hex values in component CSS.
 * !important: used ONLY on three breakpoint-exclusivity display:none rules
 *   (.wg-search-inline at max-width:768px, .wg-search-panel at min-width:769px,
 *    .wg-categories-dropdown at max-width:768px — MR2).
 *   This is a MIRA safety override preventing JS timing errors from
 *   showing the wrong panel/dropdown. No other !important anywhere.
 * BEM-flat: max 2 selector levels.
 * ============================================================
 */


/* ============================================================
   PHASE 1 — COMPONENT TOKENS
   New tokens for Phase 1. Placed in :root, grouped separately
   from Phase 0 global tokens (NOVA recommendation, Section 9).
   These are component-specific, not global design primitives.
   ============================================================ */

:root {
    /* Header heights */
    --header-height:        64px;   /* Desktop (≥769px) */
    --header-height-mobile: 56px;   /* Mobile (≤768px) */

    /* Logo wordmark size — between --text-h2 (24px) and --text-h3 (20px).
       One-off token, documented as component token, not type scale entry. */
    --text-logo-size: 1.375rem;     /* 22px */
}


/* ============================================================
   SCROLL SENTINEL
   1px, invisible, aria-hidden. IntersectionObserver target.
   ============================================================ */

#wg-scroll-sentinel {
    position: absolute;
    top: 0;
    left: 0;
    width: 1px;
    height: 1px;
    pointer-events: none;
    visibility: hidden;
}


/* ============================================================
   HEADER SHELL — .wg-header
   ============================================================ */

.wg-header {
    position: fixed;
    top: var(--wp-admin--admin-bar--height, 0px);   /* MIRA MC11 */
    left: 0;
    right: 0;
    height: var(--header-height);
    background: var(--color-surface);
    z-index: var(--z-sticky);
    overflow: visible;                               /* Dropdowns extend beyond */
    box-shadow: none;
    transition: box-shadow var(--duration-base) var(--ease-default);
}

/* Scrolled state — applied by JS IntersectionObserver (NOVA NR10) */
.wg-header--scrolled {
    box-shadow: var(--shadow-header);
}

/* Mobile: shorter header */
@media (max-width: 768px) {
    .wg-header {
        height: var(--header-height-mobile);
    }
}


/* ============================================================
   HEADER INNER — .wg-header__inner
   Three-zone flex row: logo | nav | actions
   position:relative is the containing block for #wg-search-inline
   (position:absolute). MR3 fix depends on this being set.
   ============================================================ */

.wg-header__inner {
    position: relative;             /* Containing block for absolute search panel (MR3) */
    display: flex;
    align-items: center;
    height: 100%;
    max-width: var(--container-max-width);
    margin: 0 auto;
    padding: 0 var(--space-6);
    gap: var(--space-6);
}

@media (max-width: 768px) {
    .wg-header__inner {
        padding: 0 var(--space-4);
        gap: var(--space-4);
    }
}


/* ============================================================
   LOGO ZONE — .wg-header__logo / .wg-logo
   ============================================================ */

.wg-header__logo {
    flex-shrink: 0;
}

/* MR1 FIX: min-height: 44px ensures the <a> touch target meets 44px minimum
   at mobile. display:flex + align-items:center keeps the wordmark visually
   centered within the extended hit area without changing the text size. */
.wg-logo {
    display: flex;
    align-items: center;
    min-height: 44px;               /* MR1: logo touch target ≥44px (was ~22px) */
    font-family: var(--font-display);
    font-size: var(--text-logo-size);
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1.0;
    color: var(--color-text-primary);
    text-decoration: none;
    text-transform: uppercase;
    white-space: nowrap;
    transition: color var(--duration-base) var(--ease-default);
    outline-offset: 4px;
}

.wg-logo:hover {
    color: var(--color-accent);
}

.wg-logo:active {
    color: var(--color-accent-active);
}

.wg-logo:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 4px;
    border-radius: var(--radius-md);
}


/* ============================================================
   NAV ZONE — .wg-header__nav
   Desktop only (≥769px). Hidden on mobile.
   ============================================================ */

.wg-header__nav {
    flex: 1;
}

/* Desktop-only: hidden on mobile (MIRA MC7) */
@media (max-width: 768px) {
    .wg-header__nav {
        display: none;
    }
}


/* ============================================================
   PRIMARY NAV — .wg-nav / .wg-nav__list / .wg-nav__item
   ============================================================ */

.wg-nav__list {
    display: flex;
    align-items: center;
    list-style: none;
    margin: 0;
    padding: 0;
    gap: var(--space-1);
}

/* MR4b: position:relative on .wg-nav__item is the containing block for
   .wg-categories-dropdown when it uses top:100% positioning. */
.wg-nav__item {
    position: relative;
}


/* ============================================================
   NAV LINKS — .wg-nav__link
   Shared by <a> links and <button> triggers.
   ============================================================ */

.wg-nav__link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    font-family: var(--font-display);
    font-size: var(--text-ui-md-size);
    font-weight: var(--text-ui-md-weight);
    line-height: var(--text-ui-md-lh);
    color: var(--color-text-secondary);
    text-decoration: none;
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition:
        color var(--duration-base) var(--ease-default),
        background-color var(--duration-base) var(--ease-default);
}

.wg-nav__link:hover {
    color: var(--color-text-primary);
    background: rgba(17, 16, 16, 0.04);
}

.wg-nav__link:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Active page — via aria-current="page" (set in PHP) */
.wg-nav__link[aria-current="page"] {
    color: var(--color-accent);
    background: var(--color-accent-subtle);
}

/* Categories trigger chevron icon — rotates when open */
.wg-nav__trigger-icon {
    transition: transform var(--duration-moderate) var(--ease-default);
}

.wg-nav__trigger[aria-expanded="true"] .wg-nav__trigger-icon {
    transform: rotate(180deg);
}


/* ============================================================
   ACTIONS ZONE — .wg-header__actions
   ============================================================ */

.wg-header__actions {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-shrink: 0;
}

@media (max-width: 768px) {
    .wg-header__actions {
        gap: var(--space-2);
    }
}


/* ============================================================
   ICON BUTTON BASE — .wg-header__icon-btn
   Shared by search trigger, close buttons, mobile auth icon.
   44×44px touch target (MIRA MIR3).
   ============================================================ */

.wg-header__icon-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    color: var(--color-text-secondary);
    cursor: pointer;
    text-decoration: none;
    transition: color var(--duration-base) var(--ease-default),
                background-color var(--duration-base) var(--ease-default);
    flex-shrink: 0;
}

.wg-header__icon-btn:hover {
    color: var(--color-text-primary);
    background: rgba(17, 16, 16, 0.04);
}

.wg-header__icon-btn:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}


/* ============================================================
   SEARCH TRIGGER RESPONSIVE VISIBILITY
   Desktop trigger hidden on mobile; mobile trigger hidden on desktop.
   Both must change visibility together with their respective panels (NOVA NR8).
   ============================================================ */

/* Desktop search trigger — visible ≥769px */
.wg-search-trigger {
    display: flex;
}

@media (max-width: 768px) {
    .wg-search-trigger {
        display: none;  /* Hidden on mobile — mobile trigger takes over */
    }
}

/* Mobile search trigger — visible ≤768px */
.wg-search-trigger--mobile {
    display: none;
}

@media (max-width: 768px) {
    .wg-search-trigger--mobile {
        display: flex;
    }
}


/* ============================================================
   UPLOAD BUTTON — .wg-header__upload-btn
   Desktop only. Uses Phase 0 button tokens.
   ============================================================ */

.wg-header__upload-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: var(--btn-height-md);
    padding: 0 var(--btn-padding-x-md);
    font-family: var(--font-display);
    font-size: var(--text-ui-md-size);
    font-weight: var(--text-ui-md-weight);
    line-height: var(--text-ui-md-lh);
    color: var(--color-text-inverse);
    background: var(--color-accent);
    border: none;
    border-radius: var(--btn-radius-md);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color var(--duration-base) var(--ease-default),
                transform var(--duration-instant) var(--ease-default);
    flex-shrink: 0;
}

.wg-header__upload-btn:hover {
    background: var(--color-accent-hover);
    color: var(--color-text-inverse);
}

.wg-header__upload-btn:active {
    background: var(--color-accent-active);
    transform: scale(0.97);
}

.wg-header__upload-btn:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Hidden on mobile */
@media (max-width: 768px) {
    .wg-header__upload-btn {
        display: none;
    }
}


/* ============================================================
   AUTH AREA — .wg-auth
   MR4b FIX: position:relative makes .wg-auth the containing block
   for .wg-auth-dropdown when top:100% is used instead of the
   hardcoded calc(--header-height + 8px) value.
   ============================================================ */

.wg-auth {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    position: relative;   /* MR4b: containing block for auth dropdown top:100% */
}


/* ── Logged-out desktop text link ── */

.wg-auth__login-link--desktop {
    display: inline-flex;
    align-items: center;
    padding: var(--space-2) var(--space-3);
    font-family: var(--font-display);
    font-size: var(--text-ui-md-size);
    font-weight: var(--text-ui-md-weight);
    color: var(--color-text-secondary);
    text-decoration: none;
    border-radius: var(--radius-md);
    transition: color var(--duration-base) var(--ease-default),
                background-color var(--duration-base) var(--ease-default);
}

.wg-auth__login-link--desktop:hover {
    color: var(--color-text-primary);
    background: rgba(17, 16, 16, 0.04);
}

.wg-auth__login-link--desktop:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Hidden on mobile */
@media (max-width: 768px) {
    .wg-auth__login-link--desktop {
        display: none;
    }
}


/* ── Logged-out mobile icon link ── */

.wg-auth__login-icon {
    display: none;
}

@media (max-width: 768px) {
    .wg-auth__login-icon {
        display: flex;
    }
}


/* ── Avatar button (both viewports) ── */

.wg-avatar-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 2px;           /* Creates the 40px inner circle with 2px border */
    background: transparent;
    border: none;
    border-radius: var(--radius-full);
    cursor: pointer;
    flex-shrink: 0;
    transition: box-shadow var(--duration-base) var(--ease-default);
}

.wg-avatar-btn:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.wg-avatar-btn__img {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-full);
    object-fit: cover;
    border: 2px solid var(--color-border);
    display: block;
    transition: border-color var(--duration-base) var(--ease-default);
}

.wg-avatar-btn:hover .wg-avatar-btn__img {
    border-color: var(--color-border-strong);
}

/* Border turns accent when dropdown is open */
.wg-avatar-btn[aria-expanded="true"] .wg-avatar-btn__img {
    border-color: var(--color-accent);
}

.wg-avatar-btn__initial {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-full);
    background: var(--color-accent-subtle);
    border: 2px solid var(--color-border);
    font-family: var(--font-display);
    font-size: var(--text-h4-size);
    font-weight: 600;
    color: var(--color-accent);
    line-height: 1;
    transition: border-color var(--duration-base) var(--ease-default);
}

.wg-avatar-btn:hover .wg-avatar-btn__initial {
    border-color: var(--color-border-strong);
}

.wg-avatar-btn[aria-expanded="true"] .wg-avatar-btn__initial {
    border-color: var(--color-accent);
}


/* ============================================================
   DROPDOWN BASE — .wg-dropdown
   Shared by .wg-categories-dropdown and .wg-auth-dropdown.

   MR4b FIX: top is now top: 100% (relative to the containing block
   set by position:relative on the parent: .wg-nav__item for categories,
   .wg-auth for auth dropdown). This replaces the hardcoded
   calc(var(--header-height) + 8px) which used the desktop header
   height even on mobile (56px header), creating a 16px gap instead
   of the intended 8px gap.

   The margin-top: var(--space-2) adds the 8px visual offset below
   the trigger without hard-coding a pixel distance from the header top.

   INERTNESS RULE (ATLAS §4E, NOVA NR4):
   Closed state: aria-hidden="true" + inert + display:none.
   All three required simultaneously.
   Never use opacity:0 alone — focusable content stays accessible.
   ============================================================ */

.wg-dropdown {
    position: absolute;
    top: 100%;                          /* MR4b: relative to parent, not header top */
    margin-top: var(--space-2);         /* MR4b: 8px offset — works at any breakpoint */
    min-width: 200px;
    max-width: 280px;
    background: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-dropdown);
    z-index: var(--z-dropdown);
    padding: var(--space-2) 0;
    /* Animation prep — opacity/transform for enter animation */
    opacity: 0;
    transform: translateY(-4px);
    transition:
        opacity var(--duration-moderate) var(--ease-enter),
        transform var(--duration-moderate) var(--ease-enter);
}

/* Open state: JS removes inert, sets aria-hidden="false", sets display:block */
.wg-dropdown[aria-hidden="false"] {
    display: block;
    opacity: 1;
    transform: translateY(0);
}


/* ── Categories dropdown positioning ── */

/* MR2 FIX: Explicit display:none !important at mobile.
   Rationale: the categories trigger is inside .wg-header__nav which is
   display:none at ≤768px, so JS cannot open this dropdown on mobile.
   However, a JS error or race condition could incorrectly set aria-hidden="false"
   while the trigger is invisible. This safety override prevents any such
   scenario from rendering the dropdown on mobile — same pattern as
   .wg-search-inline and .wg-search-panel overrides.
   Also prevents the layout inconsistency of a 72px top offset (desktop
   header height) appearing against a 56px tall mobile header. */
@media (max-width: 768px) {
    .wg-categories-dropdown {
        display: none !important;
    }
}

/* MR5 FIX: max-height + overflow-y:auto prevents the categories dropdown
   from growing beyond the viewport height. With up to 50 categories at
   ~40px per item = 2000px potential height, this is a hard requirement.
   calc(100vh - var(--header-height) - var(--space-4)) leaves the header
   and a small bottom clearance, making the full list scrollable. */
.wg-categories-dropdown {
    left: 0;
    max-height: calc(100vh - var(--header-height) - var(--space-4));
    overflow-y: auto;
}


/* ── Auth dropdown positioning — right-aligned to avatar ── */

.wg-auth-dropdown {
    right: 0;
    left: auto;
    min-width: 200px;
}


/* ── Dropdown items ── */

.wg-dropdown__item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    font-family: var(--font-body);
    font-size: var(--text-body-size);
    font-weight: var(--text-body-weight);
    line-height: var(--text-body-lh);
    color: var(--color-text-primary);
    text-decoration: none;
    background: transparent;
    min-height: 40px;
    transition:
        background-color var(--duration-base) var(--ease-default),
        color var(--duration-base) var(--ease-default);
}

.wg-dropdown__item:hover {
    background: var(--color-accent-subtle);
    color: var(--color-accent);
}

.wg-dropdown__item:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: -2px;
    background: var(--color-accent-subtle);
    color: var(--color-accent);
}

/* Log Out item — destructive hover treatment */
.wg-dropdown__item--logout {
    color: var(--color-text-secondary);
}

.wg-dropdown__item--logout:hover {
    color: var(--color-error);
    background: var(--color-error-subtle);
}

.wg-dropdown__item--logout:focus-visible {
    color: var(--color-error);
    background: var(--color-error-subtle);
    outline-color: var(--color-error);
}

/* Empty state text in dropdown (no categories) */
.wg-dropdown__empty {
    display: block;
    padding: var(--space-2) var(--space-4);
    font-size: var(--text-body-size);
    color: var(--color-text-disabled);
}


/* ── Dropdown divider ── */

.wg-dropdown__divider {
    margin: var(--space-1) 0;
    border: none;
    border-top: 1px solid var(--color-border);
}


/* ============================================================
   DESKTOP INLINE SEARCH PANEL — .wg-search-inline
   Overlays the nav and actions zone from the right.
   Compositor-friendly animation: max-width (no reflow width).
   Uses clip-path approach: the panel itself uses overflow:hidden.

   MR3 FIX: This element is now inside .wg-header__inner in the DOM
   (header.php). position:absolute now correctly resolves its containing
   block to .wg-header__inner (position:relative), not the viewport.
   top:50% = 50% of header height, not 50% of viewport height.

   TECHNIQUE DECISION (resolving AURORA's deferred question):
   Animating max-width from 0 to a large value with overflow:hidden
   provides the right-to-left expansion visual. This avoids reflow
   caused by animating 'width' directly on a flex item.
   The panel is position:absolute, removing it from flex flow entirely.
   ============================================================ */

.wg-search-inline {
    position: absolute;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    height: var(--btn-height-md);
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-xl);
    z-index: var(--z-dropdown);
    overflow: hidden;
    max-width: 0;
    opacity: 0;
    transition:
        max-width var(--duration-moderate) var(--ease-enter),
        opacity var(--duration-moderate) var(--ease-enter);
    /* Left boundary: leaves room for logo zone (approx 120px logo + 24px gap).
       Now correctly measured relative to .wg-header__inner, not the viewport. */
    left: 148px;
}

/* Open state */
.wg-search-inline[aria-hidden="false"] {
    display: flex;
    max-width: 100%;
    opacity: 1;
}

/* Desktop only — mobile search has its own panel */
@media (max-width: 768px) {
    .wg-search-inline {
        display: none !important;  /* Force-hide: must NEVER appear on mobile.
                                      Using !important only on this display:none
                                      because this is a safety override for the
                                      breakpoint exclusivity rule (MIRA MC7).
                                      The aria-hidden rule would also catch it,
                                      but an explicit breakpoint rule prevents
                                      any JS timing issue from accidentally
                                      making this visible on mobile. */
    }
}


/* ── Search form (shared by desktop panel and mobile panel) ── */

.wg-search-form {
    display: flex;
    align-items: center;
    width: 100%;
    height: 100%;
}

.wg-search-form__icon {
    flex-shrink: 0;
    margin-left: var(--space-3);
    color: var(--color-text-secondary);
    pointer-events: none;
}

.wg-search-input {
    flex: 1;
    height: 100%;
    padding: 0 var(--space-4);
    font-family: var(--font-body);
    font-size: var(--text-input-size);     /* 16px — MIRA MIR2, iOS zoom prevention */
    font-weight: var(--text-input-weight);
    line-height: var(--text-input-lh);
    color: var(--color-text-primary);
    background: transparent;
    border: none;
    outline: none;
    min-width: 0;   /* Prevent flex overflow */
    /* Removes browser default search input styling */
    -webkit-appearance: none;
    appearance: none;
}

.wg-search-input::placeholder {
    color: var(--color-text-disabled);
}

/* Suppress browser's built-in clear button on search inputs */
.wg-search-input::-webkit-search-cancel-button {
    display: none;
}

.wg-search-submit {
    /* Inherits .wg-header__icon-btn */
    flex-shrink: 0;
}

.wg-search-close {
    /* Inherits .wg-header__icon-btn */
    flex-shrink: 0;
    margin-right: var(--space-2);
}


/* ============================================================
   MOBILE SEARCH PANEL — .wg-search-panel
   Fixed below the sticky header. Full viewport width.
   Separate element from desktop search (NOVA NR8, AURORA decision).

   Visible ≤768px only. Hidden ≥769px via display:none.
   MIRA MC7: one search per viewport, zero overlap.
   ============================================================ */

.wg-search-panel {
    position: fixed;
    top: calc(var(--header-height-mobile) + var(--wp-admin--admin-bar--height, 0px));
    left: 0;
    right: 0;
    width: 100%;
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    box-shadow: var(--shadow-panel);
    z-index: var(--z-dropdown);   /* 100 — below sticky header (200) */
    padding: var(--space-3) var(--space-4);

    /* Animation prep */
    opacity: 0;
    transform: translateY(-8px);
    transition:
        opacity var(--duration-moderate) var(--ease-enter),
        transform var(--duration-moderate) var(--ease-enter);
}

/* Open state */
.wg-search-panel[aria-hidden="false"] {
    display: flex;
    opacity: 1;
    transform: translateY(0);
}

/* Desktop: force-hide. Must never appear above 768px (MIRA MC7). */
@media (min-width: 769px) {
    .wg-search-panel {
        display: none !important;  /* Same reasoning as .wg-search-inline override above */
    }
}

/* Mobile search form is a flex row with height for touch targets */
.wg-search-panel .wg-search-form {
    height: 44px;   /* var(--input-height) — touch target */
}


/* ============================================================
   PAGE LAYOUT OFFSET
   Body content needs top padding equal to header height so it
   starts below the fixed header. Using CSS padding on .wg-main.
   ============================================================ */

.wg-page {
    padding-top: calc(var(--header-height) + var(--wp-admin--admin-bar--height, 0px));
}

@media (max-width: 768px) {
    .wg-page {
        padding-top: calc(var(--header-height-mobile) + var(--wp-admin--admin-bar--height, 0px));
    }
}


/* ============================================================
   REDUCED MOTION OVERRIDE
   From Phase 0 spec (ATLAS §5). Included here for completeness
   when appending to main.css — Phase 0 already has this block,
   so FORGE should NOT duplicate it. Listed here for reference.
   ============================================================ */

/*
@media (prefers-reduced-motion: reduce) {
    .wg-header,
    .wg-dropdown,
    .wg-search-inline,
    .wg-search-panel,
    .wg-logo,
    .wg-nav__link,
    .wg-header__icon-btn,
    .wg-avatar-btn,
    .wg-auth__login-link--desktop {
        transition-duration: 0.01ms;
    }
}
*/
/* NOTE: Phase 0 main.css already has a global prefers-reduced-motion
   rule covering *, *::before, *::after. Do not duplicate here. */

/* ============================================================
   PHASE 2 — HOMEPAGE GRID
   REX ALL PASS — 2026-03-27
   ============================================================ */
/*
 * ============================================================
 * 8KWALLS — Phase 2: Homepage Grid CSS
 * Version: 4.2.0
 *
 * Scope: index.php components only.
 * After REX sign-off, append to /output/theme/assets/main.css
 * and bump WG_ASSET_VERSION in functions.php.
 *
 * Tokens used: all from main.css :root block (Phase 0).
 * Breakpoints: canonical set from ATLAS §8 only.
 * No !important except documented breakpoint-exclusivity overrides.
 * No nesting beyond 2 levels.
 * No raw hex values — all colors via var(--token).
 *
 * Agent decisions applied:
 *   NOVA R1  — overlay hidden via [inert]; JS removes inert on hover
 *   NOVA R3  — filter pill hrefs use wallpaper_category param (CSS is param-agnostic)
 *   NOVA R4  — mobile sort form (CSS shows/hides form vs pill group)
 *   NOVA R6  — loading attrs applied in PHP; CSS handles aspect ratios
 *   ATLAS §4A — card hover shadow via ::after opacity pattern
 *   ATLAS §4A — 4/3 aspect ratio below 480px
 *   ATLAS §8  — grid gutter switch at 769px
 *   MIRA MIR3 — pill touch zone via padding on .wg-filter-pills
 *   ECHO EC7  — ad slot placeholder styles
 * ============================================================
 */


/* ============================================================
   SHARED CONTAINER
   max-width: 1440px centred with horizontal padding.
   Padding switches at 768px breakpoint.
   ============================================================ */

.wg-container {
    max-width: 1440px;
    margin-right: auto;
    margin-left: auto;
    padding-right: var(--space-6);
    padding-left: var(--space-6);
}

@media (max-width: 768px) {
    .wg-container {
        padding-right: var(--space-4);
        padding-left: var(--space-4);
    }
}


/* ============================================================
   ZONE 1 — HERO BANNER
   Compact typographic strip. No background image.
   AURORA Component 1.
   ============================================================ */

.wg-main--homepage {
    background-color: var(--color-bg);
}

.wg-homepage-hero {
    /* Account for sticky header height + admin bar offset (MIRA M2-01, M2-02) */
    padding-top: calc(var(--header-height) + var(--wp-admin--admin-bar--height, 0px) + var(--space-10));
    padding-bottom: var(--space-8);
}

@media (max-width: 768px) {
    .wg-homepage-hero {
        /* Mobile header height + admin bar offset (MIRA M2-01, M2-02) */
        padding-top: calc(var(--header-height-mobile) + var(--wp-admin--admin-bar--height, 0px) + var(--space-6));
        padding-bottom: var(--space-6);
    }
}

.wg-homepage-hero__title {
    font-family: var(--font-display);
    font-size: 2rem;          /* --text-h1 */
    font-weight: 600;
    line-height: 1.20;
    letter-spacing: -0.02em;
    color: var(--color-text-primary);
    margin-top: 0;
    margin-bottom: var(--space-2);
    max-width: 560px;         /* Prose cap — approved raw value (no token) */
}

@media (max-width: 480px) {
    .wg-homepage-hero__title {
        font-size: 1.5rem;    /* --text-h2 on small mobile */
    }
}

.wg-homepage-hero__sub {
    font-family: var(--font-body);
    font-size: 0.9375rem;     /* --text-body */
    font-weight: 400;
    line-height: 1.60;
    color: var(--color-text-secondary);
    max-width: 480px;         /* Prose constraint — approved raw value */
    margin-top: 0;
    margin-bottom: 0;
}


/* ============================================================
   ZONE 2 — FILTER / SORT BAR
   Sticky below header. Full-width with border-bottom.
   ============================================================ */

.wg-filter-bar {
    position: sticky;
    /* Desktop: below header + admin bar offset (MIRA M2-02) */
    top: calc(var(--header-height) + var(--wp-admin--admin-bar--height, 0px));
    z-index: var(--z-sticky);
    background-color: var(--color-bg);
    border-bottom: 1px solid var(--color-border);
    padding-top: var(--space-3);
    padding-bottom: var(--space-3);
    width: 100%;
}

@media (max-width: 768px) {
    .wg-filter-bar {
        /* Mobile: below mobile header + admin bar offset (MIRA M2-02) */
        top: calc(var(--header-height-mobile) + var(--wp-admin--admin-bar--height, 0px));
    }
}

.wg-filter-bar__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
}

/* Left zone: pill row */
.wg-filter-bar__cats {
    flex: 1;
    min-width: 0;  /* Allow shrink in flex row */
    overflow: hidden;
}

/* Right zone: sort control */
.wg-filter-bar__sort {
    flex-shrink: 0;
}


/* ============================================================
   CATEGORY PILLS
   ============================================================ */

.wg-filter-pills {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--space-2);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Mobile touch zone: pad the strip so taps register — MIRA M2-03 */
    /* 8px + 32px pill + 8px = 48px strip height — meets ≥44px touch minimum */
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
}

.wg-filter-pills::-webkit-scrollbar {
    display: none;
}

@media (min-width: 769px) {
    .wg-filter-pills {
        overflow-x: visible;
        flex-wrap: wrap;
    }
}

.wg-pill {
    display: inline-flex;
    align-items: center;
    height: 32px;
    padding-right: var(--space-3);
    padding-left: var(--space-3);
    font-family: var(--font-display);
    font-size: 0.75rem;       /* --text-label */
    font-weight: 500;
    line-height: 1.40;
    letter-spacing: 0.04em;
    color: var(--color-text-secondary);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 999px;
    white-space: nowrap;
    cursor: pointer;
    text-decoration: none;
    flex-shrink: 0;
    transition:
        background-color 120ms ease,
        border-color 120ms ease,
        color 120ms ease;
}

.wg-pill:hover {
    color: var(--color-text-primary);
    background-color: var(--color-bg);
    border-color: var(--color-border-strong);
}

.wg-pill--active,
.wg-pill[aria-current="page"] {
    color: var(--color-accent);
    background-color: var(--color-accent-subtle);
    border-color: var(--color-accent-subtle-border);
    font-weight: 600;
}

.wg-pill:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}


/* ============================================================
   SORT CONTROL — DESKTOP PILLS
   ============================================================ */

.wg-sort-group {
    display: none;   /* Hidden on mobile — shown on desktop below */
    align-items: center;
    gap: var(--space-1);
}

@media (min-width: 769px) {
    .wg-sort-group {
        display: flex;
    }
}

.wg-sort-pill {
    display: inline-flex;
    align-items: center;
    height: 32px;
    padding-right: var(--space-3);
    padding-left: var(--space-3);
    font-family: var(--font-display);
    font-size: 0.75rem;       /* --text-label */
    font-weight: 500;
    letter-spacing: 0.04em;
    color: var(--color-text-secondary);
    background-color: transparent;
    border: none;
    border-radius: 999px;
    white-space: nowrap;
    cursor: pointer;
    text-decoration: none;
    transition:
        color 120ms ease,
        background-color 120ms ease;
}

.wg-sort-pill:hover {
    color: var(--color-text-primary);
    background-color: rgba(17, 16, 16, 0.04);
}

.wg-sort-pill--active,
.wg-sort-pill[aria-current="page"] {
    color: var(--color-accent);
    background-color: var(--color-accent-subtle);
    font-weight: 600;
}

.wg-sort-pill:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}


/* ============================================================
   SORT CONTROL — MOBILE FORM + SELECT
   NOVA R4: <form method="get"> wraps the select for no-JS fallback.
   ============================================================ */

.wg-sort-form {
    display: block;
}

@media (min-width: 769px) {
    .wg-sort-form {
        display: none;   /* Hidden on desktop — pill group shown instead */
    }
}

/*
 * Visually hidden submit button — present for no-JS users,
 * hidden from view but reachable by keyboard and screen readers.
 * JS users never see it because JS overrides the select onChange.
 */
.wg-sort-form__submit-btn {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Select wrapper (Phase 0 §4D pattern) */
.wg-select-wrapper {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.wg-select-wrapper--sort {
    display: none; /* Default hidden — shown on mobile */
}

@media (max-width: 768px) {
    .wg-select-wrapper--sort {
        display: inline-flex;
    }
}

.wg-select-wrapper__chevron {
    position: absolute;
    right: var(--space-3);
    pointer-events: none;
    color: var(--color-text-secondary);
    z-index: 1;
}

.wg-input--sort {
    appearance: none;
    -webkit-appearance: none;
    font-family: var(--font-body);
    font-size: var(--text-input);    /* 1rem — mandatory, prevents iOS zoom */
    font-weight: 400;
    line-height: 1.50;
    color: var(--color-text-primary);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    height: 32px;           /* Compact desktop default */
    padding-right: calc(var(--space-3) + 20px);  /* Right padding for chevron */
    padding-left: var(--space-3);
    cursor: pointer;
}

@media (max-width: 768px) {
    .wg-input--sort {
        height: 44px;       /* MIRA MIR3: 44px touch target on mobile */
    }
}

.wg-input--sort:focus-visible {
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 0;
    border-color: var(--color-accent);
}


/* ============================================================
   AD SLOTS — Leaderboard + In-grid
   ECHO EC7. Phase 9 replaces stub content with real AdSense units.
   ============================================================ */

.wg-ad {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--color-border);
    border-radius: var(--radius-xl);
}

.wg-ad__label {
    font-family: var(--font-body);
    font-size: 0.75rem;       /* --text-label */
    color: var(--color-text-disabled);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* Leaderboard: 728×90 standard, centred above grid */
.wg-ad--leaderboard {
    height: 90px;
    max-width: 728px;
    width: 100%;
    margin-right: auto;
    margin-left: auto;
    margin-bottom: var(--space-6);
}

@media (max-width: 768px) {
    /* Mobile leaderboard → banner 320×50 */
    .wg-ad--leaderboard {
        height: 50px;
        max-width: 320px;
    }
}

/* In-grid ad card: occupies same grid cell as a wallpaper card */
.wg-card-wrap--ad {
    /* grid item — same sizing as real card */
}

.wg-ad--card {
    width: 100%;
    aspect-ratio: 16 / 9;
}

@media (max-width: 480px) {
    .wg-ad--card {
        aspect-ratio: 4 / 3;
    }
}


/* ============================================================
   ZONE 3 — GRID SECTION + GRID
   ============================================================ */

.wg-grid-section {
    padding-top: var(--space-6);
    padding-bottom: var(--space-10);
}

@media (min-width: 769px) {
    .wg-grid-section {
        padding-bottom: var(--space-16);
    }
}

.wg-grid {
    /* Reset list styles */
    list-style: none;
    margin: 0;
    padding: 0;

    /* CSS Grid */
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-4);    /* Mobile gap — 16px */
}

/* 3 columns: 769px–1023px */
@media (min-width: 769px) {
    .wg-grid {
        grid-template-columns: repeat(3, 1fr);
        gap: var(--space-6);    /* Desktop gap — 24px */
    }
}

/* 4 columns: ≥1024px */
@media (min-width: 1024px) {
    .wg-grid {
        grid-template-columns: repeat(4, 1fr);
    }
}


/* ============================================================
   CARD COMPONENT
   ATLAS §4A: compositor-safe shadow via ::after opacity.
   ============================================================ */

/* .wg-card-wrap is the <li> grid item — no visual styles */
.wg-card-wrap {
    min-width: 0;  /* Prevent grid blowout */
}

/* .wg-card is the <a> interaction surface */
.wg-card {
    display: block;
    position: relative;
    background-color: var(--color-surface);
    border-radius: var(--radius-xl);
    border: none;
    overflow: hidden;
    cursor: pointer;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    /* Keyboard focus ring */
    outline: none;
}

.wg-card:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Active press: scale down slightly — 100ms */
.wg-card:active {
    transform: scale(0.99);
    transition: transform 100ms ease;
}

/*
 * Compositor-safe hover shadow (ATLAS §4A, NOVA R6 pattern):
 * Shadow is on ::after, animated via opacity only.
 * Keeps animation on GPU compositor thread — no layout/paint.
 */
.wg-card::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow:
        0 8px 24px rgba(17, 16, 16, 0.12),
        0 2px 8px rgba(17, 16, 16, 0.08);
    opacity: 0;
    transition: opacity 150ms ease;
    pointer-events: none;
    z-index: var(--z-raised);
}

.wg-card:hover::after {
    opacity: 1;
}


/* ============================================================
   CARD — IMAGE CONTAINER
   ============================================================ */

.wg-card__image-wrap {
    position: relative;
    overflow: hidden;
    aspect-ratio: 16 / 9;
    background-color: var(--color-border);   /* Placeholder while loading */
}

/* Sub-480px: 4/3 ratio (portrait-oriented small phones) */
@media (max-width: 480px) {
    .wg-card__image-wrap {
        aspect-ratio: 4 / 3;
    }
}

.wg-card__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
    transform: scale(1);
    transition: transform 150ms ease;
}

/* Image scales up on card hover */
.wg-card:hover .wg-card__img {
    transform: scale(1.02);
}

/* Placeholder style when thumbnail is missing */
.wg-card__img--placeholder {
    background-color: var(--color-border);
}


/* ============================================================
   CARD — OVERLAY (NOVA R1)
   Static HTML sets `inert`. JS removes `inert` on mouseenter.
   `[inert]` selector hides overlay from AT and pointer events.
   CSS hover is the visual layer; `inert` is the AT layer.
   No overlay on mobile (max-width: 768px).
   ============================================================ */

.wg-card__overlay {
    position: absolute;
    inset: 0;
    background-color: var(--color-scrim-card);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    opacity: 0;
    pointer-events: none;
    transition: opacity 150ms ease;
    z-index: var(--z-overlay);
}

/* Overlay shown on hover (CSS) AND when not inert (JS removed inert) */
.wg-card:hover .wg-card__overlay:not([inert]) {
    opacity: 1;
    pointer-events: auto;
}

/* When inert attribute is present: overlay stays invisible and non-interactive */
.wg-card__overlay[inert] {
    opacity: 0;                 /* !important: forced hidden when inert */
    pointer-events: none;       /* !important: always non-interactive when inert */
}

/* Hide overlay entirely on touch devices */
@media (max-width: 768px) {
    .wg-card__overlay {
        display: none;          /* !important: breakpoint-exclusivity override — ATLAS §CSS law */
    }
}


/* ============================================================
   CARD — OVERLAY ACTION BUTTONS (Download / Save)
   ============================================================ */

.wg-card__action {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    background-color: var(--color-surface);
    border: none;
    border-radius: 50%;
    color: var(--color-text-primary);
    cursor: pointer;
    flex-shrink: 0;
    transition:
        background-color 120ms ease,
        transform 80ms ease,
        color 120ms ease;
}

.wg-card__action:hover {
    background-color: var(--color-accent-subtle);
    color: var(--color-accent);
}

.wg-card__action:active {
    transform: scale(0.93);
}

/* Save button states (Phase 0 §4A card state machine) */
.wg-card__action--save[data-save-state="loading"] {
    pointer-events: none;
    opacity: 0.7;
}

.wg-card__action--save[data-save-state="saved"] {
    color: var(--color-accent);
    background-color: var(--color-accent-subtle);
}

.wg-card__action--save[data-save-state="error"] {
    color: var(--color-error);
    animation: wg-shake 300ms ease;
}


/* ============================================================
   CARD — META (Title + Category)
   ============================================================ */

.wg-card__meta {
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.wg-card__title {
    font-family: var(--font-display);
    font-size: 0.875rem;      /* --text-body-sm */
    font-weight: 400;
    line-height: 1.55;
    color: var(--color-text-primary);
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wg-card__category {
    display: block;
    font-family: var(--font-body);
    font-size: 0.8125rem;     /* --text-caption */
    font-weight: 400;
    line-height: 1.50;
    letter-spacing: 0.01em;
    color: var(--color-text-secondary);
}


/* ============================================================
   ZONE 4 — PAGINATION (No-JS fallback)
   Visible when JS is disabled. JS hides this and inserts Load More.
   ============================================================ */

.wg-pagination {
    text-align: center;
    padding-top: var(--space-8);
    padding-bottom: var(--space-8);
}

.wg-pagination .page-numbers {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 36px;
    height: 36px;
    padding-right: var(--space-2);
    padding-left: var(--space-2);
    margin: 0 2px;
    font-family: var(--font-body);
    font-size: 0.9375rem;     /* --text-body */
    font-weight: 400;
    color: var(--color-text-primary);
    text-decoration: none;
    border-radius: var(--radius-md);
    transition: background-color 120ms ease;
}

.wg-pagination .page-numbers:hover {
    background-color: var(--color-accent-subtle);
    color: var(--color-accent);
}

.wg-pagination .page-numbers.current {
    background-color: var(--color-accent);
    color: var(--color-text-inverse);
    font-weight: 600;
}

.wg-pagination .page-numbers:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.wg-pagination__link {
    display: none;   /* prev/next links hidden — paginate_links() provides full set */
}


/* ============================================================
   LOAD MORE BUTTON (JS-created — these styles must match)
   JS creates this button and appends to .wg-pagination.
   ============================================================ */

.wg-btn--load-more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    height: 44px;
    min-width: 160px;
    padding-right: var(--space-4);
    padding-left: var(--space-4);
    font-family: var(--font-body);
    font-size: 0.9375rem;     /* --text-ui-md */
    font-weight: 500;
    line-height: 1;
    color: var(--color-text-primary);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;      /* md radius */
    cursor: pointer;
    text-decoration: none;
    transition:
        background-color 120ms ease,
        border-color 120ms ease;
}

.wg-btn--load-more:hover {
    background-color: var(--color-bg);
    border-color: var(--color-border-strong);
}

.wg-btn--load-more:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.wg-btn--load-more[data-state="loading"] {
    pointer-events: none;
    cursor: not-allowed;
    opacity: 0.7;
}

.wg-btn--load-more[data-state="error"] {
    border-color: var(--color-error);
    color: var(--color-error);
    animation: wg-shake 300ms ease;
}


/* ============================================================
   PAGINATION END STATE
   ============================================================ */

.wg-pagination__end {
    font-family: var(--font-body);
    font-size: 0.9375rem;     /* --text-body */
    color: var(--color-text-secondary);
    text-align: center;
    padding-top: var(--space-8);
    padding-bottom: var(--space-8);
    margin: 0;
}

.wg-link--accent {
    color: var(--color-accent);
    text-decoration: underline;
    font-weight: 500;
}

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


/* ============================================================
   SPINNER (CSS-only, used inside Load More button)
   ============================================================ */

.wg-spinner {
    display: inline-block;
    width: 16px;
    height: 16px;
    border: 2px solid var(--color-border-strong);
    border-top-color: var(--color-text-primary);
    border-radius: 50%;
    animation: wg-spin 600ms linear infinite;
    flex-shrink: 0;
}

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

@media (prefers-reduced-motion: reduce) {
    .wg-spinner {
        animation: none;
        border-top-color: var(--color-accent);
    }
}


/* ============================================================
   SKELETON CARDS (Load More in-flight state)
   JS-appended during AJAX fetch. Not present on initial server render.
   ============================================================ */

.wg-card-skeleton {
    display: block;
    width: 100%;
}

.wg-card-skeleton__image {
    aspect-ratio: 16 / 9;
    border-radius: var(--radius-xl);
    overflow: hidden;
}

@media (max-width: 480px) {
    .wg-card-skeleton__image {
        aspect-ratio: 4 / 3;
    }
}

.wg-card-skeleton__meta {
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.wg-card-skeleton__title {
    height: 14px;
    width: 70%;
    border-radius: 4px;
}

.wg-card-skeleton__category {
    height: 13px;
    width: 40%;
    border-radius: 4px;
}

/* Shimmer animation (Phase 0 §5 — ATLAS LOCKED) */
.wg-card-skeleton__image,
.wg-card-skeleton__title,
.wg-card-skeleton__category {
    background: linear-gradient(
        90deg,
        var(--color-border) 25%,
        var(--color-bg) 50%,
        var(--color-border) 75%
    );
    background-size: 200% 100%;
    animation: wg-shimmer 1500ms linear infinite;
}

@keyframes wg-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .wg-card-skeleton__image,
    .wg-card-skeleton__title,
    .wg-card-skeleton__category {
        animation: none;
        background: var(--color-border);
    }
}


/* ============================================================
   EMPTY STATES
   ATLAS §9 universal empty state pattern.
   ============================================================ */

.wg-empty-state {
    text-align: center;
    padding: var(--space-24) var(--space-6);
    max-width: 480px;
    margin-right: auto;
    margin-left: auto;
}

.wg-empty-state__icon {
    display: block;
    margin-right: auto;
    margin-left: auto;
    margin-bottom: var(--space-4);
    color: var(--color-text-disabled);
    /* Size set via wg_icon() $size param (48px = --icon-xl) */
}

.wg-empty-state__headline {
    font-family: var(--font-display);
    font-size: 1.5rem;        /* --text-h2 */
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.015em;
    color: var(--color-text-primary);
    margin-top: 0;
    margin-bottom: var(--space-2);
}

.wg-empty-state__body {
    font-family: var(--font-body);
    font-size: 0.9375rem;     /* --text-body */
    font-weight: 400;
    line-height: 1.60;
    color: var(--color-text-secondary);
    max-width: 360px;
    margin-right: auto;
    margin-left: auto;
    margin-top: 0;
    margin-bottom: var(--space-6);
}


/* ============================================================
   SHARED BUTTON SYSTEM (wg-btn)
   Only md + primary / secondary variants needed in Phase 2.
   Full button system lives in main.css Phase 0.
   ============================================================ */

.wg-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    border: none;
    cursor: pointer;
    font-family: var(--font-body);
    font-weight: 500;
    line-height: 1;
    text-decoration: none;
    transition:
        background-color 120ms ease,
        border-color 120ms ease,
        transform 80ms ease;
}

.wg-btn:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.wg-btn:active {
    transform: scale(0.97);
}

.wg-btn[data-state="loading"] {
    pointer-events: none;
    cursor: not-allowed;
}

/* md size */
.wg-btn--md {
    height: 44px;
    padding-right: var(--space-4);
    padding-left: var(--space-4);
    font-size: 0.9375rem;     /* --text-ui-md */
    border-radius: 10px;
}

/* Primary */
.wg-btn--primary {
    background-color: var(--color-accent);
    color: var(--color-text-inverse);
}

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

.wg-btn--primary:active {
    background-color: var(--color-accent-active);
}

/* Secondary */
.wg-btn--secondary {
    background-color: var(--color-surface);
    color: var(--color-text-primary);
    border: 1px solid var(--color-border);
}

.wg-btn--secondary:hover {
    background-color: var(--color-bg);
    border-color: var(--color-border-strong);
}


/* ============================================================
   KEYFRAME ANIMATIONS (shared)
   ============================================================ */

@keyframes wg-shake {
    0%, 100% { transform: translateX(0); }
    20%       { transform: translateX(-4px); }
    40%       { transform: translateX(4px); }
    60%       { transform: translateX(-3px); }
    80%       { transform: translateX(3px); }
}


/* ============================================================
   REDUCED MOTION — GLOBAL OVERRIDE
   Matches Phase 0 ATLAS LOCKED rule.
   ============================================================ */

@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;
    }
}


/* ============================================================
   PHASE 3 — WALLPAPER DETAIL PAGE
   REX ALL PASS — 2026-03-27
   ============================================================ */

/*
 * ============================================================
 * 8KWALLS — Phase 3: Wallpaper Detail Page Styles
 * detail.css
 *
 * Scope: single-wallpaper.php ONLY.
 * All selectors are scoped to Phase 3 components.
 * No token definitions here — all tokens come from main.css.
 * CSS Law: wg- namespace, max 2 nesting levels, no !important
 *          except documented breakpoint-exclusivity overrides.
 *
 * NOVA decisions applied:
 *   R2: Tooltip inertness — [inert] CSS suppresses hidden state.
 *   R3: FAB visibility tied to .is-visible class (IntersectionObserver
 *       in detail.js adds/removes it).
 *   N3: --download-bar-height local token for single-point height edits.
 *
 * ATLAS §10 Phase 3 carry-forwards:
 *   - Hero heights from Section 4B (50vh mobile, NOT 50vw).
 *   - FAB bottom: calc(var(--download-bar-height) + var(--space-4)).
 *   - Toast bottom on .single-wallpaper.
 * ============================================================
 */


/* ============================================================
   LOCAL PAGE TOKEN
   NOVA N3: defines sticky bar height once; used by both the
   bar, the FAB offset, and the main padding.
   ============================================================ */

body.single-wallpaper,
body.wg-single-wallpaper {
    --download-bar-height: 60px;
}


/* ============================================================
   MAIN ELEMENT — padding for sticky header + sticky bar
   ============================================================ */

.wg-detail-main {
    padding-top: calc(var(--header-height, 64px) + var(--wp-admin--admin-bar--height, 0px));
    padding-bottom: var(--download-bar-height);
}

@media (max-width: 768px) {
    .wg-detail-main {
        padding-top: calc(var(--header-height-mobile, 56px) + var(--wp-admin--admin-bar--height, 0px));
    }
}


/* ============================================================
   ZONE 0 — BREADCRUMB
   ============================================================ */

.wg-breadcrumb {
    padding: var(--space-3) var(--space-6);
    background: var(--color-bg);
}

@media (max-width: 768px) {
    .wg-breadcrumb {
        padding: var(--space-3) var(--space-4);
    }
}

.wg-breadcrumb__list {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: var(--text-caption-size, 0.8125rem);
    font-weight: 400;
    line-height: var(--text-caption-lh, 1.50);
    color: var(--color-text-secondary);
}

.wg-breadcrumb__sep {
    color: var(--color-text-disabled);
    user-select: none;
}

.wg-breadcrumb__link {
    color: var(--color-text-secondary);
    text-decoration: none;
    transition: color 120ms ease;
}

.wg-breadcrumb__link:hover {
    color: var(--color-text-primary);
    text-decoration: underline;
}

.wg-breadcrumb__link:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: 2px;
}

.wg-breadcrumb__link:active {
    color: var(--color-accent);
}

.wg-breadcrumb__current {
    color: var(--color-text-secondary);
    /* Truncate on mobile only */
}

@media (max-width: 768px) {
    .wg-breadcrumb__current {
        display: inline-block;
        max-width: 280px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        vertical-align: bottom;
    }
}


/* ============================================================
   ZONE 1 — HERO
   Heights from ATLAS Section 4B. 50vh mobile — NEVER 50vw.
   ============================================================ */

.wg-detail-hero {
    position: relative;
    width: 100%;
    height: 70vh;
    min-height: 480px;
    max-height: 800px;
    background-color: var(--color-text-primary);   /* Dark placeholder — loading state */
    overflow: hidden;
}

/* Hero heights — breakpoints match ATLAS Section 4B exactly */
@media (max-width: 1279px) {
    .wg-detail-hero {
        height: 60vh;
        min-height: 400px;
        max-height: 640px;
    }
}

@media (max-width: 768px) {
    .wg-detail-hero {
        height: 50vh;   /* vh — NEVER vw. MIRA MIR1 permanent fix. */
        min-height: 280px;
        max-height: 480px;
    }
}

@media (max-width: 480px) {
    .wg-detail-hero {
        height: 50vh;
        min-height: 240px;
        max-height: 420px;
    }
}

/* picture element — fills hero */
.wg-detail-hero__picture {
    display: block;
    width: 100%;
    height: 100%;
}

/* Hero image */
.wg-detail-hero__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center center;
    /* Loading state: invisible until JS adds .is-loaded */
    opacity: 0;
    transition: opacity 200ms ease-out;
}

/* Loaded state — JS adds .is-loaded on img.onload */
.wg-detail-hero__img.is-loaded {
    opacity: 1;
}

/* Error state — img stays invisible; error icon shown via parent */
.wg-detail-hero__img.is-error {
    opacity: 0;
}

/* Error state icon — hidden by default, shown when img has .is-error */
.wg-detail-hero__error-state {
    display: none;
    position: absolute;
    inset: 0;
    align-items: center;
    justify-content: center;
    color: var(--color-text-disabled);
}

/* Show error state only when the img sibling has .is-error */
.wg-detail-hero:has(.wg-detail-hero__img.is-error) .wg-detail-hero__error-state {
    display: flex;
}

/* Scroll sentinel — zero-size, lives at bottom of hero for IntersectionObserver */
#wg-detail-scroll-sentinel {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 1px;
    pointer-events: none;
}


/* ============================================================
   ZONE 2 — INFO PANEL
   ============================================================ */

.wg-detail-info {
    background: var(--color-surface);
    border-top: 1px solid var(--color-border);
    padding-top: var(--space-6);
    padding-bottom: var(--space-8);
    width: 100%;
}

@media (max-width: 768px) {
    .wg-detail-info {
        padding-top: var(--space-5);
        padding-bottom: var(--space-6);
    }
}

.wg-detail-info__inner {
    max-width: 1440px;
    margin: 0 auto;
    padding-left: var(--space-6);
    padding-right: var(--space-6);
    display: grid;
    grid-template-columns: 1fr 240px;
    gap: var(--space-8);
    align-items: start;
}

@media (max-width: 768px) {
    .wg-detail-info__inner {
        padding-left: var(--space-4);
        padding-right: var(--space-4);
        grid-template-columns: 1fr;
        gap: var(--space-4);
    }
}

/* --- Title --- */

.wg-detail-info__title {
    font-family: var(--font-display);
    font-size: 2rem;    /* --text-h1 */
    font-weight: 600;
    line-height: 1.20;
    letter-spacing: -0.02em;
    color: var(--color-text-primary);
    margin: 0 0 var(--space-2) 0;
    max-width: 68ch;
}

@media (max-width: 480px) {
    .wg-detail-info__title {
        font-size: 1.5rem;   /* --text-h2 mobile override for long titles */
    }
}

/* --- Byline --- */

.wg-detail-info__byline {
    font-family: var(--font-body);
    font-size: 0.875rem;   /* --text-body-sm */
    font-weight: 400;
    line-height: 1.55;
    color: var(--color-text-secondary);
    margin: 0 0 var(--space-4) 0;
}

.wg-detail-info__uploader-link {
    color: var(--color-text-secondary);
    font-weight: 500;
    text-decoration: none;
    transition: color 120ms ease;
}

.wg-detail-info__uploader-link:hover {
    color: var(--color-accent);
    text-decoration: underline;
}

.wg-detail-info__uploader-link:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: 2px;
}

/* --- Tag pills container --- */

.wg-detail-info__tags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-5);
}

/* --- Tag pill --- */

.wg-tag-pill {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 var(--space-3);
    font-family: var(--font-display);
    font-size: 0.75rem;       /* --text-label */
    font-weight: 500;
    line-height: 1.40;
    letter-spacing: 0.04em;
    color: var(--color-text-secondary);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 999px;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

.wg-tag-pill:hover {
    color: var(--color-accent);
    background: var(--color-accent-subtle);
    border-color: var(--color-accent-subtle-border);
}

.wg-tag-pill:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.wg-tag-pill:active {
    color: var(--color-accent-active);
    background: var(--color-accent-subtle);
    transform: scale(0.97);
}

/* MIRA C1 (Phase 3): Tag pills are 28px tall — fails the ≥44px touch target
 * requirement on mobile. Override to min-height 44px on mobile only.
 * Desktop retains the 28px visual height per AURORA spec.
 * display: inline-flex + align-items: center already set on base rule;
 * repeating them here ensures the override is self-contained. */
@media (max-width: 768px) {
    .wg-detail-info__tags .wg-tag-pill {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }
}

/* --- Right column: resolution + count --- */

.wg-detail-info__right {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
}

@media (min-width: 769px) {
    .wg-detail-info__right {
        align-items: flex-end;
        text-align: right;
    }
}

/* Resolution badge — JetBrains Mono */
.wg-detail-info__resolution {
    display: inline-flex;
    align-items: center;
    font-family: var(--font-mono);
    font-size: 0.8125rem;   /* --text-mono */
    font-weight: 400;
    line-height: 1.50;
    color: var(--color-text-secondary);
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md, 8px);
    padding: var(--space-1) var(--space-3);
}

/* Download count */
.wg-detail-info__downloads {
    font-family: var(--font-body);
    font-size: 0.8125rem;   /* --text-caption */
    font-weight: 400;
    line-height: 1.50;
    color: var(--color-text-secondary);
    margin: 0;
}


/* ============================================================
   ZONE 3 — AD SLOT
   ============================================================ */

.wg-detail-ad-wrap {
    padding: var(--space-6);
    background: var(--color-bg);
}

@media (max-width: 768px) {
    .wg-detail-ad-wrap {
        padding: var(--space-5) var(--space-4);
    }
}

.wg-ad--detail-mid {
    width: 100%;
    min-height: 90px;
    background: var(--color-bg);
    border-radius: var(--radius-xl, 12px);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    max-width: 1440px;
    margin: 0 auto;
}

.wg-ad__label {
    display: block;
    font-size: 0.75rem;   /* --text-label */
    font-weight: 500;
    letter-spacing: 0.04em;
    color: var(--color-text-disabled);
    text-align: center;
    margin-bottom: var(--space-1);
}


/* ============================================================
   ZONE 4 — RELATED WALLPAPERS
   ============================================================ */

.wg-related {
    padding: var(--space-16) var(--space-6);
    background: var(--color-bg);
}

@media (max-width: 1023px) {
    .wg-related {
        padding: var(--space-12) var(--space-6);
    }
}

@media (max-width: 768px) {
    .wg-related {
        padding: var(--space-10) var(--space-4);
    }
}

.wg-related__inner {
    max-width: 1440px;
    margin: 0 auto;
}

.wg-related__heading {
    font-family: var(--font-display);
    font-size: 1.5rem;     /* --text-h2 */
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.015em;
    color: var(--color-text-primary);
    margin: 0 0 var(--space-6) 0;
}

.wg-related__grid {
    list-style: none;
    padding: 0;
    margin: 0;
}

/* View-all link */
.wg-related__view-all {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    font-family: var(--font-body);
    font-size: 0.875rem;   /* --text-body-sm */
    font-weight: 500;
    color: var(--color-accent);
    text-decoration: none;
    margin-top: var(--space-5);
    float: right;
    transition: color 120ms ease;
}

.wg-related__view-all:hover {
    color: var(--color-accent-hover);
    text-decoration: underline;
}

.wg-related__view-all:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: 2px;
}

.wg-related__view-all-icon {
    color: inherit;
}

/* Clearfix after the floated view-all link */
.wg-related__inner::after {
    content: '';
    display: table;
    clear: both;
}


/* ============================================================
   ZONE 5 — STICKY DOWNLOAD BAR
   position: fixed bottom: 0. Height: var(--download-bar-height).
   z-index: var(--z-sticky) = 200.
   ============================================================ */

.wg-download-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: var(--download-bar-height);
    background: var(--color-surface);
    border-top: 1px solid var(--color-border);
    z-index: var(--z-sticky, 200);
}

.wg-download-bar__inner {
    max-width: 1440px;
    margin: 0 auto;
    height: 100%;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding-left: var(--space-6);
    padding-right: var(--space-6);
}

@media (max-width: 768px) {
    .wg-download-bar__inner {
        padding-left: var(--space-4);
        padding-right: var(--space-4);
    }
}

/* Download button — primary CTA, flex: 1 on mobile */
.wg-download-bar__download {
    flex: 1;
    max-width: 320px;
    min-width: 180px;
    justify-content: center;
}

@media (max-width: 768px) {
    .wg-download-bar__download {
        max-width: none;
    }
}

/* Save button wrapper — relative for tooltip anchor */
.wg-download-bar__save-wrap {
    position: relative;
    flex-shrink: 0;
}

/* Save button — hide label text on mobile (icon only) */
@media (max-width: 768px) {
    .wg-download-bar__save .wg-btn__label {
        display: none;
    }
}

/* Save button saved state */
.wg-download-bar__save[data-save-state="saved"] {
    color: var(--color-accent);
    background: var(--color-accent-subtle);
    border-color: var(--color-accent-subtle-border);
}

/* Save button loading state */
.wg-download-bar__save[data-save-state="loading"] {
    pointer-events: none;
    opacity: 0.7;
}

/* Save button error state — shake animation */
.wg-download-bar__save[data-save-state="error"] {
    animation: wg-shake 300ms ease;
}

@keyframes wg-shake {
    0%, 100% { transform: translateX(0); }
    20%       { transform: translateX(-4px); }
    40%       { transform: translateX(4px); }
    60%       { transform: translateX(-4px); }
    80%       { transform: translateX(4px); }
}


/* ============================================================
   TOOLTIP — "Log in to save"
   NOVA R2: closed state MUST use aria-hidden="true" + inert.
   [inert] suppresses display entirely; opacity/transform animate.
   ============================================================ */

.wg-save-tooltip {
    position: absolute;
    bottom: calc(100% + var(--space-2));
    right: 0;
    z-index: var(--z-tooltip, 800);
    max-width: 200px;
    padding: var(--space-2) var(--space-3);
    background: var(--color-text-primary);
    border-radius: var(--radius-md, 8px);
    box-shadow: var(--shadow-tooltip, 0 2px 8px rgba(0, 0, 0, 0.12));
    white-space: normal;
    /* Closed state default */
    opacity: 0;
    transform: translateY(4px);
    pointer-events: none;
    transition: opacity 150ms ease-out, transform 150ms ease-out;
}

/* Hidden when [inert] — belt-and-suspenders alongside aria-hidden */
.wg-save-tooltip[inert] {
    pointer-events: none;
    opacity: 0;
    transform: translateY(4px);
}

/* Open state — JS removes inert + sets aria-hidden="false" */
.wg-save-tooltip[aria-hidden="false"]:not([inert]) {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

.wg-save-tooltip__text {
    display: block;
    font-size: 0.875rem;   /* --text-body-sm */
    font-weight: 400;
    line-height: 1.55;
    color: var(--color-text-inverse);
    margin-bottom: var(--space-1);
}

.wg-save-tooltip__link {
    display: inline-block;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-text-inverse);
    text-decoration: underline;
    transition: opacity 120ms ease;
}

.wg-save-tooltip__link:hover {
    opacity: 0.8;
}

.wg-save-tooltip__link:focus-visible {
    outline: 2px solid var(--color-text-inverse);
    outline-offset: 2px;
    border-radius: 2px;
}


/* ============================================================
   ZONE 6 — SCROLL-TO-TOP FAB
   MIRA MC8: bottom: calc(var(--download-bar-height) + var(--space-4))
   Visibility: .is-visible class added/removed by IntersectionObserver
   in detail.js (NOVA R3).
   chevron-down.svg rotated 180deg — no new SVG file (NOVA Item 10a).
   ============================================================ */

.wg-scroll-top {
    position: fixed;
    bottom: calc(var(--download-bar-height) + var(--space-4));
    right: var(--space-4);
    z-index: var(--z-fab, 300);
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 50%;
    box-shadow: 0 2px 8px rgba(17, 16, 16, 0.12);
    cursor: pointer;
    color: var(--color-text-secondary);
    /* Hidden by default */
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease-out, background-color 120ms ease, transform 80ms ease;
}

/* Visible state — JS adds .is-visible on IntersectionObserver callback */
.wg-scroll-top.is-visible {
    opacity: 1;
    pointer-events: auto;
}

.wg-scroll-top:hover {
    background: var(--color-bg);
    color: var(--color-text-primary);
}

.wg-scroll-top:active {
    transform: scale(0.94);
}

.wg-scroll-top:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Rotate chevron-down 180deg to act as chevron-up (NOVA Item 10a) */
.wg-icon-rotate-180 {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transform: rotate(180deg);
}


/* ============================================================
   TOAST BOTTOM OVERRIDE — detail page only
   AURORA Component 3.5: toast must appear ABOVE the sticky bar.
   body.single-wallpaper is added by WP core for single-wallpaper CPT.
   body.wg-single-wallpaper is the custom class from wg_body_classes filter.
   ============================================================ */

body.single-wallpaper #wg-toast-container,
body.wg-single-wallpaper #wg-toast-container {
    bottom: calc(var(--download-bar-height) + var(--space-6));
}


/* ============================================================
   REDUCED MOTION — already declared globally in main.css,
   but FAB smooth scroll behavior is handled in detail.js by
   checking window.matchMedia('(prefers-reduced-motion: reduce)').
   No additional CSS needed here.
   ============================================================ */


/* ============================================================
   PHASE 4 — AUTH MODAL
   REX ALL PASS — 2026-03-27
   ============================================================ */

/*
 * ============================================================
 * auth.css — Authentication Modal Styles
 * Phase 4 — 8KWALLS Theme v4.0.0
 *
 * Scoped to: .wg-auth-modal, .wg-modal__backdrop
 * All colors use var() tokens from main.css.
 * No raw hex values (ATLAS §1 FORGE NOTE).
 *
 * Phase 4 component token additions (NOVA + AURORA approved):
 *   --color-strength-good: #d4a017  (password strength "Good" state)
 *
 * Inertness / display note (NOVA NP6, Phase 1 pattern):
 *   Do NOT add CSS display:none on aria-hidden selectors.
 *   JS sets display:none after the exit transition completes.
 *   CSS-only display:none on aria-hidden races with transitions.
 *   The JS setTimeout(EXIT_MS + 10) pattern owns display toggling.
 *
 * Breakpoints (ATLAS §8 canonical table):
 *   max-width: 480px  — mobile bottom-sheet, small mobile
 *   max-width: 768px  — mobile
 *   min-width: 769px  — desktop
 * ============================================================
 */


/* ============================================================
   PHASE 4 COMPONENT TOKEN
   Added here per NOVA review — not in Phase 0 global block.
   ============================================================ */

:root {
    --color-strength-good: #d4a017;  /* Password strength "Good" — AURORA 2K, NOVA approved */
}


/* ============================================================
   SCREEN READER ONLY — .sr-only
   Used for the visually-hidden modal title (aria-labelledby target).
   ============================================================ */

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}


/* ============================================================
   MODAL BACKDROP
   z-index: var(--z-modal-backdrop) = 550
   JS controls display via style.display.
   Backdrop opacity animation driven by CSS classes added by JS.
   ============================================================ */

.wg-modal__backdrop {
    position: fixed;
    inset: 0;
    background: var(--color-scrim-modal);
    z-index: var(--z-modal-backdrop);
    opacity: 0;
    transition: opacity 200ms ease-out;
}

.wg-modal__backdrop.is-visible {
    opacity: 1;
}

.wg-modal__backdrop.is-closing {
    opacity: 0;
    transition: opacity 150ms ease-in;
}


/* ============================================================
   AUTH MODAL SHELL — DESKTOP (default)
   max-width: 420px, centered in viewport.
   AURORA §2A.
   ============================================================ */

.wg-auth-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) translateY(8px);
    width: 100%;
    max-width: 420px;
    background: var(--color-surface);
    border-radius: 16px;
    box-shadow: 0 8px 40px rgba(17, 16, 16, 0.20);
    padding: var(--space-8);
    z-index: var(--z-modal);
    overflow: hidden;

    /* Closed: JS sets display:none after exit animation.
       Do not set display:none here — it races with transitions. */
    display: flex;
    flex-direction: column;

    /* Entrance animation — opacity + slight vertical move */
    opacity: 0;
    transition:
        opacity 200ms ease-out,
        transform 200ms ease-out;
}

/* Open state — JS adds .is-open after _removeInertOpen() */
.wg-auth-modal.is-open {
    opacity: 1;
    transform: translate(-50%, -50%) translateY(0);
}

/* Closing state — JS adds .is-closing before setting display:none */
.wg-auth-modal.is-closing {
    opacity: 0;
    transform: translate(-50%, -50%) translateY(8px);
    transition:
        opacity 150ms ease-in,
        transform 150ms ease-in;
}


/* ============================================================
   DRAG HANDLE — mobile bottom-sheet only
   Visible only at max-width: 480px.
   AURORA §2C, ATLAS §4E.
   ============================================================ */

.wg-modal__drag-handle {
    display: none;  /* Hidden on desktop */
    width: 36px;
    height: 4px;
    border-radius: 2px;
    background: var(--color-border-strong);
    margin: 0 auto var(--space-4);
    flex-shrink: 0;
}


/* ============================================================
   CLOSE BUTTON
   44×44px touch target. Absolute positioned top-right.
   AURORA §2D.
   ============================================================ */

.wg-modal__close {
    position: absolute;
    top: var(--space-4);
    right: var(--space-4);
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: var(--radius-md, 8px);
    cursor: pointer;
    color: var(--color-text-secondary);
    transition:
        background 120ms ease,
        color 120ms ease,
        transform 80ms ease;
    flex-shrink: 0;
}

.wg-modal__close:hover {
    background: rgba(17, 16, 16, 0.06);
    color: var(--color-text-primary);
}

.wg-modal__close:active {
    background: rgba(17, 16, 16, 0.10);
    transform: scale(0.97);
}

.wg-modal__close:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}


/* ============================================================
   TAB BAR
   role="tablist". Full-width of modal content area.
   AURORA §2F.
   ============================================================ */

.wg-auth-modal__tabs {
    display: flex;
    border-bottom: 1px solid var(--color-border);
    margin-bottom: var(--space-6);
    flex-shrink: 0;
    /* Top margin accounts for close button (44px) + small gap */
    margin-top: var(--space-8);
}

.wg-auth-modal__tab {
    flex: 1;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;  /* Overlap container border-bottom */
    font-size: var(--text-ui-md-size);
    font-weight: 500;
    font-family: var(--font-body);
    color: var(--color-text-secondary);
    cursor: pointer;
    transition:
        color 120ms ease,
        border-bottom-color 120ms ease,
        font-weight 120ms ease;
    /* NOVA NP3: pointer-events blocked during loading via JS inline style.
       aria-disabled="true" also added by JS during loading. */
}

.wg-auth-modal__tab:hover {
    color: var(--color-text-primary);
}

.wg-auth-modal__tab[aria-selected="true"] {
    color: var(--color-accent);
    font-weight: 600;
    border-bottom-color: var(--color-accent);
}

.wg-auth-modal__tab:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: -2px;
}

/* Disabled visual during loading (NP3) */
.wg-auth-modal__tab[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
}


/* ============================================================
   FORM PANEL
   Tab panels. Instant show/hide — no animation per AURORA §3D.
   ============================================================ */

.wg-auth-modal__panel {
    width: 100%;
}


/* ============================================================
   FORM LAYOUT
   .wg-auth-form: the <form> element itself.
   ============================================================ */

.wg-auth-form {
    width: 100%;
}


/* ============================================================
   FORM FIELD WRAPPER
   Each input + label + error is wrapped in .wg-form__field.
   ============================================================ */

.wg-form__field {
    position: relative;  /* For password toggle absolute positioning */
    margin-bottom: var(--space-4);
}

.wg-form__field:last-of-type {
    margin-bottom: 0;
}


/* ============================================================
   FORM LABEL
   ATLAS §4D: --text-label (12px/500).
   ============================================================ */

.wg-form__label {
    display: block;
    font-size: var(--text-label-size);
    font-weight: var(--text-label-weight);
    font-family: var(--font-body);
    color: var(--color-text-primary);
    letter-spacing: var(--text-label-ls);
    margin-bottom: var(--space-1);
}


/* ============================================================
   INPUT WRAPPER (for password fields with toggle icon)
   ============================================================ */

.wg-input-wrap {
    position: relative;
    display: flex;
    align-items: center;
}

.wg-input-wrap .wg-input {
    flex: 1;
    min-width: 0;
}

.wg-input-wrap--password .wg-input {
    padding-right: 44px;  /* Room for eye toggle button */
}


/* ============================================================
   INPUT BASE
   ATLAS §4D: 44px height, 16px font (var(--text-input)).
   Tokens from main.css applied here as classes.
   ============================================================ */

.wg-input {
    display: block;
    width: 100%;
    height: 44px;
    font-size: var(--text-input-size);
    font-weight: var(--text-input-weight);
    font-family: var(--font-body);
    line-height: var(--text-input-lh);
    color: var(--color-text-primary);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    padding: 0 var(--space-3);
    box-sizing: border-box;
    transition:
        border-color 80ms ease,
        outline 80ms ease;
    -webkit-appearance: none;
    appearance: none;
}

.wg-input::placeholder {
    color: var(--color-text-disabled);
}

.wg-input:focus {
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 0;
    border-color: var(--color-accent);
}

/* Error state */
.wg-input--error {
    border-color: var(--color-error);
    outline: 2px solid var(--color-error-focus-ring);
    outline-offset: 0;
}

.wg-input--error:focus {
    border-color: var(--color-error);
    outline: 2px solid var(--color-error-focus-ring);
}

/* Disabled state (during AJAX loading) */
.wg-input:disabled {
    background: var(--color-bg);
    color: var(--color-text-disabled);
    border-color: var(--color-border);
    cursor: not-allowed;
    opacity: 1;  /* Override browser default — we control this explicitly */
}


/* ============================================================
   PASSWORD SHOW/HIDE TOGGLE
   Positioned absolutely inside .wg-input-wrap.
   44×44px touch target via padding.
   AURORA §2H.
   ============================================================ */

.wg-password-toggle {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    cursor: pointer;
    color: var(--color-text-secondary);
    transition: color 80ms ease;
    flex-shrink: 0;
}

.wg-password-toggle:hover {
    color: var(--color-text-primary);
}

.wg-password-toggle:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: 6px;
}

/* Icon visibility swap: JS toggles field type.
   CSS shows/hides show vs hide icons based on aria-pressed. */
.wg-password-toggle__icon--hide {
    display: none;
}

.wg-password-toggle[aria-pressed="true"] .wg-password-toggle__icon--show {
    display: none;
}

.wg-password-toggle[aria-pressed="true"] .wg-password-toggle__icon--hide {
    display: block;
}


/* ============================================================
   INLINE ERROR MESSAGE
   Shown below failed input. AURORA §2I.
   ============================================================ */

.wg-form__error {
    display: none;  /* JS sets display:flex to show */
    align-items: flex-start;
    gap: var(--space-1);
    margin-top: var(--space-1);
    font-size: var(--text-caption-size);
    font-weight: var(--text-caption-weight);
    font-family: var(--font-body);
    color: var(--color-error);
    line-height: var(--text-caption-lh);
}

/* Server / non-field error — displayed above submit button */
.wg-form__error--server {
    margin-bottom: var(--space-3);
    margin-top: 0;
}


/* ============================================================
   REMEMBER ME ROW
   Flex row: checkbox label left, forgot link right.
   AURORA §2L.
   ============================================================ */

.wg-auth-form__remember-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-4);
    min-height: 44px;  /* MIRA C1 — tap zone ≥44px for remember-me label + forgot link */
}

.wg-auth-form__remember-label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-body-sm-size);
    font-family: var(--font-body);
    color: var(--color-text-primary);
    cursor: pointer;
    user-select: none;
}

/* Custom checkbox — native input hidden, visual provided by .wg-checkbox__custom */
.wg-checkbox {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    margin: 0;
}

.wg-checkbox__custom {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    border-radius: 4px;
    border: 1.5px solid var(--color-border-strong);
    background: var(--color-surface);
    transition:
        background 80ms ease,
        border-color 80ms ease;
}

/* Checkmark via ::after */
.wg-checkbox__custom::after {
    content: '';
    position: absolute;
    width: 10px;
    height: 6px;
    border-left: 2px solid var(--color-text-inverse);
    border-bottom: 2px solid var(--color-text-inverse);
    transform: rotate(-45deg) translateY(-1px);
    opacity: 0;
    transition: opacity 80ms ease;
}

.wg-checkbox:checked + .wg-checkbox__custom {
    background: var(--color-accent);
    border-color: var(--color-accent);
}

.wg-checkbox:checked + .wg-checkbox__custom::after {
    opacity: 1;
}

.wg-checkbox:focus-visible + .wg-checkbox__custom {
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 2px;
}

.wg-auth-form__forgot {
    font-size: var(--text-body-sm-size);
    font-family: var(--font-body);
    color: var(--color-accent);
    text-decoration: none;
    transition: text-decoration 80ms ease;
}

.wg-auth-form__forgot:hover {
    text-decoration: underline;
}

.wg-auth-form__forgot:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: 2px;
}


/* ============================================================
   SUBMIT BUTTON
   .wg-btn--primary.wg-btn--lg.wg-btn--full
   Uses button tokens from main.css. Only full-width override here.
   AURORA §2M.
   ============================================================ */

.wg-btn--full {
    width: 100%;
}

/* Loading spinner — CSS border animation, no SVG needed */
@keyframes wg-spin {
    to { transform: rotate(360deg); }
}

.wg-btn--primary[data-state="loading"] {
    pointer-events: none;
    cursor: not-allowed;
    position: relative;
    color: transparent;  /* Hide text while loading */
}

.wg-btn--primary[data-state="loading"]::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 18px;
    height: 18px;
    margin: -9px 0 0 -9px;
    border: 2px solid rgba(248, 247, 244, 0.4);
    border-top-color: var(--color-text-inverse);
    border-radius: 50%;
    animation: wg-spin 600ms linear infinite;
}


/* ============================================================
   DIVIDER ("or")
   Login form only. Between submit and Google stub.
   AURORA §2J.
   ============================================================ */

.wg-form__divider {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: var(--space-5) 0;
}

.wg-form__divider-line {
    flex: 1;
    height: 1px;
    background: var(--color-border);
}

.wg-form__divider-text {
    font-size: var(--text-caption-size);
    font-family: var(--font-body);
    color: var(--color-text-secondary);
    white-space: nowrap;
}


/* ============================================================
   GOOGLE OAUTH STUB BUTTON
   Disabled visual. AURORA §2N. NOVA NP10: no HTML disabled attr.
   ============================================================ */

.wg-btn--google {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
}

.wg-btn--google[aria-disabled="true"] {
    background: var(--color-bg);
    border-color: var(--color-border);
    color: var(--color-text-disabled);
    cursor: not-allowed;
}

.wg-btn--google[aria-disabled="true"] .wg-icon {
    opacity: 0.4;
}

/* Tooltip wrapper */
.wg-btn-tooltip-wrapper {
    position: relative;
    display: block;
}

.wg-btn-tooltip {
    position: absolute;
    bottom: calc(100% + var(--space-2));
    left: 50%;
    transform: translateX(-50%);
    font-size: var(--text-caption-size);
    font-family: var(--font-body);
    background: var(--color-text-primary);
    color: var(--color-text-inverse);
    border-radius: 6px;
    padding: var(--space-1) var(--space-2);
    white-space: nowrap;
    z-index: var(--z-tooltip);
    opacity: 0;
    pointer-events: none;
    transition: opacity 120ms ease;
}

/* Show tooltip on parent hover or when Google button is focused */
.wg-btn-tooltip-wrapper:hover .wg-btn-tooltip,
.wg-btn--google:focus-visible + .wg-btn-tooltip {
    opacity: 1;
}


/* ============================================================
   PASSWORD STRENGTH BAR
   Register form only. 4 segments. AURORA §2K.
   ============================================================ */

.wg-password-strength {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: var(--space-2);
    margin-bottom: var(--space-1);
    gap: var(--space-3);
}

.wg-password-strength__bars {
    display: flex;
    gap: var(--space-1);
    flex: 1;
}

.wg-password-strength__segment {
    height: 4px;
    flex: 1;
    border-radius: 2px;
    background: var(--color-border);
    transition: background-color 120ms ease;
}

/* Segment fill colors set via JS inline style.
   CSS vars referenced in JS (auth.js _updateStrength):
   score 1 → var(--color-error)
   score 2 → var(--color-warning)
   score 3 → var(--color-strength-good)
   score 4 → var(--color-success) */

.wg-password-strength__label {
    font-size: var(--text-caption-size);
    font-family: var(--font-body);
    white-space: nowrap;
    min-width: 40px;
    text-align: right;
    /* color set via JS inline style to match active segment color */
}


/* ============================================================
   TERMS NOTE
   Register form. Below submit button. AURORA §2O.
   ============================================================ */

.wg-auth-form__terms {
    margin-top: var(--space-3);
    font-size: var(--text-caption-size);
    font-family: var(--font-body);
    color: var(--color-text-secondary);
    text-align: center;
    line-height: var(--text-caption-lh);
}

.wg-auth-form__terms a {
    color: var(--color-accent);
    text-decoration: none;
}

.wg-auth-form__terms a:hover {
    text-decoration: underline;
}

.wg-auth-form__terms a:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: 2px;
}


/* ============================================================
   SUCCESS STATE
   Replaces form area after AJAX success. AURORA §2P.
   JS: WG.modal._showSuccess(message) sets display:flex.
   ============================================================ */

.wg-auth-modal__success {
    display: none;  /* JS sets display:flex */
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    min-height: 240px;
    padding: var(--space-8) 0;
    opacity: 0;
    transition: opacity 200ms ease-out;
}

.wg-auth-modal__success.is-visible {
    opacity: 1;
}

.wg-auth-modal__success-icon {
    color: var(--color-success);
}

.wg-auth-modal__success-message {
    font-size: var(--text-h3-size);
    font-weight: var(--text-h3-weight);
    font-family: var(--font-body);
    color: var(--color-text-primary);
    line-height: var(--text-h3-lh);
    letter-spacing: var(--text-h3-ls);
    margin-top: var(--space-4);
    margin-bottom: 0;
}


/* ============================================================
   MOBILE BOTTOM-SHEET (max-width: 480px)
   MIRA MIR4, ATLAS §4E, AURORA §2A.
   ============================================================ */

@media (max-width: 480px) {
    .wg-auth-modal {
        /* Override centered desktop positioning */
        top: auto;
        left: 0;
        right: 0;
        bottom: 0;
        transform: translateY(100%);  /* Initial: off-screen below viewport */
        max-width: 100%;
        max-height: 90vh;
        overflow-y: auto;
        border-radius: 16px 16px 0 0;
        /* Reset desktop opacity-based transition */
        opacity: 1;
        /* Use transform-based slide-up animation */
        transition: transform 250ms ease-out;
        padding: 0 var(--space-6) var(--space-6);
    }

    /* Open state — slide up */
    .wg-auth-modal.is-open {
        transform: translateY(0);
        opacity: 1;
    }

    /* Closing state — slide down */
    .wg-auth-modal.is-closing {
        transform: translateY(100%);
        opacity: 1;  /* Keep visible during slide */
        transition: transform 200ms ease-in;
    }

    /* Show drag handle on mobile */
    .wg-modal__drag-handle {
        display: block;
        margin-top: var(--space-3);
        margin-bottom: var(--space-4);
    }

    /* Close button repositioned for bottom-sheet */
    .wg-modal__close {
        position: absolute;
        top: var(--space-3);
        right: var(--space-4);
    }

    /* Tab bar top margin reduced (drag handle provides spacing) */
    .wg-auth-modal__tabs {
        margin-top: var(--space-10);  /* 40px — space for drag handle + close btn */
    }

    /* MIRA C4 — iPhone X+ home indicator safe zone (34px on notched devices).
       env() fallback of 0px means no change on non-notched devices. */
    .wg-modal__panel {
        padding-bottom: calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
    }
}


/* ============================================================
   REDUCED MOTION
   Disable all transitions for users who prefer it.
   ATLAS §5.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
    .wg-auth-modal,
    .wg-auth-modal.is-open,
    .wg-auth-modal.is-closing,
    .wg-modal__backdrop,
    .wg-modal__backdrop.is-visible,
    .wg-modal__backdrop.is-closing,
    .wg-auth-modal__success,
    .wg-auth-modal__success.is-visible,
    .wg-password-strength__segment,
    .wg-btn-tooltip,
    .wg-input,
    .wg-modal__close {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}

/* ============================================================
   PHASE 5 — SAVE MODAL
   REX ALL PASS — 2026-03-27
   ============================================================ */
/*
 * ============================================================
 * save.css — Save to Collection Modal
 * Phase 5 — 8KWALLS Theme v4.0.0
 *
 * Component: .wg-save-modal
 * Namespace: wg-save-*
 * HTML file: phases/phase-5/save-modal.php
 * JS file:   phases/phase-5/save.js
 *
 * Tokens: all values from atlas-decision.md §1–§8 only.
 * No raw hex, no raw px values outside the spacing scale.
 *
 * Modal state is driven by:
 *   data-modal-state="loading | idle | empty | error"
 *   on #wg-save-modal
 *
 * Collection row save state:
 *   data-collection-state="saved" (present = saved, absent = unsaved)
 *   on .wg-save-modal__row buttons
 *
 * MIRA requirements applied:
 *   - Bottom-sheet at max-width: 480px (ATLAS §4E, MIRA MIR4)
 *   - safe-area-inset-bottom on mobile (same pattern as Phase 4)
 *   - All interactive targets ≥ 44px touch height on mobile
 *   - prefers-reduced-motion: global rule in main.css covers animations
 * ============================================================
 */


/* ============================================================
   MODAL SHELL — DESKTOP (default, min-width: 481px)
   AURORA §2A: 380px width, centered, elevated panel.
   ============================================================ */

.wg-save-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) translateY(8px);
    width: 100%;
    max-width: 380px;
    background: var(--color-surface);
    border-radius: 16px;
    box-shadow: 0 8px 40px rgba(17, 16, 16, 0.20);
    padding: var(--space-6);
    z-index: var(--z-modal);
    overflow: hidden;
    display: none;          /* JS sets display:flex on open */
    flex-direction: column;
    gap: var(--space-4);
    opacity: 0;
    transition:
        opacity 200ms ease-out,
        transform 200ms ease-out;
}

/* Open state — aria-hidden="false" set by WG.save._removeInertOpen() */
.wg-save-modal[aria-hidden="false"] {
    opacity: 1;
    transform: translate(-50%, -50%) translateY(0);
}

/* Closing state — WG.save._applyInertClosed() sets aria-hidden="true"
 * before the EXIT_MS timer. CSS sees this and applies exit animation. */
.wg-save-modal[aria-hidden="true"] {
    opacity: 0;
    transform: translate(-50%, -50%) translateY(8px);
    transition:
        opacity 150ms ease-in,
        transform 150ms ease-in;
}


/* ============================================================
   DRAG HANDLE — mobile only (hidden on desktop)
   ATLAS §4E: 36px wide, 4px tall, border-radius 2px
   ============================================================ */

.wg-modal__drag-handle {
    display: none;          /* hidden on desktop — shown via mobile breakpoint */
    width: 36px;
    height: 4px;
    background: var(--color-border-strong);
    border-radius: 2px;
    margin: 0 auto;
    flex-shrink: 0;
}


/* ============================================================
   MODAL HEADER
   ============================================================ */

.wg-modal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    flex-shrink: 0;
}

.wg-modal__title {
    font-family: var(--font-display);
    font-size: var(--text-h3);     /* 20px / 600 */
    font-weight: 600;
    line-height: 1.30;
    letter-spacing: -0.01em;
    color: var(--color-text-primary);
    margin: 0;
}

/* Close button reuses .wg-btn--ghost .wg-btn--icon from main.css */


/* ============================================================
   STATE VISIBILITY RULES
   CSS shows/hides regions based on data-modal-state on the root.
   Only one region is visible at any time.
   ============================================================ */

/* Hide all content regions by default */
.wg-save-modal__loading-state,
.wg-save-modal__idle-state,
.wg-save-modal__empty-state,
.wg-save-modal__error-state {
    display: none;
}

/* Loading state */
.wg-save-modal[data-modal-state="loading"] .wg-save-modal__loading-state {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* Idle state */
.wg-save-modal[data-modal-state="idle"] .wg-save-modal__idle-state {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

/* Empty state */
.wg-save-modal[data-modal-state="empty"] .wg-save-modal__empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-4);
}

/* Error state */
.wg-save-modal[data-modal-state="error"] .wg-save-modal__error-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-6) 0;
}


/* ============================================================
   LOADING SKELETON ROWS
   Reuses wg-shimmer keyframe from main.css.
   3 rows, each 56px tall matching the real collection row height.
   ============================================================ */

.wg-save-modal__skeleton-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    height: 56px;
    border-radius: var(--radius-md);
    overflow: hidden;
    flex-shrink: 0;
}

.wg-save-modal__skeleton-thumb {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    background: var(--color-border);
    flex-shrink: 0;
}

.wg-save-modal__skeleton-text {
    height: 14px;
    flex: 1;
    border-radius: var(--radius-sm);
    background: var(--color-border);
    max-width: 60%;
}

/* The wg-shimmer class provides the keyframe animation from main.css.
 * background-position animates to create the sweep effect.
 * Applied to the skeleton row container for the full-row sweep. */
.wg-save-modal__skeleton-row.wg-shimmer {
    background: linear-gradient(
        90deg,
        var(--color-bg) 25%,
        var(--color-border) 37%,
        var(--color-bg) 63%
    );
    background-size: 400% 100%;
}


/* ============================================================
   COLLECTION LIST (IDLE STATE)
   max-height 280px per AURORA §2F, overflow-y auto for scroll.
   ============================================================ */

.wg-save-modal__list {
    display: flex;
    flex-direction: column;
    max-height: 280px;
    overflow-y: auto;
    overflow-x: hidden;
    /* Custom scrollbar — minimal, matches design system */
    scrollbar-width: thin;
    scrollbar-color: var(--color-border-strong) transparent;
    /* Negative margin + padding trick to show focus rings inside scroll area */
    margin: 0 calc(-1 * var(--space-2));
    padding: 0 var(--space-2);
}

.wg-save-modal__list::-webkit-scrollbar {
    width: 4px;
}

.wg-save-modal__list::-webkit-scrollbar-track {
    background: transparent;
}

.wg-save-modal__list::-webkit-scrollbar-thumb {
    background: var(--color-border-strong);
    border-radius: 2px;
}


/* ============================================================
   COLLECTION ROW
   56px height, flex layout: [thumb] [name] [checkmark]
   ============================================================ */

.wg-save-modal__row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    min-height: 56px;
    padding: var(--space-2) var(--space-3);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    text-align: left;
    transition: background-color 120ms ease;
    flex-shrink: 0;
}

.wg-save-modal__row:hover {
    background: var(--color-bg);
}

.wg-save-modal__row:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Saved row: accent-subtle background */
.wg-save-modal__row[data-collection-state="saved"] {
    background: var(--color-accent-subtle);
}

.wg-save-modal__row[data-collection-state="saved"]:hover {
    background: var(--color-accent-subtle);
    filter: brightness(0.97);
}


/* ── Collection row thumbnail ─────────────────────────────── */

.wg-save-modal__row-thumb {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    object-fit: cover;
    flex-shrink: 0;
    background: var(--color-bg);   /* placeholder while loading */
    display: block;
}

/* Rows with no cover image: show folder-open icon via CSS pseudo-element */
.wg-save-modal__row[data-no-cover] .wg-save-modal__row-thumb {
    display: none;
}

.wg-save-modal__row[data-no-cover]::before {
    content: '';
    display: block;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    background: var(--color-bg);
    flex-shrink: 0;
    /* folder-open icon — shown as background for rows without a cover.
     * FORGE: replace this block with an inline SVG <img> in _buildRows
     * if per-row icon clarity is required. For Phase 5 this CSS approach
     * avoids an extra DOM element per row. */
}


/* ── Collection row name ──────────────────────────────────── */

.wg-save-modal__row-name {
    flex: 1;
    font-family: var(--font-body);
    font-size: var(--text-body-sm);    /* 14px / 400 */
    font-weight: 400;
    line-height: 1.55;
    color: var(--color-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wg-save-modal__row[data-collection-state="saved"] .wg-save-modal__row-name {
    font-weight: 500;
    color: var(--color-accent);
}


/* ── Collection row checkmark ─────────────────────────────── */
/*
 * NOVA Item 5: checkmark uses opacity NOT display:none.
 * This preserves layout — the cell width is always reserved.
 * opacity: 0 = invisible but occupies space (no row-width jitter on toggle).
 */

.wg-save-modal__row-check {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;                /* hidden by default */
    transition: opacity 120ms ease;
    color: var(--color-accent);
}

.wg-save-modal__row[data-collection-state="saved"] .wg-save-modal__row-check {
    opacity: 1;                /* visible when saved */
}


/* ============================================================
   "＋ NEW COLLECTION" ROW (inside the list, at the bottom)
   ============================================================ */

.wg-save-modal__new-row-wrapper {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    border-top: 1px solid var(--color-border);
    margin-top: var(--space-1);
    padding-top: var(--space-1);
}

.wg-save-modal__new-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    min-height: 56px;
    padding: var(--space-2) var(--space-3);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    text-align: left;
    transition: background-color 120ms ease;
}

.wg-save-modal__new-row:hover {
    background: var(--color-bg);
}

.wg-save-modal__new-row:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.wg-save-modal__new-row-icon {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    background: var(--color-bg);
    border: 1px dashed var(--color-border-strong);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--text-body-lg);
    color: var(--color-text-secondary);
    flex-shrink: 0;
}

.wg-save-modal__new-row-label {
    font-family: var(--font-body);
    font-size: var(--text-body-sm);
    font-weight: 500;
    color: var(--color-accent);
}


/* ── Inline input row (expanded state) ──────────────────────
 * NOVA Item 6: DOM show/hide — not a state machine state.
 * Collapsed: display:none (set by JS, not CSS selector, to avoid
 * specificity fights with JS inline style).
 * Expanded: display:flex (set by WG.save._expandInput()).
 * The parent .wg-save-modal__new-row-wrapper is always in the DOM.
 * ──────────────────────────────────────────────────────────── */

.wg-save-modal__new-input-row {
    display: none;             /* JS overrides to flex on expand */
    align-items: flex-start;
    gap: var(--space-2);
    flex-wrap: wrap;
    padding: 0 var(--space-1);
}

.wg-save-modal__name-input {
    flex: 1;
    min-width: 0;
    height: 44px;
    padding: 0 var(--space-3);
    font-size: var(--text-input);     /* 16px — MIRA MIR2 */
    font-family: var(--font-body);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    color: var(--color-text-primary);
    outline: none;
    transition: border-color 80ms ease, outline 80ms ease;
}

.wg-save-modal__name-input::placeholder {
    color: var(--color-text-disabled);
}

.wg-save-modal__name-input:focus {
    border-color: var(--color-accent);
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 0;
}

.wg-save-modal__name-input.wg-input--error {
    border-color: var(--color-error);
    outline: 2px solid var(--color-error-focus-ring);
    outline-offset: 0;
}

.wg-save-modal__cancel-input-btn {
    height: 44px;
    width: 44px;
    flex-shrink: 0;
}


/* ============================================================
   ACTIONS BAR (Done button — idle state)
   ============================================================ */

.wg-save-modal__actions {
    display: flex;
    justify-content: flex-end;
    flex-shrink: 0;
    padding-top: var(--space-2);
    border-top: 1px solid var(--color-border);
}

.wg-save-modal__done-btn {
    min-width: 80px;
}


/* ============================================================
   EMPTY STATE
   Reuses Phase 0 empty state pattern (atlas-decision.md §9).
   [Icon xl] [Headline h3] [Body text] [Input] [Primary CTA]
   ============================================================ */

.wg-save-modal__empty-state {
    text-align: center;
    padding: var(--space-6) 0 var(--space-4);
}

.wg-save-modal__empty-state .wg-empty-state__icon {
    color: var(--color-text-disabled);
    margin-bottom: var(--space-3);
}

.wg-save-modal__empty-state .wg-empty-state__headline {
    font-family: var(--font-display);
    font-size: var(--text-h3);     /* 20px / 600 — appropriate for modal context */
    font-weight: 600;
    line-height: 1.30;
    letter-spacing: -0.01em;
    color: var(--color-text-primary);
    margin: 0 0 var(--space-2);
}

.wg-save-modal__empty-state .wg-empty-state__body {
    font-family: var(--font-body);
    font-size: var(--text-body);   /* 15px */
    line-height: 1.60;
    color: var(--color-text-secondary);
    margin: 0 0 var(--space-4);
    max-width: 280px;
    text-align: center;
}

.wg-save-modal__empty-input-wrap {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
    text-align: left;
}

.wg-save-modal__empty-input-wrap .wg-save-modal__name-input {
    width: 100%;
}

.wg-save-modal__create-save-btn {
    width: 100%;
}

/* Create & Save loading state */
.wg-save-modal__create-save-btn[data-state="loading"] {
    pointer-events: none;
    cursor: not-allowed;
    opacity: 0.7;
}


/* ============================================================
   ERROR STATE
   ============================================================ */

.wg-save-modal__error-state {
    text-align: center;
}

.wg-save-modal__error-icon {
    color: var(--color-error);
    margin-bottom: var(--space-2);
}

.wg-save-modal__error-message {
    font-family: var(--font-body);
    font-size: var(--text-body);
    color: var(--color-text-secondary);
    margin: 0 0 var(--space-4);
}


/* ============================================================
   INLINE ERROR MESSAGES (both states)
   ============================================================ */

.wg-save-modal__collection-error {
    display: none;                 /* JS shows/hides via style.display */
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-body);
    font-size: var(--text-caption);   /* 13px */
    color: var(--color-error);
    line-height: 1.50;
    width: 100%;
    margin: 0;
}


/* ============================================================
   MOBILE BOTTOM-SHEET — max-width: 480px
   ATLAS §4E, MIRA MIR4: Bottom-sheet pattern required.
   ============================================================ */

@media (max-width: 480px) {
    .wg-save-modal {
        /* Override the desktop centered positioning */
        position: fixed;
        top: auto;
        bottom: 0;
        left: 0;
        right: 0;
        transform: translateY(100%);    /* off-screen initially */
        max-width: 100%;
        max-height: 90vh;
        width: 100%;
        border-radius: 16px 16px 0 0;
        overflow-y: auto;
        /* Override desktop enter/exit transitions with bottom-sheet versions */
        transition:
            transform 250ms ease-out,
            opacity 250ms ease-out;
        padding:
            var(--space-4)             /* top — drag handle sits above this */
            var(--space-6)             /* horizontal */
            calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
                                        /* bottom — safe area for notched devices */
        /* MIRA Phase 4 safe-area-inset-bottom fix: env() ensures content
         * is not occluded by iPhone home indicator or Android nav bar. */
    }

    /* Bottom-sheet open state */
    .wg-save-modal[aria-hidden="false"] {
        transform: translateY(0);
        opacity: 1;
        transition:
            transform 250ms ease-out,
            opacity 200ms ease-out;
    }

    /* Bottom-sheet close state */
    .wg-save-modal[aria-hidden="true"] {
        transform: translateY(100%);
        opacity: 0;
        transition:
            transform 200ms ease-in,
            opacity 150ms ease-in;
    }

    /* Show drag handle on mobile */
    .wg-modal__drag-handle {
        display: block;
        margin-bottom: var(--space-2);
    }

    /* Collection list: allow more height on mobile (viewport is taller in bottom-sheet) */
    .wg-save-modal__list {
        max-height: 40vh;
    }

    /* Done button: full width on mobile */
    .wg-save-modal__done-btn {
        width: 100%;
    }

    /* Retry button: full width on mobile */
    .wg-save-modal__retry-btn {
        width: 100%;
    }

    /* MIRA M5-C1: Done button bar sticky on mobile — prevents it scrolling
     * off-screen on short viewports (landscape / 390px height scenarios). */
    .wg-save-modal__actions {
        position: sticky;
        bottom: 0;
        background: var(--color-surface);
        padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
        margin-top: auto;
    }

    /* Ensure all touch targets are ≥ 44px — MIRA MIR3 */
    .wg-save-modal__row,
    .wg-save-modal__new-row {
        min-height: 56px;      /* already 56px — confirmed safe */
    }

    .wg-save-modal__name-input {
        height: 44px;          /* already 44px — confirmed safe */
    }
}


/* ============================================================
   TOAST REPOSITIONING — save modal open on mobile (MIRA M5-C6)
   When the save modal bottom-sheet is open, reposition the toast
   above the sheet so it does not occlude the Done button.
   Body class `wg-save-modal-open` is toggled by WG.save JS.
   --save-modal-height defaults to 50vh; JS may refine this.
   ============================================================ */

/* body.wg-save-modal-open .wg-toast removed Phase 8 —
   Phase 8 toast section targets #wg-toast-container correctly. */


/* ============================================================
   BACKDROP
   Shared with auth modal (Phase 4).
   Phase 5 attaches its click handler to the existing backdrop.
   Phase 8 will unify backdrop management in WG.backdrop.
   z-index: var(--z-modal-backdrop) = 550 (ATLAS §7, NOVA R7)
   The backdrop element (#wg-modal-backdrop) is output by
   auth-modal.php and shared between both modals.
   No additional backdrop CSS needed here — already in Phase 4.
   ============================================================ */


/* ============================================================
   VISUALLY HIDDEN UTILITY (if not already in main.css)
   Used for label elements that must exist for accessibility
   but must not be visually rendered.
   ============================================================ */

.wg-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}


/* ============================================================
   PHASE 6 — SUBMIT PAGE
   REX ALL PASS — 2026-03-27
   ============================================================ */

/*
 * ============================================================
 * 8KWALLS — SUBMIT PAGE STYLESHEET
 * Phase 6 — Wallpaper Submission
 * Loaded only on is_page(25) via functions.php conditional enqueue.
 *
 * State visibility is driven EXCLUSIVELY by:
 *   data-submit-state on .wg-submit-page
 *   data-file-state   on .wg-submit-dropzone
 *
 * PHP writes only "idle" or "logged-out" into data-submit-state.
 * "uploading", "success", "error" are set only by WG.submit.setState().
 *
 * All color, spacing, radius, shadow values use design-system tokens
 * from main.css. No raw hex values in this file.
 *
 * BEM naming: .wg-submit-* prefix throughout.
 * Max 2 nesting levels in selectors.
 * ============================================================
 */


/* ============================================================
   PAGE LAYOUT SHELL
   ============================================================ */

.wg-submit-page {
    max-width: 640px;
    margin: 0 auto;
    /*
     * Padding-top accounts for:
     *   - Sticky header height (set as --header-height by JS on mount)
     *   - WP admin bar height (set as --wp-admin--admin-bar--height by WP core)
     *   - Section spacing below header
     * AURORA §2A, MIRA MC11
     */
    padding-top: calc(
        var(--header-height, 64px) +
        var(--wp-admin--admin-bar--height, 0px) +
        var(--space-10)
    );
    padding-right: var(--space-6);
    padding-bottom: var(--space-16);
    padding-left: var(--space-6);
}

@media (max-width: 768px) {
    .wg-submit-page {
        padding-right: var(--space-4);
        padding-bottom: var(--space-10);
        padding-left: var(--space-4);
    }
}


/* ============================================================
   STATE VISIBILITY — data-submit-state
   The single source of truth for what is visible on the page.
   One attribute → one visible section. No JS class toggling
   ever controls section visibility — only this attribute.
   ============================================================ */

/*
 * Default: hide all state-dependent sections.
 * Each section is shown when its parent has the matching state.
 */
.wg-submit-header,
.wg-form-section,
.wg-success-panel,
.wg-auth-gate {
    display: none;
}

/* logged-out: auth gate only */
[data-submit-state="logged-out"] .wg-auth-gate {
    display: block;
}

/* idle: header + form card */
[data-submit-state="idle"] .wg-submit-header,
[data-submit-state="idle"] .wg-form-section {
    display: block;
}

/* uploading: header + form card (fields disabled) */
[data-submit-state="uploading"] .wg-submit-header,
[data-submit-state="uploading"] .wg-form-section {
    display: block;
}

/* error: header + form card (error banner visible) */
[data-submit-state="error"] .wg-submit-header,
[data-submit-state="error"] .wg-form-section {
    display: block;
}

/* success: success panel only */
[data-submit-state="success"] .wg-success-panel {
    display: block;
}

/* Progress bar: uploading state only */
.wg-upload-progress {
    display: none;
}
[data-submit-state="uploading"] .wg-upload-progress {
    display: block;
}

/* Cancel button: uploading state only */
.wg-submit-cancel {
    display: none;
}
[data-submit-state="uploading"] .wg-submit-cancel {
    display: flex;
    justify-content: center;
    width: 100%;
    margin-top: var(--space-3);
}

/* Error banner: error state only */
.wg-submit-error {
    display: none;
}
[data-submit-state="error"] .wg-submit-error {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    background: var(--color-error-subtle);
    border: 1px solid rgba(192, 57, 43, 0.30);
    border-left: 3px solid var(--color-error);
    border-radius: 10px;
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-4);
}


/* ============================================================
   FILE STATE VISIBILITY — data-file-state on .wg-submit-dropzone
   NOVA M2: three values — empty | selected | invalid
   ============================================================ */

/*
 * empty: show drop zone inner, hide preview + inline error
 * selected: hide drop zone inner, show preview, hide inline error
 * invalid: show drop zone inner (error styling), hide preview, show inline error
 */

/* Default: hide preview and error */
.wg-submit-preview,
.wg-dropzone-error {
    display: none;
}

/* empty: normal drop zone */
[data-file-state="empty"] .wg-dropzone-inner {
    display: flex;
}

/* selected: show preview only */
[data-file-state="selected"] .wg-dropzone-inner {
    display: none;
}
[data-file-state="selected"] .wg-submit-preview {
    display: block;
}

/* invalid: show drop zone inner (in error state) + show error message */
[data-file-state="invalid"] .wg-dropzone-inner {
    display: flex;
}
[data-file-state="invalid"] .wg-submit-preview {
    display: none;
}
[data-file-state="invalid"] .wg-dropzone-error {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4) var(--space-3);
}


/* ============================================================
   PAGE TITLE BLOCK
   ============================================================ */

.wg-submit-header {
    margin-bottom: var(--space-8);
}

.wg-submit-title {
    font-family: var(--font-display);
    font-size: var(--text-h1);
    font-weight: 600;
    line-height: 1.20;
    letter-spacing: -0.02em;
    color: var(--color-text-primary);
    margin: 0 0 var(--space-2);
}

.wg-submit-subtitle {
    font-family: var(--font-body);
    font-size: var(--text-body-lg);
    font-weight: 400;
    line-height: 1.60;
    color: var(--color-text-secondary);
    margin: 0;
}


/* ============================================================
   FORM CARD
   Shared by form section + success panel + auth gate
   ============================================================ */

.wg-form-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 16px;
    box-shadow: 0 2px 12px rgba(17, 16, 16, 0.08);
    padding: var(--space-6);
    width: 100%;
}

@media (max-width: 768px) {
    .wg-form-card {
        padding: var(--space-4);
    }
}


/* ============================================================
   FILE DROP ZONE
   ============================================================ */

.wg-submit-dropzone {
    position: relative;
    margin-bottom: var(--space-5);
    border-radius: 12px;
    outline: none;
}

/* Focus ring for keyboard navigation (tab to drop zone) */
.wg-submit-dropzone:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Drop zone inner — the visible area when no file is selected */
.wg-dropzone-inner {
    min-height: 200px;
    border: 2px dashed var(--color-border);
    border-radius: 12px;
    background: var(--color-bg);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    cursor: pointer;
    transition: border-color 120ms ease, background-color 120ms ease;
    padding: var(--space-8) var(--space-6);
}

.wg-dropzone-inner:hover,
.wg-submit-dropzone.wg-dropzone--drag-over .wg-dropzone-inner {
    border-color: var(--color-accent);
    background: var(--color-accent-subtle);
}

.wg-dropzone-inner:hover .wg-dropzone-icon,
.wg-submit-dropzone.wg-dropzone--drag-over .wg-dropzone-icon {
    color: var(--color-accent);
}

.wg-dropzone-inner:hover .wg-dropzone-text-primary,
.wg-submit-dropzone.wg-dropzone--drag-over .wg-dropzone-text-primary {
    color: var(--color-text-primary);
}

/* invalid state — red border, error background */
[data-file-state="invalid"] .wg-dropzone-inner {
    border-color: var(--color-error);
    background: var(--color-error-subtle);
}

/* uploading state — disabled appearance */
[data-submit-state="uploading"] .wg-dropzone-inner {
    opacity: 0.5;
    pointer-events: none;
    cursor: not-allowed;
}

.wg-dropzone-icon {
    color: var(--color-text-disabled);
    transition: color 120ms ease;
    flex-shrink: 0;
}

.wg-dropzone-text-primary {
    font-size: var(--text-body-sm);
    font-weight: 400;
    color: var(--color-text-secondary);
    margin: 0;
    text-align: center;
    transition: color 120ms ease;
}

.wg-dropzone-text-secondary {
    font-size: var(--text-caption);
    font-weight: 400;
    color: var(--color-text-disabled);
    margin: 0;
    text-align: center;
}

.wg-dropzone-browse {
    margin-top: var(--space-1);
}


/* ============================================================
   FILE PREVIEW
   ============================================================ */

.wg-submit-preview {
    border: 1px solid var(--color-border);
    border-radius: 12px;
    overflow: hidden;
    background: var(--color-surface);
}

.wg-submit-preview__img {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: 12px 12px 0 0;
}

.wg-submit-preview__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 44px;
    padding: 0 var(--space-4);
    background: var(--color-surface);
    border-top: 1px solid var(--color-border);
    border-radius: 0 0 12px 12px;
    gap: var(--space-2);
}

.wg-submit-preview__info {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    min-width: 0;
    flex: 1;
}

.wg-submit-preview__name {
    font-size: var(--text-body-sm);
    font-weight: 400;
    color: var(--color-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: calc(100% - 64px);
}

.wg-submit-preview__size {
    font-size: var(--text-caption);
    font-weight: 400;
    color: var(--color-text-secondary);
    white-space: nowrap;
    flex-shrink: 0;
}


/* ============================================================
   DROPZONE INLINE ERROR (data-file-state="invalid")
   ============================================================ */

.wg-dropzone-error {
    align-items: flex-start;
    gap: var(--space-2);
}

.wg-dropzone-error__icon {
    color: var(--color-error);
    flex-shrink: 0;
    margin-top: 1px;
}

.wg-dropzone-error__text {
    font-size: var(--text-caption);
    font-weight: 400;
    color: var(--color-error);
}


/* ============================================================
   PROGRESS BAR
   ============================================================ */

.wg-upload-progress {
    margin-bottom: var(--space-5);
}

.wg-upload-progress__track {
    width: 100%;
    height: 4px;
    background: var(--color-border);
    border-radius: 2px;
    overflow: hidden;
    margin-bottom: var(--space-2);
}

.wg-upload-progress__fill {
    height: 100%;
    background: var(--color-accent);
    border-radius: 2px;
    width: 0%;
    transition: width 100ms ease;
}

.wg-upload-progress__label {
    display: block;
    text-align: center;
    font-size: var(--text-caption);
    font-weight: 400;
    color: var(--color-text-secondary);
    margin-top: var(--space-2);
}


/* ============================================================
   FORM FIELDS STACK
   ============================================================ */

.wg-submit-fields {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    margin-top: var(--space-5);
}

/* Field wrapper */
.wg-form-field {
    display: flex;
    flex-direction: column;
}

/* Label */
.wg-label {
    font-family: var(--font-body);
    font-size: var(--text-label);
    font-weight: 500;
    line-height: 1.40;
    letter-spacing: 0.04em;
    color: var(--color-text-secondary);
    text-transform: uppercase;
    margin-bottom: var(--space-2);
}

/* Input base — shared by text, select, textarea */
.wg-input {
    height: 44px;
    font-size: var(--text-input);          /* MIRA MIR2: 1rem / 16px — prevents iOS Safari zoom */
    font-family: var(--font-body);
    font-weight: 400;
    color: var(--color-text-primary);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    padding: 0 var(--space-4);
    width: 100%;
    box-sizing: border-box;
    transition: border-color 80ms ease, outline 80ms ease;
    appearance: none;
    -webkit-appearance: none;
}

.wg-input::placeholder {
    color: var(--color-text-disabled);
}

.wg-input:focus {
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 0;
    border-color: var(--color-accent);
}

.wg-input.wg-input--error,
.wg-form-field.is-error .wg-input {
    border-color: var(--color-error);
    outline: 2px solid var(--color-error-focus-ring);
    outline-offset: 0;
}

/* Disabled state during uploading */
[data-submit-state="uploading"] .wg-input {
    background: var(--color-bg);
    color: var(--color-text-disabled);
    border-color: var(--color-border);
    cursor: not-allowed;
    pointer-events: none;
}

/* Textarea overrides */
.wg-input--textarea {
    height: auto;
    min-height: 120px;
    max-height: 300px;
    padding: var(--space-3) var(--space-4);
    resize: vertical;
    line-height: 1.60;
}

/* Select wrapper — NOVA C8: never output bare <select> without this */
.wg-select-wrapper {
    position: relative;
}

.wg-select-wrapper .wg-input {
    padding-right: 40px;   /* room for chevron icon */
    cursor: pointer;
}

.wg-select-chevron {
    position: absolute;
    right: var(--space-4);
    top: 50%;
    transform: translateY(-50%);
    color: var(--color-text-secondary);
    pointer-events: none;
    flex-shrink: 0;
}

/* Field-level error message */
.wg-field-error {
    font-size: var(--text-caption);
    font-weight: 400;
    color: var(--color-error);
    margin-top: var(--space-1);
    display: none;
}

.wg-form-field.is-error .wg-field-error {
    display: block;
}

/* Char counter */
.wg-char-counter {
    font-size: var(--text-caption);
    font-weight: 400;
    color: var(--color-text-disabled);
    text-align: right;
    margin-top: var(--space-1);
    display: block;
    transition: color 80ms ease;
}

.wg-char-counter.is-limit {
    color: var(--color-error);
}


/* ============================================================
   ERROR BANNER
   ============================================================ */

.wg-submit-error__icon {
    color: var(--color-error);
    flex-shrink: 0;
    margin-top: 2px;
}

.wg-submit-error__text {
    font-size: var(--text-body-sm);
    font-weight: 400;
    color: var(--color-error);
}


/* ============================================================
   SUBMIT BUTTON
   Full-width primary button with loading spinner state
   ============================================================ */

.wg-btn--full {
    width: 100%;
    justify-content: center;
}

.wg-submit-btn {
    margin-top: var(--space-6);
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
}

.wg-submit-btn[data-state="loading"] {
    pointer-events: none;
    cursor: not-allowed;
    opacity: 0.85;
}

.wg-submit-btn__spinner {
    display: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid rgba(248, 247, 244, 0.30);
    border-top-color: var(--color-text-inverse);
    animation: wg-spin 600ms linear infinite;
    flex-shrink: 0;
}

.wg-submit-btn[data-state="loading"] .wg-submit-btn__spinner {
    display: block;
}

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


/* ============================================================
   SUCCESS PANEL
   NOVA M1: Always in DOM for logged-in users.
   Hidden until data-submit-state="success" is set by JS.
   ============================================================ */

.wg-success-panel {
    /* Shown by [data-submit-state="success"] .wg-success-panel rule above */
}

.wg-success-panel__card {
    /* Inherits .wg-form-card styles */
}

.wg-success-panel__inner {
    padding: var(--space-8) var(--space-6);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-4);
}

@media (max-width: 768px) {
    .wg-success-panel__inner {
        padding: var(--space-6) var(--space-4);
    }
}

.wg-success-panel__icon {
    color: var(--color-success);
    flex-shrink: 0;
    margin-bottom: var(--space-2);
}

.wg-success-panel__headline {
    font-family: var(--font-display);
    font-size: var(--text-h2);
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.015em;
    color: var(--color-text-primary);
    margin: 0;
}

.wg-success-panel__body {
    font-family: var(--font-body);
    font-size: var(--text-body);
    font-weight: 400;
    line-height: 1.60;
    color: var(--color-text-secondary);
    max-width: 360px;
    margin: 0;
}

.wg-submit-another-btn {
    margin-top: var(--space-6);
    width: 100%;
    justify-content: center;
}

.wg-success-panel__view-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--space-3);
    font-size: var(--text-body-sm);
    font-weight: 500;
    color: var(--color-accent);
    text-decoration: none;
    margin-top: var(--space-3);
    transition: text-decoration 80ms ease;
}

.wg-success-panel__view-link:hover {
    text-decoration: underline;
}


/* ============================================================
   LOGGED-OUT AUTH GATE
   ============================================================ */

.wg-auth-gate__card {
    /* Inherits .wg-form-card styles */
    padding: var(--space-12) var(--space-8);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-4);
}

@media (max-width: 768px) {
    .wg-auth-gate__card {
        padding: var(--space-8) var(--space-4);
    }
}

.wg-auth-gate__icon {
    color: var(--color-text-disabled);
    flex-shrink: 0;
}

.wg-auth-gate__message {
    font-family: var(--font-display);
    font-size: var(--text-h2);
    font-weight: 600;
    line-height: 1.25;
    color: var(--color-text-primary);
    margin: 0;
}

.wg-auth-gate__support {
    font-family: var(--font-body);
    font-size: var(--text-body);
    font-weight: 400;
    line-height: 1.60;
    color: var(--color-text-secondary);
    max-width: 320px;
    margin: 0;
}

.wg-auth-gate__card .wg-btn--primary {
    width: 100%;
    justify-content: center;
}

.wg-auth-gate__register-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--space-3);
    font-size: var(--text-body-sm);
    font-weight: 500;
    color: var(--color-accent);
    text-decoration: none;
    margin-top: var(--space-2);
}

.wg-auth-gate__register-link:hover {
    text-decoration: underline;
}


/* ============================================================
   CANCEL BUTTON — ghost variant, centered
   ============================================================ */

.wg-submit-cancel {
    color: var(--color-text-secondary);
    background: transparent;
    border: none;
    cursor: pointer;
    font-size: var(--text-ui-md);
    font-weight: 500;
    height: 44px;
    padding: 0 var(--space-4);
    border-radius: 10px;
    transition: background-color 120ms ease, color 120ms ease;
}

.wg-submit-cancel:hover {
    background: rgba(17, 16, 16, 0.06);
    color: var(--color-text-primary);
}

.wg-submit-cancel:active {
    background: rgba(17, 16, 16, 0.10);
    transform: scale(0.97);
}


/* ============================================================
   BUTTON BASE STYLES
   (Minimal — full button system is in main.css)
   ============================================================ */

.wg-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    font-family: var(--font-body);
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    border: none;
    transition: background-color 120ms ease, border-color 120ms ease, transform 80ms ease;
    white-space: nowrap;
}

.wg-btn--primary {
    background: var(--color-accent);
    color: var(--color-text-inverse);
    border-radius: var(--radius-xl, 12px);
}

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

.wg-btn--primary:active {
    background: var(--color-accent-active);
    transform: scale(0.97);
}

.wg-btn--primary:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.wg-btn--primary:disabled {
    background: var(--color-border-strong);
    color: var(--color-text-disabled);
    cursor: not-allowed;
    pointer-events: none;
}

.wg-btn--secondary {
    background: var(--color-surface);
    color: var(--color-text-primary);
    border: 1px solid var(--color-border);
    border-radius: 8px;
}

.wg-btn--secondary:hover {
    background: var(--color-bg);
    border-color: var(--color-border-strong);
}

.wg-btn--ghost {
    background: transparent;
    color: var(--color-text-primary);
    border: none;
    border-radius: 8px;
}

.wg-btn--ghost:hover {
    background: rgba(17, 16, 16, 0.06);
}

.wg-btn--lg {
    height: 48px;
    font-size: var(--text-ui-md);
    padding: 0 var(--space-5);
    border-radius: 12px;
}

.wg-btn--md {
    height: 44px;
    font-size: var(--text-ui-md);
    padding: 0 var(--space-4);
    border-radius: 10px;
}

.wg-btn--sm {
    height: 32px;
    font-size: var(--text-ui-sm);
    padding: 0 var(--space-3);
    border-radius: 8px;
}


/* ============================================================
   ACCESSIBILITY UTILITIES
   ============================================================ */

/* Screen-reader only: visually hidden but accessible to AT */
.wg-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}


/* ============================================================
   REDUCED MOTION
   ATLAS §5 — required on all motion-containing components
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
    .wg-upload-progress__fill,
    .wg-submit-btn__spinner,
    .wg-dropzone-inner,
    .wg-btn,
    .wg-submit-cancel,
    .wg-input {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}


/* ============================================================
   PHASE 7 — PROFILE + SETTINGS
   ============================================================ */


/* ------------------------------------------------------------
   PROFILE HEADER
   ------------------------------------------------------------ */

.wg-profile-header {
    display: flex;
    flex-direction: row;
    gap: var(--space-4);
    padding-block: var(--space-8);
    align-items: flex-start;
}

.wg-profile-header__avatar {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.wg-profile-header__info {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.wg-profile-header__name {
    font-size: var(--text-h3-size);
    font-weight: 600;
    color: var(--color-text-primary);
    margin: 0;
    line-height: var(--text-h3-lh);
    letter-spacing: var(--text-h3-ls);
}

.wg-profile-header__username {
    font-size: var(--text-body-sm-size);
    color: var(--color-text-secondary);
    margin: 0;
}

.wg-profile-header__bio {
    font-size: var(--text-body-size);
    color: var(--color-text-secondary);
    margin: 0;
    max-width: var(--text-max-width);
}

.wg-profile-header__count {
    font-size: var(--text-body-sm-size);
    color: var(--color-text-disabled);
    margin: 0;
}

.wg-profile-grid__label {
    font-size: var(--text-body-sm-size);
    color: var(--color-text-secondary);
    margin-bottom: var(--space-4);
    margin-top: 0;
}


/* ------------------------------------------------------------
   AUTH GATE
   ------------------------------------------------------------ */

.wg-auth-gate {
    min-height: 400px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    text-align: center;
    padding: var(--space-8);
}

.wg-auth-gate__icon {
    color: var(--color-text-disabled);
}

.wg-auth-gate__headline {
    font-size: var(--text-h3-size);
    font-weight: 600;
    color: var(--color-text-primary);
    margin: 0;
    line-height: var(--text-h3-lh);
}

.wg-auth-gate__body {
    font-size: var(--text-body-size);
    color: var(--color-text-secondary);
    margin: 0;
    max-width: 40ch;
}


/* ------------------------------------------------------------
   SETTINGS SHELL — DESKTOP: sidebar 200px + flex-1 panels
   ------------------------------------------------------------ */

.wg-settings {
    display: flex;
    flex-direction: row;
    gap: var(--space-8);
    max-width: 900px;
    margin: 0 auto;
    padding: var(--space-8) var(--space-4);
    align-items: flex-start;
}

/* SETTINGS NAV — sidebar at desktop */
.wg-settings-nav {
    flex-shrink: 0;
    width: 200px;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.wg-settings-tab {
    display: block;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    color: var(--color-text-secondary);
    text-decoration: none;
    font-size: var(--text-body-sm-size);
    font-weight: 500;
    line-height: 1.4;
    transition: background var(--duration-moderate) var(--ease-default),
                color var(--duration-moderate) var(--ease-default);
    min-height: 44px;  /* touch target */
    display: flex;
    align-items: center;
}

.wg-settings-tab:hover {
    background: rgba(17, 16, 16, 0.06);
    color: var(--color-text-primary);
}

.wg-settings-tab[aria-current="true"] {
    background: var(--color-accent-subtle);
    color: var(--color-accent);
    font-weight: 600;
}

.wg-settings-tab[aria-disabled="true"] {
    opacity: 0.5;
    cursor: default;
    pointer-events: none;
}

/* SETTINGS PANELS */
.wg-settings-panels {
    flex: 1;
    min-width: 0;
}

.wg-settings-panel {
    /* hidden attribute hides the panel — no extra CSS needed for display */
}

.wg-settings-panel__title {
    font-size: var(--text-h3-size);
    font-weight: 600;
    margin-top: 0;
    margin-bottom: var(--space-6);
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--color-border);
    color: var(--color-text-primary);
    line-height: var(--text-h3-lh);
}


/* ------------------------------------------------------------
   SETTINGS FORMS
   ------------------------------------------------------------ */

.wg-settings-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.wg-settings-form__actions {
    display: flex;
    flex-direction: row;
    gap: var(--space-3);
    padding-top: var(--space-4);
    flex-wrap: wrap;
}

.wg-settings-form__inline-msg {
    font-size: var(--text-body-sm-size);
    color: var(--color-text-secondary);
    margin: 0;
    min-height: 1.4em;
}

/* Avatar field */
.wg-field--avatar {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--space-4);
}

.wg-field--avatar__controls {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.wg-avatar-preview {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--color-border);
    flex-shrink: 0;
}

.wg-avatar-upload-message {
    font-size: var(--text-body-sm-size);
    color: var(--color-success);
    margin: 0;
    min-height: 1.4em;
}

/* Textarea */
.wg-textarea {
    display: block;
    width: 100%;
    min-height: 100px;
    padding: var(--textarea-padding);
    font-family: var(--font-body);
    font-size: var(--text-input-size);  /* 16px — iOS zoom prevention */
    font-weight: var(--text-input-weight);
    line-height: var(--text-input-lh);
    color: var(--color-text-primary);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--input-radius);
    resize: vertical;
    transition: var(--transition-focus);
    box-shadow: none;
    -webkit-appearance: none;
    appearance: none;
}

.wg-textarea:focus {
    outline: 2px solid var(--color-accent-focus-ring);
    outline-offset: 0;
    border-color: var(--color-accent);
}

.wg-textarea::placeholder {
    color: var(--color-text-disabled);
}

/* Character counter */
.wg-field__counter {
    font-size: var(--text-label-size);
    color: var(--color-text-disabled);
    text-align: right;
    display: block;
    margin-top: var(--space-1);
}

/* Hidden file input */
.wg-input--hidden {
    display: none;
}

/* Readonly input */
.wg-input--readonly {
    background: var(--color-bg);
    color: var(--color-text-secondary);
    cursor: default;
    pointer-events: none;
}

/* Save button states */
#save-profile-btn .wg-btn__success,
#save-profile-btn .wg-btn__error {
    display: none;
}

#save-profile-btn[data-state="success"] .wg-btn__label,
#save-profile-btn[data-state="error"]   .wg-btn__label {
    display: none;
}

#save-profile-btn[data-state="success"] .wg-btn__success { display: inline; }
#save-profile-btn[data-state="error"]   .wg-btn__error   { display: inline; }

#save-profile-btn[data-state="loading"] {
    opacity: 0.7;
    cursor: wait;
    pointer-events: none;
}

#save-profile-btn[data-state="success"] {
    background: var(--color-success);
}

#save-profile-btn[data-state="error"] {
    background: var(--color-error);
}

/* Avatar upload button states */
#avatar-upload-btn[data-state="loading"] {
    opacity: 0.7;
    cursor: wait;
    pointer-events: none;
}


/* ------------------------------------------------------------
   SETTINGS SECTION TITLES
   ------------------------------------------------------------ */

.wg-settings-section__title {
    font-size: var(--text-body-size);
    font-weight: 600;
    color: var(--color-text-primary);
    margin-top: 0;
    margin-bottom: var(--space-2);
}

.wg-settings-section__title--danger {
    color: var(--color-error);
}


/* ------------------------------------------------------------
   SETTINGS ACCOUNT PANEL
   ------------------------------------------------------------ */

.wg-settings-account__email,
.wg-settings-account__password {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4) 0;
    border-bottom: 1px solid var(--color-border);
}

.wg-settings-account__email:first-of-type {
    padding-top: 0;
}

.wg-settings-account__current-email {
    font-size: var(--text-body-sm-size);
    color: var(--color-text-secondary);
    margin: 0;
}


/* ------------------------------------------------------------
   SETTINGS DANGER ZONE
   ------------------------------------------------------------ */

.wg-settings-danger {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4);
    border: 1px solid var(--color-error);
    border-radius: var(--radius-lg);
    background: var(--color-error-subtle);
}

.wg-settings-danger__desc {
    font-size: var(--text-body-sm-size);
    color: var(--color-text-secondary);
    max-width: 480px;
    margin: 0;
}


/* ------------------------------------------------------------
   DIVIDER
   ------------------------------------------------------------ */

.wg-divider {
    height: 1px;
    background: var(--color-border);
    margin-block: var(--space-4);
    border: none;
}


/* ------------------------------------------------------------
   STUB (Notifications coming soon)
   ------------------------------------------------------------ */

.wg-stub {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-6) 0;
}

.wg-stub__icon {
    color: var(--color-text-disabled);
}

.wg-stub__headline {
    font-size: var(--text-body-size);
    font-weight: 600;
    color: var(--color-text-primary);
    margin: 0;
}

.wg-stub__body {
    font-size: var(--text-body-sm-size);
    color: var(--color-text-secondary);
    margin: 0;
}


/* ------------------------------------------------------------
   DELETE CONFIRM MODAL
   Inherits .wg-modal base (Phase 4/5). z-index 600.
   ------------------------------------------------------------ */

.wg-modal--confirm-delete {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
}

.wg-modal--confirm-delete .wg-modal__backdrop {
    position: absolute;
    inset: 0;
    background: var(--color-scrim-modal);
}

.wg-modal--confirm-delete .wg-modal__panel--confirm-delete {
    position: relative;
    z-index: 1;
    background: var(--color-surface);
    border-radius: var(--modal-border-radius);
    padding: var(--space-8);
    max-width: var(--modal-max-width);
    width: calc(100% - var(--space-8));
    box-shadow: var(--shadow-panel);
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
    animation: wg-modal-enter var(--duration-enter) var(--ease-enter);
}

.wg-modal--confirm-delete.is-exiting .wg-modal__panel--confirm-delete {
    animation: wg-modal-exit var(--duration-moderate) var(--ease-exit);
}

.wg-modal--confirm-delete .wg-modal__header {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.wg-modal--confirm-delete .wg-modal__title {
    font-size: var(--text-h3-size);
    font-weight: 600;
    margin: 0;
    color: var(--color-text-primary);
}

.wg-modal--confirm-delete .wg-modal__body-text {
    font-size: var(--text-body-size);
    color: var(--color-text-secondary);
    margin: 0;
    line-height: var(--text-body-lh);
}

.wg-modal--confirm-delete .wg-modal__footer--confirm-delete {
    display: flex;
    flex-direction: row;
    gap: var(--space-3);
    justify-content: flex-end;
}

/* Entry/exit animations (reuse Phase 4 keyframes if they exist, else define) */
@keyframes wg-modal-enter {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes wg-modal-exit {
    from {
        opacity: 1;
        transform: translateY(0);
    }
    to {
        opacity: 0;
        transform: translateY(8px);
    }
}


/* ------------------------------------------------------------
   MOBILE — ≤ 768px
   ------------------------------------------------------------ */

@media (max-width: 768px) {

    /* Settings layout: stacked */
    .wg-settings {
        flex-direction: column;
        gap: var(--space-4);
        padding: var(--space-4) 0;
    }

    /* Nav: horizontal scrollable pill row */
    .wg-settings-nav {
        width: 100%;
        flex-direction: row;
        overflow-x: auto;
        gap: var(--space-2);
        padding-bottom: var(--space-2);
        border-bottom: 1px solid var(--color-border);
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none; /* Firefox */
    }

    .wg-settings-nav::-webkit-scrollbar {
        display: none; /* Chrome/Safari */
    }

    .wg-settings-tab {
        display: inline-flex;
        white-space: nowrap;
        flex-shrink: 0;
        padding: var(--space-2) var(--space-3);
        min-height: 44px;
    }

    /* Profile header: smaller avatar */
    .wg-profile-header__avatar {
        width: 64px;
        height: 64px;
    }

    /* Modal: bottom-sheet on mobile */
    .wg-modal--confirm-delete {
        align-items: flex-end;
        justify-content: stretch;
    }

    .wg-modal--confirm-delete .wg-modal__panel--confirm-delete {
        width: 100%;
        max-width: 100%;
        border-radius: var(--modal-border-radius-mob);
        max-height: var(--modal-max-height-mob);
        overflow-y: auto;
        padding-bottom: calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
        animation: wg-modal-enter-sheet var(--duration-sheet) var(--ease-enter);
    }

    .wg-modal--confirm-delete.is-exiting .wg-modal__panel--confirm-delete {
        animation: wg-modal-exit-sheet var(--duration-sheet) var(--ease-exit);
    }

    .wg-modal--confirm-delete .wg-modal__footer--confirm-delete {
        flex-direction: column-reverse;
    }

    @keyframes wg-modal-enter-sheet {
        from {
            transform: translateY(100%);
        }
        to {
            transform: translateY(0);
        }
    }

    @keyframes wg-modal-exit-sheet {
        from {
            transform: translateY(0);
        }
        to {
            transform: translateY(100%);
        }
    }

    /* Avatar field: stack on mobile */
    .wg-field--avatar {
        flex-direction: column;
        align-items: flex-start;
    }

    .wg-settings-form__actions {
        flex-direction: column;
    }

    .wg-settings-form__actions .wg-btn {
        width: 100%;
        justify-content: center;
    }

    /* MIRA CONDITION 1: Ensure wg-btn--sm meets 44px touch target on mobile */
    .wg-profile-header .wg-btn--sm,
    .wg-settings .wg-btn--sm {
        min-height: 44px;
    }

}


/* ------------------------------------------------------------
   REDUCED MOTION — Phase 7 additions
   ------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
    .wg-modal--confirm-delete .wg-modal__panel--confirm-delete,
    .wg-settings-tab,
    .wg-textarea,
    .wg-avatar-preview {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}


/* ============================================================
   PHASE 8 — GLOBAL JS UNIFICATION
   Toast system (WG.toast), z-index token
   ============================================================ */

/* Toast container — fixed bottom-center */
#wg-toast-container {
    position: fixed;
    bottom: calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
    left: 50%;
    transform: translateX(-50%);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    pointer-events: none;
}

/* Individual toast item */
.wg-toast {
    background: var(--color-surface);
    color: var(--color-text-primary);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill, 100px);
    padding: var(--space-2) var(--space-4);
    font-size: var(--text-body-sm-size);
    font-weight: 500;
    box-shadow: var(--shadow-panel);
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 200ms var(--ease-default, ease),
                transform 200ms var(--ease-default, ease);
    pointer-events: none;
    white-space: nowrap;
    max-width: min(320px, calc(100vw - var(--space-8)));
    overflow: hidden;
    text-overflow: ellipsis;
}

.wg-toast--visible {
    opacity: 1;
    transform: translateY(0);
}

.wg-toast--success {
    border-color: var(--color-success);
    color: var(--color-success);
}

.wg-toast--error {
    border-color: var(--color-error);
    color: var(--color-error);
}

/* Save modal open: push toast above the bottom sheet */
body.wg-save-modal-open #wg-toast-container {
    bottom: calc(60vh + var(--space-4));
}

@media (prefers-reduced-motion: reduce) {
    .wg-toast {
        transition-duration: 0.01ms !important;
    }
}


/* ============================================================
   PHASE 9 — LEGAL PAGES
   ============================================================ */

.wg-legal-main {
    padding-block: var(--space-12);
}

.wg-legal-wrap {
    max-width: 720px;
    margin: 0 auto;
}

.wg-legal-title {
    font-size: var(--text-h1-size);
    font-weight: 700;
    line-height: var(--text-h1-lh);
    letter-spacing: var(--text-h1-ls);
    color: var(--color-text-primary);
    margin-bottom: var(--space-8);
    padding-bottom: var(--space-4);
    border-bottom: 1px solid var(--color-border);
}

.wg-legal-content {
    font-size: var(--text-body-size);
    line-height: var(--text-body-lh);
    color: var(--color-text-secondary);
}

.wg-legal-content h2 {
    font-size: var(--text-h3-size);
    font-weight: 600;
    color: var(--color-text-primary);
    margin-top: var(--space-8);
    margin-bottom: var(--space-3);
}

.wg-legal-content h3 {
    font-size: var(--text-body-size);
    font-weight: 600;
    color: var(--color-text-primary);
    margin-top: var(--space-6);
    margin-bottom: var(--space-2);
}

.wg-legal-content p {
    margin-bottom: var(--space-4);
}

.wg-legal-content a {
    color: var(--color-accent);
    text-decoration: underline;
}

.wg-legal-content a:hover {
    color: var(--color-accent-hover);
}

.wg-legal-content ul,
.wg-legal-content ol {
    margin-bottom: var(--space-4);
    padding-left: var(--space-6);
}

.wg-legal-content li {
    margin-bottom: var(--space-2);
}

@media (max-width: 768px) {
    .wg-legal-main {
        padding-block: var(--space-8);
    }
    .wg-legal-title {
        font-size: var(--text-h2-size);
    }
}

/* MIRA M9-04: legal body text 1rem at ≤480px — improves readability on small screens */
@media (max-width: 480px) {
    .wg-legal-content {
        font-size: 1rem;
    }
}


/* ------------------------------------------------------------
   SKIP LINK — MIRA M9-02 (WCAG 2.4.1 Level A)
   Visible only on keyboard focus. Positioned above the sticky header.
   ------------------------------------------------------------ */

.wg-skip-link {
    position: absolute;
    top: -100%;
    left: var(--space-4);
    z-index: calc(var(--z-header, 100) + 10);
    background: var(--color-accent);
    color: #fff;
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-md);
    font-size: var(--text-body-sm-size);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: top 150ms var(--ease-default);
}

.wg-skip-link:focus {
    top: var(--space-2);
    outline: 2px solid #fff;
    outline-offset: 2px;
}


/* ============================================================
   PHASE 10 — 404 + SEARCH TEMPLATES
   ============================================================ */

/* ------------------------------------------------------------
   404 PAGE
   ------------------------------------------------------------ */

.wg-main--404 {
    min-height: 60vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding-block: var(--space-12);
}

.wg-404-suggestions {
    width: 100%;
    max-width: var(--container-max-width);
    padding: var(--space-8) 0 0;
}

.wg-404-suggestions__title {
    font-size: var(--text-h3-size);
    font-weight: 600;
    color: var(--color-text-primary);
    margin-bottom: var(--space-6);
    text-align: center;
}

.wg-404-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-4);
}

@media (max-width: 768px) {
    .wg-404-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    .wg-main--404 {
        padding-block: var(--space-8);
        justify-content: flex-start;
    }
}

/* ------------------------------------------------------------
   SEARCH RESULTS PAGE
   ------------------------------------------------------------ */

.wg-main--search {
    padding-block: var(--space-8);
}

.wg-search-results__title {
    font-size: var(--text-h2-size);
    font-weight: 700;
    line-height: var(--text-h2-lh);
    color: var(--color-text-primary);
    margin-bottom: var(--space-6);
}

.wg-search-results__count {
    color: var(--color-text-secondary);
    font-weight: 400;
}
