@oksigenia/access-panel 0.7.1 → 0.7.3

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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # @oksigenia/access-panel
2
2
 
3
+ ## 0.7.3
4
+
5
+ ### Patch Changes
6
+
7
+ - **Reading fonts no longer break icon fonts.** The dyslexia font (and the readable font in scoped panels) was forced on every element with `*`, icon elements included, so on sites that draw icons from a font, every icon turned into an empty box while the mode was on. Moodle was hit hardest, since its whole interface uses Font Awesome. The font overrides now skip the common icon fonts: Font Awesome (`.fa`, `fa-*`), Moodle's `.icon`, `icon-*`, Dashicons, Material Icons/Symbols, Glyphicons and Bootstrap Icons (`bi-*`). Text keeps the reading font as before.
8
+
9
+ ## 0.7.2
10
+
11
+ ### Patch Changes
12
+
13
+ - Two fixes:
14
+
15
+ - **The open panel no longer overflows short desktop viewports.** The panel was capped at a flat `90vh` while sitting 80–100px from its anchored edge, so at 1280×720 or on a 1366×768 laptop a `bottom-*` panel ran past the top of the screen and took the header with the close button with it (`top-*` panels overflowed the bottom the same way). Each anchor now caps the panel to the room it actually has (`calc(100dvh - <offset> - 20px)`, with a `vh` fallback), and the content area scrolls inside. Mobile is unchanged: it stays full-screen.
16
+ - **Blocked storage no longer breaks the panel.** `typeof localStorage` sat outside the `try`, and when storage is denied (all cookies blocked, sandboxed iframe) merely reading `window.localStorage` throws — the component lost its behaviour and the trigger did nothing. The check now lives inside the guard; the panel works and simply doesn't persist settings.
17
+
3
18
  ## 0.7.1
4
19
 
