/*
Theme Name: Asset Gallery
Theme URI: https://mags.greatwhitefrog.com
Author: Sebastien Marchal
Author URI: https://greatwhitefrog.com
Description: A masonry-style visual gallery for any catalogued collection — magazine covers, screenshots, books, objects — with configurable taxonomies, colour filtering, tags, and live filtering. Deployment naming lives in inc/config-site.php. Clean white minimalist design so images take centre stage.
Version: 2.0.0
Requires at least: 6.0
Requires PHP: 7.4
Text Domain: asset-gallery
*/

/* =============================================================================
   DESIGN TOKENS
   Change colours, spacing, and typography here — everything else adapts.
   ============================================================================= */
:root {
  /* Palette — light mode (default) */
  --bg:           #f8f8f8;
  --bg-off:       #f9f9f9;
  --border:       #d8d8d8;
  --border-hover: #aaaaaa;
  --text-primary:   #000;
  /* --text-secondary: #8100d6; AAA compliant */
  --text-secondary: #777;
  --text-secondary-alpha: rgba(21, 128, 250, 0.348);
  --text-muted:     #767676;
  --accent:       #111111;
  --accent-inv:   #ffffff;
  --lightbox-bg: rgba(255, 255, 255, 0.90);

  /* Colour-filter swatch dots — cosmetic only (they don't affect which
     assets match; filtering uses hue ranges in the AJAX handler).
     Tweak the swatch appearance here in one place. */
  --swatch-reds:    #e72f25;
  --swatch-oranges: #fc790f;
  --swatch-yellows: #dbc200;
  --swatch-greens:  #279c2d;
  --swatch-teals:   #189f94;
  --swatch-blues:   #2265d2;
  --swatch-purples: #a23cfb;
  --swatch-pinks:   #c64c79;

  /* Typography */
  --font-mono: 'IBM Plex Mono', 'Courier New', monospace;
  --font-mono: 'Montserrat', 'Helvetica Neue', 'Helvetica', sans-serif;
  --font-sans: 'Montserrat', 'Helvetica Neue', 'Helvetica', sans-serif;
  --letter-spacing-wide: 0.12em;
  --letter-spacing-medium: 0.10em;
  --letter-spacing-narrow: 0.08em;
  --letter-spacing-tight: 0.05em;
  --letter-spacing-negative: -0.02em;
  
  
  /* ──────────────────────────────────────────────────────────────────────────
     SPACING — two separate jobs, don't conflate them

     --gap    Gutter BETWEEN grid items. Change it to loosen or tighten the
              grid without touching the page edges. 0 gives a borderless,
              edge-to-edge tiled look.

     --margin Left/right inset of every major layout element from the viewport
              edge: header, drawers, gallery container, single-asset info bar,
              static page content, footer. Change it to move the whole layout
              in or out from the edges. Everything stays aligned because they
              all read this one token.

     Both drop at the ≤600px breakpoint — see the bottom of this file.
     Note: html has zoom: 1.25, so these render ~25% larger than their px value.
     ────────────────────────────────────────────────────────────────────────── */
  --gap: 40px;
  --margin: 100px;

  --container-max: 1800px;
  --header-h: 100px;
  --toolbar-h: 44px;

  --t-fast: 150ms ease;
  --t-base: 220ms ease;
  --t-slow: 360ms cubic-bezier(0.4, 0, 0.2, 1);

  --radius-pill: 100px;
  
  --content-width: 680px; /* static page content width */
}

/* Dark mode — activated by [data-theme="dark"] on <html> */
[data-theme="dark"] {
  --bg:           #000000;
  --bg-off:       #141414;
  --border:       #282828;
  --border-hover: #555555;
  --text-primary:   #f0f0f0;
  /* --text-secondary: #bf78fc; AAA */
  --text-secondary: #157ff9;
  --text-muted:     #999999;
  --accent:       #f0f0f0;
  --accent-inv:   #0a0a0a;
  --lightbox-bg: rgba(0, 0, 0, 0.90);
}


/* =============================================================================
   RESET
   ============================================================================= */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  zoom: 1.25; /* 125% global scale */
}

body {
  background: var(--bg);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.6;
  min-height: 100vh;
  transition: background var(--t-base), color var(--t-base);
}

img   { max-width: 100%; height: auto; display: block; }
a     { color: inherit; text-decoration: none; }
button { font-family: inherit; touch-action: manipulation; }

h1, h2, h3, h4, h5, h6 { font-family: var(--font-mono); line-height: 1.25; }


/* =============================================================================
   SITE LAYOUT
   ============================================================================= */
