Skip to main content
Auric Artisan · Documentation

Color Blindness Simulator Developer Reference

Architecture and maintenance notes for the Color Blindness Simulator: registry records, the Workbench and Palette audit views, mode-aware catalog rendering, floating panels, simulation modules, metrics, verification, and Library capture and restore.

Published: May 24, 2026 Updated: May 24, 2026 Category: Reference Author: Chirag Bansal
Back to Documentation Auric Artisan Home

Overview

The Color Blindness Simulator is a registry-driven ES module workspace. The page opens on a Workbench view that runs the shared model engine directly, renders a catalog from static simulation metadata, opens simulations as in-DOM floating panels, lazy-loads condition modules, routes controls into a shared simulation core, and exposes Library restore through window.AAVisionSim. Most feature work touches the registry, a disease module, panel state, Library binding, and discovery files together.

Table of contents

  1. 1. File map
  2. 2. Page shell and registry
  3. 3. Catalog, modes, and search
  4. 4. Floating panel lifecycle
  5. 5. Simulator panel contract
  6. 6. Models and disease modules
  7. 7. Metrics, appearance, and validation
  8. 8. Library capture and restore
  9. 9. Workbench view
  10. 10. Palette audit view
  11. 11. Extension checklist
  12. 12. Testing and risk notes

1. File map

