/*
 * AccessPlus
 *
 * Package: vtinnovations/vt-access-plus
 * Copyright: VT Innovations
 * Licence: GPL-2.0-or-later
 * Website: https://v-t.one/accessplus
 */

/**
 * Comfort overlay widget: toggle button, panel chrome, and every visual effect the
 * widget can apply.
 *
 * Self-contained, no external resources. Effects are toggled via `html.vtap-o-*`
 * classes plus a dynamically-written `<style id="vtap-overlay-dyn">` for the handful
 * of effects a fixed class cannot express (line height, letter spacing, custom
 * colours — each a continuous or open-ended value, not an on/off state). Accent
 * colour and position come from the mount point's JSON payload, applied by
 * `overlay.js` as a CSS custom property and a position class — never as a `style`
 * attribute built from payload data. See `overlay.js` for the two narrow exceptions
 * (the reading guide's position, a reader's own colour picks), both driven by the
 * reader's live input rather than anything server-sourced.
 *
 * Every widget-chrome rule below (button, panel, switches, steppers, swatches) is
 * written defensively — explicit resets plus `!important` on anything a theme
 * plausibly also targets (`button`, `select`, box model, text transform). WordPress
 * themes and page builders routinely apply global `button { ... }` styling for their
 * own call-to-action buttons; without this, that styling would leak into this
 * widget's chrome and the floating button would render as a plain theme-styled
 * button rather than the intended round accent-coloured control.
 *
 * Comfort/display layer — never a substitute for an accessible site.
 */

/* Position (default bottom-right, so the root is never unpositioned). */
/*
 * Stacking order, and why these particular numbers.
 *
 * The widget is a control surface a reader is using *right now*; a cookie banner, a chat
 * bubble or a theme's sticky header covering it makes it unusable, and the reader has no
 * way to get underneath. So it sits near the top of the 32-bit stacking range the same way
 * the reference product does — the values below are its values.
 *
 * `2147483647` is the largest a 32-bit signed stacking order holds. Stopping short of it
 * is deliberate: a site with something that genuinely must come first — a consent dialog
 * that has to be answered before anything else — can still get above this without having
 * to fight for the exact maximum. Taking the maximum would mean nothing could ever be
 * placed above the overlay, which is a decision this plugin has no business making for
 * every site that installs it.
 *
 * These only work because the widget is appended to <html>, outside <body>: it is a child
 * of the root stacking context, so no theme wrapper with a `transform` or a `filter` can
 * trap it in a lower context where a large z-index would count for nothing. See the mount
 * note in overlay.js.
 *
 * Order among the plugin's own layers: plain-language button, then the widget, then the
 * reading guide and magnifier over the page, then the toast over everything.
 */
#vtap-overlay-root {
	all: initial;
	position: fixed !important;
	z-index: 2147483000 !important;
	--vtap-overlay-accent: #1d4ed8;
	bottom: 16px;
	right: 16px;
	top: auto;
	left: auto;
}
#vtap-overlay-root * {
	box-sizing: border-box !important;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
	text-transform: none !important;
	letter-spacing: normal !important;
	text-decoration: none !important;
	text-shadow: none !important;
	box-shadow: none;
	margin: 0;
}
/*
 * `appearance: none` is applied only to the controls this stylesheet fully draws itself.
 * It is deliberately NOT in the blanket rule above: applying it to `<select>` strips the
 * native dropdown arrow, leaving the link-navigator looking like a plain empty box with
 * no affordance that it opens a list.
 */
#vtap-overlay-root button {
	-webkit-appearance: none !important;
	appearance: none !important;
}
#vtap-overlay-root.vtap-o-pos-bottomright { bottom: 16px !important; right: 16px !important; top: auto !important; left: auto !important; }
#vtap-overlay-root.vtap-o-pos-bottomleft { bottom: 16px !important; left: 16px !important; top: auto !important; right: auto !important; }
#vtap-overlay-root.vtap-o-pos-topright { top: 16px !important; right: 16px !important; bottom: auto !important; left: auto !important; }
#vtap-overlay-root.vtap-o-pos-topleft { top: 16px !important; left: 16px !important; bottom: auto !important; right: auto !important; }
#vtap-overlay-root.vtap-o-pos-middleright { top: 50% !important; right: 16px !important; bottom: auto !important; left: auto !important; transform: translateY( -50% ) !important; }
#vtap-overlay-root.vtap-o-pos-middleleft { top: 50% !important; left: 16px !important; bottom: auto !important; right: auto !important; transform: translateY( -50% ) !important; }

