/* ============================================================================
   css/payco-hud.css — HUD CONTRACT v1, the sheet half.

   WHAT IT DECLARES
     1. the --pc-* theme tokens, on :root and on [data-theme="dark"]
     2. the four viewports [data-hud="top"|"left"|"right"|"bottom"]
     3. widgets, panels, pop-outs, reorder mode
     4. the pc-tip tooltip
     5. the suppression layer

   NO HARDCODED HEX, ANYWHERE IN THIS FILE. Wave rule 5. Every colour is either a
   platform token (var(--blue), var(--ink)…) or an hsl() triple, and each hsl()
   triple is the exact same colour as the token it stands in for — written in a
   notation a grep for `#` cannot mistake for a new one. The fallbacks matter: this
   sheet is linked on pages that do NOT link payco.css (the marketing tier), so a
   bare var(--ink) there would resolve to nothing and the HUD would draw in the
   browser's default black.

   IT IS INERT UNTIL SOMETHING REGISTERS. Every rule below either names a class this
   lane created or narrows an existing one behind one. A page that links this sheet
   and registers no widget gets four token blocks and no layout change — which is
   what makes it safe to load on all 87 pages from payco-nav.js.

   THE DARK THEME IS A VARIABLE OVERRIDE AND NOT A SECOND STYLESHEET. Dark greys,
   blacks and silvers; the iconic blue is preserved at full saturation, because it is
   the one thing on the screen that says whose product this is.
   ==========================================================================*/

/* ---- 1. TOKENS ---------------------------------------------------------------
   Named --pc-* so a page can adopt the HUD's surfaces without adopting the HUD, and
   so a token that has a payco.css counterpart is visibly a REFERENCE to it rather
   than a second opinion about its value. */
/* ---- 1b. THE PLATFORM TOKEN FLOOR — added 2026-09-12 ---------------------------------------
   WHAT IT IS FOR. css/payco-system.css is the only file that defines the payco.css palette
   (--ink, --white, --line, --blue, --font, --shadow-md …). It is injected by payco-nav.js, and
   THE PUBLIC PAGES DO NOT LOAD payco-nav.js — they load payco-marketing.js. So on a marketing
   page that whole palette is undefined, and any sheet that reads it without a fallback loses the
   declaration outright.

   WHO THAT BROKE. css/payco-chat.css, which ships on every page and reads SIXTEEN of those names
   with no fallback at 159 sites. It is forbidden a literal of any kind — tests/chatsystem.mjs:883
   bans hex, rgb() AND hsl() there, correctly, so that every colour stays a var() a theme can
   reach — which means it cannot carry its own floor. MEASURED in chromium, anonymous, 2026-09-12:
   all 16 empty on pricing.html / about.html / contact.html, 11 on hardware.html, 5 on index.html,
   0 on login.html (which does load the system sheet). An empty custom property is not a colour —
   `color:var(--ink)` with --ink unset is invalid at computed-value time and the browser drops the
   declaration — so the dock fell back to the user agent on those pages.

   WHY :where(html) AND NOT :root. `:where()` has ZERO specificity, so css/payco-system.css's own
   `:root{…}` (0,1,0) and any page's inline `:root{…}` both still win, at any source order. This
   block can only fill a hole; it can never override a real definition.

   WHY IT IS NOT WRITTEN AS var(--pc-*). Because §1 below defines the --pc-* names AS
   `var(--system-name, literal)`. Pointing the system name back at its own --pc-* twin is a cycle,
   and a cycle invalidates BOTH — the first attempt did exactly that and took out the --pc-* layer
   as well. The literals below are therefore the same hsl() values §1 already carries as its own
   fallbacks, stated once on the upstream name so the two layers agree by construction rather than
   by coincidence. hsl() on purpose: this sheet forbids hex and writes hsl triples (a11yw8.mjs). */
:where(html){
  --font:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --white:hsl(0 0% 100%);
  --paper:hsl(216 43% 99%);
  --paper-warm:hsl(222 44% 97%);
  --ink:hsl(216 60% 10%);
  --ink-soft:hsl(220 37% 26%);
  --ink-mute:hsl(222 19% 44%);
  --line:hsl(219 39% 90%);
  --line-soft:hsl(218 55% 95%);
  --blue:hsl(224 78% 47%);
  --blue-electric:hsl(218 100% 62%);
  --blue-deep:hsl(223 85% 29%);
  --warn:hsl(14 71% 41%);
  --info-bg:hsl(222 100% 96%);
  --shadow-md:0 4px 24px hsl(223 85% 29% / .08),0 1px 2px hsl(216 60% 10% / .04);
  --shadow-lg:0 20px 60px hsl(223 85% 29% / .12),0 4px 12px hsl(216 60% 10% / .06);
}

