Compare commits
16 Commits
session/CF
...
session/CF
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dd4a68d71 | ||
|
|
7f6d96cbe7 | ||
|
|
e732b9d96e | ||
|
|
18dc7ae66f | ||
|
|
ec370d2d7e | ||
|
|
b517af5c2f | ||
|
|
852640a574 | ||
|
|
09a11520e8 | ||
|
|
df72e6aaba | ||
|
|
308034e40d | ||
|
|
5e76d8745a | ||
|
|
2dfc9ed8bd | ||
|
|
b6951ec29d | ||
|
|
99350eef8a | ||
|
|
c7376db2cb | ||
|
|
ba41263e48 |
@@ -30,7 +30,7 @@ env:
|
|||||||
REMOTE_USER: root
|
REMOTE_USER: root
|
||||||
DEPLOY_PATH: /opt/apps/internetforkids
|
DEPLOY_PATH: /opt/apps/internetforkids
|
||||||
HEALTH_ENDPOINT: "http://localhost:3006/health"
|
HEALTH_ENDPOINT: "http://localhost:3006/health"
|
||||||
PUBLIC_URL: "https://internetforkids.ong"
|
PUBLIC_URL: "https://internetforkids.org"
|
||||||
HEALTH_TIMEOUT: 60
|
HEALTH_TIMEOUT: 60
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -163,6 +163,24 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
echo "All smoke tests passed"
|
echo "All smoke tests passed"
|
||||||
|
|
||||||
|
indexnow:
|
||||||
|
name: IndexNow Ping
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [smoke-test]
|
||||||
|
steps:
|
||||||
|
- name: Notify search engines
|
||||||
|
run: |
|
||||||
|
KEY="40101d97ec848f6ea016fac347b1a5bc"
|
||||||
|
for url in \
|
||||||
|
"https://internetforkids.org/" \
|
||||||
|
"https://internetforkids.org/en/" \
|
||||||
|
"https://internetforkids.org/de/" \
|
||||||
|
"https://internetforkids.org/fr/" \
|
||||||
|
"https://internetforkids.org/sitemap.xml"; do
|
||||||
|
curl -sf "https://api.indexnow.org/indexnow?url=${url}&key=${KEY}" || true
|
||||||
|
done
|
||||||
|
echo "IndexNow pings sent"
|
||||||
|
|
||||||
promote:
|
promote:
|
||||||
name: Promote to Latest
|
name: Promote to Latest
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
6
.session/metadata.env
Normal file
6
.session/metadata.env
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
SESSION_ISSUE_KEY=CF-2812
|
||||||
|
PROJECT_DIR=/Users/christian.gick/Development/Apps/internetforkids
|
||||||
|
WORKSPACE_PATH=/Users/christian.gick/.claude/workspaces/cf-2812
|
||||||
|
BASE_BRANCH=main
|
||||||
|
CREATED_AT=1775206558
|
||||||
|
CLAUDE_PID=74267
|
||||||
3
.session/notes.md
Normal file
3
.session/notes.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Session CF-2812
|
||||||
|
Started: 2026-04-03 11:55
|
||||||
|
Project: internetforkids
|
||||||
0
.session/plan.md
Normal file
0
.session/plan.md
Normal file
202
assets/css/custom.css
Normal file
202
assets/css/custom.css
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/* Internet for Kids — Newsreader typography (darioamodei.com-inspired)
|
||||||
|
Warm, literary, research-publication feel */
|
||||||
|
|
||||||
|
/* Local Newsreader font — latin */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-latin.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
/* latin-ext (DE umlauts, FR accents) */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-latin-ext.woff2) format('woff2');
|
||||||
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
/* italic latin */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400 500;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-italic-latin.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
/* italic latin-ext */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400 500;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-italic-latin-ext.woff2) format('woff2');
|
||||||
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--ifk-font: 'Newsreader', 'Times New Roman', serif;
|
||||||
|
--ifk-text: #1c1917;
|
||||||
|
--ifk-bg: #fafaf9;
|
||||||
|
--ifk-accent: #4d7c0f;
|
||||||
|
--ifk-accent-hover: #3f6212;
|
||||||
|
--ifk-secondary: #059669;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global background */
|
||||||
|
body {
|
||||||
|
background-color: var(--ifk-bg) !important;
|
||||||
|
color: var(--ifk-text) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Override Congo's dark bg classes */
|
||||||
|
.bg-neutral {
|
||||||
|
background-color: var(--ifk-bg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All text in Newsreader */
|
||||||
|
body, p, li, td, th, blockquote, figcaption {
|
||||||
|
font-family: var(--ifk-font) !important;
|
||||||
|
font-size: 22px;
|
||||||
|
line-height: 36px;
|
||||||
|
color: var(--ifk-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Headings */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: var(--ifk-font) !important;
|
||||||
|
color: var(--ifk-text);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, .article-title {
|
||||||
|
font-size: 2.75rem;
|
||||||
|
line-height: 1.15;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.85rem;
|
||||||
|
line-height: 1.25;
|
||||||
|
margin-top: 3rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Article content — constrain width for readability */
|
||||||
|
article .prose,
|
||||||
|
article .content,
|
||||||
|
.article-content {
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Paragraphs */
|
||||||
|
article p {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links — subtle, Amodei-style */
|
||||||
|
article a {
|
||||||
|
color: var(--ifk-accent);
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-thickness: 1px;
|
||||||
|
text-underline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
article a:hover {
|
||||||
|
color: var(--ifk-accent-hover);
|
||||||
|
text-decoration-thickness: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blockquotes — elegant left-border */
|
||||||
|
blockquote {
|
||||||
|
font-family: var(--ifk-font) !important;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 38px;
|
||||||
|
border-left: 3px solid var(--ifk-secondary);
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
margin: 2rem 0;
|
||||||
|
color: var(--ifk-text);
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation — keep sans-serif for UI elements */
|
||||||
|
nav, nav a, nav span,
|
||||||
|
header, header a,
|
||||||
|
footer, footer a, footer span,
|
||||||
|
.breadcrumbs, .taxonomy-list,
|
||||||
|
.article-meta, .post-meta,
|
||||||
|
time, .reading-time {
|
||||||
|
font-family: system-ui, -apple-system, 'Segoe UI', sans-serif !important;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header title */
|
||||||
|
header a[href="/"] span,
|
||||||
|
header a[rel="me"] {
|
||||||
|
font-family: var(--ifk-font) !important;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tags/categories — small sans pills */
|
||||||
|
.taxonomy-term, [href*="/tags/"], [href*="/categories/"] {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif !important;
|
||||||
|
font-size: 0.8rem !important;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table of contents — smaller sans */
|
||||||
|
#TableOfContents, #TableOfContents a {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif !important;
|
||||||
|
font-size: 0.95rem !important;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Homepage recent articles */
|
||||||
|
.summary {
|
||||||
|
font-family: var(--ifk-font) !important;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Data tables in articles — keep readable */
|
||||||
|
.csm-table, .csm-table td, .csm-table th {
|
||||||
|
font-family: var(--ifk-font) !important;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stats banner — override with sans for numbers */
|
||||||
|
.ifk-stat-num {
|
||||||
|
font-family: var(--ifk-font) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ifk-stat-label {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chart labels keep sans */
|
||||||
|
.ifk-chart-card h4 {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smooth dark mode override (if ever enabled) */
|
||||||
|
/* Status badges keep their blue palette */
|
||||||
|
.csm-enforced { background: var(--ifk-accent) !important; }
|
||||||
|
.csm-passed { background: var(--ifk-secondary) !important; }
|
||||||
|
.csm-progress { background: #86efac !important; color: #14532d !important; }
|
||||||
|
.csm-guidelines { background: #d1fae5 !important; color: #065f46 !important; }
|
||||||
324
assets/css/main.css
Normal file
324
assets/css/main.css
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
/* Custom font imports */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-latin.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-latin-ext.woff2) format('woff2');
|
||||||
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400 500;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-italic-latin.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400 500;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-italic-latin-ext.woff2) format('woff2');
|
||||||
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CSS Variables */
|
||||||
|
:root {
|
||||||
|
--ifk-font: 'Newsreader', 'Times New Roman', serif;
|
||||||
|
--ifk-text: #1c1917;
|
||||||
|
--ifk-bg: #fafaf9;
|
||||||
|
--ifk-accent: #4d7c0f;
|
||||||
|
--ifk-accent-hover: #3f6212;
|
||||||
|
--ifk-secondary: #059669;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility classes for colors */
|
||||||
|
.text-ifk-accent { color: var(--ifk-accent); }
|
||||||
|
.text-ifk-text { color: var(--ifk-text); }
|
||||||
|
.bg-ifk-bg { background-color: var(--ifk-bg); }
|
||||||
|
.hover\:text-ifk-accent:hover { color: var(--ifk-accent); }
|
||||||
|
.hover\:text-ifk-accent-hover:hover { color: var(--ifk-accent-hover); }
|
||||||
|
|
||||||
|
/* Font family utility */
|
||||||
|
.font-newsreader { font-family: var(--ifk-font); }
|
||||||
|
|
||||||
|
/* Tailwind-equivalent utilities */
|
||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
.flex { display: flex; }
|
||||||
|
.flex-1 { flex: 1 1 0%; }
|
||||||
|
.flex-wrap { flex-wrap: wrap; }
|
||||||
|
.inline-block { display: inline-block; }
|
||||||
|
.grid { display: grid; }
|
||||||
|
.grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
|
||||||
|
.justify-between { justify-content: space-between; }
|
||||||
|
.items-center { align-items: center; }
|
||||||
|
.gap-4 { gap: 1rem; }
|
||||||
|
.gap-8 { gap: 2rem; }
|
||||||
|
.mx-auto { margin-left: auto; margin-right: auto; }
|
||||||
|
.max-w-2xl { max-width: 42rem; }
|
||||||
|
.max-w-3xl { max-width: 48rem; }
|
||||||
|
.max-w-4xl { max-width: 56rem; }
|
||||||
|
.px-4 { padding-left: 1rem; padding-right: 1rem; }
|
||||||
|
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
|
||||||
|
.py-12 { padding-top: 3rem; padding-bottom: 3rem; }
|
||||||
|
.p-4 { padding: 1rem; }
|
||||||
|
.pt-8 { padding-top: 2rem; }
|
||||||
|
.mb-2 { margin-bottom: 0.5rem; }
|
||||||
|
.mb-3 { margin-bottom: 0.75rem; }
|
||||||
|
.mb-4 { margin-bottom: 1rem; }
|
||||||
|
.mb-8 { margin-bottom: 2rem; }
|
||||||
|
.mb-12 { margin-bottom: 3rem; }
|
||||||
|
.mr-2 { margin-right: 0.5rem; }
|
||||||
|
.mt-12 { margin-top: 3rem; }
|
||||||
|
.mt-20 { margin-top: 5rem; }
|
||||||
|
.sticky { position: sticky; }
|
||||||
|
.top-0 { top: 0; }
|
||||||
|
.z-40 { z-index: 40; }
|
||||||
|
.border { border: 1px solid #e5e7eb; }
|
||||||
|
.border-t { border-top: 1px solid #e5e7eb; }
|
||||||
|
.border-b { border-bottom: 1px solid #e5e7eb; }
|
||||||
|
.rounded { border-radius: 0.25rem; }
|
||||||
|
.bg-white { background-color: #fff; }
|
||||||
|
.bg-gray-50 { background-color: #f9fafb; }
|
||||||
|
.text-center { text-align: center; }
|
||||||
|
.text-left { text-align: left; }
|
||||||
|
.text-right { text-align: right; }
|
||||||
|
.text-xs { font-size: 0.75rem; line-height: 1rem; }
|
||||||
|
.text-sm { font-size: 0.875rem; line-height: 1.25rem; }
|
||||||
|
.text-lg { font-size: 1.125rem; line-height: 1.75rem; }
|
||||||
|
.text-xl { font-size: 1.25rem; line-height: 1.75rem; }
|
||||||
|
.text-4xl { font-size: 2.75rem; line-height: 1.15; }
|
||||||
|
.font-semibold { font-weight: 600; }
|
||||||
|
.uppercase { text-transform: uppercase; }
|
||||||
|
.tracking-wide { letter-spacing: 0.025em; }
|
||||||
|
.leading-tight { line-height: 1.25; }
|
||||||
|
.leading-relaxed { line-height: 1.625; }
|
||||||
|
.text-gray-600 { color: #4b5563; }
|
||||||
|
.hover\:bg-gray-50:hover { background-color: #f9fafb; }
|
||||||
|
@media (min-width: 768px) { .md\:grid-cols-3 { grid-template-columns: repeat(3, 1fr); } }
|
||||||
|
|
||||||
|
/* Global typography */
|
||||||
|
body {
|
||||||
|
background-color: var(--ifk-bg);
|
||||||
|
color: var(--ifk-text);
|
||||||
|
font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
article, .prose {
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
color: var(--ifk-text);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, .article-title {
|
||||||
|
font-size: 2.75rem;
|
||||||
|
line-height: 1.15;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.85rem;
|
||||||
|
line-height: 1.25;
|
||||||
|
margin-top: 3rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Article content */
|
||||||
|
article p {
|
||||||
|
font-size: 1.375rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
article a {
|
||||||
|
color: var(--ifk-accent);
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-thickness: 1px;
|
||||||
|
text-underline-offset: 2px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
article a:hover {
|
||||||
|
color: var(--ifk-accent-hover);
|
||||||
|
text-decoration-thickness: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blockquotes */
|
||||||
|
blockquote {
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
border-left: 3px solid var(--ifk-secondary);
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
margin: 2rem 0;
|
||||||
|
color: var(--ifk-text);
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
code {
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
background: #f3f4f6;
|
||||||
|
padding: 0.1rem 0.4rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: #1f2937;
|
||||||
|
color: #f3f4f6;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
font-size: 1.1rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background: #f3f4f6;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lists */
|
||||||
|
ul, ol {
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
font-size: 1.375rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation */
|
||||||
|
nav, header, footer {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a {
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a:hover {
|
||||||
|
color: var(--ifk-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Article metadata */
|
||||||
|
.article-meta, .post-meta, time, .reading-time {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tags */
|
||||||
|
.taxonomy-term, [href*="/tags/"], [href*="/categories/"] {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--ifk-accent);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.taxonomy-term:hover, [href*="/tags/"]:hover, [href*="/categories/"]:hover {
|
||||||
|
color: var(--ifk-accent-hover);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table of Contents */
|
||||||
|
#TableOfContents {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
#TableOfContents a {
|
||||||
|
color: var(--ifk-accent);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#TableOfContents a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Status badges (for shortcodes) */
|
||||||
|
.csm-enforced { background: var(--ifk-accent); color: white; }
|
||||||
|
.csm-passed { background: var(--ifk-secondary); color: white; }
|
||||||
|
.csm-progress { background: #86efac; color: #14532d; }
|
||||||
|
.csm-guidelines { background: #d1fae5; color: #065f46; }
|
||||||
|
|
||||||
|
/* Shortcode-specific overrides */
|
||||||
|
.ifk-stat-num { font-family: var(--ifk-font); }
|
||||||
|
.ifk-stat-label { font-family: system-ui, -apple-system, sans-serif; }
|
||||||
|
.ifk-chart-card h4 { font-family: system-ui, -apple-system, sans-serif; }
|
||||||
|
|
||||||
|
/* Responsive design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
h1, .article-title {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article p, li {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,23 +28,23 @@ contentDir = "content/de"
|
|||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
identifier = "about"
|
identifier = "about"
|
||||||
name = "Über uns"
|
name = "Über uns"
|
||||||
url = "/about/"
|
pageRef = "/about"
|
||||||
weight = 2
|
weight = 2
|
||||||
|
|
||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
identifier = "tags"
|
identifier = "tags"
|
||||||
name = "Themen"
|
name = "Themen"
|
||||||
url = "/tags/"
|
pageRef = "/tags"
|
||||||
weight = 3
|
weight = 3
|
||||||
|
|
||||||
[[menus.footer]]
|
[[menus.footer]]
|
||||||
identifier = "impressum"
|
identifier = "impressum"
|
||||||
name = "Impressum"
|
name = "Impressum"
|
||||||
url = "/impressum/"
|
pageRef = "/impressum"
|
||||||
weight = 1
|
weight = 1
|
||||||
|
|
||||||
[[menus.footer]]
|
[[menus.footer]]
|
||||||
identifier = "privacy"
|
identifier = "privacy"
|
||||||
name = "Datenschutzerklärung"
|
name = "Datenschutzerklärung"
|
||||||
url = "/datenschutz/"
|
pageRef = "/datenschutz"
|
||||||
weight = 2
|
weight = 2
|
||||||
|
|||||||
@@ -28,23 +28,23 @@ contentDir = "content/en"
|
|||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
identifier = "about"
|
identifier = "about"
|
||||||
name = "About"
|
name = "About"
|
||||||
url = "/about/"
|
pageRef = "/about"
|
||||||
weight = 2
|
weight = 2
|
||||||
|
|
||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
identifier = "tags"
|
identifier = "tags"
|
||||||
name = "Topics"
|
name = "Topics"
|
||||||
url = "/tags/"
|
pageRef = "/tags"
|
||||||
weight = 3
|
weight = 3
|
||||||
|
|
||||||
[[menus.footer]]
|
[[menus.footer]]
|
||||||
identifier = "impressum"
|
identifier = "impressum"
|
||||||
name = "Imprint"
|
name = "Imprint"
|
||||||
url = "/imprint/"
|
pageRef = "/imprint"
|
||||||
weight = 1
|
weight = 1
|
||||||
|
|
||||||
[[menus.footer]]
|
[[menus.footer]]
|
||||||
identifier = "privacy"
|
identifier = "privacy"
|
||||||
name = "Privacy Policy"
|
name = "Privacy Policy"
|
||||||
url = "/privacy/"
|
pageRef = "/privacy"
|
||||||
weight = 2
|
weight = 2
|
||||||
|
|||||||
@@ -28,23 +28,23 @@ contentDir = "content/fr"
|
|||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
identifier = "about"
|
identifier = "about"
|
||||||
name = "À propos"
|
name = "À propos"
|
||||||
url = "/about/"
|
pageRef = "/about"
|
||||||
weight = 2
|
weight = 2
|
||||||
|
|
||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
identifier = "tags"
|
identifier = "tags"
|
||||||
name = "Sujets"
|
name = "Sujets"
|
||||||
url = "/tags/"
|
pageRef = "/tags"
|
||||||
weight = 3
|
weight = 3
|
||||||
|
|
||||||
[[menus.footer]]
|
[[menus.footer]]
|
||||||
identifier = "impressum"
|
identifier = "impressum"
|
||||||
name = "Mentions légales"
|
name = "Mentions légales"
|
||||||
url = "/mentions-legales/"
|
pageRef = "/mentions-legales"
|
||||||
weight = 1
|
weight = 1
|
||||||
|
|
||||||
[[menus.footer]]
|
[[menus.footer]]
|
||||||
identifier = "privacy"
|
identifier = "privacy"
|
||||||
name = "Politique de confidentialité"
|
name = "Politique de confidentialité"
|
||||||
url = "/politique-de-confidentialite/"
|
pageRef = "/politique-de-confidentialite"
|
||||||
weight = 2
|
weight = 2
|
||||||
|
|||||||
@@ -1,34 +1,18 @@
|
|||||||
colorScheme = "avocado"
|
colorScheme = "light"
|
||||||
defaultAppearance = "light"
|
defaultAppearance = "light"
|
||||||
autoSwitchAppearance = false
|
autoSwitchAppearance = false
|
||||||
mainSections = [""]
|
mainSections = [""]
|
||||||
|
|
||||||
|
# Blox Core config
|
||||||
|
minimal = false
|
||||||
|
|
||||||
[header]
|
[header]
|
||||||
layout = "basic"
|
navbar = true
|
||||||
showTitle = true
|
|
||||||
|
|
||||||
[footer]
|
[footer]
|
||||||
showCopyright = true
|
copyright = "© Internet for Kids"
|
||||||
showThemeAttribution = false
|
privacyPolicy = "/privacy"
|
||||||
showScrollToTop = true
|
|
||||||
showAppearanceSwitcher = false
|
|
||||||
|
|
||||||
[homepage]
|
[appearance]
|
||||||
layout = "profile"
|
color_theme = "ifk"
|
||||||
showRecent = true
|
font_theme = "ifk_fonts"
|
||||||
recentLimit = 5
|
|
||||||
|
|
||||||
[article]
|
|
||||||
showDate = true
|
|
||||||
showReadingTime = true
|
|
||||||
showAuthor = true
|
|
||||||
showBreadcrumbs = true
|
|
||||||
showTableOfContents = true
|
|
||||||
showTaxonomies = true
|
|
||||||
|
|
||||||
[list]
|
|
||||||
showBreadcrumbs = true
|
|
||||||
showTaxonomies = true
|
|
||||||
|
|
||||||
[taxonomy]
|
|
||||||
showTermCount = true
|
|
||||||
|
|||||||
@@ -13,8 +13,16 @@ Regierungen auf der ganzen Welt ergreifen beispiellose Maßnahmen zum Schutz von
|
|||||||
|
|
||||||
Hier erfahren Sie, was Sie über die wichtigsten Kinderschutzgesetze wissen müssen, die in diesem Jahr in Kraft treten.
|
Hier erfahren Sie, was Sie über die wichtigsten Kinderschutzgesetze wissen müssen, die in diesem Jahr in Kraft treten.
|
||||||
|
|
||||||
|
{{< stats-banner >}}
|
||||||
|
|
||||||
|
{{< world-map >}}
|
||||||
|
|
||||||
{{< child-safety-map >}}
|
{{< child-safety-map >}}
|
||||||
|
|
||||||
|
{{< law-charts >}}
|
||||||
|
|
||||||
|
{{< legislation-timeline >}}
|
||||||
|
|
||||||
## Australien: Das erste Land mit Social-Media-Verbot für unter 16-Jährige
|
## Australien: Das erste Land mit Social-Media-Verbot für unter 16-Jährige
|
||||||
|
|
||||||
Im Dezember 2025 wurde Australien das erste Land der Welt, das ein umfassendes Social-Media-Verbot für Nutzer unter 16 Jahren durchsetzt. Der *Online Safety Amendment (Social Media Minimum Age) Act 2024* verpflichtet Plattformen wie TikTok, Instagram, Snapchat, YouTube und X (ehemals Twitter), „angemessene Maßnahmen" zu ergreifen, um Minderjährige an der Erstellung oder Beibehaltung von Konten zu hindern.
|
Im Dezember 2025 wurde Australien das erste Land der Welt, das ein umfassendes Social-Media-Verbot für Nutzer unter 16 Jahren durchsetzt. Der *Online Safety Amendment (Social Media Minimum Age) Act 2024* verpflichtet Plattformen wie TikTok, Instagram, Snapchat, YouTube und X (ehemals Twitter), „angemessene Maßnahmen" zu ergreifen, um Minderjährige an der Erstellung oder Beibehaltung von Konten zu hindern.
|
||||||
|
|||||||
@@ -13,8 +13,16 @@ Governments around the world are taking unprecedented action to protect children
|
|||||||
|
|
||||||
Here is what you need to know about the most important child protection laws taking effect this year.
|
Here is what you need to know about the most important child protection laws taking effect this year.
|
||||||
|
|
||||||
|
{{< stats-banner >}}
|
||||||
|
|
||||||
|
{{< world-map >}}
|
||||||
|
|
||||||
{{< child-safety-map >}}
|
{{< child-safety-map >}}
|
||||||
|
|
||||||
|
{{< law-charts >}}
|
||||||
|
|
||||||
|
{{< legislation-timeline >}}
|
||||||
|
|
||||||
## Australia: The First Country to Ban Social Media for Under-16s
|
## Australia: The First Country to Ban Social Media for Under-16s
|
||||||
|
|
||||||
In December 2025, Australia became the first country in the world to enforce a blanket social media ban for users under 16. The *Online Safety Amendment (Social Media Minimum Age) Act 2024* requires platforms like TikTok, Instagram, Snapchat, YouTube, and X (formerly Twitter) to take "reasonable steps" to prevent minors from creating or maintaining accounts.
|
In December 2025, Australia became the first country in the world to enforce a blanket social media ban for users under 16. The *Online Safety Amendment (Social Media Minimum Age) Act 2024* requires platforms like TikTok, Instagram, Snapchat, YouTube, and X (formerly Twitter) to take "reasonable steps" to prevent minors from creating or maintaining accounts.
|
||||||
|
|||||||
@@ -13,8 +13,16 @@ Les gouvernements du monde entier prennent des mesures sans précédent pour pro
|
|||||||
|
|
||||||
Voici ce que vous devez savoir sur les lois de protection de l'enfance les plus importantes qui entrent en vigueur cette année.
|
Voici ce que vous devez savoir sur les lois de protection de l'enfance les plus importantes qui entrent en vigueur cette année.
|
||||||
|
|
||||||
|
{{< stats-banner >}}
|
||||||
|
|
||||||
|
{{< world-map >}}
|
||||||
|
|
||||||
{{< child-safety-map >}}
|
{{< child-safety-map >}}
|
||||||
|
|
||||||
|
{{< law-charts >}}
|
||||||
|
|
||||||
|
{{< legislation-timeline >}}
|
||||||
|
|
||||||
## Australie : le premier pays à interdire les réseaux sociaux aux moins de 16 ans
|
## Australie : le premier pays à interdire les réseaux sociaux aux moins de 16 ans
|
||||||
|
|
||||||
En décembre 2025, l'Australie est devenue le premier pays au monde à appliquer une interdiction générale des réseaux sociaux pour les utilisateurs de moins de 16 ans. Le *Online Safety Amendment (Social Media Minimum Age) Act 2024* oblige les plateformes comme TikTok, Instagram, Snapchat, YouTube et X (anciennement Twitter) à prendre des « mesures raisonnables » pour empêcher les mineurs de créer ou de maintenir des comptes.
|
En décembre 2025, l'Australie est devenue le premier pays au monde à appliquer une interdiction générale des réseaux sociaux pour les utilisateurs de moins de 16 ans. Le *Online Safety Amendment (Social Media Minimum Age) Act 2024* oblige les plateformes comme TikTok, Instagram, Snapchat, YouTube et X (anciennement Twitter) à prendre des « mesures raisonnables » pour empêcher les mineurs de créer ou de maintenir des comptes.
|
||||||
|
|||||||
86
data/countries.json
Normal file
86
data/countries.json
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
[
|
||||||
|
{"iso3": "AUS", "isoNum": "036", "flag": "🇦🇺", "status": "enforced", "year": 2024, "ageLimitSocial": 16,
|
||||||
|
"en": {"name": "Australia", "law": "Social Media Minimum Age Act 2024", "detail": "Social media ban for under-16s. Fines up to AUD 49.5M."},
|
||||||
|
"de": {"name": "Australien", "law": "Social Media Minimum Age Act 2024", "detail": "Social-Media-Verbot für unter 16-Jährige. Bußgelder bis 49,5 Mio. AUD."},
|
||||||
|
"fr": {"name": "Australie", "law": "Social Media Minimum Age Act 2024", "detail": "Interdiction des réseaux sociaux pour les moins de 16 ans. Amendes jusqu'à 49,5 M AUD."}},
|
||||||
|
|
||||||
|
{"iso3": "GBR", "isoNum": "826", "flag": "🇬🇧", "status": "enforced", "year": 2023, "ageLimitSocial": 13,
|
||||||
|
"en": {"name": "United Kingdom", "law": "Online Safety Act 2023", "detail": "Comprehensive online safety regime. Age verification required."},
|
||||||
|
"de": {"name": "Vereinigtes Königreich", "law": "Online Safety Act 2023", "detail": "Umfassendes Online-Sicherheitsregime. Altersverifikation erforderlich."},
|
||||||
|
"fr": {"name": "Royaume-Uni", "law": "Online Safety Act 2023", "detail": "Régime complet de sécurité en ligne. Vérification d'âge obligatoire."}},
|
||||||
|
|
||||||
|
{"iso3": "DEU", "isoNum": "276", "flag": "🇩🇪", "status": "enforced", "year": 2021, "ageLimitSocial": 13,
|
||||||
|
"en": {"name": "Germany", "law": "Jugendschutzgesetz (JuSchG)", "detail": "Youth Protection Act extended to online platforms. BzKJ monitoring."},
|
||||||
|
"de": {"name": "Deutschland", "law": "Jugendschutzgesetz (JuSchG)", "detail": "Auf Online-Plattformen ausgeweitet. BzKJ überwacht aktiv die Einhaltung."},
|
||||||
|
"fr": {"name": "Allemagne", "law": "Jugendschutzgesetz (JuSchG)", "detail": "Loi sur la protection de la jeunesse étendue aux plateformes en ligne. Surveillance BzKJ."}},
|
||||||
|
|
||||||
|
{"iso3": "CHN", "isoNum": "156", "flag": "🇨🇳", "status": "enforced", "year": 2021, "ageLimitSocial": 14,
|
||||||
|
"en": {"name": "China", "law": "Minor Protection Law", "detail": "1hr/day gaming for minors. Real-name verification mandatory."},
|
||||||
|
"de": {"name": "China", "law": "Minderjährigenschutzgesetz", "detail": "1 Std./Tag Gaming für Minderjährige. Echtnamen-Verifizierung verpflichtend."},
|
||||||
|
"fr": {"name": "Chine", "law": "Loi sur la protection des mineurs", "detail": "1h/jour de jeux vidéo pour les mineurs. Vérification d'identité obligatoire."}},
|
||||||
|
|
||||||
|
{"iso3": "KOR", "isoNum": "410", "flag": "🇰🇷", "status": "enforced", "year": 2020, "ageLimitSocial": 14,
|
||||||
|
"en": {"name": "South Korea", "law": "Youth Protection Act", "detail": "Long-standing youth protection framework. Real-name verification."},
|
||||||
|
"de": {"name": "Südkorea", "law": "Jugendschutzgesetz", "detail": "Langjähriger Jugendschutzrahmen. Echtnamen-Verifizierung für Online-Dienste."},
|
||||||
|
"fr": {"name": "Corée du Sud", "law": "Loi sur la protection de la jeunesse", "detail": "Cadre de protection de la jeunesse établi de longue date. Vérification d'identité."}},
|
||||||
|
|
||||||
|
{"iso3": "IRL", "isoNum": "372", "flag": "🇮🇪", "status": "enforced", "year": 2022, "ageLimitSocial": 13,
|
||||||
|
"en": {"name": "Ireland", "law": "Online Safety and Media Regulation Act", "detail": "Coimisiún na Meán regulates online safety with binding codes."},
|
||||||
|
"de": {"name": "Irland", "law": "Online Safety and Media Regulation Act", "detail": "Coimisiún na Meán reguliert Online-Sicherheit mit verbindlichen Kodizes."},
|
||||||
|
"fr": {"name": "Irlande", "law": "Online Safety and Media Regulation Act", "detail": "Coimisiún na Meán régule la sécurité en ligne avec des codes contraignants."}},
|
||||||
|
|
||||||
|
{"iso3": "NLD", "isoNum": "528", "flag": "🇳🇱", "status": "enforced", "year": 2024, "ageLimitSocial": 16,
|
||||||
|
"en": {"name": "Netherlands", "law": "DSA + Children's Code", "detail": "Dutch DPA actively enforcing children's data protection."},
|
||||||
|
"de": {"name": "Niederlande", "law": "DSA + Kinderkodex", "detail": "Datenschutzbehörde setzt Kinderdatenschutz aktiv durch."},
|
||||||
|
"fr": {"name": "Pays-Bas", "law": "DSA + Code de l'enfance", "detail": "Autorité de protection des données applique activement la protection des données des enfants."}},
|
||||||
|
|
||||||
|
{"iso3": "SWE", "isoNum": "752", "flag": "🇸🇪", "status": "enforced", "year": 2024, "ageLimitSocial": 13,
|
||||||
|
"en": {"name": "Sweden", "law": "DSA + National Youth Guidelines", "detail": "EU DSA framework plus national youth protection guidelines."},
|
||||||
|
"de": {"name": "Schweden", "law": "DSA + Nationale Jugendrichtlinien", "detail": "EU-DSA-Rahmen plus nationale Jugendschutzrichtlinien."},
|
||||||
|
"fr": {"name": "Suède", "law": "DSA + Directives nationales jeunesse", "detail": "Cadre DSA de l'UE plus directives nationales de protection de la jeunesse."}},
|
||||||
|
|
||||||
|
{"iso3": "FRA", "isoNum": "250", "flag": "🇫🇷", "status": "passed", "year": 2026, "ageLimitSocial": 15,
|
||||||
|
"en": {"name": "France", "law": "Loi SREN + Social Media Ban", "detail": "Senate votes to ban social media for under-15s (April 2026). Arcom blacklist."},
|
||||||
|
"de": {"name": "Frankreich", "law": "Loi SREN + Social-Media-Verbot", "detail": "Senat stimmt für Social-Media-Verbot unter 15 (April 2026). Arcom-Blacklist."},
|
||||||
|
"fr": {"name": "France", "law": "Loi SREN + Interdiction réseaux sociaux", "detail": "Le Sénat vote l'interdiction des réseaux sociaux pour les moins de 15 ans (avril 2026)."}},
|
||||||
|
|
||||||
|
{"iso3": "BRA", "isoNum": "076", "flag": "🇧🇷", "status": "passed", "year": 2025, "ageLimitSocial": 12,
|
||||||
|
"en": {"name": "Brazil", "law": "ECA Digital", "detail": "Loot box ban for minors. Age-appropriate design requirements."},
|
||||||
|
"de": {"name": "Brasilien", "law": "ECA Digital", "detail": "Lootbox-Verbot für Minderjährige. Altersgerechtes Design."},
|
||||||
|
"fr": {"name": "Brésil", "law": "ECA Digital", "detail": "Interdiction des loot boxes pour les mineurs. Exigences de design adapté à l'âge."}},
|
||||||
|
|
||||||
|
{"iso3": "IND", "isoNum": "356", "flag": "🇮🇳", "status": "passed", "year": 2023, "ageLimitSocial": 18,
|
||||||
|
"en": {"name": "India", "law": "DPDP Act 2023", "detail": "Verifiable parental consent for under-18s."},
|
||||||
|
"de": {"name": "Indien", "law": "DPDP Act 2023", "detail": "Verifizierbare elterliche Einwilligung für unter 18-Jährige."},
|
||||||
|
"fr": {"name": "Inde", "law": "DPDP Act 2023", "detail": "Consentement parental vérifiable pour les moins de 18 ans."}},
|
||||||
|
|
||||||
|
{"iso3": "ITA", "isoNum": "380", "flag": "🇮🇹", "status": "passed", "year": 2025, "ageLimitSocial": 14,
|
||||||
|
"en": {"name": "Italy", "law": "DSA + Parental Consent Law", "detail": "Digital age of consent set to 14."},
|
||||||
|
"de": {"name": "Italien", "law": "DSA + Einwilligungsgesetz", "detail": "Digitales Einwilligungsalter auf 14 festgelegt."},
|
||||||
|
"fr": {"name": "Italie", "law": "DSA + Loi sur le consentement parental", "detail": "Âge de consentement numérique fixé à 14 ans."}},
|
||||||
|
|
||||||
|
{"iso3": "ESP", "isoNum": "724", "flag": "🇪🇸", "status": "passed", "year": 2025, "ageLimitSocial": 14,
|
||||||
|
"en": {"name": "Spain", "law": "Child Protection in Digital Environments", "detail": "Comprehensive child digital protection law."},
|
||||||
|
"de": {"name": "Spanien", "law": "Organisches Kinderschutzgesetz", "detail": "Umfassendes digitales Kinderschutzgesetz."},
|
||||||
|
"fr": {"name": "Espagne", "law": "Protection de l'enfance dans les environnements numériques", "detail": "Loi complète de protection numérique de l'enfance."}},
|
||||||
|
|
||||||
|
{"iso3": "NOR", "isoNum": "578", "flag": "🇳🇴", "status": "passed", "year": 2025, "ageLimitSocial": 15,
|
||||||
|
"en": {"name": "Norway", "law": "Social Media Age Limit", "detail": "Proposed social media age limit of 15."},
|
||||||
|
"de": {"name": "Norwegen", "law": "Social-Media-Altersgrenze", "detail": "Geplante Altersgrenze von 15 Jahren."},
|
||||||
|
"fr": {"name": "Norvège", "law": "Limite d'âge réseaux sociaux", "detail": "Limite d'âge proposée à 15 ans."}},
|
||||||
|
|
||||||
|
{"iso3": "USA", "isoNum": "840", "flag": "🇺🇸", "status": "progress", "year": 2026, "ageLimitSocial": 13,
|
||||||
|
"en": {"name": "United States", "law": "KOSA + COPPA Update", "detail": "KOSA passed Senate 91-3. COPPA update by Apr 2026."},
|
||||||
|
"de": {"name": "Vereinigte Staaten", "law": "KOSA + COPPA-Update", "detail": "KOSA im Senat angenommen. COPPA-Update bis Apr. 2026."},
|
||||||
|
"fr": {"name": "États-Unis", "law": "KOSA + Mise à jour COPPA", "detail": "KOSA adopté au Sénat 91-3. Mise à jour COPPA prévue avr. 2026."}},
|
||||||
|
|
||||||
|
{"iso3": "CAN", "isoNum": "124", "flag": "🇨🇦", "status": "progress", "year": 2026, "ageLimitSocial": 13,
|
||||||
|
"en": {"name": "Canada", "law": "Online Harms Act (C-63)", "detail": "Proposed duty of care for platforms."},
|
||||||
|
"de": {"name": "Kanada", "law": "Online Harms Act (C-63)", "detail": "Sorgfaltspflicht für Plattformen in Prüfung."},
|
||||||
|
"fr": {"name": "Canada", "law": "Online Harms Act (C-63)", "detail": "Devoir de diligence proposé pour les plateformes."}},
|
||||||
|
|
||||||
|
{"iso3": "JPN", "isoNum": "392", "flag": "🇯🇵", "status": "guidelines", "year": 2024, "ageLimitSocial": 13,
|
||||||
|
"en": {"name": "Japan", "law": "Act on Regulation of Soliciting Children", "detail": "Platform self-regulation encouraged."},
|
||||||
|
"de": {"name": "Japan", "law": "Regulierung der Kontaktaufnahme", "detail": "Selbstregulierung der Plattformen empfohlen."},
|
||||||
|
"fr": {"name": "Japon", "law": "Loi sur la régulation de la sollicitation des enfants", "detail": "Autorégulation des plateformes encouragée."}}
|
||||||
|
]
|
||||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module github.com/christian/internetforkids
|
||||||
|
|
||||||
|
go 1.26.1
|
||||||
|
|
||||||
|
require github.com/HugoBlox/hugo-blox-builder/modules/blox-core v0.4.1 // indirect
|
||||||
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
github.com/HugoBlox/hugo-blox-builder/modules/blox-core v0.4.1 h1:LAIEtt5FVZVJoKVmZ+rB/M5exoek52ksCEK12HWssIo=
|
||||||
|
github.com/HugoBlox/hugo-blox-builder/modules/blox-core v0.4.1/go.mod h1:So8+V2U+TNxlXmcpZfdDX0muLh3PdJ7z92h30sv3bZg=
|
||||||
@@ -1,16 +1,19 @@
|
|||||||
baseURL = "https://internetforkids.ong/"
|
baseURL = "https://internetforkids.org/"
|
||||||
title = "Internet for Kids"
|
title = "Internet for Kids"
|
||||||
theme = "congo"
|
|
||||||
|
|
||||||
defaultContentLanguage = "en"
|
defaultContentLanguage = "en"
|
||||||
defaultContentLanguageInSubdir = true
|
defaultContentLanguageInSubdir = true
|
||||||
|
|
||||||
enableRobotsTXT = true
|
enableRobotsTXT = true
|
||||||
|
|
||||||
|
[module]
|
||||||
|
[[module.imports]]
|
||||||
|
path = "github.com/HugoBlox/hugo-blox-builder/modules/blox-core"
|
||||||
|
|
||||||
[markup]
|
[markup]
|
||||||
[markup.goldmark]
|
[markup.goldmark]
|
||||||
[markup.goldmark.renderer]
|
[markup.goldmark.renderer]
|
||||||
unsafe = false
|
unsafe = true
|
||||||
[markup.highlight]
|
[markup.highlight]
|
||||||
style = "monokai"
|
style = "monokai"
|
||||||
|
|
||||||
|
|||||||
17
i18n/de.toml
Normal file
17
i18n/de.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[recent_posts]
|
||||||
|
other = "Neueste Artikel"
|
||||||
|
|
||||||
|
[read_more]
|
||||||
|
other = "Weiterlesen"
|
||||||
|
|
||||||
|
[table_of_contents]
|
||||||
|
other = "Inhaltsverzeichnis"
|
||||||
|
|
||||||
|
[tags]
|
||||||
|
other = "Schlagwörter"
|
||||||
|
|
||||||
|
[previous]
|
||||||
|
other = "Vorheriger"
|
||||||
|
|
||||||
|
[next]
|
||||||
|
other = "Nächster"
|
||||||
17
i18n/en.toml
Normal file
17
i18n/en.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[recent_posts]
|
||||||
|
other = "Recent Articles"
|
||||||
|
|
||||||
|
[read_more]
|
||||||
|
other = "Read more"
|
||||||
|
|
||||||
|
[table_of_contents]
|
||||||
|
other = "Table of Contents"
|
||||||
|
|
||||||
|
[tags]
|
||||||
|
other = "Tags"
|
||||||
|
|
||||||
|
[previous]
|
||||||
|
other = "Previous"
|
||||||
|
|
||||||
|
[next]
|
||||||
|
other = "Next"
|
||||||
17
i18n/fr.toml
Normal file
17
i18n/fr.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[recent_posts]
|
||||||
|
other = "Articles récents"
|
||||||
|
|
||||||
|
[read_more]
|
||||||
|
other = "Lire la suite"
|
||||||
|
|
||||||
|
[table_of_contents]
|
||||||
|
other = "Table des matières"
|
||||||
|
|
||||||
|
[tags]
|
||||||
|
other = "Mots-clés"
|
||||||
|
|
||||||
|
[previous]
|
||||||
|
other = "Précédent"
|
||||||
|
|
||||||
|
[next]
|
||||||
|
other = "Suivant"
|
||||||
58
layouts/_default/baseof.html
Normal file
58
layouts/_default/baseof.html
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="{{ .Language.LanguageCode | default "en" }}" dir="{{ .Language.LanguageDirection | default "ltr" }}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="{{ .Description | default .Summary | plainify | truncate 160 }}">
|
||||||
|
<meta name="author" content="{{ .Params.author | default "Internet for Kids" }}">
|
||||||
|
|
||||||
|
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} — {{ .Site.Title }}{{ end }}</title>
|
||||||
|
|
||||||
|
{{ partial "extend-head.html" . }}
|
||||||
|
|
||||||
|
{{/* Main stylesheet with Newsreader + custom colors */}}
|
||||||
|
<link rel="stylesheet" href="{{ "css/main.css" | relURL }}">
|
||||||
|
</head>
|
||||||
|
<body style="background-color:var(--ifk-bg);color:var(--ifk-text)">
|
||||||
|
<header style="border-bottom:1px solid #e5e7eb;background:white;position:sticky;top:0;z-index:40">
|
||||||
|
<nav style="max-width:64rem;margin:0 auto;padding:1rem;display:flex;justify-content:space-between;align-items:center">
|
||||||
|
<a href="{{ "/" | relLangURL }}" style="font-family:var(--ifk-font);font-size:1.35rem;font-weight:600;color:var(--ifk-text);text-decoration:none">
|
||||||
|
{{ .Site.Title }}
|
||||||
|
</a>
|
||||||
|
<div style="display:flex;align-items:center;gap:1.5rem;font-family:system-ui,-apple-system,sans-serif;font-size:0.95rem">
|
||||||
|
{{ range .Site.Menus.main }}
|
||||||
|
{{ if ne .Identifier "locale" }}
|
||||||
|
<a href="{{ .URL | relLangURL }}" style="color:#4b5563;text-decoration:none">{{ .Name }}</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ partial "language-switcher.html" . }}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main style="flex:1">
|
||||||
|
{{ block "main" . }}{{ end }}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer style="border-top:1px solid #e5e7eb;background:white;margin-top:5rem">
|
||||||
|
<div style="max-width:64rem;margin:0 auto;padding:3rem 1rem">
|
||||||
|
<div style="display:flex;gap:2rem;flex-wrap:wrap;margin-bottom:2rem">
|
||||||
|
{{ range .Site.Menus.footer }}
|
||||||
|
<a href="{{ .URL | relLangURL }}" style="color:#6b7280;text-decoration:none;font-family:system-ui,sans-serif;font-size:0.875rem">
|
||||||
|
{{ .Name }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
<div style="border-top:1px solid #e5e7eb;padding-top:2rem;text-align:center;font-size:0.85rem;color:#6b7280;font-family:system-ui,sans-serif">
|
||||||
|
<p>
|
||||||
|
© {{ now.Year }} {{ .Site.Title }}. A publication by <a href="https://www.agiliton.eu" style="color:var(--ifk-accent);text-decoration:none">Agiliton</a>.
|
||||||
|
</p>
|
||||||
|
{{ partial "extend-footer.html" . }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
{{ partial "rybbit.html" . }}
|
||||||
|
{{ partial "structured-data.html" . }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
30
layouts/_default/home.html
Normal file
30
layouts/_default/home.html
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{{ define "main" }}
|
||||||
|
<article class="prose max-w-3xl mx-auto py-12 px-4">
|
||||||
|
{{ .Content }}
|
||||||
|
|
||||||
|
<div class="mt-12">
|
||||||
|
<h2>{{ i18n "recent_posts" | default "Recent Articles" }}</h2>
|
||||||
|
<div class="grid gap-8">
|
||||||
|
{{ range first 5 .Site.RegularPages }}
|
||||||
|
<article class="border-b pb-8">
|
||||||
|
<h3 class="text-2xl font-newsreader mb-2">
|
||||||
|
<a href="{{ .Permalink }}" class="text-ifk-accent hover:text-ifk-accent-hover">
|
||||||
|
{{ .Title }}
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
<div class="text-sm text-gray-600 mb-4">
|
||||||
|
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "January 2, 2006" }}</time>
|
||||||
|
{{ with .Params.author }}— {{ . }}{{ end }}
|
||||||
|
</div>
|
||||||
|
<p class="text-lg font-newsreader leading-relaxed">
|
||||||
|
{{ .Summary }}
|
||||||
|
</p>
|
||||||
|
<a href="{{ .Permalink }}" class="inline-block mt-4 text-ifk-accent hover:text-ifk-accent-hover font-medium">
|
||||||
|
{{ i18n "read_more" | default "Read more" }} →
|
||||||
|
</a>
|
||||||
|
</article>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
{{ end }}
|
||||||
35
layouts/_default/list.html
Normal file
35
layouts/_default/list.html
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{{ define "main" }}
|
||||||
|
<div class="max-w-3xl mx-auto py-12 px-4">
|
||||||
|
<header class="mb-12">
|
||||||
|
<h1 class="text-4xl font-newsreader font-semibold mb-4">{{ .Title }}</h1>
|
||||||
|
{{ with .Description }}
|
||||||
|
<p class="text-lg text-gray-600">{{ . }}</p>
|
||||||
|
{{ end }}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="space-y-8">
|
||||||
|
{{ range .Paginator.Pages }}
|
||||||
|
<article class="pb-8 border-b last:border-b-0">
|
||||||
|
<h2 class="text-2xl font-newsreader font-semibold mb-2">
|
||||||
|
<a href="{{ .Permalink }}" class="text-ifk-accent hover:text-ifk-accent-hover">
|
||||||
|
{{ .Title }}
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
<div class="text-sm text-gray-600 mb-3">
|
||||||
|
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "January 2, 2006" }}</time>
|
||||||
|
{{ with .Params.author }}— {{ . }}{{ end }}
|
||||||
|
{{ if .ReadingTime }}— {{ .ReadingTime }} min read{{ end }}
|
||||||
|
</div>
|
||||||
|
<p class="text-lg font-newsreader leading-relaxed mb-3">
|
||||||
|
{{ .Summary }}
|
||||||
|
</p>
|
||||||
|
<a href="{{ .Permalink }}" class="inline-block text-ifk-accent hover:text-ifk-accent-hover font-medium">
|
||||||
|
{{ i18n "read_more" | default "Read more" }} →
|
||||||
|
</a>
|
||||||
|
</article>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ template "_internal/pagination.html" . }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
102
layouts/_default/single.html
Normal file
102
layouts/_default/single.html
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
{{ define "main" }}
|
||||||
|
<div style="max-width:64rem;margin:0 auto;padding:3rem 1rem;display:grid;grid-template-columns:1fr 240px;gap:3rem">
|
||||||
|
|
||||||
|
{{/* Main article column */}}
|
||||||
|
<article>
|
||||||
|
<header style="margin-bottom:2rem">
|
||||||
|
<h1 style="font-family:var(--ifk-font);font-size:2.75rem;font-weight:600;line-height:1.15;letter-spacing:-0.01em;margin-bottom:1rem">
|
||||||
|
{{ .Title }}
|
||||||
|
</h1>
|
||||||
|
<div style="color:#6b7280;font-family:system-ui,-apple-system,sans-serif;font-size:0.95rem;display:flex;gap:1rem;flex-wrap:wrap;align-items:center">
|
||||||
|
{{ if .Date }}
|
||||||
|
<time datetime="{{ .Date.Format "2006-01-02" }}">
|
||||||
|
{{ .Date.Format "January 2, 2006" }}
|
||||||
|
</time>
|
||||||
|
{{ end }}
|
||||||
|
{{ with .Params.author }}
|
||||||
|
<span>{{ . }}</span>
|
||||||
|
{{ end }}
|
||||||
|
{{ if .ReadingTime }}
|
||||||
|
<span>{{ .ReadingTime }} min read</span>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ with .Params.tags }}
|
||||||
|
<div style="margin-top:0.75rem;display:flex;gap:0.5rem;flex-wrap:wrap">
|
||||||
|
{{ range . }}
|
||||||
|
<a href="{{ "/tags/" | relLangURL }}{{ . | urlize }}" style="font-family:system-ui,sans-serif;font-size:0.75rem;text-transform:uppercase;letter-spacing:0.05em;color:var(--ifk-accent);text-decoration:none;border:1px solid #e5e7eb;padding:0.2rem 0.6rem;border-radius:4px">
|
||||||
|
{{ . }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="article-body" style="font-family:var(--ifk-font);font-size:1.375rem;line-height:1.65">
|
||||||
|
{{ .Content }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if or .NextInSection .PrevInSection }}
|
||||||
|
<nav style="margin-top:3rem;padding-top:2rem;border-top:1px solid #e5e7eb;display:flex;justify-content:space-between;gap:1rem">
|
||||||
|
{{ with .PrevInSection }}
|
||||||
|
<a href="{{ .Permalink }}" style="flex:1;padding:1rem;border:1px solid #e5e7eb;border-radius:6px;text-decoration:none;color:var(--ifk-text)">
|
||||||
|
<div style="font-size:0.75rem;font-family:system-ui,sans-serif;text-transform:uppercase;color:#6b7280;margin-bottom:0.25rem">← {{ i18n "previous" | default "Previous" }}</div>
|
||||||
|
<div style="font-family:var(--ifk-font);font-size:1.1rem">{{ .Title }}</div>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ with .NextInSection }}
|
||||||
|
<a href="{{ .Permalink }}" style="flex:1;padding:1rem;border:1px solid #e5e7eb;border-radius:6px;text-decoration:none;color:var(--ifk-text);text-align:right">
|
||||||
|
<div style="font-size:0.75rem;font-family:system-ui,sans-serif;text-transform:uppercase;color:#6b7280;margin-bottom:0.25rem">{{ i18n "next" | default "Next" }} →</div>
|
||||||
|
<div style="font-family:var(--ifk-font);font-size:1.1rem">{{ .Title }}</div>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
</nav>
|
||||||
|
{{ end }}
|
||||||
|
</article>
|
||||||
|
|
||||||
|
{{/* Sidebar */}}
|
||||||
|
<aside style="font-family:system-ui,-apple-system,sans-serif">
|
||||||
|
{{/* Table of Contents */}}
|
||||||
|
{{ if .TableOfContents }}
|
||||||
|
<div style="position:sticky;top:5rem">
|
||||||
|
<h3 style="font-size:0.75rem;text-transform:uppercase;letter-spacing:0.08em;color:#6b7280;font-weight:600;margin-bottom:0.75rem">
|
||||||
|
{{ i18n "table_of_contents" | default "Contents" }}
|
||||||
|
</h3>
|
||||||
|
<div style="font-size:0.85rem;line-height:1.7;border-left:2px solid #e5e7eb;padding-left:0.75rem">
|
||||||
|
{{ .TableOfContents }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{/* Recent articles */}}
|
||||||
|
{{ $pages := where .Site.RegularPages "Section" .Section }}
|
||||||
|
{{ $recent := first 5 $pages }}
|
||||||
|
{{ if gt (len $recent) 1 }}
|
||||||
|
<h3 style="font-size:0.75rem;text-transform:uppercase;letter-spacing:0.08em;color:#6b7280;font-weight:600;margin-top:2rem;margin-bottom:0.75rem">
|
||||||
|
{{ i18n "recent_articles" | default "Recent" }}
|
||||||
|
</h3>
|
||||||
|
<div style="font-size:0.85rem;line-height:1.6">
|
||||||
|
{{ range $recent }}
|
||||||
|
{{ if ne .Permalink $.Permalink }}
|
||||||
|
<a href="{{ .Permalink }}" style="display:block;color:var(--ifk-text);text-decoration:none;padding:0.4rem 0;border-bottom:1px solid #f3f4f6">
|
||||||
|
{{ .Title }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
div[style*="grid-template-columns:1fr 240px"] {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
div[style*="grid-template-columns:1fr 240px"] > aside {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{{ end }}
|
||||||
@@ -1,9 +1,23 @@
|
|||||||
{{ if .IsTranslated }}
|
{{ if .IsTranslated }}
|
||||||
<nav class="language-switcher" aria-label="Language">
|
<div class="lang-switch" style="position:relative">
|
||||||
|
<button onclick="this.parentElement.classList.toggle('open')" style="background:none;border:1px solid #e5e7eb;border-radius:6px;padding:0.35rem 0.75rem;cursor:pointer;font-family:system-ui,-apple-system,sans-serif;font-size:0.875rem;color:#4b5563;display:flex;align-items:center;gap:0.4rem">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" style="opacity:0.6"><path d="M4.545 6.714L4.11 8H3l1.862-5h1.284L8 8H6.833l-.435-1.286H4.545zm1.634-.736L5.5 3.956h-.049l-.679 2.022H6.18z"/><path d="M0 2a2 2 0 012-2h7a2 2 0 012 2v3h3a2 2 0 012 2v7a2 2 0 01-2 2H7a2 2 0 01-2-2v-3H2A2 2 0 010 9V2zm2-1A1 1 0 001 2v7a1 1 0 001 1h7a1 1 0 001-1V2A1 1 0 009 1H2zm7.138 9.995c.193.301.402.583.63.846-.748.575-1.673 1.001-2.768 1.292.178.217.451.635.555.867 1.125-.359 2.08-.844 2.886-1.494.777.665 1.739 1.165 2.93 1.472.133-.254.414-.673.629-.89-1.125-.253-2.057-.694-2.82-1.284.681-.747 1.222-1.651 1.621-2.757H14V8h-3v1.047h.765c-.318.844-.74 1.546-1.272 2.13a6.066 6.066 0 01-.415-.492 1.988 1.988 0 01-.94.31z"/></svg>
|
||||||
|
{{ .Language.LanguageName }}
|
||||||
|
<svg width="10" height="10" viewBox="0 0 10 10" fill="currentColor" style="opacity:0.5"><path d="M2 3.5L5 7l3-3.5H2z"/></svg>
|
||||||
|
</button>
|
||||||
|
<div class="lang-dropdown" style="display:none;position:absolute;right:0;top:calc(100% + 4px);background:white;border:1px solid #e5e7eb;border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,0.1);overflow:hidden;min-width:140px;z-index:50">
|
||||||
|
<a href="{{ .Permalink }}" style="display:block;padding:0.5rem 1rem;font-size:0.875rem;font-family:system-ui,sans-serif;color:#4d7c0f;background:#f0fdf4;text-decoration:none;font-weight:500">
|
||||||
|
{{ .Language.LanguageName }} ✓
|
||||||
|
</a>
|
||||||
{{ range .Translations }}
|
{{ range .Translations }}
|
||||||
<a href="{{ .Permalink }}" lang="{{ .Language.Lang }}" hreflang="{{ .Language.Lang }}">
|
<a href="{{ .Permalink }}" lang="{{ .Language.Lang }}" hreflang="{{ .Language.Lang }}" style="display:block;padding:0.5rem 1rem;font-size:0.875rem;font-family:system-ui,sans-serif;color:#374151;text-decoration:none">
|
||||||
{{ .Language.LanguageName }}
|
{{ .Language.LanguageName }}
|
||||||
</a>
|
</a>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</nav>
|
</div>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
.lang-switch.open .lang-dropdown { display:block !important; }
|
||||||
|
.lang-dropdown a:hover { background:#f9fafb; }
|
||||||
|
</style>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
Agiliton VPN provides content filtering, device protection, and safe browsing for the whole family.
|
Agiliton VPN provides content filtering, device protection, and safe browsing for the whole family.
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</p>
|
</p>
|
||||||
<a href="https://go.agiliton.eu/vpn" style="display: inline-block; background: #fff; color: #1a365d; padding: 0.75rem 2rem; border-radius: 8px; text-decoration: none; font-weight: 600;">
|
<a href="https://go.agiliton.eu/vpn-app" style="display: inline-block; background: #fff; color: #1a365d; padding: 0.75rem 2rem; border-radius: 8px; text-decoration: none; font-weight: 600;">
|
||||||
{{ if eq .Language.Lang "de" }}Mehr erfahren{{ else }}Learn More{{ end }}
|
{{ if eq .Language.Lang "de" }}Mehr erfahren{{ else }}Learn More{{ end }}
|
||||||
</a>
|
</a>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
@@ -1,75 +1,31 @@
|
|||||||
{{ $lang := .Page.Language.Lang }}
|
{{ $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>
|
<style>
|
||||||
.csm-container {
|
.csm-container { max-width: 100%; margin: 2rem 0; }
|
||||||
max-width: 100%;
|
.csm-container h3 { text-align: center; margin-bottom: 0.5rem; font-size: 1.25rem; }
|
||||||
margin: 2rem 0;
|
.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-container h3 {
|
.csm-table th { background: #1e40af; color: white; padding: 0.75rem 1rem; text-align: left; font-weight: 600; }
|
||||||
text-align: center;
|
.csm-table td { padding: 0.65rem 1rem; border-bottom: 1px solid #e2e8f0; vertical-align: top; }
|
||||||
margin-bottom: 0.5rem;
|
.csm-table tr:hover { background: #f0fdf4; }
|
||||||
font-size: 1.25rem;
|
.csm-status { display: inline-block; padding: 0.15rem 0.5rem; border-radius: 4px; font-size: 0.8rem; font-weight: 600; white-space: nowrap; }
|
||||||
}
|
|
||||||
.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-enforced { background: #1e40af; color: white; }
|
||||||
.csm-passed { background: #3b82f6; color: white; }
|
.csm-passed { background: #3b82f6; color: white; }
|
||||||
.csm-progress { background: #93c5fd; color: #1e3a5f; }
|
.csm-progress { background: #93c5fd; color: #1e3a5f; }
|
||||||
.csm-guidelines { background: #dbeafe; color: #1e3a5f; }
|
.csm-guidelines { background: #dbeafe; color: #1e3a5f; }
|
||||||
.csm-legend {
|
.csm-legend { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; margin-top: 1.5rem; font-size: 0.8rem; }
|
||||||
display: flex;
|
.csm-legend-item { display: flex; align-items: center; gap: 0.35rem; }
|
||||||
flex-wrap: wrap;
|
.csm-legend-swatch { width: 14px; height: 14px; border-radius: 3px; border: 1px solid rgba(0,0,0,0.1); }
|
||||||
gap: 1rem;
|
@media (max-width: 640px) { .csm-table { font-size: 0.85rem; } .csm-table th, .csm-table td { padding: 0.5rem; } }
|
||||||
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>
|
</style>
|
||||||
|
|
||||||
<div class="csm-container">
|
<div class="csm-container">
|
||||||
@@ -86,60 +42,16 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{ if eq $lang "de" }}
|
{{ range $countries }}
|
||||||
<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>
|
{{ $loc := index . $lang | default (index . "en") }}
|
||||||
<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>
|
{{ $cls := index $statusClass .status }}
|
||||||
<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>
|
{{ $lbl := index (index $statusLabel .status) $lang | default (index (index $statusLabel .status) "en") }}
|
||||||
<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>
|
||||||
<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>
|
<td>{{ .flag }} {{ $loc.name }}</td>
|
||||||
<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>
|
<td>{{ $loc.law }}</td>
|
||||||
<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>
|
<td><span class="csm-status {{ $cls }}">{{ $lbl }}</span></td>
|
||||||
<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>
|
<td>{{ $loc.detail }}</td>
|
||||||
<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>
|
||||||
<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>
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</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>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
Agiliton VPN provides content filtering, device protection, and safe browsing for the whole family.
|
Agiliton VPN provides content filtering, device protection, and safe browsing for the whole family.
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</p>
|
</p>
|
||||||
<a href="https://go.agiliton.eu/vpn" style="display: inline-block; background: #fff; color: #1a365d; padding: 0.75rem 2rem; border-radius: 8px; text-decoration: none; font-weight: 600;">
|
<a href="https://go.agiliton.eu/vpn-app" style="display: inline-block; background: #fff; color: #1a365d; padding: 0.75rem 2rem; border-radius: 8px; text-decoration: none; font-weight: 600;">
|
||||||
{{ if eq .Page.Language.Lang "de" }}Mehr erfahren{{ else }}Learn More{{ end }}
|
{{ if eq .Page.Language.Lang "de" }}Mehr erfahren{{ else }}Learn More{{ end }}
|
||||||
</a>
|
</a>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
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:#4d7c0f"></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:#059669"></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:#86efac"></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:#d1fae5"></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: '#4d7c0f', passed: '#059669', progress: '#86efac', guidelines: '#d1fae5' };
|
||||||
|
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://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.75 : 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>
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
map $http_x_forwarded_proto $real_scheme {
|
||||||
|
default $scheme;
|
||||||
|
https https;
|
||||||
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name _;
|
server_name _;
|
||||||
@@ -35,8 +40,8 @@ server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Redirect unprefixed paths to /en/
|
# Redirect unprefixed paths to /en/
|
||||||
location ~ "^/(?!en/|de/|fr/|css/|js/|img/|favicon|android|apple|site|llms|health|robots|index\.xml|[0-9a-f]{32}\.txt)" {
|
location ~ "^/(?!en/|de/|fr/|css/|js/|img/|favicon|android|apple|site|llms|health|robots|index\.xml|BingSiteAuth|[0-9a-f]{32}\.txt)" {
|
||||||
return 302 /en$request_uri;
|
return 302 $real_scheme://$host/en$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Clean URLs
|
# Clean URLs
|
||||||
|
|||||||
4
static/BingSiteAuth.xml
Normal file
4
static/BingSiteAuth.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<users>
|
||||||
|
<user>7B8CDCFD8FC8D5E226BD9E01CEE80814</user>
|
||||||
|
</users>
|
||||||
324
static/css/main.css
Normal file
324
static/css/main.css
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
/* Custom font imports */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-latin.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-latin-ext.woff2) format('woff2');
|
||||||
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400 500;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-italic-latin.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Newsreader';
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400 500;
|
||||||
|
font-display: swap;
|
||||||
|
src: url(/fonts/newsreader/newsreader-italic-latin-ext.woff2) format('woff2');
|
||||||
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CSS Variables */
|
||||||
|
:root {
|
||||||
|
--ifk-font: 'Newsreader', 'Times New Roman', serif;
|
||||||
|
--ifk-text: #1c1917;
|
||||||
|
--ifk-bg: #fafaf9;
|
||||||
|
--ifk-accent: #4d7c0f;
|
||||||
|
--ifk-accent-hover: #3f6212;
|
||||||
|
--ifk-secondary: #059669;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility classes for colors */
|
||||||
|
.text-ifk-accent { color: var(--ifk-accent); }
|
||||||
|
.text-ifk-text { color: var(--ifk-text); }
|
||||||
|
.bg-ifk-bg { background-color: var(--ifk-bg); }
|
||||||
|
.hover\:text-ifk-accent:hover { color: var(--ifk-accent); }
|
||||||
|
.hover\:text-ifk-accent-hover:hover { color: var(--ifk-accent-hover); }
|
||||||
|
|
||||||
|
/* Font family utility */
|
||||||
|
.font-newsreader { font-family: var(--ifk-font); }
|
||||||
|
|
||||||
|
/* Tailwind-equivalent utilities */
|
||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
.flex { display: flex; }
|
||||||
|
.flex-1 { flex: 1 1 0%; }
|
||||||
|
.flex-wrap { flex-wrap: wrap; }
|
||||||
|
.inline-block { display: inline-block; }
|
||||||
|
.grid { display: grid; }
|
||||||
|
.grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
|
||||||
|
.justify-between { justify-content: space-between; }
|
||||||
|
.items-center { align-items: center; }
|
||||||
|
.gap-4 { gap: 1rem; }
|
||||||
|
.gap-8 { gap: 2rem; }
|
||||||
|
.mx-auto { margin-left: auto; margin-right: auto; }
|
||||||
|
.max-w-2xl { max-width: 42rem; }
|
||||||
|
.max-w-3xl { max-width: 48rem; }
|
||||||
|
.max-w-4xl { max-width: 56rem; }
|
||||||
|
.px-4 { padding-left: 1rem; padding-right: 1rem; }
|
||||||
|
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
|
||||||
|
.py-12 { padding-top: 3rem; padding-bottom: 3rem; }
|
||||||
|
.p-4 { padding: 1rem; }
|
||||||
|
.pt-8 { padding-top: 2rem; }
|
||||||
|
.mb-2 { margin-bottom: 0.5rem; }
|
||||||
|
.mb-3 { margin-bottom: 0.75rem; }
|
||||||
|
.mb-4 { margin-bottom: 1rem; }
|
||||||
|
.mb-8 { margin-bottom: 2rem; }
|
||||||
|
.mb-12 { margin-bottom: 3rem; }
|
||||||
|
.mr-2 { margin-right: 0.5rem; }
|
||||||
|
.mt-12 { margin-top: 3rem; }
|
||||||
|
.mt-20 { margin-top: 5rem; }
|
||||||
|
.sticky { position: sticky; }
|
||||||
|
.top-0 { top: 0; }
|
||||||
|
.z-40 { z-index: 40; }
|
||||||
|
.border { border: 1px solid #e5e7eb; }
|
||||||
|
.border-t { border-top: 1px solid #e5e7eb; }
|
||||||
|
.border-b { border-bottom: 1px solid #e5e7eb; }
|
||||||
|
.rounded { border-radius: 0.25rem; }
|
||||||
|
.bg-white { background-color: #fff; }
|
||||||
|
.bg-gray-50 { background-color: #f9fafb; }
|
||||||
|
.text-center { text-align: center; }
|
||||||
|
.text-left { text-align: left; }
|
||||||
|
.text-right { text-align: right; }
|
||||||
|
.text-xs { font-size: 0.75rem; line-height: 1rem; }
|
||||||
|
.text-sm { font-size: 0.875rem; line-height: 1.25rem; }
|
||||||
|
.text-lg { font-size: 1.125rem; line-height: 1.75rem; }
|
||||||
|
.text-xl { font-size: 1.25rem; line-height: 1.75rem; }
|
||||||
|
.text-4xl { font-size: 2.75rem; line-height: 1.15; }
|
||||||
|
.font-semibold { font-weight: 600; }
|
||||||
|
.uppercase { text-transform: uppercase; }
|
||||||
|
.tracking-wide { letter-spacing: 0.025em; }
|
||||||
|
.leading-tight { line-height: 1.25; }
|
||||||
|
.leading-relaxed { line-height: 1.625; }
|
||||||
|
.text-gray-600 { color: #4b5563; }
|
||||||
|
.hover\:bg-gray-50:hover { background-color: #f9fafb; }
|
||||||
|
@media (min-width: 768px) { .md\:grid-cols-3 { grid-template-columns: repeat(3, 1fr); } }
|
||||||
|
|
||||||
|
/* Global typography */
|
||||||
|
body {
|
||||||
|
background-color: var(--ifk-bg);
|
||||||
|
color: var(--ifk-text);
|
||||||
|
font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
article, .prose {
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
color: var(--ifk-text);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, .article-title {
|
||||||
|
font-size: 2.75rem;
|
||||||
|
line-height: 1.15;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.85rem;
|
||||||
|
line-height: 1.25;
|
||||||
|
margin-top: 3rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Article content */
|
||||||
|
article p {
|
||||||
|
font-size: 1.375rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
article a {
|
||||||
|
color: var(--ifk-accent);
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-thickness: 1px;
|
||||||
|
text-underline-offset: 2px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
article a:hover {
|
||||||
|
color: var(--ifk-accent-hover);
|
||||||
|
text-decoration-thickness: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blockquotes */
|
||||||
|
blockquote {
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
border-left: 3px solid var(--ifk-secondary);
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
margin: 2rem 0;
|
||||||
|
color: var(--ifk-text);
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
code {
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
background: #f3f4f6;
|
||||||
|
padding: 0.1rem 0.4rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: #1f2937;
|
||||||
|
color: #f3f4f6;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
font-size: 1.1rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background: #f3f4f6;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lists */
|
||||||
|
ul, ol {
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-family: var(--ifk-font);
|
||||||
|
font-size: 1.375rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation */
|
||||||
|
nav, header, footer {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a {
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a:hover {
|
||||||
|
color: var(--ifk-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Article metadata */
|
||||||
|
.article-meta, .post-meta, time, .reading-time {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tags */
|
||||||
|
.taxonomy-term, [href*="/tags/"], [href*="/categories/"] {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--ifk-accent);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.taxonomy-term:hover, [href*="/tags/"]:hover, [href*="/categories/"]:hover {
|
||||||
|
color: var(--ifk-accent-hover);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table of Contents */
|
||||||
|
#TableOfContents {
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
#TableOfContents a {
|
||||||
|
color: var(--ifk-accent);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#TableOfContents a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Status badges (for shortcodes) */
|
||||||
|
.csm-enforced { background: var(--ifk-accent); color: white; }
|
||||||
|
.csm-passed { background: var(--ifk-secondary); color: white; }
|
||||||
|
.csm-progress { background: #86efac; color: #14532d; }
|
||||||
|
.csm-guidelines { background: #d1fae5; color: #065f46; }
|
||||||
|
|
||||||
|
/* Shortcode-specific overrides */
|
||||||
|
.ifk-stat-num { font-family: var(--ifk-font); }
|
||||||
|
.ifk-stat-label { font-family: system-ui, -apple-system, sans-serif; }
|
||||||
|
.ifk-chart-card h4 { font-family: system-ui, -apple-system, sans-serif; }
|
||||||
|
|
||||||
|
/* Responsive design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
h1, .article-title {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article p, li {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
static/fonts/newsreader/newsreader-italic-latin-ext.woff2
Normal file
BIN
static/fonts/newsreader/newsreader-italic-latin-ext.woff2
Normal file
Binary file not shown.
BIN
static/fonts/newsreader/newsreader-italic-latin.woff2
Normal file
BIN
static/fonts/newsreader/newsreader-italic-latin.woff2
Normal file
Binary file not shown.
BIN
static/fonts/newsreader/newsreader-latin-ext.woff2
Normal file
BIN
static/fonts/newsreader/newsreader-latin-ext.woff2
Normal file
Binary file not shown.
BIN
static/fonts/newsreader/newsreader-latin.woff2
Normal file
BIN
static/fonts/newsreader/newsreader-latin.woff2
Normal file
Binary file not shown.
@@ -15,12 +15,13 @@ This blog covers:
|
|||||||
|
|
||||||
## Languages
|
## Languages
|
||||||
|
|
||||||
Content is available in English (/en/) and German (/de/).
|
Content is available in English (/en/), German (/de/), and French (/fr/).
|
||||||
|
|
||||||
## Sections
|
## Sections
|
||||||
|
|
||||||
- /en/ — Articles on child protection and online safety (English)
|
- /en/ — Articles on child protection and online safety (English)
|
||||||
- /de/ — Artikel zum Kinderschutz und Online-Sicherheit (Deutsch)
|
- /de/ — Artikel zum Kinderschutz und Online-Sicherheit (Deutsch)
|
||||||
|
- /fr/ — Articles sur la protection de l'enfance et la sécurité en ligne (Français)
|
||||||
- /en/about/ — About this publication
|
- /en/about/ — About this publication
|
||||||
- /en/tags/ — Browse by topic
|
- /en/tags/ — Browse by topic
|
||||||
|
|
||||||
|
|||||||
21
static/site.webmanifest
Normal file
21
static/site.webmanifest
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "Internet for Kids",
|
||||||
|
"short_name": "IFK",
|
||||||
|
"description": "Expert insights on child protection laws, online safety, and digital family protection worldwide.",
|
||||||
|
"start_url": "/en/",
|
||||||
|
"display": "standalone",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"theme_color": "#1a365d",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Submodule themes/congo deleted from b426bf91b0
Reference in New Issue
Block a user