.site-wrapper {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* No padding-top needed — header scrolls with content */
.site-main {
  flex: 1;
}


/* =============================================================================
   STATIC PAGE (page.php)
   ============================================================================= */
.ag-page {
  max-width: var(--container-max);
  margin: 0 auto;
  padding-bottom: 64px;
}

.ag-page-header {
  margin: 60px auto 40px auto;
}
.ag-page-featured-image {
}
.ag-page-title {
  font-family: var(--font-sans);
  font-size: 4em;
  font-weight: 700;
  line-height: 1;
  text-wrap: balance;
  letter-spacing: var(--letter-spacing-negative);
  color: var(--text-secondary);
  margin: 0 auto;
  padding: 0 var(--margin);
  max-width: var(--content-width);
}

.ag-page-content {
  font-size: 16px;
  line-height: 1.6;
  color: var(--text-primary);
  margin: 0 auto;
  padding: 0 var(--margin);
  max-width: var(--content-width);
}

.ag-page-content h2,
.ag-page-content h3,
.ag-page-content h4 {
  font-family: var(--font-sans);
  color: var(--text-primary);
  letter-spacing: var(--letter-spacing-medium);
  text-transform: uppercase;
  text-wrap: balance;
  font-weight: 800;
  margin: 4em 0 1.5em;
}
.ag-page-content h2 { font-size: .8em; color: var(--text-secondary); }
.ag-page-content h3 { font-size: .8em; }
.ag-page-content h4 { font-size: .7em; }

.ag-page-content p  { margin: 0 0 1.25em; }
.ag-page-content a  { text-decoration: none; color: var(--text-secondary); transition: color var(--t-fast); border-bottom: 1px solid var(--text-secondary); }
.ag-page-content a:active { color: var(--accent); border-color: var(--accent); }
.ag-page-content ul,
.ag-page-content ol { padding-left: 1.5em; margin: 0 0 1.25em; }
.ag-page-content li { margin-bottom: 0.4em; }


/* =============================================================================
   HEADER  — scrolls with content (not sticky/fixed)
   ============================================================================= */
.site-header {
  /* NOT fixed — scrolls with the page */
  position: relative;
  height: var(--header-h);
  background: var(--bg);
  display: flex;
  align-items: center;
  padding: 0 var(--margin);
  gap: 32px;
  transition: background var(--t-base);
  border-bottom: none;
}

[data-theme="dark"] .site-header {
  background: var(--bg);
}

/* wordmark */
.site-branding { flex-shrink: 0; }

.site-title {
  padding: 3px 0;
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 900;
  letter-spacing: var(--letter-spacing-narrow);
  text-transform: uppercase;
  color: var(--text-primary);
  transition: opacity var(--t-fast), color var(--t-fast);
}
.ag-icon-logo { width: 20px; height: 20px; margin: 0 8px -5px 0; transition: transform var(--t-fast); }
.site-title:hover .ag-icon-logo { transform: rotate(-30deg) scale(1.1); }
.ag-mobile-title {
  display: none;  /* Hidden on desktop */
}


/* ── Primary Nav ──────────────────────────────────────────────────────────── */
.ag-nav {
  display: flex;
  align-items: center;
  gap: 0;            /* Gap between links is handled by padding on each link */
  flex: 1;
  flex-wrap: nowrap;
  /*overflow: hidden; */ /* Overflow handled by mobile menu on small screens */
}

/*
 * Filter links — plain text, no border, no pill shape.
 * Color change on hover is the only affordance, consistent with
 * modern editorial / portfolio nav patterns.
 */
.ag-nav-link {
  background: none;
  border: none;
  padding: 6px 12px;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
  cursor: pointer;
  transition: color var(--t-fast);
  white-space: nowrap;
  line-height: 1;
  /* Explicit no-underline */
  text-decoration: none;
}


.ag-nav-link:focus { color: var(--text-secondary); }

.ag-nav-link.is-active,
.ag-nav-link[aria-expanded="true"] {
  color: var(--text-secondary);
}

/* Per-collection asset count badge */
.ag-nav-count {
  margin-left: 4px;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0em;
  color: var(--text-muted);
}

.ag-nav-link .ag-ionic,
.ag-drawer-text-btn .ag-ionic {
  display: inline-block;
  margin: 0 0 -3px 5px;
}

/* "More ↓" button */
.ag-nav-link .ag-more-arrow {
  display: inline-block;
  transition: transform var(--t-fast);
  margin: 0 0 -3px 2px;
  font-style: normal;
}

.ag-nav-link[aria-expanded="true"] .ag-more-arrow {
  transform: rotate(180deg);
}


/* ── Right Controls ───────────────────────────────────────────────────────── */
.ag-header-controls {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-shrink: 0;
  margin-left: auto;
}

/* Gallery count — used in the header right controls - disabled for now */
.ag-header-count {
  display: none;
}
.gallery-count {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-narrow);
  white-space: nowrap;
}
.gallery-count strong { color: var(--text-primary); }


/* ── Search ── */
.ag-search-wrap {
  display: flex;
  align-items: center;
  position: relative;
}

.ag-search-toggle {
  background: none;
  border: none;
  color: var(--text-primary);
  cursor: pointer;
  padding: 0;
  font-size: 18px;
  display: flex;
  align-items: center;
  transition: color var(--t-fast);
}



.ag-search-field {
  position: absolute;
  right: 25px;  /* Sit beside the toggle icon */
  width: 0;
  opacity: 0;
  background: var(--bg);
  border: none;
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 13px;
  padding: 6px 8px;
  outline: none;
  pointer-events: none;
  transition: width var(--t-base), opacity var(--t-base), border-color var(--t-base);
  white-space: nowrap;
}

.ag-search-wrap.is-open .ag-search-field {
  width: 200px;
  opacity: 1;
  border-color: var(--border);
  border: none;
  pointer-events: all;
}

.ag-search-field::placeholder { color: var(--text-muted); }

.ag-search-field::-webkit-search-cancel-button {
  -webkit-appearance: none;
  background-image: url('assets/svg/close-outline.svg');
  background-size: cover;
  height: 15px;
  width: 15px;
  cursor: pointer;
}

/* ── Dark/Light Mode Toggle ── */
.ag-theme-toggle {
  background: none;
  border: none;
  color: var(--text-primary);
  cursor: pointer;
  padding: 0;
  font-size: 18px;
  display: flex;
  align-items: center;
  transition: color var(--t-fast);
}



/* Show moon in light mode, sun in dark mode */
.ag-icon-sun  { display: none; }
.ag-icon-moon { display: block; }

[data-theme="dark"] .ag-icon-sun  { display: block; }
[data-theme="dark"] .ag-icon-moon { display: none; }

/* ── Mobile hamburger ── */
.ag-mobile-menu-btn {
  display: none;  /* Hidden on desktop */
  background: none;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  padding: 8px;
  transition: color var(--t-base);
}
.ag-mobile-menu-btn.is-open,
.ag-mobile-icon-btn.is-open { color: var(--text-primary); }

.ag-hamburger {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 15px;
}

.ag-hamburger span {
  display: block;
  height: 1px;
  background: currentColor;
  transition: transform var(--t-base), opacity var(--t-base);
}

.ag-mobile-menu-btn.is-open .ag-hamburger span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.ag-mobile-menu-btn.is-open .ag-hamburger span:nth-child(2) { opacity: 0; }
.ag-mobile-menu-btn.is-open .ag-hamburger span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

/* Mobile icon-only buttons (Shuffle, Most Liked, Search)
   Hidden on desktop; shown via the ≤960 px media query below. */
.ag-mobile-icon-btn {
  display: none;
  background: none;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  padding: 0;
  align-items: center;
  justify-content: center;
  transition: color var(--t-fast);
  line-height: 1;
}

.ag-mobile-icon-btn ion-icon {
  font-size: 18px;
  width: 18px;
  height: 18px;
  display: block;
}

.ag-mobile-icon-btn.is-active { color: var(--text-primary); }

.ag-drawer-sort-filter { display: none; }


/* =============================================================================
   COLLECTIONS DRAWER
   Full-width panel that expands below the header when "More" is clicked.
   Since the header is not fixed, the drawer uses position:relative flow
   and is inserted right after the header in the DOM.
   ============================================================================= */
.ag-collections-drawer {
  position: relative;
  z-index: 190;
  background: var(--bg);
  border-bottom: none;
  padding: 0 var(--margin);
  /* Hidden: collapsed vertically; visibility:hidden ensures accessibility checkers
     don't flag drawer contents as focusable. Delayed so it snaps hidden only after
     the opacity fade-out completes. */
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  transition: max-height 0.25s cubic-bezier(0.4, 0, 0.2, 1), opacity var(--t-base), padding var(--t-base), visibility 0s 220ms;
}

