/* ============================================================
   Tool room (.tr-*) — the equipment screen.
   Module-local only; nothing here touches a shared primitive.
   ============================================================ */
.tr-sub-l { font-size:13.5px; color:var(--ink-soft); margin:4px 0 0; max-width:70ch; }
.tr-lede  { font-size:13.5px; color:var(--ink-soft); margin:0 0 16px; max-width:70ch; }
.tr-dim   { color:var(--ink-faint); font-weight:400; }

/* View switcher */
.tr-seg { display:inline-flex; gap:2px; padding:3px; background:var(--bg2); border-radius:10px; margin-bottom:18px; }
.tr-seg-b { display:inline-flex; align-items:center; gap:6px; border:0; background:transparent; cursor:pointer;
  padding:7px 14px; border-radius:8px; font-size:13px; font-weight:600; color:var(--ink-soft); }
.tr-seg-b:hover { color:var(--ink); }
.tr-seg-b.on { background:var(--white); color:var(--ink); box-shadow:var(--shadow); }
.tr-seg-b .ti { font-size:16px; }
/* The count is the point of the Shop tab — it is what tells you to look. */
.tr-seg-n { min-width:18px; height:18px; padding:0 5px; border-radius:9px; background:#C8553D; color:#fff;
  font-size:10.5px; font-weight:700; display:inline-flex; align-items:center; justify-content:center; }

/* Queue blocks */
.tr-block { margin-bottom:20px; }
.tr-block-h { display:flex; align-items:center; gap:8px; font-size:12px; font-weight:700; text-transform:uppercase;
  letter-spacing:.05em; color:var(--ink-soft); padding-bottom:7px; margin-bottom:9px; border-bottom:2px solid var(--bd); }
