/* ============================================================
   AXIOM CATALOGUE COMPONENTS
   ------------------------------------------------------------
   The real, shared gallery/card/modal chrome, extracted verbatim
   from games/nms/catalogue/creatures.php (the gold-standard
   reference) so every catalogue built on the Dynamic Catalogue
   Engine renders identically to it by construction, not by
   separately hand-copying CSS per page -- MULTI_GAME_ARCHITECTURE.md
   Section 6a names this exact extraction as prerequisite work.

   Deliberately excluded (NMS-specific, not generic concepts):
   the filter bar (galaxy/affinity/star-type comboboxes, SSS
   toggle), badge-row/type-badge/sss-badge, modal-stats/
   modal-glyphs (creature stat blocks and portal glyphs). A future
   catalogue page that genuinely needs its own bespoke widget
   follows Section 6b's heavier per-category pattern instead of
   trying to force it in here.

   The image lightbox (zoom/pan on the modal photo) was originally
   excluded here too, on the assumption it was an NMS-only concern --
   it isn't; viewing any submitted image at full size is generic, so
   it's included below and wired into catalogue-browse.php.

   creatures.php itself is untouched and still carries its own full
   copy of this CSS (a self-contained page predating this file) --
   changing that proven, live page wasn't worth the risk just to
   deduplicate. This file is the new shared source of truth for
   every catalogue built after it.
   ============================================================ */

/* Section rhythm, matching creatures.php exactly -- was missing from the
   original extraction, which caused catalogue-browse.php's hero section
   to sit flush against the fixed header instead of clearing it, hiding
   .section-eyebrow behind the nav bar. */
section{
  position:relative;
  z-index:1;
  padding:110px 0;
  border-top:1px solid var(--line);
}
section::before{
  content:'';
  position:absolute;
  top:-1px;left:50%;
  transform:translateX(-50%) rotate(45deg);
  width:7px;height:7px;
  background:var(--void);
  border:1px solid var(--ion-dim);
}
main > section:first-of-type{
  padding-top:150px;
  border-top:none;
}
main > section:first-of-type::before{
  display:none;
}

/* Bare h2/.section-eyebrow selectors, matching creatures.php exactly --
   safe here because this file is only ever linked from catalogue pages,
   not site-wide, so there's no risk of it reshaping headings on
   unrelated pages the way linking it globally would. Keeping the exact
   same class names (not a renamed/scoped variant) means any future
   catalogue page can copy creatures.php's own markup patterns directly
   with zero translation. */
.section-head{max-width:600px;margin-bottom:40px;}
.section-head.centered{max-width:640px;margin-left:auto;margin-right:auto;text-align:center;}
.section-eyebrow{
  font-family:var(--mono);
  font-size:11.5px;
  letter-spacing:0.14em;
  text-transform:uppercase;
  color:var(--text-dimmer);
  margin-bottom:14px;
  display:block;
}
h2{
  font-family:var(--display);
  font-weight:600;
  font-size:clamp(1.7rem, 3.4vw, 2.3rem);
  letter-spacing:-0.01em;
  margin-bottom:16px;
}
h2 .accent{
  background:linear-gradient(120deg, var(--ion), var(--star));
  -webkit-background-clip:text;
  background-clip:text;
  color:transparent;
}
.section-head p{color:var(--text-dim);font-size:1.02rem;max-width:520px;}
.section-head.centered p{margin-left:auto;margin-right:auto;}
.catalogue-actions{margin-top:28px;}

/* Admin/creator-only management links -- deliberately separated from
   .catalogue-actions so the primary Submit button is always alone and
   centered, never crowded by secondary links (caught looking cramped
   and unclear on catalogue-browse.php). */
.catalogue-manage-row{
  display:flex;
  align-items:center;
  justify-content:center;
  flex-wrap:wrap;
  gap:8px 18px;
  max-width:640px;
  margin:20px auto 0;
  padding-top:18px;
  border-top:1px solid var(--line);
}
.catalogue-manage-label{
  font-family:var(--mono);
  font-size:10.5px;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--text-dimmer);
  width:100%;
  text-align:center;
}
.catalogue-manage-row a{
  color:var(--star);
  font-size:.85rem;
  text-decoration:none;
}
.catalogue-manage-row a:hover{text-decoration:underline;}

