/* T4b-1 (helper H47, 2026-10-14): THE SHARED CUSTOMER SHELL - styles for the chrome every customer page renders (customer/base.html and
   customer/homepage.html both include customer/_shell_chrome.html and customer/_shell_footer.html): the full-screen graph paper, the HUD
   bar, the floating draggable menu button and its menu, the first-visit hint, the footer with the real crawlable links, the skip link
   and the one orange focus ring. Ported from the owner-approved round-2 mockup (CC-Reports/T4b-mockups-r2/site/site.css, H42).
   Tokens only (webapp/static/tokens.css): the only literals are 0, 1, 100%, auto, angles, unitless ratios and the media-query
   breakpoints (CSS cannot read custom properties inside @media). Breakpoints: 760px (phone: no side rails, full-screen menu),
   960px (footer grid), 480px (the stacked wordmark).
   SCOPE RULE: this file is loaded on EVERY customer page, including the pages T4b-1 does not redesign (the quote flow, legal, guides),
   so it styles ONLY elements that carry a shell class, plus html and body.shell. It sets no global a / h1-h3 / p / img rule: those
   belong to site-pages.css (the redesigned pages) and customer.css (the rest). The consent sheet (#qfab-consent) is styled ONLY by the
   hologram block at the end of this file (Legal 2026-10-14 section 6), on its existing ids and classes, under body.shell.
   Glass: FLAT everywhere (round-2 NOTES "Recommendation for the build": one code path, no backdrop-filter fill-rate risk). */

/* ------------------------------------------------------------------ the dark graph paper, edge to edge, every page.
   H72 (owner R3-6): the grid STAYS STILL on every page; only the holograms and the content scroll over it. It is a position: fixed
   LAYER (body.shell::before, z-index -1 in the root stacking context: above the root's void colour, under every box of the page),
   never background-attachment: fixed (broken on iOS Safari, and H43 measured 57-67 ms frames with it; round-2 NOTES). The layer is
   static paint on its own compositor layer (will-change: transform), so a scroll moves the content over it and repaints nothing; it
   is sized to the LARGE viewport (100lvh, 100vh where lvh is unknown), so a phone's collapsing toolbar never uncovers a strip. The
   root keeps the void colour (the same colour as the paper between its lines), so the page reads the same if the layer is not drawn.
   No animation: nothing here moves by itself (reduced motion has nothing to stop). Contrast: the paper is unchanged (the same lines
   and colours), so every text-on-glass ratio in tokens.css holds. */
*, *::before, *::after { box-sizing: border-box; }
html {
  background-color: var(--c-void); color-scheme: dark;
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
}
body.shell {
  margin: 0; min-height: 100vh; background-color: transparent; color: var(--c-on-glass-2);
  font-family: var(--font-sans); font-size: var(--fs-body); line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}
body.shell::before {
  content: ""; position: fixed; z-index: -1; top: 0; left: 0; width: 100%; height: 100vh; height: 100lvh; pointer-events: none;
  background-color: var(--c-void);
  background-image:
    linear-gradient(var(--c-grid-major) var(--bw-1), transparent var(--bw-1)),
    linear-gradient(90deg, var(--c-grid-major) var(--bw-1), transparent var(--bw-1)),
    linear-gradient(var(--c-grid-minor) var(--bw-1), transparent var(--bw-1)),
    linear-gradient(90deg, var(--c-grid-minor) var(--bw-1), transparent var(--bw-1));
  background-size: var(--grid-major) var(--grid-major), var(--grid-major) var(--grid-major), var(--grid-minor) var(--grid-minor), var(--grid-minor) var(--grid-minor);
  background-position: -1px -1px;
  will-change: transform;
}
/* in-page anchors land below the sticky HUD bar (desktop) */
@media (min-width: 761px) { .shell [id] { scroll-margin-top: calc(var(--h-header) + var(--s-4)); } }

/* one orange focus ring for every control (the tint: >= 5.2:1 against the void and every glass composite). The consent sheet keeps
   its own (brand.css, higher specificity); the light legacy sheet switches to the deeper orange (customer.css). */
