/* ============================================================================
   GoPrint Accessibility (WCAG 2.1 AA)
   Native implementation, no external dependencies.

   LOADED ON EVERY PAGE by HeadTag (WI 3778), after client.css — NOT only when the
   toolbar is enabled. Therefore this file is split into two safe-to-always-load layers:

     * BASELINE (sections 0-2b): unconditional rules that must be correct even when
       the toolbar never builds — the off-screen skip-link, the sr-only utility, the
       visible :focus-visible indicator, and the logout/white-on-blue contrast fix.
       These are the ONLY globally-applied selectors; they are inert on elements that
       don't carry the matching gp-a11y-* class (skip-link, sr-only) except the single
       intended global :focus-visible outline.

     * TOOLBAR (sections 3+): contrast/zoom/launcher/panel/read-aloud styling, all
       scoped to toolbar DOM (#gp-a11y-root / #gp-a11y-panel / #gp-a11y-launcher) or to
       html[class*='gp-a11y-*'] state classes, so they stay completely inert until the
       toolbar builds and sets those classes.
   ============================================================================ */

/* ==== BASELINE (always-on, safe on every page) ============================= */

/* ---------- 0. Screen-reader-only utility ---------------------------------- */
/* Visually hidden but exposed to assistive tech. Used for injected page <h1>s and
   labels so screen-reader users get structure/orientation without visual change. */
.gp-a11y-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;
  white-space: nowrap !important;
  border: 0 !important;
}

/* ---------- 1. Skip-to-content link (WCAG 2.4.1 Bypass Blocks) ------------- */
.gp-a11y-skiplink {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
  z-index: 100000;
  background: #1F2937;
  color: #FFFFFF;
  padding: 12px 20px;
  font-size: 16px;
  font-weight: 600;
  text-decoration: none;
  border-radius: 0 0 6px 0;
}
.gp-a11y-skiplink:focus,
.gp-a11y-skiplink:focus-visible {
  position: fixed;
  left: 0;
  top: 0;
  width: auto;
  height: auto;
  outline: 3px solid #FFD600;
  outline-offset: 2px;
}

/* WI 3778 (3): skip-link text contrast (WCAG 1.4.3). The pill is dark (#1F2937) in every mode, but
   its text colour was being overridden to a dim tenant brand colour in Default, and to brown by the
   Sepia `html.gp-a11y-contrast-sepia a { color:#8B4513 }` rule — both measured ~2.07:1 on the dark
   pill. Force white text + the dark pill background in Default and in every contrast mode so the
   skip-link stays readable (14.6:1) no matter what overrides it. */
html a.gp-a11y-skiplink,
html.gp-a11y-contrast-high a.gp-a11y-skiplink,
html.gp-a11y-contrast-dark a.gp-a11y-skiplink,
html.gp-a11y-contrast-sepia a.gp-a11y-skiplink {
  color: #FFFFFF !important;
  background: #1F2937 !important;
}

/* ---------- 2. Always-on visible focus indicator (WCAG 2.4.7) -------------- */
/* Subtle by default. The toolbar's Highlight Focus mode (html.gp-a11y-kbd)
   makes it thicker and high-contrast. Use :focus-visible to avoid showing it
   on every mouse click. */
:focus-visible {
  outline: 2px solid #005FCC;
  outline-offset: 2px;
}
html.gp-a11y-kbd :focus-visible {
  outline: 3px solid #FFBF00 !important;
  outline-offset: 2px !important;
  box-shadow: 0 0 0 5px rgba(0, 0, 0, 0.65) !important;
}

/* ---------- 2b. Baseline text-contrast fix (WCAG 1.4.3) --------------------
   DEF-005 / UM: the header Logout button is <button class="button-header-brand
   button-logout"> whose colours come from the tenant brand (client.css:
   background:getButtonFace(); color:getButtonText()). Several tenants ship white
   text on a mid-blue face (e.g. ~#007BFF) which measures ≈3.9:1 — below the 4.5:1
   required for normal text. The button's inline style sets only float/font-size,
   never colour, so this rule wins. We pin the button to the neutral a11y chrome
   colour #1F2937 with #FFFFFF text = 14.6:1 (passes AA 4.5:1 and AAA 7:1) for EVERY
   tenant — tenants whose brand already passed simply get the same compliant dark
   utility button. This is a BASELINE rule (runs with the toolbar off); the toolbar
   contrast themes (section 4) fully own the button when active — the :not() guard
   below stops this baseline rule from matching once an html.gp-a11y-contrast-* class
   is set, so the chosen theme (pure black / dark / sepia) takes over cleanly. */
html:not([class*="gp-a11y-contrast-"]) .button-header-brand.button-logout {
  background-color: #1F2937 !important;
  background-image: none !important;
  color: #FFFFFF !important;
}

/* ---------- 2c. Patron upload buttons — focus visible + non-text contrast --
   DEF: #select-files-button and #submit-file (both .btn-netzcore-dark) computed
   outline-style:none in BOTH rest and focus, with identical box-shadow, so keyboard
   users got no visible focus indicator at all (unlike the working #more-settings-toggle
   model on the same page: solid 2px #005FCC ring, ~2px offset). Baseline rule — not
   scoped to a contrast mode — so it also restores focus visibility in Default. */