.ag-collections-drawer.is-open {
  max-height: none; /* was 80vh */
  opacity: 1;
  visibility: visible;
  /* Override transition: visibility snaps visible immediately (no delay) so
     the fade-in animation is visible from the start. */
  transition: max-height 0.25s cubic-bezier(0.4, 0, 0.2, 1), opacity var(--t-base), padding var(--t-base), visibility 0s;
  padding-top: 0;
  padding-bottom: 32px;
  overflow-y: auto;
}

/*
 * Collections in the drawer are rendered as large display text, wrapping like a
 * paragraph. This creates the editorial "collection catalog" feel.
 * Each collection name acts as a link/button with a hover colour change — consistent
 * with the header nav text-link style.
 */
.ag-collections-drawer-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.1vw 20px;
  align-items: baseline;
}

.ag-drawer-collection {
  background: none;
  border: none;
  font-family: var(--font-sans);
  font-size: clamp( 18px, 1.4vw, 1.5vw);  /* Large display size, fluid */
  font-weight: 600;
  letter-spacing: var(--letter-spacing-negative);
  color: var(--text-primary);
  cursor: pointer;
  padding: 4px 0;
  line-height: 1;
  transition: color var(--t-fast);
  text-align: left;
}


.ag-drawer-collection.is-active { color: var(--text-secondary); }

/* --- Wrap mode: allow collection names to break across multiple lines ---
 * Toggle on/off by adding/removing ag-collections-drawer-inner--wrap on the
 * .ag-collections-drawer-inner div in template-parts/header.php.
 * Scoped to desktop only — mobile layout is unchanged.
 */
@media (min-width: 601px) {
  .ag-collections-drawer-inner--wrap .ag-drawer-collection {
    max-width: 14em;     /* forces wrap; tune 13em–15em to taste */
    line-height: 1.2;    /* comfortable leading between wrapped lines */
  }

  .ag-collections-drawer-inner--wrap .ag-nav-count {
    white-space: nowrap; /* keeps count badge glued to the last word */
  }
}

/* Page links section inside the collections drawer (visible on mobile) */
.ag-drawer-pages {
  display: none;
}

.ag-drawer-close {
  background: none;
  border: none;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
  color: var(--text-muted);
  cursor: pointer;
  margin-top: 24px;
  padding: 0;
  display: block;
  transition: color var(--t-fast);
}

.ag-drawer-close .ag-drawer-close-icon {
  display: inline-block;
  margin: 0 0 -2px 0;
}


/* =============================================================================
   COLOURS DRAWER
   Same animation pattern as .ag-collections-drawer.
   Contains three horizontal sections: Colour · Tone · Sort.
   ============================================================================= */
.ag-colours-drawer {
  position: relative;
  z-index: 190;
  background: var(--bg);
  padding: 0 var(--margin);
  margin-top: -3px;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  transition: max-height 0.25s cubic-bezier(0.4, 0, 0.2, 1), opacity var(--t-base), padding var(--t-base), visibility 0s 220ms;
}

.ag-colours-drawer.is-open {
  max-height: none;
  opacity: 1;
  visibility: visible;
  transition: max-height 0.25s cubic-bezier(0.4, 0, 0.2, 1), opacity var(--t-base), padding var(--t-base), visibility 0s;
  padding-top: 3px;
  padding-bottom: 20px;
  overflow-y: auto;
}

.ag-colours-drawer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px 0;
}

/* Vertical divider between sections */
.ag-colour-section-divider {
  display: block;
  width: 1px;
  align-self: stretch;
  background: var(--border);
  margin: 0 30px;
  flex-shrink: 0;
}

.ag-colour-section {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.ag-colour-section-label {
  background: none;
  border: none;
  font-family: var(--font-sans);
  font-size: clamp( 18px, 1.4vw, 1.5vw);  /* Large display size, fluid */
  font-weight: 600;
  letter-spacing: var(--letter-spacing-negative);
  color: var(--text-primary);
  line-height: 1;
  transition: color var(--t-fast);
  text-align: left;
  margin-right: 4px;
  white-space: nowrap;
}

/* Colour filter chip — pill button */
.ag-colour-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--text-primary);
  border: none;
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-medium);
  color: var(--bg);
  padding: 5px 10px 5px 10px;
  cursor: pointer;
  transition: color var(--t-fast), border-color var(--t-fast), background var(--t-fast);
  white-space: nowrap;
}

.ag-colour-chip:hover {
  color: var(--bg);
  background: var(--text-secondary);
}

.ag-colour-chip.is-active {
  color: var(--bg);
  background: var(--text-secondary);
}

/* Colour dot inside a chip (shows a representative swatch) */
.ag-chip-dot {
  display: inline-block;
  width: 20px;
  height: 20px;
  border-radius: var(--radius-pill);
  flex-shrink: 0;
}
.ag-chip-dot:hover {

}

/* Swatch dot colours — driven by the chip's data-filter-value (see --swatch-* in :root) */
.ag-colour-chip[data-filter-value="reds"]    .ag-chip-dot { background: var(--swatch-reds); }
.ag-colour-chip[data-filter-value="oranges"] .ag-chip-dot { background: var(--swatch-oranges); }
.ag-colour-chip[data-filter-value="yellows"] .ag-chip-dot { background: var(--swatch-yellows); }
.ag-colour-chip[data-filter-value="greens"]  .ag-chip-dot { background: var(--swatch-greens); }
.ag-colour-chip[data-filter-value="teals"]   .ag-chip-dot { background: var(--swatch-teals); }
.ag-colour-chip[data-filter-value="blues"]   .ag-chip-dot { background: var(--swatch-blues); }
.ag-colour-chip[data-filter-value="purples"] .ag-chip-dot { background: var(--swatch-purples); }
.ag-colour-chip[data-filter-value="pinks"]   .ag-chip-dot { background: var(--swatch-pinks); }