.shell :focus { outline: none; }
.shell :focus-visible { outline: var(--focus-width) solid var(--c-focus-on-dark); outline-offset: var(--focus-offset); }

/* the side rails: on desktop no content ever enters the outer rail (--rail, 88 px since H56), which is where the menu button docks */
.wrap { --pad: var(--gutter); width: 100%; max-width: calc(var(--w-max) + 2 * var(--pad)); margin-inline: auto; padding-inline: var(--pad); }
@media (min-width: 761px) { .wrap { --pad: calc(var(--rail) + var(--s-3)); } }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.svg-symbols { position: absolute; width: 0; height: 0; overflow: hidden; }
.skip-link {
  position: absolute; left: var(--s-4); top: var(--s-2); z-index: var(--z-skip);
  min-height: var(--tap-min); display: inline-flex; align-items: center; padding-inline: var(--s-4);
  background: var(--c-glass-menu); color: var(--c-on-glass); border: var(--bw-1) solid var(--c-holo-edge-strong);
  font-family: var(--font-mono); font-size: var(--fs-small); border-radius: var(--r-1); transform: translateY(-200%);
  transition: transform var(--d-spring-snap) var(--ease-spring-snap);
}
.skip-link:focus-visible { transform: translateY(0); color: var(--c-on-glass); }

/* TEST MODE bar (both shells; the wording is each shell's existing string) */
.testbar {
  padding: var(--s-2) 0; background-color: var(--c-glass-menu); border-bottom: var(--bw-1) solid var(--c-holo-edge-soft);
  font-family: var(--font-mono); font-size: var(--fs-label); line-height: var(--lh-snug); color: var(--c-on-glass-2);
}
.testbar .wrap { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-3); align-items: baseline; }
.testbar b { color: var(--c-orange-tint); font-weight: var(--fw-medium); }

/* ------------------------------------------------------------------ the HUD bar (top): the wordmark only; no "Get a quote" */
.hud-bar {
  position: sticky; top: 0; z-index: var(--z-header);
  background-color: var(--c-glass-flat); border-bottom: var(--bw-1) solid var(--c-holo-edge-soft);
}
.hud-bar__row { display: flex; align-items: center; gap: var(--s-4); min-height: var(--h-header); }
.nojs-menu { display: none; }
html:not(.js) .nojs-menu {
  display: inline-flex; align-items: center; min-height: var(--tap-min); padding-inline: var(--s-3); margin-left: auto;
  font-family: var(--font-mono); font-size: var(--fs-small); color: var(--c-orange-on-glass);
}
@media (max-width: 760px) {
  /* phones: the bar scrolls away with the page (the menu button lives in the thumb zone instead) */
  .hud-bar { position: relative; }
}

.wordmark {
  display: inline-flex; align-items: center; gap: var(--s-3); min-height: var(--tap-min);
  text-decoration: none; color: var(--c-on-glass); border-radius: var(--r-1);
}
.wordmark:hover, .wordmark:active { color: var(--c-on-glass); text-decoration: none; }
.wordmark__mark { display: block; width: var(--mark-header); height: var(--mark-header); flex: none; stroke: var(--c-orange-tint); fill: none; }
.wordmark__text { font-weight: var(--fw-semibold); font-size: var(--fs-body); letter-spacing: var(--ls-wordmark); white-space: nowrap; }
.wordmark__labs { color: var(--c-on-glass-muted); font-weight: var(--fw-medium); }
.wordmark--footer .wordmark__mark { width: var(--mark-footer); height: var(--mark-footer); }
/* choice 5: the stacked FABRICATION / LABS wordmark on phones */
@media (max-width: 480px) {
  .hud-bar .wordmark { gap: var(--s-2); }
  .hud-bar .wordmark__text { display: flex; flex-direction: column; font-size: var(--fs-label); line-height: var(--lh-snug); }
}

