-
Light Mode (Alternative)
+
+
Light Mode
+
(Alternative)
Available as alternative but dark mode is strongly preferred
Background Hierarchy: Pure White → Natural Paper → Light Gray → Border Light
@@ -1215,7 +1321,7 @@ document.addEventListener('DOMContentLoaded', () => {
- Iconography System
+ Iconography System
@@ -1556,7 +1662,7 @@ document.addEventListener('DOMContentLoaded', () => {
- Accessibility & Vision Inclusivity
+ Accessibility & Vision Inclusivity
@@ -1578,6 +1684,63 @@ document.addEventListener('DOMContentLoaded', () => {
+
+
+
+
CHORUS 8-Color Accessibility System
+
Our advanced accessibility system remaps the core CHORUS 8-color palette (carbon, mulberry, walnut, nickel, ocean, eucalyptus, sand, coral) to vision-deficiency appropriate alternatives while preserving the light/dark theme toggle functionality.
+
+
+
+
Protanopia (Red-blind)
+
+
• Danger: Ocean → Coral
+
• Success: Sand → Eucalyptus
+
• Warning: Nickel → Sand
+
• Preserves: Carbon, Mulberry, Walnut
+
+
+
+
+
Deuteranopia (Green-blind)
+
+
• Success: Ocean → Eucalyptus
+
• Info: Sand → Ocean
+
• Accent: Coral → Walnut
+
• Enhances: Blue/yellow contrast
+
+
+
+
+
Tritanopia (Blue-blind)
+
+
• Info: Coral → Ocean
+
• Warning: Eucalyptus → Sand
+
• Primary: Mulberry → Carbon
+
• Maintains: Red/green clarity
+
+
+
+
+
Achromatopsia (Monochrome)
+
+
• Pure grayscale system
+
• Brightness hierarchy preserved
+
• Contrast ratios maintained
+
• Texture-based differentiation
+
+
+
+
+
+
Technical Implementation
+
+
The system uses CSS semantic tokens with compound selectors that combine light/dark themes with accessibility modes:
+
.dark[data-accessibility="protanopia"] { --chorus-danger: var(--chorus-info); }
+
This preserves your existing theme toggle while providing vision-inclusive alternatives.
+
+
+
Supported Vision Conditions
@@ -1794,22 +1957,10 @@ setAccessibilityTheme('protanopia');
-
-
- Web Design System
- Interactive demonstration of the CHORUS web design system, including typography, components, forms, and styling patterns.
-
-
-
The web design components and interactive examples have been preserved in the original playground file for full testing and evaluation.
-
-
-
-
+
- Typography
+ Typography
The CHORUS typography system is designed for clarity, hierarchy, and accessibility across all devices.
@@ -1845,6 +1996,49 @@ setAccessibilityTheme('protanopia');
Muted Link
+
+
+
+
Font Sizes
+
+
Extra Small (12px)
+
Small (14px)
+
Base (16px)
+
Large (18px)
+
Extra Large (20px)
+
+ 2X Large (24px)
+
+
+ 3X Large (30px)
+
+
+ 4X Large (36px)
+
+
+ 5X Large (48px)
+
+
+
+
+
+
+
Font Weights
+
+
Thin (100)
+
+
Light (300)
+
Normal (400)
+
Medium (500)
+
Semi Bold (600)
+
Bold (700)
+
+
Black (900)
+
+
+
+
+
@@ -1972,30 +2166,33 @@ setAccessibilityTheme('protanopia');
Color Vision Support
+
+ 8-color CHORUS system adaptations that preserve brand integrity while ensuring accessibility
+
Standard Vision
- Default metallic appearance
+ Default CHORUS 8-color palette
Protanopia (Red-blind)
- Enhanced blue/yellow contrast
+ Ocean replaces coral, sand replaces eucalyptus
Deuteranopia (Green-blind)
- Blue/purple dominance patterns
+ Ocean replaces eucalyptus, coral becomes accent
Tritanopia (Blue-blind)
- Red/green clarity focus
+ Coral replaces ocean, eucalyptus replaces sand
Achromatopsia (Complete color blindness)
- High-contrast monochrome
+ Grayscale system preserving contrast hierarchy
@@ -2023,24 +2220,14 @@ setAccessibilityTheme('protanopia');
// Function to update ring material based on theme
- function updateRingMaterial(isDark) {
- if (mobius) {
- const targetMaterial = isDark ? darkMaterial : lightMaterial;
- mobius.traverse((child) => {
- if (child.isMesh) {
- child.material = targetMaterial;
- }
- });
- }
- }
+ // Removed obsolete updateRingMaterial function - now handled by logo.js module
// Theme toggle (defaults to dark mode)
const toggle = document.getElementById('toggleTheme');
toggle?.addEventListener('click', () => {
const root = document.documentElement;
const isDark = root.classList.toggle('dark');
- root.setAttribute('data-theme', isDark ? 'dark' : 'light');
- updateRingMaterial(isDark);
+ // Note: Don't set data-theme here as it conflicts with accessibility themes
console.log('Theme toggled to:', isDark ? 'dark' : 'light');
console.log('updateAllLogoMaterials function available:', typeof window.updateAllLogoMaterials);
@@ -2066,24 +2253,27 @@ setAccessibilityTheme('protanopia');
function setAccessibilityTheme(themeName) {
console.log(`Setting accessibility theme: ${themeName}`);
- // Remove any existing data-theme attribute
- document.documentElement.removeAttribute('data-theme');
+ // Remove any existing accessibility attributes
+ document.documentElement.removeAttribute('data-theme'); // For logo materials
+ document.documentElement.removeAttribute('data-accessibility'); // For CSS system
// Set new theme if not standard vision
if (themeName !== 'standard') {
- document.documentElement.setAttribute('data-theme', themeName);
+ document.documentElement.setAttribute('data-theme', themeName); // Logo materials
+ document.documentElement.setAttribute('data-accessibility', themeName); // CSS system
}
// Store preference
localStorage.setItem('chorus-accessibility-theme', themeName);
- // Update logo materials if available
- if (window.updateLogoAccessibilityTheme) {
+ // Force update logo materials immediately - call the update function directly
+ const isDark = document.documentElement.classList.contains('dark');
+ if (window.updateAllLogoMaterials) {
try {
- window.updateLogoAccessibilityTheme(themeName);
- console.log('updateLogoAccessibilityTheme completed successfully');
+ window.updateAllLogoMaterials(isDark);
+ console.log('updateAllLogoMaterials called after accessibility theme change');
} catch (error) {
- console.error('Error calling updateLogoAccessibilityTheme:', error);
+ console.error('Error calling updateAllLogoMaterials after accessibility change:', error);
}
} else {
console.warn('updateLogoAccessibilityTheme not available - logo.js may not be loaded yet');
diff --git a/brand-assets/logo.js b/brand-assets/logo.js
index 9f55ab9..8dd5f1d 100644
--- a/brand-assets/logo.js
+++ b/brand-assets/logo.js
@@ -8,6 +8,7 @@ const logoInstances = new Map();
// Define materials for both themes and accessibility modes
let darkMaterial, lightMaterial;
let accessibilityMaterials = {};
+let accessibilityMaterialsDark = {};
// Animation parameters (now in an object for GUI control)
const params = {
@@ -62,60 +63,113 @@ function createMaterials() {
envMapIntensity: 0.8,
});
- // Accessibility materials for different color blindness types
+ // CHORUS 8-Color Accessibility Materials - Matching CSS system
accessibilityMaterials.protanopia = new THREE.MeshPhysicalMaterial({
- color: 0x1e40af, // Blue-800 for protanopia (red-blind)
+ color: 0x2a3441, // ocean-950 (matching --chorus-danger for protanopia)
roughness: 0.26,
metalness: 0.95,
clearcoat: 0.5,
clearcoatRoughness: 0.14,
reflectivity: 1.1,
sheen: 0.3,
- sheenColor: new THREE.Color(0xca8a04), // Yellow-600
+ sheenColor: new THREE.Color(0x473e2f), // sand-950 (matching --chorus-success for protanopia)
sheenRoughness: 0.18,
envMapIntensity: 0.9,
});
accessibilityMaterials.deuteranopia = new THREE.MeshPhysicalMaterial({
- color: 0x6b21a8, // Purple-800 for deuteranopia (green-blind)
+ color: 0x2a3441, // ocean-950 (matching --chorus-success for deuteranopia)
roughness: 0.25,
metalness: 0.96,
clearcoat: 0.49,
clearcoatRoughness: 0.13,
reflectivity: 1.15,
sheen: 0.32,
- sheenColor: new THREE.Color(0x3b82f6), // Blue-500
+ sheenColor: new THREE.Color(0x2e1d1c), // coral-950 (matching --chorus-accent for deuteranopia)
sheenRoughness: 0.17,
envMapIntensity: 0.92,
});
accessibilityMaterials.tritanopia = new THREE.MeshPhysicalMaterial({
- color: 0x991b1b, // Red-800 for tritanopia (blue-blind)
+ color: 0x2e1d1c, // coral-950 (matching --chorus-info for tritanopia)
roughness: 0.27,
metalness: 0.94,
clearcoat: 0.51,
clearcoatRoughness: 0.15,
reflectivity: 1.05,
sheen: 0.28,
- sheenColor: new THREE.Color(0x16a34a), // Green-600
+ sheenColor: new THREE.Color(0x2a3330), // eucalyptus-950 (matching --chorus-warning for tritanopia)
sheenRoughness: 0.19,
envMapIntensity: 0.88,
});
accessibilityMaterials.achromatopsia = new THREE.MeshPhysicalMaterial({
- color: 0x374151, // Gray-700 for achromatopsia (complete color blindness)
+ color: 0x111111, // Almost black (matching --chorus-danger for achromatopsia)
roughness: 0.3,
metalness: 0.9,
clearcoat: 0.45,
clearcoatRoughness: 0.16,
reflectivity: 1.0,
sheen: 0.25,
- sheenColor: new THREE.Color(0x6b7280), // Gray-500
+ sheenColor: new THREE.Color(0x444444), // Dark medium (matching --chorus-info for achromatopsia)
sheenRoughness: 0.2,
envMapIntensity: 0.85,
});
- console.log("Materials created including accessibility variants");
+ // Create dark mode variants for accessibility materials
+ accessibilityMaterialsDark.protanopia = new THREE.MeshPhysicalMaterial({
+ color: 0xcbefff, // ocean-50 (matching dark mode --chorus-danger for protanopia)
+ roughness: 0.24,
+ metalness: 1.0,
+ clearcoat: 0.48,
+ clearcoatRoughness: 0.15,
+ reflectivity: 1.2,
+ sheen: 0.35,
+ sheenColor: new THREE.Color(0xcee1be), // sand-50 (matching dark mode --chorus-success for protanopia)
+ sheenRoughness: 0.168,
+ envMapIntensity: 1,
+ });
+
+ accessibilityMaterialsDark.deuteranopia = new THREE.MeshPhysicalMaterial({
+ color: 0xcbefff, // ocean-50 (matching dark mode --chorus-success for deuteranopia)
+ roughness: 0.24,
+ metalness: 1.0,
+ clearcoat: 0.48,
+ clearcoatRoughness: 0.15,
+ reflectivity: 1.2,
+ sheen: 0.35,
+ sheenColor: new THREE.Color(0xffd6d6), // coral-50 (matching dark mode --chorus-accent for deuteranopia)
+ sheenRoughness: 0.168,
+ envMapIntensity: 1,
+ });
+
+ accessibilityMaterialsDark.tritanopia = new THREE.MeshPhysicalMaterial({
+ color: 0xffd6d6, // coral-50 (matching dark mode --chorus-info for tritanopia)
+ roughness: 0.24,
+ metalness: 1.0,
+ clearcoat: 0.48,
+ clearcoatRoughness: 0.15,
+ reflectivity: 1.2,
+ sheen: 0.35,
+ sheenColor: new THREE.Color(0xbacfbf), // eucalyptus-50 (matching dark mode --chorus-warning for tritanopia)
+ sheenRoughness: 0.168,
+ envMapIntensity: 1,
+ });
+
+ accessibilityMaterialsDark.achromatopsia = new THREE.MeshPhysicalMaterial({
+ color: 0xeeeeee, // Almost white (matching dark mode --chorus-danger for achromatopsia)
+ roughness: 0.24,
+ metalness: 1.0,
+ clearcoat: 0.48,
+ clearcoatRoughness: 0.15,
+ reflectivity: 1.2,
+ sheen: 0.35,
+ sheenColor: new THREE.Color(0xbbbbbb), // Light medium (matching dark mode --chorus-info for achromatopsia)
+ sheenRoughness: 0.168,
+ envMapIntensity: 1,
+ });
+
+ console.log("Materials created including accessibility variants and dark mode variants");
}
function initLogo(canvas) {
@@ -257,16 +311,27 @@ function initLogo(canvas) {
function updateCanvasMaterial(mobius, isDark) {
if (mobius) {
- // Check for accessibility theme first
- const accessibilityTheme = document.documentElement.getAttribute('data-theme');
+ // Check for accessibility theme first (both data-theme for legacy and data-accessibility for new system)
+ const accessibilityTheme = document.documentElement.getAttribute('data-accessibility') ||
+ document.documentElement.getAttribute('data-theme');
let targetMaterial;
- if (accessibilityTheme && accessibilityMaterials[accessibilityTheme]) {
- targetMaterial = accessibilityMaterials[accessibilityTheme];
- console.log(`Updating material to accessibility theme: ${accessibilityTheme}`);
+ if (accessibilityTheme && accessibilityTheme !== 'standard') {
+ // Choose accessibility material based on light/dark mode
+ const accessibilityMaterialSet = isDark ? accessibilityMaterialsDark : accessibilityMaterials;
+
+ if (accessibilityMaterialSet[accessibilityTheme]) {
+ targetMaterial = accessibilityMaterialSet[accessibilityTheme];
+ console.log(`Updating material to ${isDark ? 'dark' : 'light'} accessibility theme: ${accessibilityTheme}`);
+ } else {
+ // Fallback to standard materials
+ targetMaterial = isDark ? darkMaterial : lightMaterial;
+ console.log(`Accessibility material not found for ${accessibilityTheme}, using standard ${isDark ? 'dark' : 'light'} material`);
+ }
} else {
+ // Standard materials
targetMaterial = isDark ? darkMaterial : lightMaterial;
- console.log(`Updating material to:`, isDark ? 'dark' : 'light', 'material color:', targetMaterial.color.getHex().toString(16));
+ console.log(`Updating material to standard:`, isDark ? 'dark' : 'light', 'material color:', targetMaterial.color.getHex().toString(16));
}
let meshCount = 0;