/* Widget chrome. */
#vtap-overlay-root .vtap-overlay-btn {
	display: flex !important;
	align-items: center !important;
	justify-content: center !important;
	width: 52px !important;
	height: 52px !important;
	min-width: 52px !important;
	max-width: 52px !important;
	padding: 0 !important;
	border-radius: 50% !important;
	border: 2px solid #fff !important;
	background: var( --vtap-overlay-accent ) !important;
	color: #fff !important;
	font-size: 24px !important;
	line-height: 1 !important;
	cursor: pointer !important;
	box-shadow: 0 2px 10px rgba( 0, 0, 0, 0.4 ) !important;
}

#vtap-overlay-root .vtap-overlay-btn:focus-visible,
#vtap-overlay-root .vtap-overlay-panel button:focus-visible,
#vtap-overlay-root .vtap-overlay-panel select:focus-visible {
	outline: 3px solid #ffbf47 !important;
	outline-offset: 2px !important;
}

#vtap-overlay-root .vtap-overlay-panel {
	position: absolute !important;
	display: block !important;
	width: 340px !important;
	max-width: 90vw !important;
	max-height: calc( 100vh - 96px ) !important;
	overflow-y: auto !important;
	overflow-x: hidden !important;
	bottom: 64px !important;
	right: 0 !important;
	background: #fff !important;
	color: #111 !important;
	border: 1px solid #888 !important;
	border-radius: 10px !important;
	box-shadow: 0 8px 28px rgba( 0, 0, 0, 0.32 ) !important;
	padding: 14px !important;
	font-size: 15px !important;
	line-height: 1.4 !important;
	text-align: left !important;
}
#vtap-overlay-root.vtap-o-pos-bottomright .vtap-overlay-panel,
#vtap-overlay-root.vtap-o-pos-bottomleft .vtap-overlay-panel { bottom: 64px !important; top: auto !important; }
#vtap-overlay-root.vtap-o-pos-topright .vtap-overlay-panel,
#vtap-overlay-root.vtap-o-pos-topleft .vtap-overlay-panel { top: 64px !important; bottom: auto !important; }
#vtap-overlay-root.vtap-o-pos-bottomright .vtap-overlay-panel,
#vtap-overlay-root.vtap-o-pos-topright .vtap-overlay-panel { right: 0 !important; left: auto !important; }
#vtap-overlay-root.vtap-o-pos-bottomleft .vtap-overlay-panel,
#vtap-overlay-root.vtap-o-pos-topleft .vtap-overlay-panel { left: 0 !important; right: auto !important; }
/* Middle positions open to the side of the button, vertically centred. */
#vtap-overlay-root.vtap-o-pos-middleright .vtap-overlay-panel { right: 64px !important; left: auto !important; top: 50% !important; bottom: auto !important; transform: translateY( -50% ) !important; }
#vtap-overlay-root.vtap-o-pos-middleleft .vtap-overlay-panel { left: 64px !important; right: auto !important; top: 50% !important; bottom: auto !important; transform: translateY( -50% ) !important; }
#vtap-overlay-root .vtap-overlay-panel[hidden] { display: none !important; }
#vtap-overlay-root .vtap-overlay-panel h2 { display: block !important; margin: 0 0 2px !important; font-size: 17px !important; font-weight: 700 !important; color: #111 !important; }
#vtap-overlay-root .vtap-overlay-note { display: block !important; margin: 0 0 10px !important; font-size: 12px !important; color: #555 !important; }
#vtap-overlay-root .vtap-overlay-group { display: block !important; margin: 10px 0 4px !important; font-size: 13px !important; font-weight: 700 !important; color: var( --vtap-overlay-accent ) !important; border: 0 !important; border-top: 1px solid #eee !important; padding: 8px 0 0 !important; }
/*
 * Colour-picker section headings: a plain sub-label rather than an accent-coloured group
 * header, since each sits directly above its own swatch row rather than introducing a whole
 * group. A modifier class, not an inline style — the rule above is `!important`, which an
 * inline `style` attribute cannot override.
 */
