/* ============================================================================
   Accessibility base layer (WCAG 2.2)

   Plain CSS on purpose: this file is enqueued LAST, after output.css and
   custom.css, so it wins the cascade over Tailwind's `focus:outline-none`
   utilities scattered through the templates and over the inline
   `*:focus { outline: ... !important }` rule injected by the
   aria-accessibility-toolkit plugin. Keeping it out of the SCSS build also
   means a focus ring can never disappear because someone forgot to run gulp.
   ========================================================================= */

/* ---------------------------------------------------------------------------
   1. Focus visibility — 2.4.7 (A), 2.4.11 (AA), 2.4.13 Focus Appearance (AAA)

   Two concentric rings: a 2px white shadow hugging the element, then a 3px
   brand-blue outline. On light surfaces the blue ring carries the contrast
   (#1c28a0 on white = 11.9:1); on the red/blue brand surfaces the white ring
   does. That way one ring always clears 3:1 without having to enumerate every
   dark background. If a clipping ancestor eats the box-shadow, the outline
   still survives.
   ------------------------------------------------------------------------- */
:where(a, button, input, select, textarea, summary, [tabindex]):focus {
    outline: none;
}

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible,
.vb-focus-ring:focus-visible {
    outline: 3px solid #1c28a0 !important;
    outline-offset: 2px !important;
    box-shadow: 0 0 0 2px #ffffff !important;
    border-radius: 2px;
    /* Most interactive elements carry Tailwind's `transition-all duration-300`,
       which animates the ring into view over 300ms — it reads as lag and the
       ring is the wrong colour for most of that time. */
    transition-property: color, background-color, border-color, opacity, transform !important;
}

/* Elements that already sit on a saturated brand colour: lead with white. */
.bg-red-700 :focus-visible,
.bg-red-800 :focus-visible,
.bg-blue-700 :focus-visible,
.bg-blue-800 :focus-visible,
.topbar :focus-visible,
footer .bg-red-700 :focus-visible {
    outline-color: #ffffff !important;
    box-shadow: 0 0 0 2px #1f1f1f !important;
}

/* Visually hidden inputs (the styled checkbox/radio pattern in the forms) put
   the ring on the element that is actually painted. */
.sr-only:focus-visible + span,
.peer:focus-visible + span {
    outline: 3px solid #1c28a0 !important;
    outline-offset: 2px !important;
}

/* Windows high-contrast / forced-colors: system colours only. */
@media (forced-colors: active) {
    :focus-visible {
        outline: 3px solid Highlight !important;
        outline-offset: 2px !important;
        box-shadow: none !important;
    }
}

/* The header is position:fixed (62px mobile / 127px desktop). Without this the
   browser scrolls a freshly focused element underneath it — 2.4.11 (AA). */
html {
    scroll-padding-top: 14rem;
}

@media (max-width: 990px) {
    html {
        scroll-padding-top: 8rem;
    }
}

/* ---------------------------------------------------------------------------
   2. Skip link — 2.4.1 Bypass Blocks (A)

   24 focusable stops sit between <body> and <main>. The link is off-screen
   until focused, then parks itself over the header.
   ------------------------------------------------------------------------- */
.vb-skip-link {
    position: fixed;
    top: -100px;
    left: 1.6rem;
    z-index: 100010;
    display: inline-block;
    padding: 1.2rem 2rem;
    background: #ffffff;
    color: #1c28a0;
    font-size: 1.6rem;
    line-height: 1.4;
    font-weight: 700;
    text-decoration: underline;
    border: 2px solid #1c28a0;
    border-radius: 0.8rem;
    transition: top 0.15s ease-in-out;
}

.vb-skip-link:focus {
    top: 1.6rem;
}

@media (prefers-reduced-motion: reduce) {
    .vb-skip-link {
        transition: none;
    }
}

/* <main> receives focus programmatically from the skip link; never paint a
   ring on a whole page region. */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
    outline: none !important;
    box-shadow: none !important;
}

/* ---------------------------------------------------------------------------
   3. Screen-reader-only text

   Tailwind's .sr-only exists but is used inside the forms for real inputs, so
   these are separate names that can never be repurposed by a utility class.
   ------------------------------------------------------------------------- */
