From 7ddcdaf9f99d0e5cb8d1fd1d95c4cb0e3685b1b2 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 27 Sep 2026 11:17:45 +0000 Subject: [PATCH 1/4] Add project skills for quick actions and a CLAUDE.md Six skills in .claude/skills/: add-collection, triage-leads (fans out to parallel subagents and merges their drafts), verify-records, fix-broken-links, release-dataset, and site-audit. The heavier ones run in a forked subagent context. CLAUDE.md records the ground rules (honesty rule, verification, review log, permanent IDs), the checks to run, and the skill index. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_0134nrWUakNL58qJMzCVDcn6 --- .claude/skills/add-collection/SKILL.md | 41 +++++++++++++++++++++ .claude/skills/fix-broken-links/SKILL.md | 28 +++++++++++++++ .claude/skills/release-dataset/SKILL.md | 30 ++++++++++++++++ .claude/skills/site-audit/SKILL.md | 29 +++++++++++++++ .claude/skills/triage-leads/SKILL.md | 45 ++++++++++++++++++++++++ .claude/skills/verify-records/SKILL.md | 29 +++++++++++++++ .gitignore | 2 ++ CLAUDE.md | 40 +++++++++++++++++++++ 8 files changed, 244 insertions(+) create mode 100644 .claude/skills/add-collection/SKILL.md create mode 100644 .claude/skills/fix-broken-links/SKILL.md create mode 100644 .claude/skills/release-dataset/SKILL.md create mode 100644 .claude/skills/site-audit/SKILL.md create mode 100644 .claude/skills/triage-leads/SKILL.md create mode 100644 .claude/skills/verify-records/SKILL.md create mode 100644 .gitignore create mode 100644 CLAUDE.md diff --git a/.claude/skills/add-collection/SKILL.md b/.claude/skills/add-collection/SKILL.md new file mode 100644 index 0000000..658d8f4 --- /dev/null +++ b/.claude/skills/add-collection/SKILL.md @@ -0,0 +1,41 @@ +--- +name: add-collection +description: Add one real oral-history or voice-testimony collection to data/collections.json the Mapping Voices way — next MV- id, controlled vocabularies, honest verification status and provenance, review-log entry, regenerated exports. Use when asked to "add", "list", or "put on the map" a specific collection, or to turn a new-collection issue into a record. +--- + +# Add a collection + +Rules that override everything below: METHODOLOGY.md §1 (inclusion) and the +honesty rule — never invent a field. Omit what the source doesn't support. + +1. **Confirm it qualifies** (METHODOLOGY §1–2): recorded human voice; real + holder; the holder's own public page. Search for duplicates first: + `grep -i "" data/collections.json` and by URL host. +2. **Gather facts** from the holder's page (WebFetch; if blocked, WebSearch + results pointing at the holder's own pages — then the record stays + `partially_verified` and the method is `search-based`). Need: title, + holder, place (city), languages *as the source states them*, what it + documents, start/end years, access conditions. +3. **Write the record** — field reference: DATA_DICTIONARY.md §2. + - `mv_id`: next unused (`node -e 'const d=require("./data/collections.json");console.log(Math.max(...d.map(r=>+r.mv_id.slice(3)))+1)'`). + - `country`, `languages`, `themes` must be terms in `data/vocab/`. Add a + missing language (with ISO 639-3) or theme (with group + scope note) + to the vocab in the same change. Never infer languages from geography; + use `Multiple languages` + `language_note` with the source's wording. + - Pin: city-level; subject-country rule in METHODOLOGY §5. + - `citation`: `". . Retrieved from <url>."` + - `verification_status`: `partially_verified` unless a person checked + every core field against the open source page (then `verified` + + `last_reviewed`). Flag inferred fields in `verification_note`. + - `provenance`: how it was found (issue number, contributor, search). + - `date_added`: today. Keep the canonical key order (see existing records). + - `related_ids`: only genuine relations; add the reverse link too. +4. **Log it**: append to `data/review-log.json` — + `{date, mv_id, check:"new record", method, reviewer, finding, evidence:[urls], changes:null, outcome:"added"}`. +5. **Check and build**: + ```bash + node scripts/validate-data.mjs && node --test tests/*.test.mjs + node scripts/build-data.mjs && node scripts/build-data.mjs --check + ``` +6. Add a line under `## [Unreleased]` in CHANGELOG.md (create the section + if missing). Commit with a message naming the MV- id. diff --git a/.claude/skills/fix-broken-links/SKILL.md b/.claude/skills/fix-broken-links/SKILL.md new file mode 100644 index 0000000..38e40b0 --- /dev/null +++ b/.claude/skills/fix-broken-links/SKILL.md @@ -0,0 +1,28 @@ +--- +name: fix-broken-links +description: Follow up the weekly link-check issue ("Broken links detected in data/collections.json") — separate real failures from bot blocking, find each holder's current page, correct URLs and citations, flag what can't be resolved, and log every check. Use for "fix broken links", "link rot", or when the link-check issue updates. +context: fork +agent: general-purpose +--- + +# Fix broken links + +1. Read the open GitHub issue labelled `broken-links` in adab-tech/mapping + (GitHub MCP `issue_read`). Save its table to a file for the worksheet. +2. Triage by result: **404 / 410 / DNS failure** = real, fix first. + **403 / 429 / 503 / timeout** = usually bot blocking or transient; only + investigate if it persists across two weekly runs. +3. For each real failure, find the holder's **current own page** (WebFetch; + if blocked, WebSearch results on the holder's domain). Never substitute a + third-party or Wikipedia page. If a collection has truly gone, set + `verification_status: "unavailable"` with a dated `verification_note` — + never delete the record (METHODOLOGY §10). +4. Apply with a migration script (pattern: + `scripts/migrations/2026-09-27-source-review.mjs`): update `url`, replace + the old URL inside `citation`, and append one `data/review-log.json` + entry per record (check `link`, evidence URLs, changes, outcome). +5. Also move `http://` URLs to https where the same page is served there + (the validator lists them as warnings). +6. `node scripts/validate-data.mjs && node --test tests/*.test.mjs && node scripts/build-data.mjs`; + CHANGELOG `[Unreleased]` under "Broken-source changes"; commit. +7. Regenerate the worksheet with `--links` so unresolved records are priority 1. diff --git a/.claude/skills/release-dataset/SKILL.md b/.claude/skills/release-dataset/SKILL.md new file mode 100644 index 0000000..757dedf --- /dev/null +++ b/.claude/skills/release-dataset/SKILL.md @@ -0,0 +1,30 @@ +--- +name: release-dataset +description: Cut a new Mapping Voices dataset version — bump the version everywhere it appears, finalize the CHANGELOG, refresh counts, rebuild exports, and run every check. Use for "release", "bump the version", "cut v0.x". +--- + +# Release the dataset + +1. Pick the version (semantic: new records/fields → minor; corrections only → patch). +2. Update **every** place the version or counts appear — find them with: + ```bash + grep -rn "0\.[0-9]\.[0-9]" --include=*.md --include=*.html --include=*.cff --include=*.json . \ + | grep -v "data/\(collections\|languages\|themes\|countries\|stats\|review-log\)" + ``` + Always: `data/dataset-meta.json` (version, released), `CITATION.cff` + (version, date-released), `index.html` JSON-LD (version, dateModified), + `about.html` fallback figures and citation, `README.md` headline counts + and citation, `DATA_DICTIONARY.md` schema line, `PROJECT.md` status. + Counts come from `node scripts/build-data.mjs && node -e 'console.log(require("./data/stats.json").totals)'`. +3. CHANGELOG: rename `[Unreleased]` to `[x.y.z] — YYYY-MM-DD — <title>`, + grouped as Dataset (additions, removals, corrections, broken-source + changes, taxonomy), Atlas, Tooling. +4. Rebuild and run everything: + ```bash + node scripts/build-data.mjs + node scripts/validate-data.mjs && node --test tests/*.test.mjs \ + && node scripts/build-data.mjs --check && node scripts/validate-locales.mjs + ``` +5. Run the `site-audit` skill if UI changed. Commit "Release dataset vx.y.z". +6. After merge: suggest a GitHub release/tag (Zenodo mints a DOI per release + if the integration is enabled). diff --git a/.claude/skills/site-audit/SKILL.md b/.claude/skills/site-audit/SKILL.md new file mode 100644 index 0000000..fdcc4ae --- /dev/null +++ b/.claude/skills/site-audit/SKILL.md @@ -0,0 +1,29 @@ +--- +name: site-audit +description: Run the browser and accessibility audit (axe-core WCAG 2.1 AA, device emulation, reflow, keyboard, reduced motion, RTL) against a local server and fix what fails. Use after UI changes, before a release, or when asked to "test the site", "check accessibility", "check mobile". +context: fork +agent: general-purpose +--- + +# Site audit + +1. Serve the repo: `python3 -m http.server 8765` (background). +2. Get dependencies without polluting the repo, e.g. in a scratch dir: + `npm pack axe-core leaflet@1.9.4` and extract (both unpack to `package/` + — extract one at a time into separate folders). Playwright: use a global + install if present (`npm root -g`), Chromium at `/opt/pw-browsers`; do + not run `playwright install`. +3. Run: + ```bash + PW=$(npm root -g)/playwright AXE=<dir>/axe.min.js LEAFLET_DIR=<dir>/dist \ + node tests/browser/audit.mjs http://localhost:8765 + ``` + (`LEAFLET_DIR` only if the unpkg CDN is unreachable.) +4. For each FAIL: reproduce, fix in the page's CSS/JS, re-run until green. + Contrast failures on animated elements may be mid-transition — the audit + waits for animations; confirm at rest before changing colours. +5. If you add a page, add it to the page lists in `tests/browser/audit.mjs`. +6. Update the "Last run" line and results table in + docs/testing/BROWSER-TESTING.md. Only Chromium can run here — keep the + manual Safari/Firefox/device/screen-reader checklist honest. +7. Stop the server. diff --git a/.claude/skills/triage-leads/SKILL.md b/.claude/skills/triage-leads/SKILL.md new file mode 100644 index 0000000..3746a16 --- /dev/null +++ b/.claude/skills/triage-leads/SKILL.md @@ -0,0 +1,45 @@ +--- +name: triage-leads +description: Research open leads in docs/review-queue.csv (or a list the user gives) and resolve each one — add as a record, mark duplicate, out of scope, curator decision, or needs URL. Fans out to parallel subagents for batches. Use for "work the review queue", "triage leads", "process these suggestions". +context: fork +agent: general-purpose +--- + +# Triage leads + +**Input:** open rows in `docs/review-queue.csv` (column `triage_2026_09_27` +starts with `open:`), or a list from the user. Prefer leads that improve +coverage outside the US/UK — the dataset is skewed (see docs/AUDIT.md §5). + +## Delegate in batches + +For more than ~5 leads, split them into batches of 4–6 and spawn one +general-purpose subagent per batch **in parallel**. Give each the lead rows +and these instructions, and ask for JSON back — do not let subagents edit +files (avoids conflicts): + +```json +{"collection": "...", "outcome": "add|duplicate|out of scope|curator decision|needs URL", + "reason": "...", "evidence": ["https://..."], + "record": { /* full draft record per DATA_DICTIONARY §2, only when outcome=add */ }} +``` + +Each subagent: check duplicates against data/collections.json; apply the +inclusion rules (METHODOLOGY §1–2); research with WebSearch/WebFetch; draft +records only from what the holder's pages support; mark inferred languages +or unknown years in `verification_note`; never guess a URL. + +## Merge (main context) + +1. Review every draft adversarially: is the URL the holder's own page? Is + any field unsupported? Downgrade to `curator decision` when unsure. +2. Apply with a migration script in `scripts/migrations/<date>-queue-*.mjs` + (pattern: `2026-09-27-queue-additions.mjs`): assign sequential `mv_id`s, + add vocab terms, reciprocal `related_ids`, review-log entries (method + `search-based` unless pages were opened), and write outcomes into a new + `triage_<date>` column of docs/review-queue.csv. +3. `node scripts/validate-data.mjs && node --test tests/*.test.mjs && node scripts/build-data.mjs` +4. CHANGELOG `[Unreleased]`; commit. Report counts per outcome. + +Sensitive collections (trauma, legal proceedings, community-governed +material) go to `curator decision` with the reason — METHODOLOGY §11. diff --git a/.claude/skills/verify-records/SKILL.md b/.claude/skills/verify-records/SKILL.md new file mode 100644 index 0000000..b979bb0 --- /dev/null +++ b/.claude/skills/verify-records/SKILL.md @@ -0,0 +1,29 @@ +--- +name: verify-records +description: Run the field-by-field verification workflow — generate the prioritized review worksheet, or import a completed one so records become verified. Use for "verification pass", "review worksheet", "import my review", "promote records to verified". +--- + +# Verify records + +Only a **person who opened the source page** can make a record `verified` +(METHODOLOGY §4). Claude can prepare and import, not verify. Full guide: +docs/review/README.md. + +**Prepare** a worksheet (optionally raising link-check failures): +```bash +# save the body of the latest "Broken links detected" issue to /tmp/links.md if relevant +node scripts/review-worksheet.mjs [--links /tmp/links.md] +``` +Hand the user `docs/review/worksheet.csv` and the column guide from +docs/review/README.md §2. + +**Import** a completed worksheet the user provides: +```bash +node scripts/apply-review.mjs <file.csv> --dry-run # show what would change +node scripts/apply-review.mjs <file.csv> +node scripts/validate-data.mjs && node scripts/build-data.mjs +``` +Rows with fields marked `no` stay `partially_verified` and are listed for +hand correction — make those corrections in data/collections.json only from +the reviewer's notes, log them, and ask the reviewer to confirm. Report how +many records are now verified (`data/stats.json` → `by_verification_status`). diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b751c44 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Local agent worktrees (Claude Code) +.claude/worktrees/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..eff3b08 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,40 @@ +# Mapping Voices — notes for Claude sessions + +Static, no-build atlas (plain HTML/CSS/JS + Leaflet) over an open dataset of +oral-history collections. The research contribution is the metadata, so +data integrity outranks everything else. + +## Ground rules +- **Honesty rule:** never invent metadata. Omit fields the source doesn't + support; flag inferences in `verification_note`. Details: METHODOLOGY.md. +- Only a person who opened the source page can make a record `verified`. + Search-based checks may correct links but never promote. +- Every data change is logged in `data/review-log.json` and made through a + reproducible script in `scripts/migrations/` when it touches many records. +- `mv_id`s are permanent; never renumber or reuse. Never delete a record + whose source disappears — mark it `unavailable`. +- Counts describe the indexed dataset, not oral history in the world. + +## Checks (run before every commit) +```bash +node scripts/validate-data.mjs && node --test tests/*.test.mjs +node scripts/build-data.mjs --check # run without --check to regenerate exports +node scripts/validate-locales.mjs # UI strings exist in en, ha, fr, ar +``` + +## Quick actions (project skills in .claude/skills/) +| Skill | Use for | +|---|---| +| `add-collection` | Add one collection correctly | +| `triage-leads` | Work the review queue; fans out to parallel subagents | +| `verify-records` | Generate / import the field-by-field review worksheet | +| `fix-broken-links` | Follow up the weekly link-check issue | +| `release-dataset` | Bump version everywhere, finalize CHANGELOG, rebuild | +| `site-audit` | Browser + accessibility audit (tests/browser/audit.mjs) | + +## Environment notes +- The Leaflet CDN, map tiles, and many archive sites may be unreachable from + cloud sessions; WebSearch usually works. `npm pack` works for fetching + packages into a scratch dir. Chromium is at /opt/pw-browsers. +- UI strings: add every new key to all four `locales/*.json` files with real + translations. From 7d0b902539e3c96981a3f39438e28093048e8be2 Mon Sep 17 00:00:00 2001 From: Claude <noreply@anthropic.com> Date: Sun, 27 Sep 2026 11:24:45 +0000 Subject: [PATCH 2/4] Add Theme Explorer and Coverage Gaps pages themes.html + js/themes.js: the 15 theme groups, each theme with its scope note, collections, countries and languages; search, sort, URL state and #theme-<slug> anchors, following the Language Explorer. gaps.html + js/gaps.js: UN member states with and without an indexed collection per UN M49 region and subregion, with propose-a-collection links. Adds static data/reference/un-m49-countries.json (193 member states) and tests/un-m49-countries.test.mjs. Links both pages from the site nav, about page and atlas footer (new locale keys footer.themes and footer.gaps); README and CHANGELOG updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0134nrWUakNL58qJMzCVDcn6 --- CHANGELOG.md | 20 + README.md | 17 +- about.html | 6 +- css/gaps.css | 189 +++++ css/themes.css | 42 + data/reference/un-m49-countries.json | 1168 ++++++++++++++++++++++++++ gaps.html | 114 +++ index.html | 2 + js/gaps.js | 301 +++++++ js/themes.js | 388 +++++++++ languages.html | 2 + locales/ar.json | 4 +- locales/en.json | 4 +- locales/fr.json | 4 +- locales/ha.json | 4 +- tests/un-m49-countries.test.mjs | 68 ++ themes.html | 101 +++ 17 files changed, 2426 insertions(+), 8 deletions(-) create mode 100644 css/gaps.css create mode 100644 css/themes.css create mode 100644 data/reference/un-m49-countries.json create mode 100644 gaps.html create mode 100644 js/gaps.js create mode 100644 js/themes.js create mode 100644 tests/un-m49-countries.test.mjs create mode 100644 themes.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 937d307..80d74b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,26 @@ All notable changes to the Mapping Voices dataset and atlas. Dataset changes are recorded as additions, removals, corrections, metadata changes, broken-source changes, and taxonomy changes (METHODOLOGY §10, §12). +## [Unreleased] + +### Atlas +- New **Theme Explorer** (`themes.html`): the 15 top-level theme groups, + each theme with its scope note and count, the collections it is assigned + to, and the countries and languages they span, linking back into filtered + atlas views. Search, sort, and the open theme live in the URL + (`?q=…&sort=…#theme-…`). +- New **Coverage Gaps** page (`gaps.html`): per UN M49 region and subregion, + which UN member states have an indexed collection and which have none + yet, each gap with a link to propose a collection. States plainly that it + shows gaps in the indexed dataset, not in oral history. +- New static reference file `data/reference/un-m49-countries.json` (the 193 + UN member states, ISO 3166-1 alpha-2, M49 region/subregion), with a test + (`tests/un-m49-countries.test.mjs`) that it agrees with + `data/vocab/countries.json`. +- "Themes" and "Coverage gaps" added to the site navigation and the atlas + footer (new locale keys `footer.themes`, `footer.gaps` in en, ha, fr, ar). +- No dataset changes. + ## [0.3.0] — 2026-09-27 — Language Explorer, review tooling, source review ### Dataset diff --git a/README.md b/README.md index 072143d..43a98e8 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,9 @@ Tanzania, Myanmar, Burkina Faso, and many other places have no entry yet, usually because no verifiable public page for a real archive has been confirmed, not because the region lacks oral history. The absence of a pin is not evidence of absence. See [`docs/AUDIT.md`](docs/AUDIT.md) for the -gap analysis. +gap analysis, and the [Coverage Gaps](https://adamu.tech/mapping/gaps.html) +page (`gaps.html`) for every UN member state with no indexed collection yet, +by region, each with a link to propose one. ## How data is verified @@ -95,7 +97,11 @@ The dataset is licensed **CC BY 4.0** and published as: Atlas views are addressable: filters, search, and the selected collection live in the URL, e.g. [`?country=Niger&language=Hausa`](https://adamu.tech/mapping/?country=Niger&language=Hausa) -or [`?c=MV-000023`](https://adamu.tech/mapping/?c=MV-000023). +or [`?c=MV-000023`](https://adamu.tech/mapping/?c=MV-000023). The +[Language Explorer](https://adamu.tech/mapping/languages.html) and the +[Theme Explorer](https://adamu.tech/mapping/themes.html) (the 15 theme groups, +scope notes, and the collections, countries, and languages behind each theme) +browse the same data as lists and link back into these atlas views. **Mapping an archive does not grant permission to reproduce its contents.** Access to and reuse of the collections themselves is governed @@ -208,14 +214,19 @@ repository" button on the repo page). ``` index.html the atlas about.html project page: question, method, data, ethics, limitations -css/style.css, css/about.css styles +languages.html Language Explorer: languages, ISO codes, countries, collections +themes.html Theme Explorer: theme groups, scope notes, collections, countries, languages +gaps.html Coverage Gaps: UN member states with / without an indexed collection +css/*.css styles (style.css tokens; about, languages, themes, gaps pages) js/app.js map, search, filters, URL state, record panel +js/{languages,themes,gaps}.js the explorer and coverage pages locales/*.json UI translations (en, ha, fr, ar) data/collections.json canonical records (edit this) data/vocab/*.json controlled vocabularies: countries, languages, themes data/dataset-meta.json dataset version, release date, license data/collections.{csv,geojson} generated exports (don't edit by hand) data/{languages,themes,countries,stats,datapackage}.json generated indexes +data/reference/un-m49-countries.json static list of the 193 UN member states (UN M49 regions) scripts/validate-data.mjs data validator scripts/build-data.mjs export generator scripts/check-links.mjs weekly link-health check diff --git a/about.html b/about.html index dd831df..4ee81d6 100644 --- a/about.html +++ b/about.html @@ -36,6 +36,8 @@ <a href="#limitations">Limitations</a> <a href="#cite">Cite</a> <a href="languages.html">Languages</a> + <a href="themes.html">Themes</a> + <a href="gaps.html">Coverage gaps</a> <a href="./" class="page-nav-cta">Open the atlas</a> </nav> </div> @@ -116,7 +118,9 @@ <h2 id="h-method"><span class="num">02</span> Method</h2> language and theme classification, duplicate handling, and corrections — is public: <a href="https://github.com/adab-tech/mapping/blob/main/METHODOLOGY.md">METHODOLOGY.md</a>. Browse languages, their ISO codes, and the collections recorded in them in - the <a href="languages.html">Language Explorer</a>. Every field is defined in the + the <a href="languages.html">Language Explorer</a>, the thematic taxonomy in the + <a href="themes.html">Theme Explorer</a>, and where the index does not yet reach + in <a href="gaps.html">Coverage Gaps</a>. Every field is defined in the <a href="https://github.com/adab-tech/mapping/blob/main/DATA_DICTIONARY.md">data dictionary</a>. </p> </section> diff --git a/css/gaps.css b/css/gaps.css new file mode 100644 index 0000000..4921562 --- /dev/null +++ b/css/gaps.css @@ -0,0 +1,189 @@ +/* ========================================================================== + Mapping Voices — Coverage Gaps (gaps.html). + Builds on style.css (tokens), about.css (page layout, .principle, + .page-stats) and languages.css (.lx-main, .lx-status). + ========================================================================== */ + +.gx-principle { + font-size: 1.2rem; + margin: 1.5rem 0; +} + +.gx-cta { + padding: 0.8rem 1rem; + background: var(--paper-panel); + border: 1px solid var(--rule); + border-inline-start: 3px solid var(--accent); + border-radius: var(--radius); +} + +.gx-cta a { + color: var(--accent-dark); + font-weight: 600; +} + +/* Summary table ---------------------------------------------------------- */ + +.gx-table-wrap { + overflow-x: auto; +} + +.gx-table { + width: 100%; + border-collapse: collapse; + font-size: 0.92rem; +} + +.gx-table th, +.gx-table td { + text-align: start; + padding: 0.55rem 0.5rem; + border-bottom: 1px solid var(--rule-soft); + vertical-align: middle; +} + +.gx-table thead th { + font-size: 0.72rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--ink-soft); + border-bottom-color: var(--rule); +} + +.gx-table tbody th a { + color: var(--accent-dark); + font-weight: 600; +} + +.gx-table .gx-num { + text-align: end; + font-variant-numeric: tabular-nums; +} + +.gx-share { + width: 45%; +} + +.gx-share-text { + display: block; + font-variant-numeric: tabular-nums; +} + +/* Proportion bar (decorative; figures are always given in text) ---------- */ + +.gx-bar { + display: block; + height: 0.5rem; + margin-top: 0.3rem; + background: var(--paper-deep); + border: 1px solid var(--rule); + border-radius: 999px; + overflow: hidden; +} + +.gx-bar-fill { + display: block; + height: 100%; + background: var(--accent); +} + +/* Region sections ---------------------------------------------------------- */ + +.gx-region-summary { + margin: 0; +} + +.gx-region > .gx-bar { + max-width: 24rem; + margin: 0.4rem 0 1.25rem; +} + +.gx-sub { + margin: 0 0 1.5rem; +} + +.gx-sub-title { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 0.2rem 0.75rem; + font-size: 1.05rem; + margin: 0 0 0.5rem; +} + +.gx-sub-meta { + font-family: var(--font-ui); + font-size: 0.8rem; + font-weight: 500; + color: var(--ink-soft); +} + +.gx-cols { + display: grid; + grid-template-columns: 1fr; + gap: 0.75rem; +} + +@media (min-width: 640px) { + .gx-cols { + grid-template-columns: 1fr 1fr; + } +} + +.gx-col { + padding: 0.6rem 0.8rem; + background: var(--paper-panel); + border: 1px solid var(--rule-soft); + border-radius: var(--radius); +} + +.gx-col-gaps { + border-style: dashed; + border-color: var(--rule); + background: transparent; +} + +.gx-label { + margin: 0 0 0.4rem; + font-size: 0.72rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--ink-soft); +} + +.gx-list { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 0.2rem; + font-size: 0.92rem; +} + +.gx-list li { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: baseline; + gap: 0 0.75rem; +} + +.gx-count { + font-size: 0.8rem; + color: var(--ink-soft); + font-variant-numeric: tabular-nums; +} + +.gx-propose { + font-size: 0.8rem; + font-weight: 600; + color: var(--accent-dark); +} + +.gx-other { + margin: 0.5rem 0 0; + font-size: 0.85rem; + color: var(--ink-soft); +} diff --git a/css/themes.css b/css/themes.css new file mode 100644 index 0000000..06d0f11 --- /dev/null +++ b/css/themes.css @@ -0,0 +1,42 @@ +/* ========================================================================== + Mapping Voices — Theme Explorer (themes.html). + Reuses the Language Explorer's entry styles (languages.css: .lx-*); + only the two-field control row and the nested group → theme list differ. + ========================================================================== */ + +@media (min-width: 640px) { + .tx-controls { + grid-template-columns: 2fr 1fr; + } +} + +.tx-group > summary .lx-name { + font-size: 1.2rem; +} + +.tx-themes { + margin: 0.75rem 0 0; +} + +.tx-theme { + background: var(--paper); +} + +/* languages.css's `.lx-item[open] summary::before` also matches the summaries + of closed themes inside an open group; point their chevrons back. */ +.tx-theme:not([open]) > summary::before { + transform: rotate(-45deg); +} + +[dir="rtl"] .tx-theme:not([open]) > summary::before { + transform: rotate(135deg); +} + +.tx-theme > summary .lx-name { + font-size: 1rem; +} + +.tx-scope { + margin: 0.75rem 0 0; + font-size: 0.95rem; +} diff --git a/data/reference/un-m49-countries.json b/data/reference/un-m49-countries.json new file mode 100644 index 0000000..8585a47 --- /dev/null +++ b/data/reference/un-m49-countries.json @@ -0,0 +1,1168 @@ +{ + "$comment": "Static reference list of the 193 United Nations member states, used by gaps.html to show member states with no indexed collection (data/countries.json lists only countries that have one). Hand-maintained, not generated; update it if UN membership changes. `name` matches data/vocab/countries.json wherever a country appears there (common English short names). `region` and `subregion` follow UN M49 as used in data/vocab/countries.json (sub-region level, with 'Sub-Saharan Africa' and 'Latin America and the Caribbean' as the intermediate groupings). Observer states and territories are deliberately excluded; the list records no political claim.", + "sources": [ + "United Nations, Member States: https://www.un.org/en/about-us/member-states", + "UN Statistics Division, Standard country or area codes for statistical use (M49): https://unstats.un.org/unsd/methodology/m49/", + "ISO 3166-1 alpha-2 country codes" + ], + "terms": [ + { + "name": "Afghanistan", + "iso3166_1_alpha2": "AF", + "region": "Asia", + "subregion": "Southern Asia" + }, + { + "name": "Albania", + "iso3166_1_alpha2": "AL", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Algeria", + "iso3166_1_alpha2": "DZ", + "region": "Africa", + "subregion": "Northern Africa" + }, + { + "name": "Andorra", + "iso3166_1_alpha2": "AD", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Angola", + "iso3166_1_alpha2": "AO", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Antigua and Barbuda", + "iso3166_1_alpha2": "AG", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Argentina", + "iso3166_1_alpha2": "AR", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Armenia", + "iso3166_1_alpha2": "AM", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Australia", + "iso3166_1_alpha2": "AU", + "region": "Oceania", + "subregion": "Australia and New Zealand" + }, + { + "name": "Austria", + "iso3166_1_alpha2": "AT", + "region": "Europe", + "subregion": "Western Europe" + }, + { + "name": "Azerbaijan", + "iso3166_1_alpha2": "AZ", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Bahamas", + "iso3166_1_alpha2": "BS", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Bahrain", + "iso3166_1_alpha2": "BH", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Bangladesh", + "iso3166_1_alpha2": "BD", + "region": "Asia", + "subregion": "Southern Asia" + }, + { + "name": "Barbados", + "iso3166_1_alpha2": "BB", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Belarus", + "iso3166_1_alpha2": "BY", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "Belgium", + "iso3166_1_alpha2": "BE", + "region": "Europe", + "subregion": "Western Europe" + }, + { + "name": "Belize", + "iso3166_1_alpha2": "BZ", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Benin", + "iso3166_1_alpha2": "BJ", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Bhutan", + "iso3166_1_alpha2": "BT", + "region": "Asia", + "subregion": "Southern Asia" + }, + { + "name": "Bolivia", + "iso3166_1_alpha2": "BO", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Bosnia and Herzegovina", + "iso3166_1_alpha2": "BA", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Botswana", + "iso3166_1_alpha2": "BW", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Brazil", + "iso3166_1_alpha2": "BR", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Brunei", + "iso3166_1_alpha2": "BN", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Bulgaria", + "iso3166_1_alpha2": "BG", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "Burkina Faso", + "iso3166_1_alpha2": "BF", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Burundi", + "iso3166_1_alpha2": "BI", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Cabo Verde", + "iso3166_1_alpha2": "CV", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Cambodia", + "iso3166_1_alpha2": "KH", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Cameroon", + "iso3166_1_alpha2": "CM", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Canada", + "iso3166_1_alpha2": "CA", + "region": "Americas", + "subregion": "Northern America" + }, + { + "name": "Central African Republic", + "iso3166_1_alpha2": "CF", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Chad", + "iso3166_1_alpha2": "TD", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Chile", + "iso3166_1_alpha2": "CL", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "China", + "iso3166_1_alpha2": "CN", + "region": "Asia", + "subregion": "Eastern Asia" + }, + { + "name": "Colombia", + "iso3166_1_alpha2": "CO", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Comoros", + "iso3166_1_alpha2": "KM", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Costa Rica", + "iso3166_1_alpha2": "CR", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Côte d'Ivoire", + "iso3166_1_alpha2": "CI", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Croatia", + "iso3166_1_alpha2": "HR", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Cuba", + "iso3166_1_alpha2": "CU", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Cyprus", + "iso3166_1_alpha2": "CY", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Czech Republic", + "iso3166_1_alpha2": "CZ", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "Democratic Republic of the Congo", + "iso3166_1_alpha2": "CD", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Denmark", + "iso3166_1_alpha2": "DK", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "Djibouti", + "iso3166_1_alpha2": "DJ", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Dominica", + "iso3166_1_alpha2": "DM", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Dominican Republic", + "iso3166_1_alpha2": "DO", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Ecuador", + "iso3166_1_alpha2": "EC", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Egypt", + "iso3166_1_alpha2": "EG", + "region": "Africa", + "subregion": "Northern Africa" + }, + { + "name": "El Salvador", + "iso3166_1_alpha2": "SV", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Equatorial Guinea", + "iso3166_1_alpha2": "GQ", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Eritrea", + "iso3166_1_alpha2": "ER", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Estonia", + "iso3166_1_alpha2": "EE", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "Eswatini", + "iso3166_1_alpha2": "SZ", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Ethiopia", + "iso3166_1_alpha2": "ET", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Federated States of Micronesia", + "iso3166_1_alpha2": "FM", + "region": "Oceania", + "subregion": "Micronesia" + }, + { + "name": "Fiji", + "iso3166_1_alpha2": "FJ", + "region": "Oceania", + "subregion": "Melanesia" + }, + { + "name": "Finland", + "iso3166_1_alpha2": "FI", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "France", + "iso3166_1_alpha2": "FR", + "region": "Europe", + "subregion": "Western Europe" + }, + { + "name": "Gabon", + "iso3166_1_alpha2": "GA", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Gambia", + "iso3166_1_alpha2": "GM", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Georgia", + "iso3166_1_alpha2": "GE", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Germany", + "iso3166_1_alpha2": "DE", + "region": "Europe", + "subregion": "Western Europe" + }, + { + "name": "Ghana", + "iso3166_1_alpha2": "GH", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Greece", + "iso3166_1_alpha2": "GR", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Grenada", + "iso3166_1_alpha2": "GD", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Guatemala", + "iso3166_1_alpha2": "GT", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Guinea", + "iso3166_1_alpha2": "GN", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Guinea-Bissau", + "iso3166_1_alpha2": "GW", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Guyana", + "iso3166_1_alpha2": "GY", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Haiti", + "iso3166_1_alpha2": "HT", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Honduras", + "iso3166_1_alpha2": "HN", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Hungary", + "iso3166_1_alpha2": "HU", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "Iceland", + "iso3166_1_alpha2": "IS", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "India", + "iso3166_1_alpha2": "IN", + "region": "Asia", + "subregion": "Southern Asia" + }, + { + "name": "Indonesia", + "iso3166_1_alpha2": "ID", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Iran", + "iso3166_1_alpha2": "IR", + "region": "Asia", + "subregion": "Southern Asia" + }, + { + "name": "Iraq", + "iso3166_1_alpha2": "IQ", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Ireland", + "iso3166_1_alpha2": "IE", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "Israel", + "iso3166_1_alpha2": "IL", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Italy", + "iso3166_1_alpha2": "IT", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Jamaica", + "iso3166_1_alpha2": "JM", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Japan", + "iso3166_1_alpha2": "JP", + "region": "Asia", + "subregion": "Eastern Asia" + }, + { + "name": "Jordan", + "iso3166_1_alpha2": "JO", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Kazakhstan", + "iso3166_1_alpha2": "KZ", + "region": "Asia", + "subregion": "Central Asia" + }, + { + "name": "Kenya", + "iso3166_1_alpha2": "KE", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Kiribati", + "iso3166_1_alpha2": "KI", + "region": "Oceania", + "subregion": "Micronesia" + }, + { + "name": "Kuwait", + "iso3166_1_alpha2": "KW", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Kyrgyzstan", + "iso3166_1_alpha2": "KG", + "region": "Asia", + "subregion": "Central Asia" + }, + { + "name": "Laos", + "iso3166_1_alpha2": "LA", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Latvia", + "iso3166_1_alpha2": "LV", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "Lebanon", + "iso3166_1_alpha2": "LB", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Lesotho", + "iso3166_1_alpha2": "LS", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Liberia", + "iso3166_1_alpha2": "LR", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Libya", + "iso3166_1_alpha2": "LY", + "region": "Africa", + "subregion": "Northern Africa" + }, + { + "name": "Liechtenstein", + "iso3166_1_alpha2": "LI", + "region": "Europe", + "subregion": "Western Europe" + }, + { + "name": "Lithuania", + "iso3166_1_alpha2": "LT", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "Luxembourg", + "iso3166_1_alpha2": "LU", + "region": "Europe", + "subregion": "Western Europe" + }, + { + "name": "Madagascar", + "iso3166_1_alpha2": "MG", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Malawi", + "iso3166_1_alpha2": "MW", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Malaysia", + "iso3166_1_alpha2": "MY", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Maldives", + "iso3166_1_alpha2": "MV", + "region": "Asia", + "subregion": "Southern Asia" + }, + { + "name": "Mali", + "iso3166_1_alpha2": "ML", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Malta", + "iso3166_1_alpha2": "MT", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Marshall Islands", + "iso3166_1_alpha2": "MH", + "region": "Oceania", + "subregion": "Micronesia" + }, + { + "name": "Mauritania", + "iso3166_1_alpha2": "MR", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Mauritius", + "iso3166_1_alpha2": "MU", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Mexico", + "iso3166_1_alpha2": "MX", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Moldova", + "iso3166_1_alpha2": "MD", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "Monaco", + "iso3166_1_alpha2": "MC", + "region": "Europe", + "subregion": "Western Europe" + }, + { + "name": "Mongolia", + "iso3166_1_alpha2": "MN", + "region": "Asia", + "subregion": "Eastern Asia" + }, + { + "name": "Montenegro", + "iso3166_1_alpha2": "ME", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Morocco", + "iso3166_1_alpha2": "MA", + "region": "Africa", + "subregion": "Northern Africa" + }, + { + "name": "Mozambique", + "iso3166_1_alpha2": "MZ", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Myanmar", + "iso3166_1_alpha2": "MM", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Namibia", + "iso3166_1_alpha2": "NA", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Nauru", + "iso3166_1_alpha2": "NR", + "region": "Oceania", + "subregion": "Micronesia" + }, + { + "name": "Nepal", + "iso3166_1_alpha2": "NP", + "region": "Asia", + "subregion": "Southern Asia" + }, + { + "name": "Netherlands", + "iso3166_1_alpha2": "NL", + "region": "Europe", + "subregion": "Western Europe" + }, + { + "name": "New Zealand", + "iso3166_1_alpha2": "NZ", + "region": "Oceania", + "subregion": "Australia and New Zealand" + }, + { + "name": "Nicaragua", + "iso3166_1_alpha2": "NI", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Niger", + "iso3166_1_alpha2": "NE", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Nigeria", + "iso3166_1_alpha2": "NG", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "North Korea", + "iso3166_1_alpha2": "KP", + "region": "Asia", + "subregion": "Eastern Asia" + }, + { + "name": "North Macedonia", + "iso3166_1_alpha2": "MK", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Norway", + "iso3166_1_alpha2": "NO", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "Oman", + "iso3166_1_alpha2": "OM", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Pakistan", + "iso3166_1_alpha2": "PK", + "region": "Asia", + "subregion": "Southern Asia" + }, + { + "name": "Palau", + "iso3166_1_alpha2": "PW", + "region": "Oceania", + "subregion": "Micronesia" + }, + { + "name": "Panama", + "iso3166_1_alpha2": "PA", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Papua New Guinea", + "iso3166_1_alpha2": "PG", + "region": "Oceania", + "subregion": "Melanesia" + }, + { + "name": "Paraguay", + "iso3166_1_alpha2": "PY", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Peru", + "iso3166_1_alpha2": "PE", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Philippines", + "iso3166_1_alpha2": "PH", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Poland", + "iso3166_1_alpha2": "PL", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "Portugal", + "iso3166_1_alpha2": "PT", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Qatar", + "iso3166_1_alpha2": "QA", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Republic of the Congo", + "iso3166_1_alpha2": "CG", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Romania", + "iso3166_1_alpha2": "RO", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "Russia", + "iso3166_1_alpha2": "RU", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "Rwanda", + "iso3166_1_alpha2": "RW", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Saint Kitts and Nevis", + "iso3166_1_alpha2": "KN", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Saint Lucia", + "iso3166_1_alpha2": "LC", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Saint Vincent and the Grenadines", + "iso3166_1_alpha2": "VC", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Samoa", + "iso3166_1_alpha2": "WS", + "region": "Oceania", + "subregion": "Polynesia" + }, + { + "name": "San Marino", + "iso3166_1_alpha2": "SM", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "São Tomé and Príncipe", + "iso3166_1_alpha2": "ST", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Saudi Arabia", + "iso3166_1_alpha2": "SA", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Senegal", + "iso3166_1_alpha2": "SN", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Serbia", + "iso3166_1_alpha2": "RS", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Seychelles", + "iso3166_1_alpha2": "SC", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Sierra Leone", + "iso3166_1_alpha2": "SL", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Singapore", + "iso3166_1_alpha2": "SG", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Slovakia", + "iso3166_1_alpha2": "SK", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "Slovenia", + "iso3166_1_alpha2": "SI", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Solomon Islands", + "iso3166_1_alpha2": "SB", + "region": "Oceania", + "subregion": "Melanesia" + }, + { + "name": "Somalia", + "iso3166_1_alpha2": "SO", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "South Africa", + "iso3166_1_alpha2": "ZA", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "South Korea", + "iso3166_1_alpha2": "KR", + "region": "Asia", + "subregion": "Eastern Asia" + }, + { + "name": "South Sudan", + "iso3166_1_alpha2": "SS", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Spain", + "iso3166_1_alpha2": "ES", + "region": "Europe", + "subregion": "Southern Europe" + }, + { + "name": "Sri Lanka", + "iso3166_1_alpha2": "LK", + "region": "Asia", + "subregion": "Southern Asia" + }, + { + "name": "Sudan", + "iso3166_1_alpha2": "SD", + "region": "Africa", + "subregion": "Northern Africa" + }, + { + "name": "Suriname", + "iso3166_1_alpha2": "SR", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Sweden", + "iso3166_1_alpha2": "SE", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "Switzerland", + "iso3166_1_alpha2": "CH", + "region": "Europe", + "subregion": "Western Europe" + }, + { + "name": "Syria", + "iso3166_1_alpha2": "SY", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Tajikistan", + "iso3166_1_alpha2": "TJ", + "region": "Asia", + "subregion": "Central Asia" + }, + { + "name": "Tanzania", + "iso3166_1_alpha2": "TZ", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Thailand", + "iso3166_1_alpha2": "TH", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Timor-Leste", + "iso3166_1_alpha2": "TL", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Togo", + "iso3166_1_alpha2": "TG", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Tonga", + "iso3166_1_alpha2": "TO", + "region": "Oceania", + "subregion": "Polynesia" + }, + { + "name": "Trinidad and Tobago", + "iso3166_1_alpha2": "TT", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Tunisia", + "iso3166_1_alpha2": "TN", + "region": "Africa", + "subregion": "Northern Africa" + }, + { + "name": "Turkey", + "iso3166_1_alpha2": "TR", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Turkmenistan", + "iso3166_1_alpha2": "TM", + "region": "Asia", + "subregion": "Central Asia" + }, + { + "name": "Tuvalu", + "iso3166_1_alpha2": "TV", + "region": "Oceania", + "subregion": "Polynesia" + }, + { + "name": "Uganda", + "iso3166_1_alpha2": "UG", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Ukraine", + "iso3166_1_alpha2": "UA", + "region": "Europe", + "subregion": "Eastern Europe" + }, + { + "name": "United Arab Emirates", + "iso3166_1_alpha2": "AE", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "United Kingdom", + "iso3166_1_alpha2": "GB", + "region": "Europe", + "subregion": "Northern Europe" + }, + { + "name": "United States", + "iso3166_1_alpha2": "US", + "region": "Americas", + "subregion": "Northern America" + }, + { + "name": "Uruguay", + "iso3166_1_alpha2": "UY", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Uzbekistan", + "iso3166_1_alpha2": "UZ", + "region": "Asia", + "subregion": "Central Asia" + }, + { + "name": "Vanuatu", + "iso3166_1_alpha2": "VU", + "region": "Oceania", + "subregion": "Melanesia" + }, + { + "name": "Venezuela", + "iso3166_1_alpha2": "VE", + "region": "Americas", + "subregion": "Latin America and the Caribbean" + }, + { + "name": "Vietnam", + "iso3166_1_alpha2": "VN", + "region": "Asia", + "subregion": "South-eastern Asia" + }, + { + "name": "Yemen", + "iso3166_1_alpha2": "YE", + "region": "Asia", + "subregion": "Western Asia" + }, + { + "name": "Zambia", + "iso3166_1_alpha2": "ZM", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + }, + { + "name": "Zimbabwe", + "iso3166_1_alpha2": "ZW", + "region": "Africa", + "subregion": "Sub-Saharan Africa" + } + ] +} diff --git a/gaps.html b/gaps.html new file mode 100644 index 0000000..12a63a8 --- /dev/null +++ b/gaps.html @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<html lang="en"> +<head> +<meta charset="UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1.0" /> +<title>Coverage Gaps — Mapping Voices + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