/* WI 3778 (2): visible focus ring on the branded patron-upload buttons (WCAG 2.4.7). */
.btn-netzcore-dark:focus-visible {
  outline: 2px solid #005FCC !important;
  outline-offset: 2px !important;
}
/* WI 3778 (5): non-text contrast (WCAG 1.4.11). .btn-netzcore-dark renders as a bright
   blue fill (~#0099FF live) with no border on the white page, so the fill-to-page
   boundary measures under the 3:1 minimum for UI-component boundaries. A 1px #0056b3
   border gives ~7:1 against the white page — a comfortably compliant boundary in every
   state (rest/hover/focus) without changing the button's brand fill colour. */
.btn-netzcore-dark {
  border: 1px solid #0056b3 !important;
}

/* ==== TOOLBAR (inert until the toolbar builds / sets gp-a11y-* classes) ==== */

/* ---------- 3. Text-size scaling (page zoom) -------------------------------
   `zoom` on <body> enlarges ALL page text proportionally — the left nav, headings, body copy,
   BARE TEXT NODES (e.g. the admin "Active print jobs…" description, which is unwrapped text after a
   <br>), and px-styled table cells alike — preserving the type hierarchy with NO compounding.
   Replaces the earlier per-element font scaling, which could not reach bare text or the fixed
   sidebar and compounded on nesting. Layout scales coherently like browser zoom (a horizontal
   scrollbar may appear at the largest steps — acceptable per WCAG 1.4.4 / 1.4.10). Works on every
   page type (admin #contentContainer, patron <main>, login). The class on <html> is set by the
   HeadTag bootstrap (pre-paint) and a11y.js. */
html.gp-a11y-text-1 body { zoom: 1.15; }
html.gp-a11y-text-2 body { zoom: 1.30; }
html.gp-a11y-text-3 body { zoom: 1.50; }
html.gp-a11y-text-4 body { zoom: 1.75; }

/* The toolbar (#gp-a11y-root) intentionally scales WITH the page under body zoom. Counter-zooming it
   back to a fixed size broke its position:fixed panel placement (the panel jumped to the top-right
   instead of anchoring bottom-right above the launcher). Letting it scale keeps the panel correctly
   positioned and is consistent with "enlarge everything". */

/* EXCEPT #gp-a11y-panel itself (the control surface, including #gp-a11y-close): letting it inherit the
   ambient body zoom means length values evaluated INSIDE it — including its own
   `max-height: calc(100vh - 120px)` below — get PAINTED at the ambient zoom scale even though 100vh
   already resolved to real viewport pixels. At gp-a11y-text-2 (zoom 1.30) that renders the panel ~30%
   taller than the real viewport, pushing the header / #gp-a11y-close off the TOP of the screen —
   covered/unclickable (the Maximum-text-size defect). Counter-zoom ONLY the panel (never
   #gp-a11y-root/#gp-a11y-launcher — that's the regression the note above describes) back to 1:1 so its
   own box (width, max-height, font-size, the close button) stays a stable, real-pixel size no matter
   the page text-size setting. `bottom` is bumped by the same amount the (still-zoomed) launcher grew,
   so the panel keeps clearing it instead of overlapping. */
/* A1: the base rule's `max-height: calc(100vh - 120px)` (section 6) pairs with this default `bottom:
   112px` to leave an 8px gap above the panel whenever a short viewport forces it to its cap (120 - 112
   = 8). The text-1/text-2 `bottom` grows (128px / 144px) to keep clearing the taller zoomed launcher,
   but max-height was NOT re-budgeted to match — so on a short viewport (e.g. 1280x600) where the panel
   hits its cap, its OWN top edge landed 8-24px ABOVE y=0 (120-128=-8 / 120-144=-24), pushing the sticky
   header/#gp-a11y-close off the TOP of the screen with no way to scroll back to it (the panel's
   internal overflow-y:auto only scrolls content WITHIN its box — it can't fix the box itself being
   positioned above the viewport). Re-budget max-height per step to the SAME 8px gap so the panel's top
   never goes negative, however short the viewport, while still capping/scrolling long content. */
html.gp-a11y-text-1 #gp-a11y-panel {
  zoom: calc(1 / 1.15);
  bottom: calc(128px + env(safe-area-inset-bottom, 0px));
  max-height: calc(100vh - 136px);
}
html.gp-a11y-text-2 #gp-a11y-panel {
  zoom: calc(1 / 1.30);
  bottom: calc(144px + env(safe-area-inset-bottom, 0px));
  max-height: calc(100vh - 152px);
}

/* ---------- 4. Contrast modes ---------------------------------------------- */
/* Applied to <html>. Highest specificity beats client.css for color pairs.   */

/* 4a. High contrast — black bg, white text, yellow links/focus. */
/* Repaint the whole content surface — root, body, AND structural containers — so cards/panels
   that carry their own light background from client.css don't leave white-on-light text. (Bug:
   login card + Username/Password/version <span>s were invisible because only body/inputs were
   repainted.) The accessibility toolbar itself is re-isolated in 4d so it stays usable. */
