refactor(components): replace all hardcoded colors with semantic tokens

Replaces bg-white, text-brand-navy, border-brand-sand, text-gray-*, bg-[#2A2A2A],
bg-brand-purple/15, hover:bg-brand-sand, etc. across all 35 .svelte files with
semantic token utilities (bg-surface, text-ink, border-line, bg-pdf-bg, bg-nav-active,
bg-muted, text-accent, bg-primary, ...).

Also adds CSS filter: invert(1) in layout.css for De Gruyter <img> icons in dark mode,
excluding icons that carry .invert already (to prevent double-inversion).

Closes #64
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-25 12:22:50 +01:00
parent caba89dacc
commit e4539ed0f0
32 changed files with 569 additions and 613 deletions

View File

@@ -21,14 +21,14 @@ let { doc }: { doc: Doc } = $props();
<!-- DETAILS GROUP -->
<div>
<h3
class="border-brand-sand mb-4 border-b pb-2 font-sans text-xs font-bold tracking-widest text-brand-navy uppercase"
class="mb-4 border-b border-line pb-2 font-sans text-xs font-bold tracking-widest text-ink uppercase"
>
{m.doc_section_details()}
</h3>
<div class="space-y-5">
<!-- Date -->
<div class="flex items-start">
<span class="mt-0.5 w-8 text-brand-mint">
<span class="mt-0.5 w-8 text-accent">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Calendar/Calendar-Add-MD.svg"
alt=""
@@ -37,16 +37,16 @@ let { doc }: { doc: Doc } = $props();
/>
</span>
<div>
<span class="block font-serif text-lg text-brand-navy">
<span class="block font-serif text-lg text-ink">
{doc.documentDate ? formatDate(doc.documentDate) : '—'}
</span>
<span class="font-sans text-xs text-gray-500">{m.doc_label_document_date()}</span>
<span class="font-sans text-xs text-ink-2">{m.doc_label_document_date()}</span>
</div>
</div>
<!-- Creation Location -->
<div class="flex items-start">
<span class="mt-0.5 w-8 text-brand-mint">
<span class="mt-0.5 w-8 text-accent">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Location-MD.svg"
alt=""
@@ -55,17 +55,17 @@ let { doc }: { doc: Doc } = $props();
/>
</span>
<div>
<span class="block font-serif text-lg text-brand-navy">
<span class="block font-serif text-lg text-ink">
{doc.location ? doc.location : '—'}
</span>
<span class="font-sans text-xs text-gray-500">{m.doc_label_creation_location()}</span>
<span class="font-sans text-xs text-ink-2">{m.doc_label_creation_location()}</span>
</div>
</div>
<!-- Physical Archive Location -->
{#if doc.documentLocation}
<div class="flex items-start">
<span class="mt-0.5 w-8 text-brand-mint">
<span class="mt-0.5 w-8 text-accent">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Folder-MD.svg"
alt=""
@@ -74,10 +74,10 @@ let { doc }: { doc: Doc } = $props();
/>
</span>
<div>
<span class="block font-serif text-lg text-brand-navy">
<span class="block font-serif text-lg text-ink">
{doc.documentLocation}
</span>
<span class="font-sans text-xs text-gray-500"
<span class="font-sans text-xs text-ink-2"
>{m.doc_label_archive_location_original()}</span
>
</div>
@@ -87,7 +87,7 @@ let { doc }: { doc: Doc } = $props();
<!-- Tags -->
{#if doc.tags && doc.tags.length > 0}
<div class="flex items-start">
<span class="mt-0.5 w-8 text-brand-mint">
<span class="mt-0.5 w-8 text-accent">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Bookmark/Bookmark-Outline-MD.svg"
alt=""
@@ -100,14 +100,14 @@ let { doc }: { doc: Doc } = $props();
{#each doc.tags as tag (tag.id)}
<a
href="/?tag={encodeURIComponent(tag.name)}"
class="bg-brand-sand/50 inline-flex items-center rounded px-2 py-0.5 text-xs font-bold tracking-wide text-brand-navy uppercase transition-colors hover:bg-brand-navy hover:text-white"
class="inline-flex items-center rounded bg-muted px-2 py-0.5 text-xs font-bold tracking-wide text-ink uppercase transition-colors hover:bg-primary hover:text-white"
title={m.doc_tag_filter_title({ name: tag.name })}
>
{tag.name}
</a>
{/each}
</div>
<span class="font-sans text-xs text-gray-500">{m.form_label_tags()}</span>
<span class="font-sans text-xs text-ink-2">{m.form_label_tags()}</span>
</div>
</div>
{/if}
@@ -117,61 +117,59 @@ let { doc }: { doc: Doc } = $props();
<!-- PERSONEN GROUP -->
<div>
<h3
class="border-brand-sand mb-4 border-b pb-2 font-sans text-xs font-bold tracking-widest text-brand-navy uppercase"
class="mb-4 border-b border-line pb-2 font-sans text-xs font-bold tracking-widest text-ink uppercase"
>
{m.doc_section_persons()}
</h3>
<div class="mb-6">
<span class="mb-2 block font-sans text-xs text-gray-400 uppercase"
>{m.form_label_sender()}</span
>
<span class="mb-2 block font-sans text-xs text-ink-3 uppercase">{m.form_label_sender()}</span>
{#if doc.sender}
<a
href="/persons/{doc.sender.id}"
class="group border-brand-sand bg-brand-sand/20 block rounded border p-3 transition hover:border-brand-mint hover:bg-brand-mint/10"
class="group block rounded border border-line bg-muted p-3 transition hover:border-accent hover:bg-accent/10"
>
<div class="flex items-center gap-3">
<div
class="flex h-8 w-8 items-center justify-center rounded-full bg-brand-navy font-serif text-sm text-white"
class="flex h-8 w-8 items-center justify-center rounded-full bg-primary font-serif text-sm text-white"
>
{doc.sender.firstName[0]}{doc.sender.lastName[0]}
</div>
<div>
<p
class="font-serif text-brand-navy decoration-brand-mint underline-offset-2 group-hover:underline"
class="font-serif text-ink decoration-brand-mint underline-offset-2 group-hover:underline"
>
{doc.sender.firstName}
{doc.sender.lastName}
</p>
{#if doc.sender.alias}
<p class="font-sans text-xs text-gray-500">{doc.sender.alias}</p>
<p class="font-sans text-xs text-ink-2">{doc.sender.alias}</p>
{/if}
</div>
</div>
</a>
{:else}
<span class="font-serif text-sm text-gray-400 italic">{m.doc_sender_not_specified()}</span>
<span class="font-serif text-sm text-ink-3 italic">{m.doc_sender_not_specified()}</span>
{/if}
</div>
<div>
<span class="mb-2 block font-sans text-xs text-gray-400 uppercase"
<span class="mb-2 block font-sans text-xs text-ink-3 uppercase"
>{m.form_label_receivers()}</span
>
{#if doc.receivers && doc.receivers.length > 0}
<div class="space-y-2">
{#each doc.receivers as receiver (receiver.id)}
<div
class="group border-brand-sand flex items-center justify-between rounded border bg-white p-3 transition hover:border-brand-navy"
class="group flex items-center justify-between rounded border border-line bg-surface p-3 transition hover:border-primary"
>
<a href="/persons/{receiver.id}" class="flex min-w-0 flex-1 items-center gap-3">
<div
class="flex h-6 w-6 items-center justify-center rounded-full bg-gray-100 font-serif text-xs text-gray-500"
class="flex h-6 w-6 items-center justify-center rounded-full bg-gray-100 font-serif text-xs text-ink-2"
>
{receiver.firstName[0]}{receiver.lastName[0]}
</div>
<span class="truncate font-serif text-sm text-brand-navy">
<span class="truncate font-serif text-sm text-ink">
{receiver.firstName}
{receiver.lastName}
</span>
@@ -180,7 +178,7 @@ let { doc }: { doc: Doc } = $props();
{#if doc.sender}
<a
href="/conversations?senderId={doc.sender.id}&receiverId={receiver.id}"
class="text-gray-300 transition hover:text-brand-mint"
class="text-ink-3 transition hover:text-accent"
title={m.doc_conversation_title()}
>
<img
@@ -195,7 +193,7 @@ let { doc }: { doc: Doc } = $props();
{/each}
</div>
{:else}
<span class="font-serif text-sm text-gray-400 italic">{m.doc_no_receivers()}</span>
<span class="font-serif text-sm text-ink-3 italic">{m.doc_no_receivers()}</span>
{/if}
</div>
</div>