.vb-sr-only {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* Same, but becomes visible when focused (used for in-page shortcuts). */
.vb-sr-only-focusable:not(:focus):not(:focus-within) {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* ---------------------------------------------------------------------------
   4. Hiding that also removes elements from the tab order

   The mobile drawer and the language dropdown were hidden with translate /
   opacity only, which leaves every link inside them focusable on every page.
   These rules make "visually hidden" and "not focusable" the same thing.
   ------------------------------------------------------------------------- */
[hidden] {
    display: none !important;
}

.vb-inert,
.vb-inert * {
    pointer-events: none !important;
}

/* ---------------------------------------------------------------------------
   5. Target size — 2.5.8 Minimum (AA, 24px) / 2.5.5 Enhanced (AAA, 44px)

   Applied to the icon-only controls, which were 20x20. The visual icon keeps
   its size; only the hit area grows.
   ------------------------------------------------------------------------- */
:where(.vb-target, .vb-target-min) {
    display: inline-flex;
}

.vb-target {
    align-items: center;
    justify-content: center;
    min-width: 4.4rem;
    min-height: 4.4rem;
}

/* Inline controls that sit in a dense row can only reach the AA floor. */
.vb-target-min {
    align-items: center;
    justify-content: center;
    min-width: 2.4rem;
    min-height: 2.4rem;
}

/* A hidden control has no target size to meet. */
.vb-target[hidden],
.vb-target-min[hidden] {
    display: none !important;
}

/* ---------------------------------------------------------------------------
   6. Reduced motion — 2.3.3 Animation from Interactions (AAA), 2.2.2 (A)

   The theme has smooth scrolling on <html>, transitions on nearly every
   interactive element, Swiper transitions and jQuery slide/fade animations.
   CSS covers the first three; jQuery is switched off in assets/js/a11y.js.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto !important;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        animation-delay: 0ms !important;
        transition-duration: 0.01ms !important;
        transition-delay: 0ms !important;
        scroll-behavior: auto !important;
    }

    /* Swiper drives slide movement through inline transition-duration. */
    .swiper-wrapper {
        transition-duration: 0ms !important;
    }

    /* Hover cues that rely on movement lose the movement, not the cue. */
    .group:hover img,
    .group-hover\:scale-105:hover {
        transform: none !important;
    }
}

/* ---------------------------------------------------------------------------
   7. Non-text contrast — 1.4.11 (AA)

   --gray #d6d6d6 form borders are 1.45:1 against white. #767676 is the
   lightest grey that clears 3:1 (4.54:1) while staying visually quiet.
   ------------------------------------------------------------------------- */
:root {
    --vb-border-contrast: #767676;
    --vb-focus-ring: #1c28a0;
    --vb-red-on-tint: #99000a;
}

/* ---------------------------------------------------------------------------
   8. Live region container

   Injected once into the footer by inc/accessibility.php and fed by
   assets/js/a11y.js. Must stay in the DOM at all times — a live region added
   at announcement time is not reliably read.
   ------------------------------------------------------------------------- */
#vb-a11y-live,
#vb-a11y-live-assertive {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* ---------------------------------------------------------------------------
   9. Off-screen panels must leave the tab order — 2.4.3 Focus Order (A)

   #mobile-nav / #mobile-nav-profi are `display: flex !important` and merely
   translated off-canvas, so all 11 links inside them were reachable by Tab on
   every page, desktop included. The language dropdown does the same with
   opacity/height. `visibility: hidden` removes them from the accessibility
   tree and the tab order while keeping the slide-in transition intact.
   ------------------------------------------------------------------------- */
#mobile-nav:not(.is-open),
#mobile-nav-profi:not(.is-open) {
    visibility: hidden;
}

#mobile-nav.is-open,
#mobile-nav-profi.is-open {
    visibility: visible;
}

/* Transition visibility alongside transform so it flips only once the panel
   has finished sliding out. */
#mobile-nav,
#mobile-nav-profi {
    transition: transform 0.35s ease, visibility 0s linear 0.35s;
}

#mobile-nav.is-open,
#mobile-nav-profi.is-open {
    transition: transform 0.35s ease, visibility 0s linear 0s;
}

@media (prefers-reduced-motion: reduce) {
    #mobile-nav,
    #mobile-nav-profi,
    #mobile-nav.is-open,
    #mobile-nav-profi.is-open {
        transition: none !important;
    }
}

/* The language dropdown is collapsed with opacity:0;height:0 — same problem.
   The markup now also carries [hidden], which rule 4 above enforces. */
.select-wrapper:not(.show) .options {
    visibility: hidden;
}

.select-wrapper.show .options {
    visibility: visible;
}

/* ---------------------------------------------------------------------------
   10. Focus must not hide under the fixed header — 2.4.11 (AA) / 2.4.12 (AAA)

   scroll-padding-top covers keyboard scrolling; this covers the case where the
   header is translated back into view by the scroll handler in main.js.
   ------------------------------------------------------------------------- */
header.header:focus-within {
    transform: translateY(0) !important;
}

/* ---------------------------------------------------------------------------
   11. Colour contrast and use of colour — 1.4.1 (A), 1.4.3 (AA),
       1.4.6 (AAA), 1.4.11 (AA)

   These rules override Tailwind utilities that are written straight into the
   templates, which is why they live here rather than in the SCSS parts. Every
   ratio below is measured against the worst ground the rule can land on.
   ------------------------------------------------------------------------- */

/* `hover:opacity-50` sits on 20+ links across the header, the footer and the
   content blocks. Opacity dims the text along with everything else: --dark
   #333333 on white drops from 12.63:1 to 2.85:1 exactly while the pointer is
   on it. 0.85 keeps a visible fade at 7.81:1, and the underline carries the
   state without relying on colour at all. Markup that opts out with
   `no-underline` / `!no-underline` still wins. */
.hover\:opacity-50:hover {
    opacity: 0.85;
}