Coverage Gaps

+

+ Where does the index not yet reach? This page lists, region by region, the + UN member states with at least one indexed oral-history or voice-testimony + collection — and those with none yet. +

+

+ This shows gaps in the indexed dataset, not in oral history. The absence of + a pin is not evidence of absence: every country listed here as “not yet + indexed” has its own oral traditions, and very likely archives that record + them, which have not yet been found or verified. +

+
+
UN member states
–
+
With an indexed collection
–
+
None indexed yet
–
+
Territories & other entities indexed
–
+
+

+ Know a collection in one of these countries? + Propose it + — no Git or JSON needed. It must be a real, publicly documented collection + with its own page (inclusion criteria, + contributing guide). +

+

+ Counts describe the collections indexed in Mapping Voices, + placed by the country each collection's pin belongs to (Methodology + §5). + The list of 193 member states and their UN M49 regions is a static reference file, + un-m49-countries.json. + Territories and other non-member entities are shown where indexed but not + counted as gaps; grouping follows UN M49 and records no political claim. +

+
+ +
+

By region

+

Loading coverage…

+
+ + + + + + + + + + + + +
+
+ +
+ +
+ + + + + + diff --git a/index.html b/index.html index bbed509..b0ed31c 100644 --- a/index.html +++ b/index.html @@ -202,6 +202,8 @@

About this collection