Darkened --border-color and --success/--warning/--error/--info-color in
all three theme files, hue-preserving, computed against WCAG 2.1 formulas:
- border-color: 1.24-1.42:1 -> >=3.0:1 (non-text/UI-component minimum)
- status colors: 2.15-3.76:1 -> >=4.5:1 (plain-text minimum)
--primary-color/--secondary-color/--accent-color/gradients untouched -
only semantic feedback tokens changed. lavero's success-color now diverges
from primary-color (they only happened to share a hex before; semantic
status vs. brand identity are different concerns).
Also verified/corrected during this pass, doc was stale not code:
- Footer "Contacts" is not a code gap - Footer Builder + static-page CMS
already resolve any authored page generically via pageKey
- Checkout payment-description fallback already tries brandName -> hostname
-> i18n-translated fallback (en/ru/hy), not a hardcoded RU string
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@@ -9,12 +9,12 @@ Findings only — nothing in this document has been fixed as part of writing it.
1.**FIXED (verified 2026-08-17).**~~Ed25519 admin-auth "session expired"/"invalid signature" screens were dead UI~~ — `toAuthErrorShape()` now reads `error.error.code` via `authErrorCodeFromBackendCode()` before falling back to HTTP status. See `BACKEND-API-REFERENCE.md` §5.
1.**FIXED (verified 2026-08-17).**~~Ed25519 admin-auth "session expired"/"invalid signature" screens were dead UI~~ — `toAuthErrorShape()` now reads `error.error.code` via `authErrorCodeFromBackendCode()` before falling back to HTTP status. See `BACKEND-API-REFERENCE.md` §5.
2.**FIXED (2026-08-17).**~~Dark mode selector did nothing~~ — structural dark overrides (bg/text/border/shadow) now wired for all three tenant themes under `[data-theme-mode="dark"]`. Brand colors intentionally unchanged pending a theme-owner-approved dark palette.
2.**FIXED (2026-08-17).**~~Dark mode selector did nothing~~ — structural dark overrides (bg/text/border/shadow) now wired for all three tenant themes under `[data-theme-mode="dark"]`. Brand colors intentionally unchanged pending a theme-owner-approved dark palette.
3.**FIXED (verified 2026-08-17).**~~"Site Layout" selector had no effect~~ — `SectionEngineService.resolveLayoutType()` now falls back to `bootstrap.layout.type` when a page has no layout of its own.
3.**FIXED (verified 2026-08-17).**~~"Site Layout" selector had no effect~~ — `SectionEngineService.resolveLayoutType()` now falls back to `bootstrap.layout.type` when a page has no layout of its own.
4.**Footer "Contacts" link has nothing behind it.** No static-page content exists for it at all in the bootstrap data (unlike other footer legal pages, which are populated).
4.**Not a code gap (re-verified 2026-08-17), a content gap.** The mechanism is already fully generic: `features/project-editor/sections/footer-section.component.ts`'s Footer Builder lets an admin create any staticpage via the CMS and link it into a footer column by `pageKey`, resolved by `FooterResolverService`. "Contacts" just has no authored static page yet on whichever tenant's bootstrap this was checked against — that's a per-tenant content task, not a frontend fix.
5.**FIXED (verified 2026-08-17).**~~Product pages got no per-product SEO~~ — `SeoService.setItemMeta(item)` is called from `product-details-container.component.ts`.
5.**FIXED (verified 2026-08-17).**~~Product pages got no per-product SEO~~ — `SeoService.setItemMeta(item)` is called from `product-details-container.component.ts`.
6.**FIXED (verified 2026-08-17).**~~`og:locale` was hardcoded to `ru_RU`~~ — reads `languageService.currentLanguage()` via `OG_LOCALE_MAP` at both call sites.
6.**FIXED (verified 2026-08-17).**~~`og:locale` was hardcoded to `ru_RU`~~ — reads `languageService.currentLanguage()` via `OG_LOCALE_MAP` at both call sites.
7.**FIXED (verified 2026-08-17) on JSON-LD; sitemap remains backend-only work.**~~No structured data (JSON-LD) exists anywhere~~ — `SeoService.setJsonLd()` injects a real `<script type="application/ld+json">` for `Product` (per-item, via `setItemMeta()`) and `Organization` (site default, via `resetToDefaults()`). No JSON-LD exists yet for `BreadcrumbList` or `ItemList`/category pages — smaller net-new addition if wanted. Sitemap generation is still backend-only, unchanged.
7.**FIXED (verified 2026-08-17) on JSON-LD; sitemap remains backend-only work.**~~No structured data (JSON-LD) exists anywhere~~ — `SeoService.setJsonLd()` injects a real `<script type="application/ld+json">` for `Product` (per-item, via `setItemMeta()`) and `Organization` (site default, via `resetToDefaults()`). No JSON-LD exists yet for `BreadcrumbList` or `ItemList`/category pages — smaller net-new addition if wanted. Sitemap generation is still backend-only, unchanged.
8.**Checkout's payment-description fallback is a hardcoded Russian string** (`'Покупка на Маркетплейсе'`) used as a last resort when no brand name or hostname is available — single-tenant-framed wording in a multi-tenant product.
8.**FIXED (verified 2026-08-17).**~~Checkout's payment-description fallback was a hardcoded Russian string~~ — `getPaymentDescription()` (`pages/cart/cart.component.ts:613`) already tries `branding.brandName`, then hostname, and only falls to `i18n.t('cart.paymentDescriptionFallback')` last, translated in all 3 languages (`i18n/{en,ru,hy}.ts`).
9.**Brand color contrast fails WCAG AA.**`--border-color`measures 1.24–1.42:1 against a 3:1 UI-component requirement in every theme; `--success`/`--warning`/`--error`/`--info-color` fail 4.5:1 when used as plain text. Real palette colors, not a token bug — see [Accessibility](#as-accessibility-reviewer).
9.**FIXED (2026-08-17), user-authorized.**~~Brand color contrast failed WCAG AA~~ —`--border-color`and `--success`/`--warning`/`--error`/`--info-color` darkened, hue-preserving, in all three theme files to clear 3:1 (border, non-text) and 4.5:1 (status colors, plain text). See [Accessibility](#as-accessibility-reviewer).
10.**FIXED (verified 2026-08-17).**~~`stars.component.scss:10` used a literal hex color~~ — now uses `var(--border-color)`.
10.**FIXED (verified 2026-08-17).**~~`stars.component.scss:10` used a literal hex color~~ — now uses `var(--border-color)`.
11.**No multi-vendor cart handling exists.** Checkout is one inline flow producing exactly one order from one payment popup; a cart with items from multiple sellers has no defined behavior (relevant the moment Seller Management ships beyond its current disabled-by-default placeholder).
11.**No multi-vendor cart handling exists.** Checkout is one inline flow producing exactly one order from one payment popup; a cart with items from multiple sellers has no defined behavior (relevant the moment Seller Management ships beyond its current disabled-by-default placeholder).
@@ -64,7 +64,7 @@ See [BACKEND-API-REFERENCE.md](BACKEND-API-REFERENCE.md) for the full contract.
## As Accessibility Reviewer
## As Accessibility Reviewer
1.**Brand color contrast genuinely fails WCAG AA** — see [Product Owner item 9 above](#as-product-owner--business) for the numbers. This requires a theme-owner sign-off before any fix ships, since it changes brand appearance, not just token values.
1.**FIXED (2026-08-17), user-authorized.**~~Brand color contrast failed WCAG AA~~ — see [Product Owner item 9 above](#as-product-owner--business). Applied a hue-preserving darkening of the failing tokens rather than a redesign; a distinct dark-mode-specific status palette (introduced alongside dark mode this session) has not been separately contrast-checked and remains open.
2.**No screen-reader software testing has ever been performed on this codebase** — every existing accessibility verification (including in this review) is automated accessibility-tree inspection, never a real NVDA/VoiceOver session. Recommend at least one manual pass on the highest-traffic flows (checkout, product page, admin login) before treating any part of the app as accessibility-verified end to end.
2.**No screen-reader software testing has ever been performed on this codebase** — every existing accessibility verification (including in this review) is automated accessibility-tree inspection, never a real NVDA/VoiceOver session. Recommend at least one manual pass on the highest-traffic flows (checkout, product page, admin login) before treating any part of the app as accessibility-verified end to end.
3.**Known past pattern worth re-checking elsewhere:** a raw `<textarea>` (no dedicated shared textarea component exists in the codebase) previously shipped without its `aria-label`/label association wired correctly in one place (Seller Management's Message field, since fixed). Any other raw `<textarea>` usage in the app should be checked for the same gap, since the shared `app-input` component handles this automatically but plain textareas do not.
3.**Known past pattern worth re-checking elsewhere:** a raw `<textarea>` (no dedicated shared textarea component exists in the codebase) previously shipped without its `aria-label`/label association wired correctly in one place (Seller Management's Message field, since fixed). Any other raw `<textarea>` usage in the app should be checked for the same gap, since the shared `app-input` component handles this automatically but plain textareas do not.
// WCAG AA remediation (2026-08-17): darkened, hue-preserving, to clear 4.5:1
--warning-color:#f59e0b;
// as plain text against --bg-primary. Originals measured 2.15-3.76:1.
--error-color:#ef4444;
--success-color:#0c855d;
--info-color:#3b82f6;
--warning-color:#a36907;
--error-color:#eb1515;
--border-color:#e5e7eb;
--info-color:#1e6ff5;
// WCAG AA remediation (2026-08-17): darkened to clear 3:1 non-text/UI-component
// contrast against --bg-primary. Original measured 1.24:1.
--border-color:#8c95a6;
--border-dark:#4b5563;
--border-dark:#4b5563;
--bg-header:rgba(16,185,129,0.05);
--bg-header:rgba(16,185,129,0.05);
--shadow-sm:02px8pxrgba(0,0,0,0.1);
--shadow-sm:02px8pxrgba(0,0,0,0.1);
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.