:root{
  /* surfaces */
  --pc-surface:var(--white,hsl(0 0% 100%));
  --pc-surface-2:var(--paper,hsl(216 43% 99%));
  --pc-surface-3:var(--paper-warm,hsl(222 44% 97%));
  --pc-scrim:hsl(216 60% 10% / .34);
  /* ink */
  --pc-ink:var(--ink,hsl(216 60% 10%));
  --pc-ink-soft:var(--ink-soft,hsl(220 37% 26%));
  --pc-ink-mute:var(--ink-mute,hsl(222 19% 44%));
  --pc-ink-invert:hsl(0 0% 100%);
  /* line — one hair thicker sitewide, see css/payco-system.css §0 */
  --pc-line:var(--line,hsl(219 39% 90%));
  --pc-line-soft:var(--line-soft,hsl(218 55% 95%));
  --pc-hair:var(--hair,2px);
  /* THE RAIL SEAM, WHICH IS THE SAME WEIGHT ON BOTH RAILS AND IS NOT A PAGE'S TO RETUNE.
     See §12A's note: --pc-hair is redeclared by six pages, --hair by none. */
  --pc-rail-hair:var(--hair,2px);
  /* the iconic blue, preserved in both themes */
  --pc-accent:var(--blue,hsl(224 78% 47%));
  --pc-accent-hi:var(--blue-electric,hsl(218 100% 62%));
  --pc-accent-deep:var(--blue-deep,hsl(223 85% 29%));
  --pc-accent-cyan:var(--blue-cyan,hsl(196 93% 70%));
  --pc-accent-soft:hsl(218 100% 62% / .12);
  --pc-glow:hsl(218 100% 62% / .45);
  /* elevation */
  --pc-shadow:0 1px 2px hsl(216 60% 10% / .05),0 12px 34px hsl(223 85% 29% / .09);
  --pc-shadow-lg:0 24px 70px hsl(223 85% 29% / .18),0 4px 14px hsl(216 60% 10% / .08);
  /* ---- FOUR IMPORTS ADDED 2026-09-12, FOR A SHEET THAT CANNOT CARRY ITS OWN ----------------
     This block is the platform's TOKEN FLOOR: every name here is `var(--system-name, <literal>)`,
     so a page that never loads css/payco-system.css still resolves it. css/payco-chat.css cannot
     do that for itself — tests/chatsystem.mjs:883-886 forbid it a hex, an rgb() AND an hsl()
     literal, on purpose, so that every colour in it stays a var() a theme can reach. That rule is
     right, and it left the sheet with nothing to fall back TO: it reads sixteen --system names
     with no fallback, and on a marketing page none of them exist.
     MEASURED 2026-09-12 in chromium, anonymous: on pricing.html, about.html and contact.html all
     SIXTEEN compute to the empty string, so every rule in css/payco-chat.css that reads one is
     dropped at computed-value time. The five below had no --pc-* equivalent to borrow, so they
     are added here — where literals ARE allowed — and §0b of css/payco-chat.css maps the
     remaining twelve onto the names that already existed. */
  --pc-shadow-md:var(--shadow-md,0 4px 24px hsl(223 85% 29% / .08),0 1px 2px hsl(216 60% 10% / .04));
  --pc-font:var(--font,'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif);
  --pc-warn:var(--warn,hsl(14 71% 41%));
  --pc-info-bg:var(--info-bg,hsl(222 100% 96%));
  /* geometry — generous panels, symmetrical rails */
  --pc-radius:16px;
  --pc-radius-sm:11px;
  /* THE PANEL PACKING GAP, AND IT IS NOT THE LAW'S GUTTER (OPERATOR SPEC, THE VIEWPORT LAW).
     This token was called --pc-gap and it is what a HUD panel packs its rows with — a flat 14px,
     an internal measurement of a floating box. The viewport law then claimed the name --pc-gap
     for the site's OWN gutter, `clamp(16px,1.25vw,24px)`, the air between a rail and the centre,
     declared exactly once in payco.css. Two different quantities cannot share one name in a
     cascade where 165 pages link this sheet and 77 link that one, so the internal one is renamed
     and the public one is left to the law. Its five call sites in this file and the one in
     css/payco-hud-widgets.css moved with it; nothing outside those consumes it. advisor.html and
     boarding-advisor.html write `var(--pc-pack,14px)` and link neither payco.css nor this token,
     so they resolve through their own fallback to the same 14px they have always drawn. */
  --pc-pack:14px;
  --pc-pad:18px;
  /* THE RAIL WIDTH IS THE LEFT RAIL'S OWN TOKEN, NOT A SECOND OPINION ABOUT IT (W9 LANE 4).
     This said 292px. The left rail — .pc-sidenav — is --rail-w, css/payco-system.css:154, and it
     is 246px. So the two rails this file's own §2 comment promises are "mirrored exactly" were
     46px apart on every console that drew both, and nothing went red because the one suite that
     measures the pair (tests/hudwidgets.mjs §10) builds its fixture from payco-system.css and
     css/payco-hud-widgets.css and does not link THIS sheet — where the 292 lived. Measured at
     1440 with both rails up: left 246, right 292.
     Read the token and the mirror cannot drift again: retuning the left rail retunes this one.
     The literal is the fallback for the marketing tier, which links this sheet without
     payco-system.css and would otherwise get a rail of width `var(--rail-w)` = nothing. */
  --pc-rail-w:var(--rail-w,246px);   /* left AND right read this ONE number, see §2 */
  /* A THIRD OF THE RAIL, BECAUSE THE RAIL IS THREE COLUMNS WIDE. The open rail holds a 3 x 3 grid
     of tools (§3b); collapsed it keeps exactly one of those columns and the control that reopens
     it. So the shut width is not a taste — it is one column, derived, and it stays proportional
     to the open rail at every value --rail-w ever takes. 246/3 = 82px, and the one 34px control
     the collapsed bar keeps fits inside it with room on both sides (the 62px this used to say did
     not fit its own bar: see the note on the collapsed bar below). */
  --pc-rail-w-shut:calc(var(--pc-rail-w) / 3);

  /* ---- THE RIGHT RAIL IS ONE COLUMN, IN EVERY STATE (OPERATOR SPEC, HUD POLISH) ------------
     THE 3-ACROSS EXPANDED GRID IS DEAD. It was never a picture anybody asked for a second time:
     eight tools across three columns is a 3/3/2 grid whose last row `justify-content:center`
     hangs half-indented under the two above it, so no two tools in the rail shared a centre line
     and the rail was 246px wide to hold 72px of icon. One column is the whole geometry now, and
     because it is one column the width stops being "the left rail's width" and becomes what a
     column actually needs.
     THE WIDTH IS DERIVED FROM THE TOOL, not typed. --pc-tool is the one icon size §10 asks for
     and the only number here that a designer would ever retune; everything else is arithmetic
     off it, so there is no second opinion to drift.
         open   72 + 2 x 10 gutter + 2 x 2 hairline = 96px, and the tool centres in it
         shut   34 chevron + 2 x 9 + 2 x 2         = 56px, the same control, the same centre
     BOX-SIZING IS BORDER-BOX (payco.css's reset), so the border is INSIDE these numbers. That is
     the arithmetic the 3-across body got wrong in the other direction — it padded a border-box
     rail by 3px a side, lost 6px off a 246px sum that needed 240, and wrapped the third tool.
     THE LEFT DOCK KEEPS --pc-rail-w. §2's mirror is between the HUD's own two docks and this
     sheet still states it; what changed is that the RIGHT rail no longer takes part, because a
     one-column rail and a section-nav sidebar have no width in common. tests/hudcontract.mjs's
     mirror equality is re-baselined to say exactly that. */
  /* ONE ICON SIZE, AND IT IS LANE 5's TOKEN RATHER THAN A SECOND COPY OF IT. --pc-hud-tool is
     what css/payco-hud-widgets.css:86 actually sizes the buttons with; this file was declaring its
     own 72 beside it, which is two numbers that have to agree by hand. Reading it means the rail's
     WIDTH follows the button's size automatically — including the short-viewport step-down that
     sheet takes below 740px (§1 there), which is how §1's "never scroll" survives a laptop in a
     split window. The literal is the fallback for a page that links this sheet without that one. */
  --pc-tool:var(--pc-hud-tool,72px);
  --pc-rail-gut:10px;                /* the air each side of the column */
  /* ---- SYMMETRY: THE RIGHT RAIL IS THE LEFT RAIL'S WIDTH (OPERATOR SPEC, HUD v4.1 §1) --------
     The one-column pass sized this rail to its CONTENT — 72 + gutters + hairlines = 96px — which
     made it a column of icons that happened to be beside the page rather than a taskbar. The two
     rails then had nothing in common but an edge: 246 on the left, 96 on the right, and a console
     drew two surfaces that plainly were not the same component.
     IT READS THE LEFT RAIL'S OWN TOKENS NOW, and it reads them through --pc-rail-w, which is
     `var(--rail-w,246px)` — the 246px fallback matters, because 23 pages (admin.html and
     operations.html among them) do not link css/payco-system.css and have no --rail-w at all.
     The shut width is --pc-rail-w-shut, `--pc-rail-w / 3` = 82px, and that divisor was chosen in
     RAIL v2 for exactly the reason it is useful again here: one 72px tool fits in 82px with 5px of
     air on each side, so the icon column survives the collapse instead of being hidden by it.
     WHAT THIS COSTS: 246px of window for one 72px column is a lot of air, and that is the point —
     it is the same air the left rail spends on its labels, so the two bands are mirror images and
     the content between them is centred rather than merely fitted. */
  --pc-rail-col:var(--pc-rail-w);
  /* THE CHEVRON IS 44px, WHICH IS BOTH A DESIGN CHOICE AND THE ONLY LEGAL ONE. §3a puts a 44px
     min-height on every .pc-hud-btn (the WCAG 2.5.5 tap floor, pinned by tests/a11yw8.mjs and
     tests/mobilew8.mjs), and the chevron kept .pc-hud-btn while asking for 34 — so `width:34px`
     won and `height:34px` lost to the floor, and the control the operator asked to have "styled
     as a sibling of the tool icons" was rendering 34 wide by 46 tall. A rectangle nobody chose.
     Stating the floor as the size makes it a square again, keeps it a legal target, and still
     reads as chrome rather than as a ninth tool: 44 against the tools' 72 is the same step down
     the radius takes, and "smaller is fine" is what the spec asks for. */
  --pc-chev:44px;
  --pc-rail-col-shut:var(--pc-rail-w-shut);

  /* ---- THE GAP THAT GUARANTEES NO SCROLLBAR (OPERATOR SPEC, HUD v4 §1) --------------------
     "8 icons must fit without scroll at 800px viewport height — shrink gaps responsively if
     needed, never scroll." That is an inequality, so it is written as one rather than as a taste.
     A full-height rail's column is, top to bottom:
         gut + chevron + gap + 8 x tool + 7 x gap + gut     =  2 gut + chev + 8 tool + 8 gap
     and it has `100vh - chrome-top` to fit in. Solve for the gap:
         gap  <=  (100vh - chrome-top - 2 gut - chev - 8 tool) / 8
     With the platform's numbers (gut 10, chev 44, tool 72) the fixed part is 640px:
         900px viewport   (900 - 74 - 640) / 8 = 23.3   ->  capped at the design gap, 12
         800px viewport   (800 - 74 - 640) / 8 = 10.75  ->  10.75, and the column fits exactly
         760px viewport   (760 - 74 - 640) / 8 =  5.75  ->  5.75
     Below ~726px eight 72px icons cannot fit at ANY gap, which is arithmetic and not a bug — so
     css/payco-hud-widgets.css steps the tool down to 56px under 740px and this expression picks
     the new number up through --pc-tool without changing. clamp()'s floor is 2px so the column
     stays a column rather than a solid bar if a page ever reports a chrome-top nobody expected. */
  /* ---- THE GAP, RECOMPUTED WITH THE CORNER CLUSTER AS A TERM (HUD v4.1 §1) -----------------
     The no-scroll law is unchanged and it is still an inequality rather than a taste; what changed
     is the height it is solved against. The rail runs to the window's foot, and Yolanda's launcher
     and the chat tab OVERLAY its last 150px — so a column that used the full height put its last
     icon underneath the assistant. The usable height is the header's bottom to the CLUSTER's top,
     and payco-hud.js already measures exactly that and publishes it as --pc-hud-rail-floor.
         bar + 8 tool + 7 gap + floor  <=  100vh - chrome-top
     TWO OF THOSE FOUR TERMS ARE MEASURED, NOT DERIVED, and that is the whole correction. The
     first attempt reconstructed the bar as `gutter + chevron + gap` and was wrong by 12px,
     because the chevron does not resolve to --pc-chev on every page: at 1440x900 the bar measured
     76.9px against a reconstruction of 64.9, and the column overflowed its own box by 8px while
     the arithmetic said it fitted. payco-hud.js publishes the bar's real height as --pc-hud-bar-h
     and the cluster's as --pc-hud-rail-floor, so the only guessed terms left are the two this
     sheet actually owns — the tool and the gap.
     THE BAR'S BOTTOM PADDING IS A FIXED GUTTER, not the gap, or the expression is circular: the
     gap would be solved against a bar height that contains the gap.
     The 4px of slack absorbs sub-pixel distribution of a fractional clamp across seven boxes.
     Fixed part at the platform's numbers is 640px, and the two chrome terms are 74 + 150:
         1080px viewport  (1080 - 224 - 640) / 8 = 27.0  ->  capped at the design gap, 12
          940px viewport  ( 940 - 224 - 640) / 8 =  9.5  ->  9.5
          880px viewport  ( 880 - 224 - 640) / 8 =  2.0  ->  the floor of a 72px icon
     Below that no gap saves it, so css/payco-hud-widgets.css steps the TOOL down instead and this
     expression picks the new number up through --pc-tool without changing a character. */
  --pc-rail-gap:clamp(4px,
    calc((100vh - var(--pc-hud-chrome-top,var(--header-h,74px)) - var(--pc-hud-rail-floor,150px)
          - var(--pc-hud-bar-h,64px) - var(--pc-tool) * 8 - 4px) / 7),
    var(--pc-hud-tool-gap,12px));
  /* THE RAIL FLOATS OFF THE EDGE, ON YOLANDA'S OWN AXIS. Flush-right put a 2px border against the
     scrollbar and gave the rail one square corner the page had no answer for. An inset fixes that;
     WHICH inset is the design decision, and it is not a taste — the rail stops directly above
     Yolanda's launcher (§12's floor is her top edge), so the two are read as one vertical cluster
     whether or not they were meant to be. Centring the rail on her centre line makes that reading
     true instead of nearly true:
         open   24 + (112 - 96) / 2 = 32   ->  rail centre 1440 - 32 - 48 = 1360
         shut   24 + (112 - 56) / 2 = 52   ->  rail centre 1440 - 52 - 28 = 1360
         Yolanda                          ->  her  centre 1440 - 24 - 56 = 1360
     One column, both states, every width. Her two numbers are declared here as tokens rather than
     read from payco-assist.js because that file writes its geometry into an injected <style> and
     this sheet cannot see it; they are its literals (payco-assist.js:26, `.pca-bubble{bottom:24px;
     right:24px;width:112px}`) and a change to either is a change to both, which the names say. */
  --pc-assist-right:24px;
  --pc-assist-size:112px;
  /* THE RAIL IS FLUSH NOW, SO THE INSET IS ZERO (OPERATOR SPEC, HUD v4 §1). These two tokens
     placed the floating card on Yolanda's centre line. A full-height rail is flush to the window,
     so both are 0 — kept as names rather than deleted because §6c's flyout line is stated as
     `inset + col + gap` and reads better as that sum than as a special case, and because a future
     inset is then one value rather than an edit in four places. */
  --pc-rail-inset:0px;
  --pc-rail-inset-shut:0px;
  --pc-rail-radius:20px;             /* the icon radius family: tool 17, chevron 9, rail 20 */

  --pc-bar-h:56px;
  /* motion — one curve, used everywhere, so the whole shell moves as one object */
  --pc-ease:var(--ease-std,cubic-bezier(.32,.72,0,1));   /* W5 POLISH: unchanged in value */
  --pc-fast:var(--dur-fast,.16s);   /* W5 POLISH: unchanged in value */
  --pc-slow:var(--dur-slow,.34s);   /* W5 POLISH: unchanged in value */
  /* z-order. The full table is in docs/lane-reports/W7-LANE-1.md; the short version
     is that everything here sits UNDER the cookie bar (9998) and under the assist
     and bug clusters, and over ordinary page content. */
  --pc-z-hud:40;
  --pc-z-pop:60;
  /* THE TOOLTIP LOSES EVERY Z-FIGHT IT IS IN (OPERATOR SPEC, HUD POLISH §6). It used to sit at
     80, ABOVE the panels at 70, so an "About X? ASK YOLANDA" balloon left hovering as a panel
     opened painted over the panel it was describing. The law is one line of arithmetic: a tip is
     a hint about a control, a panel is the control's answer, and an answer is never under a hint.
     The bottom-right cluster's own order is the same law continued, in the 9990s where
     payco-assist.js and payco-chat.js live: Yolanda (9998) over the chat tab and its windows
     (9997/9996) over everything this sheet draws. §11 states the whole table. */
  --pc-z-tip:66;
  --pc-z-panel:70;
}

/* Dark greys, blacks and silvers. The blue does not move. */
[data-theme="dark"]{
  --pc-surface:hsl(220 18% 9%);
  --pc-surface-2:hsl(220 16% 13%);
  --pc-surface-3:hsl(220 14% 18%);
  --pc-scrim:hsl(220 24% 4% / .62);
  --pc-ink:hsl(210 22% 96%);
  --pc-ink-soft:hsl(214 14% 80%);
  --pc-ink-mute:hsl(216 11% 64%);
  --pc-ink-invert:hsl(220 18% 9%);
  --pc-line:hsl(218 13% 26%);
  --pc-line-soft:hsl(219 14% 21%);
  --pc-accent:hsl(218 100% 66%);
  --pc-accent-hi:hsl(200 96% 70%);
  --pc-accent-deep:hsl(223 62% 42%);
  --pc-accent-cyan:hsl(196 93% 70%);
  --pc-accent-soft:hsl(218 100% 66% / .16);
  --pc-glow:hsl(218 100% 66% / .55);
  --pc-shadow:0 1px 2px hsl(220 30% 2% / .5),0 14px 38px hsl(220 30% 2% / .5);
  --pc-shadow-lg:0 28px 80px hsl(220 30% 2% / .68),0 4px 16px hsl(220 30% 2% / .5);
}

/* ---- 2. THE FOUR VIEWPORTS ---------------------------------------------------
   THE RIGHT TASKBAR MIRRORS THE LEFT EXACTLY, and it mirrors it by reading the same
   custom property rather than by carrying a matching literal. Two literals is how
   two rails end up 4px apart after one of them is retuned. */
/* `display:flex` below beats the UA sheet's `[hidden]{display:none}`, so the attribute payco-hud.js
   puts on an empty dock (its syncEmpty(), which carries the measurement) needs saying again here or
   a rail holding nothing stays on the page at full size. Same shape as `.pc-hud-body[hidden]`.
   THE `[data-hud]` IS CARRYING SPECIFICITY, NOT SELECTING ANYTHING NEW — every rail has the
   attribute, and `.pc-hud[hidden]` alone was measured losing to eight pages that write their own
   copy of these rules inline. comms.html:164, staff-chat.html:73, org-team.html:227 and
   orgtree.html:342 are the same block four times, `.pc-hud[data-hud="top"]{...display:flex}`, and
   an inline <style> in the page's own <head> comes AFTER this linked sheet: equal specificity, so
   source order decided and the empty rail stayed on screen with `hidden` set on it and no effect.
   Measured on comms.html: hidden=true, display=flex, a 1440x56 empty bar over the page's tips. */
.pc-hud[data-hud][hidden]{display:none}
.pc-hud{
  position:fixed;z-index:var(--pc-z-hud);display:flex;flex-direction:column;
  background:var(--pc-surface);color:var(--pc-ink);
  box-shadow:var(--pc-shadow);
  transition:width var(--pc-slow) var(--pc-ease),height var(--pc-slow) var(--pc-ease),
             transform var(--pc-slow) var(--pc-ease);
}
/* THE RAILS START BELOW THE TOP BAR AND STOP ABOVE THE BOTTOM ONE (W7.5 LANE 1).
   They used to run the full height of the window, which put both of them ON TOP of the top
   bar's own bar — same z-index, and a rail is appended to the document after the top viewport,
   so the rail won the hit test over the first --pc-rail-w px of that row. That is exactly where
   the top bar keeps its caption, its reorder button and its COLLAPSE button, so at any width
   that shows a rail the top bar could not be collapsed or reopened by pointer at all
   (measured: elementFromPoint over the top bar's collapse button answered .pc-hud-cap owned by
   [data-hud="left"], at 1280 and at 1920).
   The two insets are the ones payco-hud.js already publishes on <html> on every viewport
   change, so this reads a number that is always current rather than assuming one: no top bar
   registered means --pc-hud-top is 0px and the rails sit exactly where they always did. */
/* THE DOCKS SIT BESIDE THE PAGE'S OWN CHROME, NOT ON IT (W9 LANE 4).
   `--pc-hud-chrome-left` and `--pc-hud-chrome-top` are published on <html> by payco-hud.js on
   every layout change — see its note, which carries the measurement. They are the two edges the
   platform's own fixed strips already own: the left rail `.pc-sidenav` and the header
   `.pc-header`. Both were being drawn over, by three of the four docks, at the same z-index.
   THIS REPLACES `--header-h` RATHER THAN ADDING TO IT. The token is 74px and is right about a
   header at rest; it is wrong about the same header once the reservation in §8b puts padding on
   <body>, because the header is `position:sticky` and moves with it. The published number is the
   header's own height plus the top dock's inset, which is the same thing measured instead of
   assumed — and it already contains --pc-hud-top, so adding that again here would count the top
   bar twice and leave a 56px band of nothing under it.
   THE FALLBACKS ARE THE OLD BEHAVIOUR EXACTLY. A page with this sheet and no payco-hud.js gets
   74px and 0px, which is where these docks have always been. */
.pc-hud[data-hud="left"],.pc-hud[data-hud="right"]{
  top:var(--pc-hud-chrome-top,var(--header-h,74px));bottom:var(--pc-hud-bottom,0px);
  width:var(--pc-rail-w);
}
.pc-hud[data-hud="left"]{left:var(--pc-hud-chrome-left,0px);border-right:var(--pc-hair) solid var(--pc-line)}
.pc-hud[data-hud="right"]{right:0;border-left:var(--pc-hair) solid var(--pc-line)}
/* THE TOP BAR IS PINNED TO THE WINDOW, ABOVE THE HEADER, and that is the one placement that has
   no circle in it. Under the header it needed the header's position to place itself, while the
   header needed the bar's height to know its own — two numbers each defined in terms of the other,
   which is how the bar ended up drawn INSIDE the header (measured: bar at y 74..130, header at
   y 56..130, elementFromPoint over the bar's collapse control answered img.pc-logo). Pinned to
   the window it is placed by nothing at all, the reservation in §8b pushes the sticky header
   clear of it, and the arithmetic runs one way only. */
/* ...AND THE RESERVATION THAT SENTENCE DEPENDS ON WAS REMOVED A WAVE LATER, WHICH IS WHY THE TOP
   BAR COULD NOT BE COLLAPSED BY POINTER AT ALL. `top:0` was correct while §8b pushed the sticky
   header past the bar. W10 lane 2 stood the reservation down for good — payco-hud.js's publish()
   now says "THE HUD RESERVES NOTHING" and REMOVES data-hud-reserve unconditionally — so nothing
   moves `header.pc-header` any more. It is `position:sticky; top:0; z-index:50` (css/payco-
   system.css:501) and the bar is z-index 40, so the two shared the window's first 56 rows and the
   header won every hit test in them.
   MEASURED (integrationproof-w8/w9 §8b, three assertions, ONE occluder): the top bar's collapse
   control at {x:80,y:11,w:44,h:44}, centre (102,33), `document.elementFromPoint` at that centre
   answering `img.pc-logo`. GATE 2 (open), GATE 4 (collapsed-but-reachable) and the all-four drill
   all reported that identical box and that identical occluder. A person who moved a widget into
   the top dock could neither collapse it nor reopen it, at any width.
   THE FIX IS THE ONE NUMBER THAT IS NOT CIRCULAR. Placing the bar under the header used to be
   impossible to express: the bar needed the header's position, the header needed the bar's height,
   and `--pc-hud-chrome-top` is the sum of the two, so reading it here would count this bar twice.
   `--pc-hud-head-h` is neither — payco-hud.js publishes it precisely because chrome().top is the
   wrong number for anything that wants to reserve the header, and it is `chromeBox('.pc-header').h`
   and nothing else: the header's own box, measured, independent of this dock. So the bar sits at
   the header's bottom edge, the two never share a pixel, the hit test has one answer, and
   `--pc-hud-chrome-top` (= head + this bar) stays exactly right for the left and right rails,
   which start below both.
   0px WHEN THERE IS NO HEADER, which is where this bar has always been, and this rule cannot
   reach a page that has no top dock: the selector needs the element payco-hud.js only builds when
   a widget is docked top.
   THE OFFLINE BANNER IS THE ONE THING THAT MOVES THE HEADER, and it says so itself
   (css/payco-system.css §30: `body.pc-is-offline .pc-header{top:var(--pc-offline-h,40px)}`). The
   header's HEIGHT is unchanged by it, so the bar follows the same offset the header took. */
/* AND IT STARTS BESIDE THE SIDE RAIL, EXACTLY AS THE BOTTOM BAR ALREADY DOES. `left:0` was the
   other half of the `top:0` assumption: a bar pinned ABOVE the header is above `.pc-sidenav` too
   (which starts at `top:var(--header-h)`), so spanning the whole window cost nothing. A bar that
   starts at the header's bottom edge is IN the side rail's band, and `.pc-sidenav` is z-index 40 —
   the same `--pc-z-hud` this dock has — so at equal z the DOM order decides the hit test and the
   page's own navigation won it. MEASURED after the top offset landed and before this line: the
   control moved from (102,33) to (102,107) and `elementFromPoint` stopped answering `img.pc-logo`
   and started answering `h4` — a heading inside the side rail. Same defect, one chrome element
   further down. `--pc-hud-chrome-left` is the side rail's measured width, published by
   payco-hud.js on every layout change and already read by the bottom dock on the line below; it is
   0px on a page with no side rail, which is where this bar has always started. */
.pc-hud[data-hud="top"]{
  top:var(--pc-hud-head-h,0px);left:var(--pc-hud-chrome-left,0px);right:0;height:var(--pc-bar-h);
  flex-direction:row;align-items:center;border-bottom:var(--pc-hair) solid var(--pc-line);
}
body.pc-is-offline .pc-hud[data-hud="top"]{
  top:calc(var(--pc-hud-head-h,0px) + var(--pc-offline-h,40px));
}
/* THE COOKIE BAR IS AT THE BOTTOM TOO, AND IT IS 9998 (css/payco-system.css §30's own table).
   That table's argument for the number — "they are all pinned to the bottom or the corners and
   this is pinned to the top, so the two sets never occupy a pixel in common" — was written before
   there was a BOTTOM DOCK. There is one now, at bottom:0, and it is z-index 40.
   MEASURED (integrationproof-w8/w9 §8a): the bottom rail's collapse control at (380,879) in a
   900px window; the topmost element there is a `p` inside `.pcc`, y=817 h=83, drawn on EVERY
   first visit. A person who has not yet answered the cookie question cannot collapse or reopen a
   bottom-docked rail — and answering it is the only way to find that out.
   NOTHING IS RE-STACKED. Raising the dock over the consent bar would put a rail on top of the
   thing a first-time visitor has to answer, which is worse. The dock stands ON the bar instead:
   payco-consent.js ALREADY publishes `--pc-consent-h` on <html> (payco-consent.js:80, measured
   from the element after it is drawn) and ALREADY removes the property when the bar goes
   (payco-consent.js:45). The seam existed; nothing read it. `0px` when the bar is not there,
   which is every visit after the first, so this rule is inert on the page it was inert on. */
.pc-hud[data-hud="bottom"]{
  left:var(--pc-hud-chrome-left,0px);right:0;bottom:var(--pc-consent-h,0px);height:var(--pc-bar-h);
  flex-direction:row;align-items:center;border-top:var(--pc-hair) solid var(--pc-line);
}
.pc-hud[data-hud="left"].pc-hud-collapsed,
.pc-hud[data-hud="right"].pc-hud-collapsed{width:var(--pc-rail-w-shut)}
.pc-hud[data-hud="top"].pc-hud-collapsed,
.pc-hud[data-hud="bottom"].pc-hud-collapsed{height:var(--pc-bar-h)}

/* the viewport's own bar: caption, reorder, collapse */
.pc-hud-bar{
  display:flex;align-items:center;gap:8px;min-height:var(--pc-bar-h);
  padding:0 12px;border-bottom:var(--pc-hair) solid var(--pc-line-soft);
  background:var(--pc-surface-2);
}
.pc-hud[data-hud="top"] .pc-hud-bar,.pc-hud[data-hud="bottom"] .pc-hud-bar{
  border-bottom:0;border-right:var(--pc-hair) solid var(--pc-line-soft);
}
/* 12px, NOT 11.5px (W8 LANE 14). The platform's type floor is 12px and this caption was the one
   thing on a console that sat under it: tests/crmui.mjs measured
   `SPAN.pc-hud-cap @11.5px: Right taskbar` on leads.html and funnel.html at 1440px and went red on
   both. The letter-spacing is what makes an uppercase caption readable at this size, not the
   half-pixel. */
.pc-hud-cap{
  flex:1;min-width:0;font-size:12px;font-weight:800;letter-spacing:.09em;
  text-transform:uppercase;color:var(--pc-ink-mute);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;
}
.pc-hud-collapsed .pc-hud-cap{opacity:0}
/* A RAIL'S BAR HAS NO CAPTION TO PUSH ITS CONTROLS ANYWHERE (W9 LANE 4). payco-hud.js stopped
   building .pc-hud-cap for the two rails — see the note there — and the caption was the flex:1
   child that held the two buttons against the far edge. Without it they would bunch at the start
   of the row, which on the LEFT rail is the window edge and on the RIGHT rail is the middle of a
   246px strip. Centred is the answer that is the same answer on both sides, which is the whole
   of the symmetry rule: the two rails are mirror images with nothing to distinguish them but
   which way the chevron points.
   THE CONTROLS SIT ON THE RAIL'S INNER EDGE, and the two rules below are one rule mirrored: the
   left rail's pair hugs its right edge, the right rail's pair hugs its left edge, so both sit
   against the content and the two collapse chevrons point at each other across the page. That is
   also where the caption used to leave them on the right rail, so the collapsed rail's overflow
   still runs OUTWARD toward the window edge — which is the symptom tests/hudcontract.mjs's
   MUTANT A re-creates by deleting the fit rules below, and it is why this is flex-start/flex-end
   rather than the `center` that was tried first: centred, an over-wide bar overflows equally on
   both sides and its control never leaves the window, so the mutant renders clean and a drill
   that has been watching a real bug since W7.5 stops watching anything. */
.pc-hud[data-hud="left"] .pc-hud-bar{justify-content:flex-end}
.pc-hud[data-hud="right"] .pc-hud-bar{justify-content:flex-start}

/* ---- 3a. THE RAIL'S BUTTON IS THE SITE'S BUTTON (W10 LANE 3) ------------------
   COPIED, NOT INVENTED, AND THE SOURCE IS NAMED SO THE NEXT READER CAN CHECK IT.
   What stood here was a component this sheet made up: a 34px borderless square on
   an 11px radius that tinted its background on hover, with a second 44px size in
   the <=560px layer. Nothing else on the platform looks like that, so the rail read
   as a different product from the page it sits beside — and as two different
   products from itself, because the small square and the phone-sized one were the
   same control at two sizes with two shapes.

   THE ONE PRE-EXISTING RULE THIS IS A COPY OF is the site's quiet, icon-only
   button: `.pc-btn.ghost` + `.pc-ico-only`, css/payco-system.css:737-743, mirrored
   at payco.css:531-537, with the shared button BEHAVIOUR block at
   css/payco-system.css:995-1002 and the one focus ring at
   css/payco-system.css:1017-1018. Verbatim:

     .pc-btn{font:inherit;font-weight:700;font-size:13px;border:0;border-radius:999px;padding:10px 18px;
       background:var(--gradient);color:<white>;cursor:pointer;display:inline-flex;align-items:center;gap:7px;
       (the source writes a three-digit white hex there; it is spelled out here because this
        sheet forbids the character and tests/hudcontract.mjs and tests/a11yw8.mjs both grep for
        it — the byte-exact quote is in docs/lane-reports/W10-LANE-3.md)
       transition:transform .12s,box-shadow .15s;box-shadow:0 2px 10px rgba(26,77,214,.22)}   :737-739
     .pc-btn.ghost{background:var(--paper-warm);color:var(--blue-deep);box-shadow:none}       :742
     .pc-btn.ghost:hover{background:var(--line-soft)}                                          :743
     .pc-btn,.cta,.btn,.go,.pri{
       transition:transform .12s cubic-bezier(.4,0,.2,1),box-shadow .18s ease,background-color .18s ease}  :995-996
     .pc-btn:hover,...{transform:translateY(-1px);box-shadow:var(--btn-shadow-hover)}          :997-998
     .pc-btn:active,...{transform:translateY(0);box-shadow:var(--btn-shadow-active)}           :999-1000
     .pc-btn.ghost:hover,...{box-shadow:none}                                                  :1002
     :where(a,button,summary,...):focus-visible{outline:2px solid var(--blue-electric);outline-offset:2px}  :1017-1018

   GHOST AND NOT THE PRIMARY, because a rail of nine gradient-blue pills is nine
   primary actions on one screen and the platform only ever draws one. Ghost is what
   css/payco-system.css already calls a quiet button, and it is the variant whose
   hover LIFTS but never grows the blue glow (:1002) — which is what a strip of
   chrome beside the page needs.

   THE COLOURS ARE THE SOURCE'S COLOURS, said through this file's own reference
   tokens so the marketing tier (which links this sheet and NOT payco.css) still
   resolves them: --pc-surface-3 is `var(--paper-warm,…)` and --pc-accent-deep is
   `var(--blue-deep,…)`, both declared in §1. Same colour, one name.

   `html body` CARRIES SPECIFICITY AND SELECTS NOTHING NEW. Five pages — intake.html:360,
   leads.html:423, proposal.html:408, refer.html:323, trial-invite.html:137 — draw their own
   `.pc-hud-btn` (a 13px-radius bordered white square) in a byte-identical block whose own
   comment says it is "written to be OVERRIDDEN by css/payco-hud.css rather than to compete
   with it: one class each, no !important, no id selector". At equal specificity it competed
   and won anyway, because a page's <style> is loaded after this sheet: measured at 1440 on
   leads.html, radius 13px / border 1px / a white background against support.html's 999px / 0 /
   --paper-warm, which is the SAME control drawn two ways on two consoles. Two element
   selectors settle it in the direction those pages asked for. Same device as
   `.pc-hud[data-hud][hidden]` in §2.

   ONE SIZE AT EVERY BREAKPOINT. 44px square is the platform's tap floor
   (css/payco-system.css:450 and :497 state min-height:44px outside any media query,
   for the same reason), it is what css/payco-hud-widgets.css:180-181 gives .pcw-btn
   in the same rail, and stating it once here is what deletes the second appearance:
   the <=560px raise this file used to carry in §9 is GONE, not moved. */
html body .pc-hud-btn{
  font:inherit;font-weight:700;font-size:13px;                 /* payco-system.css:737 */
  border:0;border-radius:999px;                                /* payco-system.css:737 */
  background:var(--pc-surface-3);                              /* .ghost, payco-system.css:742 */
  color:var(--pc-accent-deep);                                 /* .ghost, payco-system.css:742 */
  box-shadow:none;                                             /* .ghost, payco-system.css:742 */
  cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:7px;   /* :737-738 */
  width:44px;height:44px;min-width:44px;padding:0;             /* .pc-ico-only square, payco.css:664-667 */
  transition:transform var(--dur-fast,.16s) var(--ease-std,cubic-bezier(.32,.72,0,1)),box-shadow var(--dur-fast,.16s) ease,background-color var(--dur-fast,.16s) ease;   /* :995-996 */
}
html body .pc-hud-btn:hover{
  background:var(--pc-line-soft);                              /* .ghost:hover, payco-system.css:743 */
  transform:translateY(-1px);                                  /* payco-system.css:997-998 */
  box-shadow:none;                                             /* payco-system.css:1002 */
}
html body .pc-hud-btn:active{transform:translateY(0);box-shadow:none}    /* payco-system.css:999-1000 + :1002 */
/* THE GHOST BUTTON'S INK IN DARK IS NOT ITS INK IN LIGHT, AND THAT IS THE PLATFORM'S OWN MAP.
   css/payco-system.css:314 re-points `--blue-deep:var(--pc-accent-hi,hsl(200 96% 70%))` under
   [data-theme="dark"] — the copy above reads --pc-accent-deep, which is this file's name for the
   LIGHT --blue-deep and whose own dark value is hsl(223 62% 42%). Measured on the rendered rail:
   rgb(41,78,174) on rgb(39,44,52) is 1.6:1, so the icons all but vanished in dark. --pc-accent-hi
   is hsl(200 96% 70%) in dark (§1), the exact value the platform maps --blue-deep to, and it
   measures 8.4:1 on the same surface. Same rule, same role, the site's own second column. */
html[data-theme="dark"] body .pc-hud-btn{color:var(--pc-accent-hi)}
/* A VISIBLE FOCUS RING, because the hover state is not one (W8 LANE 14, WCAG 2.4.7). This is
   css/payco-system.css:1017-1018 written explicitly rather than inherited, because that rule is
   wrapped in :where() and therefore loses to any page rule at all — and it is the same two
   values, --pc-accent-hi being `var(--blue-electric,…)`. No background swap: the source's
   focus state does not repaint the button, and a ring plus a repaint was this file's invention. */
html body .pc-hud-btn:focus-visible{outline:2px solid var(--pc-accent-hi);outline-offset:2px}
/* The site's own large icon size, payco.css:668 `.pc-ico-lg{width:1.5em;height:1.5em}` — 1.5em of
   the 13px the source states at :737, so 19.5px in a 44px square. 17px was a literal with no
   source.
   THE 13px IS RE-STATED ON THE ICON, and that is not belt-and-braces: css/payco-system.css:939
   (`input, select, textarea, button{font-size:16px !important}` under 560px, the iOS zoom guard,
   payco.css:926) raises EVERY button on the platform to 16px on a phone, !important, so nothing
   in this file can hold 13px on the button itself — and an em icon then measured 24px at 375 and
   19.5px at 768 and 1440. That is the same control at two icon sizes, which is the defect this
   section exists to remove. The em stays, because `.pc-ico` is em-relative by design
   (payco.css:661-663, "sized in em so they follow the text they sit beside"); it is anchored to
   the 13px the source rule itself states, so the resolved value is 19.5px at every width. The
   button's own font-size is left at whatever the platform says: it has no text node. */
html body .pc-hud-btn .pc-ico{font-size:13px;width:1.5em;height:1.5em}
.pc-hud-collapsed .pc-hud-collapse{transform:rotate(180deg)}
.pc-hud[data-hud="right"] .pc-hud-collapse{transform:rotate(180deg)}
.pc-hud[data-hud="right"].pc-hud-collapsed .pc-hud-collapse{transform:rotate(0)}

/* A COLLAPSED RAIL'S BAR HAS TO FIT INSIDE --pc-rail-w-shut (W7.5 LANE 1).
   It did not. The bar is a nowrap flex row and its two 34px buttons carry min-width:34px, so
   its minimum content width is 34+34+8 gap+24 padding = 100px inside a 62px rail. The overflow
   went whichever way the writing direction runs: on the LEFT rail it spilled over the page and
   stayed clickable, on the RIGHT rail it spilled PAST THE WINDOW EDGE — measured at 1280, the
   collapse button's box was x=1280..1314 in a 1280px viewport, elementFromPoint answered null
   and a click never landed. That is the "a collapsed panel cannot be reopened" bug: the control
   was rendered, it was 34x34, and it was outside the screen.
   Collapsed, the rail keeps exactly ONE control — the one that opens it again. The caption is
   already blank at this width and the reorder button reorders a body nobody can see. */
.pc-hud[data-hud="left"].pc-hud-collapsed .pc-hud-bar,
.pc-hud[data-hud="right"].pc-hud-collapsed .pc-hud-bar{
  gap:0;padding:0;justify-content:center;
}
.pc-hud[data-hud="left"].pc-hud-collapsed .pc-hud-cap,
.pc-hud[data-hud="right"].pc-hud-collapsed .pc-hud-cap,
.pc-hud[data-hud="left"].pc-hud-collapsed .pc-hud-reorder,
.pc-hud[data-hud="right"].pc-hud-collapsed .pc-hud-reorder{display:none}

.pc-hud-body{
  flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;
  display:flex;flex-direction:column;gap:var(--pc-pack);padding:var(--pc-pad);
}
.pc-hud[data-hud="top"] .pc-hud-body,.pc-hud[data-hud="bottom"] .pc-hud-body{
  flex-direction:row;align-items:center;padding:0 var(--pc-pad);
}
.pc-hud-body[hidden]{display:none}

/* ---- 3b. THE RAIL IS THREE COLUMNS WIDE (W9 LANE 4) ---------------------------
   THREES. The design law asks for three boxes to a row and a 3/6/9 rhythm, and the right taskbar
   holds exactly nine tools — messaging, the assistant, the bug reporter, tooltips, notifications,
   the test viewer, the theme, settings and sign out. Three rows of three is the shape the content
   already had; it was drawn as a column of four because there were four.
   ONLY BARE WIDGETS ARE GRIDDED. A widget registered with content — an inbox list, a chart —
   still wants the full width of the rail and gets it: `grid-column:1/-1` puts a card back across
   all three columns, so a rail can hold both without either lane knowing about the other.
   THE GRID SITS ON THE RAIL'S CENTRE LINE, NOT THE BODY'S. `align-content:center` centres the
   three rows in the BODY, and the body starts below the bar — which would put the middle of the
   grid --pc-bar-h/2 below the middle of the rail. The extra bottom padding is exactly one bar
   height, which moves the centred block up by half of one, and the middle cell's centre then
   lands on the rail's own centre at every viewport height with nothing measured and no script.
   That is the same arithmetic css/payco-hud-widgets.css uses for the bell, stated once here for
   the whole grid. */
.pc-hud[data-hud="left"] .pc-hud-body,.pc-hud[data-hud="right"] .pc-hud-body{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  align-content:center;justify-items:center;align-items:center;
  padding:var(--pc-pad) var(--pc-pad) calc(var(--pc-pad) + var(--pc-bar-h));
}
.pc-hud[data-hud="left"] .pc-hud-body > .pc-hud-w:not(.pc-hud-w-bare),
.pc-hud[data-hud="right"] .pc-hud-body > .pc-hud-w:not(.pc-hud-w-bare){grid-column:1 / -1;width:100%}
/* A BARE WIDGET IS ITS CONTROL: no card, no border, no shadow, nothing to draw a second box
   around a button that already has one. One radius, one hairline, one icon set — and all three
   of them belong to the button inside, not to a wrapper around it. */
.pc-hud-w.pc-hud-w-bare{
  background:none;border:0;border-radius:0;box-shadow:none;overflow:visible;
  align-items:center;justify-content:center;
}
.pc-hud-w.pc-hud-w-bare:hover{box-shadow:none}
.pc-hud-w.pc-hud-w-bare > .pc-hud-w-body{padding:0;display:flex;align-items:center;justify-content:center}
/* COLLAPSED, THE RAIL IS ONE COLUMN. The body is hidden outright by payco-hud.js when a dock
   collapses, so this is what a rail looks like on the way in and out of that state rather than a
   state of its own — but it is stated, because a three-column grid inside an 82px rail
   mid-transition is three columns of 12px and it reads as a glitch. */
.pc-hud-collapsed .pc-hud-body{grid-template-columns:minmax(0,1fr)}

/* ---- 3. WIDGETS --------------------------------------------------------------
   Generous panel, centred content, one hair of edge. A widget is a card and reads
   like every other card on the platform, because a HUD that invents its own panel
   language is a second design system parked on the side of the first. */
.pc-hud-w{
  display:flex;flex-direction:column;background:var(--pc-surface);
  border:var(--pc-hair) solid var(--pc-line);border-radius:var(--pc-radius);
  box-shadow:var(--pc-shadow);overflow:hidden;
  transition:box-shadow var(--pc-fast) var(--pc-ease),transform var(--pc-fast) var(--pc-ease);
}
.pc-hud-w:hover{box-shadow:var(--pc-shadow-lg)}
.pc-hud-w-head{
  display:flex;align-items:center;gap:9px;padding:11px 12px;
  background:var(--pc-surface-2);border-bottom:var(--pc-hair) solid var(--pc-line-soft);
}
.pc-hud-w-shut .pc-hud-w-head{border-bottom-color:transparent}
/* THE HEAD IS A KEYBOARD CONTROL AND HAD NO FOCUS RING (W8 LANE 14, WCAG 2.4.7). payco-hud.js
   gives every widget head `tabindex="0"` so Alt+Arrow can move the widget inside its dock, which
   puts a stop in the tab order with nothing on screen to say where the caret is. It is not a
   button, so there is no UA ring to fall back on either. */
.pc-hud-w-head:focus-visible{
  outline:2px solid var(--pc-accent-hi);outline-offset:-2px;background:var(--pc-accent-soft);
}
.pc-hud-w-ico{display:inline-flex;align-items:center;color:var(--pc-accent)}
.pc-hud-w-ico .pc-ico{width:18px;height:18px}
.pc-hud-w-title{
  flex:1;min-width:0;font-size:13.5px;font-weight:700;color:var(--pc-ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.pc-hud-w-badge{
  display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;
  padding:0 6px;border-radius:999px;font-size:12px;font-weight:800;
  background:var(--pc-accent);color:var(--pc-ink-invert);
}
.pc-hud-w-badge[hidden]{display:none}
.pc-hud-w-body{padding:var(--pc-pad);font-size:13.5px;color:var(--pc-ink-soft)}
.pc-hud-w-body[hidden]{display:none}
.pc-hud-w-shut .pc-hud-w-toggle{transform:rotate(-90deg)}

/* collapsed rail: the marks stay, the words go */
.pc-hud-collapsed .pc-hud-w-title,
.pc-hud-collapsed .pc-hud-w-body,
.pc-hud-collapsed .pc-hud-w-pop,
.pc-hud-collapsed .pc-hud-w-toggle{display:none}
.pc-hud-collapsed .pc-hud-w-head{justify-content:center;padding:11px 0}

/* reorder mode says so, and it says so without moving anything */
.pc-hud-reordering .pc-hud-w{cursor:grab;border-style:dashed}
.pc-hud-reordering .pc-hud-w-head{background:var(--pc-accent-soft)}
.pc-hud-reordering .pc-hud-w:active{cursor:grabbing;transform:scale(.99)}

/* pop-open: the widget leaves the rail for a centred sheet and returns to its slot */
.pc-hud-w.pc-hud-popped{
  position:fixed;z-index:var(--pc-z-pop);top:50%;left:50%;
  transform:translate(-50%,-50%);width:min(560px,92vw);max-height:82vh;
  box-shadow:var(--pc-shadow-lg);
}
.pc-hud-w.pc-hud-popped .pc-hud-w-body{overflow:auto}

/* ---- 4. PANELS ---------------------------------------------------------------
   Centred, generous, symmetrical. One at a time — openPanel() closes the others. */
.pc-hud-panel{
  position:fixed;z-index:var(--pc-z-panel);top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(720px,94vw);max-height:86vh;display:flex;flex-direction:column;
  background:var(--pc-surface);color:var(--pc-ink);
  border:var(--pc-hair) solid var(--pc-line);border-radius:var(--pc-radius);
  box-shadow:var(--pc-shadow-lg);overflow:hidden;
}
.pc-hud-panel[hidden]{display:none}
.pc-hud-panel.pc-hud-open{animation:pcHudIn var(--pc-slow) var(--pc-ease)}
/* ---- 4a. ANCHORED TO THE RAIL (OPERATOR SPEC, HUD v3 §3) ---------------------
   payco-hud.js's repositionPanel() writes `top` and `right` in px on every open and on every
   layout change; this rule is what lets those two take effect — the centred shape above pins
   `top:50%;left:50%` and a `transform` that would otherwise drag the panel back to the middle of
   the window by half its own size.
   THE WIDTH SHRINKS TOO. 720px was the width of a centred dialog; a panel that lives beside the
   rail has the window less the rail less two gaps to work in, and 380px is what the notification
   list, the bug form and the test list all actually need. `min()` keeps it honest on a narrow
   window, where the rail is not drawn at all and the panel simply hugs the right edge.
   NO `max-height` HERE: the script writes it, because the ceiling is the header's measured
   bottom and the floor is the window's, and both move. */
.pc-hud-panel.pc-hud-panel-anchored{
  top:auto;left:auto;bottom:auto;
  transform:none;
  width:min(380px,calc(100vw - var(--pc-hud-right,0px) - var(--pc-pack) * 2));
}
.pc-hud-panel.pc-hud-panel-anchored.pc-hud-open{animation:pcHudSlide var(--pc-slow) var(--pc-ease)}
@keyframes pcHudSlide{
  from{opacity:0;transform:translateX(10px)}
  to{opacity:1;transform:translateX(0)}
}
.pc-hud-panel-head{
  display:flex;align-items:center;gap:10px;padding:16px var(--pc-pad);
  border-bottom:var(--pc-hair) solid var(--pc-line-soft);background:var(--pc-surface-2);
}
.pc-hud-panel-title{flex:1;min-width:0;font-size:15px;font-weight:800;color:var(--pc-ink)}
.pc-hud-panel-body{padding:var(--pc-pad);overflow:auto;font-size:14px;color:var(--pc-ink-soft)}
@keyframes pcHudIn{
  from{opacity:0;transform:translate(-50%,-46%) scale(.97)}
  to{opacity:1;transform:translate(-50%,-50%) scale(1)}
}

/* ---- 5. THE HEADER SLOT (seam for L3) ---------------------------------------- */
.pc-hud-slot{display:inline-flex;align-items:center;gap:6px}
.pc-hud-slot:empty{display:none}

/* ---- 6. pc-tip — GLOWING, INSTANT, TO THE POINT -------------------------------
   No transition-delay on the way in: the glow is the answer to the pointer and a
   delay is an argument with it. The bubble itself fades, because appearing without
   any motion at all reads as a rendering fault rather than as a response. */
/* 12px and an 20px disc, not 11px in an 18px one (W8 LANE 14). tests/crmui.mjs measured
   `BUTTON.pc-tip @11px: ?` on funnel.html and failed the platform's 12px type floor on it. The
   glyph is a question mark, so the disc has to grow with the type or the "?" touches the ring. */
.pc-tip{
  position:relative;font:inherit;font-size:12px;font-weight:800;line-height:1;
  display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;padding:0;border-radius:999px;
  border:var(--pc-hair) solid var(--pc-line);background:var(--pc-surface-3);
  color:var(--pc-ink-mute);cursor:help;
  transition:box-shadow var(--pc-fast) var(--pc-ease),color var(--pc-fast) var(--pc-ease),
             border-color var(--pc-fast) var(--pc-ease),background var(--pc-fast) var(--pc-ease);
}
.pc-tip:hover,.pc-tip:focus-visible,.pc-tip.pc-tip-on{
  color:var(--pc-accent);border-color:var(--pc-accent);background:var(--pc-accent-soft);
  box-shadow:0 0 0 3px var(--pc-accent-soft),0 0 14px var(--pc-glow);
}
/* The glow is a hover affordance and a box-shadow is not a focus indicator: it has no guaranteed
   contrast against whatever the tip is sitting on. Keyboard focus gets a real ring as well
   (W8 LANE 14, WCAG 2.4.7). */
.pc-tip:focus-visible{outline:2px solid var(--pc-accent-hi);outline-offset:2px}
.pc-tip-bub{
  position:absolute;z-index:var(--pc-z-tip);bottom:calc(100% + 9px);left:50%;
  transform:translateX(-50%);width:max-content;max-width:min(280px,72vw);
  padding:9px 12px;border-radius:var(--pc-radius-sm);
  background:var(--pc-ink);color:var(--pc-ink-invert);
  font-size:12.5px;font-weight:600;line-height:1.42;text-align:left;letter-spacing:0;
  text-transform:none;box-shadow:var(--pc-shadow-lg);pointer-events:none;
  animation:pcTipIn var(--pc-fast) var(--pc-ease);
}
[data-theme="dark"] .pc-tip-bub{background:var(--pc-surface-3);color:var(--pc-ink);
  border:var(--pc-hair) solid var(--pc-line)}
.pc-tip-bub[hidden]{display:none}
@keyframes pcTipIn{from{opacity:0;transform:translateX(-50%) translateY(3px)}
                   to{opacity:1;transform:translateX(-50%) translateY(0)}}

/* ---- 6b. THE `?` IS ONE GLYPH, NOT TWO (W10 LANE 3, DEFECT D) -----------------
   MEASURED, at 1440 in chromium on support.html: every tooltip on the page drew TWO
   question marks — a disc with a "?" in it, and a second bare "?" on its own line
   directly underneath, three of them in a row across the rail.

   WHY. payco-hud.js:927 defines the component as `<button class="pc-tip" …>?</button>`
   and both emitters put that "?" in as a real text node (payco-hud.js:601, :727 and
   payco-hud-widgets.js:161). support.html:464 then draws the disc AND a second "?"
   with `.pc-tip::before{content:"?"}`, because its fallback block assumed the button
   would be empty. Its `.pc-tip` is `display:inline-grid;place-items:center`, so the
   pseudo-element and the text node are two grid items, which is two ROWS: disc on
   top, orphan glyph below. Verified across the tree — support.html is the only page
   with a `content:"?"` on this pseudo-element, and every `.pc-tip` on every page
   carries the text node (10/10 support, 16/16 settings, 11/11 funnel, 8/8 invoice).

   THE FIX IS TO TAKE THE DISC OUT OF THE GRID. An absolutely positioned ::before is
   no longer a grid item, so the text node becomes the only one and is centred by the
   page's own `place-items:center`; the disc is then centred over it and is opaque, so
   the duplicate is covered by the glyph that belongs to the component. Nothing else
   is touched: on the other 97 pages that draw a tip this pseudo-element has
   `content:normal`, generates no box, and this rule is inert.
   `html body` carries specificity and selects nothing new — the rule it has to beat
   is a bare `.pc-tip::before` in a page's own <style>, which is loaded AFTER this
   sheet (that placement is deliberate and documented in each <head>) and would
   otherwise win the tie on source order. Same device as `.pc-hud[data-hud][hidden]`
   in §2. */
html body .pc-tip{position:relative}
html body .pc-tip::before{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:0}

/* THE RAIL'S TIP SITS ON ITS CONTROL, NOT UNDER IT. Two rules, in this order.
   As the rail actually renders, the tip is a plain sibling of the control and lays out as a
   44px box BELOW it — the "loose ? beside a button attached to nothing", three per row —
   because css/payco-hud-widgets.css, which positions it, is linked by NOTHING in this tree
   (see IR-1 in docs/lane-reports/W10-LANE-3.md). */

/* FIRST, INSIDE THE HUD THE TIP IS THIS SHEET'S COMPONENT AND NOBODY ELSE'S. 98 pages carry a
   `.pc-tip` in their markup and 29 of them write their own CSS block for it, which is right on the
   page — a tip in a form row is that page's affordance. In the RAIL those blocks are not right and they win anyway, because a
   page's <style> loads after this sheet: measured at 1440, funnel.html:1226-1229 and
   settings.html build the 44px-box / 20px-paint composite out of `border:12px solid transparent`,
   `background-clip:padding-box`, an inset ring and `margin:-12px -12px -12px -6px`, and dropped
   into a 38px rail control that resolves to a 24px box with NO content box, no visible disc and a
   centre 11px outside the button it explains. Two class terms restate §6's own box for the four
   docks only; every page's own tips are left exactly as that page drew them.
   The page fallback's ::before is stood down here rather than re-centred (§6b's first rule), because
   inside the rail there is no fallback to be: this sheet is present by definition. */
.pc-hud .pc-tip{
  box-sizing:border-box;width:20px;height:20px;min-width:0;min-height:0;margin:0;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:800;line-height:1;
  border:var(--pc-hair) solid var(--pc-line);border-radius:999px;
  background:var(--pc-surface-3);background-clip:border-box;color:var(--pc-ink-mute);
  box-shadow:none;cursor:help;
}
.pc-hud .pc-tip::before{content:none}
.pc-hud .pc-tip:hover,.pc-hud .pc-tip:focus-visible,.pc-hud .pc-tip.pc-tip-on{
  color:var(--pc-accent);border-color:var(--pc-accent);background:var(--pc-accent-soft);
  box-shadow:0 0 0 3px var(--pc-accent-soft),0 0 14px var(--pc-glow);
}
.pc-hud .pc-tip:focus-visible{outline:2px solid var(--pc-accent-hi);outline-offset:2px}

/* SECOND, WHERE IT SITS. This is css/payco-hud-widgets.css:217-227 copied verbatim, at IDENTICAL
   specificity (0,2,0) and EARLIER source order, so the moment that sheet is linked lane 5's copy
   wins every declaration and this one stops mattering. DELETE THIS BLOCK when IR-1 lands.
   The two custom properties are lane 5's, css/payco-hud-widgets.css:44-45; the literal fallbacks
   are that file's own values, needed only because the sheet declaring them is not loaded. */
.pcw-slot{position:relative}
.pcw-slot > .pc-tip{
  position:absolute;
  left:calc(var(--pc-hud-tip-out,6px) * -1);
  bottom:calc(var(--pc-hud-tip-out,6px) * -1);
  z-index:2;
  width:var(--pc-hud-tip-size,20px);
  height:var(--pc-hud-tip-size,20px);
  min-height:0;
}

/* ---- 6c. A TOOLTIP MAY NOT LEAVE THE RAIL (W10 LANE 3, DEFECT E) --------------
   MEASURED, at 1440 on support.html: the "Opens your message threads with the people
   you work with." balloon on the first rail widget rendered 300px wide, centred on a
   tip whose own box starts at x=1214 in a rail that starts at x=1194 — so it ran left
   across the page's content and was cut off mid-sentence.

   TWO BALLOONS, ONE RULE. Inside a rail this has to hold for BOTH of them: the
   component's own element (`.pc-tip-bub`, built by payco-hud.js:940) and the paint-only
   `.pc-tip::after` that 23 pages draw in their fallback block. They are addressed
   together because the containment is a property of the RAIL, not of which of the two a
   given page happens to be showing — and because payco-hud.js only upgrades the tips
   that exist at boot (:1242), so in the rail the page's ::after is usually the one on
   screen. Neither is given `content` here: this changes where a balloon goes, never
   whether there is one.

   position:fixed IS THE CONTAINMENT. The rail is 246px wide (--pc-rail-w, §1) and its
   widgets are a three-column grid, so a balloon centred on a widget in the outer column
   cannot be both readable and inside the rail — no `max-width` alone can fix it. Fixed
   to the window's own edge instead, with `top`/`bottom` left `auto` so the block axis
   still resolves from the balloon's static position beside its own tip, the balloon is
   pinned to the same inner column whichever widget raised it. --pc-gap (14px, §1) on the
   window side and the rail's own width as the cap put every balloon inside
   [window_edge - rail_w + gap, window_edge - gap], which is inside the rail.
   Fixed also un-clips it: a fixed box is not clipped by an ancestor's overflow, and the
   rail body scrolls.
   Nothing between the tip and the viewport establishes a containing block for a fixed
   descendant — no transform, filter or contain anywhere in this sheet (grep: zero hits)
   and none on .pcw/.pcw-slot in css/payco-hud-widgets.css.
   `transform` replaces the -50% centring with a straight lift of its own height plus the
   9px the component already used, and the entry animation is dropped in the rail because
   pcTipIn animates `transform:translateX(-50%)` and would fight it for its duration. */
/* AND NOTHING BETWEEN THE BALLOON AND THE WINDOW MAY BECOME ITS CONTAINING BLOCK. Measured on
   funnel.html: its tip carries `filter:drop-shadow(...)` on :hover (funnel.html:1231), and a
   filtered element is a containing block for every position:fixed descendant INCLUDING its own
   pseudo-elements — so `right:14px` resolved against the 44px tip instead of the window and the
   balloon painted at x=1013..1231, straight back across the page. filter, transform, perspective,
   backdrop-filter, contain and will-change are the six properties with that effect; all six are
   stood down on the tip inside a rail, which costs a page decoration and nothing else — the
   component's own hover glow is the box-shadow in §6 and is untouched. Three descendant terms so
   this outranks the `.pc-tip:hover` (0,2,0) that sets it. */
.pc-hud[data-hud="left"] .pc-tip,
.pc-hud[data-hud="right"] .pc-tip,
.pc-hud[data-hud="top"] .pc-tip,
.pc-hud[data-hud="bottom"] .pc-tip{
  filter:none;transform:none;perspective:none;backdrop-filter:none;contain:none;will-change:auto;
}
/* RE-BASELINED BY THE ONE-COLUMN RAIL (OPERATOR SPEC, HUD POLISH §5, §6).
   W10's containment put the balloon INSIDE the rail — `max-width:calc(--pc-rail-w - 28px)` — and
   that was the right answer for a 246px rail whose outer column would otherwise throw a balloon
   across the page. A one-column rail is 96px wide and 68px of content box is not a tooltip; it is
   two words and a hyphen. So the balloon stops being contained and becomes what every other
   flyout in the HUD now is: a box BESIDE the rail, obeying §5's alignment law.
   THE INLINE AXIS IS THE PANELS' OWN ANCHOR, to the pixel. payco-hud.js's repositionPanel() puts
   a panel's right edge at the rail's left edge less PANEL_GAP (12px); the same sum stated in CSS
   is `--pc-rail-inset + --pc-rail-col + 12px`, so a tooltip and a panel raised by the same tool
   share a right edge and the column of flyouts has ONE left-hand line rather than two.
   THE BLOCK AXIS IS DERIVED, and it is the one number here worth reading twice. `top`/`bottom`
   stay `auto`, so the balloon's static position is its own tip's box — and the tip badge is not
   the control, it is a 20px disc hung 6px outside the control's bottom-left corner
   (--pc-hud-tip-size / --pc-hud-tip-out, css/payco-hud-widgets.css:44). The control's top edge is
   therefore exactly `--pc-tool - --pc-hud-tip-size + --pc-hud-tip-out` above the balloon's static
   top — 72 - 20 + 6 = 58px — and lifting by that puts balloon.top on button.top, which is §5
   stated as arithmetic instead of as a hope. Every term is a token, so retuning the tool or the
   badge moves the balloon with it.
   THE CAP IS THE SPACE THAT IS ACTUALLY THERE: the window less the rail, its inset, the gap and
   a matching gutter on the far side. */
.pc-hud[data-hud="left"] .pc-tip-bub,
.pc-hud[data-hud="left"] .pc-tip::after,
.pc-hud[data-hud="right"] .pc-tip-bub,
.pc-hud[data-hud="right"] .pc-tip::after{
  position:fixed;z-index:var(--pc-z-tip);
  top:auto;bottom:auto;
  /* box-sizing, or the cap misses by the balloon's own padding: MEASURED at 1440 without it,
     max-width:218px on a content box plus 11px of padding each side painted 240px, and the
     balloon's left edge landed at x=1186 — 8px onto the page. The cap has to be the cap of the
     box that is drawn. */
  box-sizing:border-box;
  width:max-content;
  max-width:min(320px,calc(100vw - var(--pc-rail-inset) - var(--pc-rail-col) - var(--pc-pack) * 3));
  transform:translateY(calc((var(--pc-tool) - var(--pc-hud-tip-size,20px) + var(--pc-hud-tip-out,6px)) * -1));
  animation:none;
}
.pc-hud[data-hud="left"] .pc-tip-bub,
.pc-hud[data-hud="left"] .pc-tip::after{
  left:calc(var(--pc-rail-inset) + var(--pc-rail-col) + 12px);right:auto}
.pc-hud[data-hud="right"] .pc-tip-bub,
.pc-hud[data-hud="right"] .pc-tip::after{
  right:calc(var(--pc-rail-inset) + var(--pc-rail-col) + 12px);left:auto}
/* THE COLLAPSED RAIL IS NARROWER AND SITS ON A DIFFERENT INSET, and the flyout line moves with
   both or a tooltip raised on the shut rail hangs off its own anchor. One override, the same sum
   with the shut pair. */
.pc-hud[data-hud="right"].pc-hud-collapsed .pc-tip-bub,
.pc-hud[data-hud="right"].pc-hud-collapsed .pc-tip::after{
  right:calc(var(--pc-rail-inset-shut) + var(--pc-rail-col-shut) + 12px)}

/* THE SAME PROBLEM, THE OTHER TWO DOCKS. A bar is a row across the window, so its balloon does not
   run out of the SIDE — it runs off the TOP, because the component hangs the balloon above its tip
   (`bottom:calc(100% + 9px)`) and the top bar's tips are already at the top of the window.
   MEASURED at 375 with a widget in the top dock: the balloon painted at y=-89..-35 and
   x=145..415 in a 375-wide window — above the viewport AND past its right edge, so on a phone the
   tooltip could not be read at all.
   Below the bar instead, and left-aligned to the window's own gutter. The offset is
   --pc-hud-top / --pc-hud-bottom, the numbers payco-hud.js already publishes for §8/§8b, so this
   clears whatever the bar's height and offset actually are (52px at 375, 130px at 1440 with the
   site header above it) rather than a literal that would be wrong on one of them. */
.pc-hud[data-hud="top"] .pc-tip-bub,
.pc-hud[data-hud="top"] .pc-tip::after,
.pc-hud[data-hud="bottom"] .pc-tip-bub,
.pc-hud[data-hud="bottom"] .pc-tip::after{
  position:fixed;z-index:var(--pc-z-tip);box-sizing:border-box;
  left:var(--pc-pack);right:auto;transform:none;animation:none;
  width:max-content;max-width:calc(100vw - var(--pc-pack) * 2);
}
/* THE OFFSET IS THE DOCK'S OUTER EDGE, WHICH IS NOT ITS HEIGHT, and the note above already said
   so without the token to match: "130px at 1440 with the site header above it". `--pc-hud-top` is
   the bar's HEIGHT (payco-hud.js's measure(): `ins[d] = r.height` for the top dock) — 56, never
   130 — so this balloon has been hanging at y=65, inside the site header, on every page with a
   top-docked widget. `--pc-hud-chrome-top` is the number the sentence meant: the header's own box
   plus this bar, published by payco-hud.js on every layout change, and now exactly the bar's
   bottom edge. The old token is the fallback for a document with no header measurement, which is
   where this rule has always been right. The bottom balloon takes the same correction for the same
   reason as the dock above it — the cookie bar is under it on a first visit. */
.pc-hud[data-hud="top"] .pc-tip-bub,
.pc-hud[data-hud="top"] .pc-tip::after{
  top:calc(var(--pc-hud-chrome-top,var(--pc-hud-top,0px)) + 9px);bottom:auto}
.pc-hud[data-hud="bottom"] .pc-tip-bub,
.pc-hud[data-hud="bottom"] .pc-tip::after{
  bottom:calc(var(--pc-consent-h,0px) + var(--pc-hud-bottom,0px) + 9px);top:auto}

/* ---- 6d. THE HIDDEN BALLOON IS COLLAPSED, NOT MERELY INVISIBLE (W5 POLISH) ----
   THIS IS THE 320px HORIZONTAL SCROLL, AND IT IS ONE LINE.

   23 pages draw a paint-only fallback balloon as `.pc-tip::after` in their own <style>, and every
   one of those blocks hides it with `visibility:hidden`. Hidden leaves the box LAID OUT: an
   absolutely-positioned `width:max-content` bubble centred on its tip still counts toward every
   ancestor's scrollable overflow while being completely invisible, and it is a pseudo-element, so
   `querySelectorAll` cannot see it either.

   MEASURED, at 320px, before this rule (tests/designfix.mjs names all three):
       refer.html            body.scrollWidth 349 vs 320   +29px
       new-referrals.html    body.scrollWidth 349 vs 320   +29px
       button.pc-tip         scrollWidth 127 against a 44px client box — 83px of balloon
   `document.documentElement.scrollWidth` reads a clean 320 the whole time, because payco.css's
   `overflow-x:clip` propagates to the viewport. Only `document.body.scrollWidth` sees it.

   NINE PAGES ALREADY CARRY THIS FIX, hand-written into a <style> at the end of their <body>
   (settings, support, org-team, funnel, admin, checklist, operations, staff-chat, underwriting);
   tests/mobilew8.mjs §3b pins four of them and §8's M6 deletes the fix and requires the overflow
   back. The remaining fifteen could not have it, because their copy of the balloon sits inside a
   byte-shared HUD block that a page owner may not fork. So it is stated ONCE, here, in the sheet
   all 24 of them link — which is also why it is a stylesheet fix and not fifteen page edits.

   `scale`, THE INDEPENDENT PROPERTY, NOT `transform`. Every one of those blocks already puts a
   `transform` on this pseudo-element to centre it (`translate(-50%,5px)`), and restating
   `transform` here would mean restating the centring in every variant and getting one of them
   wrong. Nothing anywhere in this tree sets `scale` on `.pc-tip::after` — grep: zero hits outside
   the nine <body> blocks, which set exactly this — so there is no specificity contest to win and
   source order does not matter. The nine that already carry it restate the same value and stay
   byte-identical in effect.

   IT DOES NOT TOUCH `content`, so a page that draws no balloon still draws none, and it does not
   touch `visibility` or `opacity`, so the fade the page owns is untouched. `.pc-tip-on` is
   included because payco-hud.js:1242 flips that class on tap, where there is no :hover. */
.pc-tip::after{scale:0}
.pc-tip:hover::after,.pc-tip:focus-visible::after,.pc-tip.pc-tip-on::after{scale:1}

/* ---- 7. SUPPRESSION ----------------------------------------------------------
   payco-hud.js hides each match with an inline `display:none !important`, so this
   layer is belt AND braces: it covers an element that arrives between two observer
   ticks, and it is what a page linking the sheet without the script still gets. */
[data-pc-suppressed]{display:none!important}
body[data-hud-suppress~="chat"] .pca-bubble,
body[data-hud-suppress~="chat"] .pca-panel,
body[data-hud-suppress~="chat"] .pca-nudge,
body[data-hud-suppress~="bug"] .pcb-btn,
body[data-hud-suppress~="bug"] .pcb-panel,
body[data-hud-suppress~="bug"] .pcb-pinbar,
body[data-hud-suppress~="header-nav"] header.pc-header .pc-nav,
body[data-hud-suppress~="splash"] .pc-splash,
body[data-hud-suppress~="onboarding"] .pc-onboard{display:none!important}

/* ---- 8. THE CONTENT BOX THE HUD TOOK -----------------------------------------
   A page opts in with .pc-hud-inset and never has to listen for anything; the
   custom properties are written by payco-hud.js on every viewport change. This is
   the documented alternative to the resize event an injected rail never fires. */
.pc-hud-inset{
  padding-top:var(--pc-hud-top,0px);padding-bottom:var(--pc-hud-bottom,0px);
  padding-left:var(--pc-hud-left,0px);padding-right:var(--pc-hud-right,0px);
  transition:padding var(--pc-slow) var(--pc-ease);
}

/* ---- 8b. THE RESERVATION, MADE RATHER THAN OFFERED (W9 LANE 4) ----------------
   §8 above is an OPT-IN, and in 165 pages one page took it. Every other page got a
   position:fixed rail sitting on top of its own controls — 42 pages that were clean
   became pages where something could not be clicked the moment a widget registered,
   which is the measured reason (IR-2, docs/lane-reports/W8-LANE-1.md) the widget set
   has shipped switched off since W7.
   So the reservation is made here, by default. payco-hud.js writes
   `data-hud-reserve="<docks that took space>"` on <html> on every viewport change and
   removes the token when a dock closes or a media query hides it, so this is never a
   gutter for a rail that is not there. It stands down entirely on a page carrying
   .pc-hud-inset — that page reserved for itself and doing it twice is 492px of margin.

   WHY <body> AND NOT THE PAGE'S OWN CONTAINER. This sheet loads on 165 pages written by
   twenty lanes and the content box is called .wrap on some, main on others, .pc-wrap on
   the rest. <body> is the one element all of them have. Padding there narrows the
   normal-flow content box and moves nothing that is position:fixed — not the rails, not
   the cookie bar, not the assist bubble.
   THE HEADER USED TO BE ON THAT LIST AND IT DOES NOT BELONG THERE (HUD v4, MERGE).
   `header.pc-header` is position:STICKY, which is in normal flow, so a gutter on <body>
   takes the same width off the site header as off the page. Lane B reserved on <body> for
   real and hit it: measured at 1440, the header drawn [0..912] against a 1440 client width
   on all 64 pages that wear it, with the page's own background painted in the strip
   beyond — a bright band down the right of every console in dark theme.
   The fix is not to stop reserving; it is to give the header the gutter back with a
   negative margin, which is safe precisely because the rail is never over it: payco-hud.js
   pins the right dock's top to the measured chrome bottom, so at 1440 the rail is y74..767
   and the header y0..74 — one edge, never an area. payco.css does that now. Anything else
   in flow that DOES sit in the rail's vertical span — a footer, a view-bar, a sticky filter
   bar — needs background-to-the-edge with content held instead. See payco.css's console
   lane, which is where that reservation now lives (this file's own has stood down since
   W10 lane 2; payco-hud.js removes data-hud-reserve unconditionally).
   NOT margin: a margin on <body> would leave the page's background painted in the
   gutter's colour on every page that puts a background on <body> rather than on <html>. */
html[data-hud-reserve] body{transition:padding var(--pc-slow) var(--pc-ease)}
html[data-hud-reserve~="left"] body{padding-left:var(--pc-hud-left,0px)}
html[data-hud-reserve~="right"] body{padding-right:var(--pc-hud-right,0px)}
html[data-hud-reserve~="top"] body{padding-top:var(--pc-hud-top,0px)}
html[data-hud-reserve~="bottom"] body{padding-bottom:var(--pc-hud-bottom,0px)}

/* ---- 9. NARROW SCREENS -------------------------------------------------------
   The two rails leave at the same line payco.css draws for .pc-sidenav, and
   PaycoHUD.available() answers the same number in JS so a consumer never has to know
   it twice. The top and bottom bars stay — they are a row, and a row fits on a phone.
   1279, NOT 1100 (OPERATOR SPEC, THE VIEWPORT LAW). "Below 1280 both rails auto-
   collapse so the center stays dominant": two 246px rails and two gutters take 524px
   off the window, which leaves a 755px column at 1279 on consoles built for tables.
   Above the line the pair is drawn and reserved; below it neither is drawn and neither
   reserves, and the left rail's contents stay reachable through the header's burger. */
/* `html body`, AND IT IS LOAD-BEARING ON BOTH RULES BELOW. Four pages — comms, org-team, orgtree,
   staff-chat — carry a page-local HUD stub from the wave before this sheet existed:
   `.pc-hud[data-hud="left"],.pc-hud[data-hud="right"]{position:fixed;…;display:flex}` at (0,1,1),
   the same score as the bare selector this rule used to carry, in a <style> that loads after every
   stylesheet. At equal specificity source order decides, so the release never took effect on those
   four and their right rail was still drawn at 1279 — and had been at 1099 since the 1100px line
   was written. MEASURED on org-team.html at 1279: the rail at x1033..1279, 246px wide, over a
   centre that had already been released to the full window. (0,3,1) settles it without this lane
   editing four pages to delete a declaration each. */

/* BELOW 1100 BOTH RAILS LEAVE. Two 246px rails and two gutters take 524px; on a 1099px window that
   is more than half of it, and the left rail's contents are reachable through the header's burger.
   This was the line before the Viewport Law moved it to 1280, and it is the line again for the
   full release. */
@media(max-width:1099px){
  html body .pc-hud[data-hud="left"],html body .pc-hud[data-hud="right"]{display:none}
}

/* 1100-1279: THE LEFT RAIL LEAVES AND THE RIGHT RAIL COLLAPSES TO ITS STRIP (OPERATOR RULING).
   docs/A-NOTES.md §1 flagged the cost of the 1280 line rather than deciding it: between 1100 and
   1279 the HUD's TOOL rail used to be drawn and was released, so its widgets became unreachable on
   a half-screen window until it was widened. The ruling is that a half-screen window is a normal
   way to work. So the tool rail stays, at 82px, and payco.css reserves 82px + one gap for it.
   THE WIDTH IS SET HERE AS WELL AS BY THE COLLAPSED CLASS, and that is not redundancy: payco-hud.js
   applies .pc-hud-collapsed from script, so between first paint and boot the rail would otherwise
   draw at its full 246px inside an 82px reservation. This makes the strip true from the first
   frame, and the class — which payco-hud.js forces on in this band — carries the rest of the
   collapsed appearance. */
@media(min-width:1100px) and (max-width:1279px){
  html body .pc-hud[data-hud="left"]{display:none}
  html body .pc-hud[data-hud="right"]{width:var(--pc-rail-w-shut)}
}
@media(max-width:560px){
  .pc-hud[data-hud="top"],.pc-hud[data-hud="bottom"]{--pc-bar-h:52px}
  /* THE .pc-hud-btn RAISE THAT USED TO BE HERE IS DELETED, NOT MOVED (W10 LANE 3, DEFECT B).
     It read `.pc-hud-btn{width:44px;height:44px;min-width:44px}` and it was the second half of
     the two-appearances defect: a 34px button on a laptop and a 44px one on a phone is one
     control drawn two ways. §3a now states 44px once, outside every media query, which is also
     where css/payco-system.css:450 and :497 state the same floor. Nothing replaces it. */
  /* THE 24px IS LEFT EXACTLY AS IT WAS, AND THE REASON IT IS LEFT IS NOT THE REASON GIVEN BEFORE
     (W8 LANE 16). It was kept here so that raising the base disc to 20px could not make the tips
     other lanes' pages embed NARROWER than they had been. Re-measured at 375px in chromium, that
     rationale rests on a premise this tree does not satisfy:

       THIS SHEET DOES NOT WIN ON THE PAGES IT WAS BEING PROTECTIVE OF. All 165 pages carry a
       STATIC <link ... data-pc-hud-css> in <head>, and every one of them puts it ABOVE the page's
       own <style> (that placement is deliberate and documented in each <head>). payco-nav.js
       dedupes on that attribute and so never injects the runtime copy that would land last. At
       equal specificity source order decides, so on the 94 of 98 pages carrying a `.pc-tip` that
       also size one themselves, EVERY rule in this block is dead: org-team.html reads 20px, its
       own number, not the 24px written here. The measured regressions that scoping was protecting
       against — comms and staff-chat 0 -> +9px — cannot be reproduced from this file for the same
       reason. Four pages actually consume it: invoice.html, invoices.html, merchant360.html and
       industries/_template.html; those four are what this rule now changes, and they were measured
       at 375px before and after.

     THE RAISE IS NOT MADE HERE, AND THAT IS A MEASUREMENT, NOT A PREFERENCE. Of the four pages
     that actually consume this rule, member-directory.html carries its tips in a `#mdFilters`
     flex row with EXACTLY no slack — flex-shrink had been crushing them to 13.7px to make the row
     fit at 375px. Every way of giving that tip a 44px target was tried here and each one bought
     horizontal scroll on a page that had none:

       · `width:44px` + transparent 12px border + `margin:-12px`  →  375 becomes +14px. The
         negative margin returns the footprint to the 20px BASIS, and the basis was never what
         that row had room for.
       · a 44x44 absolutely-positioned `::after` overlay, zero layout  →  +10px. An abs-positioned
         pseudo-element is still overflow: it counts toward every ancestor's scrollable width.
       · `overflow:clip` + `overflow-clip-margin:12px` to stop that propagating  →  +6px, because
         the CLIP REGION itself is the overflow area, and the margin extends it 12px past the
         border box. (`min-width:0` is needed alongside it in any case: `overflow:clip` makes the
         tip a formatting context, and a flex item that is one stops shrinking below its content,
         which was another +6px on its own.)

     So the target on those four pages cannot come from this sheet without taking back the very
     defect the rest of this lane's work removes, and it is filed as an interface request against
     the pages instead — the fix is one `flex-wrap:wrap` on the row that has no room, which is a
     change only that page's owner may make. The 24px this block used to state is dropped rather
     than replaced: it never applied to anything (see above), so stating it only misled the next
     reader into thinking it was load-bearing.

     SO THIS LINE IS A NO-OP ON 94 OF THE 98 PAGES THAT DRAW A TIP, and on the four where it does
     apply it is the only thing keeping them at 24px rather than the 20px basis — which is why it
     stays. What changes here is the comment: the next reader should not have to re-derive that
     this block cannot reach the pages it appears to be about.

     WHERE THIS LANE COULD REACH, IT IS FIXED AND MEASURED. settings, support, org-team and funnel
     each carry a <body> block that grows the tip to a real 44x44 with a transparent border — real
     because it is TAPPED and not merely measured: a touch 4px inside the 44px box, in the border
     and well clear of the 20px painted disc, activates the button. tests/mobilew8.mjs §4d pins
     that, so it does not have to be re-derived here. */
  .pc-tip{width:24px;height:24px}
  /* The HUD's own surfaces have room, so there a tip takes the 44px as a real box: a widget head
     is not a filter row and nothing is competing for the width. */
  .pc-hud .pc-tip,.pc-hud-panel .pc-tip{width:44px;height:44px;min-width:44px;flex:none}
}

/* ---- 9b. NATIVE CONTROLS FOLLOW THE THEME HERE TOO (W5 POLISH) ---------------
   css/payco-system.css:442 declares `html{color-scheme:light}` and
   `[data-theme="dark"]{color-scheme:dark}` — the first `color-scheme` on the platform, added by
   the previous polish pass. It does not reach every page that can go dark: payco-nav.js injects
   THIS sheet (payco-nav.js:62-77) and never css/payco-system.css, so roughly 45 pages get the
   HUD's dark token set and the theme widget that flips it, and never get the declaration that
   tells the engine about it. On those pages a <select>, a date field, a checkbox and the
   scrollbar stay in their light native rendering on a dark body — the house trap recorded as
   "color-scheme:dark, or native controls go invisible".

   SAME TWO LINES, SAME VALUES, on the sheet those pages do receive. A page that links both
   sheets resolves the identical declaration from whichever loads second, so this cannot change a
   pixel where system.css is already present; it only supplies the ones where it is absent. */
html{color-scheme:light}
[data-theme="dark"]{color-scheme:dark}

/* ---- 10. REDUCED MOTION ------------------------------------------------------ */
@media(prefers-reduced-motion:reduce){
  .pc-hud,.pc-hud-w,.pc-hud-btn,.pc-tip,.pc-hud-inset{transition:none}
  html[data-hud-reserve] body{transition:none}
  .pc-hud-panel.pc-hud-open,.pc-tip-bub{animation:none}
}

/* ---- 11. THE BOTTOM-RIGHT CLUSTER STEPS OUT OF THE RAIL (W10 LANE 3, J AND K) --
   MEASURED, at 1440 on support.html and on leads.html, with the right rail up
   (x 1194..1440): payco-assist.js's launcher pair renders at
       .pcb-btn      right:44  bottom:150   72x72   z 9998   ->  x 1324..1396
       .pca-bubble   right:24  bottom:24   112x112  z 9998   ->  x 1304..1416
   and its callout at
       .pca-nudge    right:24  bottom:236  max 238  z 9997   ->  x 1178..1416
   All three are inside the rail's column, all three are above it in the z-order
   (9998/9997 against the rail's 40, §1), and on leads.html the bug button was sitting
   squarely on the rail's own Sign-out control. The callout is the "About X? Ask
   Yolanda" box, and its text changes per page, so what it covers changes per page.

   WHAT WAS CHOSEN: THEY ARE MOVED, NOT REPAINTED. The brief allowed either. Repainting
   was measured and rejected, for a reason that is written down in the file that draws
   them: payco-assist.js:760-769 states that the bug button is not a free-standing
   control but the second half of a designed pair — 72px so that 72/17 radius matches
   her 112/26, right:44 so the two centres share one axis, bottom:150 = 24 + 112 + 14,
   and the same drop shadow and inner glow "material". Restyling one of the two into the
   site's button leaves a 44px pale pill under a 112px lit sphere, which is worse than
   what is there now; restyling BOTH means redrawing an assistant persona — a character
   with an animated face whose geometry is keyed to its own size through --pca-dot,
   --pca-dot-gap and --pca-dot-track — from a stylesheet that does not own it, with
   values this lane would have to invent. Inventing a fourth component is the one thing
   this wave forbids outright.
   The rule this lane is under is that the HUD is a container for widgets. Neither of
   these is a registered widget, so the HUD may position ITSELF around them and may
   insist they do not sit on its controls; it may not repaint them. The repaint is filed
   as IR-3 against payco-assist.js instead, and the platform's own answer — retiring the
   floating pair on a console whose rail already carries the same two tools, via
   data-hud-suppress and §7 — needs no new component at all.

   HOW. margin-right and not `right`, because each of the six boxes carries a different
   `right` at each of its two breakpoints and re-stating six values here is six chances
   to drift; a margin is added to whatever that element's own offset already is. And not
   `transform`, which .pca-nudge is already using for its show/hide and .pcb-btn and
   .pca-bubble for their hover.
   The gutter is --pc-hud-right, the number payco-hud.js already publishes on <html> for
   §8/§8b, so this follows a collapsing rail and a rail that is not there. The whole
   block is gated on data-hud-reserve~="right", which §8b's own rules read: no right
   rail, no attribute, no shift — so on all 165 pages without a mounted rail, and on
   every viewport under 1100px where §9 drops the rails, this declares nothing. */
html[data-hud-reserve~="right"] body .pcb-btn,
html[data-hud-reserve~="right"] body .pcb-panel,
html[data-hud-reserve~="right"] body .pca-bubble,
html[data-hud-reserve~="right"] body .pca-panel,
html[data-hud-reserve~="right"] body .pca-nudge{
  margin-right:var(--pc-hud-right,0px);
}
/* K, THE CALLOUT'S OWN CAP. Moved, .pca-nudge's 238px still fits beside a 246px rail on a
   1440 window, but it is `max-width` on a fixed box and the window can be narrower than the
   rail plus the callout plus its gutters. Capped at what is actually free, so it can never
   grow back under the rail: the window, less the rail, less its own two 24px offsets.
   238px and 24px are payco-assist.js:105's own numbers, not new ones. */
html[data-hud-reserve~="right"] body .pca-nudge{
  max-width:min(238px,calc(100vw - var(--pc-hud-right,0px) - 48px));
}

/* ============================================================================================
 * 12. RAIL v2 — THE RIGHT DOCK IS A RAIL AGAIN, ON GATED PAGES ONLY (OPERATOR SPEC, HUD v3)
 * ============================================================================================
 * WHAT CHANGED FROM W10, IN ONE SENTENCE. The right dock stops being a bottom-right stack of nine
 * 72px icons and becomes a rail the width of the left one — because the operator's final word is
 * that a console gets a rail and a public page gets no rail at all, which is a split the stack
 * could not express: it was the same nine boxes in the same corner on every page that mounted it.
 *
 * THE ICONS ARE NOT REDESIGNED. "Collapsed = ONE column of the existing 72px icons" and "expanded
 * = the same icons three across" is the whole of the operator's geometry, and it is the arithmetic
 * that was already true: --pc-rail-w is the left rail's own --rail-w (246px, css/payco-system.css
 * :154) and --pc-rail-w-shut is a third of it (82px), so one 72px tool sits in the shut rail with
 * 5px of air on each side and three of them sit in the open one at a 12px gap with 3px of air:
 *     3 x 72 + 2 x 12 = 240,  246 - 240 = 6,  3px each side
 *     1 x 72          =  72,   82 -  72 = 10,  5px each side
 * Nothing here states a tool size and nothing states a rail width; both are read, so retuning the
 * left rail retunes this one and the mirror cannot drift. That is §1's rule, kept.
 *
 * THE FOUR EDGES.
 *   right   0 — it is a rail, flush to the window, exactly like the left one.
 *   top     --pc-hud-chrome-top, the header's own measured height plus the top dock's inset (§2).
 *           The rail starts BELOW the header and the header never moves: the HUD reserves nothing
 *           (see §RESERVATION in payco-hud.js), so nothing this file writes can reflow a sticky
 *           header the way W9's <body> padding did.
 *   bottom  --pc-hud-rail-floor, published by payco-hud.js's fitRailFloor() — the top edge of
 *           Yolanda's standalone launcher plus a gap, MEASURED, because "Yolanda standalone below
 *           the rail, not a member" means the rail has to stop above a box it does not own and
 *           that box moves at 560px. The fallback is her resting corner: 24 + 112 + 14 = 150px.
 *   width   --pc-rail-w / --pc-rail-w-shut, from §2, unchanged.
 *
 * OVERLAY DOCTRINE, UNCHANGED. The rail is position:fixed and out of flow, it writes no padding
 * on <body>, and --pc-hud-right stays INFORMATION a page may opt into with .pc-hud-inset. What
 * changed is that the number now moves between 246 and 82 as the rail opens and shuts, and every
 * consumer of it was re-probed in both states — see docs/L1-NOTES.md.
 * ------------------------------------------------------------------------------------------ */
/* ============================================================================================
 * 12A. FULL HEIGHT, FLUSH RIGHT — THE RAIL IS THE LEFT TASKBAR'S SIBLING (OPERATOR SPEC, HUD v4 §1)
 * ============================================================================================
 * THE FLOATING CARD IS DEAD. The polish pass made the rail a rounded card inset 32px from the
 * window on Yolanda's axis, hugging its content. It solved the slab and it introduced a different
 * problem: a 96x752 card floating in the right margin is not the same KIND of object as
 * `.pc-sidenav` on the left, which is a full-height surface flush to its edge — so a console drew
 * two navigation surfaces that did not agree they were the same component. The operator's word is
 * that they are siblings, so the right rail takes the left one's geometry:
 *
 *     top     --pc-hud-chrome-top, the header's own measured height. Below the header, never on it.
 *     bottom  0. The viewport's bottom edge, exactly like .pc-sidenav.
 *     right   0. Flush. The inset, the radius and the shadow all go with the card.
 *     border  ONE edge — border-left — because a surface flush to three window edges has one
 *             edge that faces the page, and that is the only one there is anything to draw on.
 *
 * WHAT THIS COSTS AND WHY IT IS PAID. The rail now runs down THROUGH the bottom-right corner that
 * payco-assist.js's launcher and payco-chat.js's tab occupy. That is deliberate and it is what
 * "Yolanda + chat tab overlay IN FRONT at the corner" means: they are at 9998 and 9997 against the
 * rail's --pc-z-hud (40), so they paint over it, and --pc-hud-rail-floor stops being a POSITION
 * this sheet reads. It is still published (payco-hud.js fitRailFloor) and still true; nothing here
 * consumes it any more.
 * ------------------------------------------------------------------------------------------ */
.pc-hud.pc-hud[data-hud="right"]{
  right:0;
  top:var(--pc-hud-chrome-top,var(--header-h,74px));
  bottom:0;
  width:var(--pc-rail-col);
  /* ONE EDGE, and it is the one facing the page. */
  border:0;
  /* --pc-rail-hair, NOT --pc-hair, AND THE DIFFERENCE IS A PAGE THAT REDECLARES ONE OF THEM.
     Six pages set `--pc-hair:1.5px` — settings.html on :root, and the five lane-14 pages on
     <body>, which this rail is a child of — so the right rail drew a 1.5px seam against the left
     rail's 2px on exactly those pages, and only those. --pc-rail-hair is resolved on :root out of
     the PLATFORM's --hair, which no page redeclares, so the pair cannot be split by a page-local
     opinion about a token it did not know the rails were reading. §1 of tests/viewportlaw.mjs
     compares the two computed border widths. */
  border-left:var(--pc-rail-hair) solid var(--pc-line);
  border-radius:0;
  background:var(--pc-surface);
  /* THE SHADOW IS GONE, AND ITS OWN NOTE IS WHY (OPERATOR SPEC, THE VIEWPORT LAW §2).
     What stood here said, in as many words, "`.pc-sidenav` carries none at all; this keeps a soft
     one because the right rail overlays content where the left one is reserved for." Both halves
     of that reason have expired. The right rail is RESERVED now — payco.css's lane takes
     --pc-rail + --pc-gap off <body> whether the rail is open or shut — so it no longer overlays
     anything and has nothing to cast a shadow onto; and the law is that the maximized right rail
     must be PIXEL-IDENTICAL to the left one: same width, same top edge, same bottom edge, same
     surface, same border, same radius. A 24px scrim on one of the pair and none on the other is
     the last thing that made a console read as two different components stuck to two edges.
     What is left is exactly what .pc-sidenav has: a flat surface and one hairline on the edge
     that faces the page. tests/viewportlaw.mjs §3 compares the two computed boxes. */
  box-shadow:none;
  /* THE RAIL IS ITS OWN LAYER, UNDER THE CORNER CLUSTER. Yolanda (9998) and the chat tab (9997)
     now overlap it rather than sitting below it, and they win — which is §9's z-order table
     unchanged, applied to a rail that reaches further than it used to. */
  z-index:var(--pc-z-hud);
  overflow:visible;
  pointer-events:auto;
  padding:0;
  gap:0;
}
/* COLLAPSED IS A DESIGNED STATE, NOT A LEFTOVER (OPERATOR SPEC, HUD POLISH §4). payco-hud.js
   hides the body outright (`b.hidden = !!st.collapsed`, payco-hud.js:305), so with a hugging
   height the collapsed rail is its bar and nothing else: a 56px rounded pill holding the one
   control that reopens it, on the same right inset and the same top as the open rail, so the
   transition is a width-and-height change of ONE object rather than two different pictures. */
/* COLLAPSED IS A SLIM FULL-HEIGHT STRIP (OPERATOR SPEC, HUD v4 §1), and that is the design call
   the spec asks to have recorded. The polish pass made it a 70x70 pill because the rail hugged its
   content and the body is hidden, so "the rail minimized" was a square in the top corner. A
   full-height rail cannot minimise into a square without becoming a different object mid-animation
   — the width would shrink and the height would collapse at the same time, and the eye reads that
   as the rail being replaced rather than narrowed. Keeping the two vertical edges fixed and moving
   only the width means ONE property changes, the transition is a slide, and the strip still reads
   as the taskbar because it still occupies the taskbar's column. It is the same choice
   `.pc-sidenav` makes on the left. */
/* MINIMIZED IS A SLIM STRIP AND NOTHING ELSE — NO BACKDROP, NO SHADOW (OPERATOR SPEC).
   The collapsed rail kept the open rail's paint: an 82px column of --pc-surface with a hairline
   and a 24px scrim, standing in a gutter the page had already reserved. Against a console's own
   --paper background that reads as a grey slab parked behind two buttons, which is exactly what
   the operator reported. Minimized, the rail is its controls: the surface, the border and the
   shadow all come off, the buttons keep their own material, and the strip's WIDTH still holds the
   column's centre line so opening and shutting moves one property and no pixels of the page.
   The reservation is unaffected — it is --pc-rail in both states by law, not the live width. */
.pc-hud.pc-hud[data-hud="right"].pc-hud-collapsed{
  width:var(--pc-rail-col-shut);padding:0;right:0;bottom:0;
  background:none;border-left:0;box-shadow:none}

/* THE TOOLS: ONE COLUMN, CENTRED, EVEN GAPS (OPERATOR SPEC, HUD POLISH §1).
   `flex-direction:column` and `align-items:center` are the whole of it, and the centring is a
   consequence rather than a calculation: the body's content box is the rail less its border and
   its gutters, the tool is --pc-tool, and centring a fixed-width child in a fixed-width box puts
   its centre on the box's centre at every viewport width and in both states. That is the
   probe-verifiable property §1 asks for — icon centreX == rail centreX — stated once.
   NO HORIZONTAL PADDING, AND NO HORIZONTAL SCROLL. The gutters are the rail's, not the body's,
   so the scroll container's content box is exactly the tool's width and `overflow-y:auto` can
   never produce a horizontal bar to squeeze the column off-centre. `scrollbar-width:none` keeps
   the vertical one out of the gutter as well — the rail is 96px wide and a 15px scrollbar inside
   it is 15px stolen from a 72px icon's air, which is the "flush against the scrollbar" the
   operator saw on the old flush-right rail.
   THE GAP IS THE ONE GAP. --pc-hud-tool-gap is the single value §10 asks for; the bar's own
   bottom padding is the same token so the space between the chevron and the first tool is the
   space between any two tools, with no dead band in between. */
.pc-hud.pc-hud[data-hud="right"] .pc-hud-body{
  display:flex;
  flex-direction:column;
  flex-wrap:nowrap;
  align-items:center;
  justify-content:flex-start;
  gap:var(--pc-rail-gap,var(--pc-hud-tool-gap,12px));
  /* THE RIGHT GUTTER PAYS FOR THE LEFT BORDER, and without it the column is off-centre by exactly
     half a hairline. §1's law is "icon centreX == RAIL centreX", and the rail is a border box whose
     ONE border is on the left: at 1440 with a 1px hair the rail spans 1345..1440 (centre 1392.5)
     while its content box spans 1346..1440 (centre 1393). A 72px tool centred in the content box
     therefore lands 0.5px right of the surface it is centred in — measured, and visible as a
     column that leans away from the page on a 2px-hair console.
     One hairline of padding on the far side makes the content box symmetric about the border box,
     so `align-items:center` centres on the rail rather than on what is left of it. */
  /* THE BOTTOM PADDING IS THE CORNER CLUSTER'S OWN HEIGHT, measured and published by
     payco-hud.js's fitRailFloor(). The rail is flush to the window's foot — that is §1's geometry
     — and the cluster overlays its last 150px, so the COLUMN stops where the cluster starts while
     the SURFACE runs the whole way down. Without it the eighth icon is drawn underneath Yolanda. */
  padding:0 var(--pc-hair) var(--pc-hud-rail-floor,150px) 0;
  /* `auto`, NOT `scroll`, and with §1's clamp it never has anything to do — the gap is solved so
     the column always fits. It stays as the safety valve for a page that puts something unexpected
     in the rail, and `scrollbar-width:none` keeps the valve from ever stealing width from a 96px
     column if it does open. §1's probe asserts scrollHeight <= clientHeight in every state. */
  overflow-y:auto;
  overflow-x:hidden;
  scrollbar-width:none;
  /* HUG, DO NOT STRETCH. `flex:1 1 auto` made the body claim every pixel the rail had, which is
     how a 250px stack of tools ended up inside an 826px box. `0 1 auto` takes its natural height
     and gives it back under the cap. */
  flex:0 1 auto;
  min-height:0;
  /* THE FADE MASK AND THE ROUNDED SCROLLING EDGE ARE BOTH GONE (OPERATOR SPEC, HUD v4 §1), and
     both for the same reason: they were treatments for a scroll that can no longer happen. The
     mask softened a guillotined eighth icon and the radius ended the column on the card's curve —
     a full-height rail has no curve and, with --pc-rail-gap solved against the viewport, nothing
     below the fold to soften. Keeping either would dim the last icon of a column that fits. */
}
.pc-hud.pc-hud[data-hud="right"] .pc-hud-body::-webkit-scrollbar{width:0;height:0}
/* THE METRIC BOX (OPERATOR SPEC, HUD v4.1 §2). payco-hud.js measures this to publish
   --pc-hud-right-open, the width the rail takes when open, in EVERY state — so a page's content
   reservation stops following the collapse. It carries the rail's own width token and nothing
   else: absolutely positioned so it is out of the column's flow, zero height so it adds none, and
   visibility:hidden so it paints nothing while still reporting a box. */
.pc-hud[data-hud="right"] .pc-rail-metric{
  position:absolute;top:0;left:0;
  width:var(--pc-rail-w);height:0;
  visibility:hidden;pointer-events:none;
}
/* AND IT REALLY GOES AWAY WHEN THE RAIL SHUTS. §3's `.pc-hud-body[hidden]{display:none}` is
   (0,2,0) and the rule above is (0,4,0), so §12 has been quietly beating the UA-style hide that
   payco-hud.js:305 relies on ever since RAIL v2 landed: the collapsed rail was 56px wide and
   *738px tall*, a hidden body still laying out eight 72px tools inside a 52px content box.
   Nothing was visible because the tools overflowed a rail with no room for them, which is why it
   read as "the rail, minimized" by accident rather than by design. Stated at (0,5,0) on the class
   the JS actually sets, and once more on the attribute so the two agree however it is driven. */
/* THE COLUMN SURVIVES THE COLLAPSE (OPERATOR SPEC, HUD v4.1 §1). payco-hud.js sets
   `body.hidden` on every collapsed dock, and for a rail whose shut width is 82px — sized in RAIL
   v2 so that one 72px tool fits with 5px of air each side — hiding it throws away the only thing
   the shut state is for. §1 asks for the icons centred in BOTH states, which is a claim about a
   column that is still drawn. The three docks that are not this rail keep the old behaviour.
   `display:flex` at (0,5,0) beats the UA sheet's `[hidden]{display:none}`, which is the same
   mechanism §2 uses on the viewports themselves and is why the attribute is left in place: it
   still says "collapsed" to anything reading the DOM. */
.pc-hud.pc-hud[data-hud="right"].pc-hud-collapsed .pc-hud-body,
.pc-hud.pc-hud[data-hud="right"] .pc-hud-body[hidden]{display:flex}

/* THE BAR IS ONE CONTROL AND IT IS VISIBLE NOW (OPERATOR SPEC §2, "reuse the .pc-hud-collapse
   seam, now visible, styled to the icon aesthetic").
   W10 hid this bar at opacity:0 in an 8px strip, because the stack's picture had no chrome in it
   and the contract's suite still had to find and click the node. A rail has room for its own
   control, so the node stops being invisible and becomes what it always was — the thing that opens
   and shuts the rail — drawn as one more icon button so the rail has ONE button vocabulary rather
   than a set of tools and a differently-shaped chevron above them. */
.pc-hud.pc-hud[data-hud="right"] .pc-hud-bar{
  position:static;
  min-height:0;
  height:auto;
  margin:0;
  /* CENTRED, LIKE EVERY OTHER MEMBER OF THE COLUMN (OPERATOR SPEC, HUD POLISH §3). It was
     `justify-content:flex-end` with 3px of side padding, which put the chevron's centre 20px
     right of the tools' centre on a 246px rail — the one control in the rail that did not share
     the column's centre line. In a one-column rail the chevron IS the top of the column, so it
     is centred by the same rule and the bottom padding is the tools' own gap: no dead band
     between the chevron and the first icon, which is what §3 asks for in as many words. */
  /* The same hairline compensation as the body's — the chevron is the top of the same column and
     shares its centre line, so it has to be centred against the same box. */
  padding:var(--pc-rail-gut) var(--pc-hair) var(--pc-rail-gut) 0;
  border:0;
  background:none;
  opacity:1;
  pointer-events:auto;
  display:flex;align-items:center;justify-content:center;
  overflow:visible;
  flex:none;
}
/* COLLAPSED THE BAR IS THE WHOLE RAIL, so it owes no gap to a body that is not drawn, and the
   11px it keeps on every side is what makes the shut state a square: 44 + 22 + 4 = 70 both ways. */
.pc-hud.pc-hud[data-hud="right"].pc-hud-collapsed .pc-hud-bar{
  padding-right:var(--pc-hair);
  /* STATED, NOT INHERITED — §2 gives every bar `min-height:var(--pc-bar-h)` (56px) for the
     captioned docks and it reaches here through the cascade. The strip's bar is the control plus
     the gutter it is centred in: 44 + 11 + 11 = 66. It sits at the TOP of the strip rather than
     in the middle of it, on the same line the chevron holds when the rail is open, so opening and
     shutting moves the width and nothing else. */
  height:calc(var(--pc-chev) + 22px);
  min-height:0;padding:0;flex:none;
  display:flex;align-items:center;justify-content:center}
/* THE CHEVRON WEARS THE TOOLS' SHELL. Same radius ratio, same hairline, same hover lift — at 34px
   rather than 72, because it is chrome and not a tool and the size is what says so. It keeps
   .pc-hud-btn, so §3a's "the rail's button is the site's button" still governs its paint and one
   restyle still reaches all of them. */
html body .pc-hud.pc-hud[data-hud="right"] .pc-hud-collapse{
  width:var(--pc-chev);height:var(--pc-chev);min-width:var(--pc-chev);
  min-height:var(--pc-chev);              /* or §3a's 44px floor wins on this axis alone */
  flex:none;
  border-radius:var(--pc-radius-sm);      /* 44/11 — the tools' 72/17 curve at the smaller size */
  padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  /* THE SAME MATERIAL AS THE TOOLS, NOT A PALE APPROXIMATION OF IT (OPERATOR SPEC, POLISH §3).
     This said `background:var(--pc-surface-3); color:var(--pc-accent)` — a near-white chip with a
     blue glyph — while the tools below it are 72px navy-gradient boxes with a 2.5px cyan edge, a
     cyan glyph and an inner glow. Rendered together they are two different components stacked in
     one column, which is the opposite of "styled as a sibling of the tool icons": in the light
     theme the chevron read as a piece of the rail's white surface rather than as a control at
     all, and in dark it was the only pale object in the stack.
     EVERY VALUE IS THE TOOLS' OWN TOKEN, so it is a sibling by construction and a restyle of the
     tools carries the chevron with it. The literals are those tokens' values from
     css/payco-hud-widgets.css:86-106, needed only where that sheet is not linked.
     THE ONE THING THAT IS NOT SHARED IS SIZE, and that is what says it is chrome: 44 against 72,
     with the radius scaled by the same ratio (17 x 44/72 = 10.4) so the corner curve is visibly
     the same curve rather than a second opinion about roundness. */
  /* THE FALLBACKS ARE THIS SHEET'S OWN TOKENS, not copies of lane 5's literals. Two reasons and
     both are rules already written down: §1 forbids a hardcoded hex in this file, and a literal
     here would be a SECOND OPINION about a colour that css/payco-hud-widgets.css already owns —
     the thing §1 exists to prevent. Where that sheet is linked its values win outright; where it
     is not, the chevron is still the deep accent and the cyan, which is the same material named
     in this file's vocabulary instead of that one's. */
  background:var(--pc-hud-tool-face,linear-gradient(160deg,var(--pc-accent-deep),var(--pc-accent)));
  color:var(--pc-hud-tool-ink,var(--pc-accent-cyan));
  border:2.5px solid var(--pc-hud-tool-edge,var(--pc-accent-cyan));
  border-radius:calc(var(--pc-hud-tool-radius,17px) * .61);
  box-shadow:var(--pc-hud-tool-shadow,var(--pc-shadow-lg));
}
/* THE CHEVRON ANSWERS THE POINTER THE WAY THE TOOLS DO (OPERATOR SPEC, HUD v4 §2) — same three
   tokens, same easing, so the rail has one hover vocabulary and not a tools one plus a chrome one.
   :focus-visible is included for the same reason it is on the tools: a keyboard user is pointing
   at it just as deliberately, and §3a's outline is a ring around the box rather than a state. */
html body .pc-hud.pc-hud[data-hud="right"] .pc-hud-collapse{
  transition:transform var(--pc-hud-hover-ease,var(--dur-fast,.16s) ease),
             box-shadow var(--pc-hud-hover-ease,var(--dur-fast,.16s) ease),
             border-color var(--pc-hud-hover-ease,var(--dur-fast,.16s) ease);
}
html body .pc-hud.pc-hud[data-hud="right"] .pc-hud-collapse:hover,
html body .pc-hud.pc-hud[data-hud="right"] .pc-hud-collapse:focus-visible{
  transform:var(--pc-hud-hover-lift,scale(1.03));
  border-color:var(--pc-hud-tool-edge-hot,var(--pc-accent-cyan));
  box-shadow:var(--pc-hud-hover-glow,var(--pc-shadow-lg));
}
@media (prefers-reduced-motion:reduce){
  html body .pc-hud.pc-hud[data-hud="right"] .pc-hud-collapse:hover,
  html body .pc-hud.pc-hud[data-hud="right"] .pc-hud-collapse:focus-visible{transform:none}
}

/* A BARE TOOL IS THE BUTTON AND NOTHING ELSE — kept verbatim from W10. The card, its head, its
   chevron and its badge frame all belonged to a widget that was a panel; in the rail the widget IS
   its control, and that is what makes "the existing 72px icons, not redesigned" true. */
.pc-hud.pc-hud[data-hud="right"] .pc-hud-w{
  background:none;border:0;border-radius:0;box-shadow:none;overflow:visible;
  width:auto;padding:0;margin:0;flex:none;
}
.pc-hud.pc-hud[data-hud="right"] .pc-hud-w-head{ display:none; }
.pc-hud.pc-hud[data-hud="right"] .pc-hud-w-body{
  padding:0;display:flex;align-items:center;justify-content:center;
}
/* NOTHING BUT THE TOOLS. A page that registers a page-function widget (a jump list, a progress
   meter, a home grid) put a PANEL in the rail, which is the duplication the operator asked to have
   gutted and which the rebuild removed. The rail draws bare tools; anything that is not one is not
   drawn. */
.pc-hud.pc-hud[data-hud="right"] .pc-hud-w:not(.pc-hud-w-bare){ display:none; }

/* ---- 12a. THE PUBLIC CORNER — PLAIN BUTTONS, NO RAIL (OPERATOR SPEC, HUD v3 §1) -------------
   payco-hud.js's mountCorner() builds this on a public page and on no other. Two switches, on the
   one vertical axis payco-assist.js's own pair already shares (24 + 112/2 = 80px from the right
   edge; 44 + 72/2 = 80px), stacked above whichever of those two is DRAWN — the offset is measured
   in fitCorner() and arrives as --pc-corner-bottom.
   56px and radius 13: 112/26, 72/17 and 56/13 are the same curve at three sizes, so the corner has
   one radius rather than three. `.pc-hud-btn` carries the paint, so these are the site's button
   (§3a) and not a fourth component. */
.pc-corner{
  position:fixed;
  /* THE AXIS IS READ, NOT RE-DERIVED (2026-09-12). This was `right:52px`, and the comment above it
     showed the arithmetic: the cluster's axis was 80px from the right edge, because Yolanda was
     right:24 on a 112px box and the reporter right:44 on a 72px box, and 52 + 28 lands a 56px
     button on the same 80.
     Every term in that sentence has since changed. The launcher is 64px and the reporter 56px, and
     BOTH now read --pc-corner-axis, which payco-hud.js:694 publishes as 56 on a public page
     (CORNER_BASE 24 + size 64 / 2). This rule kept its literal and stayed at 80 — so the two
     switches sat 24px inboard of the two controls they stack above, and the column of four was
     bent again, in the other direction. Measured at 1440 on hardware.html: bubble and reporter
     centred at x=1384, these two at x=1360.
     Derived from the same published axis as its neighbours, so there is no literal left in the
     cluster to drift. */
  right:calc(var(--pc-corner-axis,56px) - var(--pc-hud-tool,56px) / 2);
  bottom:var(--pc-corner-bottom,236px);
  z-index:9997;                  /* under payco-assist.js's pair (9998), over ordinary content */
  /* `column`, NOT `column-reverse`, AND THAT ONE WORD WAS SIX FAILING ASSERTIONS.
     payco-hud.js:1965 appends the hints switch and :1981 the theme switch, in that order, so
     under `column-reverse` the theme button PAINTED 58px above the button that precedes it in the
     DOM. A keyboard user tabbed hints then theme and saw theme then hints — WCAG 1.3.2, and
     tests/mobilewave2.mjs's "DOM order is reading order" measured exactly that on refer.html and
     partner-activate.html across six scenarios. The box does not move: the container is
     bottom-anchored with `bottom:` and no `top:`, its height is its content either way, and both
     buttons are the same size — only the order inside it changes. If the operator wants the theme
     switch on top, the fix is to swap those two appendChild calls in payco-hud.js so that reading
     order follows it; it is not to paint the column backwards. */
  display:flex;flex-direction:column;align-items:center;
  gap:14px;                      /* payco-assist.js:770's gap, so the column has one rhythm */
  pointer-events:none;
}
.pc-corner > *{pointer-events:auto}
html body .pc-corner .pc-corner-btn{
  /* Sized off the one cluster token, so these two, the reporter and the nine rail tools are one
     size by construction rather than by four matching literals. */
  width:var(--pc-hud-tool,56px);height:var(--pc-hud-tool,56px);min-width:var(--pc-hud-tool,56px);flex:none;
  border-radius:var(--pc-hud-tool-radius,14px);
  padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  /* A FLOATING CONTROL NEEDS AN EDGE; A RAIL BUTTON DOES NOT. §3a paints `.pc-hud-btn` on
     --pc-surface-3, which is right inside the rail because the rail is a card and the pale ground
     reads against it. These two sit on the PAGE — measured on pricing.html at 1440, that ground is
     the same near-white, and the two switches rendered as bare glyphs with no button under them.
     The surface, the hairline and the platform's own elevation are what every other floating
     control on this site already wears (payco-assist.js's pair included), so this is the corner's
     existing vocabulary rather than a fourth component. */
  background:var(--pc-surface);
  /* --pc-ink-mute, NOT --pc-line, AND THE DIFFERENCE IS A MEASUREMENT.
     tests/mobilewave2.mjs §5b scores every control's boundary at WCAG 1.4.11's 3:1 as
     max(border-vs-outside, fill-vs-outside). These two switches float on the page's own
     near-white, so the fill scores 1.0 and the whole boundary rests on the border — and
     --pc-line measures 1.29:1 on white. Nine assertions on refer.html and
     partner-activate.html named exactly `button#pc-corner-tips-btn 1.2:1` and
     `button#pc-corner-theme-btn 1.2:1`, and they are the only two controls on either page
     that failed. --pc-ink-mute is 4.99:1 on --pc-surface and 4.71:1 on the app ground, and
     it is a token this sheet already consumes, so nothing is invented. The rail's own
     buttons keep --pc-line: they sit INSIDE a card, where the card is the boundary.
     The hover state still moves the border to --pc-accent, so the resting and hovered
     edges stay two different colours and the switch has not lost its hover signal. */
  border:var(--pc-hair) solid var(--pc-ink-mute);
  box-shadow:var(--pc-shadow);
  color:var(--pc-accent);
}
html body .pc-corner .pc-corner-btn:hover{
  background:var(--pc-surface-2);
  border-color:var(--pc-accent);
  color:var(--pc-accent-hi);
  box-shadow:var(--pc-shadow-lg);
}
/* THE ON/OFF STATE IS VISIBLE, not only announced. The hints switch is a toggle and a toggle whose
   only "off" signal is aria-pressed is a toggle a sighted reader cannot read. Same treatment the
   rail's own tools use for pressed (css/payco-hud-widgets.css:379). */
html body .pc-corner[data-tips-state="off"] .pc-corner-tips,
html body .pc-corner[data-theme-state="dark"] .pc-corner-theme{
  background:var(--pc-accent-soft);border-color:var(--pc-accent);
}
.pc-corner .pc-corner-btn svg{width:24px;height:24px;display:block}
/* A page that yields its corner yields the switches with it — one attribute, one meaning, and it
   is payco-assist.js's declaration in §... see [data-pc-corner-yield] there. */
.pc-corner[data-pc-corner-yield]{display:none}
/* THE PHONE KEEPS THEM, SMALLER, ON THE SAME AXIS. payco-assist.js's own 560px query moves the bug
   button to right:32/bottom:98 at 48px, so the axis becomes 32 + 48/2 = 56px from the edge and the
   switches follow it. Still a 44px tap target with room to spare. */
@media(max-width:560px){
  .pc-corner{--pc-hud-tool:48px;--pc-hud-tool-radius:12px;gap:10px}
  
  .pc-corner .pc-corner-btn svg{width:22px;height:22px}
}


/* ---- 12b. WITHDRAWN. It hid every dock that carried no registerWidget() count, which on the
   four money consoles (disputes, verify-review, reconcile, outbox-console) is the LEFT taskbar —
   a static <nav data-hud="left" role="toolbar"> the PAGE draws and the HUD never registers into.
   Measured by tests/adminpagesc.mjs at 1280 and 1920: "the HUD taskbar is painted and has real
   width" went red on all four, and their content boxes stopped being centred, because the column
   they reserve was suddenly display:none. The operator's rule keeps those rails — "left rails
   return to standard section nav" — so an empty-dock rule that cannot tell a page's own nav from
   an unused viewport has no safe form and is not restated here. Empty docks were already handled
   before this task: payco-hud.js reveals a viewport when something goes into it. */

/* ---- 12c. THE HINTS TOGGLE ACTUALLY TOGGLES SOMETHING — DEFECT 5 ---------------------------
   payco-hud-widgets.js's tips tool has always written `data-pc-tips="off"` onto <html> and read
   it back, so the BUTTON worked perfectly: it stored the preference, it flipped aria-pressed, it
   restored the state on the next load. What it did not do was change anything a person could see,
   because nothing in this tree ever read the attribute — a grep for `data-pc-tips` across css/
   answered with the writer and no reader. That is the whole of defect 5: a switch wired to
   nothing.
   THIS IS THE READER. `.pc-tip` is the platform's one hint component (css/payco-hud.css §5,
   payco-hud.js upgrades every instance), so hiding it here turns off every hint on the page at
   once — which is what the control's own label promises. The rail's nine no longer emit one at
   all (W10 IR-2), so what this governs is the hints the PAGES draw, which is what a reader who
   turns hints off wants gone. */
html[data-pc-tips="off"] .pc-tip{ display:none !important; }