/* Mono dot: grey gradient to represent achromatic */
.ag-chip-dot-mono {
  background: linear-gradient(135deg, #888 0%, #ccc 100%);
}

/* Swatch-only chip: dot is the sole visual element; use symmetric padding */
.ag-colour-chip--swatch {
  padding: 0;
  gap: 0;
  background: none;
  transition: transform var(--t-fast), box-shadow var(--t-fast);
}
.ag-colour-chip--swatch:hover,
.ag-colour-chip--swatch.is-active {
  transform: scale(.85);
  box-shadow: 0 0 0 3px var(--text-secondary);
}

/* =============================================================================
   PALETTE SWATCHES — single asset page info bar
   ============================================================================= */

/* Container */
.lb-swatches {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
}

/* Individual swatch circle */
.lb-swatch {
  display: inline-block;
  width: 15px;
  height: 15px;
  border-radius: var(--radius-pill);
  /* border: 1px solid rgba(255,255,255,.18); */
  cursor: pointer;
  flex-shrink: 0;
  transition: transform var(--t-fast), box-shadow var(--t-fast);
}

.lb-swatch:hover {
  transform: scale(.85);
  box-shadow: 0 0 0 2px var(--text-secondary);
}

.lb-swatch.is-copied {
  transform: scale(1);
  box-shadow: 0 0 0 2px var(--text-secondary);
}

/* Clipboard copy toast — appears inline to the right of the swatch row */
.lb-swatch-toast {
  font-size: 11px;
  font-family: var(--font-mono);
  color: var(--text-secondary);
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
}

.lb-swatch-toast.is-visible {
  animation: swatch-toast-fade 1.5s ease forwards;
}

@keyframes swatch-toast-fade {
  0%   { opacity: 0; }
  12%  { opacity: 1; }
  72%  { opacity: 1; }
  100% { opacity: 0; }
}

/* =============================================================================
   TAG BAR  — scrollable row of tag filter buttons below the header
   ============================================================================= */
.ag-tag-bar {
  /* Scrolls with content — not fixed */
  position: relative;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  display: none; /* Temporarily hidden — remove this line to re-enable the tag bar */
  align-items: center;
  padding: 0 var(--margin);
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: none; /* Keep tag-bar internal scrollbar hidden (it's decorative) */
  height: 40px;
  transition: background var(--t-base), border-color var(--t-base);
}

.ag-tag-bar::-webkit-scrollbar { display: none; }

/* Tag filter buttons — text style matching the header nav */
.filter-btn {
  background: none;
  border: none;
  padding: 4px 8px;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 400;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--t-fast);
  line-height: 1;
  flex-shrink: 0;
}


.filter-btn.is-active { color: var(--text-primary); font-weight: 600; }


/* =============================================================================
   GALLERY CONTAINER
   ============================================================================= */
.gallery-container {
  padding-top: 0;
  padding-bottom: 0;
  padding-left: var(--margin);
  padding-right: var(--margin);
  max-width: var(--container-max);
  margin: 0 auto;
}

/* Load More */
.ag-load-more-wrap { text-align: center; }

.ag-load-more-btn {
  background: var(--text-secondary);
  border: none;
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
  padding: 10px 25px; margin-top: 40px;
  cursor: pointer;
  transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast);
}



.ag-end-count {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10px;
  /* letter-spacing: var(--letter-spacing-narrow); */
  text-align: center;
  margin: 40px 0 0 0;
  padding: 0;
}


/* =============================================================================
   GRID LAYOUTS
   ─────────────────────────────────────────────────────────────────────────────
   The gallery supports multiple layouts, chosen in Assets → Options and applied
   as a `layout-{slug}` class on #ag-grid (see archive-ag_asset.php). Shared grid
   and card-shape rules come first, then one self-contained block per layout.

   To add a layout: register it in ag_get_option_fields() (inc/admin-options.php)
   and add a matching block below. Keep each block's rules together, and scope
   every rule — including responsive overrides — to its `.layout-*` class so
   layouts can never leak into one another.

   Cards must remain DIRECT CHILDREN of #ag-grid in every layout: the lightbox
   builds its navigation order from that DOM order.
   ============================================================================= */

/* ── Shared: base grid ── */
.ag-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gap);
}


/* =============================================================================
   Layout: EDITORIAL
   ─────────────────────────────────────────────────────────────────────────────
   Alternates one full-width hero row with multi-column rows, and crops every
   card to a uniform 16:9 — built for wide, landscape assets.

   The pattern per 5 cards (one cycle):
     Card 1 → full width  (1 column)
     Card 2 → col A  ┐ row of 2
     Card 3 → col B  ┘
     Card 4 → col A  ┐ row of 2
     Card 5 → col B  ┘
   Implemented by targeting :nth-child positions relative to the 5-card cycle.
   Featured cards always break out to full width regardless of position.

   Column count is --ag-editorial-cols, which drops to 1 below the tablet
   breakpoint (override at the end of this block).
   ============================================================================= */
.ag-grid.layout-editorial {
  --ag-editorial-cols: 2;
  grid-template-columns: repeat(var(--ag-editorial-cols), 1fr);
}

/* Uniform 16:9 crop — this layout's defining shape. Cards carry no aspect
   ratio of their own, so any layout that wants natural heights simply
   doesn't set one. */
.ag-grid.layout-editorial .asset-card {
  aspect-ratio: 16/9;
}

/* Full-width "hero" rows at positions 1, 6, 11… (every 5th starting at 1).
   Cycle length = 1 hero + (2 cols × 2 rows) = 5. */
.ag-grid.layout-editorial .asset-card:nth-child(5n + 1):not(.card-is-featured) {
  grid-column: 1 / -1;
}

/* Featured assets always span the full width here */
.ag-grid.layout-editorial .card-is-featured {
  grid-column: 1 / -1;
}

/* Below the tablet breakpoint the grid becomes a single full-width column,
   which makes the hero rule above a no-op (every card already spans it). */
@media (max-width: 1150px) {
  .ag-grid.layout-editorial { --ag-editorial-cols: 1; }
}


/* =============================================================================
   Layout: MASONRY
   ─────────────────────────────────────────────────────────────────────────────
   Fixed-width columns, natural card heights, nothing cropped — built for
   portrait assets such as magazine covers or book jackets.

   Cards are absolutely positioned by layoutGrid() in assets/js/gallery.js.
   CSS owns the column count; JS reads the resolved --ag-cols off the grid and
   sets each card's left/top/width, then sets the grid's height. Card height
   comes from `aspect-ratio: var(--ratio)`, published per card by card.php from
   the image's real dimensions — so cards reserve correct space before their
   image loads, and JS never has to measure the DOM.

   JS sets left/top (not transform) because transform is already spoken for by
   the cardIn animation and the :hover lift.

   --ag-masonry-cols is set inline on the grid from the Options page value;
   the responsive steps below take over on smaller screens.
   ============================================================================= */
.ag-grid.layout-masonry {
  --ag-cols: var(--ag-masonry-cols, 4);
  display: block;          /* JS positions the children; grid would fight it */
  position: relative;
  /* Height is set by JS once cards are placed. min-height avoids a collapsed
     container (and a jumping load-more button) on the first paint. */
  min-height: 1px;
}

