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

@@ -25,16 +25,16 @@ let {
<!-- Desktop / tablet panel (≥ sm): absolute overlay on the right side -->
<div
class="border-brand-sand absolute top-0 right-0 z-50 hidden h-full w-80 flex-col border-l bg-white shadow-2xl sm:flex"
class="absolute top-0 right-0 z-50 hidden h-full w-80 flex-col border-l border-line bg-surface shadow-2xl sm:flex"
>
<div class="border-brand-sand flex shrink-0 items-center justify-between border-b px-4 py-3">
<h3 class="font-sans text-xs font-bold tracking-widest text-brand-navy uppercase">
<div class="flex shrink-0 items-center justify-between border-b border-line px-4 py-3">
<h3 class="font-sans text-xs font-bold tracking-widest text-ink uppercase">
{m.comment_panel_title()}
</h3>
<button
onclick={onClose}
aria-label={m.comment_panel_close()}
class="hover:bg-brand-sand/50 rounded p-1 text-gray-400 transition-colors hover:text-brand-navy"
class="rounded p-1 text-ink-3 transition-colors hover:bg-muted hover:text-ink"
>
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
@@ -60,15 +60,15 @@ let {
<div class="flex-1 bg-black/40" onclick={onClose} role="presentation"></div>
<!-- Slide-up panel -->
<div class="flex max-h-[80vh] flex-col rounded-t-2xl bg-white shadow-2xl">
<div class="border-brand-sand flex shrink-0 items-center justify-between border-b px-4 py-3">
<h3 class="font-sans text-xs font-bold tracking-widest text-brand-navy uppercase">
<div class="flex max-h-[80vh] flex-col rounded-t-2xl bg-surface shadow-2xl">
<div class="flex shrink-0 items-center justify-between border-b border-line px-4 py-3">
<h3 class="font-sans text-xs font-bold tracking-widest text-ink uppercase">
{m.comment_panel_title()}
</h3>
<button
onclick={onClose}
aria-label={m.comment_panel_close()}
class="hover:bg-brand-sand/50 rounded p-1 text-gray-400 transition-colors hover:text-brand-navy"
class="rounded p-1 text-ink-3 transition-colors hover:bg-muted hover:text-ink"
>
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />

View File

@@ -26,20 +26,20 @@ const visible = $derived(activeAnnotationId !== null);
</script>
<div
class="border-brand-sand absolute inset-y-0 right-0 z-10 flex w-80 flex-col border-l bg-white shadow-[-4px_0_16px_rgba(0,0,0,0.08)] transition-transform duration-200 {visible
class="absolute inset-y-0 right-0 z-10 flex w-80 flex-col border-l border-line bg-surface shadow-[-4px_0_16px_rgba(0,0,0,0.08)] transition-transform duration-200 {visible
? 'translate-x-0'
: 'pointer-events-none translate-x-full'}"
data-testid="annotation-side-panel"
>
<!-- Header -->
<div class="border-brand-sand flex shrink-0 items-center justify-between border-b px-4 py-3">
<span class="font-sans text-xs font-medium text-brand-navy">
<div class="flex shrink-0 items-center justify-between border-b border-line px-4 py-3">
<span class="font-sans text-xs font-medium text-ink">
{m.doc_panel_discussion_annotation_tab({ page: String(activeAnnotationPage ?? '?') })}
</span>
<button
onclick={onClose}
aria-label={m.comment_panel_close()}
class="hover:bg-brand-sand/50 rounded p-1 text-gray-400 transition-colors hover:text-brand-navy"
class="rounded p-1 text-ink-3 transition-colors hover:bg-muted hover:text-ink"
>
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />

View File

@@ -191,26 +191,26 @@ onMount(() => {
<div class="space-y-4">
{#each comments as thread, ti (thread.id)}
<div class={ti > 0 ? 'border-brand-sand border-t pt-4' : ''}>
<div class={ti > 0 ? 'border-t border-line pt-4' : ''}>
<!-- Root comment -->
<div>
{#if editingId === thread.id}
<div class="flex flex-col gap-2">
<textarea
class="border-brand-sand w-full resize-none rounded border px-3 py-2 font-serif text-sm text-brand-navy focus:ring-1 focus:ring-brand-mint focus:outline-none"
class="w-full resize-none rounded border border-line px-3 py-2 font-serif text-sm text-ink focus:ring-1 focus:ring-accent focus:outline-none"
rows={3}
bind:value={editText}
></textarea>
<div class="flex items-center gap-3">
<button
class="rounded bg-brand-navy px-3 py-1.5 font-sans text-xs font-medium text-white hover:bg-brand-navy/80 disabled:opacity-40"
class="rounded bg-primary px-3 py-1.5 font-sans text-xs font-medium text-white hover:bg-primary/80 disabled:opacity-40"
disabled={posting}
onclick={() => saveEdit(thread.id)}
>
{m.btn_save()}
</button>
<button
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
onclick={cancelEdit}
>
{m.btn_cancel()}
@@ -221,12 +221,10 @@ onMount(() => {
<div class="flex items-start justify-between gap-2">
<div class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<span class="font-sans text-xs font-semibold text-brand-navy"
>{thread.authorName}</span
>
<span class="font-sans text-xs text-gray-400">{timeAgo(thread.createdAt)}</span>
<span class="font-sans text-xs font-semibold text-ink">{thread.authorName}</span>
<span class="font-sans text-xs text-ink-3">{timeAgo(thread.createdAt)}</span>
{#if wasEdited(thread)}
<span class="font-sans text-xs text-gray-400">
<span class="font-sans text-xs text-ink-3">
{m.comment_edited_label()}
{timeAgo(thread.updatedAt)}
</span>
@@ -237,13 +235,13 @@ onMount(() => {
{#if canModify(thread)}
<div class="flex shrink-0 items-center gap-2">
<button
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
onclick={() => startEdit(thread)}
>
{m.btn_edit()}
</button>
<button
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
onclick={() => deleteComment(thread.id)}
>
{m.btn_delete()}
@@ -255,7 +253,7 @@ onMount(() => {
{#if thread.replies.length === 0 && canComment}
<div class="mt-1">
<button
class="font-sans text-xs font-medium text-brand-mint transition-colors hover:text-brand-navy"
class="font-sans text-xs font-medium text-accent transition-colors hover:text-ink"
onclick={() => startReply(thread.id)}
>
{m.comment_btn_reply()}
@@ -267,24 +265,24 @@ onMount(() => {
<!-- Replies -->
{#each thread.replies as reply, ri (reply.id)}
<div class="border-brand-sand mt-3 ml-6 border-l-2 pl-4">
<div class="mt-3 ml-6 border-l-2 border-line pl-4">
{#if editingId === reply.id}
<div class="flex flex-col gap-2">
<textarea
class="border-brand-sand w-full resize-none rounded border px-3 py-2 font-serif text-sm text-brand-navy focus:ring-1 focus:ring-brand-mint focus:outline-none"
class="w-full resize-none rounded border border-line px-3 py-2 font-serif text-sm text-ink focus:ring-1 focus:ring-accent focus:outline-none"
rows={3}
bind:value={editText}
></textarea>
<div class="flex items-center gap-3">
<button
class="rounded bg-brand-navy px-3 py-1.5 font-sans text-xs font-medium text-white hover:bg-brand-navy/80 disabled:opacity-40"
class="rounded bg-primary px-3 py-1.5 font-sans text-xs font-medium text-white hover:bg-primary/80 disabled:opacity-40"
disabled={posting}
onclick={() => saveEdit(reply.id)}
>
{m.btn_save()}
</button>
<button
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
onclick={cancelEdit}
>
{m.btn_cancel()}
@@ -295,12 +293,10 @@ onMount(() => {
<div class="flex items-start justify-between gap-2">
<div class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<span class="font-sans text-xs font-semibold text-brand-navy"
>{reply.authorName}</span
>
<span class="font-sans text-xs text-gray-400">{timeAgo(reply.createdAt)}</span>
<span class="font-sans text-xs font-semibold text-ink">{reply.authorName}</span>
<span class="font-sans text-xs text-ink-3">{timeAgo(reply.createdAt)}</span>
{#if wasEdited(reply)}
<span class="font-sans text-xs text-gray-400">
<span class="font-sans text-xs text-ink-3">
{m.comment_edited_label()}
{timeAgo(reply.updatedAt)}
</span>
@@ -311,13 +307,13 @@ onMount(() => {
{#if canModify(reply)}
<div class="flex shrink-0 items-center gap-2">
<button
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
onclick={() => startEdit(reply)}
>
{m.btn_edit()}
</button>
<button
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
onclick={() => deleteComment(reply.id)}
>
{m.btn_delete()}
@@ -329,7 +325,7 @@ onMount(() => {
{#if ri === thread.replies.length - 1 && canComment}
<div class="mt-1">
<button
class="font-sans text-xs font-medium text-brand-mint transition-colors hover:text-brand-navy"
class="font-sans text-xs font-medium text-accent transition-colors hover:text-ink"
onclick={() => startReply(thread.id)}
>
{m.comment_btn_reply()}
@@ -344,21 +340,21 @@ onMount(() => {
{#if replyingTo === thread.id}
<div class="mt-3 ml-6 flex flex-col gap-2">
<textarea
class="border-brand-sand w-full resize-none rounded border px-3 py-2 font-serif text-sm text-brand-navy focus:ring-1 focus:ring-brand-mint focus:outline-none"
class="w-full resize-none rounded border border-line px-3 py-2 font-serif text-sm text-ink focus:ring-1 focus:ring-accent focus:outline-none"
rows={3}
placeholder={m.comment_placeholder()}
bind:value={replyText}
></textarea>
<div class="flex items-center gap-3">
<button
class="rounded bg-brand-navy px-3 py-1.5 font-sans text-xs font-medium text-white hover:bg-brand-navy/80 disabled:opacity-40"
class="rounded bg-primary px-3 py-1.5 font-sans text-xs font-medium text-white hover:bg-primary/80 disabled:opacity-40"
disabled={posting}
onclick={() => postReply(thread.id)}
>
{m.comment_btn_post()}
</button>
<button
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
onclick={cancelReply}
>
{m.btn_cancel()}
@@ -371,17 +367,17 @@ onMount(() => {
<!-- New top-level comment textarea -->
{#if canComment}
<div class={comments.length > 0 ? 'border-brand-sand border-t pt-4' : ''}>
<div class={comments.length > 0 ? 'border-t border-line pt-4' : ''}>
<div class="flex flex-col gap-2">
<textarea
class="border-brand-sand w-full resize-none rounded border px-3 py-2 font-serif text-sm text-brand-navy focus:ring-1 focus:ring-brand-mint focus:outline-none"
class="w-full resize-none rounded border border-line px-3 py-2 font-serif text-sm text-ink focus:ring-1 focus:ring-accent focus:outline-none"
rows={3}
placeholder={m.comment_placeholder()}
bind:value={newText}
></textarea>
<div>
<button
class="rounded bg-brand-navy px-3 py-1.5 font-sans text-xs font-medium text-white hover:bg-brand-navy/80 disabled:opacity-40"
class="rounded bg-primary px-3 py-1.5 font-sans text-xs font-medium text-white hover:bg-primary/80 disabled:opacity-40"
disabled={posting || !newText.trim()}
onclick={postComment}
>

View File

@@ -121,13 +121,13 @@ const panelHeight = $derived(open ? height : MIN_HEIGHT);
</script>
<div
class="border-brand-sand fixed right-0 bottom-0 left-0 z-30 flex flex-col border-t bg-white shadow-[0_-4px_16px_rgba(0,0,0,0.08)]"
class="fixed right-0 bottom-0 left-0 z-30 flex flex-col border-t border-line bg-surface shadow-[0_-4px_16px_rgba(0,0,0,0.08)]"
style="height: {panelHeight}px"
data-testid="bottom-panel"
>
<!-- Drag handle -->
<div
class="flex h-2 shrink-0 cursor-ns-resize items-center justify-center bg-white"
class="flex h-2 shrink-0 cursor-ns-resize items-center justify-center bg-surface"
style="touch-action: none"
role="separator"
aria-orientation="horizontal"
@@ -141,13 +141,13 @@ const panelHeight = $derived(open ? height : MIN_HEIGHT);
</div>
<!-- Tab bar -->
<div class="border-brand-sand flex shrink-0 items-center border-b bg-white px-4">
<div class="flex shrink-0 items-center border-b border-line bg-surface px-4">
{#each tabs as tab (tab.id)}
<button
onclick={() => openTab(tab.id)}
class="mr-1 px-3 py-2.5 font-sans text-xs font-medium transition-colors {activeTab === tab.id && open
? 'border-b-2 border-brand-navy text-brand-navy'
: 'text-gray-400 hover:text-brand-navy'}"
? 'border-b-2 border-primary text-ink'
: 'text-ink-3 hover:text-ink'}"
aria-pressed={activeTab === tab.id && open}
>
{tab.label()}
@@ -162,7 +162,7 @@ const panelHeight = $derived(open ? height : MIN_HEIGHT);
onclick={closePanel}
data-testid="panel-close-btn"
aria-label="Panel schließen"
class="hover:bg-brand-sand/50 rounded p-1.5 text-gray-400 transition-colors hover:text-brand-navy"
class="rounded p-1.5 text-ink-3 transition-colors hover:bg-muted hover:text-ink"
>
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />

View File

@@ -58,17 +58,17 @@ const compactMeta = $derived.by(() => {
</script>
<div
class="border-brand-sand z-20 flex shrink-0 items-center justify-between border-b bg-white px-6 py-3 shadow-sm"
class="z-20 flex shrink-0 items-center justify-between border-b border-line bg-surface px-6 py-3 shadow-sm"
data-topbar
>
<!-- Left: back + title -->
<div class="flex min-w-0 items-center gap-4 overflow-hidden">
<a
href="/"
class="group flex shrink-0 items-center gap-2 font-sans text-sm font-medium text-gray-500 transition-colors hover:text-brand-navy"
class="group flex shrink-0 items-center gap-2 font-sans text-sm font-medium text-ink-2 transition-colors hover:text-ink"
>
<div
class="bg-brand-sand flex h-8 w-8 items-center justify-center rounded-full transition-colors group-hover:bg-brand-mint"
class="flex h-8 w-8 items-center justify-center rounded-full bg-canvas transition-colors group-hover:bg-accent"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Arrow/Arrow-Left-MD.svg"
@@ -80,15 +80,15 @@ const compactMeta = $derived.by(() => {
<span class="hidden sm:inline">{m.btn_back()}</span>
</a>
<div class="min-w-0 border-l border-gray-200 pl-4">
<div class="min-w-0 border-l border-line pl-4">
<h1
class="truncate font-serif text-base leading-tight text-brand-navy"
class="truncate font-serif text-base leading-tight text-ink"
title={doc.title ?? doc.originalFilename ?? ''}
>
{doc.title || doc.originalFilename}
</h1>
{#if compactMeta}
<p class="truncate font-sans text-xs text-gray-500" title={compactMeta}>
<p class="truncate font-sans text-xs text-ink-2" title={compactMeta}>
{compactMeta}
</p>
{/if}
@@ -102,8 +102,8 @@ const compactMeta = $derived.by(() => {
onclick={() => (annotateMode = !annotateMode)}
aria-label={annotateMode ? m.doc_panel_annotate_stop() : m.doc_panel_annotate()}
class="flex items-center gap-1.5 rounded px-3 py-1.5 font-sans text-xs font-medium transition {annotateMode
? 'bg-brand-navy text-white'
: 'border border-brand-navy text-brand-navy hover:bg-brand-navy hover:text-white'}"
? 'bg-primary text-white'
: 'border border-primary text-ink hover:bg-primary hover:text-white'}"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Note/Note-Add-MD.svg"
@@ -118,7 +118,7 @@ const compactMeta = $derived.by(() => {
{#if canWrite}
<a
href="/documents/{doc.id}/edit"
class="flex items-center gap-2 rounded border border-brand-navy bg-transparent px-3 py-1.5 text-xs font-medium text-brand-navy transition hover:bg-brand-navy hover:text-white"
class="flex items-center gap-2 rounded border border-primary bg-transparent px-3 py-1.5 text-xs font-medium text-ink transition hover:bg-primary hover:text-white"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
@@ -134,7 +134,7 @@ const compactMeta = $derived.by(() => {
<a
href={fileUrl}
download={doc.originalFilename}
class="bg-brand-sand/50 rounded border border-transparent p-1.5 text-brand-navy transition hover:bg-brand-mint"
class="rounded border border-transparent bg-muted p-1.5 text-ink transition hover:bg-accent"
title={m.doc_download_title()}
>
<img

View File

@@ -32,9 +32,9 @@ let {
}: Props = $props();
</script>
<div class="absolute inset-0 bg-[#2A2A2A]">
<div class="absolute inset-0 bg-pdf-bg">
{#if isLoading}
<div class="flex h-full flex-col items-center justify-center text-brand-mint">
<div class="flex h-full flex-col items-center justify-center text-accent">
<svg
class="mb-4 h-8 w-8 animate-spin"
xmlns="http://www.w3.org/2000/svg"
@@ -52,7 +52,7 @@ let {
<span class="font-sans text-sm tracking-wide">{m.doc_loading()}</span>
</div>
{:else if error}
<div class="flex h-full flex-col items-center justify-center px-4 text-center text-gray-400">
<div class="flex h-full flex-col items-center justify-center px-4 text-center text-ink-3">
<p class="mb-2 font-serif">{error}</p>
{#if doc.filePath}
<a
@@ -65,8 +65,8 @@ let {
{/if}
</div>
{:else if !doc.filePath}
<div class="flex h-full flex-col items-center justify-center text-gray-400">
<div class="mb-6 rounded-full bg-white/5 p-8">
<div class="flex h-full flex-col items-center justify-center text-ink-3">
<div class="mb-6 rounded-full bg-surface/5 p-8">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/PDF-Document-MD.svg"
alt=""

View File

@@ -18,14 +18,14 @@ $effect(() => {
<div
bind:this={el}
style={!expanded ? `overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: ${maxLines}` : ''}
class="border-brand-sand bg-brand-sand/30 rounded border p-5 font-serif text-sm leading-relaxed whitespace-pre-wrap text-brand-navy"
class="rounded border border-line bg-muted p-5 font-serif text-sm leading-relaxed whitespace-pre-wrap text-ink"
>
{text}
</div>
{#if isClamped || expanded}
<button
onclick={() => (expanded = !expanded)}
class="mt-2 font-sans text-xs text-gray-400 transition hover:text-brand-navy"
class="mt-2 font-sans text-xs text-ink-3 transition hover:text-ink"
>
{expanded ? m.comp_expandable_show_less() : m.comp_expandable_show_more()}
</button>

View File

@@ -270,11 +270,11 @@ $effect(() => {
<div class="space-y-4 p-6">
{#if historyLoading}
<p class="font-sans text-xs text-gray-400">{m.history_loading()}</p>
<p class="font-sans text-xs text-ink-3">{m.history_loading()}</p>
{:else if !historyLoaded}
<!-- initial state before effect runs — show nothing -->
{:else if versions.length === 0}
<p class="font-serif text-sm text-gray-400 italic">{m.history_empty()}</p>
<p class="font-serif text-sm text-ink-3 italic">{m.history_empty()}</p>
{:else}
<!-- Compare mode toggle -->
<div class="flex justify-end">
@@ -286,8 +286,8 @@ $effect(() => {
selectedVersionId = null;
}}
class="font-sans text-xs font-medium transition {compareMode
? 'text-brand-navy underline'
: 'text-gray-400 hover:text-brand-navy'}"
? 'text-ink underline'
: 'text-ink-3 hover:text-ink'}"
>
{m.history_compare_mode()}
</button>
@@ -296,13 +296,13 @@ $effect(() => {
{#if compareMode}
<div class="space-y-2">
<div>
<label for="compare-a" class="mb-1 block font-sans text-[10px] text-gray-400 uppercase"
<label for="compare-a" class="mb-1 block font-sans text-[10px] text-ink-3 uppercase"
>{m.history_compare_select_a()}</label
>
<select
id="compare-a"
bind:value={compareA}
class="border-brand-sand w-full rounded border bg-white px-2 py-1 font-sans text-xs text-brand-navy focus:ring-1 focus:ring-brand-mint focus:outline-none"
class="w-full rounded border border-line bg-surface px-2 py-1 font-sans text-xs text-ink focus:ring-1 focus:ring-accent focus:outline-none"
>
<option value=""></option>
{#each versions as v, i (v.id)}
@@ -311,13 +311,13 @@ $effect(() => {
</select>
</div>
<div>
<label for="compare-b" class="mb-1 block font-sans text-[10px] text-gray-400 uppercase"
<label for="compare-b" class="mb-1 block font-sans text-[10px] text-ink-3 uppercase"
>{m.history_compare_select_b()}</label
>
<select
id="compare-b"
bind:value={compareB}
class="border-brand-sand w-full rounded border bg-white px-2 py-1 font-sans text-xs text-brand-navy focus:ring-1 focus:ring-brand-mint focus:outline-none"
class="w-full rounded border border-line bg-surface px-2 py-1 font-sans text-xs text-ink focus:ring-1 focus:ring-accent focus:outline-none"
>
<option value=""></option>
{#each versions as v, i (v.id)}
@@ -328,7 +328,7 @@ $effect(() => {
<button
onclick={applyCompare}
disabled={!compareA || !compareB || compareA === compareB}
class="w-full rounded bg-brand-navy px-3 py-1.5 font-sans text-xs font-medium text-white transition hover:bg-brand-navy/80 disabled:cursor-not-allowed disabled:opacity-40"
class="w-full rounded bg-primary px-3 py-1.5 font-sans text-xs font-medium text-white transition hover:bg-primary/80 disabled:cursor-not-allowed disabled:opacity-40"
>
{m.history_compare_apply()}
</button>
@@ -336,23 +336,23 @@ $effect(() => {
<!-- Diff panel for compare mode -->
{#if diffLoading}
<p class="font-sans text-xs text-gray-400">{m.history_loading()}</p>
<p class="font-sans text-xs text-ink-3">{m.history_loading()}</p>
{:else if noDiff}
<div
data-testid="history-diff"
class="border-brand-sand rounded-sm border bg-white p-4 font-serif text-sm text-gray-400 italic"
class="rounded-sm border border-line bg-surface p-4 font-serif text-sm text-ink-3 italic"
>
{m.history_diff_no_changes()}
</div>
{:else if diffEntries.length > 0}
<div
data-testid="history-diff"
class="border-brand-sand space-y-4 rounded-sm border bg-white p-4"
class="space-y-4 rounded-sm border border-line bg-surface p-4"
>
{#each diffEntries as entry (entry.field)}
<div>
<span
class="mb-1.5 block font-sans text-[10px] font-bold tracking-wide text-gray-400 uppercase"
class="mb-1.5 block font-sans text-[10px] font-bold tracking-wide text-ink-3 uppercase"
>{entry.label}</span
>
{#if entry.kind === 'text'}
@@ -371,7 +371,7 @@ $effect(() => {
<div class="flex items-center gap-2 font-serif text-sm">
<span class="text-red-600 line-through">{entry.oldVal || '—'}</span>
<svg
class="h-3 w-3 flex-shrink-0 text-gray-400"
class="h-3 w-3 flex-shrink-0 text-ink-3"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
@@ -412,25 +412,25 @@ $effect(() => {
<button
onclick={() => selectVersion(v.id)}
data-testid="history-version"
class="hover:bg-brand-sand/30 w-full py-2 text-left transition {selectedVersionId ===
class="w-full py-2 text-left transition hover:bg-muted {selectedVersionId ===
v.id
? 'border-l-2 border-brand-mint pl-2'
? 'border-l-2 border-accent pl-2'
: 'pl-0'}"
>
<div class="flex items-baseline justify-between gap-2">
<span class="font-sans text-xs font-medium text-brand-navy">
<span class="font-sans text-xs font-medium text-ink">
Version {i + 1}
</span>
<span class="font-sans text-[10px] text-gray-400">
<span class="font-sans text-[10px] text-ink-3">
{formatDateTime(v.savedAt)}
</span>
</div>
<span class="font-sans text-[11px] text-gray-500">{v.editorName}</span>
<span class="font-sans text-[11px] text-ink-2">{v.editorName}</span>
{#if v.changedFields && v.changedFields.length > 0}
<div class="mt-1 flex flex-wrap gap-1">
{#each v.changedFields as field (field)}
<span
class="bg-brand-sand/50 rounded px-1.5 py-0.5 font-sans text-[10px] tracking-wide text-gray-500 uppercase"
class="rounded bg-muted px-1.5 py-0.5 font-sans text-[10px] tracking-wide text-ink-2 uppercase"
>
{fieldLabels[field] ? fieldLabels[field]() : field}
</span>
@@ -442,23 +442,23 @@ $effect(() => {
<!-- Diff shown inline below the selected version -->
{#if selectedVersionId === v.id}
{#if diffLoading}
<p class="pb-3 pl-2 font-sans text-xs text-gray-400">{m.history_loading()}</p>
<p class="pb-3 pl-2 font-sans text-xs text-ink-3">{m.history_loading()}</p>
{:else if noDiff}
<div
data-testid="history-diff"
class="border-brand-sand mb-2 rounded-sm border bg-white p-4 font-serif text-sm text-gray-400 italic"
class="mb-2 rounded-sm border border-line bg-surface p-4 font-serif text-sm text-ink-3 italic"
>
{m.history_diff_no_changes()}
</div>
{:else if diffEntries.length > 0}
<div
data-testid="history-diff"
class="border-brand-sand mb-2 space-y-4 rounded-sm border bg-white p-4"
class="mb-2 space-y-4 rounded-sm border border-line bg-surface p-4"
>
{#each diffEntries as entry (entry.field)}
<div>
<span
class="mb-1.5 block font-sans text-[10px] font-bold tracking-wide text-gray-400 uppercase"
class="mb-1.5 block font-sans text-[10px] font-bold tracking-wide text-ink-3 uppercase"
>{entry.label}</span
>
{#if entry.kind === 'text'}
@@ -477,7 +477,7 @@ $effect(() => {
<div class="flex items-center gap-2 font-serif text-sm">
<span class="text-red-600 line-through">{entry.oldVal || '—'}</span>
<svg
class="h-3 w-3 flex-shrink-0 text-gray-400"
class="h-3 w-3 flex-shrink-0 text-ink-3"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"

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>

View File

@@ -12,28 +12,24 @@ let { doc }: { doc: Doc } = $props();
<div class="flex justify-center px-6 py-8">
<div class="w-full max-w-prose space-y-8">
{#if !doc.summary && !doc.transcription}
<p class="font-serif text-sm text-gray-400 italic"></p>
<p class="font-serif text-sm text-ink-3 italic"></p>
{/if}
{#if doc.summary}
<div>
<span
class="mb-3 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-3 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.doc_label_summary()}
</span>
<p class="font-serif text-base leading-relaxed text-brand-navy">{doc.summary}</p>
<p class="font-serif text-base leading-relaxed text-ink">{doc.summary}</p>
</div>
{/if}
{#if doc.transcription}
<div>
<span
class="mb-3 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-3 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.form_label_transcription()}
</span>
<p class="font-serif text-base leading-relaxed whitespace-pre-wrap text-brand-navy">
<p class="font-serif text-base leading-relaxed whitespace-pre-wrap text-ink">
{doc.transcription}
</p>
</div>

View File

@@ -295,25 +295,23 @@ function zoomOut() {
</script>
{#if !url}
<div class="flex h-full w-full items-center justify-center bg-[#2A2A2A] text-gray-400">
<div class="flex h-full w-full items-center justify-center bg-pdf-bg text-ink-3">
<p class="font-sans text-sm">Keine Datei vorhanden</p>
</div>
{:else if error}
<div
class="flex h-full w-full flex-col items-center justify-center gap-3 bg-[#2A2A2A] text-gray-300"
>
<div class="flex h-full w-full flex-col items-center justify-center gap-3 bg-pdf-bg text-ink-3">
<p class="font-sans text-sm text-red-400">Fehler beim Laden der PDF</p>
<a
href={url}
target="_blank"
rel="noopener noreferrer"
class="font-sans text-xs text-brand-mint underline hover:opacity-80"
class="font-sans text-xs text-accent underline hover:opacity-80"
>
Direkt öffnen
</a>
</div>
{:else}
<div class="flex h-full w-full flex-col bg-[#2A2A2A]">
<div class="flex h-full w-full flex-col bg-pdf-bg">
{#if outdatedCount > 0}
<div
class="flex shrink-0 items-center gap-2 border-b border-amber-500/30 bg-amber-500/10 px-4 py-2"
@@ -337,7 +335,7 @@ function zoomOut() {
{/if}
<!-- Controls -->
<div
class="flex shrink-0 items-center justify-between gap-2 border-b border-white/10 px-4 py-2"
class="flex shrink-0 items-center justify-between gap-2 border-b border-pdf-ctrl px-4 py-2"
>
<!-- Page navigation -->
<div class="flex items-center gap-2">
@@ -345,7 +343,7 @@ function zoomOut() {
onclick={prevPage}
disabled={currentPage <= 1}
aria-label="Zurück"
class="rounded p-1 text-gray-300 transition hover:bg-white/10 disabled:opacity-40"
class="rounded p-1 text-ink-3 transition hover:bg-surface/10 disabled:opacity-40"
>
<svg
class="h-4 w-4"
@@ -359,7 +357,7 @@ function zoomOut() {
</button>
{#if totalPages > 0}
<span class="font-sans text-xs text-gray-300 tabular-nums">
<span class="font-sans text-xs text-ink-3 tabular-nums">
{currentPage} / {totalPages}
</span>
{/if}
@@ -368,7 +366,7 @@ function zoomOut() {
onclick={nextPage}
disabled={!pdfDoc || currentPage >= totalPages}
aria-label="Weiter"
class="rounded p-1 text-gray-300 transition hover:bg-white/10 disabled:opacity-40"
class="rounded p-1 text-ink-3 transition hover:bg-surface/10 disabled:opacity-40"
>
<svg
class="h-4 w-4"
@@ -387,7 +385,7 @@ function zoomOut() {
<button
onclick={zoomOut}
aria-label="Verkleinern"
class="rounded p-1 text-gray-300 transition hover:bg-white/10"
class="rounded p-1 text-ink-3 transition hover:bg-surface/10"
>
<svg
class="h-4 w-4"
@@ -405,7 +403,7 @@ function zoomOut() {
<button
onclick={zoomIn}
aria-label="Vergrößern"
class="rounded p-1 text-gray-300 transition hover:bg-white/10"
class="rounded p-1 text-ink-3 transition hover:bg-surface/10"
>
<svg
class="h-4 w-4"
@@ -438,8 +436,8 @@ function zoomOut() {
onclick={() => (showAnnotations = !showAnnotations)}
aria-label={showAnnotations ? m.pdf_annotations_hide() : m.pdf_annotations_show()}
class="flex items-center gap-1.5 rounded px-2 py-1 font-sans text-xs transition {showAnnotations
? 'text-gray-300 hover:bg-white/10'
: 'bg-white/10 text-brand-mint'}"
? 'text-ink-3 hover:bg-surface/10'
: 'bg-surface/10 text-accent'}"
>
<svg
class="h-3.5 w-3.5 shrink-0"

View File

@@ -80,18 +80,18 @@ function clickOutside(node: HTMLElement) {
<div class="relative" use:clickOutside>
<div
class="flex min-h-[42px] flex-wrap gap-2 rounded border border-gray-300 bg-white p-2 focus-within:border-brand-navy focus-within:ring-1 focus-within:ring-brand-navy"
class="flex min-h-[42px] flex-wrap gap-2 rounded border border-gray-300 bg-surface p-2 focus-within:border-ink focus-within:ring-1 focus-within:ring-ink"
>
{#each selectedPersons as person (person.id)}
<span
class="bg-brand-sand/40 inline-flex items-center gap-1 rounded px-2 py-1 text-sm font-medium text-brand-navy"
class="inline-flex items-center gap-1 rounded bg-muted px-2 py-1 text-sm font-medium text-ink"
>
{person.firstName}
{person.lastName}
<button
type="button"
onclick={() => removePerson(person.id)}
class="ml-0.5 text-brand-navy/50 hover:text-red-500 focus:outline-none"
class="ml-0.5 text-ink/50 hover:text-red-500 focus:outline-none"
aria-label={m.comp_multiselect_remove()}
>
<svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -121,14 +121,14 @@ function clickOutside(node: HTMLElement) {
{#if showDropdown && (results.length > 0 || loading)}
<div
style={dropdownStyle}
class="ring-opacity-5 z-50 max-h-60 overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black sm:text-sm"
class="ring-opacity-5 z-50 max-h-60 overflow-auto rounded-md bg-surface py-1 text-base shadow-lg ring-1 ring-black sm:text-sm"
>
{#if loading}
<div class="p-2 text-sm text-gray-500">{m.comp_multiselect_loading()}</div>
<div class="p-2 text-sm text-ink-2">{m.comp_multiselect_loading()}</div>
{:else}
{#each results as person (person.id)}
<div
class="hover:bg-brand-sand/30 cursor-pointer py-2 pr-9 pl-3 text-gray-900 select-none"
class="cursor-pointer py-2 pr-9 pl-3 text-gray-900 select-none hover:bg-muted"
onclick={() => selectPerson(person)}
onkeydown={(e) => e.key === 'Enter' && selectPerson(person)}
role="button"

View File

@@ -128,10 +128,10 @@ function clickOutside(node: HTMLElement) {
{#if showDropdown && (results.length > 0 || loading)}
<div
class="ring-opacity-5 absolute top-full left-0 z-50 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black focus:outline-none sm:text-sm"
class="ring-opacity-5 absolute top-full left-0 z-50 mt-1 max-h-60 w-full overflow-auto rounded-md bg-surface py-1 text-base shadow-lg ring-1 ring-black focus:outline-none sm:text-sm"
>
{#if loading}
<div class="p-2 text-sm text-gray-500">{m.comp_typeahead_loading()}</div>
<div class="p-2 text-sm text-ink-2">{m.comp_typeahead_loading()}</div>
{:else}
{#each results as person (person.id)}
<div

View File

@@ -85,19 +85,17 @@ function clickOutside(node: HTMLElement) {
<div class="w-full" use:clickOutside>
<!-- Tag Container -->
<div
class="flex min-h-[42px] flex-wrap gap-2 rounded border border-gray-300 bg-white p-2 focus-within:border-brand-navy focus-within:ring-1 focus-within:ring-brand-navy"
class="flex min-h-[42px] flex-wrap gap-2 rounded border border-gray-300 bg-surface p-2 focus-within:border-ink focus-within:ring-1 focus-within:ring-ink"
>
<!-- Render Selected Tags -->
{#each tags as tag, i (i)}
<span
class="bg-brand-sand/30 flex items-center gap-1 rounded px-2 py-1 text-sm font-medium text-brand-navy"
>
<span class="flex items-center gap-1 rounded bg-muted px-2 py-1 text-sm font-medium text-ink">
{tag}
<button
type="button"
onclick={() => removeTag(i)}
aria-label={m.comp_taginput_remove()}
class="text-brand-navy/50 hover:text-red-500 focus:outline-none"
class="text-ink/50 hover:text-red-500 focus:outline-none"
>
<svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"
><path
@@ -130,15 +128,15 @@ function clickOutside(node: HTMLElement) {
<!-- Typeahead Dropdown -->
{#if showSuggestions && suggestions.length > 0}
<ul
class="absolute top-full left-0 z-50 mt-1 max-h-48 w-full overflow-y-auto rounded border border-gray-200 bg-white shadow-lg"
class="absolute top-full left-0 z-50 mt-1 max-h-48 w-full overflow-y-auto rounded border border-line bg-surface shadow-lg"
>
{#each suggestions as suggestion, i (i)}
<li
role="option"
aria-selected={i === activeIndex}
tabindex="0"
class="hover:bg-brand-sand/20 cursor-pointer px-3 py-2 text-sm {i === activeIndex
? 'bg-brand-sand/20 font-bold text-brand-navy'
class="cursor-pointer px-3 py-2 text-sm hover:bg-muted {i === activeIndex
? 'bg-muted font-bold text-ink'
: 'text-gray-700'}"
onclick={() => addTag(suggestion)}
onkeydown={(e) => e.key === 'Enter' && addTag(suggestion)}
@@ -151,6 +149,6 @@ function clickOutside(node: HTMLElement) {
</div>
</div>
{#if allowCreation}
<p class="mt-1 text-xs text-gray-400">{m.comp_taginput_create_hint()}</p>
<p class="mt-1 text-xs text-ink-3">{m.comp_taginput_create_hint()}</p>
{/if}
</div>

View File

@@ -46,9 +46,9 @@ function clickOutside(node: HTMLElement) {
}
</script>
<div class="min-h-screen bg-white" data-hydrated={hydrated || undefined}>
<div class="min-h-screen bg-canvas" data-hydrated={hydrated || undefined}>
{#if !['/login', '/forgot-password', '/reset-password'].some((p) => page.url.pathname.startsWith(p))}
<header class="sticky top-0 z-50 border-b border-gray-100 bg-white">
<header class="sticky top-0 z-50 border-b border-line-2 bg-surface">
<!-- De Gruyter Brill purple accent strip -->
<div class="h-1 bg-brand-purple"></div>
@@ -58,7 +58,7 @@ function clickOutside(node: HTMLElement) {
<div class="flex">
<div class="mr-10 flex flex-shrink-0 items-center">
<a href="/" class="flex items-center" aria-label="Familienarchiv">
<span class="font-sans text-xl font-bold tracking-widest text-brand-navy uppercase"
<span class="font-sans text-xl font-bold tracking-widest text-ink uppercase"
>Familienarchiv</span
>
</a>
@@ -69,8 +69,8 @@ function clickOutside(node: HTMLElement) {
href="/"
class="inline-flex items-center px-3 py-1.5 font-sans text-xs font-bold tracking-widest uppercase transition-colors
{page.url.pathname === '/' || page.url.pathname.startsWith('/documents')
? 'rounded bg-brand-purple/15 text-brand-navy'
: 'hover:bg-brand-sand/60 rounded text-gray-500 hover:text-brand-navy'}"
? 'rounded bg-nav-active text-ink'
: 'rounded text-ink-2 hover:bg-muted hover:text-ink'}"
>
{m.nav_documents()}
</a>
@@ -79,8 +79,8 @@ function clickOutside(node: HTMLElement) {
href="/persons"
class="inline-flex items-center px-3 py-1.5 font-sans text-xs font-bold tracking-widest uppercase transition-colors
{page.url.pathname.startsWith('/persons')
? 'rounded bg-brand-purple/15 text-brand-navy'
: 'hover:bg-brand-sand/60 rounded text-gray-500 hover:text-brand-navy'}"
? 'rounded bg-nav-active text-ink'
: 'rounded text-ink-2 hover:bg-muted hover:text-ink'}"
>
{m.nav_persons()}
</a>
@@ -89,8 +89,8 @@ function clickOutside(node: HTMLElement) {
href="/conversations"
class="inline-flex items-center px-3 py-1.5 font-sans text-xs font-bold tracking-widest uppercase transition-colors
{page.url.pathname.startsWith('/conversations')
? 'rounded bg-brand-purple/15 text-brand-navy'
: 'hover:bg-brand-sand/60 rounded text-gray-500 hover:text-brand-navy'}"
? 'rounded bg-nav-active text-ink'
: 'rounded text-ink-2 hover:bg-muted hover:text-ink'}"
>
{m.nav_conversations()}
</a>
@@ -99,8 +99,8 @@ function clickOutside(node: HTMLElement) {
href="/admin"
class="inline-flex items-center px-3 py-1.5 font-sans text-xs font-bold tracking-widest uppercase transition-colors
{page.url.pathname.startsWith('/admin')
? 'rounded bg-brand-purple/15 text-brand-navy'
: 'hover:bg-brand-sand/60 rounded text-gray-500 hover:text-brand-navy'}"
? 'rounded bg-nav-active text-ink'
: 'rounded text-ink-2 hover:bg-muted hover:text-ink'}"
>
{m.nav_admin()}
</a>
@@ -111,15 +111,15 @@ function clickOutside(node: HTMLElement) {
<!-- Right Side -->
<div class="flex items-center gap-3">
<!-- Language selector -->
<div class="flex items-center gap-1 border-r border-gray-200 pr-3">
<div class="flex items-center gap-1 border-r border-line pr-3">
{#each locales as locale (locale)}
<button
type="button"
onclick={() => setLocale(localeMap[locale])}
class="px-1.5 py-1 font-sans text-xs tracking-widest transition-colors
{activeLocale === locale
? 'font-bold text-brand-navy'
: 'font-normal text-gray-400 hover:text-brand-navy'}"
? 'font-bold text-ink'
: 'font-normal text-ink-3 hover:text-ink'}"
>
{locale}
</button>
@@ -142,7 +142,7 @@ function clickOutside(node: HTMLElement) {
aria-expanded={userMenuOpen}
aria-haspopup="true"
onclick={() => (userMenuOpen = !userMenuOpen)}
class="flex h-8 w-8 items-center justify-center rounded-full bg-brand-navy font-sans text-xs font-bold text-white transition-opacity hover:opacity-80"
class="flex h-8 w-8 items-center justify-center rounded-full bg-primary font-sans text-xs font-bold text-white transition-opacity hover:opacity-80"
>
{userInitials}
</button>
@@ -153,7 +153,7 @@ function clickOutside(node: HTMLElement) {
aria-expanded={userMenuOpen}
aria-haspopup="true"
onclick={() => (userMenuOpen = !userMenuOpen)}
class="inline-flex items-center gap-1.5 px-3 py-2 font-sans text-xs font-bold tracking-widest text-gray-400 uppercase transition-colors hover:text-brand-navy"
class="inline-flex items-center gap-1.5 px-3 py-2 font-sans text-xs font-bold tracking-widest text-ink-3 uppercase transition-colors hover:text-ink"
>
<img
src="/degruyter-icons/Simple/Small-16px/SVG/Action/Account-SM.svg"
@@ -166,20 +166,20 @@ function clickOutside(node: HTMLElement) {
{#if userMenuOpen}
<div
class="border-brand-sand absolute top-full right-0 z-50 mt-1 min-w-[10rem] rounded-sm border bg-white shadow-md"
class="absolute top-full right-0 z-50 mt-1 min-w-[10rem] rounded-sm border border-line bg-overlay shadow-md"
>
<a
href="/profile"
onclick={() => (userMenuOpen = false)}
class="hover:bg-brand-sand/40 block px-4 py-2.5 font-sans text-xs font-bold tracking-widest text-gray-600 uppercase transition-colors hover:text-brand-navy"
class="block px-4 py-2.5 font-sans text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:bg-muted hover:text-ink"
>
{m.nav_profile()}
</a>
<div class="border-brand-sand border-t">
<div class="border-t border-line">
<form action="/logout" method="POST" use:enhance>
<button
type="submit"
class="hover:bg-brand-sand/40 w-full px-4 py-2.5 text-left font-sans text-xs font-bold tracking-widest text-gray-400 uppercase transition-colors hover:text-brand-navy"
class="w-full px-4 py-2.5 text-left font-sans text-xs font-bold tracking-widest text-ink-3 uppercase transition-colors hover:bg-muted hover:text-ink"
>
{m.nav_logout()}
</button>

View File

@@ -78,7 +78,7 @@ $effect(() => {
<!-- Outer Container: Matches the 'Sand' background of the layout -->
<main class="mx-auto max-w-7xl py-8 font-sans sm:px-6 lg:px-8">
<!-- SEARCH & FILTER CARD -->
<div class="border-brand-sand mb-8 rounded-sm border bg-white p-6 shadow-sm">
<div class="mb-8 rounded-sm border border-line bg-surface p-6 shadow-sm">
<!-- ROW 1: Main Search (One Line) -->
<div class="flex items-center gap-4">
<!-- Full Text Search -->
@@ -90,7 +90,7 @@ $effect(() => {
onfocus={() => (qFocused = true)}
onblur={() => (qFocused = false)}
placeholder={m.docs_search_placeholder()}
class="block w-full border-gray-300 py-2.5 pr-10 pl-3 placeholder-gray-400 shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full border-gray-300 py-2.5 pr-10 pl-3 placeholder-gray-400 shadow-sm focus:border-ink focus:ring-ink"
/>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
<img
@@ -105,7 +105,7 @@ $effect(() => {
<!-- Toggle Advanced Button -->
<button
onclick={() => (showAdvanced = !showAdvanced)}
class="flex items-center gap-2 border border-gray-300 bg-gray-50 px-4 py-2.5 text-sm font-bold tracking-wide text-gray-600 uppercase transition hover:bg-gray-100 hover:text-brand-navy"
class="flex items-center gap-2 border border-gray-300 bg-gray-50 px-4 py-2.5 text-sm font-bold tracking-wide text-ink-2 uppercase transition hover:bg-gray-100 hover:text-ink"
>
<img
src="/degruyter-icons/Simple/Small-16px/SVG/Action/Chevron/Chevron-Down-SM.svg"
@@ -119,7 +119,7 @@ $effect(() => {
<!-- Reset Button -->
<a
href="/"
class="flex items-center justify-center border border-transparent px-3 py-2.5 text-gray-400 transition hover:text-red-500"
class="flex items-center justify-center border border-transparent px-3 py-2.5 text-ink-3 transition hover:text-red-500"
title={m.docs_btn_reset_title()}
>
<img
@@ -135,11 +135,11 @@ $effect(() => {
{#if showAdvanced}
<div
transition:slide
class="mt-6 grid grid-cols-1 gap-6 border-t border-gray-100 pt-6 md:grid-cols-12"
class="mt-6 grid grid-cols-1 gap-6 border-t border-line-2 pt-6 md:grid-cols-12"
>
<!-- Tag Filter -->
<div class="md:col-span-12">
<p class="mb-2 block text-xs font-bold tracking-widest text-gray-500 uppercase">
<p class="mb-2 block text-xs font-bold tracking-widest text-ink-2 uppercase">
{m.docs_filter_label_tags()}
</p>
<TagInput bind:tags={tagNames} allowCreation={false} />
@@ -148,7 +148,7 @@ $effect(() => {
<!-- Sender -->
<div class="md:col-span-3">
<div
class="[&_input]:border-gray-300 [&_input]:py-2.5 [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-gray-500 [&_label]:uppercase"
class="[&_input]:border-gray-300 [&_input]:py-2.5 [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-ink-2 [&_label]:uppercase"
>
<PersonTypeahead
name="senderId"
@@ -163,7 +163,7 @@ $effect(() => {
<!-- Receiver -->
<div class="md:col-span-3">
<div
class="[&_input]:border-gray-300 [&_input]:py-2.5 [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-gray-500 [&_label]:uppercase"
class="[&_input]:border-gray-300 [&_input]:py-2.5 [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-ink-2 [&_label]:uppercase"
>
<PersonTypeahead
name="receiverId"
@@ -180,7 +180,7 @@ $effect(() => {
<div>
<label
for="from"
class="mb-2 block text-xs font-bold tracking-widest text-gray-500 uppercase"
class="mb-2 block text-xs font-bold tracking-widest text-ink-2 uppercase"
>{m.docs_filter_label_from()}</label
>
<input
@@ -194,7 +194,7 @@ $effect(() => {
<div>
<label
for="to"
class="mb-2 block text-xs font-bold tracking-widest text-gray-500 uppercase"
class="mb-2 block text-xs font-bold tracking-widest text-ink-2 uppercase"
>{m.docs_filter_label_to()}</label
>
<input
@@ -215,7 +215,7 @@ $effect(() => {
{#if data.canWrite}
<a
href="/documents/new"
class="inline-flex items-center gap-1 text-sm font-medium text-brand-navy/60 transition-colors hover:text-brand-navy"
class="inline-flex items-center gap-1 text-sm font-medium text-ink/60 transition-colors hover:text-ink"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Add/Add-General-MD.svg"
@@ -229,15 +229,15 @@ $effect(() => {
</div>
<!-- DOCUMENT LIST -->
<div class="border-brand-sand border bg-white shadow-sm">
<div class="border border-line bg-surface shadow-sm">
{#if data.error}
<div class="bg-red-50 p-8 text-center text-red-600">
{data.error}
</div>
{:else if data.documents && data.documents.length > 0}
<ul class="divide-y divide-gray-100">
<ul class="divide-y divide-line-2">
{#each data.documents as doc (doc.id)}
<li class="group hover:bg-brand-sand/10 transition-colors duration-200">
<li class="group transition-colors duration-200 hover:bg-muted/50">
<!-- LINK TO DETAIL PAGE -->
<a href="/documents/{doc.id}" class="block p-6">
<div class="flex flex-col gap-6 sm:flex-row">
@@ -246,14 +246,14 @@ $effect(() => {
<div class="mb-2 flex items-baseline justify-between">
<!-- Title: Serif & Brand Navy -->
<h3
class="font-serif text-xl font-medium text-brand-navy decoration-brand-mint decoration-2 underline-offset-4 group-hover:underline"
class="font-serif text-xl font-medium text-ink decoration-brand-mint decoration-2 underline-offset-4 group-hover:underline"
>
{doc.title || doc.originalFilename}
</h3>
</div>
<!-- Metadata Row -->
<div class="mb-4 flex flex-wrap gap-6 font-sans text-sm text-gray-500">
<div class="mb-4 flex flex-wrap gap-6 font-sans text-sm text-ink-2">
<div class="flex items-center">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Calendar/Calendar-Add-MD.svg"
@@ -280,7 +280,7 @@ $effect(() => {
<div class="grid grid-cols-1 gap-4 font-serif text-sm sm:grid-cols-2">
<div class="flex items-baseline">
<span
class="w-10 font-sans text-xs font-bold tracking-wide text-gray-400 uppercase"
class="w-10 font-sans text-xs font-bold tracking-wide text-ink-3 uppercase"
>{m.docs_list_from()}</span
>
{#if doc.sender}
@@ -288,12 +288,12 @@ $effect(() => {
>{doc.sender.firstName} {doc.sender.lastName}</span
>
{:else}
<span class="text-gray-400 italic">{m.docs_list_unknown()}</span>
<span class="text-ink-3 italic">{m.docs_list_unknown()}</span>
{/if}
</div>
<div class="flex items-baseline">
<span
class="w-10 font-sans text-xs font-bold tracking-wide text-gray-400 uppercase"
class="w-10 font-sans text-xs font-bold tracking-wide text-ink-3 uppercase"
>{m.docs_list_to()}</span
>
{#if doc.receivers && doc.receivers.length > 0}
@@ -301,7 +301,7 @@ $effect(() => {
{doc.receivers.map((p) => p.firstName + ' ' + p.lastName).join(', ')}
</span>
{:else}
<span class="text-gray-400 italic">{m.docs_list_unknown()}</span>
<span class="text-ink-3 italic">{m.docs_list_unknown()}</span>
{/if}
</div>
</div>
@@ -312,7 +312,7 @@ $effect(() => {
{#each doc.tags as tag (tag.id)}
<button
type="button"
class="bg-brand-sand/30 relative z-10 inline-flex cursor-pointer items-center rounded px-2 py-1 text-[10px] font-bold tracking-widest text-brand-navy uppercase transition-colors hover:bg-brand-navy hover:text-white"
class="relative z-10 inline-flex cursor-pointer items-center rounded bg-muted px-2 py-1 text-[10px] font-bold tracking-widest text-ink uppercase transition-colors hover:bg-primary hover:text-white"
onclick={(e) => { e.preventDefault(); e.stopPropagation(); goto(`/?tag=${encodeURIComponent(tag.name)}`); }}
>
{tag.name}
@@ -324,7 +324,7 @@ $effect(() => {
<!-- Arrow Icon -->
<div
class="hidden items-center text-gray-300 transition-colors group-hover:text-brand-mint sm:flex"
class="hidden items-center text-ink-3 transition-colors group-hover:text-accent sm:flex"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Arrow/Arrow-Right-MD.svg"
@@ -341,9 +341,7 @@ $effect(() => {
{:else}
<!-- Empty State -->
<div class="p-16 text-center">
<div
class="bg-brand-sand/30 mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full"
>
<div class="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Mag-Glass-MD.svg"
alt=""
@@ -351,13 +349,13 @@ $effect(() => {
class="h-6 w-6"
/>
</div>
<h3 class="font-serif text-lg font-medium text-brand-navy">{m.docs_empty_heading()}</h3>
<p class="mt-1 font-sans text-sm text-gray-500">
<h3 class="font-serif text-lg font-medium text-ink">{m.docs_empty_heading()}</h3>
<p class="mt-1 font-sans text-sm text-ink-2">
{m.docs_empty_text()}
</p>
<button
onclick={() => goto('/')}
class="mt-6 text-sm font-bold tracking-wide text-brand-mint uppercase transition hover:text-brand-navy"
class="mt-6 text-sm font-bold tracking-wide text-accent uppercase transition hover:text-ink"
>
{m.docs_empty_btn_clear()}
</button>

View File

@@ -65,54 +65,54 @@ async function backfillFileHashes() {
<div class="mx-auto max-w-7xl py-8 font-sans sm:px-6 lg:px-8">
<div class="mb-8 flex items-center justify-between">
<h1 class="font-serif text-3xl text-brand-navy">{m.admin_heading()}</h1>
<h1 class="font-serif text-3xl text-ink">{m.admin_heading()}</h1>
<!-- Tabs -->
<div class="flex rounded-lg border border-gray-200 bg-white p-1 shadow-sm">
<div class="flex rounded-lg border border-line bg-surface p-1 shadow-sm">
<button
class="rounded-md px-4 py-2 text-sm font-bold tracking-wide uppercase transition {activeTab ===
'users'
? 'bg-brand-navy text-white'
: 'text-gray-500 hover:text-brand-navy'}"
? 'bg-primary text-white'
: 'text-ink-2 hover:text-ink'}"
onclick={() => (activeTab = 'users')}>{m.admin_tab_users()}</button
>
<button
class="rounded-md px-4 py-2 text-sm font-bold tracking-wide uppercase transition {activeTab ===
'groups'
? 'bg-brand-navy text-white'
: 'text-gray-500 hover:text-brand-navy'}"
? 'bg-primary text-white'
: 'text-ink-2 hover:text-ink'}"
onclick={() => (activeTab = 'groups')}>{m.admin_tab_groups()}</button
>
<button
class="rounded-md px-4 py-2 text-sm font-bold tracking-wide uppercase transition {activeTab ===
'tags'
? 'bg-brand-navy text-white'
: 'text-gray-500 hover:text-brand-navy'}"
? 'bg-primary text-white'
: 'text-ink-2 hover:text-ink'}"
onclick={() => (activeTab = 'tags')}>{m.admin_tab_tags()}</button
>
<button
class="rounded-md px-4 py-2 text-sm font-bold tracking-wide uppercase transition {activeTab ===
'system'
? 'bg-brand-navy text-white'
: 'text-gray-500 hover:text-brand-navy'}"
? 'bg-primary text-white'
: 'text-ink-2 hover:text-ink'}"
onclick={() => (activeTab = 'system')}>{m.admin_tab_system()}</button
>
</div>
</div>
{#if form?.message}
<div class="mb-6 rounded border border-brand-mint/50 bg-brand-mint/20 p-4 text-brand-navy">
<div class="mb-6 rounded border border-accent/50 bg-accent/20 p-4 text-ink">
{form.message}
</div>
{/if}
{#if activeTab === 'users'}
<div class="border-brand-sand overflow-hidden rounded-lg border bg-white shadow-sm" in:slide>
<div class="flex items-center justify-between border-b border-gray-100 p-6">
<div class="overflow-hidden rounded-lg border border-line bg-surface shadow-sm" in:slide>
<div class="flex items-center justify-between border-b border-line-2 p-6">
<h2 class="text-lg font-bold text-gray-700">{m.admin_section_users()}</h2>
<a
href="/admin/users/new"
class="inline-flex items-center gap-1 rounded-sm bg-brand-navy px-4 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
class="inline-flex items-center gap-1 rounded-sm bg-primary px-4 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
>
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
@@ -129,35 +129,34 @@ async function backfillFileHashes() {
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-gray-500 uppercase"
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-ink-2 uppercase"
>{m.admin_col_login()}</th
>
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-gray-500 uppercase"
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-ink-2 uppercase"
>{m.admin_col_full_name()}</th
>
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-gray-500 uppercase"
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-ink-2 uppercase"
>{m.admin_col_groups()}</th
>
<th
class="px-6 py-3 text-right text-xs font-bold tracking-wider text-gray-500 uppercase"
<th class="px-6 py-3 text-right text-xs font-bold tracking-wider text-ink-2 uppercase"
>{m.admin_col_actions()}</th
>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 bg-surface">
{#each data.users as user (user.id)}
<tr class="group/row hover:bg-gray-50">
<td class="px-6 py-4 text-sm font-medium whitespace-nowrap text-gray-900">
{user.username}
</td>
<td class="px-6 py-4 text-sm whitespace-nowrap text-gray-500">
<td class="px-6 py-4 text-sm whitespace-nowrap text-ink-2">
{#if user.firstName || user.lastName}
{user.firstName ?? ''} {user.lastName ?? ''}
{:else}
<span class="text-gray-300 italic"></span>
<span class="text-ink-3 italic"></span>
{/if}
</td>
<td class="px-6 py-4 text-sm text-gray-500">
<td class="px-6 py-4 text-sm text-ink-2">
<div class="flex flex-wrap gap-1">
{#if user.groups && user.groups.length > 0}
{#each user.groups as group (group.id)}
@@ -168,7 +167,7 @@ async function backfillFileHashes() {
</span>
{/each}
{:else}
<span class="text-xs text-gray-400 italic">{m.admin_no_groups()}</span>
<span class="text-xs text-ink-3 italic">{m.admin_no_groups()}</span>
{/if}
</div>
</td>
@@ -176,7 +175,7 @@ async function backfillFileHashes() {
<div class="flex items-center justify-end gap-4">
<a
href="/admin/users/{user.id}"
class="text-sm font-bold tracking-wide text-brand-mint uppercase hover:text-brand-navy"
class="text-sm font-bold tracking-wide text-accent uppercase hover:text-ink"
>
{m.btn_edit()}
</a>
@@ -196,7 +195,7 @@ async function backfillFileHashes() {
>
<input type="hidden" name="id" value={user.id} />
<button
class="p-1 text-gray-300 transition-colors hover:text-red-600"
class="p-1 text-ink-3 transition-colors hover:text-red-600"
title={m.admin_btn_delete_user_title()}
>
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -217,8 +216,8 @@ async function backfillFileHashes() {
</table>
</div>
{:else if activeTab === 'tags'}
<div class="border-brand-sand overflow-hidden rounded-lg border bg-white shadow-sm" in:slide>
<div class="border-b border-gray-100 bg-yellow-50/50 p-6">
<div class="overflow-hidden rounded-lg border border-line bg-surface shadow-sm" in:slide>
<div class="border-b border-line-2 bg-yellow-50/50 p-6">
<h2 class="text-lg font-bold text-gray-700">{m.admin_section_tags()}</h2>
<p class="mt-1 text-xs text-yellow-800">
{m.admin_tags_warning()}
@@ -244,7 +243,7 @@ async function backfillFileHashes() {
type="text"
name="name"
bind:value={editingTagName}
class="flex-1 rounded border-brand-mint px-2 py-1 text-sm ring-1 ring-brand-mint"
class="flex-1 rounded border-accent px-2 py-1 text-sm ring-1 ring-brand-mint"
/>
<button aria-label={m.btn_save()} class="text-green-600 hover:text-green-800"
><svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
@@ -260,7 +259,7 @@ async function backfillFileHashes() {
type="button"
onclick={cancelEditTag}
aria-label={m.btn_cancel()}
class="text-gray-400 hover:text-gray-600"
class="text-ink-3 hover:text-ink-2"
><svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
><path
stroke-linecap="round"
@@ -272,7 +271,7 @@ async function backfillFileHashes() {
>
</form>
{:else}
<span class="bg-brand-sand/30 rounded px-2 py-1 text-sm font-medium text-brand-navy">
<span class="rounded bg-muted px-2 py-1 text-sm font-medium text-ink">
{tag.name}
</span>
<div
@@ -281,7 +280,7 @@ async function backfillFileHashes() {
<button
onclick={() => startEditTag(tag)}
aria-label={m.admin_btn_edit_tag_label()}
class="p-1 text-gray-400 hover:text-brand-navy"
class="p-1 text-ink-3 hover:text-ink"
>
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"
><path
@@ -310,7 +309,7 @@ async function backfillFileHashes() {
<input type="hidden" name="id" value={tag.id} />
<button
aria-label={m.admin_btn_delete_tag_label()}
class="p-1 text-gray-400 hover:text-red-600"
class="p-1 text-ink-3 hover:text-red-600"
>
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"
><path
@@ -329,27 +328,26 @@ async function backfillFileHashes() {
</ul>
</div>
{:else if activeTab === 'groups'}
<div class="border-brand-sand overflow-hidden rounded-lg border bg-white shadow-sm" in:slide>
<div class="flex items-center justify-between border-b border-gray-100 p-6">
<div class="overflow-hidden rounded-lg border border-line bg-surface shadow-sm" in:slide>
<div class="flex items-center justify-between border-b border-line-2 p-6">
<h2 class="text-lg font-bold text-gray-700">{m.admin_section_groups()}</h2>
</div>
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-gray-500 uppercase"
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-ink-2 uppercase"
>{m.admin_col_name()}</th
>
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-gray-500 uppercase"
<th class="px-6 py-3 text-left text-xs font-bold tracking-wider text-ink-2 uppercase"
>{m.admin_col_permissions()}</th
>
<th
class="px-6 py-3 text-right text-xs font-bold tracking-wider text-gray-500 uppercase"
<th class="px-6 py-3 text-right text-xs font-bold tracking-wider text-ink-2 uppercase"
>{m.admin_col_actions()}</th
>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<tbody class="divide-y divide-gray-200 bg-surface">
{#each data.groups as group (group.id)}
<tr class="group/row hover:bg-gray-50">
{#if editingGroupId === group.id}
@@ -372,7 +370,7 @@ async function backfillFileHashes() {
type="text"
name="name"
value={group.name}
class="w-full rounded border-brand-mint text-sm"
class="w-full rounded border-accent text-sm"
required
/>
</div>
@@ -380,14 +378,14 @@ async function backfillFileHashes() {
<div class="flex h-full flex-1 flex-wrap items-center gap-4 pt-2">
{#each availablePermissions as perm (perm)}
<label
class="inline-flex items-center text-xs font-bold text-gray-600 uppercase"
class="inline-flex items-center text-xs font-bold text-ink-2 uppercase"
>
<input
type="checkbox"
name="permissions"
value={perm}
checked={group.permissions.includes(perm)}
class="mr-2 rounded border-gray-300 text-brand-navy focus:ring-brand-mint"
class="mr-2 rounded border-gray-300 text-ink focus:ring-accent"
/>
{perm.replace('_', ' ')}
</label>
@@ -413,7 +411,7 @@ async function backfillFileHashes() {
type="button"
onclick={cancelEditGroup}
aria-label={m.btn_cancel()}
class="p-1 text-gray-400 hover:text-red-500"
class="p-1 text-ink-3 hover:text-red-500"
>
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"
><path
@@ -429,17 +427,17 @@ async function backfillFileHashes() {
</td>
{:else}
<!-- VIEW MODE -->
<td class="px-6 py-4 text-sm font-bold whitespace-nowrap text-brand-navy">
<td class="px-6 py-4 text-sm font-bold whitespace-nowrap text-ink">
{group.name}
</td>
<td class="px-6 py-4 text-sm text-gray-500">
<td class="px-6 py-4 text-sm text-ink-2">
<div class="flex flex-wrap gap-1">
{#each group.permissions as perm (perm)}
<span
class="rounded-full px-2 py-0.5 text-[10px] font-bold uppercase
{perm === 'ADMIN'
? 'border-red-100 bg-red-50 text-red-700'
: 'border-gray-200 bg-gray-100 text-gray-600'}"
: 'border-line bg-gray-100 text-ink-2'}"
>
{perm}
</span>
@@ -450,7 +448,7 @@ async function backfillFileHashes() {
<div class="flex items-center justify-end gap-3">
<button
onclick={() => startEditGroup(group.id)}
class="text-sm font-bold tracking-wide text-brand-mint uppercase hover:text-brand-navy"
class="text-sm font-bold tracking-wide text-accent uppercase hover:text-ink"
>
{m.btn_edit()}
</button>
@@ -469,7 +467,7 @@ async function backfillFileHashes() {
>
<input type="hidden" name="id" value={group.id} />
<button
class="p-1 text-gray-300 transition-colors hover:text-red-600"
class="p-1 text-ink-3 transition-colors hover:text-red-600"
title={m.btn_delete()}
>
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -491,8 +489,8 @@ async function backfillFileHashes() {
</table>
<!-- CREATE GROUP FORM -->
<div class="border-t border-gray-200 bg-gray-50 p-6">
<h3 class="mb-4 text-xs font-bold tracking-wide text-gray-500 uppercase">
<div class="border-t border-line bg-gray-50 p-6">
<h3 class="mb-4 text-xs font-bold tracking-wide text-ink-2 uppercase">
{m.admin_section_new_group()}
</h3>
<form
@@ -513,12 +511,12 @@ async function backfillFileHashes() {
<div class="flex items-center gap-4">
{#each availablePermissions as perm (perm)}
<label class="inline-flex items-center text-xs font-bold text-gray-600 uppercase">
<label class="inline-flex items-center text-xs font-bold text-ink-2 uppercase">
<input
type="checkbox"
name="permissions"
value={perm}
class="mr-2 rounded border-gray-300 text-brand-navy focus:ring-brand-mint"
class="mr-2 rounded border-gray-300 text-ink focus:ring-accent"
/>
{perm.replace('_', ' ')}
</label>
@@ -527,7 +525,7 @@ async function backfillFileHashes() {
<button
type="submit"
class="w-full rounded bg-brand-navy px-6 py-2 text-sm font-bold text-white uppercase hover:bg-brand-mint hover:text-brand-navy md:w-auto"
class="w-full rounded bg-primary px-6 py-2 text-sm font-bold text-white uppercase hover:bg-accent hover:text-ink md:w-auto"
>
{m.btn_create()}
</button>
@@ -535,37 +533,37 @@ async function backfillFileHashes() {
</div>
</div>
{:else if activeTab === 'system'}
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-1 text-lg font-bold text-gray-700">{m.admin_system_backfill_heading()}</h2>
<p class="mb-4 text-sm text-gray-500">{m.admin_system_backfill_description()}</p>
<p class="mb-4 text-sm text-ink-2">{m.admin_system_backfill_description()}</p>
<button
onclick={backfillVersions}
disabled={backfillLoading}
class="rounded bg-brand-navy px-6 py-2 text-sm font-bold text-white uppercase transition hover:bg-brand-mint hover:text-brand-navy disabled:cursor-not-allowed disabled:opacity-50"
class="rounded bg-primary px-6 py-2 text-sm font-bold text-white uppercase transition hover:bg-accent hover:text-ink disabled:cursor-not-allowed disabled:opacity-50"
>
{backfillLoading ? '…' : m.admin_system_backfill_btn()}
</button>
{#if backfillResult !== null}
<p class="mt-4 text-sm font-medium text-brand-navy">
<p class="mt-4 text-sm font-medium text-ink">
{m.admin_system_backfill_success({ count: backfillResult })}
</p>
{/if}
</div>
<div class="border-brand-sand mt-4 rounded-sm border bg-white p-6 shadow-sm">
<div class="mt-4 rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-1 text-lg font-bold text-gray-700">
{m.admin_system_backfill_hashes_heading()}
</h2>
<p class="mb-4 text-sm text-gray-500">{m.admin_system_backfill_hashes_description()}</p>
<p class="mb-4 text-sm text-ink-2">{m.admin_system_backfill_hashes_description()}</p>
<button
onclick={backfillFileHashes}
disabled={backfillHashesLoading}
class="rounded bg-brand-navy px-6 py-2 text-sm font-bold text-white uppercase transition hover:bg-brand-mint hover:text-brand-navy disabled:cursor-not-allowed disabled:opacity-50"
class="rounded bg-primary px-6 py-2 text-sm font-bold text-white uppercase transition hover:bg-accent hover:text-ink disabled:cursor-not-allowed disabled:opacity-50"
>
{backfillHashesLoading ? '…' : m.admin_system_backfill_hashes_btn()}
</button>
{#if backfillHashesResult !== null}
<p class="mt-4 text-sm font-medium text-brand-navy">
<p class="mt-4 text-sm font-medium text-ink">
{m.admin_system_backfill_hashes_success({ count: backfillHashesResult })}
</p>
{/if}

View File

@@ -41,7 +41,7 @@ function handleBirthDateInput(e: Event) {
<div class="mx-auto max-w-3xl px-4 py-8 sm:px-6 lg:px-8">
<a
href="/admin"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-gray-500 uppercase transition-colors hover:text-brand-navy"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:text-ink"
>
<svg
class="mr-2 h-4 w-4 transform transition-transform group-hover:-translate-x-1"
@@ -55,7 +55,7 @@ function handleBirthDateInput(e: Event) {
{m.btn_back_to_overview()}
</a>
<h1 class="mb-6 font-serif text-3xl font-bold text-brand-navy">
<h1 class="mb-6 font-serif text-3xl font-bold text-ink">
{m.admin_user_edit_heading({ username: data.editUser.username })}
</h1>
@@ -72,8 +72,8 @@ function handleBirthDateInput(e: Event) {
<form method="POST" use:enhance class="space-y-6">
<!-- Profile card -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_section_personal()}
</h2>
@@ -81,7 +81,7 @@ function handleBirthDateInput(e: Event) {
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_first_name()}
</span>
@@ -89,13 +89,13 @@ function handleBirthDateInput(e: Event) {
type="text"
name="firstName"
value={data.editUser.firstName ?? ''}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_last_name()}
</span>
@@ -103,15 +103,13 @@ function handleBirthDateInput(e: Event) {
type="text"
name="lastName"
value={data.editUser.lastName ?? ''}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
</div>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_birth_date()}
</span>
<input
@@ -119,36 +117,32 @@ function handleBirthDateInput(e: Event) {
placeholder="TT.MM.JJJJ"
value={birthDateDisplay}
oninput={handleBirthDateInput}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
<input type="hidden" name="birthDate" value={birthDateIso} />
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_email()}
</span>
<input
type="email"
name="email"
value={data.editUser.email ?? ''}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_contact()}
</span>
<textarea
name="contact"
rows="3"
placeholder={m.profile_contact_placeholder()}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
>{data.editUser.contact ?? ''}</textarea
>
</label>
@@ -156,8 +150,8 @@ function handleBirthDateInput(e: Event) {
</div>
<!-- Groups card -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.admin_col_groups()}
</h2>
@@ -169,7 +163,7 @@ function handleBirthDateInput(e: Event) {
name="groupIds"
value={group.id}
checked={data.editUser.groups?.some((g: { id: string }) => g.id === group.id)}
class="rounded border-gray-300 text-brand-navy focus:ring-brand-mint"
class="rounded border-gray-300 text-ink focus:ring-accent"
/>
{group.name}
</label>
@@ -178,35 +172,31 @@ function handleBirthDateInput(e: Event) {
</div>
<!-- Password card -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.admin_label_new_password_optional()}
</h2>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_new_password()}
</span>
<input
type="password"
name="newPassword"
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_new_password_confirm()}
</span>
<input
type="password"
name="confirmPassword"
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
</div>
@@ -214,17 +204,17 @@ function handleBirthDateInput(e: Event) {
<!-- Save bar -->
<div
class="border-brand-sand sticky bottom-0 z-10 -mx-4 flex items-center justify-between border-t bg-white px-6 py-4 shadow-[0_-2px_8px_rgba(0,0,0,0.06)]"
class="sticky bottom-0 z-10 -mx-4 flex items-center justify-between border-t border-line bg-surface px-6 py-4 shadow-[0_-2px_8px_rgba(0,0,0,0.06)]"
>
<a
href="/admin"
class="font-sans text-xs font-bold tracking-widest text-gray-500 uppercase hover:text-brand-navy"
class="font-sans text-xs font-bold tracking-widest text-ink-2 uppercase hover:text-ink"
>
{m.btn_cancel()}
</a>
<button
type="submit"
class="rounded-sm bg-brand-navy px-5 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
class="rounded-sm bg-primary px-5 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
>
{m.btn_save()}
</button>

View File

@@ -31,7 +31,7 @@ function handleBirthDateInput(e: Event) {
<div class="mx-auto max-w-3xl px-4 py-8 sm:px-6 lg:px-8">
<a
href="/admin"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-gray-500 uppercase transition-colors hover:text-brand-navy"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:text-ink"
>
<svg
class="mr-2 h-4 w-4 transform transition-transform group-hover:-translate-x-1"
@@ -45,7 +45,7 @@ function handleBirthDateInput(e: Event) {
{m.btn_back_to_overview()}
</a>
<h1 class="mb-6 font-serif text-3xl font-bold text-brand-navy">{m.admin_user_new_heading()}</h1>
<h1 class="mb-6 font-serif text-3xl font-bold text-ink">{m.admin_user_new_heading()}</h1>
{#if form?.error}
<div class="mb-5 rounded border border-red-200 bg-red-50 p-3 text-sm text-red-700">
@@ -53,118 +53,104 @@ function handleBirthDateInput(e: Event) {
</div>
{/if}
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<form method="POST" use:enhance class="space-y-5">
<!-- Account -->
<h2 class="text-xs font-bold tracking-widest text-gray-400 uppercase">
<h2 class="text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.admin_section_users()}
</h2>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.admin_col_login()}
</span>
<input
type="text"
name="username"
required
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.admin_label_initial_password()}
</span>
<input
type="password"
name="password"
required
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<!-- Profile -->
<h2 class="pt-2 text-xs font-bold tracking-widest text-gray-400 uppercase">
<h2 class="pt-2 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_section_personal()}
</h2>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_first_name()}
</span>
<input
type="text"
name="firstName"
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_last_name()}
</span>
<input
type="text"
name="lastName"
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
</div>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_birth_date()}
</span>
<input
type="text"
placeholder="TT.MM.JJJJ"
oninput={handleBirthDateInput}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
<input type="hidden" name="birthDate" value={birthDateIso} />
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_email()}
</span>
<input
type="email"
name="email"
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
>
<span class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_label_contact()}
</span>
<textarea
name="contact"
rows="3"
placeholder={m.profile_contact_placeholder()}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
></textarea>
</label>
<!-- Groups -->
<h2 class="pt-2 text-xs font-bold tracking-widest text-gray-400 uppercase">
<h2 class="pt-2 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.admin_col_groups()}
</h2>
@@ -175,7 +161,7 @@ function handleBirthDateInput(e: Event) {
type="checkbox"
name="groupIds"
value={group.id}
class="rounded border-gray-300 text-brand-navy focus:ring-brand-mint"
class="rounded border-gray-300 text-ink focus:ring-accent"
/>
{group.name}
</label>
@@ -184,17 +170,17 @@ function handleBirthDateInput(e: Event) {
<!-- Save bar -->
<div
class="border-brand-sand mt-4 flex items-center justify-between rounded-sm border bg-white px-6 py-4 shadow-sm"
class="mt-4 flex items-center justify-between rounded-sm border border-line bg-surface px-6 py-4 shadow-sm"
>
<a
href="/admin"
class="font-sans text-xs font-bold tracking-widest text-gray-500 uppercase hover:text-brand-navy"
class="font-sans text-xs font-bold tracking-widest text-ink-2 uppercase hover:text-ink"
>
{m.btn_cancel()}
</a>
<button
type="submit"
class="rounded-sm bg-brand-navy px-5 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
class="rounded-sm bg-primary px-5 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
>
{m.btn_create()}
</button>

View File

@@ -67,19 +67,19 @@ const enrichedDocuments = $derived(
<div class="mx-auto max-w-5xl px-4 py-10">
<!-- Page Header -->
<div class="mb-8 border-b border-brand-navy/10 pb-4">
<h1 class="font-serif text-3xl font-medium text-brand-navy">{m.conv_heading()}</h1>
<p class="mt-2 font-sans text-sm text-brand-navy/60">
<div class="mb-8 border-b border-ink/10 pb-4">
<h1 class="font-serif text-3xl font-medium text-ink">{m.conv_heading()}</h1>
<p class="mt-2 font-sans text-sm text-ink/60">
{m.conv_subtitle()}
</p>
</div>
<!-- FILTER BAR -->
<div class="border-brand-sand relative z-20 mb-10 border bg-white p-8 shadow-sm">
<div class="relative z-20 mb-10 border border-line bg-surface p-8 shadow-sm">
<div class="mb-6 grid grid-cols-1 items-end gap-4 md:grid-cols-[1fr_auto_1fr] md:gap-6">
<!-- Sender -->
<div
class="relative z-30 [&_input]:border-gray-300 [&_input]:py-2.5 [&_input]:focus:border-brand-navy [&_input]:focus:ring-brand-navy [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-gray-500 [&_label]:uppercase"
class="relative z-30 [&_input]:border-gray-300 [&_input]:py-2.5 [&_input]:focus:border-ink [&_input]:focus:ring-ink [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-ink-2 [&_label]:uppercase"
>
<PersonTypeahead
name="senderId"
@@ -98,7 +98,7 @@ const enrichedDocuments = $derived(
<button
data-testid="conv-swap-btn"
onclick={swapPersons}
class="border-brand-sand flex w-full items-center justify-center gap-2 border px-3 py-2.5 text-xs font-bold tracking-widest text-brand-navy uppercase transition-colors hover:bg-brand-navy hover:text-white md:w-auto {senderId &&
class="flex w-full items-center justify-center gap-2 border border-line px-3 py-2.5 text-xs font-bold tracking-widest text-ink uppercase transition-colors hover:bg-primary hover:text-white md:w-auto {senderId &&
receiverId
? ''
: 'invisible'}"
@@ -123,7 +123,7 @@ const enrichedDocuments = $derived(
<!-- Receiver -->
<div
class="relative z-30 [&_input]:border-gray-300 [&_input]:py-2.5 [&_input]:focus:border-brand-navy [&_input]:focus:ring-brand-navy [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-gray-500 [&_label]:uppercase"
class="relative z-30 [&_input]:border-gray-300 [&_input]:py-2.5 [&_input]:focus:border-ink [&_input]:focus:ring-ink [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-ink-2 [&_label]:uppercase"
>
<PersonTypeahead
name="receiverId"
@@ -141,7 +141,7 @@ const enrichedDocuments = $derived(
<div>
<label
for="dateFrom"
class="mb-2 block text-xs font-bold tracking-widest text-gray-500 uppercase"
class="mb-2 block text-xs font-bold tracking-widest text-ink-2 uppercase"
>{m.conv_label_from()}</label
>
<input
@@ -149,7 +149,7 @@ const enrichedDocuments = $derived(
type="date"
bind:value={fromDate}
onchange={() => applyFilters()}
class="block w-full border-gray-300 py-2.5 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full border-gray-300 py-2.5 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
</div>
@@ -157,7 +157,7 @@ const enrichedDocuments = $derived(
<div>
<label
for="dateTo"
class="mb-2 block text-xs font-bold tracking-widest text-gray-500 uppercase"
class="mb-2 block text-xs font-bold tracking-widest text-ink-2 uppercase"
>{m.conv_label_to()}</label
>
<input
@@ -165,7 +165,7 @@ const enrichedDocuments = $derived(
type="date"
bind:value={toDate}
onchange={() => applyFilters()}
class="block w-full border-gray-300 py-2.5 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full border-gray-300 py-2.5 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
</div>
@@ -173,7 +173,7 @@ const enrichedDocuments = $derived(
<div>
<button
onclick={toggleSort}
class="border-brand-sand flex h-[42px] w-full items-center justify-center border text-xs font-bold tracking-wide text-brand-navy uppercase transition-colors hover:bg-brand-navy hover:text-white"
class="flex h-[42px] w-full items-center justify-center border border-line text-xs font-bold tracking-wide text-ink uppercase transition-colors hover:bg-primary hover:text-white"
>
<span class="mr-2">{m.conv_sort_label()}</span>
<span>{sortDir === 'DESC' ? m.conv_sort_newest() : m.conv_sort_oldest()}</span>
@@ -196,9 +196,9 @@ const enrichedDocuments = $derived(
<!-- RESULTS LIST SECTION -->
{#if !senderId || !receiverId}
<div
class="border-brand-sand flex flex-col items-center justify-center rounded-sm border border-dashed bg-white py-24 text-center"
class="flex flex-col items-center justify-center rounded-sm border border-dashed border-line bg-surface py-24 text-center"
>
<div class="bg-brand-sand/30 mb-4 rounded-full p-4 text-brand-navy">
<div class="mb-4 rounded-full bg-muted p-4 text-ink">
<svg class="h-8 w-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"
><path
stroke-linecap="round"
@@ -208,25 +208,25 @@ const enrichedDocuments = $derived(
/></svg
>
</div>
<p class="font-serif text-lg text-brand-navy">{m.conv_empty_heading()}</p>
<p class="mt-1 font-sans text-sm text-gray-500">{m.conv_empty_text()}</p>
<p class="font-serif text-lg text-ink">{m.conv_empty_heading()}</p>
<p class="mt-1 font-sans text-sm text-ink-2">{m.conv_empty_text()}</p>
</div>
{:else if data.documents.length === 0}
<div
class="border-brand-sand flex flex-col items-center justify-center rounded-sm border bg-white py-24 text-center shadow-sm"
class="flex flex-col items-center justify-center rounded-sm border border-line bg-surface py-24 text-center shadow-sm"
>
<p class="font-serif text-brand-navy">{m.conv_no_results_heading()}</p>
<p class="mt-2 text-sm text-gray-400">{m.conv_no_results_text()}</p>
<p class="font-serif text-ink">{m.conv_no_results_heading()}</p>
<p class="mt-2 text-sm text-ink-3">{m.conv_no_results_text()}</p>
</div>
{:else}
<!-- Summary bar -->
<div class="mb-4 flex items-center justify-between">
{#if yearFrom !== null && yearTo !== null}
<p data-testid="conv-summary" class="font-sans text-sm font-medium text-brand-navy/70">
<p data-testid="conv-summary" class="font-sans text-sm font-medium text-ink/70">
{m.conv_summary({ count: data.documents.length, yearFrom, yearTo })}
</p>
{:else}
<p data-testid="conv-summary" class="font-sans text-sm font-medium text-brand-navy/70">
<p data-testid="conv-summary" class="font-sans text-sm font-medium text-ink/70">
{data.documents.length}
</p>
{/if}
@@ -234,7 +234,7 @@ const enrichedDocuments = $derived(
<a
data-testid="conv-new-doc-link"
href="/documents/new?senderId={senderId}&receiverId={receiverId}"
class="inline-flex items-center gap-1 text-sm font-medium text-brand-navy/60 transition-colors hover:text-brand-navy"
class="inline-flex items-center gap-1 text-sm font-medium text-ink/60 transition-colors hover:text-ink"
>
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"
@@ -246,10 +246,10 @@ const enrichedDocuments = $derived(
</div>
<!-- CHAT CONTAINER -->
<div class="border-brand-sand relative overflow-hidden rounded-sm border bg-white shadow-sm">
<div class="relative overflow-hidden rounded-sm border border-line bg-surface shadow-sm">
<!-- Decoration: Central Timeline Line -->
<div
class="bg-brand-sand/30 absolute top-0 bottom-0 left-1/2 hidden w-px -translate-x-1/2 transform md:block"
class="absolute top-0 bottom-0 left-1/2 hidden w-px -translate-x-1/2 transform bg-muted md:block"
></div>
<div class="p-6 md:p-8">
@@ -257,12 +257,11 @@ const enrichedDocuments = $derived(
{#each enrichedDocuments as { doc, year, showYearDivider } (doc.id)}
{#if showYearDivider}
<div data-testid="year-divider" class="relative flex items-center py-2 text-center">
<div class="border-brand-sand flex-grow border-t"></div>
<span
class="mx-4 font-sans text-xs font-bold tracking-widest text-brand-navy/40 uppercase"
<div class="flex-grow border-t border-line"></div>
<span class="mx-4 font-sans text-xs font-bold tracking-widest text-ink/40 uppercase"
>{year}</span
>
<div class="border-brand-sand flex-grow border-t"></div>
<div class="flex-grow border-t border-line"></div>
</div>
{/if}
{@const isRight = doc.sender?.id === senderId}
@@ -280,8 +279,8 @@ const enrichedDocuments = $derived(
<div
class="flex h-8 w-8 items-center justify-center rounded-full border font-serif text-xs shadow-sm
{isRight
? 'border-brand-navy bg-brand-navy text-white'
: 'border-brand-sand bg-white text-brand-navy'}"
? 'border-primary bg-primary text-white'
: 'border-line bg-surface text-ink'}"
>
{#if doc.sender}
{doc.sender.firstName[0]}{doc.sender.lastName[0]}
@@ -296,15 +295,15 @@ const enrichedDocuments = $derived(
href="/documents/{doc.id}"
class="group block transform rounded border p-4 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md
{isRight
? 'rounded-br-none border-brand-navy bg-brand-navy text-white'
: 'border-brand-sand bg-brand-sand/10 rounded-bl-none text-brand-navy'}"
? 'rounded-br-none border-primary bg-primary text-white'
: 'rounded-bl-none border-line bg-muted/50 text-ink'}"
>
<!-- Header -->
<div class="mb-2 flex items-start justify-between gap-4">
<h3
class="font-serif text-sm leading-snug font-medium {isRight
? 'text-white'
: 'text-brand-navy'}"
: 'text-ink'}"
>
{doc.title || doc.originalFilename}
</h3>
@@ -313,7 +312,7 @@ const enrichedDocuments = $derived(
<span
class="mt-1.5 h-1.5 w-1.5 flex-shrink-0 rounded-full
{doc.status === 'UPLOADED'
? 'bg-brand-mint'
? 'bg-accent'
: 'bg-yellow-400'}"
title={doc.status}
>
@@ -324,7 +323,7 @@ const enrichedDocuments = $derived(
<div
class="flex flex-wrap gap-3 font-sans text-[10px] tracking-wider uppercase opacity-80 {isRight
? 'text-blue-100'
: 'text-gray-500'}"
: 'text-ink-2'}"
>
<span class="flex items-center">
{doc.documentDate ? formatDate(doc.documentDate) : '—'}

View File

@@ -120,7 +120,7 @@ $effect(() => {
</svelte:head>
<div
class="fixed right-0 bottom-0 left-0 z-40 flex flex-col overflow-hidden bg-white"
class="fixed right-0 bottom-0 left-0 z-40 flex flex-col overflow-hidden bg-surface"
style="top: {navHeight}px"
data-hydrated
>

View File

@@ -43,7 +43,7 @@ function handleDateInput(e: Event) {
<div class="mb-6">
<a
href="/documents/{doc.id}"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-gray-500 uppercase transition-colors hover:text-brand-navy"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:text-ink"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Arrow/Arrow-Left-MD.svg"
@@ -53,9 +53,9 @@ function handleDateInput(e: Event) {
/>
{m.btn_back_to_document()}
</a>
<h1 class="font-serif text-3xl text-brand-navy">
<h1 class="font-serif text-3xl text-ink">
{m.doc_edit_heading()}
<span class="text-brand-navy/70">{doc.title || doc.originalFilename}</span>
<span class="text-ink/70">{doc.title || doc.originalFilename}</span>
</h1>
</div>
@@ -65,8 +65,8 @@ function handleDateInput(e: Event) {
<form method="POST" enctype="multipart/form-data" use:enhance class="space-y-6 pb-20">
<!-- ── Section 1: Wer & Wann ── -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.doc_section_who_when()}
</h2>
@@ -85,7 +85,7 @@ function handleDateInput(e: Event) {
placeholder={m.form_placeholder_date()}
maxlength="10"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm
{dateInvalid ? 'border-red-400 focus:border-red-500 focus:ring-red-500' : 'focus:border-brand-navy focus:ring-brand-navy'}"
{dateInvalid ? 'border-red-400 focus:border-red-500 focus:ring-red-500' : 'focus:border-ink focus:ring-ink'}"
aria-describedby={dateInvalid ? 'date-error' : undefined}
/>
<input type="hidden" name="documentDate" value={dateIso} />
@@ -105,7 +105,7 @@ function handleDateInput(e: Event) {
name="location"
value={doc.location || ''}
placeholder={m.form_placeholder_location()}
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
</div>
@@ -128,8 +128,8 @@ function handleDateInput(e: Event) {
</div>
<!-- ── Section 2: Beschreibung ── -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.doc_section_description()}
</h2>
@@ -145,7 +145,7 @@ function handleDateInput(e: Event) {
name="title"
value={doc.title || ''}
required
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
</div>
@@ -160,9 +160,9 @@ function handleDateInput(e: Event) {
name="documentLocation"
value={doc.documentLocation || ''}
placeholder={m.form_placeholder_archive_location()}
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
<p class="mt-1 text-xs text-gray-400">{m.form_helper_archive_location()}</p>
<p class="mt-1 text-xs text-ink-3">{m.form_helper_archive_location()}</p>
</div>
<!-- Schlagworte -->
@@ -182,7 +182,7 @@ function handleDateInput(e: Event) {
name="summary"
rows="5"
placeholder={m.form_placeholder_content()}
class="block w-full rounded border border-gray-300 p-2 font-serif text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 font-serif text-sm shadow-sm focus:border-ink focus:ring-ink"
>{doc.summary || ''}</textarea
>
</div>
@@ -190,8 +190,8 @@ function handleDateInput(e: Event) {
</div>
<!-- ── Section 3: Transkription ── -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.form_label_transcription()}
</h2>
<textarea
@@ -199,20 +199,18 @@ function handleDateInput(e: Event) {
name="transcription"
rows="12"
placeholder={m.form_placeholder_transcription()}
class="block w-full rounded border border-gray-300 p-2 font-serif text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 font-serif text-sm shadow-sm focus:border-ink focus:ring-ink"
>{doc.transcription || ''}</textarea
>
</div>
<!-- ── Section 4: Datei ── -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.doc_section_file()}
</h2>
<div
class="bg-brand-sand/20 mb-4 flex items-center gap-3 rounded px-3 py-2 text-sm text-gray-600"
>
<div class="mb-4 flex items-center gap-3 rounded bg-muted px-3 py-2 text-sm text-ink-2">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/PDF-Document-MD.svg"
alt=""
@@ -221,40 +219,40 @@ function handleDateInput(e: Event) {
/>
<span
>{m.doc_current_file_label()}
<strong class="font-medium text-brand-navy">{doc.originalFilename}</strong></span
<strong class="font-medium text-ink">{doc.originalFilename}</strong></span
>
</div>
<label for="file-upload" class="mb-1 block text-sm font-medium text-gray-700">
{m.doc_file_replace_label()}
<span class="font-normal text-gray-400">({m.doc_file_replace_note()})</span>
<span class="font-normal text-ink-3">({m.doc_file_replace_note()})</span>
</label>
<input
id="file-upload"
type="file"
name="file"
class="file:bg-brand-sand/40 hover:file:bg-brand-sand/60 block w-full
cursor-pointer text-sm text-gray-500
file:mr-4 file:rounded
file:border-0 file:px-4
file:py-2 file:text-sm
file:font-semibold file:text-brand-navy"
class="block w-full cursor-pointer text-sm
text-ink-2 file:mr-4 file:rounded
file:border-0 file:bg-muted
file:px-4 file:py-2
file:text-sm file:font-semibold
file:text-ink hover:file:bg-muted"
/>
</div>
<!-- ── Sticky Save Bar ── -->
<div
class="border-brand-sand sticky bottom-0 z-10 -mx-4 flex items-center justify-between border-t bg-white px-6 py-4 shadow-[0_-2px_8px_rgba(0,0,0,0.06)]"
class="sticky bottom-0 z-10 -mx-4 flex items-center justify-between border-t border-line bg-surface px-6 py-4 shadow-[0_-2px_8px_rgba(0,0,0,0.06)]"
>
<a
href="/documents/{doc.id}"
class="text-sm font-medium text-gray-500 transition-colors hover:text-brand-navy"
class="text-sm font-medium text-ink-2 transition-colors hover:text-ink"
>
{m.btn_cancel()}
</a>
<button
type="submit"
class="rounded bg-brand-navy px-6 py-2 text-sm font-bold tracking-widest text-white uppercase transition-colors hover:bg-brand-navy/80"
class="rounded bg-primary px-6 py-2 text-sm font-bold tracking-widest text-white uppercase transition-colors hover:bg-primary/80"
>
{m.btn_save()}
</button>

View File

@@ -50,7 +50,7 @@ function handleDateInput(e: Event) {
<div class="mb-6">
<a
href="/"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-gray-500 uppercase transition-colors hover:text-brand-navy"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:text-ink"
>
<svg
class="mr-2 h-4 w-4 transform transition-transform group-hover:-translate-x-1"
@@ -67,7 +67,7 @@ function handleDateInput(e: Event) {
</svg>
{m.btn_back_to_overview()}
</a>
<h1 class="font-serif text-3xl text-brand-navy">{m.doc_new_heading()}</h1>
<h1 class="font-serif text-3xl text-ink">{m.doc_new_heading()}</h1>
</div>
{#if form?.error}
@@ -76,8 +76,8 @@ function handleDateInput(e: Event) {
<form method="POST" enctype="multipart/form-data" use:enhance class="space-y-6 pb-20">
<!-- ── Section 1: Wer & Wann ── -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.doc_section_who_when()}
</h2>
@@ -96,7 +96,7 @@ function handleDateInput(e: Event) {
placeholder={m.form_placeholder_date()}
maxlength="10"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm
{dateInvalid ? 'border-red-400 focus:border-red-500 focus:ring-red-500' : 'focus:border-brand-navy focus:ring-brand-navy'}"
{dateInvalid ? 'border-red-400 focus:border-red-500 focus:ring-red-500' : 'focus:border-ink focus:ring-ink'}"
aria-describedby={dateInvalid ? 'date-error' : undefined}
/>
<input type="hidden" name="documentDate" value={dateIso} />
@@ -117,7 +117,7 @@ function handleDateInput(e: Event) {
type="text"
name="location"
placeholder={m.form_placeholder_location()}
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
</div>
@@ -140,8 +140,8 @@ function handleDateInput(e: Event) {
</div>
<!-- ── Section 2: Beschreibung ── -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.doc_section_description()}
</h2>
@@ -156,7 +156,7 @@ function handleDateInput(e: Event) {
type="text"
name="title"
required
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
</div>
@@ -170,9 +170,9 @@ function handleDateInput(e: Event) {
type="text"
name="documentLocation"
placeholder={m.form_placeholder_archive_location()}
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
<p class="mt-1 text-xs text-gray-400">{m.form_helper_archive_location()}</p>
<p class="mt-1 text-xs text-ink-3">{m.form_helper_archive_location()}</p>
</div>
<!-- Schlagworte -->
@@ -192,15 +192,15 @@ function handleDateInput(e: Event) {
name="summary"
rows="5"
placeholder={m.form_placeholder_content()}
class="block w-full rounded border border-gray-300 p-2 font-serif text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 font-serif text-sm shadow-sm focus:border-ink focus:ring-ink"
></textarea>
</div>
</div>
</div>
<!-- ── Section 3: Transkription ── -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.form_label_transcription()}
</h2>
<textarea
@@ -208,43 +208,43 @@ function handleDateInput(e: Event) {
name="transcription"
rows="12"
placeholder={m.form_placeholder_transcription()}
class="block w-full rounded border border-gray-300 p-2 font-serif text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 font-serif text-sm shadow-sm focus:border-ink focus:ring-ink"
></textarea>
</div>
<!-- ── Section 4: Datei ── -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.doc_section_file()}
</h2>
<label for="file-upload" class="mb-1 block text-sm font-medium text-gray-700">
{m.doc_file_upload_label()}
<span class="font-normal text-gray-400">({m.doc_file_upload_note()})</span>
<span class="font-normal text-ink-3">({m.doc_file_upload_note()})</span>
</label>
<input
id="file-upload"
type="file"
name="file"
class="file:bg-brand-sand/40 hover:file:bg-brand-sand/60 block w-full
cursor-pointer text-sm text-gray-500
file:mr-4 file:rounded
file:border-0 file:px-4
file:py-2 file:text-sm
file:font-semibold file:text-brand-navy"
class="block w-full cursor-pointer text-sm
text-ink-2 file:mr-4 file:rounded
file:border-0 file:bg-muted
file:px-4 file:py-2
file:text-sm file:font-semibold
file:text-ink hover:file:bg-muted"
/>
</div>
<!-- ── Sticky Save Bar ── -->
<div
class="border-brand-sand sticky bottom-0 z-10 -mx-4 flex items-center justify-between border-t bg-white px-6 py-4 shadow-[0_-2px_8px_rgba(0,0,0,0.06)]"
class="sticky bottom-0 z-10 -mx-4 flex items-center justify-between border-t border-line bg-surface px-6 py-4 shadow-[0_-2px_8px_rgba(0,0,0,0.06)]"
>
<a href="/" class="text-sm font-medium text-gray-500 transition-colors hover:text-brand-navy">
<a href="/" class="text-sm font-medium text-ink-2 transition-colors hover:text-ink">
{m.btn_cancel()}
</a>
<button
type="submit"
class="rounded bg-brand-navy px-6 py-2 text-sm font-bold tracking-widest text-white uppercase transition-colors hover:bg-brand-navy/80"
class="rounded bg-primary px-6 py-2 text-sm font-bold tracking-widest text-white uppercase transition-colors hover:bg-primary/80"
>
{m.btn_save()}
</button>

View File

@@ -4,7 +4,7 @@ import { m } from '$lib/paraglide/messages.js';
let { form }: { form?: { error?: string; success?: boolean } } = $props();
</script>
<div class="relative flex min-h-screen flex-col bg-white">
<div class="relative flex min-h-screen flex-col bg-surface">
<!-- Accent strip -->
<div class="h-1 bg-brand-purple"></div>
@@ -13,15 +13,15 @@ let { form }: { form?: { error?: string; success?: boolean } } = $props();
<!-- Logo -->
<div class="mb-10 text-center">
<a href="/" class="inline-flex items-center" aria-label="Familienarchiv">
<span class="font-sans text-2xl font-bold tracking-widest text-brand-navy uppercase"
<span class="font-sans text-2xl font-bold tracking-widest text-ink uppercase"
>Familienarchiv</span
>
</a>
</div>
<!-- Card -->
<div class="border-brand-sand rounded-sm border bg-white p-8 shadow-sm">
<h1 class="mb-6 font-sans text-sm font-bold tracking-widest text-brand-navy uppercase">
<div class="rounded-sm border border-line bg-surface p-8 shadow-sm">
<h1 class="mb-6 font-sans text-sm font-bold tracking-widest text-ink uppercase">
{m.forgot_password_heading()}
</h1>
@@ -30,9 +30,7 @@ let { form }: { form?: { error?: string; success?: boolean } } = $props();
<p class="font-sans text-xs text-green-700">{m.forgot_password_success()}</p>
</div>
<a
href="/login"
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
<a href="/login" class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
>{m.forgot_password_back_to_login()}</a
>
{:else}
@@ -40,7 +38,7 @@ let { form }: { form?: { error?: string; success?: boolean } } = $props();
<div>
<label
for="email"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-gray-500 uppercase"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-ink-2 uppercase"
>{m.forgot_password_email_label()}</label
>
<input
@@ -49,7 +47,7 @@ let { form }: { form?: { error?: string; success?: boolean } } = $props();
id="email"
required
autocomplete="email"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-brand-navy placeholder-gray-400 focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-ink placeholder-gray-400 focus:border-ink focus:ring-1 focus:ring-ink focus:outline-none"
/>
</div>
@@ -59,15 +57,13 @@ let { form }: { form?: { error?: string; success?: boolean } } = $props();
<button
type="submit"
class="mt-2 w-full bg-brand-navy py-2.5 font-sans text-xs font-bold tracking-widest text-white uppercase transition-colors hover:bg-brand-navy/90"
class="mt-2 w-full bg-primary py-2.5 font-sans text-xs font-bold tracking-widest text-white uppercase transition-colors hover:bg-primary/90"
>
{m.forgot_password_submit()}
</button>
<div class="mt-4 text-center">
<a
href="/login"
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
<a href="/login" class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
>{m.forgot_password_back_to_login()}</a
>
</div>
@@ -79,6 +75,6 @@ let { form }: { form?: { error?: string; success?: boolean } } = $props();
<!-- Footer -->
<div class="py-4 text-center">
<p class="font-sans text-xs tracking-widest text-gray-300 uppercase">Familienarchiv</p>
<p class="font-sans text-xs tracking-widest text-ink-3 uppercase">Familienarchiv</p>
</div>
</div>

View File

@@ -146,7 +146,23 @@
--c-pdf-text: #d1d1d1;
}
/* ─── 6. Base styles ───────────────────────────────────────────────────────── */
/* ─── 6. Icon inversion — De Gruyter icons are black SVGs loaded as <img> ──── */
/*
In dark mode, invert all brand icons so they read as white on dark surfaces.
Exclude .invert icons (already inverted for placement on dark backgrounds)
so they don't get double-inverted back to black.
*/
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) img[src*='degruyter-icons']:not(.invert) {
filter: invert(1);
}
}
:root[data-theme='dark'] img[src*='degruyter-icons']:not(.invert) {
filter: invert(1);
}
/* ─── 7. Base styles ───────────────────────────────────────────────────────── */
@layer base {
html {
overscroll-behavior: none;

View File

@@ -9,7 +9,7 @@ const localeMap = { DE: 'de', EN: 'en', ES: 'es' } as const;
const activeLocale = $derived(getLocale().toUpperCase());
</script>
<div class="relative flex min-h-screen flex-col bg-white">
<div class="relative flex min-h-screen flex-col bg-surface">
<!-- DGB purple accent strip -->
<div class="h-1 bg-brand-purple"></div>
@@ -21,8 +21,8 @@ const activeLocale = $derived(getLocale().toUpperCase());
onclick={() => setLocale(localeMap[locale])}
class="px-1.5 py-1 font-sans text-xs tracking-widest transition-colors
{activeLocale === locale
? 'font-bold text-brand-navy'
: 'font-normal text-gray-400 hover:text-brand-navy'}"
? 'font-bold text-ink'
: 'font-normal text-ink-3 hover:text-ink'}"
>
{locale}
</button>
@@ -34,15 +34,15 @@ const activeLocale = $derived(getLocale().toUpperCase());
<!-- Logo -->
<div class="mb-10 text-center">
<a href="/" class="inline-flex items-center" aria-label="Familienarchiv">
<span class="font-sans text-2xl font-bold tracking-widest text-brand-navy uppercase"
<span class="font-sans text-2xl font-bold tracking-widest text-ink uppercase"
>Familienarchiv</span
>
</a>
</div>
<!-- Card -->
<div class="border-brand-sand rounded-sm border bg-white p-8 shadow-sm">
<h1 class="mb-6 font-sans text-sm font-bold tracking-widest text-brand-navy uppercase">
<div class="rounded-sm border border-line bg-surface p-8 shadow-sm">
<h1 class="mb-6 font-sans text-sm font-bold tracking-widest text-ink uppercase">
{m.login_heading()}
</h1>
@@ -50,7 +50,7 @@ const activeLocale = $derived(getLocale().toUpperCase());
<div>
<label
for="username"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-gray-500 uppercase"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-ink-2 uppercase"
>{m.login_label_username()}</label
>
<input
@@ -59,14 +59,14 @@ const activeLocale = $derived(getLocale().toUpperCase());
id="username"
required
autocomplete="username"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-brand-navy placeholder-gray-400 focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-ink placeholder-gray-400 focus:border-ink focus:ring-1 focus:ring-ink focus:outline-none"
/>
</div>
<div>
<label
for="password"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-gray-500 uppercase"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-ink-2 uppercase"
>{m.login_label_password()}</label
>
<input
@@ -75,7 +75,7 @@ const activeLocale = $derived(getLocale().toUpperCase());
id="password"
required
autocomplete="current-password"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-brand-navy placeholder-gray-400 focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-ink placeholder-gray-400 focus:border-ink focus:ring-1 focus:ring-ink focus:outline-none"
/>
</div>
@@ -85,7 +85,7 @@ const activeLocale = $derived(getLocale().toUpperCase());
<button
type="submit"
class="mt-2 w-full bg-brand-navy py-2.5 font-sans text-xs font-bold tracking-widest text-white uppercase transition-colors hover:bg-brand-navy/90"
class="mt-2 w-full bg-primary py-2.5 font-sans text-xs font-bold tracking-widest text-white uppercase transition-colors hover:bg-primary/90"
>
{m.login_btn_submit()}
</button>
@@ -93,7 +93,7 @@ const activeLocale = $derived(getLocale().toUpperCase());
<div class="mt-4 text-center">
<a
href="/forgot-password"
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
>{m.login_forgot_password()}</a
>
</div>
@@ -104,6 +104,6 @@ const activeLocale = $derived(getLocale().toUpperCase());
<!-- Footer -->
<div class="py-4 text-center">
<p class="font-sans text-xs tracking-widest text-gray-300 uppercase">Familienarchiv</p>
<p class="font-sans text-xs tracking-widest text-ink-3 uppercase">Familienarchiv</p>
</div>
</div>

View File

@@ -26,17 +26,17 @@ function handleSearch() {
<div class="mx-auto max-w-7xl py-12 sm:px-6 lg:px-8">
<!-- Header Area -->
<div
class="mb-10 flex flex-col justify-between gap-6 border-b border-brand-navy/10 pb-6 md:flex-row md:items-end"
class="mb-10 flex flex-col justify-between gap-6 border-b border-ink/10 pb-6 md:flex-row md:items-end"
>
<div>
<h1 class="font-serif text-3xl font-medium text-brand-navy">{m.persons_heading()}</h1>
<p class="mt-2 max-w-xl font-sans text-sm text-brand-navy/60">
<h1 class="font-serif text-3xl font-medium text-ink">{m.persons_heading()}</h1>
<p class="mt-2 max-w-xl font-sans text-sm text-ink/60">
{m.persons_subtitle()}
</p>
{#if data.canWrite}
<a
href="/persons/new"
class="mt-3 inline-flex items-center gap-1 text-sm font-medium text-brand-navy/60 transition-colors hover:text-brand-navy"
class="mt-3 inline-flex items-center gap-1 text-sm font-medium text-ink/60 transition-colors hover:text-ink"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Add/Add-General-MD.svg"
@@ -61,10 +61,10 @@ function handleSearch() {
oninput={handleSearch}
onfocus={() => (qFocused = true)}
onblur={() => (qFocused = false)}
class="block w-full rounded-sm border border-gray-300 bg-white py-2.5 pr-10 pl-4 font-sans text-sm text-brand-navy placeholder-gray-400 shadow-sm focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none"
class="block w-full rounded-sm border border-gray-300 bg-surface py-2.5 pr-10 pl-4 font-sans text-sm text-ink placeholder-gray-400 shadow-sm focus:border-ink focus:ring-1 focus:ring-ink focus:outline-none"
/>
<div
class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3 text-gray-400"
class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3 text-ink-3"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Mag-Glass-MD.svg"
@@ -79,11 +79,9 @@ function handleSearch() {
{#if data.persons.length === 0}
<div
class="border-brand-sand flex flex-col items-center justify-center rounded-lg border border-dashed bg-white py-16 text-center"
class="flex flex-col items-center justify-center rounded-lg border border-dashed border-line bg-surface py-16 text-center"
>
<div
class="bg-brand-sand/30 mb-3 flex h-12 w-12 items-center justify-center rounded-full text-brand-navy"
>
<div class="mb-3 flex h-12 w-12 items-center justify-center rounded-full bg-muted text-ink">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Account-MD.svg"
alt=""
@@ -91,25 +89,25 @@ function handleSearch() {
class="h-6 w-6"
/>
</div>
<p class="font-serif text-lg text-brand-navy">{m.persons_empty_heading()}</p>
<p class="mt-1 font-sans text-sm text-gray-500">{m.persons_empty_text()}</p>
<p class="font-serif text-lg text-ink">{m.persons_empty_heading()}</p>
<p class="mt-1 font-sans text-sm text-ink-2">{m.persons_empty_text()}</p>
</div>
{:else}
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{#each data.persons as person (person.id)}
<a href="/persons/{person.id}" class="group block h-full">
<div
class="border-brand-sand relative flex h-full items-center gap-4 overflow-hidden rounded border bg-white p-6 shadow-sm transition-all duration-200 hover:border-brand-navy hover:shadow-md"
class="relative flex h-full items-center gap-4 overflow-hidden rounded border border-line bg-surface p-6 shadow-sm transition-all duration-200 hover:border-primary hover:shadow-md"
>
<!-- Decorative Accent on Hover -->
<div
class="absolute top-0 bottom-0 left-0 w-1 bg-brand-navy opacity-0 transition-opacity group-hover:opacity-100"
class="absolute top-0 bottom-0 left-0 w-1 bg-primary opacity-0 transition-opacity group-hover:opacity-100"
></div>
<!-- Avatar -->
<div class="flex-shrink-0">
<div
class="flex h-12 w-12 items-center justify-center rounded-full bg-brand-navy font-serif text-lg text-white transition-colors group-hover:bg-brand-mint group-hover:text-brand-navy"
class="flex h-12 w-12 items-center justify-center rounded-full bg-primary font-serif text-lg text-white transition-colors group-hover:bg-accent group-hover:text-ink"
>
{person.firstName[0]}{person.lastName[0]}
</div>
@@ -118,13 +116,13 @@ function handleSearch() {
<!-- Info -->
<div class="min-w-0 flex-1">
<p
class="truncate font-serif text-base font-medium text-brand-navy decoration-brand-mint decoration-2 underline-offset-2 group-hover:underline"
class="truncate font-serif text-base font-medium text-ink decoration-brand-mint decoration-2 underline-offset-2 group-hover:underline"
>
{person.firstName}
{person.lastName}
</p>
{#if person.alias}
<p class="mt-0.5 truncate font-sans text-xs text-gray-500">"{person.alias}"</p>
<p class="mt-0.5 truncate font-sans text-xs text-ink-2">"{person.alias}"</p>
{/if}
</div>
</div>

View File

@@ -98,7 +98,7 @@ $effect(() => {
<div class="mb-6">
<a
href="/persons"
class="group inline-flex items-center text-xs font-bold tracking-widest text-gray-500 uppercase transition-colors hover:text-brand-navy"
class="group inline-flex items-center text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:text-ink"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Arrow/Arrow-Left-MD.svg"
@@ -111,15 +111,15 @@ $effect(() => {
</div>
<!-- Header / Metadata Card -->
<div class="border-brand-sand mb-10 overflow-hidden rounded-sm border bg-white shadow-sm">
<div class="h-2 w-full bg-brand-navy"></div>
<div class="mb-10 overflow-hidden rounded-sm border border-line bg-surface shadow-sm">
<div class="h-2 w-full bg-primary"></div>
<div class="p-8 md:p-10">
{#if editMode && data.canWrite}
<!-- Edit Form -->
<form method="POST" action="?/update" use:enhance>
<div class="flex flex-col gap-6">
<h2 class="border-b border-gray-100 pb-3 font-serif text-xl text-brand-navy">
<h2 class="border-b border-line-2 pb-3 font-serif text-xl text-ink">
{m.person_edit_heading()}
</h2>
@@ -133,7 +133,7 @@ $effect(() => {
<div>
<label
for="firstName"
class="mb-1 block text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block text-xs font-bold tracking-widest text-ink-3 uppercase"
>{m.form_label_first_name()} *</label
>
<input
@@ -142,13 +142,13 @@ $effect(() => {
type="text"
required
value={person.firstName}
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-brand-navy focus:border-brand-navy focus:outline-none"
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-ink focus:border-ink focus:outline-none"
/>
</div>
<div>
<label
for="lastName"
class="mb-1 block text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block text-xs font-bold tracking-widest text-ink-3 uppercase"
>{m.form_label_last_name()} *</label
>
<input
@@ -157,13 +157,13 @@ $effect(() => {
type="text"
required
value={person.lastName}
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-brand-navy focus:border-brand-navy focus:outline-none"
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-ink focus:border-ink focus:outline-none"
/>
</div>
<div class="md:col-span-2">
<label
for="alias"
class="mb-1 block text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block text-xs font-bold tracking-widest text-ink-3 uppercase"
>{m.form_label_alias()}</label
>
<input
@@ -171,13 +171,13 @@ $effect(() => {
name="alias"
type="text"
value={person.alias ?? ''}
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-brand-navy focus:border-brand-navy focus:outline-none"
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-ink focus:border-ink focus:outline-none"
/>
</div>
<div>
<label
for="birthYear"
class="mb-1 block text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block text-xs font-bold tracking-widest text-ink-3 uppercase"
>{m.person_label_birth_year()}</label
>
<input
@@ -188,13 +188,13 @@ $effect(() => {
max="2100"
placeholder={m.person_placeholder_year()}
value={person.birthYear ?? ''}
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-brand-navy focus:border-brand-navy focus:outline-none"
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-ink focus:border-ink focus:outline-none"
/>
</div>
<div>
<label
for="deathYear"
class="mb-1 block text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block text-xs font-bold tracking-widest text-ink-3 uppercase"
>{m.person_label_death_year()}</label
>
<input
@@ -205,13 +205,13 @@ $effect(() => {
max="2100"
placeholder={m.person_placeholder_year()}
value={person.deathYear ?? ''}
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-brand-navy focus:border-brand-navy focus:outline-none"
class="block w-full rounded border border-gray-300 px-3 py-2 font-serif text-ink focus:border-ink focus:outline-none"
/>
</div>
<div class="md:col-span-2">
<label
for="notes"
class="mb-1 block text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block text-xs font-bold tracking-widest text-ink-3 uppercase"
>{m.person_label_notes()}</label
>
<textarea
@@ -219,7 +219,7 @@ $effect(() => {
name="notes"
rows="4"
placeholder={m.person_placeholder_notes()}
class="block w-full resize-y rounded border border-gray-300 px-3 py-2 font-serif text-brand-navy focus:border-brand-navy focus:outline-none"
class="block w-full resize-y rounded border border-gray-300 px-3 py-2 font-serif text-ink focus:border-ink focus:outline-none"
>{person.notes ?? ''}</textarea
>
</div>
@@ -228,14 +228,14 @@ $effect(() => {
<div class="flex gap-3">
<button
type="submit"
class="rounded bg-brand-navy px-5 py-2 text-sm font-bold tracking-widest text-white uppercase transition-colors hover:bg-brand-navy/80"
class="rounded bg-primary px-5 py-2 text-sm font-bold tracking-widest text-white uppercase transition-colors hover:bg-primary/80"
>
{m.btn_save()}
</button>
<button
type="button"
onclick={() => (editMode = false)}
class="rounded border border-gray-300 px-5 py-2 text-sm font-bold tracking-widest text-gray-600 uppercase transition-colors hover:bg-gray-50"
class="rounded border border-gray-300 px-5 py-2 text-sm font-bold tracking-widest text-ink-2 uppercase transition-colors hover:bg-gray-50"
>
{m.btn_cancel()}
</button>
@@ -247,15 +247,15 @@ $effect(() => {
<div class="flex flex-col items-start gap-8 md:flex-row">
<div class="flex-shrink-0">
<div
class="border-brand-sand bg-brand-sand/30 flex h-24 w-24 items-center justify-center rounded-full border text-brand-navy"
class="flex h-24 w-24 items-center justify-center rounded-full border border-line bg-muted text-ink"
>
<span class="font-serif text-3xl">{person.firstName[0]}{person.lastName[0]}</span>
</div>
</div>
<div class="w-full flex-1">
<div class="mb-8 flex items-start justify-between border-b border-gray-100 pb-4">
<h1 class="font-serif text-4xl text-brand-navy">
<div class="mb-8 flex items-start justify-between border-b border-line-2 pb-4">
<h1 class="font-serif text-4xl text-ink">
{person.firstName}
{person.lastName}
</h1>
@@ -263,7 +263,7 @@ $effect(() => {
{#if data.canWrite}
<button
onclick={() => (editMode = true)}
class="inline-flex items-center gap-1.5 rounded border border-gray-300 px-3 py-1.5 text-xs font-bold tracking-widest text-gray-500 uppercase transition-colors hover:border-brand-navy hover:text-brand-navy"
class="inline-flex items-center gap-1.5 rounded border border-gray-300 px-3 py-1.5 text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:border-primary hover:text-ink"
>
<img
src="/degruyter-icons/Simple/Small-16px/SVG/Action/Edit-Content-SM.svg"
@@ -280,10 +280,10 @@ $effect(() => {
<div class="grid grid-cols-1 gap-8 md:grid-cols-2">
<div>
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>{m.person_label_full_name()}</span
>
<span class="block font-serif text-lg text-brand-navy"
<span class="block font-serif text-lg text-ink"
>{person.firstName} {person.lastName}</span
>
</div>
@@ -291,23 +291,21 @@ $effect(() => {
{#if person.alias}
<div>
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>{m.form_label_alias()}</span
>
<span class="block font-serif text-lg text-brand-navy italic"
>"{person.alias}"</span
>
<span class="block font-serif text-lg text-ink italic">"{person.alias}"</span>
</div>
{/if}
{#if person.birthYear || person.deathYear}
<div>
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{#if person.birthYear && person.deathYear}{m.person_label_birth_year()} / {m.person_label_death_year()}{:else if person.birthYear}{m.person_label_birth_year()}{:else}{m.person_label_death_year()}{/if}
</span>
<span class="block font-serif text-lg text-brand-navy">
<span class="block font-serif text-lg text-ink">
{#if person.birthYear}* {person.birthYear}{/if}{#if person.birthYear && person.deathYear}
&nbsp;{/if}{#if person.deathYear}{person.deathYear}{/if}
</span>
@@ -317,10 +315,10 @@ $effect(() => {
{#if person.notes}
<div class="md:col-span-2">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>{m.person_label_notes()}</span
>
<p class="font-serif text-base whitespace-pre-wrap text-brand-navy">
<p class="font-serif text-base whitespace-pre-wrap text-ink">
{person.notes}
</p>
</div>
@@ -335,10 +333,10 @@ $effect(() => {
<!-- Merge Section -->
{#if data.canWrite}
{#key person.id}
<div class="border-brand-sand mb-10 overflow-hidden rounded-sm border bg-white shadow-sm">
<div class="mb-10 overflow-hidden rounded-sm border border-line bg-surface shadow-sm">
<div class="p-6 md:p-8">
<h2 class="mb-1 font-serif text-lg text-brand-navy">{m.person_merge_heading()}</h2>
<p class="mb-5 font-sans text-sm text-gray-500">
<h2 class="mb-1 font-serif text-lg text-ink">{m.person_merge_heading()}</h2>
<p class="mb-5 font-sans text-sm text-ink-2">
{m.person_merge_description()}
</p>
@@ -381,7 +379,7 @@ $effect(() => {
<button
type="button"
onclick={() => (showMergeConfirm = false)}
class="rounded border border-gray-300 px-4 py-2 text-sm font-bold tracking-widest text-gray-500 uppercase transition-colors hover:bg-gray-50"
class="rounded border border-gray-300 px-4 py-2 text-sm font-bold tracking-widest text-ink-2 uppercase transition-colors hover:bg-gray-50"
>
{m.btn_cancel()}
</button>
@@ -406,17 +404,17 @@ $effect(() => {
<!-- Co-Correspondents Section -->
{#if coCorrespondents.length > 0}
<div class="mb-6">
<h3 class="mb-3 text-xs font-bold tracking-widest text-gray-400 uppercase">
<h3 class="mb-3 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.person_co_correspondents_heading()}
</h3>
<div class="flex flex-wrap gap-2">
{#each coCorrespondents as c (c.id)}
<a
href="/conversations?senderId={person.id}&receiverId={c.id}"
class="border-brand-sand inline-flex items-center gap-1.5 rounded-full border px-3 py-1 font-serif text-sm text-brand-navy transition-colors hover:border-brand-navy"
class="inline-flex items-center gap-1.5 rounded-full border border-line px-3 py-1 font-serif text-sm text-ink transition-colors hover:border-primary"
>
{c.name}
<span class="font-sans text-xs text-gray-400">({c.count})</span>
<span class="font-sans text-xs text-ink-3">({c.count})</span>
</a>
{/each}
</div>
@@ -425,18 +423,18 @@ $effect(() => {
<!-- Sent Documents Section -->
<div class="mb-10">
<div class="mb-6 flex items-center gap-3 border-b border-brand-navy/10 pb-2">
<h2 class="font-serif text-xl text-brand-navy">{m.person_docs_heading()}</h2>
<span class="rounded-full bg-brand-navy px-2 py-1 text-xs font-bold text-white">
<div class="mb-6 flex items-center gap-3 border-b border-ink/10 pb-2">
<h2 class="font-serif text-xl text-ink">{m.person_docs_heading()}</h2>
<span class="rounded-full bg-primary px-2 py-1 text-xs font-bold text-white">
{sentDocuments.length}
</span>
{#if sentYearRange}
<span class="font-sans text-xs text-gray-400">{sentYearRange}</span>
<span class="font-sans text-xs text-ink-3">{sentYearRange}</span>
{/if}
{#if sentDocuments.length > 1}
<button
onclick={() => (sortDirSent = sortDirSent === 'DESC' ? 'ASC' : 'DESC')}
class="ml-auto text-xs font-bold tracking-widest text-gray-400 uppercase transition-colors hover:text-brand-navy"
class="ml-auto text-xs font-bold tracking-widest text-ink-3 uppercase transition-colors hover:text-ink"
>
{sortDirSent === 'DESC' ? m.conv_sort_newest() : m.conv_sort_oldest()}
</button>
@@ -444,8 +442,8 @@ $effect(() => {
</div>
{#if sentDocuments.length === 0}
<div class="border-brand-sand rounded-sm border border-dashed bg-white p-12 text-center">
<p class="font-sans text-gray-500">{m.person_no_docs()}</p>
<div class="rounded-sm border border-dashed border-line bg-surface p-12 text-center">
<p class="font-sans text-ink-2">{m.person_no_docs()}</p>
</div>
{:else}
<ul class="space-y-3">
@@ -453,12 +451,12 @@ $effect(() => {
<li class="group">
<a
href="/documents/{doc.id}"
class="border-brand-sand block border bg-white p-4 transition-all duration-200 hover:border-brand-navy hover:shadow-md"
class="block border border-line bg-surface p-4 transition-all duration-200 hover:border-primary hover:shadow-md"
>
<div class="flex items-center justify-between">
<div class="flex items-center gap-4 overflow-hidden">
<div
class="bg-brand-sand/20 flex h-10 w-10 flex-shrink-0 items-center justify-center rounded text-brand-navy transition-colors group-hover:bg-brand-mint group-hover:text-brand-navy"
class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded bg-muted text-ink transition-colors group-hover:bg-accent group-hover:text-ink"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/PDF-Document-MD.svg"
@@ -469,16 +467,16 @@ $effect(() => {
</div>
<div class="min-w-0">
<div
class="truncate font-serif text-base font-medium text-brand-navy decoration-brand-mint decoration-2 underline-offset-2 group-hover:underline"
class="truncate font-serif text-base font-medium text-ink decoration-brand-mint decoration-2 underline-offset-2 group-hover:underline"
>
{doc.title || doc.originalFilename}
</div>
<div class="mt-0.5 flex items-center space-x-2 font-sans text-xs text-gray-500">
<div class="mt-0.5 flex items-center space-x-2 font-sans text-xs text-ink-2">
<span
>{doc.documentDate ? formatDate(doc.documentDate) : m.doc_no_date()}</span
>
{#if doc.location}
<span class="text-brand-mint"></span>
<span class="text-accent"></span>
<span>{doc.location}</span>
{/if}
</div>
@@ -488,7 +486,7 @@ $effect(() => {
<span
class="hidden items-center rounded-full border px-2 py-0.5 text-[10px] font-bold tracking-wide uppercase sm:inline-flex
{doc.status === 'UPLOADED'
? 'border-brand-mint/50 bg-brand-mint/20 text-brand-navy'
? 'border-accent/50 bg-accent/20 text-ink'
: 'border-yellow-200 bg-yellow-50 text-yellow-800'}"
>
{doc.status}
@@ -508,7 +506,7 @@ $effect(() => {
{#if sentDocuments.length > DOCS_PREVIEW_LIMIT && !showAllSent}
<button
onclick={() => (showAllSent = true)}
class="mt-3 text-xs font-bold tracking-widest text-brand-navy/50 uppercase transition-colors hover:text-brand-navy"
class="mt-3 text-xs font-bold tracking-widest text-ink/50 uppercase transition-colors hover:text-ink"
>
{m.person_show_more({ count: sentDocuments.length - DOCS_PREVIEW_LIMIT })}
</button>
@@ -518,18 +516,18 @@ $effect(() => {
<!-- Received Documents Section -->
<div>
<div class="mb-6 flex items-center gap-3 border-b border-brand-navy/10 pb-2">
<h2 class="font-serif text-xl text-brand-navy">{m.person_received_docs_heading()}</h2>
<span class="rounded-full bg-brand-navy px-2 py-1 text-xs font-bold text-white">
<div class="mb-6 flex items-center gap-3 border-b border-ink/10 pb-2">
<h2 class="font-serif text-xl text-ink">{m.person_received_docs_heading()}</h2>
<span class="rounded-full bg-primary px-2 py-1 text-xs font-bold text-white">
{receivedDocuments.length}
</span>
{#if receivedYearRange}
<span class="font-sans text-xs text-gray-400">{receivedYearRange}</span>
<span class="font-sans text-xs text-ink-3">{receivedYearRange}</span>
{/if}
{#if receivedDocuments.length > 1}
<button
onclick={() => (sortDirReceived = sortDirReceived === 'DESC' ? 'ASC' : 'DESC')}
class="ml-auto text-xs font-bold tracking-widest text-gray-400 uppercase transition-colors hover:text-brand-navy"
class="ml-auto text-xs font-bold tracking-widest text-ink-3 uppercase transition-colors hover:text-ink"
>
{sortDirReceived === 'DESC' ? m.conv_sort_newest() : m.conv_sort_oldest()}
</button>
@@ -537,8 +535,8 @@ $effect(() => {
</div>
{#if receivedDocuments.length === 0}
<div class="border-brand-sand rounded-sm border border-dashed bg-white p-12 text-center">
<p class="font-sans text-gray-500">{m.person_no_received_docs()}</p>
<div class="rounded-sm border border-dashed border-line bg-surface p-12 text-center">
<p class="font-sans text-ink-2">{m.person_no_received_docs()}</p>
</div>
{:else}
<ul class="space-y-3">
@@ -546,12 +544,12 @@ $effect(() => {
<li class="group">
<a
href="/documents/{doc.id}"
class="border-brand-sand block border bg-white p-4 transition-all duration-200 hover:border-brand-navy hover:shadow-md"
class="block border border-line bg-surface p-4 transition-all duration-200 hover:border-primary hover:shadow-md"
>
<div class="flex items-center justify-between">
<div class="flex items-center gap-4 overflow-hidden">
<div
class="bg-brand-sand/20 flex h-10 w-10 flex-shrink-0 items-center justify-center rounded text-brand-navy transition-colors group-hover:bg-brand-mint group-hover:text-brand-navy"
class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded bg-muted text-ink transition-colors group-hover:bg-accent group-hover:text-ink"
>
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/PDF-Document-MD.svg"
@@ -562,16 +560,16 @@ $effect(() => {
</div>
<div class="min-w-0">
<div
class="truncate font-serif text-base font-medium text-brand-navy decoration-brand-mint decoration-2 underline-offset-2 group-hover:underline"
class="truncate font-serif text-base font-medium text-ink decoration-brand-mint decoration-2 underline-offset-2 group-hover:underline"
>
{doc.title || doc.originalFilename}
</div>
<div class="mt-0.5 flex items-center space-x-2 font-sans text-xs text-gray-500">
<div class="mt-0.5 flex items-center space-x-2 font-sans text-xs text-ink-2">
<span
>{doc.documentDate ? formatDate(doc.documentDate) : m.doc_no_date()}</span
>
{#if doc.location}
<span class="text-brand-mint"></span>
<span class="text-accent"></span>
<span>{doc.location}</span>
{/if}
</div>
@@ -581,7 +579,7 @@ $effect(() => {
<span
class="hidden items-center rounded-full border px-2 py-0.5 text-[10px] font-bold tracking-wide uppercase sm:inline-flex
{doc.status === 'UPLOADED'
? 'border-brand-mint/50 bg-brand-mint/20 text-brand-navy'
? 'border-accent/50 bg-accent/20 text-ink'
: 'border-yellow-200 bg-yellow-50 text-yellow-800'}"
>
{doc.status}
@@ -601,7 +599,7 @@ $effect(() => {
{#if receivedDocuments.length > DOCS_PREVIEW_LIMIT && !showAllReceived}
<button
onclick={() => (showAllReceived = true)}
class="mt-3 text-xs font-bold tracking-widest text-brand-navy/50 uppercase transition-colors hover:text-brand-navy"
class="mt-3 text-xs font-bold tracking-widest text-ink/50 uppercase transition-colors hover:text-ink"
>
{m.person_show_more({ count: receivedDocuments.length - DOCS_PREVIEW_LIMIT })}
</button>

View File

@@ -8,7 +8,7 @@ let { form } = $props();
<div class="mb-6">
<a
href="/persons"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-gray-500 uppercase transition-colors hover:text-brand-navy"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:text-ink"
>
<svg
class="mr-2 h-4 w-4 transform transition-transform group-hover:-translate-x-1"
@@ -25,7 +25,7 @@ let { form } = $props();
</svg>
{m.btn_back_to_overview()}
</a>
<h1 class="font-serif text-3xl text-brand-navy">{m.persons_new_heading()}</h1>
<h1 class="font-serif text-3xl text-ink">{m.persons_new_heading()}</h1>
</div>
{#if form?.error}
@@ -33,8 +33,8 @@ let { form } = $props();
{/if}
<form method="POST">
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.persons_section_details()}
</h2>
@@ -48,7 +48,7 @@ let { form } = $props();
name="firstName"
type="text"
required
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
</div>
@@ -61,7 +61,7 @@ let { form } = $props();
name="lastName"
type="text"
required
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
</div>
@@ -74,7 +74,7 @@ let { form } = $props();
name="alias"
type="text"
placeholder={m.form_placeholder_alias()}
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-brand-navy focus:ring-brand-navy"
class="block w-full rounded border border-gray-300 p-2 text-sm shadow-sm focus:border-ink focus:ring-ink"
/>
</div>
</div>
@@ -82,17 +82,14 @@ let { form } = $props();
<!-- Save Bar -->
<div
class="border-brand-sand mt-4 flex items-center justify-between rounded-sm border bg-white px-6 py-4 shadow-sm"
class="mt-4 flex items-center justify-between rounded-sm border border-line bg-surface px-6 py-4 shadow-sm"
>
<a
href="/persons"
class="text-sm font-medium text-gray-500 transition-colors hover:text-brand-navy"
>
<a href="/persons" class="text-sm font-medium text-ink-2 transition-colors hover:text-ink">
{m.btn_cancel()}
</a>
<button
type="submit"
class="rounded bg-brand-navy px-6 py-2 text-sm font-bold tracking-widest text-white uppercase transition-colors hover:bg-brand-navy/80"
class="rounded bg-primary px-6 py-2 text-sm font-bold tracking-widest text-white uppercase transition-colors hover:bg-primary/80"
>
{m.btn_create()}
</button>

View File

@@ -42,7 +42,7 @@ function handleBirthDateInput(e: Event) {
<!-- Back link -->
<a
href="/"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-gray-500 uppercase transition-colors hover:text-brand-navy"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:text-ink"
>
<svg
class="mr-2 h-4 w-4 transform transition-transform group-hover:-translate-x-1"
@@ -56,12 +56,12 @@ function handleBirthDateInput(e: Event) {
{m.btn_back_to_overview()}
</a>
<h1 class="mb-6 font-serif text-3xl font-bold text-brand-navy">{m.profile_heading()}</h1>
<h1 class="mb-6 font-serif text-3xl font-bold text-ink">{m.profile_heading()}</h1>
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
<!-- Personal info card -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_section_personal()}
</h2>
@@ -80,7 +80,7 @@ function handleBirthDateInput(e: Event) {
<div class="space-y-4">
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_first_name()}
</span>
@@ -88,13 +88,13 @@ function handleBirthDateInput(e: Event) {
type="text"
name="firstName"
value={data.user?.firstName ?? ''}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_last_name()}
</span>
@@ -102,13 +102,13 @@ function handleBirthDateInput(e: Event) {
type="text"
name="lastName"
value={data.user?.lastName ?? ''}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_birth_date()}
</span>
@@ -117,14 +117,14 @@ function handleBirthDateInput(e: Event) {
placeholder="TT.MM.JJJJ"
value={birthDateDisplay}
oninput={handleBirthDateInput}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
<input type="hidden" name="birthDate" value={birthDateIso} />
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_email()}
</span>
@@ -132,13 +132,13 @@ function handleBirthDateInput(e: Event) {
type="email"
name="email"
value={data.user?.email ?? ''}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_contact()}
</span>
@@ -146,7 +146,7 @@ function handleBirthDateInput(e: Event) {
name="contact"
rows="3"
placeholder={m.profile_contact_placeholder()}
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
>{data.user?.contact ?? ''}</textarea
>
</label>
@@ -154,7 +154,7 @@ function handleBirthDateInput(e: Event) {
<button
type="submit"
class="mt-5 rounded-sm bg-brand-navy px-5 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
class="mt-5 rounded-sm bg-primary px-5 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
>
{m.btn_save()}
</button>
@@ -162,8 +162,8 @@ function handleBirthDateInput(e: Event) {
</div>
<!-- Password change card -->
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-gray-400 uppercase">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<h2 class="mb-5 text-xs font-bold tracking-widest text-ink-3 uppercase">
{m.profile_section_password()}
</h2>
@@ -186,7 +186,7 @@ function handleBirthDateInput(e: Event) {
<div class="space-y-4">
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_current_password()}
</span>
@@ -194,13 +194,13 @@ function handleBirthDateInput(e: Event) {
type="password"
name="currentPassword"
required
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_new_password()}
</span>
@@ -208,13 +208,13 @@ function handleBirthDateInput(e: Event) {
type="password"
name="newPassword"
required
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
<label class="block">
<span
class="mb-1 block font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
class="mb-1 block font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>
{m.profile_label_new_password_confirm()}
</span>
@@ -222,14 +222,14 @@ function handleBirthDateInput(e: Event) {
type="password"
name="confirmPassword"
required
class="border-brand-sand w-full rounded-sm border px-3 py-2 font-serif text-sm focus:border-brand-navy focus:outline-none"
class="w-full rounded-sm border border-line px-3 py-2 font-serif text-sm focus:border-ink focus:outline-none"
/>
</label>
</div>
<button
type="submit"
class="mt-5 rounded-sm bg-brand-navy px-5 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
class="mt-5 rounded-sm bg-primary px-5 py-2 font-sans text-xs font-bold tracking-widest text-white uppercase transition-opacity hover:opacity-80"
>
{m.btn_save()}
</button>

View File

@@ -11,7 +11,7 @@ let {
} = $props();
</script>
<div class="relative flex min-h-screen flex-col bg-white">
<div class="relative flex min-h-screen flex-col bg-surface">
<!-- Accent strip -->
<div class="h-1 bg-brand-purple"></div>
@@ -20,15 +20,15 @@ let {
<!-- Logo -->
<div class="mb-10 text-center">
<a href="/" class="inline-flex items-center" aria-label="Familienarchiv">
<span class="font-sans text-2xl font-bold tracking-widest text-brand-navy uppercase"
<span class="font-sans text-2xl font-bold tracking-widest text-ink uppercase"
>Familienarchiv</span
>
</a>
</div>
<!-- Card -->
<div class="border-brand-sand rounded-sm border bg-white p-8 shadow-sm">
<h1 class="mb-6 font-sans text-sm font-bold tracking-widest text-brand-navy uppercase">
<div class="rounded-sm border border-line bg-surface p-8 shadow-sm">
<h1 class="mb-6 font-sans text-sm font-bold tracking-widest text-ink uppercase">
{m.reset_password_heading()}
</h1>
@@ -37,9 +37,7 @@ let {
<p class="font-sans text-xs text-green-700">{m.reset_password_success()}</p>
</div>
<a
href="/login"
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
<a href="/login" class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
>{m.forgot_password_back_to_login()}</a
>
{:else}
@@ -49,7 +47,7 @@ let {
<div>
<label
for="newPassword"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-gray-500 uppercase"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-ink-2 uppercase"
>{m.reset_password_label()}</label
>
<input
@@ -58,14 +56,14 @@ let {
id="newPassword"
required
autocomplete="new-password"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-brand-navy placeholder-gray-400 focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-ink placeholder-gray-400 focus:border-ink focus:ring-1 focus:ring-ink focus:outline-none"
/>
</div>
<div>
<label
for="confirmPassword"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-gray-500 uppercase"
class="mb-1.5 block font-sans text-xs font-bold tracking-widest text-ink-2 uppercase"
>{m.reset_password_confirm_label()}</label
>
<input
@@ -74,7 +72,7 @@ let {
id="confirmPassword"
required
autocomplete="new-password"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-brand-navy placeholder-gray-400 focus:border-brand-navy focus:ring-1 focus:ring-brand-navy focus:outline-none"
class="block w-full border border-gray-300 px-3 py-2.5 font-serif text-sm text-ink placeholder-gray-400 focus:border-ink focus:ring-1 focus:ring-ink focus:outline-none"
/>
</div>
@@ -88,15 +86,13 @@ let {
<button
type="submit"
class="mt-2 w-full bg-brand-navy py-2.5 font-sans text-xs font-bold tracking-widest text-white uppercase transition-colors hover:bg-brand-navy/90"
class="mt-2 w-full bg-primary py-2.5 font-sans text-xs font-bold tracking-widest text-white uppercase transition-colors hover:bg-primary/90"
>
{m.reset_password_submit()}
</button>
<div class="mt-4 text-center">
<a
href="/login"
class="font-sans text-xs text-gray-400 transition-colors hover:text-brand-navy"
<a href="/login" class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
>{m.forgot_password_back_to_login()}</a
>
</div>
@@ -108,6 +104,6 @@ let {
<!-- Footer -->
<div class="py-4 text-center">
<p class="font-sans text-xs tracking-widest text-gray-300 uppercase">Familienarchiv</p>
<p class="font-sans text-xs tracking-widest text-ink-3 uppercase">Familienarchiv</p>
</div>
</div>

View File

@@ -23,7 +23,7 @@ const initials = $derived.by(() => {
<!-- Back link -->
<a
href="/"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-gray-500 uppercase transition-colors hover:text-brand-navy"
class="group mb-4 inline-flex items-center text-xs font-bold tracking-widest text-ink-2 uppercase transition-colors hover:text-ink"
>
<svg
class="mr-2 h-4 w-4 transform transition-transform group-hover:-translate-x-1"
@@ -37,21 +37,21 @@ const initials = $derived.by(() => {
Zurück
</a>
<h1 class="mb-6 font-serif text-3xl font-bold text-brand-navy">{m.user_profile_heading()}</h1>
<h1 class="mb-6 font-serif text-3xl font-bold text-ink">{m.user_profile_heading()}</h1>
<div class="max-w-md">
<div class="border-brand-sand rounded-sm border bg-white p-6 shadow-sm">
<div class="rounded-sm border border-line bg-surface p-6 shadow-sm">
<!-- Avatar -->
<div class="mb-5 flex justify-center">
{#if initials}
<div
class="flex h-16 w-16 items-center justify-center rounded-full bg-brand-navy text-white"
class="flex h-16 w-16 items-center justify-center rounded-full bg-primary text-white"
>
<span class="font-serif text-xl font-bold">{initials}</span>
</div>
{:else}
<div
class="flex h-16 w-16 items-center justify-center rounded-full bg-brand-navy text-white"
class="flex h-16 w-16 items-center justify-center rounded-full bg-primary text-white"
>
<svg
class="h-8 w-8"
@@ -72,9 +72,9 @@ const initials = $derived.by(() => {
<!-- Name and username -->
<div class="mb-5 text-center">
<h2 class="font-serif text-xl font-bold text-brand-navy">{fullName}</h2>
<h2 class="font-serif text-xl font-bold text-ink">{fullName}</h2>
{#if data.profileUser.firstName || data.profileUser.lastName}
<p class="mt-0.5 font-sans text-sm text-gray-400">@{data.profileUser.username}</p>
<p class="mt-0.5 font-sans text-sm text-ink-3">@{data.profileUser.username}</p>
{/if}
</div>
@@ -82,19 +82,19 @@ const initials = $derived.by(() => {
<div class="flex flex-col gap-4">
{#if data.profileUser.email}
<div class="flex flex-col gap-0.5">
<span class="font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
<span class="font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>E-Mail</span
>
<span class="font-serif text-sm text-brand-navy">{data.profileUser.email}</span>
<span class="font-serif text-sm text-ink">{data.profileUser.email}</span>
</div>
{/if}
{#if data.profileUser.contact}
<div class="flex flex-col gap-0.5">
<span class="font-sans text-xs font-bold tracking-widest text-gray-400 uppercase"
<span class="font-sans text-xs font-bold tracking-widest text-ink-3 uppercase"
>Kontakt</span
>
<span class="font-serif text-sm text-brand-navy">{data.profileUser.contact}</span>
<span class="font-serif text-sm text-ink">{data.profileUser.contact}</span>
</div>
{/if}
</div>