+
  • Page shell: tool/vision-simulation/index.html provides metadata, hero content, guide surfaces, filters, card hosts, SVG filters, and script imports, plus the view bar host ([data-vlab-navhost]), the Workbench container (#vd-workbench), and the container for the other four views (#vd-app).
  • Page entry: js/tool/vision-deficiency.js renders the scope menu, cards, mode switching, favorites, Open Panels, keyboard shortcuts, and window.AAVisionSim, and lazy-loads the Compare, Palette audit, and Analytics views from js/tool/vision-compare.js, vision-audit.js, and vision-analytics.js. js/tool/vision-workbench.js renders the Workbench view and the view tabs.
  • Gating: js/tool/vision-deficiency-gating.js applies the free daily simulation limit and usage meter around catalog activation; no mode or category is locked.
  • Registry: tool/modules/registry/simulations.js defines the category map, 78 simulation records, model option presets, complexity values, and lazy module paths.
  • Condition facts: tool/modules/registry/condition-facts.js, generated by scripts/generate-condition-facts.mjs, is the Node-safe list of all 78 conditions with severity score, summary, prevalence, color or spatial transform, and baked preview. The Workbench, the Palette audit, the catalog cards, and the API read it.
  • Workbench support: js/tool/vision-field-effects.js holds the field families shared by the Workbench stage and the catalog card, and js/tool/vision-url-state.js writes the shareable #v= hash, including the current view.
  • Floating panels: tool/modules/floating/panel-manager.js, floating-panel.js, panel-state.js, panel-extensions.js, control-center.js, and verification-panel.js manage the workspace.
  • Core: tool/modules/core/simulation-core.js mounts the standard simulator UI, while engine.js provides the model registry.
  • Models: tool/modules/models/register-all.js registers CVD matrix, cone isolation, grayscale, inversion, rod vision, tint, and spectral model handlers.
  • Diseases: tool/modules/diseases/*.js export condition-specific diseaseConfig objects and math functions.
  • Library binding: js/library/tool-bindings.js captures and restores Color Blindness Simulator assets under tool id vision-simulation.
  • Styles: css/vision-deficiency.css, vision-panel.css, vision-universal.css, and vision-workbench.css own the workspace-specific surfaces with shared support from analyzer, color science, unified, dark mode, and legal CSS.

2. Page shell and registry

+

The registry is the source of truth for what the page can show and what a panel can open. The page does not hard-code the full catalog; it asks the registry for categories and filtered simulation records.

  • Counts: the current registry contains 78 simulations, 11 categories, 17 Basic simulations, and 61 Advanced simulations.
  • Category keys: color-vision, cone-isolation, ocular-conditions, retinal-dystrophies, optic-nerve-disorders, corneal-anterior-segment, perceptual-effects, vascular-retinal, vitreous-structural, developmental-congenital, and functional-aging.
  • Record fields: each simulation has slug, name, category, prefix, complexity, optional models, legacyHref, and modulePath.
  • Model presets: CVD panels can expose Brettel (1997), Vienot (1999), and Machado-like choices. Cataract exposes yellow brunescence, sclerotic haze, and combined modes.
  • Helpers: getSimulation(), listSimulations(), listAllCategories(), listSimulationsByCategory(), filterByComplexity(), and loadDiseaseConfig() isolate catalog access.
  • Lazy import: loadDiseaseConfig(slug) imports the disease module only when a panel is opened.

3. Catalog, modes, and search

+
  • Entry state: js/tool/vision-deficiency.js stores active category, favorites, recents, guide dismissal, and the current complexity mode in localStorage-backed state.
  • Special tabs: __all__, __favorites__, __compare__, __audit__, __analytics__, __image__, and __open__ route the page into non-category views.
  • Search: card filtering is debounced by 120 ms and checks each card's text: name, category, description, and its kind, complexity, and prevalence tags.
  • Mode bridge: getComplexityMode(), setComplexityMode(), applyModeVisibility(), and watchModeVisibility() keep the page aligned with platform Basic, Advanced, and Both modes.
  • Favorites: favorite slugs live under aa_vd_favorites. Recents live under aa_vd_recents and are capped at 12.
  • Card activation: onCardActivate() calls panelManager.open(sim, { allowDuplicate }). Shift, Ctrl, and Cmd request duplicate panels.
  • Public API: window.AAVisionSim.sims exposes registry data, open(slug) opens a panel, and restoreState(slug, state) reopens and restores a saved panel state.

4. Floating panel lifecycle

+
  • Manager: panel-manager.js creates the host and dock, enforces the five-panel cap, focuses panels, emits aa-vd-panel-change, and persists sessions under aa_vd_session_v1.
  • Open flow: the page resolves the registry record and records recents; then open() evicts an old unpinned panel if needed, creates a panel instance, mounts content, focuses it, and persists session data.
  • Panel actions: close, closeAll, focus, minimize, restore, minimizeAll, restoreAll, maximize, tileAll, cascadeAll, splitHorizontalAll, splitVerticalAll, stackAll, linkAll, and exportComparisonGrid are centralized on the manager; duplicate and pin are per-panel title bar actions.
  • Panel DOM: floating-panel.js builds titlebar, body, resize handle, dock item, lazy module import, simulator template, and deferred initialization without iframes.
  • State: panel-state.js persists key controls under aa_vd_panel_states_v1 and exposes read, write, collect, apply, and delayed save helpers.
  • Extensions: panel-extensions.js adds smart presets, CAM and illuminant controls, snapshots, recent changes, tooltips, and recommended parameters.
  • Control center: control-center.js creates the draggable Vision Control surface with bulk layout, sync, export, verify, and one focus tab per open panel.
  • Verification: verification-panel.js renders a comparison grid, Delta E 2000 chart, refresh, export, and automatic sweep controls.

5. Simulator panel contract

+

Standard simulations are mounted through initializeSimulation(). Disease modules own the math. The panel shell owns controls, output tabs, copy actions, state persistence, and image rendering hooks.

  • Config shape: a disease module exposes diseaseConfig with names, prefixes, defaults, sample image, model options, simulateColor(), processImageData(), optional CVD helpers, and optional post-filter controls.
  • Mount options: panel mode passes a scoped root, per-panel prefix, disableUrl, disableSampleAutoload, and disableWindowListeners where needed.
  • Generated controls: base color, HEX, random, severity, model, perceptual severity curve, deep pass, image input, copy HEX, copy CSS, advanced toggle, cone weights, export all CVD, and environment sections are created by the shared template.
  • Output tabs: Chromaticity, Metrics, Image, Mindmap, and Model audit read the same panel state and update together.
  • Render cadence: the core debounces color rendering and comparison rendering so slider movement and image changes stay responsive.
  • Duplicate safety: IDs are generated with a panel-specific prefix, allowing two instances of the same simulation to coexist.
  • Destroy: standard core instances return a destroyable controller so panel close can remove listeners and release image resources cleanly.

6. Models and disease modules

+
  • Engine registry: tool/modules/core/engine.js provides registerModel(), getModel(), hasModel(), listModels(), listModelsByCategory(), simulateWithModel(), processImageWithModel(), and unregisterModel().
  • Model bootstrap: tool/modules/models/register-all.js registers matrix-based CVD models, cone isolation, grayscale, inversion, rod vision, tint, and spectral handlers.
  • CVD axes: protan, deutan, and tritan simulations can expose Brettel, Vienot, and Machado-like model choices.
  • Condition modules: disease modules define disease-specific color transforms, image processing, sample assets, post filters, labels, and explanatory copy.
  • Bespoke records: registry records can be marked bespoke when a condition does not yet match the shared simulator contract. Keep the escape path through legacyHref.
  • Risk: changing shared model math changes card previews, panel output, image processing, metrics, comparison exports, Library thumbnails, and saved restore expectations.

7. Metrics, appearance, and validation

+
  • Color metrics: panel helpers compute normalized HEX, RGB, HSL, LMS, CIE xy, Delta E 76, and Delta E 2000 for reference and simulated values.
  • Charts: panel state helpers produce small canvas or DOM charts for RGB, HSL, LMS, chromaticity, and difference values.
  • CAM controls: extension controls expose CAT16 adaptation, CAM16-UCS perceptual assumptions, CIECAM02 surround, Hunt-Stevens brightness, white point adaptation, illuminants, temperature, observer, surround, and viewing distance.
  • Snapshots: snapshot data lives under aa_vd_snapshots_v1 and can restore named panel states.
  • History: recent change history tracks the last 10 panel changes and supports undo and clear.
  • Verification panel: reads current panels through manager snapshots, charts Delta E 2000, and can export or sweep the active workspace for regression-style checks.
  • Analytics: the catalog dashboard uses registry data plus severity metadata to render Matrix, Map, and Statistics views, with JSON and CSV export.

8. Library capture and restore

+
  • Binding: js/library/tool-bindings.js attaches /tool/vision-simulation/ as tool id vision-simulation and asset type simulation.
  • Focused capture: the capture path prefers the focused .vd-panel.is-focused panel, then visible panels, then a workspace bookmark if no panels are open.
  • Canvas selection: capture looks for simulated output canvases by suffix and can fall back to the largest visible canvas.
  • Asset payload: saved data includes simulation slug, category, the reference color (the panel's base HEX), the simulated chip color, Delta E 76, Delta E 2000, settings, panel_state (the panel's controls keyed by id suffix), and image preview data when available.
  • Settings fallback: if no canvas can be captured, the Library still saves a preset-style asset with semantic settings and restore data.
  • Restore bridge: every panel gets a random instance prefix, so saved ids never match a reopened panel. The binding therefore writes panel_state into aa_vd_panel_states_v1 under the slug, which the panel applies when it mounts, and then calls window.AAVisionSim.restoreState(slug, state). That closes an existing same-slug panel, opens a fresh panel, waits two animation frames, applies saved input values, dispatches input and change events, and focuses the panel. Saves made before panel_state have their suffixes recovered from the stored ids, and a panel asset waits (the restore returns false and the Library retries) until AAVisionSim exists.
  • Compatibility: when changing generated control IDs, update capture suffix matching, restore fallbacks, and stored state fields together.

9. Workbench view

+
  • Shell: js/tool/vision-workbench.js runs mountShell() on load. It draws the five view buttons (Workbench, Catalogue, Compare, Palette audit, Analytics) into [data-vlab-navhost] and adds goToView(), currentView() and toWorkbench(slug) to window.AAVisionLab. The other four views are still rendered by vision-deficiency.js into #vd-app: the router calls AAVisionLab.switchCategory() with __all__, __compare__, __audit__ or __analytics__, and Catalogue returns to the category saved in aa_vd_active_category.
  • Start view: the last view is stored in aa_vd_lab_view; a ?vw= link always starts on the Workbench.
  • Data: the condition list comes from CONDITION_FACTS and the ten reference swatches from REFERENCE_STRIP in tool/modules/registry/condition-facts.js. Until the engine has loaded, a color condition shows its baked preview, which is the engine's output at the clinical default.
  • Engine: after the first paint, loadEngine() imports tool/modules/models/register-all.js and tool/modules/core/engine.js. simHex() calls simulateWithModel() with the condition's registry model, and a dropped image goes through processImageWithModel() after it is scaled to at most 900 pixels on its longer side. Nothing is reimplemented, so the Workbench, the panels and the API use the same functions.
  • Model choice: axisOf() recognizes the Brettel, Viénot and Machado protan, deutan and tritan model ids, so only those six conditions take the model buttons; modelIdFor() swaps the publication and keeps the axis.
  • Field conditions: fieldKind() and fieldCss() from js/tool/vision-field-effects.js map each of the 61 spatial conditions to one of the six families in FIELD_LABEL. The catalog card uses the same map, so both paint the same loss.
  • What collapses: collapsedPairs() checks the 45 pairs of reference swatches and keeps a pair whose Delta E 2000 was 12 or more before simulation and is under 8 after it, sorted by how far it fell.
  • State: aa_vd_workbench stores the condition, severity, model, specimen and base color, written 400 ms after the last change. The defaults are deuteranopia, 100, Brettel, the interface specimen and #E53E3E. readDeepLink() reads ?vw=<slug>:<severity>:<model>.
  • Exports: mountWorkbench(host), mountShell(), goToView(name) and hasDeepLink().

10. Palette audit view

+
  • Loading: when the page switches to __audit__, vision-deficiency.js imports js/tool/vision-audit.js and calls renderPaletteAudit(host). That first loads register-all.js, engine.js and core/color-math.js, which no other view needs.
  • The audit: computeAudit(palette, threshold) takes the 17 conditions from listColorConditions(), simulates every color with each condition's transform.model at its transform.severity, and compares every pair in CIELAB with Delta E 2000. Pairs under the threshold are kept with their Delta E before and after, and each color counts how many merges it is part of. Conditions are sorted by merges, then severity score, then name; the first is the worst if it merges anything. The Workbench's model and severity are not used.
  • Suggest a fix: suggestFix(pair, condition, threshold) blends the second color of the pair toward white and toward black in 4% steps up to 80%, and returns the first step at which the simulated Delta E 2000 reaches 1.25 times the threshold, taking the smaller RGB change when both directions work, or null.
  • Inputs and storage: normalisePalette() keeps unique #RRGGBB values up to MAX_COLORS = 24; DEFAULT_THRESHOLD is 5. The palette and threshold are stored in aa_vd_audit_palette and aa_vd_audit_threshold; search, the failing filter and suggested fixes live only in the session.
  • Exports: renderPaletteAudit(host), and auditPalette(palette, threshold), the audit without any DOM, for tests.
  • API: POST /v1/vision/audit in api/lib/handlers/vision.js answers the same question on the same engine; neither wraps the other.
  • Tests: tests/website/vision-audit.spec.js (run with npm run test:website:browser) checks that the audit covers every color condition, finds a merging pair, gates on the threshold, that a suggested fix separates its pair, that the palette survives a reload and the three-column layout. npm run test:vision runs tests/vision/condition-facts.test.js against the registry and the engine.

11. Extension checklist

+
  1. Choose the existing category that best matches the simulation before adding a new category.
  2. Create or update a disease module in tool/modules/diseases/ that exports a complete diseaseConfig.
  3. Add a registry record with stable slug, name, category, prefix, complexity, and model options.
  4. Only mark a record bespoke when the standard simulator contract cannot support it yet.
  5. Register any reusable model math in tool/modules/core/engine.js through register-all.js.
  6. Check that opening the new simulation's card still counts toward the free daily simulation limit.
  7. Verify panel state fields, linked control keys, snapshot behavior, and recent-change behavior.
  8. Update Library capture and restore when new controls add important semantic state.
  9. Update user and developer documentation, documentation JSON, RSS, sitemaps, PWA cache manifest, and search index.
  10. Run catalog, panel, metrics, export, restore, and accessibility smoke tests before release.

12. Testing and risk notes

+
  • Catalog: verify All, scope menu categories, Favorites, Compare, Palette audit, Analytics, Open Panels, mode switch, search debounce, favorites, recents, keyboard shortcuts, and empty state.
  • Gating: test the usage meter, daily limit behavior, and card click interception.
  • Panels: open five panels, duplicate a panel, exceed the cap, pin every panel, drag, resize, minimize, restore, maximize, close, tile, cascade, split, and stack.
  • Linked controls: link two or more panels and test base color, severity, model, perceptual curve, deep pass, cone weights, illuminant, CAM controls, and image-dependent controls.
  • Metrics: smoke test Delta E 76, Delta E 2000, CIE xy, LMS, RGB, HSL, charts, model audit, and mindmap output.
  • Image rendering: test upload, clear, multi-pass deep, comparison grid, high-DPI canvas sizing, and large image responsiveness.
  • Workspace views: test Compare selection, Matrix, Map, Statistics, JSON export, CSV export, verification refresh, verification export, and automatic sweep.
  • Library: save a focused panel, save multiple visible panels, save a workspace bookmark, restore each asset, and confirm values are applied after the two-frame restore pass.
  • Risk: registry changes affect catalog UX, search, Analytics, Compare, Library saves, generated documentation feeds, and SEO pages. Shared model changes affect every panel using that model family.