<?php
/**
 * Glossar — Übersichtsseite + Detailansicht.
 *
 *   /App/pages/glossar.php                 → Alle Begriffe als Grid
 *   /App/pages/glossar.php?term=co2        → Eintrag direkt geöffnet (für Tooltip-Links aus Sims)
 *   /App/pages/glossar.php?module=klima    → vorgefilterter Grid
 *
 * Datenquelle: /php/api/glossar.php
 * Modul-Metadaten: DB-Tabelle module_info (Admin-pflegbar)
 */
require_once __DIR__ . '/../php/config/app.php';
require_once __DIR__ . '/../php/config/db.php';

$term   = isset($_GET['term'])   ? preg_replace('/[^a-z0-9_-]/', '', strtolower($_GET['term']))   : '';
$module = isset($_GET['module']) ? preg_replace('/[^a-z0-9_-]/', '', strtolower($_GET['module'])) : '';

$bp  = BASE_PATH;
$api = BASE_URL . '/php/api/glossar.php';

// Modul-Metadaten aus DB (Icons + Titel; Farben bleiben Design-Code)
$modDb = getDB()->query("
    SELECT module_id, title, icon, sort_order
    FROM module_info
    WHERE status IN ('aktiv', 'beta')
    ORDER BY sort_order, title
")->fetchAll(PDO::FETCH_ASSOC);
$moduleMeta  = [];
$moduleOrder = [];
foreach ($modDb as $m) {
    $moduleMeta[$m['module_id']] = [
        'icon'  => $m['icon'] ?: '📘',
        'label' => $m['title'],
    ];
    $moduleOrder[] = $m['module_id'];
}
?><!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Glossar geograsim.at<?= $term ? ' — ' . htmlspecialchars($term) : '' ?></title>
<meta name="description" content="Das GeoGraSim-Glossar erklärt Fachbegriffe aus Klima, Energie, Raumplanung und Geografie kinderverständlich mit konkreten Beispielen und Vergleichsgrafiken.">
<link rel="icon" type="image/svg+xml" href="<?= $bp ?>/favicon.svg">
<link rel="icon" type="image/png" href="<?= $bp ?>/favicon-96x96.png" sizes="96x96">
<link rel="stylesheet" href="<?= $bp ?>/assets/fonts/inter.css">
<link rel="stylesheet" href="<?= $bp ?>/assets/css/design-system.css">
<style>
  /* Override body overflow — Glossar is scrollable */
  body { overflow: auto; height: auto; min-height: 100vh; background: var(--ggs-bg); }

  /* ===== Topbar (wie ueber.html, handbuch.html) ===== */
  .gl-topbar {
    background: var(--ggs-white);
    padding: .55rem 1.2rem;
    display: flex;
    align-items: center;
    gap: .8rem;
    border-bottom: 1px solid var(--ggs-border);
    position: sticky; top: 0; z-index: 50;
  }
  .gl-topbar a { text-decoration: none; }
  .gl-topbar-brand { display: flex; align-items: center; gap: .5rem; }
  .gl-topbar-brand img.gl-text { height: 40px; display: block; }
  .gl-topbar .spacer { flex: 1; }
  .gl-btn-sm {
    display: inline-flex; align-items: center; gap: .3rem;
    min-height: 40px; padding: .4rem .8rem;
    border: 1px solid var(--ggs-border);
    border-radius: var(--ggs-radius-sm); background: var(--ggs-white);
    font-size: .78rem; font-weight: 600; cursor: pointer;
    color: var(--ggs-text); font-family: inherit;
    text-decoration: none;
  }
  .gl-btn-sm.gl-btn-primary { background: var(--ggs-fjord); color: var(--ggs-white); border-color: var(--ggs-fjord); }
  @media (hover: hover) {
    .gl-btn-sm:hover { background: var(--ggs-fjord-light); color: var(--ggs-fjord-dark); border-color: var(--ggs-fjord); }
    .gl-btn-sm.gl-btn-primary:hover { background: var(--ggs-fjord-dark); }
  }

  /* ===== Hero ===== */
  .gl-hero {
    background: linear-gradient(135deg, var(--ggs-fjord-dark) 0%, var(--ggs-fjord) 100%);
    color: var(--ggs-white);
    padding: 3rem 1.5rem 3.5rem;
    text-align: center;
  }
  .gl-hero h1 { font-size: clamp(1.8rem, 4vw, 2.6rem); font-weight: 900; letter-spacing: -.03em; margin-bottom: .5rem; }
  .gl-hero p { font-size: 1.02rem; color: rgba(255,255,255,.88); max-width: 640px; margin: 0 auto 1.8rem; }
  .gl-hero-stats { display: flex; justify-content: center; gap: 2rem; flex-wrap: wrap; margin-top: 1.2rem; }
  .gl-hero-stat { text-align: center; }
  .gl-hero-stat-num { font-size: 1.8rem; font-weight: 900; display: block; }
  .gl-hero-stat-lbl { font-size: .72rem; opacity: .8; text-transform: uppercase; letter-spacing: .08em; }

  /* ===== Controls (Search + Filter) ===== */
  .gl-controls { max-width: 1100px; margin: -1.8rem auto 1.5rem; padding: 0 1.2rem; position: relative; z-index: 5; }
  .gl-search-wrap {
    background: var(--ggs-white); border-radius: var(--ggs-radius-lg);
    box-shadow: var(--ggs-shadow-lg); padding: 1rem 1.2rem;
    display: flex; align-items: center; gap: .8rem; border: 1px solid var(--ggs-border);
  }
  .gl-search-icon { font-size: 1.2rem; opacity: .55; }
  .gl-search-input {
    flex: 1; border: 0; outline: 0; font-size: 1rem; font-family: inherit;
    color: var(--ggs-text); background: transparent; padding: .4rem 0;
  }
  .gl-search-input::placeholder { color: var(--ggs-text-light); }
  .gl-search-clear {
    background: transparent; border: 0; cursor: pointer; color: var(--ggs-text-muted);
    font-size: 1.3rem; padding: 0 .4rem; display: none;
  }
  .gl-search-clear.show { display: inline-block; }

  .gl-filters { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1rem; justify-content: center; }
  .gl-chip {
    display: inline-flex; align-items: center; gap: .3rem;
    min-height: 38px; padding: .45rem 1rem;
    border-radius: var(--ggs-radius-pill);
    background: var(--ggs-white); border: 1.5px solid var(--ggs-border);
    font-size: .82rem; font-weight: 600; color: var(--ggs-text-muted);
    cursor: pointer; transition: all .2s var(--ggs-ease); font-family: inherit;
    white-space: nowrap;
  }
  .gl-chip.active { background: var(--ggs-fjord); color: var(--ggs-white); border-color: var(--ggs-fjord); }
  @media (hover: hover) {
    .gl-chip:hover { border-color: var(--ggs-fjord); color: var(--ggs-fjord); }
  }
  .gl-chip-count { font-size: .65rem; opacity: .65; font-weight: 500; }

  /* ===== Grid ===== */
  .gl-grid-wrap { max-width: 1100px; margin: 0 auto 3rem; padding: 0 1.2rem; scroll-behavior: smooth; }
  html { scroll-behavior: smooth; }
  .gl-grid-info { font-size: .8rem; color: var(--ggs-text-muted); margin-bottom: .8rem; padding: 0 .3rem; }

  /* Buchstaben-Sprungnavigation (A-Z-Leiste) */
  .gl-letter-nav {
    display: flex; flex-wrap: wrap; gap: .2rem;
    background: var(--ggs-white);
    border: 1px solid var(--ggs-border);
    border-radius: var(--ggs-radius-md);
    padding: .5rem .6rem;
    margin: .3rem 0 1rem;
    position: sticky; top: 52px; z-index: 40;
    box-shadow: var(--ggs-shadow-sm);
  }
  .gl-letter-nav a, .gl-letter-nav span {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 28px; height: 28px; padding: 0 .35rem;
    font-size: .82rem; font-weight: 700;
    border-radius: var(--ggs-radius-sm);
    text-decoration: none; user-select: none;
  }
  .gl-letter-nav a {
    color: var(--ggs-fjord-dark); background: var(--ggs-fjord-light);
    transition: all .15s var(--ggs-ease);
  }
  .gl-letter-nav a, .gl-letter-nav span {
    min-width: 36px; height: 36px;
  }
  @media (hover: hover) {
    .gl-letter-nav a:hover { background: var(--ggs-fjord); color: var(--ggs-white); }
  }
  .gl-letter-nav span { color: var(--ggs-text-light); opacity: .45; cursor: default; }

  /* Buchstabenbanner (Warning-Style: schmal, volle Breite, Buchstabe links) */
  .gl-letter-banner {
    grid-column: 1 / -1;
    background: var(--ggs-sand);
    color: var(--ggs-fjord-dark);
    border-left: 5px solid var(--ggs-sand-dark);
    border-radius: var(--ggs-radius-sm);
    padding: .5rem 1rem;
    font-size: 1.15rem; font-weight: 900;
    letter-spacing: -.01em;
    display: flex; align-items: baseline; gap: .6rem;
    scroll-margin-top: 100px;
    margin-top: .4rem;
  }
  .gl-letter-banner:first-child { margin-top: 0; }
  .gl-letter-banner-count {
    font-size: .72rem; font-weight: 600; color: var(--ggs-text-muted);
    letter-spacing: 0;
  }

  .gl-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 1rem;
  }
  .gl-card {
    background: var(--ggs-white); border: 1px solid var(--ggs-border);
    border-radius: var(--ggs-radius-md); overflow: hidden; cursor: pointer;
    transition: all .25s var(--ggs-ease); text-align: left;
    font-family: inherit; padding: 0; display: flex; flex-direction: column;
  }
  @media (hover: hover) {
    .gl-card:hover { transform: translateY(-3px); border-color: var(--ggs-fjord); box-shadow: var(--ggs-shadow-md); }
  }
  .gl-card:active { transform: scale(.98); border-color: var(--ggs-fjord); }
  .gl-card-img {
    height: 110px; background: var(--ggs-fjord-light);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden; position: relative;
  }
  .gl-card-img img, .gl-card-img svg { max-width: 100%; max-height: 100%; object-fit: contain; }
  .gl-card-img.gl-no-img {
    background: linear-gradient(135deg, var(--ggs-fjord-light), var(--ggs-moss-light));
  }
  .gl-card-img-emoji { font-size: 3rem; opacity: .45; }
  .gl-card-body { padding: .9rem 1rem 1rem; flex: 1; display: flex; flex-direction: column; }
  .gl-card-category {
    font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
    color: var(--ggs-fjord); margin-bottom: .2rem;
  }
  .gl-card-title { font-size: 1rem; font-weight: 800; color: var(--ggs-fjord-dark); margin-bottom: .3rem; line-height: 1.25; }
  .gl-card-short { font-size: .82rem; color: var(--ggs-text); line-height: 1.45; flex: 1; }
  .gl-card-modules { display: flex; gap: .25rem; margin-top: .6rem; }
  .gl-card-mod { font-size: .85rem; }

  /* Empty / loading */
  .gl-empty { text-align: center; padding: 3rem 1rem; color: var(--ggs-text-muted); }
  .gl-empty strong { display: block; font-size: 1.1rem; color: var(--ggs-text); margin-bottom: .3rem; }
  .gl-loading {
    text-align: center; padding: 3rem 1rem; color: var(--ggs-text-muted);
    font-size: .9rem;
  }

  /* ===== Detail Modal ===== */
  .gl-modal {
    position: fixed; inset: 0; background: rgba(31, 78, 90, .78); backdrop-filter: blur(6px);
    z-index: 100; display: none; align-items: flex-start; justify-content: center;
    overflow-y: auto; padding: 2rem 1rem;
  }
  .gl-modal.open { display: flex; }
  .gl-modal-card {
    background: var(--ggs-white); border-radius: var(--ggs-radius-lg);
    max-width: 780px; width: 100%; padding: 1.8rem 2rem 2rem;
    position: relative; box-shadow: 0 20px 60px rgba(0,0,0,.3);
    margin: auto;
  }
  .gl-modal-close {
    position: absolute; top: 14px; right: 14px;
    width: 34px; height: 34px; border-radius: 50%;
    background: var(--ggs-bg); border: 0; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.3rem; color: var(--ggs-text-muted);
    transition: all .2s var(--ggs-ease);
  }
  .gl-modal-close:hover { background: var(--ggs-coral-light); color: var(--ggs-coral); }

  .gl-detail-category {
    display: inline-block; font-size: .68rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .08em; color: var(--ggs-fjord);
    background: var(--ggs-fjord-light); padding: 3px 10px;
    border-radius: var(--ggs-radius-pill); margin-bottom: .4rem;
  }
  .gl-detail-title { font-size: 1.7rem; font-weight: 900; color: var(--ggs-fjord-dark); margin-bottom: .3rem; letter-spacing: -.02em; }
  .gl-detail-short { font-size: 1.02rem; color: var(--ggs-text); font-style: italic; margin-bottom: 1rem; line-height: 1.5; }
  .gl-detail-img {
    background: var(--ggs-bg);
    border-radius: var(--ggs-radius-md);
    margin: 1rem 0 1.2rem; padding: 1rem;
    text-align: center; border: 1px solid var(--ggs-border);
    cursor: zoom-in; position: relative;
    transition: border-color .2s var(--ggs-ease);
  }
  .gl-detail-img:hover { border-color: var(--ggs-fjord); }
  .gl-detail-img img, .gl-detail-img svg { max-width: 100%; height: auto; }
  .gl-detail-img::after {
    content: '⤢ Vollbild';
    position: absolute; bottom: 6px; right: 10px;
    font-size: .7rem; font-weight: 700; color: var(--ggs-text-muted);
    background: var(--ggs-white); padding: 2px 8px;
    border-radius: var(--ggs-radius-pill);
    opacity: .75; pointer-events: none;
  }

  /* Toggle Leichte Sprache */
  .gl-easy-toggle {
    display: inline-flex; background: var(--ggs-bg);
    border-radius: var(--ggs-radius-pill); padding: 3px;
    gap: 2px; margin-bottom: 1rem;
    border: 1px solid var(--ggs-border);
  }
  .gl-easy-toggle button {
    display: inline-flex; align-items: center; gap: .3rem;
    min-height: 32px; padding: .25rem .75rem;
    border: 0; background: transparent; font-family: inherit;
    font-size: .78rem; font-weight: 600; color: var(--ggs-text-muted);
    cursor: pointer; border-radius: var(--ggs-radius-pill);
    transition: all .15s var(--ggs-ease);
  }
  .gl-easy-toggle button.active {
    background: var(--ggs-fjord); color: var(--ggs-white);
    box-shadow: 0 1px 3px rgba(0,0,0,.12);
  }
  .gl-easy-toggle button:not(.active):hover { color: var(--ggs-fjord-dark); }

  /* Lightbox für Infografiken */
  .gl-lightbox {
    position: fixed; inset: 0; z-index: 200;
    background: rgba(15, 34, 48, .94);
    display: none; align-items: center; justify-content: center;
    padding: 40px 2vw 60px; cursor: zoom-out;
    animation: gl-fade-in .2s var(--ggs-ease);
    overflow: auto;
  }
  .gl-lightbox.open { display: flex; }
  .gl-lightbox-frame {
    /* KONKRETE Breite — sonst kollabiert der Flex-Item auf Padding, */
    /* wenn die SVG-intrinsische Größe 0 ist (Safari / iPad-Bug). */
    width: min(1200px, 96vw);
    background: var(--ggs-bg);
    border-radius: var(--ggs-radius-md);
    box-shadow: 0 20px 80px rgba(0,0,0,.5);
    padding: 20px;
    box-sizing: border-box;
    display: block;
  }
  .gl-lightbox-frame img {
    display: block;
    width: 100%;
    height: auto;
    max-height: calc(100vh - 140px);
  }
  .gl-lightbox-hint {
    position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%);
    color: var(--ggs-white); font-size: .8rem; opacity: .75;
    background: rgba(0,0,0,.4); padding: 6px 14px; border-radius: var(--ggs-radius-pill);
    pointer-events: none;
  }
  @keyframes gl-fade-in { from { opacity: 0 } to { opacity: 1 } }
  .gl-detail-text { font-size: .95rem; line-height: 1.7; color: var(--ggs-text); margin-bottom: 1rem; }
  .gl-detail-text p { margin-bottom: .9rem; }
  .gl-detail-text p:last-child { margin-bottom: 0; }
  .gl-inline-link {
    color: var(--ggs-fjord); text-decoration: none; font-weight: 600;
    border-bottom: 1px dashed var(--ggs-fjord);
  }
  @media (hover: hover) {
    .gl-inline-link:hover { color: var(--ggs-fjord-dark); border-bottom-style: solid; background: var(--ggs-fjord-light); }
  }
  .gl-inline-ext { color: var(--ggs-fjord); text-decoration: underline; }
  .gl-ref a {
    font-size: .72em; font-weight: 700; color: var(--ggs-coral);
    text-decoration: none; padding: 0 2px;
  }
  .gl-ref a:hover { color: var(--ggs-fjord-dark); }
  .gl-sources {
    padding-left: 1.5em; margin-bottom: 1rem;
    font-size: .82rem; line-height: 1.6; color: var(--ggs-text);
  }
  .gl-sources li { margin-bottom: .3rem; }
  .gl-sources li::marker { color: var(--ggs-coral); font-weight: 700; }
  .gl-sources a { color: var(--ggs-fjord-dark); text-decoration: none; border-bottom: 1px dotted var(--ggs-fjord); }
  .gl-sources a:hover { color: var(--ggs-fjord); border-bottom-style: solid; }
  .gl-source-date { font-size: .85em; color: var(--ggs-text-muted); }
  .gl-source-hi { background: var(--ggs-sand); transition: background .4s; border-radius: var(--ggs-radius-sm); padding: 2px 4px; }

  /* ===== Interaktive Experimente ===== */
  .gl-experiment {
    margin: 1.4rem 0;
    padding: 1rem 1.2rem;
    background: linear-gradient(180deg, var(--ggs-fjord-light), var(--ggs-white));
    border: 1px solid var(--ggs-border);
    border-radius: var(--ggs-radius-md);
  }
  .ge-wrap { display: flex; flex-direction: column; gap: .8rem; }
  .ge-head h3 { font-size: 1rem; font-weight: 800; color: var(--ggs-fjord-dark); margin-bottom: .2rem; }
  .ge-head p { font-size: .85rem; color: var(--ggs-text); line-height: 1.5; }
  .ge-track, .ge-albedo-svg { width: 100%; height: auto; background: var(--ggs-white); border-radius: var(--ggs-radius-sm); padding: .4rem; }
  .ge-controls { display: flex; gap: .5rem; flex-wrap: wrap; }
  .ge-btn {
    display: inline-flex; align-items: center; gap: .3rem;
    min-height: 40px; padding: .4rem 1rem;
    border: 1.5px solid var(--ggs-border);
    border-radius: var(--ggs-radius-sm);
    background: var(--ggs-white); color: var(--ggs-text);
    font-family: inherit; font-size: .82rem; font-weight: 600;
    cursor: pointer; text-align: left;
  }
  .ge-btn-primary { background: var(--ggs-fjord); color: var(--ggs-white); border-color: var(--ggs-fjord); }
  @media (hover: hover) {
    .ge-btn:not(.ge-btn-primary):hover { border-color: var(--ggs-fjord); color: var(--ggs-fjord); }
    .ge-btn-primary:hover { background: var(--ggs-fjord-dark); }
  }
  .ge-btn:active { transform: scale(.97); }
  .ge-legend { list-style: none; padding: 0; font-size: .82rem; line-height: 1.6; }
  .ge-legend li { display: flex; align-items: center; gap: .5rem; margin-bottom: .2rem; }
  .ge-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
  .ge-note { font-size: .75rem; color: var(--ggs-text-muted); line-height: 1.5; font-style: italic; }

  /* ppm-Raster */
  .ge-ppm-grid {
    display: grid;
    gap: 0;
    background: var(--ggs-bg);
    padding: 4px;
    border-radius: var(--ggs-radius-sm);
    border: 1px solid var(--ggs-border);
    cursor: crosshair;
  }
  .ge-ppm-grid > span {
    aspect-ratio: 1;
    background: var(--ggs-fjord-light);
  }
  .ge-ppm-grid > span.ge-ppm-special {
    background: var(--ggs-coral);
    border-radius: 50%;
    position: relative; z-index: 1;
  }
  .ge-ppm-grid > span.ge-ppm-flash { animation: ge-flash 1.8s ease-out; }
  @keyframes ge-flash {
    0%   { box-shadow: 0 0 0 0 rgba(200,92,74,.95); }
    60%  { box-shadow: 0 0 0 24px rgba(200,92,74,0); transform: scale(3); }
    100% { transform: scale(1); }
  }
  .ge-ppm-grid > span.ge-ppm-hit {
    position: relative; z-index: 10;
    animation: ge-ppm-bounce 1.1s cubic-bezier(.22, 1, .36, 1) both;
  }
  @keyframes ge-ppm-bounce {
    0%   { transform: scale(1)  translateY(0); }
    25%  { transform: scale(5)  translateY(-10px); }
    45%  { transform: scale(4)  translateY(0); }
    60%  { transform: scale(4.5) translateY(-6px); }
    80%  { transform: scale(4)  translateY(0); }
    100% { transform: scale(4)  translateY(-2px); }
  }
  .ge-ppm-msg {
    font-size: .9rem; font-weight: 700; color: var(--ggs-moss-dark);
    padding: .4rem .6rem; min-height: 22px;
    opacity: 0; transition: opacity .25s var(--ggs-ease);
  }
  .ge-ppm-msg.show { opacity: 1; }
  .ge-ppm-msg.miss { color: var(--ggs-text-muted); font-weight: 600; }

  /* Albedo */
  .ge-albedo-choice { display: flex; gap: .4rem; flex-wrap: wrap; }
  .ge-albedo-stats {
    display: flex; gap: 1.2rem; flex-wrap: wrap;
    font-size: .88rem;
    background: var(--ggs-bg); padding: .6rem .9rem;
    border-radius: var(--ggs-radius-sm);
  }
  .ge-albedo-stats strong { color: var(--ggs-fjord-dark); }

  /* Fußabdruck-Rechner */
  .ge-calc { display: flex; flex-direction: column; gap: .7rem; }
  .ge-calc-row { display: flex; flex-direction: column; gap: .3rem; }
  .ge-calc-q { font-size: .85rem; font-weight: 700; color: var(--ggs-fjord-dark); }
  .ge-calc-opts { display: flex; gap: .35rem; flex-wrap: wrap; }
  .ge-calc-opts .ge-btn { flex: 1 1 30%; font-size: .78rem; min-height: 44px; padding: .4rem .6rem; justify-content: center; text-align: center; }
  .ge-calc-result {
    background: var(--ggs-white);
    border: 1.5px solid var(--ggs-fjord);
    border-radius: var(--ggs-radius-sm);
    padding: .8rem 1rem;
    text-align: center;
  }
  .ge-calc-result > div:first-child { font-size: .82rem; color: var(--ggs-text-muted); }
  .ge-calc-total { font-size: 1.4rem; font-weight: 900; color: var(--ggs-fjord-dark); display: block; margin: .2rem 0 .5rem; }
  .ge-calc-bar {
    height: 10px; background: var(--ggs-bg); border-radius: var(--ggs-radius-pill);
    overflow: hidden; margin-bottom: .3rem;
  }
  .ge-calc-fill {
    height: 100%; background: linear-gradient(90deg, var(--ggs-moss), var(--ggs-orange), var(--ggs-coral));
    transition: width .4s var(--ggs-ease);
  }
  .ge-calc-scale { display: flex; justify-content: space-between; font-size: .65rem; color: var(--ggs-text-muted); margin-bottom: .3rem; }
  .ge-calc-label { font-size: .75rem; color: var(--ggs-text); }
  .gl-detail-unit {
    display: inline-block; font-size: .78rem; font-weight: 700; font-family: var(--ggs-font-mono);
    color: var(--ggs-fjord-dark); background: var(--ggs-fjord-light);
    padding: 4px 10px; border-radius: var(--ggs-radius-sm); margin-bottom: 1rem;
  }
  .gl-section-title {
    font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em;
    color: var(--ggs-text-muted); margin: 1.3rem 0 .6rem;
  }
  .gl-examples { list-style: none; padding: 0; }
  .gl-examples li {
    background: var(--ggs-bg); border-left: 3px solid var(--ggs-moss);
    padding: .55rem .9rem; border-radius: 0 var(--ggs-radius-sm) var(--ggs-radius-sm) 0;
    margin-bottom: .35rem; font-size: .88rem;
  }
  .gl-links, .gl-related { display: flex; flex-wrap: wrap; gap: .5rem; }
  .gl-link, .gl-related a {
    display: inline-flex; align-items: center; gap: .3rem;
    background: var(--ggs-white); border: 1.5px solid var(--ggs-border);
    border-radius: var(--ggs-radius-sm); padding: .4rem .8rem;
    font-size: .8rem; color: var(--ggs-fjord-dark); text-decoration: none; font-weight: 600;
  }
  .gl-link:hover, .gl-related a:hover { border-color: var(--ggs-fjord); background: var(--ggs-fjord-light); color: var(--ggs-fjord); }
  .gl-modules-row { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .2rem; margin-bottom: .6rem; }
  .gl-modules-row .gl-chip { cursor: default; font-size: .7rem; padding: .25rem .6rem; }

  /* ===== Footer ===== */
  .gl-footer {
    text-align: center; padding: 2rem 1rem 2.5rem;
    font-size: .72rem; color: var(--ggs-text-muted);
    border-top: 1px solid var(--ggs-border);
    background: var(--ggs-white);
  }
  .gl-footer img { height: 36px; opacity: .5; margin-bottom: .5rem; }
  .gl-footer a { color: var(--ggs-fjord); text-decoration: none; }

  /* Responsive */
  @media (max-width: 640px) {
    .gl-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: .6rem; }
    .gl-hero { padding: 2rem 1rem 2.5rem; }
    .gl-hero-stats { gap: 1.2rem; }
    .gl-modal-card { padding: 1.3rem 1.2rem 1.5rem; }
    .gl-detail-title { font-size: 1.3rem; }
  }
