#tpa-toolbar {
    position: fixed;
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    z-index: 9999;
}

#tpa-toolbar button {
    position: relative;
    padding: 0.5rem;
    width: 3rem;
    height: 3rem;
    border: none;
    background: #000;
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

#tpa-toolbar svg {
    width: 1.5rem;
    height: 1.5rem;
}

#tpa-toolbar button.tpa-active {
    background: #fff;
    color: #000;
    outline: 2px solid #000;
}

#tpa-toolbar .tpa-tooltip {
    position: absolute;
    left: 100%;
    top: 50%;
    transform: translateY(-50%);
    background: #000;
    color: #fff;
    padding: 0.25rem 0.5rem;
    white-space: nowrap;
    /* Not rendered until wanted, rather than rendered at opacity 0. A label that
       is laid out but invisible is still text to a checker: WAVE reported all
       three as "very low contrast" on every page, and went on doing so with
       opacity forced to 1 and with visibility:hidden. Only display:none is
       skipped. Costs the 0.2s fade. */
    display: none;
    pointer-events: none;
    margin-left: 0.5rem;
    font-size: 0.875rem;
}

#tpa-toolbar button:hover .tpa-tooltip,
#tpa-toolbar button:focus .tpa-tooltip {
    display: block;
}

.tpa-high-contrast,
.tpa-high-contrast * {
    background-color: #000 !important;
    color: #fff !important;
}

.tpa-high-contrast a {
    color: #0ff !important;
}

.tpa-high-contrast #tpa-toolbar button.tpa-active {
    background: #fff !important;
    color: #000 !important;
}

.tpa-dyslexic,
.tpa-dyslexic *:not(i):not(svg):not([class*="icon"]):not([class*="dashicon"]):not(.fa):not([class*="fa-"]) {
    font-family: 'OpenDyslexic', sans-serif !important;
}

.tpa-dyslexic #tpa-toolbar,
.tpa-dyslexic #tpa-toolbar * {
    font-family: initial !important;
    font-size: initial !important;
}

/* Body only, never the root: a font-size on <html> redefines what 1rem means
   and would resize everything on the site that is sized in rem. */
body.tpa-dyslexic,
html.tpa-dyslexic body {
    font-size: 18px !important;
}

.tpa-dyslexic div:not(#tpa-toolbar):not([class*="icon"]):not([class*="dashicon"]):not(.fa):not([class*="fa-"]) {
    font-size: 18px !important;
}

.tpa-dyslexic h1 {
    font-size: 40px !important;
}

.tpa-dyslexic h2 {
    font-size: 34px !important;
}

.tpa-dyslexic h3 {
    font-size: 24px !important;
}

.tpa-dyslexic h4 {
    font-size: 20px !important;
}

.tpa-dyslexic h5 {
    font-size: 18px !important;
}

.tpa-dyslexic h6 {
    font-size: 16px !important;
}

.tpa-dyslexic h1,
.tpa-dyslexic h2,
.tpa-dyslexic h3,
.tpa-dyslexic h4,
.tpa-dyslexic h5,
.tpa-dyslexic h6,
.tpa-dyslexic strong,
.tpa-dyslexic b {
    font-weight: 700 !important;
}

.tpa-dyslexic a {
    font-style: italic !important;
}

/*
 * The toolbar sits inside an <aside> so that its buttons live in a landmark
 * (axe "region" flags any content outside one). The toolbar itself is
 * position: fixed, so the wrapper must not contribute a box of its own —
 * it would otherwise pick up the theme's default aside margins and push the
 * footer down. display: contents is deliberately avoided: some browsers drop
 * elements with it from the accessibility tree, which would undo the point.
 */
.tpa-landmark {
    margin: 0;
    padding: 0;
    border: 0;
}

/* The single banner wrapped round a template's header rows (merge_header_run).
   It must add nothing: the rows inside are fixed or in normal flow and must sit
   exactly where they did. */
.tpa-banner {
    margin: 0;
    padding: 0;
    border: 0;
}