.ag-grid.layout-masonry .asset-card {
  position: absolute;
  top: 0;
  left: 0;
  /* Natural height from the image's own ratio — no cropping */
  aspect-ratio: var(--ratio, 3/4);
}

/* Featured items are ordinary cards here: a full-width breakout would tear a
   hole through the columns. They keep their breakout in the editorial layout. */

@media (max-width: 1150px) {
  .ag-grid.layout-masonry { --ag-cols: 2; }
}

@media (max-width: 600px) {
  .ag-grid.layout-masonry { --ag-cols: 1; }
}


/* ── NOTE ON IMAGE SHARPNESS ──────────────────────────────────────────────────
   Cards use object-fit:cover to fill their box. The <img> src is the
   'asset-card' size, with a srcset spanning thumb → card → medium → full and a
   per-layout `sizes` hint set by updateCardSizes() in gallery.js, so the
   browser picks an appropriate resolution for the column width and display
   density rather than always pulling the full-size image.

   In masonry the card box matches the image's own ratio, so `cover` has
   nothing to crop; in editorial the 16:9 box crops to fill, which is the
   intended behaviour for that layout.
   ─────────────────────────────────────────────────────────────────────────────
*/

/* =============================================================================
   ASSET CARD
   ============================================================================= */
.asset-card {
  background: var(--bg-off);
  overflow: hidden;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform var(--t-slow);
  position: relative;
  animation: cardIn 300ms both;
  /* No aspect-ratio here — each layout defines its own card shape (see the
     GRID LAYOUTS section): editorial crops to 16:9, masonry uses the image's
     own --ratio. */
}

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

.asset-card:hover {
  transform: translateY(-2px);
  z-index: 2;
}

.asset-card.is-hidden { display: none; }

/* Card image */
.card-image-wrap {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 100%;
  /* isolation: isolate establishes a stacking context so that .card-lqip's
     z-index: -1 stays within this element (behind <img>) rather than escaping
     to the parent stacking context. */
  isolation: isolate;
}

/* LQIP blur layer — sits behind the real <img> via z-index: -1 within the
   stacking context established by .card-image-wrap. inset: -15% extends the
   element beyond the container so blurred edges are clipped by overflow:hidden
   rather than visible as a faded border. */
.card-lqip {
  position: absolute;
  inset: -15%;
  z-index: -1;
  background-size: cover;
  background-position: center;
  filter: blur(20px);
  transition: filter var(--t-fast);
  transition-delay: 1s; /* delay so that the lqip image is never seen without the blur */
}
.card-image-wrap:has(img.is-loaded) .card-lqip {
  filter: none;
}

.card-image-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity var(--t-slow), transform var(--t-slow);
}

/* Fade in once the browser has decoded the image (class added by JS) */
.card-image-wrap img.is-loaded {
  opacity: 1;
}

.asset-card:hover .card-image-wrap img {
  transform: scale(1.02);
}

/* Hover overlay — no dark gradient, just a container for the collection pill */
.card-overlay {
  position: absolute;
  inset: 0;
  /* NO background gradient — images shown clean */
  background: transparent;
  opacity: 0;
  transition: opacity var(--t-base);
  display: flex;
  align-items: flex-end;
  padding: 12px;
  pointer-events: none;
  z-index: 2;
}

.asset-card:hover .card-overlay { opacity: 1; }
.asset-card:focus-within .card-overlay { opacity: 1; }

.card-overlay-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  width: 100%;
  justify-content: space-between; /* collection pills left · like pill right */
  pointer-events: all;
}

.card-overlay-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
  background: rgba(0,0,0,0.55);
  color: rgba(255,255,255,0.92);
  border: none;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  white-space: nowrap;
}

.card-overlay-pill.pill-collection {
  cursor: pointer;
  transition: background var(--t-fast);
}



/* Like pill — anchored to the bottom-right of the overlay */
.card-overlay-pill.pill-like {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
  flex-shrink: 0;
}

.card-overlay-pill.pill-like ion-icon {
  font-size: 10px;
  width: 10px;
  height: 10px;
}

.card-overlay-pill.pill-like.is-liked {
  background: var(--text-secondary);
  color: var(--bg);
}

/* Secondary Like pill only for display until hover, not interactive */
.ranked-mode-likes {
  position: absolute;
  right: 12px; bottom: 12px;
  display: inline-flex;
  align-items: center;
  gap: 4px;              /* matches .pill-like gap */
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
  color: rgba(255,255,255,0.92);
  border: none;
  white-space: nowrap;
  opacity: 0; /* hidden on default views */
  z-index: 1;
  transition: opacity var(--t-fast);
}
.ranked-mode-likes ion-icon {
  font-size: 10px;       /* matches .pill-like ion-icon */
  width: 10px;
  height: 10px;
}
.asset-card:hover .ranked-mode-likes { opacity: 0.2; } /* hide when showing the pill button */

body.ag-mode-likes .ranked-mode-likes {
  opacity: 0.7;
}


/* card-body hidden — layout is image-only */
.card-body { display: none; }


/* =============================================================================
   LIGHTBOX
   Full-viewport overlay. The image fills the frame; a slim 48 px bar sits at
   the bottom. Close + nav controls float above everything, not inside the
   animated inner so they never clip or shift.
   ============================================================================= */

