/* =============================================================================
   ACCESSIBILITY TOOLBAR — floating button + panel, independent of WordPress.
   Replaces the old "Accessibility OneTap" plugin, which was WordPress-only
   and has no equivalent on a static site. Settings persist in localStorage
   and are re-applied before first paint by the inline script in base.njk's
   <head>, so there's no flash of unstyled state on reload.
   ============================================================================= */

.toz-skip-link {
  position: fixed;
  top: -60px;
  left: 16px;
  z-index: 999;
  background: var(--toz-teal-bright);
  color: var(--toz-black);
  font-family: 'Poppins', sans-serif;
  font-weight: 400;
  font-size: 14px;
  padding: 12px 20px;
  border-radius: 4px;
  transition: top 0.2s var(--ease-spring);
}
.toz-skip-link:focus {
  top: 16px;
}

.toz-a11y {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 300;
}

.toz-a11y-toggle {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: none;
  background: var(--toz-teal-bright);
  color: var(--toz-indigo-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(9, 6, 18, 0.35);
  transition: transform 0.2s var(--ease-spring), background 0.2s var(--ease-spring);
}
.toz-a11y-toggle:hover { transform: translateY(-2px); background: #fff; }
.toz-a11y-toggle:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
.toz-a11y-icon { width: 28px; height: 28px; }

.toz-a11y-panel {
  position: absolute;
  right: 0;
  bottom: 68px;
  width: min(320px, calc(100vw - 48px));
  max-height: min(560px, calc(100vh - 140px));
  overflow-y: auto;
  background: rgba(20, 20, 54, 0.97);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
          backdrop-filter: blur(24px) saturate(180%);
  border: 1px solid rgba(229, 228, 235, 0.12);
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 16px 48px rgba(9, 6, 18, 0.45);
  color: var(--toz-white);
}
.toz-a11y-panel[hidden] { display: none; }

.toz-a11y-panel__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.toz-a11y-panel__title {
  font-family: 'Poppins', sans-serif;
  font-weight: 400;
  font-size: 16px;
  letter-spacing: 0.04em;
  margin: 0;
}
.toz-a11y-close {
  width: 28px; height: 28px;
  flex: 0 0 auto;
  border-radius: 50%;
  border: none;
  background: rgba(229, 228, 235, 0.08);
  color: var(--toz-white);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.toz-a11y-close:hover { background: rgba(229, 228, 235, 0.16); }
.toz-a11y-close:focus-visible { outline: 2px solid var(--toz-teal-bright); outline-offset: 2px; }

.toz-a11y-group {
  margin-bottom: 12px;
  padding-bottom: 16px;
  border-bottom: 1px solid rgba(229, 228, 235, 0.1);
}
.toz-a11y-group__label {
  display: block;
  font-family: 'Poppins', sans-serif;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.7;
  margin-bottom: 10px;
}
.toz-a11y-stepper {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.toz-a11y-stepper__btn {
  flex: 0 0 auto;
  width: 40px; height: 36px;
  border-radius: 6px;
  border: 1px solid rgba(229, 228, 235, 0.24);
  background: transparent;
  color: var(--toz-white);
  font-family: 'Poppins', sans-serif;
  font-size: 14px;
  cursor: pointer;
}
.toz-a11y-stepper__btn:hover { background: rgba(229, 228, 235, 0.1); }
.toz-a11y-stepper__btn:focus-visible { outline: 2px solid var(--toz-teal-bright); outline-offset: 2px; }
.toz-a11y-stepper__value {
  flex: 1 1 auto;
  text-align: center;
  font-family: 'Poppins', sans-serif;
  font-size: 14px;
  opacity: 0.85;
}

.toz-a11y-toggle-row {
  position: relative;
  width: 100%;
  display: block;
  background: transparent;
  border: none;
  color: var(--toz-white);
  font-family: 'Poppins', sans-serif;
  font-size: 14px;
  text-align: left;
  padding: 10px 48px 10px 0;
  cursor: pointer;
}
.toz-a11y-toggle-row:hover { color: var(--toz-teal-bright); }
.toz-a11y-toggle-row:focus-visible { outline: 2px solid var(--toz-teal-bright); outline-offset: 2px; border-radius: 4px; }
.toz-a11y-toggle-row::before {
  content: '';
  position: absolute;
  right: 0; top: 50%;
  transform: translateY(-50%);
  width: 36px; height: 20px;
  border-radius: 999px;
  background: rgba(229, 228, 235, 0.22);
  transition: background 0.2s var(--ease-spring);
}
.toz-a11y-toggle-row::after {
  content: '';
  position: absolute;
  right: 18px; top: 50%;
  transform: translateY(-50%);
  width: 14px; height: 14px;
  border-radius: 50%;
  background: #fff;
  transition: right 0.2s var(--ease-spring), background 0.2s var(--ease-spring);
}
.toz-a11y-toggle-row[aria-pressed="true"]::before { background: var(--toz-teal-bright); }
.toz-a11y-toggle-row[aria-pressed="true"]::after { right: 2px; background: var(--toz-indigo-alt); }

.toz-a11y-reset {
  width: 100%;
  margin-top: 12px;
  padding: 10px;
  border-radius: 6px;
  border: 1px solid rgba(229, 228, 235, 0.24);
  background: transparent;
  color: var(--toz-white);
  font-family: 'Poppins', sans-serif;
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
}
.toz-a11y-reset:hover { background: rgba(229, 228, 235, 0.1); }
.toz-a11y-reset:focus-visible { outline: 2px solid var(--toz-teal-bright); outline-offset: 2px; }

.toz-a11y-statement-link {
  margin: 14px 0 0;
  text-align: center;
  font-family: 'Poppins', sans-serif;
  font-size: 12px;
}
.toz-a11y-statement-link a {
  color: var(--toz-white);
  opacity: 0.7;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.toz-a11y-statement-link a:hover { opacity: 1; color: var(--toz-teal-bright); }
.toz-a11y-statement-link a:focus-visible {
  outline: 2px solid var(--toz-teal-bright);
  outline-offset: 2px;
  border-radius: 2px;
}

@media (max-width: 480px) {
  .toz-a11y { right: 16px; bottom: 16px; }
  .toz-a11y-toggle { width: 48px; height: 48px; }
  .toz-a11y-icon { width: 24px; height: 24px; }
}

/* =============================================================================
   APPLIED STATES — each toggled via a class on <html>. Split from the toggle
   UI above since these rules affect the whole page, not just the widget.
   ============================================================================= */

/* Readable font: Atkinson Hyperlegible (designed for low-vision legibility),
   falling back to Arial rather than the site's decorative Karla/Poppins. */
html.toz-a11y-readable-font body,
html.toz-a11y-readable-font button,
html.toz-a11y-readable-font input,
html.toz-a11y-readable-font select,
html.toz-a11y-readable-font textarea,
html.toz-a11y-readable-font p,
html.toz-a11y-readable-font li,
html.toz-a11y-readable-font span,
html.toz-a11y-readable-font a {
  font-family: 'Atkinson Hyperlegible', Arial, Helvetica, sans-serif !important;
  font-weight: 400 !important;
  letter-spacing: 0.01em;
}
/* Section/card headings sitewide are set in their own thin (100-300)
   display weight (Poppins/Karla), which as an explicit rule on the
   heading itself wins over the inherited body font-family/weight above —
   without this, "readable font" visibly changed body copy but left every
   heading exactly as thin as before. Bold (700, actually shipped — see
   the font <link> in base.njk) rather than 400, since at heading scale a
   merely-regular weight doesn't read as meaningfully different from the
   site's existing thin headings. */
html.toz-a11y-readable-font h1,
html.toz-a11y-readable-font h2,
html.toz-a11y-readable-font h3,
html.toz-a11y-readable-font h4,
html.toz-a11y-readable-font h5,
html.toz-a11y-readable-font h6 {
  font-family: 'Atkinson Hyperlegible', Arial, Helvetica, sans-serif !important;
  font-weight: 700 !important;
}
html.toz-a11y-readable-font p,
html.toz-a11y-readable-font li {
  line-height: 1.85 !important;
}

/* Every page's full-bleed hero title is `white-space: nowrap` by design at
   100% zoom (see e.g. home.css .hero__title) — deliberately kept to one
   line. Readable Font's forced bold weight, and/or the text-size stepper
   above 100% (both drive the zoom applied to <html> in a11y.js), can need
   more width than one line has at that zoom level; without this override
   the extra width has nowhere to go but past the viewport edge, and
   `overflow-x: hidden` on html/body (shared.css) silently clips it instead
   of wrapping. Letting it wrap to two lines here costs only hero height,
   which is unconstrained, so nothing else clips as a result. */
/* overflow-wrap covers the case where the forced-bold weight and/or zoom
   above 100% makes even a single word ("Teegatha'Oh", no space to wrap on)
   wider than the viewport on its own — confirmed still clipping at 390px
   and 320px with white-space: normal alone, since that only creates a wrap
   opportunity between words, not within one. */
html.toz-a11y-readable-font .hero__title,
html.toz-a11y-text-lg .hero__title {
  white-space: normal !important;
  overflow-wrap: anywhere !important;
}

/* The hero isn't the only heading with this problem — every page also has
   at least one section heading built the same way (e.g. Home's
   `.who-we-are__title`, repeating the same "Teegatha'Oh Zheh" text as the
   hero). Those are already `white-space: normal` by default so they do
   wrap between words, but confirmed still clipping at 390px/320px under
   Readable Font + 140%: same root cause as the hero fix above, a single
   long word wider than the viewport with nowhere to break. Applied to
   every heading level sitewide, not just the classes known to repeat this
   particular phrase, since any section title with a long unhyphenated
   word is equally at risk once bold weight and/or zoom push it past one
   line's available width. */
html.toz-a11y-readable-font h1,
html.toz-a11y-readable-font h2,
html.toz-a11y-readable-font h3,
html.toz-a11y-readable-font h4,
html.toz-a11y-readable-font h5,
html.toz-a11y-readable-font h6,
html.toz-a11y-text-lg h1,
html.toz-a11y-text-lg h2,
html.toz-a11y-text-lg h3,
html.toz-a11y-text-lg h4,
html.toz-a11y-text-lg h5,
html.toz-a11y-text-lg h6 {
  overflow-wrap: anywhere !important;
}

/* Underline links — exempt the widget's own chrome so the toggle/close
   buttons don't sprout underlines (they aren't <a> tags anyway, but the
   :not() guards stay in case markup changes later). */
html.toz-a11y-underline-links a:not(.toz-a11y-toggle):not(.toz-a11y-close) {
  text-decoration: underline !important;
  text-underline-offset: 3px;
}

/* Enhanced keyboard-focus visibility, independent of the site's own
   per-component focus-visible rules (which are more subtle by design). */
/* Plain :focus, not :focus-visible — this toggle is opt-in (the visitor
   explicitly turned it on), so the browser's default "don't show a ring
   on a mouse click, only real keyboard nav" heuristic just gets in the
   way here: clicking a button/link with the mouse legitimately doesn't
   match :focus-visible, so testing this feature by clicking around looks
   like it does nothing even though it's working exactly as built. Once
   someone has asked for maximum focus visibility, show it every time,
   regardless of input method. */
html.toz-a11y-focus *:focus {
  outline: 3px solid #ffe600 !important;
  outline-offset: 3px !important;
}

/* Reduce motion — same effect as the existing prefers-reduced-motion query
   in shared.css, but under manual control regardless of OS setting. Also
   flattens the parallax `background-attachment: fixed` bands sitewide,
   since a fixed background scrolling underneath fixed content is itself a
   motion trigger for vestibular-sensitive users, not just transitions. */
html.toz-a11y-reduce-motion,
html.toz-a11y-reduce-motion * {
  scroll-behavior: auto !important;
  transition-duration: 0.01ms !important;
  animation-duration: 0.01ms !important;
  animation-iteration-count: 1 !important;
  background-attachment: scroll !important;
}

/* High contrast — flat black/white/yellow palette overriding the site's
   brand colors, borders forced visible, decorative CSS background-images
   (parallax bands, hero photo bands) removed in favor of solid contrast.
   Real <img> content (galleries, portraits) is untouched — only CSS
   background-image declarations are cleared. */
html.toz-a11y-contrast body {
  background: #000 !important;
  color: #fff !important;
}
/* `*`, not a list of container tags — components across the site (e.g.
   .vision__title, .quotes__item) set their own explicit `color`/
   `background-color` on the text elements themselves (h2/p/span/li/...),
   not just on the wrapping section. A directly-matched color on an element
   always wins over an inherited one regardless of !important upstream, so
   overriding only the containers left plenty of text at its original brand
   color (e.g. dark indigo) sitting almost invisibly on the new black
   background. Going universal is what actually forces every element's own
   color, not just what descendants would've inherited. */
html.toz-a11y-contrast * {
  background-color: #000 !important;
  background-image: none !important;
  color: #fff !important;
}
/* img gets no forced background-color: CSS `filter` (brightness(0) invert(1),
   used to turn the logo art pure white — see shared.css .toz-logo-invert)
   applies to the element's whole rendered box, its own background paint
   included, not just the pixel content. Forcing black onto a transparent
   PNG/WebP's box turns that black solid too, which brightness/invert then
   flips to solid white right along with the linework itself — collapsing
   the logo into an unreadable white rectangle instead of white-on-black
   line art. Opaque photos are unaffected either way since their own pixels
   already cover the box completely. */
html.toz-a11y-contrast img {
  background-color: transparent !important;
}
/* `*` doesn't reach ::before/::after — several decorative photo/tint layers
   sitewide are painted on pseudo-elements rather than the element itself
   (e.g. .contact-form::before is a background photo, .contact-form::after
   is a blurred frosted-glass tint on top of it; contact.css even leaves a
   comment explaining why — the real box carries no bg so the ::before photo
   isn't hidden behind it). Without this, those pseudo-elements' photos and
   backdrop-filter blur survive high-contrast mode untouched, which is
   exactly the washed-out "photo still bleeding through" look this is meant
   to eliminate. backdrop-filter: none also stops them blurring whatever is
   now behind them (their own forced-black background, harmlessly, but no
   reason to keep an expensive backdrop-filter blur doing nothing). */
html.toz-a11y-contrast *::before,
html.toz-a11y-contrast *::after {
  background-color: #000 !important;
  background-image: none !important;
  color: #fff !important;
  -webkit-backdrop-filter: none !important;
          backdrop-filter: none !important;
}
html.toz-a11y-contrast a {
  color: #ffe600 !important;
  text-decoration: underline !important;
}
html.toz-a11y-contrast button,
html.toz-a11y-contrast input,
html.toz-a11y-contrast select,
html.toz-a11y-contrast textarea {
  background: #000 !important;
  color: #ffe600 !important;
  border: 2px solid #ffe600 !important;
}
/* The toolbar's own toggle-row switches and the mobile-menu hamburger draw
   their visible parts with `background-color` on plain elements/pseudo-
   elements (the switch track/knob; the hamburger's 3 <span> bars) rather
   than with a border or text color, so the universal `*`/`::before`/
   `::after` rules above — which flatten every background to solid #000 —
   were painting both the on and off switch states, and the hamburger bars,
   the exact same black as the page behind them: functionally invisible,
   not just low-contrast. Overridden here with a class-qualified selector,
   which naturally out-specifies the universal one regardless of source
   order, so on/off reads as a filled-vs-outlined track with a knob that
   swaps sides and color, and the hamburger bars go bright yellow. */
html.toz-a11y-contrast .toz-a11y-toggle-row::before {
  background: transparent !important;
  border: 2px solid #ffe600 !important;
}
html.toz-a11y-contrast .toz-a11y-toggle-row::after {
  background: #fff !important;
}
html.toz-a11y-contrast .toz-a11y-toggle-row[aria-pressed="true"]::before {
  background: #ffe600 !important;
}
html.toz-a11y-contrast .toz-a11y-toggle-row[aria-pressed="true"]::after {
  background: #000 !important;
}
html.toz-a11y-contrast .toz-menu-toggle span {
  background-color: #ffe600 !important;
}
/* Same problem, one more place: the Home page's 3 dot-based carousels
   (quotes, program/TOZPAS, pullquote) draw their active-vs-inactive state
   as a `background` on a ::before pseudo-element, which the universal
   `*::before` rule above already flattens to solid black for every dot
   regardless of state. Each dot is also a <button>, so the generic
   `button` rule already gives it a yellow border — the result was every
   dot rendering as an identical yellow-outlined, black-filled circle, with
   no visible way to tell which slide is active. Filling the active dot
   yellow (inactive stays black, i.e. invisible against the black page,
   same as before) restores a visible filled-vs-empty distinction inside
   the same yellow ring. */
html.toz-a11y-contrast .quotes__dot.is-active::before,
html.toz-a11y-contrast .program__carousel-dot.is-active::before,
html.toz-a11y-contrast .pullquote__carousel-dot.is-active::before {
  background: #ffe600 !important;
}
/* Deliberately not touching img { filter } here — .toz-logo-invert (in
   shared.css) already forces the header/footer/mobile-menu logo to pure
   white via brightness(0) invert(1), and a same-specificity-class rule here
   would win by source order and silently revert it to its natural dark
   colors, making the logo unreadable against the black contrast-mode bg. */
