  :root{
    --ink:#141A24; --slate-900:#1C2530; --slate-700:#34414F; --slate-500:#5B6B7B;
    --line:#E4E8EE; --paper:#F6F7F9; --surface:#FFFFFF;
    --gold:#C8912A; --gold-bright:#E0A93E; --gold-soft:#FAF3E2;
    --danger:#C8332B; --warn:#92600A;
    --display:'Space Grotesk',ui-sans-serif,system-ui,sans-serif;
    --body:'IBM Plex Sans',ui-sans-serif,system-ui,sans-serif;
    --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,monospace;
    --radius:10px; --shadow:0 1px 2px rgba(20,26,36,.06),0 4px 16px rgba(20,26,36,.05);
    /* Assignment 16A — single source of truth for sidebar width. .main's
       grid track, .bulkbar's centering, and the responsive breakpoint all
       read this one variable so none of them can drift apart from another.
       Declared on :root (not #appshell) because .bulkbar renders outside
       #appshell and must inherit it too. */
    --sidebar-w:240px;
  }
  *{box-sizing:border-box}
  html,body{margin:0;padding:0}
  body{font-family:var(--body);background:var(--paper);color:var(--ink);-webkit-font-smoothing:antialiased;line-height:1.45}
  button{font-family:var(--body);cursor:pointer}
  input,select{font-family:var(--body)}
  .mono{font-family:var(--mono);font-variant-numeric:tabular-nums}

  /* ============================================================
     Assignment 16A — application shell (sidebar + workspace)
     ============================================================
     Replaces the old .appbar/.tabs horizontal chrome. Every .tab button
     keeps its pre-16A class/data-tab; go() (core-util.js) and every test's
     .tab[data-tab="..."] selector are unchanged. Nav-specific rules are
     scoped under .sidebar so a bare .tab/.count never leaks into an
     unrelated component. #appshell's data-active-tab (set by go()) is read
     below to size .wrap per active tab — see the Scan Studio override
     further down. ============================================= */
  #appshell{display:grid;grid-template-columns:var(--sidebar-w) 1fr;min-height:100vh}
  .sidebar{width:var(--sidebar-w);background:var(--slate-900);color:#fff;display:flex;flex-direction:column;gap:2px;padding:16px 0 24px;position:sticky;top:0;height:100vh;overflow-y:auto}
  .sidebrand{display:flex;flex-direction:column;gap:3px;padding:0 18px 18px;margin-bottom:4px;border-bottom:1px solid #2c3846}
  .sidebrand-top{display:flex;align-items:center;gap:10px;font-family:var(--display);font-weight:700;letter-spacing:.2px;font-size:14px}
  .sidebrand .dot{width:12px;height:12px;border-radius:3px;background:var(--gold-bright);box-shadow:0 0 0 3px rgba(224,169,62,.22);transform:rotate(45deg);flex-shrink:0}
  .sidebrand-name{white-space:nowrap}
  .sidebrand small{display:block;font-family:var(--body);font-weight:400;color:#9fb0c0;font-size:11px;letter-spacing:.3px;text-transform:uppercase;margin-left:22px;white-space:nowrap}
  .navgroup{margin-bottom:6px}
  .navlabel{font-family:var(--mono);font-size:10.5px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:#7d8fa2;padding:10px 18px 6px}
  .sidebar .tab{display:flex;align-items:center;width:100%;border:none;background:none;text-align:left;padding:9px 18px;font-family:var(--display);font-weight:600;font-size:13.5px;color:#c4cddb;border-left:2.5px solid transparent;white-space:nowrap}
  .sidebar .tab:hover{color:#fff;background:rgba(255,255,255,.04)}
  .sidebar .tab.active{color:#fff;border-left-color:var(--gold);background:rgba(255,255,255,.06)}
  .sidebar .tab .count{font-family:var(--mono);font-size:11px;color:#9fb0c0;margin-left:auto;font-weight:500;padding-left:8px}
  .sidebar .tab.active .count{color:#cdd8e3}

  /* ------------------------------------------------------------
     Assignment 18D — a collapsible nav group (eBay is its first and
     only instance).
     ------------------------------------------------------------
     The parent is a DISCLOSURE, not a destination: it carries no
     data-tab, never becomes a route, and its only job is to open and
     close the list beneath it. It still takes the .active treatment
     while one of its children is the active workspace, because a
     COLLAPSED group has to be able to say "you are in here".

     Children are indented by exactly one step and separated from the
     parent by a single hairline rail rather than by a box, an icon or a
     second background — the hierarchy is legible without any of them,
     and each extra device would be another border in a sidebar that
     already has enough. */
  .navsub{display:flex;flex-direction:column}
  .sidebar .navparent{display:flex;align-items:center;gap:8px;width:100%;border:none;background:none;text-align:left;padding:9px 18px;font-family:var(--display);font-weight:600;font-size:13.5px;color:#c4cddb;border-left:2.5px solid transparent;white-space:nowrap}
  .sidebar .navparent:hover{color:#fff;background:rgba(255,255,255,.04)}
  .sidebar .navparent.active{color:#fff;border-left-color:var(--gold)}
  .sidebar .navparent:focus-visible{outline:2px solid var(--gold-bright);outline-offset:-2px}
  .navparent-label{flex:0 0 auto}
  .sidebar .navparent .count{font-family:var(--mono);font-size:11px;color:#9fb0c0;margin-left:auto;font-weight:500;padding-left:8px}
  .sidebar .navparent.active .count{color:#cdd8e3}
  /* A restrained chevron: one 6px stroke pair, rotated. No icon font, no
     glyph that changes character between states. */
  .navchevron{width:10px;height:10px;flex:0 0 auto;position:relative}
  .navchevron::before{content:"";position:absolute;left:2px;top:2px;width:5px;height:5px;
    border-right:1.6px solid currentColor;border-bottom:1.6px solid currentColor;
    transform:rotate(-45deg);transform-origin:center;transition:transform .14s ease;opacity:.75}
  .sidebar .navparent[aria-expanded="true"] .navchevron::before{transform:rotate(45deg)}
  .navchildren{display:flex;flex-direction:column;margin-left:18px;border-left:1px solid #2c3846}
  .navchildren.collapsed{display:none}
  .sidebar .tab.navchild{padding:7px 14px;font-size:12.5px;font-weight:500;color:#9fb0c0;border-left:2px solid transparent;margin-left:-1px}
  .sidebar .tab.navchild:hover{color:#fff;background:rgba(255,255,255,.04)}
  .sidebar .tab.navchild.active{color:#fff;background:rgba(255,255,255,.07);border-left-color:var(--gold)}
  .sidebar .tab.navchild:focus-visible{outline:2px solid var(--gold-bright);outline-offset:-2px}

  /* Deliberately plain block flow, not a flex column: .wrap's own
     `margin:0 auto` centering (below) relies on ordinary block-level
     width/margin resolution. A flex-column parent would trigger flexbox's
     auto-margin-suppresses-stretch rule and shrink .wrap to its content
     width instead of filling/capping it. .workspacebar and .wrap already
     stack correctly as ordinary block siblings, exactly as .appbar/.tabs/
     .wrap did before this redesign. */
  .main{min-width:0}
  .workspacebar{display:flex;align-items:center;gap:16px;background:var(--surface);border-bottom:1px solid var(--line);padding:12px 24px;position:sticky;top:0;z-index:40}
  .workspace-title{font-family:var(--display);font-weight:700;font-size:14px;margin:0;color:var(--ink)}
  .barbtn{background:transparent;border:1px solid var(--line);color:var(--slate-700);padding:7px 12px;border-radius:8px;font-size:12.5px;font-weight:500}
  .barbtn:hover{border-color:#C3CCd6;color:var(--ink)}

  .main .wrap{max-width:1400px;margin:0 auto;padding:24px 24px 130px}
  /* Assignment 16A — Scan Studio needs materially more width than every
     other tab. A child of .wrap cannot exceed .wrap's own content-box width,
     so the override has to control .wrap itself (keyed off #appshell's
     data-active-tab, set by go()) rather than #tab-scanstudio directly. */
  #appshell[data-active-tab="scanstudio"] .main .wrap{max-width:none;padding-left:32px;padding-right:32px}

  /* Assignment 16A — narrower-desktop-window responsive step (this product
     is desktop/laptop-only per PRODUCT.md, so "narrower" means an
     unmaximized window, not a phone). --sidebar-w narrows so .main/.bulkbar
     follow automatically (single source of truth); every nav label stays
     fully visible text (no icon rail, no truncation) and no font-size drops
     below DESIGN.md's documented Title (13.5px) or Label (10.5px) floor —
     only the sidebar's own width and horizontal padding tighten. No .tab is
     ever display:none at this or any width. */
  @media(max-width:1100px){
    :root{ --sidebar-w:200px; }
    .sidebar .tab{ padding:9px 14px; }
    .navlabel{ padding:10px 14px 6px; }
    .sidebrand{ padding:0 14px 18px; }
    /* 18D — the collapsible group tightens with everything else. The
       indent step shrinks; it never disappears, because the indent IS
       the parent/child relationship at this width. */
    .sidebar .navparent{ padding:9px 14px; }
    .navchildren{ margin-left:14px; }
    .sidebar .tab.navchild{ padding:7px 12px; }
  }
  /* Assignment 13E.1 — Add Acquired Inventory overlay: hosts the SAME
     #tab-intake DOM as a full-viewport takeover instead of a tab switch, so
     the acquisition flow completes without leaving the Card Show workspace
     (.tab.active/data-tab stays "cardshows" throughout). No markup is
     duplicated — only #tab-intake's own display mode changes. */
  #tab-intake.overlay-mode{position:fixed;inset:0;z-index:70;background:var(--paper);overflow:auto;padding:20px 20px 60px}
  #tab-intake.overlay-mode>*{max-width:1180px;margin-left:auto;margin-right:auto}
  .panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
  /* Assignment 13E.1 — quieter panel treatment: drops the ambient shadow
     (Elevation & Depth's own resting-state shadow) without changing
     anything else, for content that's reachable but not yet the primary
     thing to attend to (e.g. Reconciliation while a show is still Active). */
  .panel-quiet{box-shadow:none}
  /* Assignment 13E.1 — archival treatment for content that's frozen/
     history-only (Legacy Manual Sales), reusing the same opacity + italic
     language already established for retired Value Box tiers/boxes
     (.vbtier-retired, .vbbox[data-archived]) rather than inventing a new one. */
  .dashpanel-archival{opacity:.85}
  .dashpanel-archival .dashhd{font-style:italic}
  h2.section{font-family:var(--display);font-size:19px;font-weight:700;margin:0 0 4px}
  .sub{color:var(--slate-500);font-size:13.5px;margin:0 0 20px}
  .eyebrow{font-family:var(--mono);font-size:11px;letter-spacing:1px;text-transform:uppercase;color:var(--gold);font-weight:600;margin-bottom:8px}

  .drop{border:1.5px dashed #C3CCd6;border-radius:var(--radius);background:var(--surface);padding:40px 24px;text-align:center;transition:border-color .15s,background .15s}
  .drop.drag{border-color:var(--gold);background:var(--gold-soft)}
  .drop h3{font-family:var(--display);margin:12px 0 4px;font-size:16px}
  .drop p{color:var(--slate-500);font-size:13px;margin:0 0 16px}
  .drop svg{color:var(--slate-500)}
  .filebtn{display:inline-block;background:var(--ink);color:#fff;border:none;padding:10px 18px;border-radius:8px;font-weight:600;font-size:13.5px}
  .filebtn:hover{background:#000}

  .grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
  @media(max-width:720px){.grid2{grid-template-columns:1fr}}
  .grid3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px}
  @media(max-width:720px){.grid3{grid-template-columns:1fr}}
  .fld textarea{width:100%;padding:9px 11px;border:1px solid var(--line);border-radius:8px;font-size:14px;background:#fff;font-family:inherit;resize:vertical}
  .fld textarea:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .imgslot{border:1.5px dashed #C3CCd6;border-radius:10px;height:110px;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:4px;cursor:pointer;font-size:11.5px;font-weight:600;color:var(--slate-500);text-align:center;position:relative;overflow:hidden;background:var(--surface)}
  .imgslot.has{border-style:solid}
  .imgslot.has img{width:100%;height:100%;object-fit:cover}
  .imgslot.drag{border-color:var(--gold);background:var(--gold-soft)}
  .imgslot .rm{position:absolute;top:4px;right:4px;background:rgba(20,26,36,.7);color:#fff;border:none;border-radius:5px;width:20px;height:20px;font-size:12px;cursor:pointer;line-height:1}
  .costunknown{background:#FFF4E0;color:var(--warn);font-size:10.5px;font-weight:700;padding:2px 7px;border-radius:5px;letter-spacing:.3px;white-space:nowrap}
  .costestimated{background:#EAF1FF;color:#2554A6;font-size:10.5px;font-weight:700;padding:2px 7px;border-radius:5px;letter-spacing:.3px;white-space:nowrap}
  label.fld{display:block;margin-bottom:12px}
  label.fld span{display:block;font-size:12px;font-weight:600;color:var(--slate-700);margin-bottom:5px}
  .fld input,.fld select{width:100%;padding:9px 11px;border:1px solid var(--line);border-radius:8px;font-size:14px;background:#fff}
  .fld input:focus,.fld select:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}

  .alloc{display:flex;gap:8px;flex-wrap:wrap;margin-top:2px}
  .alloc label{display:flex;align-items:center;gap:7px;border:1px solid var(--line);border-radius:8px;padding:9px 12px;font-size:13px;font-weight:500;cursor:pointer;background:#fff}
  .alloc label:has(input:checked){border-color:var(--gold);background:var(--gold-soft);color:#7a5a15}
  .alloc input{accent-color:var(--gold)}

  .summary{display:flex;gap:20px;flex-wrap:wrap;padding:14px 16px;background:var(--slate-900);color:#fff;border-radius:var(--radius);margin:18px 0}
  .summary .item{display:flex;flex-direction:column}
  .summary .k{font-size:10.5px;text-transform:uppercase;letter-spacing:.6px;color:#9fb0c0;font-weight:600}
  .summary .v{font-family:var(--mono);font-size:18px;font-weight:600;margin-top:2px}
  .summary .v.warn{color:var(--gold-bright)} .summary .v.ok{color:#7ee0a0}

  .tablewrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);background:#fff}
  table{border-collapse:collapse;width:100%;font-size:13px}
  th{background:#fafbfc;text-align:left;padding:10px 12px;font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--slate-500);font-weight:600;border-bottom:1px solid var(--line);white-space:nowrap}
  td{padding:9px 12px;border-bottom:1px solid var(--line);vertical-align:middle}
  tr:last-child td{border-bottom:none}
  tbody tr:hover{background:#fbfcfd}
  td.num,th.num{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums}
  .thumb{width:40px;height:56px;object-fit:contain;border-radius:4px;background:#f0f2f5;display:block}
  .cellcard{display:flex;align-items:center;gap:10px}
  .cellcard .nm{font-weight:600;line-height:1.25} .cellcard .meta{color:var(--slate-500);font-size:11.5px}
  .costinput{width:82px;padding:6px 8px;border:1px solid var(--line);border-radius:6px;font-family:var(--mono);font-size:12.5px;text-align:right}
  .costinput.locked{border-color:var(--gold);background:var(--gold-soft)}

  .btn{border:1px solid var(--line);background:#fff;color:var(--ink);padding:9px 15px;border-radius:8px;font-weight:600;font-size:13.5px}
  .btn:hover{border-color:#c7cfda}
  .btn.primary{background:var(--ink);color:#fff;border-color:var(--ink)} .btn.primary:hover{background:#000}
  .btn.primary:disabled{background:#c3ccd6;border-color:#c3ccd6;cursor:not-allowed}
  .btn.gold{background:var(--gold);border-color:var(--gold);color:#fff} .btn.gold:hover{filter:brightness(1.06)}
  .btn.ghost{background:transparent;border-color:transparent;color:var(--slate-500)} .btn.ghost:hover{color:var(--ink);background:#f0f2f5}
  .btn.sm{padding:6px 10px;font-size:12px}
  .row-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px}
  .cellactions{display:flex;gap:5px;flex-wrap:wrap}

  .chip{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:20px;font-size:11.5px;font-weight:600;white-space:nowrap}
  .chip::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.85}
  .chip.inv{background:#EEF1F4;color:#34414F} .chip.wn{background:#EFE9FB;color:#6D28D9}
  .chip.eb{background:#E6F0FD;color:#1D4ED8} .chip.gr{background:#FAF0DA;color:#92610A}
  .chip.sold{background:#E4F3EA;color:#15803D} .chip.ret{background:#EDEFF2;color:#64748B}
  .chip.cancelled{background:#FBE7E7;color:#B91C1C}
  /* Assignment 11E.1 — derived "in transit" indicator, shown alongside the
     Ordered status chip, so it needs a color distinct from every existing
     status chip rather than reusing one and reading as a second status. */
  .chip.transit{background:#E0F7F5;color:#0F766E}
  /* Assignment 13E.1 — dedicated Card Show lifecycle palette. Deliberately
     separate from the marketplace/transaction Fixed Status Palette above:
     Planned/Active/Reconciliation/Closed describe the show's own workflow
     state, not a channel or transaction outcome, so none of these reuse an
     existing chip color (previously Active/Reconciliation borrowed the
     Whatnot/Grading hues, colliding with Awaiting Import on the same page).
     Values are WCAG AA-checked at chip text size (>=4.5:1) — see DESIGN.md. */
  .chip.csplanned{background:#EEEFF1;color:#696D75}
  .chip.csactive{background:#E2F3F7;color:#0D7692}
  .chip.csrecon{background:#FBEFF2;color:#9D5A73}
  .chip.csclosed{background:#EDEEF1;color:#3A4250}

  /* condition + grade badges over card image */
  .cbadge{position:absolute;bottom:7px;left:7px;font-family:var(--display);font-weight:700;font-size:11px;letter-spacing:.4px;padding:2px 7px;border-radius:5px;color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3)}
  .cbadge.nm{background:#1a9d55}.cbadge.lp{background:#7aa020}.cbadge.mp{background:#d08a1a}
  .cbadge.hp{background:#d1691f}.cbadge.dmg{background:#c33}.cbadge.seal{background:#2563eb}.cbadge.other{background:#5B6B7B}
  .gbadge{position:absolute;bottom:7px;left:7px;font-family:var(--display);font-weight:700;font-size:11px;padding:2px 8px;border-radius:5px;color:#3a2a06;background:linear-gradient(180deg,#f2d27a,#d9a93a);box-shadow:0 1px 3px rgba(0,0,0,.3)}

  .invbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
  .search{flex:1;min-width:180px;position:relative}
  .search input{width:100%;padding:9px 11px 9px 34px;border:1px solid var(--line);border-radius:9px;font-size:14px;background:#fff}
  .search input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .search svg{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:var(--slate-500)}
  .filters{display:flex;gap:6px;flex-wrap:wrap}
  .fpill{border:1px solid var(--line);background:#fff;color:var(--slate-700);padding:7px 12px;border-radius:20px;font-size:12.5px;font-weight:600}
  .fpill.active{background:var(--ink);color:#fff;border-color:var(--ink)}
  .viewtoggle{display:flex;border:1px solid var(--line);border-radius:8px;overflow:hidden}
  .viewtoggle button{border:none;background:#fff;padding:8px 12px;color:var(--slate-500);font-size:15px;line-height:1}
  .viewtoggle button.active{background:var(--ink);color:#fff}

  .gallery{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px}
  .gcard{border:1px solid var(--line);border-radius:var(--radius);background:#fff;overflow:hidden;position:relative;transition:box-shadow .15s}
  .gcard:hover{box-shadow:var(--shadow)}
  .gcard.sel{box-shadow:0 0 0 2.5px var(--gold);border-color:var(--gold)}
  .gcard .imgwrap{aspect-ratio:5/7;background:#f0f2f5;display:flex;align-items:center;justify-content:center;overflow:hidden;position:relative}
  .gcard .imgwrap img{width:100%;height:100%;object-fit:contain}
  .gcard .gbody{padding:9px 10px 11px}
  .gcard .gnm{font-weight:600;font-size:12.5px;line-height:1.25;margin-bottom:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .gcard .gmeta{color:var(--slate-500);font-size:11px;margin-bottom:7px}
  .gcard .gfoot{display:flex;justify-content:space-between;align-items:center}
  .gcard .gprice{font-family:var(--mono);font-size:12px;font-weight:600}
  .gcard .gcost{font-size:11px;margin:2px 0 7px;display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}
  .gcard .gcost .paid{color:var(--slate-500)}
  .prof{font-weight:700} .prof.up{color:#15803d} .prof.down{color:#c8332b}
  .gcheck{position:absolute;top:8px;left:8px;width:22px;height:22px;border-radius:6px;border:1.5px solid #c3ccd6;background:rgba(255,255,255,.92);display:flex;align-items:center;justify-content:center;z-index:2;color:#fff;font-size:13px}
  .gcard.sel .gcheck{background:var(--gold);border-color:var(--gold)}
  .gcard .gsku{position:absolute;top:8px;right:8px;font-family:var(--mono);font-size:9.5px;background:rgba(20,26,36,.72);color:#fff;padding:2px 6px;border-radius:5px}

  /* Assignment 16A — recentered over the workspace (viewport minus the
     sidebar) rather than the full viewport, reading the same --sidebar-w
     token the shell layout uses so the two can never disagree. */
  .bulkbar{position:fixed;left:calc(var(--sidebar-w) + (100% - var(--sidebar-w))/2);bottom:20px;transform:translate(-50%,150%);background:var(--slate-900);color:#fff;border-radius:14px;padding:12px 14px;display:flex;align-items:center;gap:9px;box-shadow:0 12px 34px rgba(20,26,36,.32);z-index:50;transition:transform .22s cubic-bezier(.2,.8,.2,1);flex-wrap:wrap;max-width:94vw}
  .bulkbar.show{transform:translate(-50%,0)}
  .bulkbar .seln{font-family:var(--mono);font-weight:600;font-size:13px;padding-right:6px;border-right:1px solid #3a4756;margin-right:2px}
  .bulkbar button{border:none;border-radius:8px;padding:8px 12px;font-size:12.5px;font-weight:600;color:#fff;background:#2c3846}
  .bulkbar button:hover{filter:brightness(1.15)}
  .bulkbar button.wn{background:#6D28D9}.bulkbar button.eb{background:#1D4ED8}
  .bulkbar button.gr{background:#B07d17}.bulkbar button.sold{background:#15803D}.bulkbar button.ret{background:#4b5a6a}
  .bulkbar .x{background:transparent;color:#9fb0c0;padding:8px 8px}

  .lotrow{cursor:pointer}
  .lotdetail td{background:#fafbfc;padding:0}
  .lotdetail .inner{padding:12px 14px}
  .minicard{display:inline-flex;align-items:center;gap:8px;background:#fff;border:1px solid var(--line);border-radius:8px;padding:6px 10px;margin:0 8px 8px 0;font-size:12px}
  .minicard img{width:26px;height:36px;object-fit:contain;border-radius:3px;background:#f0f2f5}

  .empty{text-align:center;padding:52px 24px;color:var(--slate-500)}
  .empty h3{font-family:var(--display);color:var(--ink);margin:14px 0 6px;font-size:17px}
  .empty p{margin:0 0 18px;font-size:13.5px}

  .maptags{display:flex;flex-wrap:wrap;gap:6px}
  .maptag{font-size:11px;background:#eef1f4;border-radius:6px;padding:4px 8px;color:var(--slate-700)}
  .maptag b{color:var(--ink)} .maptag.miss{background:#fdecec;color:#b42318}

  /* Assignment 14I.1 — Value Box CSV import destination (Scope 1). Reuses
     .panel/.fld/.filters/.fpill/.sub verbatim; scoped additions only. */
  .intakevb-destpanel{margin-top:0}
  .intakevb-summary{margin-top:10px}
  .intakevb-vbstatus{font-size:12.5px;font-weight:600;color:var(--ink)}
  .intakevb-vbreason{font-size:11.5px;color:var(--slate-500);margin-top:1px}
  .intakevb-vbsel{margin-top:4px;font-size:12px}

  .toasts{position:fixed;top:16px;right:16px;display:flex;flex-direction:column;gap:8px;z-index:90}
  .toast{background:var(--ink);color:#fff;padding:11px 15px;border-radius:9px;font-size:13px;font-weight:500;box-shadow:0 8px 24px rgba(20,26,36,.28);opacity:0;transform:translateX(12px);transition:.2s}
  .toast.show{opacity:1;transform:none} .toast.good{background:#15803D}

  /* modal */
  .overlay{position:fixed;inset:0;background:rgba(20,26,36,.5);display:none;align-items:center;justify-content:center;z-index:70;padding:18px}
  .overlay.show{display:flex}
  .modalbox{background:#fff;border-radius:14px;width:100%;max-width:640px;max-height:88vh;display:flex;flex-direction:column;box-shadow:0 24px 60px rgba(20,26,36,.4);overflow:hidden}
  .modalhd{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--line);font-family:var(--display);font-weight:700;font-size:16px}
  .modalx{border:none;background:none;font-size:16px;color:var(--slate-500);padding:4px 6px}
  .modalbd{padding:18px 20px;overflow:auto}
  .modalft{padding:14px 20px;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:10px;flex-wrap:wrap}
  .choicecard{border:1px solid var(--line);border-radius:10px;padding:12px 14px;cursor:pointer;margin-bottom:10px}
  .choicecard:hover{border-color:var(--gold)}
  .choicecard.sel{border-color:var(--gold);background:var(--gold-soft)}
  .choicecard .t{font-weight:700;font-size:13.5px} .choicecard .m{color:var(--slate-500);font-size:12px}
  /* Assignment 14I.1 — Add Card chooser's "Find a card" primary badge.
     Scoped to this one chooser; copies .filterbadge's own existing
     values verbatim (font-size/radius/padding/colors) rather than
     inventing new ones. */
  .addcard-recbadge{display:inline-block;font-size:10.5px;font-weight:800;border-radius:9px;background:var(--gold);color:#1a1200;padding:1px 6px;margin-left:6px;vertical-align:middle}

  /* container lists (PSA / Whatnot) */
  .conlist{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(260px,1fr))}
  .concard{border:1px solid var(--line);border-radius:var(--radius);background:#fff;padding:15px 16px;cursor:pointer;box-shadow:var(--shadow);transition:box-shadow .15s}
  .concard:hover{box-shadow:0 6px 20px rgba(20,26,36,.08)}
  .concard .ct{font-family:var(--display);font-weight:700;font-size:15px;margin-bottom:2px}
  .concard .cm{color:var(--slate-500);font-size:12px;margin-bottom:10px}
  .concard .crow{display:flex;justify-content:space-between;font-size:12px;margin-top:4px}
  .concard .crow .lbl{color:var(--slate-500)} .concard .crow .val{font-family:var(--mono);font-weight:600}

  .detailhd{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-bottom:6px}
  .metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:12px;background:#fafbfc;border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px;margin:14px 0}
  .metagrid .k{font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600}
  .metagrid .v{font-family:var(--mono);font-size:15px;font-weight:600;margin-top:2px}
  .gradesel,.gradeinput{padding:6px 8px;border:1px solid var(--line);border-radius:6px;font-size:12.5px}
  .gradeinput{width:100%;font-family:var(--mono)}
  .slabrow td{background:#fff}
  .outcomepick{display:flex;gap:4px}
  .outcomepick button{border:1px solid var(--line);background:#fff;font-size:11px;padding:4px 8px;border-radius:6px;font-weight:600;color:var(--slate-500)}
  .outcomepick button.on-g{background:var(--gold);border-color:var(--gold);color:#fff}
  .outcomepick button.on-r{background:#4b5a6a;border-color:#4b5a6a;color:#fff}
  .outcomepick button.on-x{background:#c8332b;border-color:#c8332b;color:#fff}

  /* Dashboard (Assignment 9D, simplified in 9E) */
  .dashhdr{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;flex-wrap:wrap;margin-bottom:16px}
  .dashcaption{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600;margin:22px 0 8px}
  .dashcaption-workspace{margin-top:14px}
  .dashcaption-tight{margin-top:2px}
  .dashhd{font-family:var(--display);font-size:13.5px;font-weight:700;color:var(--ink);margin:22px 0 10px}
  .dashgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:12px;margin-bottom:4px}
  .dashgrid3{grid-template-columns:repeat(3,1fr)}
  @media(max-width:720px){.dashgrid3{grid-template-columns:1fr}}
  .dashcols{display:grid;grid-template-columns:1fr 1fr;gap:24px;margin-top:4px}
  @media(max-width:860px){.dashcols{grid-template-columns:1fr}}

  .monthnav{display:flex;align-items:center;gap:6px}
  .monthnav select{padding:7px 10px;border:1px solid var(--line);border-radius:8px;font-size:13px;font-weight:600;color:var(--ink);background:#fff}
  .monthnav select:focus{outline:none;border-color:var(--gold)}
  .monthnav .btn{padding:6px 10px;line-height:1}
  .monthnav .btn:disabled{opacity:.35;cursor:default}

  .statcard{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:14px 16px}
  .statcard .stat-label{font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600;margin-bottom:7px}
  .statcard .stat-value{font-family:var(--mono);font-size:20px;font-weight:600;color:var(--ink);letter-spacing:-.2px;word-break:break-word}
  .statcard .stat-sub{font-size:11px;color:var(--slate-500);margin-top:5px;line-height:1.35}

  /* Compact metagrid-based panel — reuses .metagrid's label/value pattern
     instead of one large statcard per metric, per 9E's "reduce card count". */
  .dashpanel{padding:14px 16px 16px}
  .dashpanel .metagrid{margin:0;background:transparent;border:none;padding:0}
  .dashpanel .metagrid .v{font-size:16px}
  .dashpanel .dashnote{font-size:11.5px;color:var(--slate-500);margin-top:10px}
  .dashpanel .empty{padding:6px 2px;text-align:left}
  .dashpanel .empty p{margin:0}

  .cmprow{display:flex;flex-wrap:wrap;gap:14px 22px;margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
  .cmprow .cmpitem{font-size:11.5px;color:var(--slate-500)}
  .cmprow .cmpitem b{color:var(--ink);font-weight:600}
  .cmp{font-family:var(--mono);font-weight:600;margin-left:4px}
  .cmp.cmp-pos{color:#15803D} .cmp.cmp-neg{color:#C8332B} .cmp.cmp-neutral{color:var(--slate-500)}

  .dashlist{display:flex;flex-direction:column;gap:8px}
  .attn-item{background:var(--surface);border:1px solid var(--line);border-left:3px solid var(--slate-500);border-radius:8px;padding:11px 13px;cursor:pointer}
  .attn-item:hover{box-shadow:var(--shadow)}
  .attn-item.attn-info{border-left-color:#2554A6}
  .attn-item.attn-warn{border-left-color:var(--gold)}
  .attn-item.attn-bad{border-left-color:#C8332B}
  .attn-item .attn-text{font-weight:600;font-size:13px;color:var(--ink)}
  .attn-item .attn-detail{font-size:12px;color:var(--slate-500);margin-top:3px}
  .attn-item .attn-go{margin-top:8px}

  /* Recent activity — a compact one-line-per-row timeline, not a card per item. */
  .acttimeline{display:flex;flex-direction:column}
  .acttimeline .ti{display:flex;align-items:baseline;gap:10px;padding:7px 2px;border-bottom:1px solid var(--line);cursor:pointer}
  .acttimeline .ti:last-child{border-bottom:none}
  .acttimeline .ti:hover{background:#fafbfc}
  .acttimeline .ti-date{font-family:var(--mono);font-size:10.5px;color:var(--slate-500);min-width:46px;flex-shrink:0}
  .acttimeline .ti-text{flex:1;font-size:12.5px;font-weight:500;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .acttimeline .ti-amt{font-family:var(--mono);font-size:11.5px;color:var(--slate-700);white-space:nowrap}

  .comingsoonrow{font-size:11.5px;color:var(--slate-500);padding:10px 2px 0;margin-top:18px;border-top:1px solid var(--line)}
  .comingsoonrow b{color:var(--slate-700);font-weight:600}

  /* Card Shows (Assignment 10A) — reuses the 9E dashboard language */
  .csbanner{background:var(--gold-soft);border:1px solid #ecd9a9;border-radius:8px;padding:10px 13px;font-size:12.5px;color:#7a5a15;line-height:1.4}
  .csbanner b{color:#6a4d12}
  .csacqgrid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
  @media(max-width:720px){.csacqgrid{grid-template-columns:1fr}}
  .dashcols3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px}
  @media(max-width:860px){.dashcols3{grid-template-columns:1fr}}
  .csrow{cursor:pointer}
  .csnote{display:flex;justify-content:space-between;gap:10px;align-items:flex-start;padding:8px 0;border-bottom:1px solid var(--line)}
  .csnote:last-child{border-bottom:none}
  .csnote-text{font-size:12.5px;color:var(--ink);line-height:1.35}
  .csnote-meta{font-family:var(--mono);font-size:10.5px;color:var(--slate-500);margin-top:2px}
  .csnote-actions{display:flex;gap:2px;flex-shrink:0}

  /* Assignment 10B */
  .pctpaid{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
  .pctpaid .pctlabel{font-size:12.5px;font-weight:600;color:var(--slate-700)}
  .pctpaid input{padding:7px 9px;border:1px solid var(--line);border-radius:8px;font-size:13px}
  .pctpaid input:focus{outline:none;border-color:var(--gold)}
  .methodsel{padding:5px 7px;border:1px solid var(--line);border-radius:6px;font-size:12px;background:#fff;max-width:150px}
  .ncsection{border-top:1px solid var(--line);padding-top:12px}
  .ncmini{font-size:11.5px;color:var(--slate-500);margin-top:8px;line-height:1.5}

  /* Assignment 11A — Active Card Show Workspace */
  .cswork-actions{display:flex;gap:8px;flex-wrap:wrap;margin:6px 0 4px}
  /* Assignment 13E.1 — grouped action bar: Sales / Acquisitions / Other,
     separated by the system's ordinary 1px Line divider (not a colored
     accent), with one small uppercase label per group. */
  .cswork-actgroup{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding-right:14px;border-right:1px solid var(--line)}
  .cswork-actgroup:last-child{border-right:none;padding-right:0}
  .cswork-actlabel{font-family:var(--mono);font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600;margin-right:2px}
  .cswork-timeline{max-height:340px;overflow:auto}
  .cswork-timeline .ti[data-goto]{cursor:pointer}
  .ti-amt.ti-pos{color:#15803D} .ti-amt.ti-neg{color:#C8332B} .ti-amt.ti-neutral{color:var(--slate-700)}

  /* ============================================================
     Assignment 13E.1B — Active Card Show Workspace visual transformation.
     Every rule below is scoped under .csworkspace (see index.html's
     #csDetail) so none of it reaches Dashboard, Purchases, or any other
     tab — this is a presentation-only pass over one workspace, not a
     shared-component or app-shell change. No shared class (.panel,
     .dashpanel, .dashcaption, table, .btn, .chip, .metagrid, .attn-item)
     is redefined; everything here is additive and scoped. ============= */
  .csworkspace .backlink{margin-bottom:14px}
  .csworkspace .backlink:hover{background:transparent;text-decoration:underline}

  /* Show identity header: a single contained panel instead of a bare flex row,
     so name/date/venue/fee/status read as one scannable unit (13E.1B §2). */
  .csworkspace .cshead{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:18px 22px 16px;margin-bottom:4px}
  .csworkspace .cshead .detailhd{margin-bottom:0}
  .csworkspace .cshead-meta{font-family:var(--mono);font-size:12.5px;color:var(--slate-500);margin:3px 0 0}
  .csworkspace .cshead-side{display:flex;flex-direction:column;align-items:flex-end;gap:10px}
  .csworkspace .cshead-actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}
  .csworkspace .cshead-notes{font-size:12.5px;color:var(--slate-500);margin:10px 0 0;padding-top:10px;border-top:1px solid var(--line)}

  /* Section rhythm: a consistent divider + spacing step between the workspace's
     major regions (13E.1B §1) — the system's ordinary 1px Line rule used as a
     horizontal separator, never a colored accent. */
  .csworkspace .cszone{margin-top:32px;padding-top:24px;border-top:1px solid var(--line)}
  .csworkspace .cszone > p.dashcaption:first-child{margin-top:0}

  /* Needs Attention: a contained, tinted alert surface with a leading status
     dot — deliberately NOT the side-tab/border-left treatment (craft-floor
     ban); text is tinted from the gold-soft surface's own hue, never gray,
     both combinations verified ≥4.5:1. */
  .csworkspace .csattn-list{display:flex;flex-direction:column;gap:8px}
  .csworkspace .csattn-item{display:flex;align-items:center;gap:12px;background:var(--gold-soft);border:1px solid #ecd9a9;border-radius:8px;padding:11px 14px}
  .csworkspace .csattn-dot{width:8px;height:8px;border-radius:50%;background:var(--gold);flex-shrink:0}
  .csworkspace .csattn-body{flex:1;min-width:0}
  .csworkspace .csattn-text{font-weight:600;font-size:13px;color:#7a5a15}
  .csworkspace .csattn-detail{font-size:11.5px;color:#8a6520;margin-top:2px}

  /* The action bar becomes a contained command surface (13E.1B §3) — the
     existing .cswork-actions/.cswork-actgroup grouping and every button id
     are unchanged; this only gives the row a bordered, padded surface. */
  .csworkspace .cscommandbar{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);padding:14px 18px}
  .csworkspace .cscommandbar .cswork-actions{margin:0}

  /* Running Activity: grouped metric panels replacing the flat metagrid
     (13E.1B §4). Rows, not nested cards, live inside each group panel — a
     row never carries its own border/shadow, avoiding a nested-card layout.
     Every figure below is read from the same csRunningActivity(cs) object
     used before this pass; no value here is computed differently. */
  .csworkspace .csmetrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px;margin:14px 0}
  @media(max-width:720px){.csworkspace .csmetrics{grid-template-columns:1fr}}
  .csworkspace .csmetric-group{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:14px 16px}
  .csworkspace .csmetric-grouplabel{font-family:var(--mono);font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600;margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--line)}
  .csworkspace .csmetric-row{display:flex;justify-content:space-between;align-items:baseline;gap:10px;padding:6px 0}
  .csworkspace .csmetric-row+.csmetric-row{border-top:1px solid var(--line)}
  .csworkspace .csmetric-row .k{font-size:12px;color:var(--slate-700)}
  .csworkspace .csmetric-row .v{font-family:var(--mono);font-size:13px;font-weight:600;color:var(--ink);text-align:right;white-space:nowrap}
  .csworkspace .csmetric-row .v .csmetric-detail{display:block;font-weight:400;font-size:10.5px;color:var(--slate-500);margin-top:1px;white-space:normal}
  .csworkspace .csmetric-row.csmetric-primary{background:var(--paper);margin:0 -16px;padding:8px 16px;border-radius:6px}
  .csworkspace .csmetric-row.csmetric-primary .k{font-weight:600;color:var(--ink)}
  .csworkspace .csmetric-row.csmetric-primary .v{font-size:16px}

  /* Collapsed accounting-explanation disclosures (13E.1B §4/§7) — native
     <details>, no new JS. Content is unchanged, only its default visibility. */
  .csworkspace .csdetails{margin-top:10px}
  .csworkspace .csdetails summary{cursor:pointer;font-family:var(--mono);font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--slate-500);font-weight:600;list-style:none;display:flex;align-items:center;gap:6px;padding:2px 0}
  .csworkspace .csdetails summary::-webkit-details-marker{display:none}
  .csworkspace .csdetails summary::before{content:"▸";font-size:10px;color:var(--slate-500);transition:transform .12s}
  .csworkspace .csdetails[open] summary::before{transform:rotate(90deg)}
  .csworkspace .csdetails summary:hover{color:var(--ink)}
  .csworkspace .csdetails-body{font-size:11.5px;color:var(--slate-500);margin-top:8px;line-height:1.5}

  /* Table + panel polish (13E.1B §7) — slightly roomier panels, stronger
     header contrast; no data, column, or action is added or removed. */
  .csworkspace .dashpanel{padding:16px 18px 18px}
  .csworkspace table th{color:var(--slate-700);font-weight:700;border-bottom:1.5px solid var(--line)}
  .csworkspace table td{padding:10px 12px}

  /* Assignment 11B — structured card show sale builder */
  /* 11B.1 — rebalanced ~40/60 (results/builder) via 2fr/3fr, was ~42/58 */
  .modalbox.cssale-modal{max-width:920px}
  .cssale{display:grid;grid-template-columns:minmax(200px,2fr) minmax(340px,3fr);gap:16px;align-items:start}
  .cssale-results{max-height:44vh;overflow:auto;border:1px solid var(--line);border-radius:8px}
  .cssale-row{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:7px 10px;border-bottom:1px solid var(--line)}
  .cssale-row:last-child{border-bottom:none}
  .cssale-row:hover{background:#fafbfc}
  .cssale-rowmain{min-width:0;flex:1}
  .cssale-fields{margin-top:12px}
  @media (max-width:720px){ .cssale{grid-template-columns:1fr} }

  /* 11B.1 — thumbnails + hover preview (visual only; see cssThumbSrc/cssThumbHTML in app.js) */
  .cssale-thumbwrap{display:inline-flex;flex-shrink:0}
  .cssale-thumb{width:42px;height:56px;object-fit:cover;border-radius:4px;border:1px solid var(--line);background:#f4f6f8;display:block;cursor:default}
  .cssale-hoverpreview{position:fixed;display:none;z-index:80;max-width:200px;max-height:280px;width:auto;height:auto;object-fit:contain;border:1px solid var(--line);border-radius:8px;background:#fff;box-shadow:0 10px 30px rgba(20,26,36,.35);padding:4px;pointer-events:none}

  /* Assignment 11C — quantity-aware inventory + sale builder.
     .qtybadge is rendered on EVERY inventory card/row for consistent markup;
     data-multi="0" (a single copy) is muted so multi-copy positions are the
     ones that catch the eye. */
  .qtybadge{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.3px;padding:1px 6px;border-radius:5px;vertical-align:middle;background:var(--blue-50,#EAF2FE);color:var(--blue-700,#1B4F9C);border:1px solid rgba(27,79,156,.18)}
  .qtybadge[data-multi="0"]{background:transparent;color:var(--slate-500);border-color:var(--line);font-weight:600}
  .cssale-avail{display:inline-block;font-size:10.5px;font-weight:700;padding:1px 6px;border-radius:5px;background:#EAF7EE;color:#15803D;border:1px solid rgba(21,128,61,.18);white-space:nowrap}
  .cssale-avail[data-avail="0"]{background:#FDECEA;color:#C8332B;border-color:rgba(200,51,43,.2)}
  .cssale-qty{display:inline-flex;align-items:center;gap:2px;justify-content:flex-end;white-space:nowrap}
  .cssale-qty .btn.sm{padding:1px 5px;min-width:20px;line-height:1.2;font-weight:700}
  .cssale-qty .btn.sm[disabled]{opacity:.4;cursor:not-allowed}
  .cssale-qty .cssQtyInput{width:40px;text-align:center;padding:3px 2px}
  .cssale-ofqty{font-size:10px;color:var(--slate-500);text-align:right;margin-top:1px}
  /* The Qty column pushes this table past the pane's width, so let it scroll
     horizontally inside its own wrapper instead of crushing the card name to
     one character per line. */
  .cssale-selwrap{overflow:auto}
  .cssale-seltable{min-width:520px}
  .cssale-seltable td,.cssale-seltable th{padding-left:6px;padding-right:6px}
  .cssale-cardcell{min-width:150px}
  .cssale-cardcell .meta{white-space:normal}
  .cssale-seltable .cssAllocInput{width:74px;text-align:right}

  /* Assignment 11D — Value Box workspace, tiers, containers */
  .vbboxtabs{display:flex;gap:6px;flex-wrap:wrap;margin:4px 0 14px;border-bottom:1px solid var(--line);padding-bottom:10px}
  .vbboxtab{background:transparent;border:1px solid var(--line);border-radius:8px;padding:6px 12px;font-size:12.5px;font-weight:600;cursor:pointer;color:var(--slate-700,#334155);display:inline-flex;align-items:center;gap:6px}
  .vbboxtab:hover{background:#f4f6f8}
  .vbboxtab.active{background:var(--ink,#141a24);color:#fff;border-color:var(--ink,#141a24)}
  .vbboxtab-review{border-color:rgba(200,51,43,.35);color:#C8332B}
  .vbboxtab-review.active{background:#C8332B;border-color:#C8332B;color:#fff}
  .vbboxn{font-size:11px;font-weight:700;opacity:.75}
  .vbbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:12px}
  .vbbar .search{flex:1;min-width:200px}
  .vbtier{display:inline-block;font-size:10.5px;font-weight:700;padding:2px 8px;border-radius:5px;white-space:nowrap;
    background:color-mix(in srgb, var(--vbc, #64748B) 14%, transparent);color:var(--vbc,#64748B);border:1px solid color-mix(in srgb, var(--vbc,#64748B) 35%, transparent)}
  .vbtier-retired{opacity:.65;text-decoration:line-through}
  .vbtier-missing,.vbbox-missing{background:#FDECEA;color:#C8332B;border:1px solid rgba(200,51,43,.25)}
  .vbbox{display:inline-block;font-size:10.5px;font-weight:700;padding:2px 8px;border-radius:5px;white-space:nowrap;background:#EEF2F7;color:#334155;border:1px solid var(--line)}
  .vbbox[data-archived="1"]{opacity:.6;font-style:italic}
  .vbswatch{display:inline-block;width:11px;height:11px;border-radius:3px;vertical-align:middle;border:1px solid rgba(0,0,0,.12)}
  .vbtierrow{display:flex;align-items:center;gap:10px;padding:6px 2px;border-bottom:1px solid var(--line);font-size:12.5px}
  .vbtierrow:last-child{border-bottom:none}
  .vbtierrow-name{font-weight:600;min-width:110px}
  .vbtierrow-price{font-weight:700;min-width:60px}
  .vbtierrow-range{flex:1}
  .vbtierrow-n{font-weight:600}
  .vbtier-retiredrow{opacity:.6}
  .vbbulk{display:none;gap:8px;align-items:center;flex-wrap:wrap;padding:9px 12px;margin:10px 0;border:1px solid var(--line);border-radius:9px;background:#f7f9fb;font-size:12.5px;font-weight:600}
  .vbbulk.show{display:flex}
  .cssale-vbline{display:flex;gap:5px;flex-wrap:wrap;margin:2px 0}
  /* Batch-assignment dialog: rows already partly committed this session, and
     the running "assigned so far" trail. */
  .vba-touched{background:#F2FAF4}
  .vba-touchnote{font-size:10.5px;font-weight:700;color:#15803D;margin-top:2px}
  .vba-session{background:#F2FAF4;border:1px solid rgba(21,128,61,.22)}
  /* Import-suggestion thumbnail cell: keeps the column as narrow as the image
     itself so the thumbnail adds width, not row height, beyond the 56px the
     shared .cssale-thumb already defines. */
  /* Assignment 11D Final Polish — shared search/sort/filter toolbar,
     reused by both the Inventory tab and the Value Box Cards list. */
  .sortselect{padding:9px 11px;border:1px solid var(--line);border-radius:8px;font-size:13px;font-weight:600;color:var(--ink);background:#fff;max-width:230px}
  .btn.ghost.sm.active{background:var(--ink);color:#fff;border-color:var(--ink)}
  .filterbadge{display:inline-block;background:var(--gold);color:#1a1200;font-size:10.5px;font-weight:800;border-radius:9px;padding:1px 6px;margin-left:3px;vertical-align:middle}
  .filterpanel{border:1px solid var(--line);border-radius:var(--radius);background:#fafbfc;padding:14px 16px;margin:10px 0}
  .filterpanel .grid3{margin-bottom:10px} .filterpanel .grid3:last-child,.filterpanel .grid2:last-child{margin-bottom:0}
  .filterpanel .grid2{margin-bottom:10px}

  /* Assignment 13B — Settings / Payment Profiles. The list reuses .tablewrap
     and .chip wholesale; these two rules only give the secondary lines under
     each profile the same muted treatment .cellcard .meta already has. */
  #ppCards td{vertical-align:top}
  #ppCards .meta{color:var(--slate-500);font-size:11.5px;margin-top:2px}

  .vbi-thumbcell,.vb-thumbcell{width:1%;white-space:nowrap;padding-right:4px}
  .vbi-thumbcell .cssale-thumb{cursor:zoom-in}
  /* The 56px thumbnail is now the tallest thing in the row, so trim the
     surrounding vertical padding — the image sets the height, not dead space. */
  .vbi-row td{padding-top:5px;padding-bottom:5px;vertical-align:middle}

  /* Assignment 10C — trade acquisition */
  .tradesec{border-top:1px solid var(--line);margin-top:14px;padding-top:12px}
  .tradesechd{display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
  .tradesechd span{font-weight:700;font-size:12.5px}
  .tradetotals{margin-top:12px}

  .hide{display:none!important}
  .checkcell input{width:16px;height:16px;accent-color:var(--gold);cursor:pointer}
  .foot{margin-top:24px;color:var(--slate-500);font-size:12px;display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap}

  /* Assignment 14C — Catalog Search UI. Everything here is scoped under
     .catsearch (the modal body's own wrapper) so nothing shared is
     redefined; the modal shell itself (.modalbox/.modalhd/.modalbd/.modalft)
     is the existing stackedModal() pattern, untouched. */
  .catsearch-ctx{font-family:var(--body);font-weight:400;font-size:13px;color:var(--slate-500);margin-top:3px}
  .catsearch-searchrow{display:flex;gap:8px;margin-bottom:10px}
  .catsearch-input{flex:1;padding:9px 11px;border:1px solid var(--line);border-radius:8px;font-size:14px;background:#fff}
  .catsearch-input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .catsearch-filters{display:flex;align-items:flex-end;gap:12px;margin-bottom:12px;flex-wrap:wrap}
  .catsearch-filterfld{display:flex;flex-direction:column;gap:5px;font-size:12px;font-weight:600;color:var(--slate-700)}
  .catsearch-filterfld select,.catsearch-filterfld input{padding:7px 9px;border:1px solid var(--line);border-radius:8px;font-size:13px;background:#fff;min-width:140px}
  .catsearch-filterfld select:focus,.catsearch-filterfld input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .catsearch-providerbar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 0;border-bottom:1px solid var(--line);margin-bottom:10px;min-height:20px}
  .catsearch-providerlabel{font-family:var(--mono);font-size:11px;letter-spacing:.3px;color:var(--slate-500)}
  .catsearch-results{min-height:220px;max-height:46vh;overflow:auto}

  .catsearch-row{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:#fff;border:1px solid var(--line);border-radius:8px;padding:8px 10px;margin-bottom:8px;font-family:var(--body)}
  .catsearch-row:hover{border-color:#c3ccd6;background:#fbfcfd}
  .catsearch-row:focus-visible{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .catsearch-row-selected{border-color:var(--gold);background:var(--gold-soft)}
  .catsearch-thumb{width:40px;height:56px;object-fit:cover;border-radius:5px;border:1px solid var(--line);flex-shrink:0;background:var(--paper)}
  .catsearch-rowbody{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  .catsearch-rowname{font-weight:600;font-size:13.5px;color:var(--ink)}
  .catsearch-rowmeta{font-family:var(--mono);font-size:11.5px;color:var(--slate-500)}
  .catsearch-selectbtn{flex-shrink:0;pointer-events:none}

  .catsearch-skeleton{display:flex;flex-direction:column;gap:8px}
  .catsearch-skelrow{display:flex;align-items:center;gap:12px;border:1px solid var(--line);border-radius:8px;padding:8px 10px}
  .catsearch-skelimg{width:40px;height:56px;border-radius:5px;background:var(--paper);flex-shrink:0}
  .catsearch-skellines{flex:1;display:flex;flex-direction:column;gap:6px}
  .catsearch-skelline{height:10px;border-radius:5px;background:var(--paper)}
  .catsearch-skelline.w70{width:70%} .catsearch-skelline.w40{width:40%}

  .catsearch-empty,.catsearch-error{padding:28px 12px;text-align:center}
  .catsearch-emptytitle{font-weight:600;font-size:14px;color:var(--ink);margin-bottom:6px}
  .catsearch-emptysub{font-size:13px;color:var(--slate-500);max-width:420px;margin:0 auto}
  .catsearch-error .catsearch-emptytitle{color:var(--danger)}
  .catsearch-error button{margin-top:10px}

  .catsearch-detailloading{padding:28px 12px;text-align:center;color:var(--slate-500);font-size:13px}
  .catsearch-confirmbody{display:flex;gap:16px;padding:12px 2px}
  .catsearch-confirmimg{width:120px;height:168px;object-fit:cover;border-radius:8px;border:1px solid var(--line);flex-shrink:0;background:var(--paper)}
  .catsearch-confirminfo{flex:1;min-width:0}
  .catsearch-confirmname{font-family:var(--display);font-weight:700;font-size:17px;color:var(--ink);margin-bottom:4px}
  .catsearch-confirmmeta{font-size:13px;color:var(--slate-700);margin-bottom:3px}
  .catsearch-variants{display:flex;gap:5px;flex-wrap:wrap;margin:8px 0}
  .catsearch-providerbadge{font-family:var(--mono);font-size:11px;color:var(--slate-500);margin-top:8px}
  .catsearch-confirmactions{display:flex;justify-content:flex-end;padding:10px 2px 2px;border-top:1px solid var(--line);margin-top:6px}

  /* Assignment 14G.3 — reference-only advisory pricing in the Catalog
     Search review panel. Scoped under .cmprice* (same non-shared-scoping
     precedent as .catsearch*/.macat*/.cstrowcat*) — nothing shared is
     redefined. Vault Gold stays reserved for "Use this card" (still the
     only .btn.gold in this modal); the advisory/estimated Info token
     (#2554A6, already used by .costestimated elsewhere) marks the
     headline reference figures as advisory, never as a second warm
     accent. Flat panel, no elevation, no charts/sparklines, no red/green
     market-movement styling — supporting evidence, not a dashboard. */
  .cmprice{border-top:1px solid var(--line);margin-top:10px;padding-top:12px}
  .cmprice-heading{font-family:var(--display);font-weight:700;font-size:13px;letter-spacing:.2px;color:var(--slate-700);margin:0 0 8px;text-transform:uppercase}
  .cmprice-source{background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:10px 12px;margin-bottom:8px}
  .cmprice-variantrow{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--slate-700);margin-bottom:6px}
  .cmprice-variantrow .btn{margin-left:auto}
  .cmprice-lbl{font-size:11px;font-weight:600;color:var(--slate-500);text-transform:uppercase;letter-spacing:.2px}
  .cmprice-headline{display:flex;align-items:baseline;gap:8px;margin-bottom:4px}
  .cmprice-hlabel{font-size:12.5px;font-weight:600;color:var(--slate-700)}
  .cmprice-hval{font-size:19px;font-weight:700;color:#2554A6}
  .cmprice-currency{font-family:var(--mono);font-size:11px;color:var(--slate-500)}
  .cmprice-secondaries{display:flex;gap:16px;flex-wrap:wrap;margin-bottom:4px}
  .cmprice-secondary{display:flex;flex-direction:column;gap:2px}
  .cmprice-secval{font-size:13px;color:var(--slate-700)}
  .cmprice-updated{font-family:var(--mono);font-size:11px;color:var(--slate-500)}
  .cmprice-partial{margin-bottom:4px}
  .cmprice-partialtitle{font-size:12.5px;color:var(--slate-700);font-weight:600}
  .cmprice-warn{margin-top:6px;padding-top:6px;border-top:1px solid var(--line);font-size:12px;color:var(--slate-700);display:flex;flex-direction:column;gap:3px}
  .cmprice-empty{background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:12px;margin-bottom:8px}
  .cmprice-emptytitle{font-size:13px;font-weight:600;color:var(--ink);margin-bottom:3px}
  .cmprice-emptysub{font-size:12px;color:var(--slate-500)}
  .cmprice-chooser{background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:10px 12px;margin-bottom:8px}
  .cmprice-chooserprompt{font-size:12.5px;color:var(--slate-700);margin-bottom:8px}
  .cmprice-variantopt{display:flex;align-items:center;gap:9px;padding:7px 8px;border:1px solid var(--line);border-radius:8px;background:#fff;margin-bottom:6px;cursor:pointer;font-size:12.5px}
  .cmprice-variantopt:last-child{margin-bottom:0}
  .cmprice-variantopt:has(input:focus-visible){outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .cmprice-variantopt-label{flex:1;color:var(--ink);font-weight:600}
  .cmprice-variantopt-key{font-size:10.5px;color:var(--slate-500)}
  .cmprice-variantopt-price{font-size:12.5px;color:var(--slate-700)}
  .cmprice-cmwrap{margin-top:2px}
  .cmprice-cmpanel{margin-top:8px}
  .cmprice-cmnote{font-size:11.5px;color:var(--slate-500);margin-bottom:6px}

  /* Assignment 14G.4 — explicit marketplace-value approval ("Use as market
     value" / the approval panel / the applied summary). Same .cmprice*
     scoping as 14G.3 directly above — nothing shared redefined. "Use as
     market value" and "Apply market value" are both .btn.ghost/.btn.primary
     (never .btn.gold — Vault Gold stays reserved for "Use this card," the
     One Warm Color Rule). The approval panel keeps the marketplace
     reference and the owner's own editable decision as two visually
     distinct blocks, never merged into one line. */
  .cmprice-mvzone{margin-bottom:8px}
  .cmprice-mvapplied{background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:9px 12px;margin-bottom:8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  .cmprice-mvappliedval{font-size:13px;font-weight:700;color:var(--ink)}
  .cmprice-mvappliedmeta{font-size:11.5px;color:var(--slate-500)}
  .cmprice-mvapplied .btn{margin-left:auto}
  .cmprice-approval{background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:12px;margin-bottom:8px}
  .cmprice-approvalref{border-bottom:1px solid var(--line);padding-bottom:10px;margin-bottom:10px}
  .cmprice-approvalrefline{display:flex;align-items:baseline;justify-content:space-between;gap:8px;font-size:13px;color:var(--slate-700);margin:4px 0}
  .cmprice-approvalfld{display:flex;flex-direction:column;gap:5px;margin-bottom:4px}
  .cmprice-approvalfld label{font-size:11px;font-weight:600;color:var(--slate-500);text-transform:uppercase;letter-spacing:.2px}
  .cmprice-approvalfld input{font-family:var(--mono);font-size:14px;padding:7px 9px;border:1px solid var(--line);border-radius:8px;max-width:160px}
  .cmprice-approvalfld input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .cmprice-mverror{font-size:12px;color:var(--danger);margin:2px 0 8px}
  .cmprice-approvalactions{display:flex;gap:8px;margin-top:10px}

  /* Assignment 14D — Catalog Search / Manual Entry integration. Scoped
     under .macat* (same non-shared scoping precedent as .catsearch* /
     .csworkspace) — nothing shared is redefined. No new warm color: the
     One Warm Color Rule is already spent elsewhere on this screen (Save &
     New), so Find/Change/Clear stay on the existing neutral .btn/.btn.ghost
     registers. */
  .macat-findrow{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .macat-hint{font-size:12px;color:var(--slate-500)}
  .macat-summary{display:flex;align-items:center;gap:12px;border:1px solid var(--line);border-radius:8px;padding:10px 12px;background:var(--paper)}
  .macat-thumb{width:44px;height:62px;object-fit:cover;border-radius:5px;border:1px solid var(--line);flex-shrink:0;background:#fff}
  .macat-info{flex:1;min-width:0}
  .macat-name{font-weight:600;font-size:13.5px;color:var(--ink)}
  .macat-meta{font-size:12px;color:var(--slate-700);margin-top:2px}
  .macat-provider{font-family:var(--mono);font-size:11px;color:var(--slate-500);margin-top:3px}
  .macat-actions{display:flex;gap:8px;flex-shrink:0;flex-wrap:wrap}

  /* Assignment 14E — Catalog Search / Structured Trade incoming-row
     integration. Scoped under .cstrowcat* (same non-shared scoping
     precedent as .macat*/.catsearch*) — the compose-form draft reuses
     .macat* verbatim (already generic); this is only the compact per-row
     badge shown under an ALREADY-ADDED incoming row once it carries a
     catalogRef. */
  .cstrowcat{display:flex;align-items:center;gap:6px;margin-top:4px}
  .cstrowcat-thumb{width:28px;height:39px;object-fit:cover;border-radius:4px;border:1px solid var(--line);flex-shrink:0;background:#fff}
  .cstrowcat-meta{font-family:var(--mono);font-size:11px;color:var(--slate-500)}

  /* Assignment 14G.5A — read-only Pricing Review report. Scoped under
     .pricereview*/.prbadge* — everything else on this screen (.metagrid,
     .filterpanel, .tablewrap, .detailhd, .empty) is reused verbatim from
     the existing system, unmodified. Deliberately no red/green judgment
     color anywhere here: an adjustment being positive or negative is not
     automatically good or bad (DESIGN.md), so .pricereview-summary/the
     detail table's difference column stay plain ink/mono, never
     .prof.up/.down's green-red pair. .prbadge is a neutral slate tag, the
     same visual register as .costunknown/.costestimated — never a Fixed
     Status Palette color, since a stale/warned decision is a data-quality
     fact, not a marketplace/lifecycle state. */
  .pricereview-summary{margin-top:14px}
  .pricereview-summary .meta{font-size:11px;color:var(--slate-500);margin-top:2px}
  .prbadge{display:inline-block;font-family:var(--mono);font-size:10.5px;font-weight:600;letter-spacing:.2px;color:var(--slate-700);background:var(--paper);border:1px solid var(--line);border-radius:20px;padding:2px 8px;margin:0 4px 2px 0}
  .prbadge-dq{color:var(--warn)}

  /* Assignment 14I.2 — Purchase Rapid Intake. Scoped under .rpi* (same
     non-shared scoping precedent as .catsearch*/.cmprice*/.macat*) —
     .panel/.grid2/.tablewrap/.fld/.btn/.chip are all reused verbatim. The
     embedded search list reuses .catsearch-row's visual language (thumb +
     name + mono meta) at a slightly tighter density since it lives inside
     an always-open panel, not a modal. Ready/Needs-review status is a
     text label plus a small dot, never color alone (accessibility). */
  .rpi-sticky .grid2{margin-bottom:0}
  .rpi-searchrow{display:flex;gap:8px;align-items:center}
  .rpi-searchinput{flex:1;padding:9px 11px;border:1px solid var(--line);border-radius:8px;font-size:14px;background:#fff}
  .rpi-searchinput:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .rpi-providerbar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 0 2px;min-height:18px}
  .rpi-providerlabel{font-size:11px;color:var(--slate-500)}
  .rpi-results{margin-top:8px;max-height:280px;overflow:auto}
  .rpi-loading,.rpi-empty{padding:14px 4px;color:var(--slate-500);font-size:13px}

  .rpi-result{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:#fff;border:1px solid var(--line);border-radius:8px;padding:7px 9px;margin-bottom:6px}
  .rpi-result:last-child{margin-bottom:0}
  .rpi-result:hover{border-color:#c3ccd6;background:#fbfcfd}
  .rpi-result:focus-visible,.rpi-result-active{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .rpi-resultthumb{width:34px;height:48px;object-fit:cover;border-radius:5px;border:1px solid var(--line);flex-shrink:0;background:var(--paper)}
  .rpi-resultbody{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  .rpi-resultname{font-weight:600;font-size:13.5px;color:var(--ink)}
  .rpi-resultmeta{font-size:11.5px;color:var(--slate-500)}
  .rpi-resultbusy{font-size:11px;color:var(--slate-500);flex-shrink:0}

  .rpi-variantpicker{background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:10px 12px}
  .rpi-variantprompt{font-size:12.5px;color:var(--slate-700);margin-bottom:8px}
  .rpi-variantopt{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;text-align:left;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:#fff;margin-bottom:6px;font-size:12.5px}
  .rpi-variantopt:hover{border-color:#c3ccd6}
  .rpi-variantopt:focus-visible,.rpi-variantopt-active{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .rpi-variantopt-label{font-weight:600;color:var(--ink)}
  .rpi-variantopt-price{color:var(--slate-700)}

  .rpi-rowidentity{display:flex;gap:10px;align-items:flex-start}
  .rpi-rowthumb{width:32px;height:45px;object-fit:cover;border-radius:4px;border:1px solid var(--line);flex-shrink:0;background:var(--paper)}
  .rpi-rowidentitybody{min-width:0}
  .rpi-rowname{font-weight:600;font-size:13px;color:var(--ink)}
  .rpi-rowmeta{font-size:11px;color:var(--slate-500)}
  .rpi-rowref{font-size:11px;color:var(--slate-700);margin-top:2px;max-width:260px}
  .rpi-rowidentitybody .btn{margin-top:4px}
  .rpi-qty{display:flex;align-items:center;gap:6px;white-space:nowrap}
  .rpi-qtyval{min-width:14px;text-align:center;display:inline-block}
  .rpi-mvinput{width:90px;padding:6px 8px;border:1px solid var(--line);border-radius:6px}
  .rpi-mvinput:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .rpi-status{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;white-space:nowrap}
  .rpi-status-ready{color:var(--status-sold,#15803D)}
  .rpi-status-review{color:var(--danger)}

  .rpi-footer{position:sticky;bottom:0;display:flex;align-items:center;gap:16px;background:var(--slate-900);color:#fff;padding:10px 16px;border-radius:10px;box-shadow:0 12px 34px rgba(20,26,36,.32);font-family:var(--mono);font-size:12.5px;margin-top:-96px}
  .rpi-footer span{opacity:.92}

  /* Assignment 14I.2B (Subphase A) — Catalog Intake. Scoped under .ci*
     (same non-shared scoping precedent as .catsearch*/.cmprice*/.rpi*).
     .panel/.grid3/.fld/.btn/.mono are all reused verbatim. The search list
     deliberately shares .rpi-result's visual language so the two intake
     surfaces read as one system; the intake stage is a plain stack of
     panels — identity first, the owner's own inputs second, pricing
     subordinate underneath them, acquisition last. */
  .ci-searchrow{display:flex;gap:8px;align-items:center}
  .ci-searchinput{flex:1;padding:9px 11px;border:1px solid var(--line);border-radius:8px;font-size:14px;background:#fff}
  .ci-searchinput:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .ci-providerbar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 0 2px;min-height:18px}
  .ci-providerlabel{font-size:11px;color:var(--slate-500)}
  .ci-results{margin-top:8px;max-height:320px;overflow:auto}
  .ci-loading,.ci-empty{padding:14px 4px;color:var(--slate-500);font-size:13px}
  .ci-result{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:#fff;border:1px solid var(--line);border-radius:8px;padding:7px 9px;margin-bottom:6px}
  .ci-result:last-child{margin-bottom:0}
  .ci-result:hover{border-color:#c3ccd6;background:#fbfcfd}
  .ci-result:focus-visible,.ci-result-active{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .ci-resultthumb{width:34px;height:48px;object-fit:cover;border-radius:5px;border:1px solid var(--line);flex-shrink:0;background:var(--paper)}
  .ci-resultbody{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  .ci-resultname{font-weight:600;font-size:13.5px;color:var(--ink)}
  .ci-resultmeta{font-size:11.5px;color:var(--slate-500)}
  .ci-resultbusy{font-size:11px;color:var(--slate-500);flex-shrink:0}

  .ci-variantpicker{background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:10px 12px}
  .ci-variantprompt{font-size:12.5px;color:var(--slate-700);margin-bottom:8px}
  .ci-variantopt{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;text-align:left;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:#fff;margin-bottom:6px;font-size:12.5px}
  .ci-variantopt:hover{border-color:#c3ccd6}
  .ci-variantopt:focus-visible,.ci-variantopt-active{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .ci-variantopt-label{font-weight:600;color:var(--ink)}
  .ci-variantopt-price{color:var(--slate-700)}
  .ci-variantnote{font-size:11px;color:var(--slate-500);margin:2px 0 8px}

  .ci-identity{display:flex;gap:16px;align-items:flex-start}
  .ci-identityimg{width:96px;height:134px;object-fit:cover;border-radius:6px;border:1px solid var(--line);flex-shrink:0;background:var(--paper)}
  .ci-identitybody{flex:1;min-width:0}
  .ci-identityname{font-family:var(--display);font-weight:700;font-size:19px;color:var(--ink);line-height:1.2}
  .ci-identitymeta{font-size:11.5px;color:var(--slate-500);margin-top:3px}
  .ci-identitygrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:10px 18px;margin:12px 0 0}
  .ci-identitygrid dt{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-500)}
  .ci-identitygrid dd{margin:2px 0 0;font-size:13px;font-weight:600;color:var(--slate-900)}
  .ci-sectionhd{font-weight:700;font-size:12.5px;margin-bottom:10px}
  .ci-pricing{display:flex;flex-direction:column;gap:3px;margin-top:4px;padding-top:10px;border-top:1px solid var(--line)}
  .ci-priceref{font-size:12.5px;color:var(--slate-700)}
  .ci-priceapplied{font-size:11.5px;color:var(--slate-500)}
  .ci-pricenote{font-size:11.5px;color:var(--warn)}
  .ci-actions{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:14px}
  .ci-fallbackrow{padding-top:2px}

  /* Assignment 14I.2B (Subphase B) — the concrete per-record list inside
     the card-show close preflight dialog. Calm, no alarm color: it states
     counts, not urgency. */
  .csattn-plainlist{margin:0 0 14px;padding-left:18px;color:var(--slate-700);font-size:12.5px}
  .csattn-plainlist li{margin-bottom:3px}

  /* Assignment 14I.2B (Subphase C) — the active Inventory alert-filter
     banner and its per-row "why this qualifies" line. Informational, not
     alarming: the same quiet gold-soft surface the Card Show workspace's
     own attention list already uses, never the danger palette. */
  .invalert{display:flex;align-items:center;gap:12px;background:var(--gold-soft);border:1px solid #ecd9a9;border-radius:8px;padding:11px 14px;margin:12px 0 0}
  .invalert-body{flex:1;min-width:0}
  .invalert-title{font-weight:600;font-size:13px;color:var(--ink)}
  .invalert-detail{font-size:11.5px;color:var(--slate-700);margin-top:2px}
  .invalert-why{font-size:11px;color:var(--warn);margin-top:3px}

  /* Assignment 14I.2B (Subphase E) — Whatnot quantity controls. Kept
     right next to the card they belong to, in the same table row, so the
     inventory/staged/sold counts stay scannable with no hidden
     arithmetic. Reuses the input treatment .rpi-mvinput already
     established for an in-table number field. */
  .wnqtyinput{width:64px;padding:6px 8px;border:1px solid var(--line);border-radius:6px;font-family:var(--mono);text-align:right}
  .wnqtyinput:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .wnqtyinput:disabled{background:var(--paper);color:var(--slate-500)}
  .wnqtyblock{margin:0 0 14px}
  .wnqtyhd{font-weight:700;font-size:12.5px;margin-bottom:8px}
  .wnqtynote{font-size:11.5px;margin:6px 0 0}
  .wnsoldqtycell{white-space:nowrap}

  /* Assignment 14I.2C (Subphase B) — derived sellable positions. One calm
     panel per sellable card; the acquisition lots underneath are an
     ordinary table because the owner is comparing costs down a column.
     Reuses the existing panel surface, chip and table treatments — no new
     colors, radii or type steps are introduced here. */
  .invgrp-note{font-size:11.5px;margin:0 0 10px}
  .invgrp{border:1px solid var(--line);border-radius:8px;background:#fff;margin-bottom:10px;overflow:hidden}
  .invgrp-hd{display:flex;align-items:flex-start;gap:12px;padding:11px 14px}
  .invgrp-thumb img{width:38px;height:53px;object-fit:contain;border-radius:4px;background:#f0f2f5}
  .invgrp-main{flex:1;min-width:0}
  .invgrp-name{font-weight:600;font-size:13px;color:var(--ink)}
  .invgrp-meta{font-size:11.5px;color:var(--slate-500);margin-top:2px}
  .invgrp-own{font-size:11.5px;color:var(--slate-700);margin-top:4px}
  .invgrp-partial{font-size:11px;color:var(--slate-500);margin-top:3px}
  .invgrp-money{text-align:right;white-space:nowrap}
  .invgrp-qty{font-family:var(--mono);font-size:13px;font-weight:600}
  .invgrp-market{font-size:11.5px;color:var(--slate-700);margin-top:2px}
  .invgrp-basis{font-size:11px;color:var(--slate-500);margin-top:2px}
  .invgrp-actions{display:flex;flex-direction:column;gap:6px;align-self:center}
  .invgrp-toggle{align-self:stretch}
  .invgrp-lots{border-top:1px solid var(--line);background:var(--paper);padding:10px 14px 12px}
  .invgrp-lotshd{font-weight:700;font-size:11.5px;color:var(--slate-700);margin-bottom:7px}

  /* Assignment 14I.2C (Subphase E) — the trade's Cost Basis Review panel.
     Informational, never alarming: it states what is known, what is not,
     and the figure the existing formula produces from it. Reuses the
     existing panel/table/costunknown treatments. */
  .cstcr{border:1px solid var(--line);border-radius:8px;background:var(--paper);padding:12px 14px;margin:14px 0 0}
  .cstcr-hd{font-weight:700;font-size:12.5px;margin-bottom:6px}
  .cstcr-note{font-size:12px;margin:0 0 10px}
  .cstcr-totals{margin-top:10px}
  .cstcr-blocked{font-size:12px;color:var(--warn);margin:8px 0 0}
  .cstcr-value{font-size:11.5px;color:var(--slate-500);margin:8px 0 0}
  .cstcr-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}

  @media(prefers-reduced-motion:reduce){*{transition:none!important}}

  /* ============================================================
     Assignment 15B — Scan Studio
     ============================================================
     A review workstation, not a file uploader. The images are the
     content, so everything around them is quiet: one flat drop surface,
     one summary strip, and a three-lane workspace (queue · viewer ·
     status) that stays put while the owner works down a 20-card batch.
     No gradients, no hero, no new colors, radii or type steps — the
     panel, chip, stat and button treatments are the ones already in
     this file. */
  .ssdrop{border:1.5px dashed #cbd4de;border-radius:var(--radius);background:var(--surface);padding:26px 20px;text-align:center;color:var(--slate-500)}
  .ssdrop.drag{border-color:var(--gold);background:var(--gold-soft);color:var(--slate-700)}
  .ssdrop h3{font-family:var(--display);font-size:14px;font-weight:600;color:var(--ink);margin:10px 0 4px}
  .ssdrop-sub{font-size:13px;margin:0 0 14px}
  .ssdrop-actions{display:flex;gap:8px;justify-content:center;flex-wrap:wrap}
  .ssdrop-note{font-size:11px;color:var(--slate-500);margin:12px auto 0;max-width:560px}
  /* With a batch open the drop zone is a secondary "add more" affordance,
     not the headline — it keeps every control and gives the vertical space
     back to the review lanes. */
  .ssdrop-compact{padding:12px 16px;display:flex;align-items:center;gap:14px;text-align:left}
  .ssdrop-compact svg,.ssdrop-compact .ssdrop-sub,.ssdrop-compact .ssdrop-note{display:none}
  .ssdrop-compact h3{margin:0;font-size:13px;font-weight:600}
  .ssdrop-compact .ssdrop-actions{margin-left:auto;justify-content:flex-end}
  /* In the compact strip these are a secondary affordance, so they drop
     to outline weight — full-ink buttons there competed with Continue
     during setup and with the card's own primary action during review. */
  .ssdrop-compact .filebtn{background:var(--surface);color:var(--slate-700);border:1px solid var(--line);padding:7px 13px;font-size:13px}
  .ssdrop-compact .filebtn:hover{background:var(--paper);color:var(--ink);border-color:color-mix(in srgb, var(--slate-500) 45%, transparent)}

  /* ============================================================
     Assignment 15B.1 — stages, batch setup, and the Inspector
     ============================================================
     Same tokens, same type ramp, same radii, same two-temperature
     palette. What changed is emphasis: the stage rail says where the
     owner is, batch setup is one compact panel, and the right lane
     spends its weight on the ONE decision the selected card needs
     rather than on six correction buttons. */

  /* Stage rail — a signpost, not a progress bar. No fill, no animation:
     the numeral and the ink-weight carry the state. */
  .ssstages{display:flex;flex-wrap:wrap;gap:6px;list-style:none;margin:14px 0 0;padding:0}
  .ssstage{display:flex;align-items:center;gap:7px;padding:6px 11px;border:1px solid var(--line);border-radius:20px;background:var(--surface);font-size:13px;color:var(--slate-500)}
  .ssstage-n{display:inline-flex;align-items:center;justify-content:center;width:17px;height:17px;border-radius:20px;background:var(--paper);color:var(--slate-500);font-size:11px;font-weight:600}
  .ssstage-now{border-color:var(--gold);background:var(--gold-soft);color:var(--ink)}
  .ssstage-now .ssstage-n{background:var(--gold);color:#fff}
  .ssstage-done{color:var(--slate-700)}
  .ssstage-done .ssstage-n{background:var(--ink);color:#fff}
  .ssstage-btn{display:flex;align-items:center;gap:7px;background:none;border:none;padding:0;font:inherit;color:inherit}
  .ssstage-btn:hover{color:var(--ink)}

  /* Batch setup — four fields and one button, deliberately no taller
     than it needs to be. It is answered once per batch and then gone. */
  .sssetup{padding:16px 18px;margin:14px 0 0}
  .sssetup-title{font-family:var(--display);font-size:19px;font-weight:700;color:var(--ink);margin:2px 0 3px}
  .sssetup-sub{font-size:13px;color:var(--slate-500);margin:0;max-width:60ch}
  .sssetup-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:12px;margin-top:14px}
  .sssetup-struct{border:none;margin:14px 0 0;padding:0}
  .sssetup-struct legend{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-500);padding:0;margin-bottom:8px}
  .sssetup-structopts{display:flex;gap:8px;flex-wrap:wrap}
  .ssradio{display:flex;flex-direction:column;gap:2px;border:1px solid var(--line);border-radius:8px;padding:9px 12px;min-width:210px;cursor:pointer;background:var(--surface)}
  .ssradio input{position:absolute;opacity:0;pointer-events:none}
  .ssradio-on{border-color:var(--gold);background:var(--gold-soft)}
  .ssradio-l{font-size:13px;font-weight:600;color:var(--ink)}
  .ssradio-d{font-size:11px;color:var(--slate-500)}
  .sssetup-actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
  .sssetup-note{font-size:11px;color:var(--slate-500)}

  /* The durability statement. It is a permanent fact about how Scan
     Studio works, so it is stated permanently — but 15B ran it as a
     two-line gold banner over the workspace, which in real use is a
     standing interruption. 15B.1 keeps the words and gives them one
     quiet line the owner can dismiss for the batch. */
  .ssnotice{display:flex;align-items:baseline;gap:10px;background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:8px 12px;margin:12px 0 0}
  .ssnotice-t{font-size:13px;font-weight:600;color:var(--ink)}
  .ssnotice-d{font-size:11px;color:var(--slate-700)}
  .ssnotice-x{margin-left:auto;flex:none;background:none;border:none;padding:0;font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-500)}
  .ssnotice-x:hover{color:var(--ink)}

  .sssummary{padding:14px 16px;margin:14px 0 0}
  .sssummary-hd{display:flex;align-items:flex-start;gap:14px;flex-wrap:wrap}
  .sssummary-name{font-family:var(--display);font-size:14px;font-weight:600;color:var(--ink);margin-top:2px}
  .sssummary-meta{font-size:11px;color:var(--slate-500);margin-top:2px}
  .sssummary-actions{display:flex;gap:8px;margin-left:auto;flex-wrap:wrap}
  .ssstats{display:flex;gap:22px;flex-wrap:wrap;margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
  .ssstat-l{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-500)}
  .ssstat-v{font-size:19px;font-weight:600;color:var(--ink);margin-top:1px}
  .ssstat-review .ssstat-v{color:var(--warn)}
  .ssbulkblock{font-size:11px;color:var(--warn);margin-top:10px}
  .ssbulknote{font-size:11px;color:var(--slate-500);margin-top:10px}

  .sswork{display:grid;grid-template-columns:288px minmax(0,1fr) 336px;gap:14px;align-items:start;margin-top:14px}
  .sswork-hd{display:flex;align-items:center;gap:8px;font-weight:700;font-size:11px;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-500);padding:12px 14px;border-bottom:1px solid var(--line)}
  .sswork-hd .mono{text-transform:none;letter-spacing:normal;color:var(--slate-700)}
  .sswork-queue,.sswork-viewer,.sswork-inspect{overflow:hidden}

  .ssq{max-height:560px;overflow-y:auto}
  .ssq-empty{padding:16px 14px;font-size:13px;color:var(--slate-500)}
  .ssq-row{display:flex;align-items:center;gap:9px;width:100%;text-align:left;background:none;border:none;border-bottom:1px solid var(--line);padding:8px 12px}
  .ssq-row:hover{background:var(--paper)}
  .ssq-row-active{background:var(--gold-soft)}
  .ssq-row-active:hover{background:var(--gold-soft)}
  .ssq-idx{font-size:11px;color:var(--slate-500);width:26px;flex:none}
  .ssq-thumbs{display:flex;gap:2px;flex:none}
  .ssq-thumb{width:24px;height:33px;object-fit:cover;border-radius:3px;background:#eef1f5;border:1px solid var(--line)}
  .ssq-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--slate-500)}
  /* Name, the reason line, then the state chip on its own row. At fifty
     cards these are scanned vertically, so nothing may wrap or squeeze
     its neighbour — the reason line truncates, the chip never does. */
  .ssq-body{min-width:0;flex:1;display:flex;flex-direction:column;align-items:flex-start;gap:1px}
  .ssq-name{display:block;font-size:13px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ssq-status{display:block;font-size:11px;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ssq-status-suggested{color:var(--slate-500)}
  .ssq-status-review{color:var(--warn)}
  .ssq-status-ready{color:#0D7692}
  .ssq-status-done{color:#15803D}

  /* The viewer is the point of the screen: both sides side by side, large
     enough that a mismatched back is obvious at a glance. */
  .ssv{display:grid;grid-template-columns:1fr 1fr;gap:14px;padding:14px}
  .ssv-none{padding:18px 14px;font-size:13px;color:var(--slate-500)}
  .ssv-side{margin:0;display:flex;flex-direction:column;gap:6px}
  .ssv-caption{display:flex;align-items:baseline;gap:8px;min-width:0}
  .ssv-role{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-700)}
  .ssv-file{font-size:11px;color:var(--slate-500);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .ssv-img{width:100%;max-height:420px;object-fit:contain;background:var(--paper);border:1px solid var(--line);border-radius:8px}
  .ssv-dims{font-size:11px;color:var(--slate-500)}
  .ssv-slot{display:flex;align-items:center;justify-content:center;text-align:center;min-height:220px;padding:16px;border:1px dashed #cbd4de;border-radius:8px;background:var(--paper);font-size:13px;color:var(--slate-500)}
  .ssv-slot-bad{border-color:#e3b3af;color:var(--danger)}

  .ssi{padding:14px}
  .ssi-none{padding:16px 14px;font-size:13px;color:var(--slate-500)}
  .ssi-block{padding-bottom:14px;margin-bottom:14px;border-bottom:1px solid var(--line)}
  .ssi-block:last-child{border-bottom:none;padding-bottom:0;margin-bottom:0}
  .ssi-lbl{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-500);margin-bottom:8px}
  .ssi-actions{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:6px}
  .ssi-note{font-size:11px;color:var(--slate-500);margin:8px 0 0}
  .ssi-done{background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:11px 12px;margin-bottom:12px}
  .ssi-donehd{font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:#15803D}
  .ssi-sku{font-size:14px;font-weight:600;color:var(--ink);margin-top:3px}
  .ssi-card{font-size:13px;color:var(--slate-700);margin-top:2px}

  /* ---- 15B.1 right lane ---- */
  /* One headline, one primary action, one explanatory line. Everything
     that is an exception tool sits under a disclosure below it. */
  .ssi-headline{font-size:13px;font-weight:600;color:var(--ink);margin-bottom:9px}
  .ssi-applied{font-size:11px;color:#15803D;margin:8px 0 0}
  .ssi-footer{border-top:1px solid var(--line);border-bottom:none;padding-top:12px;margin-top:2px}
  /* The repair tools, only ever rendered when the owner opened them. */
  .ssrepair{margin-top:10px;padding:10px 11px;border:1px solid var(--line);border-radius:8px;background:var(--paper)}

  /* Operational state chip — the queue's answer to "what does this card
     need next?". Text, never colour alone. */
  /* Tint and border are mixed FROM the state's own documented colour
     rather than hand-picked, so these chips add no new values to the
     palette — the same color-mix convention the Value Box tier badges
     already use. Colours are DESIGN.md's: status-info (needs match),
     lifecycle-active (ready), status-sold (completed), --warn (review). */
  .ssq-state{flex:none;font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.4px;border-radius:20px;padding:3px 9px;white-space:nowrap;border:1px solid var(--line);background:var(--surface);color:var(--slate-500)}
  .ssq-state-review{--ssc:var(--warn)}
  .ssq-state-match{--ssc:#2554A6}
  .ssq-state-ready{--ssc:#0D7692}
  .ssq-state-done{--ssc:#15803D}
  /* 15F-A — Auto Matched is the one queue state that gets Vault Gold: it
     is literally "the system already confirmed this," the exact meaning
     the One Warm Color Rule reserves gold for, spent on one chip at a
     time rather than a fill. */
  .ssq-state-auto{--ssc:var(--gold)}
  .ssq-state-review,.ssq-state-match,.ssq-state-ready,.ssq-state-done,.ssq-state-auto{
    color:var(--ssc);
    border-color:color-mix(in srgb, var(--ssc) 30%, transparent);
    background:color-mix(in srgb, var(--ssc) 8%, transparent)}
  .ssq-row .ssq-state{margin-top:3px}
  .sswork-hd .ssq-state{margin-left:auto;text-transform:none}

  /* Condition as a five-key segmented control rather than a select: at
     fifty cards this is the field touched most often, and the printed
     digit is what makes the 1–5 shortcut discoverable instead of
     folklore. */
  .sscond{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:11px}
  .sscond-b{display:flex;align-items:center;gap:5px;border:1px solid var(--line);background:var(--surface);border-radius:6px;padding:6px 9px;font-size:13px;font-weight:600;color:var(--slate-700)}
  .sscond-b:hover{border-color:color-mix(in srgb, var(--slate-500) 45%, transparent);color:var(--ink)}
  .sscond-on{border-color:var(--gold);background:var(--gold-soft);color:var(--ink)}
  .sscond-k{font-size:11px;font-weight:600;color:var(--slate-500)}
  .sscond-on .sscond-k{color:var(--gold)}
  .ssqty{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-bottom:10px}

  /* Read-only card facts: label left, value right, mono where it is data. */
  .ssfields{margin:0;padding:0}
  .ssf-row{display:flex;align-items:baseline;gap:10px;padding:4px 0;border-bottom:1px solid var(--line)}
  .ssf-row:last-child{border-bottom:none}
  .ssf-row dt{flex:none;width:92px;font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.4px;text-transform:uppercase;color:var(--slate-500)}
  .ssf-row dd{margin:0;min-width:0;font-size:13px;color:var(--ink);word-break:break-word}
  .ssf-name{font-weight:600}
  .ssf-sub{display:block;font-size:11px;color:var(--slate-500)}
  .ssf-warn{color:var(--warn)}

  /* The printing chooser. Nothing preselected — a printing is a fact
     about the card, never a default. */
  .ssprint{margin-top:10px;border:1px solid var(--line);border-radius:8px;padding:10px 11px;background:var(--paper)}
  .ssprint-hd{font-size:13px;font-weight:600;color:var(--ink);margin-bottom:8px}
  .ssprint-b{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;text-align:left;border:1px solid var(--line);background:var(--surface);border-radius:6px;padding:7px 10px;margin-bottom:5px;font-size:13px;color:var(--ink)}
  .ssprint-b:hover{border-color:var(--gold);background:var(--gold-soft)}
  .ssprint-p{font-size:13px;font-weight:600;color:var(--slate-700)}

  /* 15C — OCR-suggested candidates. Same color-mix convention as
     .ssq-state above: a band's colour is mixed FROM its own documented
     token, never a new hand-picked value. HIGH=lifecycle-active,
     MEDIUM=--warn, LOW=slate (never --danger — a LOW suggestion is not
     wrong, only weak evidence, and Search manually is always right
     there). Text always carries the band label too — colour is never
     the only signal. */
  .ssocc{border:1px solid var(--line);border-radius:8px;padding:9px 11px;margin-bottom:8px;background:var(--paper)}
  .ssocc-hd{display:flex;align-items:center;justify-content:space-between;gap:8px}
  .ssocc-n{font-size:13px;font-weight:600;color:var(--ink)}
  .ssocc-band{flex:none;font-family:var(--mono);font-size:10.5px;font-weight:700;letter-spacing:.5px;border-radius:20px;padding:2px 8px;border:1px solid var(--line);background:var(--surface);color:var(--slate-500)}
  .ssocc-band-high{--occc:#0D7692}
  .ssocc-band-medium{--occc:var(--warn)}
  .ssocc-band-low{--occc:var(--slate-500)}
  .ssocc-band-high,.ssocc-band-medium,.ssocc-band-low{
    color:var(--occc);
    border-color:color-mix(in srgb, var(--occc) 30%, transparent);
    background:color-mix(in srgb, var(--occc) 8%, transparent)}
  .ssocc-sub{font-size:12px;color:var(--slate-700);margin-top:2px}
  .ssocc-reasons{font-size:11px;color:var(--slate-500);margin-top:5px;line-height:1.5}
  .ssocc .ssi-actions{margin-top:8px;margin-bottom:0}

  /* ============================================================
     Assignment 15F-A — Scanning screen, queue filters, Auto Matched,
     completion summary. Same tokens, same radii, same two-temperature
     palette — no new colours, no gradients, no animated fills. */

  /* Queue grouping — small ghost-style toggle chips above the queue,
     the same visual family as the condition/printing pickers rather than
     a new control. */
  .ssqf{display:flex;flex-wrap:wrap;gap:5px;padding:8px 12px;border-bottom:1px solid var(--line)}
  .ssqf-b{display:flex;align-items:center;gap:4px;border:1px solid var(--line);border-radius:20px;background:var(--surface);color:var(--slate-500);font-size:11px;padding:3px 9px}
  .ssqf-b:hover{color:var(--ink);border-color:color-mix(in srgb, var(--slate-500) 45%, transparent)}
  .ssqf-on{border-color:var(--gold);background:var(--gold-soft);color:var(--ink)}

  /* The Scanning screen — real counts, real bars, no invented percentage
     and no fixed-duration animation standing in for actual progress
     (the fill width is set directly from done/total, no CSS transition
     pretending motion between renders). */
  .ssscan{padding:16px 18px;margin-top:14px}
  .ssscan-hd{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap}
  .ssscan-title{font-family:var(--display);font-size:19px;font-weight:700;color:var(--ink);margin:2px 0 0}
  .ssscan-rows{margin-top:16px;display:flex;flex-direction:column;gap:10px}
  .ssscan-row{display:grid;grid-template-columns:160px 1fr 70px;align-items:center;gap:10px}
  .ssscan-rowl{font-size:13px;color:var(--slate-700)}
  .ssscan-bar{height:6px;border-radius:20px;background:var(--paper);border:1px solid var(--line);overflow:hidden}
  .ssscan-fill{height:100%;background:var(--gold);border-radius:20px}
  .ssscan-rown{font-size:11px;color:var(--slate-500);text-align:right}
  .ssscan .ssstats{margin-top:16px}

  /* Auto Matched — the one place a "why" checklist appears; ✓/✗ text
     carries the meaning, colour is a secondary cue only. */
  .ssi-auto{background:var(--gold-soft);border:1px solid color-mix(in srgb, var(--gold) 35%, transparent);border-radius:8px;padding:12px;margin:0 0 14px;border-bottom:none}
  .ssauto-reasons{list-style:none;margin:0;padding:0;font-size:11px;color:var(--slate-700);display:flex;flex-direction:column;gap:3px}
  .ssauto-ok{color:#0D7692}
  .ssauto-bad{color:var(--danger)}

  /* Completion summary — one dismissable panel, same family as the
     durability notice and the batch summary strip. */
  .sscomplete{padding:14px 16px;margin:14px 0 0;border:1px solid var(--gold);background:var(--gold-soft)}
  .sscomplete-hd{display:flex;align-items:center;justify-content:space-between;gap:10px}
  .sscomplete .ssstats{border-top:1px solid color-mix(in srgb, var(--gold) 30%, transparent)}

  /* ============================================================
     Assignment 16F — reconciliation against existing Inventory.
     No new colours and no new component family: a match row is the
     same full-width choice button the printing chooser already uses
     (.ssprint-b), so "pick which one" looks the same wherever it is
     asked. The single-match card is the same shape without the button
     affordance, because there is nothing to pick. */
  .ssrec-list{display:flex;flex-direction:column;gap:0}
  .ssrec-one,.ssrec-row{display:flex;flex-direction:column;gap:3px;width:100%;text-align:left;border:1px solid var(--line);background:var(--surface);border-radius:6px;padding:8px 10px;margin-bottom:5px}
  .ssrec-row:hover{border-color:var(--gold);background:var(--gold-soft)}
  .ssrec-row[disabled]{opacity:.55}
  .ssrec-one{background:var(--paper)}
  .ssrec-sku{font-size:13px;font-weight:600;color:var(--ink)}
  .ssrec-facts{font-size:12px;color:var(--slate-700)}
  .ssrec-cond{font-weight:600}
  .ssrec-copies{color:var(--warn)}
  .ssrec-src{display:block;font-size:11px;color:var(--slate-500)}
  .ssrec-else{margin-top:4px;padding:8px 9px;border:1px solid var(--line);border-radius:8px;background:var(--paper)}
  .ssrec-else .ssi-lbl{margin-bottom:6px}
  .ssrec-cov{font-family:var(--mono);font-size:11px;color:var(--slate-500);margin-top:3px}

  /* ============================================================
     Assignment 19A — automatic reconciliation, condition provenance,
     the economic-bucket chooser and the batch overview.
     Still no new colour family: gold means "Card Master decided or is
     asking", warn-amber means "two of your own facts disagree", and
     everything else is the existing paper/line/slate vocabulary. */

  /* An economic bucket, not a SKU. The acquisition leads, because that is
     the question being asked; the SKU trails as the answer's receipt. */
  .ssrec-group{display:grid;grid-template-columns:1fr auto;grid-template-areas:"src sku" "facts sku";column-gap:10px;align-items:center}
  .ssrec-gsrc{grid-area:src;font-size:13px;font-weight:600;color:var(--ink)}
  .ssrec-group .ssrec-facts{grid-area:facts}
  .ssrec-gsku{grid-area:sku;font-size:11px;color:var(--slate-500);white-space:nowrap}

  /* A condition conflict between two owner-entered facts. Never styled
     as an error — nothing is broken, two statements simply disagree. */
  .ssrec-conflict{margin-top:8px;padding:9px 10px;border:1px solid color-mix(in srgb, var(--warn) 45%, transparent);border-radius:8px;background:color-mix(in srgb, var(--warn) 7%, transparent)}
  .ssrec-conflict .ssi-lbl{color:var(--warn);margin-bottom:5px}
  .ssrec-row-warn{border-color:color-mix(in srgb, var(--warn) 40%, transparent)}
  .ssrec-row-warn:hover{border-color:var(--warn);background:color-mix(in srgb, var(--warn) 10%, transparent)}
  .ssrec-anyway{font-size:11px;font-weight:600;color:var(--warn)}

  /* The scan's own condition, with where it came from. One line, because
     it is a statement the owner already made and is only being shown. */
  .sscondline{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:10px 0 4px;padding:7px 9px;border:1px solid var(--line);border-radius:6px;background:var(--paper)}
  .sscondline-l{font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase;color:var(--slate-500)}
  .sscondline-v{font-size:13px;font-weight:600;color:var(--ink)}
  .sscond-inline{flex-basis:100%;margin:4px 0 0}

  /* The automatic result. The card's own name is the largest thing in the
     panel — the owner asked to be shown what Card Master thought this
     card was, not merely told that it succeeded. */
  .ssi-done-auto{border-color:color-mix(in srgb, var(--gold) 45%, transparent);background:var(--gold-soft)}
  .ssi-ident{margin:6px 0 8px}
  .ssi-identname{font-size:17px;font-weight:600;line-height:1.25;color:var(--ink)}
  .ssi-identmeta{font-size:12px;color:var(--slate-700)}
  .ssi-identset{font-size:12px;color:var(--slate-500)}
  .ssevidence{margin-top:2px}
  .ssevidence .ssauto-reasons{margin-top:6px}

  /* Listing readiness on a finished card. */
  .sslisting{margin:12px 0;padding:10px 11px;border:1px solid var(--line);border-radius:8px;background:var(--paper)}
  .sslisting-ready{border-color:color-mix(in srgb, #15803D 40%, transparent)}
  .sslisting-needs_attention{border-color:color-mix(in srgb, var(--warn) 45%, transparent)}
  .sslane{display:inline-block;font-size:11px;font-weight:600;padding:2px 7px;border-radius:20px;border:1px solid var(--line);color:var(--slate-700);background:var(--surface)}
  .sslane-ready{border-color:color-mix(in srgb, #15803D 45%, transparent);color:#15803D}
  .sslane-needs_attention{border-color:color-mix(in srgb, var(--warn) 45%, transparent);color:var(--warn)}
  .sslane-none{color:var(--slate-500)}

  /* Batch overview — a table of finished cards, collapsed by default so
     it never competes with the queue of what still needs doing. */
  .ssoverview{padding:0;margin-top:12px;overflow:hidden}
  .ssov-hd{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 14px}
  .ssov-toggle{display:flex;align-items:center;gap:10px;background:none;border:0;padding:0;text-align:left;color:var(--ink)}
  .ssov-count{font-size:13px;font-weight:600}
  .ssov-caret{color:var(--slate-500)}
  .ssov-filters{padding:0 14px 10px}
  .ssov-scroll{overflow-x:auto}
  .ssov-table{width:100%;border-collapse:collapse;font-size:12.5px;min-width:640px}
  .ssov-table th{text-align:left;font-size:10.5px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-500);padding:7px 10px;border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--paper);white-space:nowrap}
  .ssov-table td{padding:8px 10px;border-bottom:1px solid var(--line);vertical-align:middle}
  .ssov-table tbody tr:hover{background:var(--paper);cursor:pointer}
  .ssov-img{width:44px}
  .ssov-img img{width:34px;height:46px;object-fit:cover;border-radius:4px;border:1px solid var(--line);display:block}
  .ssov-noimg{display:flex;align-items:center;justify-content:center;width:34px;height:46px;border:1px dashed var(--line);border-radius:4px;color:var(--slate-500);font-size:11px}
  .ssov-card{min-width:170px}
  .ssov-name{display:block;font-weight:600;color:var(--ink)}
  .ssov-set{display:block;font-size:11px;color:var(--slate-500)}
  .ssov-num{text-align:right;white-space:nowrap}
  .ssov-gone{padding:14px;color:var(--slate-500);font-size:12px;text-align:center}
  .sssummary-notes{margin-top:5px;font-size:12px;color:var(--slate-700)}
  .sssetup-notes{grid-column:1 / -1}

  @media (max-width:1100px){
    .ssov-table{min-width:560px}
  }

  /* The scans panel on an inventory record. Read-only by construction —
     no remove control, no upload target; the record's own editable
     Images sit in their own panel below it. */
  .invscan{display:grid;grid-template-columns:1fr 1fr;gap:12px;max-width:420px}
  .invscan-hd{font-size:11.5px;color:var(--slate-500);margin-bottom:9px}
  .invscan-side{display:flex;flex-direction:column;gap:4px;min-width:0}
  .invscan-role{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-700)}
  .invscan-img{width:100%;max-height:200px;object-fit:contain;background:var(--paper);border:1px solid var(--line);border-radius:8px}
  .invscan-file{font-size:11px;color:var(--slate-700);word-break:break-all}
  .invscan-meta{font-size:11px;color:var(--slate-500)}
  .invscan-none{font-size:12px;color:var(--slate-500)}

  .ssdone{margin-top:10px;font-size:13px;font-weight:600;color:#15803D}
  .ssstat-ready .ssstat-v{color:#0D7692}
  .ssstat-done .ssstat-v{color:#15803D}
  /* The catalog's own picture, beside the scans — a reference, never a
     substitute, and labelled as one. */
  .ssv-side-ref{opacity:.92}
  .ssv-img-ref{max-height:300px}

  .ssissues{padding:0 0 14px;margin-top:14px}
  .ssissue-list{list-style:none;margin:0;padding:0}
  .ssissue-list li{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;padding:8px 14px;border-bottom:1px solid var(--line);font-size:13px}
  .ssissue-k{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--warn);flex:none;width:96px}
  .ssissue-n{color:var(--ink);word-break:break-all}
  .ssissue-d{color:var(--slate-500);font-size:11px}
  .ssissues .btn{margin:12px 14px 0}

  /* Assignment 15B — the Catalog Intake context strip shown only when the
     intake was opened from a scan pair. Ordinary Catalog Intake never
     renders it, so the two surfaces stay visually identical otherwise. */
  .ciscan{display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:9px 12px;margin-bottom:12px}
  .ciscan-l{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--slate-500)}
  .ciscan-v{font-size:13px;color:var(--ink)}
  .ciscan-f{font-size:11px;color:var(--slate-500);margin-left:auto}

  @media(max-width:860px){
    .sswork{grid-template-columns:1fr}
    .ssq{max-height:320px}
  }

  /* ============================================================
     Assignment 17A — Listings.
     No new component family and no new colour. The workspace is
     .invbar + .filters/.fpill + .tablewrap + .empty verbatim; the editor
     is .panel + .metagrid + .fld + .btn verbatim. Only the pieces below
     — a listing-state chip, a readiness checklist, and the photo strip —
     have no existing equivalent, and each reuses a documented palette
     entry rather than introducing one.

     The three status chips deliberately borrow three EXISTING Fixed
     Status Palette meanings rather than inventing a fourth hue:
     positive/complete (#15803D), negative/needs-correcting (#B91C1C) and
     neutral/no-state-yet (#64748B) — the same values .chip.sold,
     .chip.cancelled and .chip.ret already carry. They get their own
     class names because a listing draft is not a sale, a cancellation or
     a return, and the DOM should not say it is. */
  .chip.lsready{background:#E4F3EA;color:#15803D}
  .chip.lsattn{background:#FBE7E7;color:#B91C1C}
  .chip.lsdraft{background:#EDEFF2;color:#64748B}
  /* A button whose whole label IS a chip — used on Inventory rows, where
     one control both reports the listing state and opens it. */
  .lschipbtn{padding:2px 4px;border-color:transparent;background:transparent}
  .lschipbtn:hover{background:#f0f2f5}
  .lsmuted{color:var(--slate-500);font-size:11.5px}
  .lsissue{font-size:12px;color:var(--slate-700);max-width:280px}
  /* SKU, date and the action pair are single facts — they wrap into two
     lines before the flexible Card/Issues columns give up any width, so
     they are pinned. */
  #lsBody td.mono,#lsBody td:last-child{white-space:nowrap}
  #lsBody td:last-child .cellactions{flex-wrap:nowrap}
  /* The gallery card's action row — Edit beside the listing control,
     replacing the single full-width Edit button. */
  .gcard .gactions{display:flex;gap:5px;align-items:center;margin-top:8px}
  .gcard .gactions .btn{flex:1;justify-content:center;text-align:center}
  .bulkbar button.ls{background:#1D4ED8}

  .lshead{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-bottom:14px}
  .lshead-name{font-family:var(--display);font-size:16px;font-weight:700}
  .lshead-meta{color:var(--slate-500);font-size:12.5px;margin-top:2px}
  .lshead-facts{display:flex;align-items:center;gap:9px;font-size:12px;color:var(--slate-700);flex-wrap:wrap}
  .lspanel{padding:14px 16px;margin-bottom:14px}
  .lspanel-hd{font-weight:700;font-size:12.5px;margin-bottom:10px}

  /* Readiness at a glance — the same information the issue list spells
     out, compressed to one line so a fifty-card session can scan it. */
  .lscheck{display:flex;gap:6px;flex-wrap:wrap}
  .lscheck-i{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.4px;padding:3px 8px;border-radius:5px}
  .lscheck-i.ok{background:#E4F3EA;color:#15803D}
  .lscheck-i.no{background:#FFF4E0;color:var(--warn)}
  .lsissues{list-style:none;margin:10px 0 0;padding:0}
  .lsissues li{font-size:12.5px;color:var(--slate-700);padding:4px 0 4px 14px;position:relative}
  .lsissues li::before{content:"•";position:absolute;left:2px;color:var(--slate-500)}
  .lsissues li.err{color:var(--danger)}
  .lsissues li.err::before{color:var(--danger)}

  .lstitlebar{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .lstitlebar .over{color:var(--danger);font-weight:700}
  .lsmarket{margin:0}
  .lsmarket input{width:100%;padding:7px 9px;border:1px solid var(--line);border-radius:8px;font-family:var(--mono);font-size:15px;font-weight:600;background:#fff}
  .lsmarket input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}
  .lsmargin{font-family:var(--mono);font-size:11.5px;font-weight:600;margin-top:4px}
  .lsmargin.up{color:#15803D} .lsmargin.down{color:var(--danger)}
  .lsresearch{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:10px}
  .lsresearch .btn{text-decoration:none;display:inline-flex;align-items:center}
  .lsrow{display:flex;gap:22px;align-items:flex-start;flex-wrap:wrap}
  .lsrow .k{font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600}
  .lsrow .v{font-size:14px;font-weight:600;margin-top:2px}
  .lsrow .btn{margin-left:auto}

  /* Photos are REFERENCES to the inventory record's own assets — there is
     deliberately no upload target, no remove control and no crop here. */
  .lsphotos{display:flex;gap:12px;flex-wrap:wrap}
  .lsphoto{width:150px;display:flex;flex-direction:column;gap:4px}
  .lsphoto-img{aspect-ratio:5/7;background:var(--paper);border:1px solid var(--line);border-radius:8px;display:flex;align-items:center;justify-content:center;overflow:hidden}
  .lsphoto-img img{width:100%;height:100%;object-fit:contain}
  .lsphoto-off{font-size:11px;color:var(--slate-500);text-align:center;padding:8px}
  .lsphoto-cap{font-size:11.5px;color:var(--slate-700)}
  .lsphoto-n{font-family:var(--mono);font-size:10.5px;font-weight:700;background:var(--ink);color:#fff;border-radius:5px;padding:1px 5px;margin-right:4px}
  .lsphoto-file{font-size:10px;color:var(--slate-500);word-break:break-all}
  .lsphoto-move{display:flex;gap:4px}
  .lsphoto-move .btn{flex:1;padding:3px 6px;border:1px solid var(--line)}
  .lsphoto-move .btn[disabled]{opacity:.35;cursor:default}

  /* Description is generated, correct, and rarely touched — demoted
     behind one disclosure instead of occupying the form. */
  .lsdisclose{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);padding:12px 16px}
  .lsdisclose summary{font-weight:700;font-size:12.5px;cursor:pointer}
  .lsdisclose textarea{font-size:13px;line-height:1.5}

  /* ---------------- Assignment 17B: Account Connections + eBay Settings ----------------
     The connection row IS the navigation target — there is no separate
     "Manage" button, so the whole row has to read and behave like one
     control. Everything else here is a small, plain vocabulary for one
     page: a status chip, a banner, a notice, an environment segment. */
  .ebconn{display:flex;align-items:center;gap:14px;width:100%;text-align:left;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px;box-shadow:var(--shadow);transition:border-color .15s,box-shadow .15s}
  .ebconn:hover{border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.12)}
  .ebconn-mark{font-family:var(--display);font-weight:800;font-size:12px;letter-spacing:.4px;color:var(--slate-700);background:var(--paper);border:1px solid var(--line);border-radius:8px;padding:8px 10px;flex-shrink:0}
  .ebconn-body{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
  .ebconn-title{font-family:var(--display);font-weight:700;font-size:14px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  .ebconn-sub{font-size:12px;color:var(--slate-500)}
  .ebconn-go{font-size:20px;color:var(--slate-500);flex-shrink:0;line-height:1}

  .ebchip{font-size:10.5px;font-weight:700;letter-spacing:.3px;padding:2px 8px;border-radius:20px;white-space:nowrap}
  .ebchip.on{background:#E6F6EC;color:#15803D}
  .ebchip.warn{background:#FFF4E0;color:var(--warn)}
  .ebchip.off{background:var(--paper);color:var(--slate-500);border:1px solid var(--line)}

  .ebback{background:none;border:none;color:var(--slate-500);font-size:12.5px;font-weight:600;padding:0 0 10px}
  .ebback:hover{color:var(--ink)}

  .ebintro{font-size:14px;color:var(--slate-700);max-width:34rem;margin:0 0 16px}
  .btn.lg{padding:11px 22px;font-size:14px}
  .ebactions{display:flex;gap:8px;flex-wrap:wrap;align-items:center}

  .ebbanner{border:1px solid var(--line);border-left-width:3px;border-radius:10px;background:var(--surface);padding:12px 16px;font-size:13px;color:var(--slate-700);margin-bottom:16px;max-width:44rem}
  .ebbanner.ok{border-left-color:#15803D;background:#F4FBF6}
  .ebbanner.warn{border-left-color:var(--warn);background:#FFFBF2}

  .ebnotice{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);padding:18px 20px;max-width:44rem}
  .ebnotice h3{font-family:var(--display);font-size:14.5px;margin:0 0 8px}
  .ebnotice p{font-size:13px;color:var(--slate-700);margin:0 0 10px}
  .ebnotice p:last-child{margin-bottom:0}

  .ebenv{margin-top:26px;padding-top:18px;border-top:1px solid var(--line);max-width:44rem}
  .ebenv-label{font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600;margin-bottom:6px}
  .ebenv-seg{display:inline-flex;border:1px solid var(--line);border-radius:8px;overflow:hidden;background:var(--surface)}
  .ebenv-b{background:none;border:none;padding:7px 16px;font-size:12.5px;font-weight:600;color:var(--slate-500)}
  .ebenv-b.on{background:var(--ink);color:#fff}
  .ebenv-note{font-size:11.5px;margin:8px 0 0;max-width:38rem}

  .ebdefaults{max-width:44rem}
  .ebmissing{display:block;font-size:11.5px;color:var(--warn);margin-top:4px}
  .ebready{font-family:var(--display);font-weight:700;font-size:13.5px;margin:12px 0 4px}
  .ebready.ok{color:#15803D}
  .ebready.no{color:var(--warn)}
  .ebreturn{margin-top:20px;max-width:44rem}

  /* The account context strip on a Listing Draft: derived from the
     connection, never stored on the draft. */
  .lsebay{display:flex;gap:18px;flex-wrap:wrap;align-items:baseline;border:1px solid var(--line);border-radius:10px;background:var(--paper);padding:10px 14px;margin-top:12px}
  .lsebay .k{font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600}
  .lsebay .v{font-size:12.5px;font-weight:600}
  .lsebay .v.no{color:var(--warn)}
  .lsebay-note{flex-basis:100%;font-size:11.5px;color:var(--slate-500);margin:2px 0 0}

  /* 17C — publication readiness. A STATEMENT, not a control: it explains
     exactly what would stop this draft becoming an eBay listing, grouped
     by who owns the answer. There is no Publish button, because
     publishing is not built. */
  .lspub{border:1px solid var(--line);border-radius:10px;background:var(--paper);padding:10px 14px;margin-top:10px}
  .lspub-hd{font-family:var(--display);font-weight:700;font-size:12.5px;margin-bottom:8px}
  .lspub-hd .lsmuted{font-family:var(--sans);font-weight:400}
  .lspub-group{margin-top:8px}
  .lspub-group-k{font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600;margin-bottom:4px}
  .lspub-note{font-size:11.5px;color:var(--slate-500);margin:10px 0 0}
  .lspub-why{list-style:none;margin:6px 0 0;padding:0}
  .lspub-why li{font-size:11.5px;color:var(--slate-700);padding:3px 0 3px 14px;position:relative}
  .lspub-why li::before{content:'!';position:absolute;left:0;color:var(--warn);font-weight:700}

  /* ============================================================
     eBay operations subsystem — Assignment 18D
     ============================================================
     One scoped design system for five pages, built on the app's existing
     tokens rather than a second one. Four rules produce most of the look:

       SPACING IS A LADDER, NOT A CHOICE. 8 / 16 / 24 / 32 only, through
       --eo-1..4. 18C's eBay surfaces used 5, 6, 7, 9, 10, 12, 13, 14, 18
       and 20px in inline styles, which is why nothing lined up with
       anything and everything felt like it was touching.

       BORDERS ARE EARNED. A card gets an outline when it is genuinely a
       separate object; a table does not, a metric does not, and a group
       of metrics is ONE outlined object with hairlines inside it rather
       than five outlined boxes side by side.

       MONEY IS A COLUMN, NOT A SENTENCE. Every figure is right-aligned
       tabular mono at one size, so the eye compares vertically without
       needing gridlines to help it.

       ONE ACCENT PER ROW AT MOST. An exception is marked by an accent
       rail AND a worded pill — never by colour alone, and never by a
       fourth badge.
     ============================================================ */
  .eohost{
    --eo-1:8px; --eo-2:16px; --eo-3:24px; --eo-4:32px;
    max-width:1180px;
  }

  /* ---- page and section rhythm ---- */
  .eopage-hd{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--eo-3);flex-wrap:wrap;margin-bottom:var(--eo-3)}
  .eopage-hd h2{font-family:var(--display);font-size:21px;font-weight:700;letter-spacing:-.01em;margin:0 0 4px;color:var(--ink)}
  .eopage-hd p{margin:0;font-size:13.5px;color:var(--slate-500);max-width:66ch}
  .eopage-hd-a{display:flex;gap:var(--eo-1);flex-wrap:wrap;padding-top:2px}
  .eosection{margin-top:var(--eo-4)}
  .eosection-hd{display:flex;align-items:baseline;justify-content:space-between;gap:var(--eo-2);flex-wrap:wrap;margin-bottom:var(--eo-2)}
  .eosection-hd h3{font-family:var(--display);font-size:13.5px;font-weight:700;margin:0;color:var(--ink)}
  .eonote{font-size:12px;color:var(--slate-500)}
  .eofoot{font-size:12px;color:var(--slate-500);margin:var(--eo-4) 0 0;max-width:80ch}
  /* Every monetary metric names its period. It sits UNDER the figures it
     qualifies rather than beside the section heading, because at a wide
     viewport a right-aligned sentence ends up a screen away from the
     numbers it is about. */
  .eoperiod{font-size:12px;color:var(--slate-500);margin:10px 0 0;max-width:80ch}
  .warnink{color:var(--warn)}

  /* ---- the connection strip ---- */
  /* Identity on the left, the two controls that act on it on the right,
     and the last-sync sentence underneath. It is a strip rather than a
     panel because it is chrome for the page, not content on it. */
  .eoconn{display:flex;align-items:center;justify-content:space-between;gap:var(--eo-2);flex-wrap:wrap;
    background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--eo-2) var(--eo-2)}
  .eoconn-id{display:flex;align-items:center;gap:var(--eo-1);flex-wrap:wrap;min-width:0}
  .eoconn-seller{font-size:12px;color:var(--slate-700)}
  .eoconn-note{font-size:12px;color:var(--slate-500)}
  .eoconn-a{display:flex;align-items:center;gap:var(--eo-1);flex-wrap:wrap}
  .eoconn-last{flex-basis:100%;margin:0;font-size:12px;color:var(--slate-500);border-top:1px solid var(--line);padding-top:var(--eo-1)}
  .eowindow{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--slate-500);margin:0}
  .eowindow select{padding:7px 9px;border:1px solid var(--line);border-radius:8px;font-size:12.5px;background:#fff;color:var(--ink)}
  .eowindow select:focus-visible{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(200,145,42,.14)}

  /* ---- notices ---- */
  /* One notice component for every "here is a fact about the system"
     statement across all five pages, replacing 18C's four hand-rolled
     .panel + inline-style variants. */
  .eonotice{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:var(--eo-2)}
  .eonotice.warn{border-color:var(--gold);background:var(--gold-soft)}
  .eonotice.tight{margin-top:var(--eo-2);padding:12px var(--eo-2)}
  .eoconn .eonotice{flex-basis:100%;margin-top:var(--eo-1)}
  .eonotice-t{font-family:var(--display);font-weight:700;font-size:12.5px;color:var(--ink);display:flex;align-items:center;gap:var(--eo-1);flex-wrap:wrap}
  .eonotice p{margin:6px 0 0;font-size:12.5px;color:var(--slate-500);max-width:80ch}
  .eonotice .eonotice-only{margin:0}
  .eonotice .btn{margin-top:12px}

  /* ---- KPI strip ---- */
  /* ONE outlined object with hairlines between the cells, not N cards.
     Restrained on purpose: the Overview answers "what happened / what
     needs attention", and a wall of equal-weight tiles answers neither. */
  .eokpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:1px;
    background:var(--line);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
  .eokpi{background:var(--surface);padding:var(--eo-2) var(--eo-2) 14px}
  .eokpi .k{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--slate-500);font-weight:600}
  .eokpi .v{display:block;font-family:var(--display);font-size:24px;font-weight:600;color:var(--ink);margin-top:6px;line-height:1.15;font-variant-numeric:tabular-nums}
  .eokpi .v .eopending{font-size:15px}
  .eokpi .n{display:block;font-size:11.5px;color:var(--slate-500);margin-top:4px;line-height:1.35}
  /* An actionable count, not an alarm: a warm ground and a warm number,
     and the label under it says what to do. */
  .eokpi.act{background:var(--gold-soft)}
  .eokpi.act .v{color:var(--warn)}

  /* ---- tables ---- */
  /* Borderless: no wrapper card, no vertical rules, one hairline per row.
     A table on a page is not a separate object from the page. */
  /* The 3px inset-and-pull-back gives italic glyphs in the flush-right
     money column room to overhang without being trimmed by the scroll
     container, while leaving the table's own edges aligned with the
     headings above it. */
  .eotablewrap{overflow-x:auto;padding:0 3px;margin:0 -3px}
  .eotable{width:100%;border-collapse:collapse;font-size:13px}
  .eotable th{background:transparent;text-align:left;padding:0 var(--eo-2) 10px;font-size:11px;text-transform:uppercase;
    letter-spacing:.4px;color:var(--slate-500);font-weight:600;border-bottom:1px solid var(--line);white-space:nowrap}
  .eotable td{padding:14px var(--eo-2);border-bottom:1px solid #EFF2F6;vertical-align:middle}
  .eotable tbody tr:last-child td{border-bottom:none}
  .eotable th:first-child,.eotable td:first-child{padding-left:0}
  .eotable th:last-child,.eotable td:last-child{padding-right:0}
  .eotable td.num,.eotable th.num{text-align:right}
  .eotable-compact td{padding-top:11px;padding-bottom:11px}
  .eotable .eocell-item{min-width:200px}

  /* The economics ladder on Analytics reuses the same table with its own
     subtotal rules, so the arithmetic reads the way it does in the
     drawer rather than in a second visual language. */
  .eoladder tr.sum td{font-weight:600;color:var(--ink);border-top:1px solid var(--line)}
  .eoladder tr.total td{font-weight:700;border-top:2px solid var(--ink);font-size:13.5px}
  .eoladder tr.muted td{color:var(--slate-500)}
  .eoladder tbody tr:hover{background:transparent}

  /* ---- row internals ---- */
  .eoitem{font-weight:600;font-size:13px;color:var(--slate-900);line-height:1.35}
  /* Secondary identity (SKU, listing id, link state) sits under the title
     at a genuinely smaller weight, so the eye lands on the card first. */
  .eometa{font-size:11.5px;color:var(--slate-500);margin-top:5px;display:flex;flex-wrap:wrap;gap:6px var(--eo-1);align-items:center}
  .eometa-strong{font-size:12.5px;color:var(--slate-700);font-weight:500}
  .eonum{font-family:var(--mono);font-size:12.5px;font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--ink)}
  .eonum-sub{font-family:var(--mono);font-size:11px;font-variant-numeric:tabular-nums;color:var(--slate-500);white-space:nowrap;margin-top:3px}
  .eomono{font-family:var(--mono);font-variant-numeric:tabular-nums}
  /* "Pending" is a first-class value, never rendered as $0.00. It reads
     as deliberately unresolved rather than as a number. */
  .eopending{font-style:italic;color:var(--slate-500);font-family:var(--body);font-size:11.5px;font-weight:400}

  /* A clickable order row. The affordance is the cursor and the hover
     wash — no chevron column, because a whole extra column of identical
     glyphs is noise that never once told anyone anything. */
  .eorow{cursor:pointer}
  .eorow:hover{background:var(--paper)}
  .eorow:focus-visible{outline:2px solid var(--gold);outline-offset:-2px}
  /* An exception's accent rail. It accompanies the worded pill in the
     first cell; it never carries the meaning by itself. */
  .eorow.attn td:first-child{box-shadow:inset 3px 0 0 var(--danger)}
  .eorow.attn td:first-child{padding-left:12px}

  /* ---- filters ---- */
  .eofilters{display:flex;align-items:center;justify-content:space-between;gap:var(--eo-2);flex-wrap:wrap;margin:var(--eo-3) 0 var(--eo-2)}
  .eofilters-g{display:flex;gap:6px;flex-wrap:wrap}

  /* ---- the attention banner and list ---- */
  .eobanner{display:flex;align-items:center;gap:var(--eo-1);flex-wrap:wrap;margin-top:var(--eo-2);
    background:var(--gold-soft);border:1px solid var(--gold);border-radius:var(--radius);padding:12px var(--eo-2);font-size:12.5px;color:var(--slate-700)}
  .eobanner-a{display:flex;gap:var(--eo-1);margin-left:auto;flex-wrap:wrap}

  .eoattn{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);overflow:hidden}
  .eoattn.empty-quiet{background:transparent;border-style:dashed}
  .eoattn.empty-quiet p{margin:0;padding:var(--eo-2)}
  .eoattn-row{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--eo-2);flex-wrap:wrap;
    padding:var(--eo-2);border-bottom:1px solid var(--line);border-left:3px solid var(--danger)}
  .eoattn-row:last-child{border-bottom:none}
  .eoattn-main{min-width:260px;flex:1 1 340px}
  .eoattn-t{font-weight:600;font-size:13px;color:var(--slate-900)}
  .eoattn-w{display:flex;align-items:baseline;gap:var(--eo-1);flex-wrap:wrap;font-size:12.5px;color:var(--slate-700);margin-top:6px}
  .eoattn-m{font-size:11.5px;color:var(--slate-500);margin-top:5px}
  .eoattn-act{display:flex;gap:6px;flex-wrap:wrap;align-items:center}

  /* ---- settlement state ---- */
  /* Provisional is warm-neutral, not alarming — an order awaiting its
     label fee is normal, not a problem. Sized to match .chip exactly,
     because the drawer header shows one of each side by side and two
     pill dialects in one row reads as an accident. */
  .eostate{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;padding:3px 9px;border-radius:20px;white-space:nowrap}
  .eostate.prov{background:var(--gold-soft);color:var(--warn)}
  .eostate.settled{background:#E8F3EC;color:#1F6B3F}

  /* ---- the drawer ---- */
  /* Sits UNDER the modal layer (z-index 70) on purpose, so the link
     picker opens over it rather than behind it. */
  .eoscrim{position:fixed;inset:0;background:rgba(20,26,36,.42);z-index:60}
  .eodrawer{position:fixed;top:0;right:0;bottom:0;width:min(520px,100vw);background:var(--surface);border-left:1px solid var(--line);
    box-shadow:-18px 0 44px rgba(20,26,36,.18);z-index:61;display:flex;flex-direction:column;
    --eo-1:8px; --eo-2:16px; --eo-3:24px; --eo-4:32px}
  .eodrawer:focus{outline:none}
  .eodrawer-hd{padding:var(--eo-3);border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:flex-start;gap:var(--eo-2);flex:0 0 auto}
  .eodrawer-t{font-family:var(--display);font-weight:700;font-size:14px;color:var(--ink)}
  .eodrawer-bd{padding:0 var(--eo-3) var(--eo-4);overflow-y:auto;flex:1 1 auto}
  .eodrawer-x{border:0;background:none;font-size:22px;line-height:1;cursor:pointer;color:var(--slate-500);padding:2px 8px;border-radius:8px}
  .eodrawer-x:hover{background:var(--paper);color:var(--ink)}
  .eodrawer-x:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
  .eodrawer-note{margin:var(--eo-2) 0 0;font-size:12px;color:var(--slate-500)}
  .eogroup{margin-top:var(--eo-3)}
  .eogroup-k{font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;color:var(--slate-500);font-weight:700;padding-bottom:var(--eo-1);border-bottom:1px solid var(--line)}
  .eodrawer-item{padding:var(--eo-2) 0;border-bottom:1px solid var(--line)}
  .eodrawer-item:last-child{border-bottom:none}
  .eodrawer-item-a{display:flex;gap:6px;flex-wrap:wrap;margin-top:12px}

  /* Financial completeness, stated once instead of inferred from where
     the word "Pending" happens to appear in the ladder. Every chip
     carries its state as a WORD; the tint is confirmation, never the
     message. */
  .eofacts{display:flex;flex-wrap:wrap;gap:6px;margin-top:12px}
  .eofact{display:inline-flex;align-items:baseline;gap:6px;border:1px solid var(--line);border-radius:8px;padding:5px 9px;font-size:11px;background:var(--paper)}
  .eofact-k{color:var(--slate-500)}
  .eofact-v{font-weight:700;color:var(--slate-700)}
  .eofact.ok{background:#F1F8F3;border-color:#D7E9DD}
  .eofact.ok .eofact-v{color:#1F6B3F}
  .eofact.wait{background:var(--gold-soft);border-color:#EBDCB6}
  .eofact.wait .eofact-v{color:var(--warn)}

  /* The economics ledger. A definition list rendered as rows so the
     money column aligns; subtotal and total rules carry the arithmetic
     visually instead of restating it in prose. */
  .eofin{width:100%;border-collapse:collapse;margin-top:12px}
  .eofin td{padding:6px 0;font-size:12.5px;color:var(--slate-700);vertical-align:baseline}
  .eofin td+td{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--ink)}
  .eofin td.gap{padding-top:var(--eo-2)}
  .eofin tr.spacer td{padding:0;height:var(--eo-1)}
  .eofin tr.sum td{border-top:1px solid var(--line);font-weight:600;color:var(--ink);padding-top:8px}
  .eofin tr.total td{border-top:2px solid var(--ink);font-weight:700;font-size:13.5px;padding-top:10px}
  .eofin tr.muted td{color:var(--slate-500)}
  .eofin td .why{display:block;font-size:11px;color:var(--slate-500);font-family:var(--body);font-weight:400;font-variant-numeric:normal;margin-top:2px;white-space:normal}

  .eohost .empty{padding:var(--eo-4) var(--eo-3)}
  .eohost .empty+.eonotice{margin-top:var(--eo-3)}

  /* ------------------------------------------------------------
     Responsive. This is a desktop tool, so "narrow" means an
     unmaximized window. Nothing scales down uniformly: the SECONDARY
     column steps aside and everything that survives keeps its size,
     because a 10px order date helps nobody.
     ------------------------------------------------------------ */
  @media (max-width:1180px){
    .eohost{--eo-3:20px; --eo-4:28px}
  }
  /* Date/buyer on Orders, canonical SKU on Listings, the explanation
     column on the Analytics ladder. Item, status, money and profit — the
     four a queue is actually read for — always stay.

     The breakpoint is 1180px rather than something tighter because the
     column has to leave BEFORE the table starts clipping, not once it
     already has: below roughly this width the five columns no longer fit
     the workspace, and an overflow-scrolled Profit column is a Profit
     column the owner cannot see. */
  @media (max-width:1180px){
    .eotable .eocol-secondary{display:none}
  }
  @media (max-width:860px){
    .eokpis{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
    .eoconn{align-items:flex-start}
    .eoconn-a{width:100%;justify-content:flex-start}
    .eoattn-act{width:100%}
  }
  @media (max-width:720px){
    .eodrawer{width:100vw}
  }

  /* ============================================================
     Offers — Assignment 18E
     ============================================================
     Deliberately small. The Offers workspace reuses the eBay
     subsystem's whole visual system — .eotable, .eodrawer, .eofin,
     .fpill, .eobanner, .chip, .eopending — and adds only the four
     things it genuinely has that Orders does not: a countdown, a
     negotiation timeline, a counter-offer calculator, and an action
     bar. Anything that looked like it needed a new rule was a sign the
     page was drifting away from its sibling. */

  /* The countdown. Colour is CONFIRMATION, never the message: the row
     always spells the remaining time in words, so "2h left" is legible
     with no colour perception at all. */
  .mofleft.soon{color:var(--warn);font-weight:700}
  .mofleft.muted{font-style:italic}

  /* The action bar. Buttons sit at the END of the drawer, after every
     number that should inform them — a layout choice, not a decorative
     one. */
  .mofactions{display:flex;gap:var(--eo-1);flex-wrap:wrap;margin-top:var(--eo-2)}

  /* The negotiation timeline. Oldest first, one line per real
     transition, with the amount right-aligned so a sequence of offers
     and counters reads as a column of money rather than a paragraph. */
  .mofhist{list-style:none;margin:var(--eo-2) 0 0;padding:0}
  .mofhist li{display:grid;grid-template-columns:1fr auto;gap:2px var(--eo-2);
    padding:var(--eo-1) 0;border-bottom:1px solid var(--line)}
  .mofhist li:last-child{border-bottom:none}
  .mofhist-w{font-size:12.5px;font-weight:600;color:var(--ink)}
  .mofhist-a{font-family:var(--mono);font-size:12.5px;color:var(--ink);text-align:right;white-space:nowrap}
  .mofhist-t{grid-column:1 / -1;font-size:11.5px;color:var(--slate-500)}

  /* The counter-offer calculator. One input, and the consequences of
     what is typed in it directly underneath. */
  .mofcounter{margin-top:var(--eo-2)}
  .mofcounter label{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.4px;
    color:var(--slate-500);font-weight:600;margin-bottom:5px}
  .mofcounter input{width:140px;padding:9px 11px;border:1px solid var(--line);border-radius:8px;
    font-family:var(--mono);font-size:14px;text-align:right;background:#fff}
  .mofcounter input:focus-visible{outline:2px solid var(--gold);outline-offset:1px}
  .mofcalc{margin-top:var(--eo-1)}

  /* Narrow widths: the offer table drops the same secondary column the
     order table does, and for the same reason — card, ask, offer and
     time left are what a decision needs, and they stay. */
  @media (max-width:860px){
    .mofhist li{grid-template-columns:1fr}
    .mofhist-a{text-align:left}
  }

  /* ============================================================
     Listings — Assignment 18F
     ============================================================
     Deliberately small, on exactly the terms 18E set for Offers. The
     Listings workspace reuses the eBay subsystem's whole visual system
     — .eotable, .eodrawer, .eofin, .eokpis, .fpill, .eobanner, .chip,
     .eopending — and adds only the two things it genuinely has that
     neither sibling does: a review panel that advances, and a chooser
     list of physical inventory copies. Anything that looked like it
     needed a third rule was a sign the page was drifting away from its
     siblings. */

  /* The suggestion review panel. Two columns — what eBay is showing, and
     the one record Card Master thinks it is — so the comparison is a
     glance rather than a memory test. It sits ABOVE the table because it
     is the fast path, and the table is the fallback. */
  .mlreview{border:1px solid var(--gold);background:var(--gold-soft);border-radius:var(--radius);
    padding:var(--eo-2);margin-top:var(--eo-2)}
  .mlreview-hd{display:flex;align-items:baseline;justify-content:space-between;gap:var(--eo-2);flex-wrap:wrap}
  .mlreview-hd .eogroup-k{border-bottom:none;padding-bottom:0}
  .mlreview-bd{display:grid;grid-template-columns:1fr 1fr;gap:var(--eo-2);margin-top:12px}
  .mlreview-col .eonote{display:block;font-size:10.5px;text-transform:uppercase;letter-spacing:.6px;
    color:var(--slate-500);font-weight:700;margin-bottom:6px}
  /* The evidence sentence, never a score. It is the whole justification
     for the button beside it, so it sits between the two. */
  .mlreview-why{margin:12px 0 0;font-size:12px;color:var(--slate-700);max-width:80ch}

  /* The chooser. One button per eligible physical copy, full width, with
     the discriminators — condition, cost, holding age, quantity — on the
     row itself. A person picking between three identical Mewtwo ex is
     picking between three costs, so the costs are what they see. */
  .mlcands{display:flex;flex-direction:column;gap:6px;margin-top:12px}
  .mlcand{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--eo-2);width:100%;
    text-align:left;background:var(--surface);border:1px solid var(--line);border-radius:10px;
    padding:12px var(--eo-2);cursor:pointer;font:inherit;color:inherit}
  .mlcand:hover:not(:disabled){border-color:var(--gold);background:var(--paper)}
  .mlcand:focus-visible{outline:2px solid var(--gold);outline-offset:1px}
  .mlcand:disabled{opacity:.55;cursor:default}
  .mlcand-b{flex:1 1 auto;min-width:0}
  .mlcand-q{font-family:var(--mono);font-size:11.5px;color:var(--slate-500);white-space:nowrap;padding-top:2px}

  /* Narrow widths: the review panel stacks rather than shrinking two
     columns into unreadable ones. Same principle as everywhere else in
     this subsystem — things step aside, they do not scale down. */
  @media (max-width:860px){
    .mlreview-bd{grid-template-columns:1fr}
  }

  /* ============================================================
     Assignment 19B-B — hosted shell: environment badge, sign-in gate,
     fail-closed panel
     ============================================================
     Three additions, no redesign. Every pre-19B-B rule above is
     untouched, and in LOCAL mode none of the selectors below ever
     matches anything visible: the badge, the gate and the panel all
     ship with .hide and only src/cloud-shell-ui.js removes it.

     The badge is DELIBERATELY UNDERSTATED. Its job is to be noticed once
     — "this is not the real business data" — and then to stay out of the
     way. A banner across the workspace would be noticed once too, and
     then resented, and then removed, which is how environment markers
     stop working. It sits under the existing brand block, in the
     sidebar's own dark palette, and Production shows nothing at all. */

  .envbadge{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:8px 0 0 22px}
  .envbadge-tag{font-family:var(--mono);font-size:9.5px;font-weight:600;letter-spacing:.7px;
    text-transform:uppercase;color:#0f1620;background:var(--gold-bright);
    border-radius:4px;padding:2px 6px;white-space:nowrap}
  .envbadge-ws{font-family:var(--body);font-size:10.5px;color:#c4cddb;white-space:nowrap;
    overflow:hidden;text-overflow:ellipsis;max-width:100%}
  .envbadge-select{font-family:var(--body);font-size:10.5px;color:#e6edf5;background:#22303e;
    border:1px solid #38485a;border-radius:5px;padding:2px 4px;max-width:150px}
  .envbadge-user{flex-basis:100%;font-family:var(--mono);font-size:9.5px;color:#7d8fa2;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .envbadge-signout{font-family:var(--body);font-size:10.5px;color:#9fb0c0;background:none;
    border:none;padding:0;text-decoration:underline;text-underline-offset:2px}
  .envbadge-signout:hover{color:#fff}

  /* The gate and the fail panel are full-viewport and opaque. They do not
     overlay a rendered application — bootstrap.js has not called loadAll()
     yet when either is showing — but they are painted as if they might,
     because a privacy control should not depend on the boot order staying
     the way it is today. */
  .cloudgate,.cloudfail{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;
    justify-content:center;padding:24px;background:var(--slate-900);overflow-y:auto}
  body.cloud-gated #appshell,body.cloud-blocked #appshell{visibility:hidden}

  .cloudgate-card,.cloudfail-card{width:100%;max-width:380px;background:var(--surface);
    border-radius:var(--radius);box-shadow:var(--shadow);padding:28px}
  .cloudgate-brand{display:flex;align-items:center;gap:10px;font-family:var(--display);
    font-weight:700;font-size:13px;letter-spacing:.2px;color:var(--slate-700)}
  .cloudgate-brand .dot{width:12px;height:12px;border-radius:3px;background:var(--gold-bright);
    box-shadow:0 0 0 3px rgba(224,169,62,.22);transform:rotate(45deg);flex-shrink:0}
  .cloudgate-card h1,.cloudfail-card h1{font-family:var(--display);font-size:21px;font-weight:700;
    margin:14px 0 4px}
  .cloudgate-env{font-family:var(--mono);font-size:10.5px;font-weight:600;letter-spacing:.6px;
    text-transform:uppercase;color:var(--warn);margin:0 0 18px}
  .cloudgate-card label{display:block;font-size:11.5px;font-weight:600;color:var(--slate-500);
    margin:12px 0 4px}
  .cloudgate-card input{width:100%;padding:9px 10px;border:1px solid var(--line);
    border-radius:8px;font-size:14px;color:var(--ink);background:var(--surface)}
  .cloudgate-card input:focus{outline:2px solid var(--gold);outline-offset:1px;border-color:var(--gold)}
  .cloudgate-card button[type=submit]{width:100%;margin-top:18px;padding:10px;border:none;
    border-radius:8px;background:var(--slate-900);color:#fff;font-family:var(--display);
    font-weight:600;font-size:14px}
  .cloudgate-card button[type=submit]:hover:not(:disabled){background:var(--slate-700)}
  .cloudgate-card button[type=submit]:disabled{opacity:.6;cursor:default}
  .cloudgate-error{margin:14px 0 0;font-size:12.5px;color:var(--danger)}

  .cloudfail-card{border-top:3px solid var(--danger)}
  .cloudfail-card p{margin:8px 0 0;font-size:13px;color:var(--slate-700);line-height:1.5}