html.gp-a11y-contrast-high,
html.gp-a11y-contrast-high body,
html.gp-a11y-contrast-high div,
html.gp-a11y-contrast-high section,
html.gp-a11y-contrast-high article,
html.gp-a11y-contrast-high aside,
html.gp-a11y-contrast-high nav,
html.gp-a11y-contrast-high header,
html.gp-a11y-contrast-high footer,
html.gp-a11y-contrast-high main,
html.gp-a11y-contrast-high form,
html.gp-a11y-contrast-high fieldset,
html.gp-a11y-contrast-high table,
html.gp-a11y-contrast-high thead,
html.gp-a11y-contrast-high tbody,
html.gp-a11y-contrast-high tr,
html.gp-a11y-contrast-high td,
html.gp-a11y-contrast-high th {
  background-color: #000000 !important;
  color: #FFFFFF !important;
  border-color: #FFFFFF !important;
}
/* Text-bearing inline/heading elements get readable foreground (links handled separately below). */
html.gp-a11y-contrast-high span,
html.gp-a11y-contrast-high p,
html.gp-a11y-contrast-high label,
html.gp-a11y-contrast-high li,
html.gp-a11y-contrast-high dt,
html.gp-a11y-contrast-high dd,
html.gp-a11y-contrast-high h1,
html.gp-a11y-contrast-high h2,
html.gp-a11y-contrast-high h3,
html.gp-a11y-contrast-high h4,
html.gp-a11y-contrast-high h5,
html.gp-a11y-contrast-high h6,
html.gp-a11y-contrast-high strong,
html.gp-a11y-contrast-high b,
html.gp-a11y-contrast-high em,
html.gp-a11y-contrast-high small,
html.gp-a11y-contrast-high code,
html.gp-a11y-contrast-high kbd {
  color: #FFFFFF !important;
  background-color: transparent !important;
}
/* Links: WHITE + underline (not saturated yellow). GoPrint's admin UI styles navigation AND
   entity names (menu items, device names, ASK units…) as branded gold links, so forcing every
   <a> to pure #FFFF00 turned link-dense pages into an unreadable "sea of yellow". White text
   matching the body, distinguished by an underline, is readable and satisfies WCAG 1.4.1 (colour
   is not the only link cue). Hover/focus get a yellow accent so links remain identifiable. */
html.gp-a11y-contrast-high a,
html.gp-a11y-contrast-high a:visited {
  color: #FFFFFF !important;
  text-decoration: underline !important;
}
html.gp-a11y-contrast-high a:focus,
html.gp-a11y-contrast-high a:hover {
  color: #FFFF00 !important;
  background-color: #000080 !important;
  text-decoration: underline !important;
}
html.gp-a11y-contrast-high button,
html.gp-a11y-contrast-high input,
html.gp-a11y-contrast-high select,
html.gp-a11y-contrast-high textarea {
  background-color: #000000 !important;
  color: #FFFFFF !important;
  border: 2px solid #FFFFFF !important;
}
/* WI 3778 (1c): backstop for a JS timing race. Branded buttons (.btn-netzcore-dark) carry a
   Bootstrap `background-color 0.15s ease-in-out` transition; the JS contrast fixer reads the
   background mid-transition and can commit the wrong text colour. Kill the transition on
   interactive controls while this contrast mode is active so the background change is instant. */
html.gp-a11y-contrast-high button,
html.gp-a11y-contrast-high input,
html.gp-a11y-contrast-high select,
html.gp-a11y-contrast-high textarea,
html.gp-a11y-contrast-high .btn,
html.gp-a11y-contrast-high .btn-netzcore-dark {
  transition: none !important;
}
html.gp-a11y-contrast-high :focus-visible {
  outline: 3px solid #FFFF00 !important;
  outline-offset: 2px !important;
}
/* Preserve content imagery; skip the brand logos by leaving them alone. */
html.gp-a11y-contrast-high img:not(.gp-a11y-preserve) {
  /* Optional invert: filter: invert(1) hue-rotate(180deg); */
  /* Leaving images untouched is the safer default. */
}

/* 4b. Dark mode — softer than high contrast, comfortable for low-light. */
html.gp-a11y-contrast-dark,
html.gp-a11y-contrast-dark body,
html.gp-a11y-contrast-dark div,
html.gp-a11y-contrast-dark section,
html.gp-a11y-contrast-dark article,
html.gp-a11y-contrast-dark aside,
html.gp-a11y-contrast-dark nav,
html.gp-a11y-contrast-dark header,
html.gp-a11y-contrast-dark footer,
html.gp-a11y-contrast-dark main,
html.gp-a11y-contrast-dark form,
html.gp-a11y-contrast-dark fieldset,
html.gp-a11y-contrast-dark table,
html.gp-a11y-contrast-dark thead,
html.gp-a11y-contrast-dark tbody,
html.gp-a11y-contrast-dark tr,
html.gp-a11y-contrast-dark td,
html.gp-a11y-contrast-dark th {
  background-color: #1A1A1A !important;
  color: #E0E0E0 !important;
  border-color: #555555 !important;
}
html.gp-a11y-contrast-dark span,
html.gp-a11y-contrast-dark p,
html.gp-a11y-contrast-dark label,
html.gp-a11y-contrast-dark li,
html.gp-a11y-contrast-dark dt,
html.gp-a11y-contrast-dark dd,
html.gp-a11y-contrast-dark h1,
html.gp-a11y-contrast-dark h2,
html.gp-a11y-contrast-dark h3,
html.gp-a11y-contrast-dark h4,
html.gp-a11y-contrast-dark h5,
html.gp-a11y-contrast-dark h6,
html.gp-a11y-contrast-dark strong,
html.gp-a11y-contrast-dark b,
html.gp-a11y-contrast-dark em,
html.gp-a11y-contrast-dark small,
html.gp-a11y-contrast-dark code,
html.gp-a11y-contrast-dark kbd {
  color: #E0E0E0 !important;
  background-color: transparent !important;
}
html.gp-a11y-contrast-dark a,
html.gp-a11y-contrast-dark a:visited {
  color: #66B3FF !important;
}
html.gp-a11y-contrast-dark button,
html.gp-a11y-contrast-dark input,
html.gp-a11y-contrast-dark select,
html.gp-a11y-contrast-dark textarea {
  background-color: #2A2A2A !important;
  color: #E0E0E0 !important;
  border-color: #555555 !important;
}
/* WI 3778 (1c): backstop for a JS timing race (see High-Contrast note above). Kill the background
   transition on interactive controls while Dark mode is active so the contrast fixer never samples
   a mid-transition background colour. */
