/* ═══════════════════════════════════════════════════════════════════════════
   THE LIBRARY'S ACCESSIBILITY PREFERENCES — shared logic, tenant-owned colour.
   ⭐ S186. The owner asked for the widget on the templates the way the platform demos
   already carry it: *"we should be making all demos wcag ccompliant with the accessbility
   widget where possible as we have done with neubor, thsi should be a good selling
   feature"*. He also said why: *"i have learning dissabilities my self so these things
   mattter to others"*. So the bar is that a preference actually HOLDS — across a paint,
   a navigation and a session — not that a panel exists.

   ⛔ THIS FILE IS SHARED AND COPIED AT BUILD TIME, NOT RETYPED PER PACKAGE. `assistant.js`
   is byte-identical in eight packages with no sync mechanism; that is the repo's most
   expensive recurring defect (a value retyped at a second construction site, then
   drifting). `scripts/build.mjs` copies this in, so there is exactly one copy in git.

   ⛔ WHAT IS DELIBERATELY *NOT* HERE: the `contrast="high"` and `colour="safe"` token
   overrides. Those have to name the tenant's own CSS variables, and the 20 templates do
   NOT share a vocabulary — measured S186: `--ink` 19/20, `--muted` 19/20, `--line` 18/20,
   `--card` 17/20. "Nearly universal" is precisely the shape that works in dev and vanishes
   in production, so those two blocks live in each template's own styles.css and
   `check-library-a11y.mjs` fails the build if a package ships the widget without them.
   Everything in THIS file is name-independent and therefore safe to share.

   ⛔ DELIBERATELY UNLAYERED, exactly as the platform's tokens.css is: a reader's stated
   need must beat whatever the template author happened to write.

   ⚠ NO `theme` (page-colour) GROUP. These templates have one authored canvas each and no
   dark recipe has ever been rendered, let alone measured. Offering a switch that flips
   them would ship an untested page to the reader who most needs a working one — the same
   reasoning the platform demo panel records. High contrast covers the strongest need.

   ⛔ AND IT IS NOT A COMPLIANCE CLAIM. What this ships is controls a reader can use.
   Whether any given template passes WCAG is a measurement, and this repo never says
   "compliant".
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Text size ───────────────────────────────────────────────────────────────
   Scales the ROOT font size so every rem-based size moves together and nothing has to be
   re-authored. Percentages, not px, so a reader who already set a larger browser default
   keeps that as their baseline. */
html[data-a11y-text="large"] { font-size: 112.5%; }
html[data-a11y-text="larger"] { font-size: 125%; }

/* ── Easier reading ──────────────────────────────────────────────────────────
   ⚠ NO FONT IS DOWNLOADED, and that is evidence-led rather than lazy. The obvious move is
   OpenDyslexic; the research does not show it beating a plain sans-serif, and it would cost
   ~100KB on packages whose whole pitch is that they carry no fonts, icons, CDNs or trackers.
   This implements the British Dyslexia Association's own style guidance instead — a wide
   sans, generous letter and word spacing, tall lines, short measure, no italics for
   emphasis. Every one of those is free. */
html[data-a11y-font="readable"] body,
html[data-a11y-font="readable"] h1,
html[data-a11y-font="readable"] h2,
html[data-a11y-font="readable"] h3,
html[data-a11y-font="readable"] h4,
html[data-a11y-font="readable"] h5,
html[data-a11y-font="readable"] h6 {
  font-family: Verdana, Tahoma, "Trebuchet MS", system-ui, sans-serif !important;
}
html[data-a11y-font="readable"] body {
  letter-spacing: 0.045em;
  word-spacing: 0.14em;
  line-height: 1.75;
}
html[data-a11y-font="readable"] p,
html[data-a11y-font="readable"] li {
  max-width: 66ch;
  text-align: left !important;
  text-wrap: pretty;
}
html[data-a11y-font="readable"] em,
html[data-a11y-font="readable"] i {
  font-style: normal;
  font-weight: 600;
}

