All checks were successful
Deploy production / deploy (push) Successful in 1m9s
118 lines
2.8 KiB
Svelte
118 lines
2.8 KiB
Svelte
<script lang="ts">
|
|
import { flag, fmtNumber, monogram, brandHue, thumbAt } from '#lib/trains/shared.js';
|
|
import ArrowLeft from 'lucide-svelte/icons/arrow-left';
|
|
import type { PageProps } from './$types';
|
|
|
|
let { data }: PageProps = $props();
|
|
</script>
|
|
|
|
<div class="mx-auto max-w-6xl px-4 py-12 sm:px-6 sm:py-16">
|
|
<a href="/trackers/trains" class="back"><ArrowLeft size={15} /> all trains</a>
|
|
<header class="mt-6 mb-8">
|
|
<h1 class="text-4xl font-semibold tracking-tight sm:text-5xl">countries</h1>
|
|
<p class="mt-3 max-w-2xl text-[var(--site-muted)]">
|
|
Train types from {fmtNumber(data.countries.length)} countries, counted where they were built and
|
|
where they ran. Tap one for its trains, oldest first.
|
|
</p>
|
|
</header>
|
|
|
|
<ul class="grid">
|
|
{#each data.countries as c, i (c.slug)}
|
|
<li>
|
|
<a href="/trackers/trains/countries/{c.slug}" class="tile">
|
|
<span class="media" style:--hue={brandHue(c.name)}>
|
|
{#if c.photo}
|
|
<img
|
|
src={thumbAt(c.photo, 330)}
|
|
alt=""
|
|
loading={i < 8 ? 'eager' : 'lazy'}
|
|
decoding="async"
|
|
width="330"
|
|
height="186"
|
|
/>
|
|
{:else}
|
|
<span class="placeholder" aria-hidden="true">{monogram(c.name)}</span>
|
|
{/if}
|
|
</span>
|
|
<span class="name">{flag(c.name)} {c.name}</span>
|
|
<span class="meta">{fmtNumber(c.types)} {c.types === 1 ? 'type' : 'types'}</span>
|
|
</a>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
</div>
|
|
|
|
<style>
|
|
.back {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.35rem;
|
|
font-size: 0.85rem;
|
|
color: var(--site-muted);
|
|
}
|
|
.back:hover {
|
|
color: var(--site-text);
|
|
}
|
|
.grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
|
|
gap: 0.75rem;
|
|
}
|
|
.tile {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.3rem;
|
|
height: 100%;
|
|
padding: 0 0 0.65rem;
|
|
overflow: hidden;
|
|
border: 1px solid var(--site-border);
|
|
border-radius: 0.9rem;
|
|
background: var(--site-surface);
|
|
transition:
|
|
transform 0.15s,
|
|
border-color 0.15s,
|
|
background 0.15s;
|
|
}
|
|
.tile:hover,
|
|
.tile:focus-visible {
|
|
transform: translateY(-2px);
|
|
border-color: var(--site-muted);
|
|
background: var(--site-hover);
|
|
}
|
|
.media {
|
|
position: relative;
|
|
display: block;
|
|
aspect-ratio: 16 / 9;
|
|
margin-bottom: 0.3rem;
|
|
background: radial-gradient(circle at 30% 20%, hsl(var(--hue) 35% 22%), hsl(var(--hue) 30% 9%));
|
|
}
|
|
.media img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
.placeholder {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: grid;
|
|
place-items: center;
|
|
font-size: 2rem;
|
|
font-weight: 800;
|
|
color: hsl(var(--hue) 50% 60% / 0.25);
|
|
}
|
|
.name,
|
|
.meta {
|
|
padding: 0 0.75rem;
|
|
}
|
|
.name {
|
|
font-size: 0.9rem;
|
|
font-weight: 600;
|
|
line-height: 1.2;
|
|
}
|
|
.meta {
|
|
font-size: 0.72rem;
|
|
color: var(--site-muted);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
</style>
|