/* Tapered inventory page — "Option 7" (2026-07-23)
   ---------------------------------------------------------------------------
   The signed-in inventory is one continuous vessel: the search neck is the width
   of the rest of the page, and the panel FLARES OUT WIDER below it (toward the
   corner docks), so the inventory takes up more room. Neck + flare are a single
   svg path (no seams). The card grid is the default view; "Table View" opens the
   existing table in a full-screen overlay.

   Colours follow the user's chosen theme — accent = var(--accent), surfaces =
   the theme's panel/line/text tokens — so it matches whatever appearance is set.
   On small screens the flare collapses to a plain rectangle. */

.inventoryPage.tapered{
  --tA:var(--accent,#4ea1ff); --tA2:var(--accent2,#7dd3fc); --tFrame:var(--accent,#4ea1ff); --tFrameW:2px;
  --tFill:var(--panel2,#161b25); --tPanel:var(--panel,#12161e);
  --tText:var(--text,#e9edf4); --tMuted:var(--muted,#8a94a6);
  --tLine:var(--line,#28303f);
  --tGood:var(--good,#41c56e); --tWarn:var(--warn,#e0a53a); --tBad:var(--bad,#ff6a6a);
  --tOnA:#fff;                              /* text/icons on an accent fill */
  --invW:min(1160px, 94vw);                 /* only the inventory LIST flares out wider than the page */
  /* strip the card chrome so the sections sit directly on the page. The top
     (header + metrics + breakdown) stays at the normal page width — same as every
     other page frame — and is NOT broken out. */
  background:transparent!important; border:0!important; box-shadow:none!important;
  padding:0!important; overflow:visible!important;
}
.inventoryPage.tapered *{box-sizing:border-box}
.invHiddenChrome{display:none!important}

/* The whole inventory sits at the page width — search, metrics and the list panel
   all the same size as the rest of the page. No breakout, no flare. */
.invTaper{position:relative;width:100%;margin-top:22px;}
/* honeycomb texture that follows the theme (accent-tinted, via a mask so the
   colour is themable — a plain data-URI background can't read CSS vars). */
.invVesselFill{position:relative;background:var(--tFill)}
.invVesselFill::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:0;border-radius:inherit;
  background:var(--tA);opacity:.08;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='48' viewBox='0 0 56 48'%3E%3Cpath d='M14 0l14 8v16l-14 8L0 24V8zM42 0l14 8v16l-14 8-14-8V8zM28 24l14 8v16l-14 8-14-8V32z' fill='none' stroke='%23fff' stroke-width='1.4'/%3E%3C/svg%3E") 0 0/56px 48px;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='48' viewBox='0 0 56 48'%3E%3Cpath d='M14 0l14 8v16l-14 8L0 24V8zM42 0l14 8v16l-14 8-14-8V8zM28 24l14 8v16l-14 8-14-8V32z' fill='none' stroke='%23fff' stroke-width='1.4'/%3E%3C/svg%3E") 0 0/56px 48px;}
/* ---------- search box: compact + centred, inside the panel above the total value ---------- */
/* one border only (a global input rule used to add a second one on the field) */
.invSearch{position:relative;z-index:1;width:min(520px,100%);margin:0 auto 18px;height:46px;
  display:flex;align-items:center;gap:10px;padding:0 15px;
  border-radius:999px;border:1px solid var(--tLine);background:var(--bg,#0c0f15);
  box-shadow:inset 0 1px 3px rgba(0,0,0,.3)}
.invSearch svg{width:20px;height:20px;flex:0 0 20px;fill:none;stroke:var(--tMuted);stroke-width:2}
.invSearch input{flex:1;min-width:0;border:0!important;box-shadow:none!important;background:transparent!important;color:var(--tText);font-size:.98rem;outline:none;padding:0;height:100%}
.invSearch input::placeholder{color:var(--tMuted)}
/* Focus: never let a rectangular input frame show through the pill. Kill any input-level
   outline/ring and put ONE clean, fully-rounded ring on the whole search bar instead. */
.invSearch input:focus,.invSearch input:focus-visible{outline:none!important;box-shadow:none!important;border:0!important}
.invSearch:focus-within{border-color:color-mix(in srgb,var(--tA) 55%,var(--tLine));
  box-shadow:0 0 0 3px color-mix(in srgb,var(--tA) 20%,transparent),inset 0 1px 3px rgba(0,0,0,.3)}

/* metric cards, between the search and the panel */
.invMetricsSlot{position:relative;margin:0 0 16px}
.invMetricsSlot:empty{display:none}
.invMetricsSlot .inventoryPageMetrics{margin:0}

/* the tabs bar is sticky (62px tall); leave room so the panel header + the add form
   never tuck UNDER it when scrolled into view (which had the tabs eat clicks). */
.invBodyHead,#inventoryAddForm{scroll-margin-top:78px}

/* ---------- Total Inventory Value ----------
   A plain centred block at the top of the panel — no divot; the panel is a normal
   rounded rectangle with a straight top border. */
.invHero{position:relative;z-index:1;pointer-events:none;margin:0 0 18px;padding:2px 0 0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center}
.invHeroLabel{font-size:.64rem;font-weight:800;letter-spacing:.26em;text-transform:uppercase;color:var(--tA2);opacity:.92}
.invHeroValue{position:relative;margin-top:3px;font-size:clamp(1.9rem,3.6vw,2.9rem);font-weight:850;line-height:1;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;
  background:linear-gradient(180deg,#fff 0%,color-mix(in srgb,var(--tA2) 55%,#fff) 48%,var(--tA2) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 4px 20px color-mix(in srgb,var(--tA) 42%,transparent))}
.invHeroSub{margin-top:7px;font-size:.78rem;color:var(--tMuted)}
.invHero.play .invHeroValue{animation:invHeroPop .7s cubic-bezier(.2,.9,.25,1.15) both}
@keyframes invHeroPop{from{opacity:0;transform:translateY(10px) scale(.94)}to{opacity:1;transform:none}}
.invHero.play .invHeroLabel,.invHero.play .invHeroSub{animation:invHeroFade .7s ease .12s both}
@keyframes invHeroFade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.invSpark{position:absolute;pointer-events:none;border-radius:50%;opacity:0;transform:scale(0);
  background:radial-gradient(circle,#fff 0 30%,var(--tA2) 46%,transparent 70%);
  box-shadow:0 0 6px color-mix(in srgb,var(--tA2) 85%,transparent)}
.invHero.play .invSpark{animation:invSparkle var(--dur,1s) ease-out var(--delay,0s) 1}
@keyframes invSparkle{0%{opacity:0;transform:scale(0)}25%{opacity:1}60%{opacity:.95;transform:scale(1)}100%{opacity:0;transform:scale(.2) translateY(-12px)}}
@media(prefers-reduced-motion:reduce){.invHero.play *{animation:none!important}}

/* ---------- the inventory panel (full page width) ---------- */
/* A normal rounded rectangle: full border, rounded all round, straight top edge. */
.invBody{width:100%;padding:22px 24px 26px;border-radius:22px;
  border:var(--tFrameW) solid var(--tFrame);position:relative}
/* themed glare pooled around the flare, dissolving down into the honeycomb */
.invBody::after{content:"";position:absolute;left:0;right:0;top:0;height:300px;pointer-events:none;z-index:0;border-radius:inherit;
  background:radial-gradient(150% 300px at 50% -70px, color-mix(in srgb,var(--tA) 14%,transparent), color-mix(in srgb,var(--tA) 5%,transparent) 48%, transparent 78%);}

/* ---------- fancy header ---------- */
.invBodyHead{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:0 0 18px;
  position:relative;z-index:1;padding:15px 18px;border-radius:16px;flex-wrap:wrap;
  border:1px solid color-mix(in srgb,var(--tA) 24%,var(--tLine));
  background:linear-gradient(120deg, color-mix(in srgb,var(--tA) 13%,var(--tPanel)) 0%, color-mix(in srgb,var(--tFill) 88%, var(--tA) 5%) 60%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05), 0 10px 26px -16px color-mix(in srgb,var(--tA) 40%,transparent);overflow:hidden}
.invBodyHead::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(120% 180% at 100% -30%, color-mix(in srgb,var(--tA) 14%,transparent), transparent 55%)}
.invHeadLeft{display:flex;align-items:center;gap:14px;min-width:0;position:relative;z-index:1}
.invHeadIcon{width:48px;height:48px;flex:0 0 48px;border-radius:14px;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--tA),var(--tA2));box-shadow:0 8px 20px color-mix(in srgb,var(--tA) 45%,transparent)}
.invHeadIcon svg{width:27px;height:27px;fill:none;stroke:var(--tOnA);stroke-width:1.9}
.invHeadText{min-width:0}
.invEyebrow{font-size:.62rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:var(--tA2)}
.invBodyHead h2{margin:2px 0 7px;font-size:1.3rem;color:var(--tText);display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.invBodyHead h2 .invCnt{color:var(--tMuted);font-size:.8rem;font-weight:600}
.invHeadStats{display:flex;gap:8px;flex-wrap:wrap}
.invStat{display:inline-flex;align-items:center;gap:6px;font-size:.72rem;color:var(--tMuted);
  padding:4px 11px;border-radius:999px;background:color-mix(in srgb,var(--tFill) 82%,transparent);border:1px solid var(--tLine)}
.invStat b{color:var(--tText);font-variant-numeric:tabular-nums}
.invStat .sdot{width:7px;height:7px;border-radius:50%;box-shadow:0 0 6px currentColor}
.invStat.ok .sdot{background:var(--tGood);color:var(--tGood)}
.invStat.low .sdot{background:var(--tWarn);color:var(--tWarn)}
.invStat.out .sdot{background:var(--tBad);color:var(--tBad)}
.invHeadRight{display:flex;align-items:center;gap:14px;position:relative;z-index:1;flex-wrap:wrap;justify-content:flex-end}
.invHeadBtns{display:flex;gap:10px;flex:0 0 auto}
.invBtn{border:1px solid var(--tLine);background:color-mix(in srgb,var(--tFill) 80%,transparent);color:var(--tText);
  border-radius:12px;padding:11px 15px;font:600 .84rem inherit;cursor:pointer;display:inline-flex;align-items:center;gap:8px;white-space:nowrap}
.invBtn:hover{border-color:color-mix(in srgb,var(--tA) 45%,var(--tLine))}
.invBtn svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2}
.invBtn.primary{background:linear-gradient(135deg,var(--tA),var(--tA2));border-color:transparent;color:var(--tOnA);font-weight:800}

/* ---------- column header + card grid (default view) ---------- */
/* Fixed non-flex tracks (loc/status/qr/cost/actions) so the header row and every
   card line up on the exact same columns; only the filament + available columns flex. */
/* scoped to .invTaper so these do NOT leak onto the page-upgrade full-view cards,
   which reuse the .invCard class with a different column structure */
.invTaper .invCard,.invTaper .invColHead{grid-template-columns:66px minmax(150px,1fr) 100px 46px minmax(0,1.8fr) 104px 124px;
  grid-template-areas:"loc id badge qr avail cost acts";gap:16px;align-items:center}
.invColHead{display:grid;position:relative;z-index:1;padding:0 18px 9px;margin:0 0 8px;border-bottom:1px solid var(--tLine)}
.invColHead span{font-size:.62rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:var(--tA);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.invColHead span[style*="loc"],.invColHead span[style*="qr"]{text-align:center}

/* the list scrolls WITHIN the frame after ~7 rows */
.invCards{display:flex;flex-direction:column;gap:11px;position:relative;z-index:1;
  max-height:min(648px,72vh);overflow-y:auto;overflow-x:hidden;padding-right:6px;
  scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--tA) 45%,var(--tLine)) transparent}
.invCards::-webkit-scrollbar{width:9px}
.invCards::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--tA) 45%,var(--tLine));border-radius:999px;border:2px solid transparent;background-clip:content-box}
.invCards::-webkit-scrollbar-track{background:transparent}
.invCardsEmpty{padding:34px 18px;text-align:center;color:var(--tMuted);
  border:1px dashed var(--tLine);border-radius:15px;background:color-mix(in srgb,var(--tFill) 55%,transparent)}