/* Bar height as a variable so the nav-arrow offset stays in sync */
:root { --lb-bar-h: 48px; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  /* visibility snaps hidden after the 220ms fade-out completes */
  transition: opacity var(--t-base), visibility 0s 220ms;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.lightbox.is-open {
  opacity: 1;
  pointer-events: all;
  visibility: visible;
  /* visibility snaps visible immediately so the fade-in is visible from the start */
  transition: opacity var(--t-base), visibility 0s;
}

.lightbox-backdrop {
  position: absolute;
  inset: 0;
  background: var(--lightbox-bg);
}

/* ── Close — viewport top-right ───────────────────────────── */
.lightbox-close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 11;
  width: 26px;
  height: 26px;
  background: none;
  border: none;
  color: var(--text-primary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: color var(--t-fast);
}



.lightbox-close ion-icon {
  font-size: 26px;
  width: 26px;
  height: 26px;
  display: block;
}

/* ── Nav arrows — centred in the image area ───────────────── */
/* top = 50% of viewport minus half the bar = centre of the image area */
.lightbox-nav {
  position: absolute;
  z-index: 10;
  top: calc(50% - var(--lb-bar-h) / 2);
  transform: translateY(-50%);
  width: 52px;
  height: 70vh;
  background: none;
  border: none;
  color: var(--text-primary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  opacity: 0.1;
  transition: color var(--t-fast), opacity var(--t-fast);
}



.lightbox-nav ion-icon {
  font-size: 40px;
  width: 40px;
  height: 40px;
  display: block;
}

.lightbox-prev { left: 12px; }
.lightbox-next { right: 12px; }

/* ── Inner — fills the full overlay, flex column ─────────── */
.lightbox-inner {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  transform: scale(0.97) translateY(12px);
  transition: transform var(--t-slow);
}

.lightbox.is-open .lightbox-inner {
  transform: scale(1) translateY(0);
}

/* ── Image panel — grows to fill all space above the bar ─── */
.lightbox-image-panel {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.lb-img-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Lightbox image: invisible until loaded, then fades in.
   transition lives on .is-loaded so removing the class is instant —
   the old image disappears immediately on navigation with no flash. */
#ag-lightbox-img { opacity: 0; }
#ag-lightbox-img.is-loaded {
  opacity: 1;
  transition: opacity 250ms ease;
}

/* Spinner overlay — visible while is-loading */
#ag-lb-img-wrap.is-loading::after {
  content: '';
  position: absolute;
  width: 36px;
  height: 36px;
  border: 3px solid var(--border-hover);
  border-top-color: var(--text-secondary);
  border-radius: 50%;
  animation: lb-spin 0.75s linear infinite;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
@keyframes lb-spin { to { transform: translate(-50%, -50%) rotate(360deg); } }

.lightbox-image-panel img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}

/* ── Info bar — single line, fixed height, full width ─────── */
.lightbox-info-panel {
  flex-shrink: 0;
  height: var(--lb-bar-h);
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  padding: 0 24px 10px 24px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.lightbox-info-panel::-webkit-scrollbar { display: none; }

/* Fullscreen: hide info panel until mouse/keyboard activity */
.lightbox:fullscreen .lightbox-info-panel,
.lightbox:-webkit-full-screen .lightbox-info-panel {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-base);
}
.lightbox:fullscreen.fs-ui-visible .lightbox-info-panel,
.lightbox:-webkit-full-screen.fs-ui-visible .lightbox-info-panel {
  opacity: 1;
  pointer-events: all;
}

/* Fullscreen: hide close button + nav arrows until mouse/keyboard activity
   (same fs-ui-visible mechanism as the info panel above) */
.lightbox:fullscreen .lightbox-close,
.lightbox:-webkit-full-screen .lightbox-close,
.lightbox:fullscreen .lightbox-nav,
.lightbox:-webkit-full-screen .lightbox-nav {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-base);
}
.lightbox:fullscreen.fs-ui-visible .lightbox-close,
.lightbox:-webkit-full-screen.fs-ui-visible .lightbox-close,
.lightbox:fullscreen.fs-ui-visible .lightbox-nav,
.lightbox:-webkit-full-screen.fs-ui-visible .lightbox-nav {
  opacity: 1;
  pointer-events: all;
}

/* Title */
.lb-bar-title {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 320px;
  flex-shrink: 1;
  min-width: 0;
}
.lightbox-info-panel .lb-bar-title { display: none; } /* hiding from the lightbox for now */

/* Push everything right */
.lb-bar-spacer { flex: 1; min-width: 16px; }

/* Category */
.lb-bar-category {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Resolution */
.lb-bar-resolution {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Capture Date */
.lb-bar-capture-date {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Invisible flex line-break before buttons — only activated on mobile */
.lb-bar-break { display: none; }

/* ── Action buttons — uniform style ──────────────────────── */
.lb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 6px 10px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-medium);
  border: none;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  text-decoration: none;
  background: var(--text-primary);
  color: var(--bg);
  transition: background var(--t-fast);
  line-height: 1;
  border-radius: var(--radius-pill);
}



/* Like button — same base, fill when liked */
.ag-lb-like { display: inline-flex; align-items: center; gap: 5px; }

.ag-lb-like.is-liked {
  background: var(--text-secondary);
  color: var(--bg);
}


/* =============================================================================
   EMPTY STATE
   ============================================================================= */
.gallery-empty {
  display: none;
  text-align: center;
  padding: 80px 24px;
}

.gallery-empty.is-visible { display: block; }

.gallery-empty-icon {
  font-size: 35px;
  margin: 0 auto 16px;
}

.gallery-empty h3 {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 6px;
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-medium);
}

.gallery-empty p {
  font-size: 12px;
  color: var(--text-muted);
}


/* =============================================================================
   SITE FOOTER
   ============================================================================= */
.site-footer {
  background: var(--bg);
  border-top: none;
  padding: 50px var(--margin) 40px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
  transition: background var(--t-base), border-color var(--t-base);
}

.site-footer a { color: var(--text-secondary); transition: color var(--t-fast); }



/* =============================================================================
   BACK TO TOP
   ============================================================================= */

.ag-back-to-top {
  position: fixed;
  bottom: 8px;
  right: 5px;
  z-index: 500;
  width: 20px;
  height: 40px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-base), background var(--t-fast), color var(--t-fast);
}

.ag-back-to-top.is-visible {
  opacity: 1;
  pointer-events: auto;
}



.ag-back-to-top ion-icon {
  font-size: 15px;
  display: block;
}


/* =============================================================================
   ADMIN BAR OFFSET
   The WP admin bar is 32px tall when logged in. We only need to account for
   it on fixed/sticky elements. Since the header scrolls, nothing to offset.
   ============================================================================= */
/* No fixed elements to offset — header scrolls with content */


/* =============================================================================
   SINGLE ASSET PAGE
   ============================================================================= */
.ag-single {
  max-width: var(--container-max);
  margin: 0 auto;
  padding-bottom: 64px;
}

/* Hero image: full container width, natural aspect ratio */
.ag-single-image {
  display: block;
  width: 100%;
  height: auto;
}

/* Info bar: mirrors the lightbox info panel layout but unconstrained in height */
.ag-single-info-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px var(--margin);
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
  border-bottom: none;
  margin-bottom: 48px;
}

/* Allow title to shrink and truncate on narrow viewports */
.ag-single-info-bar .lb-bar-title { min-width: 0; }

/* Content column: inherits all typography from ag-page-content; this adds padding */
.ag-single-content { }


/* =============================================================================
   LOADING SKELETON
   ============================================================================= */
@keyframes shimmer {
  0%   { background-position: -600px 0; }
  100% { background-position:  600px 0; }
}

.skeleton {
  background: linear-gradient(90deg, var(--bg-off) 25%, var(--border) 50%, var(--bg-off) 75%);
  background-size: 600px 100%;
  animation: shimmer 1.4s infinite;
}


