All checks were successful
Test and deploy staging / staging (push) Successful in 1m49s
World map with switchable layers (what "liberal" means, what left vs right is about, traditional/secular and survival/self-expression values), country cards, a shared-scale party compass, a values scatter and national narratives of major events. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
96 lines
3.2 KiB
Svelte
96 lines
3.2 KiB
Svelte
<script lang="ts">
|
|
import EyeOff from 'lucide-svelte/icons/eye-off';
|
|
import Swords from 'lucide-svelte/icons/swords';
|
|
import { countryById, divides, liberalMeanings, profileById, regions } from './data';
|
|
|
|
let { id }: { id: string } = $props();
|
|
|
|
let country = $derived(countryById.get(id));
|
|
let profile = $derived(profileById.get(id));
|
|
|
|
const colors: Record<string, string> = {
|
|
left: 'var(--wo-s1)',
|
|
market: 'var(--wo-s2)',
|
|
western: 'var(--wo-s3)',
|
|
economy: 'var(--wo-s1)',
|
|
culture: 'var(--wo-s2)',
|
|
history: 'var(--wo-s3)',
|
|
none: 'var(--wo-none)'
|
|
};
|
|
// Map a -2.5…2.5 score onto the gauge.
|
|
const position = (value: number) => `${Math.min(Math.max((value + 2.5) / 5, 0), 1) * 100}%`;
|
|
</script>
|
|
|
|
{#if country}
|
|
<div class="wo-card">
|
|
<div class="mb-4 flex flex-wrap items-baseline justify-between gap-2">
|
|
<h3 class="text-2xl font-semibold">{country.name}</h3>
|
|
<span class="text-sm text-[var(--site-muted)]">{regions[country.region]}</span>
|
|
</div>
|
|
|
|
{#if profile}<p class="mb-5 text-lg">{profile.center}</p>{/if}
|
|
|
|
<div class="grid gap-6 md:grid-cols-2">
|
|
<div class="space-y-4">
|
|
{#if country.values}
|
|
{#each [{ label: ['traditional', 'secular'], value: country.values.y }, { label: ['survival', 'self-expression'], value: country.values.x }] as gauge (gauge.label[0])}
|
|
<div>
|
|
<div class="wo-gauge" aria-hidden="true">
|
|
<span class="wo-gauge-marker" style:left={position(gauge.value)}></span>
|
|
</div>
|
|
<div class="mt-1 flex justify-between text-xs text-[var(--site-muted)]">
|
|
<span>{gauge.label[0]}</span><span>{gauge.label[1]}</span>
|
|
</div>
|
|
<span class="sr-only">{gauge.label[0]} to {gauge.label[1]}: {gauge.value}</span>
|
|
</div>
|
|
{/each}
|
|
{/if}
|
|
<div class="flex flex-wrap gap-2 text-sm">
|
|
{#if country.liberal}
|
|
<span class="wo-tag"
|
|
><span class="wo-swatch" style:background={colors[country.liberal]}></span>"liberal" = {liberalMeanings[
|
|
country.liberal
|
|
]}</span
|
|
>
|
|
{/if}
|
|
{#if country.divide}
|
|
<span class="wo-tag"
|
|
><span class="wo-swatch" style:background={colors[country.divide]}></span>left vs
|
|
right: {divides[country.divide]}</span
|
|
>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
|
|
{#if profile}
|
|
<div class="space-y-4">
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<span class="wo-tag-label"><Swords size={16} aria-hidden="true" />fights over</span>
|
|
{#each profile.fights as fight (fight)}
|
|
<span class="wo-tag">{fight}</span>
|
|
{/each}
|
|
</div>
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<span class="wo-tag-label"><EyeOff size={16} aria-hidden="true" />blind spots</span>
|
|
{#each profile.blindSpots as spot (spot)}
|
|
<span class="wo-tag wo-tag-dashed">{spot}</span>
|
|
{/each}
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
|
|
{#if profile}
|
|
<ol class="wo-timeline mt-8" aria-label="History that shaped it">
|
|
{#each profile.timeline as moment (moment.year)}
|
|
<li>
|
|
<span class="wo-timeline-year">{moment.year}</span>
|
|
<span class="wo-timeline-dot" aria-hidden="true"></span>
|
|
<span class="wo-timeline-label">{moment.label}</span>
|
|
</li>
|
|
{/each}
|
|
</ol>
|
|
{/if}
|
|
</div>
|
|
{/if}
|