/* ------------------------------------------------------------------ the floating menu button (desktop and phone) */
.fab { display: none; }
.js .fab { display: block; }
.fab__button {
  position: fixed; left: 0; top: 0; z-index: var(--z-fab);
  translate: var(--fab-x, 0) var(--fab-y, 0);
  width: var(--fab-size); height: var(--fab-size); padding: 0; margin: 0;
  display: grid; place-items: center; align-content: center; gap: var(--s-1);
  /* H56 (owner M3): the cookie pop-up's button style (the hologram block's .cta below): the 14% orange wash, a crisp orange-tint
     border, the r-1 corners, the sans semibold label; on hover the void with the strong glow and the lift, pressed the void and the
     press. The wash sits over the OPAQUE menu glass, as the pop-up's own background does, so page text never shows through. */
  color: var(--c-on-glass);
  background: linear-gradient(var(--c-glass-hover), var(--c-glass-hover)), var(--c-glass-menu);
  border: var(--bw-1) solid var(--c-orange-tint); border-radius: var(--r-1);
  box-shadow: var(--glow-1), var(--shadow-glass);
  font-family: var(--font-sans); font-size: var(--fs-small); font-weight: var(--fw-semibold); letter-spacing: 0;
  cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent;
  opacity: 0;
  /* the snap: the settle spring moves it to the edge on release; zero under reduced motion (tokens) */
  transition:
    translate var(--d-spring-settle) var(--ease-spring-settle),
    transform var(--d-spring-snap) var(--ease-spring-snap),
    scale var(--d-spring-snap) var(--ease-spring-snap),
    box-shadow var(--d-spring-snap) var(--ease-spring-snap),
    background var(--d-spring-snap) var(--ease-spring-snap);
}
.fab-ready .fab__button { opacity: 1; }
/* no transition until the first coordinates are in (no slide-in from 0,0) */
html:not(.fab-ready) .fab__button, html:not(.fab-ready) .fab-hint, html:not(.fab-ready) .site-menu { transition: none; }
.fab__button:hover { background: var(--c-void); box-shadow: var(--glow-2), var(--shadow-glass); transform: translateY(var(--lift-hover)); }
.fab__button:active { background: var(--c-void); box-shadow: var(--shadow-glass); transform: translateY(var(--press-shift)) scale(var(--press-scale)); cursor: grabbing; }
.fab__button[aria-expanded="true"] { background: var(--c-void); box-shadow: var(--glow-2), var(--shadow-glass); }
.fab__button:focus-visible { outline: var(--focus-width) solid var(--c-focus-on-dark); outline-offset: var(--focus-offset); box-shadow: var(--glow-2), var(--shadow-glass); }
.fab.is-dragging .fab__button { transition: none; cursor: grabbing; scale: 1.06; transform: none; background: var(--c-void); box-shadow: var(--glow-2), var(--shadow-glass); }
/* the drag came within --fab-snap of an edge: the button has already snapped there (site-menu.js); the release keeps that edge */
.fab.is-dragging.is-snapped .fab__button { scale: 1; }
.fab__icon { display: block; width: var(--s-6); height: var(--s-6); stroke: var(--c-orange-tint); fill: none; stroke-width: 2; }
.fab__icon line { transition: transform var(--d-spring-settle) var(--ease-spring-settle), opacity var(--d-fast) var(--ease-standard); transform-origin: center; transform-box: fill-box; }
.fab__button[aria-expanded="true"] .fab__icon .l1 { transform: translateY(var(--s-1)) rotate(45deg) scaleX(1.25); }
.fab__button[aria-expanded="true"] .fab__icon .l2 { opacity: 0; }
.fab__button[aria-expanded="true"] .fab__icon .l3 { transform: translateY(calc(-1 * var(--s-1))) rotate(-45deg) scaleX(1.25); }
.fab__text { font-size: var(--fs-small); line-height: 1; color: var(--c-on-glass); }
@media (max-width: 760px) { .fab__icon { width: var(--s-5); height: var(--s-5); } }