/* Scrollbar: system default — not overridden */


/* =============================================================================
   ACCESSIBILITY
   ============================================================================= */
/* Skip-navigation link — visible only on keyboard focus (WCAG 2.4.1) */
.ag-skip-link {
  position: absolute;
  top: -100%;
  left: 0;
  z-index: 9999;
  padding: 8px 16px;
  background: var(--text-primary);
  color: var(--bg);
  font-size: 13px;
  font-family: var(--font-sans);
  text-decoration: none;
  transition: none;
}
.ag-skip-link:focus { top: 0; }

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

:focus-visible { outline: 2px solid var(--text-secondary); outline-offset: 0; }


/* =============================================================================
   HOVER-CAPABLE DEVICES ONLY
   All :hover styles live here so touch devices (hover: none) activate elements
   on the first tap. Card hover styles are intentionally kept outside this block
   — they enable the two-tap overlay-reveal behaviour on mobile.
   ============================================================================= */

@media (hover: hover) {
  .ag-page-content a:hover { color: var(--accent); border-color: var(--accent); }
  .site-title:hover { opacity: 1; color: var(--text-secondary); }
  .ag-nav-link:hover { color: var(--text-secondary); }
  .ag-search-toggle:hover { color: var(--text-secondary); }
  .ag-theme-toggle:hover { color: var(--text-secondary); }
  .ag-mobile-icon-btn:hover { color: var(--text-secondary); }
  .ag-drawer-collection:hover { color: var(--text-secondary); }
  .ag-drawer-close:hover { color: var(--text-primary); }
  .filter-btn:hover { color: var(--text-primary); }
  .ag-load-more-btn:hover {
    border-color: var(--border-hover);
    color: var(--bg);
    background: var(--accent);
  }
  .card-overlay-pill.pill-collection:hover {
    color: var(--bg);
    background: var(--text-secondary);
  }
  .card-overlay-pill.pill-like:hover {
    background: var(--text-secondary);
    color: var(--bg);
  }
  .lightbox-close:hover { color: var(--text-secondary); }
  .lightbox-nav:hover { color: var(--text-secondary); opacity: 1; }
  .lb-btn:hover { opacity: 1; background: var(--text-secondary); color: var(--bg); }
  .site-footer a:hover { color: var(--text-primary); }
  .ag-back-to-top:hover {
    background: var(--text-secondary);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    color: var(--bg);
  }
}


/* =============================================================================
   RESPONSIVE
   ============================================================================= */

/* Small screens */

@media (max-width: 1299px) {

  .ag-collections-drawer.is-open {
    max-height: 80vh; /* impose a limit from this size down */
  }

}

/* === KEYBOARD SHORTCUTS MODAL === */

.ag-shortcuts-modal {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
}

.ag-shortcuts-modal[hidden] { display: none; }

.ag-shortcuts-inner {
  position: relative;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 24px 28px 28px;
  max-width: 420px;
  width: calc(100% - 40px);
}

.ag-shortcuts-heading {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  margin: 0 0 16px 0;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.ag-shortcuts-close {
  position: absolute;
  top: 12px;
  right: 12px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-muted);
  padding: 4px;
  display: flex;
  align-items: center;
  border-radius: 4px;
}
.ag-shortcuts-close ion-icon { font-size: 20px; }
.ag-shortcuts-close:hover { color: var(--text-secondary); }

.ag-shortcuts-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 10px 16px;
  margin: 0;
}

.ag-shortcuts-list dt {
  display: flex;
  gap: 4px;
  align-items: center;
  justify-content: flex-end;
  white-space: nowrap;
}

.ag-shortcuts-list dd {
  margin: 0;
  color: var(--text-secondary);
  font-size: 13px;
  align-self: center;
}

kbd {
  font-family: var(--font-mono);
  font-size: 10px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 2px 6px;
  color: var(--text-secondary);
  display: inline-block;
  line-height: 1.6;
}


/* Tablet */
@media (max-width: 1150px) { /* was 960 */

  /* Grid column counts are per-layout and live with their layout blocks in the
     GRID LAYOUTS section — not here. */

  /* Title */
  .ag-mobile-title { display: inline; }
  .ag-mobile-title .ag-icon-logo { width: 24px; height: 24px; margin: 0 4px -7px 0; }
  .site-title { font-size: 16px; }
  .ag-hamburger { width: 20px; gap: 6px; }
  .ag-hamburger span { height: 1px; }
  .ag-mobile-menu-btn.is-open .ag-hamburger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .ag-mobile-menu-btn.is-open .ag-hamburger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  .ag-mobile-icon-btn ion-icon { font-size: 22px; width: 22px; height: 22px; }

  /* Nav is desktop-only; hamburger now opens the collections drawer */
  .ag-nav { display: none; }

  /* Show hamburger */
  .ag-mobile-menu-btn { 
    display: flex; 
    padding-left: 0;
    padding-right: 0;
  }

  .ag-header-controls {
    gap: 18px;
  }

  /* Hide desktop-only nav buttons on mobile */
  .ag-hide-on-mobile { display: none !important; }

  /* Show mobile icon buttons */
  .ag-mobile-icon-btn { display: inline-flex; }

  .ag-collections-drawer { margin-top: 0; }

  /* ── Sort/filter section inside collections drawer ────────────────────── */
  .ag-drawer-sort-filter {
    display: block;
    padding-top: 16px;
    margin-top: 8px;
    border-top: 1px solid var(--text-secondary-alpha);
  }
  .ag-drawer-sort-options {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .ag-drawer-text-btn {
    background: none;
    border: none;
    padding: 4px 0;
    color: var(--text-secondary);
    font-family: var(--font-sans);
    font-size: 16px;
    cursor: pointer;
    text-align: left;
    transition: color var(--t-fast);
  }
  .ag-drawer-text-btn.is-active {
    color: var(--text-primary);
  }
  @media (hover: hover) {
    .ag-drawer-text-btn:hover { color: var(--text-primary); }
  }
  .ag-drawer-colours-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    color: var(--text-secondary);
    font-family: var(--font-sans);
    font-size: 16px;
    cursor: pointer;
    padding: 2px 0;
    margin-top: 4px;
  }
  .ag-drawer-colours-toggle:hover {
    color: var(--text-primary);
  }
  .ag-drawer-colours-toggle ion-icon {
    transition: transform 0.2s ease;
    font-size: 12px;
  }
  .ag-drawer-colours-toggle.is-open ion-icon {
    transform: rotate(180deg);
  }
  .ag-drawer-colours-content {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.3s ease;
  }
  .ag-drawer-colours-content.is-open {
    max-height: 300px;
  }
  .ag-drawer-colours-content .ag-colour-section {
    padding: 8px 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
  }

  /* Colours drawer: wrap sections vertically on mobile */
  .ag-colours-drawer-inner {
    flex-direction: column;
    gap: 14px;
    padding-bottom: 10px;
  }
  .ag-colour-section-divider {
    display: none; /* hide vertical dividers; sections stack vertically */
  }

  /* ── Search: slide-down full-width panel ─────────────────────────── */
  /* On mobile the search wrap becomes an absolute panel below the
     header.  The inline toggle inside it is replaced by the mobile
     icon button that sits in the controls bar.                        */
  .ag-search-wrap {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin-top: -3px;
    z-index: 150;
    background: var(--bg);
    border-bottom: none;
    padding: 0 16px 16px 16px;
    /* Hidden state */
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
    display: block;
    transition: max-height 0.25s cubic-bezier(0.4, 0, 0.2, 1),
                opacity     0.2s  ease,
                border-color 0.2s ease;
    box-shadow: 0 15px 15px rgba(0,0,0,0.10);
  }

  .ag-search-wrap.is-open {
    max-height: 80px;
    opacity: 1;
    pointer-events: auto;
  }

  /* Inline toggle is hidden; the mobile icon button is used instead */
  .ag-search-toggle { display: none; }

  /* Input fills the full panel width */
  .ag-search-field {
    position: static !important;
    width: 100%    !important;
    opacity: 1     !important;
    pointer-events: all !important;
    font-size: 16px;   /* Prevent iOS auto-zoom on focus */
    outline: none;
    padding: 16px 12px;
    height: auto;
    display: block;
    box-sizing: border-box;
    white-space: normal;
  }

  .header-stats { display: none; }

  /* Single asset page — mobile info bar stacks like the lightbox:
     related items grouped onto shared rows via real break spans, not
     every item forced onto its own row. */
  .ag-single { padding-bottom: 32px; }
  .ag-single-info-bar {
    justify-content: center;
    gap: 6px;
    padding: 10px var(--margin) 12px;
    margin-bottom: 28px;
  }
  .ag-single-info-bar .lb-bar-spacer { display: none; }
  .ag-single-info-bar .lb-bar-break  { display: block; flex: 0 0 100%; height: 0; }
}