/*
 * Visually hidden, but still read aloud. Used for the corner cell of a
 * converted document's header row: the page has to keep looking like the
 * original PDF, while a screen reader still gets a name for the column.
 */
.tpa-visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/*
 * Links inside the cookie policy inherit the site link colour, which on the
 * policy's near-white panels measures 3.2-3.5:1 — under the 4.5:1 AA minimum
 * for body-size text. It affects the contents list, the service notes and the
 * cookiedatabase.org references. Darken them here, scoped to that page,
 * rather than changing the site-wide link colour and every other page with it.
 */
.tpcc-policy a,
.tpcc-policy a:visited {
    color: #1e3a8a;
}

/*
 * WooCommerce's info notice ships as #0ea5e9 on #e0f2fe — 2.6:1, well under
 * the 4.5:1 AA minimum. It is the box a shopper sees when a search returns
 * nothing, so it is exactly the message that must be readable.
 */
.woocommerce-info,
.woocommerce-message,
.woocommerce-error,
.woocommerce .woocommerce-info,
.woocommerce .woocommerce-message,
.woocommerce .woocommerce-error {
    /* The theme's own rule is more specific, so match it and win on order. */
    color: #075985 !important;
}

/*
 * TP External Link Notice marks outbound links with .tpeln-external. The site
 * link colour is usually a light blue that lands at 3.7:1 on white, under the
 * 4.5:1 AA minimum for body text (measured on Whicham's planning applications
 * table, 14px #3b82f6 on #fff). Darken just these rather than changing the
 * site-wide link colour.
 *
 * 0.5.7 used #1d4ed8, which is 6.7:1 on white but only 3.42:1 on Askam's
 * #5fcf80 footer - so the fix for white backgrounds BECAME the contrast error
 * on every page of a site with a coloured footer, 251 of them. #1e3a8a is
 * 10.4:1 on white and 5.3:1 on that green, so it passes on any light panel,
 * and repairs.js measures the real background and overrides this where the
 * panel is dark. Re-check both if you change it.
 */
.tpeln-external,
.tpeln-external:visited {
    color: #1e3a8a;
}

/*
 * repairs.js makes any sideways-scrolling box keyboard focusable (WCAG 2.1.1).
 * Anything focusable needs a visible focus indicator (WCAG 2.4.7, 2.4.13), and
 * these boxes have no styling of their own to carry one.
 */
[data-tpa-scroll]:focus-visible {
    outline: 3px solid #0b2447;
    outline-offset: 2px;
}

[data-tpa-scroll]:focus:not(:focus-visible) {
    outline: none;
}

/*
 * Breakdance's skip link inherits the site link colour. On these sites that is
 * #3b82f6, which WAVE flags as a contrast error even while the link is clipped,
 * and which would be genuinely unreadable the moment a keyboard user tabs to it.
 * Give it a solid high-contrast treatment and make it properly visible on focus.
 */
.bde-skip-link {
    color: #ffffff !important;
    background-color: #0b2447 !important;
}

.bde-skip-link:focus {
    position: fixed !important;
    top: 8px !important;
    left: 8px !important;
    z-index: 100000 !important;
    width: auto !important;
    height: auto !important;
    padding: 12px 20px !important;
    clip: auto !important;
    clip-path: none !important;
    overflow: visible !important;
    border-radius: 4px !important;
    outline: 3px solid #ffd60a !important;
    outline-offset: 2px !important;
    text-decoration: underline !important;
}

/*
 * Breakdance's header search fails WCAG 2.2 target size (2.5.8) on every page.
 * NOT because the button is small — it measures 52x52. The search input is
 * stacked over the top of it, so only a 1.4px-wide strip is actually clickable
 * ("partially obscured", axe target-size). A min-size rule does nothing for
 * that; the button has to come forward. z-index only — no geometry changes, so
 * the header looks identical.
 */
.search-form__button,
button.search-form__button {
    position: relative;
    z-index: 2;
    min-width: 24px;
    min-height: 24px;
}