#vtap-overlay-root .vtap-overlay-group.vtap-overlay-group--plain {
	color: #333 !important;
	font-weight: 600 !important;
	border-top: 0 !important;
	padding-top: 0 !important;
}
#vtap-overlay-root .vtap-overlay-row { display: flex !important; align-items: center !important; justify-content: space-between !important; gap: 10px !important; margin: 8px 0 !important; flex-wrap: wrap !important; }
#vtap-overlay-root .vtap-overlay-row > span { flex: 1 1 auto !important; min-width: 120px !important; color: #111 !important; font-size: 15px !important; }
#vtap-overlay-root .vtap-overlay-panel button { font-size: 14px !important; cursor: pointer !important; }
#vtap-overlay-root .vtap-overlay-step button,
#vtap-overlay-root .vtap-overlay-align button {
	display: inline-block !important;
	width: auto !important;
	height: auto !important;
	padding: 6px 10px !important;
	border: 1px solid var( --vtap-overlay-accent ) !important;
	background: #fff !important;
	color: var( --vtap-overlay-accent ) !important;
	border-radius: 6px !important;
}
#vtap-overlay-root .vtap-overlay-align button[aria-pressed="true"] { background: var( --vtap-overlay-accent ) !important; color: #fff !important; }
#vtap-overlay-root .vtap-overlay-step,
#vtap-overlay-root .vtap-overlay-align { display: flex !important; align-items: center !important; gap: 6px !important; flex-wrap: wrap !important; }
#vtap-overlay-root .vtap-overlay-step output { display: inline-block !important; min-width: 64px !important; text-align: center !important; font-weight: 700 !important; color: #111 !important; }

/* Toggle switch. */
#vtap-overlay-root .vtap-overlay-switch {
	display: block !important;
	position: relative !important;
	width: 48px !important;
	height: 26px !important;
	min-width: 48px !important;
	max-width: 48px !important;
	border-radius: 13px !important;
	border: none !important;
	background: #c4c4c4 !important;
	padding: 0 !important;
	flex: 0 0 auto !important;
	transition: background 0.15s !important;
}
#vtap-overlay-root .vtap-overlay-switch::after {
	content: "" !important;
	position: absolute !important;
	top: 3px !important;
	left: 3px !important;
	width: 20px !important;
	height: 20px !important;
	border-radius: 50% !important;
	background: #fff !important;
	box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.4 ) !important;
	transition: left 0.15s !important;
}
#vtap-overlay-root .vtap-overlay-switch[aria-pressed="true"] { background: var( --vtap-overlay-accent ) !important; }
#vtap-overlay-root .vtap-overlay-switch[aria-pressed="true"]::after { left: 25px !important; }

#vtap-overlay-root .vtap-overlay-swatches { display: flex !important; flex-wrap: wrap !important; gap: 6px !important; margin: 4px 0 !important; }
#vtap-overlay-root .vtap-overlay-swatch {
	display: inline-block !important;
	width: 24px !important;
	height: 24px !important;
	min-width: 24px !important;
	border-radius: 50% !important;
	border: 1px solid #999 !important;
	cursor: pointer !important;
	padding: 0 !important;
}
#vtap-overlay-root .vtap-overlay-swatch.vtap-overlay-clear { background: #fff !important; color: #333 !important; border-style: dashed !important; width: auto !important; border-radius: 6px !important; padding: 2px 8px !important; }
#vtap-overlay-root .vtap-overlay-panel select {
	display: inline-block !important;
	width: auto !important;
	max-width: 170px !important;
	height: auto !important;
	padding: 5px !important;
	border: 1px solid #888 !important;
	border-radius: 6px !important;
	background: #fff !important;
	color: #111 !important;
	font-size: 14px !important;
}
#vtap-overlay-root .vtap-overlay-reset {
	display: block !important;
	width: 100% !important;
	height: auto !important;
	margin-top: 12px !important;
	padding: 8px !important;
	border: 1px solid #888 !important;
	background: #fff !important;
	color: #333 !important;
	border-radius: 6px !important;
	font-size: 14px !important;
}
#vtap-overlay-toast {
	all: initial;
	position: fixed !important;
	left: 50% !important;
	bottom: 24px !important;
	transform: translateX( -50% ) !important;
	z-index: 2147483002 !important;
	background: #111 !important;
	color: #fff !important;
	padding: 10px 16px !important;
	border-radius: 8px !important;
	font: 14px sans-serif !important;
	max-width: 90vw !important;
}