/* Mobile */
@media (max-width: 600px) {
  :root {
    --gap: 15px;
    --margin: 15px;
    --header-h: 52px;
    --lb-bar-h: 128px; /* 4-row info panel: collection / title / category+resolution / buttons */
    /* Grid is already single-column from the 1150px breakpoint */
  }

  .site-header { padding: 0 var(--margin); gap: 12px; }
  .site-title { font-size: 15px; letter-spacing: var(--letter-spacing-narrow); }
  
  .ag-header-controls {
    gap: 12px;
  }
  
  .ag-collections-drawer {
    padding: 0 var(--margin);
  }
  .ag-collections-drawer.is-open {
    max-height: 80vh;
    overflow-y: auto;
    padding: 10px var(--margin) 20px;
  }
  .ag-collections-drawer-inner {
    padding-bottom: 40px;
    max-height: 270px;  /* leaves ~130px for pages section + close button */
    gap: 4px 16px;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* Theme-agnostic bottom fade — no hardcoded colour needed */
    -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 60px), transparent 100%);
            mask-image: linear-gradient(to bottom, black calc(100% - 60px), transparent 100%);
  }
  .ag-drawer-collection {
    font-size: 20px;  /* Large display size, fluid */
    padding: 2px 0;
    outline: 0;
  }
  
  /* Page links section inside the collections drawer (visible on mobile) */
  .ag-drawer-pages {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 15px;
    width: 100%;
    padding-top: 15px;
    margin-top: 15px;
    border-top: 1px solid var(--text-secondary-alpha);
  }
  .ag-drawer-page-link {
    font-family: var(--font-sans);
    font-size: 16px;
    color: var(--text-secondary);
    text-decoration: none;
    transition: color var(--t-fast);
  }
  .ag-drawer-page-link.is-active { color: var(--text-primary); }
  @media (hover: hover) {
    .ag-drawer-page-link:hover { color: var(--text-primary); }
  }
  
  .ag-colour-section-label { width: 100%; } /* force colour chips to next row */
  
  .ag-drawer-close { margin-top: 12px; }

  .lightbox-close  { top: 10px; right: 10px; width: 36px; height: 36px; }
  .lightbox-close ion-icon { font-size: 20px; width: 20px; height: 20px; }
  .lightbox-nav    { width: 40px; height: 40px; opacity: 0; }
  .lightbox-nav ion-icon { font-size: 28px; width: 28px; height: 28px; }
  .lightbox-prev   { left: 4px; }
  .lightbox-next   { right: 4px; }
  .lightbox-info-panel {
    height: auto;
    padding: 8px 12px 30px 12px;
    gap: 6px;
    flex-wrap: wrap;
    align-content: flex-start;
    justify-content: center;
    overflow: visible;
  }
  /* collection stays auto/fit-content — title being flex:100% wraps to row 2,
     leaving collection alone on row 1 where justify-content:center centres it */
  .lightbox-info-panel .lb-bar-title { flex: 0 0 100%; text-align: center; display: inherit; visibility: hidden; height: 0; }
  .lightbox-info-panel .lb-bar-spacer { display: none; }
  .lightbox-info-panel .lb-bar-break  { display: block; flex: 0 0 100%; height: 0; }
  .lightbox-info-panel #ag-lb-fullscreen { display: none; } /* not needed on mobile */

  .gallery-container { padding: 0 var(--margin); }
  
  .ag-grid { gap: var(--gap); }

  .ag-load-more-wrap { margin: 0 0 10px 0; }
  .ag-end-count { margin: 30px 0 10px 0; }
  
  /* Static pages */
  .ag-page {
    padding: 0 0 20px;
  }
  .ag-page-featured-image {
  }
  .ag-page-header {
    margin: 30px auto;
  }
  .ag-page-title {
    font-family: var(--font-sans);
    font-size: 2em;
    line-height: 1;
    color: var(--text-secondary);
    margin: 0;
    
    max-width: var(--content-width);
  }
  .ag-page-content {
    font-size: 14px;
    line-height: 1.5;
    color: var(--text-primary);
    max-width: var(--content-width);
  }
  
  .site-footer{ padding: 20px var(--margin) 30px; }
  .ag-back-to-top.is-visible { opacity: 0; } /* don't show on mobile */
}