.reveal{
  opacity:0;
  transform:translateY(18px);
  transition:opacity .7s ease, transform .7s ease;
}
.reveal.in-view{opacity:1;transform:translateY(0);}

/* ============ ENTRY BADGES ============
   Generalizes creatures.php's hardcoded SSS-Class pill (.sss-badge) --
   same visual treatment, but driven by a catalogue's own configurable
   badge_rules_json instead of creature-specific tier logic. Color is
   set inline per rule since it's genuinely per-catalogue config, not a
   fixed palette. */
.badge-row{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:12px;}
.entry-badge{
  display:inline-block;
  font-family:var(--mono);
  font-size:0.72rem;
  font-weight:700;
  letter-spacing:0.06em;
  text-transform:uppercase;
  color:var(--void);
  padding:4px 10px;
  border-radius:4px;
  box-shadow:0 0 12px rgba(143,211,255,0.35);
}

/* ============ FILTER BAR ============
   Generalizes creatures.php's Galaxy/Affinity/Star-Type filter comboboxes
   into a real engine capability -- one searchable combobox per field an
   admin/creator flags filterable, auto-submitting on select. A large
   option list (Galaxy has 257) is genuinely unusable as a native select,
   so this reuses the same searchable-combobox interaction as the
   submission forms: type to filter, "All X" pinned at the top, Enter/
   click commits and auto-submits, Escape/blur reverts unsaved typing. */
/* position+z-index here, not just on .cat-filter-combobox-list --
   confirmed live (backdrop-filter disabled/re-enabled on .card as a
   direct test) that .card's own backdrop-filter:blur() promotes it
   to a compositing layer that painted above the combobox dropdown
   regardless of the dropdown's own z-index:50, since that z-index
   only ever competed within whatever shared context it was already
   in. Giving the whole filter bar its own explicit stacking context,
   comfortably below header's z-index:100, forces it above the card
   grid regardless of what individual cards do internally. */
.cat-filter-bar{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin:0 0 28px;position:relative;z-index:10;}
.cat-filter-combobox{position:relative;width:200px;}
.cat-filter-combobox-input{
  width:100%;min-height:44px;padding:10px 34px 10px 14px;background:rgba(5,7,13,0.5);
  border:1px solid var(--line);color:var(--text);border-radius:8px;
  font-family:var(--body);font-size:0.85rem;cursor:pointer;
}
.cat-filter-combobox-input:focus{outline:none;border-color:var(--ion);box-shadow:0 0 0 3px rgba(76,141,255,0.15);cursor:text;}
.cat-filter-combobox-chevron{position:absolute;top:50%;right:12px;transform:translateY(-50%);width:14px;height:14px;color:var(--text-dim);pointer-events:none;}
.cat-filter-combobox-list{
  position:absolute;z-index:var(--z-dropdown);top:calc(100% + 6px);left:0;right:0;max-height:260px;overflow-y:auto;
  margin:0;padding:6px;list-style:none;background:var(--panel-2);border:1px solid var(--line);
  border-radius:8px;box-shadow:0 16px 40px rgba(0,0,0,0.55);
}
.cat-filter-combobox-option{padding:11px 12px;min-height:44px;display:flex;align-items:center;border-radius:6px;font-size:0.85rem;color:var(--text-dim);cursor:pointer;}
.cat-filter-combobox-option:hover,.cat-filter-combobox-option.active{background:rgba(76,141,255,0.12);color:var(--text);}
.cat-filter-combobox-empty{padding:11px 12px;font-size:0.82rem;color:var(--text-dimmer);font-family:var(--mono);}
.cat-filter-clear{display:inline-flex;align-items:center;color:var(--text-dimmer);font-size:0.82rem;text-decoration:none;visibility:hidden;}
.cat-filter-clear.cat-filter-clear-active{visibility:visible;}

/* Badge-only filter toggle -- generalizes creatures.php's dedicated
   "SSS-Class Only" checkbox (its own filter control, not just the
   per-card badge pill) into config so any catalogue with a badge rule
   gets the same toggle, not just Creatures. */