/*
 * WCAG 1.4.10 Reflow — a clerk's email address used as link text.
 *
 * "theclerk@millomwithoutparishcouncil.gov.uk" is one unbreakable 42-character
 * word. At a 320px viewport it cannot wrap, so it pushes the page 536px wide
 * and the whole site scrolls sideways — content lost in two dimensions, which
 * is exactly what 1.4.10 forbids. Measured on six of the seven council sites
 * (statement pages and two home pages) on 11 October 2026.
 *
 * The block elements are included so the next pasted URL cannot do the same
 * thing. Which value each gets, and why, is in the two rules below.
 */
a[href^="mailto:"],
a[href^="tel:"],
a[href^="http"] {
    /*
     * anywhere, not break-word. Both wrap a long word, but only `anywhere`
     * reduces the element's MIN-CONTENT width, and that is what a flex item
     * is sized by — Breakdance's Text Link is display:flex, so with
     * break-word the address still measured 392px inside a 277px parent and
     * the page still scrolled. Proven by setting each value on the live
     * element and measuring: break-word 392px, anywhere 277px. min-width:0
     * does nothing here; it was already 0.
     */
    overflow-wrap: anywhere;
}

p, li, td, dd, blockquote,
h1, h2, h3, h4, h5, h6 {
    /* Prose is not a flex item, so the gentler value is right here: it only
     * breaks a word that would otherwise overflow. */
    overflow-wrap: break-word;
}

/*
 * A Breakdance Button inside a flex row will not shrink, so at 320px it hangs
 * out of its column and scrolls the whole page sideways — Bootle's home page
 * measured 323px against a 320px viewport because of "Meet the Councillors".
 *
 * min-width:0 is the fix and max-width:100% is not: a flex item is sized by
 * its min-content width, and capping max-width leaves that untouched. Measured
 * on the live element — min-width:0 took the page to 320 and let the label
 * wrap; max-width:100% left it at 323. The rule is inert at normal widths,
 * where the column has room.
 */
.bde-button {
    min-width: 0;
}

/*
 * The skip link this plugin adds on a site whose builder does not provide one
 * (see add_main_landmark()). Clipped until focused, then a solid high-contrast
 * chip at the top left — the same treatment as Breakdance's own, so a keyboard
 * user sees the same thing on every council site.
 */
.tpa-skip-link {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: 0;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    color: #ffffff !important;
    background-color: #0b2447 !important;
}

.tpa-skip-link:focus {
    position: fixed !important;
    top: 8px !important;
    left: 8px !important;
    z-index: 100000 !important;
    width: auto !important;
    height: auto !important;
    padding: 12px 20px !important;
    clip: auto !important;
    clip-path: none !important;
    overflow: visible !important;
    border-radius: 4px !important;
    outline: 3px solid #ffd60a !important;
    outline-offset: 2px !important;
    text-decoration: underline !important;
}

/* A main landmark we added must not pick up a focus ring when the skip link
 * sends focus to it. tabindex="-1" is there to make it focusable at all, and
 * the target id is the builder's own, so this is matched on the tag. */
[role="main"][tabindex="-1"]:focus,
main[tabindex="-1"]:focus {
    outline: none;
}

/*
 * Oxygen's post-loop date badge sits on whatever photograph the post happens
 * to carry, so its contrast is whatever that image gives you — measured at
 * 4.01:1 against the 4.5 the text size needs, on every blog card of the
 * council site built with Oxygen.
 *
 * A fixed dark scrim is the only answer that holds for ANY image behind it.
 * At 85% black the worst case is a pure white photograph: the composite sits
 * at 0.15 luminance, which still gives white text about 5.2:1. The badge was
 * already dark, so this reads as the same design, slightly firmer.
 */
.oxy-post-image-date-overlay {
    background-color: rgba(0, 0, 0, 0.85) !important;
    color: #ffffff !important;
}