5
20
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -168,7 +168,7 @@ interface PanelController {
168
168
  declare function bindPanelBehavior(root: ShadowRoot, opts?: BehaviorOptions): PanelController;
169
169
 
170
170
  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/* Porthole preset: a brushed-metal ring framing the standard glyph. The glyph\n itself is untouched (discoverability), only the button gets the frame.\n Hosts wanting a bespoke frame can target ::part(trigger) from light DOM. */\n.oks-access-btn[data-trigger-icon=\"porthole\"] {\n box-shadow: 0 0 0 4px #b0bec5, 0 0 0 7px #546e7a, 0 6px 18px rgba(0,0,0,0.3);\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 flex: 0 0 auto;\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/* flex:1 1 auto + min-height:0 lets the content scroll inside the 90vh panel.\n Without min-height:0 a flex child won't shrink below its content, so the\n header (\u00D7) and footer (Reset) get pushed off-screen on short viewports or at\n high zoom \u2014 the panel becomes impossible to close. */\n.oks-access-content { flex: 1 1 auto; min-height: 0; 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/* Screen-reader-only: keeps the category headings in the accessibility tree\n (flat scoped layout) while taking them out of the grid flow so they don't\n force a visual row break or occupy a cell. */\n.oks-sr-only {\n position: absolute !important;\n width: 1px; height: 1px;\n margin: 0; padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\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 flex: 0 0 auto;\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 (prefers-reduced-motion: reduce) {\n .oks-access-btn, .oks-access-panel, .oks-access-close,\n .oks-preset, .oks-access-opt { transition: none; }\n .oks-access-btn:hover { transform: scale(1); }\n .oks-preset.is-flashing { transform: none; }\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";
171
- 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\n/* Focus highlight colour is themeable via --oks-focus-color (default #005fcc):\n set it on :root for a dark theme so the highlight stays visible. The\n persistent \"all interactive\" dashed derives a 45% tint from it; the glow can\n be overridden on its own with --oks-focus-glow. */\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 color-mix(in srgb, var(--oks-focus-color, #005fcc) 45%, transparent) !important;\n outline-offset: 2px !important;\n}\nbody.oks-a11y-focus *:focus-visible {\n outline: 3px solid var(--oks-focus-color, #005fcc) !important;\n outline-offset: 3px !important;\n box-shadow: 0 0 0 6px var(--oks-focus-glow, color-mix(in srgb, var(--oks-focus-color, #005fcc) 25%, transparent)) !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";
171
+ 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 *:not(.fa, [class*=\"fa-\"], .icon, [class^=\"icon-\"], [class*=\" icon-\"], .dashicons, [class*=\"dashicons-\"], .material-icons, [class^=\"material-symbols\"], .glyphicon, [class^=\"bi-\"], [class*=\" bi-\"]) {\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\n/* Focus highlight colour is themeable via --oks-focus-color (default #005fcc):\n set it on :root for a dark theme so the highlight stays visible. The\n persistent \"all interactive\" dashed derives a 45% tint from it; the glow can\n be overridden on its own with --oks-focus-glow. */\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 color-mix(in srgb, var(--oks-focus-color, #005fcc) 45%, transparent) !important;\n outline-offset: 2px !important;\n}\nbody.oks-a11y-focus *:focus-visible {\n outline: 3px solid var(--oks-focus-color, #005fcc) !important;\n outline-offset: 3px !important;\n box-shadow: 0 0 0 6px var(--oks-focus-glow, color-mix(in srgb, var(--oks-focus-color, #005fcc) 25%, transparent)) !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";
172
172
  /**
173
173
  * Scoped-mode effect CSS (#scope). Emits only the controls that can be confined
174
174
  * to a container by selector — the same rules as EFFECT_CSS but anchored to the
package/dist/index.js CHANGED
@@ -256,29 +256,32 @@ function escapeAttr(s) {
256
256
  function positionRules(position) {
257
257
  switch (position) {
258
258
  case "top-left":
259
- return { wrap: "top: 20px; left: 20px;", panel: "top: 80px; left: 20px;" };
259
+ return { wrap: "top: 20px; left: 20px;", panel: "top: 80px; left: 20px;", reserve: 100 };
260
260
  case "top-center":
261
- return { wrap: "top: 20px; left: 50%; transform: translateX(-50%);", panel: "top: 80px; left: 50%; transform: translateX(-50%);" };
261
+ return { wrap: "top: 20px; left: 50%; transform: translateX(-50%);", panel: "top: 80px; left: 50%; transform: translateX(-50%);", reserve: 100 };
262
262
  case "top-right":
263
- return { wrap: "top: 20px; right: 20px;", panel: "top: 80px; right: 20px;" };
263
+ return { wrap: "top: 20px; right: 20px;", panel: "top: 80px; right: 20px;", reserve: 100 };
264
264
  case "mid-left":
265
- return { wrap: "top: 50%; left: 20px; transform: translateY(-50%);", panel: "top: 50%; left: 90px; transform: translateY(-50%);" };
265
+ return { wrap: "top: 50%; left: 20px; transform: translateY(-50%);", panel: "top: 50%; left: 90px; transform: translateY(-50%);", reserve: 40 };
266
266
  case "mid-center":
267
- return { wrap: "top: 50%; left: 50%; transform: translate(-50%, -50%);", panel: "top: 50%; left: 50%; transform: translate(-50%, -50%);" };
267
+ return { wrap: "top: 50%; left: 50%; transform: translate(-50%, -50%);", panel: "top: 50%; left: 50%; transform: translate(-50%, -50%);", reserve: 40 };
268
268
  case "mid-right":
269
- return { wrap: "top: 50%; right: 20px; transform: translateY(-50%);", panel: "top: 50%; right: 90px; transform: translateY(-50%);" };
269
+ return { wrap: "top: 50%; right: 20px; transform: translateY(-50%);", panel: "top: 50%; right: 90px; transform: translateY(-50%);", reserve: 40 };
270
270
  case "bottom-left":
271
- return { wrap: "bottom: 20px; left: 20px;", panel: "bottom: 100px; left: 20px;" };
271
+ return { wrap: "bottom: 20px; left: 20px;", panel: "bottom: 100px; left: 20px;", reserve: 120 };
272
272
  case "bottom-center":
273
- return { wrap: "bottom: 20px; left: 50%; transform: translateX(-50%);", panel: "bottom: 100px; left: 50%; transform: translateX(-50%);" };
273
+ return { wrap: "bottom: 20px; left: 50%; transform: translateX(-50%);", panel: "bottom: 100px; left: 50%; transform: translateX(-50%);", reserve: 120 };
274
274
  case "bottom-right":
275
- return { wrap: "bottom: 20px; right: 20px;", panel: "bottom: 100px; right: 20px;" };
275
+ return { wrap: "bottom: 20px; right: 20px;", panel: "bottom: 100px; right: 20px;", reserve: 120 };
276
276
  }
277
277
  }
278
+ function panelMaxHeight(reserve) {
279
+ return `max-height: calc(100vh - ${reserve}px); max-height: calc(100dvh - ${reserve}px);`;
280
+ }
278
281
  function positionCss(position, mobile) {
279
282
  const d = positionRules(position);
280
283
  let css = `.oks-access-wrapper { ${d.wrap} }`;
281
- css += `@media (min-width: 769px) { .oks-access-panel { ${d.panel} } }`;
284
+ css += `@media (min-width: 769px) { .oks-access-panel { ${d.panel} ${panelMaxHeight(d.reserve)} } }`;
282
285
  if (mobile && mobile !== position) {
283
286
  const m = positionRules(mobile);
284
287
  css += `@media (max-width: 768px) { .oks-access-wrapper { top: auto; right: auto; bottom: auto; left: auto; transform: none; ${m.wrap} } }`;
@@ -307,8 +310,8 @@ var DEFAULT_STATE = Object.freeze({
307
310
  bigTargets: false
308
311
  });
309
312
  function loadState(key) {
310
- if (typeof localStorage === "undefined") return { ...DEFAULT_STATE };
311
313
  try {
314
+ if (typeof localStorage === "undefined") return { ...DEFAULT_STATE };
312
315
  const raw = localStorage.getItem(key);
313
316
  if (!raw) return { ...DEFAULT_STATE };
314
317
  const parsed = JSON.parse(raw);
@@ -319,8 +322,8 @@ function loadState(key) {
319
322
  }
320
323
  }
321
324
  function saveState(key, state) {
322
- if (typeof localStorage === "undefined") return;
323
325
  try {
326
+ if (typeof localStorage === "undefined") return;
324
327
  const out = {};
325
328
  for (const [k, v] of Object.entries(state)) {
326
329
  if (typeof v === "number" && v > 0) out[k] = v;
@@ -1084,6 +1087,7 @@ var PANEL_CSS = `
1084
1087
  .oks-access-reset { padding: 14px; font-size: 14px; }
1085
1088
  }
1086
1089
  `;
1090
+ var NOT_ICON_FONT = ':not(.fa, [class*="fa-"], .icon, [class^="icon-"], [class*=" icon-"], .dashicons, [class*="dashicons-"], .material-icons, [class^="material-symbols"], .glyphicon, [class^="bi-"], [class*=" bi-"])';
1087
1091
  var EFFECT_CSS = `
1088
1092
  html.oks-colorblind-1 { filter: url('#oks-filter-protanopia'); }
1089
1093
  html.oks-colorblind-2 { filter: url('#oks-filter-deuteranopia'); }
@@ -1111,7 +1115,7 @@ body.oks-lh-3 * { line-height: 2.2 !important; }
1111
1115
 
1112
1116
  body.oks-a11y-font { font-family: Arial, sans-serif !important; }
1113
1117
 
1114
- body.oks-dyslexia * {
1118
+ body.oks-dyslexia *${NOT_ICON_FONT} {
1115
1119
  font-family: 'Comic Sans MS', 'Verdana', sans-serif !important;
1116
1120
  letter-spacing: 0.05em !important;
1117
1121
  word-spacing: 0.1em !important;
@@ -1258,9 +1262,9 @@ ${s}.oks-lh-1 * { line-height: 1.6 !important; }
1258
1262
  ${s}.oks-lh-2 * { line-height: 1.9 !important; }
1259
1263
  ${s}.oks-lh-3 * { line-height: 2.2 !important; }
1260
1264
 
1261
- ${s}.oks-a11y-font, ${s}.oks-a11y-font * { font-family: Arial, sans-serif !important; }
1265
+ ${s}.oks-a11y-font, ${s}.oks-a11y-font *${NOT_ICON_FONT} { font-family: Arial, sans-serif !important; }
1262
1266
 
1263
- ${s}.oks-dyslexia * {
1267
+ ${s}.oks-dyslexia *${NOT_ICON_FONT} {
1264
1268
  font-family: 'Comic Sans MS', 'Verdana', sans-serif !important;
1265
1269
  letter-spacing: 0.05em !important;
1266
1270
  word-spacing: 0.1em !important;