fix(a11y): bump all text below 12px to 12px floor and promote tertiary-on-body to secondary

Brand guidelines (docs/brand/magnotia-brand-guidelines.md §4) say "Never go
below 12px for any text" and "tertiary text must be ≥18px bold or ≥24px
regular". Audit found 246 sub-12px className sites and 166 cases of
text-text-tertiary paired with body sizes.

Bumped text-[9/10/11px] → text-[12px] across 26 .svelte files in src/lib
and src/routes. Promoted text-text-tertiary → text-text-secondary at body
sizes (12-14px) where context allowed; left placeholder pseudo-states,
ternary-conditional inactive states, and line-through "done" states alone
(8 residual pairings, all decorative).

Affects neurodivergent users on 1366×768 budget hardware most directly.
svelte-check: 0 errors, 0 warnings.
This commit is contained in:
2026-05-07 11:18:10 +01:00
parent 6da15d1ac8
commit ca3a55320b
26 changed files with 257 additions and 257 deletions

View File

@@ -61,7 +61,7 @@
<div class="flex flex-col gap-1.5">
<div class="flex justify-between">
<p class="text-[12px] text-text-secondary font-medium">Font size</p>
<span class="text-[11px] text-text-tertiary">{prefs.accessibility.fontSize}px</span>
<span class="text-[12px] text-text-secondary">{prefs.accessibility.fontSize}px</span>
</div>
<input type="range" min="16" max="24" step="1" value={prefs.accessibility.fontSize}
oninput={(e) => updateAccessibility({ fontSize: rangeValue(e) })}
@@ -72,7 +72,7 @@
<div class="flex flex-col gap-1.5">
<div class="flex justify-between">
<p class="text-[12px] text-text-secondary font-medium">Letter spacing</p>
<span class="text-[11px] text-text-tertiary">{prefs.accessibility.letterSpacing.toFixed(2)}em</span>
<span class="text-[12px] text-text-secondary">{prefs.accessibility.letterSpacing.toFixed(2)}em</span>
</div>
<input type="range" min="0" max="0.15" step="0.01" value={prefs.accessibility.letterSpacing}
oninput={(e) => updateAccessibility({ letterSpacing: rangeValue(e) })}
@@ -83,7 +83,7 @@
<div class="flex flex-col gap-1.5">
<div class="flex justify-between">
<p class="text-[12px] text-text-secondary font-medium">Line height</p>
<span class="text-[11px] text-text-tertiary">{prefs.accessibility.lineHeight.toFixed(1)}</span>
<span class="text-[12px] text-text-secondary">{prefs.accessibility.lineHeight.toFixed(1)}</span>
</div>
<input type="range" min="1.3" max="2.2" step="0.1" value={prefs.accessibility.lineHeight}
oninput={(e) => updateAccessibility({ lineHeight: rangeValue(e) })}
@@ -94,7 +94,7 @@
<div class="flex flex-col gap-1.5">
<div class="flex justify-between">
<p class="text-[12px] text-text-secondary font-medium">Transcript font size</p>
<span class="text-[11px] text-text-tertiary">{prefs.accessibility.transcriptSize}px</span>
<span class="text-[12px] text-text-secondary">{prefs.accessibility.transcriptSize}px</span>
</div>
<input type="range" min="16" max="24" step="1" value={prefs.accessibility.transcriptSize}
oninput={(e) => updateAccessibility({ transcriptSize: rangeValue(e) })}

View File

@@ -65,7 +65,7 @@
<button
type="button"
class="energy-chip inline-flex items-center justify-center rounded-md border px-1 {chipSize} text-[10px] font-medium
class="energy-chip inline-flex items-center justify-center rounded-md border px-1 {chipSize} text-[12px] font-medium
{energy === null
? 'opacity-0 group-hover:opacity-100 text-text-tertiary border-border-subtle hover:border-accent hover:text-text-secondary'
: ''}

View File