html.gp-a11y-contrast-dark button,
html.gp-a11y-contrast-dark input,
html.gp-a11y-contrast-dark select,
html.gp-a11y-contrast-dark textarea,
html.gp-a11y-contrast-dark .btn,
html.gp-a11y-contrast-dark .btn-netzcore-dark {
  transition: none !important;
}

/* 4c. Sepia — eye-strain reduction for long reading sessions. */
html.gp-a11y-contrast-sepia,
html.gp-a11y-contrast-sepia body,
html.gp-a11y-contrast-sepia div,
html.gp-a11y-contrast-sepia section,
html.gp-a11y-contrast-sepia article,
html.gp-a11y-contrast-sepia aside,
html.gp-a11y-contrast-sepia nav,
html.gp-a11y-contrast-sepia header,
html.gp-a11y-contrast-sepia footer,
html.gp-a11y-contrast-sepia main,
html.gp-a11y-contrast-sepia form,
html.gp-a11y-contrast-sepia fieldset,
html.gp-a11y-contrast-sepia table,
html.gp-a11y-contrast-sepia thead,
html.gp-a11y-contrast-sepia tbody,
html.gp-a11y-contrast-sepia tr,
html.gp-a11y-contrast-sepia td,
html.gp-a11y-contrast-sepia th {
  background-color: #F4E8C9 !important;
  color: #4B3621 !important;
  border-color: #4B3621 !important;
}
html.gp-a11y-contrast-sepia span,
html.gp-a11y-contrast-sepia p,
html.gp-a11y-contrast-sepia label,
html.gp-a11y-contrast-sepia li,
html.gp-a11y-contrast-sepia dt,
html.gp-a11y-contrast-sepia dd,
html.gp-a11y-contrast-sepia h1,
html.gp-a11y-contrast-sepia h2,
html.gp-a11y-contrast-sepia h3,
html.gp-a11y-contrast-sepia h4,
html.gp-a11y-contrast-sepia h5,
html.gp-a11y-contrast-sepia h6,
html.gp-a11y-contrast-sepia strong,
html.gp-a11y-contrast-sepia b,
html.gp-a11y-contrast-sepia em,
html.gp-a11y-contrast-sepia small,
html.gp-a11y-contrast-sepia code,
html.gp-a11y-contrast-sepia kbd {
  color: #4B3621 !important;
  background-color: transparent !important;
}
html.gp-a11y-contrast-sepia a,
html.gp-a11y-contrast-sepia a:visited {
  color: #8B4513 !important;
}
/* WI 3778 (1c): backstop for a JS timing race (see High-Contrast note above). Kill the background
   transition on interactive controls while Sepia mode is active so the contrast fixer never samples
   a mid-transition background colour. */
html.gp-a11y-contrast-sepia button,
html.gp-a11y-contrast-sepia input,
html.gp-a11y-contrast-sepia select,
html.gp-a11y-contrast-sepia textarea,
html.gp-a11y-contrast-sepia .btn,
html.gp-a11y-contrast-sepia .btn-netzcore-dark {
  transition: none !important;
}

/* 4c-2. Standalone "card" containers (e.g. the login card) are delineated in normal mode ONLY by
   their background colour + a faint drop-shadow. Once a contrast mode flattens backgrounds, a card
   on a same-coloured page loses its outline (high contrast: black card on black page; dark/sepia
   likewise). Give such cards an explicit per-mode border so the full rectangle is visible, and drop
   the now-invisible shadow. Card classes are enumerated (NOT a blanket div border, which would
   outline every nested element). Add new standalone-card classes here as they need it. */
html.gp-a11y-contrast-high .login-container {
  border: 2px solid #FFFFFF !important;
  box-shadow: none !important;
}
html.gp-a11y-contrast-dark .login-container {
  border: 2px solid #66B3FF !important;
  box-shadow: none !important;
}
html.gp-a11y-contrast-sepia .login-container {
  border: 2px solid #4B3621 !important;
  box-shadow: none !important;
}

/* 4c-3. The side/top navigation links carry a branded foreground (#navMenuContainer li a ->
   getNavMenuItemFg) whose ID specificity outranks the generic link rules above, so in contrast
   modes they kept a dim, low-contrast branded colour. Force the nav links + submenu links to the
   mode's foreground on the mode's background for full legibility (ID-scoped to win specificity). */