</style>
</head>
<body>

<div class="gl-topbar">
  <a href="<?= $bp ?>/index.html" class="gl-topbar-brand">
    <img class="gl-text" src="<?= $bp ?>/assets/img/geograsim_t.svg" alt="GeoGraSim">
  </a>
  <span class="spacer"></span>
  <a href="<?= $bp ?>/pages/mindmap.php" class="gl-btn-sm">🧠 Mindmap</a>
  <a href="<?= $bp ?>/index.html" class="gl-btn-sm">Startseite</a>
  <a href="<?= $bp ?>/handbuch.html" class="gl-btn-sm">Handbuch</a>
  <a href="<?= $bp ?>/login.html" class="gl-btn-sm gl-btn-primary">Anmelden</a>
</div>

<section class="gl-hero">
  <h1>Das GeoGraSim-Glossar</h1>
  <p>Fachbegriffe aus Klima, Energie, Raumplanung und Geografie — kinderverständlich erklärt, mit konkreten Zahlen und Vergleichen, die Größenordnungen fassbar machen.</p>
  <div class="gl-hero-stats">
    <div class="gl-hero-stat"><span class="gl-hero-stat-num" id="gl-stat-total">–</span><span class="gl-hero-stat-lbl">Begriffe</span></div>
    <div class="gl-hero-stat"><span class="gl-hero-stat-num" id="gl-stat-images">–</span><span class="gl-hero-stat-lbl">Grafiken</span></div>
    <div class="gl-hero-stat"><span class="gl-hero-stat-num">4</span><span class="gl-hero-stat-lbl">Simulationen</span></div>
  </div>