/* the first-visit hint (removed after the first interaction) */
.fab-hint {
  /* H56 (owner M1): smaller - narrower (224 px, was 272), tighter padding, the label type size, the quieter glow */
  position: fixed; left: 0; top: 0; z-index: var(--z-fab-hint); width: calc(var(--menu-w) - var(--s-9));
  translate: var(--hint-x, 0) var(--hint-y, 0);
  padding: var(--s-2) var(--s-3); display: grid; gap: var(--s-1); justify-items: start;
  background-color: var(--c-glass-menu); border: var(--bw-1) solid var(--c-holo-edge-strong); border-radius: var(--r-2);
  box-shadow: var(--glow-1), var(--shadow-glass); font-size: var(--fs-label); color: var(--c-on-glass);
  opacity: 0; transition: opacity var(--d-base) var(--ease-standard), translate var(--d-spring-settle) var(--ease-spring-settle);
}
.fab-ready .fab-hint { opacity: 1; }
.fab-hint[hidden] { display: none; }
.fab-hint p { margin: 0; line-height: var(--lh-snug); }
.fab-hint__label {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: var(--fw-medium);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--c-orange-tint);
}
.fab-hint__ok {
  display: inline-flex; align-items: center; justify-content: center; min-height: var(--tap-min); min-width: var(--tap-min); margin: 0;
  padding: var(--s-1) var(--s-3); font-family: var(--font-sans); font-size: var(--fs-label); font-weight: var(--fw-semibold); line-height: var(--lh-snug);
  color: var(--c-on-glass); background: transparent; border: var(--bw-1) solid var(--c-holo-edge); border-radius: var(--r-1); cursor: pointer;
  transition: background-color var(--d-fast) var(--ease-standard), border-color var(--d-fast) var(--ease-standard), transform var(--d-spring-snap) var(--ease-spring-snap);
}
.fab-hint__ok:hover { background-color: var(--c-glass-hover); border-color: var(--c-holo-edge-strong); }
.fab-hint__ok:active { background-color: var(--c-glass-press); transform: translateY(var(--press-shift)) scale(var(--press-scale)); }
.fab.is-dragging ~ .fab-hint { transition: none; }

/* the holographic menu: desktop = a panel docked beside the button */
.site-menu {
  position: fixed; left: 0; top: 0; z-index: var(--z-fab-menu); width: var(--menu-w);
  translate: var(--menu-x, 0) var(--menu-y, 0);
  padding: var(--s-4); display: grid; gap: var(--s-4);
  background-color: var(--c-glass-menu); background-image: linear-gradient(180deg, var(--c-glass-tint), transparent 45%);
  border: var(--bw-1) solid var(--c-holo-edge-strong); border-radius: var(--r-2);
  box-shadow: var(--glow-2), var(--shadow-glass); color: var(--c-on-glass-2);
  visibility: hidden; opacity: 0; scale: .96; clip-path: inset(0 0 100% 0 round var(--r-2));
  transition: opacity var(--d-fast) var(--ease-standard), scale var(--d-spring-settle) var(--ease-spring-settle),
    clip-path var(--d-spring-settle) var(--ease-spring-settle), visibility 0s linear var(--d-spring-settle);
}
/* without JS the menu panel never shows: the footer nav carries the same links (the HUD bar's "Menu" link jumps there) */
html:not(.js) .site-menu { display: none; }
.site-menu[data-from="left"] { transform-origin: left top; }
.site-menu[data-from="right"] { transform-origin: right top; }
.site-menu[data-from="top"] { transform-origin: center top; }
.site-menu.is-open {
  visibility: visible; opacity: 1; scale: 1; clip-path: inset(0 0 0 0 round var(--r-2));
  transition: opacity var(--d-fast) var(--ease-standard), scale var(--d-spring-settle) var(--ease-spring-settle),
    clip-path var(--d-spring-settle) var(--ease-spring-settle), visibility 0s;
}
.site-menu__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding-bottom: var(--s-3); border-bottom: var(--bw-1) solid var(--c-holo-rule); }
.site-menu__head .wordmark { display: none; }
.site-menu__title {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: var(--fw-medium);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--c-orange-tint);
}
.site-menu__list { list-style: none; padding: 0; margin: 0; display: grid; }
.site-menu__list li + li { border-top: var(--bw-1) solid var(--c-holo-rule); }
.site-menu__link {
  position: relative; display: flex; align-items: center; gap: var(--s-3); min-height: calc(var(--tap-min) + var(--s-2)); padding-inline: var(--s-2);
  font-family: var(--font-mono); font-size: var(--fs-body); color: var(--c-on-glass); text-decoration: none; border-radius: var(--r-1);
  transition: background-color var(--d-fast) var(--ease-standard), color var(--d-fast) var(--ease-standard), padding var(--d-spring-base) var(--ease-spring-base);
}
.site-menu__idx { font-size: var(--fs-label); color: var(--c-orange-tint); }
.site-menu__link::after { content: "\2192"; margin-left: auto; color: var(--c-orange-tint); opacity: 0; translate: calc(-1 * var(--s-2)) 0; transition: opacity var(--d-fast) var(--ease-standard), translate var(--d-spring-base) var(--ease-spring-base); }
.site-menu__link:hover { background-color: var(--c-glass-hover); color: var(--c-on-glass); padding-left: var(--s-3); }
.site-menu__link:hover::after, .site-menu__link:focus-visible::after { opacity: 1; translate: 0 0; }
.site-menu__link:active { background-color: var(--c-glass-press); }
.site-menu__link[aria-current="page"] { color: var(--c-orange-on-glass); }
.site-menu__link[aria-current="page"] .site-menu__idx::before { content: "\25CF  "; }