html.gp-a11y-contrast-high #navMenuContainer li a,
html.gp-a11y-contrast-high #navMenuContainer li ul li a {
  color: #FFFFFF !important;
  background-color: #000000 !important;
}
html.gp-a11y-contrast-high #navMenuContainer li a:hover,
html.gp-a11y-contrast-high #navMenuContainer li a:focus {
  color: #FFFF00 !important;
  background-color: #000080 !important;
}
html.gp-a11y-contrast-dark #navMenuContainer li a,
html.gp-a11y-contrast-dark #navMenuContainer li ul li a {
  color: #E0E0E0 !important;
  background-color: #1A1A1A !important;
}
html.gp-a11y-contrast-sepia #navMenuContainer li a,
html.gp-a11y-contrast-sepia #navMenuContainer li ul li a {
  color: #4B3621 !important;
  background-color: #F4E8C9 !important;
}

/* 4c-4. Admin action-icon buttons (.button-action-brand + .img-pencil/.img-add/.img-delete/…) paint
   a WHITE PNG glyph on a branded button face. The broad Sepia rule strips that face, leaving a white
   glyph invisible on the cream page. Darken the glyph so it's visible. High-contrast / Dark keep the
   white glyph (visible on their dark backgrounds), so this is Sepia-only. */
html.gp-a11y-contrast-sepia [class*="button-action-brand"] {
  filter: brightness(0) !important;
}

/* ---------- 4d. Toolbar theme isolation -----------------------------------
   The launcher + panel ARE the control surface for the contrast themes, so they must keep their
   own skin no matter which contrast mode is active. The broad container/text repaint in 4a-4c
   would otherwise black-out the panel and override the segmented "selected" state (the panel's
   class-level rules lose to the element-level contrast rules). Scoped to an active contrast mode
   and using ID specificity + !important so they outrank the contrast overrides. They do NOT apply
   in the normal (no-contrast) state, so the system-dark panel chrome in section 9 is preserved.
   Mirrors the ASK a11y.css panel-isolation block. -------------------------------------------- */