a.hover\:opacity-50:hover,
a.hover\:opacity-50:focus-visible,
button.hover\:opacity-50:hover,
button.hover\:opacity-50:focus-visible {
    text-decoration: underline;
    text-underline-offset: 0.3em;
}

/* --black on --red-700 is 2.29:1, so `hover:text-black` made the
   Visitor/Professional switch and the topbar contact links vanish under the
   pointer. White holds 7.19:1 and the underline is the cue. The resting 80%
   white was 4.87:1 — AA, but short of the AAA the brief asks for. */
.topbar a:hover,
.topbar a:focus-visible {
    color: #ffffff;
    text-decoration: underline;
    text-underline-offset: 0.3em;
}

.topbar .opacity-80 {
    opacity: 1;
}

/* --dark-gray #858585 is 3.69:1 on white: usable as a non-text fill, not as
   body copy or as the value the user types into an input. --lightBlack
   #535252 is 7.79:1. */
.text-darkGray {
    color: #535252;
}

.placeholder\:text-\[\#666666\]::placeholder,
.placeholder\:text-\[\#AAAAAA\]::placeholder {
    color: #4d4d4d;
}

/* Static opacity on copy is not a hover state — it is the permanent colour of
   the section headings, the event dates and the "no results" message in the
   search overlay (--black at 40% = 2.46:1, --dark at 50% = 2.85:1). Scoped to
   the overlay so the photo scrims elsewhere, which legitimately use the same
   utilities, are left alone. */
#header-search-overlay p.opacity-40,
#header-search-overlay p.opacity-50,
#header-search-overlay span.opacity-40,
#header-search-overlay span.opacity-50 {
    opacity: 1;
    color: #4d4d4d;
}

/* --gray #d6d6d6 is 1.45:1 against white, so a field outlined in it has no
   visible boundary at all. 1.4.11 covers controls only, so the decorative
   rules and panel edges that share the class keep the light tone. */
input.border-gray,
select.border-gray,
textarea.border-gray,
label.border-gray,
button.border-gray,
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
    border-color: var(--vb-border-contrast);
}

/* --red-700 #B3000C clears AAA on white (7.19:1) but only reaches 6.09:1 on
   the tinted grounds it is usually paired with — --red-100 and --blue-100 are
   both #f8e9e7. That is the colour of the POI detail chips (date, "Show on the
   map", "In the text", "Nonstop", the website link) and of the "Learn more" /
   "Show all" buttons in the light-blue sections of the Professional home page,
   all of it 14–16px text that 1.4.6 wants at 7:1. --vb-red-on-tint is the same
   hue at 7.55:1 on #f8e9e7 and 8.90:1 on white, so a single value covers the
   tinted section and any white card nested inside it. */
.bg-red-100 .text-red-700,
.bg-blue-100 .text-red-700,
.bg-red-100.text-red-700,
.bg-blue-100.text-red-700 {
    color: var(--vb-red-on-tint);
}

/* This file loads last, so without an explicit carve-out the rule above would
   also win over `hover:text-black` (same specificity, earlier in the sheet)
   and the buttons would lose their hover state. --black on #f8e9e7 is 13.97:1. */
.bg-red-100 .text-red-700.hover\:text-black:hover,
.bg-blue-100 .text-red-700.hover\:text-black:hover,
.bg-red-100 .text-red-700.hover\:text-black:focus-visible,
.bg-blue-100 .text-red-700.hover\:text-black:focus-visible {
    color: var(--black);
}

/* Tailwind's preflight strips both the colour and the underline from every
   <a>. The theme only puts them back inside .wrapper-text, so editor content
   rendered anywhere else (hero copy, the CTA block, 404, flexible content)
   marks its links with nothing — and in the hero the link is the same white as
   the paragraph around it. A link with no class attribute is exactly the one
   that came out of the editor; template links always carry classes. */
main a:not([class]) {
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

/* ---------------------------------------------------------------------------
   12. Target size on dense controls — 2.5.8 (AA) / 2.5.5 (AAA)

   The filter radios and checkboxes are 24x24 (AA floor) inside a label that is
   only as tall as its text. Padding the label to 44px gives the whole row —
   control plus text — an AAA-sized target without changing the control's own
   appearance. Only the filter lists are affected; the styled radio/checkbox
   pattern used inside the three public forms already has its own hit area.
   ------------------------------------------------------------------------- */
.filter-item .radio-label,
.filter-item .checkbox-label,
.filter-body label {
    min-height: 4.4rem;
    padding-block: 0.4rem;
}

/* Leaflet's zoom buttons on the POI detail map are the only way to zoom
   without a pinch gesture, so they must clear the AAA floor too. */
.poi-map-zoom-button {
    min-width: 4.4rem;
    min-height: 4.4rem;
}

/* Swiper arrows and bullets: bullets are 8px dots with no spacing, which fails
   even the AA floor once two sit side by side. */
.swiper-pagination-bullet {
    min-width: 2.4rem;
    min-height: 2.4rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-clip: content-box;
    padding: 0.8rem;
}

.left-arrow,
.right-arrow {
    min-width: 4.4rem;
    min-height: 4.4rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
