/* =========================================================================
 * Display preferences
 *
 * A small control, bottom left, and the switches it sets.
 *
 * CONTRAST, measured
 *   cream #f2e7d0 on blue-deep #01426a   8.61:1
 *   blue-deep on cream                   8.61:1
 * Both well clear of 4.5:1, which matters more here than anywhere else on the
 * site: this is the control somebody reaches for when they are already
 * struggling to read the page.
 *
 * ON !important
 * The rest of this codebase does not use it and says so. Here it is correct
 * and not a shortcut. These rules exist to override author styles on request
 * of the reader, which is precisely the case the cascade reserves it for; a
 * user preference that loses to a component's own colour is not a preference.
 * ====================================================================== */

/*
 * The theme puts padding on buttons, which made the round toggle 60x52: an
 * ellipse, not a circle. Border-box and an explicit reset keep the shape the
 * width and height say it is, whatever a theme decides about buttons.
 */
.a11y,
.a11y *,
.a11y *::before,
.a11y *::after {
	box-sizing: border-box;
}

.a11y {
	--a11y-blue: #01426a;
	--a11y-blue-lift: #015c94;
	--a11y-cream: #f2e7d0;
	--a11y-orange: #e58d05;
	--a11y-on-orange: #26180a;
	--a11y-display: Impact, Haettenschweiler, 'Arial Narrow Bold', 'Arial Black', sans-serif;
	/* Impact is single-weight; stop the browser faking the bolds. */
	font-synthesis: none;
	--a11y-body: Helvetica, Arial, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
	--a11y-ease: cubic-bezier(.2, .7, .3, 1);
}

/* ---- The button --------------------------------------------------------
 * Bottom left, out of the way of the cookie banner's buttons on the right
 * and of anything a page puts bottom-right.
 * --------------------------------------------------------------------- */

/*
 * EVERY BUTTON RULE BELOW IS SCOPED WITH .a11y, AND HAS TO BE.
 *
 * This widget rendered in hello-elementor's pink, #c36, on production and on
 * staging: a transparent pill with a pink border and a pink icon, and a panel
 * whose every control was pink on cream. None of that colour appears anywhere
 * in this file. The theme's reset.css carries
 *
 *   [type=button],[type=submit],button {
 *     background-color: transparent; border: 1px solid #c36; color: #c36;
 *   }
 *
 * and [type=button] is an attribute selector, which is specificity (0,1,0) —
 * exactly the same as a bare class like .a11y__toggle. A tie is broken by
 * source order, and the theme's stylesheet is enqueued after this plugin's, so
 * the reset won every one of these properties.
 *
 * Adding the wrapper takes these rules to (0,2,0), which wins on specificity
 * instead of on load order. That matters more than the two characters suggest:
 * enqueue order is decided by other people's plugins and by WordPress, and a
 * rule that only works while it happens to load last is a rule that will break
 * again without anybody touching this file.
 *
 * Not !important, which would win the same argument by refusing to have it and
 * would make this widget unthemeable by anything downstream.
 */
.a11y .a11y__toggle {
	position: fixed;
	left: clamp(12px, 2.5vw, 24px);
	bottom: clamp(12px, 2.5vw, 24px);
	z-index: 2147482000;

	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	min-width: 52px;
	padding: 0;
	flex: none;
	line-height: 1;

	border: 2px solid var(--a11y-cream);
	border-radius: 50%;
	background: var(--a11y-blue);
	color: var(--a11y-cream);
	cursor: pointer;

	box-shadow: 0 4px 16px rgba(1, 66, 106, .35);
	transition: background .18s var(--a11y-ease), transform .18s var(--a11y-ease);
}

.a11y .a11y__toggle:hover,
.a11y .a11y__toggle:focus-visible {
	background: var(--a11y-blue-lift);
}

.a11y .a11y__toggle:active {
	transform: translateY(1px);
}

.a11y .a11y__toggle svg {
	width: 26px;
	height: 26px;
	display: block;
}

/*
 * Lift clear of the cookie banner while it is showing.
 *
 * The banner is a fixed full width bar along the bottom and would sit exactly
 * on top of this. Somebody may need these controls in order to read that
 * banner, so the button moves instead of waiting.
 *
 * The two offsets are deliberately different. Giving both the same `bottom`,
 * as this rule used to, stacked the panel directly on the button instead of
 * above it. The panel keeps the same 62px clearance it has in the resting
 * state, so the relationship between the two is identical whether the banner
 * is up or not.
 */
html[data-a11y-raised] .a11y__toggle {
	bottom: clamp(150px, 34vh, 260px);
}

html[data-a11y-raised] .a11y__panel {
	bottom: calc(clamp(150px, 34vh, 260px) + 62px);
}

/* ---- The panel ---------------------------------------------------------
 * A popover, not a modal. It does not cover the page, does not trap focus and
 * does not stop anything behind it working.
 * --------------------------------------------------------------------- */

