accessify-widget 0.3.38 → 0.3.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { d, i } from "./index-Bgb3ILLq.js";
1
+ import { d, i } from "./index-BD3C-sG-.js";
2
2
  export {
3
3
  d as destroy,
4
4
  i as init
@@ -0,0 +1,176 @@
1
+ const TOKENS = {
2
+ light: {
3
+ colorScheme: "light",
4
+ pageBg: "#fbf7ef",
5
+ text: "#1a1a1a",
6
+ textStrong: "#0d0d0d",
7
+ link: "#0047b3",
8
+ linkVisited: "#3d2b85",
9
+ focusRing: "#0047b3",
10
+ borderContent: "#888078",
11
+ inputBg: "#ffffff",
12
+ inputBorder: "#6f675d",
13
+ imgFilter: ""
14
+ },
15
+ dark: {
16
+ colorScheme: "dark",
17
+ pageBg: "#101418",
18
+ text: "#e8e4dc",
19
+ textStrong: "#ffffff",
20
+ link: "#7cc8f5",
21
+ linkVisited: "#b8a0e8",
22
+ focusRing: "#7cc8f5",
23
+ borderContent: "#3a4a58",
24
+ inputBg: "#1a2028",
25
+ inputBorder: "#4a5a68",
26
+ imgFilter: "brightness(0.90) contrast(1.06)"
27
+ },
28
+ high: {
29
+ colorScheme: "dark",
30
+ pageBg: "#000000",
31
+ text: "#ffffff",
32
+ textStrong: "#ffffff",
33
+ link: "#ffff00",
34
+ linkVisited: "#ffff00",
35
+ focusRing: "#ffff00",
36
+ borderContent: "#ffffff",
37
+ inputBg: "#000000",
38
+ inputBorder: "#ffffff",
39
+ imgFilter: "contrast(1.25) brightness(0.95)"
40
+ }
41
+ };
42
+ const EX = ":not(#accessify-root):not(#accessify-root *)";
43
+ function buildCSS(mode) {
44
+ const t = TOKENS[mode];
45
+ const isHigh = mode === "high";
46
+ const base = `
47
+ html {
48
+ color-scheme: ${t.colorScheme} !important;
49
+ }
50
+ html, body {
51
+ background-color: ${t.pageBg} !important;
52
+ }
53
+ `;
54
+ const textColor = `
55
+ body *${EX} {
56
+ color: ${t.text} !important;
57
+ }
58
+ body :where(h1, h2, h3, h4, h5, h6, strong, b, th)${EX} {
59
+ color: ${t.textStrong} !important;
60
+ }
61
+ `;
62
+ const links = `
63
+ body :where(a)${EX} {
64
+ color: ${t.link} !important;
65
+ text-decoration: underline !important;
66
+ text-decoration-color: ${t.link} !important;
67
+ ${isHigh ? "text-decoration-thickness: 2px !important; text-underline-offset: 3px !important;" : ""}
68
+ }
69
+ body :where(a:visited)${EX} {
70
+ color: ${t.linkVisited} !important;
71
+ }
72
+ body :where(a:hover, a:focus)${EX} {
73
+ opacity: 0.85 !important;
74
+ }
75
+ `;
76
+ const forms = `
77
+ body :where(input, textarea, select)${EX} {
78
+ background-color: ${t.inputBg} !important;
79
+ color: ${t.text} !important;
80
+ border: 1px solid ${t.inputBorder} !important;
81
+ box-shadow: none !important;
82
+ }
83
+ body :where(button, [role="button"])${EX} {
84
+ color: ${t.text} !important;
85
+ border-color: ${t.inputBorder} !important;
86
+ ${isHigh ? `background-color: ${t.pageBg} !important; border: 2px solid ${t.inputBorder} !important;` : ""}
87
+ }
88
+ `;
89
+ const focus = `
90
+ body :where(a, button, input, textarea, select, [tabindex])${EX}:focus-visible {
91
+ outline: ${isHigh ? "3px" : "2px"} solid ${t.focusRing} !important;
92
+ outline-offset: 2px !important;
93
+ }
94
+ `;
95
+ const borders = `
96
+ body :where(table, th, td, hr, fieldset)${EX} {
97
+ border-color: ${t.borderContent} !important;
98
+ }
99
+ `;
100
+ const images = t.imgFilter ? `
101
+ body :where(img, video, picture)${EX} {
102
+ filter: ${t.imgFilter} !important;
103
+ }
104
+ ` : "";
105
+ const highExtras = isHigh ? `
106
+ body :where(::placeholder)${EX} {
107
+ color: #aaaaaa !important;
108
+ opacity: 1 !important;
109
+ }
110
+ body :where(::selection) {
111
+ background: #ffff00 !important;
112
+ color: #000000 !important;
113
+ }
114
+ body :where(mark)${EX} {
115
+ background: #ffff00 !important;
116
+ color: #000000 !important;
117
+ }
118
+ ` : "";
119
+ const sectionBg = `
120
+ body :where(main, article, aside, header, footer, section, nav)${EX} {
121
+ background-color: ${t.pageBg} !important;
122
+ }
123
+ `;
124
+ return base + textColor + links + forms + focus + borders + images + highExtras + sectionBg;
125
+ }
126
+ function createContrastModule() {
127
+ let currentMode = "off";
128
+ const STYLE_ID = "accessify-contrast";
129
+ const STORAGE_KEY = "accessify-contrast-mode";
130
+ function applyStyles(mode) {
131
+ let styleEl = document.getElementById(STYLE_ID);
132
+ if (mode === "off") {
133
+ styleEl?.remove();
134
+ return;
135
+ }
136
+ if (!styleEl) {
137
+ styleEl = document.createElement("style");
138
+ styleEl.id = STYLE_ID;
139
+ document.head.appendChild(styleEl);
140
+ }
141
+ styleEl.textContent = buildCSS(mode);
142
+ }
143
+ function activate() {
144
+ const saved = localStorage.getItem(STORAGE_KEY);
145
+ currentMode = saved === "light" || saved === "dark" || saved === "high" ? saved : "dark";
146
+ applyStyles(currentMode);
147
+ }
148
+ function deactivate() {
149
+ currentMode = "off";
150
+ applyStyles("off");
151
+ localStorage.removeItem(STORAGE_KEY);
152
+ }
153
+ return {
154
+ id: "contrast",
155
+ name: () => "Contrast",
156
+ description: "Increase contrast for better readability",
157
+ icon: "contrast",
158
+ category: "visual",
159
+ activate,
160
+ deactivate,
161
+ getState: () => ({ id: "contrast", enabled: currentMode !== "off", value: currentMode }),
162
+ setState: (mode) => {
163
+ currentMode = mode === "light" || mode === "dark" || mode === "high" ? mode : "off";
164
+ applyStyles(currentMode);
165
+ if (currentMode === "off") {
166
+ localStorage.removeItem(STORAGE_KEY);
167
+ } else {
168
+ localStorage.setItem(STORAGE_KEY, currentMode);
169
+ }
170
+ }
171
+ };
172
+ }
173
+ export {
174
+ createContrastModule as default
175
+ };
176
+ //# sourceMappingURL=contrast-F7lHj833.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contrast-F7lHj833.js","sources":["../src/features/contrast.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Accessify – Contrast Modes (Accessibility Feature)\n// ---------------------------------------------------------------------------\n//\n// Three modes: light, dark, high — each as a clearly defined token set.\n//\n// Design principles:\n// 1. CONTENT elements (text, headings, links, buttons, form controls) get\n// explicit color overrides — these are what users need to read.\n// 2. STRUCTURAL elements (wrapper divs, sections, nav) get background only\n// via `html` and `body` — not individually. This prevents breaking\n// Framer/CSS-Grid/Flex layouts where divs use fit-content, overflow:hidden,\n// or fixed heights.\n// 3. The widget itself (inside #accessify-root / Shadow DOM) is NEVER touched.\n// 4. Focus indicators are defined in ALL modes, not just high contrast.\n// 5. border-color is NOT globally overridden — only on elements that have\n// visible borders for content separation (tables, fieldsets, hr).\n//\n// Selector strategy:\n// - `:where()` for zero-specificity (site styles can still win if needed,\n// but `!important` ensures accessibility overrides take priority).\n// - `body :where(...)` scopes to page content.\n// - `body *:not(#accessify-root):not(#accessify-root *)` used only where\n// we need broad text color coverage.\n// - Framer-safe: no background-color on generic div/section/article — only\n// on html/body. Content readability comes from text color, not from\n// painting every container.\n//\n// ---------------------------------------------------------------------------\n\nimport type { FeatureModule, FeatureState } from '../types';\n\ntype ContrastMode = 'off' | 'light' | 'dark' | 'high';\n\n// ---------------------------------------------------------------------------\n// Token definitions — each mode is a self-contained color system\n// ---------------------------------------------------------------------------\n\ninterface ContrastTokens {\n colorScheme: string;\n pageBg: string;\n text: string;\n textStrong: string; // headings, bold\n link: string;\n linkVisited: string;\n focusRing: string;\n borderContent: string; // for tables, hr, fieldset — NOT every div\n inputBg: string;\n inputBorder: string;\n imgFilter: string; // empty string = no filter\n}\n\nconst TOKENS: Record<Exclude<ContrastMode, 'off'>, ContrastTokens> = {\n light: {\n colorScheme: 'light',\n pageBg: '#fbf7ef',\n text: '#1a1a1a',\n textStrong: '#0d0d0d',\n link: '#0047b3',\n linkVisited: '#3d2b85',\n focusRing: '#0047b3',\n borderContent:'#888078',\n inputBg: '#ffffff',\n inputBorder: '#6f675d',\n imgFilter: '',\n },\n dark: {\n colorScheme: 'dark',\n pageBg: '#101418',\n text: '#e8e4dc',\n textStrong: '#ffffff',\n link: '#7cc8f5',\n linkVisited: '#b8a0e8',\n focusRing: '#7cc8f5',\n borderContent:'#3a4a58',\n inputBg: '#1a2028',\n inputBorder: '#4a5a68',\n imgFilter: 'brightness(0.90) contrast(1.06)',\n },\n high: {\n colorScheme: 'dark',\n pageBg: '#000000',\n text: '#ffffff',\n textStrong: '#ffffff',\n link: '#ffff00',\n linkVisited: '#ffff00',\n focusRing: '#ffff00',\n borderContent:'#ffffff',\n inputBg: '#000000',\n inputBorder: '#ffffff',\n imgFilter: 'contrast(1.25) brightness(0.95)',\n },\n};\n\n// ---------------------------------------------------------------------------\n// CSS generation — separated into logical layers\n// ---------------------------------------------------------------------------\n\n/** Elements to exclude from page-level contrast (the widget itself) */\nconst EX = ':not(#accessify-root):not(#accessify-root *)';\n\nfunction buildCSS(mode: Exclude<ContrastMode, 'off'>): string {\n const t = TOKENS[mode];\n const isHigh = mode === 'high';\n\n // ── Layer 1: Page-level base (html/body only) ──\n // Only html+body get background. NOT every div — that breaks Framer layouts\n // where wrapper divs use overflow:hidden, fixed heights, fit-content etc.\n const base = `\n html {\n color-scheme: ${t.colorScheme} !important;\n }\n html, body {\n background-color: ${t.pageBg} !important;\n }\n `;\n\n // ── Layer 2: Text color on ALL content elements ──\n // Using body * ensures text inside any container is readable, without\n // painting the container's background (which would break layouts).\n const textColor = `\n body *${EX} {\n color: ${t.text} !important;\n }\n body :where(h1, h2, h3, h4, h5, h6, strong, b, th)${EX} {\n color: ${t.textStrong} !important;\n }\n `;\n\n // ── Layer 3: Links — distinct color + underline for visibility ──\n const links = `\n body :where(a)${EX} {\n color: ${t.link} !important;\n text-decoration: underline !important;\n text-decoration-color: ${t.link} !important;\n ${isHigh ? 'text-decoration-thickness: 2px !important; text-underline-offset: 3px !important;' : ''}\n }\n body :where(a:visited)${EX} {\n color: ${t.linkVisited} !important;\n }\n body :where(a:hover, a:focus)${EX} {\n opacity: 0.85 !important;\n }\n `;\n\n // ── Layer 4: Form controls — explicit bg + border for readability ──\n // These get background because they ARE content, not structural wrappers.\n const forms = `\n body :where(input, textarea, select)${EX} {\n background-color: ${t.inputBg} !important;\n color: ${t.text} !important;\n border: 1px solid ${t.inputBorder} !important;\n box-shadow: none !important;\n }\n body :where(button, [role=\"button\"])${EX} {\n color: ${t.text} !important;\n border-color: ${t.inputBorder} !important;\n ${isHigh ? `background-color: ${t.pageBg} !important; border: 2px solid ${t.inputBorder} !important;` : ''}\n }\n `;\n\n // ── Layer 5: Focus indicators — in ALL modes, stronger in high ──\n const focus = `\n body :where(a, button, input, textarea, select, [tabindex])${EX}:focus-visible {\n outline: ${isHigh ? '3px' : '2px'} solid ${t.focusRing} !important;\n outline-offset: 2px !important;\n }\n `;\n\n // ── Layer 6: Content borders — only on elements that visually separate ──\n // NOT on generic divs — that destroys Framer card layouts.\n const borders = `\n body :where(table, th, td, hr, fieldset)${EX} {\n border-color: ${t.borderContent} !important;\n }\n `;\n\n // ── Layer 7: Images — gentle filter, skip decorative SVG icons ──\n const images = t.imgFilter ? `\n body :where(img, video, picture)${EX} {\n filter: ${t.imgFilter} !important;\n }\n ` : '';\n\n // ── Layer 8: High contrast extras ──\n const highExtras = isHigh ? `\n body :where(::placeholder)${EX} {\n color: #aaaaaa !important;\n opacity: 1 !important;\n }\n body :where(::selection) {\n background: #ffff00 !important;\n color: #000000 !important;\n }\n body :where(mark)${EX} {\n background: #ffff00 !important;\n color: #000000 !important;\n }\n ` : '';\n\n // ── Layer 9: Background for large content sections (NOT small wrappers) ──\n // Only target semantic HTML5 landmarks + explicitly large containers.\n // Framer wraps everything in nested divs — we do NOT paint those.\n // Instead, the html/body bg shines through. For sections that have their\n // own bg (hero, colored blocks), we override only semantic elements.\n const sectionBg = `\n body :where(main, article, aside, header, footer, section, nav)${EX} {\n background-color: ${t.pageBg} !important;\n }\n `;\n\n return base + textColor + links + forms + focus + borders + images + highExtras + sectionBg;\n}\n\n// ---------------------------------------------------------------------------\n// Module\n// ---------------------------------------------------------------------------\n\nexport default function createContrastModule(): FeatureModule {\n let currentMode: ContrastMode = 'off';\n const STYLE_ID = 'accessify-contrast';\n const STORAGE_KEY = 'accessify-contrast-mode';\n\n function applyStyles(mode: ContrastMode) {\n let styleEl = document.getElementById(STYLE_ID);\n if (mode === 'off') {\n styleEl?.remove();\n return;\n }\n if (!styleEl) {\n styleEl = document.createElement('style');\n styleEl.id = STYLE_ID;\n document.head.appendChild(styleEl);\n }\n styleEl.textContent = buildCSS(mode);\n }\n\n function activate() {\n const saved = localStorage.getItem(STORAGE_KEY) as ContrastMode;\n currentMode = saved === 'light' || saved === 'dark' || saved === 'high' ? saved : 'dark';\n applyStyles(currentMode);\n }\n\n function deactivate() {\n currentMode = 'off';\n applyStyles('off');\n localStorage.removeItem(STORAGE_KEY);\n }\n\n return {\n id: 'contrast',\n name: () => 'Contrast',\n description: 'Increase contrast for better readability',\n icon: 'contrast',\n category: 'visual',\n activate,\n deactivate,\n getState: (): FeatureState => ({ id: 'contrast', enabled: currentMode !== 'off', value: currentMode }),\n setState: (mode: ContrastMode) => {\n currentMode = mode === 'light' || mode === 'dark' || mode === 'high' ? mode : 'off';\n applyStyles(currentMode);\n if (currentMode === 'off') {\n localStorage.removeItem(STORAGE_KEY);\n } else {\n localStorage.setItem(STORAGE_KEY, currentMode);\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}
@@ -254,8 +254,6 @@ https://svelte.dev/e/svelte_boundary_reset_onerror`);
254
254
  }