html[class*="gp-a11y-contrast-"] #gp-a11y-launcher {
  background-color: #1F2937 !important;
  color: #FFFFFF !important;
  border-color: #FFFFFF !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-launcher .gp-a11y-launcher-label {
  color: #FFFFFF !important;
  background-color: transparent !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-launcher .gp-a11y-active-dot { background-color: #16A34A !important; }
html[class*="gp-a11y-contrast-"] #gp-a11y-launcher.is-speaking .gp-a11y-active-dot { background-color: #DC2626 !important; }
html[class*="gp-a11y-contrast-"] #gp-a11y-panel {
  background-color: #FFFFFF !important;
  color: #1F2937 !important;
  border-color: #D1D5DB !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-panel header { background-color: #1F2937 !important; }
html[class*="gp-a11y-contrast-"] #gp-a11y-panel header h2 {
  color: #FFFFFF !important;
  background-color: transparent !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-close {
  background-color: transparent !important;
  color: #FFFFFF !important;
  border-color: transparent !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-row {
  background-color: #FFFFFF !important;
  border-color: #E5E7EB !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-row-label {
  color: #1F2937 !important;
  background-color: transparent !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-row-hint,
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-read-controls label {
  /* Was #6B7280, which measures ~4.4:1 on the #F3F4F6 read-controls background — just UNDER the 4.5:1
     AA text minimum. Darkened to match the footer label's #4B5563 (~6.8:1+ on every panel surface). */
  color: #4B5563 !important;
  background-color: transparent !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-read-controls { background-color: #F3F4F6 !important; }
/* .gp-a11y-footer itself carries no visible text of its own (all real text is in its children below),
   but it IS a <div> and therefore also matches the broad per-mode `div{color:#FFFFFF}` rule in section
   4a-4c directly (not merely by inheritance) — nothing here previously overrode that for the footer
   element itself. Pin an explicit color so nothing under it can inherit white-on-light by accident. */
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-footer { background-color: #F9FAFB !important; color: #4B5563 !important; }
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-footer label {
  color: #4B5563 !important;
  background-color: transparent !important;
}
/* The WCAG-conformance line (.gp-a11y-conformance) is ALSO a bare <div>, so — like .gp-a11y-footer
   above — it matches the per-mode `div{background:#000;color:#fff}` rule directly and, being more
   deeply nested, was never re-isolated: under High Contrast/Dark/Sepia it rendered as an opaque black
   (or mode-coloured) patch inside the otherwise light-skinned footer, breaking the "panel stays
   light-skinned" isolation guarantee (TC6) for this one line. Re-isolate it explicitly. */
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-conformance {
  color: #4B5563 !important;
  background-color: transparent !important;
  border-top-color: #E5E7EB !important;
}
/* B6: the segmented-control CONTAINER (.gp-a11y-segmented) is itself a bare <div>, so — same bug as
   .gp-a11y-conformance above — it matches the broad per-mode `div{background:#000}` rule directly.
   Its isolated child buttons (below) cover the button faces, but the container's OWN background still
   shows through any part of its box the buttons don't cover. ENG-023 fixed the specific case this was
   originally written for (the text-size row reusing a hard-coded 4-column grid for only 3 buttons,
   leaving an empty 4th cell) by sizing the grid to the row's actual button count, so there is no longer
   a leftover cell to show through — this rule is kept as a harmless defense-in-depth re-isolation of
   the container in case any future layout gap (rounding, an added row with a different count, etc.)
   exposes it again. Re-isolate the container to the panel's light skin in every contrast mode. */
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-segmented {
  background-color: #FFFFFF !important;
  border-color: #D1D5DB !important;
}
/* Panel controls keep their light skin plus the dark "selected / primary" accents. */
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-textsize button,
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-segmented button,
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-read-secondary,
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-read-controls select,
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-reset {
  background-color: #F9FAFB !important;
  color: #1F2937 !important;
  border-color: #D1D5DB !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-segmented button[aria-pressed="true"] {
  background-color: #1F2937 !important;
  color: #FFFFFF !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-read-primary {
  background-color: #1F2937 !important;
  color: #FFFFFF !important;
  border-color: #1F2937 !important;
}
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-switch { background-color: #D1D5DB !important; }
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-switch[aria-pressed="true"] { background-color: #16A34A !important; }
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-textsize-dot { background-color: #E5E7EB !important; }
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-textsize-dot.is-on { background-color: #1F2937 !important; }
html[class*="gp-a11y-contrast-"] #gp-a11y-panel .gp-a11y-help {
  color: #2563EB !important;
  background-color: transparent !important;
}
/* Neutralise the broad contrast TEXT-colour overrides (section 4a-4c) for inline text INSIDE the
   toolbar, so panel text follows the panel's own isolated colours rather than the page's mode
   foreground. Without this, the Sepia `span{color:#4B3621}` rule painted the "Play"/"Stop" label
   (a <span> inside the dark read button) dark-brown on dark = unreadable. `inherit` makes each take
   its (correctly isolated) parent's colour: white on the dark read button, dark on light rows, etc. */
html[class*="gp-a11y-contrast-"] #gp-a11y-root span,
html[class*="gp-a11y-contrast-"] #gp-a11y-root strong,
html[class*="gp-a11y-contrast-"] #gp-a11y-root em,
html[class*="gp-a11y-contrast-"] #gp-a11y-root small {
  color: inherit !important;
}

/* Read Aloud — currently-spoken paragraph highlight (WCAG 1.4.11) */
.gp-a11y-tts-active {
  background-color: rgba(255, 235, 59, 0.45) !important;
  outline: 2px solid #FFC107;
  outline-offset: 2px;
}
html.gp-a11y-contrast-high .gp-a11y-tts-active {
  background-color: #FFFF00 !important;
  color: #000000 !important;
}

/* ---------- 5. The floating launcher --------------------------------------- */
#gp-a11y-root {
  position: fixed;
  bottom: 16px;
  right: 16px;
  /* iOS / Android safe areas */
  bottom: max(16px, env(safe-area-inset-bottom, 16px));
  right: max(16px, env(safe-area-inset-right, 16px));
  /* WI 3778 (ENG-014a): the launcher layer must sit above the APPLICATION's topmost modal/backdrop
     layer — never above a framework default. Calibrating to Bootstrap's defaults (modal 1050 /
     backdrop 1040) put this at 1080, but GoPrint's patron success dialog (#successDialog-app in
     netZcoreCloudPrintingUserUpload.jsp) is authored at z-index 9999: live retest found
     elementFromPoint() at the launcher's centre returning the modal, so mouse/touch patrons could
     not reach the accessibility tools while that dialog was open (Tab still reached it). 10010
     clears the real 9999 ceiling with headroom. It is NOT the highest z-index in the app: the a11y
     skip-link (line ~46) intentionally sits above everything at z-index 100000, since it must be
     reachable even over this launcher/panel.
     The panel stays above the launcher via the local stacking context. */
  z-index: 10010;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.4;
  color: #1F2937;
}

#gp-a11y-launcher {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-width: 80px;
  height: 80px;
  padding: 0 22px;
  border-radius: 40px;
  border: 2px solid #FFFFFF;
  background-color: #1F2937;
  color: #FFFFFF;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
  font-size: 16px;
  font-weight: 600;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  position: relative;
}
#gp-a11y-launcher.is-collapsed {
  padding: 0;
  width: 80px;
}
#gp-a11y-launcher .gp-a11y-launcher-icon {
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
}
#gp-a11y-launcher .gp-a11y-launcher-label {
  white-space: nowrap;
}
#gp-a11y-launcher.is-collapsed .gp-a11y-launcher-label {
  display: none;
}
#gp-a11y-launcher:hover {
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
  transform: translateY(-1px);
}
#gp-a11y-launcher:focus-visible {
  outline: 3px solid #FFD600;
  outline-offset: 2px;
}
#gp-a11y-launcher .gp-a11y-active-dot {
  display: none;
  position: absolute;
  top: 6px;
  right: 6px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #16A34A;
  border: 2px solid #FFFFFF;
}
#gp-a11y-launcher.is-active .gp-a11y-active-dot {
  display: block;
}
#gp-a11y-launcher.is-speaking .gp-a11y-active-dot {
  background: #DC2626;
  animation: gp-a11y-pulse 1.4s ease-in-out infinite;
}

@keyframes gp-a11y-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.3); opacity: 0.7; }
}