.a11y__panel {
	position: fixed;
	left: clamp(12px, 2.5vw, 24px);
	bottom: calc(clamp(12px, 2.5vw, 24px) + 62px);
	z-index: 2147482001;

	width: min(310px, calc(100vw - 24px));
	padding: 18px;

	border: 2px solid var(--a11y-blue);
	border-radius: 16px;
	background: var(--a11y-cream);
	color: var(--a11y-blue);
	font-family: var(--a11y-body);

	box-shadow: 0 12px 40px rgba(1, 66, 106, .3);
}

.a11y__panel[hidden] {
	display: none;
}

.a11y__title {
	margin: 0 0 4px;
	font-family: var(--a11y-body);
	font-weight: 600;
	font-size: 15px;
	letter-spacing: .12em;
	text-transform: uppercase;
}

.a11y__note {
	margin: 0 0 14px;
	font-size: 13px;
	line-height: 1.5;
	color: #14303f;
}

.a11y__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 8px;
}

.a11y .a11y__opt {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	width: 100%;
	min-height: 44px;
	padding: 8px 14px;

	border: 1.5px solid var(--a11y-blue);
	border-radius: 999px;
	background: transparent;
	color: var(--a11y-blue);

	font-family: var(--a11y-body);
	font-weight: 500;
	font-size: 13.5px;
	letter-spacing: .06em;
	text-transform: uppercase;
	text-align: left;
	cursor: pointer;

	transition: background .16s var(--a11y-ease), color .16s var(--a11y-ease);
}

.a11y .a11y__opt:hover {
	background: rgba(1, 66, 106, .08);
}

/*
 * aria-pressed carries the state for a screen reader and the fill carries it
 * for everyone else, so neither is doing the job alone. The tick is a third
 * channel, which matters because this is the one control on the site most
 * likely to be used by somebody who cannot rely on colour.
 */
.a11y .a11y__opt[aria-pressed="true"] {
	background: var(--a11y-blue);
	color: var(--a11y-cream);
}

.a11y .a11y__opt[aria-pressed="true"] .a11y__tick {
	visibility: visible;
}

.a11y__tick {
	visibility: hidden;
	flex: none;
	width: 15px;
	height: 15px;
}

.a11y .a11y__value {
	font-variant-numeric: tabular-nums;
	font-weight: 600;
}

.a11y__foot {
	margin: 14px 0 0;
	padding-top: 12px;
	border-top: 1px solid rgba(1, 66, 106, .25);
	font-size: 13px;
	line-height: 1.5;
}

.a11y__foot a {
	color: var(--a11y-blue);
	font-weight: 600;
}

.a11y .a11y__reset {
	margin-top: 10px;
	min-height: 44px;
	width: 100%;
	padding: 8px 14px;
	border: 1.5px solid rgba(1, 66, 106, .45);
	border-radius: 999px;
	background: transparent;
	color: var(--a11y-blue);
	font-family: var(--a11y-body);
	font-weight: 500;
	font-size: 13px;
	letter-spacing: .06em;
	text-transform: uppercase;
	cursor: pointer;
}

.a11y .a11y__reset:hover {
	background: rgba(1, 66, 106, .08);
}

.a11y :focus-visible,
.a11y .a11y__toggle:focus-visible {
	outline: 3px solid var(--a11y-orange);
	outline-offset: 2px;
}

/* =========================================================================
 * What the preferences actually do
 * ====================================================================== */

/* ---- Underline every link ---------------------------------------------
 * Colour alone is not a link cue. This is the switch for anybody who cannot
 * see the colour difference, so it applies to every link on the page rather
 * than trying to guess which ones "look like buttons already".
 * --------------------------------------------------------------------- */

html[data-a11y-links="on"] a {
	text-decoration: underline !important;
	text-underline-offset: .18em;
	text-decoration-thickness: from-font;
}

/* ---- Stronger contrast -------------------------------------------------
 * The site's own muted inks are pushed to their darkest sibling. These are
 * tokens this codebase defines, so this is turning our own dials up rather
 * than trying to repaint arbitrary markup, which is where overlay widgets
 * come unstuck.
 *
 * WHERE a token is declared decides where it can be overridden, and this file
 * had it wrong. --ink-2, --edge, --edge-ctl, --cc-ink-soft and --csc-ink-2 are
 * every one of them declared on their own component's root — .cb, .mc, .cs,
 * .cc-panel, .csc-legal — and never on :root. A declaration on the component
 * is closer to the elements reading it than one on html[…], so overriding them
 * at the root reached nothing at all. The control looked implemented and was,
 * for those components, doing nothing.
 *
 * So each is answered where it is declared. The failure is silent — no error,
 * no warning, the panel just does not visibly work — so when a component gains
 * its own palette, it needs a line here.
 * --------------------------------------------------------------------- */