@media (max-width: 760px) {
  /* phones: round 1's full-screen menu ("Perfect"), restyled as a hologram. The button stays on top as the Close control. */
  .site-menu {
    inset: 0; width: auto; border-radius: 0; border-width: 0; scale: 1;
    padding: var(--s-4) var(--gutter) calc(var(--fab-size) + var(--s-7));
    align-content: start; overflow-y: auto; overscroll-behavior: contain;
    translate: 0 var(--menu-shift); clip-path: none;
  }
  .site-menu.is-open { translate: 0 0; clip-path: none; }
  .site-menu__head { min-height: calc(var(--h-header) - var(--s-4)); }
  .site-menu__head .wordmark { display: inline-flex; gap: var(--s-2); }
  .site-menu__head .wordmark__text { display: flex; flex-direction: column; font-size: var(--fs-label); line-height: var(--lh-snug); }
  .site-menu__link { min-height: calc(var(--tap-min) + var(--s-2)); padding-inline: var(--s-1); }
  .menu-open { overflow: hidden; }
}

/* ------------------------------------------------------------------ the footer: the REAL crawlable links (the same five as the menu,
   then the columns), on every customer page */
.site-footer {
  margin-top: var(--section-y); padding-block: var(--s-7) var(--s-6); font-size: var(--fs-small); line-height: var(--lh-body);
  color: var(--c-on-glass-2); border-top: var(--bw-1) solid var(--c-holo-edge-soft); background-color: var(--c-glass-flat);
}
.site-footer p { margin: 0; }
.site-footer__main { margin-bottom: var(--s-6); padding-bottom: var(--s-5); border-bottom: var(--bw-1) solid var(--c-holo-rule); }
.footer-main { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 0 var(--s-6); }
.footer-main a {
  display: inline-flex; align-items: center; min-height: var(--tap-min); font-family: var(--font-mono); font-size: var(--fs-body);
  color: var(--c-on-glass); text-decoration: none; transition: color var(--d-fast) var(--ease-standard);
}
.footer-main a:hover { color: var(--c-orange-on-glass); text-decoration: underline; }
.footer-main a:active, .footer-main a[aria-current="page"] { color: var(--c-orange-on-glass); }
.site-footer__grid { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: var(--s-6); }
.site-footer__brand p { margin-top: var(--s-4); max-width: 32ch; }
.site-footer__brand a:not(.wordmark) { color: var(--c-orange-on-glass); }
.site-footer__brand a:not(.wordmark):hover { color: var(--c-on-glass); }
.site-footer__heading {
  margin: 0 0 var(--s-2); font-family: var(--font-mono); font-size: var(--fs-label); font-weight: var(--fw-medium); line-height: var(--lh-snug);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--c-on-glass-muted);
}
.footer-links { list-style: none; padding: 0; margin: 0; }
.footer-links a {
  display: flex; align-items: center; min-height: var(--tap-min); color: var(--c-on-glass-2); text-decoration: none;
  transition: color var(--d-fast) var(--ease-standard), transform var(--d-spring-base) var(--ease-spring-base);
}
.footer-links a:hover { color: var(--c-orange-on-glass); text-decoration: underline; transform: translateX(var(--s-1)); }
.footer-links a:active { color: var(--c-on-glass); }
.footer-links a[aria-current="page"] { color: var(--c-on-glass); }
.site-footer__legal { margin-top: var(--s-6); padding-top: var(--s-5); border-top: var(--bw-1) solid var(--c-holo-rule); font-family: var(--font-mono); font-size: var(--fs-label); line-height: var(--lh-body); color: var(--c-on-glass-muted); }
@media (max-width: 960px) { .site-footer__grid { grid-template-columns: 1fr 1fr; } .site-footer__brand { grid-column: 1 / -1; } }
@media (max-width: 760px) { .site-footer { padding-bottom: calc(var(--fab-size) + var(--s-7)); } }
@media (max-width: 480px) { .site-footer__grid { grid-template-columns: 1fr; gap: var(--s-5); } }