/* Reading guide. */
/*
 * Visibility is a class, not an inline style. This matters: everything in this file is
 * `!important` to survive theme CSS, and an `!important` declaration cannot be overridden
 * by an element's inline `style` attribute. So `display: none !important` here plus
 * `guideEl.style.display = 'block'` in the JS would leave the guide permanently invisible —
 * which is exactly the bug this replaced. The reference implementation got away with inline
 * display because its stylesheet used no `!important` at all.
 *
 * The guide's `top` is still inline, and has to be: it tracks the reader's cursor, and no
 * rule here sets `top`, so there is nothing for it to lose to.
 */
#vtap-overlay-guide {
	all: initial;
	position: fixed !important;
	z-index: 2147483001 !important;
	left: 0 !important;
	right: 0 !important;
	height: 2.4em !important;
	pointer-events: none !important;
	background: rgba( 255, 235, 59, 0.18 ) !important;
	border-top: 2px solid rgba( 0, 0, 0, 0.55 ) !important;
	border-bottom: 2px solid rgba( 0, 0, 0, 0.55 ) !important;
	display: none !important;
}
#vtap-overlay-guide.vtap-o-guide-visible {
	display: block !important;
}

/*
 * OpenDyslexic, for the dyslexia-friendly font toggle.
 *
 * The font file is NOT shipped with this plugin — see assets/fonts/README.md for why and
 * how to add it. This @font-face rule has to exist regardless: without it, adding the file
 * to assets/fonts/ would have no effect at all, because nothing would ever reference it and
 * the family name would silently fall through to the next entry in the stack forever.
 *
 * With the file absent the request 404s, the browser discards this @font-face, and the
 * `font-family` stack below falls through to Comic Sans MS / Verdana — a rough approximation
 * of OpenDyslexic's heavier baseline, and honestly labelled as a fallback rather than
 * presented as the real thing. `font-display: swap` keeps text visible while it loads.
 */
@font-face {
	font-family: "OpenDyslexic";
	src: url( "../fonts/OpenDyslexic-Regular.woff2" ) format( "woff2" );
	font-weight: normal;
	font-style: normal;
	font-display: swap;
}

/* Effects, applied to <html> — every one is a pre-written rule; none is written
   from payload data. */
html.vtap-o-readfont body, html.vtap-o-readfont p, html.vtap-o-readfont li, html.vtap-o-readfont a,
html.vtap-o-readfont span, html.vtap-o-readfont td, html.vtap-o-readfont h1, html.vtap-o-readfont h2,
html.vtap-o-readfont h3, html.vtap-o-readfont h4, html.vtap-o-readfont h5, html.vtap-o-readfont h6,
html.vtap-o-readfont label, html.vtap-o-readfont button, html.vtap-o-readfont input, html.vtap-o-readfont textarea {
	font-family: Verdana, Tahoma, "Segoe UI", sans-serif !important;
}
html.vtap-o-dysfont body, html.vtap-o-dysfont p, html.vtap-o-dysfont li, html.vtap-o-dysfont a,
html.vtap-o-dysfont span, html.vtap-o-dysfont td, html.vtap-o-dysfont h1, html.vtap-o-dysfont h2,
html.vtap-o-dysfont h3, html.vtap-o-dysfont h4, html.vtap-o-dysfont h5, html.vtap-o-dysfont h6,
html.vtap-o-dysfont label, html.vtap-o-dysfont button {
	/* See the @font-face rule above: OpenDyslexic is used when the font file has been added,
	   and this stack degrades to Comic Sans MS / Verdana when it has not. */
	font-family: "OpenDyslexic", "Comic Sans MS", Verdana, sans-serif !important;
	letter-spacing: 0.03em !important;
}
/* Restore icon fonts (dashicons/Font Awesome/Material ligatures) that the two rules above
   would otherwise break. */