255
255
  const EACH_ITEM_REACTIVE = 1;
256
256
  const EACH_INDEX_REACTIVE = 1 << 1;
257
- const EACH_IS_CONTROLLED = 1 << 2;
258
- const EACH_IS_ANIMATED = 1 << 3;
259
257
  const EACH_ITEM_IMMUTABLE = 1 << 4;
260
258
  const PROPS_IS_IMMUTABLE = 1;
261
259
  const PROPS_IS_UPDATED = 1 << 2;
@@ -3836,8 +3834,7 @@ var offscreen_anchor;
3836
3834
  function each(node, flags2, get_collection, get_key, render_fn2, fallback_fn = null) {
3837
3835
  var anchor = node;
3838
3836
  var items = /* @__PURE__ */ new Map();
3839
- var is_controlled = (flags2 & EACH_IS_CONTROLLED) !== 0;
3840
- if (is_controlled) {
3837
+ {
3841
3838
  var parent_node = (
3842
3839
  /** @type {Element} */
3843
3840
  node
@@ -3962,31 +3959,17 @@ function skip_to_branch(effect2) {
3962
3959
  return effect2;
3963
3960
  }
3964
3961
  function reconcile(state2, array, anchor, flags2, get_key) {
3965
- var is_animated = (flags2 & EACH_IS_ANIMATED) !== 0;
3966
3962
  var length = array.length;
3967
3963
  var items = state2.items;
3968
3964
  var current = skip_to_branch(state2.effect.first);
3969
3965
  var seen;
3970
3966
  var prev = null;
3971
- var to_animate;
3972
3967
  var matched = [];
3973
3968
  var stashed = [];
3974
3969
  var value;
3975
3970
  var key;
3976
3971
  var effect2;
3977
3972
  var i;
3978
- if (is_animated) {
3979
- for (i = 0; i < length; i += 1) {
3980
- value = array[i];
3981
- key = get_key(value, i);
3982
- effect2 = /** @type {EachItem} */
3983
- items.get(key).e;
3984
- if ((effect2.f & EFFECT_OFFSCREEN) === 0) {
3985
- effect2.nodes?.a?.measure();
3986
- (to_animate ?? (to_animate = /* @__PURE__ */ new Set())).add(effect2);
3987
- }
3988
- }
3989
- }
3990
3973
  for (i = 0; i < length; i += 1) {
3991
3974
  value = array[i];
3992
3975
  key = get_key(value, i);
@@ -4021,10 +4004,6 @@ function reconcile(state2, array, anchor, flags2, get_key) {
4021
4004
  }
4022
4005
  if ((effect2.f & INERT) !== 0) {
4023
4006
  resume_effect(effect2);
4024
- if (is_animated) {
4025
- effect2.nodes?.a?.unfix();
4026
- (to_animate ?? (to_animate = /* @__PURE__ */ new Set())).delete(effect2);
4027
- }
4028
4007
  }
4029
4008
  if (effect2 !== current) {
4030
4009
  if (seen !== void 0 && seen.has(effect2)) {
@@ -4103,26 +4082,10 @@ function reconcile(state2, array, anchor, flags2, get_key) {
4103
4082
  }
4104
4083
  var destroy_length = to_destroy.length;
4105
4084
  if (destroy_length > 0) {
4106
- var controlled_anchor = (flags2 & EACH_IS_CONTROLLED) !== 0 && length === 0 ? anchor : null;
4107
- if (is_animated) {
4108
- for (i = 0; i < destroy_length; i += 1) {
4109
- to_destroy[i].nodes?.a?.measure();
4110
- }
4111
- for (i = 0; i < destroy_length; i += 1) {
4112
- to_destroy[i].nodes?.a?.fix();
4113
- }
4114
- }
4085
+ var controlled_anchor = length === 0 ? anchor : null;
4115
4086
  pause_effects(state2, to_destroy, controlled_anchor);
4116
4087
  }
4117
4088
  }
4118
- if (is_animated) {
4119
- queue_micro_task(() => {
4120
- if (to_animate === void 0) return;
4121
- for (effect2 of to_animate) {
4122
- effect2.nodes?.a?.apply();
4123
- }
4124
- });
4125
- }
4126
4089
  }
4127
4090
  function create_item(items, anchor, value, key, index2, render_fn2, flags2, get_collection) {
4128
4091
  var v = (flags2 & EACH_ITEM_REACTIVE) !== 0 ? (flags2 & EACH_ITEM_IMMUTABLE) === 0 ? /* @__PURE__ */ mutable_source(value, false, false) : source(value) : null;
@@ -6553,12 +6516,16 @@ function getEnglishSimplificationPrompt() {
6553
6516
 
6554
6517
  Return ONLY the simplified text.`;
6555
6518
  }
6556
- var root_2$1 = /* @__PURE__ */ from_html(`<button class="accessify-chip accessify-chip--icon"><span class="accessify-chip-icon" aria-hidden="true"></span> <span> </span></button>`);
6519
+ var root_3$1 = /* @__PURE__ */ from_html(`<span class="accessify-chip-check" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"></path></svg></span>`);
6520
+ var root_4 = /* @__PURE__ */ from_html(`<span class="accessify-chip-icon" aria-hidden="true"></span>`);
6521
+ var root_2$1 = /* @__PURE__ */ from_html(`<button class="accessify-chip accessify-chip--icon"><!> <span> </span></button>`);
6557
6522
  var root_1$2 = /* @__PURE__ */ from_html(`<div class="accessify-control-row" role="group"><div class="accessify-control-label"><span class="accessify-control-label-icon" aria-hidden="true"></span> <span class="accessify-control-label-text"> </span></div> <div class="accessify-chip-row"></div></div>`);
6558
- var root_4 = /* @__PURE__ */ from_html(`<button><span>A</span></button>`);
6559
- var root_3$1 = /* @__PURE__ */ from_html(`<div class="accessify-control-row" role="group"><div class="accessify-control-label"><span class="accessify-control-label-icon" aria-hidden="true"></span> <span class="accessify-control-label-text"> </span></div> <div class="accessify-size-steps"></div></div>`);
6560
- var root_6 = /* @__PURE__ */ from_html(`<div class="accessify-card-wrap"><button class="accessify-card" role="switch"><span class="accessify-card-icon" aria-hidden="true"></span> <span class="accessify-card-label"> </span></button> <span class="accessify-card-info" role="note"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span></div>`);
6561
- var root_5 = /* @__PURE__ */ from_html(`<div class="accessify-features"></div>`);
6523
+ var root_7 = /* @__PURE__ */ from_html(`<span class="accessify-chip-check" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"></path></svg></span>`);
6524
+ var root_8 = /* @__PURE__ */ from_html(`<span aria-hidden="true">A</span>`);
6525
+ var root_6 = /* @__PURE__ */ from_html(`<button class="accessify-chip accessify-chip--icon"><!> <span> </span></button>`);
6526
+ var root_5 = /* @__PURE__ */ from_html(`<div class="accessify-control-row" role="group"><div class="accessify-control-label"><span class="accessify-control-label-icon" aria-hidden="true"></span> <span class="accessify-control-label-text"> </span></div> <div class="accessify-chip-row"></div></div>`);
6527
+ var root_10 = /* @__PURE__ */ from_html(`<div class="accessify-card-wrap"><button class="accessify-card" role="switch"><span class="accessify-card-icon" aria-hidden="true"></span> <span class="accessify-card-label"> </span></button> <span class="accessify-card-info" role="note"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span></div>`);
6528
+ var root_9 = /* @__PURE__ */ from_html(`<div class="accessify-features"></div>`);
6562
6529
  var root$2 = /* @__PURE__ */ from_html(`<!> <!> <div class="accessify-section-divider"></div> <!>`, 1);
6563
6530
  function FeatureGrid($$anchor, $$props) {
6564
6531
  push($$props, true);
@@ -6659,16 +6626,16 @@ function FeatureGrid($$anchor, $$props) {
6659
6626
  const AI_FEATURES = /* @__PURE__ */ new Set(["text-simplify", "alt-text"]);
6660
6627
  const loadedModules = /* @__PURE__ */ new Map();
6661
6628
  const FEATURE_LOADERS = {
6662
- contrast: () => import("./contrast-CqsICAkU.js"),
6629
+ contrast: () => import("./contrast-F7lHj833.js"),
6663
6630
  "text-size": () => import("./text-size-m_mHNPWo.js"),
6664
- "keyboard-nav": () => import("./keyboard-nav-BOWxbDrQ.js"),
6631
+ "keyboard-nav": () => import("./keyboard-nav-ohhgkfVh.js"),
6665
6632
  "link-highlight": () => import("./link-highlight-DBGm067Y.js"),
6666
6633
  "reading-guide": () => import("./reading-guide-VT8NciIL.js"),
6667
6634
  "reading-mask": () => import("./reading-mask-BABChuCz.js"),
6668
6635
  "animation-stop": () => import("./animation-stop-_chC8bg1.js"),
6669
6636
  "hide-images": () => import("./hide-images-B_LeCBcd.js"),
6670
6637
  "big-cursor": () => import("./big-cursor-B2UKu9dQ.js"),
6671
- "page-structure": () => import("./page-structure-BYAhe_xH.js"),
6638
+ "page-structure": () => import("./page-structure-BuecyE3V.js"),
6672
6639
  tts: () => import("./tts-CjszLRnb.js"),
6673
6640
  "text-simplify": () => import("./text-simplify-CK2GFhq2.js"),
6674
6641
  "alt-text": () => Promise.resolve().then(() => altText)
@@ -6817,7 +6784,7 @@ function FeatureGrid($$anchor, $$props) {
6817
6784
  var fragment = root$2();
6818
6785
  var node = first_child(fragment);
6819
6786
  {
6820
- var consequent = ($$anchor2) => {
6787
+ var consequent_1 = ($$anchor2) => {
6821
6788
  var div = root_1$2();
6822
6789
  var div_1 = child(div);
6823
6790
  var span = child(div_1);
@@ -6827,10 +6794,24 @@ function FeatureGrid($$anchor, $$props) {
6827
6794
  var div_2 = sibling(div_1, 2);
6828
6795
  each(div_2, 21, () => CONTRAST_MODES, index, ($$anchor3, mode) => {
6829
6796
  var button = root_2$1();
6830
- var span_2 = child(button);
6831
- html(span_2, () => get(mode).icon, true);
6832
- var span_3 = sibling(span_2, 2);
6833
- var text_1 = child(span_3);
6797
+ var node_1 = child(button);
6798
+ {
6799
+ var consequent = ($$anchor4) => {
6800
+ var span_2 = root_3$1();
6801
+ append($$anchor4, span_2);
6802
+ };
6803
+ var alternate = ($$anchor4) => {
6804
+ var span_3 = root_4();
6805
+ html(span_3, () => get(mode).icon, true);
6806
+ append($$anchor4, span_3);
6807
+ };
6808
+ if_block(node_1, ($$render) => {
6809
+ if (get(contrastMode) === get(mode).id) $$render(consequent);
6810
+ else $$render(alternate, -1);
6811
+ });
6812
+ }
6813
+ var span_4 = sibling(node_1, 2);
6814
+ var text_1 = child(span_4);
6834
6815
  template_effect(
6835
6816
  ($0) => {
6836
6817
  set_attribute(button, "data-active", get(contrastMode) === get(mode).id);
@@ -6856,39 +6837,66 @@ function FeatureGrid($$anchor, $$props) {
6856
6837
  };
6857
6838
  var d = /* @__PURE__ */ user_derived(() => get(visibleFeatureIds).has("contrast"));
6858
6839
  if_block(node, ($$render) => {
6859
- if (get(d)) $$render(consequent);
6840
+ if (get(d)) $$render(consequent_1);
6860
6841
  });
6861
6842
  }
6862
- var node_1 = sibling(node, 2);
6843
+ var node_2 = sibling(node, 2);
6863
6844
  {
6864
- var consequent_1 = ($$anchor2) => {
6865
- var div_3 = root_3$1();
6845
+ var consequent_3 = ($$anchor2) => {
6846
+ var div_3 = root_5();
6866
6847
  var div_4 = child(div_3);
6867
- var span_4 = child(div_4);
6868
- html(span_4, () => getIcon("text-size"), true);
6869
- var span_5 = sibling(span_4, 2);
6870
- var text_2 = child(span_5);
6848
+ var span_5 = child(div_4);
6849
+ html(span_5, () => getIcon("text-size"), true);
6850
+ var span_6 = sibling(span_5, 2);
6851
+ var text_2 = child(span_6);
6871
6852
  var div_5 = sibling(div_4, 2);
6872
6853
  each(
6873
6854
  div_5,
6874
- 20,
6855
+ 21,
6875
6856
  () => [
6876
- { pct: 85, size: "11px" },
6877
- { pct: 125, size: "16px" },
6878
- { pct: 150, size: "20px" }
6857
+ {
6858
+ pct: 85,
6859
+ size: "12px",
6860
+ label: $$props.config.lang?.startsWith("de") ? "Kleiner" : "Smaller"
6861
+ },
6862
+ {
6863
+ pct: 125,
6864
+ size: "16px",
6865
+ label: $$props.config.lang?.startsWith("de") ? "Größer" : "Bigger"
6866
+ },
6867
+ {
6868
+ pct: 150,
6869
+ size: "20px",
6870
+ label: $$props.config.lang?.startsWith("de") ? "Groß" : "Large"
6871
+ }
6879
6872
  ],
6880
6873
  index,
6881
6874
  ($$anchor3, step) => {
6882
- var button_1 = root_4();
6883
- let classes;
6884
- var span_6 = child(button_1);
6875
+ var button_1 = root_6();
6876
+ var node_3 = child(button_1);
6877
+ {
6878
+ var consequent_2 = ($$anchor4) => {
6879
+ var span_7 = root_7();
6880
+ append($$anchor4, span_7);
6881
+ };
6882
+ var alternate_1 = ($$anchor4) => {
6883
+ var span_8 = root_8();
6884
+ template_effect(() => set_style(span_8, `font-size:${get(step).size ?? ""};font-weight:700;line-height:1`));
6885
+ append($$anchor4, span_8);
6886
+ };
6887
+ if_block(node_3, ($$render) => {
6888
+ if (get(textSize) === get(step).pct) $$render(consequent_2);
6889
+ else $$render(alternate_1, -1);
6890
+ });
6891
+ }
6892
+ var span_9 = sibling(node_3, 2);
6893
+ var text_3 = child(span_9);
6885
6894
  template_effect(() => {
6886
- classes = set_class(button_1, 1, "accessify-size-step-btn", null, classes, { active: get(textSize) === step.pct });
6887
- set_attribute(button_1, "aria-label", `${step.pct ?? ""}%`);
6888
- set_attribute(button_1, "aria-pressed", get(textSize) === step.pct);
6889
- set_style(span_6, `font-size:${step.size ?? ""}`);
6895
+ set_attribute(button_1, "data-active", get(textSize) === get(step).pct);
6896
+ set_attribute(button_1, "aria-pressed", get(textSize) === get(step).pct);
6897
+ set_text(text_3, get(step).label);
6890
6898
  });
6891
- delegated("click", button_1, () => setTextSize(get(textSize) === step.pct ? 100 : step.pct));
6899
+ delegated("click", button_1, () => setTextSize(get(textSize) === get(step).pct ? 100 : get(step).pct));
6892
6900
  append($$anchor3, button_1);
6893
6901
  }
6894
6902
  );
@@ -6905,14 +6913,14 @@ function FeatureGrid($$anchor, $$props) {
6905
6913
  append($$anchor2, div_3);
6906
6914
  };
6907
6915
  var d_1 = /* @__PURE__ */ user_derived(() => get(visibleFeatureIds).has("text-size"));
6908
- if_block(node_1, ($$render) => {
6909
- if (get(d_1)) $$render(consequent_1);
6916
+ if_block(node_2, ($$render) => {
6917
+ if (get(d_1)) $$render(consequent_3);
6910
6918
  });
6911
6919
  }
6912
- var node_2 = sibling(node_1, 4);
6920
+ var node_4 = sibling(node_2, 4);
6913
6921
  {
6914
- var consequent_2 = ($$anchor2) => {
6915
- var div_6 = root_5();
6922
+ var consequent_4 = ($$anchor2) => {
6923
+ var div_6 = root_9();
6916
6924
  each(
6917
6925
  div_6,
6918
6926
  21,
@@ -6924,21 +6932,21 @@ function FeatureGrid($$anchor, $$props) {
6924
6932
  (feature) => feature.id,
6925
6933
  ($$anchor3, feature) => {
6926
6934
  const isActive = /* @__PURE__ */ user_derived(() => $$props.activeFeatures.get(get(feature).id) ?? false);
6927
- var div_7 = root_6();
6935
+ var div_7 = root_10();
6928
6936
  var button_2 = child(div_7);
6929
- var span_7 = child(button_2);
6930
- html(span_7, () => getIcon(get(feature).iconId), true);
6931
- var span_8 = sibling(span_7, 2);
6932
- var text_3 = child(span_8);
6933
- var span_9 = sibling(button_2, 2);
6937
+ var span_10 = child(button_2);
6938
+ html(span_10, () => getIcon(get(feature).iconId), true);
6939
+ var span_11 = sibling(span_10, 2);
6940
+ var text_4 = child(span_11);
6941
+ var span_12 = sibling(button_2, 2);
6934
6942
  template_effect(
6935
6943
  ($0, $1, $2, $3) => {
6936
6944
  set_attribute(button_2, "data-active", get(isActive));
6937
6945
  set_attribute(button_2, "aria-checked", get(isActive));
6938
6946
  set_attribute(button_2, "aria-label", $0);
6939
- set_text(text_3, $1);
6940
- set_attribute(span_9, "aria-label", $2);
6941
- set_attribute(span_9, "title", $3);
6947
+ set_text(text_4, $1);
6948
+ set_attribute(span_12, "aria-label", $2);
6949
+ set_attribute(span_12, "title", $3);
6942
6950
  },
6943
6951
  [
6944
6952
  () => t(get(feature).nameKey, $$props.config.lang),
@@ -6953,8 +6961,8 @@ function FeatureGrid($$anchor, $$props) {
6953
6961
  );
6954
6962
  append($$anchor2, div_6);
6955
6963
  };
6956
- if_block(node_2, ($$render) => {
6957
- if (get(visualFeatures).length > 0 || get(readingFeatures).length > 0 || get(aiFeatures).length > 0) $$render(consequent_2);
6964
+ if_block(node_4, ($$render) => {
6965
+ if (get(visualFeatures).length > 0 || get(readingFeatures).length > 0 || get(aiFeatures).length > 0) $$render(consequent_4);
6958
6966
  });
6959
6967
  }
6960
6968
  append($$anchor, fragment);
@@ -7986,10 +7994,21 @@ function createWidgetStyles(config2) {
7986
7994
  transition: background var(--fast), color var(--fast), border-color var(--fast);
7987
7995
  }
7988
7996
  .accessify-chip:hover { border-color: var(--border-hl); background: var(--surface-hover); }
7989
- .accessify-chip[data-active="true"] { background: var(--accent); color: var(--accent-on); border-color: var(--accent); }
7990
- .accessify-chip--icon { gap: 6px; }
7991
- .accessify-chip-icon { display: inline-flex; width: 14px; height: 14px; flex-shrink: 0; }
7992
- .accessify-chip-icon svg { width: 14px; height: 14px; }
7997
+ .accessify-chip[data-active="true"] {
7998
+ background: var(--accent); color: var(--accent-on);
7999
+ border-color: var(--accent);
8000
+ border-width: 2px;
8001
+ font-weight: 700;
8002
+ }
8003
+ .accessify-chip--icon { gap: 6px; flex-direction: column; }
8004
+ .accessify-chip-icon { display: inline-flex; width: 16px; height: 16px; flex-shrink: 0; }
8005
+ .accessify-chip-icon svg { width: 16px; height: 16px; }
8006
+ .accessify-chip-check {
8007
+ display: inline-flex; align-items: center; justify-content: center;
8008
+ width: 20px; height: 20px; border-radius: 50%;
8009
+ background: rgba(255,255,255,0.25); flex-shrink: 0;
8010
+ }
8011
+ .accessify-chip-check svg { width: 14px; height: 14px; }
7993
8012
 
7994
8013
  /* Text Size stepper */
7995
8014
  .accessify-control-row:has(.accessify-stepper) {
@@ -8013,22 +8032,7 @@ function createWidgetStyles(config2) {
8013
8032
  font-size: 13px; font-weight: 600; color: var(--text); user-select: none;
8014
8033
  }
8015
8034
 
8016
- /* Text Size 3-step buttons */
8017
- .accessify-size-steps {
8018
- display: flex; align-items: flex-end; gap: 6px;
8019
- }
8020
- .accessify-size-step-btn {
8021
- display: inline-flex; align-items: center; justify-content: center;
8022
- width: 36px; height: 36px; border-radius: 8px;
8023
- border: 1.5px solid var(--border); background: var(--surface-dim);
8024
- color: var(--text); cursor: pointer; font-weight: 700;
8025
- font-family: inherit; transition: all var(--fast);
8026
- line-height: 1;
8027
- }
8028
- .accessify-size-step-btn:hover { background: var(--surface-hover); }
8029
- .accessify-size-step-btn.active {
8030
- background: var(--accent); color: #fff; border-color: var(--accent);
8031
- }
8035
+ /* Text Size: uses same .accessify-chip-row / .accessify-chip as contrast */
8032
8036
 
8033
8037
  /* ─── Feature Cards (2-column grid) ─── */
8034
8038
  .accessify-features {
@@ -8984,4 +8988,4 @@ export {
8984
8988
  init as i,
8985
8989
  t
8986
8990
  };
8987
- //# sourceMappingURL=index-Bgb3ILLq.js.map
8991
+ //# sourceMappingURL=index-BD3C-sG-.js.map