/* COPIED FROM ANTSOFT. Do not edit here.
   Source: E:ntsoft\css/components.css (design blueprint artifact c62c59c9).
   This is the shared UCI OIT design system: same tokens, same components,
   so this app and AntSoft read as one product. App-specific rules belong in
   styles.css, which loads after this. Re-copy from AntSoft when it changes.
   Copied 2026-08-25. */
/* ============================================================================
   AntSoft component library — extracted from the blueprint (artifact c62c59c9).
   Every class here is charter-compliant: AAA body contrast, 44px+ targets,
   labeled state (never color alone), reduced-motion safe, fluid at every width.
   ========================================================================== */
* { box-sizing: border-box; }
/* The hidden attribute ALWAYS wins — author display rules (e.g. .terms-row{display:flex})
   must never resurrect an element JS hid. (Bug: admin-only rows showing for everyone.) */
[hidden] { display: none !important; }
html { font-size: calc(1.125rem * var(--scale)); scroll-behavior: smooth; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: var(--sans); line-height: 1.6; -webkit-text-size-adjust: 100%;
  min-height: 100dvh;
}
img { max-width: 100%; height: auto; }
a { color: var(--link); text-underline-offset: .15em; }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible {
  outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 4px;
}
.skip { position: absolute; left: -9999px; top: 0; background: var(--gold); color: #3a2c00;
  font-weight: 800; padding: .8rem 1.2rem; border-radius: 0 0 .6rem 0; z-index: 200; }
.skip:focus { left: 0; }
/* One width for the whole page, chrome included. The header, the impersonation banner
   and the footer used to be capped at 72rem while main.wrap was 62rem, so the wordmark
   sat 5rem to the left of the heading beneath it and the header read as off centre.
   :has() lets the chrome follow a wide main without either knowing about the other. */