.badge-toggle{
  display:flex;align-items:center;gap:9px;padding:0 16px;min-height:44px;
  border:1px solid var(--line);border-radius:8px;cursor:pointer;
  font-family:var(--mono);font-size:0.78rem;color:var(--text-dim);
  transition:all .2s ease;white-space:nowrap;
}
.badge-toggle input{accent-color:var(--star);width:16px;height:16px;cursor:pointer;flex-shrink:0;}
.badge-toggle:hover{border-color:var(--ion-dim);}
.badge-toggle.active{border-color:var(--star);background:rgba(143,211,255,0.1);color:var(--star);}

/* ============ PAGINATION ============
   Generalizes creatures.php's 24-per-page archive paging -- every
   catalogue's browse page pages instead of shipping every entry at once. */
.cat-pagination{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-top:36px;flex-wrap:wrap;}
.cat-pagination-info{font-family:var(--mono);font-size:0.8rem;color:var(--text-dimmer);text-align:center;flex:1;}

/* ============ CATALOGUE GRID ============ */
.gallery{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(280px, 1fr));
  gap:28px;
}
.card{
  position:relative;
  overflow:hidden;
  background:rgba(12,19,34,0.65);
  border:1px solid var(--line);
  border-radius:12px;
  padding:22px;
  backdrop-filter:blur(8px);
  -webkit-backdrop-filter:blur(8px);
  box-shadow:0 8px 32px rgba(0,0,0,0.45);
  transition:transform .25s ease, border-color .25s ease, box-shadow .25s ease;
  cursor:pointer;
}
/* A catalogue entry's element icon(s), enlarged and faint, skewed and
   left-shifted, deliberately oversized so it bleeds past the card's
   own top/bottom edges -- cropped clean by .card's own overflow:hidden
   above. z-index:-1 (not just DOM order) is load-bearing: .card
   already forms its own stacking context via backdrop-filter, and a
   position:absolute descendant paints ABOVE static in-flow siblings
   regardless of DOM order unless given a negative stack level -- this
   is what actually keeps it behind the real card content. Fixed
   neutral tone regardless of the viewer's active skin (a deliberate
   choice, not an oversight): this represents the Pal's own element,
   not the viewer's theme -- tying it to var(--star) would collapse
   every element to one shared hue per viewer, and most visitors have
   no skin active at all, which would mean every element rendering
   identically. Compared live against a pure off-white
   (rgba(237,242,250,0.07)) directly on the real card: the blue-grey
   cast below reads as a deliberate, integrated part of the panel's own
   dark-blue palette, where the off-white read more like a stray light
   smudge -- so this is --text-dim's own hue (#7c8aa6), not white,
   picked from a real side-by-side, not by default. */
.card-element-watermark{
  position:absolute;
  top:-14%;
  left:-70px;
  height:128%;
  z-index:-1;
  display:flex;
  align-items:center;
  gap:4px;
  transform:skewX(-12deg);
  color:rgba(124,138,166,0.13);
  pointer-events:none;
}
.card-element-watermark svg{height:100%;width:auto;flex-shrink:0;}
/* Small, crisp, functional companion to the watermark above -- same
   icon, real size, fully legible, right-aligned opposite the name/
   number so it never competes with the name for the row's left-to-
   right reading order. Uses var(--star) like every other icon on the
   card already does (card-icon-chip) -- this one IS meant to track
   the viewer's skin, unlike the watermark. */