</section>

<div class="gl-controls">
  <div class="gl-search-wrap">
    <span class="gl-search-icon">🔍</span>
    <input id="gl-search" class="gl-search-input" type="search" autocomplete="off"
           placeholder="Begriff suchen — z.B. Treibhaus, ppm, Photovoltaik …">
    <button id="gl-search-clear" class="gl-search-clear" aria-label="Suche löschen">×</button>
  </div>
  <div id="gl-filters" class="gl-filters"></div>
</div>

<div class="gl-grid-wrap">
  <div id="gl-grid-info" class="gl-grid-info"></div>
  <nav id="gl-letter-nav" class="gl-letter-nav" aria-label="Sprung zu Buchstabe"></nav>
  <div id="gl-grid" class="gl-grid"></div>
  <div id="gl-loading" class="gl-loading">Glossar wird geladen …</div>
</div>

<div id="gl-modal" class="gl-modal" role="dialog" aria-modal="true" aria-labelledby="gl-detail-title">
  <div class="gl-modal-card">
    <button id="gl-modal-close" class="gl-modal-close" aria-label="Schließen">×</button>
    <div id="gl-modal-content">
      <div class="gl-loading">Lädt …</div>
    </div>
  </div>
</div>

<div id="gl-lightbox" class="gl-lightbox" role="dialog" aria-modal="true" aria-label="Grafik Vollbildansicht">
  <div class="gl-lightbox-frame">
    <img id="gl-lightbox-img" src="" alt="">
  </div>
  <div class="gl-lightbox-hint">Tippen oder Esc drücken, um zu schließen</div>