:root { --page-max: 70rem; }
:root:has(main.wrap.wide) { --page-max: 84rem; }
.wrap { max-width: var(--page-max); margin: 0 auto; padding: 0 1rem 4rem; }
.mono { font-family: var(--mono); font-size: .9em; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---- header ---- */
.hdr { position: sticky; top: 0; z-index: 50; background: var(--surface);
  border-bottom: 3px solid var(--gold); }

/* the site voice: display face on headings + brand + product names, body stays system */
h1, h2, h3, .brand > span { font-family: var(--display); letter-spacing: -.012em; }
/* admin impersonation / persona-preview banner — state carried by icon + border, never color alone */
.imp-banner { display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  flex-wrap: wrap; max-width: var(--page-max); margin: 0 auto; padding: .6rem 1rem;
  background: var(--warn-bg, #f8f1d8); color: var(--warn-ink, #6d5200);
  border: 2px solid var(--warn-ink, #6d5200); border-top: none;
  border-radius: 0 0 var(--r-sm) var(--r-sm); font-size: .9rem; }
.imp-banner strong { font-weight: 800; }
.imp-banner .btn.plain { min-height: 2.5rem; }
:root[data-theme="dark"] .imp-banner { background: #241f10; color: #ecca5e; border-color: #ecca5e; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .imp-banner {
  background: #241f10; color: #ecca5e; border-color: #ecca5e; } }
.hdr-in { max-width: var(--page-max); margin: 0 auto; display: flex; align-items: center; gap: .7rem;
  padding: .6rem 1rem; flex-wrap: wrap; }
.brand { display: flex; align-items: center; gap: .5rem; text-decoration: none; color: var(--ink); }
.brand .peter { width: 2rem; height: 2rem; border-radius: 50%; background: var(--hero-grad);
  display: flex; align-items: center; justify-content: center; color: var(--gold); font-size: .95rem; flex: none; }
.brand b { font-size: 1.05rem; color: var(--blue); }
.brand span { font-size: .78rem; color: var(--muted); }
.hdr-sp { flex: 1; }
/* Tabs. This was one bordered oval wrapping every item, which suits two and looks like a
   stretched lozenge at four. The current page is marked three ways: heavier weight, a 3px
   underline, and colour, so it never depends on colour alone. */
.seg { display: inline-flex; gap: .1rem; align-items: stretch; }
.seg a, .seg button { border: none; background: none; cursor: pointer;
  padding: .5rem .85rem; color: var(--muted); font-weight: 600; font-size: .84rem;
  text-decoration: none; min-height: 2.75rem;
  display: inline-flex; align-items: center; gap: .35rem;
  border-bottom: 3px solid transparent; border-radius: var(--r-sm) var(--r-sm) 0 0;
  white-space: nowrap; }
.seg a:hover, .seg button:hover { color: var(--ink); background: var(--surface-2);
  border-bottom-color: var(--line); }
.seg a:focus-visible, .seg button:focus-visible { outline: 3px solid var(--focus);
  outline-offset: -2px; }
.seg [aria-current="true"], .seg [aria-pressed="true"] { color: var(--blue); font-weight: 800;
  border-bottom-color: var(--blue); background: none; }
.iconbtn { min-width: 2.75rem; min-height: 2.75rem; border: 2px solid var(--line);
  border-radius: var(--r-sm); background: var(--surface); color: var(--ink);
  font-size: 1rem; font-weight: 700; cursor: pointer; }
/* admin "view as" quick lookup (classic LC parity: type a UID + Enter) */
.imp-field input { min-height: 2.75rem; width: 8.5rem; padding: 0 .7rem;
  border: 2px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
  color: var(--ink); font-size: .85rem; font-weight: 600; transition: width .15s ease; }
.imp-field input:focus { width: 12rem; }
.imp-field input::placeholder { color: var(--muted); opacity: 1; }
.avatar { width: 2.75rem; height: 2.75rem; border-radius: 50%; background: var(--surface-2);
  border: 2px solid var(--line); display: inline-flex; align-items: center; justify-content: center;
  font-size: .82rem; font-weight: 800; color: var(--ink); cursor: pointer; padding: 0; }
.avatar:hover, .avatar[aria-expanded="true"] { border-color: var(--blue); }
/* account menu (opens from the avatar) */
.avatar-menu { position: absolute; right: 1rem; top: calc(100% - .35rem); z-index: 60;
  min-width: 15rem; max-width: calc(100vw - 2rem);
  background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-md);
  box-shadow: var(--sh-lg); padding: .4rem; display: flex; flex-direction: column; }
.avatar-menu .am-id { font-size: .84rem; color: var(--muted); padding: .55rem .7rem .6rem;
  border-bottom: 2px solid var(--line); margin-bottom: .3rem; line-height: 1.45; }
.avatar-menu .am-id b { color: var(--ink); }
.avatar-menu .am-note { font-size: .78rem; }
.avatar-menu [role="menuitem"] { display: flex; align-items: center; gap: .5rem; width: 100%;
  min-height: 2.75rem; padding: .45rem .7rem; border: none; border-radius: var(--r-sm);
  background: none; color: var(--ink); font: inherit; font-weight: 600; font-size: .92rem;
  text-align: left; text-decoration: none; cursor: pointer; }
.avatar-menu [role="menuitem"]:hover, .avatar-menu [role="menuitem"]:focus-visible {
  background: var(--surface-2); }

/* ---- a11y bar (A- / A / A+) ---- */
.a11y { display: flex; gap: .35rem; align-items: center; }
.a11y button { min-width: 2.75rem; min-height: 2.75rem; font-weight: 800; font-size: .95rem;
  border: 2px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
  color: var(--ink); cursor: pointer; }

/* ---- buttons ---- */
/* Buttons look like buttons. They were flat fills with no border, no shadow, no hover and
   no pressed state, so a gold button and a gold badge were the same object to the eye.
   Raised now: a hard bottom edge (the thing that actually reads as "button"), a soft cast
   shadow, a lift on hover and a real press on click.

   None of this is load-bearing for accessibility. The control is still identified by its
   role, its label, its fill and a 2.85rem target; the shadow is affordance on top. Under
   prefers-contrast:more it becomes a solid border instead, and under
   prefers-reduced-motion nothing moves. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  border: none; border-radius: .55rem; font-weight: 700; font-size: .95rem;
  padding: .72rem 1.3rem; cursor: pointer; min-height: 2.85rem; text-decoration: none;
  box-shadow: 0 2px 0 rgba(8, 22, 40, .22), 0 3px 8px rgba(8, 22, 40, .18);
  transition: transform .08s ease, box-shadow .12s ease, filter .12s ease; }
.btn:hover {
  transform: translateY(-1px); filter: brightness(1.04);
  box-shadow: 0 3px 0 rgba(8, 22, 40, .24), 0 6px 14px rgba(8, 22, 40, .22); }
/* The press is the point: the hard edge collapses, so it goes down rather than just dimming. */
.btn:active {
  transform: translateY(1px);
  box-shadow: 0 1px 0 rgba(8, 22, 40, .26), 0 1px 3px rgba(8, 22, 40, .2); }
.btn:disabled, .btn:disabled:hover {
  transform: none; filter: none;
  box-shadow: 0 1px 0 rgba(8, 22, 40, .12); }
/* On a dark ground a cast shadow is nearly invisible, so the raised edge comes from a light
   top highlight instead. */
:root[data-theme="dark"] .btn, :root:not([data-theme="light"]) .btn {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16),
              0 2px 0 rgba(0, 0, 0, .45), 0 4px 10px rgba(0, 0, 0, .4); }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .btn {
    box-shadow: 0 2px 0 rgba(8, 22, 40, .22), 0 3px 8px rgba(8, 22, 40, .18); }
}
/* !important earns its place here. The theme rules above are `:root:not([data-theme=...])
   .btn`, which outranks a bare `.btn`, so without it the shadow survived this query and only
   the border appeared. Measured, not guessed: the computed style still reported the shadow.
   An accessibility escape hatch that loses a specificity argument is not an escape hatch. */
@media (prefers-contrast: more) {
  .btn,
  .btn:hover,
  .btn:active,
  .btn:disabled { border: 2px solid currentColor; box-shadow: none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
  .btn:hover, .btn:active { transform: none; }
}
.btn.gold { background: var(--gold); color: #3a2c00; }
.btn.navy { background: var(--blue); color: #fff; }
:root[data-theme="dark"] .btn.navy, :root:not([data-theme="light"]) .btn.navy { color: #04283f; }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .btn.navy { color: #fff; } }
:root[data-theme="light"] .btn.navy { color: #fff; }
.btn.plain { background: var(--surface-2); color: var(--ink); border: 2px solid var(--line); }
.btn.danger { background: var(--bad); color: #fff; }
:root[data-theme="dark"] .btn.danger { color: #2c1512; }
.btn.ghost { background: rgba(255,255,255,.14); color: #fff; border: 2px solid rgba(255,255,255,.45); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn .why { font-weight: 500; font-size: .78rem; }
.btn.wide { width: 100%; }

/* ---- pills: state = icon + word + border, never color alone ---- */
.pill { display: inline-flex; align-items: center; gap: .3em; font-family: var(--mono);
  font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .02em;
  padding: .22em .65em; border-radius: var(--r-full); border: 2px solid currentColor;
  white-space: nowrap; }
.pill.good { color: var(--good); background: var(--good-bg); }
.pill.warn { color: var(--warn); background: var(--warn-bg); }
.pill.bad  { color: var(--bad);  background: var(--bad-bg); }
.pill.info { color: var(--info); background: var(--info-bg); }
.pill.neutral { color: var(--muted); background: var(--surface-2); }

/* ---- cards & callouts ---- */
.card { background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-md);
  padding: 1rem 1.15rem; box-shadow: var(--sh-md); }
.callout { border-radius: .6rem; padding: .8rem 1rem; margin: .8rem 0; border: 2px solid; font-size: .92rem; }
.callout.info { background: var(--info-bg); border-color: var(--info); }
.callout.warn { background: var(--warn-bg); border-color: var(--warn); }
.callout.good { background: var(--good-bg); border-color: var(--good); }
.callout.bad  { background: var(--bad-bg);  border-color: var(--bad); }

/* ---- hero ---- */
.hero { background: var(--hero-grad); color: #fff; border-radius: var(--r-lg);
  padding: clamp(1.4rem, 4vw, 2.4rem) clamp(1.1rem, 3vw, 2rem); margin: 1rem 0;
  position: relative; overflow: hidden; }
/* faint anchor watermark, purely decorative (CSS background: nothing for AT to announce).
   Sits right of center where no text lands; 7% white keeps every text contrast intact. */
.hero::after { content: ""; position: absolute; right: -2rem; top: 50%;
  width: 16rem; height: 16rem; transform: translateY(-50%) rotate(12deg);
  pointer-events: none; opacity: .07;
  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><g fill="none" stroke="white" stroke-width="6" stroke-linecap="round"><circle cx="32" cy="13" r="5" stroke-width="4.5"/><line x1="32" y1="19" x2="32" y2="51"/><line x1="21" y1="27" x2="43" y2="27"/><path d="M14 38 q4 14 18 14 q14 0 18 -14"/></g></svg>') center / contain no-repeat; }
@media (max-width: 44rem) { .hero::after { width: 11rem; height: 11rem; right: -2.5rem; } }
.hero .hb { display: inline-block; background: rgba(255,210,0,.22); color: #ffe685;
  border: 1.5px solid rgba(255,210,0,.55); border-radius: var(--r-full);
  font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  padding: .25em .8em; margin-bottom: .6rem; }
.hero h1 { margin: .1rem 0 .4rem; font-size: clamp(1.5rem, 4.5vw, 2.3rem); line-height: 1.15;
  letter-spacing: -.01em; color: #fff; text-wrap: balance; }
.hero h1 b { color: var(--gold); }
.hero p { color: #d7e6f2; font-size: .98rem; max-width: 56ch; margin: 0 0 1rem; }

/* ---- catalog ---- */
.cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr)); gap: .9rem; }
.prod { background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-md);
  padding: 1rem; box-shadow: var(--sh-md); display: flex; flex-direction: column; gap: .45rem;
  color: var(--ink); text-decoration: none;
  transition: box-shadow .15s ease, transform .15s ease, border-color .15s ease; }
.prod:hover, .prod:focus-visible { box-shadow: var(--sh-lg); border-color: var(--blue);
  transform: translateY(-3px); }
.tile { width: 3rem; height: 3rem; border-radius: .7rem; display: flex; align-items: center;
  justify-content: center; font-size: 1.35rem; color: #fff; flex: none; }
.prod h3 { margin: .1rem 0 0; font-size: 1rem; line-height: 1.25; }
/* quiet vendor tag under the product name (secondary info, never the organizing axis) */
.prod .vend { font-size: .72rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--muted); margin-top: -.25rem; }
.prod .desc { font-size: .82rem; color: var(--muted); line-height: 1.45; flex: 1; }
/* "You have this" / "Order in progress" badge on catalog cards */
.prod .own-badge { align-self: flex-start; margin: -.15rem 0 .1rem; }
/* price line: main + sub STACKED on their own lines — no mixed-size mid-phrase
   wrapping at any viewport (the "Staff & faculty students: see…" desktop bug). */
.prod .price { display: flex; flex-direction: column; gap: .1rem; }
.prod .price b { font-weight: 800; font-size: 1rem; line-height: 1.3; }
.prod .price small { font-weight: 500; color: var(--muted); font-size: .78rem; line-height: 1.35; }

/* ---- receipt / detail card ---- */
.rec { background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-md);
  overflow: hidden; box-shadow: var(--sh-md); }
.rec .rh { display: flex; justify-content: space-between; align-items: center; gap: .6rem;
  background: var(--surface-2); border-bottom: 2px solid var(--line); padding: .7rem 1rem; flex-wrap: wrap; }
.rec .rh .oid { font-family: var(--mono); font-weight: 700; font-size: .9rem; }
.rec .rr { display: flex; justify-content: space-between; gap: 1rem; padding: .58rem 1rem;
  border-bottom: 1px solid var(--line); font-size: .9rem; }
.rec .rr:last-child { border-bottom: none; }
.rec .rr .l { color: var(--muted); }
.rec .rr .v { font-weight: 600; text-align: right; overflow-wrap: anywhere; }

/* ---- provisioning stepper ---- */
.prog { height: .55rem; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-full); overflow: hidden; margin: .4rem 0 1rem; }
.prog i { display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--blue), #28a565); transition: width .5s; }
.plog { list-style: none; margin: 0; padding: 0; }
.plog li { display: flex; gap: .85rem; padding: .72rem 0; border-bottom: 1.5px dashed var(--line);
  opacity: .42; transition: opacity .3s; }
.plog li:last-child { border-bottom: none; }
.plog li.active, .plog li.done { opacity: 1; }
.pdot { flex: none; width: 1.75rem; height: 1.75rem; border-radius: 50%;
  background: var(--surface-2); border: 2px solid var(--line); color: var(--muted);
  display: flex; align-items: center; justify-content: center; font-size: .82rem; font-weight: 800; }
.plog li.active .pdot { background: var(--gold); border-color: var(--gold); color: #3a2c00; }
.plog li.done .pdot { background: var(--good); border-color: var(--good); color: #fff; }
:root[data-theme="dark"] .plog li.done .pdot { color: #0f2a1e; }
.ptxt b { display: block; font-size: .93rem; }
.ptxt span { font-size: .8rem; color: var(--muted); }
.plog li.active .ptxt b::after { content: " · in progress"; font-size: .74rem; color: var(--gold-deep); font-weight: 700; }
.plog li.done .ptxt b::after { content: " ✓"; color: var(--good); }

/* ---- order rows ---- */
.orow { display: flex; align-items: center; gap: .8rem; background: var(--surface);
  border: 2px solid var(--line); border-radius: .7rem; padding: .75rem .95rem; margin: .5rem 0;
  flex-wrap: wrap; text-decoration: none; color: var(--ink); }
.orow:hover, .orow:focus-visible { border-color: var(--blue); box-shadow: var(--sh-md); }
.orow .t { flex: 1; min-width: 9rem; }
.orow .t b { display: block; font-size: .95rem; }
.orow .t span { font-size: .78rem; color: var(--muted); }
.orow .oid { font-family: var(--mono); font-size: .78rem; color: var(--muted); }

/* ---- forms ---- */
.field { margin: .8rem 0; }
.field label { display: block; font-weight: 700; font-size: .88rem; margin-bottom: .3rem; }
.field input, .field select, .field textarea { width: 100%; font: inherit; color: var(--ink);
  background: var(--surface); border: 2px solid var(--line); border-radius: .55rem;
  padding: .65rem .8rem; min-height: 2.85rem; }
.field .hint { font-size: .78rem; color: var(--muted); margin-top: .25rem; }
.field .err { display: none; font-size: .82rem; color: var(--bad); font-weight: 600; margin-top: .3rem; }
.field.invalid input, .field.invalid textarea { border-color: var(--bad); }
.field.invalid .err { display: block; }

/* ---- toast (one system, aria-live host) ---- */
#toastHost { position: fixed; top: 1rem; right: 1rem; z-index: 120; display: flex;
  flex-direction: column; gap: .5rem; max-width: min(22rem, calc(100vw - 2rem)); }
.toast { background: var(--surface); border: 2px solid var(--line); border-left-width: 6px;
  border-radius: .6rem; box-shadow: var(--sh-lg); padding: .7rem .9rem; font-size: .88rem; }
.toast.good { border-left-color: var(--good); } .toast.bad { border-left-color: var(--bad); }
.toast.warn { border-left-color: var(--warn); } .toast.info { border-left-color: var(--info); }

/* ---- dialog (one modal service: focus trap, esc, backdrop) ---- */
dialog.lc { border: 2px solid var(--line); border-radius: var(--r-lg); background: var(--surface);
  color: var(--ink); box-shadow: var(--sh-lg); padding: 0; width: min(30rem, calc(100vw - 2rem)); }
dialog.lc::backdrop { background: rgba(4, 20, 38, .55); }
dialog.lc .dlg-h { display: flex; align-items: center; gap: .6rem; padding: .9rem 1.1rem;
  border-bottom: 2px solid var(--line); font-weight: 800; }
dialog.lc .dlg-b { padding: 1rem 1.1rem; font-size: .92rem; }
dialog.lc .dlg-f { display: flex; gap: .6rem; justify-content: flex-end; padding: .8rem 1.1rem;
  border-top: 2px solid var(--line); flex-wrap: wrap; }

/* ---- bottom action sheet (mobile) / panel (desktop) ---- */
.sheet { background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--sh-lg); padding: .4rem .5rem .6rem; }
.sheet .act { display: flex; align-items: center; gap: .65rem; width: 100%; text-align: left;
  background: none; border: none; border-bottom: 1px solid var(--line); font: inherit;
  font-size: .9rem; font-weight: 600; color: var(--ink); padding: .62rem .55rem;
  min-height: 2.85rem; cursor: pointer; }
.sheet .act:last-child { border-bottom: none; }
.sheet .act .ic { flex: none; width: 1.9rem; text-align: center; }
.sheet .act .chev { margin-left: auto; color: var(--muted); }
.sheet .act.danger { color: var(--bad); }

/* ---- skeletons ---- */
.skel { background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface) 50%, var(--surface-2) 75%);
  background-size: 200% 100%; animation: skel 1.2s linear infinite; border-radius: .5rem; min-height: 1.1rem; }
@keyframes skel { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ---- footer ---- */
/* short pages: the footer band rides the bottom edge instead of floating mid-viewport */
body { display: flex; flex-direction: column; min-height: 100dvh; }
/* width:100% matters — .wrap's `margin: 0 auto` would otherwise cancel flex stretching and
   size main to its CONTENT, so identical pages rendered at different widths. */
body > main, body > .wrap { flex: 1 0 auto; width: 100%; }
.foot { margin-top: 3rem; background: var(--navy); border-top: 3px solid var(--gold);
  padding: 1.4rem 0 2rem; font-size: .82rem; color: #d7e6f2; }
.foot a { color: var(--gold); }
:root[data-theme="dark"] .foot, :root:not([data-theme="light"]) .foot { color: #c9d9e8; }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .foot { color: #d7e6f2; } }

/* ---- responsive table→cards ---- */
.tbl-wrap { overflow-x: auto; border: 2px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
table.lc { width: 100%; border-collapse: collapse; font-size: .9rem; }
table.lc th, table.lc td { text-align: left; padding: .6rem .85rem; border-bottom: 1px solid var(--line); }
table.lc thead th { background: var(--surface-2); font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; }
.as-cards { display: none; }
@media (max-width: 719px) {
  .as-table { display: none; }
  .as-cards { display: flex; flex-direction: column; gap: .6rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
  .prod:hover, .prod:focus-visible { transform: none; }   /* no hover motion either */
}
@media print {
  .hdr, .a11y, #toastHost, .btn, .skip { display: none !important; }
  body { background: #fff; color: #000; }
  .card, .rec { box-shadow: none; border-color: #000; }
}