.card-name-icons{display:flex;align-items:center;gap:4px;margin-left:auto;color:var(--star);flex-shrink:0;}
.card-name-icons svg{display:block;}
.card:hover{
  transform:translateY(-5px);
  border-color:var(--ion-dim);
  box-shadow:0 16px 40px rgba(76,141,255,0.16), 0 8px 32px rgba(0,0,0,0.45);
}
.card:focus-visible{outline:2px solid var(--ion);outline-offset:3px;}
.card-img-wrap{position:relative;margin-bottom:16px;}
.card img{
  width:100%;
  height:200px;
  object-fit:cover;
  border-radius:8px;
  border:1px solid var(--line);
  display:block;
  background:var(--panel-2);
}
.expand-hint{
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  background:rgba(5,7,13,0.55);
  backdrop-filter:blur(2px);
  color:var(--star);
  font-family:var(--mono);
  font-size:0.78rem;
  letter-spacing:0.08em;
  text-transform:uppercase;
  border-radius:8px;
  opacity:0;
  transition:opacity .2s ease;
  pointer-events:none;
}
.card:hover .expand-hint,
.card:focus-visible .expand-hint{opacity:1;}
.card h3{
  font-family:var(--display);
  font-weight:600;
  font-size:1.25rem;
  letter-spacing:-0.01em;
  color:var(--text);
  margin-bottom:0;
}
/* A catalogue's own identifying number (Paldex's Palpedia No.) sits
   directly beside the name instead of its own separate section --
   generic, only appears when axiom_catalogue_browse_number_field()
   names a field for this catalogue. */
.card-name-row{display:flex;align-items:baseline;gap:8px;margin-bottom:6px;}
.card-number{font-family:var(--mono);font-size:0.85rem;color:var(--text-dimmer);white-space:nowrap;}
.card-catalogued-by{font-size:0.85rem !important;color:var(--text-dim);margin:0 0 6px !important;font-style:normal;}
.card-catalogued-by-link{color:var(--star);font-weight:600;text-decoration:none;}
.card-catalogued-by-link:hover{text-decoration:underline;}
.card-discoverer{font-size:0.72rem !important;color:var(--text-dimmer);margin:-2px 0 10px !important;font-style:italic;line-height:1.2;}
.card-meta{
  font-family:var(--mono);
  font-size:0.78rem;
  color:var(--text-dimmer);
  margin:0 0 10px !important;
}
.card p{
  font-size:0.92rem;
  color:var(--text-dim);
  margin:6px 0;
  line-height:1.5;
}
.card-notes{
  display:-webkit-box;
  -webkit-line-clamp:3;
  -webkit-box-orient:vertical;
  overflow:hidden;
}
.base-glyphs{font-size:.74rem;color:var(--text-dimmer);font-family:var(--mono);}
.json-indicator{display:inline-flex;align-items:center;gap:4px;font-family:var(--mono);font-size:.68rem;color:var(--star);margin-top:6px;}

/* ============ CARD ICON CHIPS ============
   Generic card-face treatment for multiselect/multiselect_leveled
   fields whose options carry icon assignments -- one row per such
   field (Paldex's Element and Work Suitability today, confirmed via
   direct DB query to be the only catalogue with either field type).
   A leveled field's chip also shows its numeral level, so proficiency
   reads at a glance without opening the modal. */
.card-icon-chips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 10px;}
.card-icon-chip{
  display:inline-flex;align-items:center;gap:4px;
  padding:4px 7px;border-radius:6px;
  background:rgba(var(--ion-rgb),0.1);border:1px solid rgba(var(--ion-rgb),0.28);
  color:var(--star);
}
.card-icon-chip svg{width:15px;height:15px;flex-shrink:0;display:block;}
.card-icon-chip-level{font-family:var(--mono);font-size:0.66rem;font-style:normal;color:var(--text-dimmer);}

.empty-state{
  grid-column:1/-1;
  text-align:center;
  padding:60px 20px;
  color:var(--text-dimmer);
  font-family:var(--mono);
  font-size:0.95rem;
  border:1px dashed var(--line);
  border-radius:12px;
}
.empty-state a{color:var(--star);}
.empty-state a:hover{text-decoration:underline;}