@@ -198,19 +198,19 @@
>
<span class="sr-only" aria-live="polite">{srStatus}</span>
{#if recording}
<span class="text-[11px] text-text-tertiary italic">Hold Ctrl/Alt/Super + key. Esc to cancel.</span>
<span class="text-[12px] text-text-secondary italic">Hold Ctrl/Alt/Super + key. Esc to cancel.</span>
{:else}
{#each chips as chip, i}
{#if i > 0}
<span class="text-[10px] text-text-tertiary" aria-hidden="true">+</span>
<span class="text-[12px] text-text-secondary" aria-hidden="true">+</span>
{/if}
<span class="px-2 py-0.5 rounded-md bg-bg-elevated border border-border text-[11px] font-medium text-text
<span class="px-2 py-0.5 rounded-md bg-bg-elevated border border-border text-[12px] font-medium text-text
shadow-[inset_0_1px_2px_rgba(0,0,0,0.3)]">{chip}</span>
{/each}
{/if}
</button>
{#if rejectionReason}
<span class="text-[11px] text-warning" role="alert">
<span class="text-[12px] text-warning" role="alert">
Couldn't bind that combo. {rejectionReason}.
</span>
{/if}

View File

@@ -122,13 +122,13 @@
<div class="space-y-5">
<div>
<p class="text-[11px] text-text-tertiary mb-4">
<p class="text-[12px] text-text-secondary mb-4">
Build simple if-then rules. They respect Mute for now in Nudges, and everything stays local.
</p>
<div class="rounded-lg border border-border-subtle bg-bg-input p-4">
<div class="grid grid-cols-1 md:grid-cols-[120px_1fr] gap-3 items-start">
<p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider pt-2">If</p>
<p class="text-[12px] font-medium text-text-secondary uppercase tracking-wider pt-2">If</p>
<div class="flex flex-wrap gap-2">
<select
class="bg-bg border border-border rounded-lg px-3 py-2 text-[12px] text-text focus:border-accent"
@@ -147,7 +147,7 @@
{/if}
</div>
<p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider pt-2">Then</p>
<p class="text-[12px] font-medium text-text-secondary uppercase tracking-wider pt-2">Then</p>
<div class="space-y-3">
<div class="flex flex-col gap-2">
<Toggle
@@ -188,7 +188,7 @@
/>
<div>
<label for="rule-speak-line" class="block text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">
<label for="rule-speak-line" class="block text-[12px] font-medium text-text-secondary uppercase tracking-wider mb-2">
Speak aloud
</label>
<input
@@ -204,7 +204,7 @@
</div>
{#if error}
<p class="text-[11px] text-danger mt-3">{error}</p>
<p class="text-[12px] text-danger mt-3">{error}</p>
{/if}
<div class="flex justify-end mt-4">
@@ -224,11 +224,11 @@
</div>
<div>
<p class="text-[10px] font-medium text-text-tertiary uppercase tracking-wider mb-2">Saved rules</p>
<p class="text-[12px] font-medium text-text-secondary uppercase tracking-wider mb-2">Saved rules</p>
{#if loading}
<p class="text-[11px] text-text-tertiary">Loading…</p>
<p class="text-[12px] text-text-secondary">Loading…</p>
{:else if implementationRules.length === 0}
<p class="text-[11px] text-text-tertiary italic">No rules yet.</p>
<p class="text-[12px] text-text-secondary italic">No rules yet.</p>
{:else}
<div class="space-y-2">
{#each implementationRules as rule (rule.id)}

View File

@@ -45,7 +45,7 @@
></span>
{:else}
<span
class="inline-flex items-center gap-1.5 px-2 py-[3px] rounded-full bg-bg-elevated border border-border-subtle text-[10px] text-text-secondary whitespace-nowrap"
class="inline-flex items-center gap-1.5 px-2 py-[3px] rounded-full bg-bg-elevated border border-border-subtle text-[12px] text-text-secondary whitespace-nowrap"
title={llmStatus.detail ?? label}
>
<span class="inline-block w-[6px] h-[6px] rounded-full {dotClass}"></span>

View File

@@ -193,13 +193,13 @@
<div class="pl-6 mt-1 flex flex-col gap-1">
{#if loading}
<div class="flex items-center gap-2 text-[12px] text-text-tertiary py-1">
<div class="flex items-center gap-2 text-[12px] text-text-secondary py-1">
<Loader2 size={12} class="animate-spin" aria-hidden="true" />
Loading steps…
</div>
{:else if subtasks.length === 0 && !error}
<button
class="flex items-center gap-1.5 text-[12px] text-text-tertiary hover:text-accent py-1 disabled:opacity-50"
class="flex items-center gap-1.5 text-[12px] text-text-secondary hover:text-accent py-1 disabled:opacity-50"
onclick={decompose}
disabled={decomposing}
aria-label="Break down this task into micro-steps"
@@ -213,7 +213,7 @@
{/if}
</button>
{:else if error}
<p class="text-[11px] text-text-tertiary py-1">{error}</p>
<p class="text-[12px] text-text-secondary py-1">{error}</p>
{:else}
{#each subtasks as step (step.id)}
<div class="flex items-center gap-2 group py-0.5">
@@ -295,7 +295,7 @@
<SpeakerButton text={step.text} label="Read this step aloud" size={10} />
</span>
<button
class="opacity-0 group-hover:opacity-100 flex items-center gap-1 text-[10px] text-text-tertiary hover:text-accent"
class="opacity-0 group-hover:opacity-100 flex items-center gap-1 text-[12px] text-text-secondary hover:text-accent"
onclick={() => startTimer(step.id)}
aria-label="Start 2-minute timer for this step"
style={reduceMotion ? '' : 'transition: opacity var(--duration-ui)'}

View File

@@ -74,7 +74,7 @@
<p class="text-[13px] text-text-secondary mb-1">
Magnotia needs the <span class="font-medium text-text">{modelSize}</span> model to transcribe speech.
</p>
<p class="text-[11px] text-text-tertiary mb-6">
<p class="text-[12px] text-text-secondary mb-6">
{currentModelInfo?.size ?? "?"} · {currentModelInfo?.accuracy ?? "?"} accuracy · 100% offline
</p>
@@ -104,7 +104,7 @@
<p class="text-[12px] text-danger mt-3">{error}</p>
{/if}
<p class="text-[10px] text-text-tertiary mt-5">
<p class="text-[12px] text-text-secondary mt-5">
Models are cached locally. No data leaves your machine.
</p>
</div>

View File

@@ -281,7 +281,7 @@
<div class="flex-1 overflow-y-auto px-6 pb-3 min-h-0">
{#if loading}
<p class="text-[12px] text-text-tertiary py-6 text-center">Loading your list…</p>
<p class="text-[12px] text-text-secondary py-6 text-center">Loading your list…</p>
{:else}
<ul class="flex flex-col gap-1.5">
{#each tasks as task (task.id)}
@@ -317,7 +317,7 @@
<div class="px-6 pb-5 pt-2">
<p
class="text-[11px] mb-3 min-h-[16px] transition-colors
class="text-[12px] mb-3 min-h-[16px] transition-colors
{tooManyFlash ? 'text-warning' : 'text-text-tertiary'}"
aria-live="polite"
>
@@ -332,7 +332,7 @@
<div class="flex items-center justify-between gap-3">
<button
type="button"
class="px-3 py-2 text-[12px] text-text-tertiary hover:text-text"
class="px-3 py-2 text-[12px] text-text-secondary hover:text-text"
onclick={skipForToday}
disabled={applying}
>

View File

@@ -6,7 +6,7 @@
{#each options as option}
<button
class="rounded-lg font-medium
{size === 'small' ? 'px-2.5 py-1 text-[11px]' : 'px-3.5 py-[6px] text-[12px]'}
{size === 'small' ? 'px-2.5 py-1 text-[12px]' : 'px-3.5 py-[6px] text-[12px]'}
{value === option
? 'bg-accent text-bg shadow-[0_1px_4px_rgba(214,132,80,0.3)]'
: 'text-text-secondary hover:text-text hover:bg-hover'}"

View File

@@ -58,7 +58,7 @@
<div class="flex-1">
<p class="text-sm text-text font-semibold">{title}</p>
{#if description}
<p class="text-[11px] text-text-tertiary tracking-wide mt-1">{description}</p>
<p class="text-[12px] text-text-secondary tracking-wide mt-1">{description}</p>
{/if}
</div>
</summary>

View File

@@ -39,12 +39,12 @@
<!-- Header -->
<div class="flex items-center gap-2 px-4 pt-4 pb-3">
<h3 class="text-[13px] font-semibold text-text">Tasks</h3>
<span class="text-[10px] px-1.5 py-0.5 rounded-full bg-bg-elevated text-text-tertiary">
<span class="text-[12px] px-1.5 py-0.5 rounded-full bg-bg-elevated text-text-secondary">
{taskCount}
</span>
<div class="flex-1"></div>
<button
class="text-[11px] text-text-tertiary hover:text-accent"
class="text-[12px] text-text-secondary hover:text-accent"
onclick={() => page.current = "tasks"}
>View all</button>
<button
@@ -74,7 +74,7 @@
<!-- Task list -->
<div class="flex-1 overflow-y-auto px-3 pb-3 min-h-0">
{#if activeTasks.length === 0}
<p class="text-[11px] text-text-tertiary text-center py-6 opacity-60">No active tasks</p>
<p class="text-[12px] text-text-secondary text-center py-6 opacity-60">No active tasks</p>
{:else}
<div class="flex flex-col gap-0.5">
{#each activeTasks as task (task.id)}
@@ -87,7 +87,7 @@
onclick={() => completeTask(task.id)}
aria-label="Complete task"
></button>
<span class="text-[11px] text-text leading-snug flex-1 min-w-0">{task.text}</span>
<span class="text-[12px] text-text leading-snug flex-1 min-w-0">{task.text}</span>
<span class="w-2 h-2 rounded-full mt-1 flex-shrink-0 {BUCKET_DOT_COLORS[task.bucket] || 'bg-text-tertiary'}"></span>
</div>
{/each}

View File

@@ -83,7 +83,7 @@
<div class="flex-1 min-w-0">
<p class="text-[13px] text-text leading-tight">{label}</p>
{#if description}
<p class="text-[11px] text-text-tertiary mt-0.5 leading-snug">{description}</p>
<p class="text-[12px] text-text-secondary mt-0.5 leading-snug">{description}</p>
{/if}
</div>
</div>

View File

@@ -182,7 +182,7 @@
</button>
<!-- Timestamp -->
{#if showTimestamps}
<span class="text-[10px] text-text-tertiary tabular-nums flex-shrink-0 mt-0.5 min-w-[36px]">
<span class="text-[12px] text-text-secondary tabular-nums flex-shrink-0 mt-0.5 min-w-[36px]">
{formatTime(seg.start)}
</span>
{/if}

View File

@@ -60,7 +60,7 @@
<!-- Active tasks (WIP-limited) -->
{#if visibleTasks.length === 0}
<p class="text-[12px] text-text-tertiary text-center py-4">No active tasks</p>
<p class="text-[12px] text-text-secondary text-center py-4">No active tasks</p>
{:else}
<div class="flex flex-col gap-1">
{#each visibleTasks as task (task.id)}
@@ -105,7 +105,7 @@
{/if}
</button>
<button
class="text-text-tertiary hover:text-danger opacity-0 group-hover:opacity-100 text-[11px]"
class="text-text-secondary hover:text-danger opacity-0 group-hover:opacity-100 text-[12px]"
onclick={() => deleteTask(task.id)}
aria-label="Delete task"
>
@@ -124,7 +124,7 @@
<!-- Overflow -->
{#if hasOverflow}
<button
class="flex items-center gap-1.5 text-[11px] text-text-tertiary hover:text-text-secondary px-3"
class="flex items-center gap-1.5 text-[12px] text-text-secondary hover:text-text-secondary px-3"
onclick={() => showOverflow = !showOverflow}
>
<ChevronDown size={12} class="transform {showOverflow ? 'rotate-180' : ''}" aria-hidden="true"
@@ -146,7 +146,7 @@
<!-- WIP indicator -->
{#if activeTasks.length > 0}
<p class="text-[10px] text-text-tertiary text-right">
<p class="text-[12px] text-text-secondary text-right">
{Math.min(activeTasks.length, wipLimit)}/{wipLimit} active
</p>
{/if}

View File

@@ -29,7 +29,7 @@
aria-pressed={prefs.zone === zone.id || (zone.id === 'default' && !prefs.zone)}
>
<div class="w-8 h-8 rounded-lg {zone.swatch} border border-border-subtle"></div>
<span class="text-[11px] text-text-secondary">{zone.label}</span>
<span class="text-[12px] text-text-secondary">{zone.label}</span>
</button>
{/each}
</div>