.tr-block-h.bad  { color:#B91C1C; border-bottom-color:color-mix(in srgb,#B91C1C 35%,var(--bd)); }
.tr-block-h.warn { color:#B45309; border-bottom-color:color-mix(in srgb,#B45309 35%,var(--bd)); }
.tr-block-h.info { color:var(--accent); border-bottom-color:color-mix(in srgb,var(--accent) 35%,var(--bd)); }
.tr-n { min-width:20px; height:20px; padding:0 6px; border-radius:10px; background:var(--bg2); color:var(--ink-soft);
  font-size:11px; display:inline-flex; align-items:center; justify-content:center; }

/* Tables */
.tr-wrap { border:1px solid var(--bd); border-radius:11px; overflow:auto; box-shadow:var(--shadow); }
.tr-table { width:100%; border-collapse:collapse; font-size:13px; }
.tr-table th { position:sticky; top:0; z-index:1; background:var(--bg2); text-align:left; padding:8px 12px;
  font-size:10.5px; text-transform:uppercase; letter-spacing:.04em; color:var(--ink-faint); border-bottom:1.5px solid var(--bd); }
.tr-table td { padding:8px 12px; border-bottom:1px solid color-mix(in srgb,var(--bd) 55%,transparent); vertical-align:middle; }
.tr-table tbody tr:hover { background:color-mix(in srgb,var(--accent) 5%,transparent); }
.tr-sub { font-size:11.5px; color:var(--ink-faint); margin-top:2px; }
.tr-od  { color:#B91C1C; font-weight:700; }
.tr-act { text-align:right; white-space:nowrap; }
.tr-flag { font-size:11px; font-weight:700; color:#B45309;
  background:color-mix(in srgb,#B45309 12%,transparent); padding:2px 8px; border-radius:999px; }
.tr-rent { font-size:11px; font-weight:700; color:var(--accent);
  background:color-mix(in srgb,var(--accent) 12%,transparent); padding:2px 8px; border-radius:999px; }

/* Empty states carry WHY there is nothing, not just that there is nothing. */
.tr-empty { font-size:13px; color:var(--ink-faint); padding:14px 2px; }
.tr-empty-lg { text-align:center; padding:48px 16px; }
.tr-empty-lg .ti { font-size:34px; color:var(--ink-faint); display:block; margin-bottom:10px; }
.tr-empty-lg h3 { margin:0 0 6px; font-size:16px; color:var(--ink); }

.tr-bar { margin-bottom:14px; }
.tr-search { flex:1; min-width:180px; max-width:340px; padding:7px 11px; border:1px solid var(--bd);
  border-radius:8px; background:var(--white); color:var(--ink); font-size:13px; }

/* Register data table — density comes from PTTable (.ptt-d-*), so padding is
   set there, not here. */
.tr-bar-r { display:inline-flex; align-items:center; gap:8px; margin-left:auto; }
.tr-strong { font-weight:600; color:var(--ink); }
.tr-act-h { width:1%; }
.tr-cf { color:var(--ink-soft); }

/* Custom-field manager */
.tr-frow { display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:9px 0; border-bottom:1px solid color-mix(in srgb,var(--bd) 55%,transparent); }
.tr-fadd { margin-top:14px; padding-top:14px; border-top:2px solid var(--bd); }
.tr-chk { display:flex; align-items:center; gap:7px; font-size:13px; color:var(--ink); margin:6px 0 12px; cursor:pointer; }
.tr-cfblock { margin-top:14px; padding-top:12px; border-top:2px solid var(--bd); }
.tr-cfblock-h { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.05em;
  color:var(--ink-faint); margin-bottom:9px; }

/* ── Batch intake: one input per tool ─────────────────────────
   A scanner sends the code then Enter, so Enter opens the next box. Pasting a
   column splits across boxes rather than stuffing 100 serials into one. */
.tu-serrow { display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.tu-sern { flex:0 0 22px; text-align:right; font-size:11px; color:var(--ink-faint);
  font-variant-numeric:tabular-nums; }
.tu-ser { flex:1; min-width:0; padding:7px 10px; border:1px solid var(--bd); border-radius:7px;
  background:var(--white); color:var(--ink); font-size:13px;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }
.tu-ser:focus { outline:none; border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 18%,transparent); }
.tu-serbar { display:flex; align-items:center; gap:8px; margin-top:8px; }
.tu-serbar .tr-dim { margin-left:auto; font-size:12px; }
#tu-serlist { max-height:240px; overflow-y:auto; padding-right:2px; }

/* The no-serials fallback is folded away — it is the exception, not the path. */
.tu-noser { margin-top:12px; }
.tu-noser summary { cursor:pointer; font-size:12.5px; color:var(--ink-soft); }
.tu-noser summary:hover { color:var(--accent); }

/* Says what is about to be created, before it is. */
.tu-preview { font-size:12.5px; margin:10px 0 0; color:var(--ink-faint); }
.tu-preview.on { color:var(--accent); font-weight:600; }

/* Inline category creation, inside the unit form. */
.tu-catrow { display:flex; gap:6px; align-items:center; }
.tu-catrow select { flex:1; min-width:0; }
.tu-catnew { display:flex; gap:6px; align-items:center; margin-top:7px; }
.tu-catnew input { flex:1; min-width:0; padding:7px 10px; border:1px solid var(--accent);
  border-radius:7px; background:var(--white); color:var(--ink); font-size:13px; }
.tu-catnew input:focus { outline:none; box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 18%,transparent); }
/* Rename-in-place in the category manager. */
.tr-cname { flex:1; min-width:0; padding:6px 9px; border:1px solid transparent; border-radius:6px;
  background:transparent; color:var(--ink); font-size:13px; font-weight:600; }
.tr-cname:hover { border-color:var(--bd); }
.tr-cname:focus { outline:none; border-color:var(--accent); background:var(--white);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 15%,transparent); }

/* Field-level hints — explain the mechanic before it is used, not after it
   surprises someone. */
.tu-hint { display:block; font-size:11.5px; line-height:1.45; color:var(--ink-faint); margin:4px 0 0; }
.tu-hint b { color:var(--ink-soft); font-family:ui-monospace,Menlo,monospace; }
.tu-noser .tu-hint:first-of-type { margin-top:10px; }

/* ── Telemetry ────────────────────────────────────────────────
   Same components at every scope, so a branch reads like the org and a job
   reads like both. */
.tr-kpis { display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:12px; margin-bottom:16px; }
.tr-kpi { border:1px solid var(--bd); border-radius:12px; padding:14px 16px; background:var(--white); box-shadow:var(--shadow); }
.tr-kpi-l { font-size:10.5px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-faint); }
.tr-kpi-v { font-size:26px; font-weight:800; color:var(--ink); margin:5px 0 2px; font-variant-numeric:tabular-nums; }
.tr-kpi-s { font-size:11.5px; color:var(--ink-faint); line-height:1.4; }
.tr-kpi.bad .tr-kpi-v { color:#B91C1C; }

.tr-statgrid { display:grid; grid-template-columns:repeat(auto-fit,minmax(110px,1fr)); gap:10px; }
.tr-stat { border:1px solid var(--bd); border-radius:10px; padding:11px 12px; text-align:center; background:var(--white); }
.tr-stat-n { font-size:20px; font-weight:800; color:var(--ink); font-variant-numeric:tabular-nums; }
.tr-stat-l { font-size:11px; color:var(--ink-faint); margin-top:2px; }
.tr-stat.bad  { border-color:color-mix(in srgb,#B91C1C 45%,var(--bd)); }
.tr-stat.bad .tr-stat-n  { color:#B91C1C; }
.tr-stat.warn { border-color:color-mix(in srgb,#B45309 45%,var(--bd)); }
.tr-stat.warn .tr-stat-n { color:#B45309; }

.tr-period { font-weight:400; text-transform:none; letter-spacing:0; color:var(--ink-faint); font-size:11.5px; }
.tr-lossval { font-size:13px; font-weight:700; color:#B91C1C; margin:11px 0 0; }
.tr-warnline { display:flex; align-items:center; gap:7px; font-size:12.5px; color:#B45309; margin:0 0 10px; }
.tr-r { text-align:right; font-variant-numeric:tabular-nums; }
.tr-ev { font-size:11px; font-weight:700; padding:2px 8px; border-radius:999px;
  background:var(--bg2); color:var(--ink-soft); white-space:nowrap; }
.tr-ev.bad { background:color-mix(in srgb,#B91C1C 12%,transparent); color:#B91C1C; }

/* ── One tool ─────────────────────────────────────────────────
   Rows open the item; the action buttons keep their own clicks. */
.tr-rowlink { cursor:pointer; }
.tr-dhead { display:flex; align-items:flex-start; gap:14px; margin-bottom:18px; flex-wrap:wrap; }
.tr-dtitle { flex:1; min-width:200px; }
.tr-dtitle h2 { margin:0; font-size:20px; font-weight:800; color:var(--ink); }
.tr-dsub { font-size:13px; color:var(--ink-soft); margin-top:2px; }
.tr-dacts { display:flex; gap:8px; flex-wrap:wrap; }
.tr-note { font-size:13.5px; color:var(--ink); line-height:1.55; margin:0; }
.tr-stbadge { display:inline-block; padding:2px 10px; border-radius:999px; font-size:13px; font-weight:700;
  background:var(--bg2); color:var(--ink-soft); }
.tr-stbadge.s-available { background:color-mix(in srgb,#15803D 12%,transparent); color:#15803D; }
.tr-stbadge.s-assigned  { background:color-mix(in srgb,var(--accent) 14%,transparent); color:var(--accent); }
.tr-stbadge.s-out_for_repair { background:color-mix(in srgb,#B45309 14%,transparent); color:#B45309; }
.tr-stbadge.s-lost, .tr-stbadge.s-stolen { background:color-mix(in srgb,#B91C1C 12%,transparent); color:#B91C1C; }

/* One timeline — custody and lifecycle woven together, because the merge IS
   the story and two tables would make the reader do it. */
.tr-tl { list-style:none; margin:0; padding:0; }
.tr-tl-i { display:flex; gap:12px; padding:10px 0 10px 12px; border-left:2px solid var(--bd);
  position:relative; align-items:flex-start; }
.tr-tl-i::before { content:''; position:absolute; left:-5px; top:15px; width:8px; height:8px;
  border-radius:50%; background:var(--bd); }
.tr-tl-i.bad  { border-left-color:#B91C1C; }
.tr-tl-i.bad::before  { background:#B91C1C; }
.tr-tl-i.warn { border-left-color:#B45309; }
.tr-tl-i.warn::before { background:#B45309; }
.tr-tl-d { flex:0 0 84px; font-size:11.5px; color:var(--ink-faint); padding-top:1px; }
.tr-tl-k { flex:0 0 116px; font-size:12px; font-weight:700; color:var(--ink-soft); }
.tr-tl-i.bad .tr-tl-k  { color:#B91C1C; }
.tr-tl-i.warn .tr-tl-k { color:#B45309; }
.tr-tl-b { flex:1; min-width:0; font-size:13px; color:var(--ink); }
.tr-tl-n { font-size:12.5px; color:var(--ink-soft); margin-top:3px; }
.tr-tl-m { font-size:11.5px; color:var(--ink-faint); margin-top:2px; }

/* The full record on the item page. Anything the form collects is readable
   back here — otherwise the two screens describe different objects. */
.tr-facts { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:2px 20px; margin:0; }
.tr-fact { padding:8px 0; border-bottom:1px solid color-mix(in srgb,var(--bd) 45%,transparent); min-width:0; }
.tr-fact dt { font-size:10.5px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--ink-faint); }
.tr-fact dd { margin:2px 0 0; font-size:13.5px; color:var(--ink); word-break:break-word; }
.tr-fact-h { display:block; font-size:11px; color:var(--ink-faint); margin-top:1px; }

/* ── Containers ──────────────────────────────────────────────────
   A cart is an item AND a place. The badge has to read as a property of
   the item rather than a status, so it is quiet — it sits beside the name
   the way "3 inside" is a fact about the cart, not a warning about it. */
/* Two marks, deliberately opposite: a plain box for a thing that HOLDS
   items, an arrow going INTO a box for a thing that is inside one. They sit
   inline with the name at roughly cap height, so a column of names still
   scans as a column of names. */
.tr-boxtag, .tr-intag { display:inline-flex; align-items:center; gap:3px; vertical-align:baseline;
  position:relative; top:1px; white-space:nowrap; font-size:11px; font-weight:700; }
.tr-boxtag { color:var(--accent,#4F46E5); }
.tr-intag  { color:#7C3AED; }
.tr-boxtag i, .tr-intag i { font-size:14px; line-height:1; }
.tr-boxtag-n { font-size:10px; font-weight:800; line-height:1; padding:1px 4px; border-radius:20px;
  background:color-mix(in srgb, var(--accent) 14%, transparent); }
/* The header versions carry a word, so they get the pill treatment. */
.tr-boxtag.lg, .tr-intag.lg { font-size:11.5px; padding:2px 9px; margin-left:6px; border-radius:20px; top:-2px; }
.tr-boxtag.lg { background:var(--accent-bg,#EEF2FF); }
.tr-intag.lg  { background:color-mix(in srgb, #7C3AED 12%, transparent); }

/* "Sam Ruiz › Rolling Cart 2" — the responsible party, then the boxes to
   open. The separator is lighter than either end so the chain reads as one
   answer rather than a list. */
.tr-chain-sep { color:var(--ink-faint); margin:0 6px; font-weight:400; }
.tr-inbox { display:inline-flex; align-items:center; gap:4px; font-size:.86em; color:var(--ink-soft); }
.tr-inbox i { font-size:1em; opacity:.75; }

.tr-blk-act { margin-left:auto; }
.tr-warnline.info { color:var(--accent,#4F46E5); }
.tu-container-field { margin-top:2px; }
.tu-container-field .tr-chk { margin:0 0 4px; }

/* ── The destination picker ──────────────────────────────────────
   One search box over people, jobs, branches and containers. The list is
   scrollable rather than paged: you are looking for one known thing, and a
   pager would put it behind a click. */
.tr-pick { display:flex; align-items:center; gap:8px; padding:0 10px; border:1px solid var(--bd);
  border-radius:8px; background:var(--white); }
.tr-pick i { color:var(--ink-faint); font-size:15px; flex:0 0 auto; }
.tr-pick input { flex:1; min-width:0; border:0; background:transparent; padding:9px 0; font-size:13.5px;
  color:var(--ink); outline:none; }
.tr-picklist { max-height:236px; overflow-y:auto; margin-top:6px; }
.tr-picklist:empty { margin-top:0; }
.tr-pick-g { font-size:10px; font-weight:800; text-transform:uppercase; letter-spacing:.06em;
  color:var(--ink-faint); padding:8px 4px 4px; position:sticky; top:0; background:var(--white); }
.tr-pick-opt { display:flex; align-items:center; gap:9px; width:100%; text-align:left;
  padding:7px 8px; border:0; border-radius:7px; background:transparent; cursor:pointer; color:var(--ink); }
.tr-pick-opt:hover, .tr-pick-opt:focus-visible { background:var(--bg2); outline:none; }
.tr-pick-opt > i { color:var(--ink-faint); font-size:15px; flex:0 0 auto; }
.tr-pick-n { font-size:13.5px; font-weight:600; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.tr-pick-m { margin-left:auto; font-size:11px; color:var(--ink-faint); flex:0 0 auto;
  max-width:48%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.tr-pick-none { padding:12px 8px; font-size:12.5px; color:var(--ink-faint); }
.tr-chosen { display:flex; align-items:center; gap:8px; margin-top:8px; padding:8px 10px;
  border-radius:8px; background:var(--accent-bg,#EEF2FF); color:var(--ink); font-size:13.5px; }
.tr-chosen i { color:var(--accent,#4F46E5); }
.tr-chosen .btn-icon { margin-left:auto; }

/* ── Row tones ───────────────────────────────────────────────────
   The register shades rows the way the employee list does. Two rules keep it
   readable rather than decorative:

   1. The SHOP GETS NO TINT. It is where most of the register sits most of the
      time; tinting the resting state would leave the exceptions competing with
      a wall of colour instead of standing out of it.
   2. A decision beats a location. Lost, stolen, out-for-repair and retired
      override wherever the thing happens to be sitting.

   Tint carries the row; a 3px edge on the first cell carries the scan. The
   edge is what survives a dark theme and a projector, where a 6% wash does not,
   and it is why these do not rely on the background alone. */
.tr-t-employee       > td { background:color-mix(in srgb, var(--accent) 7%, transparent); }
.tr-t-employee       > td:first-child { box-shadow:inset 3px 0 0 0 var(--accent); }
.tr-t-project        > td { background:color-mix(in srgb, #0F766E 8%, transparent); }
.tr-t-project        > td:first-child { box-shadow:inset 3px 0 0 0 #0F766E; }
.tr-t-container      > td { background:color-mix(in srgb, #7C3AED 8%, transparent); }
.tr-t-container      > td:first-child { box-shadow:inset 3px 0 0 0 #7C3AED; }
.tr-t-branch         > td { background:color-mix(in srgb, #1D4ED8 7%, transparent); }
.tr-t-branch         > td:first-child { box-shadow:inset 3px 0 0 0 #1D4ED8; }
.tr-t-vendor         > td { background:color-mix(in srgb, #B45309 8%, transparent); }
.tr-t-vendor         > td:first-child { box-shadow:inset 3px 0 0 0 #B45309; }
.tr-t-mixed          > td { background:color-mix(in srgb, var(--ink-soft) 8%, transparent); }
.tr-t-mixed          > td:first-child { box-shadow:inset 3px 0 0 0 var(--ink-soft); }
.tr-t-out_for_repair > td { background:color-mix(in srgb, #B45309 11%, transparent); }
.tr-t-out_for_repair > td:first-child { box-shadow:inset 3px 0 0 0 #B45309; }
.tr-t-lost           > td { background:color-mix(in srgb, #B91C1C 10%, transparent); }
.tr-t-lost           > td:first-child { box-shadow:inset 3px 0 0 0 #B91C1C; }
.tr-t-stolen         > td { background:color-mix(in srgb, #B91C1C 15%, transparent); }
.tr-t-stolen         > td:first-child { box-shadow:inset 3px 0 0 0 #991B1B; }
/* Retired is the one that should recede rather than announce itself — it is
   still on the register only so its history stays reachable. */
.tr-t-retired        > td { color:var(--ink-faint); background:color-mix(in srgb, var(--ink-soft) 6%, transparent); }
.tr-t-retired        > td:first-child { box-shadow:inset 3px 0 0 0 var(--ink-faint); }

/* Hover has to stay visible on a tinted row, so it layers over the tint
   rather than being replaced by it. */
.tr-table tbody tr[class*="tr-t-"]:hover > td { background-image:linear-gradient(var(--bg2), var(--bg2)); }

/* ── The colour key, which is also the filter ────────────────────
   A key you can only read is a legend; a key you can click is a tool. Each
   chip filters to its tone, and clicking the active one clears it. */
.tr-legend { display:flex; flex-wrap:wrap; gap:6px; align-items:center; margin:0 0 10px; }
.tr-lg { display:inline-flex; align-items:center; gap:6px; padding:3px 9px 3px 6px;
  border:1px solid var(--bd); border-radius:999px; background:var(--white);
  font-size:11.5px; font-weight:600; color:var(--ink-soft); cursor:pointer; }
.tr-lg:hover { border-color:var(--ink-faint); color:var(--ink); }
.tr-lg.on { border-color:currentColor; background:var(--bg2); color:var(--ink); }
.tr-lg-sw { width:9px; height:9px; border-radius:3px; flex:0 0 auto; background:var(--ink-faint); }
.tr-lg-n { font-size:10.5px; font-weight:700; color:var(--ink-faint); }
.tr-lg.on .tr-lg-n { color:var(--ink-soft); }
.tr-lg.tr-t-shop           .tr-lg-sw { background:#15803D; }
.tr-lg.tr-t-employee       .tr-lg-sw { background:var(--accent); }
.tr-lg.tr-t-project        .tr-lg-sw { background:#0F766E; }
.tr-lg.tr-t-container      .tr-lg-sw { background:#7C3AED; }
.tr-lg.tr-t-branch         .tr-lg-sw { background:#1D4ED8; }
.tr-lg.tr-t-vendor         .tr-lg-sw { background:#B45309; }
.tr-lg.tr-t-mixed          .tr-lg-sw { background:var(--ink-soft); }
.tr-lg.tr-t-out_for_repair .tr-lg-sw { background:#B45309; }
.tr-lg.tr-t-lost           .tr-lg-sw { background:#B91C1C; }
.tr-lg.tr-t-stolen         .tr-lg-sw { background:#991B1B; }
.tr-lg.tr-t-retired        .tr-lg-sw { background:var(--ink-faint); }
.tr-lg-clear { border:0; background:transparent; color:var(--accent); font-size:11.5px;
  font-weight:600; cursor:pointer; padding:3px 6px; }

/* The "Where it is" card wears the same tone as the register row, as a left
   edge — the card is already busy with a value and a hint, so a full wash
   would fight the text it is meant to qualify. */
.tr-kpi[class*="tr-t-"] { border-left-width:4px; }
.tr-kpi.tr-t-employee       { border-left-color:var(--accent); }
.tr-kpi.tr-t-project        { border-left-color:#0F766E; }
.tr-kpi.tr-t-container      { border-left-color:#7C3AED; }
.tr-kpi.tr-t-branch         { border-left-color:#1D4ED8; }
.tr-kpi.tr-t-vendor         { border-left-color:#B45309; }
.tr-kpi.tr-t-mixed          { border-left-color:var(--ink-soft); }
.tr-kpi.tr-t-out_for_repair { border-left-color:#B45309; }
.tr-kpi.tr-t-lost           { border-left-color:#B91C1C; }
.tr-kpi.tr-t-stolen         { border-left-color:#991B1B; }
.tr-kpi.tr-t-retired        { border-left-color:var(--ink-faint); }
.tr-kpi.tr-t-shop           { border-left-color:#15803D; }

/* ── Links to another item ───────────────────────────────────────
   A container's name is a way in, not a label: "it's in the socket box" is
   half an answer if finding the socket box means going back to the register
   and searching for it. These inherit their surrounding colour so a chain
   still reads as one sentence, and announce themselves on hover rather than
   with permanent link-blue that would fight the row tints. */
.tr-ulink { color:inherit; text-decoration:none; cursor:pointer; border-radius:4px; }
.tr-ulink:hover, .tr-ulink:focus-visible { text-decoration:underline; text-underline-offset:2px; }
.tr-ulink:focus-visible { outline:2px solid var(--accent); outline-offset:1px; text-decoration:none; }
/* The header pill is a link too — keep the pill, drop the underline for it. */
a.tr-intag.lg:hover, a.tr-intag.lg:focus-visible { text-decoration:none; background:color-mix(in srgb, #7C3AED 20%, transparent); }

/* ── Labels ──────────────────────────────────────────────────── */
.tr-lab-ck { width:34px; text-align:center; }
.tr-lab-n { display:inline-flex; align-items:center; gap:5px; font-size:11.5px; color:var(--ink-soft); white-space:nowrap; }
.tr-lab-n input { width:52px; padding:5px 6px; border:1px solid var(--bd); border-radius:6px;
  background:var(--white); color:var(--ink); font-size:12.5px; }
.tr-labrow td { cursor:default; }

/* ── Scan ────────────────────────────────────────────────────
   Two columns on a desk, stacked on the phone that will actually be holding
   the camera. The viewfinder keeps a fixed aspect so the layout does not jump
   when the stream attaches. */
.tr-scan-wrap { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:start; }
@media (max-width:860px) { .tr-scan-wrap { grid-template-columns:1fr; } }
.tr-scan-cam { border:1px solid var(--bd); border-radius:12px; overflow:hidden; background:var(--bg2); }
.tr-scan-cam video { display:block; width:100%; aspect-ratio:4/3; object-fit:cover; background:#000; }
.tr-scan-off { display:flex; flex-direction:column; align-items:center; justify-content:center;
  aspect-ratio:4/3; color:var(--ink-faint); gap:6px; }
.tr-scan-off i { font-size:34px; }
.tr-scan-off p { margin:0; font-size:13px; }
/* The reticle is a guide, not a crop — the detector reads the whole frame. */
.tr-scan-ret { position:relative; margin:-27% auto 0; width:56%; aspect-ratio:1;
  border:2px solid rgba(255,255,255,.9); border-radius:14px; pointer-events:none;
  box-shadow:0 0 0 100vmax rgba(0,0,0,.28); }
.tr-scan-acts { display:flex; justify-content:center; gap:8px; padding:10px; }
.tr-scan-list { min-width:0; }
.tr-scan-do { display:flex; gap:8px; margin-top:10px; flex-wrap:wrap; }
