feat(IFK-9): interactive world map, charts, stats banner, timeline
All checks were successful
Deploy Internet for Kids / Build & Push (push) Successful in 9s
Deploy Internet for Kids / Deploy (push) Successful in 6s
Deploy Internet for Kids / Health Check (push) Successful in 2s
Deploy Internet for Kids / Smoke Tests (push) Successful in 4s
Deploy Internet for Kids / IndexNow Ping (push) Successful in 8s
Deploy Internet for Kids / Promote to Latest (push) Successful in 1s
Deploy Internet for Kids / Rollback (push) Has been skipped
Deploy Internet for Kids / Audit (push) Successful in 2s
All checks were successful
Deploy Internet for Kids / Build & Push (push) Successful in 9s
Deploy Internet for Kids / Deploy (push) Successful in 6s
Deploy Internet for Kids / Health Check (push) Successful in 2s
Deploy Internet for Kids / Smoke Tests (push) Successful in 4s
Deploy Internet for Kids / IndexNow Ping (push) Successful in 8s
Deploy Internet for Kids / Promote to Latest (push) Successful in 1s
Deploy Internet for Kids / Rollback (push) Has been skipped
Deploy Internet for Kids / Audit (push) Successful in 2s
- Add centralized data/countries.json with all 17 countries (EN/DE/FR) - Add Leaflet choropleth world map with TopoJSON boundaries - Add stats banner shortcode (enforced/passed/progress/guidelines counts) - Add Chart.js charts (status donut, age limits bar, legislation timeline) - Add Mermaid timeline of legislation milestones 2020-2026 - Refactor child-safety-map table to use data file (DRY) - Update all 3 language articles (EN/DE/FR) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,75 +1,31 @@
|
||||
{{ $lang := .Page.Language.Lang }}
|
||||
{{ $countries := hugo.Data.countries }}
|
||||
|
||||
{{ $statusClass := dict "enforced" "csm-enforced" "passed" "csm-passed" "progress" "csm-progress" "guidelines" "csm-guidelines" }}
|
||||
{{ $statusLabel := dict
|
||||
"enforced" (dict "en" "Enforced" "de" "In Kraft" "fr" "En vigueur")
|
||||
"passed" (dict "en" "Passed" "de" "Verabschiedet" "fr" "Adopté")
|
||||
"progress" (dict "en" "In Progress" "de" "In Bearbeitung" "fr" "En cours")
|
||||
"guidelines" (dict "en" "Guidelines" "de" "Richtlinien" "fr" "Directives")
|
||||
}}
|
||||
|
||||
<style>
|
||||
.csm-container {
|
||||
max-width: 100%;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
.csm-container h3 {
|
||||
text-align: center;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
.csm-subtitle {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.csm-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.csm-table th {
|
||||
background: #1e40af;
|
||||
color: white;
|
||||
padding: 0.75rem 1rem;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
}
|
||||
.csm-table td {
|
||||
padding: 0.65rem 1rem;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
vertical-align: top;
|
||||
}
|
||||
.csm-table tr:hover {
|
||||
background: #f0fdf4;
|
||||
}
|
||||
.csm-status {
|
||||
display: inline-block;
|
||||
padding: 0.15rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.csm-container { max-width: 100%; margin: 2rem 0; }
|
||||
.csm-container h3 { text-align: center; margin-bottom: 0.5rem; font-size: 1.25rem; }
|
||||
.csm-subtitle { text-align: center; color: #666; font-size: 0.85rem; margin-bottom: 1rem; }
|
||||
.csm-table { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
|
||||
.csm-table th { background: #1e40af; color: white; padding: 0.75rem 1rem; text-align: left; font-weight: 600; }
|
||||
.csm-table td { padding: 0.65rem 1rem; border-bottom: 1px solid #e2e8f0; vertical-align: top; }
|
||||
.csm-table tr:hover { background: #f0fdf4; }
|
||||
.csm-status { display: inline-block; padding: 0.15rem 0.5rem; border-radius: 4px; font-size: 0.8rem; font-weight: 600; white-space: nowrap; }
|
||||
.csm-enforced { background: #1e40af; color: white; }
|
||||
.csm-passed { background: #3b82f6; color: white; }
|
||||
.csm-progress { background: #93c5fd; color: #1e3a5f; }
|
||||
.csm-guidelines { background: #dbeafe; color: #1e3a5f; }
|
||||
.csm-legend {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
margin-top: 1.5rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.csm-legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
.csm-legend-swatch {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.csm-table { font-size: 0.85rem; }
|
||||
.csm-table th, .csm-table td { padding: 0.5rem; }
|
||||
}
|
||||
.csm-legend { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; margin-top: 1.5rem; font-size: 0.8rem; }
|
||||
.csm-legend-item { display: flex; align-items: center; gap: 0.35rem; }
|
||||
.csm-legend-swatch { width: 14px; height: 14px; border-radius: 3px; border: 1px solid rgba(0,0,0,0.1); }
|
||||
@media (max-width: 640px) { .csm-table { font-size: 0.85rem; } .csm-table th, .csm-table td { padding: 0.5rem; } }
|
||||
</style>
|
||||
|
||||
<div class="csm-container">
|
||||
@@ -86,60 +42,16 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ if eq $lang "de" }}
|
||||
<tr><td>🇦🇺 Australien</td><td>Social Media Minimum Age Act 2024</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Social-Media-Verbot für unter 16-Jährige. Bußgelder bis 49,5 Mio. AUD.</td></tr>
|
||||
<tr><td>🇬🇧 Vereinigtes Königreich</td><td>Online Safety Act 2023</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Umfassendes Online-Sicherheitsregime. Altersverifikation erforderlich.</td></tr>
|
||||
<tr><td>🇩🇪 Deutschland</td><td>Jugendschutzgesetz (JuSchG)</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Auf Online-Plattformen ausgeweitet. BzKJ überwacht aktiv die Einhaltung.</td></tr>
|
||||
<tr><td>🇨🇳 China</td><td>Minderjährigenschutzgesetz</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>1 Std./Tag Gaming für Minderjährige. Echtnamen-Verifizierung verpflichtend.</td></tr>
|
||||
<tr><td>🇰🇷 Südkorea</td><td>Jugendschutzgesetz</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Langjähriger Jugendschutzrahmen. Echtnamen-Verifizierung für Online-Dienste.</td></tr>
|
||||
<tr><td>🇮🇪 Irland</td><td>Online Safety and Media Regulation Act</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Coimisiún na Meán reguliert Online-Sicherheit mit verbindlichen Kodizes.</td></tr>
|
||||
<tr><td>🇳🇱 Niederlande</td><td>DSA + Kinderkodex</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>Datenschutzbehörde setzt Kinderdatenschutz aktiv durch.</td></tr>
|
||||
<tr><td>🇸🇪 Schweden</td><td>DSA + Nationale Jugendrichtlinien</td><td><span class="csm-status csm-enforced">In Kraft</span></td><td>EU-DSA-Rahmen plus nationale Jugendschutzrichtlinien.</td></tr>
|
||||
<tr><td>🇫🇷 Frankreich</td><td>Loi SREN + Social-Media-Verbot</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Senat stimmt für Social-Media-Verbot unter 15 (April 2026). Arcom-Blacklist. Vermittlung läuft.</td></tr>
|
||||
<tr><td>🇧🇷 Brasilien</td><td>ECA Digital</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Lootbox-Verbot für Minderjährige. Altersgerechtes Design.</td></tr>
|
||||
<tr><td>🇮🇳 Indien</td><td>DPDP Act 2023</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Verifizierbare elterliche Einwilligung für unter 18-Jährige.</td></tr>
|
||||
<tr><td>🇮🇹 Italien</td><td>DSA + Einwilligungsgesetz</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Digitales Einwilligungsalter auf 14 festgelegt.</td></tr>
|
||||
<tr><td>🇪🇸 Spanien</td><td>Organisches Kinderschutzgesetz</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Umfassendes digitales Kinderschutzgesetz.</td></tr>
|
||||
<tr><td>🇳🇴 Norwegen</td><td>Social-Media-Altersgrenze</td><td><span class="csm-status csm-passed">Verabschiedet</span></td><td>Geplante Altersgrenze von 15 Jahren.</td></tr>
|
||||
<tr><td>🇺🇸 Vereinigte Staaten</td><td>KOSA + COPPA-Update</td><td><span class="csm-status csm-progress">In Bearbeitung</span></td><td>KOSA im Senat angenommen. COPPA-Update bis Apr. 2026.</td></tr>
|
||||
<tr><td>🇨🇦 Kanada</td><td>Online Harms Act (C-63)</td><td><span class="csm-status csm-progress">In Bearbeitung</span></td><td>Sorgfaltspflicht für Plattformen in Prüfung.</td></tr>
|
||||
<tr><td>🇯🇵 Japan</td><td>Regulierung der Kontaktaufnahme</td><td><span class="csm-status csm-guidelines">Richtlinien</span></td><td>Selbstregulierung der Plattformen empfohlen.</td></tr>
|
||||
{{ else if eq $lang "fr" }}
|
||||
<tr><td>🇦🇺 Australie</td><td>Social Media Minimum Age Act 2024</td><td><span class="csm-status csm-enforced">En vigueur</span></td><td>Interdiction des réseaux sociaux pour les moins de 16 ans. Amendes jusqu'à 49,5 M AUD.</td></tr>
|
||||
<tr><td>🇬🇧 Royaume-Uni</td><td>Online Safety Act 2023</td><td><span class="csm-status csm-enforced">En vigueur</span></td><td>Régime complet de sécurité en ligne. Vérification d'âge obligatoire.</td></tr>
|
||||
<tr><td>🇩🇪 Allemagne</td><td>Jugendschutzgesetz (JuSchG)</td><td><span class="csm-status csm-enforced">En vigueur</span></td><td>Loi sur la protection de la jeunesse étendue aux plateformes en ligne. Surveillance BzKJ.</td></tr>
|
||||
<tr><td>🇨🇳 Chine</td><td>Loi sur la protection des mineurs</td><td><span class="csm-status csm-enforced">En vigueur</span></td><td>1h/jour de jeux vidéo pour les mineurs. Vérification d'identité obligatoire.</td></tr>
|
||||
<tr><td>🇰🇷 Corée du Sud</td><td>Loi sur la protection de la jeunesse</td><td><span class="csm-status csm-enforced">En vigueur</span></td><td>Cadre de protection de la jeunesse établi de longue date. Vérification d'identité.</td></tr>
|
||||
<tr><td>🇮🇪 Irlande</td><td>Online Safety and Media Regulation Act</td><td><span class="csm-status csm-enforced">En vigueur</span></td><td>Coimisiún na Meán régule la sécurité en ligne avec des codes contraignants.</td></tr>
|
||||
<tr><td>🇳🇱 Pays-Bas</td><td>DSA + Code de l'enfance</td><td><span class="csm-status csm-enforced">En vigueur</span></td><td>Autorité de protection des données applique activement la protection des données des enfants.</td></tr>
|
||||
<tr><td>🇸🇪 Suède</td><td>DSA + Directives nationales jeunesse</td><td><span class="csm-status csm-enforced">En vigueur</span></td><td>Cadre DSA de l'UE plus directives nationales de protection de la jeunesse.</td></tr>
|
||||
<tr><td>🇫🇷 France</td><td>Loi SREN + Interdiction réseaux sociaux</td><td><span class="csm-status csm-passed">Adopté</span></td><td>Le Sénat vote l'interdiction des réseaux sociaux pour les moins de 15 ans (avril 2026). Liste noire Arcom. Conciliation en cours.</td></tr>
|
||||
<tr><td>🇧🇷 Brésil</td><td>ECA Digital</td><td><span class="csm-status csm-passed">Adopté</span></td><td>Interdiction des loot boxes pour les mineurs. Exigences de design adapté à l'âge.</td></tr>
|
||||
<tr><td>🇮🇳 Inde</td><td>DPDP Act 2023</td><td><span class="csm-status csm-passed">Adopté</span></td><td>Consentement parental vérifiable pour les moins de 18 ans.</td></tr>
|
||||
<tr><td>🇮🇹 Italie</td><td>DSA + Loi sur le consentement parental</td><td><span class="csm-status csm-passed">Adopté</span></td><td>Âge de consentement numérique fixé à 14 ans.</td></tr>
|
||||
<tr><td>🇪🇸 Espagne</td><td>Protection de l'enfance dans les environnements numériques</td><td><span class="csm-status csm-passed">Adopté</span></td><td>Loi complète de protection numérique de l'enfance.</td></tr>
|
||||
<tr><td>🇳🇴 Norvège</td><td>Limite d'âge réseaux sociaux</td><td><span class="csm-status csm-passed">Adopté</span></td><td>Limite d'âge proposée à 15 ans.</td></tr>
|
||||
<tr><td>🇺🇸 États-Unis</td><td>KOSA + Mise à jour COPPA</td><td><span class="csm-status csm-progress">En cours</span></td><td>KOSA adopté au Sénat 91-3. Mise à jour COPPA prévue avr. 2026.</td></tr>
|
||||
<tr><td>🇨🇦 Canada</td><td>Online Harms Act (C-63)</td><td><span class="csm-status csm-progress">En cours</span></td><td>Devoir de diligence proposé pour les plateformes.</td></tr>
|
||||
<tr><td>🇯🇵 Japon</td><td>Loi sur la régulation de la sollicitation des enfants</td><td><span class="csm-status csm-guidelines">Directives</span></td><td>Autorégulation des plateformes encouragée.</td></tr>
|
||||
{{ else }}
|
||||
<tr><td>🇦🇺 Australia</td><td>Social Media Minimum Age Act 2024</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Social media ban for under-16s. Fines up to AUD 49.5M.</td></tr>
|
||||
<tr><td>🇬🇧 United Kingdom</td><td>Online Safety Act 2023</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Comprehensive online safety regime. Age verification required.</td></tr>
|
||||
<tr><td>🇩🇪 Germany</td><td>Jugendschutzgesetz (JuSchG)</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Youth Protection Act extended to online platforms. BzKJ monitoring.</td></tr>
|
||||
<tr><td>🇨🇳 China</td><td>Minor Protection Law</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>1hr/day gaming for minors. Real-name verification mandatory.</td></tr>
|
||||
<tr><td>🇰🇷 South Korea</td><td>Youth Protection Act</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Long-standing youth protection framework. Real-name verification.</td></tr>
|
||||
<tr><td>🇮🇪 Ireland</td><td>Online Safety and Media Regulation Act</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Coimisiún na Meán regulates online safety with binding codes.</td></tr>
|
||||
<tr><td>🇳🇱 Netherlands</td><td>DSA + Children's Code</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>Dutch DPA actively enforcing children's data protection.</td></tr>
|
||||
<tr><td>🇸🇪 Sweden</td><td>DSA + National Youth Guidelines</td><td><span class="csm-status csm-enforced">Enforced</span></td><td>EU DSA framework plus national youth protection guidelines.</td></tr>
|
||||
<tr><td>🇫🇷 France</td><td>Loi SREN + Social Media Ban</td><td><span class="csm-status csm-passed">Passed</span></td><td>Senate votes to ban social media for under-15s (April 2026). Arcom blacklist. Reconciliation pending.</td></tr>
|
||||
<tr><td>🇧🇷 Brazil</td><td>ECA Digital</td><td><span class="csm-status csm-passed">Passed</span></td><td>Loot box ban for minors. Age-appropriate design requirements.</td></tr>
|
||||
<tr><td>🇮🇳 India</td><td>DPDP Act 2023</td><td><span class="csm-status csm-passed">Passed</span></td><td>Verifiable parental consent for under-18s.</td></tr>
|
||||
<tr><td>🇮🇹 Italy</td><td>DSA + Parental Consent Law</td><td><span class="csm-status csm-passed">Passed</span></td><td>Digital age of consent set to 14.</td></tr>
|
||||
<tr><td>🇪🇸 Spain</td><td>Child Protection in Digital Environments</td><td><span class="csm-status csm-passed">Passed</span></td><td>Comprehensive child digital protection law.</td></tr>
|
||||
<tr><td>🇳🇴 Norway</td><td>Social Media Age Limit</td><td><span class="csm-status csm-passed">Passed</span></td><td>Proposed social media age limit of 15.</td></tr>
|
||||
<tr><td>🇺🇸 United States</td><td>KOSA + COPPA Update</td><td><span class="csm-status csm-progress">In Progress</span></td><td>KOSA passed Senate 91-3. COPPA update by Apr 2026.</td></tr>
|
||||
<tr><td>🇨🇦 Canada</td><td>Online Harms Act (C-63)</td><td><span class="csm-status csm-progress">In Progress</span></td><td>Proposed duty of care for platforms.</td></tr>
|
||||
<tr><td>🇯🇵 Japan</td><td>Act on Regulation of Soliciting Children</td><td><span class="csm-status csm-guidelines">Guidelines</span></td><td>Platform self-regulation encouraged.</td></tr>
|
||||
{{ range $countries }}
|
||||
{{ $loc := index . $lang | default (index . "en") }}
|
||||
{{ $cls := index $statusClass .status }}
|
||||
{{ $lbl := index (index $statusLabel .status) $lang | default (index (index $statusLabel .status) "en") }}
|
||||
<tr>
|
||||
<td>{{ .flag }} {{ $loc.name }}</td>
|
||||
<td>{{ $loc.law }}</td>
|
||||
<td><span class="csm-status {{ $cls }}">{{ $lbl }}</span></td>
|
||||
<td>{{ $loc.detail }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
124
layouts/shortcodes/law-charts.html
Normal file
124
layouts/shortcodes/law-charts.html
Normal file
@@ -0,0 +1,124 @@
|
||||
{{ $lang := .Page.Language.Lang }}
|
||||
{{ $countries := hugo.Data.countries }}
|
||||
|
||||
<style>
|
||||
.ifk-charts { margin: 2rem 0; }
|
||||
.ifk-charts h3 { text-align: center; margin-bottom: 1.5rem; font-size: 1.25rem; }
|
||||
.ifk-chart-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; }
|
||||
.ifk-chart-card {
|
||||
background: #fafbfc; border: 1px solid #e2e8f0; border-radius: 10px;
|
||||
padding: 1.25rem; text-align: center;
|
||||
}
|
||||
.ifk-chart-card h4 { margin: 0 0 1rem; font-size: 0.95rem; color: #334155; }
|
||||
.ifk-chart-card canvas { max-height: 280px; }
|
||||
@media (max-width: 640px) {
|
||||
.ifk-chart-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="ifk-charts">
|
||||
<h3>{{ if eq $lang "de" }}Analyse der Kinderschutzgesetze{{ else if eq $lang "fr" }}Analyse des lois de protection{{ else }}Child Protection Law Analysis{{ end }}</h3>
|
||||
<div class="ifk-chart-grid">
|
||||
<div class="ifk-chart-card">
|
||||
<h4>{{ if eq $lang "de" }}Gesetzgebungsstatus{{ else if eq $lang "fr" }}Statut législatif{{ else }}Legislative Status{{ end }}</h4>
|
||||
<canvas id="ifk-chart-status"></canvas>
|
||||
</div>
|
||||
<div class="ifk-chart-card">
|
||||
<h4>{{ if eq $lang "de" }}Mindestalter für soziale Medien{{ else if eq $lang "fr" }}Âge minimum réseaux sociaux{{ else }}Social Media Age Limits{{ end }}</h4>
|
||||
<canvas id="ifk-chart-age"></canvas>
|
||||
</div>
|
||||
<div class="ifk-chart-card" style="grid-column: 1 / -1;">
|
||||
<h4>{{ if eq $lang "de" }}Zeitachse der Gesetzgebung{{ else if eq $lang "fr" }}Chronologie législative{{ else }}Legislation Timeline{{ end }}</h4>
|
||||
<canvas id="ifk-chart-timeline"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
|
||||
<script>
|
||||
(function() {
|
||||
var LANG = {{ $lang }};
|
||||
var countries = {{ $countries | jsonify }};
|
||||
|
||||
var statusLabels = {
|
||||
en: { enforced: 'Enforced', passed: 'Passed', progress: 'In Progress', guidelines: 'Guidelines' },
|
||||
de: { enforced: 'In Kraft', passed: 'Verabschiedet', progress: 'In Bearbeitung', guidelines: 'Richtlinien' },
|
||||
fr: { enforced: 'En vigueur', passed: 'Adopté', progress: 'En cours', guidelines: 'Directives' }
|
||||
};
|
||||
var labels = statusLabels[LANG] || statusLabels.en;
|
||||
|
||||
/* Pie: status distribution */
|
||||
var counts = { enforced: 0, passed: 0, progress: 0, guidelines: 0 };
|
||||
countries.forEach(function(c) { counts[c.status]++; });
|
||||
|
||||
new Chart(document.getElementById('ifk-chart-status'), {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: [labels.enforced, labels.passed, labels.progress, labels.guidelines],
|
||||
datasets: [{
|
||||
data: [counts.enforced, counts.passed, counts.progress, counts.guidelines],
|
||||
backgroundColor: ['#1e40af', '#3b82f6', '#93c5fd', '#dbeafe'],
|
||||
borderWidth: 2, borderColor: '#fff'
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: { position: 'bottom', labels: { padding: 16, usePointStyle: true } }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Horizontal bar: age limits */
|
||||
var sorted = countries.slice().sort(function(a, b) { return b.ageLimitSocial - a.ageLimitSocial; });
|
||||
var colors = { enforced: '#1e40af', passed: '#3b82f6', progress: '#93c5fd', guidelines: '#dbeafe' };
|
||||
|
||||
new Chart(document.getElementById('ifk-chart-age'), {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: sorted.map(function(c) { return c.flag + ' ' + (c[LANG] || c.en).name; }),
|
||||
datasets: [{
|
||||
label: LANG === 'de' ? 'Mindestalter' : LANG === 'fr' ? 'Âge minimum' : 'Min. Age',
|
||||
data: sorted.map(function(c) { return c.ageLimitSocial; }),
|
||||
backgroundColor: sorted.map(function(c) { return colors[c.status]; }),
|
||||
borderRadius: 4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
indexAxis: 'y', responsive: true,
|
||||
scales: {
|
||||
x: { min: 0, max: 20, title: { display: true, text: LANG === 'de' ? 'Jahre' : LANG === 'fr' ? 'Ans' : 'Years' } }
|
||||
},
|
||||
plugins: { legend: { display: false } }
|
||||
}
|
||||
});
|
||||
|
||||
/* Bar: timeline by year */
|
||||
var yearCounts = {};
|
||||
countries.forEach(function(c) {
|
||||
if (!yearCounts[c.year]) yearCounts[c.year] = { enforced: 0, passed: 0, progress: 0, guidelines: 0 };
|
||||
yearCounts[c.year][c.status]++;
|
||||
});
|
||||
var years = Object.keys(yearCounts).sort();
|
||||
|
||||
new Chart(document.getElementById('ifk-chart-timeline'), {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: years,
|
||||
datasets: [
|
||||
{ label: labels.enforced, data: years.map(function(y) { return yearCounts[y].enforced; }), backgroundColor: '#1e40af', borderRadius: 4 },
|
||||
{ label: labels.passed, data: years.map(function(y) { return yearCounts[y].passed; }), backgroundColor: '#3b82f6', borderRadius: 4 },
|
||||
{ label: labels.progress, data: years.map(function(y) { return yearCounts[y].progress; }), backgroundColor: '#93c5fd', borderRadius: 4 },
|
||||
{ label: labels.guidelines, data: years.map(function(y) { return yearCounts[y].guidelines; }), backgroundColor: '#dbeafe', borderRadius: 4 }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {
|
||||
x: { stacked: true }, y: { stacked: true, beginAtZero: true, ticks: { stepSize: 1 } }
|
||||
},
|
||||
plugins: { legend: { position: 'bottom', labels: { padding: 16, usePointStyle: true } } }
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
82
layouts/shortcodes/legislation-timeline.html
Normal file
82
layouts/shortcodes/legislation-timeline.html
Normal file
@@ -0,0 +1,82 @@
|
||||
{{ $lang := .Page.Language.Lang }}
|
||||
|
||||
<style>
|
||||
.ifk-timeline-wrap { margin: 2rem 0; }
|
||||
.ifk-timeline-wrap h3 { text-align: center; margin-bottom: 1rem; font-size: 1.25rem; }
|
||||
.ifk-mermaid-container {
|
||||
background: #fafbfc; border: 1px solid #e2e8f0; border-radius: 10px;
|
||||
padding: 1.5rem; overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="ifk-timeline-wrap">
|
||||
<h3>{{ if eq $lang "de" }}Meilensteine der Gesetzgebung{{ else if eq $lang "fr" }}Jalons législatifs{{ else }}Legislation Milestones{{ end }}</h3>
|
||||
<div class="ifk-mermaid-container">
|
||||
<pre class="mermaid">
|
||||
timeline
|
||||
{{ if eq $lang "de" -}}
|
||||
title Kinderschutzgesetze — Meilensteine
|
||||
2020 : 🇰🇷 Südkorea Jugendschutzgesetz
|
||||
2021 : 🇩🇪 JuSchG-Novelle (Online)
|
||||
: 🇨🇳 Minderjährigenschutzgesetz
|
||||
2022 : 🇮🇪 Online Safety Act
|
||||
2023 : 🇬🇧 Online Safety Act
|
||||
: 🇮🇳 DPDP Act
|
||||
2024 : 🇦🇺 Social Media Ban (unter 16)
|
||||
: 🇳🇱 DSA + Kinderkodex
|
||||
: 🇸🇪 DSA + Jugendrichtlinien
|
||||
: 🇯🇵 Regulierung Kontaktaufnahme
|
||||
2025 : 🇧🇷 ECA Digital
|
||||
: 🇮🇹 Einwilligungsgesetz (14+)
|
||||
: 🇪🇸 Digitaler Kinderschutz
|
||||
: 🇳🇴 Social-Media-Altersgrenze (15)
|
||||
2026 : 🇫🇷 Social-Media-Verbot (unter 15)
|
||||
: 🇺🇸 KOSA + COPPA-Update
|
||||
: 🇨🇦 Online Harms Act
|
||||
{{- else if eq $lang "fr" -}}
|
||||
title Lois de protection de l'enfance — Jalons
|
||||
2020 : 🇰🇷 Loi protection jeunesse
|
||||
2021 : 🇩🇪 JuSchG en ligne
|
||||
: 🇨🇳 Loi protection mineurs
|
||||
2022 : 🇮🇪 Online Safety Act
|
||||
2023 : 🇬🇧 Online Safety Act
|
||||
: 🇮🇳 DPDP Act
|
||||
2024 : 🇦🇺 Interdiction réseaux sociaux (-16)
|
||||
: 🇳🇱 DSA + Code enfance
|
||||
: 🇸🇪 DSA + Directives jeunesse
|
||||
: 🇯🇵 Régulation sollicitation
|
||||
2025 : 🇧🇷 ECA Digital
|
||||
: 🇮🇹 Consentement (14+)
|
||||
: 🇪🇸 Protection enfance numérique
|
||||
: 🇳🇴 Limite âge réseaux (15)
|
||||
2026 : 🇫🇷 Interdiction réseaux (-15)
|
||||
: 🇺🇸 KOSA + COPPA
|
||||
: 🇨🇦 Online Harms Act
|
||||
{{- else -}}
|
||||
title Child Protection Laws — Milestones
|
||||
2020 : 🇰🇷 South Korea Youth Protection Act
|
||||
2021 : 🇩🇪 Germany JuSchG Online Extension
|
||||
: 🇨🇳 China Minor Protection Law
|
||||
2022 : 🇮🇪 Ireland Online Safety Act
|
||||
2023 : 🇬🇧 UK Online Safety Act
|
||||
: 🇮🇳 India DPDP Act
|
||||
2024 : 🇦🇺 Australia Social Media Ban (under 16)
|
||||
: 🇳🇱 Netherlands DSA + Children's Code
|
||||
: 🇸🇪 Sweden DSA + Youth Guidelines
|
||||
: 🇯🇵 Japan Solicitation Regulation
|
||||
2025 : 🇧🇷 Brazil ECA Digital
|
||||
: 🇮🇹 Italy Consent Law (14+)
|
||||
: 🇪🇸 Spain Digital Child Protection
|
||||
: 🇳🇴 Norway Social Media Age (15)
|
||||
2026 : 🇫🇷 France Social Media Ban (under 15)
|
||||
: 🇺🇸 USA KOSA + COPPA Update
|
||||
: 🇨🇦 Canada Online Harms Act
|
||||
{{- end }}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
|
||||
<script>
|
||||
mermaid.initialize({ startOnLoad: true, theme: 'neutral', timeline: { useMaxWidth: true } });
|
||||
</script>
|
||||
49
layouts/shortcodes/stats-banner.html
Normal file
49
layouts/shortcodes/stats-banner.html
Normal file
@@ -0,0 +1,49 @@
|
||||
{{ $lang := .Page.Language.Lang }}
|
||||
{{ $countries := hugo.Data.countries }}
|
||||
|
||||
{{ $enforced := 0 }}{{ $passed := 0 }}{{ $progress := 0 }}{{ $guidelines := 0 }}
|
||||
{{ range $countries }}
|
||||
{{ if eq .status "enforced" }}{{ $enforced = add $enforced 1 }}
|
||||
{{ else if eq .status "passed" }}{{ $passed = add $passed 1 }}
|
||||
{{ else if eq .status "progress" }}{{ $progress = add $progress 1 }}
|
||||
{{ else if eq .status "guidelines" }}{{ $guidelines = add $guidelines 1 }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
<style>
|
||||
.ifk-stats {
|
||||
display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem;
|
||||
margin: 2rem 0; text-align: center;
|
||||
}
|
||||
.ifk-stat {
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
||||
border-radius: 10px; padding: 1.25rem 0.75rem;
|
||||
border: 1px solid #e2e8f0; transition: transform 0.15s;
|
||||
}
|
||||
.ifk-stat:hover { transform: translateY(-2px); }
|
||||
.ifk-stat-num { font-size: 2rem; font-weight: 800; line-height: 1.1; }
|
||||
.ifk-stat-label { font-size: 0.75rem; color: #64748b; margin-top: 0.25rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; }
|
||||
@media (max-width: 480px) {
|
||||
.ifk-stats { grid-template-columns: repeat(2, 1fr); }
|
||||
.ifk-stat-num { font-size: 1.5rem; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="ifk-stats">
|
||||
<div class="ifk-stat">
|
||||
<div class="ifk-stat-num" style="color:#1e40af">{{ $enforced }}</div>
|
||||
<div class="ifk-stat-label">{{ if eq $lang "de" }}In Kraft{{ else if eq $lang "fr" }}En vigueur{{ else }}Enforced{{ end }}</div>
|
||||
</div>
|
||||
<div class="ifk-stat">
|
||||
<div class="ifk-stat-num" style="color:#3b82f6">{{ $passed }}</div>
|
||||
<div class="ifk-stat-label">{{ if eq $lang "de" }}Verabschiedet{{ else if eq $lang "fr" }}Adoptées{{ else }}Passed{{ end }}</div>
|
||||
</div>
|
||||
<div class="ifk-stat">
|
||||
<div class="ifk-stat-num" style="color:#6366f1">{{ $progress }}</div>
|
||||
<div class="ifk-stat-label">{{ if eq $lang "de" }}In Bearbeitung{{ else if eq $lang "fr" }}En cours{{ else }}In Progress{{ end }}</div>
|
||||
</div>
|
||||
<div class="ifk-stat">
|
||||
<div class="ifk-stat-num" style="color:#8b5cf6">{{ $guidelines }}</div>
|
||||
<div class="ifk-stat-label">{{ if eq $lang "de" }}Richtlinien{{ else if eq $lang "fr" }}Directives{{ else }}Guidelines{{ end }}</div>
|
||||
</div>
|
||||
</div>
|
||||
91
layouts/shortcodes/world-map.html
Normal file
91
layouts/shortcodes/world-map.html
Normal file
@@ -0,0 +1,91 @@
|
||||
{{ $lang := .Page.Language.Lang }}
|
||||
{{ $countries := hugo.Data.countries }}
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.css" />
|
||||
<style>
|
||||
.ifk-map-wrap { max-width: 100%; margin: 2rem 0; }
|
||||
.ifk-map-wrap h3 { text-align: center; margin-bottom: 0.5rem; font-size: 1.25rem; }
|
||||
.ifk-map-subtitle { text-align: center; color: #666; font-size: 0.85rem; margin-bottom: 1rem; }
|
||||
#ifk-world-map { width: 100%; height: 420px; border-radius: 8px; background: #f0f4f8; }
|
||||
.ifk-map-legend {
|
||||
display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center;
|
||||
margin-top: 1rem; font-size: 0.8rem;
|
||||
}
|
||||
.ifk-map-legend-item { display: flex; align-items: center; gap: 0.35rem; }
|
||||
.ifk-map-legend-swatch { width: 14px; height: 14px; border-radius: 3px; border: 1px solid rgba(0,0,0,0.1); }
|
||||
@media (max-width: 640px) { #ifk-world-map { height: 280px; } }
|
||||
</style>
|
||||
|
||||
<div class="ifk-map-wrap">
|
||||
<h3>{{ if eq $lang "de" }}Interaktive Weltkarte: Kinderschutzgesetze{{ else if eq $lang "fr" }}Carte interactive : lois de protection de l'enfance{{ else }}Interactive Map: Child Protection Laws{{ end }}</h3>
|
||||
<p class="ifk-map-subtitle">{{ if eq $lang "de" }}Klicken Sie auf ein Land für Details{{ else if eq $lang "fr" }}Cliquez sur un pays pour plus de détails{{ else }}Click a country for details{{ end }}</p>
|
||||
<div id="ifk-world-map"></div>
|
||||
<div class="ifk-map-legend">
|
||||
<div class="ifk-map-legend-item"><div class="ifk-map-legend-swatch" style="background:#1e40af"></div>{{ if eq $lang "de" }}In Kraft{{ else if eq $lang "fr" }}En vigueur{{ else }}Enforced{{ end }}</div>
|
||||
<div class="ifk-map-legend-item"><div class="ifk-map-legend-swatch" style="background:#3b82f6"></div>{{ if eq $lang "de" }}Verabschiedet{{ else if eq $lang "fr" }}Adopté{{ else }}Passed{{ end }}</div>
|
||||
<div class="ifk-map-legend-item"><div class="ifk-map-legend-swatch" style="background:#93c5fd"></div>{{ if eq $lang "de" }}In Bearbeitung{{ else if eq $lang "fr" }}En cours{{ else }}In Progress{{ end }}</div>
|
||||
<div class="ifk-map-legend-item"><div class="ifk-map-legend-swatch" style="background:#dbeafe"></div>{{ if eq $lang "de" }}Richtlinien{{ else if eq $lang "fr" }}Directives{{ else }}Guidelines{{ end }}</div>
|
||||
<div class="ifk-map-legend-item"><div class="ifk-map-legend-swatch" style="background:#e2e8f0"></div>{{ if eq $lang "de" }}Keine Daten{{ else if eq $lang "fr" }}Pas de données{{ else }}No Data{{ end }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3.1.0/dist/topojson-client.min.js"></script>
|
||||
<script>
|
||||
(function() {
|
||||
var LANG = {{ $lang }};
|
||||
var STATUS_COLORS = { enforced: '#1e40af', passed: '#3b82f6', progress: '#93c5fd', guidelines: '#dbeafe' };
|
||||
var STATUS_LABELS = {
|
||||
en: { enforced: 'Enforced', passed: 'Passed', progress: 'In Progress', guidelines: 'Guidelines' },
|
||||
de: { enforced: 'In Kraft', passed: 'Verabschiedet', progress: 'In Bearbeitung', guidelines: 'Richtlinien' },
|
||||
fr: { enforced: 'En vigueur', passed: 'Adopté', progress: 'En cours', guidelines: 'Directives' }
|
||||
};
|
||||
|
||||
var countries = {{ $countries | jsonify }};
|
||||
var byIsoNum = {};
|
||||
countries.forEach(function(c) { byIsoNum[c.isoNum] = c; });
|
||||
|
||||
var map = L.map('ifk-world-map', {
|
||||
center: [25, 10], zoom: 2, minZoom: 2, maxZoom: 6,
|
||||
scrollWheelZoom: false, zoomControl: true
|
||||
});
|
||||
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||
maxZoom: 6
|
||||
}).addTo(map);
|
||||
|
||||
fetch('https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json')
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(topo) {
|
||||
var geo = topojson.feature(topo, topo.objects.countries);
|
||||
L.geoJSON(geo, {
|
||||
style: function(feature) {
|
||||
var id = String(feature.id).padStart(3, '0');
|
||||
var c = byIsoNum[id];
|
||||
return {
|
||||
fillColor: c ? STATUS_COLORS[c.status] : '#e2e8f0',
|
||||
weight: 0.8,
|
||||
color: '#94a3b8',
|
||||
fillOpacity: c ? 0.8 : 0.3
|
||||
};
|
||||
},
|
||||
onEachFeature: function(feature, layer) {
|
||||
var id = String(feature.id).padStart(3, '0');
|
||||
var c = byIsoNum[id];
|
||||
if (!c) return;
|
||||
var loc = c[LANG] || c.en;
|
||||
var labels = STATUS_LABELS[LANG] || STATUS_LABELS.en;
|
||||
layer.bindPopup(
|
||||
'<strong>' + c.flag + ' ' + loc.name + '</strong><br>' +
|
||||
'<em>' + loc.law + '</em><br>' +
|
||||
'<span style="color:' + STATUS_COLORS[c.status] + ';font-weight:600">' + labels[c.status] + '</span> (' + c.year + ')<br>' +
|
||||
loc.detail
|
||||
);
|
||||
layer.on('mouseover', function(e) { e.target.setStyle({ weight: 2, color: '#1e293b' }); });
|
||||
layer.on('mouseout', function(e) { e.target.setStyle({ weight: 0.8, color: '#94a3b8' }); });
|
||||
}
|
||||
}).addTo(map);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
Reference in New Issue
Block a user