/* ============================================================================
   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; }
.wrap { max-width: 72rem; 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: 72rem; 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: 72rem; 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);
  min-height: 2.75rem; }   /* the home link is a target too: 44px, like every other control */
.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; }
/* text size + theme + account travel together, so the avatar never wraps onto a line by itself */
.hdr-tools { display: flex; align-items: center; gap: .7rem; }
/* Phones (and 200% zoom on a laptop): the header must never pin a big block over the content.
   It scrolls away (relative, not static: the account menu is positioned against it) and drops
   the tagline. Then it settles into two tidy rows, home + My orders, then the tools on the right.
   A-/A+/theme stay visible because low-vision people need them most, and tab order still
   matches reading order (home, My orders, A-, A+, theme, account). */
/* scoped under .hdr so these out-rank the later `.btn { display: inline-flex }` rule (equal
   specificity + later source would otherwise win: Menu leaking onto desktop, My orders onto phones) */
.hdr .hdr-menu { display: none; }
@media (max-width: 40rem) {
  .hdr { position: relative; }
  .hdr-in { gap: .35rem; padding: .5rem .75rem; flex-wrap: nowrap; }
  .brand > span > span { display: none; }
  /* ONE row on phones (Mike, 2026-10-07, after seeing the admin header stack into three ragged
     rows): just the logo and "☰ Menu". My orders, the admin lookup + View as, text size, theme
     and the account all live in the menu (js/core.js toggleAccountMenu adds the text/theme row). */
  .hdr .hdr-orders, .hdr .imp-field, .hdr #viewAsBtn, .hdr .hdr-tools { display: none; }
  .hdr .hdr-menu { display: inline-flex; }
}
/* the text size + theme row inside the phone menu: square 44px buttons, not full-width menu rows */
.avatar-menu .am-display { display: flex; align-items: center; gap: .35rem; padding: .5rem .7rem .35rem;
  border-top: 2px solid var(--line); margin-top: .3rem; }
.avatar-menu .am-display .am-label { flex: 1; font-size: .84rem; font-weight: 600; color: var(--muted); }
.avatar-menu .am-display [role="menuitem"] { width: auto; min-width: 2.75rem; justify-content: center;
  border: 2px solid var(--line); background: var(--surface); padding: 0; }
.seg { display: inline-flex; border: 2px solid var(--line); border-radius: var(--r-full);
  overflow: hidden; }
.seg a, .seg button { border: none; padding: .5rem 1rem; background: var(--surface);
  color: var(--muted); cursor: pointer; font-weight: 700; font-size: .82rem; text-decoration: none;
  min-height: 2.75rem; display: inline-flex; align-items: center; gap: .35rem; }
.seg [aria-current="true"], .seg [aria-pressed="true"] { background: var(--blue); color: #fff; }
.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 ---- */
/* ONE button size, everywhere (Mike, 2026-10-07: no wrapping, no buttons that change size from
   screen to screen). A label never wraps, so a button is the same slim single line on a phone
   and on a monitor. 44px is the floor at any text size (A- included); A+ still grows it. Labels
   are kept short enough to fit a 320px phone, so don't patch sizes per page: shorten the label. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  border: none; border-radius: .55rem; font-weight: 700; font-size: .9rem; line-height: 1.2;
  padding: .5rem 1.05rem; cursor: pointer; min-height: max(44px, 2.5rem); text-decoration: none;
  white-space: nowrap; max-width: 100%; }
.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%; }
/* Safety net only: on screens narrower than any current phone, wrapping beats spilling off the
   edge. Labels are written to fit at 320px, so this should never actually fire. */
@media (max-width: 19.5rem) { .btn { white-space: normal; text-align: center; } }

/* ---- 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; }
/* the eyebrow pill: full name on wide screens, "UC Irvine · OIT" on phones so it never wraps
   into a two-line pill (the full name stays in the abbreviation's title) */
.hero .hb-abbr { display: none; text-decoration: none; }
@media (max-width: 40rem) { .hero .hb-full { display: none; } .hero .hb-abbr { display: inline; } }

/* ---- 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; }
/* program attribution (e.g. Microsoft Student Use Benefit): a quiet indicator, not a status */
.prod .prog-badge { align-self: flex-start; margin: -.1rem 0 .1rem; font-size: .68rem;
  text-transform: none; letter-spacing: 0; }
/* 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; }

/* ---- auth surfaces: the sign-in splash and the expired-session modal ----
   Same language as login.html (navy gradient ground, gold thread, anchor mark) so the two
   moments the site takes over the page still feel like the site. Both are injected by
   js/auth.js, so every page gets them without its own markup. */
/* AUTH GATE (js/authgate.js sets the class in <head>, auth.js clears it): while sign-in or the
   eligibility check is pending, nothing on the page draws. The splash and the session dialog
   override it, since they ARE the sign-in moment. */
html.auth-pending body { visibility: hidden; }
html.auth-pending .authsplash, html.auth-pending dialog.authdlg { visibility: visible; }
.authsplash { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center;
  justify-content: center; padding: 1rem; background: var(--hero-grad); }
.authsplash-card { background: var(--surface); color: var(--ink); border: 2px solid var(--line);
  border-top: 4px solid var(--gold); border-radius: var(--r-md); box-shadow: var(--sh-lg);
  padding: 1.5rem 1.6rem; text-align: center; max-width: 22rem; width: 100%;
  display: flex; flex-direction: column; gap: .35rem; }
.authsplash-card b { font-family: var(--display); font-size: 1.2rem; }
.authsplash-card span { color: var(--muted); font-size: .9rem; }
/* An indeterminate sweep, the blueprint's one motion idea (blue to green), so the splash
   reads as work in progress. Under reduced-motion it settles into a static bar. */
/* Explicit width, not stretch: an auto cross-axis margin cancels a flex item's stretch, so
   a max-width-only bar collapses to its (empty) content. */
.authsplash-card .bar { height: .32rem; border-radius: 999px; background: var(--surface-2);
  border: 1px solid var(--line); overflow: hidden; margin: .7rem auto 0;
  width: 12rem; max-width: 100%; }
.authsplash-card .bar i { display: block; height: 100%; width: 40%;
  background: linear-gradient(90deg, var(--blue), var(--good));
  animation: authsweep 1.15s ease-in-out infinite alternate; }
@keyframes authsweep { from { transform: translateX(-25%); } to { transform: translateX(175%); } }
@media (prefers-reduced-motion: reduce) {
  .authsplash-card .bar i { animation: none; width: 100%; }
}
.authmark { width: 3rem; height: 3rem; border-radius: 50%; background: var(--hero-grad);
  display: inline-flex; align-items: center; justify-content: center; color: var(--gold);
  font-size: 1.4rem; margin: 0 auto .3rem; }

dialog.authdlg { border: 2px solid var(--line); border-top: 4px solid var(--gold);
  border-radius: var(--r-lg); background: var(--surface); color: var(--ink);
  box-shadow: var(--sh-lg); padding: 1.4rem 1.5rem 1.2rem; text-align: center;
  width: min(26rem, calc(100vw - 2rem)); }
dialog.authdlg::backdrop { background: rgba(4, 20, 38, .62); }
dialog.authdlg h2 { font-size: 1.25rem; margin: 0 0 .5rem; }
dialog.authdlg p { margin: 0 0 .9rem; font-size: .92rem; }
dialog.authdlg p:last-child { margin-bottom: 0; }
dialog.authdlg .hint { color: var(--muted); font-size: .82rem; }

/* ---- 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; }
}