/* ============ DETAIL MODAL ============ */
.modal-share{
  position:absolute;
  top:16px;right:62px;
  z-index:2;
  height:36px;
  display:flex;
  align-items:center;
  gap:6px;
  padding:0 12px;
  background:rgba(5,7,13,0.65);
  border:1px solid var(--line);
  border-radius:18px;
  color:var(--text);
  font-family:var(--mono);
  font-size:0.75rem;
  cursor:pointer;
  transition:all .2s ease;
}
.modal-share:hover{border-color:var(--ion);color:var(--star);background:rgba(76,141,255,0.15);}
.modal-share.copied{border-color:#1f8f4f;color:#5fe39a;background:rgba(31,143,79,0.15);}
.modal-img-wrap{width:100%;height:280px;background:var(--panel-2);position:relative;overflow:hidden;}
.modal-img-wrap img{width:100%;height:100%;object-fit:cover;display:block;border-bottom:1px solid var(--line);cursor:zoom-in;}
.modal-img-wrap img:focus-visible{outline:2px solid var(--ion);outline-offset:-2px;}
.modal-zoom-hint{
  position:absolute;
  bottom:12px;right:12px;
  font-family:var(--mono);
  font-size:0.68rem;
  color:var(--text);
  background:rgba(5,7,13,0.7);
  border:1px solid var(--line);
  padding:5px 10px;
  border-radius:6px;
  pointer-events:none;
  opacity:0;
  transition:opacity .2s ease;
}
.modal-img-wrap:hover .modal-zoom-hint{opacity:1;}
/* Tells the viewer there is more than one image behind the cover, so a
   gallery entry does not look like a single-image entry. */
.modal-gallery-count{
  position:absolute;
  top:12px;left:12px;
  padding:4px 10px;
  background:rgba(5,7,13,0.78);
  border:1px solid var(--line);
  border-radius:20px;
  font-family:var(--mono);
  font-size:0.64rem;
  letter-spacing:.04em;
  color:var(--text);
  pointer-events:none;
  z-index:2;
}
.modal-gallery-count[hidden]{display:none;}
/* Same identifying-number-beside-name treatment as .card-number, for
   the modal header -- generic, only appears when
   axiom_catalogue_browse_number_field() names a field for this
   catalogue. */
.modal-name-number{font-family:var(--mono);font-weight:400;font-size:1rem;color:var(--text-dimmer);margin-left:10px;}
/* Same crisp companion icon as .card-name-icons, mirrored into the
   modal header -- the watermark itself stays card-only. inline-flex on
   the span keeps it flowing naturally after the name/number text
   inside the <h2>, rather than needing .modal-name itself restructured
   into a flex row. */
.modal-name-icons{display:inline-flex;align-items:center;gap:4px;margin-left:10px;color:var(--star);vertical-align:middle;}
.modal-name-icons svg{display:block;}
.modal-catalogued-by{font-family:var(--mono);font-size:0.78rem;color:var(--text-dimmer);margin-bottom:22px;}
.modal-catalogued-by a{color:var(--star);font-weight:600;text-decoration:none;}
.modal-catalogued-by a:hover{text-decoration:underline;}

/* Generalizes creatures.php's hardcoded Combat/Agility/Health stat
   grid and its gold-on-qualifying-badge highlight into a real,
   reusable field-level treatment -- any select-type field on any
   catalogue can opt in via render_as='stat', and its value goes gold
   whenever it was part of a badge rule this entry actually, fully
   qualified for (see the highlightedKeys logic in catalogue-browse.php).
   Not Creatures-specific: nothing here references creature stats,
   tiers, or SSS-Class by name. */
.modal-stats{display:grid;grid-template-columns:repeat(3, 1fr);gap:10px;margin-bottom:26px;}
.modal-stat{text-align:center;padding:12px 6px;border:1px solid var(--line);border-radius:8px;background:rgba(5,7,13,0.35);}
.modal-stat .stat-label{display:block;font-family:var(--mono);font-size:0.65rem;letter-spacing:0.08em;text-transform:uppercase;color:var(--text-dimmer);margin-bottom:6px;}
.modal-stat .stat-value{display:block;font-family:var(--display);font-weight:600;font-size:1.3rem;color:var(--star);}
.modal-stat .stat-value.empty{color:var(--text-dimmer);font-size:1rem;}
.modal-stat .stat-value.gold{color:#ffd76a;text-shadow:0 0 14px rgba(255,215,106,0.55);}
@media (max-width:600px){
  .modal-stats{grid-template-columns:1fr 1fr 1fr;gap:6px;}
  .modal-stat{padding:10px 4px;}
  .modal-stat .stat-value{font-size:1.1rem;}
}

/* Modal equivalent of the card's icon chips (above), for any
   multiselect/multiselect_leveled field -- also the fix for a real
   bug: multiselect_leveled's array-of-objects value previously hit the
   plain val.join(', ') branch below and rendered as literal
   "[object Object]" text (confirmed live before this existed). A
   level-bearing item gets a 5-pip row matching the same visual
   language as the leveled picker on the submission form itself. */
.modal-chip-row{display:flex;flex-wrap:wrap;gap:8px;}
.modal-value-chip{display:inline-flex;align-items:center;gap:6px;padding:5px 10px;border-radius:8px;background:rgba(var(--ion-rgb),0.1);border:1px solid rgba(var(--ion-rgb),0.28);font-size:0.85rem;color:var(--text);}
.modal-value-chip-icon{display:flex;color:var(--star);}
.modal-value-chip-icon svg{width:16px;height:16px;}
.modal-value-chip-pips{display:flex;gap:2px;margin-left:2px;}
.chip-pip{width:6px;height:6px;border-radius:50%;background:var(--line);display:inline-block;}
.chip-pip.filled{background:var(--star);}

.modal-block{margin-bottom:22px;}
.modal-block:last-child{margin-bottom:0;}
.modal-label{
  display:block;
  font-family:var(--mono);
  font-size:0.68rem;
  letter-spacing:0.1em;
  text-transform:uppercase;
  color:var(--star);
  margin-bottom:10px;
}
.modal-block p{color:var(--text-dim);font-size:0.95rem;line-height:1.6;}

@media (max-width:600px){
  .modal-img-wrap{height:180px;}
  .modal-share{height:34px;top:12px;right:56px;padding:0;width:34px;justify-content:center;}
  .modal-share-label{display:none;}
}

@media (max-width:480px){
  .gallery{grid-template-columns:1fr;gap:20px;}
  .card{padding:18px;}
  .card img{height:180px;}
}

/* The image lightbox moved to assets/site.css and assets/site.js. It was
   never catalogue-specific -- Feed had its own lesser copy and chat needed
   one for GIFs, so it is now a single shared component. This file is loaded
   by one page; the lightbox is needed on several. */

/* FILTER COMBOBOXES ON A PHONE. .cat-filter-combobox is a hard 200px and
   .cat-filter-bar is a centred wrapping flex, so at 380px two of them cannot
   sit side by side (410 > 356 available), wrap, and then each centres itself
   independently. Measured on the live Paldex: the two boxes landed at left
   90 and left 48 while the search field below them sat at left 24 and 332
   wide -- three controls, three different widths, three different left
   edges. Full width makes all three agree.

   This block is at the END of the file on purpose. The rule it overrides is
   declared at line 169 and media queries add no specificity, so placing it
   any earlier would have made it silently dead -- which is exactly what
   happened twice elsewhere in this same session before being measured and
   caught. */
@media (max-width:600px){
  .cat-filter-bar{justify-content:flex-start;}
  .cat-filter-combobox{width:100%;}
  .cat-filter-clear{width:100%;}
}

/* THE FILTER ROW SITS OFF CENTRE, and the cause is not the comboboxes.
   .cat-filter-clear is visibility:hidden until a filter is active -- but a
   visibility:hidden element still OCCUPIES layout, so justify-content:center
   was centring a group 85px wider than anything on screen (its 75px plus the
   10px gap). The visible boxes therefore sat exactly half of that -- 42px --
   left of centre, while the search field below them centred correctly.
   Measured: bar centre 545, combobox group centre 503.

   Taking it out of flow fixes both states at once. Centring now sees only
   what is visible, and because the link is absolutely positioned it can
   appear and disappear without shifting the row -- which is the thing
   visibility:hidden was chosen for in the first place. That intent is kept;
   only the side effect goes.

   Desktop only. Below 600px the bar is justify-content:flex-start with
   full-width comboboxes, so nothing is being centred and the clear link
   keeps its own full-width row. */
@media (min-width: 601px) {
  .cat-filter-clear { position: absolute; right: 0; top: 50%; transform: translateY(-50%); }
}
