1e51ef7def
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/ - 12 code-workspace-Files - STATUS-*.md - viele M/D/R-Änderungen an bereits getrackten Files - .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
757 lines
32 KiB
PHP
757 lines
32 KiB
PHP
<?php
|
||
/**
|
||
* Lehrplan-Übersicht
|
||
* -------------------
|
||
* Gesammelte Lehrplan-Verankerungen für alle Simulationen, gruppiert nach
|
||
* didaktischem Kompetenzbereich, mit Filter für Land (AT/DE/CH/LI), Thema
|
||
* und Anker-Typ.
|
||
*
|
||
* URL: http://localhost/geograsim/App/lehrplan (Front-Controller)
|
||
* ?country=AT vorgewählter Länder-Filter (Default: AT)
|
||
* ?theme=klima vorgewählter Themen-Filter
|
||
* ?module=fluss vorgewähltes Modul
|
||
*/
|
||
|
||
require_once __DIR__ . '/../php/config/app.php';
|
||
require_once __DIR__ . '/../php/config/db.php';
|
||
require_once __DIR__ . '/../php/lib/EasyLang.php';
|
||
require_once __DIR__ . '/../php/lib/Country.php';
|
||
|
||
$db = getDB();
|
||
|
||
// Filter: Default ist das aktuelle Landes-Setting (Kaskade), per URL überschreibbar
|
||
$allowedCountries = ['AT', 'DE', 'CH', 'LI'];
|
||
if (isset($_GET['country'])) {
|
||
$qCountry = strtoupper(trim($_GET['country']));
|
||
if (!in_array($qCountry, $allowedCountries, true) && $qCountry !== 'ALL') {
|
||
$qCountry = Country::current();
|
||
}
|
||
} else {
|
||
$qCountry = Country::current();
|
||
}
|
||
|
||
$qTheme = preg_replace('/[^a-z0-9_-]/', '', strtolower($_GET['theme'] ?? ''));
|
||
$qModule = preg_replace('/[^a-z0-9_-]/', '', strtolower($_GET['module'] ?? ''));
|
||
|
||
// Wenn `?module=X` gesetzt: Metadaten des Moduls laden (fuer Banner + Titel)
|
||
$moduleFocus = null;
|
||
if ($qModule !== '') {
|
||
$stmt = $db->prepare('SELECT module_id, title, icon, card_image, status, page_url FROM module_info WHERE module_id = ?');
|
||
$stmt->execute([$qModule]);
|
||
$moduleFocus = $stmt->fetch() ?: null;
|
||
if (!$moduleFocus) $qModule = ''; // ungueltiger Slug
|
||
}
|
||
|
||
// Kompetenzen laden — optional gefiltert auf Modul-Zuordnungen
|
||
if ($qModule !== '') {
|
||
$stmt = $db->prepare('
|
||
SELECT k.id, k.key_slug, k.title, k.description, k.category, k.age_min, k.age_max, k.sort_order
|
||
FROM kompetenzen k
|
||
INNER JOIN kompetenz_modules km ON km.kompetenz_id = k.id
|
||
WHERE km.module_id = ?
|
||
GROUP BY k.id
|
||
ORDER BY k.sort_order, k.title
|
||
');
|
||
$stmt->execute([$qModule]);
|
||
$kompetenzen = $stmt->fetchAll();
|
||
} else {
|
||
$kompetenzen = $db->query('
|
||
SELECT id, key_slug, title, description, category, age_min, age_max, sort_order
|
||
FROM kompetenzen
|
||
ORDER BY sort_order, title
|
||
')->fetchAll();
|
||
}
|
||
|
||
// Module je Kompetenz — nur aktive/beta-Sims, keine geplanten oder archivierten
|
||
$modStmt = $db->prepare("
|
||
SELECT mi.module_id, mi.title, mi.icon, mi.card_image, mi.status, mi.page_url,
|
||
km.strength
|
||
FROM kompetenz_modules km
|
||
INNER JOIN module_info mi ON mi.module_id = km.module_id
|
||
WHERE km.kompetenz_id = ?
|
||
AND mi.status IN ('aktiv','beta')
|
||
ORDER BY FIELD(km.strength, 'primaer', 'sekundaer'), mi.sort_order
|
||
");
|
||
|
||
// Anker je Kompetenz
|
||
$ankerStmt = $db->prepare("
|
||
SELECT anchor_type, country, region, school_type, grade, subject,
|
||
title, reference, reference_url, quote
|
||
FROM lehrplan_anchors
|
||
WHERE kompetenz_id = ?
|
||
ORDER BY FIELD(anchor_type, 'fach', 'uebergreifendes_thema', 'anderes_fach'),
|
||
country, sort_order
|
||
");
|
||
|
||
foreach ($kompetenzen as &$k) {
|
||
$modStmt->execute([$k['id']]);
|
||
$k['modules'] = $modStmt->fetchAll();
|
||
|
||
$ankerStmt->execute([$k['id']]);
|
||
$rows = $ankerStmt->fetchAll();
|
||
$k['anchors_fach'] = array_values(array_filter($rows, fn($r) => $r['anchor_type'] === 'fach'));
|
||
$k['anchors_uebergreifend'] = array_values(array_filter($rows, fn($r) => $r['anchor_type'] === 'uebergreifendes_thema'));
|
||
$k['anchors_andere_faecher'] = array_values(array_filter($rows, fn($r) => $r['anchor_type'] === 'anderes_fach'));
|
||
$k['anchors_all'] = $rows;
|
||
}
|
||
unset($k);
|
||
|
||
// Zählungen (global) für Filter-Badges
|
||
$totalAnchors = (int) $db->query('SELECT COUNT(*) FROM lehrplan_anchors')->fetchColumn();
|
||
$countsByCountry = [];
|
||
foreach ($db->query("SELECT country, COUNT(*) AS n FROM lehrplan_anchors GROUP BY country") as $r) {
|
||
$countsByCountry[$r['country']] = (int)$r['n'];
|
||
}
|
||
$countsByType = [];
|
||
foreach ($db->query("SELECT anchor_type, COUNT(*) AS n FROM lehrplan_anchors GROUP BY anchor_type") as $r) {
|
||
$countsByType[$r['anchor_type']] = (int)$r['n'];
|
||
}
|
||
|
||
/* N.5.2 — Transparenz-Zähler: wie viele Anker werden für die aktuelle Land-Auswahl
|
||
tatsächlich sichtbar (Fach-Anker des Landes + alle übergreifenden Anker land-agnostisch) */
|
||
$factForCountryStmt = $db->prepare(
|
||
"SELECT COUNT(*) FROM lehrplan_anchors WHERE anchor_type = 'fach' AND country = ?"
|
||
);
|
||
if ($qCountry !== 'ALL') {
|
||
$factForCountryStmt->execute([$qCountry]);
|
||
$visibleFach = (int)$factForCountryStmt->fetchColumn();
|
||
} else {
|
||
$visibleFach = (int)($countsByType['fach'] ?? 0);
|
||
}
|
||
$visibleUniversal = (int)(($countsByType['uebergreifendes_thema'] ?? 0) + ($countsByType['anderes_fach'] ?? 0));
|
||
|
||
$bp = BASE_PATH;
|
||
$easyActive = EasyLang::isActive();
|
||
|
||
function esc(?string $s): string { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
|
||
|
||
$countryMeta = [
|
||
'AT' => ['flag' => '🇦🇹', 'label' => 'Österreich'],
|
||
'DE' => ['flag' => '🇩🇪', 'label' => 'Deutschland'],
|
||
'CH' => ['flag' => '🇨🇭', 'label' => 'Schweiz'],
|
||
'LI' => ['flag' => '🇱🇮', 'label' => 'Liechtenstein'],
|
||
];
|
||
|
||
$categoryMeta = [
|
||
'klima' => ['label' => 'Klima'],
|
||
'natur' => ['label' => 'Naturgefahren'],
|
||
'raum' => ['label' => 'Raum'],
|
||
'gesellschaft' => ['label' => 'Gesellschaft'],
|
||
];
|
||
?><!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||
<title><?= $moduleFocus ? 'Lehrplan-Bezug: ' . esc($moduleFocus['title']) : 'Lehrplan-Übersicht' ?> — Lehrplan geograsim.at</title>
|
||
<meta name="description" content="<?= $moduleFocus ? 'Lehrplan-Verankerung der Simulation ' . esc($moduleFocus['title']) . ' in Österreich, Deutschland, Schweiz und Liechtenstein.' : 'Alle Lehrplan-Verankerungen der GeoGraSim-Simulationen für Österreich, Deutschland, Schweiz und Liechtenstein — gruppiert nach didaktischem Kompetenzbereich.' ?>">
|
||
<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>
|
||
body { overflow: auto; height: auto; min-height: 100dvh; background: var(--ggs-bg); }
|
||
|
||
/* ===== Topbar (wie modul-detail) ===== */
|
||
.lp-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;
|
||
}
|
||
.lp-topbar a { text-decoration: none; }
|
||
.lp-topbar-brand img { height: 40px; display: block; }
|
||
.lp-topbar .spacer { flex: 1; }
|
||
.lp-btn-sm {
|
||
padding: .5rem .85rem; 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;
|
||
display: inline-flex; align-items: center; min-height: 40px;
|
||
}
|
||
.lp-btn-sm:hover { background: var(--ggs-fjord-light); color: var(--ggs-fjord-dark); border-color: var(--ggs-fjord); }
|
||
.lp-btn-sm.lp-btn-primary { background: var(--ggs-fjord); color: var(--ggs-white); border-color: var(--ggs-fjord); }
|
||
.lp-easy-pill { background: var(--ggs-moss-light); color: var(--ggs-moss-dark); border-color: var(--ggs-moss); font-weight: 700; }
|
||
|
||
/* ===== Modul-Fokus-Banner (bei ?module=X) ===== */
|
||
.lp-focus-banner {
|
||
background: var(--ggs-fjord-light); color: var(--ggs-fjord-dark);
|
||
border-bottom: 1px solid var(--ggs-border);
|
||
padding: .9rem 1.5rem;
|
||
display: flex; align-items: center; gap: 1rem;
|
||
flex-wrap: wrap;
|
||
}
|
||
.lp-focus-icon { font-size: 1.8rem; line-height: 1; }
|
||
.lp-focus-text { flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: 2px; }
|
||
.lp-focus-text strong { font-size: 1rem; font-weight: 800; }
|
||
.lp-focus-sub { font-size: .82rem; color: var(--ggs-text-muted); }
|
||
.lp-focus-action {
|
||
display: inline-flex; align-items: center; min-height: 36px;
|
||
padding: .4rem .9rem; border-radius: var(--ggs-radius-pill);
|
||
background: var(--ggs-white); color: var(--ggs-fjord-dark);
|
||
border: 1px solid var(--ggs-fjord);
|
||
font-size: .82rem; font-weight: 600; text-decoration: none;
|
||
transition: all .2s var(--ggs-ease);
|
||
}
|
||
.lp-focus-action:hover { background: var(--ggs-fjord); color: var(--ggs-white); }
|
||
|
||
/* ===== Hero ===== */
|
||
.lp-hero {
|
||
background: linear-gradient(135deg, var(--ggs-fjord-dark) 0%, var(--ggs-fjord) 100%);
|
||
color: var(--ggs-white);
|
||
padding: 2.5rem 1.5rem 3rem;
|
||
text-align: center;
|
||
}
|
||
.lp-hero h1 {
|
||
font-size: clamp(1.8rem, 4vw, 2.6rem);
|
||
font-weight: 900; letter-spacing: -.03em;
|
||
margin-bottom: .5rem;
|
||
}
|
||
.lp-hero p { font-size: 1.02rem; color: rgba(255,255,255,.88); max-width: 640px; margin: 0 auto 1.4rem; }
|
||
.lp-hero-stats { display: flex; justify-content: center; gap: 2rem; flex-wrap: wrap; margin-top: 1.2rem; }
|
||
.lp-hero-stat { text-align: center; }
|
||
.lp-hero-stat-num { font-size: 1.8rem; font-weight: 900; display: block; }
|
||
.lp-hero-stat-lbl { font-size: .72rem; opacity: .8; text-transform: uppercase; letter-spacing: .08em; }
|
||
|
||
/* ===== Transparenz-Zeile (N.5.2) ===== */
|
||
.lp-context-line {
|
||
max-width: 1100px; margin: 1rem auto .8rem; padding: .7rem 1.1rem;
|
||
background: var(--ggs-fjord-light); border-left: 4px solid var(--ggs-fjord);
|
||
border-radius: 6px; font-size: .82rem; color: var(--ggs-fjord-dark);
|
||
line-height: 1.5;
|
||
}
|
||
.lp-context-line strong { color: var(--ggs-fjord-dark); font-weight: 800; }
|
||
|
||
/* ===== Filter-Bar ===== */
|
||
.lp-filters {
|
||
max-width: 1100px; margin: -1.4rem auto 1.5rem;
|
||
padding: 1rem 1.2rem; background: var(--ggs-white);
|
||
border-radius: var(--ggs-radius-lg); box-shadow: var(--ggs-shadow-lg);
|
||
border: 1px solid var(--ggs-border);
|
||
position: relative; z-index: 5;
|
||
display: flex; flex-direction: column; gap: .9rem;
|
||
}
|
||
.lp-filter-row {
|
||
display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;
|
||
}
|
||
.lp-filter-label {
|
||
font-size: .72rem; font-weight: 800; text-transform: uppercase;
|
||
letter-spacing: .08em; color: var(--ggs-text-muted);
|
||
min-width: 60px;
|
||
}
|
||
.lp-chip {
|
||
display: inline-flex; align-items: center; gap: .3rem;
|
||
padding: .55rem 1rem; border-radius: var(--ggs-radius-pill);
|
||
background: var(--ggs-white); border: 1.5px solid var(--ggs-border);
|
||
font-size: .88rem; font-weight: 600; color: var(--ggs-text-muted);
|
||
cursor: pointer; transition: all .2s var(--ggs-ease); font-family: inherit;
|
||
min-height: 40px; min-width: 40px;
|
||
}
|
||
.lp-chip:hover { border-color: var(--ggs-fjord); color: var(--ggs-fjord); }
|
||
.lp-chip:active { transform: scale(0.96); }
|
||
.lp-chip.active { background: var(--ggs-fjord); color: var(--ggs-white); border-color: var(--ggs-fjord); }
|
||
.lp-chip-badge {
|
||
font-size: .7rem; padding: 1px 6px; border-radius: var(--ggs-radius-pill);
|
||
background: var(--ggs-bg-dark); color: var(--ggs-text-muted);
|
||
font-weight: 700;
|
||
}
|
||
.lp-chip.active .lp-chip-badge {
|
||
background: rgba(255,255,255,.22); color: var(--ggs-white);
|
||
}
|
||
|
||
/* ===== Kompetenz-Karten ===== */
|
||
.lp-wrap { max-width: 1100px; margin: 0 auto 3rem; padding: 0 1.2rem; }
|
||
.lp-results-info {
|
||
font-size: .82rem; color: var(--ggs-text-muted);
|
||
margin-bottom: 1rem;
|
||
}
|
||
.lp-kompetenz {
|
||
background: var(--ggs-white); border: 1px solid var(--ggs-border);
|
||
border-radius: var(--ggs-radius-md);
|
||
padding: 1.4rem 1.6rem;
|
||
margin-bottom: 1.2rem;
|
||
scroll-margin-top: 80px;
|
||
}
|
||
.lp-kompetenz-head {
|
||
display: flex; flex-wrap: wrap; align-items: flex-start;
|
||
gap: .8rem; margin-bottom: .5rem;
|
||
}
|
||
.lp-kompetenz-title {
|
||
font-size: 1.3rem; font-weight: 900; color: var(--ggs-fjord-dark);
|
||
letter-spacing: -.02em;
|
||
}
|
||
.lp-kompetenz-cat {
|
||
font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
|
||
background: var(--ggs-fjord-light); color: var(--ggs-fjord-dark);
|
||
padding: 3px 10px; border-radius: var(--ggs-radius-pill);
|
||
}
|
||
.lp-kompetenz-age {
|
||
font-size: .75rem; color: var(--ggs-text-muted);
|
||
background: var(--ggs-bg-dark); padding: 3px 10px;
|
||
border-radius: var(--ggs-radius-pill);
|
||
}
|
||
.lp-kompetenz-desc {
|
||
font-size: .93rem; line-height: 1.55; color: var(--ggs-text);
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
/* Modul-Cards innerhalb einer Kompetenz */
|
||
.lp-modules-label {
|
||
font-size: .72rem; font-weight: 800; text-transform: uppercase;
|
||
letter-spacing: .1em; color: var(--ggs-text-muted);
|
||
margin: .4rem 0 .5rem;
|
||
}
|
||
.lp-modules {
|
||
display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 1.2rem;
|
||
}
|
||
.lp-module-card {
|
||
display: inline-flex; align-items: center; gap: .55rem;
|
||
padding: .55rem .95rem .55rem .7rem;
|
||
background: var(--ggs-white); border: 1.5px solid var(--ggs-border);
|
||
border-radius: var(--ggs-radius-md);
|
||
text-decoration: none; color: var(--ggs-text);
|
||
transition: all .2s var(--ggs-ease);
|
||
min-height: 44px;
|
||
}
|
||
.lp-module-card:hover, .lp-module-card:active {
|
||
border-color: var(--ggs-fjord); background: var(--ggs-fjord-light);
|
||
transform: translateY(-1px);
|
||
}
|
||
.lp-module-icon { font-size: 1.3rem; line-height: 1; }
|
||
.lp-module-name { font-size: .92rem; font-weight: 700; color: var(--ggs-fjord-dark); }
|
||
.lp-module-strength {
|
||
font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
|
||
padding: 1px 6px; border-radius: var(--ggs-radius-sm);
|
||
background: var(--ggs-moss-light); color: var(--ggs-moss-dark);
|
||
}
|
||
.lp-module-strength.sekundaer { background: var(--ggs-bg-dark); color: var(--ggs-text-muted); }
|
||
.lp-module-status {
|
||
font-size: .6rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
|
||
padding: 1px 5px; border-radius: var(--ggs-radius-sm);
|
||
}
|
||
.lp-module-status.aktiv { background: var(--ggs-moss); color: var(--ggs-white); }
|
||
.lp-module-status.beta { background: var(--ggs-sand-dark); color: var(--ggs-white); }
|
||
.lp-module-status.geplant { background: var(--ggs-fjord); color: var(--ggs-white); opacity: .7; }
|
||
|
||
/* Anker — wie modul-detail */
|
||
.lp-anchor-group { margin-top: .8rem; }
|
||
.lp-anchor-group-head {
|
||
display: flex; align-items: baseline; gap: .6rem;
|
||
margin: .4rem 0 .5rem; flex-wrap: wrap;
|
||
}
|
||
.lp-anchor-group-title {
|
||
font-size: .72rem; font-weight: 800; text-transform: uppercase;
|
||
letter-spacing: .1em; color: var(--ggs-fjord-dark);
|
||
}
|
||
.lp-anchor-group-sub {
|
||
font-size: .72rem; color: var(--ggs-text-muted); font-weight: 500;
|
||
}
|
||
.lp-anchors { display: grid; gap: .55rem; }
|
||
.lp-anchor {
|
||
display: grid; grid-template-columns: 28px 1fr; gap: .6rem; align-items: start;
|
||
font-size: .9rem; padding: .6rem .8rem;
|
||
background: var(--ggs-bg); border-radius: var(--ggs-radius-sm);
|
||
border-left: 3px solid var(--ggs-fjord-light);
|
||
}
|
||
.lp-anchor-flag { font-size: 1.2rem; line-height: 1.3; text-align: center; }
|
||
.lp-anchor-meta { font-size: .75rem; color: var(--ggs-text-muted); margin-bottom: .15rem; }
|
||
.lp-anchor-title { font-weight: 700; color: var(--ggs-fjord-dark); margin-bottom: .2rem; }
|
||
.lp-anchor-quote { font-size: .88rem; color: var(--ggs-text); font-style: italic; line-height: 1.45; }
|
||
.lp-anchor-ref { font-size: .72rem; color: var(--ggs-text-muted); margin-top: .3rem; }
|
||
.lp-anchor-link {
|
||
color: var(--ggs-fjord); text-decoration: none; font-weight: 600;
|
||
border-bottom: 1px dotted var(--ggs-fjord); padding: 2px 0;
|
||
}
|
||
.lp-anchor-link:hover { color: var(--ggs-fjord-dark); border-bottom-style: solid; }
|
||
.lp-anchor--fach { border-left-color: var(--ggs-fjord); }
|
||
.lp-anchor--uebergreifendes_thema { border-left-color: var(--ggs-moss); background: var(--ggs-moss-light); }
|
||
.lp-anchor--anderes_fach { border-left-color: var(--ggs-sand-dark); background: var(--ggs-bg-dark); }
|
||
.lp-anchor--uebergreifendes_thema .lp-anchor-flag,
|
||
.lp-anchor--anderes_fach .lp-anchor-flag { opacity: .65; }
|
||
.lp-anchor.hidden { display: none; }
|
||
|
||
.lp-kompetenz-empty {
|
||
padding: 1rem 0; color: var(--ggs-text-muted); font-style: italic;
|
||
font-size: .9rem;
|
||
}
|
||
|
||
.lp-hint {
|
||
font-size: .82rem; color: var(--ggs-text-muted); font-style: italic;
|
||
margin-top: 1.5rem; max-width: 780px;
|
||
}
|
||
|
||
.lp-toc {
|
||
background: var(--ggs-white); border: 1px solid var(--ggs-border);
|
||
border-radius: var(--ggs-radius-md);
|
||
padding: 1rem 1.2rem;
|
||
margin-bottom: 1.2rem;
|
||
}
|
||
.lp-toc-title {
|
||
font-size: .72rem; font-weight: 800; text-transform: uppercase;
|
||
letter-spacing: .1em; color: var(--ggs-text-muted);
|
||
margin-bottom: .5rem;
|
||
}
|
||
.lp-toc-list { display: flex; flex-wrap: wrap; gap: .4rem; }
|
||
.lp-toc-item {
|
||
display: inline-flex; align-items: center; gap: .3rem;
|
||
padding: .35rem .75rem; border-radius: var(--ggs-radius-pill);
|
||
background: var(--ggs-fjord-light); color: var(--ggs-fjord-dark);
|
||
font-size: .82rem; font-weight: 600; text-decoration: none;
|
||
transition: background .2s var(--ggs-ease);
|
||
min-height: 32px;
|
||
}
|
||
.lp-toc-item:hover { background: var(--ggs-fjord); color: var(--ggs-white); }
|
||
.lp-toc-count { font-size: .7rem; opacity: .7; }
|
||
|
||
/* Footer */
|
||
.lp-footer {
|
||
text-align: center; padding: 2rem 1rem 2.5rem;
|
||
font-size: .78rem; color: var(--ggs-text-muted);
|
||
border-top: 1px solid var(--ggs-border);
|
||
background: var(--ggs-white);
|
||
margin-top: 2rem;
|
||
}
|
||
.lp-footer img { height: 36px; opacity: .5; margin-bottom: .5rem; }
|
||
.lp-footer a { color: var(--ggs-fjord); text-decoration: none; padding: .3rem .2rem; }
|
||
|
||
@media (max-width: 900px) {
|
||
.lp-filter-row { flex-direction: column; align-items: flex-start; gap: .3rem; }
|
||
.lp-filter-label { min-width: 0; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<?php
|
||
/* Standard-Hauptnav + Kontext-Sub-Nav (N.5.1 Vorschlag — umgesetzt 2026-05-28) */
|
||
$activeMain = 'lehrplan';
|
||
$activeSub = 'lehrplan';
|
||
$showCountryPicker = true;
|
||
include __DIR__ . '/_partials/public_topnav.php';
|
||
include __DIR__ . '/_partials/erkundungs_subnav.php';
|
||
?>
|
||
|
||
<?php if ($moduleFocus): ?>
|
||
<!-- Modul-Fokus-Banner: der Link kommt aus einer Simulation oder Modul-Detailseite -->
|
||
<div class="lp-focus-banner">
|
||
<span class="lp-focus-icon"><?= esc($moduleFocus['icon']) ?></span>
|
||
<div class="lp-focus-text">
|
||
<strong>Lehrplan-Bezug für <?= esc($moduleFocus['title']) ?></strong>
|
||
<span class="lp-focus-sub">Gefiltert auf die Kompetenzbereiche dieser Simulation.</span>
|
||
</div>
|
||
<?php if (!empty($moduleFocus['page_url'])): ?>
|
||
<a href="<?= $bp ?>/<?= esc($moduleFocus['page_url']) ?>" class="lp-focus-action">← Zurück zur Simulation</a>
|
||
<?php endif; ?>
|
||
<a href="<?= $bp ?>/pages/lehrplan.php" class="lp-focus-action">Alle Module anzeigen</a>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- HERO -->
|
||
<section class="lp-hero">
|
||
<h1><?= $moduleFocus ? 'Lehrplan-Bezug: ' . esc($moduleFocus['title']) : 'Lehrplan-Übersicht' ?></h1>
|
||
<p>
|
||
<?php if ($moduleFocus): ?>
|
||
Diese Ansicht zeigt alle Kompetenzbereiche, die die Simulation
|
||
<strong><?= esc($moduleFocus['title']) ?></strong> abdeckt — fachlich,
|
||
fächerübergreifend und mit Anknüpfungspunkten in weiteren Fächern.
|
||
<?php else: ?>
|
||
Alle GeoGraSim-Simulationen sind auf didaktische Kompetenzbereiche
|
||
abgebildet. Für jeden Bereich zeigen wir, wo er in den Lehrplänen
|
||
für Österreich, Deutschland, Schweiz und Liechtenstein verankert ist —
|
||
fachlich, fächerübergreifend und mit Anknüpfungspunkten in weiteren Fächern.
|
||
<?php endif; ?>
|
||
</p>
|
||
<div class="lp-hero-stats">
|
||
<div class="lp-hero-stat"><span class="lp-hero-stat-num"><?= count($kompetenzen) ?></span><span class="lp-hero-stat-lbl"><?= $moduleFocus ? 'Kompetenzen für dieses Modul' : 'Kompetenzbereiche' ?></span></div>
|
||
<div class="lp-hero-stat"><span class="lp-hero-stat-num"><?= $totalAnchors ?></span><span class="lp-hero-stat-lbl">Lehrplan-Anker gesamt</span></div>
|
||
<div class="lp-hero-stat"><span class="lp-hero-stat-num">4</span><span class="lp-hero-stat-lbl">Länder</span></div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- N.5.2 — Transparenz-Zeile (statt redundanter Land-Chip-Reihe; Land kommt vom Picker oben) -->
|
||
<div class="lp-context-line">
|
||
<strong>Anzeige:</strong>
|
||
<?php if ($qCountry === 'ALL'): ?>
|
||
🌐 alle Länder · <strong><?= $visibleFach ?></strong> Fach-Anker
|
||
<?php else:
|
||
$cm = $countryMeta[$qCountry];
|
||
?>
|
||
<?= $cm['flag'] ?> <strong><?= esc($cm['label']) ?></strong> · <strong><?= $visibleFach ?></strong> Lehrplan-Anker
|
||
<?php endif; ?>
|
||
+ <strong><?= $visibleUniversal ?></strong> fächerübergreifende Anker
|
||
(universell, aus dem österreichischen Lehrplan abgeleitet — didaktisch ländervergreifend nutzbar).
|
||
</div>
|
||
|
||
<!-- FILTER (Land entfernt — wird über den Country-Picker in der Sub-Nav gesetzt) -->
|
||
<div class="lp-filters" id="lp-filters">
|
||
<div class="lp-filter-row">
|
||
<span class="lp-filter-label">Thema</span>
|
||
<button type="button" class="lp-chip<?= !$qTheme ? ' active' : '' ?>" data-filter="theme" data-value="">
|
||
Alle <span class="lp-chip-badge"><?= count($kompetenzen) ?></span>
|
||
</button>
|
||
<?php foreach ($kompetenzen as $k): ?>
|
||
<?php $slug = esc($k['key_slug']); ?>
|
||
<button type="button" class="lp-chip<?= $qTheme === $k['key_slug'] ? ' active' : '' ?>"
|
||
data-filter="theme" data-value="<?= $slug ?>">
|
||
<?= esc($k['title']) ?>
|
||
</button>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
|
||
<div class="lp-filter-row">
|
||
<span class="lp-filter-label">Typ</span>
|
||
<button type="button" class="lp-chip active" data-filter="type" data-value="">
|
||
Alle <span class="lp-chip-badge"><?= $totalAnchors ?></span>
|
||
</button>
|
||
<button type="button" class="lp-chip" data-filter="type" data-value="fach">
|
||
Fachbezug <span class="lp-chip-badge"><?= $countsByType['fach'] ?? 0 ?></span>
|
||
</button>
|
||
<button type="button" class="lp-chip" data-filter="type" data-value="uebergreifendes_thema">
|
||
Fächerübergreifend <span class="lp-chip-badge"><?= $countsByType['uebergreifendes_thema'] ?? 0 ?></span>
|
||
</button>
|
||
<button type="button" class="lp-chip" data-filter="type" data-value="anderes_fach">
|
||
Andere Fächer <span class="lp-chip-badge"><?= $countsByType['anderes_fach'] ?? 0 ?></span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="lp-wrap">
|
||
|
||
<!-- TOC — Sprung zu Kompetenzen -->
|
||
<nav class="lp-toc" aria-label="Sprung zu Kompetenz">
|
||
<div class="lp-toc-title">Kompetenzbereiche auf dieser Seite</div>
|
||
<div class="lp-toc-list">
|
||
<?php foreach ($kompetenzen as $k):
|
||
$total = count($k['anchors_all']); ?>
|
||
<a class="lp-toc-item" href="#k-<?= esc($k['key_slug']) ?>">
|
||
<?= esc($k['title']) ?>
|
||
<span class="lp-toc-count"><?= $total ?></span>
|
||
</a>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="lp-results-info" id="lp-results-info"></div>
|
||
|
||
<?php foreach ($kompetenzen as $k): ?>
|
||
<article class="lp-kompetenz" id="k-<?= esc($k['key_slug']) ?>"
|
||
data-theme="<?= esc($k['key_slug']) ?>">
|
||
<header class="lp-kompetenz-head">
|
||
<div class="lp-kompetenz-title"><?= esc($k['title']) ?></div>
|
||
<?php if (!empty($k['category']) && isset($categoryMeta[$k['category']])): ?>
|
||
<span class="lp-kompetenz-cat"><?= esc($categoryMeta[$k['category']]['label']) ?></span>
|
||
<?php endif; ?>
|
||
<?php if (!empty($k['age_min']) && !empty($k['age_max'])): ?>
|
||
<span class="lp-kompetenz-age">👧 <?= (int)$k['age_min'] ?>–<?= (int)$k['age_max'] ?> Jahre</span>
|
||
<?php endif; ?>
|
||
</header>
|
||
|
||
<?php if (!empty($k['description'])): ?>
|
||
<p class="lp-kompetenz-desc"><?= esc($k['description']) ?></p>
|
||
<?php endif; ?>
|
||
|
||
<!-- Module, die dieser Kompetenz zugeordnet sind -->
|
||
<?php if (!empty($k['modules'])): ?>
|
||
<div class="lp-modules-label">Simulationen zu diesem Bereich</div>
|
||
<div class="lp-modules">
|
||
<?php foreach ($k['modules'] as $m): ?>
|
||
<a class="lp-module-card" href="<?= $bp ?>/<?= esc($m['page_url']) ?>">
|
||
<span class="lp-module-icon"><?= esc($m['icon']) ?></span>
|
||
<span class="lp-module-name"><?= esc($m['title']) ?></span>
|
||
<span class="lp-module-strength <?= esc($m['strength']) ?>">
|
||
<?= $m['strength'] === 'primaer' ? 'Primär' : 'Sekundär' ?>
|
||
</span>
|
||
<span class="lp-module-status <?= esc($m['status']) ?>"><?= esc($m['status']) ?></span>
|
||
</a>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- Anker-Gruppen -->
|
||
<?php
|
||
$groups = [
|
||
['anchors_fach', 'Fachbezug', 'Direkte Zuordnung im Fach-Lehrplan'],
|
||
['anchors_uebergreifend', 'Fächerübergreifende Themen', 'Verbindliche Querschnittsthemen des Lehrplans'],
|
||
['anchors_andere_faecher', 'Anknüpfungspunkte in anderen Fächern', 'Wo das Thema zusätzlich auftaucht'],
|
||
];
|
||
foreach ($groups as [$key, $heading, $sub]):
|
||
$list = $k[$key] ?? [];
|
||
if (empty($list)) continue;
|
||
?>
|
||
<div class="lp-anchor-group" data-group-type="<?= esc($key) ?>">
|
||
<div class="lp-anchor-group-head">
|
||
<span class="lp-anchor-group-title"><?= esc($heading) ?></span>
|
||
<span class="lp-anchor-group-sub"><?= esc($sub) ?></span>
|
||
</div>
|
||
<div class="lp-anchors">
|
||
<?php foreach ($list as $a): ?>
|
||
<?php
|
||
$cm = $countryMeta[$a['country']] ?? ['flag' => '🏳️', 'label' => $a['country']];
|
||
/* N.5.3 (a) — Übergreifende + Anderes-Fach-Anker sind land-agnostisch.
|
||
🌐-Icon + „Universell"-Label statt Country-Flagge zeigt das visuell. */
|
||
$isUniversal = ($a['anchor_type'] !== 'fach');
|
||
$iconHtml = $isUniversal ? '🌐' : $cm['flag'];
|
||
$iconTitle = $isUniversal ? 'Universell — aus ' . $cm['label'] . '-Lehrplan abgeleitet' : $cm['label'];
|
||
?>
|
||
<div class="lp-anchor lp-anchor--<?= esc($a['anchor_type']) ?>"
|
||
data-country="<?= esc($a['country']) ?>"
|
||
data-anchor-type="<?= esc($a['anchor_type']) ?>">
|
||
<div class="lp-anchor-flag" title="<?= esc($iconTitle) ?>"><?= $iconHtml ?></div>
|
||
<div>
|
||
<div class="lp-anchor-meta">
|
||
<?php if ($isUniversal): ?>
|
||
<strong>Universell</strong> <span style="opacity:.7">(aus <?= esc($a['country']) ?>-Lehrplan)</span>
|
||
<?php else: ?>
|
||
<strong><?= esc($a['country']) ?></strong>
|
||
<?php endif; ?>
|
||
<?= $a['region'] ? ' · ' . esc($a['region']) : '' ?>
|
||
<?= $a['school_type'] ? ' · ' . esc($a['school_type']) : '' ?>
|
||
<?= $a['grade'] ? ' · ' . esc($a['grade']) : '' ?>
|
||
<?= $a['subject'] ? ' · ' . esc($a['subject']) : '' ?>
|
||
</div>
|
||
<div class="lp-anchor-title"><?= esc($a['title']) ?></div>
|
||
<?php if (!empty($a['quote'])): ?>
|
||
<div class="lp-anchor-quote">„<?= esc($a['quote']) ?>"</div>
|
||
<?php endif; ?>
|
||
<?php if (!empty($a['reference'])): ?>
|
||
<div class="lp-anchor-ref">
|
||
Quelle:
|
||
<?php if (!empty($a['reference_url'])): ?>
|
||
<a href="<?= esc($a['reference_url']) ?>" target="_blank"
|
||
rel="noopener noreferrer" class="lp-anchor-link"><?= esc($a['reference']) ?> ↗</a>
|
||
<?php else: ?>
|
||
<?= esc($a['reference']) ?>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
|
||
<?php if (empty($k['anchors_all'])): ?>
|
||
<div class="lp-kompetenz-empty">Noch keine Lehrplan-Anker hinterlegt.</div>
|
||
<?php endif; ?>
|
||
</article>
|
||
<?php endforeach; ?>
|
||
|
||
<p class="lp-hint">
|
||
Anker sind Beispiele — bitte mit dem konkreten Jahresplan abgleichen.
|
||
<strong>🌐-Anker</strong> sind fächerübergreifend / anderes Fach: aus dem
|
||
österreichischen Lehrplan abgeleitet, didaktisch ländervergreifend nutzbar.
|
||
</p>
|
||
</div>
|
||
|
||
<footer class="lp-footer">
|
||
<img src="<?= $bp ?>/assets/img/bildLogo.png" alt="">
|
||
<div>
|
||
Lehrplan geograsim.at ·
|
||
<a href="<?= $bp ?>/pages/simulationen.php">Simulationen</a> ·
|
||
<a href="<?= $bp ?>/glossar">Glossar</a> ·
|
||
<a href="<?= $bp ?>/ueber.html">Über</a> ·
|
||
<a href="<?= $bp ?>/impressum.html">Impressum</a> ·
|
||
<a href="<?= $bp ?>/datenschutz.html">Datenschutz</a>
|
||
</div>
|
||
<?php include __DIR__ . '/_partials/country_footer.php'; ?>
|
||
</footer>
|
||
|
||
<script>
|
||
// Filter-Logik: Land / Thema / Typ
|
||
(function () {
|
||
const filterBar = document.getElementById('lp-filters');
|
||
const resultsInfo = document.getElementById('lp-results-info');
|
||
|
||
const state = {
|
||
country: <?= json_encode($qCountry) ?>,
|
||
theme: <?= json_encode($qTheme) ?>,
|
||
type: '',
|
||
};
|
||
|
||
// Chips aktiv-Zustand beim Laden setzen (falls URL-Filter vorgewählt)
|
||
function activate(row, value) {
|
||
filterBar.querySelectorAll(`.lp-chip[data-filter="${row}"]`).forEach(c => {
|
||
c.classList.toggle('active', c.dataset.value === value);
|
||
});
|
||
}
|
||
|
||
filterBar.addEventListener('click', (e) => {
|
||
const btn = e.target.closest('.lp-chip');
|
||
if (!btn) return;
|
||
const filter = btn.dataset.filter;
|
||
const value = btn.dataset.value;
|
||
state[filter] = value;
|
||
activate(filter, value);
|
||
apply();
|
||
// URL aktualisieren, ohne Reload (damit Deep-Links funktionieren)
|
||
const params = new URLSearchParams();
|
||
if (state.country && state.country !== 'ALL') params.set('country', state.country);
|
||
if (state.theme) params.set('theme', state.theme);
|
||
const q = params.toString();
|
||
history.replaceState(null, '', q ? '?' + q : location.pathname);
|
||
});
|
||
|
||
function apply() {
|
||
let shownKomp = 0;
|
||
let shownAnchors = 0;
|
||
document.querySelectorAll('.lp-kompetenz').forEach(k => {
|
||
// Thema-Filter
|
||
if (state.theme && k.dataset.theme !== state.theme) {
|
||
k.style.display = 'none';
|
||
return;
|
||
}
|
||
k.style.display = '';
|
||
shownKomp++;
|
||
|
||
// Anker-Filter: Land + Typ
|
||
k.querySelectorAll('.lp-anchor').forEach(a => {
|
||
let hide = false;
|
||
// Land-Filter (Default = aktuelles Land aus Country::current(), in der Regel AT):
|
||
// - anchor_type='fach' wird strikt nach Land gefiltert
|
||
// - uebergreifende Themen + andere Faecher bleiben sichtbar
|
||
// (sie sind primaer aus dem AT-Lehrplan abgeleitet, didaktisch
|
||
// land-agnostisch nutzbar)
|
||
if (state.country && state.country !== 'ALL') {
|
||
const anchorCountry = a.dataset.country;
|
||
const type = a.dataset.anchorType;
|
||
if (type === 'fach') {
|
||
if (anchorCountry && anchorCountry !== state.country) hide = true;
|
||
}
|
||
// anchor_type !== 'fach': land-agnostisch sichtbar lassen
|
||
}
|
||
if (state.type && a.dataset.anchorType !== state.type) hide = true;
|
||
|
||
a.classList.toggle('hidden', hide);
|
||
if (!hide) shownAnchors++;
|
||
});
|
||
|
||
// Wenn in einer Kompetenz keine Anker sichtbar sind, Kompetenz ausblenden
|
||
const visibleInKomp = k.querySelectorAll('.lp-anchor:not(.hidden)').length;
|
||
if (visibleInKomp === 0 && (state.country !== 'ALL' || state.type)) {
|
||
k.style.display = 'none';
|
||
shownKomp--;
|
||
}
|
||
|
||
// Auch Anker-Gruppen ausblenden, wenn sie leer sind
|
||
k.querySelectorAll('.lp-anchor-group').forEach(g => {
|
||
const v = g.querySelectorAll('.lp-anchor:not(.hidden)').length;
|
||
g.style.display = v === 0 ? 'none' : '';
|
||
});
|
||
});
|
||
|
||
// Ergebnis-Info aktualisieren
|
||
const parts = [`${shownAnchors} Anker sichtbar`];
|
||
if (shownKomp !== <?= count($kompetenzen) ?>) parts.push(`${shownKomp} Kompetenzbereich(e)`);
|
||
resultsInfo.textContent = parts.join(' · ');
|
||
}
|
||
|
||
// Initial
|
||
apply();
|
||
})();
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|