html.vtap-o-readfont i, html.vtap-o-readfont .fa, html.vtap-o-readfont .dashicons, html.vtap-o-readfont [class*="icon"],
html.vtap-o-readfont [class*="fa-"], html.vtap-o-readfont [class*="material-icons"],
html.vtap-o-dysfont i, html.vtap-o-dysfont .fa, html.vtap-o-dysfont .dashicons, html.vtap-o-dysfont [class*="icon"],
html.vtap-o-dysfont [class*="fa-"], html.vtap-o-dysfont [class*="material-icons"] {
	font-family: revert !important;
	letter-spacing: normal !important;
}

html.vtap-o-hltitles h1, html.vtap-o-hltitles h2, html.vtap-o-hltitles h3,
html.vtap-o-hltitles h4, html.vtap-o-hltitles h5, html.vtap-o-hltitles h6 {
	outline: 2px dashed var( --vtap-overlay-accent ) !important;
	outline-offset: 2px;
	background: rgba( 29, 78, 216, 0.06 ) !important;
}
html.vtap-o-hllinks a { text-decoration: underline !important; outline: 1px solid var( --vtap-overlay-accent ) !important; outline-offset: 1px; }

/* Contrast modes (dark/light/high-contrast) are mutually exclusive, enforced in JS.
   Monochrome stacks on top of any of them. The widget lives under <html>, outside
   <body>, so `body *` rules below never touch it. */
html.vtap-o-mono body { filter: grayscale( 1 ); }