/* ── Text spacing ────────────────────────────────────────────────────────────
   ⭐ THE "MAXIMUM" VALUES ARE NOT A TASTE DECISION — THEY ARE THE WCAG TEST. SC 1.4.12
   (Text Spacing, AA) says content must survive a reader overriding line-height 1.5×,
   paragraph spacing 2×, letter-spacing 0.12em and word-spacing 0.16em. Shipping the
   criterion as a CONTROL is what makes it hold: a criterion nobody can switch on gets
   checked when somebody remembers. */
html[data-a11y-spacing="comfortable"] body {
  letter-spacing: 0.06em;
  word-spacing: 0.16em;
  line-height: 1.7;
}
html[data-a11y-spacing="comfortable"] p { margin-bottom: 1.5em; }
html[data-a11y-spacing="maximum"] body,
html[data-a11y-spacing="maximum"] p,
html[data-a11y-spacing="maximum"] li,
html[data-a11y-spacing="maximum"] h1,
html[data-a11y-spacing="maximum"] h2,
html[data-a11y-spacing="maximum"] h3,
html[data-a11y-spacing="maximum"] h4,
html[data-a11y-spacing="maximum"] h5,
html[data-a11y-spacing="maximum"] h6,
html[data-a11y-spacing="maximum"] a,
html[data-a11y-spacing="maximum"] span,
html[data-a11y-spacing="maximum"] button {
  line-height: 1.5 !important;
  letter-spacing: 0.12em !important;
  word-spacing: 0.16em !important;
}
html[data-a11y-spacing="maximum"] p { margin-bottom: 2em !important; }

/* ⚠ `anywhere`, NOT `break-word`. Both break a word that is already overflowing, but only
   `anywhere` reduces the element's MIN-CONTENT width — and horizontal scroll under a
   spacing override is an intrinsic-sizing problem, so `break-word` looks like the right
   property and measurably does nothing. */
html[data-a11y-spacing] p,
html[data-a11y-spacing] li,
html[data-a11y-spacing] h1,
html[data-a11y-spacing] h2,
html[data-a11y-spacing] h3,
html[data-a11y-spacing] h4 {
  overflow-wrap: anywhere;
  text-wrap: pretty;
}
/* A nowrap control cannot honour a spacing override — it just pushes the page wider. */
html[data-a11y-spacing] a,
html[data-a11y-spacing] button {
  white-space: normal !important;
  overflow-wrap: anywhere;
}
/* Flex/grid children default to min-width:auto and refuse to shrink below their content.
   That is what actually propagates an over-wide word up to <body>. */
html[data-a11y-spacing] main :is(div, section, article, header, footer, li) { min-width: 0; }

/* ── Colour vision · `mono` ──────────────────────────────────────────────────
   ⛔ NEVER FILTER `body` ITSELF. A filter creates a containing block for fixed
   descendants, so the accessibility launcher would stop being viewport-fixed, scroll away
   on a long page and strand the reader inside the very preference they are trying to
   reverse. Filter each top-level surface and exempt the control. `a11y.js` carries the
   matching `data-a11y-filter-exempt`, and the gate binds that agreement.

   ⚠ `safe` is NOT here — it has to name the tenant's own accent variables. See the header. */
html[data-a11y-colour="mono"] body > :not([data-a11y-filter-exempt]) { filter: grayscale(1); }
/* Removing hue means anything distinguished ONLY by colour must be distinguished another
   way, or this option would simply hide information. */