/*
 * Oxygen's "Read More" is a bare text link about 19px tall, which fails WCAG
 * 2.5.8 target size (24x24) — ten of them on every blog card page. It is a
 * block-level link in a card, not a word inside a sentence, so the inline
 * exception does not rescue it. Padding gets it over the line without moving
 * anything around it.
 */
.oxy-read-more {
    display: inline-block;
    min-height: 24px;
    padding-top: 3px;
    padding-bottom: 3px;
}

/* Breakdance's multi-step form stepper: the numbers on the steps not yet
   reached are white on #9CA3AF, measured at 2.54:1 where WCAG 1.4.3 AA needs
   4.5:1 (bootleparishcouncil.co.uk/community-plan/). The text is already
   white, so no foreground change can fix it and the runtime contrast repair
   correctly left it alone — the background is what has to move. #6B7280 is
   the next step down Breakdance's own grey ramp and takes white to 4.83:1
   while still reading as "not yet reached" beside the near-black active step.
   Done in CSS because the stepper is markup the form element generates, with
   no builder control over it. */
.breakdance-form-stepper__step:not(.is-active) .breakdance-form-stepper__step-icon {
    background-color: #6b7280;
}

/*
 * PDF Embedder's page toolbar ("Page 1 / 23", "Zoom 100%") is light grey on
 * mid grey: #d3d3d3 on #808080, 2.63:1 at 12px, where WCAG 1.4.3 needs 4.5:1.
 * Both colours are the plugin's own flat values, so both are set here - white
 * on #595959 is 7:1. Setting only the text would not do: nothing lighter than
 * white exists and white on #808080 is still only 3.95:1.
 */
div.pdfemb-viewer div.pdfemb-toolbar {
    background-color: #595959;
    color: #ffffff;
}

div.pdfemb-viewer div.pdfemb-toolbar div,
div.pdfemb-viewer div.pdfemb-toolbar span {
    color: #ffffff;
}

/*
 * FOCUS RING (0.9.31) — WCAG 2.4.7 Focus Visible, 1.4.11 Non-text Contrast.
 *
 * A manual audit of Eskdale (Matthew, 13 Oct 2026) found no designed focus
 * indicator: the menu fell back to the browser's 1px blue on navy, and the
 * search field had `outline: none` and showed nothing at all.
 *
 * One colour cannot be the answer. A yellow ring is invisible on a yellow
 * button, a navy one on the navy menu. So the ring is TWO colours, drawn as
 * three bands outward from the element:
 *
 *     element | navy 2px | yellow 3px | navy 2px | page
 *
 * Navy #0B2447 and yellow #FFD60A are far enough apart that ANY colour has at
 * least 3.3:1 against one of them (the worst case is a mid-tone, where both
 * give 3.3:1). So whatever the element's own colour and whatever it sits on,
 * one band always reaches the 3:1 that 1.4.11 asks for, and the two bands
 * against each other are 11:1. tests/focus-ring.test.mjs proves the worst case
 * by sweeping every grey and a spread of colours rather than trusting the sum.
 *
 * :focus-visible, not :focus — a mouse click on a link should not ring it.
 * !important because builders set `outline: none` on fields with no fallback,
 * which is exactly the fault being repaired. :where() keeps the selector at
 * zero specificity so the only thing winning is the !important itself.
 */
:where(a[href], button, input, select, textarea, summary, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [contenteditable="true"], [tabindex]:not([tabindex="-1"])):focus-visible {
    outline: 3px solid #ffd60a !important;
    outline-offset: 2px !important;
    box-shadow: 0 0 0 2px #0b2447, 0 0 0 7px #0b2447 !important;
}

/* An inline link that wraps over two lines draws its box-shadow per fragment
   and looks torn. box-decoration-break closes each fragment properly. */
:where(a[href]):focus-visible {
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
}

/* Windows High Contrast drops box-shadow; give it a ring the system colours. */
@media (forced-colors: active) {
    :where(a[href], button, input, select, textarea, summary, [role="button"], [tabindex]:not([tabindex="-1"])):focus-visible {
        outline: 3px solid Highlight !important;
        box-shadow: none !important;
    }
}