</div>

<script src="<?= $bp ?>/assets/js/glossar-experiments.js?v=<?= @filemtime(__DIR__ . '/../assets/js/glossar-experiments.js') ?: time() ?>"></script>

<footer class="gl-footer">
  <img src="<?= $bp ?>/assets/img/bildLogo.png" alt="">
  <div>GeoGraSim · <a href="<?= $bp ?>/ueber.html">Über</a> · <a href="<?= $bp ?>/handbuch.html">Handbuch</a> · <a href="<?= $bp ?>/impressum.html">Impressum</a> · <a href="<?= $bp ?>/datenschutz.html">Datenschutz</a></div>
</footer>

<script>
const API      = <?= json_encode($api) ?>;
const BP       = <?= json_encode($bp) ?>;
const INIT_TERM   = <?= json_encode($term) ?>;
const INIT_MODULE = <?= json_encode($module) ?>;

// Aus DB-Tabelle module_info (Admin-pflegbar, Source-of-Truth)
const MODULE_META  = <?= json_encode($moduleMeta, JSON_UNESCAPED_UNICODE) ?>;
const MODULE_ORDER = <?= json_encode($moduleOrder, JSON_UNESCAPED_UNICODE) ?>;
const CATEGORY_LABEL = {
  klima: 'Klima',
  einheit: 'Einheit',
  energie: 'Energie',
  stadt: 'Stadt',
  wasser: 'Wasser',
  geologie: 'Geologie',
  wirtschaft: 'Wirtschaft',
  biologie: 'Biologie'
};