/* ------------------------------------------------------------------ the consent lines on the dark paper. The sheet's two IN-FLOW lines
   ("Cookie choices" and the GPC line) are drawn by brand.css in graphite text with no background - on the dark paper that would fail
   contrast. T4b-2 (H78, owner round 4: the light rounded box on the dark page): they are now the FOOTER'S LAST ROW, themed like the
   footer's own legal line - full width, aligned with the footer's content, the mono label type, a hairline rule above - on an OPAQUE
   backing (--c-glass-menu, the footer glass's opaque twin: the in-flow contrast check needs a solid background): the link #CDD1D6 on
   #181310 and the GPC line #A4AAB2 on #181310 both pass AA by a wide margin (tools/t4b1/equal-prominence.mjs measures them). The TA's
   consent rules are untouched: the link stays a real link with brand.css's 44 px target and its handler (consent.js), the sheet and
   Accept / Decline (the hologram block below) are not restyled here, and this rule names no button. On a phone the row moves up into the
   footer's menu-button clearance and keeps that clearance under itself. */
body.shell > #qfab-consent ~ p.hint, body.shell > p.hint.consent-gpc {
  max-width: none; margin: 0; padding: var(--s-2) var(--gutter) var(--s-6);
  background-color: var(--c-glass-menu); border-top: var(--bw-1) solid var(--c-holo-rule);
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: var(--fw-regular); line-height: var(--lh-body); color: var(--c-on-glass-muted);
}
@media (min-width: 761px) {
  body.shell > #qfab-consent ~ p.hint, body.shell > p.hint.consent-gpc {
    padding-inline: max(calc(var(--rail) + var(--s-3)), calc((100% - var(--w-max)) / 2));
  }
}
@media (max-width: 760px) {
  body.shell > #qfab-consent ~ p.hint, body.shell > p.hint.consent-gpc {
    margin-top: calc(var(--s-5) - var(--fab-size) - var(--s-7)); padding-bottom: calc(var(--fab-size) + var(--s-7));
  }
}
body.shell > #qfab-consent ~ p.hint a {
  color: var(--c-on-glass-2); text-decoration-color: var(--c-orange-tint); text-decoration-thickness: var(--bw-1); text-underline-offset: 0.25em;
  transition: color var(--d-fast) var(--ease-standard);
}
body.shell > #qfab-consent ~ p.hint a:hover { color: var(--c-orange-on-glass); text-decoration-color: currentColor; }

