feat: case-study template, all pages, routing, sitemap, 404

- case-study components: CsHeader, TldrBox, MiniToc, SectionRenderer, DecisionList,
  ArchDiagram (data-driven), Gallery, NextPrev, CaseStudyPage
- standalone pages: projects index, about, experience, contact (with form),
  cv hub, colophon — all EN/NO compositions
- full route tree: EN root + /no localised slugs (prosjekter, om-meg, erfaring,
  kontakt, kolofon, hjemmelab) per ROUTING_SPEC
- bilingual 404 with trace-fray motif; robots.txt + sitemap.xml from slug map
- Portrait atom; reusable sections gain header/eyebrow toggles for standalone pages

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
cesnimda
2026-07-04 01:30:32 +02:00
parent 9a6d0edf6d
commit 2330f374fc
44 changed files with 1112 additions and 31 deletions
@@ -7,9 +7,9 @@ import SectionLabel from '@components/ui/SectionLabel.astro';
interface Props {
locale: Locale;
compact?: boolean; // when true (experience page), render heading differently
eyebrow?: boolean; // false on the standalone experience page (it has its own H1)
}
const { locale } = Astro.props;
const { locale, eyebrow = true } = Astro.props;
const d = useDict(locale);
const items = getExperience(locale);
const firstAlongside = items.findIndex((i) => i.alongside);
@@ -17,9 +17,19 @@ const firstAlongside = items.findIndex((i) => i.alongside);
const period = (from: number, to: number | null) => `${from}${to ?? d.home.present}`;
---
<section id={homeAnchor('experience', locale)} class="mx-auto max-w-[--content-max] px-6 pt-24" data-reveal>
<SectionLabel number="03" text={d.home.experienceLabel} />
<h2 class="mt-4 text-h2">{d.home.experienceHeading}</h2>
<section
id={homeAnchor('experience', locale)}
class:list={['mx-auto max-w-[--content-max] px-6', eyebrow && 'pt-24']}
data-reveal
>
{
eyebrow && (
<>
<SectionLabel number="03" text={d.home.experienceLabel} />
<h2 class="mt-4 text-h2">{d.home.experienceHeading}</h2>
</>
)
}
<div class="relative mt-10 pl-8">
<span