/* ---------- 6. The panel --------------------------------------------------- */
#gp-a11y-panel {
  position: fixed;
  bottom: 112px;
  right: 16px;
  bottom: calc(112px + env(safe-area-inset-bottom, 0px));
  right: max(16px, env(safe-area-inset-right, 16px));
  width: 360px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 120px);
  overflow-y: auto;
  background: #FFFFFF;
  border: 1px solid #D1D5DB;
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.20);
  /* LOCAL to #gp-a11y-root's stacking context (it is positioned WITH a z-index), so this value only
     orders the panel against its siblings inside the widget — the whole widget layer is lifted above
     the app by #gp-a11y-root's z-index (see §5, 10010 vs the app's real 9999 ceiling). */
  z-index: 1060;
  display: none;
}
#gp-a11y-panel[aria-hidden="false"] {
  display: block;
}

#gp-a11y-panel header {
  /* Sticky (not just first-in-flow): keeps #gp-a11y-close pinned to the top of the panel's own
     overflow-y:auto viewport as the row content scrolls beneath it, so it can never be scrolled out
     of reach even if the row content is taller than max-height allows. */
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px;
  background: #1F2937;
  color: #FFFFFF;
  border-radius: 12px 12px 0 0;
}
#gp-a11y-panel header h2 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #FFFFFF;
}
#gp-a11y-close {
  background: transparent;
  border: 0;
  color: #FFFFFF;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
}
#gp-a11y-close:focus-visible {
  outline: 2px solid #FFD600;
  outline-offset: 2px;
}

.gp-a11y-row {
  padding: 14px 16px;
  border-bottom: 1px solid #E5E7EB;
}
.gp-a11y-row:last-of-type {
  border-bottom: 0;
}
.gp-a11y-row-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-weight: 600;
  font-size: 14px;
  color: #1F2937;
  margin-bottom: 8px;
}
.gp-a11y-row-hint {
  font-size: 12px;
  color: #6B7280;
  margin-top: 6px;
}

/* Text-size row: A−   dots   A+ */
.gp-a11y-textsize {
  display: flex;
  align-items: center;
  gap: 8px;
}
.gp-a11y-textsize button {
  flex: 0 0 40px;
  height: 40px;
  border-radius: 6px;
  border: 1px solid #D1D5DB;
  background: #F9FAFB;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  color: #1F2937;
}
.gp-a11y-textsize button:hover {
  background: #E5E7EB;
}
.gp-a11y-textsize button:focus-visible {
  outline: 2px solid #005FCC;
  outline-offset: 2px;
}
.gp-a11y-textsize button[aria-label="larger"] {
  font-size: 20px;
}
.gp-a11y-textsize-dots {
  flex: 1;
  display: flex;
  justify-content: center;
  gap: 6px;
}
.gp-a11y-textsize-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #E5E7EB;
  border: 1px solid #9CA3AF;
}
.gp-a11y-textsize-dot.is-on {
  background: #1F2937;
  border-color: #1F2937;
}

/* Shared segmented-button control (Text size row = 3 buttons, Contrast row = 4 buttons). QA v6
   (ENG-023): a hard-coded 4-column template (sized for Contrast) left the 3-button Text size row
   with a visible empty trailing cell. grid-auto-flow/grid-auto-columns instead sizes the grid to
   however many direct button children a given row actually has, so both rows render fully equal-
   width segments with no leftover cell — see ~/.claude/ada-standards.md §2. */
.gp-a11y-segmented {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border: 1px solid #D1D5DB;
  border-radius: 6px;
  overflow: hidden;
}
.gp-a11y-segmented button {
  padding: 8px 4px;
  border: 0;
  border-right: 1px solid #D1D5DB;
  background: #F9FAFB;
  font-size: 12px;
  color: #1F2937;
  cursor: pointer;
}
.gp-a11y-segmented button:last-child {
  border-right: 0;
}
.gp-a11y-segmented button:hover {
  background: #E5E7EB;
}
.gp-a11y-segmented button[aria-pressed="true"] {
  background: #1F2937;
  color: #FFFFFF;
  font-weight: 600;
}
.gp-a11y-segmented button:focus-visible {
  outline: 2px solid #005FCC;
  outline-offset: -2px;
}

/* Read aloud row */
.gp-a11y-read-controls {
  display: none;
  margin-top: 10px;
  padding: 10px;
  background: #F3F4F6;
  border-radius: 6px;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}