/* ------------------------------------------------------------------ the HOLOGRAM consent sheet (helper H53; Legal 2026-10-14 section 6:
   "the hologram variant may ride the T4b-1 build as a pure restyle of the already-approved floating sheet"; PM 16:11Z acceptance).
   The round-2 mockup's banner/banner.css, ported as a STYLESHEET-ONLY restyle of the approved Q1 sheet:
   - it styles the partial's EXISTING ids and classes (#qfab-consent, h2, p, .consent-actions, .cta, .hint) under body.shell (the T4b-1
     shells), so its rules out-rank brand.css's by specificity; partials/consent_banner.html, brand/brand.css and consent.js are
     byte-unchanged (tests/test_t4b1_hologram.py pins them), and nothing here needs a CSP change (no url(), no inline style);
   - Accept and Decline: ONE rule for both (the shared .cta class; no rule names a data-action or a position), in two equal grid tracks
     at every width, so the two boxes, fonts, fills, borders and glows are identical at rest, on hover and on focus;
   - no close control and no overlay: only a choice dismisses it (consent.js); the [hidden] state is brand.css's (no display here);
   - reduced motion: the pop and the scan line exist ONLY under prefers-reduced-motion: no-preference; the hover lift and the
     transitions read the motion tokens, which tokens.css zeroes under reduce. The glow is a hover/focus STATE, never a pulse;
   - the mockup's two new fills (--q-holo-glass-raised / -sunk) are not T4b-1 tokens: the buttons use the shell's own glass tokens
     (rest: the 14% orange wash over the opaque menu glass; hover / press: the void). Every text contrast is computed in the harness
     from the rendered colours (tools/t4b1/equal-prominence.mjs).
   - the mockup's corner brackets were a ::before outside the box; the sheet scrolls (brand.css overflow-y: auto) and would clip it, so
     the same eight 2 px arms are background layers on the border box instead (they stay at the corners when the sheet scrolls). */
body.shell > #qfab-consent {
  margin: 0; max-width: none; padding: var(--s-4);
  color: var(--c-on-glass);
  background:
    linear-gradient(var(--c-orange-tint), var(--c-orange-tint)) left top / var(--bracket) var(--bw-2) no-repeat border-box,
    linear-gradient(var(--c-orange-tint), var(--c-orange-tint)) left top / var(--bw-2) var(--bracket) no-repeat border-box,
    linear-gradient(var(--c-orange-tint), var(--c-orange-tint)) right top / var(--bracket) var(--bw-2) no-repeat border-box,
    linear-gradient(var(--c-orange-tint), var(--c-orange-tint)) right top / var(--bw-2) var(--bracket) no-repeat border-box,
    linear-gradient(var(--c-orange-tint), var(--c-orange-tint)) left bottom / var(--bracket) var(--bw-2) no-repeat border-box,
    linear-gradient(var(--c-orange-tint), var(--c-orange-tint)) left bottom / var(--bw-2) var(--bracket) no-repeat border-box,
    linear-gradient(var(--c-orange-tint), var(--c-orange-tint)) right bottom / var(--bracket) var(--bw-2) no-repeat border-box,
    linear-gradient(var(--c-orange-tint), var(--c-orange-tint)) right bottom / var(--bw-2) var(--bracket) no-repeat border-box,
    var(--c-glass-menu);
  border: var(--bw-1) solid var(--c-holo-edge); border-radius: var(--r-1);
  box-shadow: var(--glow-1), var(--shadow-glass);
  font-family: var(--font-sans); font-size: var(--fs-body); font-weight: var(--fw-medium); line-height: var(--lh-body);
}
body.shell > #qfab-consent h2 {
  margin: 0 0 var(--s-2); padding-bottom: var(--s-2); border-bottom: var(--bw-1) solid var(--c-holo-edge);
  font-family: var(--font-sans); font-size: var(--fs-body); font-weight: var(--fw-semibold); line-height: var(--lh-snug); letter-spacing: 0;
  color: var(--c-on-glass);
}
body.shell > #qfab-consent p { margin: 0 0 var(--s-3); font-size: var(--fs-label); line-height: 1.5; color: var(--c-on-glass-2); }
body.shell > #qfab-consent .hint { margin: 0; font-size: var(--fs-label); color: var(--c-on-glass-muted); }
/* the two choices: one rule, two equal tracks at EVERY width (brand.css's 11rem tracks above 640 px are replaced, not kept) */
body.shell > #qfab-consent .consent-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); margin: 0 0 var(--s-3); }
body.shell > #qfab-consent .consent-actions .cta {
  display: inline-flex; align-items: center; justify-content: center;
  width: 100%; min-width: var(--tap-min); min-height: var(--tap-min); margin: 0; padding: var(--s-2) var(--s-4);
  background: var(--c-glass-hover); color: var(--c-on-glass); border: var(--bw-1) solid var(--c-orange-tint); border-radius: var(--r-1);
  box-shadow: none; transform: none;
  font-family: var(--font-sans); font-size: var(--fs-body); font-weight: var(--fw-semibold); line-height: 1.2; letter-spacing: 0; cursor: pointer;
  transition: background-color var(--d-spring-snap) var(--ease-spring-snap), box-shadow var(--d-spring-snap) var(--ease-spring-snap),
    transform var(--d-spring-snap) var(--ease-spring-snap);
}
body.shell > #qfab-consent .consent-actions .cta:hover {
  background: var(--c-void); color: var(--c-on-glass); border-color: var(--c-orange-tint);
  box-shadow: var(--glow-2); transform: translateY(var(--lift-hover));
}
body.shell > #qfab-consent .consent-actions .cta:active {
  background: var(--c-void); color: var(--c-on-glass); border-color: var(--c-orange-tint);
  box-shadow: none; transform: translateY(var(--press-shift)) scale(var(--press-scale));
}
body.shell > #qfab-consent .consent-actions .cta:focus-visible { outline: var(--focus-width) solid var(--c-focus-on-dark); outline-offset: var(--focus-offset); }
body.shell > #qfab-consent .consent-actions .cta:focus:not(:focus-visible) { outline: none; }
/* wider than a phone: the mockup's pop-up, bottom right, 480 px (its 30rem) inside the page gutter. brand.css caps the sheet's height
   at --consent-reserve and the body reserves that same cap while the sheet shows; the pop-up is narrower than brand.css's 760 px sheet
   and so taller, so the shell raises the cap (sheet and reservation together: brand.css reads the one custom property for both). */