let STATE = {
  all: [],
  filter: { module: '', category: '', search: '' },
  easy: localStorage.getItem('ggs-glossar-easy') === '1',
  currentKey: null
};

function esc(s) {
  return String(s ?? '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}
function fmtImg(path) {
  if (!path) return null;
  if (/^https?:/.test(path)) return path;
  return BP + '/' + path.replace(/^\//, '');
}

/**
 * Fachartikel-Rendering: nimmt Plain-Text mit Markdown-artigen Markups und
 * baut daraus sicheres HTML.
 *   [text](glossar:slug)  → klickbarer Glossar-Link (öffnet Detail-Modal)
 *   [^n]                  → Hochgestellte Quellen-Referenz
 *   **fett**              → <strong>
 *   *kursiv*              → <em>
 *   Absätze durch Leerzeilen.
 */
function renderArticle(text) {
  if (!text) return '';
  // Zuerst HTML-escapen, dann Markups einsetzen (deren Syntax benutzt ASCII-Zeichen).
  let h = esc(text);
  // Glossar-Links
  h = h.replace(/\[([^\]]+)\]\(glossar:([a-z0-9_-]+)\)/g,
    (_, label, slug) => `<a class="gl-inline-link" href="?term=${encodeURIComponent(slug)}" data-key="${esc(slug)}">${label}</a>`);
  // Externe Links (normale Markdown)
  h = h.replace(/\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g,
    (_, label, url) => `<a class="gl-inline-ext" href="${esc(url)}" target="_blank" rel="noopener">${label}</a>`);
  // Quellen-Refs [^n] → hochgestellt
  h = h.replace(/\[\^(\d+)\]/g,
    (_, n) => `<sup class="gl-ref"><a href="#gl-source-${n}" data-ref="${n}">${n}</a></sup>`);
  // Einfache Textauszeichnung
  h = h.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
  h = h.replace(/(?<!\*)\*([^*\n]+)\*(?!\*)/g, '<em>$1</em>');
  // Absätze
  const paras = h.split(/\n\s*\n/).map(p => p.trim()).filter(Boolean);
  return paras.map(p => '<p>' + p.replace(/\n/g, '<br>') + '</p>').join('');
}

/** Datum yyyy-mm-dd → Abgerufen am D.M.YYYY */
function fmtDate(d) {
  if (!d) return '';
  const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(d);
  if (!m) return d;
  return `abgerufen ${+m[3]}.${+m[2]}.${m[1]}`;
}

/** Inline-Varianten-Rendering für Beispiele (ein Satz pro Item, keine Absätze). */
function renderInline(text) {
  if (!text) return '';
  let h = esc(text);
  h = h.replace(/\[([^\]]+)\]\(glossar:([a-z0-9_-]+)\)/g,
    (_, label, slug) => `<a class="gl-inline-link" href="?term=${encodeURIComponent(slug)}" data-key="${esc(slug)}">${label}</a>`);
  h = h.replace(/\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g,
    (_, label, url) => `<a class="gl-inline-ext" href="${esc(url)}" target="_blank" rel="noopener">${label}</a>`);
  h = h.replace(/\[\^(\d+)\]/g,
    (_, n) => `<sup class="gl-ref"><a href="#gl-source-${n}" data-ref="${n}">${n}</a></sup>`);
  h = h.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
  return h;
}
function categoryLabel(key) {
  if (!key) return '';
  return CATEGORY_LABEL[key] || (key.charAt(0).toUpperCase() + key.slice(1));
}

// ============ LOAD ============
async function loadAll() {
  const loading = document.getElementById('gl-loading');
  try {
    const res = await fetch(API);
    if (!res.ok) throw new Error('HTTP ' + res.status);
    const list = await res.json();
    STATE.all = Array.isArray(list) ? list : [];
    // Statistik
    document.getElementById('gl-stat-total').textContent  = STATE.all.length;
    document.getElementById('gl-stat-images').textContent = STATE.all.filter(e => e.image_path).length;
    loading.style.display = 'none';
    renderFilters();
    render();
    // Tiefen-Link ausführen
    if (INIT_TERM) openDetail(INIT_TERM, false);
  } catch (err) {
    loading.innerHTML = '<strong style="color:var(--ggs-coral)">Glossar konnte nicht geladen werden.</strong><br>' + esc(err.message);
  }
}

// ============ FILTERS ============
function renderFilters() {
  const wrap = document.getElementById('gl-filters');
  const modules = {};
  const cats = {};
  STATE.all.forEach(e => {
    (e.modules || []).forEach(m => { modules[m] = (modules[m] || 0) + 1; });
    if (e.category) cats[e.category] = (cats[e.category] || 0) + 1;
  });

  let html = `<button class="gl-chip${!STATE.filter.module && !STATE.filter.category ? ' active' : ''}" data-type="all">
    Alle <span class="gl-chip-count">${STATE.all.length}</span>
  </button>`;

  // Module-Filter (Reihenfolge aus DB sort_order)
  MODULE_ORDER.forEach(m => {
    if (!modules[m]) return;
    const meta = MODULE_META[m] || { icon: '•', label: m };
    html += `<button class="gl-chip${STATE.filter.module === m ? ' active' : ''}" data-type="module" data-value="${m}">
      ${meta.icon} ${meta.label} <span class="gl-chip-count">${modules[m]}</span>
    </button>`;
  });

  // Kategorie-Filter (nur wenn vorhanden)
  Object.keys(cats).sort().forEach(c => {
    html += `<button class="gl-chip${STATE.filter.category === c ? ' active' : ''}" data-type="category" data-value="${c}">
      ${esc(categoryLabel(c))} <span class="gl-chip-count">${cats[c]}</span>
    </button>`;
  });

  wrap.innerHTML = html;

  wrap.querySelectorAll('.gl-chip').forEach(btn => {
    btn.addEventListener('click', () => {
      const type = btn.dataset.type, val = btn.dataset.value || '';
      if (type === 'all') {
        STATE.filter.module = '';
        STATE.filter.category = '';
      } else if (type === 'module') {
        STATE.filter.module = STATE.filter.module === val ? '' : val;
        STATE.filter.category = '';
      } else if (type === 'category') {
        STATE.filter.category = STATE.filter.category === val ? '' : val;
        STATE.filter.module = '';
      }
      renderFilters(); render();
    });
  });
}

// ============ RENDER GRID ============
const ALPHABET = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','#'];

function normFirstLetter(title) {
  const c = String(title || '').trim().charAt(0).toUpperCase();
  if (c === 'Ä') return 'A';
  if (c === 'Ö') return 'O';
  if (c === 'Ü') return 'U';
  if (c === 'ß') return 'S';
  if (!/[A-Z]/.test(c)) return '#';
  return c;
}

function renderCard(e) {
  const img = fmtImg(e.image_path);
  const imgBlock = img
    ? `<div class="gl-card-img"><img src="${esc(img)}" alt="" loading="lazy"></div>`
    : `<div class="gl-card-img gl-no-img"><span class="gl-card-img-emoji">${moduleEmoji(e.modules)}</span></div>`;
  const modEmoji = (e.modules || []).map(m => MODULE_META[m] ? MODULE_META[m].icon : '').join('');
  return `<button class="gl-card" data-key="${esc(e.key_slug)}">
    ${imgBlock}
    <div class="gl-card-body">
      ${e.category ? `<span class="gl-card-category">${esc(categoryLabel(e.category))}</span>` : ''}
      <div class="gl-card-title">${esc(e.title)}</div>
      <div class="gl-card-short">${esc(e.short || '')}</div>
      ${modEmoji ? `<div class="gl-card-modules"><span class="gl-card-mod">${modEmoji}</span></div>` : ''}
    </div>
  </button>`;
}

function render() {
  const grid = document.getElementById('gl-grid');
  const info = document.getElementById('gl-grid-info');
  const nav  = document.getElementById('gl-letter-nav');
  const s = STATE.filter.search.trim().toLowerCase();

  const filtered = STATE.all.filter(e => {
    if (STATE.filter.module && !(e.modules || []).includes(STATE.filter.module)) return false;
    if (STATE.filter.category && e.category !== STATE.filter.category) return false;
    if (s) {
      const hay = (e.title + ' ' + (e.short || '') + ' ' + (e.key_slug || '')).toLowerCase();
      if (!hay.includes(s)) return false;
    }
    return true;
  });

  if (filtered.length === 0) {
    info.innerHTML = '';
    nav.innerHTML = '';
    nav.style.display = 'none';
    grid.innerHTML = `<div class="gl-empty" style="grid-column:1/-1">
      <strong>Kein Begriff gefunden.</strong>
      ${s ? 'Versuche einen anderen Suchbegriff oder entferne den Filter.' : 'Ändere den Filter oben, um andere Kategorien zu sehen.'}
    </div>`;
    return;
  }

  info.innerHTML = `<strong>${filtered.length}</strong> Begriff${filtered.length === 1 ? '' : 'e'}${s ? ' für „' + esc(s) + '"' : ''}`;

  // Alphabetisch sortieren (Deutsch, Umlaute korrekt)
  filtered.sort((a, b) => a.title.localeCompare(b.title, 'de', { sensitivity: 'base' }));

  // Nach Anfangsbuchstaben gruppieren
  const groups = new Map();
  filtered.forEach(e => {
    const L = normFirstLetter(e.title);
    if (!groups.has(L)) groups.set(L, []);
    groups.get(L).push(e);
  });

  // Sprung-Nav: alle Buchstaben, aktive sind Links, fehlende sind graue Spans
  nav.style.display = '';
  let navHtml = '';
  ALPHABET.forEach(L => {
    if (groups.has(L)) {
      navHtml += `<a href="#gl-letter-${L === '#' ? 'hash' : L}" data-letter="${L}">${L}</a>`;
    } else {
      navHtml += `<span>${L}</span>`;
    }
  });
  nav.innerHTML = navHtml;

  // Grid: Banner + Cards pro Buchstabe
  let html = '';
  groups.forEach((entries, L) => {
    const anchor = L === '#' ? 'hash' : L;
    html += `<div class="gl-letter-banner" id="gl-letter-${anchor}">
      <span>${esc(L)}</span>
      <span class="gl-letter-banner-count">${entries.length} Begriff${entries.length === 1 ? '' : 'e'}</span>
    </div>`;
    entries.forEach(e => { html += renderCard(e); });
  });
  grid.innerHTML = html;

  grid.querySelectorAll('.gl-card').forEach(card => {
    card.addEventListener('click', () => openDetail(card.dataset.key, true));
  });
}

function moduleEmoji(modules) {
  if (!modules || !modules.length) return '📘';
  return MODULE_META[modules[0]] ? MODULE_META[modules[0]].icon : '📘';
}

// ============ DETAIL MODAL ============
async function openDetail(key, pushUrl) {
  const modal   = document.getElementById('gl-modal');
  const content = document.getElementById('gl-modal-content');
  modal.classList.add('open');
  document.body.style.overflow = 'hidden';
  content.innerHTML = '<div class="gl-loading">Lädt …</div>';
  STATE.currentKey = key;

  if (pushUrl) {
    try { history.pushState({ term: key }, '', '?term=' + encodeURIComponent(key)); } catch {}
  }

  try {
    const url = API + '?key=' + encodeURIComponent(key) + (STATE.easy ? '&easy=1' : '');
    const res = await fetch(url);
    if (!res.ok) throw new Error('Eintrag nicht gefunden.');
    const d = await res.json();
    if (d.error) throw new Error(d.error);

    // Hat dieser Eintrag überhaupt eine Leichte-Sprache-Version?
    // (Wenn kein text_easy, zeigt API automatisch Normaltext — Toggle bleibt sichtbar als Info)
    const hasEasy = STATE.easy ? d._easy === true : true;

    const img = fmtImg(d.image_path);
    let html = '';

    // Toggle: Standard / Leichte Sprache
    html += `<div class="gl-easy-toggle" role="tablist" aria-label="Sprach-Niveau">
      <button type="button" data-easy="0" class="${STATE.easy ? '' : 'active'}" role="tab" aria-selected="${!STATE.easy}">📖 Standard</button>
      <button type="button" data-easy="1" class="${STATE.easy ? 'active' : ''}" role="tab" aria-selected="${STATE.easy}">🙂 Leichte Sprache</button>
    </div>`;

    if (d.category) html += `<span class="gl-detail-category">${esc(categoryLabel(d.category))}</span>`;
    html += `<h1 id="gl-detail-title" class="gl-detail-title">${esc(d.title)}</h1>`;
    if (d.short) html += `<div class="gl-detail-short">${esc(d.short)}</div>`;

    if (d.modules && d.modules.length) {
      html += '<div class="gl-modules-row">';
      d.modules.forEach(m => {
        const meta = MODULE_META[m] || { icon: '•', label: m };
        html += `<span class="gl-chip">${meta.icon} ${meta.label}</span>`;
      });
      html += '</div>';
    }

    if (img) {
      html += `<div class="gl-detail-img" data-src="${esc(img)}" data-alt="Vergleichsgrafik ${esc(d.title)}" role="button" tabindex="0" aria-label="Grafik im Vollbild ansehen"><img src="${esc(img)}" alt="Vergleichsgrafik ${esc(d.title)}"></div>`;
    }
    if (d.text)  html += `<div class="gl-detail-text">${renderArticle(d.text)}</div>`;
    if (d.unit)  html += `<div class="gl-detail-unit">${esc(d.unit)}</div>`;

    // Interaktives Experiment, falls für diesen key_slug registriert
    if (window.GlossarExperiments && window.GlossarExperiments[d.key_slug]) {
      html += `<div class="gl-section-title">Selbst ausprobieren</div>
               <div class="gl-experiment" id="gl-experiment-root"></div>`;
    }

    if (d.examples && d.examples.length) {
      html += '<div class="gl-section-title">Zahlen zum Einordnen</div><ul class="gl-examples">';
      d.examples.forEach(ex => {
        const txt = typeof ex === 'string' ? ex : ex.text;
        const ref = typeof ex === 'object' && ex.source_ref ? ` <sup class="gl-ref"><a href="#gl-source-${ex.source_ref}" data-ref="${ex.source_ref}">${ex.source_ref}</a></sup>` : '';
        html += '<li>' + renderInline(txt) + ref + '</li>';
      });
      html += '</ul>';
    }
    if (d.sources && d.sources.length) {
      html += '<div class="gl-section-title">Quellen</div><ol class="gl-sources">';
      d.sources.forEach(s => {
        html += `<li id="gl-source-${s.ref_num}" value="${s.ref_num}">` +
          (s.url ? `<a href="${esc(s.url)}" target="_blank" rel="noopener">${esc(s.label)}</a>` : esc(s.label)) +
          (s.access_date ? ` <span class="gl-source-date">(${fmtDate(s.access_date)})</span>` : '') +
          '</li>';
      });
      html += '</ol>';
    }
    if (d.links && d.links.length) {
      html += '<div class="gl-section-title">Weiterführende Links</div><div class="gl-links">';
      d.links.forEach(l => { html += `<a class="gl-link" href="${esc(l.url)}" target="_blank" rel="noopener">${esc(l.label)} →</a>`; });
      html += '</div>';
    }
    if (d.related && d.related.length) {
      html += '<div class="gl-section-title">Verwandte Begriffe</div><div class="gl-related">';
      d.related.forEach(r => { html += `<a data-key="${esc(r.key_slug)}" href="?term=${encodeURIComponent(r.key_slug)}">${esc(r.title)}</a>`; });
      html += '</div>';
    }

    content.innerHTML = html;
    document.title = 'Glossar geograsim.at — ' + d.title;

    // Related + Inline-Links im Modal abfangen (zu anderen Glossar-Begriffen)
    content.querySelectorAll('.gl-related a, .gl-inline-link').forEach(a => {
      a.addEventListener('click', ev => {
        ev.preventDefault();
        openDetail(a.dataset.key, true);
      });
    });
    // Footnote-Klicks: smooth scroll zur Quelle
    content.querySelectorAll('.gl-ref a').forEach(a => {
      a.addEventListener('click', ev => {
        ev.preventDefault();
        const ref = a.dataset.ref;
        const t = content.querySelector('#gl-source-' + ref);
        if (t) t.scrollIntoView({ behavior: 'smooth', block: 'center' });
        if (t) { t.classList.add('gl-source-hi'); setTimeout(() => t.classList.remove('gl-source-hi'), 1500); }
      });
    });
    // Experiment instanziieren, falls Container vorhanden
    const expRoot = content.querySelector('#gl-experiment-root');
    if (expRoot && window.GlossarExperiments && window.GlossarExperiments[d.key_slug]) {
      try { window.GlossarExperiments[d.key_slug](expRoot); }
      catch (e) { expRoot.innerHTML = '<div class="gl-empty">Experiment konnte nicht geladen werden.</div>'; }
    }

    // Easy-Toggle: umschalten und neu laden
    content.querySelectorAll('.gl-easy-toggle button').forEach(btn => {
      btn.addEventListener('click', () => {
        const want = btn.dataset.easy === '1';
        if (STATE.easy === want) return;
        STATE.easy = want;
        localStorage.setItem('ggs-glossar-easy', want ? '1' : '0');
        openDetail(STATE.currentKey, false);
      });
    });
    // Infografik-Klick öffnet Lightbox — robust: nimm data-src ODER inneres <img>
    content.querySelectorAll('.gl-detail-img').forEach(el => {
      const getSrc = () => el.dataset.src || el.querySelector('img')?.getAttribute('src') || '';
      const getAlt = () => el.dataset.alt || el.querySelector('img')?.getAttribute('alt') || '';
      el.addEventListener('click', ev => { ev.stopPropagation(); openLightbox(getSrc(), getAlt()); });
      el.addEventListener('keydown', ev => {
        if (ev.key === 'Enter' || ev.key === ' ') { ev.preventDefault(); openLightbox(getSrc(), getAlt()); }
      });
    });
  } catch (err) {
    content.innerHTML = '<div class="gl-empty"><strong>Eintrag nicht verfügbar</strong>' + esc(err.message) + '</div>';
  }
}

function closeDetail(replaceUrl) {
  const modal = document.getElementById('gl-modal');
  modal.classList.remove('open');
  document.body.style.overflow = '';
  document.title = 'Glossar geograsim.at';
  STATE.currentKey = null;
  if (replaceUrl) {
    try { history.pushState({}, '', location.pathname); } catch {}
  }
}

// ============ LIGHTBOX ============
function openLightbox(src, alt) {
  if (!src) return;
  const box = document.getElementById('gl-lightbox');
  const img = document.getElementById('gl-lightbox-img');
  img.src = src;
  img.alt = alt || '';
  box.classList.add('open');
  document.body.style.overflow = 'hidden';
}
function closeLightbox() {
  const box = document.getElementById('gl-lightbox');
  box.classList.remove('open');
  document.getElementById('gl-lightbox-img').src = '';
  if (!document.getElementById('gl-modal').classList.contains('open')) {
    document.body.style.overflow = '';
  }
}
document.getElementById('gl-lightbox').addEventListener('click', closeLightbox);

// ============ EVENTS ============
document.getElementById('gl-modal-close').addEventListener('click', () => closeDetail(true));
document.getElementById('gl-modal').addEventListener('click', ev => {
  if (ev.target.id === 'gl-modal') closeDetail(true);
});
document.addEventListener('keydown', ev => {
  if (ev.key !== 'Escape') return;
  // Priorität: erst Lightbox schließen, dann Modal
  if (document.getElementById('gl-lightbox').classList.contains('open')) {
    closeLightbox();
  } else if (document.getElementById('gl-modal').classList.contains('open')) {
    closeDetail(true);
  }
});

const search = document.getElementById('gl-search');
const searchClear = document.getElementById('gl-search-clear');
search.addEventListener('input', () => {
  STATE.filter.search = search.value;
  searchClear.classList.toggle('show', !!search.value);
  render();
});
searchClear.addEventListener('click', () => {
  search.value = ''; STATE.filter.search = '';
  searchClear.classList.remove('show');
  search.focus(); render();
});

// Back-Button schließt Detail oder navigiert zurück
window.addEventListener('popstate', ev => {
  const term = new URLSearchParams(location.search).get('term');
  if (term) openDetail(term, false);
  else closeDetail(false);
});

// Initial: Modul-Filter aus URL übernehmen
if (INIT_MODULE) STATE.filter.module = INIT_MODULE;

loadAll();
</script>
</body>
</html>