/*
 * The exception, and the reason it is worth keeping components on shared
 * tokens: the SPA's blue-ground palette lives on :root in Homepage.css, so one
 * override covers the homepage, About, Events, Issues, Recognition and the
 * opportunities strip together.
 *
 * The muted cream is the same cream at 92% opacity, so full opacity is
 * literally its darkest sibling. The pink reads as decoration at body size on
 * this blue and goes to cream, matching the header and footer below. The
 * hairline is the one non-text value here: at 0.18 a card boundary is a
 * suggestion, and on these pages the boundary is the information.
 */
html[data-a11y-contrast="on"] {
	--chd-ink-on-blue-2: #f6efe0;
	--chd-pink-text: #f2e7d0;
	--chd-line: rgba(242, 231, 208, 0.42);
}

/* Paper grounds. The muted body ink goes to the blue that measures 9.9:1. */
html[data-a11y-contrast="on"] .cb {
	--ink-2: #01426a;
	--ink-3: #01426a;
	--edge: #8f8471;
}

/*
 * Dark grounds, and the reason this rule is separate.
 *
 * .mc and .cs used to sit in the paper-grounds rule above, on the assumption
 * that a token called --ink-2 means the same thing everywhere. It does not.
 * Both pages are dark: .mc-app is on --blue #015c94 and its nav on --blue-ink
 * #013755, and both declare --ink-2 as rgba(246,239,224,.78), cream at 78%.
 *
 * So "stronger contrast" was painting #01426a, a deep blue, onto a blue
 * ground — roughly 1.5:1, which is not low contrast but no contrast. Turning
 * the control on made My Circle and the Staff Portal harder to read than
 * leaving it off, which is the precise failure the top of a11y.js says this
 * widget exists not to commit.
 *
 * On a dark ground the muted ink's darkest sibling is the full-opacity cream,
 * not a blue. #f6efe0 measures 6.19:1 on --blue and 10.9:1 on --blue-ink.
 *
 * --ink-3 and --edge are not in that rule because neither page declares them;
 * they were dead weight. The hairline is --line here, and on pages that are
 * mostly panel boundaries the boundary is information, so it goes up too.
 */
html[data-a11y-contrast="on"] .mc,
html[data-a11y-contrast="on"] .cs {
	--ink-2: #f6efe0;
	--line: rgba(242, 231, 208, 0.42);
	--line-2: rgba(242, 231, 208, 0.62);
}

/* The unselected control boundary, which measures 3.61:1 as shipped. */
html[data-a11y-contrast="on"] .cb--index {
	--edge-ctl: #01426a;
}

html[data-a11y-contrast="on"] .crw {
	--ink-soft: #2c3f4b;
}

html[data-a11y-contrast="on"] .cc-panel {
	--cc-ink-soft: #102734;
}

html[data-a11y-contrast="on"] .csc-legal {
	--csc-ink-2: #102734;
}

/* Cream on the deep blue grounds rather than the softer pinks and greys. */
html[data-a11y-contrast="on"] .csc-ftr,
html[data-a11y-contrast="on"] .csc-hdr {
	--csc-pink-text: #f2e7d0;
}

/* ---- Reduce motion -----------------------------------------------------
 * Also fixes something the theme does site-wide: it sets scroll-behavior to
 * smooth for everybody, which is exactly the effect somebody with vestibular
 * sensitivity would be turning this on to escape.
 * --------------------------------------------------------------------- */

html[data-a11y-motion="reduce"] *,
html[data-a11y-motion="reduce"] *::before,
html[data-a11y-motion="reduce"] *::after {
	animation-duration: .001ms !important;
	animation-iteration-count: 1 !important;
	transition-duration: .001ms !important;
	scroll-behavior: auto !important;
}

html[data-a11y-motion="reduce"] {
	scroll-behavior: auto !important;
}

/* ---- Larger text -------------------------------------------------------
 * Set on the root, so everything sized in rem or em follows. Sizes written in
 * px do not, which is why the panel says outright that browser zoom scales
 * everything and this does not. Saying so is the difference between a control
 * and a placebo.
 * --------------------------------------------------------------------- */

html[data-a11y-text="1"] {
	font-size: 112.5%;
}

html[data-a11y-text="2"] {
	font-size: 125%;
}

/* ---- The widget respects the system setting too ---------------------- */

@media (prefers-reduced-motion: reduce) {
	.a11y__toggle,
	.a11y__opt {
		transition: none;
	}

	.a11y__toggle:active {
		transform: none;
	}
}

@media (forced-colors: active) {
	.a11y__toggle {
		forced-color-adjust: none;
		background: Canvas;
		color: CanvasText;
		border-color: CanvasText;
	}

	.a11y__opt[aria-pressed="true"] {
		forced-color-adjust: none;
		background: Highlight;
		color: HighlightText;
	}
}