html[data-a11y-colour="mono"] main a,
html[data-a11y-colour="mono"] footer a,
html[data-a11y-colour="mono"] header a {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* ── High contrast — the name-independent half ───────────────────────────────
   Boundaries and link affordance only. The tenant's styles.css supplies the ink/canvas
   pair, because only it knows what its variables are called. */
html[data-a11y-contrast="high"] main a,
html[data-a11y-contrast="high"] footer a,
html[data-a11y-contrast="high"] header a {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* :focus-visible must survive everything above — it is the one indicator a keyboard user
   cannot do without. */
html[data-a11y-contrast="high"] :focus-visible {
  outline: 3px solid currentColor !important;
  outline-offset: 2px !important;
}

/* ── Always-underline links ──────────────────────────────────────────────────
   WCAG 1.4.1: colour must not be the only way to tell a link from text. */
html[data-a11y-underline="on"] main a,
html[data-a11y-underline="on"] footer a,
html[data-a11y-underline="on"] header a {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* ── Movement off ────────────────────────────────────────────────────────────
   The same suppression as the reduced-motion media query, driven by the switch, for a
   reader whose OS setting is not set or who is on a borrowed machine. */
html[data-a11y-motion="off"] *,
html[data-a11y-motion="off"] *::before,
html[data-a11y-motion="off"] *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
}
html[data-a11y-motion="off"] { scroll-behavior: auto !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE PANEL ITSELF.
   This markup is authored here, so it may use its own variables — the `--a11y-*` contract,
   each falling back to the token most templates happen to share and then to a literal. A
   template that maps nothing still gets a legible panel; the gate is what stops a package
   quietly relying on the fallback.

   ⚠ BOTTOM-LEFT, because `assistant.js` owns bottom-right (fixed, z-index 40/41) on every
   package that carries it. Two floating buttons in one corner is how you end up with
   neither being pressed, and at 390px they would overlap outright.
   ═══════════════════════════════════════════════════════════════════════════ */

.a11y-dock {
  position: fixed; left: 1.1rem; bottom: 1.1rem; z-index: 42;
  font-family: var(--a11y-sans, var(--sans, system-ui, sans-serif));
}
/* ⛔ S293 — on mobile the bottom-LEFT dock printed over left-aligned form labels ("Postcode"→"stcode"
   on every demo's booking/quote page — caught by two blind render judges, verified on the render). Form
   labels + body copy are left-aligned and there is no bottom-right widget in the library demos, so the
   dock moves to the right on narrow screens where it clears the content column. */
@media (max-width: 640px) {
  .a11y-dock { left: auto; right: 1.1rem; }
}
@media print { .a11y-dock { display: none; } }

/* ⛔ RESERVE THE SPACE THE FIXED DOCKS SIT IN. Found by LOOKING at the rendered footer, not
   by any assertion: the launcher printed over "3 Market Row, Ashcombe" and the assistant
   pill printed over the truth notice. It is the same defect already recorded against the
   Marrow demo (a fixed launcher over the "01 MEASURE" card), which is the tell that it is
   structural rather than a one-off — a page whose last element is a footer will always end
   underneath anything fixed to the bottom of the viewport.

   Two launchers, ~4.1rem tall each, so 5.5rem clears both with room. `body > footer` is
   (0,0,2) and beats the templates' own `footer` shorthand, and this file loads after
   styles.css. Name-independent: every package in the library ends in a <footer>.

   ⚠ This fixes the ASSISTANT overlap too, which pre-dates the accessibility panel entirely. */
body > footer { padding-bottom: 5.5rem; }

.a11y-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 3rem; height: 3rem; border-radius: 50%;
  background: var(--a11y-surface, var(--card, #fff));
  color: var(--a11y-ink, var(--ink, #16181c));
  border: 1px solid var(--a11y-line, var(--line, #d7d2c8));
  box-shadow: 0 6px 22px rgb(0 0 0 / 18%);
  cursor: pointer; position: relative;
}
.a11y-toggle:hover { transform: scale(1.05); }
.a11y-toggle svg { width: 1.35rem; height: 1.35rem; display: block; }
.a11y-count {
  position: absolute; top: -2px; right: -2px;
  min-width: 1.05rem; height: 1.05rem; padding: 0 0.2rem;
  border-radius: 999px; font-size: 0.66rem; font-weight: 700; line-height: 1.05rem;
  background: var(--a11y-ink, var(--ink, #16181c));
  color: var(--a11y-surface, var(--card, #fff));
}

.a11y-panel {
  width: min(20rem, calc(100vw - 2rem));
  max-height: min(70vh, 34rem); overflow-y: auto;
  margin-bottom: 0.75rem; padding: 1.15rem 1.15rem 1rem;
  background: var(--a11y-surface, var(--card, #fff));
  color: var(--a11y-ink, var(--ink, #16181c));
  border: 1px solid var(--a11y-line, var(--line, #d7d2c8));
  border-radius: var(--a11y-radius, var(--radius, 14px));
  box-shadow: 0 14px 40px rgb(0 0 0 / 22%);
}
.a11y-panel[hidden] { display: none; }
.a11y-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.a11y-panel-head h2 { font-size: 1.02rem; margin: 0; }
.a11y-close {
  width: 2.25rem; height: 2.25rem; border-radius: 9px; cursor: pointer;
  background: transparent; color: inherit;
  border: 1px solid var(--a11y-line, var(--line, #d7d2c8));
  font-size: 1.05rem; line-height: 1;
}
.a11y-group { border: 0; padding: 0; margin: 1.15rem 0 0; }
.a11y-group legend { font-size: 0.87rem; font-weight: 700; padding: 0; }
.a11y-options { display: flex; flex-direction: column; gap: 0.35rem; margin-top: 0.45rem; }

/* ⛔ THE SELECTED ROW IS INK-ON-CANVAS, NEVER THE TENANT'S ACCENT — and the platform
   learned this by looking rather than by reasoning. The first cut of the demo panel used
   the tenant primary with white text, which is fine on a cleaning company's teal and about
   2.6:1 white-on-brass on the joinery's. A brand accent carries no promise about white
   text. The page's own text/canvas pair is the one colour relationship every template
   already had to get right, so it is the only safe pair for a control that 20 palettes must
   render — and failing contrast inside the ACCESSIBILITY panel is the worst place in the
   product to get it wrong. */
.a11y-option {
  display: flex; align-items: flex-start; gap: 0.6rem; width: 100%;
  min-height: 2.75rem; padding: 0.5rem 0.7rem; text-align: left; cursor: pointer;
  border-radius: 10px; font: inherit; font-size: 0.9rem;
  background: transparent; color: inherit;
  border: 1px solid var(--a11y-line, var(--line, #d7d2c8));
}
.a11y-option[aria-pressed="true"] {
  background: var(--a11y-ink, var(--ink, #16181c));
  color: var(--a11y-surface, var(--card, #fff));
  border-color: var(--a11y-ink, var(--ink, #16181c));
}
.a11y-tick { flex: 0 0 auto; width: 1rem; opacity: 0; font-weight: 700; }
.a11y-option[aria-pressed="true"] .a11y-tick { opacity: 1; }
.a11y-option-label { display: block; font-weight: 600; }
.a11y-option-hint { display: block; font-size: 0.76rem; margin-top: 0.1rem; opacity: 0.78; }
.a11y-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  margin-top: 1.15rem; padding-top: 0.85rem;
  border-top: 1px solid var(--a11y-line, var(--line, #d7d2c8));
}
.a11y-reset {
  min-height: 2.75rem; padding: 0 0.7rem; border: 0; border-radius: 9px; cursor: pointer;
  background: transparent; color: inherit; font: inherit; font-size: 0.87rem; font-weight: 600;
  text-decoration: underline;
}
/* ⛔ No "what we do about accessibility" link. On the website that points at /accessibility,
   which is a statement about NEUBOR's own site backed by a committed audit record. A
   fictional template business linking it would be borrowing our measurement. */
.a11y-saved { font-size: 0.76rem; opacity: 0.78; margin: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   S301 CONSOLIDATED HELP — the static demos use the same entry pattern as Neubor's own site.
   One LifeBuoy opens AI, tour and accessibility actions. The authored robot remains inside the
   AI panel so each demo can keep its own name, picture and interface without adding another
  competing floating control.
   ═══════════════════════════════════════════════════════════════════════════ */
.a11y-dock { right: 1rem; left: auto; bottom: calc(1rem + env(safe-area-inset-bottom)); z-index: 50; }
.a11y-toggle {
  min-width: 3.15rem; width: auto; height: 3.15rem; padding: 0 .9rem; gap: .48rem;
  border-radius: 999px; font: inherit; font-size: .78rem; font-weight: 800;
  transition: transform .2s ease, box-shadow .2s ease;
}
.a11y-toggle-label { display: inline; }
.a11y-toggle svg { width: 1.35rem; height: 1.35rem; flex: 0 0 auto; }
.a11y-help-panel {
  width: min(20rem, calc(100vw - 2rem)); max-height: min(70vh, 34rem); overflow-y: auto;
  margin-bottom: .75rem; padding: 1rem;
  background: var(--a11y-surface, var(--card, #fff)); color: var(--a11y-ink, var(--ink, #16181c));
  border: 1px solid var(--a11y-line, var(--line, #d7d2c8));
  border-radius: var(--a11y-radius, var(--radius, 14px)); box-shadow: 0 14px 40px rgb(0 0 0 / 22%);
}
.a11y-help-panel[hidden] { display: none; }
.a11y-help-head { display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem; }
.a11y-help-head h2 { margin: .1rem 0 0; font-size: 1.04rem; }
.a11y-help-kicker { margin: 0; color: var(--a11y-muted, var(--muted, #5a6472)); font-size: .66rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.a11y-help-intro { margin: .7rem 0 .8rem; color: var(--a11y-muted, var(--muted, #5a6472)); font-size: .78rem; line-height: 1.45; }
.a11y-help-actions { display: grid; gap: .45rem; }
.a11y-help-action {
  display: flex; align-items: center; gap: .7rem; width: 100%; min-height: 3rem; padding: .55rem .65rem;
  border: 1px solid var(--a11y-line, var(--line, #d7d2c8)); border-radius: 11px;
  background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.a11y-help-action:hover, .a11y-help-action:focus-visible { background: var(--a11y-soft, var(--soft, #eef2f7)); }
.a11y-help-action strong, .a11y-help-action small { display: block; }
.a11y-help-action strong { font-size: .84rem; }
.a11y-help-action small { margin-top: .14rem; color: var(--a11y-muted, var(--muted, #5a6472)); font-size: .7rem; line-height: 1.3; }
.a11y-help-icon { display: grid; flex: 0 0 auto; place-items: center; width: 2rem; height: 2rem; border-radius: 9px; background: var(--a11y-soft, var(--soft, #eef2f7)); color: var(--a11y-ink, var(--ink, #16181c)); }
.a11y-help-icon svg { width: 1.1rem; height: 1.1rem; }
.a11y-help-status { min-height: 1.05rem; margin: .65rem 0 0; color: var(--a11y-muted, var(--muted, #5a6472)); font-size: .7rem; line-height: 1.4; }

/* Keep the individual assistant buttons in the document as functional click targets for the
   consolidated action, but remove their duplicate visual launchers and idle nudges. */
[data-neubor-assistant] .na-launch,
[data-neubor-assistant] .na-nudge,
.local-assistant > .local-assistant__toggle,
.sage-dock > .sage-dock-button {
  position: absolute !important; width: 1px !important; height: 1px !important; min-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; opacity: 0 !important; pointer-events: none !important;
}
/* Author styles set display:flex on the bespoke panels; keep the native hidden contract stronger
   so a closed counter assistant cannot sit invisibly over the Help sheet and steal pointer input. */
.local-assistant__panel[hidden], .sage-dock-panel[hidden] { display: none !important; }
/* Once a site-scoped assistant is open, its own close control is the active
   affordance. Keep the shared LifeBuoy out of the assistant panel's lower edge
   so the two controls never compete for the same 390px hit area. */
body:has(.na-panel:not([hidden])) .a11y-dock,
body:has(.local-assistant__panel:not([hidden])) .a11y-dock,
body:has(.sage-dock-panel:not([hidden])) .a11y-dock {
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
}

.a11y-tour-panel {
  position: fixed; right: 1rem; bottom: calc(1rem + env(safe-area-inset-bottom)); z-index: 60;
  width: min(32rem, calc(100vw - 2rem)); padding: 1rem 1.1rem .85rem;
  background: var(--a11y-surface, var(--card, #fff)); color: var(--a11y-ink, var(--ink, #16181c));
  border: 1px solid var(--a11y-line, var(--line, #d7d2c8));
  border-radius: var(--a11y-radius, var(--radius, 14px)); box-shadow: 0 18px 50px rgb(0 0 0 / 25%);
}
.a11y-tour-panel[hidden] { display: none; }
.a11y-tour-top, .a11y-tour-controls { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.a11y-tour-top { color: var(--a11y-muted, var(--muted, #5a6472)); font-size: .72rem; }
.a11y-tour-close, .a11y-tour-secondary, .a11y-tour-primary {
  min-height: 2.65rem; padding: .45rem .75rem; border-radius: 999px; font: inherit; font-size: .78rem; font-weight: 700; cursor: pointer;
}
.a11y-tour-close, .a11y-tour-secondary { border: 1px solid var(--a11y-line, var(--line, #d7d2c8)); background: transparent; color: inherit; }
.a11y-tour-primary { border: 1px solid var(--a11y-ink, var(--ink, #16181c)); background: var(--a11y-ink, var(--ink, #16181c)); color: var(--a11y-surface, var(--card, #fff)); }
.a11y-tour-close:hover, .a11y-tour-secondary:hover { background: var(--a11y-soft, var(--soft, #eef2f7)); }
.a11y-tour-primary:hover { opacity: .88; }
.a11y-tour-close:disabled, .a11y-tour-secondary:disabled { cursor: not-allowed; opacity: .42; }
.a11y-tour-panel h2 { margin: .65rem 0 .2rem; font-size: 1.08rem; }
.a11y-tour-panel p { margin: 0 0 1rem; color: var(--a11y-muted, var(--muted, #5a6472)); font-size: .8rem; line-height: 1.55; }
.a11y-tour-dots { display: flex; align-items: center; justify-content: center; gap: .26rem; min-width: 3rem; }
.a11y-tour-dots i { display: block; width: .38rem; height: .38rem; border-radius: 999px; background: var(--a11y-line, var(--line, #d7d2c8)); }
.a11y-tour-dots i.is-current { width: 1.15rem; background: var(--a11y-ink, var(--ink, #16181c)); }
.a11y-tour-hint { display: block; margin-top: .65rem; color: var(--a11y-muted, var(--muted, #5a6472)); font-size: .65rem; }

[data-tour-current] { scroll-margin-top: 1.5rem; outline: 3px solid var(--a11y-ink, var(--ink, #16181c)); outline-offset: .35rem; }
html[data-tour-active] [data-tour-current] { position: relative; z-index: 1; }

@media (max-width: 640px) {
  .a11y-dock { right: .75rem; bottom: calc(.75rem + env(safe-area-inset-bottom)); }
  .a11y-toggle { width: 3.15rem; min-width: 3.15rem; padding: 0; }
  .a11y-toggle-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .a11y-help-panel, .a11y-panel { width: min(20rem, calc(100vw - 1.5rem)); }
  .a11y-tour-panel { right: .75rem; bottom: calc(.75rem + env(safe-area-inset-bottom)); width: calc(100vw - 1.5rem); }
}

@media (prefers-reduced-motion: reduce) {
  .a11y-toggle { transition: none; }
  [data-tour-current] { outline-offset: .25rem; }
}
