diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 9d641e4..5d81105 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -10,7 +10,6 @@ "footer_tech": "Open Source OCR running in your browser. Using {ocrs} and {onnx}.", "footer_github": "GitHub", "nav_privacy": "Privacy", - "nav_mon_heritage": "Vulnerable Language", "about_title": "About MonOCR", "about_vulnerable": "Mon (mnw) is my mother tongue. It is currently classified as a vulnerable language by UNESCO.", "about_digital_presence": "The biggest challenge is the lack of digital presence for Mon. This makes AI development difficult since most texts are in scanned books.", @@ -92,7 +91,6 @@ "docs_governance": "Governance", "docs_governance_privacy": "Privacy Policy", "docs_governance_license": "MIT License", - "docs_governance_contributors": "Contributors", "docs_hero_title": "Academic-grade Inference", "docs_hero_desc": "High-performance, private, and localized optical character recognition framework optimized for archival language preservation.", "docs_install_title": "Installation", @@ -109,7 +107,6 @@ "docs_cli_desc": "Batch processing for historical archives.", "docs_privacy_guarantee": "Local recognition guarantee. Data integrity is maintained on-device. No manuscript information ever leaves your environment.", "docs_license_desc": "Open-source governance for research and preservation project. You are free to use and modify the engine for any purpose.", - "docs_contributors_title": "Core Contributors", "docs_footer_prev": "Workspace", "docs_footer_next": "Feedback Service" } diff --git a/apps/web/messages/mnw.json b/apps/web/messages/mnw.json index c59e19e..3592aba 100644 --- a/apps/web/messages/mnw.json +++ b/apps/web/messages/mnw.json @@ -10,7 +10,6 @@ "footer_tech": "ဒှ် Open Source သွက်ဂွံစကာအာ ပ္ဍဲကဵု browser။ စကာလဝ် {ocrs} ကဵု {onnx}။", "footer_github": "GitHub", "nav_privacy": "ပရောပူဂဵု တင်မဒးဂိုင်ဒေပ်ပၞုက်လဝ်", - "nav_mon_heritage": "ဘာသာ မဒးမင်မွဲ", "about_title": "ပရော MonOCR", "about_vulnerable": "ဘာသာမန် (mnw) ဂှ် ဒှ်အရေဝ်မိအဲရ။ ပ္ဍဲအခိင်လၟုဟ် ညးစကာအောန်စှ်ေကၠုင်တုဲ UNESCO ဟီုလဝ် ဒှ်ဘာသာ မဒးမင်မွဲရ။", "about_digital_presence": "ပြဒ္ဒညာဇၞော်အိုတ်ဂှ် ပ္ဍဲကဵုလောက ဒစ်ဂျစ်တယ်ဂှ် လိခ်မန်ပိုဲ နွံအောန်ကွေဟ်ရ။ ဟိုတ်ဂှ်တုဲ သွက်ဂွံပတုဲအာ ကမၠောန် AI ဂှ် ဝါတ်ဂါတ်ဒၟံင်ရ။ လိခ်ပိုဲ ဗွဲမဂၠိုင်ဂှ် နွံဒၟံင် ပ္ဍဲကဵု လိခ်ကၞပ် စကင်န်တအ်ရ။", @@ -92,7 +91,6 @@ "docs_governance": "Governance", "docs_governance_privacy": "Privacy Policy", "docs_governance_license": "MIT License", - "docs_governance_contributors": "Contributors", "docs_hero_title": "Academic-grade Inference", "docs_hero_desc": "High-performance, private, and localized optical character recognition framework optimized for archival language preservation.", "docs_install_title": "Installation", @@ -109,7 +107,6 @@ "docs_cli_desc": "Batch processing for historical archives.", "docs_privacy_guarantee": "Local recognition guarantee. Data integrity is maintained on-device. No manuscript information ever leaves your environment.", "docs_license_desc": "Open-source governance for research and preservation project. You are free to use and modify the engine for any purpose.", - "docs_contributors_title": "Core Contributors", "docs_footer_prev": "Workspace", "docs_footer_next": "Feedback Service" } diff --git a/apps/web/messages/my.json b/apps/web/messages/my.json index c2e42e0..89b5e7a 100644 --- a/apps/web/messages/my.json +++ b/apps/web/messages/my.json @@ -10,7 +10,6 @@ "footer_tech": "ဘရောက်ဇာတွင် အသုံးပြုနိုင်သော Open Source OCR။ {ocrs} နှင့် {onnx} ကို အသုံးပြုထားသည်။", "footer_github": "GitHub", "nav_privacy": "ကိုယ်ရေးလုံခြုံမှု", - "nav_mon_heritage": "ထိန်းသိမ်းရန် လိုအပ်သော ဘာသာစကား", "about_title": "မွန် OCR အကြောင်း", "about_vulnerable": "မွန်ဘာသာစကား (mnw) သည် ကျွန်ုပ်၏ မိခင်ဘာသာစကား ဖြစ်သည်။ လက်ရှိတွင် UNESCO မှ ထိန်းသိမ်းရန် လိုအပ်သော ဘာသာစကားအဖြစ် သတ်မှတ်ထားသည်။", "about_digital_presence": "အကြီးမားဆုံး စိန်ခေါ်မှုမှာ မွန်ဘာသာစကား၏ ဒစ်ဂျစ်တယ် တည်ရှိမှု နည်းပါးခြင်းဖြစ်သည်။ ထို့ကြောင့် AI ဖွံ့ဖြိုးတိုးတက်မှုအတွက် ခက်ခဲစေသည်။", @@ -92,7 +91,6 @@ "docs_governance": "စီမံခန့်ခွဲမှု", "docs_governance_privacy": "ကိုယ်ရေးလုံခြုံမှု မူဝါဒ", "docs_governance_license": "MIT လိုင်စင်", - "docs_governance_contributors": "ပါဝင်ကူညီသူများ", "docs_hero_title": "အဆင့်မြင့် OCR အင်ဂျင်", "docs_hero_desc": "မွန်စာပေ ထိန်းသိမ်းရန်အတွက် အထူးပြုလုပ်ထားသော မြန်နှုန်းမြင့် OCR စနစ်။", "docs_install_title": "တပ်ဆင်ခြင်း", @@ -109,7 +107,6 @@ "docs_cli_desc": "ဖိုင်အများအပြားကို တစ်ပြိုင်နက် လုပ်ဆောင်ရန် CLI ကို အသုံးပြုပါ။", "docs_privacy_guarantee": "သင်၏ အချက်အလက်များသည် သင့်စက်ထဲတွင်သာ ရှိနေမည်ဖြစ်ပြီး မည်သည့်နေရာသို့မျှ ပေးပို့ခြင်း မရှိပါ။", "docs_license_desc": "ဤပရောဂျက်သည် Open Source ဖြစ်ပြီး မည်သူမဆို လွတ်လပ်စွာ အသုံးပြုနိုင်ပါသည်။", - "docs_contributors_title": "အဓိက ပါဝင်သူများ", "docs_footer_prev": "အလုပ်နေရာ", "docs_footer_next": "တုံ့ပြန်ချက်စနစ်" } diff --git a/apps/web/src/app.css b/apps/web/src/app.css index 95af672..e1cfe33 100644 --- a/apps/web/src/app.css +++ b/apps/web/src/app.css @@ -28,7 +28,10 @@ /* Professional Productivity Palette - Neutral & Utilitarian */ --primary: #1a1a1a; /* Pure, deep professional gray/black */ --primary-tint: #4338ca; /* Indigo 700 tint for subtle accents */ - --accent-gold: #b2940a; + /* #b2940a computed to 2.85:1 on --bg-canvas -- fails WCAG AA (4.5:1). Darkened for + light mode only; the original value is restored under .dark below, where it + already passes (6.19:1) against the much darker canvas there. */ + --accent-gold: #7a6200; --background-light: #ffffff; --background-dark: #0a0a0a; --color-border-raw: 224, 224, 224; /* RGB for --bg-border */ @@ -36,7 +39,12 @@ /* Text Hierarchy - Softered for Eye Comfort */ --fg-primary: #2a2a2b; /* Soft Deep Gray */ --fg-secondary: #5c5c5e; /* Muted Zinc */ - --fg-muted: #8a8a8c; /* Zinc 500 equivalent */ + /* #8a8a8c computed to 3.33:1 on --bg-canvas -- fails WCAG AA (4.5:1) for normal text, + and this token is used at full size (docs body copy) as well as small/uppercase + labels. Darkened to a value that clears 4.5:1 against both --bg-canvas (5.14:1) + and --bg-canvas-subtle (4.83:1); dark mode's #8e8e93 already passes and is + untouched. */ + --fg-muted: #6b6b6d; --fg-accent: #3a3a3c; /* Zinc 900 equivalent */ /* Buttons/Interactive */ @@ -54,6 +62,9 @@ --bg-canvas-subtle: #1c1c1e; --bg-canvas-glass: rgba(21, 21, 23, 0.8); --bg-border: #222224; + /* Restore the original gold -- it's the light-mode value above that fails contrast, + not this one (6.19:1 against this dark canvas). */ + --accent-gold: #b2940a; --fg-primary: #d1d1d6; --fg-secondary: #8e8e93; --fg-muted: #8e8e93; @@ -89,7 +100,6 @@ --color-accent-gold: var(--accent-gold); --font-display: 'Inter', system-ui, sans-serif; - --font-public-sans: 'Public Sans', system-ui, sans-serif; --color-background: var(--bg-canvas); --color-foreground: var(--fg-primary); @@ -134,11 +144,28 @@ } .btn-primary { - @apply bg-primary-action text-fg-on-primary inline-flex items-center justify-center rounded-[var(--radius-lg)] px-5 py-2.5 text-[11px] font-semibold tracking-[0.05em] uppercase transition-all duration-150 ease-out hover:brightness-110 active:scale-[0.98]; + @apply bg-primary-action text-fg-on-primary inline-flex items-center justify-center rounded-[var(--radius-lg)] border border-transparent px-5 py-2.5 text-[11px] font-semibold tracking-[0.05em] uppercase transition-all duration-150 ease-out hover:brightness-110 active:scale-[0.98] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50; } .btn-secondary { - @apply border-border bg-btn-bg text-fg-secondary dark:text-fg-primary hover:bg-btn-hover hover:text-fg-primary inline-flex items-center justify-center rounded-[var(--radius-lg)] border px-4 py-2.5 text-[11px] font-semibold tracking-[0.05em] uppercase transition-all duration-150 ease-out active:scale-[0.98]; + @apply border-border bg-btn-bg text-fg-secondary dark:text-fg-primary hover:bg-btn-hover hover:text-fg-primary inline-flex items-center justify-center rounded-[var(--radius-lg)] border px-4 py-2.5 text-[11px] font-semibold tracking-[0.05em] uppercase transition-all duration-150 ease-out active:scale-[0.98] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50; + } + + /* A real compact variant, not a utility-class override: .btn-primary/.btn-secondary's + own padding is @apply'd in this same layer, so a call site adding `px-3 py-1` on top + loses the cascade -- later-in-layer wins at equal specificity, regardless of source + order in the markup. Combine with .btn-primary/.btn-secondary instead of overriding. */ + .btn-compact { + @apply px-3 py-1.5; + } + + /* Same cascade issue as .btn-compact above, caught by a verifier on ConfirmationModal's + destructive button: `border-red-500 bg-red-500` layered on top of .btn-primary lost to + its own @apply'd background, so the button rendered near-black instead of red -- + undercutting the one signal that a confirm action is irreversible. A real modifier, + defined after .btn-primary in this same layer, wins the cascade instead of losing it. */ + .btn-danger { + @apply border-red-500 bg-red-500 hover:bg-red-600; } } @@ -252,11 +279,17 @@ body { } .section-label { - @apply mb-4 block text-[9px] font-bold tracking-[0.3em] text-slate-400 uppercase dark:text-slate-400; + /* Was hardcoded text-slate-400 in both themes (2.48:1 on light canvas, failing WCAG AA) + -- text-fg-muted is theme-aware and, with --fg-muted's light-mode value corrected + above, now clears 4.5:1 in both themes. */ + @apply text-fg-muted mb-4 block text-[9px] font-bold tracking-[0.3em] uppercase; } .zen-label { - @apply text-fg-muted/50 text-[10px] font-bold tracking-[0.2em] uppercase; + /* Was text-fg-muted/50 (1.72:1 on light canvas at this token's old value, and opacity + alone drops any color below AA regardless of the base -- dropped the opacity instead + of chasing it with an ever-darker base color). */ + @apply text-fg-muted text-[10px] font-bold tracking-[0.2em] uppercase; } .zen-code-block { @@ -265,7 +298,9 @@ body { /* Improved Syntax Highlighting */ .zen-code-comment { - @apply text-fg-muted/40 italic; + /* Was text-fg-muted/40 (well under 3:1) -- italic already differentiates comments from + code without needing a contrast-failing opacity cut on top. */ + @apply text-fg-muted italic; } .zen-code-keyword { @@ -360,26 +395,3 @@ label { animation: shimmer 1.5s infinite linear; will-change: background-position; } - -@keyframes spin-slow { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -.animate-spin-slow { - animation: spin-slow 3s linear infinite; -} - -/* Material Symbols - Minimalist & Elegant */ -.material-symbols-outlined { - font-variation-settings: - 'FILL' 0, - 'wght' 300, - 'GRAD' 0, - 'opsz' 20 !important; - display: inline-block; -} diff --git a/apps/web/src/lib/actions/focus-trap.ts b/apps/web/src/lib/actions/focus-trap.ts index 6f9d322..80e41bb 100644 --- a/apps/web/src/lib/actions/focus-trap.ts +++ b/apps/web/src/lib/actions/focus-trap.ts @@ -6,8 +6,17 @@ * - Focus Restoration: Returns focus to previous element on destroy. * - Dynamic Support: Uses MutationObserver to handle content changes. * - Safety: Guarded against empty sets. + * - Escape-to-close: an optional `onEscape` callback, called on Escape. + * + * Escape handling lives here, not on each modal's backdrop element. Focus + * moves inside this node as soon as the trap activates, so a keydown + * listener on a backdrop `
+
{message}
+
{m.footer_copy({ year: new Date().getFullYear().toString() })}
-+
{m.footer_tech({ ocrs: 'MobileNetV3+BiLSTM', onnx: 'ONNX Runtime Web' })}
- Our architecture aligns with the **General Data Protection Regulation (GDPR)** and the - **California Consumer Privacy Act (CCPA)** by providing users with full access and - erasure rights over their local data. + Our architecture aligns with the + General Data Protection Regulation (GDPR) and the + California Consumer Privacy Act (CCPA) by providing users with full access + and erasure rights over their local data.
@@ -151,7 +151,7 @@ "{originalText}"