@media (min-width: 561px) {
  body.shell > #qfab-consent {
    left: auto; right: var(--s-5); bottom: var(--s-5); width: min(calc(5 * var(--s-9)), calc(100vw - 2 * var(--gutter)));
    padding: var(--s-5);
  }
  body.shell > #qfab-consent h2 { font-size: var(--fs-h3); }
  body.shell > #qfab-consent p { font-size: var(--fs-small); }
  body.shell > #qfab-consent .hint { font-size: var(--fs-label); }
}
@media (min-width: 640px) { body.shell { --consent-reserve: min(60vh, 440px); } }
/* the pop: the sheet projects in (the settle spring) while a scan line sweeps it once - on arrival and on reopen (the [hidden]
   attribute coming off restarts it). Under reduced motion neither rule exists. */
@media (prefers-reduced-motion: no-preference) {
  body.shell > #qfab-consent:not([hidden]) { animation: qfab-holo-pop var(--d-spring-settle) var(--ease-spring-settle) both; }
  body.shell > #qfab-consent:not([hidden])::after {
    content: ""; position: absolute; left: 0; right: 0; top: 0; height: var(--bw-2); background: var(--c-holo-edge); pointer-events: none;
    animation: qfab-holo-scan var(--d-slow) var(--ease-standard) both;
  }
}
@keyframes qfab-holo-pop {
  from { opacity: 0; transform: translateY(calc(var(--s-2) + var(--bw-2))) scale(.96); box-shadow: var(--glow-2), var(--shadow-glass); }
  to { opacity: 1; transform: none; }
}
@keyframes qfab-holo-scan { from { top: 0; opacity: 1; } to { top: calc(100% - var(--bw-2)); opacity: 0; } }

/* ------------------------------------------------------------------ reduced motion: belt and braces on top of the zeroed tokens.
   ALL motion off: transitions (including the drag snap and the menu reveal), animations, smooth scrolling. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0s !important; transition-delay: 0s !important; animation-duration: 0s !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; }
  .fab.is-dragging .fab__button { scale: 1; }
  .fab__button:hover, .fab__button:active { transform: none; }
}