.gp-a11y-row.is-reading .gp-a11y-read-controls {
  display: flex;
}
.gp-a11y-read-primary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border: 1px solid #1F2937;
  background: #1F2937;
  color: #FFFFFF;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
}
.gp-a11y-read-primary:hover { background: #111827; }
.gp-a11y-read-secondary {
  padding: 6px 10px;
  border: 1px solid #D1D5DB;
  background: #FFFFFF;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
}
.gp-a11y-read-controls select {
  padding: 5px 8px;
  border: 1px solid #D1D5DB;
  border-radius: 6px;
  background: #FFFFFF;
  font-size: 12px;
  /* WI 3778 (ENG-012): the compact Speed control keeps this cap so it stays inline next to
     Pause/Stop. The Voice control is handled separately below — its full voice names (e.g.
     "Microsoft David Desktop - English (United States)") are far wider than Speed and can never
     line up beside it, so it gets its own full-width row instead of an awkward left-flush wrap. */
  max-width: 120px;
  flex: 0 1 auto;
  min-width: 0;
}
.gp-a11y-read-controls label {
  /* WI 3778 (ENG-012): keep each control's label + <select> together as one inline unit. */
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: #4B5563;
  min-width: 0;
}
/* WI 3778 (ENG-012): give the Voice control (the last item in the read-aloud group) its OWN
   full-width row directly beneath Pause/Stop/Speed, flush-left with those controls, and let its
   <select> stretch to fill that row. This replaces the broken ~44px left-flush wrap with a
   deliberate, aligned two-row layout that adapts to any voice-name length. Scoped to the
   read-aloud panel group; Speed keeps its inline cap above. */
.gp-a11y-read-controls label:last-child {
  flex: 1 0 100%;
}
.gp-a11y-read-controls label:last-child select {
  flex: 1 1 auto;
  max-width: none;
  /* WI 3778 (ENG-012): long voice names ("Microsoft David Desktop - English (United States)") ran
     straight into the native dropdown arrow. Truncate with an ellipsis and reserve 28px of right
     clearance so the text can never collide with the arrow, at every text size / contrast mode.
     The arrow itself is left native (no appearance:none) so the control still looks like a select. */
  padding-right: 28px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Highlight focus toggle */
.gp-a11y-switch {
  position: relative;
  width: 48px;
  height: 26px;
  background: #D1D5DB;
  border-radius: 13px;
  border: 0;
  cursor: pointer;
  padding: 0;
  transition: background 0.15s ease;
}
.gp-a11y-switch:after {
  content: '';
  position: absolute;
  left: 3px;
  top: 3px;
  width: 20px;
  height: 20px;
  background: #FFFFFF;
  border-radius: 50%;
  transition: transform 0.15s ease;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.gp-a11y-switch[aria-pressed="true"] {
  background: #16A34A;
}
.gp-a11y-switch[aria-pressed="true"]:after {
  transform: translateX(22px);
}
.gp-a11y-switch:focus-visible {
  outline: 2px solid #005FCC;
  outline-offset: 2px;
}

/* Footer with kiosk checkbox + Reset + Help */
.gp-a11y-footer {
  padding: 14px 16px 18px;
  background: #F9FAFB;
  border-radius: 0 0 12px 12px;
}
/* Accessibility-conformance version shown in the panel footer (e.g. "Conforms to WCAG 2.1 Level AA"). */
.gp-a11y-conformance {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid #E5E7EB;
  font-size: 12px;
  color: #4B5563;
  text-align: center;
}
.gp-a11y-footer label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: #4B5563;
  margin-bottom: 12px;
  cursor: pointer;
}
.gp-a11y-footer label input {
  width: 16px;
  height: 16px;
}
.gp-a11y-reset {
  width: 100%;
  padding: 10px;
  border: 1px solid #D1D5DB;
  background: #FFFFFF;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: #1F2937;
  margin-bottom: 10px;
}
.gp-a11y-reset:hover {
  background: #F3F4F6;
}
.gp-a11y-reset:focus-visible {
  outline: 2px solid #005FCC;
  outline-offset: 2px;
}
.gp-a11y-help {
  display: inline-block;
  font-size: 13px;
  color: #2563EB;
  text-decoration: underline;
}

/* Status live-region (offscreen, announced to screen readers) */
.gp-a11y-srlive {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---------- 7. Bottom-sheet on small screens ------------------------------- */
@media (max-width: 600px) {
  #gp-a11y-panel {
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-width: 100%;
    max-height: 80vh;
    border-radius: 16px 16px 0 0;
    border-bottom: 0;
  }
  #gp-a11y-panel header {
    border-radius: 16px 16px 0 0;
  }
  #gp-a11y-launcher {
    /* Always icon-only on small screens to avoid covering content. */
    padding: 0;
    width: 80px;
  }
  #gp-a11y-launcher .gp-a11y-launcher-label {
    display: none;
  }
}

/* ---------- 8. Reduced motion / print -------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  #gp-a11y-launcher,
  .gp-a11y-switch,
  .gp-a11y-switch:after,
  #gp-a11y-launcher.is-speaking .gp-a11y-active-dot {
    transition: none !important;
    animation: none !important;
  }
}

@media print {
  #gp-a11y-root,
  .gp-a11y-skiplink { display: none !important; }
}

/* ---------- 9. Dark-scheme system preference for the panel chrome --------- */
/* Independent of the contrast toggle — adjusts widget chrome only.          */
@media (prefers-color-scheme: dark) {
  #gp-a11y-panel {
    background: #1F2937;
    border-color: #374151;
    color: #E5E7EB;
  }
  #gp-a11y-panel .gp-a11y-row {
    border-bottom-color: #374151;
  }
  #gp-a11y-panel .gp-a11y-row-label { color: #F3F4F6; }
  #gp-a11y-panel .gp-a11y-row-hint { color: #9CA3AF; }
  .gp-a11y-textsize button,
  .gp-a11y-segmented button,
  .gp-a11y-read-secondary,
  .gp-a11y-reset {
    background: #374151;
    color: #F3F4F6;
    border-color: #4B5563;
  }
  .gp-a11y-textsize-dot { background: #4B5563; }
  .gp-a11y-textsize-dot.is-on { background: #F3F4F6; }
  .gp-a11y-footer { background: #111827; }
}
