@oksigenia/access-panel 0.3.8 → 0.4.1

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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,110 @@
1
+ # @oksigenia/access-panel
2
+
3
+ ## 0.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ Include `CHANGELOG.md` in the published npm tarball. The `files` array in
8
+ `package.json` was an allow-list that excluded the changelog, so consumers
9
+ using `npm view` or reading their installed `node_modules` had no
10
+ visibility into release notes. Pure packaging fix — no runtime change.
11
+
12
+ ## 0.4.0
13
+
14
+ ### Minor Changes
15
+
16
+ - 8d395a3: Add **reading mask** (dark overlay that follows the cursor with a lit reading band, complementary to the existing reading guide), **big targets** (boosts interactive hit-area to 44×44 minimum per WCAG 2.5.5/2.5.8 with `padding` + `min-*` only, no layout-breaking `display` changes), and **4 additive profile presets** (low vision, dyslexia, motor, no distractions) that bundle related toggles in one click. Presets are triggers, not modes — they apply flags and let the user adjust afterwards; a 250 ms flash gives click feedback without a persistent active state.
17
+
18
+ Also fixes a latent Shadow DOM event-target bug in the document-level "click outside the panel" handler. `panel.contains(e.target)` returned `false` for any click originating inside the panel because the target is retargeted to the host element when the event crosses the shadow boundary. Replaced with `e.composedPath()` which is shadow-aware, so the panel no longer closes spuriously on its own button clicks.
19
+
20
+ New fields in `PanelState` (`readingMask`, `bigTargets`), new translation keys for all 8 locales (`mask`, `targets`, `presets`, `pLow`, `pDys`, `pMot`, `pCalm`), and two new SVG icons (`ICON_MASK`, `ICON_TARGETS`).
21
+
22
+ ## 0.3.8
23
+
24
+ ### Patch Changes
25
+
26
+ Mobile panel densified and big-cursor option hidden on touch devices. The WP plugin already did this; the web component lagged behind. Three concrete changes inside the `@media (max-width: 768px)` block:
27
+
28
+ - `.oks-access-opt[data-class="oks-big-cursor"] { display: none; }` — the option only makes sense with a mouse; `pointer: coarse` devices never see it.
29
+ - `.oks-access-opt[data-class="oks-a11y-focus"] { grid-column: span 2; }` — fills the gap left by the hidden cursor button so the grid stays even.
30
+ - Compacted spacing: `min-height` 88 → 72 px (still well above the 44×44 minimum from WCAG 2.5.5), padding 14/8 → 10/8, gap 10 → 8, icons 30 → 26, content padding 16/24 → 14/20, section titles 14/6 → 10/4. Result: all 14 controls fit one screen on common mobile viewports (~640-844 px high) without scrolling.
31
+
32
+ ## 0.3.7
33
+
34
+ ### Patch Changes
35
+
36
+ Real fix for the mobile panel overflow reported on granjaoga.com. The grid `minmax(0, 1fr)` change in 0.3.6 was a red herring — the actual cause was in `positionCss()`. Dynamic position rules (`top: 50%; left: 90px; transform: translateY(-50%)` for `position="mid-left"`, etc.) were injected into the Shadow DOM **after** the mobile `@media (max-width: 768px)` block that puts the panel fullscreen. The dynamic rules sat at the bottom of the stylesheet, so they overrode `top`, `left`, `transform` on mobile too, leaving the panel `width: 100%` but anchored at `left: 90px` — clipping its right side by 90px on narrow viewports. Position rules for `.oks-access-panel` now live inside `@media (min-width: 769px)` so they only apply on desktop. Wrapper (trigger button) rules are unaffected.
37
+
38
+ ## 0.3.6
39
+
40
+ ### Patch Changes
41
+
42
+ Mobile responsive fix: the option grid (`.oks-access-grid`) used `grid-template-columns: 1fr 1fr`, which lets each column grow to its min-content. On narrow viewports, long labels (FUENTE DISLEXIA, LINKS DESTACADOS, INTERLINEADO) pushed the second column off-screen — the right half of the panel was clipped on mobile. Switched to `minmax(0, 1fr) minmax(0, 1fr)`, added `min-width: 0` on `.oks-access-opt` and `overflow-wrap: anywhere; word-break: break-word;` on `.oks-label`. The panel now fits the viewport on every device.
43
+
44
+ ## 0.3.5
45
+
46
+ ### Patch Changes
47
+
48
+ First release published via **npm Trusted Publishing (GitHub Actions OIDC)** instead of a long-lived publish token. Same code as 0.3.4 — this bump exists to validate the OIDC-based publish workflow. The published tarball ships with an [npm provenance attestation](https://docs.npmjs.com/generating-provenance-statements) that links the package back to the exact commit + workflow run that produced it (verifiable in the [sigstore transparency log](https://search.sigstore.dev/)).
49
+
50
+ ## 0.3.4
51
+
52
+ ### Patch Changes
53
+
54
+ - Fix: text-size levels had no visible effect on sites whose CSS sizes things in `rem` (anchored to `<html>`).
55
+
56
+ The 0.3.3 fix moved `oks-zoom-*` from the universal selector to `<body>` with percent values, which only moves descendants that inherit `font-size` from `<body>`. Sites whose CSS uses `rem` (anchored to `<html>`) saw no change at all.
57
+
58
+ Anchor the change at `<html>` via `:has(body.oks-zoom-N)` so the root font-size updates once and every `rem` descendant scales cleanly. No compounding, no missed descendants, hard-coded `px` intentionally left alone.
59
+
60
+ `:has()` is supported in Chrome 105+, Safari 15.4+ and Firefox 121+.
61
+
62
+ ## 0.3.3
63
+
64
+ ### Patch Changes
65
+
66
+ Re-publish of the same content shipped as 0.3.2 below — the 0.3.2 tarball on
67
+ the npm registry went out without the `dist/` directory because the local
68
+ build had errored just before `npm pack` (a stray backtick inside a template
69
+ literal made `tsup` fail) and the publish proceeded anyway. **Do not use
70
+ 0.3.2** — it is missing all compiled output. Use 0.3.3.
71
+
72
+ ## 0.3.2 (broken — DO NOT USE)
73
+
74
+ ### Patch Changes
75
+
76
+ - Fix: Text-size levels (`oks-zoom-1` through `oks-zoom-4`) blew up the layout exponentially.
77
+
78
+ The previous rules applied `font-size: 1.20em !important` to every descendant of `<body>` via `*`. Since `em` is relative to the parent, doing that at every nesting level compounded the factor — a heading three levels deep ended up at `1.20³ = 1.73×` its intended size, which is why headings spilled out of the viewport at level 3 and the page became unusable at level 4.
79
+
80
+ New rules target the `<body>` only with percentage values (10 / 20 / 35 / 50%). `font-size` inherits natively, so descendants using `em` or `rem` scale exactly once. Hard-coded `px` values are intentionally left alone — that's what the browser's own zoom is for.
81
+
82
+ No new API. No behavioural change when the controls are off.
83
+
84
+ ## 0.3.1
85
+
86
+ ### Patch Changes
87
+
88
+ - Fix: reading guide painted a solid black band on top of the text when **High contrast** was also active.
89
+
90
+ The high-contrast mode flips every descendant of `<body>` to `background-color: #000 !important; color: #ff0`. That selector was also catching the reading-guide overlay (`.oks-reading-guide`), overriding its semi-transparent yellow with an opaque black, which defeated the purpose of the feature.
91
+
92
+ Two corrective rules added right after the high-contrast block: the reading guide keeps its translucent yellow background and gets `#ff0` borders (visible on the new black page), and `.oks-overlay-effect` is forced back to `transparent` for the same reason.
93
+
94
+ No behavioural change when high-contrast is off. No new API.
95
+
96
+ ## 0.3.0
97
+
98
+ ### Minor Changes
99
+
100
+ - Expose `--oks-z` CSS custom property to control the trigger and panel z-index from outside the Shadow DOM.
101
+
102
+ Default unchanged (`9999999`). Consumers can lower it to sit below specific modals, or raise it to outrank other floating widgets:
103
+
104
+ ```css
105
+ oksigenia-access-panel {
106
+ --oks-z: 99999;
107
+ }
108
+ ```
109
+
110
+ This makes the z-index deterministic across browsers — previously, attempts to control the trigger's stacking from outside via the host element's z-index were best-effort because the trigger is `position: fixed` inside the Shadow DOM and creates its own stacking context.
package/README.md CHANGED
@@ -6,12 +6,16 @@
6
6
 
7
7
  <img src="https://raw.githubusercontent.com/OksigeniaSL/oksigenia-web-libs/main/packages/access-panel/assets/icon.png" alt="" width="80" align="right" />
8
8
 
9
- Accessibility panel as a web component. Drop in one tag, get 15 controls.
10
-
11
- - **15 controls**: text size (4 levels), line height (3), text alignment (3),
12
- letter spacing (3), readable font toggle, dyslexia font toggle, high contrast,
13
- grayscale overlay, hide images, highlight links, colorblind filters (3 types),
14
- reading guide, big cursor, pause animations, focus outlines.
9
+ Accessibility panel as a web component. Drop in one tag, get 17 controls and
10
+ 4 profile presets.
11
+
12
+ - **17 atomic controls**: text size (4 levels), line height (3), text alignment
13
+ (3), letter spacing (3), readable font toggle, dyslexia font toggle, high
14
+ contrast, grayscale overlay, hide images, highlight links, colorblind filters
15
+ (3 types), reading guide, reading mask, big cursor, big targets (44×44 hit
16
+ area, WCAG 2.5.5), pause animations, focus outlines.
17
+ - **4 profile presets** (additive — pressing several unions their flags):
18
+ low vision, dyslexia, motor, no distractions.
15
19
  - **8 locales**: es, en, gn (Guaraní), fr, it, de, nl, sv.
16
20
  - **Privacy-first**: zero dependencies, no analytics, no remote calls. User
17
21
  preferences persist in `localStorage` only.
@@ -29,7 +33,7 @@ re-packaged as a framework-agnostic web library.
29
33
  ## Screenshot
30
34
 
31
35
  <p align="center">
32
- <img src="https://raw.githubusercontent.com/OksigeniaSL/oksigenia-web-libs/main/packages/access-panel/assets/screenshot.png" alt="Open accessibility panel showing Text, Visual and Orientation sections with 15 controls" width="320" />
36
+ <img src="https://raw.githubusercontent.com/OksigeniaSL/oksigenia-web-libs/main/packages/access-panel/assets/screenshot.png" alt="Open accessibility panel showing profile presets and Text, Visual and Orientation sections" width="320" />
33
37
  </p>
34
38
 
35
39
  ## Install
@@ -103,6 +107,30 @@ If you need to brand the panel itself, fork the package and customize
103
107
  <oksigenia-access-panel locale="es-PY"></oksigenia-access-panel>
104
108
  ```
105
109
 
110
+ ## Use it in Ghost (CMS)
111
+
112
+ Ghost has no plugin system for frontend components, but Code Injection
113
+ covers this case in one snippet. In the admin, go to **Settings → Code
114
+ injection → Site Footer** and paste:
115
+
116
+ ```html
117
+ <oksigenia-access-panel locale="en" position="bottom-left"></oksigenia-access-panel>
118
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@oksigenia/access-panel/dist/web-component.js"></script>
119
+ ```
120
+
121
+ Save. Reload any page on the site — the floating trigger appears.
122
+ Same attributes as above (`locale`, `position`, `trigger-icon`, etc.)
123
+ work as inline attributes on the tag.
124
+
125
+ The snippet above loads the bundle from jsDelivr, which logs requests
126
+ like any third-party CDN. To keep everything first-party, download
127
+ `dist/web-component.js` from npm or GitHub, upload it as a theme asset
128
+ (`assets/access-panel.js` in your active Ghost theme), and point the
129
+ `<script src=…>` at your own domain. Same component, no third-party hop.
130
+
131
+ Discussion on the Ghost forum (questions, issues, feedback):
132
+ <https://forum.ghost.org/t/accessibility-panel-for-ghost-via-code-injection-web-component-45-kb-no-tracking/62940>.
133
+
106
134
  ## Low-level building blocks
107
135
 
108
136
  If you want to render the panel manually or write your own behavior
package/dist/index.d.ts CHANGED
@@ -15,6 +15,8 @@ interface Translation {
15
15
  links: string;
16
16
  ori: string;
17
17
  guide: string;
18
+ mask: string;
19
+ targets: string;
18
20
  cursor: string;
19
21
  pause: string;
20
22
  reset: string;
@@ -22,6 +24,13 @@ interface Translation {
22
24
  ls: string;
23
25
  cb: string;
24
26
  focus: string;
27
+ /** Section title for the preset row. */
28
+ presets: string;
29
+ /** Preset labels. */
30
+ pLow: string;
31
+ pDys: string;
32
+ pMot: string;
33
+ pCalm: string;
25
34
  }
26
35
  declare function getTranslation(locale: string): Translation;
27
36
  declare function supportedLocales(): readonly LocaleCode[];
@@ -68,6 +77,10 @@ interface PanelState {
68
77
  grayOverlay: boolean;
69
78
  /** Guía horizontal de lectura. */
70
79
  readingGuide: boolean;
80
+ /** Máscara de lectura: oscurece todo menos una banda alrededor del cursor. */
81
+ readingMask: boolean;
82
+ /** Aumenta el hit-area de interactivos a 44×44 mínimo (WCAG 2.5.5/2.5.8). */
83
+ bigTargets: boolean;
71
84
  }
72
85
  declare const DEFAULT_STATE: Readonly<PanelState>;
73
86
  declare function loadState(key: string): PanelState;
@@ -85,7 +98,7 @@ interface BehaviorOptions {
85
98
  */
86
99
  declare function bindPanelBehavior(root: ShadowRoot, opts?: BehaviorOptions): () => void;
87
100
 
88
- declare const PANEL_CSS = "\n:host {\n --oks-btn-size: 55px;\n --oks-bg: #000;\n --oks-icon: #fff;\n --oks-h-bg: #fff;\n --oks-h-icon: #000;\n --oks-z: 9999999;\n}\n.oks-access-wrapper {\n position: fixed;\n z-index: var(--oks-z);\n line-height: 1;\n}\n.oks-access-btn {\n width: var(--oks-btn-size);\n height: var(--oks-btn-size);\n border-radius: 50%;\n background: var(--oks-bg);\n color: var(--oks-icon);\n border: 2px solid #fff;\n box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: 0.2s;\n padding: 0;\n}\n.oks-access-btn:hover {\n background: var(--oks-h-bg);\n color: var(--oks-h-icon);\n transform: scale(1.1);\n}\n.oks-access-btn svg {\n fill: currentColor;\n display: block;\n margin: 0 auto;\n width: 60%;\n height: 60%;\n}\n.oks-active-badge {\n position: absolute;\n top: -2px;\n right: -2px;\n width: 20px;\n height: 20px;\n background: #25D366;\n border-radius: 50%;\n border: 2px solid #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n opacity: 0;\n pointer-events: none;\n}\n.oks-active-badge svg { width: 12px; height: 12px; }\n.oks-access-wrapper.has-active .oks-active-badge { opacity: 1; }\n\n.oks-access-panel {\n position: fixed;\n width: 340px;\n max-height: 90vh;\n background: #fff;\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n z-index: var(--oks-z);\n display: flex;\n flex-direction: column;\n opacity: 0;\n pointer-events: none;\n transition: 0.2s;\n border: 1px solid rgba(0,0,0,0.1);\n font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n color: #333;\n}\n.oks-access-panel.is-open { opacity: 1; pointer-events: all; }\n.oks-access-header {\n padding: 15px 20px;\n border-bottom: 1px solid #eee;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.oks-access-header h3 { margin: 0; font-size: 18px; color: #000; }\n.oks-access-close {\n background: #f0f0f0;\n color: #333;\n border: 1px solid #ddd;\n width: 44px;\n height: 44px;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: 0.2s;\n padding: 0;\n}\n.oks-access-close:hover { background: #e0e0e0; border-color: #ccc; }\n.oks-access-close svg { width: 24px; height: 24px; stroke-width: 2.5px; }\n.oks-access-content { padding: 0 20px 20px; overflow-y: auto; }\n.oks-access-title {\n margin: 10px 0 5px;\n font-size: 11px;\n font-weight: 800;\n text-transform: uppercase;\n color: #888;\n}\n.oks-access-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }\n.oks-access-opt {\n background: #f9f9f9;\n border: 2px solid #eee;\n border-radius: 10px;\n padding: 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n min-width: 0;\n min-height: 70px;\n color: #333;\n transition: 0.2s;\n font: inherit;\n}\n.oks-access-opt.full-width { grid-column: span 2; }\n.oks-access-opt.is-active {\n border-color: #000;\n background: #fff;\n box-shadow: 0 0 0 1px #000;\n}\n.oks-access-opt:hover { background: #000; color: #fff; border-color: #000; }\n.oks-icon { font-size: 28px; margin-bottom: 3px; display: block; line-height: 1; }\n.oks-icon svg { width: 24px; height: 24px; fill: currentColor; }\n.oks-label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n text-align: center;\n line-height: 1.2;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n.oks-levels { display: flex; gap: 3px; height: 5px; width: 50%; margin-top: 5px; }\n.oks-levels span { flex: 1; background: #ddd; border-radius: 3px; }\n.oks-access-opt[data-level=\"1\"] .oks-levels span:nth-child(1),\n.oks-access-opt[data-level=\"2\"] .oks-levels span:nth-child(-n+2),\n.oks-access-opt[data-level=\"3\"] .oks-levels span:nth-child(-n+3),\n.oks-access-opt[data-level=\"4\"] .oks-levels span:nth-child(-n+4) { background: #000; }\n.oks-access-opt:hover .oks-levels span { background: #555; }\n.oks-access-footer {\n padding: 12px 20px;\n border-top: 1px solid #eee;\n text-align: center;\n}\n.oks-access-reset {\n width: 100%;\n padding: 8px;\n border: 2px solid #000;\n color: #000;\n background: transparent;\n font-weight: 700;\n cursor: pointer;\n border-radius: 6px;\n font-size: 12px;\n}\n.oks-access-reset:hover { background: #000; color: #fff; }\n.oks-access-branding { margin-top: 12px; font-size: 12px; color: #000; font-weight: 700; }\n.oks-access-branding a { color: #000; text-decoration: none; border-bottom: 1px dotted #000; }\n\n@media (max-width: 768px) {\n .oks-access-panel {\n width: 100%; height: 100%; max-height: 100%;\n top: 0; left: 0; right: 0; bottom: 0;\n border-radius: 0;\n }\n .oks-access-opt { min-height: 72px; padding: 10px 8px; }\n .oks-icon svg { width: 26px; height: 26px; }\n .oks-label { font-size: 12px; line-height: 1.25; }\n .oks-access-grid { gap: 8px; }\n .oks-access-content { padding: 0 14px 20px; }\n .oks-access-title { font-size: 11px; margin: 10px 0 4px; }\n /* Cursor grande no aplica en t\u00E1ctil: oculto y dejo el \u00FAltimo bot\u00F3n\n de la secci\u00F3n ocupando 2 columnas para no romper la grilla par. */\n .oks-access-opt[data-class=\"oks-big-cursor\"] { display: none; }\n .oks-access-opt[data-class=\"oks-a11y-focus\"] { grid-column: span 2; }\n .oks-access-reset { padding: 14px; font-size: 14px; }\n}\n";
89
- declare const EFFECT_CSS = "\nhtml.oks-colorblind-1 { filter: url('#oks-filter-protanopia'); }\nhtml.oks-colorblind-2 { filter: url('#oks-filter-deuteranopia'); }\nhtml.oks-colorblind-3 { filter: url('#oks-filter-tritanopia'); }\n\n/* Text-size levels.\n Applied to <html> via :has(), not to <body>. rem is anchored to the root\n element, so a site whose CSS sizes things in rem (most modern Astro / Tailwind\n builds) needs the root font-size to change for the scale to take effect.\n A previous version applied this to body with %, which only moved descendants\n that inherited font-size from body \u2014 anything sized in rem stayed locked to\n the 16px default of <html>. An even earlier version used the universal\n selector with em and compounded the factor at every nesting level.\n :has(body.oks-zoom-N) is the right anchor: one change at the root, rem\n descendants scale exactly once. Hard-coded px is intentionally left alone;\n browser zoom covers that case. */\nhtml:has(body.oks-zoom-1) { font-size: 110% !important; }\nhtml:has(body.oks-zoom-2) { font-size: 120% !important; }\nhtml:has(body.oks-zoom-3) { font-size: 135% !important; }\nhtml:has(body.oks-zoom-4) { font-size: 150% !important; }\n\nbody.oks-lh-1 * { line-height: 1.6 !important; }\nbody.oks-lh-2 * { line-height: 1.9 !important; }\nbody.oks-lh-3 * { line-height: 2.2 !important; }\n\nbody.oks-a11y-font { font-family: Arial, sans-serif !important; }\n\nbody.oks-dyslexia * {\n font-family: 'Comic Sans MS', 'Verdana', sans-serif !important;\n letter-spacing: 0.05em !important;\n word-spacing: 0.1em !important;\n line-height: 1.6 !important;\n}\n\nbody.oks-a11y-hide img { opacity: 0 !important; visibility: hidden !important; }\nbody.oks-a11y-links a { text-decoration: underline !important; background: #ff0 !important; color: #000 !important; }\n\nbody.oks-align-1 * { text-align: left !important; }\nbody.oks-align-2 * { text-align: center !important; }\nbody.oks-align-3 * { text-align: right !important; }\n\nbody.oks-a11y-pause * { animation: none !important; transition: none !important; }\n\nbody.oks-ls-1 * { letter-spacing: 0.05em !important; }\nbody.oks-ls-2 * { letter-spacing: 0.10em !important; }\nbody.oks-ls-3 * { letter-spacing: 0.16em !important; }\n\nbody.oks-a11y-focus a:not(oksigenia-access-panel):not(oksigenia-access-panel *),\nbody.oks-a11y-focus button:not(oksigenia-access-panel):not(oksigenia-access-panel *),\nbody.oks-a11y-focus input,\nbody.oks-a11y-focus select,\nbody.oks-a11y-focus textarea {\n outline: 2px dashed rgba(0, 95, 204, 0.45) !important;\n outline-offset: 2px !important;\n}\nbody.oks-a11y-focus *:focus-visible {\n outline: 3px solid #005fcc !important;\n outline-offset: 3px !important;\n box-shadow: 0 0 0 6px rgba(0, 95, 204, 0.25) !important;\n}\n\nbody.oks-a11y-contrast.oks-a11y-focus *:focus,\nbody.oks-a11y-contrast.oks-a11y-focus *:focus-visible {\n outline-color: #0ff !important;\n box-shadow: 0 0 0 6px rgba(0, 255, 255, 0.3) !important;\n}\n\n@media (pointer: fine) {\n body.oks-big-cursor, body.oks-big-cursor a, body.oks-big-cursor button {\n cursor: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='48' viewBox='0 0 24 24'%3E%3Cpath d='M4 2L4 18L8 14L11 21L14 19.5L11 13L15.5 13Z' stroke='white' stroke-width='4' stroke-linejoin='round' fill='white'/%3E%3Cpath d='M4 2L4 18L8 14L11 21L14 19.5L11 13L15.5 13Z' fill='black'/%3E%3C/svg%3E\") 8 4, auto !important;\n }\n}\n\nbody.oks-a11y-contrast,\nbody.oks-a11y-contrast *:not(oksigenia-access-panel):not(oksigenia-access-panel *) {\n background-color: #000 !important;\n color: #ff0 !important;\n border-color: #ff0 !important;\n text-shadow: none !important;\n box-shadow: none !important;\n}\nbody.oks-a11y-contrast img { filter: grayscale(100%) contrast(120%) !important; }\nbody.oks-a11y-contrast a:not(oksigenia-access-panel *) { color: #0ff !important; text-decoration: underline !important; }\n\n/* High-contrast applies background:#000 to every descendant of body to flip\n the page to inverted colours. That selector also catches our own overlays\n (.oks-reading-guide, .oks-overlay-effect), which would then paint a solid\n black band on top of the text and defeat their purpose. Restore the\n overlay-specific values here so they keep working in high-contrast mode. */\nbody.oks-a11y-contrast .oks-reading-guide {\n background-color: rgba(255, 255, 0, 0.25) !important;\n border-top-color: #ff0 !important;\n border-bottom-color: #ff0 !important;\n}\nbody.oks-a11y-contrast .oks-overlay-effect {\n background-color: transparent !important;\n}\n\n.oks-overlay-effect {\n position: fixed; top: 0; left: 0;\n width: 100%; height: 100%;\n pointer-events: none;\n z-index: 999990;\n display: none;\n backdrop-filter: grayscale(100%);\n}\n.oks-overlay-effect.is-active { display: block; }\n\n.oks-reading-guide {\n position: fixed; left: 0;\n width: 100%; height: 50px;\n background: rgba(255, 255, 0, 0.2);\n border-top: 3px solid red;\n border-bottom: 3px solid red;\n pointer-events: none;\n z-index: 2147483647;\n display: none;\n transform: translateY(-50%);\n}\nbody.oks-a11y-guide .oks-reading-guide { display: block; }\n";
101
+ declare const PANEL_CSS = "\n:host {\n --oks-btn-size: 55px;\n --oks-bg: #000;\n --oks-icon: #fff;\n --oks-h-bg: #fff;\n --oks-h-icon: #000;\n --oks-z: 9999999;\n}\n.oks-access-wrapper {\n position: fixed;\n z-index: var(--oks-z);\n line-height: 1;\n}\n.oks-access-btn {\n width: var(--oks-btn-size);\n height: var(--oks-btn-size);\n border-radius: 50%;\n background: var(--oks-bg);\n color: var(--oks-icon);\n border: 2px solid #fff;\n box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: 0.2s;\n padding: 0;\n}\n.oks-access-btn:hover {\n background: var(--oks-h-bg);\n color: var(--oks-h-icon);\n transform: scale(1.1);\n}\n.oks-access-btn svg {\n fill: currentColor;\n display: block;\n margin: 0 auto;\n width: 60%;\n height: 60%;\n}\n.oks-active-badge {\n position: absolute;\n top: -2px;\n right: -2px;\n width: 20px;\n height: 20px;\n background: #25D366;\n border-radius: 50%;\n border: 2px solid #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n opacity: 0;\n pointer-events: none;\n}\n.oks-active-badge svg { width: 12px; height: 12px; }\n.oks-access-wrapper.has-active .oks-active-badge { opacity: 1; }\n\n.oks-access-panel {\n position: fixed;\n width: 340px;\n max-height: 90vh;\n background: #fff;\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n z-index: var(--oks-z);\n display: flex;\n flex-direction: column;\n opacity: 0;\n pointer-events: none;\n transition: 0.2s;\n border: 1px solid rgba(0,0,0,0.1);\n font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n color: #333;\n}\n.oks-access-panel.is-open { opacity: 1; pointer-events: all; }\n.oks-access-header {\n padding: 15px 20px;\n border-bottom: 1px solid #eee;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.oks-access-header h3 { margin: 0; font-size: 18px; color: #000; }\n.oks-access-close {\n background: #f0f0f0;\n color: #333;\n border: 1px solid #ddd;\n width: 44px;\n height: 44px;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: 0.2s;\n padding: 0;\n}\n.oks-access-close:hover { background: #e0e0e0; border-color: #ccc; }\n.oks-access-close svg { width: 24px; height: 24px; stroke-width: 2.5px; }\n.oks-access-content { padding: 0 20px 20px; overflow-y: auto; }\n.oks-access-title {\n margin: 10px 0 5px;\n font-size: 11px;\n font-weight: 800;\n text-transform: uppercase;\n color: #888;\n}\n.oks-access-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }\n.oks-access-presets { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }\n.oks-preset {\n background: #f0f4f8;\n border: 2px solid transparent;\n border-radius: 8px;\n padding: 8px 4px;\n display: flex;\n flex-direction: column;\n align-items: center;\n cursor: pointer;\n font: inherit;\n color: #333;\n min-width: 0;\n transition: 0.15s;\n}\n.oks-preset:hover { background: #000; color: #fff; }\n.oks-preset:focus-visible { outline: 2px solid #000; outline-offset: 2px; }\n/* Click feedback: a 250 ms flip + slight squeeze. Pure transient \u2014 the\n button does not carry persistent active state because a preset is a\n trigger, not a mode. */\n.oks-preset.is-flashing {\n background: #000;\n color: #fff;\n transform: scale(0.96);\n}\n.oks-preset .oks-icon { font-size: 22px; margin-bottom: 4px; }\n.oks-preset .oks-icon svg { width: 20px; height: 20px; }\n.oks-preset .oks-label {\n font-size: 10px; font-weight: 700; text-transform: uppercase;\n text-align: center; line-height: 1.15;\n overflow-wrap: anywhere; word-break: break-word;\n /* Reserve room for 2 lines so 1-line labels (DISLEXIA, MOTOR) and\n 2-line labels (BAJA VISI\u00D3N, SIN DISTRAC.) end up the same height,\n centred. Without this the row looks ragged. */\n min-height: 2.3em;\n display: flex; align-items: center; justify-content: center;\n}\n.oks-access-opt {\n background: #f9f9f9;\n border: 2px solid #eee;\n border-radius: 10px;\n padding: 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n min-width: 0;\n min-height: 70px;\n color: #333;\n transition: 0.2s;\n font: inherit;\n}\n.oks-access-opt.full-width { grid-column: span 2; }\n.oks-access-opt.is-active {\n border-color: #000;\n background: #fff;\n box-shadow: 0 0 0 1px #000;\n}\n.oks-access-opt:hover { background: #000; color: #fff; border-color: #000; }\n.oks-icon { font-size: 28px; margin-bottom: 3px; display: block; line-height: 1; }\n.oks-icon svg { width: 24px; height: 24px; fill: currentColor; }\n.oks-label {\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n text-align: center;\n line-height: 1.2;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n.oks-levels { display: flex; gap: 3px; height: 5px; width: 50%; margin-top: 5px; }\n.oks-levels span { flex: 1; background: #ddd; border-radius: 3px; }\n.oks-access-opt[data-level=\"1\"] .oks-levels span:nth-child(1),\n.oks-access-opt[data-level=\"2\"] .oks-levels span:nth-child(-n+2),\n.oks-access-opt[data-level=\"3\"] .oks-levels span:nth-child(-n+3),\n.oks-access-opt[data-level=\"4\"] .oks-levels span:nth-child(-n+4) { background: #000; }\n.oks-access-opt:hover .oks-levels span { background: #555; }\n.oks-access-footer {\n padding: 12px 20px;\n border-top: 1px solid #eee;\n text-align: center;\n}\n.oks-access-reset {\n width: 100%;\n padding: 8px;\n border: 2px solid #000;\n color: #000;\n background: transparent;\n font-weight: 700;\n cursor: pointer;\n border-radius: 6px;\n font-size: 12px;\n}\n.oks-access-reset:hover { background: #000; color: #fff; }\n.oks-access-branding { margin-top: 12px; font-size: 12px; color: #000; font-weight: 700; }\n.oks-access-branding a { color: #000; text-decoration: none; border-bottom: 1px dotted #000; }\n\n@media (max-width: 768px) {\n .oks-access-panel {\n width: 100%; height: 100%; max-height: 100%;\n top: 0; left: 0; right: 0; bottom: 0;\n border-radius: 0;\n }\n .oks-access-opt { min-height: 72px; padding: 10px 8px; }\n .oks-icon svg { width: 26px; height: 26px; }\n .oks-label { font-size: 12px; line-height: 1.25; }\n .oks-access-grid { gap: 8px; }\n .oks-access-content { padding: 0 14px 20px; }\n .oks-access-title { font-size: 11px; margin: 10px 0 4px; }\n /* Cursor grande no aplica en t\u00E1ctil: oculto y dejo el \u00FAltimo bot\u00F3n\n de la secci\u00F3n ocupando 2 columnas para no romper la grilla par. */\n .oks-access-opt[data-class=\"oks-big-cursor\"] { display: none; }\n .oks-access-opt[data-class=\"oks-a11y-focus\"] { grid-column: span 2; }\n .oks-access-reset { padding: 14px; font-size: 14px; }\n}\n";
102
+ declare const EFFECT_CSS = "\nhtml.oks-colorblind-1 { filter: url('#oks-filter-protanopia'); }\nhtml.oks-colorblind-2 { filter: url('#oks-filter-deuteranopia'); }\nhtml.oks-colorblind-3 { filter: url('#oks-filter-tritanopia'); }\n\n/* Text-size levels.\n Applied to <html> via :has(), not to <body>. rem is anchored to the root\n element, so a site whose CSS sizes things in rem (most modern Astro / Tailwind\n builds) needs the root font-size to change for the scale to take effect.\n A previous version applied this to body with %, which only moved descendants\n that inherited font-size from body \u2014 anything sized in rem stayed locked to\n the 16px default of <html>. An even earlier version used the universal\n selector with em and compounded the factor at every nesting level.\n :has(body.oks-zoom-N) is the right anchor: one change at the root, rem\n descendants scale exactly once. Hard-coded px is intentionally left alone;\n browser zoom covers that case. */\nhtml:has(body.oks-zoom-1) { font-size: 110% !important; }\nhtml:has(body.oks-zoom-2) { font-size: 120% !important; }\nhtml:has(body.oks-zoom-3) { font-size: 135% !important; }\nhtml:has(body.oks-zoom-4) { font-size: 150% !important; }\n\nbody.oks-lh-1 * { line-height: 1.6 !important; }\nbody.oks-lh-2 * { line-height: 1.9 !important; }\nbody.oks-lh-3 * { line-height: 2.2 !important; }\n\nbody.oks-a11y-font { font-family: Arial, sans-serif !important; }\n\nbody.oks-dyslexia * {\n font-family: 'Comic Sans MS', 'Verdana', sans-serif !important;\n letter-spacing: 0.05em !important;\n word-spacing: 0.1em !important;\n line-height: 1.6 !important;\n}\n\nbody.oks-a11y-hide img { opacity: 0 !important; visibility: hidden !important; }\nbody.oks-a11y-links a { text-decoration: underline !important; background: #ff0 !important; color: #000 !important; }\n\nbody.oks-align-1 * { text-align: left !important; }\nbody.oks-align-2 * { text-align: center !important; }\nbody.oks-align-3 * { text-align: right !important; }\n\nbody.oks-a11y-pause * { animation: none !important; transition: none !important; }\n\nbody.oks-ls-1 * { letter-spacing: 0.05em !important; }\nbody.oks-ls-2 * { letter-spacing: 0.10em !important; }\nbody.oks-ls-3 * { letter-spacing: 0.16em !important; }\n\nbody.oks-a11y-focus a:not(oksigenia-access-panel):not(oksigenia-access-panel *),\nbody.oks-a11y-focus button:not(oksigenia-access-panel):not(oksigenia-access-panel *),\nbody.oks-a11y-focus input,\nbody.oks-a11y-focus select,\nbody.oks-a11y-focus textarea {\n outline: 2px dashed rgba(0, 95, 204, 0.45) !important;\n outline-offset: 2px !important;\n}\nbody.oks-a11y-focus *:focus-visible {\n outline: 3px solid #005fcc !important;\n outline-offset: 3px !important;\n box-shadow: 0 0 0 6px rgba(0, 95, 204, 0.25) !important;\n}\n\nbody.oks-a11y-contrast.oks-a11y-focus *:focus,\nbody.oks-a11y-contrast.oks-a11y-focus *:focus-visible {\n outline-color: #0ff !important;\n box-shadow: 0 0 0 6px rgba(0, 255, 255, 0.3) !important;\n}\n\n@media (pointer: fine) {\n body.oks-big-cursor, body.oks-big-cursor a, body.oks-big-cursor button {\n cursor: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='48' viewBox='0 0 24 24'%3E%3Cpath d='M4 2L4 18L8 14L11 21L14 19.5L11 13L15.5 13Z' stroke='white' stroke-width='4' stroke-linejoin='round' fill='white'/%3E%3Cpath d='M4 2L4 18L8 14L11 21L14 19.5L11 13L15.5 13Z' fill='black'/%3E%3C/svg%3E\") 8 4, auto !important;\n }\n}\n\nbody.oks-a11y-contrast,\nbody.oks-a11y-contrast *:not(oksigenia-access-panel):not(oksigenia-access-panel *) {\n background-color: #000 !important;\n color: #ff0 !important;\n border-color: #ff0 !important;\n text-shadow: none !important;\n box-shadow: none !important;\n}\nbody.oks-a11y-contrast img { filter: grayscale(100%) contrast(120%) !important; }\nbody.oks-a11y-contrast a:not(oksigenia-access-panel *) { color: #0ff !important; text-decoration: underline !important; }\n\n/* High-contrast applies background:#000 to every descendant of body to flip\n the page to inverted colours. That selector also catches our own overlays\n (.oks-reading-guide, .oks-overlay-effect), which would then paint a solid\n black band on top of the text and defeat their purpose. Restore the\n overlay-specific values here so they keep working in high-contrast mode. */\nbody.oks-a11y-contrast .oks-reading-guide {\n background-color: rgba(255, 255, 0, 0.25) !important;\n border-top-color: #ff0 !important;\n border-bottom-color: #ff0 !important;\n}\nbody.oks-a11y-contrast .oks-overlay-effect {\n background-color: transparent !important;\n}\n\n.oks-overlay-effect {\n position: fixed; top: 0; left: 0;\n width: 100%; height: 100%;\n pointer-events: none;\n z-index: 999990;\n display: none;\n backdrop-filter: grayscale(100%);\n}\n.oks-overlay-effect.is-active { display: block; }\n\n.oks-reading-guide {\n position: fixed; left: 0;\n width: 100%; height: 50px;\n background: rgba(255, 255, 0, 0.2);\n border-top: 3px solid red;\n border-bottom: 3px solid red;\n pointer-events: none;\n z-index: 2147483647;\n display: none;\n transform: translateY(-50%);\n}\nbody.oks-a11y-guide .oks-reading-guide { display: block; }\n\n/* Reading mask: dark overlay leaving a horizontal band lit around the cursor.\n --oks-mask-y is updated from JS on mousemove; band is \u00B190px around it. */\n.oks-reading-mask {\n position: fixed; top: 0; left: 0;\n width: 100vw; height: 100vh;\n pointer-events: none;\n z-index: 2147483646;\n background: rgba(0, 0, 0, 0.75);\n display: none;\n clip-path: polygon(\n 0 0, 100% 0,\n 100% calc(var(--oks-mask-y, 50vh) - 90px),\n 0 calc(var(--oks-mask-y, 50vh) - 90px),\n 0 calc(var(--oks-mask-y, 50vh) + 90px),\n 100% calc(var(--oks-mask-y, 50vh) + 90px),\n 100% 100%, 0 100%\n );\n}\nbody.oks-a11y-mask .oks-reading-mask { display: block; }\nbody.oks-a11y-contrast .oks-reading-mask { background-color: rgba(0, 0, 0, 0.85) !important; }\n\n/* Big targets: bump interactive hit-areas to WCAG 2.5.5 (44\u00D744 minimum).\n Only adjusts padding + min-* \u2014 never display, so layouts that rely on\n inline flow or grid placement survive. Exempts our own shadow-DOM host. */\nbody.oks-a11y-bigtargets a:not(oksigenia-access-panel):not(oksigenia-access-panel *),\nbody.oks-a11y-bigtargets button:not(oksigenia-access-panel):not(oksigenia-access-panel *),\nbody.oks-a11y-bigtargets [role=\"button\"]:not(oksigenia-access-panel):not(oksigenia-access-panel *),\nbody.oks-a11y-bigtargets input[type=\"checkbox\"]:not(oksigenia-access-panel):not(oksigenia-access-panel *),\nbody.oks-a11y-bigtargets input[type=\"radio\"]:not(oksigenia-access-panel):not(oksigenia-access-panel *),\nbody.oks-a11y-bigtargets summary:not(oksigenia-access-panel):not(oksigenia-access-panel *) {\n min-height: 44px !important;\n min-width: 44px !important;\n padding: 8px 12px !important;\n box-sizing: border-box !important;\n}\n";
90
103
 
91
104
  export { type BehaviorOptions, COLORBLIND_FILTERS_SVG, DEFAULT_STATE, EFFECT_CSS, type LocaleCode, PANEL_CSS, type PanelState, type Position, type Translation, type TriggerIcon, bindPanelBehavior, buildPanelHtml, getTranslation, isStateEmpty, loadState, positionCss, saveState, supportedLocales };
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  // src/translations.ts
2
2
  var DICT = {
3
- es: { title: "Accesibilidad", close: "Cerrar", txt: "Texto", size: "Tama\xF1o", lh: "Interlineado", align: "Alineaci\xF3n", font: "Legible", dyslexia: "Fuente Dislexia", vis: "Visual", contrast: "Contraste", gray: "Grises", hide: "Ocultar Img", links: "Links", ori: "Orientaci\xF3n", guide: "Gu\xEDa", cursor: "Cursor Grande", pause: "Parar Animac.", reset: "Restablecer Todo", dev: "Desarrollado por", ls: "Espaciado", cb: "Daltonismo", focus: "Foco" },
4
- en: { title: "Accessibility", close: "Close", txt: "Text", size: "Size", lh: "Line Height", align: "Align", font: "Readable Font", dyslexia: "Dyslexia Font", vis: "Visual", contrast: "Contrast", gray: "Grayscale", hide: "Hide Images", links: "Highlight Links", ori: "Orientation", guide: "Reading Guide", cursor: "Big Cursor", pause: "Pause Anim.", reset: "Reset All", dev: "Developed by", ls: "Letter Spacing", cb: "Color Blind", focus: "Focus" },
5
- gn: { title: "Oikeha (Accesibilidad)", close: "Mboty", txt: "Mo\xF1e'\u1EBDr\xE3", size: "Tuichakue", lh: "Jei", align: "Mbojoja", font: "Letra Por\xE3", dyslexia: "Dislexia", vis: "Hechapy", contrast: "Sa'y", gray: "H\u0169 ha T\u0129", hide: "Moka\xF1y Ta'anga", links: "Joajuha", ori: "S\xE3mbyhy", guide: "S\xE3mbyhyha", cursor: "Cursor Guasu", pause: "Mboopyta", reset: "Mbojevy", dev: "Apojare", ls: "Rapykue", cb: "Sa'yvy", focus: "\xD1emoha" },
6
- fr: { title: "Accessibilit\xE9", close: "Fermer", txt: "Texte", size: "Taille", lh: "Interligne", align: "Alignement", font: "Police Lisible", dyslexia: "Police Dyslexie", vis: "Visuel", contrast: "Contraste", gray: "Niveaux Gris", hide: "Masquer Img", links: "Liens", ori: "Orientation", guide: "Guide Lecture", cursor: "Grand Curseur", pause: "Pause Anim.", reset: "R\xE9initialiser", dev: "D\xE9velopp\xE9 par", ls: "Espacement", cb: "Daltonisme", focus: "Focus" },
7
- it: { title: "Accessibilit\xE0", close: "Chiudi", txt: "Testo", size: "Dimensione", lh: "Interlinea", align: "Allineamento", font: "Leggibile", dyslexia: "Font Dislessia", vis: "Visivo", contrast: "Contrasto", gray: "Scala Grig.", hide: "Nascondi Img", links: "Link", ori: "Orientamento", guide: "Guida", cursor: "Cursore Grande", pause: "Pausa Anim.", reset: "Reimposta", dev: "Sviluppato da", ls: "Spaziatura", cb: "Daltonismo", focus: "Focus" },
8
- de: { title: "Barrierefreiheit", close: "Schlie\xDFen", txt: "Text", size: "Gr\xF6\xDFe", lh: "Zeilenh\xF6he", align: "Ausrichtung", font: "Lesbar", dyslexia: "Dyslexie", vis: "Visuell", contrast: "Kontrast", gray: "Graustufen", hide: "Bilder Aus", links: "Links", ori: "Orientierung", guide: "Lesehilfe", cursor: "Gro\xDFer Cursor", pause: "Anim. Stopp", reset: "Zur\xFCcksetzen", dev: "Entwickelt von", ls: "Buchst.abst.", cb: "Farbblindheit", focus: "Fokus" },
9
- nl: { title: "Toegankelijkheid", close: "Sluiten", txt: "Tekst", size: "Grootte", lh: "Regelhoogte", align: "Uitlijning", font: "Leesbaar", dyslexia: "Dyslexie", vis: "Visueel", contrast: "Contrast", gray: "Grijstinten", hide: "Verberg Afb.", links: "Links", ori: "Ori\xEBntatie", guide: "Leesgids", cursor: "Grote Cursor", pause: "Anim. Pauze", reset: "Resetten", dev: "Ontwikkeld door", ls: "Letterspatie", cb: "Kleurenblind", focus: "Focus" },
10
- sv: { title: "Tillg\xE4nglighet", close: "St\xE4ng", txt: "Text", size: "Storlek", lh: "Radh\xF6jd", align: "Justering", font: "L\xE4sbar", dyslexia: "Dyslexi", vis: "Visuell", contrast: "Kontrast", gray: "Gr\xE5skala", hide: "D\xF6lj Bilder", links: "L\xE4nkar", ori: "Orientering", guide: "L\xE4slinjal", cursor: "Stor Mark\xF6r", pause: "Pausa Anim.", reset: "\xC5terst\xE4ll", dev: "Utvecklad av", ls: "Bokstavsavst.", cb: "F\xE4rgblindhet", focus: "Fokus" }
3
+ es: { title: "Accesibilidad", close: "Cerrar", txt: "Texto", size: "Tama\xF1o", lh: "Interlineado", align: "Alineaci\xF3n", font: "Legible", dyslexia: "Fuente Dislexia", vis: "Visual", contrast: "Contraste", gray: "Grises", hide: "Ocultar Img", links: "Links", ori: "Orientaci\xF3n", guide: "Gu\xEDa", mask: "M\xE1scara", targets: "\xC1reas Grandes", cursor: "Cursor Grande", pause: "Parar Animac.", reset: "Restablecer Todo", dev: "Desarrollado por", ls: "Espaciado", cb: "Daltonismo", focus: "Foco", presets: "Perfiles", pLow: "Baja Visi\xF3n", pDys: "Dislexia", pMot: "Motor", pCalm: "Sin Distrac." },
4
+ en: { title: "Accessibility", close: "Close", txt: "Text", size: "Size", lh: "Line Height", align: "Align", font: "Readable Font", dyslexia: "Dyslexia Font", vis: "Visual", contrast: "Contrast", gray: "Grayscale", hide: "Hide Images", links: "Highlight Links", ori: "Orientation", guide: "Reading Guide", mask: "Reading Mask", targets: "Big Targets", cursor: "Big Cursor", pause: "Pause Anim.", reset: "Reset All", dev: "Developed by", ls: "Letter Spacing", cb: "Color Blind", focus: "Focus", presets: "Profiles", pLow: "Low Vision", pDys: "Dyslexia", pMot: "Motor", pCalm: "No Distract." },
5
+ gn: { title: "Oikeha (Accesibilidad)", close: "Mboty", txt: "Mo\xF1e'\u1EBDr\xE3", size: "Tuichakue", lh: "Jei", align: "Mbojoja", font: "Letra Por\xE3", dyslexia: "Dislexia", vis: "Hechapy", contrast: "Sa'y", gray: "H\u0169 ha T\u0129", hide: "Moka\xF1y Ta'anga", links: "Joajuha", ori: "S\xE3mbyhy", guide: "S\xE3mbyhyha", mask: "Mbohov\xE1i", targets: "Tenda Guasu", cursor: "Cursor Guasu", pause: "Mboopyta", reset: "Mbojevy", dev: "Apojare", ls: "Rapykue", cb: "Sa'yvy", focus: "\xD1emoha", presets: "Tekor\xE3", pLow: "Hechapy Vai", pDys: "Dislexia", pMot: "Po-rehegua", pCalm: "Py\u02BCa Guapy" },
6
+ fr: { title: "Accessibilit\xE9", close: "Fermer", txt: "Texte", size: "Taille", lh: "Interligne", align: "Alignement", font: "Police Lisible", dyslexia: "Police Dyslexie", vis: "Visuel", contrast: "Contraste", gray: "Niveaux Gris", hide: "Masquer Img", links: "Liens", ori: "Orientation", guide: "Guide Lecture", mask: "Masque Lecture", targets: "Grandes Cibles", cursor: "Grand Curseur", pause: "Pause Anim.", reset: "R\xE9initialiser", dev: "D\xE9velopp\xE9 par", ls: "Espacement", cb: "Daltonisme", focus: "Focus", presets: "Profils", pLow: "Basse Vision", pDys: "Dyslexie", pMot: "Moteur", pCalm: "Sans Distrac." },
7
+ it: { title: "Accessibilit\xE0", close: "Chiudi", txt: "Testo", size: "Dimensione", lh: "Interlinea", align: "Allineamento", font: "Leggibile", dyslexia: "Font Dislessia", vis: "Visivo", contrast: "Contrasto", gray: "Scala Grig.", hide: "Nascondi Img", links: "Link", ori: "Orientamento", guide: "Guida", mask: "Maschera", targets: "Aree Grandi", cursor: "Cursore Grande", pause: "Pausa Anim.", reset: "Reimposta", dev: "Sviluppato da", ls: "Spaziatura", cb: "Daltonismo", focus: "Focus", presets: "Profili", pLow: "Ipovisione", pDys: "Dislessia", pMot: "Motorio", pCalm: "No Distraz." },
8
+ de: { title: "Barrierefreiheit", close: "Schlie\xDFen", txt: "Text", size: "Gr\xF6\xDFe", lh: "Zeilenh\xF6he", align: "Ausrichtung", font: "Lesbar", dyslexia: "Dyslexie", vis: "Visuell", contrast: "Kontrast", gray: "Graustufen", hide: "Bilder Aus", links: "Links", ori: "Orientierung", guide: "Lesehilfe", mask: "Lesemaske", targets: "Gro\xDFe Ziele", cursor: "Gro\xDFer Cursor", pause: "Anim. Stopp", reset: "Zur\xFCcksetzen", dev: "Entwickelt von", ls: "Buchst.abst.", cb: "Farbblindheit", focus: "Fokus", presets: "Profile", pLow: "Sehschw\xE4che", pDys: "Dyslexie", pMot: "Motorik", pCalm: "Ohne Ablenk." },
9
+ nl: { title: "Toegankelijkheid", close: "Sluiten", txt: "Tekst", size: "Grootte", lh: "Regelhoogte", align: "Uitlijning", font: "Leesbaar", dyslexia: "Dyslexie", vis: "Visueel", contrast: "Contrast", gray: "Grijstinten", hide: "Verberg Afb.", links: "Links", ori: "Ori\xEBntatie", guide: "Leesgids", mask: "Leesmasker", targets: "Grote Doelen", cursor: "Grote Cursor", pause: "Anim. Pauze", reset: "Resetten", dev: "Ontwikkeld door", ls: "Letterspatie", cb: "Kleurenblind", focus: "Focus", presets: "Profielen", pLow: "Slechtziend", pDys: "Dyslexie", pMot: "Motoriek", pCalm: "Geen Afleid." },
10
+ sv: { title: "Tillg\xE4nglighet", close: "St\xE4ng", txt: "Text", size: "Storlek", lh: "Radh\xF6jd", align: "Justering", font: "L\xE4sbar", dyslexia: "Dyslexi", vis: "Visuell", contrast: "Kontrast", gray: "Gr\xE5skala", hide: "D\xF6lj Bilder", links: "L\xE4nkar", ori: "Orientering", guide: "L\xE4slinjal", mask: "L\xE4smask", targets: "Stora Ytor", cursor: "Stor Mark\xF6r", pause: "Pausa Anim.", reset: "\xC5terst\xE4ll", dev: "Utvecklad av", ls: "Bokstavsavst.", cb: "F\xE4rgblindhet", focus: "Fokus", presets: "Profiler", pLow: "Synneds\xE4tt.", pDys: "Dyslexi", pMot: "Motorik", pCalm: "Inga Distrak." }
11
11
  };
12
12
  function getTranslation(locale) {
13
13
  const lc = locale.toLowerCase();
@@ -35,6 +35,8 @@ var ICON_PAUSE = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M6 19h4V
35
35
  var ICON_LS = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M5 5v14h2V5H5zm4 0v14h2V5H9zm4 4v6h2V9h-2zm4-4v14h2V5h-2z"/></svg>';
36
36
  var ICON_COLORBLIND = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></svg>';
37
37
  var ICON_FOCUS = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 7V3h4v2H5v2H3zm14-4h4v4h-2V5h-2V3zm4 14v4h-4v-2h2v-2h2zM7 21H3v-4h2v2h2v2z"/></svg>';
38
+ var ICON_MASK = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M2 4h20v6H2zm0 10h20v6H2zm2-9v4h16V5zm0 10v4h16v-4z" opacity=".55"/><rect x="2" y="10" width="20" height="4"/></svg>';
39
+ var ICON_TARGETS = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 3h4v2H5v2H3zm14 0h4v4h-2V5h-2zm0 18v-2h2v-2h2v4zM3 21v-4h2v2h2v2zM12 8a4 4 0 100 8 4 4 0 000-8zm0 2a2 2 0 110 4 2 2 0 010-4z"/></svg>';
38
40
  var TRIGGER_ICONS = {
39
41
  vitruvian: '<svg viewBox="0 0 122.88 122.88" fill="currentColor"><path d="M61.44,0A61.46,61.46,0,1,1,18,18,61.21,61.21,0,0,1,61.44,0Zm-.39,74.18L52.1,98.91a4.94,4.94,0,0,1-2.58,2.83A5,5,0,0,1,42.7,95.5l6.24-17.28a26.3,26.3,0,0,0,1.17-4,40.64,40.64,0,0,0,.54-4.18c.24-2.53.41-5.27.54-7.9s.22-5.18.29-7.29c.09-2.63-.62-2.8-2.73-3.3l-.44-.1-18-3.39A5,5,0,0,1,27.08,46a5,5,0,0,1,5.05-7.74l19.34,3.63c.77.07,1.52.16,2.31.25a57.64,57.64,0,0,0,7.18.53A81.13,81.13,0,0,0,69.9,42c.9-.1,1.75-.21,2.6-.29l18.25-3.42A5,5,0,0,1,94.5,39a5,5,0,0,1,1.3,7,5,5,0,0,1-3.21,2.09L75.15,51.37c-.58.13-1.1.22-1.56.29-1.82.31-2.72.47-2.61,3.06.08,1.89.31,4.15.61,6.51.35,2.77.81,5.71,1.29,8.4.31,1.77.6,3.19,1,4.55s.79,2.75,1.39,4.42l6.11,16.9a5,5,0,0,1-6.82,6.24,4.94,4.94,0,0,1-2.58-2.83L63,74.23,62,72.4l-1,1.78Zm.39-53.52a8.83,8.83,0,1,1-6.24,2.59,8.79,8.79,0,0,1,6.24-2.59Zm36.35,4.43a51.42,51.42,0,1,0,15,36.35,51.27,51.27,0,0,0-15-36.35Z"/></svg>',
40
42
  wheelchair: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M19 13v-2c-1.54.02-3.09-.75-4.07-1.83l-1.29-1.43c-.17-.19-.38-.34-.61-.45-.01 0-.01-.01-.02-.01H13c-.35-.2-.75-.3-1.19-.26C10.76 7.11 10 8.04 10 9.09V15c0 1.1.9 2 2 2h5v5h2v-5.5c0-1.1-.9-2-2-2h-3v-3.45c1.29 1.07 3.25 1.94 5 1.95zm-6.17 5c-.41 1.16-1.52 2-2.83 2-1.66 0-3-1.34-3-3 0-1.31.84-2.41 2-2.83V12.1c-2.28.46-4 2.48-4 4.9 0 2.76 2.24 5 5 5 2.42 0 4.44-1.72 4.9-4h-2.07zM12 6c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/></svg>',
@@ -57,6 +59,8 @@ function buildPanelHtml(opts) {
57
59
  const toggle = (klass, label, icon) => `<button class="oks-access-opt" data-action="toggle" data-class="${klass}" aria-pressed="false" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span></button>`;
58
60
  const overlay = (id, label, icon) => `<button class="oks-access-opt" data-action="overlay" data-target="${id}" aria-pressed="false" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span></button>`;
59
61
  const guide = (label, icon) => `<button class="oks-access-opt" data-action="guide" aria-pressed="false" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span></button>`;
62
+ const mask = (label, icon) => `<button class="oks-access-opt" data-action="mask" aria-pressed="false" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span></button>`;
63
+ const preset = (id, label, icon) => `<button class="oks-preset" data-action="preset" data-preset="${id}" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span></button>`;
60
64
  return `
61
65
  <div class="oks-access-wrapper" id="oks-wrapper" data-position="${opts.position}">
62
66
  <button class="oks-access-btn" id="oks-trigger" aria-label="${escapeAttr(t.title)}" aria-expanded="false" aria-controls="oks-panel" type="button">
@@ -70,6 +74,13 @@ function buildPanelHtml(opts) {
70
74
  <button class="oks-access-close" id="oks-close" aria-label="${escapeAttr(t.close)}" type="button">${ICON_CLOSE}</button>
71
75
  </div>
72
76
  <div class="oks-access-content">
77
+ <h4 class="oks-access-title">${escapeHtml(t.presets)}</h4>
78
+ <div class="oks-access-presets">
79
+ ${preset("lowvision", t.pLow, ICON_CONTRAST)}
80
+ ${preset("dyslexia", t.pDys, ICON_DYSLEXIA)}
81
+ ${preset("motor", t.pMot, ICON_CURSOR)}
82
+ ${preset("calm", t.pCalm, ICON_HIDE)}
83
+ </div>
73
84
  <h4 class="oks-access-title">${escapeHtml(t.txt)}</h4>
74
85
  ${grid([
75
86
  multi("multi", "oks-zoom", 4, t.size, ICON_TXT),
@@ -90,7 +101,9 @@ function buildPanelHtml(opts) {
90
101
  <h4 class="oks-access-title">${escapeHtml(t.ori)}</h4>
91
102
  ${grid([
92
103
  guide(t.guide, ICON_GUIDE),
104
+ mask(t.mask, ICON_MASK),
93
105
  toggle("oks-big-cursor", t.cursor, ICON_CURSOR),
106
+ toggle("oks-a11y-bigtargets", t.targets, ICON_TARGETS),
94
107
  toggle("oks-a11y-pause", t.pause, ICON_PAUSE),
95
108
  toggle("oks-a11y-focus", t.focus, ICON_FOCUS)
96
109
  ])}
@@ -156,7 +169,9 @@ var DEFAULT_STATE = Object.freeze({
156
169
  pauseAnim: false,
157
170
  focusOutline: false,
158
171
  grayOverlay: false,
159
- readingGuide: false
172
+ readingGuide: false,
173
+ readingMask: false,
174
+ bigTargets: false
160
175
  });
161
176
  function loadState(key) {
162
177
  if (typeof localStorage === "undefined") return { ...DEFAULT_STATE };
@@ -187,7 +202,7 @@ function saveState(key, state) {
187
202
  }
188
203
  }
189
204
  function isStateEmpty(state) {
190
- return state.zoom === 0 && state.lh === 0 && state.align === 0 && state.ls === 0 && state.colorblind === 0 && !state.font && !state.dyslexia && !state.contrast && !state.hideImages && !state.highlightLinks && !state.bigCursor && !state.pauseAnim && !state.focusOutline && !state.grayOverlay && !state.readingGuide;
205
+ return state.zoom === 0 && state.lh === 0 && state.align === 0 && state.ls === 0 && state.colorblind === 0 && !state.font && !state.dyslexia && !state.contrast && !state.hideImages && !state.highlightLinks && !state.bigCursor && !state.pauseAnim && !state.focusOutline && !state.grayOverlay && !state.readingGuide && !state.readingMask && !state.bigTargets;
191
206
  }
192
207
 
193
208
  // src/behavior.ts
@@ -213,7 +228,14 @@ var TOGGLE_KEYS = {
213
228
  "oks-a11y-links": "highlightLinks",
214
229
  "oks-big-cursor": "bigCursor",
215
230
  "oks-a11y-pause": "pauseAnim",
216
- "oks-a11y-focus": "focusOutline"
231
+ "oks-a11y-focus": "focusOutline",
232
+ "oks-a11y-bigtargets": "bigTargets"
233
+ };
234
+ var PRESETS = {
235
+ lowvision: { zoom: 2, contrast: true, highlightLinks: true, bigCursor: true, focusOutline: true },
236
+ dyslexia: { dyslexia: true, lh: 2, ls: 2, readingGuide: true },
237
+ motor: { bigCursor: true, bigTargets: true, focusOutline: true },
238
+ calm: { hideImages: true, pauseAnim: true }
217
239
  };
218
240
  function bindPanelBehavior(root, opts = {}) {
219
241
  const storageKey = opts.storageKey ?? "oksiacSettings";
@@ -222,7 +244,7 @@ function bindPanelBehavior(root, opts = {}) {
222
244
  const closeBtn = root.getElementById("oks-close");
223
245
  const resetBtn = root.getElementById("oks-reset");
224
246
  const wrapper = root.getElementById("oks-wrapper");
225
- const opts$ = Array.from(root.querySelectorAll(".oks-access-opt"));
247
+ const opts$ = Array.from(root.querySelectorAll(".oks-access-opt, .oks-preset"));
226
248
  if (!trigger || !panel || !closeBtn || !resetBtn || !wrapper) {
227
249
  return () => {
228
250
  };
@@ -247,6 +269,8 @@ function bindPanelBehavior(root, opts = {}) {
247
269
  if (state.pauseAnim) body.classList.add("oks-a11y-pause");
248
270
  if (state.focusOutline) body.classList.add("oks-a11y-focus");
249
271
  if (state.readingGuide) body.classList.add("oks-a11y-guide");
272
+ if (state.readingMask) body.classList.add("oks-a11y-mask");
273
+ if (state.bigTargets) body.classList.add("oks-a11y-bigtargets");
250
274
  const overlay = ensureOverlay();
251
275
  overlay.classList.toggle("is-active", state.grayOverlay);
252
276
  syncButtonsFromState();
@@ -276,6 +300,9 @@ function bindPanelBehavior(root, opts = {}) {
276
300
  } else if (action === "guide") {
277
301
  btn.classList.toggle("is-active", state.readingGuide);
278
302
  btn.setAttribute("aria-pressed", state.readingGuide ? "true" : "false");
303
+ } else if (action === "mask") {
304
+ btn.classList.toggle("is-active", state.readingMask);
305
+ btn.setAttribute("aria-pressed", state.readingMask ? "true" : "false");
279
306
  }
280
307
  }
281
308
  }
@@ -302,6 +329,14 @@ function bindPanelBehavior(root, opts = {}) {
302
329
  if (state.grayOverlay) state.contrast = false;
303
330
  } else if (action === "guide") {
304
331
  state.readingGuide = !state.readingGuide;
332
+ } else if (action === "mask") {
333
+ state.readingMask = !state.readingMask;
334
+ } else if (action === "preset") {
335
+ const id = btn.getAttribute("data-preset") ?? "";
336
+ const preset = PRESETS[id];
337
+ if (preset) Object.assign(state, preset);
338
+ btn.classList.add("is-flashing");
339
+ setTimeout(() => btn.classList.remove("is-flashing"), 250);
305
340
  }
306
341
  applyState();
307
342
  saveState(storageKey, state);
@@ -331,8 +366,9 @@ function bindPanelBehavior(root, opts = {}) {
331
366
  };
332
367
  const onDocClick = (e) => {
333
368
  if (!panel.classList.contains("is-open")) return;
334
- const t = e.target;
335
- if (!panel.contains(t) && !trigger.contains(t) && !wrapper.contains(t)) closePanel();
369
+ const path = e.composedPath();
370
+ if (path.includes(panel) || path.includes(trigger) || path.includes(wrapper)) return;
371
+ closePanel();
336
372
  };
337
373
  const onKeyDown = (e) => {
338
374
  if (!panel.classList.contains("is-open")) return;
@@ -359,11 +395,17 @@ function bindPanelBehavior(root, opts = {}) {
359
395
  }
360
396
  };
361
397
  const onMove = (e) => {
362
- if (!state.readingGuide) return;
363
- const guide = document.getElementById("oks-reading-guide");
364
- if (!guide) return;
398
+ if (!state.readingGuide && !state.readingMask) return;
365
399
  const y = e.touches?.[0]?.clientY ?? e.clientY;
366
- if (typeof y === "number") guide.style.top = `${y}px`;
400
+ if (typeof y !== "number") return;
401
+ if (state.readingGuide) {
402
+ const guide = document.getElementById("oks-reading-guide");
403
+ if (guide) guide.style.top = `${y}px`;
404
+ }
405
+ if (state.readingMask) {
406
+ const mask = document.getElementById("oks-reading-mask");
407
+ if (mask) mask.style.setProperty("--oks-mask-y", `${y}px`);
408
+ }
367
409
  };
368
410
  trigger.addEventListener("click", onTriggerClick);
369
411
  closeBtn.addEventListener("click", closePanel);
@@ -508,6 +550,43 @@ var PANEL_CSS = `
508
550
  color: #888;
509
551
  }
510
552
  .oks-access-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
553
+ .oks-access-presets { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
554
+ .oks-preset {
555
+ background: #f0f4f8;
556
+ border: 2px solid transparent;
557
+ border-radius: 8px;
558
+ padding: 8px 4px;
559
+ display: flex;
560
+ flex-direction: column;
561
+ align-items: center;
562
+ cursor: pointer;
563
+ font: inherit;
564
+ color: #333;
565
+ min-width: 0;
566
+ transition: 0.15s;
567
+ }
568
+ .oks-preset:hover { background: #000; color: #fff; }
569
+ .oks-preset:focus-visible { outline: 2px solid #000; outline-offset: 2px; }
570
+ /* Click feedback: a 250 ms flip + slight squeeze. Pure transient \u2014 the
571
+ button does not carry persistent active state because a preset is a
572
+ trigger, not a mode. */
573
+ .oks-preset.is-flashing {
574
+ background: #000;
575
+ color: #fff;
576
+ transform: scale(0.96);
577
+ }
578
+ .oks-preset .oks-icon { font-size: 22px; margin-bottom: 4px; }
579
+ .oks-preset .oks-icon svg { width: 20px; height: 20px; }
580
+ .oks-preset .oks-label {
581
+ font-size: 10px; font-weight: 700; text-transform: uppercase;
582
+ text-align: center; line-height: 1.15;
583
+ overflow-wrap: anywhere; word-break: break-word;
584
+ /* Reserve room for 2 lines so 1-line labels (DISLEXIA, MOTOR) and
585
+ 2-line labels (BAJA VISI\xD3N, SIN DISTRAC.) end up the same height,
586
+ centred. Without this the row looks ragged. */
587
+ min-height: 2.3em;
588
+ display: flex; align-items: center; justify-content: center;
589
+ }
511
590
  .oks-access-opt {
512
591
  background: #f9f9f9;
513
592
  border: 2px solid #eee;
@@ -708,6 +787,42 @@ body.oks-a11y-contrast .oks-overlay-effect {
708
787
  transform: translateY(-50%);
709
788
  }
710
789
  body.oks-a11y-guide .oks-reading-guide { display: block; }
790
+
791
+ /* Reading mask: dark overlay leaving a horizontal band lit around the cursor.
792
+ --oks-mask-y is updated from JS on mousemove; band is \xB190px around it. */
793
+ .oks-reading-mask {
794
+ position: fixed; top: 0; left: 0;
795
+ width: 100vw; height: 100vh;
796
+ pointer-events: none;
797
+ z-index: 2147483646;
798
+ background: rgba(0, 0, 0, 0.75);
799
+ display: none;
800
+ clip-path: polygon(
801
+ 0 0, 100% 0,
802
+ 100% calc(var(--oks-mask-y, 50vh) - 90px),
803
+ 0 calc(var(--oks-mask-y, 50vh) - 90px),
804
+ 0 calc(var(--oks-mask-y, 50vh) + 90px),
805
+ 100% calc(var(--oks-mask-y, 50vh) + 90px),
806
+ 100% 100%, 0 100%
807
+ );
808
+ }
809
+ body.oks-a11y-mask .oks-reading-mask { display: block; }
810
+ body.oks-a11y-contrast .oks-reading-mask { background-color: rgba(0, 0, 0, 0.85) !important; }
811
+
812
+ /* Big targets: bump interactive hit-areas to WCAG 2.5.5 (44\xD744 minimum).
813
+ Only adjusts padding + min-* \u2014 never display, so layouts that rely on
814
+ inline flow or grid placement survive. Exempts our own shadow-DOM host. */
815
+ body.oks-a11y-bigtargets a:not(oksigenia-access-panel):not(oksigenia-access-panel *),
816
+ body.oks-a11y-bigtargets button:not(oksigenia-access-panel):not(oksigenia-access-panel *),
817
+ body.oks-a11y-bigtargets [role="button"]:not(oksigenia-access-panel):not(oksigenia-access-panel *),
818
+ body.oks-a11y-bigtargets input[type="checkbox"]:not(oksigenia-access-panel):not(oksigenia-access-panel *),
819
+ body.oks-a11y-bigtargets input[type="radio"]:not(oksigenia-access-panel):not(oksigenia-access-panel *),
820
+ body.oks-a11y-bigtargets summary:not(oksigenia-access-panel):not(oksigenia-access-panel *) {
821
+ min-height: 44px !important;
822
+ min-width: 44px !important;
823
+ padding: 8px 12px !important;
824
+ box-sizing: border-box !important;
825
+ }
711
826
  `;
712
827
 
713
828
  export { COLORBLIND_FILTERS_SVG, DEFAULT_STATE, EFFECT_CSS, PANEL_CSS, bindPanelBehavior, buildPanelHtml, getTranslation, isStateEmpty, loadState, positionCss, saveState, supportedLocales };