.invTaper .invCard{display:grid;padding:14px 18px;border-radius:15px;
  border:1px solid var(--tLine);border-left:3px solid var(--c);
  background:linear-gradient(155deg, color-mix(in srgb,var(--tFill) 92%, var(--tA) 8%), var(--tPanel));}

.invLocCol{grid-area:loc;display:flex;flex-direction:column;align-items:center;gap:5px;width:66px;text-align:center}
.invLocBox{width:44px;height:44px;border-radius:13px;display:grid;place-items:center;
  background:color-mix(in srgb,var(--tA) 16%, var(--tFill));border:1px solid color-mix(in srgb,var(--tA) 38%,var(--tLine))}
.invLocBox svg{width:24px;height:24px;fill:none;stroke:var(--tA2);stroke-width:1.7}
.invLocCol small{font-size:.7rem;color:var(--tMuted);font-weight:600;max-width:66px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.invId{grid-area:id;display:flex;align-items:center;gap:11px;min-width:0}
.invId .idText{min-width:0}
.invName{font-size:1rem;font-weight:750;line-height:1.2;color:var(--tText);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.invSub{margin-top:2px;color:var(--tMuted);font-size:.76rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.invBadge{grid-area:badge;justify-self:start;font-size:.62rem;font-weight:800;padding:4px 10px;border-radius:999px;white-space:nowrap;border:1px solid transparent}
.invBadge.ok{color:var(--tGood);background:color-mix(in srgb,var(--tGood) 15%,transparent);border-color:color-mix(in srgb,var(--tGood) 40%,transparent)}
.invBadge.low{color:var(--tWarn);background:color-mix(in srgb,var(--tWarn) 16%,transparent);border-color:color-mix(in srgb,var(--tWarn) 42%,transparent)}
.invBadge.out{color:var(--tBad);background:color-mix(in srgb,var(--tBad) 16%,transparent);border-color:color-mix(in srgb,var(--tBad) 42%,transparent)}

/* QR thumbnail — filled + wired by inventory-qr.js (reused as-is) */
.invCard .invQrCell{grid-area:qr;width:46px;height:46px;flex:0 0 46px;border-radius:8px;overflow:hidden;
  display:grid;place-items:center;background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.3);cursor:pointer;padding:0}
.invCard .invQrCell .invQrThumb{border:0;background:transparent;padding:0;width:100%;height:100%;display:block;cursor:pointer}
.invCard .invQrCell svg{display:block;width:100%;height:100%}

.invAvail{grid-area:avail;min-width:0}
.invAvail .invAvailTop{display:flex;justify-content:space-between;gap:10px;font-size:.77rem;color:var(--tMuted)}
.invAvail .invAvailTop b{color:var(--tText);font-variant-numeric:tabular-nums}
.invBar{height:7px;margin-top:6px;border-radius:999px;background:var(--bg,#0c0f15);border:1px solid var(--tLine);overflow:hidden}
.invBar i{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,var(--tA),var(--tA2))}
.invCard.low .invBar i{background:linear-gradient(90deg,var(--tWarn),#f4c66a)}
.invCard.out .invBar i{background:linear-gradient(90deg,var(--tBad),#ff9a9a)}
.invSubline{margin-top:5px;font-size:.7rem;color:color-mix(in srgb,var(--tMuted) 78%,transparent)}

.invCostCol{grid-area:cost;display:flex;flex-direction:column;gap:2px}
.invCostCol .invLbl{color:var(--tMuted);font-size:.72rem;font-weight:600}
.invCostCol b{font-size:.9rem;color:var(--tText);font-variant-numeric:tabular-nums}

.invRowActs{grid-area:acts;display:flex;flex-direction:column;gap:6px}
.invActRow{display:flex;gap:6px}
.invMini{border:1px solid var(--tLine);background:color-mix(in srgb,var(--tFill) 80%,transparent);color:var(--tText);
  border-radius:10px;padding:7px 12px;font:600 .75rem inherit;cursor:pointer;text-align:center;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;gap:6px}
.invMini:hover{border-color:color-mix(in srgb,var(--tA) 40%,var(--tLine))}
.invActRow .invMini{flex:1}
.invMini.reorder{color:var(--tOnA);font-weight:800;background:linear-gradient(135deg,color-mix(in srgb,var(--tA) 86%,black 14%),var(--tA2));border-color:transparent;text-shadow:0 1px 2px rgba(0,0,0,.45)}
.invMini.reorder svg{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:2}
.invMini.del{color:var(--tBad);border-color:color-mix(in srgb,var(--tBad) 45%,var(--tLine));background:color-mix(in srgb,var(--tBad) 8%,transparent)}

/* ---------- Add Item modal (pop-up) — same overlay mechanism as Table View ----------
   The modal is appended to <body>, OUTSIDE .inventoryPage.tapered, so it must use the
   GLOBAL theme tokens (--panel/--accent/--line/--bg), NOT the taper-scoped --tPanel/
   --tA/--tLine (which are undefined here and made the panel render invisible). */
body.invAddModalOpen{overflow:hidden}
.invAddModal{position:fixed;inset:0;z-index:2000;display:flex;padding:24px;
  background:color-mix(in srgb,var(--bg,#07080b) 78%,transparent);backdrop-filter:blur(6px)}
.invAddModal.hidden{display:none}
.invAddModalPanel{margin:auto;width:min(680px,100%);max-height:100%;overflow:auto;padding:8px;
  background:var(--panel,#12161e);border:1px solid color-mix(in srgb,var(--accent,#4ea1ff) 30%,var(--line,#28303f));
  border-radius:20px;box-shadow:0 30px 80px -20px rgba(0,0,0,.7)}
/* the moved-in form always shows in the modal, fills it, and the panel owns the frame */
.invAddModalPanel #inventoryAddForm{margin:0!important;max-width:none!important;width:100%;
  border:0!important;box-shadow:none!important;background:transparent!important}
/* release-completion-20260718.css force-hides #inventoryAddForm when signed in unless it
   is inside .inventoryAddModalBackdrop. Our pop-up uses .invAddModal, so RE-SHOW the form
   here with a selector that out-specifies that rule — this is why Add Item never opened
   while actually signed in. */
html body .invAddModal #inventoryAddForm,
html body.signed-in .invAddModal #inventoryAddForm{display:block!important}

/* ---------- Table View overlay (sortable headers + filter) ---------- */
body.invTaperOverlayOpen{overflow:hidden}
/* The overlay + Add modal are appended to <body>, OUTSIDE .inventoryPage.tapered, so
   the taper tokens (--tPanel etc.) never reach them — the panel background was actually
   TRANSPARENT and only looked dark because of the backdrop blur. Re-map the taper tokens
   to the global theme tokens here so every --t* reference inside the overlay resolves. */
.invTaperOverlay,.invAddModal{
  --tA:var(--accent,#4ea1ff); --tA2:var(--accent2,#7dd3fc);
  --tPanel:var(--panel,#12161e); --tFill:var(--panel2,#161b25);
  --tText:var(--text,#e9edf4); --tMuted:var(--muted,#8a94a6);
  --tLine:var(--line,#28303f); --tBad:var(--bad,#ff6a6a); --tOnA:#fff;
}
.invTaperOverlay{position:fixed;inset:0;z-index:1400;display:flex;padding:26px;
  background:color-mix(in srgb,var(--bg,#07080b) 78%, transparent);backdrop-filter:blur(6px)}
.invTaperOverlay.hidden{display:none}
/* Wide enough that the full 12-column table fits without a side-scroll on desktop
   (the reason "Delete" was clipped off the right edge before). */
.invOvPanel{margin:auto;width:min(1560px,97vw);max-height:100%;display:flex;flex-direction:column;
  background:var(--tPanel);border:1px solid color-mix(in srgb,var(--tA) 22%,var(--tLine));border-radius:20px;
  box-shadow:0 30px 80px -20px rgba(0,0,0,.7), 0 0 0 1px color-mix(in srgb,var(--tA) 8%,transparent);overflow:hidden}
.invOvHead{display:flex;align-items:center;justify-content:space-between;gap:16px 24px;padding:16px 20px;flex-wrap:wrap;
  border-bottom:1px solid var(--tLine);
  background:linear-gradient(120deg, color-mix(in srgb,var(--tA) 12%,var(--tPanel)), var(--tPanel) 62%)}
.invOvTitle h2{margin:2px 0 0;font-size:1.2rem;color:var(--tText)}
/* Total Inventory Value, back at the top-right of the expanded view */
.invOvHeadRight{display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.invOvTotal{display:flex;flex-direction:column;align-items:flex-end;line-height:1.1;
  padding:6px 16px;border-radius:14px;border:1px solid color-mix(in srgb,var(--tA) 28%,var(--tLine));
  background:color-mix(in srgb,var(--tA) 10%,var(--tPanel))}
.invOvTotalLabel{font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;color:var(--tMuted,var(--muted))}
.invOvTotalAmount{font-size:1.4rem;font-weight:800;color:var(--tText);font-variant-numeric:tabular-nums;
  background:linear-gradient(92deg,var(--tText),color-mix(in srgb,var(--tA) 70%,var(--tText)));
  -webkit-background-clip:text;background-clip:text}
.invOvBody{padding:18px 20px 22px;overflow:auto}
.invOvBody #inventoryCatalog{margin:0}

/* ---- bulk select + delete controls (overlay lives on <body>, so use GLOBAL tokens) ---- */
/* the bulk + backup buttons sit inside the catalog toolbar, kept LEFT of QR Labels via
   flex order (DOM order can't be trusted — QR Labels is prepended on a later refresh) */
.invOvBulkGroup{display:flex;gap:9px;align-items:center;flex-wrap:wrap;order:-1}
.invTaperOverlay .invBtn{border:1px solid var(--line);background:color-mix(in srgb,var(--panel2,var(--panel)) 82%,transparent);color:var(--text)}
.invTaperOverlay .invBtn:hover{border-color:color-mix(in srgb,var(--accent) 48%,var(--line))}
.invTaperOverlay .invBtn:disabled{opacity:.45;cursor:default}
.invTaperOverlay .invBtn.danger{color:var(--bad,#ff6a6a);border-color:color-mix(in srgb,var(--bad,#ff6a6a) 45%,var(--line));background:color-mix(in srgb,var(--bad,#ff6a6a) 12%,transparent)}
.invTaperOverlay .invBtn.danger:hover{border-color:var(--bad,#ff6a6a);background:color-mix(in srgb,var(--bad,#ff6a6a) 20%,transparent)}
/* the toolbar's button row is a flex container so the bulk group's order:-1 pins it left */
.invTaperOverlay .inventoryCatalogButtons{display:flex;flex-wrap:wrap;gap:9px;align-items:center}
.invTaperOverlay .inventoryTableActions{flex-wrap:wrap;gap:12px}
.invOvSelectBar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
  margin:12px 0 2px;padding:10px 14px;border-radius:12px;
  border:1px solid color-mix(in srgb,var(--accent) 32%,var(--line));background:color-mix(in srgb,var(--accent) 10%,var(--panel))}
.invOvSelectBar[hidden]{display:none}
.invOvSelectBar > strong{font-size:.86rem;color:var(--text);font-variant-numeric:tabular-nums}
.invOvSelActions{display:flex;gap:8px;flex-wrap:wrap}
/* selection mode: rows toggle on click; hide their per-row action buttons to avoid mis-clicks */
.invTaperOverlay.invSelecting #inventoryTableBody tr[data-inventory-id]{cursor:pointer}
.invTaperOverlay.invSelecting #inventoryTableBody .inventoryRowActions{visibility:hidden}
.invTaperOverlay #inventoryTableBody tr.invRowSelected{background:color-mix(in srgb,var(--accent) 18%,transparent)!important;box-shadow:inset 3px 0 0 var(--accent)}
/* a filter icon on the stock-status control */
.invFilterIcon{width:15px;height:15px;vertical-align:-2px;margin-right:6px;fill:none;stroke:var(--tA2);stroke-width:2}
/* sortable column headers */
.invOvBody .inventoryTable th.invSortable{cursor:pointer;user-select:none;white-space:nowrap}
.invOvBody .inventoryTable th.invSortable:hover{color:var(--tA2)}
.invSortCaret{display:inline-block;width:0;height:0;margin-left:6px;vertical-align:middle;opacity:.3;
  border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid currentColor}
.invSortCaret.asc{border-top:0;border-bottom:5px solid currentColor;opacity:1}
.invSortCaret.desc{border-bottom:0;border-top:5px solid currentColor;opacity:1}

/* ---------- responsive ---------- */
@media(max-width:1040px){
  .invColHead{display:none}   /* the card layout reflows here, so the aligned header no longer applies */
  .invTaper .invCard{grid-template-columns:auto minmax(0,1fr) auto;
    grid-template-areas:
      "loc id    badge"
      "loc qr    avail"
      "loc cost  acts";}
  .invRowActs{align-self:end}
}
/* small screens: everything is already page width; just soften the corners and the
   divot so the big value fits. */
@media(max-width:720px){
  .invHeroValue{font-size:clamp(1.8rem,7vw,2.3rem)}
  .invBody{border-radius:16px}
}
@media(max-width:680px){
  .invBody{padding:18px 14px 20px}
  .invBodyHead{padding:13px 14px}
  .invHeadRight{width:100%;justify-content:space-between}
  /* 4 no-wrap buttons overflow a phone row (Add Item fell off-screen): let them wrap and
     fill, and give the primary Add Item its own full-width row so it's always fully visible. */
  .invHeadBtns{flex:1 1 100%;flex-wrap:wrap;gap:8px;justify-content:flex-end}
  .invHeadBtns .invBtn{flex:1 1 auto;justify-content:center}
  .invHeadBtns .invBtn.primary{flex-basis:100%}
  .invTaper .invCard{grid-template-columns:auto minmax(0,1fr);
    grid-template-areas:
      "loc id"
      "loc badge"
      "avail avail"
      "cost  qr"
      "acts  acts";
    gap:12px 14px}
  .invLocCol{width:56px}
  .invLocBox{width:40px;height:40px}
  .invCard .invQrCell{justify-self:end}
  .invMini{padding:9px 12px}
}