/* Dark: invert the page, then counter-invert media so photos and video stay natural. */
html.vtap-o-dark body { background: #fff !important; filter: invert( 1 ) hue-rotate( 180deg ); }
html.vtap-o-dark img, html.vtap-o-dark video, html.vtap-o-dark picture, html.vtap-o-dark iframe,
html.vtap-o-dark [style*="background-image"] { filter: invert( 1 ) hue-rotate( 180deg ); }

/* Light: force a white background and black text across the whole page — not just
   `body` — so a themed section with its own dark background becomes readable too. */
html.vtap-o-light body, html.vtap-o-light body * { background: #fff !important; color: #000 !important; }
html.vtap-o-light body a { color: #0036c7 !important; }
html.vtap-o-light body img, html.vtap-o-light body picture, html.vtap-o-light body video, html.vtap-o-light body svg { filter: none !important; }

/* High contrast: black background, yellow text, cyan links. */
html.vtap-o-highcontrast body, html.vtap-o-highcontrast body * { background: #000 !important; color: #ff0 !important; border-color: #ff0 !important; }
html.vtap-o-highcontrast body a { color: #0ff !important; }
html.vtap-o-highcontrast body img, html.vtap-o-highcontrast body picture, html.vtap-o-highcontrast body video { filter: none !important; }

/* Backgrounds that carry meaning, exempted from the blanket overrides above.
   A progress bar shows its value *as* a filled background; forcing every element to one
   colour makes the fill identical to its track, so the bar reads as empty at any value.
   The same goes for <meter> and for anything a page has declared as a progressbar.

   Keyed on the ARIA and HTML the page states about itself rather than on a framework's
   class names — Elementor, Bootstrap and hand-rolled bars all carry role="progressbar",
   and a plugin that special-cased one of them would silently fail on the rest.

   `revert` returns the property to whatever the page's own stylesheet said, which is the
   only value that can be right here: the overlay has no way to know what the bar's colour
   is meant to be. These selectors outrank `body *` on class-column specificity, so they
   win despite coming from the same !important origin. */
html.vtap-o-light [role="progressbar"],
html.vtap-o-light [role="progressbar"] *,
html.vtap-o-light progress,
html.vtap-o-light meter,
html.vtap-o-highcontrast [role="progressbar"],
html.vtap-o-highcontrast [role="progressbar"] *,
html.vtap-o-highcontrast progress,
html.vtap-o-highcontrast meter {
	background: revert !important;
	background-color: revert !important;
}

html.vtap-o-stopanim *, html.vtap-o-stopanim *::before, html.vtap-o-stopanim *::after {
	animation-duration: 0.001ms !important;
	animation-iteration-count: 1 !important;
	transition-duration: 0.001ms !important;
	scroll-behavior: auto !important;
}

/* Hide content images and inline url() backgrounds; CSS gradients (also technically
   background-image) are design, not photos, and are left alone. */
html.vtap-o-hideimg img, html.vtap-o-hideimg picture, html.vtap-o-hideimg video { visibility: hidden !important; }
html.vtap-o-hideimg [style*="url("] { background-image: none !important; }

html.vtap-o-bigcursor,
html.vtap-o-bigcursor * {
	cursor: url( 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24"><path d="M4 2l16 9-7 1 4 8-3 1-4-8-6 4z" fill="black" stroke="white" stroke-width="1.2"/></svg>' ) 2 2, auto !important;
}

html.vtap-o-focus :focus,
html.vtap-o-focus :focus-visible {
	outline: 3px solid #e74c3c !important;
	outline-offset: 2px !important;
	box-shadow: 0 0 0 3px rgba( 231, 76, 60, 0.4 ) !important;
}

html.vtap-o-align-left body, html.vtap-o-align-left p, html.vtap-o-align-left li, html.vtap-o-align-left td,
html.vtap-o-align-left h1, html.vtap-o-align-left h2, html.vtap-o-align-left h3, html.vtap-o-align-left h4, html.vtap-o-align-left h5, html.vtap-o-align-left h6 { text-align: left !important; }
html.vtap-o-align-center body, html.vtap-o-align-center p, html.vtap-o-align-center li, html.vtap-o-align-center td,
html.vtap-o-align-center h1, html.vtap-o-align-center h2, html.vtap-o-align-center h3, html.vtap-o-align-center h4, html.vtap-o-align-center h5, html.vtap-o-align-center h6 { text-align: center !important; }
html.vtap-o-align-right body, html.vtap-o-align-right p, html.vtap-o-align-right li, html.vtap-o-align-right td,
html.vtap-o-align-right h1, html.vtap-o-align-right h2, html.vtap-o-align-right h3, html.vtap-o-align-right h4, html.vtap-o-align-right h5, html.vtap-o-align-right h6 { text-align: right !important; }

html.vtap-o-hoverhighlight .vtap-o-hovered { outline: 3px solid #ffbf47 !important; outline-offset: 1px; }

.vtap-o-bionic-b { font-weight: 700; }

/* --- Narrow screens -------------------------------------------------------------------
 *
 * The panel is 340px wide and opens beside the toggle. For the four corner positions that
 * is fine at any width, because the panel's right edge sits on the root's own edge and
 * `max-width: 90vw` already keeps it on screen.
 *
 * The two *middle* positions are different: there the panel is pushed 64px inwards to
 * clear the 52px button, and that offset was never subtracted from the width cap. Add the
 * root's own 16px inset and a 340px panel needs 420px of viewport — so on a 360px phone
 * it hung 60px off the edge and the first characters of every label were cut off. This is
 * inherited from the reference product, which has no media queries at all and the same
 * arithmetic; it is a deviation from parity, deliberately.
 *
 * The panel must never simply cover the button either: Escape closes it, and a phone has
 * no Escape key, so the toggle has to stay reachable.
 */
#vtap-overlay-root.vtap-o-pos-middleright .vtap-overlay-panel,
#vtap-overlay-root.vtap-o-pos-middleleft .vtap-overlay-panel {
	max-width: calc( 100vw - 88px ) !important;
}

@media ( max-width: 480px ) {

	/* Reclaim horizontal space for the controls, which is scarcer than vertical space. */
	#vtap-overlay-root .vtap-overlay-panel {
		padding: 10px !important;
		font-size: 14px !important;
	}

	/* A label needs less than 120px before it is allowed to sit on its own line; below
	   that the stepper wrapped even where both would have fitted side by side. */
	#vtap-overlay-root .vtap-overlay-row > span {
		min-width: 96px !important;
		font-size: 14px !important;
	}

	/* Taller than wide: let the panel use the height it now needs after wrapping. */
	#vtap-overlay-root .vtap-overlay-panel {
		max-height: calc( 100vh - 48px ) !important;
	}
}

/* Landscape phones: almost no vertical room, so the panel scrolls rather than being
   clipped by the viewport it is centred in. */
@media ( max-height: 480px ) {
	#vtap-overlay-root .vtap-overlay-panel {
		max-height: calc( 100vh - 24px ) !important;
	}
}
