/* ============================================================================
   Moedatech Sales — design system v1
   Built from scratch for the sales product. Deliberately NOT the dashboard's
   system: this is a separate product with its own palette, type and shape.
   Do not import design-system/tokens.css here.

   Direction: the white studio equipment render. White body, cool graphite
   ground, darks reserved for the few parts that are genuinely dark. One
   signal colour, borrowed from hi-vis, spent only on urgency.

   Laptop first. The phone is the field case, not the design target.
   ========================================================================= */

/* ---- palette ------------------------------------------------------------
   Cool graphite. The dashboard's neutrals are warm, so the two products can
   never be mistaken for each other even on a shared screen. */
:root{
  --s0:#ffffff;
  --s5:#fafbfc;
  --s10:#f3f5f7;
  --s20:#e8eaee;
  --s30:#d7dae0;
  --s40:#b6bbc4;
  /* Measured, not asserted. The value that used to sit here claimed 4.6:1
     and was actually 3.19:1 on --s5 and 2.74:1 on --s20, so every secondary
     line in the app failed AA. This one clears 4.5:1 on every ground it is
     used on. If it changes, measure it again. */
  --s50:#667080;
  --s60:#5d646f;
  --s70:#3d434c;
  --s80:#262a31;
  --s90:#14171b;

  /* Signal. Hi-vis, and spent ONLY on time running out. If this colour shows
     up anywhere that is not urgency, the system is already leaking. */
  /* #c8461a measured 4.42:1 on --bg: close enough to look fine and still a
     fail. This clears 4.5 on every ground the clock sits on while staying
     the same hi-vis hue. */
  --signal:#bf4118;
  --signal-soft:#fbe9e3;

  /* Outcome. Rare by design: a queue row is neutral until it is resolved. */
  --good:#1f6b4a;
  --good-soft:#e2efe9;

  /* Caution. Lived on .bidpanel alone until 10 Sep 2026, which meant three
     rules in the outreach worklist -- .rq.spsp, .rc-star and the "talking"
     status -- resolved to NOTHING, because #wl-body is a top-level view and
     never had the variable in scope. An SPSP chip rendered with no pill at all
     and "Negotiating" printed in body ink. Palette-level, so a surface cannot
     reference it and silently get nothing. */
  --warn:#8a5a12;
  --warn-soft:#fdf3e3;

  --bg:var(--s10);
  --panel:var(--s0);
  --line:var(--s20);
  --line-strong:var(--s30);
  --ink:var(--s90);
  --ink-2:var(--s60);
  --ink-3:var(--s50);

  --font:'Instrument Sans','Noto Sans Arabic',-apple-system,BlinkMacSystemFont,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,'SF Mono',monospace;

  /* Type scale. Four steps, nothing between them. A dense table tempts you into
     11.5 / 12.5 / 13.5 to make a row fit; that is drift, not hierarchy. If a
     size is not one of these four, it is a bug. */
  /* Ratios checked, not assumed: 1.27 / 1.29 / 1.28. The first version of this
     scale was 11/13/16/20, which replaced drift with four numbers but left two
     of the three steps under 1.25 -- close enough that nothing separated a
     label from body text. Body moved 13 -> 14, which costs about 2px of row
     height and reads better. */
  --t-micro:11px;  --lh-micro:15px;   /* labels, counts, secondary meta */
  --t-body:14px;   --lh-body:20px;    /* everything a rep actually reads */
  --t-mid:18px;    --lh-mid:24px;     /* page and panel titles */
  --t-head:23px;   --lh-head:30px;    /* the one heading on a screen */

  /* Shape lock: one radius. Chips are the single exception and they are pills. */
  --r:6px;
  --r-pill:999px;

  /* Two curves, three durations. Never ease-in on interface. */
  --out:cubic-bezier(.22,1,.36,1);
  --in-out:cubic-bezier(.65,0,.35,1);
  --t-fast:110ms;
  --t:180ms;
  --t-slow:320ms;

  --detail:400px;
}

@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --s0:#16191e;  --s5:#1a1e24;  --s10:#12151a; --s20:#272c34;
    --s30:#353b45; --s40:#4c545f; --s50:#8e96a2; --s60:#aeb5bf;
    --s70:#cbd1d9; --s80:#e4e8ed; --s90:#f5f7f9;
    --signal:#f0733f; --signal-soft:#3a221a;
    --good:#5cb98d;   --good-soft:#163025;
    --warn:#e0a350;   --warn-soft:#3a2a12;
    --bg:var(--s10); --panel:var(--s5); --line:var(--s20); --line-strong:var(--s30);
  }
}
:root[data-theme="dark"]{
  --s0:#16191e;  --s5:#1a1e24;  --s10:#12151a; --s20:#272c34;
  --s30:#353b45; --s40:#4c545f; --s50:#8e96a2; --s60:#aeb5bf;
  --s70:#cbd1d9; --s80:#e4e8ed; --s90:#f5f7f9;
  --signal:#f0733f; --signal-soft:#3a221a;
  --good:#5cb98d;   --good-soft:#163025;
  --warn:#e0a350;   --warn-soft:#3a2a12;
  --bg:var(--s10); --panel:var(--s5); --line:var(--s20); --line-strong:var(--s30);
}

*,*::before,*::after{box-sizing:border-box}

html,body{height:100%}
body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--font);
  font-size:var(--t-body);
  line-height:var(--lh-body);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
[dir="rtl"] body{ font-feature-settings:"ss01"; }

/* Every number is mono. In a queue the eye scans columns of figures, and
   proportional digits make that column ragged. */
.num,time,.metric{font-family:var(--mono);font-variant-numeric:tabular-nums}

button,input,select{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:0;padding:0}
a{color:inherit}

::selection{background:var(--s80);color:var(--s0)}

:where(a,button,input,select,[tabindex]):focus-visible{
  outline:2px solid var(--ink);
  outline-offset:2px;
  border-radius:var(--r);
}


/* ---- viewing as --------------------------------------------------------
   Deliberately outside the app's palette: it is not part of the product, it
   is a state the product is in. Same treatment as the dashboard banner. */
.viewing{
  position:sticky;top:0;z-index:60;
  display:flex;align-items:center;justify-content:center;
  padding:7px 14px;
  background:#7c2d12;color:#fff;
  font-size:var(--t-micro);line-height:var(--lh-micro);font-weight:600;
  letter-spacing:.01em;
}
/* The frame is a full-height grid, so a banner above it has to come out of
   that height or the bottom of the app falls off the screen. */
body:has(.viewing) .app{height:calc(100dvh - 29px)}

/* ---- app frame ---------------------------------------------------------
   One column. The rail is gone: its nine destinations hang off the page title
   instead, which gives the table the full window. The detail panel still docks
   on the side; on a phone it still becomes a sheet and the bottom bar still
   carries navigation, exactly as before. */
.app{
  display:grid;
  grid-template-columns:minmax(0,1fr);
  height:100dvh;
  overflow:hidden;
}

/* The old rail, now a menu under the title. Same children, same ids: only the
   box around them changed. */
.navmenu{
  position:absolute;top:52px;left:50%;transform:translateX(-50%);
  z-index:60;width:250px;max-height:min(70vh,560px);overflow:auto;
  background:var(--panel);border:1px solid var(--line-strong);
  border-radius:10px;box-shadow:0 14px 40px rgba(20,23,27,.16);
  padding:8px 0 4px;
}
.navmenu[hidden]{display:none}

.nav{padding:6px 8px;display:flex;flex-direction:column;gap:1px}
.nav-item{
  display:flex;align-items:center;gap:10px;
  padding:7px 8px;border-radius:var(--r);
  color:var(--ink-2);
  transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out);
  text-decoration:none;
  width:100%;
}
.nav-item svg{width:16px;height:16px;flex:none;stroke-width:1.6}
.nav-item:hover{background:var(--s10);color:var(--ink)}
.nav-item[aria-current="page"]{background:var(--s20);color:var(--ink);font-weight:550}
.nav-count{
  margin-inline-start:auto;
  font-family:var(--mono);font-size:var(--t-micro);
  color:var(--ink-3);font-variant-numeric:tabular-nums;
}

.rail-foot{padding:8px;border-top:1px solid var(--line);margin-top:4px}

.new-btn{
  display:flex;align-items:center;justify-content:center;gap:7px;
  width:100%;padding:9px;border-radius:var(--r);
  background:var(--ink);color:var(--s0);
  font-size:var(--t-body);font-weight:550;
  transition:transform var(--t-fast) var(--out),opacity var(--t-fast) var(--out);
}
.new-btn svg{width:15px;height:15px;stroke-width:2}
.new-btn:hover{opacity:.88}
.new-btn:active{transform:translateY(1px)}

/* ---- main --------------------------------------------------------------- */
.main{display:flex;flex-direction:column;min-width:0;min-height:0}

.topbar{
  position:relative;
  /* The header is a LAYER, not just a bar, and it has to be one for the account
     menu to be usable at all.

     The menu hangs out of this header over the table and already carried
     z-index:140, which by the rules should have settled it -- the table's sticky
     header cells are z-index:2. It did not. A position:sticky cell inside a
     scrolling container gets its own composited layer, and that layer painted
     OVER the menu: elementsFromPoint at the "Open" column returned
     TH -> whoas -> whomenu, so the top third of the menu was covered by table
     headings and half its rows were unclickable.

     Raising the menu further would not have fixed it, because the two were not
     really being compared. Giving the header its own stacking context is: the
     whole header subtree now sorts above the whole scroll subtree in one
     decision, and no individual z-index inside either has to be tuned again.

     100, not 200: it must sit BELOW the modal veil at 120, so a dialog still
     covers the header rather than the header punching through it. */
  z-index:100;
  display:flex;align-items:center;gap:12px;
  padding:0 18px;height:58px;flex:none;
  border-bottom:1px solid var(--line);
  background:var(--panel);
}
.hdr-right{margin-inline-start:auto;display:flex;align-items:center;gap:10px;z-index:1}

/* Centred on the HEADER, not on the space left between the tabs and the identity
   chip -- flowed centring drifts every time either side changes width, and the
   right side changes width the moment initials go from two letters to one. */
.ttl{
  position:absolute;inset-inline:0;
  display:flex;justify-content:center;pointer-events:none;
}
.ttl-b{
  pointer-events:auto;
  display:inline-flex;align-items:center;gap:6px;
  padding:4px 10px;border-radius:var(--r);
  font-size:var(--t-mid);line-height:var(--lh-mid);font-weight:650;
  letter-spacing:-.01em;color:var(--ink);
  transition:background var(--t-fast) var(--out);
}
.ttl-b:hover{background:var(--s10)}
.ttl-b .caret{width:15px;height:15px;opacity:.55}
.ttl-b[aria-expanded="true"] .caret{transform:rotate(180deg)}
.ttl-b[aria-expanded="true"]{background:var(--s10)}
/* The page title is the top of the hierarchy and was sitting at the same size
   as a panel heading, so the tallest thing on screen was only 1.3x body.
   --t-head existed and was going unused outside the sign-in screen. */
.h1{font-size:var(--t-head);line-height:var(--lh-head);font-weight:600;letter-spacing:-.02em;margin:0}

.search{
  position:relative;width:260px;max-width:38vw;
}
.search input{
  width:100%;padding:7px 10px 7px 30px;
  background:var(--bg);
  border:1px solid transparent;border-radius:var(--r);
  transition:border-color var(--t-fast) var(--out),background var(--t-fast) var(--out);
}
.search input::placeholder{color:var(--ink-3)}
.search input:focus{background:var(--panel);border-color:var(--line-strong);outline:none}
.search svg{
  position:absolute;left:9px;top:50%;transform:translateY(-50%);
  width:14px;height:14px;color:var(--ink-3);pointer-events:none;
}
[dir="rtl"] .search input{padding:7px 30px 7px 10px}
[dir="rtl"] .search svg{left:auto;right:9px}

.who{
  width:26px;height:26px;border-radius:var(--r-pill);
  background:var(--s20);color:var(--ink-2);
  display:grid;place-items:center;
  font-size:var(--t-micro);font-weight:600;flex:none;
}



/* ---- the side filter ----------------------------------------------------
   The master control: which half of the market a rep is working. It sits
   immediately left of the search because it governs the search too, and
   reading left to right the narrowing happens before the query. */
.sides{
  display:flex;align-items:center;gap:18px;flex:none;z-index:1;
}
/* Underlined text, not pills. Exactly one is pressed at any moment, so the
   selected one has to be unmistakable rather than merely darker -- the rule
   under it is what carries that, and the weight change backs it up. */
.side-x{
  font:inherit;font-size:var(--t-body);font-weight:550;
  color:var(--ink-3);background:none;border:0;cursor:pointer;
  padding:19px 0 17px;line-height:1;white-space:nowrap;
  border-bottom:2px solid transparent;
  transition:color var(--t-fast) var(--out),border-color var(--t-fast) var(--out);
}
.side-x:hover{color:var(--ink)}
.side-x[aria-pressed="true"]{color:var(--ink);border-bottom-color:var(--ink);font-weight:650}



/* The same New, in reach of the filters a rep is already using. Icon only:
   the sidebar button carries the word, this is the shortcut. */
.side-new{
  display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:var(--r-pill);
  border:1px solid var(--line-strong);background:var(--panel);color:var(--ink-2);
  cursor:pointer;flex:none;
  transition:background var(--t-fast) var(--out),border-color var(--t-fast) var(--out),
             color var(--t-fast) var(--out);
}
.side-new svg{width:16px;height:16px;display:block}
.side-new:hover{background:var(--ink);border-color:var(--ink);color:var(--panel)}

/* Rewind undoes a close. Quiet by default: it is a correction, not an action
   a rep should be invited to take on a row they closed correctly. */
.rewind{
  font:inherit;font-size:var(--t-micro);line-height:1;
  padding:6px 11px;border-radius:var(--r-pill);
  border:1px solid var(--line-strong);background:var(--panel);color:var(--ink-2);
  cursor:pointer;
  transition:background var(--t-fast) var(--out),border-color var(--t-fast) var(--out),
             color var(--t-fast) var(--out);
}
.rewind:hover{background:var(--ink);border-color:var(--ink);color:var(--panel)}
.rewind:disabled{opacity:.55;cursor:default}


/* ---- grouped buckets ----------------------------------------------------
   A family of buckets behind one chip. The count reads as the family total
   until something is picked, then as how many of the family are on -- so the
   chip always answers "how much is in here" or "how much have I narrowed to". */
.chip.grp{display:inline-flex;align-items:center;gap:6px}
.chip.grp .caret{width:13px;height:13px;opacity:.55;flex:none}
.chip.grp[aria-expanded="true"] .caret{transform:rotate(180deg)}

.bkt-menu{
  position:fixed;z-index:60;min-width:216px;
  background:var(--panel);border-radius:var(--r);
  box-shadow:0 1px 2px rgba(20,23,27,.10), 0 10px 26px -8px rgba(20,23,27,.24);
  padding:5px;
}
.bkt-opt{
  display:flex;align-items:center;gap:10px;
  padding:9px 10px;border-radius:var(--r);cursor:pointer;
  font-size:var(--t-body);color:var(--ink);
  transition:background var(--t-fast) var(--out);
}
.bkt-opt:hover{background:var(--s10)}
.bkt-opt span{flex:1;min-width:0}
.bkt-opt input{
  width:15px;height:15px;flex:none;accent-color:var(--ink);cursor:pointer;margin:0;
}
.bkt-opt .n{
  font-family:var(--mono);font-size:var(--t-micro);font-weight:400;
  color:var(--ink-3);font-variant-numeric:tabular-nums;
}


/* The forward move in the OS pipeline is the one a rep is usually here to make,
   so it carries weight; the reverse ones stay quiet. */
.rewind.go{background:var(--ink);border-color:var(--ink);color:var(--panel)}
.rewind.go:hover{opacity:.9}
.bucket[data-b="os_prospect"]{background:var(--s20);color:var(--ink-2)}
.bucket[data-b="os_trial"]{background:var(--accent-soft,#e4edf5);color:#1f5c8b}
.bucket[data-b="os_paid"]{background:var(--good-soft);color:var(--good)}
.bucket[data-b="os_churned"]{background:var(--s20);color:var(--ink-3)}


/* ---- status as a row tone -----------------------------------------------
   A stripe on the row instead of a word in a column. Only the two failures
   carry a tint as well: if every state were tinted, none of them would read
   as a warning. */
.q tbody tr[data-tone]{box-shadow:inset 3px 0 0 var(--tone, transparent)}
.q tbody tr[data-tone="bad"]  {--tone:#bf4118;background:rgba(191,65,24,.045)}
.q tbody tr[data-tone="warn"] {--tone:#c98a2e;background:rgba(201,138,46,.04)}
.q tbody tr[data-tone="live"] {--tone:#1f5c8b}
.q tbody tr[data-tone="good"] {--tone:#1f6b4a}
.q tbody tr[data-tone="done"] {--tone:var(--line-strong)}
.q tbody tr[data-tone="bad"]:hover {background:rgba(191,65,24,.075)}
.q tbody tr[data-tone="warn"]:hover{background:rgba(201,138,46,.07)}


/* The key for the row stripes. Quiet, and next to the rows it explains. */
.legend{display:flex;align-items:center;gap:12px;flex:none;padding-inline-start:14px}
.lg-i{display:inline-flex;align-items:center;gap:5px;
  font-size:var(--t-micro);line-height:1;color:var(--ink-3);white-space:nowrap}
.lg-i i{width:9px;height:9px;border-radius:2px;display:block;background:var(--line-strong)}
.lg-i i[data-tone="bad"] {background:#bf4118}
.lg-i i[data-tone="warn"]{background:#c98a2e}
.lg-i i[data-tone="live"]{background:#1f5c8b}
.lg-i i[data-tone="good"]{background:#1f6b4a}
.lg-i i[data-tone="done"]{background:var(--line-strong)}

/* Three controls, one cell. Forward and gone are quiet until hovered; the
   trophy is the one worth noticing. */
.row-acts{display:inline-flex;align-items:center;gap:2px}
.tick.trophy:hover{color:#a8791f;background:rgba(168,121,31,.10)}
.tick.bad:hover{color:var(--signal);background:var(--signal-soft)}
@media (max-width:1100px){ .legend{display:none} }


/* Verified. Green, small, and only ever present when true. Sits on the text
   baseline so it reads as part of the name rather than a column of its own. */
.ver{
  width:13px;height:13px;display:inline-block;vertical-align:-2px;
  margin-inline-start:6px;color:var(--good);flex:none;
}

/* The machine mark. Fixed at two states -- one machine or several -- so a rep
   learns two shapes instead of decoding a different silhouette every row. */
.equip-btn{position:relative}
.equip-n{
  position:absolute;top:-2px;inset-inline-end:-4px;
  min-width:14px;height:14px;padding:0 3px;border-radius:99px;
  background:var(--ink);color:var(--panel);
  font:500 9px/14px var(--mono);text-align:center;
}


/* ---- the fulfillment wizard --------------------------------------------- */
.ff-seg{display:flex;gap:4px;padding:12px 12px 0;flex-wrap:wrap}
.ff-seg-b{
  font:inherit;font-size:var(--t-micro);line-height:1;padding:8px 11px;
  border:1px solid var(--line-strong);background:var(--panel);color:var(--ink-2);
  border-radius:var(--r-pill);cursor:pointer;
}
.ff-seg-b[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--panel)}

.ffa-list{display:flex;flex-direction:column;gap:8px}
.ffa{border:1px solid var(--line-strong);border-radius:var(--r);padding:9px 10px;background:var(--panel)}
.ffa-top{display:flex;align-items:baseline;gap:8px}
.ffa-mode{
  font:500 9px/1 var(--mono);letter-spacing:.05em;text-transform:uppercase;
  padding:3px 5px;border-radius:3px;background:var(--s20);color:var(--ink-3);flex:none;
}
.ffa-name{flex:1;min-width:0;font-weight:550;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ffa-ph{font-weight:400;color:var(--ink-3);font-family:var(--mono);font-size:var(--t-micro)}
.ffa-tot{font-family:var(--mono);font-size:var(--t-micro);color:var(--good);font-variant-numeric:tabular-nums}
.ffa-x{border:0;background:none;color:var(--ink-3);cursor:pointer;font-size:15px;line-height:1;padding:0 3px}
.ffa-x:hover{color:var(--signal)}
.ffa-f{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}
.ffa-f label{
  display:flex;flex-direction:column;gap:3px;
  font-size:10px;color:var(--ink-3);letter-spacing:.03em;
}
.ffa-f input,.ffa-f select{
  font:inherit;font-size:var(--t-micro);padding:6px 7px;
  border:1px solid var(--line-strong);border-radius:var(--r);background:var(--panel);color:var(--ink);
  width:88px;font-variant-numeric:tabular-nums;
}
.ffa-f input[type=date]{width:126px}
/* The documented data error in this product: a monthly rate typed as daily. */
.ffa-warn{margin-top:7px;font-size:var(--t-micro);color:var(--signal)}

.ff-bids{display:flex;flex-direction:column;gap:4px}
.ff-bid{
  display:flex;align-items:baseline;gap:10px;width:100%;text-align:start;
  padding:7px 9px;border-radius:var(--r);border:1px solid var(--line);
  background:var(--panel);cursor:pointer;font:inherit;
}
.ff-bid:hover{border-color:var(--ink-3)}
.ff-bid-who{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ff-bid-amt{font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-2)}

.ff-off{display:flex;gap:6px;flex-wrap:wrap}
.ff-off input{
  flex:1;min-width:110px;font:inherit;font-size:var(--t-body);padding:8px 10px;
  border:1px solid var(--line-strong);border-radius:var(--r);background:var(--panel);color:var(--ink);
}
.ff-tot{
  display:flex;justify-content:space-between;align-items:baseline;
  padding:12px;border-top:1px solid var(--line);
  font-size:var(--t-micro);color:var(--ink-3);
}
.ff-tot b{font-family:var(--mono);font-size:var(--t-mid);color:var(--ink);font-variant-numeric:tabular-nums}

/* ---- drawer detail rows -------------------------------------------------- */
.f-row{display:flex;gap:12px;align-items:baseline;padding:5px 12px}
.f-k{width:118px;flex:none;font-size:var(--t-micro);color:var(--ink-3)}
.f-v{flex:1;min-width:0;font-size:var(--t-body);color:var(--ink);unicode-bidi:plaintext;overflow-wrap:anywhere}
.chips{display:flex;gap:6px;flex-wrap:wrap;padding:12px}
.tiles{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;padding:12px}
.tile{border:1px solid var(--line);border-radius:var(--r);padding:9px 10px}
.tile b{display:block;font-size:var(--t-mid);font-weight:600;font-variant-numeric:tabular-nums}
.tile span{font-size:var(--t-micro);color:var(--ink-3)}
.cust-req{
  display:flex;align-items:baseline;gap:9px;width:100%;text-align:start;
  padding:7px 12px;border:0;background:none;cursor:pointer;font:inherit;
  transition:background var(--t-fast) var(--out);
}
.cust-req:hover{background:var(--s10)}
.cr-code{font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-3);flex:none}
.cr-eq{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cr-when{font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-3);flex:none}


/* ---- scrollbars ---------------------------------------------------------
   Hidden everywhere the app scrolls. The platform bar here renders with arrow
   buttons and a heavy track, which reads as a control to operate rather than
   the passive edge of a list -- and the content already runs to the edge, so
   there is nothing to discover. Scrolling itself is untouched: wheel, trackpad,
   keys and touch all behave exactly as before, and focus still scrolls into
   view. */
.scroll,.dock-body,.sheet-body,.find,.bkt-menu,.q-wrap,.view{
  scrollbar-width:none;              /* Firefox */
  -ms-overflow-style:none;           /* old Edge */
}
.scroll::-webkit-scrollbar,
.dock-body::-webkit-scrollbar,
.sheet-body::-webkit-scrollbar,
.find::-webkit-scrollbar,
.bkt-menu::-webkit-scrollbar,
.q-wrap::-webkit-scrollbar,
.view::-webkit-scrollbar{width:0;height:0;display:none}


/* A printed phone number is a control. It looks like text until you approach
   it, so it never shouts, but the cursor and the hover say it can be taken. */
.tel{
  font:inherit;font-family:var(--mono);font-size:inherit;
  color:inherit;background:none;border:0;padding:1px 3px;margin:0 -3px;
  border-radius:3px;cursor:pointer;unicode-bidi:plaintext;
  transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.tel:hover{background:var(--s20);color:var(--ink)}
.tel.copied{background:var(--good-soft);color:var(--good)}
.find-meta .tel{font-size:var(--t-micro)}
.ffa-ph + .tel{font-size:var(--t-micro);color:var(--ink-3)}

/* ---- find --------------------------------------------------------------- */
.find{
  /* Anchored to the input's end edge and allowed to be wider than it: the
     input is a compact affordance, the results are the actual reading.

     FIXED, not absolute. .app is the 100dvh grid shell and carries
     overflow:hidden -- that clip is load-bearing, it is what stops the page
     itself scrolling while .scroll does the scrolling. An absolutely
     positioned dropdown inside it is clipped by it, which costs nothing at a
     tall window and silently cuts the results off at a short one. Fixed
     escapes the clip; findAnchor() puts it under the input and sizes it to
     the room actually left on screen. */
  /* NO min-width HERE. There used to be one, with a comment saying it "has to
     yield to the max-width findAnchor() sets" — which is not how the cascade
     works. min-width beats max-width, always, so the floor won and the panel
     ran off the edge of the window exactly as the comment feared. findAnchor()
     now sets BOTH bounds inline from one measurement of the room available;
     leaving a floor here would be a second opinion about the same number. */
  position:fixed;z-index:50;
  box-sizing:border-box;overflow-x:hidden;
  /* Elevation, not elevation plus a drawn edge. A tight contact shadow does
     the work a border was doing -- separating the panel from what it covers --
     and the wider ambient one carries the height. */
  background:var(--panel);border-radius:var(--r);
  box-shadow:0 1px 2px rgba(20,23,27,.10), 0 8px 20px -6px rgba(20,23,27,.20);
  overflow:auto;display:none;padding:4px;   /* max-height is set by findAnchor */
}
.find.on{display:block}

.find-h{
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
  letter-spacing:.03em;padding:8px 10px 4px;
}
/* A grid, not a flex row. Under flex the name was the only shrinkable child,
   so a long company tag squeezed it to nothing -- a result row that showed a
   phone number and no name at all. Columns give the name a guaranteed share
   and make the tag the thing that truncates. */
.find-row{
  display:grid;grid-template-columns:minmax(0,1.5fr) auto minmax(0,1fr);
  align-items:baseline;gap:10px;width:100%;
  padding:7px 10px;border-radius:var(--r);text-align:start;
  transition:background var(--t-fast) var(--out);
}
.find-row:hover{background:var(--s10)}
.find-nm,.find-tag{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* plaintext: an Arabic name in an otherwise-English list keeps its own
   direction, so it truncates at its own end rather than losing its first word */
.find-nm{font-weight:550;unicode-bidi:plaintext}
.find-meta{font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-2);white-space:nowrap}
.find-tag{font-size:var(--t-micro);color:var(--ink-3);text-align:end}
.find-empty{padding:12px 10px;font-size:var(--t-micro);color:var(--ink-3)}

/* ---- filter strip ------------------------------------------------------- */
/* Search and the chips filter the same list, so they share one row. The row owns
   the padding and the rule; .strip is just the scrolling part inside it. */
.filters{
  display:flex;align-items:center;gap:10px;
  padding:9px 18px;flex:none;
  border-bottom:1px solid var(--line);
  background:var(--panel);
  min-width:0;
}
.filters .search{width:230px;flex:none}
.filters .search input{border-radius:var(--r-pill);background:var(--s10);border-color:transparent}
.filters .search input:focus{background:var(--panel);border-color:var(--line-strong)}

.strip{
  display:flex;align-items:center;gap:6px;
  flex:1;min-width:0;
  background:var(--panel);
  overflow-x:auto;scrollbar-width:none;
}
.strip::-webkit-scrollbar{display:none}

.chip{
  display:inline-flex;align-items:center;gap:6px;
  padding:4px 10px;border-radius:var(--r-pill);
  border:1px solid var(--line-strong);
  color:var(--ink-2);white-space:nowrap;
  font-size:var(--t-body);
  transition:border-color var(--t-fast) var(--out),background var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.chip:hover{border-color:var(--s40);color:var(--ink)}
.chip[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--s0)}
.chip .n{font-family:var(--mono);font-size:var(--t-micro);font-variant-numeric:tabular-nums;opacity:.7}

.chips{display:flex;flex-wrap:wrap;gap:6px;padding-top:2px}
#pf-body .facts{grid-template-columns:92px 1fr}

.strip-sep{width:1px;height:18px;background:var(--line);flex:none;margin:0 4px}
.strip-right{
  margin-inline-start:auto;
  display:flex;align-items:center;gap:6px;flex:none;
  padding-inline-start:14px;
}


/* ---- queue table -------------------------------------------------------
   Laptop gets a real table. The phone gets the same rows as cards, driven
   by data-label, so there is one renderer and not two. */
.scroll{overflow:auto;flex:1;min-height:0}

.q{width:100%;border-collapse:collapse}
.q thead th{
  position:sticky;top:0;z-index:2;
  background:var(--bg);
  text-align:start;font-weight:500;font-size:var(--t-micro);line-height:var(--lh-micro);
  letter-spacing:.02em;color:var(--ink-3);
  padding:8px 12px;
  border-bottom:1px solid var(--line);
  white-space:nowrap;
}
.q tbody tr{
  border-bottom:1px solid var(--line);
  transition:background var(--t-fast) var(--out);
  cursor:pointer;
}
.q tbody tr:hover{background:var(--panel)}
.q tbody tr[aria-selected="true"]{background:var(--panel);box-shadow:inset 2px 0 0 var(--ink)}
.q td{padding:9px 12px;vertical-align:middle}

.lead-name{font-weight:550;letter-spacing:-.005em}

/* The supplier name is a way into the supplier page, so it has to look like
   one -- but quietly. A blue link in a dense table is the loudest thing on the
   row and it is not the most important thing on the row. */
.lead-link{
  color:inherit;text-decoration:underline;text-decoration-color:var(--s30);
  text-underline-offset:3px;cursor:pointer;
  transition:text-decoration-color var(--t-fast) var(--out);
}
.lead-link:hover{text-decoration-color:var(--ink)}

/* Put in a bucket by a person rather than computed into it. Said on the row,
   not on hover: a row that is there because somebody decided so is a different
   fact from one the definition caught, and a rep reading the list is entitled
   to know which they are looking at. */
.lead-hand{
  color:var(--ink-3);font-size:var(--t-micro);line-height:var(--lh-micro);
  margin-top:2px;font-family:var(--mono);
}

/* Machines and yards, in words. "70 · 1y" joined two different quantities with
   a dot and labelled only the second, with a single letter. */
.fleetcell{line-height:var(--lh-body)}
.fleetcell b{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:600}
.fleetcell-sub{color:var(--ink-3);font-size:var(--t-micro);line-height:var(--lh-micro)}

/* One person, not a business. Outlined rather than filled: it is a fact about
   the record, not a status somebody should act on, and the row it sits on is
   already carrying a stage chip that IS one. Deliberately not --signal — a
   one-man yard is a perfectly good customer, not a problem. */
.indiv{
  display:inline-block;margin-inline-start:6px;padding:1px 7px;
  border-radius:var(--r-pill);box-shadow:inset 0 0 0 1px var(--line-strong);
  color:var(--ink-3);font-size:var(--t-micro);line-height:var(--lh-micro);
  vertical-align:middle;white-space:nowrap;
}

/* ---- the pager ----------------------------------------------------------
   Prospect stopped being 72 rows the day it started meaning every supplier by
   latest role. It lives in #state, the strip the empty and error states
   already own, so there is one place under the table rather than three. */
.pager{
  display:flex;align-items:center;gap:8px;
  padding:10px 18px;border-top:1px solid var(--line);
}
.pager-txt{
  flex:1;min-width:0;font-family:var(--mono);font-size:var(--t-micro);
  color:var(--ink-3);font-variant-numeric:tabular-nums;
}
.pg{
  font:inherit;font-size:var(--t-micro);padding:5px 12px;
  border-radius:var(--r-pill);border:1px solid var(--line-strong);
  background:var(--panel);color:var(--ink-2);cursor:pointer;
  transition:border-color var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.pg:hover:not(:disabled){border-color:var(--ink);color:var(--ink)}
.pg:disabled{opacity:.45;cursor:default}
.lead-sub{color:var(--ink-3);font-size:var(--t-micro);line-height:var(--lh-micro);margin-top:2px}

/* Equipment thumbnail. The silhouette is the label — this is why the render
   set has to keep one facing direction. */
/* Drawn, not photographed. Inherits currentColor so it themes with everything
   else, and holds its shape at 38px where a photo would be a smudge. */
.equip{
  width:38px;height:26px;
  color:var(--ink-3);
  flex:none;display:block;
  transition:color var(--t-fast) var(--out);
}
tr:hover .equip,
tr[aria-selected="true"] .equip{color:var(--ink)}

.empty-mark{width:64px;height:44px;color:var(--s30);display:block}

.bucket{
  display:inline-block;padding:2px 8px;border-radius:var(--r-pill);
  background:var(--s20);color:var(--ink-2);
  font-size:var(--t-micro);line-height:var(--lh-micro);white-space:nowrap;
}

/* A disqualify is not a step on any ladder, so it does not borrow a ladder
   colour. Its own chip, in the signal colour the disqualify block itself uses,
   because the two are the same decision seen from either end. */
.bucket.dq{background:var(--signal-soft);color:var(--signal);font-weight:550}
/* The reason it left, under the chip. Wraps -- a reason worth recording is
   usually a sentence, and truncating it to one line would leave the record
   looking like a label. */
.cl-note{
  margin-top:3px;max-width:38ch;white-space:normal;
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
}

/* The request ladder is ORDINAL, so it reads as one deepening ramp rather than
   a set of unrelated hues. The dashboard says the same thing in a warm family;
   this system is monochrome, and a monochrome ramp carries "further along"
   better than colour does anyway.
   Recurring is the one break in the ramp, and it earns it: at four requests
   they are not a lead with a request, they are a customer with a habit, and
   that is a different call. */
.bucket[data-b="first_request"]{background:var(--s20);color:var(--ink-2)}
.bucket[data-b="second_request"]{background:var(--s30);color:var(--ink)}
/* --ink, not --s0. White on s40 measures 1.93:1 and fails AA outright;
   ink on the same ground is 9.33:1. The ramp still deepens through the
   background, which is what carries the ordering anyway. */
.bucket[data-b="third_request"]{background:var(--s40);color:var(--ink)}
.bucket[data-b="recurring_request"]{background:var(--good-soft);color:var(--good)}

/* The two shared-link buckets are one story, not two: money on the table from
   someone never signed. Outlined rather than filled, so they read as a pair
   and stay distinct from the ladder without adding a second accent. */
.bucket[data-b="link_no_account"],
.bucket[data-b="link_not_converted"]{
  background:transparent;color:var(--ink-2);
  box-shadow:inset 0 0 0 1px var(--line-strong);
}
.bucket[data-b="link_not_converted"]{color:var(--ink)}

/* A bucket this row also qualified for, but did not win. Present, secondary,
   never mistaken for the one that decides the call. */
.bucket.ghost{
  background:transparent;color:var(--ink-3);
  box-shadow:inset 0 0 0 1px var(--line);
  margin-inline-start:4px;
}

/* ============ THE QUEUE'S CELLS SPEAK ONE LANGUAGE ========================

   Six columns had six visual systems: a 44px fill track, a 16px SVG ring, a
   filled black pill, three numbers joined by slashes with a 16px (i) beside
   them, five coloured status variants, and five different renderings of an em
   dash. Every one of them was defensible alone. Together they made a row that
   has to be READ rather than scanned, and colour that meant four unrelated
   things within 900 pixels.

   The rule now: THE VALUE IS THE CELL. One numeric treatment, one chip, one
   absence, and colour reserved for the single thing on this desk worth
   interrupting a scan for — work that has gone cold or cannot be served.
   ======================================================================== */

/* Every number in the table, one treatment. Tabular so a column scans as a
   column: without it, 8 and 11 sit at different widths and the eye has to
   re-find the left edge on every row. */
.metric{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:var(--t-body);color:var(--ink-2);line-height:1;
}
/* Weight, not colour, carries the distinction — a thin request is quiet and a
   strong one is not, and neither of them is an alarm. */
.metric.hi{color:var(--ink);font-weight:600}
.metric.lo{color:var(--ink-3)}

/* ONE ABSENCE. This was .sup-na, .real-n, .bids-0, .mini-empty and a bare
   string, all rendering the same character at four different weights, so a
   column of nothing looked like four different kinds of nothing. */
.dash{
  font-family:var(--mono);font-size:var(--t-body);color:var(--s40);
  font-variant-numeric:tabular-nums;
}

.bids{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:var(--t-body)}

/* The bid count. It was a filled black pill and it pulled the eye off the
   lead's name on every row, including the ones reading 1. A count is not a
   decision: it sits at the weight of every other number, and the affordance
   arrives when the pointer does. */
.bid-chip{
  display:inline-flex;align-items:center;gap:3px;
  padding:2px 6px;margin-inline-start:-6px;border-radius:var(--r);
  background:transparent;color:var(--ink);
  transition:background var(--t-fast) var(--out);
}
.bid-chip-n{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:var(--t-body);font-weight:600;
}
/* The chevron is the promise that this opens something. It costs nothing until
   it is wanted, and reserving its width stops the row shifting on hover. */
.bid-chip svg{
  width:11px;height:11px;opacity:0;
  transition:opacity var(--t-fast) var(--out);
}
@media (hover:hover) and (pointer:fine){
  .bid-chip:hover{background:var(--s10)}
  .bid-chip:hover svg{opacity:.55}
}
.bid-chip:focus-visible svg{opacity:.55}
.bid-chip:active{transform:scale(.97)}

/* Status is context, not a call to action, so it stays quiet next to the chip.
   Only the two that mean "stop working this" carry any colour. */
.req-status{
  display:inline-block;padding:2px 8px;border-radius:var(--r-pill);
  background:var(--s10);color:var(--ink-2);
  font-size:var(--t-micro);line-height:var(--lh-micro);white-space:nowrap;
}
/* The per-STATUS rules are gone with the per-status labels. Nothing emits
   data-s on a request any more — every surface folds through reqState and
   carries data-fam — so these could only ever have matched a caller that had
   not been folded yet, which is the drift they would have hidden. */

/* The age. The ring is gone; what it did that the number could not was give a
   glance, and a dot does that at a tenth of the ink. Present only when the row
   has gone cold — a marker on every row marks nothing. */
.clock{
  display:inline-flex;align-items:center;gap:6px;
  font-family:var(--mono);font-size:var(--t-body);
  font-variant-numeric:tabular-nums;color:var(--ink-2);
  white-space:nowrap;line-height:1;
}
.clock-n{line-height:1}
.clock.warm{color:var(--ink)}
.clock.hot{color:var(--signal);font-weight:600}
.clock-dot{
  width:5px;height:5px;border-radius:var(--r-pill);
  background:currentColor;flex:none;
}

.owner{display:flex;align-items:center;gap:6px;color:var(--ink-2);font-size:var(--t-body)}
.owner-dot{
  width:22px;height:22px;border-radius:var(--r-pill);
  background:var(--s20);display:grid;place-items:center;
  font-size:var(--t-micro);font-weight:600;color:var(--ink-2);flex:none;
}
.unowned{color:var(--ink-3)}

.tick{
  width:26px;height:26px;border-radius:var(--r);
  border:1px solid var(--line-strong);
  display:grid;place-items:center;color:var(--ink-3);
  transition:border-color var(--t-fast) var(--out),color var(--t-fast) var(--out),background var(--t-fast) var(--out);
}
.tick svg{width:14px;height:14px;stroke-width:2}
.tick:hover{border-color:var(--good);color:var(--good);background:var(--good-soft)}


/* ---- ownership controls ------------------------------------------------
   One control per cell. The previous version drew the owner as a chip and then
   put a separate select underneath it repeating the same name, which read as
   two answers to one question and made every row two lines tall. */
.claim{
  padding:3px 10px;border-radius:var(--r-pill);
  border:1px solid var(--line-strong);color:var(--ink-2);
  font-size:var(--t-micro);
  transition:border-color var(--t-fast) var(--out),color var(--t-fast) var(--out),background var(--t-fast) var(--out);
}
.claim:hover{border-color:var(--ink);color:var(--ink);background:var(--s10)}

/* The card is the button. The <select> sits over the whole thing invisibly, so
   the menu is the platform's own while what you see is the owner. */
/* Control and release travel together. Apart they broke across two lines in a
   narrow column, and one row being taller than its neighbours is the thing a
   column of rows is least able to hide. */
.owner-wrap{display:inline-flex;align-items:center;gap:2px;max-width:100%;min-width:0}

.owner-ctl{
  position:relative;min-width:0;
  display:inline-flex;align-items:center;gap:6px;
  padding:3px 7px 3px 3px;border-radius:var(--r-pill);
  border:1px solid transparent;
  max-width:100%;
  transition:border-color var(--t-fast) var(--out),background var(--t-fast) var(--out);
}
.owner-ctl:hover{background:var(--s10);border-color:var(--line-strong)}
.owner-ctl:focus-within{border-color:var(--ink)}

.owner-name{
  font-size:var(--t-body);color:var(--ink-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.owner-ctl.is-empty .owner-name{color:var(--ink-3)}

/* Only appears on hover or focus: an admin needs to know it is changeable,
   but a column of carets is noise on every row. */
.owner-caret{
  width:13px;height:13px;flex:none;color:var(--ink-3);
  opacity:0;transition:opacity var(--t-fast) var(--out);
}
.owner-ctl:hover .owner-caret,
.owner-ctl:focus-within .owner-caret{opacity:1}

.owner-pick{
  position:absolute;inset:0;width:100%;height:100%;
  opacity:0;cursor:pointer;border:0;padding:0;
  font-size:var(--t-body);
}

.owner-dot-empty{
  background:transparent;
  box-shadow:inset 0 0 0 1px var(--line-strong);
  color:var(--ink-3);font-weight:500;
}

.owner-x{
  display:grid;place-items:center;
  width:18px;height:18px;border-radius:var(--r-pill);
  color:var(--ink-3);flex:none;margin-inline-start:2px;
  transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.owner-x svg{width:10px;height:10px;stroke-width:2.4}
.owner-x:hover{background:var(--signal-soft);color:var(--signal)}

/* A write that failed has to say so somewhere. The queue has no room for an
   inline error per row, so it surfaces once, briefly, out of the way. */
.toast{
  position:fixed;inset-inline:0;bottom:22px;margin-inline:auto;
  width:max-content;max-width:min(420px,88vw);z-index:70;
  padding:9px 14px;border-radius:var(--r);
  background:var(--s90);color:var(--s0);
  font-size:var(--t-body);
  opacity:0;transform:translateY(6px);pointer-events:none;
  transition:opacity var(--t) var(--out),transform var(--t) var(--out);
}
:root[data-theme="dark"] .toast{background:var(--s20);color:var(--s90)}
.toast.on{opacity:1;transform:none}


/* ---- data module -------------------------------------------------------
   A question with two answers. The two names sit on one line so the eye
   compares them directly instead of reading a sentence about them. */
.pair{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:10px 0;border-bottom:1px solid var(--line);
}
.pair:last-of-type{border-bottom:0}
.pair-names{display:flex;align-items:center;gap:10px;flex:1;min-width:0;flex-wrap:wrap}
.pair-new{font-weight:550}
.pair-old{color:var(--ink-2)}
.pair-vs{
  font-family:var(--mono);font-size:var(--t-micro);
  color:var(--ink-3);padding:1px 6px;border-radius:var(--r-pill);
  background:var(--s10);flex:none;
}
.pair-meta{font-size:var(--t-micro);color:var(--ink-3)}
.pair-acts{display:flex;gap:6px;flex:none}

.toggle{display:flex;align-items:center;gap:9px;cursor:pointer;font-size:var(--t-body)}
.toggle input{width:15px;height:15px;accent-color:var(--ink);flex:none}


/* Why a derived number says what it says. Chips, not a sentence: each one is a
   fact that moved the score, and a rep should be able to scan them. */
.why{display:flex;flex-wrap:wrap;gap:5px}
.why-bit{
  font-size:var(--t-micro);line-height:var(--lh-micro);
  padding:2px 8px;border-radius:var(--r-pill);
  background:var(--s10);color:var(--ink-2);
  box-shadow:inset 0 0 0 1px var(--line);
}


/* The machine as a door. Only rendered where there is a request behind it, so
   every one of these is clickable and none is decoration. */
.equip-btn{
  display:block;padding:2px;border-radius:var(--r);
  transition:background var(--t-fast) var(--out);
}
.equip-btn:hover{background:var(--s20)}
.equip-btn:hover .equip{color:var(--ink)}

/* The request drawer leads with the machine, because that is what the request
   is about. Large, quiet, and not competing with the facts under it. */
.req-hero{
  display:grid;place-items:center;
  padding:14px 0 16px;
  color:var(--s30);
}
.req-hero .equip{width:96px;height:66px}


/* ---- the call log sheet -------------------------------------------------
   Chips, not a select. A rep logging a call has one hand on a phone; a
   dropdown costs two taps and hides its own options until you commit. */
.lg-g{display:block;padding:12px 12px 14px;border-bottom:1px solid var(--line)}
.lg-g:last-of-type{border-bottom:0}
.lg-l{display:block;font-size:var(--t-micro);line-height:var(--lh-micro);
  color:var(--ink-3);letter-spacing:.03em;margin-bottom:8px}
.lg-l i{font-style:normal;color:var(--s50);opacity:.75}

.opts{display:flex;flex-wrap:wrap;gap:6px}
.opt{
  font:inherit;font-size:var(--t-micro);line-height:1;
  padding:8px 11px;border-radius:var(--r-pill);
  border:1px solid var(--line-strong);background:var(--panel);color:var(--ink-2);
  cursor:pointer;display:inline-flex;align-items:center;gap:6px;
  transition:background var(--t-fast) var(--out),border-color var(--t-fast) var(--out),
             color var(--t-fast) var(--out);
}
.opt:hover{border-color:var(--s50);color:var(--ink)}
.opt[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--panel)}
/* The two signals that reach outside the app carry the warning on the chip
   itself, so it is read before the press rather than after. */
.opt-note{font-style:normal;font-size:10px;letter-spacing:.02em;opacity:.7}
.opt[aria-pressed="true"] .opt-note{opacity:.8}

.lg-g textarea{
  width:100%;font:inherit;font-size:var(--t-body);color:var(--ink);
  background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r);
  padding:9px 10px;resize:vertical;unicode-bidi:plaintext;
}
.lg-g textarea:focus{outline:none;border-color:var(--ink-3)}


/* ---- recording the award ------------------------------------------------ */
.lg-g input{
  width:100%;font:inherit;font-size:var(--t-body);color:var(--ink);
  background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r);
  padding:9px 10px;unicode-bidi:plaintext;
}
.lg-g input:focus{outline:none;border-color:var(--ink-3)}
.ff-row{display:flex;align-items:center;gap:8px}
.ff-row input{flex:1;font-family:var(--mono);font-variant-numeric:tabular-nums}
.ff-cur{font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-3);flex:none}
/* An award already claimed is a state, not a button — it reads as one. */
.act[data-state]{cursor:default;color:var(--ink-3)}
.act[data-state="approved"]{color:var(--good)}
.act[data-state="rejected"]{color:var(--signal)}

/* ---- states ------------------------------------------------------------- */
.skel{
  height:11px;border-radius:3px;
  background:linear-gradient(90deg,var(--s20) 25%,var(--s10) 37%,var(--s20) 63%);
  background-size:400% 100%;
  animation:shimmer 1.3s ease-in-out infinite;
}
@keyframes shimmer{from{background-position:100% 0}to{background-position:0 0}}

.empty{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;padding:64px 24px;text-align:center;color:var(--ink-3);
}
.empty img{width:180px;max-width:60%;opacity:.5}
.empty p{margin:0;font-size:var(--t-body)}

.fail{
  margin:18px;padding:12px 14px;border-radius:var(--r);
  border:1px solid var(--line-strong);
  display:flex;align-items:center;gap:10px;
}
.fail svg{width:16px;height:16px;color:var(--signal);flex:none}
.retry{
  margin-inline-start:auto;padding:5px 10px;border-radius:var(--r);
  border:1px solid var(--line-strong);font-size:var(--t-body);
  transition:background var(--t-fast) var(--out);
}
.retry:hover{background:var(--s10)}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important}
}





/* A single-word verdict. Outreach answers "can I send" with a state, not a
   paragraph, so the word carries the colour and nothing else is said. */
.state-line{
  font-size:var(--t-mid);line-height:var(--lh-mid);font-weight:600;
  letter-spacing:-.01em;color:var(--ink-2);
}
.state-line[data-tone="good"]{color:var(--good)}
.state-line[data-tone="bad"]{color:var(--signal)}

/* ---- views -------------------------------------------------------------
   One scroll region, one view at a time. Contacts is the umbrella: supplier
   and rentee are a FILTER on one registry, never two registries. Two lists
   means the same company entered twice and drifting apart, which is the
   duplicate problem this company already paid to fix once. */
.view{display:none}
.view.on{display:block}

.tier{
  display:inline-grid;place-items:center;
  width:18px;height:18px;border-radius:var(--r-pill);
  font-size:var(--t-micro);font-weight:600;
  background:var(--s20);color:var(--ink-2);
}
.tier[data-t="A"]{background:var(--good-soft);color:var(--good)}
.tier[data-t="B"]{background:var(--s30);color:var(--ink)}

/* plaintext, not direction:rtl. Setting the element rtl also flips `start`, so
   the Arabic name drifts to the far edge of a wide column instead of sitting
   under the English one. plaintext orders the glyphs from the content while
   the box stays aligned to the column. */
.name-ar{
  color:var(--ink-3);font-size:var(--t-micro);line-height:var(--lh-micro);
  margin-top:2px;unicode-bidi:plaintext;text-align:start;
}

.on-app{
  display:inline-flex;align-items:center;gap:5px;
  font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-2);
}
.on-app::before{
  content:"";width:6px;height:6px;border-radius:var(--r-pill);background:var(--good);
}

.more{
  display:block;width:100%;padding:12px;
  font-size:var(--t-body);color:var(--ink-2);
  border-top:1px solid var(--line);
  transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.more:hover{background:var(--panel);color:var(--ink)}
.more[disabled]{opacity:.4;pointer-events:none}

/* ---- create ------------------------------------------------------------
   The + makes exactly two things, because those are the only two a rep
   creates from nothing. Everything else is reached, not made. */
.pick{display:grid;gap:6px;padding:10px}
.pick-item{
  display:flex;align-items:center;gap:11px;width:100%;
  padding:13px 14px;border-radius:var(--r);
  border:1px solid var(--line-strong);text-align:start;
  transition:background var(--t-fast) var(--out),border-color var(--t-fast) var(--out);
}
.pick-item:hover{background:var(--s10);border-color:var(--s40)}
.pick-item svg{width:18px;height:18px;stroke-width:1.7;flex:none;color:var(--ink-2)}
.pick-item[aria-disabled="true"]{opacity:.42;pointer-events:none}

.field{padding:0 16px 12px}
.field label{
  display:block;font-size:var(--t-micro);line-height:var(--lh-micro);
  color:var(--ink-2);margin-bottom:6px;
}
.field input,.field select,.field textarea{
  width:100%;padding:9px 11px;
  background:var(--bg);color:var(--ink);
  border:1px solid var(--line-strong);border-radius:var(--r);
  font-size:var(--t-body);font-family:inherit;
  transition:border-color var(--t-fast) var(--out),box-shadow var(--t-fast) var(--out);
}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none;border-color:var(--ink);box-shadow:0 0 0 3px var(--s20);
}
.field textarea{resize:vertical;min-height:66px}
.field input.bad{border-color:var(--signal)}
.field .hint{
  font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-3);
  margin-top:5px;min-height:15px;
}
.field .hint.bad{color:var(--signal)}
.field .hint.ok{color:var(--good)}

/* ---- the customer record: theirs vs ours -------------------------------
   The whole point of this dialog is that a rep can tell at a glance which half
   of it they are allowed to change, so the two zones are separated by GROUND,
   not by a heading alone. The app zone sits on the sunken surface and carries
   no input controls at all; ours sits on the panel and looks like a form.
   A greyed-out input would have been the obvious way to show read-only and the
   wrong one — it reads as broken rather than as somebody else's record. */
.ed-zone{padding-top:14px}
.ed-zone + .ed-zone{border-top:1px solid var(--line);margin-top:4px}
.ed-zone-h{
  display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  padding:0 16px 10px;font-weight:600;font-size:var(--t-body);color:var(--ink);
}
.ed-zone-h span{font-weight:400;font-size:var(--t-micro);color:var(--ink-3)}
.ed-zone.theirs{background:var(--s5);padding-bottom:12px;margin-bottom:4px}
.ed-zone.theirs .mini-empty{padding:0 16px 4px}

/* ---- two views of one record --------------------------------------------
   One side is ours and editable; the other is the customer's own words and is
   not ours to change. The tabs say that before a single field is read, which a
   label on a mixed list cannot. The pressed one is marked by a rule under it
   rather than by a fill: this sits at the top of a dialog that already has a
   coloured header state, and two loud things compete. */
.ed-tabs{display:flex;gap:2px;padding:0 12px;border-bottom:1px solid var(--line)}
.ed-tab{
  appearance:none;background:none;border:0;cursor:pointer;text-align:start;
  padding:10px 8px 9px;margin-bottom:-1px;border-bottom:2px solid transparent;
  font:inherit;font-weight:600;font-size:var(--t-body);color:var(--ink-3);
  display:flex;flex-direction:column;gap:1px;
}
.ed-tab span{font-weight:400;font-size:var(--t-micro);color:var(--ink-3)}
.ed-tab:hover{color:var(--ink-2)}
.ed-tab.on{color:var(--ink);border-bottom-color:var(--ink)}

/* The empty half of a zone, and the one control that unfolds it. A record
   shows what it holds; a form shows every box there could ever be. */
.ed-more{
  appearance:none;background:none;border:0;cursor:pointer;font:inherit;
  font-size:var(--t-micro);color:var(--ink-3);padding:2px 16px 10px;text-align:start;
}
.ed-more:hover{color:var(--ink-2);text-decoration:underline}

/* How this person may be reached. Only what is SET is on screen, so an
   untouched contact carries one quiet sentence instead of four unticked boxes. */
.ed-flags{display:flex;flex-wrap:wrap;gap:6px 14px;padding:0 16px 12px}
.ed-flags-none{font-size:var(--t-micro);color:var(--ink-3)}
.ed-flag{display:flex;align-items:center;gap:6px;font-size:var(--t-micro);color:var(--ink-2)}
.ed-flag input{accent-color:var(--ink)}
/* `display:contents` is what lets the folded fields sit in the zone's own flow
   rather than in a box of their own -- and it OVERRIDES the hidden attribute,
   whose whole effect is display:none. Without the second rule the fold does
   nothing at all: every empty field renders, which is the thing this was built
   to stop. */
.ed-empties{display:contents}
.ed-empties[hidden]{display:none}

/* WHICH person, when the company holds several. */
.ed-who{display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding:10px 16px 0}
.ed-who-k{font-size:var(--t-micro);color:var(--ink-3);margin-inline-end:2px}
.ed-who-b{
  appearance:none;cursor:pointer;font:inherit;font-size:var(--t-micro);
  display:inline-flex;align-items:center;gap:5px;
  padding:3px 9px;border-radius:999px;border:1px solid var(--line);
  background:var(--s5);color:var(--ink-2);
}
.ed-who-b:hover{border-color:var(--ink-3)}
.ed-who-b.on{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.ed-who-app{font-size:9px;letter-spacing:.04em;text-transform:uppercase;opacity:.7}
/* Above six people the chips become a list, or thirty of them push the fields
   they belong to off the screen. */
.ed-who-sel{
  flex:1 1 200px;min-width:0;font:inherit;font-size:var(--t-micro);
  padding:4px 8px;border-radius:8px;border:1px solid var(--line);
  background:var(--paper);color:var(--ink-2);
}
.ed-who-n{font-size:var(--t-micro);color:var(--ink-3)}

/* What we hold, beside what they said, on the read-only side. */
.ed-ro-ours{font-size:var(--t-micro);color:var(--ink-3);grid-column:2;unicode-bidi:plaintext}
.ed-ro-ours b{color:var(--ink-2);font-weight:600}

/* A two-column read, not a form row: label and value, nothing to focus. */
.ed-ro{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.6fr);
  gap:10px;align-items:baseline;padding:4px 16px;
}
.ed-ro-k{font-size:var(--t-micro);color:var(--ink-3)}
.ed-ro-v{font-size:var(--t-micro);color:var(--ink-2);overflow-wrap:anywhere;unicode-bidi:plaintext}
.ed-ro-v.num{font-family:var(--mono)}

/* ---- the comparison itself ---------------------------------------------
   Every comparable field says which of three things is true, because silence
   is ambiguous: a field with no line under it might agree with the app, or the
   app might never have asked, and those are opposite facts. Only `differs` is
   coloured — agreement should be legible without being loud, or the screen
   reads as nine warnings. */
.field .hint.ed-cmp{
  font-family:inherit;display:flex;align-items:center;gap:6px;flex-wrap:wrap;
  min-height:22px;
}
.ed-cmp.same{color:var(--ink-3)}
.ed-cmp.same svg{width:12px;height:12px;flex:none;color:var(--good)}
.ed-cmp.none{color:var(--ink-3);font-style:italic}
.ed-cmp.diff{color:var(--ink-2)}
.ed-cmp.diff b{color:var(--ink);font-weight:600;unicode-bidi:plaintext}
.ed-cmp-l{color:var(--ink-3)}

/* The whole reason to show the app's value is to be able to take it. Retyping
   a name you are looking at is how a comparison becomes a typo. */
.ed-use{
  font:inherit;font-size:var(--t-micro);line-height:1;
  padding:3px 8px;margin-inline-start:2px;
  border:1px solid var(--line-strong);border-radius:var(--r-pill);
  background:var(--panel);color:var(--ink-2);cursor:pointer;
  transition:border-color var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.ed-use:hover{border-color:var(--ink);color:var(--ink)}
.ed-use:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* A row that differs is marked on its EDGE rather than by tinting the input —
   a coloured field reads as invalid, and disagreeing with the app is not an
   error. It is the ordinary state of a record a rep has corrected.

   --ink, not an amber. The obvious choice was --warn and it would have failed
   silently: that variable is defined inside .bidpanel and nowhere else, so it
   resolves here to whatever fallback is written beside it and the marker would
   have been grey for no visible reason. --signal is the error red and says the
   wrong thing. Full-strength ink is neutral, present, and actually defined. */
.ed-row[data-cmp="diff"]{
  box-shadow:inset 2px 0 0 var(--ink);
}

/* The count, and the answer to "is this thing even checking". */
.ed-cmp-head{
  padding:12px 16px;background:var(--s5);
  border-bottom:1px solid var(--line);
  display:flex;flex-direction:column;gap:2px;align-items:flex-start;
}
.ed-cmp-head b{font-size:var(--t-body);color:var(--ink)}
.ed-cmp-head span{font-size:var(--t-micro);color:var(--ink-3)}
.ed-cmp-head.has-diff b{color:var(--ink)}
.ed-only{
  font:inherit;font-size:var(--t-micro);margin-top:8px;
  padding:5px 10px;border:1px solid var(--line-strong);border-radius:var(--r-pill);
  background:var(--panel);color:var(--ink-2);cursor:pointer;
}
.ed-only:hover{border-color:var(--ink);color:var(--ink)}
.ed-only[aria-pressed="true"]{background:var(--ink);color:var(--panel);border-color:var(--ink)}

/* The filter hides rows, never the section headings — a zone whose fields all
   match should say so by being empty under its own name rather than
   disappearing and making the rep wonder where it went. */
.ed-diff-only .ed-row:not([data-cmp="diff"]){display:none}
.ed-zone-note{padding:0 16px 12px;color:var(--ink-3)}

/* Segmented control. Two options, so a pair of buttons beats a select. */
.seg{display:flex;gap:0;border:1px solid var(--line-strong);border-radius:var(--r);overflow:hidden}
.seg button{
  flex:1;padding:8px;font-size:var(--t-body);color:var(--ink-2);
  transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.seg button + button{border-inline-start:1px solid var(--line-strong)}
.seg button[aria-pressed="true"]{background:var(--ink);color:var(--s0)}

/* ---- detail dock -------------------------------------------------------
   Opening a row must land on the thing itself. Reps were copying a request
   number and searching for it, which is the queue failing at its one job.
   Laptop: the dock takes a column, the table keeps working beside it.
   Phone: it becomes a sheet, because there is no room for two things. */
.app.detail-open{grid-template-columns:minmax(0,1fr) var(--detail)}

.dock{
  grid-column:2;
  background:var(--panel);
  border-inline-start:1px solid var(--line);
  display:none;flex-direction:column;min-height:0;
}
.app.detail-open .dock{display:flex}

.dock-head{
  padding:14px 16px;border-bottom:1px solid var(--line);flex:none;
  display:flex;align-items:flex-start;gap:4px;
}
/* The edit control sits with Close, not in the body: it acts on the whole
   record rather than on any one field. */
.dock-head .x:first-of-type{margin-inline-start:auto}
.dock-head .x + .x{margin-inline-start:0}
.dock-title{font-size:var(--t-mid);line-height:var(--lh-mid);font-weight:600;letter-spacing:-.01em;margin:0}
.dock-sub{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);margin-top:2px}

.dock-body{overflow:auto;flex:1;min-height:0}

/* Actions sit above everything: on a queue row the next move is a call. */
.acts{display:flex;gap:6px;padding:12px 16px;border-bottom:1px solid var(--line)}
.act{
  flex:1;display:flex;align-items:center;justify-content:center;gap:6px;
  padding:8px;border-radius:var(--r);
  border:1px solid var(--line-strong);color:var(--ink);
  font-size:var(--t-body);
  transition:background var(--t-fast) var(--out),border-color var(--t-fast) var(--out);
  text-decoration:none;
}
.act:hover{background:var(--s10)}
.act svg{width:15px;height:15px;stroke-width:1.8}
.act[data-primary]{background:var(--ink);border-color:var(--ink);color:var(--s0)}
.act[data-primary]:hover{opacity:.88;background:var(--ink)}
.act[aria-disabled="true"]{opacity:.4;pointer-events:none}

/* Facts. A definition grid, not sentences: the label is the smallest thing
   on screen and the value carries the weight. */
.facts{display:grid;grid-template-columns:76px 1fr;gap:7px 12px;padding:14px 16px}
.facts dt{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);margin:0}
.facts dd{margin:0;font-size:var(--t-body)}
/* The trailing half of a fact — "2 · holding 99". Quieter than the number
   it follows, because the count is the fact and the rest is the context. */
.facts dd .fact-sub{font-size:var(--t-micro);color:var(--ink-3)}

.sec{border-top:1px solid var(--line);padding:12px 16px}
.sec-h{
  display:flex;align-items:baseline;gap:8px;margin-bottom:8px;
}
.sec-h span{font-size:var(--t-micro);color:var(--ink-3)}
.sec-h b{font-size:var(--t-body);font-weight:600}

.bid-row{
  display:flex;align-items:baseline;gap:10px;
  padding:7px 0;border-bottom:1px solid var(--line);
}
.bid-row:last-child{border-bottom:0}
.bid-who{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bid-amt{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:var(--t-body)}
.bid-unit{font-size:var(--t-micro);color:var(--ink-3)}

/* Timeline. One rail, events hanging off it, newest first. */
.tl{position:relative;padding-inline-start:16px}
.tl::before{
  content:"";position:absolute;inset-inline-start:3px;top:4px;bottom:4px;
  width:1px;background:var(--line);
}
.tl-item{position:relative;padding:6px 0}
.tl-item::before{
  content:"";position:absolute;inset-inline-start:-16px;top:11px;
  width:7px;height:7px;border-radius:var(--r-pill);
  background:var(--s30);
}
.tl-item[data-tone="blemish"]::before{background:var(--signal)}
.tl-item[data-tone="positive"]::before{background:var(--good)}
.tl-what{font-size:var(--t-body)}
.tl-when{font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-3)}

.mini-empty{font-size:var(--t-micro);color:var(--ink-3);padding:2px 0}

@media (max-width:860px){
  .app.detail-open{grid-template-columns:1fr}
  .dock{
    position:fixed;inset-inline:0;bottom:0;top:auto;z-index:30;
    height:min(84dvh,640px);
    border-inline-start:0;border-top:1px solid var(--line);
    border-radius:var(--r) var(--r) 0 0;
    box-shadow:0 -8px 32px rgba(20,23,27,.18);
  }
}

/* ---- phone -------------------------------------------------------------
   Not the design target, but it must not break. The rail leaves, a bottom
   bar arrives with the + in the middle, and the table becomes rows. */
.bar{display:none}

@media (max-width:860px){
  /* iOS zooms any input under 16px on focus. --t-mid is 18px, which clears
     that AND stays on the scale -- a bare 16px sat between body and mid and
     put a 1.14 step into a scale whose whole point is 1.25+. */
  input,select,textarea{font-size:var(--t-mid)}
  .app{grid-template-columns:1fr}
  /* No rail to hide any more. The nav menu still works on a phone, but the
     bottom bar is the primary navigation there and always was. */
  .navmenu{width:min(280px,92vw);top:48px;left:12px;transform:none}
  .filters{padding-inline:12px;gap:8px}
  .filters .search{width:auto;flex:1;min-width:120px}
  .sides{gap:14px}
  .side-x{padding:16px 0 14px;font-size:var(--t-micro)}
  /* A centred title cannot survive next to three tabs on a 360px screen, so it
     goes back to flowing after them rather than overlapping. */
  .ttl{position:static;justify-content:flex-start;flex:1;min-width:0}
  .ttl-b{padding-inline:6px}

  /* A wrapping flex line, NOT a grid. Every meta cell is its own <td>, so
     assigning them all to one named grid area stacks them in the same cell
     and they render on top of each other. Flex + an explicit break element
     lets them flow onto a second line instead, and it works for all three
     tables without knowing their columns. */
  .q thead{display:none}
  .q,.q tbody,.q tr,.q td{display:block;width:100%}
  .q tbody tr{
    background:var(--panel);
    border:1px solid var(--line);border-radius:var(--r);
    margin:8px 12px;padding:10px 12px;
    display:flex;flex-wrap:wrap;align-items:center;
    column-gap:10px;row-gap:4px;
    width:auto;
  }
  /* Zero-height full-width item: forces everything after it onto line two. */
  .q tbody tr::after{content:"";flex-basis:100%;height:0;order:3}

  .q td{padding:0;border:0;width:auto;flex:none;order:4}
  .q td:empty{display:none}
  .q td[data-cell="img"]{order:0}
  .q td[data-cell="lead"]{order:1;flex:1 1 auto;min-width:0}
  .q td[data-cell="tick"]{order:2;margin-inline-start:auto}
  .equip{width:44px;height:34px}

  .scroll{padding-bottom:78px}

  .bar{
    display:flex;align-items:center;justify-content:space-around;
    position:fixed;inset-inline:0;bottom:0;z-index:20;
    height:62px;padding-bottom:env(safe-area-inset-bottom);
    background:var(--panel);border-top:1px solid var(--line);
  }
  .bar-item{
    display:flex;flex-direction:column;align-items:center;gap:3px;
    color:var(--ink-3);font-size:var(--t-micro);padding:6px 10px;
    text-decoration:none;
  }
  .bar-item svg{width:19px;height:19px;stroke-width:1.7}
  .bar-item[aria-current="page"]{color:var(--ink)}
  .bar-new{
    width:44px;height:44px;border-radius:var(--r-pill);
    background:var(--ink);color:var(--s0);
    display:grid;place-items:center;
    box-shadow:0 4px 14px rgba(20,23,27,.22);
  }
  .bar-new svg{width:20px;height:20px;stroke-width:2.2}
}


/* ---- request drawer, restructured --------------------------------------- */
/* The company is the heading and the person is the subheading, and both are the
   same link. Underlined only on hover: a drawer title that is permanently
   underlined reads as a link first and a name second. */
.dk-link{color:inherit;text-decoration:none;border-bottom:1px solid transparent;cursor:pointer}
.dk-link:hover{border-bottom-color:currentColor}
.dk-muted{color:var(--ink-3)}
/* R34 · the number beside the name. `.tel` is already font-size:inherit, so it
   matches the name rather than being demoted to a caption — it is the same
   fact. The dot is the only thing that recedes. */
.dk-dot{color:var(--s40);margin:0 5px}

/* R34 · the site chip, as a link out to Maps. It keeps the chip shape (it is
   still one value in the quadrant) and earns an underline on hover, which is
   the only thing separating it from the chips that do nothing. */
a.qv.link{cursor:pointer;text-decoration:none;gap:4px;color:var(--ink)}
a.qv.link:hover{box-shadow:inset 0 0 0 1px var(--line-strong);background:var(--s10)}
a.qv.link:hover .qv-pin{color:var(--ink)}
.qv-pin{width:12px;height:12px;flex:none;color:var(--ink-3)}

/* Equipment and operator both answer "what, and is it gated" on one line, so
   the badge sits with the name rather than claiming a row of its own. */
.eq-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:7px 12px}
.eq-line + .eq-line{border-top:1px solid var(--line)}
.eq-name{font-size:var(--t-body);color:var(--ink);unicode-bidi:plaintext;flex:1;min-width:0}
.eq-code{margin-inline-start:auto;font-size:var(--t-micro);color:var(--ink-3)}
/* A gate, not an outcome -- so it stays inside the greyscale and borrows
   --good only for the affirmative case, where a cert genuinely IS the good
   news for a supplier hunt. */
.cert{
  font-size:var(--t-micro);line-height:1;padding:4px 7px;border-radius:var(--r-pill);
  border:1px solid var(--line);white-space:nowrap;
}
.cert.on{background:var(--good-soft);color:var(--good);border-color:transparent}
.cert.off{background:var(--s10);color:var(--ink-3)}
.bucket.direct{background:var(--s20);color:var(--ink-2);border:1px solid var(--line-strong)}

/* A row that opens something else. Reads as one control, not a field with a
   stray arrow: the whole strip is the target. */
.drill{
  display:flex;align-items:center;gap:10px;width:100%;
  padding:13px 16px;border:0;border-top:1px solid var(--line);
  background:transparent;cursor:pointer;text-align:start;font:inherit;color:inherit;
  transition:background var(--t-fast) var(--out);
}
.drill:hover{background:var(--s10)}
.drill-k{font-size:var(--t-body);font-weight:600}
.drill-v{margin-inline-start:auto;color:var(--ink-3)}
.drill svg{width:16px;height:16px;flex:none;color:var(--ink-3);stroke-width:1.8}
/* Force expire is the one destructive control in the drawer, and --signal is
   reserved for time running out -- which is exactly what this does to a
   request. Nothing else here may borrow it. */
.act.danger{color:var(--signal);border-color:var(--line-strong)}
.act.danger:hover{background:var(--signal-soft)}
.warn{color:var(--signal)}

/* ---- the sheet ----------------------------------------------------------- */
/* Wider than the drawer because it holds a table, and layered over it rather
   than beside it: at 1440px there is no room for a rail, a list, a drawer AND a
   table, and the rep's place in the list is the thing we refuse to lose. */
.pane{
  /* 110, with the sheet. It was 40 -- the same level as the veil and below the
     topbar at 100 -- so the pane opened with its own header, title and close
     button hidden behind the app header. The layer order is written down in the
     inline block at the top of sales/index.html. */
  position:fixed;inset-block:0;inset-inline-end:0;z-index:110;
  width:min(860px,100vw);
  background:var(--panel);
  /* Elevation, not elevation plus a drawn edge -- the same call .find already
     makes above. The sheet floats OVER the drawer rather than sitting beside
     it, so height is the true signal; a hairline as well would be the surface
     claiming to be both adjacent and raised. The tight contact shadow does the
     separating a border was doing, the wide one carries the height. */
  box-shadow:-1px 0 2px rgba(20,23,27,.10), -14px 0 34px -10px rgba(20,23,27,.20);
  display:flex;flex-direction:column;min-height:0;
}
.pane[hidden]{display:none}
.pane-head{
  padding:14px 16px;border-bottom:1px solid var(--line);flex:none;
  display:flex;align-items:flex-start;gap:8px;
}
.pane-head .x:last-of-type{margin-inline-start:auto}
.pane-title{font-size:var(--t-mid);line-height:var(--lh-mid);font-weight:600;letter-spacing:-.01em;margin:0}
.pane-sub{
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
  margin-top:2px;unicode-bidi:plaintext;
}
.pane-body{overflow:auto;flex:1;min-height:0;scrollbar-width:none}
.pane-body::-webkit-scrollbar{width:0;height:0}
.pane-lede{font-size:var(--t-micro);color:var(--ink-3)}
.pane-table{overflow-x:auto}
.pane-table table{width:100%}

/* ---- bids ---------------------------------------------------------------- */
.bid-tot{font-size:var(--t-body);font-weight:600}
.bid-st{
  font-size:var(--t-micro);line-height:1;padding:4px 8px;border-radius:var(--r-pill);
  letter-spacing:.03em;white-space:nowrap;
  background:var(--s10);color:var(--ink-3);border:1px solid var(--line);
}
/* Won and lost are outcomes, so they get the outcome colours. Pending is the
   default state of almost every bid and stays neutral -- colouring the common
   case is how a table stops meaning anything. */
.bid-st[data-s="accepted"],.bid-st[data-s="won"]{background:var(--good-soft);color:var(--good);border-color:transparent}
.bid-st[data-s="rejected"],.bid-st[data-s="withdrawn"]{background:var(--signal-soft);color:var(--signal);border-color:transparent}
.bid-st[data-s="off-platform"]{background:var(--s20);color:var(--ink-2);border-color:var(--line-strong)}
.bid-note-row td{padding-top:0;color:var(--ink-3);font-size:var(--t-micro)}
.bid-note-row b{color:var(--ink-2);font-weight:600;margin-inline-end:6px}
.btn-chat{
  display:inline-flex;align-items:center;gap:6px;
  padding:6px 10px;border-radius:var(--r);border:1px solid var(--ink);
  background:var(--ink);color:var(--s0);font:inherit;font-size:var(--t-micro);cursor:pointer;
}
.btn-chat svg{width:14px;height:14px;stroke-width:1.8}
.btn-chat:hover{opacity:.88}
.linkish{
  background:none;border:0;padding:0;font:inherit;font-size:var(--t-micro);
  color:var(--ink);cursor:pointer;text-align:start;border-bottom:1px solid var(--line-strong);
}
.linkish:hover{border-bottom-color:currentColor}
.dim{color:var(--ink-3)}

/* ---- deal room ----------------------------------------------------------- */
/* Two parties, two sides. The rep is neither -- nothing here composes a
   message -- so this is a transcript, read the way the customer sees it. */
.chat{display:flex;flex-direction:column;gap:14px;padding:16px 18px}
.msg{display:flex;flex-direction:column;max-width:min(72%,520px)}
.msg.s{align-self:flex-start;align-items:flex-start}
.msg.r{align-self:flex-end;align-items:flex-end}
.msg-who{
  font-size:var(--t-micro);line-height:1;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);margin-bottom:4px;
}
.bub{
  padding:9px 13px;border-radius:var(--r);font-size:var(--t-body);line-height:var(--lh-body);
  unicode-bidi:plaintext;overflow-wrap:anywhere;white-space:pre-wrap;
}
.msg.s .bub{background:var(--s10);color:var(--ink);border:1px solid var(--line)}
.msg.r .bub{background:var(--ink);color:var(--s0)}
.msg-at{font-size:var(--t-micro);line-height:1;color:var(--ink-3);margin-top:4px}
.msg.sys{align-self:center;max-width:100%}
.msg.sys span{
  display:inline-block;padding:5px 12px;border-radius:var(--r-pill);
  background:var(--s10);color:var(--ink-3);font-size:var(--t-micro);
}
.att{display:block;margin-top:6px;font-size:var(--t-micro);color:inherit;opacity:.85;text-decoration:underline}

/* ---- edit form ----------------------------------------------------------- */
.f-v input,.f-v select,.f-v textarea{
  width:100%;font:inherit;font-size:var(--t-body);color:var(--ink);
  background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r);
  padding:7px 9px;unicode-bidi:plaintext;
}
.f-v textarea{resize:vertical;min-height:72px}
.f-v input:focus,.f-v select:focus,.f-v textarea:focus{
  outline:2px solid var(--ink);outline-offset:-1px;border-color:transparent;
}

@media (max-width:820px){
  .pane{width:100vw;border-inline-start:0}
  .msg{max-width:88%}
}

/* ---- search from anywhere ------------------------------------------------ */
/* Sits above the nav rather than in it: searching is not a place you go, it is
   a thing you do from wherever you already are. */
.rail-find{
  display:flex;align-items:center;gap:8px;width:calc(100% - 16px);
  margin:0 8px 6px;padding:8px 10px;
  border:1px solid var(--line);border-radius:var(--r);
  background:var(--bg);color:var(--ink-3);
  font:inherit;font-size:var(--t-body);cursor:pointer;text-align:start;
  transition:border-color var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.rail-find:hover{border-color:var(--line-strong);color:var(--ink)}
.rail-find svg{width:15px;height:15px;flex:none}
.rail-find span{flex:1;min-width:0}
.rail-find kbd{
  font:inherit;font-size:var(--t-micro);color:var(--ink-3);
  border:1px solid var(--line);border-radius:4px;padding:1px 4px;
}

.spot{position:fixed;inset:0;z-index:60;display:flex;justify-content:flex-end;align-items:stretch}
.spot[hidden]{display:none}
/* NOT a scrim any more, and that is structural rather than cosmetic. The
   palette is the drag SOURCE and the queue is the drop TARGET: with a veil at
   inset:0 over the table, every pointer position during a drag resolves to the
   veil and the drop never reaches the bucket. Kept as an element so a click
   outside still closes, and made transparent and click-through everywhere the
   drawer is not. */
.spot-veil{position:absolute;inset:0;background:transparent}
.spot-box{
  position:relative;width:min(420px,86vw);height:100%;
  background:var(--panel);border-inline-start:1px solid var(--line);
  box-shadow:-14px 0 40px -12px rgba(20,23,27,.22);
  display:flex;flex-direction:column;min-height:0;
}
.spot-in{display:flex;align-items:center;gap:10px;padding:12px 14px;border-bottom:1px solid var(--line)}
.spot-in svg{width:17px;height:17px;flex:none;color:var(--ink-3)}
.spot-in input{
  flex:1;min-width:0;border:0;background:transparent;outline:none;
  font:inherit;font-size:var(--t-mid);color:var(--ink);
}
.spot-in input::-webkit-search-cancel-button{display:none}
.spot-list{overflow:auto;min-height:0;scrollbar-width:none}
.spot-list::-webkit-scrollbar{width:0}
.spot-list:empty{display:none}
/* The palette reuses the dropdown's rows verbatim, so it must not inherit the
   dropdown's absolute positioning -- that is what would drop it out of the box. */
.spot-list .find-row{
  width:100%;
  grid-template-columns:minmax(0,1fr) auto;
  grid-template-areas:"nm put" "meta put" "tag put";
  row-gap:1px;align-items:center;
}
.spot-list .find-nm{grid-area:nm}
.spot-list .find-meta{grid-area:meta;text-align:start}
.spot-list .find-tag{grid-area:tag;text-align:start}
.spot-list .find-row[draggable]{cursor:grab}
.spot-list .find-row[draggable]:active{cursor:grabbing}

/* The way in that is not a drag. Drag is unreachable by keyboard and unreliable
   on a tablet in a yard, which is where half of these reps are standing. */
.find-put{
  grid-area:put;align-self:center;white-space:nowrap;
  font-size:var(--t-micro);color:var(--ink-2);
  border:1px solid var(--line-strong);border-radius:var(--r-pill);
  padding:3px 9px;cursor:pointer;
  transition:border-color var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.find-put:hover{border-color:var(--ink);color:var(--ink)}
.find-put:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* ---- the bucket rail ----------------------------------------------------
   The drop targets, named. "The queue" was never a target: it is one screen
   over two datasets and nine buckets, and only the rep knows which of them a
   company they just found belongs in. Appears with the search drawer rather
   than only once a drag starts, because seeing where something CAN go is part
   of deciding to move it. */
.droprail{
  display:flex;align-items:flex-start;gap:12px;
  padding:9px 18px;flex:none;
  border-bottom:1px solid var(--line);background:var(--s5);
}
.droprail[hidden]{display:none}
.rail-lead{
  flex:none;padding-top:4px;max-width:108px;
  color:var(--ink-2);font-size:var(--t-micro);line-height:var(--lh-micro);
}
.rail-chips{display:flex;flex-wrap:wrap;align-items:center;gap:6px;min-width:0}
.rail-fam{
  color:var(--ink-3);font-size:var(--t-micro);letter-spacing:.03em;
  padding-inline-start:6px;
}
.rail-chips > .rail-fam:first-child{padding-inline-start:0}
.railchip{
  display:inline-flex;align-items:center;gap:5px;
  font:inherit;font-size:var(--t-micro);padding:5px 11px;
  border-radius:var(--r-pill);border:1px dashed var(--line-strong);
  background:var(--panel);color:var(--ink-2);cursor:copy;white-space:nowrap;
  transition:background var(--t-fast) var(--out),border-color var(--t-fast) var(--out),
             color var(--t-fast) var(--out);
}
.railchip i{font-style:normal;color:var(--ink-3);opacity:.85}
.railchip.here{border-style:solid;border-color:var(--ink);color:var(--ink)}
.railchip.over{background:var(--ink);border-color:var(--ink);color:var(--panel)}
.railchip.over i{color:var(--panel);opacity:.75}
/* Refused, and saying why on its face. A disabled control with no reason is one
   a rep tries twice and then stops trusting the rest of the row. */
.railchip.off{
  border-style:solid;border-color:var(--line);color:var(--ink-3);
  background:transparent;cursor:not-allowed;
  text-decoration:line-through;text-decoration-color:var(--s30);
}
.railchip.off i{
  text-decoration:none;color:var(--ink-3);font-size:10px;
  border:1px solid var(--line);border-radius:3px;padding:0 4px;
}
body.dragging .railchip:not(.off){border-color:var(--ink-3)}

/* A toast that is asking rather than telling. Used when a write landed
   somewhere the rep is not looking, where no way over makes a success
   indistinguishable from nothing happening. */
.toast-go{
  font:inherit;font-size:var(--t-micro);margin-inline-start:10px;
  padding:2px 10px;border-radius:var(--r-pill);
  border:1px solid rgba(255,255,255,.45);background:transparent;
  color:inherit;cursor:pointer;
}
.toast-go:hover{background:rgba(255,255,255,.14)}

/* ---- what is actually being sold ---------------------------------------
   Four cards, one pressed. The old drawer asked for a rate per machine and
   multiplied it by a machine count, which put a price on screen that no rep had
   agreed and no customer had been quoted. */
/* ONE column. The drawer is 400px, so two tracks gave each card 180px to hold a
   price, a unit and a four-line feature list — it was cramped before the badge
   collision made it worse. */
.tiers{display:grid;grid-template-columns:1fr;gap:8px;margin-bottom:10px}
/* RENAMED off `.tier`. That class is an 18x18 fit-tier BADGE (sales.css:1111,
   display:inline-grid, width:18px, height:18px) and these subscription cards
   inherited every bit of it — they rendered as 23px squares with their own text
   spilling out beside them, which is the "layout issues" Awab reported. The
   card rule never declared a width or a display, so the badge's won.

   Third class collision in this file today, after `.pane` and the two [hidden]
   overrides. Nothing checks for it: check-ids catches two elements claiming one
   id, and nothing catches two components claiming one class. */
.os-tier{
  text-align:start;font:inherit;padding:10px 11px;cursor:pointer;
  border:1px solid var(--line);border-radius:var(--r);
  background:var(--panel);color:var(--ink);
  transition:border-color var(--t-fast) var(--out),box-shadow var(--t-fast) var(--out);
}
.os-tier:hover{border-color:var(--line-strong)}
.os-tier.on{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
/* The plan has a NAME again as of 19 Sep 2026 -- Basic, Pro, Growth, Enterprise
   -- so the card leads with it and the price sits under it. It used to lead with
   the price because the price was the only name a plan had. */
.os-tier{position:relative}
.os-tier-n{display:block;font-weight:600;margin-bottom:1px}
.os-tier-p{display:block;font-weight:600;margin-bottom:6px}
.os-tier-p i{
  font-style:normal;font-weight:400;color:var(--ink-3);
  font-size:var(--t-micro);margin-inline-start:5px;
}
.os-tier-b{
  display:block;font-size:var(--t-micro);line-height:15px;
  color:var(--ink-3);margin-bottom:6px;
}
/* Marketing's own badge, carried through from the pricing page so the rep and
   the supplier are looking at the same card. Absolute so a long plan name cannot
   push it onto its own line. */
.os-tier-badge{
  position:absolute;inset-block-start:9px;inset-inline-end:10px;
  font-size:var(--t-micro);font-weight:600;letter-spacing:.02em;
  color:var(--ink-2);background:var(--bg);
  border:1px solid var(--line);border-radius:999px;padding:1px 7px;
}
.os-tier ul{margin:0;padding-inline-start:15px;color:var(--ink-2)}
.os-tier li{font-size:var(--t-micro);line-height:16px;margin-bottom:2px}
/* What the plan does NOT include. The pricing page prints these too, and leaving
   them off would make Basic and Pro read as unlimited when the storefront is the
   whole reason to pay for Growth. */
.os-tier li.no{color:var(--ink-3);list-style:none;margin-inline-start:-15px}
.os-tier li.no::before{content:"\2014";margin-inline-end:6px}
/* The one line on a card that is a boundary rather than a feature. It is the
   colour reserved for urgency and this earns it: "No Moedatech OS" changes what
   the deal IS, not what it includes -- it decides whether a sale belongs in this
   pipeline at all, now that OS is Enterprise-only. */
.os-tier li.flag{color:var(--signal);font-weight:600;letter-spacing:.01em}

.seg2{
  display:inline-flex;border:1px solid var(--line-strong);
  border-radius:var(--r-pill);overflow:hidden;margin-bottom:12px;
}
.seg2 button{
  font:inherit;font-size:var(--t-micro);padding:5px 15px;border:0;
  background:transparent;color:var(--ink-2);cursor:pointer;
}
.seg2 button.on{background:var(--ink);color:var(--panel)}

/* ---- chats --------------------------------------------------------------- */
/* A group header, not a row: it names the thing the rows below belong to, so it
   is not clickable and does not pretend to be. */
tr.grp td{
  background:var(--bg);color:var(--ink-2);
  font-size:var(--t-micro);letter-spacing:.02em;
  padding:8px 12px;border-top:1px solid var(--line);
}
tr.grp td .num{color:var(--ink-3);margin-inline-start:8px}
tr.grp:hover td{background:var(--bg)}

/* ---- an action with no endpoint behind it -------------------------------- */
/* Grey, dashed, and marked with a hollow dot. Deliberately NOT --signal: this
   is not urgent and not an error, it is unbuilt -- and if "unbuilt" borrowed
   the urgency colour, urgency would stop meaning anything. Deliberately not
   aria-disabled either, because pressing it is how a rep finds out why. */
.act.nowire{
  color:var(--ink-3);border-style:dashed;border-color:var(--line-strong);
  background:var(--bg);
}
.act.nowire:hover{background:var(--s10);color:var(--ink-2)}
.act.nowire svg{opacity:.7}
.act.nowire .nw{
  width:6px;height:6px;flex:none;border-radius:50%;
  border:1.5px solid currentColor;opacity:.8;
}
.act.nowire[aria-disabled="true"]{opacity:1;pointer-events:none}

.nowire-note{
  font-size:var(--t-micro);line-height:var(--lh-body);color:var(--ink-2);
  padding:12px;border:1px dashed var(--line-strong);border-radius:var(--r);background:var(--bg);
}
.nowire-note b{color:var(--ink);font-weight:600}
.nowire-needs{margin-top:8px;color:var(--ink-3)}
.nowire-needs span{
  display:inline-block;margin-inline-end:6px;
  font-size:var(--t-micro);letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);
}


/* ---- motion -------------------------------------------------------------
   Three rules decide everything below.

   Frequency sets whether a thing animates at all. The sheet opens a few times
   an hour, so it is worth animating. The search palette is bound to a keyboard
   shortcut and will be hit a hundred times a day, so it is NOT animated -- a
   keyboard action that waits for a transition feels broken no matter how short
   the transition is.

   Direction sets the easing. Entering and leaving both use ease-out, because
   it moves immediately, which is the frame the eye is on. ease-in would delay
   exactly the moment the rep is watching.

   Leaving is always quicker than arriving: arriving is the system explaining
   itself, leaving is the system getting out of the way. */
:root{
  /* The built-in curves are too soft to read as deliberate at these speeds. */
  --ease-out-strong:cubic-bezier(.23,1,.32,1);
  --ease-sheet:cubic-bezier(.32,.72,0,1);
}

/* The sheet is a drawer: it comes from the edge it lives on, so the way it
   arrives already tells you where it went when it leaves. translate, not
   width -- width would relayout the table inside it on every frame. */
.pane{
  transform:translateX(100%);
  transition:transform 200ms var(--ease-out-strong);
}
.pane.on{
  transform:translateX(0);
  transition:transform 280ms var(--ease-sheet);
}
[dir="rtl"] .pane{transform:translateX(-100%)}
[dir="rtl"] .pane.on{transform:translateX(0)}

/* The drawer body is replaced wholesale when a row is opened. A swap with no
   transition reads as a glitch; a long one gets in the way of a rep opening
   twenty rows in a row. Opacity only, and brief. */
.dock-body > *{animation:dk-in 130ms var(--ease-out-strong) both}
@keyframes dk-in{from{opacity:0}to{opacity:1}}

/* Pressable things confirm they were pressed. Subtle enough to feel like the
   surface gave, not like the button moved. */
.act,.drill,.btn-chat,.rail-find{transition:transform 140ms var(--ease-out-strong),
  background var(--t-fast) var(--out),border-color var(--t-fast) var(--out),color var(--t-fast) var(--out)}
.act:active,.btn-chat:active,.rail-find:active{transform:scale(.97)}
/* A full-width row scales from the edge it is anchored to, not its middle --
   scaling a 400px strip about its centre pulls both ends inward and reads as
   the row shrinking rather than being pushed. */
.drill{transform-origin:center left}
.drill:active{transform:scale(.995)}
[dir="rtl"] .drill{transform-origin:center right}

/* Reduced motion means less movement, not less feedback: the colour and
   opacity changes stay because they carry meaning, the travel goes. */
@media (prefers-reduced-motion:reduce){
  .pane,.pane.on{transform:none;transition:opacity 120ms linear}
  .pane{opacity:0}
  .pane.on{opacity:1}
  .dock-body > *{animation:none}
  .act:active,.btn-chat:active,.drill:active,.rail-find:active{transform:none}
}


/* ---- deal-room state ----------------------------------------------------- */
/* Abandoned is the majority state, so it stays quiet -- colouring the common
   case is how a column stops meaning anything. Only the two states a rep can
   still act on carry any weight. */
.room-st{
  font-size:var(--t-micro);line-height:1;padding:4px 8px;border-radius:var(--r-pill);
  white-space:nowrap;background:var(--s10);color:var(--ink-3);border:1px solid var(--line);
}
.room-st[data-s="negotiating"]{background:var(--good-soft);color:var(--good);border-color:transparent}
.room-st[data-s="open"]{background:var(--panel);color:var(--ink-2);border-color:var(--line-strong)}
.chip-gap{flex:1}

.bid-st[data-s="unreviewed"]{background:var(--s10);color:var(--ink-2);border-color:var(--line-strong)}
.bid-st[data-s="seen"]{background:var(--good-soft);color:var(--good);border-color:transparent}
.bid-st[data-s="rejected"]{background:var(--signal-soft);color:var(--signal);border-color:transparent}

/* ---- the request desk --------------------------------------------------
   Tarek's job is one number: every request on 4+ bids. These are the two cells
   that answer it at a glance, and the dialog that closes a row. */

/* The gap has to be readable without arithmetic, so the count is the loud half
   and the target is the quiet one. Kept LTR under RTL: a bid count is a
   quantity, not prose, and mirroring it reads as a different number. */
.gap{display:inline-flex;align-items:baseline;font-family:var(--mono);
  font-variant-numeric:tabular-nums;direction:ltr}
.gap b{font-size:var(--t-mid);line-height:1;font-weight:650}
.gap i{font-style:normal;color:var(--ink-3);font-size:var(--t-micro)}
.gap.met b{color:var(--good)}
.need{display:block;font-size:var(--t-micro);color:var(--signal);margin-top:2px}

/* Late only counts when the target is UNMET. A six-bid request four hours old is
   not late, it is finished. */
.clock.late{color:var(--signal);font-weight:600}

.ord{font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-2);
  border:1px solid var(--line);border-radius:var(--r-pill);padding:2px 7px;white-space:nowrap}

/* ---- outcome dialog ---- */
.oc-veil{
  position:fixed;inset:0;z-index:120;
  background:rgba(20,23,27,.42);
  display:grid;place-items:center;padding:20px;
}
.oc-veil[hidden]{display:none}
/* THE BUTTON HE HAS TO PRESS IS NEVER OFF-SCREEN. The box scrolled as a whole,
   so on a 656px window the footer sat at 599..668 — Cancel and Record below the
   fold, on a dialog whose entire purpose is pressing one of them. Now the BODY
   scrolls inside a fixed frame: header pinned at the top, footer at the bottom,
   and the outcomes scroll between them. */
.oc-box{
  width:min(560px,100%);max-height:88dvh;
  display:flex;flex-direction:column;min-height:0;
  background:var(--panel);border-radius:12px;
  box-shadow:0 24px 70px rgba(20,23,27,.28);
}
.oc-box>.oc-head,.oc-box>.oc-foot{flex:none}
.oc-box>.oc-body{flex:1;min-height:0;overflow:auto}
/* Disqualify stays with the footer rather than scrolling away — it is permanent
   by U10, and a permanent control you have to scroll to find is not permanent. */
.oc-box>.oc-dq{flex:none}
.oc-head{position:relative;padding:18px 20px 12px;border-bottom:1px solid var(--line)}
.oc-head h2{margin:0;font-size:var(--t-mid);line-height:var(--lh-mid);font-weight:650;
  letter-spacing:-.01em}
.oc-sub{margin-top:4px;font-size:var(--t-micro);color:var(--ink-3);
  unicode-bidi:plaintext;overflow-wrap:anywhere}
.oc-x{position:absolute;inset-block-start:14px;inset-inline-end:14px;
  width:28px;height:28px;border-radius:var(--r);color:var(--ink-3);
  display:grid;place-items:center}
.oc-x:hover{background:var(--s10);color:var(--ink)}
.oc-x svg{width:15px;height:15px}
.oc-body{padding:16px 20px}

/* The win is the point of the job, so it is the biggest thing on the screen. */
.oc-b.win{
  display:flex;align-items:center;gap:12px;width:100%;
  padding:14px 16px;border-radius:10px;
  border:1px solid var(--good);background:var(--good-soft);color:var(--good);
  font-size:var(--t-mid);font-weight:650;text-align:start;
  transition:transform var(--t-fast) var(--out),box-shadow var(--t-fast) var(--out);
}
.oc-b.win svg{width:26px;height:26px;flex:none}
.oc-b.win em{margin-inline-start:auto;font-style:normal;font-size:var(--t-micro);
  font-weight:500;opacity:.75;white-space:nowrap}
.oc-b.win:hover{transform:translateY(-1px);box-shadow:0 6px 18px rgba(31,107,74,.18)}
.oc-b.win[aria-pressed="true"]{background:var(--good);color:var(--s0);border-color:var(--good)}
.oc-b.win[aria-pressed="true"] em{opacity:.85}

.oc-sep{display:flex;align-items:center;gap:10px;margin:16px 0 12px;
  font-size:var(--t-micro);color:var(--ink-3)}
.oc-sep::before,.oc-sep::after{content:"";height:1px;background:var(--line);flex:1}

.oc-lose{display:flex;flex-wrap:wrap;gap:7px}
.oc-b{
  border:1px solid var(--line-strong);border-radius:var(--r-pill);
  padding:6px 13px;font-size:var(--t-body);color:var(--ink-2);background:var(--panel);
  transition:border-color var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.oc-b:hover{border-color:var(--s40);color:var(--ink)}
.oc-b[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--s0)}

.oc-nl{display:block;font-size:var(--t-micro);color:var(--ink-2);margin:16px 0 5px}
.oc-nl .req{color:var(--signal)}
.oc-nl .opt{color:var(--ink-3);font-weight:400}
#oc-note{
  width:100%;resize:vertical;padding:9px 11px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--s5);
  font:inherit;font-size:var(--t-body);color:var(--ink);
}
#oc-note:focus{background:var(--panel);border-color:var(--line-strong);outline:none}
.oc-tag{margin-top:9px;font-size:var(--t-micro);color:var(--ink-3);
  display:flex;gap:10px;align-items:baseline;flex-wrap:wrap}
.oc-tag code{font-family:var(--mono);background:var(--s10);border-radius:4px;
  padding:1px 6px;color:var(--ink-2)}
.oc-tag .term{color:var(--ink-2)}
.oc-foot{display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  padding:14px 20px 18px;border-top:1px solid var(--line)}
.oc-foot .go{
  padding:8px 18px;border-radius:var(--r);background:var(--ink);color:var(--s0);
  font-size:var(--t-body);font-weight:550;
}
.oc-foot .go[disabled]{opacity:.4;pointer-events:none}
.oc-why{font-size:var(--t-micro);color:var(--signal)}

/* Disqualify sits in the outcome dialog's foot but is NOT an outcome, so it is
   pushed away from Record and Cancel with margin-inline-end:auto rather than
   sitting in the same group -- the gap is the sentence "this is a different
   kind of decision". Quiet by default; the confirm step is the loud one. */
.dq-open{
  margin-inline-end:auto;padding:8px 12px;border-radius:var(--r);
  font-size:var(--t-micro);color:var(--ink-3);background:transparent;
}
.dq-open:hover{color:var(--signal);background:var(--signal-soft)}
/* ONE ROW, not three. Permanent by U10 and therefore always taking height from
   the outcomes above it — as a stacked label, input and button it took about
   180px of a 656px window, and the last row of chips was sliced in half at the
   fold. Awab looked at this dialog and asked where Move to supplier had gone: it
   was there, cut across the middle by this block. Inline, it costs a third of
   that and stays just as impossible to miss. */
.oc-dq{
  display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  padding:10px 20px;border-top:1px solid var(--line);background:var(--signal-soft);
}
.oc-dq label{font-size:var(--t-micro);color:var(--ink-2);flex-basis:100%}
.oc-dq input{
  flex:1;min-width:180px;
  padding:7px 11px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--s0);font-size:var(--t-micro);color:var(--ink);
}
.oc-dq input:focus{outline:2px solid var(--signal);outline-offset:-1px}
.oc-dq input[disabled]{opacity:.5}
/* The same line carries two different things in here — why the control is
   unavailable, and why a write was refused — and both are the answer to "I
   pressed it and nothing happened". On this block's signal-soft ground the
   shared --ink-3 sits too far back to read as either. */
.oc-dq .oc-blocked{color:var(--signal);font-weight:550;margin-top:2px}
/* The "not yet" half of the same line. A prompt that turns itself off the
   moment it is satisfied should not shout in the same red as a dead end the
   rep can do nothing about. */
.oc-dq .oc-blocked.hint{color:var(--ink-3);font-weight:400}
.dq-go{
  flex:none;padding:7px 14px;border-radius:var(--r);white-space:nowrap;
  background:var(--signal);color:var(--s0);font-size:var(--t-micro);font-weight:550;
}
.dq-go[disabled]{opacity:.4;pointer-events:none}

/* Undo lives near the thumb, not back up in the row that just left. */
.oc-toast{
  position:fixed;inset-block-end:20px;inset-inline-start:50%;
  transform:translateX(-50%);z-index:130;
  display:flex;align-items:center;gap:14px;
  background:var(--s90);color:var(--s0);
  border-radius:var(--r-pill);padding:9px 10px 9px 16px;
  box-shadow:0 12px 34px rgba(20,23,27,.3);font-size:var(--t-body);
}
.oc-toast button{
  border-radius:var(--r-pill);padding:5px 13px;font-size:var(--t-micro);
  font-weight:600;background:rgba(255,255,255,.14);color:var(--s0);
}
.oc-toast button:hover{background:rgba(255,255,255,.24)}

@media (max-width:860px){
  .oc-box{width:100%}
  .oc-b.win{font-size:var(--t-body)}
  .oc-b.win em{display:none}
}

/* ---- account menu ---- */
.whowrap{position:relative;flex:none}
.who{cursor:pointer;border:0}
.who:hover{background:var(--s30)}
.who[aria-expanded="true"]{background:var(--ink);color:var(--s0)}
.whomenu{
  /* Above everything this app draws. 70 put it level with .toast and under the
     outcome dialog's veil; an account menu that can be covered by the app's own
     furniture is a menu you cannot dismiss your way out of. */
  position:absolute;inset-block-start:calc(100% + 8px);inset-inline-end:0;z-index:140;
  min-width:210px;background:var(--panel);
  border:1px solid var(--line-strong);border-radius:10px;
  box-shadow:0 14px 40px rgba(20,23,27,.16);
  padding:6px;
}
.whomenu[hidden]{display:none}
.whoid{padding:8px 10px 10px;border-bottom:1px solid var(--line);margin-bottom:6px}
.whoid b{display:block;font-size:var(--t-body);font-weight:600;color:var(--ink);
  overflow-wrap:anywhere}
.whoid span{display:block;font-size:var(--t-micro);color:var(--ink-3);
  overflow-wrap:anywhere;margin-top:1px}
.whoitem{
  display:flex;align-items:center;gap:9px;width:100%;
  padding:8px 10px;border-radius:var(--r);
  font-size:var(--t-body);color:var(--ink-2);text-align:start;
}
.whoitem svg{width:16px;height:16px;flex:none}
.whoitem:hover{background:var(--s10);color:var(--ink)}

/* The row-colour key, on demand rather than spelled across the filter row. */
.tone-pop{
  position:fixed;z-index:140;
  background:var(--panel);border:1px solid var(--line-strong);border-radius:10px;
  box-shadow:0 14px 40px rgba(20,23,27,.16);
  padding:10px 12px;display:flex;flex-direction:column;gap:6px;
}
.tone-h{font-size:var(--t-micro);color:var(--ink-3);text-transform:uppercase;
  letter-spacing:.06em;margin-bottom:2px}
.tone-pop .lg-i{display:flex;align-items:center;gap:8px;font-size:var(--t-body);
  color:var(--ink-2);white-space:nowrap}
.chip.info[aria-expanded="true"]{background:var(--ink);border-color:var(--ink);color:var(--s0)}

/* ---- Supply ------------------------------------------------------------
   Three numbers narrowing left to right. The middle one is the answer — how
   many suppliers can ACTUALLY bid — so it carries the colour, and the tone is
   the whole cell rather than one digit, because a request nobody can bid on is
   a property of the row, not of a number in it. */
/* The supply triple. One target, not two: this was a cell containing a 16px
   (i) button, inside a row that is itself clickable — three nested targets in
   eighteen pixels, with the explanation on the smallest of them. The whole cell
   is the control now. */
.sup{
  display:inline-flex;align-items:baseline;gap:3px;direction:ltr;
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  padding:2px 6px;margin-inline-start:-6px;border-radius:var(--r);
  background:transparent;border:0;cursor:pointer;
  transition:background var(--t-fast) var(--out);
}
@media (hover:hover) and (pointer:fine){ .sup:hover{background:var(--s10)} }
.sup:active{transform:scale(.97)}
.sup b{font-weight:600;font-size:var(--t-body);line-height:1;color:var(--ink-2)}
/* A middle dot, not a slash. Three numbers joined by slashes read as a
   fraction, and these are not a fraction — they are one set narrowing left to
   right. */
.sup i{font-style:normal;color:var(--s40);font-size:var(--t-micro)}
.sup-none{font-style:normal;color:var(--s40);font-size:var(--t-body)}
/* Nobody can bid on this. The one supply case worth seeing without reading —
   and it colours the NUMBER rather than filling the cell, because a filled cell
   competes with the row's own tone for the same meaning. */
.sup-warn b:nth-of-type(2),.sup-bad b:nth-of-type(2){color:var(--signal)}
.sup-zero{color:var(--signal)}

/* Where the app says a request actually is — in the SAME FOUR WORDS the drawer
   uses, so a row and the drawer that opens from it cannot disagree. The class
   is now the FAMILY rather than the rung, because there are four families and
   there were seven rungs. */
.appst{
  display:inline-flex;align-items:center;gap:6px;
  font-size:var(--t-micro);line-height:var(--lh-micro);
  padding:2px 9px;border-radius:var(--r-pill);white-space:nowrap;
  background:var(--s10);color:var(--ink-2);cursor:help;
}
.appst::before{
  content:"";width:5px;height:5px;border-radius:var(--r-pill);
  background:var(--s40);flex:none;
}
.appst-live::before{background:var(--ink-3)}
.appst-talking::before{background:var(--ink-2)}
.appst-won::before{background:var(--good)}
.appst-closed::before{background:var(--s40)}
.appst-closed{color:var(--ink-3)}
/* An unmapped rung is outlined rather than coloured: a status nobody has folded
   yet must not pass as one of the four. */
.appst-unknown{
  background:transparent;color:var(--warn);box-shadow:inset 0 0 0 1px var(--warn);
}
/* THE ONE THAT STILL SHOUTS. It reads Open like the other two live rungs, and
   keeps the treatment, because "live and nobody has been told" is the work on a
   desk whose whole job is getting bids onto a request. It earns the colour
   precisely because nothing around it competes for it any more. */
.appst-silent{background:var(--signal-soft);color:var(--signal);font-weight:600}
.appst-silent::before{background:var(--signal)}

/* The (i) button's rules went with the button. */

.supi-row{display:flex;gap:14px;padding:12px 0;border-bottom:1px solid var(--line)}
.supi-row:last-child{border-bottom:0}
.supi-n{font-family:var(--mono);font-size:var(--t-head);line-height:1;font-weight:650;
  min-width:44px;text-align:end;font-variant-numeric:tabular-nums}
.supi-l{font-size:var(--t-body);font-weight:600;color:var(--ink)}
.supi-d{font-size:var(--t-micro);line-height:1.5;color:var(--ink-2);margin-top:2px}
.supi-w{font-size:var(--t-micro);line-height:1.5;color:var(--signal);margin-top:5px}
.supi-good .supi-n{color:var(--good)}
.supi-warn .supi-n,.supi-bad .supi-n{color:var(--signal)}
.supi-neutral .supi-n{color:var(--ink)}
.supi-unknown .supi-n{color:var(--ink-3)}

/* The supplier message, as it will actually arrive — preserved line breaks and
   emoji, not reflowed into a paragraph. */
.tpl{
  margin:0;padding:12px 14px;border-radius:var(--r);
  background:var(--s5);border:1px solid var(--line);
  font:inherit;font-size:var(--t-body);line-height:1.55;color:var(--ink);
  white-space:pre-wrap;overflow-wrap:anywhere;unicode-bidi:plaintext;
  max-height:46vh;overflow:auto;
}

/* A rep's own judgement that a request is real. On, it should read as a state
   rather than as a button they might press again by accident. */
.act[data-on]{background:var(--good-soft);border-color:var(--good);color:var(--good);font-weight:600}
.act[data-on] svg{fill:currentColor;stroke:currentColor}

/* Scope, as icons. Same pill as every other chip so the row stays one family. */
.chip.ico{width:30px;padding:4px 0;justify-content:center}
/* With a count, the chip stops being square and earns room for the number. The
   badge answers the question the filter row could not: "Moedatech OS 73" and
   "none of these are yours yet" are both true, and the number on the scope is
   what reconciles them. */
.chip.ico.has-n{width:auto;padding:4px 8px 4px 7px;gap:5px}
.ico-n{font-family:var(--mono);font-size:var(--t-micro);font-variant-numeric:tabular-nums;
  line-height:1;color:inherit}
/* Zero still prints -- it is the thing that explains an empty table -- but it
   does not ask for attention the way a real number does. */
.ico-n.is-zero{opacity:.45}
.chip.ico svg{width:15px;height:15px;display:block}
.chip.ico[aria-pressed="true"] svg{stroke-width:2}

/* A multi-line request says so rather than reporting its first line as the whole. */
.more-n{margin-inline-start:6px;font-family:var(--mono);font-size:var(--t-micro);
  color:var(--ink-3);font-weight:400}

/* ---- Moedatech OS: documents and the trial clock -------------------------
   Two facts in one column, kept visibly apart. Relay's coverage is a fraction
   over the whole fleet; the health file is one document about the supplier.
   Stacking them as one number would let a documented health file cover for
   forty undocumented machines. */
.doc-pair{display:flex;align-items:center;gap:8px;flex-wrap:wrap}

.doccov{font-family:var(--mono);font-size:var(--t-micro);font-variant-numeric:tabular-nums;
  padding:2px 6px;border-radius:var(--r-sm);background:var(--s5);color:var(--ink-2)}
/* Colour only where it means act. Nothing documented at all is the one state
   worth interrupting a scan for; partial is a fact, not an alarm. */
.doccov-bad{background:var(--signal-soft);color:var(--signal);font-weight:600}
.doccov-ok{background:var(--good-soft);color:var(--good)}

.doc-add,.doc-has>a{
  display:inline-flex;align-items:center;gap:4px;
  font:inherit;font-size:var(--t-micro);line-height:1;
  padding:4px 7px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--panel);color:var(--ink-2);
  cursor:pointer;text-decoration:none;white-space:nowrap;
}
.doc-add svg,.doc-has>a svg{width:12px;height:12px;flex:none}
.doc-add:hover{border-color:var(--line-strong);color:var(--ink)}
/* Present reads as a fact you can open, not as another thing to do. */
.doc-has{display:inline-flex;align-items:center;gap:2px}
.doc-has>a{border-color:var(--good);color:var(--good);background:var(--good-soft)}
.doc-has>a:hover{filter:brightness(.97)}
.doc-del{border:0;background:none;cursor:pointer;color:var(--ink-3);
  font-size:14px;line-height:1;padding:2px 4px;border-radius:var(--r-sm)}
.doc-del:hover{color:var(--signal);background:var(--signal-soft)}

/* The opportunity report sits beside the two documents and is deliberately NOT
   styled as one. Relay and Health are files somebody uploaded — they exist or
   they do not. This is generated on demand from the product's own tables and is
   always available for an account that has one, so it reads as an action rather
   than as a green "present" badge. */
.opp-go{
  display:inline-flex;align-items:center;gap:4px;
  font:inherit;font-size:var(--t-micro);line-height:1;
  padding:4px 7px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--panel);color:var(--ink-2);
  text-decoration:none;white-space:nowrap;
}
.opp-go svg{width:12px;height:12px;flex:none}
.opp-go:hover{border-color:var(--ink);color:var(--ink)}

/* The trial clock. Overdue is not "ending soon" and must not read as it: a
   lapsed trial is a subscription nobody is being billed for. */
.trialend{font-family:var(--mono);font-size:var(--t-micro);font-variant-numeric:tabular-nums;
  color:var(--ink-2)}
.trialend-warn{color:var(--ink);font-weight:600}
.trialend-bad{color:var(--signal);font-weight:600}

/* ---- view-as ------------------------------------------------------------
   The identity chip carries the viewed person's initials, so on its own it is
   indistinguishable from having signed in as them. The ring says otherwise. */
.whoas{border-top:1px solid var(--line);padding:8px 10px 4px;display:grid;gap:6px}
.whoas-h{font-size:var(--t-micro);color:var(--ink-3);letter-spacing:.02em}
.whoas-h em{font-style:normal;color:var(--signal);font-weight:600}
.whoas-sel{font:inherit;font-size:var(--t-micro);padding:5px 6px;
  border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--panel);color:var(--ink);width:100%}
.whoas-back{color:var(--signal)}

/* The bucket beside the lead, not in a column. Sized down from the old cell:
   it sits after a name now, so it must read as a marker on that name rather
   than as a second heading competing with it. */
.lead-buckets{display:inline-flex;gap:4px;margin-inline-start:8px;vertical-align:middle}
.lead-buckets .bucket{font-size:var(--t-micro);padding:1px 6px}

/* The filter chip naming its one selected bucket. The group is the quiet half
   and the bucket is what the rep is actually looking at. */
.chip.grp em{font-style:normal;font-weight:600;margin-inline-start:5px;opacity:.85}

/* Staging only: view as an address the roster has never heard of. */
.whoas-any{display:flex;gap:4px}
.whoas-any input{flex:1;min-width:0;font:inherit;font-size:var(--t-micro);
  padding:5px 6px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--panel);color:var(--ink)}
.whoas-any button{font:inherit;font-size:var(--t-micro);padding:5px 9px;
  border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--s5);color:var(--ink-2);cursor:pointer}
.whoas-any button:hover{border-color:var(--line-strong);color:var(--ink)}

/* Nothing selected: the instruction IS the screen, so it gets room rather than
   sitting like a failed load. */
.pick-first p{margin:0}
.pick-first p b{font-size:var(--t-body);color:var(--ink)}
.pick-first .sub{margin-top:6px;max-width:44ch;font-size:var(--t-micro);
  color:var(--ink-3);line-height:1.55}

/* ---- collapsible sections -----------------------------------------------
   The header becomes the control. A chevron rather than a plus/minus: these
   fold, they are not added and removed, and the rotation carries the state
   without a second glyph to learn. */
.sec[data-foldable] > .sec-h{
  cursor:pointer;user-select:none;
  display:flex;align-items:center;gap:8px;
}
.sec[data-foldable] > .sec-h::after{
  content:'';flex:none;margin-inline-start:auto;
  width:8px;height:8px;
  border-inline-end:1.6px solid var(--ink-3);
  border-block-end:1.6px solid var(--ink-3);
  transform:rotate(45deg) translate(-2px,-2px);
  transition:transform .15s ease;
}
.sec[data-foldable][data-folded] > .sec-h::after{
  transform:rotate(-45deg) translate(-1px,1px);
}
.sec[data-foldable] > .sec-h:hover::after{border-color:var(--ink)}
.sec[data-foldable] > .sec-h:focus-visible{
  outline:2px solid var(--ink);outline-offset:2px;border-radius:var(--r-sm);
}
/* Everything but the header goes. `display:none` rather than a height
   animation: these sections hold lists that fetch, and animating an unknown
   height either jumps or has to be measured on every repaint. */
.sec[data-folded] > *:not(.sec-h){display:none !important}

/* ---- customer drawer, rebuilt -------------------------------------------
   The company leads and carries the tick, because row.verified is a property of
   the company record. The person is the second line and carries the pencil. */
.dock-title .ver{width:15px;height:15px;margin-inline-start:6px;vertical-align:-2px;color:var(--good)}
.dock-sub{display:flex;align-items:center;gap:6px}
.dk-pencil{border:0;background:none;cursor:pointer;padding:2px;line-height:0;
  color:var(--ink-3);border-radius:var(--r-sm);flex:none}
.dk-pencil svg{width:13px;height:13px}
.dk-pencil:hover{color:var(--ink);background:var(--s10)}

/* The buckets tile holds chips, not a number, so it needs the row to itself. */
.tile-wide{grid-column:1/-1}
/* `.tile b` sets display:block and font-weight:600 and out-specifies a bare
   class, so this has to match at least as tightly or the chips render as a
   block of bold text. */
.tile b.tile-chips{display:flex;flex-wrap:wrap;gap:4px;font-weight:400;font-size:var(--t-micro)}
.tile b.tile-chips .bucket{font-size:var(--t-micro)}

/* One unlabelled strip in place of seven labelled rows. Each value says what it
   is by looking like itself, so the labels were width spent on nothing. */
.idstrip{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px}
.idbit{font-size:var(--t-micro);color:var(--ink-2)}
.idbit + .idbit::before{content:'·';margin-inline-end:10px;color:var(--ink-3)}
.idbit-none{color:var(--ink-3);font-style:italic}

/* Who raised the request: they asked, or we asked for them. */
.orig{flex:none;line-height:0;color:var(--ink-3)}
.orig svg{width:13px;height:13px}
.orig-us{color:var(--ink-2)}

.cr-n{font-style:normal;font-size:var(--t-micro);color:var(--ink-3);margin-inline-start:6px}
/* MIXED is not one of the four and does not pretend to be. It is a statement
   about a GROUP whose items disagree, which is a different subject from where
   one request got to, so it keeps its own word and its own quiet treatment. */
.req-status[data-fam="mixed"]{background:var(--s10);color:var(--ink-2);font-style:italic}
.cust-more{width:100%;margin-top:6px;padding:7px;border:1px dashed var(--line-strong);
  border-radius:var(--r);background:none;color:var(--ink-2);cursor:pointer;
  font:inherit;font-size:var(--t-micro)}
.cust-more:hover{border-style:solid;color:var(--ink)}

/* "We could not ask" and "they never asked" are different facts and a rep acts
   differently on each, so the failure says so instead of rendering as empty. */
.fail-inline{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:10px;border-radius:var(--r);background:var(--signal-soft);
  color:var(--signal);font-size:var(--t-micro)}

/* ---- sortable column header ---------------------------------------------
   The header IS the button. A separate control beside the label would be a
   second thing to aim at in a row that is already tight. */
.th-sort{
  display:inline-flex;align-items:center;gap:4px;
  font:inherit;color:inherit;background:none;border:0;padding:0;
  cursor:pointer;letter-spacing:inherit;text-transform:inherit;
}
/* The arrows stay faint until the column is actually sorting, so a header row
   of eight columns does not read as eight active controls. */
.th-sort svg{width:11px;height:11px;flex:none;opacity:.35;transition:opacity .12s}
.th-sort:hover svg{opacity:.7}
.th-sort.on{color:var(--ink)}
.th-sort.on svg{opacity:1}
.th-sort:focus-visible{outline:2px solid var(--ink);outline-offset:2px;border-radius:var(--r-sm)}

/* An offline offer is a different quantity from an app bid — same request, two
   pools — so it is appended rather than summed into the count. Quieter than the
   main number because it is the secondary fact. */
.bid-chip-split{gap:3px}
.bid-chip-form{
  font-family:var(--mono);font-size:var(--t-micro);font-variant-numeric:tabular-nums;
  opacity:.6;margin-inline-start:1px;
}

/* ---- the visit form ------------------------------------------------------
   Repeating rows for emails and the people met. Same shape as the dashboard's
   visit form, which is the screen this was ported from. */
.vs-row{display:grid;grid-template-columns:1fr 110px 26px;gap:6px;margin-bottom:6px}
.vs-row-3{grid-template-columns:1fr 1fr 1fr 26px}
.vs-row input{width:100%;min-width:0}
.vs-x{border:1px solid var(--line);background:var(--panel);color:var(--ink-3);
  border-radius:var(--r-sm);cursor:pointer;font-size:15px;line-height:1;padding:0}
.vs-x:hover{color:var(--signal);border-color:var(--signal)}
.vs-add{border:1px dashed var(--line-strong);background:none;color:var(--ink-2);
  border-radius:var(--r-sm);cursor:pointer;font:inherit;font-size:var(--t-micro);
  padding:5px 9px;margin-top:2px}
.vs-add:hover{border-style:solid;color:var(--ink)}

/* Picking the company that is already on file. The server resolves a visit to a
   company BY NAME, so a near-miss creates a duplicate rather than a link — this
   is what stops that happening by accident. */
.mk-ac{position:relative}
.mk-ac-list{position:absolute;inset-inline:0;top:calc(100% + 4px);z-index:20;
  background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r);
  box-shadow:0 12px 32px rgba(20,23,27,.14);overflow:hidden;max-height:220px;overflow-y:auto}
.mk-ac-list[hidden]{display:none}
.mk-ac-item{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  width:100%;text-align:start;border:0;background:none;cursor:pointer;
  padding:8px 10px;font:inherit;font-size:var(--t-micro);color:var(--ink)}
.mk-ac-item em{font-style:normal;color:var(--ink-3);flex:none}
.mk-ac-item:hover{background:var(--s10)}

/* A glyph in the identity strip sits on the line, not above it. */
.idbit-ico{display:inline-flex;align-items:center;line-height:0}
.idbit-ico svg{width:15px;height:15px}
.idstrip .owner-dot{width:22px;height:22px;font-size:10px}

/* ---- bids panel ---------------------------------------------------------
   Ported from docs/proto/sales-bids-panel-uat.html. Every rule is scoped under
   .bidpanel — the prototype scoped them under .stage, and rehoming rather than
   un-scoping keeps a card style from leaking into the queue table below it.

   Five variables the prototype had and this system does not. Defined HERE, in
   terms of tokens that already exist, rather than added to the palette: an
   amber that only the fit chips use does not belong in the same list as the
   colours every screen shares. */
.bidpanel{
  /* --warn / --warn-soft used to be declared HERE and nowhere else. They are in
     the palette now; redeclaring them would put the panel back in charge of a
     colour four other surfaces read. */
  --lh-micro:1.45; --lh-body:1.5; --lh-mid:1.35;
  position:fixed;inset:0;z-index:200;
  background:rgba(20,23,27,.42);
  display:flex;align-items:flex-start;justify-content:center;
  padding:40px 20px;overflow-y:auto;
}
.bidpanel .panel{
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;width:100%;
}
.bidpanel .p-head{
  display:flex;align-items:center;gap:14px;
  padding:14px 18px;border-bottom:1px solid var(--line);
}
.bidpanel .p-title{font-size:var(--t-mid);line-height:var(--lh-mid);font-weight:600;letter-spacing:-.01em}
.bidpanel .p-sub{font-size:var(--t-micro);color:var(--ink-3);unicode-bidi:plaintext}
.bidpanel .p-counts{display:flex;gap:8px;margin-inline-start:auto}
.bidpanel .p-count{
  padding:4px 10px;border-radius:var(--r-pill);background:var(--s10);
  font-size:var(--t-micro);color:var(--ink-2);white-space:nowrap;
}
.bidpanel .p-count b{font-family:var(--mono);font-size:var(--t-body);color:var(--ink);margin-inline-end:3px}
.bidpanel .p-count.unknown{background:var(--signal-soft);color:var(--signal)}
.bidpanel .p-count.unknown b{color:var(--signal)}
.bidpanel .p-x{
  border:1px solid var(--line-strong);background:transparent;color:var(--ink);
  border-radius:var(--r);padding:5px 11px;font:inherit;font-size:var(--t-micro);cursor:pointer;
}
.bidpanel .p-banner{
  padding:10px 18px;border-bottom:1px solid var(--line);
  background:var(--warn-soft);color:var(--warn);
  font-size:var(--t-micro);line-height:var(--lh-micro);
}
.bidpanel .p-banner.bad{background:var(--signal-soft);color:var(--signal)}
.bidpanel .p-banner code{font-family:var(--mono);font-size:10px}
.bidpanel .p-retry{
  border:1px solid currentColor;background:transparent;color:inherit;
  border-radius:var(--r);padding:2px 8px;font:inherit;font-size:10px;cursor:pointer;
  margin-inline-start:4px;
}
.bidpanel .p-empty{padding:34px 18px;text-align:center;color:var(--ink-3);font-size:var(--t-micro)}
/* Two columns where the window allows it — comparing offers is the whole job. */
.bidpanel .p-list{
  display:grid;gap:12px;padding:14px 18px;
  grid-template-columns:repeat(auto-fill,minmax(320px,1fr));
  align-items:start;
}
.bidpanel .card{
  border:1px solid var(--line);border-radius:var(--r);padding:12px 14px;
  background:var(--panel);display:flex;flex-direction:column;gap:9px;min-width:0;
}
.bidpanel .card.is-withdrawn{opacity:.72;border-style:dashed}
.bidpanel .c-head{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}
.bidpanel .c-who{display:flex;align-items:center;min-width:0;flex:1}
.bidpanel .c-name{font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;unicode-bidi:plaintext}
.bidpanel .c-tags{display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.bidpanel .type-pill{
  display:inline-flex;align-items:center;gap:4px;
  padding:2px 8px;border-radius:var(--r-pill);
  font-size:var(--t-micro);line-height:var(--lh-micro);white-space:nowrap;
  background:var(--s10);color:var(--ink-2);
}
.bidpanel .type-pill svg{width:11px;height:11px}
.bidpanel .type-pill.link{background:#ede9fe;color:#5b21b6}
@media (prefers-color-scheme:dark){ .bidpanel .type-pill.link{background:#2b2340;color:#c4b5fd} }
.bidpanel .c-status{
  padding:2px 8px;border-radius:var(--r-pill);background:var(--s10);color:var(--ink-2);
  font-size:var(--t-micro);line-height:var(--lh-micro);white-space:nowrap;
}
.bidpanel .c-status[data-s="withdrawn"]{background:var(--signal-soft);color:var(--signal)}
/* Four words, because pending-but-visible is its own state. */
.bidpanel .mod-chip{
  padding:2px 8px;border-radius:var(--r-pill);
  font-size:var(--t-micro);line-height:var(--lh-micro);white-space:nowrap;font-weight:550;
}
.bidpanel .mod-chip.pending{background:var(--warn-soft);color:var(--warn)}
.bidpanel .mod-chip.live{background:var(--signal-soft);color:var(--signal)}
.bidpanel .mod-chip.approved{background:var(--good-soft);color:var(--good)}
.bidpanel .mod-chip.rejected{background:var(--s20);color:var(--ink-2)}
.bidpanel .mod-unrev{
  padding:2px 7px;border-radius:var(--r-pill);
  box-shadow:inset 0 0 0 1px var(--warn);color:var(--warn);
  font-size:10px;line-height:15px;white-space:nowrap;
}
.bidpanel .c-count{font-size:var(--t-micro);color:var(--warn)}
.bidpanel .c-count.live{color:var(--signal)}
.bidpanel .c-withdrawn{
  padding:6px 9px;border-radius:var(--r);
  background:var(--signal-soft);color:var(--signal);
  font-size:var(--t-micro);line-height:var(--lh-micro);
}
.bidpanel .c-price{
  display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:var(--t-mid);line-height:var(--lh-mid);font-weight:600;
}
.bidpanel .c-unit,.bidpanel .c-total{font-family:var(--font);font-size:var(--t-micro);
  font-weight:400;color:var(--ink-3)}
.bidpanel .c-noprice{font-family:var(--font);font-size:var(--t-body);font-weight:400;color:var(--ink-3)}
.bidpanel .c-kvs{display:grid;grid-template-columns:auto 1fr;gap:3px 10px;font-size:var(--t-micro)}
.bidpanel .c-kv{display:contents}
.bidpanel .c-k{color:var(--ink-3);white-space:nowrap}
.bidpanel .c-v{color:var(--ink);min-width:0;overflow-wrap:anywhere;unicode-bidi:plaintext}
.bidpanel .c-dim{color:var(--ink-3)}
.bidpanel .c-ttb{font-family:var(--mono)}
.bidpanel .c-expired{color:var(--signal)}
.bidpanel .chip{
  display:inline-block;padding:2px 8px;border-radius:var(--r-pill);
  background:var(--s10);color:var(--ink-2);
  font-size:10px;line-height:15px;white-space:nowrap;
}
.bidpanel .chip.tick::before{content:"✓ ";color:var(--good)}
.bidpanel .chip.doc{text-decoration:none;box-shadow:inset 0 0 0 1px var(--line-strong);background:transparent}
.bidpanel .chip.doc.dead{opacity:.55;text-decoration:line-through}
.bidpanel .c-terms,.bidpanel .c-confirms,.bidpanel .c-docs{display:flex;gap:4px;flex-wrap:wrap}
.bidpanel .c-warn{
  padding:6px 9px;border-radius:var(--r);background:var(--signal-soft);color:var(--signal);
  font-size:var(--t-micro);line-height:var(--lh-micro);
}
.bidpanel .c-note,.bidpanel .c-msg{
  padding:6px 9px;border-radius:var(--r);background:var(--s10);
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-2);
  unicode-bidi:plaintext;
}
.bidpanel .c-msgs{display:flex;flex-direction:column;gap:4px}
.bidpanel .c-noitems{font-size:var(--t-micro)}
.bidpanel .c-items{display:flex;flex-direction:column;gap:6px}
.bidpanel .c-line{border-top:1px solid var(--line);padding-top:6px}
.bidpanel .c-line-h{display:flex;align-items:baseline;gap:8px;font-size:var(--t-micro)}
.bidpanel .c-line-l{flex:1;min-width:0;unicode-bidi:plaintext}
.bidpanel .c-line-v{font-family:var(--mono);white-space:nowrap}
.bidpanel .c-line-sub{font-size:10px;color:var(--ink-3);margin-top:2px}
.bidpanel .c-units{
  margin-inline-start:6px;padding:1px 6px;border-radius:var(--r-pill);
  background:var(--s10);color:var(--ink-3);font-family:var(--mono);font-size:10px;
}
.bidpanel .c-units.short{background:var(--signal-soft);color:var(--signal)}
.bidpanel .c-reqsec{border:1px solid var(--line);border-radius:var(--r);padding:8px 10px;margin-top:6px}
.bidpanel .c-reqsec.cur{border-color:var(--ink)}
.bidpanel .c-reqsec-h{display:flex;align-items:baseline;gap:8px;font-size:var(--t-micro);margin-bottom:4px}
.bidpanel .c-reqsec-h b{font-family:var(--mono)}
.bidpanel .c-thisreq{padding:1px 7px;border-radius:var(--r-pill);background:var(--ink);color:var(--s0);
  font-size:10px}
.bidpanel .c-subtotal{margin-inline-start:auto;font-family:var(--mono);color:var(--ink-3)}
.bidpanel .c-foot{display:flex;align-items:center;gap:8px;font-size:var(--t-micro)}
/* Verdict area + ladder. */
.bidpanel .c-mod{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  border-top:1px solid var(--line);padding-top:9px;
}
.bidpanel .c-mod.done{font-size:var(--t-micro);color:var(--ink-3)}
.bidpanel .c-verdict{padding:3px 10px;border-radius:var(--r);font-size:var(--t-micro);font-weight:600}
.bidpanel .c-verdict.approved{background:var(--good-soft);color:var(--good)}
.bidpanel .c-verdict.rejected{background:var(--s20);color:var(--ink-2)}
.bidpanel .c-reason{flex-basis:100%;font-size:var(--t-micro);color:var(--ink-2)}
.bidpanel .c-btn{
  border:1px solid var(--line-strong);background:transparent;color:var(--ink);
  border-radius:var(--r);padding:5px 11px;font:inherit;font-size:var(--t-micro);cursor:pointer;
  transition:background var(--t-fast) var(--out);
}
.bidpanel .c-btn:hover{background:var(--s10)}
.bidpanel .c-btn.ok{border-color:var(--good);color:var(--good)}
.bidpanel .c-btn.no{border-color:var(--line-strong)}
.bidpanel .c-btn.danger{background:var(--signal);border-color:var(--signal);color:#fff}
.bidpanel .c-btn.danger:hover{opacity:.9;background:var(--signal)}
.bidpanel .c-btn.off,.bidpanel .c-link.off{opacity:.4;cursor:not-allowed}
.bidpanel .c-link{
  border:0;background:none;color:var(--ink-3);font:inherit;font-size:var(--t-micro);
  cursor:pointer;text-decoration:underline;text-underline-offset:2px;padding:2px 4px;
}
.bidpanel .c-link:hover{color:var(--ink)}
.bidpanel .c-reject-box,.bidpanel .c-confirm{
  flex-basis:100%;display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  padding:9px;border-radius:var(--r);background:var(--s10);margin-top:6px;
}
.bidpanel .c-reject-box[hidden],.bidpanel .c-confirm[hidden]{display:none}
.bidpanel .c-reject-box textarea{
  flex-basis:100%;border:1px solid var(--line-strong);border-radius:var(--r);
  background:var(--panel);color:var(--ink);font:inherit;font-size:var(--t-micro);
  padding:6px;resize:vertical;min-height:44px;
}
.bidpanel .c-confirm-t{flex-basis:100%;font-weight:600;font-size:var(--t-body)}
.bidpanel .c-confirm-b{flex-basis:100%;font-size:var(--t-micro);color:var(--ink-2)}
.bidpanel .c-confirm-b label{display:block;margin-top:5px}
.bidpanel .c-actnote{
  flex-basis:100%;font-size:var(--t-micro);color:var(--ink-2);
  padding:6px 9px;border-radius:var(--r);background:var(--s10);margin-top:6px;
}
.bidpanel .c-actnote[hidden]{display:none}
.bidpanel .c-actnote.bad{background:var(--signal-soft);color:var(--signal)}
.bidpanel .ladder{border-top:1px solid var(--line);padding-top:9px;display:flex;
  flex-direction:column;gap:5px}
.bidpanel .lad-h{font-size:var(--t-micro);color:var(--ink-3);font-weight:600}
.bidpanel .lad-step{display:flex;align-items:center;gap:8px;font-size:var(--t-micro)}
.bidpanel .lad-dot{
  width:8px;height:8px;border-radius:var(--r-pill);flex:none;
  box-shadow:inset 0 0 0 1px var(--line-strong);
}
.bidpanel .lad-step.done .lad-dot{background:var(--good);box-shadow:none}
.bidpanel .lad-step.ready .lad-dot{box-shadow:inset 0 0 0 2px var(--ink)}
.bidpanel .lad-step.locked{color:var(--ink-3)}
.bidpanel .lad-l{flex:1;min-width:0}
.bidpanel .lad-when{font-family:var(--mono);color:var(--ink-3)}
.bidpanel .lad-locked{color:var(--ink-3);font-size:10px}
.bidpanel .lad-warn{
  font-size:10px;line-height:15px;color:var(--signal);
  padding:5px 8px;border-radius:var(--r);background:var(--signal-soft);
}
/* ---- round 2: price-and-fit card ---- */

.bidpanel .c-head{align-items:flex-start}
.bidpanel .c-who{display:block;flex:1;min-width:0}
.bidpanel .c-name{font-size:var(--t-body);font-weight:600;line-height:var(--lh-body)}
.bidpanel .c-person{
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;unicode-bidi:plaintext;
}
/* Time to bid rides under the pills, not in the fact list. */
.bidpanel .c-ttb-row{
  flex-basis:100%;font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-3);
  margin-top:1px;
}
/* One icon shape for every hover-explained control on the card. */
.bidpanel .ico{
  width:24px;height:24px;flex:none;padding:0;
  display:inline-grid;place-items:center;border-radius:var(--r);
  border:1px solid transparent;background:transparent;color:var(--ink-3);
  cursor:pointer;transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.bidpanel .ico svg{width:15px;height:15px}
.bidpanel button.ico:hover{background:var(--s10);color:var(--ink);border-color:var(--line-strong)}
.bidpanel .ico.on{color:var(--ink)}
.bidpanel .ico.off{color:var(--s40);cursor:help}
.bidpanel span.ico{cursor:help}
/* Money block: the price is the first thing, the legs are footnotes to it. */
.bidpanel .c-money{display:flex;flex-direction:column;gap:5px}
.bidpanel .c-price{
  display:flex;align-items:baseline;gap:7px;flex-wrap:wrap;
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:23px;line-height:30px;font-weight:600;letter-spacing:-.01em;
}
.bidpanel .c-unit{font-family:var(--font);font-size:var(--t-micro);font-weight:400;color:var(--ink-3)}
.bidpanel .c-total{font-family:var(--mono);font-size:var(--t-micro);font-weight:400;color:var(--ink-3)}
.bidpanel .c-legs{display:flex;gap:6px;flex-wrap:wrap}
.bidpanel .leg{
  display:inline-flex;align-items:baseline;gap:5px;
  padding:2px 8px;border-radius:var(--r-pill);background:var(--s10);
  font-size:var(--t-micro);line-height:var(--lh-micro);
}
.bidpanel .leg-l{color:var(--ink-3)}
.bidpanel .leg-v{font-family:var(--mono);color:var(--ink)}
/* A supplier absorbing a cost the rentee asked about is a reason to pick them. */
.bidpanel .leg.free{background:var(--good-soft)}
.bidpanel .leg.free .leg-l,.bidpanel .leg.free .leg-v{color:var(--good)}
/* Fit. Colour carries the verdict; the label carries the fact. No sentences. */
.bidpanel .fit{
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  padding:9px 0;display:flex;flex-direction:column;gap:7px;
}
.bidpanel .fit-h{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.bidpanel .fit-verdict{
  padding:2px 9px;border-radius:var(--r-pill);
  font-size:var(--t-micro);line-height:var(--lh-micro);font-weight:600;
}
.bidpanel .fit-verdict.met{background:var(--good-soft);color:var(--good)}
.bidpanel .fit-verdict.miss{background:var(--signal-soft);color:var(--signal)}
.bidpanel .fit-verdict.check{background:var(--warn-soft);color:var(--warn)}
.bidpanel .fit-verdict.silent{background:var(--s10);color:var(--ink-2)}
.bidpanel .fit-verdict.none{background:var(--s10);color:var(--ink-3);font-weight:400}
.bidpanel .fit-split{
  padding:2px 8px;border-radius:var(--r-pill);cursor:help;
  box-shadow:inset 0 0 0 1px var(--warn);color:var(--warn);
  font-size:10px;line-height:15px;
}
.bidpanel .fit-rows{display:flex;gap:5px;flex-wrap:wrap}
.bidpanel .fit-row{
  display:inline-flex;align-items:baseline;gap:6px;cursor:help;
  padding:2px 9px;border-radius:var(--r-pill);
  font-size:var(--t-micro);line-height:var(--lh-micro);
  background:var(--s10);
}
.bidpanel .fit-k{color:var(--ink-3)}
.bidpanel .fit-v{font-family:var(--mono);color:var(--ink)}
.bidpanel .fit-ask{color:var(--ink-3)}
.bidpanel .fit-row.met{background:var(--good-soft)}
.bidpanel .fit-row.met .fit-k,.bidpanel .fit-row.met .fit-v{color:var(--good)}
.bidpanel .fit-row.miss{background:var(--signal-soft)}
.bidpanel .fit-row.miss .fit-k,.bidpanel .fit-row.miss .fit-v,
.bidpanel .fit-row.miss .fit-ask{color:var(--signal)}
.bidpanel .fit-row.check{background:var(--warn-soft)}
.bidpanel .fit-row.check .fit-k,.bidpanel .fit-row.check .fit-v,
.bidpanel .fit-row.check .fit-ask{color:var(--warn)}
.bidpanel .fit-row.silent{background:transparent;box-shadow:inset 0 0 0 1px var(--line)}
.bidpanel .fit-row.silent .fit-k,.bidpanel .fit-row.silent .fit-v{color:var(--ink-3)}
.bidpanel .fit-none{font-size:var(--t-micro)}
/* Volunteered, and nobody asked. Present, and visibly not part of the verdict. */
.bidpanel .fit-extras{display:flex;gap:5px;flex-wrap:wrap;padding-top:1px}
.bidpanel .fit-extra{
  font-size:10px;line-height:15px;color:var(--ink-3);cursor:help;
  padding:1px 7px;border-radius:var(--r-pill);background:var(--s5);
  box-shadow:inset 0 0 0 1px var(--line);
}
.bidpanel .fit-extra b{font-weight:600;color:var(--ink-2)}
/* Equipment: last, unlabelled, quiet. He probably did not pick it. */
.bidpanel .c-foot{justify-content:space-between;gap:10px}
.bidpanel .c-equip{
  font-size:var(--t-micro);color:var(--ink-3);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.bidpanel .c-icons{display:flex;align-items:center;gap:2px;flex:none}
.bidpanel .c-contact{
  border-top:1px solid var(--line);padding-top:9px;
  display:flex;flex-direction:column;gap:6px;align-items:flex-start;
}
.bidpanel .c-contact[hidden]{display:none}
.bidpanel .c-contact-h{font-size:var(--t-micro);color:var(--ink-3);font-weight:600}
/* ---- round 3: pills, icons, two fit groupings ---- */

/* The pill row: kind · state · speed · who. The contact control takes the same
   shape as the state pill and adds only the affordance the others do not need. */
.bidpanel .c-ttb{
  padding:2px 8px;border-radius:var(--r-pill);background:var(--s10);color:var(--ink-2);
  font-family:var(--mono);font-size:var(--t-micro);line-height:var(--lh-micro);
  white-space:nowrap;cursor:help;
}
.bidpanel .c-contact-btn{
  display:inline-flex;align-items:center;gap:5px;
  padding:2px 9px 2px 7px;border-radius:var(--r-pill);
  background:var(--s10);color:var(--ink-2);
  border:1px dashed var(--line-strong);
  font:inherit;font-size:var(--t-micro);line-height:var(--lh-micro);
  cursor:pointer;white-space:nowrap;
  transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out),
             border-color var(--t-fast) var(--out);
}
.bidpanel .c-contact-btn svg{width:12px;height:12px}
.bidpanel .c-contact-btn:hover{background:var(--s20);color:var(--ink);
  border-color:var(--ink);border-style:solid}
/* A leg priced at zero still prints 0 — the number is the fact. Colour carries
   that it is a good number, not a word standing in for it. */
.bidpanel .leg.free .leg-v{font-weight:600}
/* The grouping switcher. */
.bidpanel .p-seg{display:inline-flex;border:1px solid var(--line-strong);border-radius:var(--r);
  overflow:hidden}
.bidpanel .p-seg button{
  border:0;background:transparent;color:var(--ink-2);
  font:inherit;font-size:var(--t-micro);padding:4px 10px;cursor:pointer;white-space:nowrap;
}
.bidpanel .p-seg button + button{border-inline-start:1px solid var(--line)}
.bidpanel .p-seg button:hover{background:var(--s10)}
.bidpanel .p-seg button[aria-pressed="true"]{background:var(--ink);color:var(--s0)}
/* Chips are glyph + value now. The label lives in the icon and the tooltip,
   so the row stops being a wall of words. */
.bidpanel .fit-i{width:13px;height:13px;flex:none;opacity:.85}
.bidpanel .fit-row{gap:5px;padding:2px 9px 2px 7px}
.bidpanel .fit-row .fit-v{display:inline-flex;align-items:baseline;gap:3px}
/* Variant B — by the brief's own sections. */
.bidpanel .fit-secs{display:flex;flex-direction:column;gap:7px}
.bidpanel .fit-sec{display:flex;flex-direction:column;gap:4px}
.bidpanel .fit-sec-h{
  display:flex;align-items:center;gap:5px;
  font-size:10px;line-height:15px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--ink-3);
}
.bidpanel .fit-sec-i{width:13px;height:13px;flex:none;opacity:.8}
/* ---- round 4: unverified ---- */

/* Answered from a listing the supplier did not choose. Dashed, because the value
   is real but the evidence is not. */
.bidpanel .fit-row.unsure{
  background:transparent;
  box-shadow:inset 0 0 0 1px var(--line-strong);
  border:1px dashed transparent;
}
.bidpanel .fit-row.unsure .fit-v{color:var(--ink-2)}
.bidpanel .fit-row.unsure .fit-ask{color:var(--ink-3)}
.bidpanel .fit-row.unsure .fit-i{opacity:.55}
/* Qualifies the verdict rather than replacing it. */
.bidpanel .fit-qual{
  padding:2px 8px;border-radius:var(--r-pill);cursor:help;
  box-shadow:inset 0 0 0 1px var(--line-strong);color:var(--ink-3);
  font-size:10px;line-height:15px;white-space:nowrap;
}
/* ---- round 5: notes, and the summary line's removal ---- */

/* Collapsed, but the text is on screen. A heading alone would make a rep open
   every card to learn whether there is anything in it. */
.bidpanel .c-notes{
  border-top:1px solid var(--line);padding-top:8px;
  font-size:var(--t-micro);line-height:var(--lh-micro);
}
.bidpanel .c-notes summary{
  display:flex;align-items:baseline;gap:7px;cursor:pointer;list-style:none;
  color:var(--ink-3);
}
.bidpanel .c-notes summary::-webkit-details-marker{display:none}
.bidpanel .c-notes summary::after{
  content:"";flex:none;width:6px;height:6px;margin-inline-start:auto;
  border-inline-end:1.4px solid currentColor;border-block-end:1.4px solid currentColor;
  transform:rotate(45deg) translateY(-2px);
  transition:transform var(--t-fast) var(--out);
}
.bidpanel .c-notes[open] summary::after{transform:rotate(-135deg) translateY(-1px)}
.bidpanel .c-notes-h{flex:none;font-weight:600;color:var(--ink-3)}
.bidpanel .c-notes-peek{
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--ink-2);unicode-bidi:plaintext;
}
.bidpanel .c-notes[open] .c-notes-peek{visibility:hidden}
.bidpanel .c-notes-full{
  margin-top:6px;padding:7px 9px;border-radius:var(--r);background:var(--s10);
  color:var(--ink-2);unicode-bidi:plaintext;
}
/* The verdict line is gone; only the disagreement marker can appear here. */
.bidpanel .fit-h:empty{display:none}
/* ---- round 6: border identity, quadrant, verify strip, CTA, paging ---- */

.bidpanel .sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0;
}
/* Where the offer came in, carried by the card edge instead of a pill. App is
   the norm and stays neutral; the form bid is the exception and is marked. */
.bidpanel .card{border-inline-start:3px solid var(--line)}
.bidpanel .card.is-app{border-inline-start-color:var(--line)}
.bidpanel .card.form{border-inline-start-color:#7c3aed}
@media (prefers-color-scheme:dark){ .bidpanel .card.form{border-inline-start-color:#a78bfa} }
/* The head becomes a three-part row: who, the call to action, then the pills. */
.bidpanel .c-head{flex-wrap:wrap}
.bidpanel .c-cta{
  margin-inline-start:auto;flex:none;
  display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end;
}
.bidpanel .c-cta.done{font-size:var(--t-micro);color:var(--ink-3)}
.bidpanel .c-cta-state{
  padding:3px 11px;border-radius:var(--r);cursor:help;
  font-size:var(--t-micro);line-height:var(--lh-micro);font-weight:600;
}
.bidpanel .c-cta-state.ok{background:var(--good-soft);color:var(--good)}
.bidpanel .c-cta-state.no{background:var(--s20);color:var(--ink-2)}
/* Accepted because a timer ran out, not because a person said so. */
.bidpanel .c-cta-state.auto{box-shadow:inset 0 0 0 1px var(--good)}
.bidpanel .c-cta .c-reject-box{flex-basis:100%;order:9}
.bidpanel .c-tags{flex-basis:100%;order:10}
/* The quadrant: two sections per line. */
.bidpanel .fit-quad{
  display:grid;grid-template-columns:1fr 1fr;gap:8px 12px;
}
.bidpanel .fit-quad .fit-sec{min-width:0}
.bidpanel .fit-offered{margin-top:7px}
/* Equipment is not a quadrant cell — it is a strip, and what it wants is a
   check rather than a comparison. */
.bidpanel .fit-verify{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin-top:8px;padding:5px 9px;border-radius:var(--r);
  background:var(--s5);box-shadow:inset 0 0 0 1px var(--line);
}
.bidpanel .fit-verify-l{
  display:flex;align-items:center;gap:5px;flex:none;
  font-size:10px;line-height:15px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--ink-3);
}
.bidpanel .fit-verify .fit-rows{flex:1;min-width:0}
/* Paging and the note about what cannot be ranked. */
.bidpanel .p-tailnote{
  padding:0 18px 10px;font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
}
.bidpanel .p-more{padding:0 18px 16px;display:flex}
.bidpanel .p-more-btn{
  flex:1;display:flex;align-items:center;justify-content:center;gap:8px;
  padding:9px;border-radius:var(--r);
  border:1px solid var(--line-strong);background:transparent;color:var(--ink);
  font:inherit;font-size:var(--t-micro);cursor:pointer;
  transition:background var(--t-fast) var(--out);
}
.bidpanel .p-more-btn:hover{background:var(--s10)}
.bidpanel .p-more-n{font-family:var(--mono);color:var(--ink-3)}
@media (max-width:520px){
  .bidpanel .fit-quad{grid-template-columns:1fr}
}

/* U67: an unanswered brief must not look like a clean one. */
.bidpanel .fit-none{
  font-size:var(--t-micro);color:var(--warn);
  background:var(--warn-soft);border-radius:var(--r-sm);
  padding:7px 9px;line-height:var(--lh-micro);
}

/* ---- panel chips, renamed out of the queue's way -------------------------
   The ported markup used class="chip tick" and class="chip doc". In THIS
   stylesheet .chip is the queue's filter pill and .tick is the circular trophy
   button, so thirteen confirmations rendered as thirteen 30px circles with
   their labels clipped to two characters and overlapping each other. The
   prototype's .chip meant something else entirely in its own scope.

   Renamed rather than over-ridden: a rule that wins by specificity is one
   stylesheet edit away from losing again. */
.bidpanel .c-cf{
  display:inline-flex;align-items:center;gap:4px;
  font-size:var(--t-micro);line-height:1.3;
  padding:2px 7px;border-radius:999px;
  background:var(--good-soft);color:var(--good);
  white-space:nowrap;max-width:100%;
}
.bidpanel .c-cf::before{content:'\2713';font-size:10px;opacity:.8}
/* The confirmations are a LIST, not a row — thirteen of them on a fixed-width
   card must wrap rather than run off the edge. */
.bidpanel .c-confirms{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}

.bidpanel .c-doc{
  display:inline-flex;align-items:center;gap:5px;
  font-size:var(--t-micro);padding:3px 8px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--panel);color:var(--ink-2);
  text-decoration:none;white-space:nowrap;
}
.bidpanel .c-doc:hover{border-color:var(--line-strong);color:var(--ink)}
.bidpanel .c-doc.dead{opacity:.55;cursor:not-allowed}

/* Releasing an OS account you hold. Quiet — it sits beside your own name and is
   the rarer of the two actions. */
.osrelease{border:0;background:none;cursor:pointer;color:var(--ink-3);
  font-size:14px;line-height:1;padding:0 4px;border-radius:var(--r-sm)}
.osrelease:hover{color:var(--signal);background:var(--signal-soft)}

/* The deal's monthly value, which is the number the whole drawer is about. */
.deal-total{display:flex;align-items:baseline;gap:8px;padding:12px}
.deal-total b{font-size:var(--t-lg,22px);font-weight:600;font-variant-numeric:tabular-nums}
.deal-total span{font-size:var(--t-micro);color:var(--ink-3)}

/* ---- the title as a search bar ------------------------------------------
   It was a caret button, and the only search behind it was a menu row reading
   "Search" with a keyboard hint — discoverable by nobody. Shaped like what it
   does. */
.ttl-search{
  display:inline-flex;align-items:center;gap:7px;
  padding:5px 12px 5px 10px;border-radius:999px;
  border:1px solid var(--line);background:var(--s5);
  transition:border-color .12s, background .12s;
}
.ttl-search:hover{border-color:var(--line-strong);background:var(--panel)}
.ttl-search[aria-expanded="true"]{border-color:var(--ink);background:var(--panel)}
.ttl-mag{width:14px;height:14px;flex:none;color:var(--ink-3)}

/* The menu's own search field, in place of the button that used to sit here. */
.navq{display:flex;align-items:center;gap:8px;padding:10px 12px;
  border-bottom:1px solid var(--line)}
.navq > svg{width:15px;height:15px;flex:none;color:var(--ink-3)}
.navq input{flex:1;min-width:0;border:0;background:none;outline:none;
  font:inherit;font-size:var(--t-body);color:var(--ink)}
.navq input::-webkit-search-cancel-button{cursor:pointer}
/* WIDTH AND MARGIN TOO, not just the paint.
   `.rail-find` is a FULL-WIDTH BAR from the old rail — width:calc(100% - 16px)
   with 8px side margins — and the nav menu reuses the class for a small badge
   at the end of the search row. This rule reset the border, the background and
   the padding and left the geometry behind, so inside a 250px menu the button
   claimed the entire row: the input (flex:1, min-width:0) collapsed to nothing,
   its placeholder vanished, and the button's own margins pushed the menu into a
   horizontal scrollbar. Pressing Ctrl K showed a search you could not type in.

   Same shape as .pane, .tier and .app before it, with one difference that
   matters: those were two classes on one element, which tools/check-class-collisions.js
   now catches. This is ONE class doing two jobs in two places, which it does
   not — a scoped override that resets some properties and not others is
   invisible to a checker that only reads class attributes. */
.navq .rail-find{
  border:0;background:none;padding:0;cursor:pointer;flex:none;
  width:auto;margin:0;
}

.navres{overflow-y:auto;max-height:52vh}
.navres[hidden]{display:none}
.navmenu .nav[hidden]{display:none}
/* Kept inside the window by navFit(), which measures after render — a centred
   menu under a centred title otherwise runs off whichever edge is nearer. */
.navmenu{overflow-y:auto}

/* The row a search landed on. Temporary, and NOT the selected state: selected
   means "the dock is showing this", this means "here is what you asked for". */
@keyframes qs-fade{from{background:var(--good-soft)}to{background:transparent}}
.q tbody tr.qs-hit{animation:qs-fade 2.6s ease-out}
.q tbody tr.qs-hit td:first-child{box-shadow:inset 3px 0 0 var(--good)}

/* The role, on the row. P2 — Abdulsalam wants to see at a glance whether a lead
   is a rentee or a supplier without opening them, because the call is different.
   Same glyph as the drawer's identity strip, sized down to sit inside a name. */
.lead-name .idbit-ico{margin-inline-start:6px;vertical-align:middle}
.lead-name .idbit-ico svg{width:13px;height:13px;color:var(--ink-3)}


/* ======================= the request drawer, rebuilt =======================
   docs/proto/sales-request-drawer-uat.html. Row ids in the comments.
   ========================================================================= */

/* R1 · the money and the window, where the bid card puts price. */
.hero{
  padding:2px 16px 12px;display:flex;flex-direction:column;gap:5px;
  border-bottom:1px solid var(--line);
}
.hero-money{
  display:flex;align-items:baseline;gap:7px;
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:23px;line-height:30px;font-weight:600;letter-spacing:-.01em;
}
.hero-cap{font-family:var(--font);font-size:var(--t-micro);font-weight:400;color:var(--ink-3)}
.hero-none{font-family:var(--font);font-size:var(--t-body);font-weight:400;color:var(--ink-3)}
.hero-when{display:flex;gap:8px;flex-wrap:wrap}
.hw{
  display:inline-flex;align-items:center;gap:5px;
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-2);
}
.hw-i{width:12px;height:12px;color:var(--ink-3);flex:none}

/* R21 · one worded action, five icons, and no overflow menu. */
.rq-acts{align-items:center;gap:8px;flex-wrap:nowrap}
.act-cta{
  flex:0 1 auto;background:var(--ink);border-color:var(--ink);color:var(--s0);
  font-size:var(--t-body);font-weight:550;padding:9px 16px;gap:7px;
}
.act-cta:hover{opacity:.9;background:var(--ink)}
.act-cta svg{width:15px;height:15px}
/* R22 · already marked: the control states the fact rather than repeating the
   offer, so the black treatment belongs to the unmarked state. */
.act-cta[data-on]{background:var(--warn-soft);border-color:var(--warn);color:var(--warn)}
.act-cta[data-on] svg{fill:currentColor}

.act-icons{display:flex;align-items:center;gap:2px;margin-inline-start:auto;flex:none}
.iact{
  width:32px;height:32px;flex:none;padding:0;position:relative;
  display:inline-grid;place-items:center;border-radius:var(--r);
  border:1px solid transparent;background:transparent;color:var(--ink-2);cursor:pointer;
  transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out),
             border-color var(--t-fast) var(--out);
}
.iact svg{width:16px;height:16px;stroke-width:1.7}
button.iact:hover{background:var(--s10);color:var(--ink);border-color:var(--line-strong)}
.iact.off{color:var(--s40);cursor:help}
.iact.nowire{color:var(--s40)}
.iact.nowire:hover{color:var(--ink-3)}
/* R23 · the dot says "no endpoint behind this" in the corner; the explanation
   is in the accessible name, not only on hover. */
.iact .nw{
  position:absolute;inset-block-start:4px;inset-inline-end:4px;
  width:5px;height:5px;border-radius:var(--r-pill);background:var(--s40);
}

/* R35/R36/R37 · native details, so keyboard operation and the expanded state
   are announced without reimplementing either. */
.fold{border-top:1px solid var(--line)}
.fold summary{
  display:flex;align-items:baseline;gap:10px;cursor:pointer;list-style:none;padding:11px 16px;
}
.fold summary::-webkit-details-marker{display:none}
.fold summary::after{
  content:"";flex:none;width:6px;height:6px;margin-inline-start:auto;align-self:center;
  border-inline-end:1.5px solid var(--ink-3);border-block-end:1.5px solid var(--ink-3);
  transform:rotate(45deg) translateY(-2px);
  transition:transform var(--t-fast) var(--out);
}
.fold[open] summary::after{transform:rotate(-135deg) translateY(-1px)}
.fold summary:hover{background:var(--s5)}
.fold-h{flex:none;display:flex;align-items:center;gap:6px;font-size:var(--t-body);font-weight:600}
/* R36 · the summary IS the point of the fold: it names what a rep would have
   opened it for, so a closed section is still an answer. */
.fold-sum{
  flex:1;min-width:0;font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;unicode-bidi:plaintext;
}
.fold[open] .fold-sum{visibility:hidden}
.fold-more{
  margin-inline-start:6px;padding:1px 6px;border-radius:var(--r-pill);
  background:var(--s10);color:var(--ink-3);font-family:var(--mono);font-size:10px;
}
.fold-body{padding:0 16px 12px}
.fold-body .quad{border-top:0;padding:0}
.fold-body .eq-line:first-child{padding-top:0}
.sec-i{width:14px;height:14px;flex:none;opacity:.75}

/* R3/R25 · the brief in the bid card's sections, two to a line, each a box.
   Two chips loose on a page do not read as a group; the same two inside a frame
   do, and the eye can then skip a whole box. */
.quad{
  border-top:1px solid var(--line);padding:12px 16px;
  display:grid;grid-template-columns:1fr 1fr;gap:8px;
}
.qsec{
  min-width:0;display:flex;flex-direction:column;gap:6px;
  border:1px solid var(--line);border-radius:var(--r);padding:8px 9px 9px;background:var(--s5);
}
.qsec-h{
  display:flex;align-items:center;gap:5px;
  font-size:10px;line-height:15px;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3);
}
.qrows{display:flex;gap:4px;flex-wrap:wrap}
/* R4 · a chip says itself in two words and carries NO icon. A glyph on every
   value turned each box into pictograms a rep had to decode; only the section
   heading carries one. */
.qv{
  display:inline-flex;align-items:center;gap:0;cursor:help;
  padding:2px 8px;border-radius:var(--r-pill);background:var(--s10);
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink);
  max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;
}
.qsec .qv{background:var(--panel);box-shadow:inset 0 0 0 1px var(--line)}
.qsec .cert{margin-top:1px}
/* R32 · the site name is the one value that may run long, because it is a
   proper noun with no shorthand to normalise into. */
.qv.wide{white-space:normal;max-width:100%}
/* Typed by the rentee rather than authored here, so it clips rather than
   pretending to fit the two-word rule. */
.qv.raw{max-width:190px}
.qv.wide.raw{max-width:100%}
.eq-rows{margin-top:7px}

/* The "Not specified" block's rules went with the block. .gaps, .gap-more,
   .gap-rest and .qv.gap had exactly one consumer each and no other surface
   reaches for them — leaving them would be styling for markup nothing emits. */

/* R18 · the footer: what the request is, how long it has been, where it came
   from, who holds it. */
.rq-foot{
  border-top:1px solid var(--line);padding:10px 16px;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
}
.age-state{display:inline-flex;align-items:baseline;gap:5px;padding:2px 9px;cursor:help}
.as-age{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:600}
.as-dot{opacity:.45}
.as-state{font-weight:550}
/* R16 · colour is the FAMILY, the word is the state, and the stored value is on
   hover. An unmapped status is outlined rather than coloured, so a product
   status nobody has mapped yet cannot pass as one of the four. */
.req-status[data-fam]{font-weight:550;cursor:help}
.req-status[data-fam="live"]{background:var(--s10);color:var(--ink-2)}
.req-status[data-fam="talking"]{background:var(--warn-soft);color:var(--warn)}
.req-status[data-fam="won"]{background:var(--good-soft);color:var(--good)}
.req-status[data-fam="closed"]{background:var(--s20);color:var(--ink-3)}
.req-status[data-fam="unknown"]{
  background:transparent;color:var(--warn);box-shadow:inset 0 0 0 1px var(--warn);
}
.ft-ico{display:inline-grid;place-items:center;width:18px;height:18px;color:var(--ink-3);cursor:help}
.ft-i{width:15px;height:15px}
/* R33 · an unrecorded origin keeps its slot, so the footer never shifts
   between one request and the next. */
.ft-ico.none{width:12px;height:12px;border-radius:3px;box-shadow:inset 0 0 0 1px var(--line)}
.ft-date{margin-inline-start:auto;font-family:var(--mono);cursor:help}
.rq-flags{padding:10px 16px 0}

/* R14 · one column below the fold width, so an Arabic brief and a long site
   name have somewhere to go rather than squeezing the chips to nothing. */
@media (max-width:520px){ .quad{grid-template-columns:1fr} }

/* R14 · An Arabic company name is 58 characters here and it must not wrap the
   header into three lines and push the hero off the screen. plaintext-bidi so
   a name that starts Latin and continues Arabic reads in its own direction
   rather than the paragraph's, and one line with an ellipsis rather than a
   wrap — the full name is on the element's own title. */
.dock-title{unicode-bidi:plaintext;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dock-sub{unicode-bidi:plaintext;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* U54 · the shared-link pill. Quiet: it marks which door an offer came
   through, which matters, but it is not the thing a rep is reading the card
   for. An app bid carries nothing here — absence is the label. */
.bidpanel .c-kind{
  padding:1px 7px;border-radius:var(--r-pill);
  background:var(--s10);color:var(--ink-3);
  font-size:10px;line-height:15px;font-weight:550;white-space:nowrap;cursor:help;
}


/* ===================== the outreach worklist ==============================
   docs/proto/sales-outreach-worklist-uat.html. Row ids in the comments.

   SCOPED UNDER .wl, the same way the bids panel is scoped under .bidpanel.
   Not because everything here collides today -- only .c-name and .c-msg do,
   and both of those are already .bidpanel-scoped -- but because the card
   vocabulary of the two surfaces is deliberately similar and an unscoped
   .c-top would eventually reach the wrong card.
   ========================================================================= */

.wl{display:flex;flex-direction:column;min-height:0}

/* G35 · ONE ROW, segments divided by a rule, filling the width beside the
   title. It replaced four stacked rows in a box pinned right, with the left
   half of the header empty. */
.wl .wl-head{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:12px 16px;border-bottom:1px solid var(--line);
}
.wl .wl-title{font-size:var(--t-mid);line-height:var(--lh-mid);font-weight:600;flex:none}
.wl .reqcard{
  flex:1;min-width:0;display:flex;align-items:center;gap:0;
  border:1px solid var(--line);border-radius:var(--r);background:var(--panel);
  padding:0;overflow:hidden;cursor:pointer;text-align:start;
  transition:border-color var(--t-fast) var(--out),background var(--t-fast) var(--out);
}
.wl .reqcard:hover{border-color:var(--line-strong);background:var(--s5)}
.wl .rc-seg{
  padding:8px 11px;font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-2);
  border-inline-end:1px solid var(--line);white-space:nowrap;unicode-bidi:plaintext;
  display:flex;align-items:center;gap:6px;
}
/* Only the equipment segment truncates: it is the one that can run long, and
   everything else is short by nature. */
.wl .rc-eq{
  flex:1;min-width:0;color:var(--ink);font-weight:550;
  overflow:hidden;text-overflow:ellipsis;display:block;
}
.wl .rc-star{color:var(--warn)}
.wl .rc-q{font-family:var(--mono);color:var(--ink-3);margin-inline-start:5px}
.wl .rc-when{font-family:var(--mono);font-variant-numeric:tabular-nums}
.wl .rc-brief{gap:4px}
/* What the cards are judged against, read once (G41). */
.wl .rq{
  padding:1px 6px;border-radius:var(--r-pill);background:var(--s10);
  font-size:10px;line-height:15px;font-weight:600;color:var(--ink-2);
}
.wl .rq.spsp{background:var(--warn-soft);color:var(--warn)}
/* G51 · A CERTIFICATE BELONGS TO A MACHINE OR TO A PERSON, and the row used to
   print both in one undifferentiated run -- so a rep reading "SPSP  SASO
   Technical" could not tell which of the two the supplier's yard has to satisfy
   and which the driver has to carry in his pocket. Two labelled clusters, and
   the label is the only thing carrying colour: the chips stay neutral so the
   segment does not start competing with the status for attention (Awab, 10 Sep
   2026 -- "option 2, caption only"). */
.wl .rqg{display:inline-flex;flex-direction:column;align-items:flex-start;gap:1px;line-height:1}
.wl .rqg-chips{display:flex;gap:3px}
/* 10px, not 9. Below the chip it sits under is drift, not hierarchy -- the
   caption is separated by WEIGHT, TRACKING and HUE instead. */
.wl .rqg-cap{
  font-size:10px;line-height:12px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;padding-inline-start:6px;
}
/* The two hues. DECLARED AND READ IN THE SAME SCOPE, which is the whole
   difference between this and the --warn bug directly above: a variable is
   safe to keep local when nothing outside .wl can reference it. Blue is not in
   the sales palette on purpose -- it names one distinction on one segment and
   does not belong beside the colours every screen shares. --good already has
   both modes, so only the blue needs a dark value. */
.wl{--eq-side:#3a5f96}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .wl{--eq-side:#8fa8d1}}
:root[data-theme="dark"] .wl{--eq-side:#8fa8d1}
.wl .rqg[data-t="eq"] .rqg-cap{color:var(--eq-side)}
.wl .rqg[data-t="op"] .rqg-cap{color:var(--good)}
.wl .rc-st{font-weight:550}
.wl .rc-st[data-fam="live"]{color:var(--ink-2)}
.wl .rc-st[data-fam="talking"]{color:var(--warn)}
.wl .rc-st[data-fam="won"]{color:var(--good)}
.wl .rc-st[data-fam="closed"],.wl .rc-st[data-fam="unknown"]{color:var(--ink-3)}
.wl .rc-go{padding:0 10px;color:var(--ink-3);border-inline-end:0}
.wl .rc-secs{display:flex;gap:2px;flex:none}
/* G44 · three icons, and a dot means the customer answered something in there.
   Dimmed means the section is blank, which is itself worth seeing before a
   call. */
.wl .rc-ico{
  position:relative;width:32px;height:32px;display:inline-grid;place-items:center;
  border:1px solid var(--line);border-radius:var(--r);background:var(--panel);
  color:var(--ink-2);cursor:pointer;
}
.wl .rc-ico:hover{background:var(--s10);border-color:var(--line-strong);color:var(--ink)}
.wl .rc-ico.empty{color:var(--s40)}
.wl .rc-ii{width:15px;height:15px}
.wl .rc-idot{
  position:absolute;inset-block-start:4px;inset-inline-end:4px;
  width:5px;height:5px;border-radius:var(--r-pill);background:var(--good);
}

/* G22 · the pill and the plus. No × — there is always exactly one. */
.wl .wl-picks{position:relative;display:flex;gap:6px;align-items:center;padding:10px 16px}
.wl .wl-pick{
  padding:5px 11px;border-radius:var(--r-pill);border:1px solid var(--line);
  background:var(--panel);font-size:var(--t-micro);line-height:var(--lh-micro);
  color:var(--ink);cursor:pointer;display:inline-flex;align-items:center;gap:5px;
}
.wl .wl-pick.cur{background:var(--ink);border-color:var(--ink);color:var(--s0)}
.wl .wl-pick.cur .rc-star{color:var(--s0)}
.wl .wl-pick.add{color:var(--ink-3)}
.wl .wl-pick:hover{border-color:var(--line-strong)}
.wl .wl-pop{
  position:absolute;inset-block-start:100%;inset-inline-start:16px;z-index:6;
  min-width:320px;max-height:380px;overflow:auto;
  background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r);
  box-shadow:0 10px 30px rgba(20,23,27,.16);padding:5px;
}
.wl .pp-h{
  padding:7px 10px 5px;font-size:10px;line-height:15px;text-transform:uppercase;
  letter-spacing:.05em;color:var(--ink-3);
}
.wl .pp-s{
  padding:7px 10px 3px;font-size:10px;line-height:15px;text-transform:uppercase;
  letter-spacing:.05em;color:var(--ink-3);border-top:1px solid var(--line);margin-top:4px;
}
.wl .pp-r{
  display:flex;width:100%;padding:7px 10px;border-radius:4px;background:none;border:0;
  text-align:start;cursor:pointer;
}
.wl .pp-r:hover{background:var(--s10)}
.wl .pp-r.on{background:var(--s20)}
.wl .pp-b{display:flex;flex-direction:column;gap:2px;min-width:0}
.wl .pp-t{font-size:var(--t-body);font-weight:550;color:var(--ink);unicode-bidi:plaintext}
.wl .pp-m{font-size:var(--t-micro);color:var(--ink-3);unicode-bidi:plaintext}
.wl .pp-none{padding:12px;font-size:var(--t-micro);color:var(--ink-3)}

.wl .wl-tabs{display:flex;gap:2px;padding:0 16px;border-bottom:1px solid var(--line)}
.wl .wl-tab{
  padding:9px 14px;background:none;border:0;border-bottom:2px solid transparent;
  font-size:var(--t-body);font-weight:550;color:var(--ink-3);cursor:pointer;
  display:inline-flex;align-items:center;gap:7px;
}
.wl .wl-tab:hover{color:var(--ink-2)}
.wl .wl-tab.on{color:var(--ink);border-bottom-color:var(--ink)}
/* G36 · narrow on purpose. The first two tabs are work; this one is a
   reference, and the width says so before the label does. */
.wl .wl-tab.slim{
  flex:none;padding:9px 10px;font-size:var(--t-micro);
  border-inline-start:1px solid var(--line);margin-inline-start:6px;
}
.wl .tn{
  font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:var(--t-micro);
  color:var(--ink-3);
}
.wl .wl-tab.on .tn{color:var(--ink-2)}

.wl .wl-band{border-bottom:1px solid var(--line)}
/* CENTRED, because these two are a CHOICE rather than a list. Left-aligned
   behind a caret they read as the start of a paragraph; centred, the name and
   the count are the whole row and the two bands line up as a pair a rep picks
   between. The caret keeps its own place at the start so the control still
   looks like something that opens. */
.wl .band-h{
  display:flex;width:100%;align-items:baseline;gap:9px;padding:12px 16px;
  background:none;border:0;text-align:center;cursor:pointer;
}
.wl .band-h .band-t{margin-inline-start:auto}
.wl .band-h .band-n{margin-inline-end:auto}
.wl .band-h:hover{background:var(--s5)}
.wl .band-caret{color:var(--ink-3);width:10px;flex:none}
.wl .band-t{font-size:var(--t-body);font-weight:600;flex:none}
.wl .band-n{
  font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:var(--t-micro);
  color:var(--ink-3);flex:none;
}
.wl .band-why{
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.wl .band-none{padding:0 16px 12px;font-size:var(--t-micro);color:var(--ink-3)}
.wl .wl-note,.wl .wl-own{
  padding:9px 16px;font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
  border-bottom:1px solid var(--line);background:var(--s5);
}
.wl .wl-empty{
  display:flex;flex-direction:column;gap:5px;padding:28px 16px;text-align:center;
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
}
.wl .wl-empty b{font-size:var(--t-body);color:var(--ink)}
.wl .wl-nav{
  padding:9px 16px;background:var(--warn-soft);color:var(--warn);
  font-size:var(--t-micro);line-height:var(--lh-micro);
}
.wl .wl-expand{
  display:flex;align-items:center;gap:8px;width:100%;padding:10px 16px;
  background:none;border:0;border-bottom:1px solid var(--line);
  font-size:var(--t-micro);color:var(--ink-3);cursor:pointer;text-align:start;
}
.wl .wl-expand:hover{background:var(--s5);color:var(--ink)}
.wl .ex-box{
  width:14px;height:14px;flex:none;display:grid;place-items:center;
  border:1px solid var(--line-strong);border-radius:3px;font-size:10px;color:var(--ink);
}
.wl .wl-expand.on .ex-box{background:var(--ink);color:var(--s0);border-color:var(--ink)}
.wl .ex-n{margin-inline-start:auto;font-family:var(--mono);color:var(--ink-3)}

/* G44 · the modal, three tabs, switchable without closing. */
.wl .wl-modal{
  position:fixed;inset:0;z-index:120;background:rgba(20,23,27,.34);
  display:grid;place-items:center;padding:20px;
}
.wl .m-card{
  width:min(440px,100%);max-height:80vh;overflow:auto;background:var(--panel);
  border-radius:var(--r-lg,10px);box-shadow:0 20px 50px rgba(20,23,27,.28);
}
.wl .m-h{
  display:flex;align-items:center;gap:8px;padding:14px 16px;
  border-bottom:1px solid var(--line);font-size:var(--t-body);font-weight:600;
}
.wl .m-x{
  margin-inline-start:auto;width:28px;height:28px;display:grid;place-items:center;
  border:0;background:none;border-radius:var(--r);color:var(--ink-3);cursor:pointer;font-size:18px;
}
.wl .m-x:hover{background:var(--s10);color:var(--ink)}
.wl .m-tabs{display:flex;gap:2px;padding:0 16px;border-bottom:1px solid var(--line)}
.wl .m-tab{
  padding:8px 11px;background:none;border:0;border-bottom:2px solid transparent;
  font-size:var(--t-micro);color:var(--ink-3);cursor:pointer;
}
.wl .m-tab.on{color:var(--ink);border-bottom-color:var(--ink)}
.wl .m-b{padding:6px 16px 12px}
.wl .m-row{display:flex;gap:12px;align-items:baseline;padding:6px 0}
.wl .m-k{width:170px;flex:none;font-size:var(--t-micro);color:var(--ink-3)}
.wl .m-v{flex:1;min-width:0;font-size:var(--t-body);unicode-bidi:plaintext}
/* "They did not say" is a thing a rep needs to know before promising it, so an
   unanswered field is present and quiet rather than absent. */
.wl .m-row.unset .m-v{color:var(--s40);font-style:italic}
.wl .m-f{
  padding:11px 16px;border-top:1px solid var(--line);background:var(--s5);
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
}

.wl .wl-card{padding:11px 16px 13px;border-top:1px solid var(--line)}
.wl .wl-card.blocked{background:var(--s5)}
.wl .c-top{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
/* A BUTTON NOW, because the name opens the supplier's account. Styled to stay
   a name — a rep reads this list for who to call, and turning six names a card
   into six links would make the list look like navigation rather than work. It
   underlines on hover, which is where the affordance belongs. */
.wl .c-name{
  font-size:var(--t-body);font-weight:600;min-width:0;unicode-bidi:plaintext;
  display:inline-flex;align-items:center;gap:5px;
  appearance:none;border:0;background:none;padding:0;margin:0;
  font-family:inherit;color:var(--ink);text-align:start;cursor:pointer;
}
.wl .c-name:hover{text-decoration:underline;text-underline-offset:3px}
.wl .c-name:focus-visible{outline:2px solid var(--ink-3);outline-offset:2px;border-radius:4px}
.wl .c-name .ver{width:14px;height:14px;color:var(--good)}
.wl .c-city{font-size:var(--t-micro);color:var(--ink-3);unicode-bidi:plaintext}
.wl .c-act{
  display:inline-flex;align-items:center;gap:5px;padding:2px 8px;border-radius:var(--r-pill);
  border:1px solid var(--line);background:var(--panel);
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-2);cursor:pointer;
}
.wl .c-act:hover{border-color:var(--line-strong);color:var(--ink)}
.wl .c-n{font-family:var(--mono);font-variant-numeric:tabular-nums;color:var(--ink-3)}
.wl .c-act.none{cursor:default;color:var(--s40);border-style:dashed}
.wl .act .dots{letter-spacing:1px;font-size:9px}
.wl .act.hot .dots{color:var(--good)}
.wl .act.warm .dots{color:var(--warn)}
.wl .act.cold .dots{color:var(--ink-3)}
.wl .c-msg{
  margin-inline-start:auto;padding:5px 12px;border-radius:var(--r);
  background:var(--ink);border:1px solid var(--ink);color:var(--s0);
  font-size:var(--t-micro);font-weight:550;cursor:pointer;
}
.wl .c-msg:hover{opacity:.9}
/* G52 · Open chat is the SECOND button in a pair, so it is outlined rather than
   filled: two solid dark buttons side by side make a rep choose between two
   things that look equally final. It keeps .c-msg's `margin-inline-start:auto`,
   which is what holds the pair against the right edge. */
.wl .c-msg.chat{
  margin-inline-end:6px;background:transparent;
  border-color:var(--line-strong);color:var(--ink);
}
.wl .c-msg.chat:hover{border-color:var(--ink);background:var(--s10);opacity:1}

.wl .bdgs{display:flex;gap:5px;flex-wrap:wrap;margin-top:7px}
.wl .bdg{
  padding:1px 7px;border-radius:var(--r-pill);background:var(--s10);
  font-size:10px;line-height:15px;color:var(--ink-3);cursor:help;white-space:nowrap;
}
.wl .bdg.on{background:var(--good-soft);color:var(--good)}
.wl .bdg.has-app{background:var(--good-soft);color:var(--good);
  /* Belt and braces: this badge is inline no matter what a future bare rule
     called .has-app decides. The colour rule alone is what let .app's grid
     through last time. */
  display:inline-block;height:auto;overflow:visible}
.wl .bdg.gone,.wl .bdg.off{background:var(--s10);color:var(--ink-3)}
.wl .bdg.cold{background:var(--s20);color:var(--ink-3)}
/* G43 · three states, and the third is not a no. */
.wl .bdg.ara.yes{background:var(--good-soft);color:var(--good)}
.wl .bdg.ara.no{background:var(--s20);color:var(--ink-3)}
.wl .bdg.ara.unknown{background:transparent;color:var(--warn);box-shadow:inset 0 0 0 1px var(--warn)}

/* G45 · GREEN is the machine WE PICKED — a choice of ours, and the only thing
   on this card that could be the wrong unit. */
.wl .wl-kit{
  display:flex;align-items:center;gap:10px;width:100%;margin-top:9px;padding:8px 10px;
  border:1px solid var(--good);border-radius:var(--r);background:var(--good-soft);
  cursor:pointer;text-align:start;
}
.wl .wl-kit:hover{filter:brightness(.98)}
/* A near miss keeps the green and adds the amber edge: it is still the unit we
   picked, and the edge says it does not fit. */
.wl .wl-kit.near{border-color:var(--warn);box-shadow:inset 3px 0 0 var(--warn)}
.wl .wl-kit.crm{border-style:dashed}
.wl .kit-img{
  width:46px;height:34px;flex:none;border-radius:4px;background:var(--panel);
  display:grid;place-items:center;font-size:9px;color:var(--s40);
}
.wl .kit-img.none{border:1px dashed var(--line-strong)}
/* Once a photo lands the tile stops being a placeholder and becomes the frame
   for it. object-fit:cover so a portrait phone photo of a crane fills the box
   instead of letterboxing inside it. */
.wl .kit-img img{width:100%;height:100%;object-fit:cover;border-radius:4px;display:block}
.wl .kit-b{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.wl .kit-t{
  font-size:var(--t-body);font-weight:550;color:var(--ink);unicode-bidi:plaintext;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.wl .kit-m{display:flex;gap:8px;font-size:var(--t-micro);color:var(--ink-2);flex-wrap:wrap}
.wl .kit-m .dim{color:var(--ink-3)}
.wl .kit-m .num{font-family:var(--mono)}
.wl .kit-go{color:var(--ink-3);flex:none}

/* G45 · BLUE is WHERE the machine sits — a fact about them, not a choice of
   ours. Two colours on the card, one meaning each; everything else monochrome,
   which is what lets these two read in a crowded list. */
.wl .wl-yards{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:8px}
.wl .y-h{
  font-size:10px;line-height:15px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--ink-3);flex:none;
}
.wl .y{
  display:inline-flex;align-items:center;gap:5px;padding:1px 8px;border-radius:var(--r-pill);
  background:var(--info-soft,#e8effb);color:var(--info,#2f5bb7);
  font-size:10px;line-height:15px;unicode-bidi:plaintext;
}
.wl .y.near{font-weight:600}
.wl .y-km{font-family:var(--mono);opacity:.75}
.wl .y.none,.wl .y.more{background:var(--s10);color:var(--ink-3)}

.wl .wl-tags{display:flex;gap:5px;flex-wrap:wrap;margin-top:8px}
.wl .gtag{
  display:inline-flex;align-items:baseline;gap:5px;padding:2px 8px;
  border-radius:var(--r-pill);background:var(--s10);color:var(--ink-2);
  font-size:var(--t-micro);line-height:var(--lh-micro);cursor:help;
}
.wl .gtag.hard{background:var(--signal-soft);color:var(--signal)}
/* G18 · why it might be wrong, ON the tag. A rep who has to hover to learn
   that a TUV is usually obtained on site will not hover. */
.wl .gtag .soft-why{font-size:10px;opacity:.75}

.wl .wl-msg{margin-top:9px;border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.wl .msg-h{
  display:flex;align-items:baseline;gap:9px;padding:7px 10px;background:var(--s5);
  border-bottom:1px solid var(--line);font-size:var(--t-micro);font-weight:600;
}
.wl .msg-lang{margin-inline-start:auto;font-weight:400;color:var(--ink-3)}
.wl .msg-b{
  margin:0;padding:10px;font-family:var(--font);font-size:var(--t-micro);
  line-height:1.55;color:var(--ink-2);white-space:pre-wrap;unicode-bidi:plaintext;
}

/* G53 · THE TWO MESSAGE MODALS.

   The supplier draft reuses .msg-h / .msg-b above; it only moved out of the
   card and no longer needs the .wl-msg frame, which the modal's own card
   provides. Everything below is the customer message.

   A note is a SENTENCE about the send, not a field, so it sits outside the
   .m-row grid and carries its own colour: neutral for a fact, warn for "this
   would be the second one", bad for a refusal, good for what just happened. */
.wl .m-note{
  margin:8px 0 0;padding:8px 10px;border-radius:var(--r);
  font-size:var(--t-micro);line-height:1.5;color:var(--ink-2);background:var(--s5);
}
.wl .m-note.warn{background:var(--warn-bg,var(--s5));color:var(--warn)}
.wl .m-note.bad{background:var(--bad-bg,var(--s5));color:var(--bad)}
.wl .m-note.good{background:var(--good-bg,var(--s5));color:var(--good)}
.wl .m-send{
  display:flex;align-items:baseline;gap:7px;flex-wrap:wrap;
  margin-top:12px;padding-top:10px;border-top:1px solid var(--line);
  font-size:var(--t-micro);
}
.wl .m-copy{
  margin-top:10px;padding:6px 12px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--s5);color:var(--ink);font:inherit;font-size:var(--t-micro);cursor:pointer;
}
.wl .m-copy:hover{opacity:.9}
/* The card the draft is open for, so a rep who scrolled the list behind the
   modal can still see which one they pressed. */
.wl .c-msg.on{outline:1px solid var(--line);outline-offset:1px}

.wl .wl-og{display:inline-flex;color:var(--ink-3)}
.wl .wl-ogi{width:12px;height:12px}

@media (max-width:760px){
  /* Wraps rather than scrolls: a header that scrolls sideways hides the half a
     rep did not think to look for. */
  .wl .reqcard{flex-wrap:wrap}
  .wl .rc-seg{border-inline-end:0}
}

/* G33 · never bid is a STATE, not a dim level. Dashed so it reads as a fact
   about the relationship rather than as missing data. */
.wl .c-act.never{
  border-style:dashed;color:var(--ink-3);cursor:help;font-style:italic;
}
/* G46 · levelless on purpose. It answers whether a message will be seen, which
   is not the same question as whether they are working with us — dots here
   would invite reading the two as one scale. */
.wl .c-seen{
  font-size:10px;line-height:15px;color:var(--ink-3);cursor:help;
  font-family:var(--mono);
}

/* History carries three sources now, and two of them need a mark the product's
   own events do not. */
.tl-who{
  margin-inline-start:7px;font-size:10px;color:var(--ink-3);font-family:var(--mono);
}
/* A call the telephony system never saw is the rep's own record of it. Worth
   marking, not worth shouting about. */
.tl-off{
  margin-inline-start:6px;padding:0 5px;border-radius:var(--r-pill);
  background:var(--s10);color:var(--ink-3);font-size:9px;line-height:14px;cursor:help;
}
.mini-note{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);padding:6px 0}
.mini-note.bad{color:var(--signal)}

/* History carries two kinds now: what happened TO the customer, and what this
   desk DID about it. Marked rather than separated — two lists would make a rep
   interleave them by eye to answer the one question that matters, which is
   whether we reached out before or after the thing that happened. */
.tl-tag{
  display:inline-block;margin-inline-end:6px;padding:0 6px;border-radius:var(--r-pill);
  background:var(--s20);color:var(--ink-3);font-size:9px;line-height:14px;
  text-transform:uppercase;letter-spacing:.04em;vertical-align:1px;
}
/* Something a person here did, so it reads a shade louder than a milestone
   nobody chose. */
.tl-call .tl-what,.tl-sent .tl-what,.tl-memo .tl-what{color:var(--ink)}
.tl-sent .tl-tag{background:var(--good-soft);color:var(--good)}
.tl-note{
  margin-top:2px;font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;
  unicode-bidi:plaintext;cursor:help;
}
.tl-more{padding:6px 0;font-size:var(--t-micro);color:var(--ink-3)}
/* The rail's dot: hollow for a milestone (it happened, nobody here chose it),
   filled for an outreach row (somebody here did it). */
.tl-call::before,.tl-sent::before,.tl-memo::before{background:var(--ink-2)}

/* G49 · two cards to a row in Needs verification only. Grid so both share the
   taller one's height and the rule runs the full way down; the filler cell
   keeps an odd last card at half width rather than letting it stretch into a
   shape no other card in the band has. */
.wl .band-body.two{
  display:grid;grid-template-columns:1fr 1fr;
}
.wl .band-body.two > *{border-inline-end:1px solid var(--line)}
.wl .band-body.two > *:nth-child(2n){border-inline-end:0}
.wl .wl-filler{border-top:1px solid var(--line)}
@media (max-width:820px){ .wl .band-body.two{grid-template-columns:1fr} }

/* G50 · the count triages, the panel explains. */
.wl .wl-verify{
  display:inline-flex;align-items:center;gap:6px;margin-top:8px;
  padding:2px 9px;border-radius:var(--r-pill);
  border:1px solid var(--warn);background:transparent;color:var(--warn);
  font-size:var(--t-micro);line-height:var(--lh-micro);cursor:pointer;
}
.wl .wl-verify:hover,.wl .wl-verify.on{background:var(--warn-soft)}
.wl .v-q{font-weight:700}
.wl .v-n{font-family:var(--mono);font-variant-numeric:tabular-nums}
.wl .v-panel{
  margin-top:7px;padding:9px 11px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--s5);display:flex;flex-direction:column;gap:9px;
}
.wl .v-row{display:flex;flex-direction:column;gap:3px}
.wl .v-row b{font-size:var(--t-micro);color:var(--ink)}
.wl .v-row span{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3)}
.wl .v-cat{
  align-self:flex-start;margin-top:3px;display:inline-flex;align-items:center;gap:5px;
  padding:2px 9px;border-radius:var(--r-pill);border:1px solid var(--line-strong);
  background:var(--panel);font-size:var(--t-micro);color:var(--ink);cursor:pointer;
}
.wl .v-cat:hover{background:var(--s10)}

/* G48 · the only write on this surface, and the copy comes before the click. */
.wl .bdg.ara.set{border:0;cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.wl .ara-go{
  padding:0 5px;border-radius:var(--r-pill);background:var(--warn);color:var(--s0);
  font-size:9px;line-height:13px;text-transform:uppercase;letter-spacing:.04em;
}
.wl .ara-set{
  margin-top:8px;padding:10px 11px;border:1px solid var(--warn);border-radius:var(--r);
  background:var(--warn-soft);display:flex;flex-direction:column;gap:8px;
}
.wl .ara-say{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-2)}
.wl .ara-btns{display:flex;gap:6px;flex-wrap:wrap}
.wl .ara-yes,.wl .ara-no,.wl .ara-cancel{
  padding:5px 12px;border-radius:var(--r);font-size:var(--t-micro);font-weight:550;cursor:pointer;
  border:1px solid var(--line-strong);background:var(--panel);color:var(--ink);
}
.wl .ara-yes{background:var(--good);border-color:var(--good);color:var(--s0)}
.wl .ara-no{background:var(--ink);border-color:var(--ink);color:var(--s0)}
.wl .ara-cancel{color:var(--ink-3)}
.wl .ara-why{font-size:var(--t-micro);color:var(--signal)}
.wl .ara-why:empty{display:none}

/* Numbers align on their right edge, which is the only edge that means
   anything: 8 and 118 share a units column and the eye stops re-finding it on
   every row. Text columns are untouched — right-aligned words are unreadable. */
.q td[data-cell="real"],
.q td[data-cell="bids"],
.q td[data-cell="clock"]{text-align:end}

/* ============ the worklist, fixed against the first real look ============= */

/* THE GREEN BLOB. A card in the two-up band is a GRID ITEM, and a grid item
   stretches to its row's height by default — which is what G49 asks for, so the
   rule between the columns runs the full way down. The cost nobody sees until
   there is real data in it: whatever sits at the bottom of a block-level card
   absorbs that extra height. The badge row is a flex container, its children
   stretch to the line box, and "Has the app" rendered as a 350px green column.

   The card is a flex COLUMN now, so it still fills the row and its contents
   still pack to the top. Every block inside is flex:none, so none of them can
   volunteer to soak up the difference. */
.wl .wl-card{
  display:flex;flex-direction:column;align-items:stretch;min-width:0;
}
.wl .c-top,.wl .bdgs,.wl .wl-kit,.wl .wl-yards,.wl .wl-tags,
.wl .wl-verify,.wl .v-panel,.wl .wl-msg,.wl .ara-set{flex:none}
/* A wrapping row of pills is top-aligned, always. Stretch on a pill is never
   what anyone means. */
.wl .bdgs{align-items:flex-start;align-content:flex-start}
.wl .c-top{align-items:center}
/* The two controls that sat inside the flex row and grew with it. */
.wl .c-act,.wl .c-seen,.wl .c-msg{align-self:center;flex:none}

/* THE TABS RUN THE WIDTH OF THE PAGE. They are the top-level division of this
   screen — three lists, and which one you are in is the first thing to know —
   so the rule under them belongs to the page, not to the words. It stopped
   after "Bid" because the strip was only as wide as its content. */
.wl .wl-tabs{
  width:100%;box-sizing:border-box;
  padding:0 16px;gap:0;
}
.wl .wl-tab{padding:10px 16px;border-radius:0}
.wl .wl-tab:first-child{padding-inline-start:0}
/* The reference tab keeps its rule and its distance, but the rule is a divider
   between two kinds of thing rather than a box around one. */
.wl .wl-tab.slim{margin-inline-start:14px;padding-inline-start:14px}

/* The equipment card is the one green thing on a card and it should be the size
   of its contents. */
.wl .wl-kit{align-items:center;min-height:0}

/* ---- the visit form's duplicate guard ------------------------------------
   The phone is the one field here that is an IDENTITY rather than a
   description, so it is the one that gets checked. A warning, never a block: a
   number legitimately reaches two people at one business, and a form that
   refuses to save is a form a rep works around by leaving the number out —
   which is the same duplicate with less evidence. */
.mk-hits{
  margin-top:7px;border:1px solid var(--warn);border-radius:var(--r);
  background:var(--warn-soft);overflow:hidden;
}
.mk-hit-h{
  padding:7px 10px 5px;font-size:10px;line-height:15px;text-transform:uppercase;
  letter-spacing:.05em;color:var(--warn);font-weight:600;
}
.mk-hit{
  display:flex;align-items:baseline;gap:8px;width:100%;padding:7px 10px;
  border:0;background:transparent;text-align:start;cursor:pointer;
  border-top:1px solid color-mix(in srgb,var(--warn) 22%,transparent);
}
.mk-hit:hover{background:color-mix(in srgb,var(--warn) 10%,transparent)}
.mk-hit-n{font-size:var(--t-body);font-weight:600;color:var(--ink);unicode-bidi:plaintext}
.mk-hit-c{font-size:var(--t-micro);color:var(--ink-2);unicode-bidi:plaintext;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.mk-hit-go{
  margin-inline-start:auto;flex:none;font-size:var(--t-micro);color:var(--warn);
  font-weight:550;white-space:nowrap;
}
/* The clear case gets a line too. "Nobody has this number" is the answer a rep
   needs before creating somebody, and silence is not that answer. */
.mk-hits .mk-hit.none{
  border-top:0;cursor:default;font-size:var(--t-micro);color:var(--ink-3);
  display:block;padding:8px 10px;
}
.mk-hits .none{background:transparent}
.mk-hit-why{
  padding:6px 10px 8px;font-size:var(--t-micro);line-height:var(--lh-micro);
  color:var(--ink-2);border-top:1px solid color-mix(in srgb,var(--warn) 22%,transparent);
}

/* Add new is a RESULT, at the bottom, after what already exists. It used to be
   what happened when a rep picked nothing — the most consequential outcome in
   the form, reached by doing nothing at all. */
.mk-ac-h{
  padding:7px 10px 4px;font-size:10px;line-height:15px;text-transform:uppercase;
  letter-spacing:.05em;color:var(--ink-3);
}
.mk-ac-new{border-top:1px solid var(--line)}
.mk-ac-new span{color:var(--ink)}
.mk-ac-new em{color:var(--ink-3)}

/* ======================= the Suppliers module =============================
   docs/proto/sales-suppliers-uat.html. Scoped to #v-suppliers rather than a
   .stage: the tokens are the host's already, and the module's class names --
   .row, .chip, .act, .tab -- are common enough that unscoped rules would reach
   the queue. The prototype's own token block is dropped for the same reason:
   redefining the palette inside one view is how two screens drift apart.
   ========================================================================= */
@media (prefers-color-scheme:dark){
  #v-suppliers{
    --s0:#16191e; --s5:#1a1e24; --s10:#12151a; --s20:#272c34; --s30:#353b45;
    --s40:#4c545f; --s50:#8e96a2; --s60:#aeb5bf; --s90:#f5f7f9;
    --signal:#f0733f; --signal-soft:#3a221a; --good:#5cb98d; --good-soft:#163025;
    --panel:var(--s5);
  }
}
#v-suppliers button{font:inherit;cursor:pointer}

/* ---- shared table (the .q table in sales.css) ---- */
#v-suppliers table.q{width:100%;border-collapse:collapse;table-layout:fixed}
#v-suppliers .q th{
  text-align:start;font-size:var(--t-micro);line-height:var(--lh-micro);font-weight:500;
  color:var(--ink-3);text-transform:uppercase;letter-spacing:.04em;
  padding:8px 10px;border-bottom:1px solid var(--line);background:var(--panel);
  position:sticky;top:0;z-index:1;
}
#v-suppliers .q td{
  padding:9px 10px;border-bottom:1px solid var(--line);vertical-align:top;
  overflow:hidden;text-overflow:ellipsis;
}
#v-suppliers .q tbody tr{cursor:pointer}
#v-suppliers .q tbody tr:hover{background:var(--s5)}
#v-suppliers .q tbody tr[aria-selected="true"]{background:var(--s10)}
#v-suppliers .num{font-family:var(--mono);font-variant-numeric:tabular-nums}
#v-suppliers .lead-name{font-weight:550;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
#v-suppliers .name-ar{
  color:var(--ink-3);font-size:var(--t-micro);line-height:var(--lh-micro);margin-top:2px;
  unicode-bidi:plaintext;text-align:start;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
#v-suppliers .on-app{display:inline-flex;align-items:center;gap:5px;font-family:var(--mono);
  font-size:var(--t-micro);color:var(--ink-2)}
#v-suppliers .on-app::before{content:"";width:6px;height:6px;border-radius:var(--r-pill);background:var(--good)}
#v-suppliers .mini-empty{color:var(--ink-3);font-size:var(--t-micro);line-height:var(--lh-micro);padding:8px 0}
#v-suppliers .chip{
  display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:var(--r-pill);
  border:1px solid var(--line-strong);color:var(--ink-2);white-space:nowrap;
  font-size:var(--t-micro);background:transparent;
}
#v-suppliers .chip[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--s0)}
#v-suppliers .more{
  display:block;width:100%;padding:10px;border:0;border-top:1px solid var(--line);
  background:transparent;color:var(--ink-2);font-size:var(--t-micro);
}

/* ---- BEFORE: the two sources ---- */
#v-suppliers .b-tabs{display:flex;gap:0;border-bottom:1px solid var(--line)}
#v-suppliers .b-tabs button{
  border:0;background:transparent;color:var(--ink-2);padding:8px 14px;
  font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.05em;
  border-bottom:2px solid transparent;
}
#v-suppliers .b-tabs button[aria-pressed="true"]{color:var(--ink);border-bottom-color:var(--ink)}
#v-suppliers .b-nav{padding:12px 14px;border-bottom:1px solid var(--line);background:var(--s5)}
#v-suppliers .b-nav-h,#v-suppliers .b-sec,#v-suppliers .ch-sec{
  font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3);
  margin-bottom:6px;
}
#v-suppliers .b-sec,#v-suppliers .ch-sec{padding:12px 14px 0}
#v-suppliers .b-nav-i{padding:4px 0;color:var(--ink)}
#v-suppliers .b-nav-note{margin-top:8px;font-size:var(--t-micro);color:var(--signal)}
#v-suppliers .b-gap{
  margin:12px 14px;padding:10px 12px;border:1px dashed var(--line-strong);border-radius:var(--r);
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-2);
}

/* ---- BEFORE: c-hub, recreated ---- */
#v-suppliers .ch-head{padding:12px 14px 0;font-weight:600}
#v-suppliers .ch-filters{padding:8px 14px 10px;border-bottom:1px solid var(--line)}
#v-suppliers .ch-search{
  width:100%;padding:7px 10px;border:1px solid var(--line-strong);border-radius:var(--r);
  background:var(--s5);color:var(--ink-3);font:inherit;font-size:var(--t-micro);
}
#v-suppliers .ch-fl{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:8px;
  font-size:var(--t-micro);color:var(--ink-3)}
#v-suppliers .ch-fl input[type=date],#v-suppliers .ch-fl select{
  border:1px solid var(--line-strong);border-radius:var(--r);background:var(--s5);
  color:var(--ink-3);font:inherit;font-size:var(--t-micro);padding:2px 6px;
}
#v-suppliers .ch-chip{
  border:1px solid var(--line-strong);border-radius:var(--r);background:transparent;
  color:var(--ink-2);font-size:var(--t-micro);padding:2px 9px;
}
#v-suppliers .ch-count{
  padding:10px 14px 4px;font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-3);
  letter-spacing:.04em;
}
#v-suppliers .ch-row{display:flex;gap:12px;padding:12px 14px;border-bottom:1px solid var(--line)}
#v-suppliers .ch-av{
  width:34px;height:34px;border-radius:var(--r-pill);flex:none;display:grid;place-items:center;
  background:var(--s10);color:var(--ink-2);font-size:var(--t-micro);font-weight:600;
  box-shadow:inset 0 0 0 1px var(--line);
}
#v-suppliers .ch-main{flex:1;min-width:0}
#v-suppliers .ch-nm{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-weight:600}
#v-suppliers .ch-sub{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);margin-top:2px;
  unicode-bidi:plaintext;text-align:start}
#v-suppliers .ch-pill{
  font-size:10px;padding:1px 7px;border-radius:var(--r-pill);font-weight:500;
  box-shadow:inset 0 0 0 1px var(--line);color:var(--ink-2);background:var(--s10);
}
#v-suppliers .ch-ver{background:#e8f0fe;color:#1d4ed8;box-shadow:none}
#v-suppliers .ch-rej{background:var(--signal-soft);color:var(--signal);box-shadow:none}
#v-suppliers .ch-store{background:var(--good-soft);color:var(--good);box-shadow:none}
#v-suppliers .ch-docs{display:flex;gap:4px;flex-wrap:wrap;margin-top:7px;align-items:center}
#v-suppliers .cd{font-size:10px;padding:1px 6px;border-radius:var(--r-pill)}
#v-suppliers .cd-ok{background:var(--good-soft);color:var(--good)}
#v-suppliers .cd-no{background:var(--signal-soft);color:var(--signal)}
#v-suppliers .ch-miss{font-size:10px;color:var(--ink-3);margin-inline-start:4px}
#v-suppliers .ch-none{font-size:var(--t-micro);color:var(--ink-3);font-style:italic;margin-top:6px}
#v-suppliers .ch-act{flex:none}
#v-suppliers .ch-btn{
  border:1px solid #bfd0f5;border-radius:var(--r);background:transparent;color:#2563eb;
  font-size:var(--t-micro);padding:3px 9px;
}
#v-suppliers .ch-miss-box{
  margin:12px 14px;padding:10px 12px;border-radius:var(--r);
  background:var(--signal-soft);color:var(--signal);
  font-size:var(--t-micro);line-height:var(--lh-micro);
}
#v-suppliers .ch-prof{padding:0 14px 14px}
#v-suppliers .ch-pf-h{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;
  padding:10px 0;border-bottom:1px solid var(--line)}
#v-suppliers .ch-pf-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px}
#v-suppliers .ch-box{border:1px solid var(--line);border-radius:var(--r);padding:10px 12px}
#v-suppliers .ch-box-h{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);
  margin-bottom:6px}
#v-suppliers .ch-rings{display:flex;gap:6px;flex-wrap:wrap}
#v-suppliers .ch-ring{font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-2);
  border:1px solid var(--line);border-radius:var(--r-pill);padding:1px 8px}
#v-suppliers .ch-doc{font-size:var(--t-micro);color:var(--ink-2);padding:2px 0}
#v-suppliers .ch-tabs{display:flex;gap:14px;align-items:baseline;flex-wrap:wrap;margin:12px 0 4px;
  font-size:var(--t-micro);color:var(--ink-3)}
#v-suppliers .ch-tabs .on{color:var(--ink);font-weight:600}
#v-suppliers .ch-eq th,#v-suppliers .ch-eq td{font-size:var(--t-micro)}

/* ---- AFTER: the Suppliers view ---- */
#v-suppliers .af-strip{padding:9px 12px;border-bottom:1px solid var(--line)}
#v-suppliers .af-search input{
  width:100%;max-width:260px;padding:6px 9px;border:1px solid var(--line-strong);
  border-radius:var(--r);background:var(--s5);color:var(--ink);font:inherit;font-size:var(--t-micro);
}
#v-suppliers .af-chips{display:flex;gap:5px;align-items:center;flex-wrap:wrap;margin-top:7px}
#v-suppliers .af-chips .sep{width:1px;height:15px;background:var(--line)}
#v-suppliers .af-count{font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-3);
  margin-inline-start:4px}
#v-suppliers .src-tag{
  padding:1px 5px;border-radius:var(--r-pill);font-family:var(--mono);font-size:10px;
  background:var(--s20);color:var(--ink-3);
}
#v-suppliers .src-tag.mg{background:var(--good-soft);color:var(--good)}
#v-suppliers .sup-st{
  display:inline-block;padding:2px 8px;border-radius:var(--r-pill);
  font-size:var(--t-micro);line-height:var(--lh-micro);
  background:var(--s10);color:var(--ink-2);box-shadow:inset 0 0 0 1px var(--line);
}
#v-suppliers .sup-st[data-s="Verified"]{background:var(--good-soft);color:var(--good);box-shadow:none}
#v-suppliers .sup-st[data-s="Rejected"]{background:var(--signal-soft);color:var(--signal);box-shadow:none}
#v-suppliers .af-warn,#v-suppliers .af-fail{
  margin:9px 12px;padding:8px 11px;border-radius:var(--r);font-size:var(--t-micro);
  line-height:var(--lh-micro);
}
#v-suppliers .af-warn{background:var(--s10);color:var(--ink-2)}
#v-suppliers .af-fail{background:var(--signal-soft);color:var(--signal);display:flex;gap:10px;align-items:center}
/* tighter rows: the list is a scanning surface, not a reading one */
#v-suppliers .af-list .q td{padding:7px 10px}

/* ---- AFTER: one supplier, one screen ----
   Header, numbers, rail and tab strip are all above the fold. Only the tab body
   scrolls, and it scrolls inside itself. Shape borrowed from Attio's record
   page: a sections rail, a highlights strip, then tabs.
   https://attio.com/help/reference/managing-your-data/records/configure-record-pages */
#v-suppliers .af-page{
  position:relative;
  display:flex;flex-direction:column;min-height:0;
  height:min(680px, calc(100dvh - 260px));
}

#v-suppliers .pg-head{
  display:flex;gap:10px;align-items:center;flex-wrap:wrap;
  padding:9px 12px;border-bottom:1px solid var(--line);
}
#v-suppliers .back{
  border:1px solid var(--line-strong);border-radius:var(--r);background:transparent;
  color:var(--ink-2);font-size:var(--t-body);line-height:1;padding:4px 9px;flex:none;
}
#v-suppliers .back:hover{border-color:var(--s40);color:var(--ink)}
#v-suppliers .pg-id{flex:1;min-width:180px}
#v-suppliers .pg-head h2{
  margin:0;font-size:var(--t-body);line-height:var(--lh-body);font-weight:600;
  unicode-bidi:plaintext;text-align:start;
}
#v-suppliers .pg-sub{
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
  unicode-bidi:plaintext;text-align:start;
}
#v-suppliers .alias{margin-inline-start:8px;color:var(--ink-2)}
#v-suppliers .pg-tags{display:flex;gap:5px;align-items:center;flex:none}
#v-suppliers .pg-crumb{font-family:var(--mono);font-size:10px;color:var(--ink-3)}
#v-suppliers .acts{display:flex;gap:5px;flex:none;flex-wrap:wrap}
#v-suppliers .act{
  border:1px solid var(--line-strong);border-radius:var(--r);padding:4px 9px;
  font-size:var(--t-micro);color:var(--ink-2);
}
#v-suppliers .act.primary{background:var(--ink);border-color:var(--ink);color:var(--s0)}
#v-suppliers .act.off{opacity:.5}

/* the numbers. Plain cells on hairlines - at this density a card around every
   metric is noise, so the grid lines do the separating. */
#v-suppliers .stats{
  display:grid;grid-template-columns:repeat(11,minmax(0,1fr));
  border-bottom:1px solid var(--line);background:var(--line);gap:1px;
}
#v-suppliers .stat{background:var(--panel);padding:7px 10px;min-width:0}
#v-suppliers .stat-n{
  font-family:var(--mono);font-size:var(--t-body);line-height:18px;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
#v-suppliers .stat-l{
  font-size:10px;line-height:14px;color:var(--ink-3);
  text-transform:uppercase;letter-spacing:.04em;
}
#v-suppliers .stat.good .stat-n{color:var(--good)}
#v-suppliers .stat.bad .stat-n{color:var(--signal)}
#v-suppliers .stat.muted .stat-n{color:var(--ink-3)}

/* THE HEIGHT CHAIN, all the way from the app shell.
   `.pg-cols` asks for `flex:1` and got nothing, because every ancestor between
   it and `.main` was a plain block: `.view.on` is display:block, and #sr-body
   and .af-page had no rule at all. So the supplier page sized to its CONTENT
   inside a `.app` that is `height:100dvh; overflow:hidden` — anything past the
   fold was clipped with no scrollbar to reach it. That is why the page read as
   cropped, why the bottom section was never "true to size", and why the yards
   in the equipment modal could not be reached.

   Each link has to say BOTH `flex:1` and `min-height:0`. A flex item's default
   `min-height:auto` refuses to shrink below its content, which is exactly how
   one long tab body pushes the whole column past the viewport again. */
#v-suppliers.on{display:flex;flex-direction:column;flex:1;min-height:0}
#v-suppliers > #sr-body{flex:1;min-height:0;display:flex;flex-direction:column}
#v-suppliers .af-page{flex:1;min-height:0;display:flex;flex-direction:column}
#v-suppliers .pg-cols{display:flex;flex:1;min-height:0}
#v-suppliers .rail{
  width:250px;flex:none;border-inline-end:1px solid var(--line);
  overflow:auto;padding:10px 12px;
}
#v-suppliers .rail-sec + .rail-sec{margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
#v-suppliers .rail-sec h3,#v-suppliers .pane-body h3{
  margin:0 0 6px;font-size:10px;line-height:14px;font-weight:600;
  text-transform:uppercase;letter-spacing:.06em;color:var(--ink-3);
  display:flex;align-items:center;gap:8px;
}
#v-suppliers .rail-sec h3 .mini-btn{margin-inline-start:auto}

#v-suppliers .kv{display:flex;gap:8px;align-items:baseline;padding:2px 0;font-size:var(--t-micro);
  line-height:var(--lh-micro)}
#v-suppliers .kv-k{width:56px;flex:none;color:var(--ink-3)}
#v-suppliers .kv-v{flex:1;min-width:0;unicode-bidi:plaintext;text-align:start}
#v-suppliers .note-body{
  margin:6px 0 0;font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-2);
}
#v-suppliers .own{margin-top:7px;font-size:var(--t-micro);color:var(--ink-2)}
#v-suppliers .own-src{display:block;color:var(--ink-3);font-size:10px;margin-top:2px}

/* store: the logo tile is small on purpose. It is identity, not the subject. */
#v-suppliers .store-row{display:flex;gap:9px;align-items:center}
#v-suppliers .store-nm{font-size:var(--t-micro);line-height:var(--lh-micro);font-weight:550;
  unicode-bidi:plaintext;text-align:start}
#v-suppliers .store-meta{font-size:10px;color:var(--ink-3)}
#v-suppliers .img-tile{
  border-radius:var(--r);border:1px dashed var(--line-strong);
  display:grid;place-items:center;color:var(--ink-3);font-size:9px;letter-spacing:.04em;
  text-transform:uppercase;
  background:repeating-linear-gradient(135deg,transparent 0 6px,var(--s10) 6px 12px);
}
#v-suppliers .img-tile.logo{width:52px;height:52px;flex:none}
#v-suppliers .img-tile.eq{aspect-ratio:16/9;border-radius:var(--r) var(--r) 0 0;border-bottom:0}

/* A tile that HAS a picture stops being a placeholder: the dashed border and
   the hatch were there to say "nothing here", and leaving them behind a real
   photo reads as a loading state that never finished. The label stays, over
   the image, because four identical machine photos are only distinguishable by
   which slot they are. */
/* "prod only" — the photo EXISTS and this deployment cannot fetch it. Held
   apart from the plain placeholder on purpose: that one means nobody took a
   photo, this one means we cannot reach the one they took, and a rep testing on
   staging was reading the second as the first. Amber rather than red — nothing
   is broken. */
#v-suppliers .img-tile.prod-only{
  position:relative;border-style:dashed;border-color:var(--signal);
  background:var(--signal-soft);
}
#v-suppliers .img-tile.prod-only>span:last-child{opacity:.6}
#v-suppliers .po-tag{
  display:inline-block;font-family:var(--mono);font-size:9px;letter-spacing:.04em;
  text-transform:uppercase;color:var(--signal);background:var(--s0);
  border:1px solid var(--signal);border-radius:calc(var(--r) / 2);
  padding:1px 5px;white-space:nowrap;
}
#v-suppliers .img-tile.prod-only .po-tag{position:absolute;top:6px;left:6px}
#v-suppliers .img-tile.has-img{
  position:relative;border-style:solid;border-color:var(--line);background:var(--s10);
  overflow:hidden;
}
#v-suppliers .img-tile.has-img img{
  width:100%;height:100%;object-fit:cover;display:block;
}
#v-suppliers .img-tile.has-img>span{
  position:absolute;left:0;right:0;bottom:0;padding:3px 5px;
  background:linear-gradient(transparent,rgba(0,0,0,.62));color:#fff;
  text-align:center;pointer-events:none;
}
/* The make and model, under the group name. Dimmer than the name because the
   name is what the rep matches a request against; the model is what they say
   on the phone. */
#v-suppliers .eq-model{
  font-size:10px;color:var(--ink-3);margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
#v-suppliers .eq-facts span.warn{background:var(--signal-soft);color:var(--ink-2)}

/* Renamed off `.pane` — that class is the global slide-out drawer, and this
   section was inheriting its position:fixed and translateX(100%). See the note
   at the <section> in index.html. */
#v-suppliers .sr-pane{flex:1;min-width:0;display:flex;flex-direction:column;min-height:0}
#v-suppliers .tabs{display:flex;gap:0;border-bottom:1px solid var(--line);padding:0 12px}
#v-suppliers .tabs button{
  border:0;background:transparent;color:var(--ink-3);font:inherit;font-size:var(--t-micro);
  padding:8px 11px;border-bottom:2px solid transparent;display:flex;align-items:center;gap:6px;
}
#v-suppliers .tabs button:hover{color:var(--ink)}
#v-suppliers .tabs button[aria-pressed="true"]{color:var(--ink);border-bottom-color:var(--ink)}
#v-suppliers .tab-n{font-family:var(--mono);font-size:10px;color:var(--ink-3)}
#v-suppliers .pane-body{flex:1;min-height:0;overflow:auto;padding:12px}

#v-suppliers .gap-note,#v-suppliers .warn-box{
  margin:8px 0 0;padding:7px 9px;border-radius:var(--r);
  font-size:10px;line-height:14px;
}
#v-suppliers .gap-note{background:var(--s10);color:var(--ink-3);font-family:var(--mono)}
#v-suppliers .warn-box{background:var(--signal-soft);color:var(--signal);font-size:var(--t-micro);
  line-height:var(--lh-micro)}

/* equipment: the block the page is really for */
#v-suppliers .eq-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(178px,1fr));gap:9px}
#v-suppliers .eq-card{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;
  background:var(--panel)}
#v-suppliers .eq-b{padding:8px 9px}
#v-suppliers .eq-nm{font-weight:550;font-size:var(--t-micro);line-height:var(--lh-micro);
  display:flex;gap:8px;align-items:baseline;unicode-bidi:plaintext;text-align:start}
#v-suppliers .eq-x{margin-inline-start:auto;font-family:var(--mono);color:var(--ink-2);flex:none}
#v-suppliers .eq-facts{display:flex;flex-wrap:wrap;gap:3px;margin-top:6px}
#v-suppliers .eq-facts span{font-size:10px;color:var(--ink-2);background:var(--s10);
  border-radius:var(--r-pill);padding:1px 7px}
#v-suppliers .eq-facts span.bad{background:var(--signal-soft);color:var(--signal)}
#v-suppliers .eq-facts span.ok{background:var(--good-soft);color:var(--good)}
/* one card per machine (srMachineCard) -- status pill, update stamp, count line */
#v-suppliers .eq-st{margin-inline-start:auto;flex:none;font-size:10px;font-weight:600;
  border-radius:var(--r-pill);padding:1px 7px}
#v-suppliers .eq-st.ok{background:var(--good-soft);color:var(--good)}
#v-suppliers .eq-st.bad{background:var(--signal-soft);color:var(--signal)}
#v-suppliers .eq-upd{margin-top:6px;font-size:10px;color:var(--ink-3)}
#v-suppliers .eq-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;margin:0 0 10px}
#v-suppliers .eq-head .eq-facts{margin-top:0;margin-inline-start:auto}
#v-suppliers .eq-head-sub{font-size:12px;color:var(--ink-3)}
#v-suppliers .sr-verify{margin:0 0 10px;line-height:1.45}
#v-suppliers .sr-verify q{font-weight:600;unicode-bidi:plaintext}
#v-suppliers .sr-verify .mini-btn{margin-inline-start:6px}
#v-suppliers .eq-st.warn{background:var(--c-amber-soft);color:var(--c-amber)}
#v-suppliers .eq-st:not(.ok):not(.bad):not(.warn){background:var(--s10);color:var(--ink-2)}
#v-suppliers .sr-subs td{vertical-align:top}
#v-suppliers .sr-subs td[dir="auto"]{unicode-bidi:plaintext;white-space:normal}

/* conditions */
#v-suppliers .gates{border:1px solid var(--line);border-radius:var(--r);padding:0 10px}
#v-suppliers .gate{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;padding:8px 0;
  border-bottom:1px solid var(--line);font-size:var(--t-micro);line-height:var(--lh-micro)}
#v-suppliers .gate:last-child{border-bottom:0}
#v-suppliers .gate-c{font-family:var(--mono);font-size:10px;color:var(--ink-3);flex:none;width:16px}
#v-suppliers .gate-n::before{
  content:"";display:inline-block;width:6px;height:6px;border-radius:var(--r-pill);
  background:var(--s40);margin-inline-end:7px;
}
#v-suppliers .gate[data-ok="true"] .gate-n::before{background:var(--good)}
#v-suppliers .gate[data-ok="false"] .gate-n{color:var(--ink-2)}
#v-suppliers .gate[data-ok="false"] .gate-n::before{background:var(--signal)}
#v-suppliers .gate[data-ok="dead"]{opacity:.75}
#v-suppliers .gate[data-ok="dead"] .gate-n{text-decoration:line-through;color:var(--ink-3)}
#v-suppliers .gate[data-ok="dead"] .gate-c{color:var(--signal)}
#v-suppliers .gate-w{flex:1;min-width:130px;color:var(--ink-3)}
#v-suppliers .gate-x{flex-basis:100%;margin-inline-start:24px;color:var(--signal);font-size:10px;
  line-height:14px}
#v-suppliers .gate[data-ok="true"] .gate-x{color:var(--ink-3)}

/* reach */
#v-suppliers .verdict{margin:0 0 10px;font-size:var(--t-body);line-height:var(--lh-body)}
#v-suppliers .fun{display:grid;grid-template-columns:repeat(5,1fr);gap:10px}
#v-suppliers .fun-s{min-width:0}
#v-suppliers .fun-bar{height:5px;border-radius:var(--r-pill);background:var(--s10);overflow:hidden}
#v-suppliers .fun-bar span{display:block;height:100%;background:var(--ink)}
#v-suppliers .fun-n{font-family:var(--mono);font-size:18px;line-height:24px;margin-top:5px}
#v-suppliers .fun-l{font-size:10px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.04em}
#v-suppliers .fun-d{font-family:var(--mono);font-size:10px;color:var(--signal);min-height:14px}
#v-suppliers .fun-x{display:flex;gap:5px;flex-wrap:wrap;margin-top:10px}
#v-suppliers .fun-x span{font-size:10px;color:var(--ink-2);background:var(--s10);
  border-radius:var(--r-pill);padding:2px 8px}

/* certifications */
#v-suppliers .cert-cat + .cert-cat{margin-top:10px;padding-top:9px;border-top:1px solid var(--line)}
#v-suppliers .cert-cat-h{display:flex;justify-content:space-between;align-items:center;gap:8px;
  font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3);margin-bottom:4px}
#v-suppliers .mini-btn{
  border:1px solid var(--line-strong);border-radius:var(--r-pill);background:transparent;
  color:var(--ink-2);font-size:10px;padding:1px 8px;text-transform:none;letter-spacing:0;
}
#v-suppliers .mini-btn:hover{border-color:var(--s40);color:var(--ink)}
#v-suppliers .ed{margin-top:7px;padding:9px;border:1px solid var(--line-strong);border-radius:var(--r);
  background:var(--s5)}
#v-suppliers .ed-l{font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3);
  margin:6px 0 4px}
#v-suppliers .ed-l:first-child{margin-top:0}
#v-suppliers .ed-chips{display:flex;gap:5px;flex-wrap:wrap}
#v-suppliers .ed input,#v-suppliers .ed select,#v-suppliers .ed textarea{
  width:100%;padding:5px 8px;border:1px solid var(--line-strong);border-radius:var(--r);
  background:var(--panel);color:var(--ink);font:inherit;font-size:var(--t-micro);
}
#v-suppliers .ed textarea{min-height:46px;resize:vertical}
#v-suppliers .ed-f{display:flex;align-items:center;gap:8px;margin-top:9px;flex-wrap:wrap}
#v-suppliers .confirm{
  border:1px solid var(--ink);border-radius:var(--r);background:var(--ink);color:var(--s0);
  font-size:var(--t-micro);padding:4px 11px;
}
#v-suppliers .ed-note{font-family:var(--mono);font-size:10px;color:var(--ink-3);flex:1;min-width:150px}

/* Narrow: the rail stops being a column and the numbers wrap to three up. */
@media (max-width:900px){
  #v-suppliers .stats{grid-template-columns:repeat(3,minmax(0,1fr))}
  #v-suppliers .pg-cols{display:block}
  #v-suppliers .rail{width:auto;border-inline-end:0;border-bottom:1px solid var(--line)}
  #v-suppliers .fun{grid-template-columns:repeat(2,1fr)}
  #v-suppliers .ch-pf-grid{grid-template-columns:1fr}
}

/* impression: the engine's four states, not an invented number. Colour only at
   the two ends - an unproven account is not a problem, it is a new one. */
#v-suppliers .imp{
  display:inline-flex;align-items:center;gap:6px;padding:2px 8px;border-radius:var(--r-pill);
  font-size:var(--t-micro);line-height:var(--lh-micro);
  background:var(--s10);color:var(--ink-2);box-shadow:inset 0 0 0 1px var(--line);
}
#v-suppliers .imp[data-s="good"]{background:var(--good-soft);color:var(--good);box-shadow:none}
#v-suppliers .imp[data-s="burned"]{background:var(--signal-soft);color:var(--signal);box-shadow:none}
#v-suppliers .imp[data-s="at_risk"]{background:var(--s20);color:var(--ink);box-shadow:none}
#v-suppliers .imp-n{font-family:var(--mono);font-size:10px;opacity:.75}
#v-suppliers .imp-none{font-size:var(--t-micro);color:var(--ink-3)}
#v-suppliers .imp-head{display:flex;align-items:center;gap:8px;margin-bottom:6px}
#v-suppliers .imp-open{font-family:var(--mono);font-size:10px;color:var(--signal)}
#v-suppliers .imp-ev{display:flex;gap:8px;align-items:baseline;padding:3px 0;font-size:var(--t-micro);
  line-height:var(--lh-micro)}
#v-suppliers .imp-ev-l{flex:1;min-width:0}
#v-suppliers .imp-ev-l::before{
  content:"";display:inline-block;width:5px;height:5px;border-radius:var(--r-pill);
  background:var(--s40);margin-inline-end:7px;
}
#v-suppliers .imp-ev[data-sign="bad"] .imp-ev-l::before{background:var(--signal)}
#v-suppliers .imp-ev[data-sign="good"] .imp-ev-l::before{background:var(--good)}
#v-suppliers .imp-ev-w{font-family:var(--mono);font-size:10px;color:var(--ink-3);flex:none}
#v-suppliers .chip.clear{border-style:dashed;color:var(--ink-3)}

/* the tick, and the rule between the two action groups */
#v-suppliers .pg-head h2{display:flex;align-items:center;gap:7px}
#v-suppliers .v-tick{display:inline-flex;color:var(--good);flex:none}
#v-suppliers .tick{width:14px;height:14px}
#v-suppliers .acts.docs{
  padding-inline-start:9px;margin-inline-start:1px;
  border-inline-start:1px solid var(--line);
}

/* icon actions */
#v-suppliers .act.icon{
  display:inline-grid;place-items:center;width:30px;height:26px;padding:0;
  background:transparent;color:var(--ink-2);cursor:pointer;
}
#v-suppliers .act.icon svg{width:15px;height:15px}
#v-suppliers .act.icon:hover{border-color:var(--s40);color:var(--ink)}
#v-suppliers .act.icon.primary{background:var(--ink);border-color:var(--ink);color:var(--s0)}
#v-suppliers button.act{font:inherit;font-size:var(--t-micro);cursor:pointer}

/* a card that opens something has to look pressable and take focus */
#v-suppliers .eq-card{cursor:pointer;transition:border-color var(--t-fast,110ms) ease}
#v-suppliers .eq-card:hover{border-color:var(--s40)}
#v-suppliers .eq-card:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* unit modal */
/* FIXED, not absolute. Absolute pinned the veil to the supplier page's box,
   so when that page was taller than the window the dialog was centred on the
   page and sat below the fold: Compose opened and a rep had to scroll to find
   it. Fixed centres it on the window, whatever is scrolled behind. */
#v-suppliers .modal-veil{
  position:fixed;inset:0;background:rgba(20,23,27,.34);
  display:grid;place-items:center;padding:20px;z-index:20;
}
#v-suppliers .modal{
  width:min(680px,100%);max-height:100%;display:flex;flex-direction:column;
  background:var(--panel);border-radius:var(--r);
  box-shadow:0 1px 2px rgba(20,23,27,.10), 0 18px 44px -12px rgba(20,23,27,.34);
}
#v-suppliers .modal-h{
  display:flex;align-items:flex-start;gap:10px;padding:11px 13px;
  border-bottom:1px solid var(--line);
}
#v-suppliers .modal-h b{font-size:var(--t-body);unicode-bidi:plaintext}
#v-suppliers .modal-sub{font-size:10px;color:var(--ink-3);margin-top:2px}
#v-suppliers .modal-x{
  margin-inline-start:auto;border:0;background:transparent;color:var(--ink-3);
  display:grid;place-items:center;width:24px;height:24px;flex:none;
}
#v-suppliers .modal-x svg{width:14px;height:14px}
#v-suppliers .modal-x:hover{color:var(--ink)}
#v-suppliers .modal-b{padding:12px 13px;overflow:auto}
#v-suppliers .modal-gal{display:grid;grid-template-columns:repeat(4,1fr);gap:7px;margin-bottom:12px}
#v-suppliers .img-tile.slot{aspect-ratio:4/3}
#v-suppliers .modal-facts{
  display:grid;grid-template-columns:1fr 1fr;gap:0 18px;
  padding-bottom:10px;border-bottom:1px solid var(--line);
}
#v-suppliers .kv-note{font-family:var(--mono);font-size:10px;color:var(--ink-3)}
#v-suppliers .bad-t{color:var(--signal)}
#v-suppliers .modal-h4{
  margin:12px 0 6px;font-size:10px;line-height:14px;font-weight:600;
  text-transform:uppercase;letter-spacing:.06em;color:var(--ink-3);
}
#v-suppliers .modal-units th,#v-suppliers .modal-units td{font-size:var(--t-micro);padding:6px 8px}
#v-suppliers .modal-units tbody tr{cursor:default}
#v-suppliers .modal-units tbody tr:hover{background:transparent}

#v-suppliers .doc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(158px,1fr));gap:6px}
#v-suppliers .doc-chip{
  font-size:var(--t-micro);line-height:var(--lh-micro);padding:5px 9px;border-radius:var(--r);
  background:var(--s10);color:var(--ink-3);
}
#v-suppliers .doc-chip[data-has="true"]{background:var(--good-soft);color:var(--good)}
#v-suppliers .warn-t{color:var(--signal)}
#v-suppliers .store-nm.dim{color:var(--ink-3);font-weight:400}
#v-suppliers .af-strip.row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
#v-suppliers .af-strip.row .af-chips{margin-top:0}
#v-suppliers .pane-body a{color:var(--ink);text-underline-offset:2px}

/* survey pill and the two pencils */
#v-suppliers .pill{
  display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:var(--r-pill);
  border:1px solid var(--line-strong);background:transparent;color:var(--ink-2);
  font:inherit;font-size:10px;line-height:15px;cursor:pointer;
}
#v-suppliers .pill svg{width:12px;height:12px}
#v-suppliers .pill.survey:hover{border-color:var(--s40);color:var(--ink)}
#v-suppliers .pill.dim{opacity:.55;cursor:default}
#v-suppliers .icon-btn{
  display:inline-grid;place-items:center;width:22px;height:22px;flex:none;
  border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r);
}
#v-suppliers .icon-btn svg{width:13px;height:13px}
#v-suppliers .icon-btn:hover{color:var(--ink);background:var(--s10)}
#v-suppliers .icon-btn.tiny{width:18px;height:18px}
#v-suppliers .icon-btn.tiny svg{width:11px;height:11px}
#v-suppliers .modal.sm{width:min(440px,100%)}

/* the supplier-facing report preview */
#v-suppliers .modal.rep{width:min(520px,100%)}
#v-suppliers .rep-acts{display:flex;gap:5px;margin-inline-start:auto;align-items:center}
#v-suppliers .rep-acts .mini-btn[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--s0)}
#v-suppliers .rep-doc h4{margin:0 0 2px;font-size:var(--t-body);unicode-bidi:plaintext}
#v-suppliers .rep-doc h5{
  margin:14px 0 6px;font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-3);
}
#v-suppliers .rep-lede{margin:0 0 12px;font-size:var(--t-micro);color:var(--ink-3)}
#v-suppliers .rep-row{
  display:flex;align-items:baseline;gap:10px;padding:6px 0;border-bottom:1px solid var(--line);
  font-size:var(--t-micro);
}
#v-suppliers .rep-n{font-family:var(--mono);font-size:var(--t-body);min-width:34px;flex:none}
#v-suppliers .rep-row.ar .rep-n{margin-inline-start:auto;text-align:end}
#v-suppliers .rep-l{flex:1;min-width:0}
#v-suppliers .rep-block{
  margin-top:10px;padding:9px 11px;border-radius:var(--r);
  background:var(--signal-soft);color:var(--signal);font-size:var(--t-micro);line-height:var(--lh-micro);
}
#v-suppliers .rep-fix{margin:0;padding-inline-start:18px;font-size:var(--t-micro);line-height:18px}
#v-suppliers .rep-fix li + li{margin-top:5px}
#v-suppliers .rep-doc.ar{text-align:start}

/* compose: one status line, one chip row, and either a draft to copy or an
   approved template to send. Nothing explains itself twice. */
#v-suppliers .modal.cp{width:min(480px,100%)}
#v-suppliers .cp-status{display:flex;flex-wrap:wrap;gap:3px 12px;margin-top:4px;font-size:var(--t-micro);color:var(--ink-3)}
#v-suppliers .cp-ch{unicode-bidi:plaintext}
#v-suppliers .cp-ch::before{
  content:"";display:inline-block;width:6px;height:6px;border-radius:var(--r-pill);
  background:var(--signal);margin-inline-end:5px;vertical-align:1px;
}
#v-suppliers .cp-ch[data-ok="true"]::before{background:var(--good)}
#v-suppliers .cp-ch[data-ok="true"]{color:var(--ink-2)}
#v-suppliers .cp-status .linkish{margin-inline-start:4px;font-size:inherit}
#v-suppliers .cp-hist{
  margin:0 0 10px;padding:6px 10px;border-radius:var(--r);background:var(--s10);
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-2);
}
#v-suppliers .cp-hist.warn{background:var(--signal-soft);color:var(--signal)}
#v-suppliers .cp-chips{display:flex;flex-wrap:wrap;gap:5px}
#v-suppliers .cp-chips .mini-btn[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--s0)}
#v-suppliers .cp-meta{
  margin-inline-start:5px;padding:0 4px;border-radius:var(--r);background:var(--s10);
  color:var(--ink-3);font-family:var(--mono);font-size:10px;text-transform:uppercase;
}
#v-suppliers .mini-btn[aria-pressed="true"] .cp-meta{background:transparent;color:inherit;opacity:.7}
#v-suppliers .cp-draft{
  display:block;width:100%;margin-top:10px;padding:9px 11px;resize:vertical;
  border:1px solid var(--line);border-radius:var(--r);background:var(--s0);color:var(--ink);
  font:inherit;font-size:var(--t-body);line-height:1.8;text-align:start;
}
#v-suppliers .cp-prev{
  margin-top:10px;padding:9px 11px;max-height:220px;overflow:auto;border-radius:var(--r);
  background:var(--s5);color:var(--ink-2);font-size:var(--t-small);line-height:1.7;
  white-space:pre-wrap;text-align:start;
}
#v-suppliers .cp-fine{margin:6px 0 0;font-size:var(--t-micro);color:var(--ink-3)}
#v-suppliers .cp-fine a{color:inherit;text-decoration:underline}
#v-suppliers .cp-fine .linkish{font-size:inherit}
#v-suppliers .cp-acts{display:flex;align-items:center;gap:6px;margin-top:8px}
#v-suppliers .cp-holes{margin-inline-end:auto;font-size:var(--t-micro);color:var(--good)}
#v-suppliers .cp-holes:not([data-n="0"]){color:var(--signal)}
#v-suppliers .cp-acts .mini-btn:disabled{opacity:.45;cursor:not-allowed}
#v-suppliers .cp-acts .mini-btn.primary{background:var(--ink);border-color:var(--ink);color:var(--s0)}
/* Send from the CRM: the approved-template block under a meta chip in Compose,
   and the same block under the worklist's supplier draft (.wl .m-tpl). One
   confirm step, in words, and the outcome as a note, never as a toast that
   vanishes before the rep has read whether it went. */
#v-suppliers .cp-send{margin-top:8px}
#v-suppliers .cp-row{display:flex;align-items:center;gap:6px;margin-top:8px}
#v-suppliers .cp-req{
  flex:1;min-width:0;padding:6px 8px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--s0);color:var(--ink);font:inherit;font-size:var(--t-small);
}
#v-suppliers .cp-msg{
  margin:6px 0 0;padding:7px 10px;border-radius:var(--r);
  font-size:var(--t-micro);line-height:1.5;color:var(--ink-2);background:var(--s5);
}
#v-suppliers .cp-msg a{color:inherit;text-decoration:underline}
#v-suppliers .cp-msg.warn{background:var(--signal-soft);color:var(--signal)}
#v-suppliers .cp-msg.bad{background:var(--bad-bg,var(--s5));color:var(--bad)}
#v-suppliers .cp-msg.good{background:var(--good-bg,var(--s5));color:var(--good)}
.wl .m-tpl{margin-top:12px;padding-top:10px;border-top:1px dashed var(--line)}
.wl .m-tpl .msg-lang a{color:inherit;text-decoration:underline}


/* impression faces */
#v-suppliers .imp{
  display:inline-flex;align-items:center;gap:6px;padding:0;border-radius:0;
  background:transparent;box-shadow:none;color:var(--ink-3);
}
#v-suppliers .imp .face{width:17px;height:17px;flex:none}
#v-suppliers .imp[data-s="good"]{color:var(--good)}
#v-suppliers .imp[data-s="at_risk"]{color:var(--ink-2)}
#v-suppliers .imp[data-s="burned"]{color:var(--signal)}
#v-suppliers .imp-w{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink)}
#v-suppliers .imp-n{
  font-family:var(--mono);font-size:10px;padding:0 5px;border-radius:var(--r-pill);
  background:var(--signal-soft);color:var(--signal);
}
#v-suppliers .imp[data-s="good"] .imp-n{background:var(--good-soft);color:var(--good)}
#v-suppliers .imp-dash{font-family:var(--mono);color:var(--ink-3)}
/* ============================ END FILL =================================== */


/* The gaps block folds closed with the rest of the drawer. Its summary carries
   the count, which is the question — how thin is this brief — and the chips
   answer the follow-up behind one click. */


/* Blocked-but-drawn. Awab, 30 Aug 2026: no UI element should be absent — greyed
   with a placeholder is fine. A control a rep cannot see reads as a capability
   that does not exist; a dark one with the route named reads as a wait, and the
   screen doubles as the checklist for the access request. */
#v-suppliers .verq{
  border:1px dashed var(--line-strong);border-radius:var(--r);
  padding:11px 12px;display:flex;flex-direction:column;gap:9px;background:var(--s5);
}
#v-suppliers .verq-state{display:flex;align-items:baseline;gap:7px;font-size:var(--t-body)}
#v-suppliers .verq-now{font-weight:600}
#v-suppliers .verq-sep{color:var(--s40)}
#v-suppliers .verq-dim{font-size:var(--t-micro);color:var(--ink-3)}
#v-suppliers .verq-acts{display:flex;gap:6px}
#v-suppliers .verq .btn.nowire{
  position:relative;opacity:.5;cursor:not-allowed;
  border:1px solid var(--line-strong);background:var(--panel);
  padding:5px 12px;border-radius:var(--r);font-size:var(--t-micro);
}
#v-suppliers .verq .nw{
  position:absolute;inset-block-start:3px;inset-inline-end:3px;
  width:5px;height:5px;border-radius:var(--r-pill);background:var(--s40);
}
/* The panel behind a dark control says the ask is filed, so the reader is not
   left to wonder whether anyone has noticed. */
.nowire-filed{
  margin-top:7px;font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
}
.nowire-needs code{
  font-family:var(--mono);font-size:var(--t-micro);
  background:var(--s10);padding:1px 5px;border-radius:4px;
}
.gap-note code{font-family:var(--mono);font-size:10px;background:var(--s10);padding:1px 4px;border-radius:3px}

/* U7 — Today. Leads the filter row, quieter than the search box beside it: it is
   the first thing read and never the thing clicked. Hidden entirely rather than
   shown empty (U21), so it has no empty state to style. */
.today{
  display:flex;align-items:center;gap:5px;white-space:nowrap;
  font-size:var(--t-micro);color:var(--ink-2);
  padding:0 10px 0 2px;margin-inline-end:2px;
  border-inline-end:1px solid var(--line);
}
.today-k{text-transform:uppercase;letter-spacing:.05em;font-size:10px;color:var(--ink-3)}
.today .num{font-family:var(--mono);color:var(--ink);font-weight:550}
.today-sep{color:var(--ink-3);margin:0 1px}
@media (max-width:900px){ .today{display:none} }

/* ---- Abdulsalam's onboarding queue ---------------------------------------- */

/* U2 "On their own". Fixed shape: always both icons, lit or dim. He scans this
   column vertically, and a cell that shows only what is true makes every row a
   different silhouette and forces him to read each one. */
.own-pair{display:flex;align-items:center;gap:5px}
.own{position:relative;display:inline-grid;place-items:center;width:20px;height:20px;
     color:var(--ink-3);opacity:.42;border-radius:4px}
.own svg{width:16px;height:16px}
.own.on{color:var(--good);opacity:1}
.own:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* U2b/U40 a POPOVER, not a tooltip — the answers are the reason he opens it.
   Opens on hover AND focus; nothing inside is interactive, so Tab moves past. */
.own-pop{
  position:absolute;top:calc(100% + 6px);inset-inline-start:0;z-index:120;
  display:none;min-width:230px;max-width:320px;padding:9px 10px;
  background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r);
  box-shadow:0 10px 28px -12px rgba(20,23,27,.34);
  font-size:var(--t-micro);color:var(--ink-2);text-align:start;white-space:normal;
}
.own:hover .own-pop,.own:focus-visible .own-pop{display:block}
.own-pop-h{display:block;color:var(--ink);font-weight:600;margin-bottom:2px}
.own-pop-when{color:var(--ink-3);font-family:var(--mono);font-size:10px;margin-bottom:6px}
.own-pop-r{display:flex;gap:8px;justify-content:space-between;padding:2px 0;
           border-top:1px solid var(--line)}
.own-pop-r span{color:var(--ink-3)}
.own-pop-r b{color:var(--ink);font-weight:550;text-align:end}

/* U41 the name is the control. It always opened the drawer; now it says so. */
.lead-open{
  background:none;border:0;padding:0;margin:0;font:inherit;color:inherit;
  cursor:pointer;text-align:start;
}
.lead-open:hover{text-decoration:underline;text-underline-offset:2px}
.lead-open:focus-visible{outline:2px solid var(--ink);outline-offset:2px;border-radius:3px}

/* U24 no number, no control — so this has no empty state. */
.copy-n{
  background:none;border:0;padding:2px;margin-inline-start:4px;cursor:pointer;
  color:var(--ink-3);display:inline-grid;place-items:center;vertical-align:middle;
}
.copy-n svg{width:13px;height:13px}
.copy-n:hover{color:var(--ink)}
.copy-n.done{color:var(--good)}

/* U5 the City column control. In the header, never in the filter row: a chip up
   there would read "the screen is narrowed to Riyadh". */
.th-city{position:static}
.th-pick{
  display:inline-flex;align-items:center;gap:4px;background:none;border:0;padding:0;
  font:inherit;color:inherit;cursor:pointer;
}
.th-pick svg{width:12px;height:12px}
.th-pick.on{color:var(--ink)}
.th-pill{
  font-family:var(--mono);font-size:9px;padding:1px 4px;border-radius:3px;
  background:var(--s20);color:var(--ink-2);
}
.cmenu{
  position:absolute;z-index:130;margin-top:4px;min-width:190px;max-height:280px;
  overflow:auto;padding:4px;background:var(--panel);
  border:1px solid var(--line-strong);border-radius:var(--r);
  box-shadow:0 10px 28px -12px rgba(20,23,27,.34);
}
.cmenu-row{display:flex;align-items:center;gap:7px;padding:4px 6px;border-radius:4px;
           cursor:pointer;font-weight:400;text-transform:none;letter-spacing:0}
.cmenu-row:hover{background:var(--s10)}
.cmenu-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cmenu-n{color:var(--ink-3);font-size:10px}
.cmenu-clear{
  width:100%;margin-top:2px;padding:5px;background:none;border:0;border-top:1px solid var(--line);
  color:var(--ink-2);font:inherit;font-size:var(--t-micro);cursor:pointer;text-align:start;
}
.cmenu-clear:hover{color:var(--ink)}

/* U9. The handoff panel. Only when Spoke to lead is ticked, and it names the
   queue and the date rather than implying the row is simply gone. */
/* [hidden] LOSES TO display:flex, and did. The panel carries `hidden` when no
   advance is ticked and still drew as an empty green bar across the dialog —
   the attribute sets display:none at user-agent weight, and any display in a
   stylesheet beats it. Every hidden element styled with a display needs this
   line, which is why it is worth stating rather than fixing quietly. */
.oc-back[hidden]{display:none}
.oc-back{
  display:flex;flex-direction:column;gap:2px;margin:8px 0 0;padding:8px 10px;
  border:1px solid var(--good);background:var(--good-soft);border-radius:var(--r);
  font-size:var(--t-micro);
}
.oc-back b{color:var(--ink);font-weight:600}
.oc-back span{color:var(--ink-2);font-family:var(--mono);font-size:10px}

/* U38. Dashed because it is not an outcome — nothing is recorded about how the
   work ended, the row belonged somewhere else. */
.oc-b.move{border-style:dashed}
.oc-b.move[aria-pressed="true"]{border-style:solid;background:var(--s20);color:var(--ink)}
.oc-b.move:disabled{opacity:.45;cursor:not-allowed}

/* U10. Permanent, and it looks like the thing it is rather than like the rest. */
.oc-dq{margin-top:10px}

/* A FACT, not an ending — so it reads differently from both the outcomes and
   from Move. Ticking it does not clear anything. */
.oc-b.fact[aria-pressed="true"]{background:var(--good-soft);border-color:var(--good);color:var(--ink)}
.oc-b.fact:disabled{opacity:.45;cursor:not-allowed}

/* U44. Completed's own toolbar. Sits above the table rather than in the filter
   row, because it belongs to this view and not to the queue. */
/* [hidden] loses to display:flex. Second instance in this file today — the
   first was .oc-back, and the sweep I wrote after it missed this one, which
   is why the rule is now stated on every such class rather than remembered. */
.cl-bar[hidden]{display:none}
.cl-bar{display:flex;gap:8px;align-items:center;padding:8px 12px 0}
.cl-bar input,.cl-bar select{
  font:inherit;font-size:var(--t-micro);padding:5px 8px;
  border:1px solid var(--line-strong);border-radius:var(--r);
  background:var(--panel);color:var(--ink);
}
.cl-bar input{flex:1;min-width:0;max-width:280px}
/* A group heading is a row in the same table, so the columns stay aligned. */
tr.cl-h td{
  padding-top:12px;color:var(--ink-3);font-size:10px;text-transform:uppercase;
  letter-spacing:.05em;border-bottom:1px solid var(--line);
}
tr.cl-h b{color:var(--ink-2);font-weight:600}
tr.cl-h .num{margin-inline-start:6px;font-family:var(--mono);color:var(--ink-3)}

/* An ADVANCE is a step, not a claim — it wins the same block as a request win
   because on this desk it IS the win, but it does not promise a wizard. */
/* COMPACT. As full-height win buttons the four advances ate the dialog and
   pushed every negative outcome below the fold — the opposite failure to having
   none of them, and just as bad: he could not see the six reasons a call goes
   badly without scrolling. Same block, same colour, a third of the height. */
.oc-b.win.adv{
  border-color:var(--good);background:var(--good-soft);
  padding:7px 11px;font-size:var(--t-micro);gap:7px;
}
.oc-b.win.adv svg{width:15px;height:15px}
.oc-b.win.adv em{font-size:10px}
.oc-b.win.adv[aria-pressed="true"]{background:var(--good);color:var(--s0)}
.oc-b.win.adv[aria-pressed="true"] em{color:var(--s0);opacity:.8}

/* The reason a control is dark, in words, on screen. It lived in a title
   attribute, so a chip at 45% opacity said nothing at all — and this is the
   state 73% of the bucket is in. */
.oc-blocked{
  flex-basis:100%;margin-top:6px;font-size:var(--t-micro);color:var(--ink-3);
  padding-inline-start:2px;
}

/* The body scrolls, so its bottom edge has to LOOK scrollable. Without this the
   last row of chips is simply cut and reads as the end of the list — which is
   exactly how a visible control gets reported missing. */
.oc-box>.oc-body{
  background:
    linear-gradient(var(--panel) 30%, rgba(255,255,255,0)) top / 100% 18px no-repeat,
    linear-gradient(rgba(255,255,255,0), var(--panel) 70%) bottom / 100% 18px no-repeat,
    radial-gradient(farthest-side at 50% 0, rgba(20,23,27,.12), rgba(0,0,0,0)) top / 100% 7px no-repeat,
    radial-gradient(farthest-side at 50% 100%, rgba(20,23,27,.12), rgba(0,0,0,0)) bottom / 100% 7px no-repeat;
  background-attachment:local, local, scroll, scroll;
}


/* ---- add a person, inside the deal drawer --------------------------------
   Collapsed to a single line until it is wanted. This sits under two selects
   that are the common case -- picking someone already on file -- and a form
   permanently open above them would make the rare thing look like the job. */
.addp{margin-top:10px;padding-top:10px;border-top:1px solid var(--line)}
.addp-open{
  display:inline-flex;align-items:center;gap:6px;
  padding:6px 10px;border:1px dashed var(--line-strong);border-radius:var(--r);
  background:transparent;color:var(--ink-2);
  font-size:var(--t-micro);font-family:inherit;cursor:pointer;
  transition:border-color var(--t-fast) var(--out),color var(--t-fast) var(--out);
}
.addp-open:hover{border-color:var(--ink-3);color:var(--ink)}
.addp-open svg{width:14px;height:14px;stroke-width:2}
/* `display:none`, not `[hidden]`. Twice today a `[hidden]` attribute lost to a
   `display:flex` further down the file and left an empty control on screen --
   specificity beats the attribute, and the rule that wins is whichever was
   written last. A class the container owns cannot be overridden by accident. */
.addp .addp-form{display:none}
.addp.on .addp-open{display:none}
.addp.on .addp-form{display:grid;gap:7px}
.addp-form input{
  width:100%;padding:8px 10px;
  background:var(--bg);color:var(--ink);
  border:1px solid var(--line-strong);border-radius:var(--r);
  font-size:var(--t-body);font-family:inherit;
}
.addp-form input:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 3px var(--s20)}
.addp-acts{display:flex;gap:7px}
.addp-acts .btn-min{
  padding:7px 12px;border-radius:var(--r);border:1px solid var(--ink);
  background:var(--ink);color:var(--bg);
  font-size:var(--t-micro);font-family:inherit;cursor:pointer;
}
.addp-acts .btn-min.ghost{background:transparent;color:var(--ink-2);border-color:var(--line-strong)}
.addp-acts .btn-min[disabled]{opacity:.45;pointer-events:none}
/* The shared note is positioned for the sheet it was written for; inside a
   section its 18px side margin reads as a misalignment. */
.addp .sheet-note{margin:2px 0 0;padding:8px 10px}


/* ---- the copied-link strip ------------------------------------------------
   Bottom centre, thin, and over everything: it is a receipt, not a panel. It
   never covers the request it is about, which is the whole reason the drawer
   this replaces was the wrong shape. */
.sharebar{
  position:fixed;left:50%;bottom:18px;transform:translateX(-50%) translateY(8px);
  z-index:200;display:flex;align-items:center;gap:8px;
  max-width:min(680px,92vw);padding:7px 8px 7px 12px;
  background:var(--panel);color:var(--ink);
  border:1px solid var(--line-strong);border-radius:999px;
  box-shadow:0 10px 30px -8px rgba(20,23,27,.28);
  opacity:0;pointer-events:none;
  transition:opacity var(--t-fast) var(--out),transform var(--t-fast) var(--out);
}
.sharebar.on{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
.sharebar .sb-msg{font-size:var(--t-micro);font-weight:600;flex:none}
.sharebar .sb-msg.ok{color:var(--good)}
.sharebar .sb-msg.bad{color:var(--signal)}
.sharebar .sb-url{
  flex:1;min-width:0;border:0;background:none;outline:none;
  font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-2);
  text-overflow:ellipsis;
}
.sharebar .sb-copy{
  flex:none;border:1px solid var(--line-strong);border-radius:999px;
  background:var(--bg);color:var(--ink);font:inherit;font-size:var(--t-micro);
  padding:4px 11px;cursor:pointer;
}
.sharebar .sb-copy:hover{border-color:var(--ink-3)}
.sharebar .sb-x{
  flex:none;border:0;background:none;color:var(--ink-3);cursor:pointer;
  font-size:15px;line-height:1;padding:2px 6px;
}
.sharebar .sb-x:hover{color:var(--ink)}
@media (max-width:520px){ .sharebar{max-width:94vw} }

/* The ad card preview. 1080 square from the renderer, shown at whatever the
   pane is wide, because the point is to check it before it goes to a supplier. */
.tpl-card-sec .tpl-card-img{
  display:block;width:100%;height:auto;border-radius:var(--r);
  border:1px solid var(--line);background:var(--s5);
}
.tpl-card-sec .acts{margin-top:8px}
.tpl-card-sec .act[disabled]{opacity:.45;pointer-events:none}

/* A checkbox row in the edit form: the label IS the control, so the whole line
   is a hit target rather than an 11px square. */
.rqe-chk{display:flex;align-items:center;gap:9px;cursor:pointer;padding:2px 0}
.rqe-chk input{width:16px;height:16px;flex:none;accent-color:var(--ink)}
.rqe-chk span{font-size:var(--t-body);color:var(--ink)}
.field input[readonly]{background:var(--s5);color:var(--ink-2);cursor:default}

/* One equipment item in the edit pane. Carded, because the fields inside repeat
   per machine and a flat list of thirty controls gives no clue which quantity
   belongs to which crane. */
.rqi-card{border:1px solid var(--line);border-radius:var(--r);padding:10px 12px;margin:8px 0}
.rqi-card + .rqi-card{margin-top:10px}
.rqi-h{font-size:var(--t-body);font-weight:600;color:var(--ink);margin-bottom:2px}
.rqi-card .hint{margin-bottom:6px}
.mini-note{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);padding:4px 0}

/* The map picker. Sits under the two coordinate fields rather than replacing
   them — exact coordinates typed by hand stay faster than hunting on a map. */
.pk{margin:2px 0 10px}
.pk-bar{display:flex;gap:7px;margin-bottom:7px}
.pk-q{
  flex:1;min-width:0;padding:8px 10px;background:var(--bg);color:var(--ink);
  border:1px solid var(--line-strong);border-radius:var(--r);
  font:inherit;font-size:var(--t-micro);
}
.pk-q:focus{outline:none;border-color:var(--ink)}
.pk-go{
  flex:none;padding:8px 12px;border:1px solid var(--ink);border-radius:var(--r);
  background:var(--ink);color:var(--bg);font:inherit;font-size:var(--t-micro);cursor:pointer;
}
.pk-go[disabled]{opacity:.45;pointer-events:none}
.pk-map{height:240px;border-radius:var(--r);overflow:hidden;border:1px solid var(--line)}
.pk-co{margin-top:6px;font-family:var(--mono);font-size:var(--t-micro);color:var(--ink-3)}
/* Leaflet paints its own controls; keep them under the app's drawers. */
.pk .leaflet-pane,.pk .leaflet-top,.pk .leaflet-bottom{z-index:1}

/* The channel icon in a history tag. Sized to the tag's own type so the row
   height does not move when one appears. */
.tl-tag .tl-i{width:11px;height:11px;flex:none;margin-inline-end:4px;vertical-align:-1px}
.tl-tag{display:inline-flex;align-items:center}
.tl-visit .tl-tag{color:var(--ink-2)}
/* A CALL IS RED, and the arrow says which way it went. Awab, 2 Sep. Red is not
   alarm here — it is the one channel that costs a person's time at both ends,
   and in a rail of grey milestones and green messages it is the row a rep is
   looking for. The direction lives in the icon (callin / callout); the colour
   only makes the row findable. */
.tl-maqsam .tl-tag,.tl-call .tl-tag,.tl-crmcall .tl-tag{
  background:var(--signal-soft);color:var(--signal);
}
/* An answered call keeps the red tag and earns a green spine, so "we spoke to
   them" is still separable at a glance from "it rang out". */
.tl-maqsam[data-tone="positive"]::before{background:var(--good)}

/* A message row opens the conversation, so it has to look touchable. */
.tl-item[data-thread]{cursor:pointer;border-radius:6px}
.tl-item[data-thread]:hover{background:var(--s5)}
.tl-item[data-thread]:focus-visible{outline:2px solid var(--signal);outline-offset:1px}

/* ── The conversation modal ──────────────────────────────────────────────────
   Its own prefix: the drawer has no modal of its own, and the page's `.modal-*`
   set is scoped to #v-suppliers. Reusing that name would have styled nothing
   here and looked like a rendering bug. */
.tlm-veil{
  position:fixed;inset:0;background:rgba(20,23,27,.42);z-index:60;
  display:grid;place-items:center;padding:24px;
}
.tlm{
  width:min(560px,100%);max-height:min(72vh,760px);display:flex;flex-direction:column;
  background:var(--panel);border-radius:var(--r);
  box-shadow:0 1px 2px rgba(20,23,27,.10), 0 18px 44px -12px rgba(20,23,27,.34);
}
.tlm-h{
  display:flex;align-items:flex-start;gap:12px;padding:14px 16px;
  border-bottom:1px solid var(--line);
}
.tlm-h > div:first-child{flex:1;min-width:0}
.tlm-h b{font-size:var(--t-body)}
.tlm-sub{font-size:var(--t-micro);color:var(--ink-3);margin-top:2px}
/* The way out of this modal and into the inbox that holds the rest of the
   conversation. Sits before the close button, so the last thing under the
   pointer is not "leave". */
.tlm-cw{
  font-size:var(--t-micro);color:var(--good);text-decoration:none;
  white-space:nowrap;
}
.tlm-cw:hover{text-decoration:underline}
.tlm-go{
  padding:3px 8px;border:1px solid var(--line);
  border-radius:var(--r-pill);color:var(--ink-2);
}
.tlm-go:hover{background:var(--s5);text-decoration:none}
.tlm-x{
  margin-inline-start:8px;background:none;border:0;cursor:pointer;
  font-size:20px;line-height:1;color:var(--ink-3);padding:0 2px;
}
.tlm-x:hover{color:var(--ink)}
.tlm-b-wrap{padding:14px 16px;overflow:auto;display:flex;flex-direction:column;gap:8px}
.tlm-row{display:flex}
.tlm-out{justify-content:flex-end}
.tlm-in{justify-content:flex-start}
.tlm-b{
  max-width:82%;padding:8px 10px;border-radius:12px;
  font-size:var(--t-micro);line-height:var(--lh-micro);
  /* The desk writes Arabic and English into the same thread, so each bubble
     picks its own direction from its own first strong character. */
  unicode-bidi:plaintext;white-space:pre-wrap;overflow-wrap:anywhere;
}
.tlm-out .tlm-b{background:var(--good-soft);color:var(--ink)}
.tlm-in .tlm-b{background:var(--s10);color:var(--ink)}
.tlm-m{margin-top:4px;font-size:9px;color:var(--ink-3);unicode-bidi:plaintext}

/* A one-way action. Not red for drama — red because close, force-expire and
   re-notify cannot be undone, and the two buttons beside them can. */
.acts .act.danger{border-color:var(--signal);color:var(--signal)}
.acts .act.danger:hover{background:var(--signal-soft)}
.acts .act.danger[disabled]{opacity:.45;pointer-events:none}

/* ── Downloads · the strip above the log ──────────────────────────────────────
   Deliberately one line tall. Awab asked for a "very small segment" and meant
   it: the growth question is answered by five figures and a twelve-bar curve,
   and the screen underneath is the log. Anything that wants a second row
   belongs on the Workspace, not here. */
.dl-top{
  display:flex;flex-wrap:wrap;align-items:flex-end;gap:22px;
  padding:12px 14px 10px;
}
.dl-fig{display:flex;flex-direction:column;gap:1px;min-width:0}
.dl-fig b{
  font-size:var(--t-mid);font-weight:600;line-height:1.1;
  font-variant-numeric:tabular-nums;
}
.dl-fig span{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3)}
/* Pushed to the far end so the numbers read as a row and the curve as its own
   thing, rather than as a sixth figure. */
.dl-spark{margin-inline-start:auto;display:flex;flex-direction:column;gap:3px}
.dl-spark svg{display:block}
.dl-spark span{font-size:var(--t-micro);color:var(--ink-3)}
/* --s40 rather than --s30: it reads as a chart on white AND on the dark ground,
   where --s30 is barely off the panel. The bars are all one weight — the last
   block ends now and is a complete seven days like every other, so there is no
   partial bar to mark. */
.dl-bar{fill:var(--s40)}
.dl-note{
  padding:0 14px 12px;max-width:92ch;
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);
  border-bottom:1px solid var(--line);
}
.dl-note b{color:var(--ink);font-weight:600}

/* ── Workspace · the landing screen ───────────────────────────────────────────
   One column, left-aligned to a reading measure rather than stretched across
   the viewport. A landing screen that fills 1400px is a wall; this one is a
   list somebody reads top to bottom and then leaves. */
/* The whole screen has to fit without scrolling, so this padding is a budget
   rather than a taste.

   1280, not 820. At 820 a 1422px window left 602px of empty grey down the
   right-hand side and the screen read as a column that had been cropped out of
   something wider. Prose has a reading measure and this is not prose -- it is
   six cards and a list of counts, all of them scanned. The cap is only there so
   an ultrawide monitor does not stretch three cards to a metre each. */
.ws-pad{padding:14px 22px 16px;max-width:1280px}
.ws-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.ws-since{font-size:var(--t-micro);color:var(--ink-3)}
.ws-since.none{font-style:italic}

/* Nothing moved, and first run. Both end in the same single action, because
   the honest answer to "there is nothing here" is to hand the rep onward
   rather than leave them on an empty screen deciding what to do. */
.ws-note{
  border:1px solid var(--line);border-radius:var(--r);padding:16px 18px;
  display:flex;flex-direction:column;align-items:flex-start;gap:6px;
  background:var(--panel);
}
.ws-note b{font-size:var(--t-body);color:var(--ink)}
.ws-note span{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3);max-width:60ch}
.ws-go{
  margin-top:8px;display:inline-flex;align-items:center;
  padding:7px 14px;border-radius:var(--r-pill);
  background:var(--ink);color:var(--s0);text-decoration:none;
  font-size:var(--t-micro);font-weight:500;
  transition:transform 140ms var(--out),opacity 140ms var(--out);
}
.ws-go:hover{opacity:.88}
.ws-go:active{transform:scale(.97)}

.ws-stale{
  border:1px solid var(--signal);background:var(--signal-soft);
  border-radius:var(--r);padding:11px 14px;margin-bottom:12px;
  font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink);
}
.ws-stale b{font-weight:600}

/* The rows. A number, a sentence, a door — nothing else earns a place. */
.ws-moved{display:flex;flex-direction:column;border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;background:var(--panel)}
.ws-mv{
  display:flex;align-items:center;gap:14px;padding:9px 16px;
  border-bottom:1px solid var(--line);
}
.ws-mv:last-child{border-bottom:0}
.ws-n{
  flex:none;min-width:34px;text-align:right;
  font-size:var(--t-mid);font-weight:600;color:var(--ink-3);
  font-variant-numeric:tabular-nums;
}
/* Colour carries ONE thing here: somebody has to act on this today. Spend it
   on the number, which is where the eye lands, and nowhere else. */
.ws-mv.urg .ws-n{color:var(--signal)}
.ws-b{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.ws-b b{font-size:var(--t-body);font-weight:500;color:var(--ink)}
.ws-b span{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3)}
.ws-open{
  flex:none;padding:5px 12px;border-radius:var(--r-pill);
  border:1px solid var(--line-strong);background:transparent;color:var(--ink-3);
  font-size:var(--t-micro);
  transition:border-color 140ms var(--out),color 140ms var(--out),transform 140ms var(--out);
}
.ws-open:hover{border-color:var(--s40);color:var(--ink)}
.ws-open:active{transform:scale(.97)}

/* Standing figures, not deltas — so they sit apart from the rows above and
   read as context rather than as things that happened. */
.ws-book{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  margin-top:14px;padding:12px 16px;
  border:1px solid var(--line);border-radius:var(--r);
}
.ws-book-l{font-size:var(--t-micro);color:var(--ink-3);
  text-transform:uppercase;letter-spacing:.06em}
.ws-bk{font-size:var(--t-micro);color:var(--ink-3)}
.ws-bk b{font-size:var(--t-body);font-weight:600;color:var(--ink);margin-inline-end:4px}
.ws-bk.due b{color:var(--signal)}
.ws-book-go{
  margin-inline-start:auto;padding:5px 12px;border-radius:var(--r-pill);
  border:1px solid var(--line-strong);background:transparent;color:var(--ink-3);
  font-size:var(--t-micro);
  transition:border-color 140ms var(--out),color 140ms var(--out),transform 140ms var(--out);
}
.ws-book-go:hover{border-color:var(--s40);color:var(--ink)}
.ws-book-go:active{transform:scale(.97)}

/* The six that lost their menu entry. Always here, so nothing became
   unreachable — this is the row that makes the nav change reversible. */
/* All six, always, in a fixed grid. Workspace is the only way into these pages
   now, so this block cannot change shape with the news -- a rep should be able
   to aim at Equipment without reading the others. */
/* ---- accounts a rep holds that are on nobody's desk ----------------------
   982 of 1,513 production rows are in this state, so the band has to be
   readable without being an alarm: a rep did nothing wrong, and the fix is a
   manager changing an assignment. Quiet until it has a number, and it only
   ever gets one after they press it. */
.ws-held{
  display:flex;align-items:center;flex-wrap:wrap;gap:8px 10px;margin-top:12px;
  padding:10px 12px;border:1px solid var(--line);border-radius:12px;background:var(--s5);
}
.ws-held-l{font-size:var(--t-micro);color:var(--ink-3);flex:1 1 240px;min-width:0}
.ws-held-l b{color:var(--ink-2);font-weight:600}
.ws-held.on{background:var(--paper)}
.ws-held-n{font-size:20px;font-weight:650;color:var(--ink);line-height:1;font-variant-numeric:tabular-nums}
.ws-held-b{
  appearance:none;cursor:pointer;font:inherit;font-size:var(--t-micro);
  padding:4px 10px;border-radius:999px;border:1px solid var(--line);
  background:var(--paper);color:var(--ink-2);
}
.ws-held-b:hover{border-color:var(--ink-3);color:var(--ink)}
.ws-held-bs{display:flex;flex-wrap:wrap;gap:6px;flex:1 1 100%}
.ws-held-chip{
  appearance:none;cursor:pointer;font:inherit;font-size:var(--t-micro);
  display:inline-flex;align-items:center;gap:6px;
  padding:3px 9px;border-radius:999px;border:1px solid var(--line);
  background:var(--s5);color:var(--ink-2);
}
.ws-held-chip .n{font-family:var(--mono);color:var(--ink-3)}
.ws-held-chip:hover{border-color:var(--ink-3)}
.ws-held-chip.on{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.ws-held-chip.on .n{color:var(--paper);opacity:.75}
.ws-held-list{
  flex:1 1 100%;display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));
  gap:4px;margin-top:2px;max-height:240px;overflow-y:auto;
}
.ws-held-row{
  appearance:none;cursor:pointer;font:inherit;text-align:start;
  display:flex;align-items:baseline;gap:8px;min-width:0;
  padding:5px 8px;border:0;border-radius:8px;background:none;color:var(--ink-2);
}
.ws-held-row:hover{background:var(--s5);color:var(--ink)}
.ws-held-who{font-size:var(--t-micro);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;unicode-bidi:plaintext}
.ws-held-c{font-size:var(--t-micro);color:var(--ink-3);flex:none}

.ws-secs{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:12px}
.ws-secs-l{grid-column:1/-1;font-size:var(--t-micro);color:var(--ink-3);
  text-transform:uppercase;letter-spacing:.06em;margin-bottom:-2px}
/* The card is the container; the button inside it is the door. They were one
   element, which meant a chip nested inside a button -- invalid, and the inner
   press fired the outer one on the way past. */
.ws-sec{
  display:flex;flex-direction:column;align-items:stretch;
  border:1px solid var(--line);border-radius:var(--r);background:transparent;
  transition:border-color 140ms var(--out),background 140ms var(--out);
}
.ws-sec:hover{border-color:var(--s40);background:var(--panel)}
.ws-sec-open{
  display:flex;flex-direction:column;align-items:flex-start;gap:5px;
  padding:9px 12px 7px;text-align:start;border:0;background:transparent;width:100%;
  transition:transform 140ms var(--out);
}
.ws-sec-open:active{transform:scale(.99)}
.ws-sec-h{font-size:var(--t-body);font-weight:500;color:var(--ink)}
.ws-sec-f{display:flex;align-items:center;gap:6px;min-height:16px;flex-wrap:wrap}
.ws-sec-n{font-size:var(--t-body);font-weight:600;color:var(--ink)}
/* A figure that has not landed is a dot, not a zero. A zero is an answer. */
.ws-sec-n.wait{color:var(--s30);font-weight:400}
.ws-sec-l{font-size:var(--t-micro);line-height:var(--lh-micro);color:var(--ink-3)}

@media (max-width:720px){ .ws-secs{grid-template-columns:1fr 1fr} }
.ws-foot{margin:16px 0 0;font-size:var(--t-micro);line-height:var(--lh-micro);
  color:var(--ink-3);max-width:60ch}

/* The source cell. Icon and word together — the icon alone would need learning
   and there are four states, one of which is an absence. */
.dl-src{display:inline-flex;align-items:center;gap:5px;color:var(--ink);
  font-size:var(--t-micro)}
.dl-src svg{width:13px;height:13px;flex:none}
.dl-src.none{color:var(--ink-3)}

/* The User CRM carries twelve filters. One row of them clips the moment the
   drawer opens, and a chip you cannot see is a chip nobody presses — so this
   one row wraps rather than scrolling. Opt-in: every other view fits. */
.strip.wrap{flex-wrap:wrap;overflow-x:visible;row-gap:6px}

/* The mark, top left, and the way back to the Workspace. Black artwork on a
   transparent ground, so dark mode inverts it rather than shipping a second
   file that can drift from the first. */
.brand{
  flex:none;display:inline-flex;align-items:center;
  padding:4px 6px;margin-inline-start:-6px;border:0;background:transparent;
  border-radius:var(--r);
  transition:opacity 140ms var(--out),transform 140ms var(--out);
}
.brand-mark{height:22px;width:auto;display:block;opacity:.88}
.brand:hover .brand-mark{opacity:1}
/* The press has to be felt. This is the one control on the header a rep hits
   without looking at it. */
.brand:active{transform:scale(.97)}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .brand-mark{filter:invert(1)}
}
:root[data-theme="dark"] .brand-mark{filter:invert(1)}

/* ── Workspace cards · the parts that make one worth opening ─────────────────
   Every card carries the same three things in the same places — name, figure,
   one shape — so the six read as one block and the eye can skip to the row it
   wants. What changes between them is what the shape IS, because the question
   each page answers is different and pretending otherwise would make all six
   equally ignorable. */

/* The request status split. Monochrome: this desk spends colour on one thing,
   "somebody has to act", and a closed request is not that. */
.ws-bar{display:flex;width:58px;height:5px;border-radius:3px;overflow:hidden;
  gap:1px;margin-inline-start:2px;flex:none}
.ws-bar i{background:var(--s40);display:block}
.ws-bar i[data-b="0"]{background:var(--s60)}
.ws-bar i[data-b="2"]{background:var(--s30)}
.ws-bar i[data-b="3"],.ws-bar i[data-b="4"]{background:var(--s20)}

.ws-spark{flex:none;margin-inline-start:2px}
.ws-spark rect{fill:var(--s40)}

/* Channel state. The dot is a second reading of a word that is already there —
   it is what makes "not sending" findable across the room. */
.ws-dot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--s40);
  margin-inline-start:2px}
.ws-dot[data-v="good"]{background:var(--good)}
.ws-dot[data-v="bad"]{background:var(--signal)}

/* Chips open the page ALREADY narrowed, so they sit below the door rather than
   inside it — pressing one is a different act from opening the page. */
.ws-sec-c{display:flex;flex-wrap:wrap;gap:5px;padding:0 12px 9px}
.ws-chip{
  font-size:var(--t-micro);line-height:1.5;
  padding:2px 8px;border-radius:var(--r-pill);
  border:1px solid var(--line);background:var(--panel);color:var(--ink-3);
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  transition:border-color 140ms var(--out),color 140ms var(--out),transform 140ms var(--out);
}
.ws-chip:hover{border-color:var(--s40);color:var(--ink)}
.ws-chip:active{transform:scale(.96)}
/* Not every card has somewhere to send you. Performance shows two more figures
   instead, and they are text rather than chips because they are not buttons. */
.ws-mini{font-size:var(--t-micro);color:var(--ink-3);padding:2px 0}
.ws-mini.due{color:var(--signal)}
.ws-mini + .ws-mini{margin-inline-start:10px}

/* The rows that did not make the top three. Not hidden — named, countable, and
   one press from the page they came from. A "+2 more" with no nouns in it is
   the same as not showing them. */
.ws-mv.more{gap:6px;flex-wrap:wrap;padding:8px 16px}

/* The one search box, in the row that already existed. Six pages behind one
   screen is exactly when "which page is this on" becomes the question. */
.ws-find{
  margin-inline-start:auto;display:flex;align-items:center;gap:6px;
  padding:4px 10px;min-width:210px;
  border:1px solid var(--line);border-radius:var(--r-pill);background:var(--panel);
  transition:border-color 140ms var(--out);
}
.ws-find:focus-within{border-color:var(--s40)}
.ws-find svg{width:14px;height:14px;flex:none;color:var(--ink-3)}
.ws-find input{
  border:0;background:transparent;outline:none;width:100%;
  font-size:var(--t-micro);color:var(--ink);
}
.ws-find input::placeholder{color:var(--ink-3)}
.ws-find input::-webkit-search-cancel-button{-webkit-appearance:none}

/* A result says WHERE before it says what. That is the question being asked. */
.ws-mv.res .ws-where{
  flex:none;min-width:84px;
  font-size:var(--t-micro);color:var(--ink-3);
  text-transform:uppercase;letter-spacing:.05em;
}
.ws-mv.res .ws-where i{font-style:normal;margin-inline-start:4px;color:var(--s40)}

/* ── Find Suppliers · sorting and the account claim ──────────────────────────
   The header is a control now, so it has to look like one on hover and say
   which way it is sorted without a legend. */
.sr-tbl thead th.sr-th{cursor:pointer;user-select:none;white-space:nowrap;
  transition:color 140ms var(--out)}
.sr-tbl thead th.sr-th:hover{color:var(--ink)}
.sr-ind{display:inline-block;min-width:9px;margin-inline-start:3px;
  color:var(--s30);font-size:10px;vertical-align:1px;
  transition:color 140ms var(--out)}
.sr-tbl thead th.sr-th:hover .sr-ind{color:var(--ink-3)}
/* The column actually sorting states its direction in full ink. */
.sr-ind.on{color:var(--ink)}

/* The login, not the address — every row shares the domain and it would be the
   widest thing in a 104px column. */
.sr-am{font-size:var(--t-micro);color:var(--ink-2)}
.sr-am.none{color:var(--ink-3);font-style:italic}

.sr-own{
  flex:none;max-width:180px;
  padding:4px 8px;border-radius:var(--r-pill);
  border:1px solid var(--line);background:var(--panel);color:var(--ink-3);
  font-size:var(--t-micro);
  transition:border-color 140ms var(--out),color 140ms var(--out);
}
.sr-own:hover{border-color:var(--s40);color:var(--ink)}
.sr-own:focus{outline:none;border-color:var(--s40);color:var(--ink)}


/* ---- Bids: the master filter and what hangs off it ----------------------
   One view, three modes (F1). The bar sits above the table rather than in the
   chip strip because the strip already belongs to the review chips, and two
   rows of pills that filter different things is how a rep stops reading either. */
.bd-bar{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:10px 18px;border-bottom:1px solid var(--line);background:var(--panel);
}
.bd-bar:empty{display:none}
.bd-modes{display:flex;gap:0;border:1px solid var(--line-strong);border-radius:var(--r);overflow:hidden}
.bd-mode{
  font:inherit;font-size:var(--t-micro);line-height:1;
  padding:7px 12px;border:0;background:var(--panel);color:var(--ink-2);cursor:pointer;
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
}
.bd-mode + .bd-mode{border-inline-start:1px solid var(--line)}
.bd-mode .n{font-family:var(--mono);color:var(--ink-3)}
.bd-mode:hover{background:var(--s10);color:var(--ink)}
.bd-mode[aria-pressed="true"]{background:var(--ink);color:var(--panel)}
.bd-mode[aria-pressed="true"] .n{color:var(--panel);opacity:.75}

.bd-seg{display:flex;gap:0;border:1px solid var(--line-strong);border-radius:var(--r);overflow:hidden}
.bd-seg button{
  font:inherit;font-size:var(--t-micro);line-height:1;padding:7px 10px;
  border:0;background:var(--panel);color:var(--ink-2);cursor:pointer;white-space:nowrap;
}
.bd-seg button + button{border-inline-start:1px solid var(--line)}
.bd-seg button:hover{background:var(--s10);color:var(--ink)}
.bd-seg button[aria-pressed="true"]{background:var(--s20);color:var(--ink);font-weight:600}

.bd-toggle{
  font:inherit;font-size:var(--t-micro);line-height:1;padding:7px 10px;
  border:1px solid var(--line-strong);border-radius:var(--r-pill);
  background:var(--panel);color:var(--ink-2);cursor:pointer;white-space:nowrap;
}
.bd-toggle:hover{border-color:var(--ink);color:var(--ink)}
.bd-toggle[aria-pressed="true"]{background:var(--ink);color:var(--panel);border-color:var(--ink)}

/* A sortable head reads as pressable, which is what makes R4's way back
   comprehensible: the rep can see they did this. */
.th-sort{
  font:inherit;font-size:inherit;color:inherit;background:none;border:0;padding:0;
  cursor:pointer;text-align:inherit;
}
.th-sort:hover{color:var(--ink);text-decoration:underline}
.th-sort[aria-pressed="true"]{color:var(--ink);font-weight:600}

/* R1's grouping header. A band, not a row that looks clickable. */
tr.grp td{
  background:var(--s5);font-size:var(--t-micro);color:var(--ink-2);
  padding:7px 18px;border-top:1px solid var(--line);
}
tr.grp .n{font-family:var(--mono);color:var(--ink-3);margin-inline-start:8px}

.doc-n{
  font:inherit;font-family:var(--mono);font-size:var(--t-micro);
  padding:3px 9px;border:1px solid var(--line-strong);border-radius:var(--r-pill);
  background:var(--panel);color:var(--ink-2);cursor:pointer;
}
.doc-n:hover{border-color:var(--ink);color:var(--ink)}

.bd-docs{padding:4px 16px 8px}
.bd-doc{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:9px 0;border-bottom:1px solid var(--line);font-size:var(--t-micro);
}
.bd-doc a{color:var(--ink);text-decoration:none;overflow-wrap:anywhere}
.bd-doc a:hover{text-decoration:underline}
.bd-dl{color:var(--ink-3) !important;white-space:nowrap}
/* C2. Listed, visibly not openable, and it says why. */
.bd-doc.dead{color:var(--ink-3);flex-direction:column;align-items:flex-start;gap:2px}
.bd-why{color:var(--ink-3);font-style:italic}


/* ---- H3-H7: the bidder's history and its basis --------------------------
   The basis is not decoration. A name match can be wrong, and a rep quoting a
   price back to somebody who never bid it is how that costs something — so the
   label sits in the heading where it is read before the rows are. */
.hist{padding:14px 18px 18px;border-top:1px solid var(--line);background:var(--panel)}
.hist-h{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  font-weight:600;font-size:var(--t-body);color:var(--ink);margin-bottom:8px;
}
.hist-h .n{font-family:var(--mono);font-weight:400;color:var(--ink-3)}
.hist-basis{font-weight:400;font-size:var(--t-micro)}
.hist-basis.ok{color:var(--ink-3)}
.hist-basis.warn{color:var(--signal)}
.hist-row{
  display:grid;grid-template-columns:76px 104px 96px minmax(0,1fr);
  gap:10px;align-items:baseline;padding:6px 0;
  border-bottom:1px solid var(--line);font-size:var(--t-micro);
}
.hist-when,.hist-val{color:var(--ink-2)}
.hist-req{color:var(--ink)}
.hist-end{color:var(--ink-2)}
/* Converted is the one ending that means they are on the platform. */
.hist-end[data-e="converted"]{color:var(--good);font-weight:600}
.hist-end[data-e="rejected"]{color:var(--signal)}
.hist-end[data-e="open"]{color:var(--ink-3)}


/* ---- the Request CRM's row controls -------------------------------------
   Two buttons in one cell: mark serious, and copy the public bid link.

   Sized and coloured off the drawer's .iact rather than reinvented, because
   they are the same two controls one screen earlier -- a rep who learns the
   star in the drawer should not have to learn a different one in the list.

   Quieter at rest, though. Six hundred rows of full-strength icons would read
   as twelve hundred things asking for attention, so they sit at --s40 and come
   up on hover. */
.rq-acts-cell{white-space:nowrap;text-align:end}
.rq-acts-cell .icon-btn{
  width:26px;height:26px;flex:none;padding:0;
  display:inline-grid;place-items:center;border-radius:var(--r);
  border:1px solid transparent;background:transparent;color:var(--s40);cursor:pointer;
  transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out),
             border-color var(--t-fast) var(--out);
}
.rq-acts-cell .icon-btn svg{width:15px;height:15px;stroke-width:1.7}
.rq-acts-cell button.icon-btn:hover{
  background:var(--s10);color:var(--ink);border-color:var(--line-strong);
}
.rq-acts-cell .icon-btn.off{cursor:help;color:var(--s30)}
/* SET, not hovered. A marked request has to be findable by eye down a long
   list, which is the whole reason the flag exists -- so this is the one state
   here that is allowed to be loud, in the same hue every other "look at this"
   on the desk uses. */
.rq-acts-cell .rq-star[data-on]{color:var(--signal)}
.rq-acts-cell .rq-star[data-on] svg{fill:var(--signal-soft);stroke-width:1.9}
.rq-acts-cell .icon-btn.copied{background:var(--good-soft);color:var(--good)}


/* ---- the new-version bar -------------------------------------------------
   Bottom LEFT, not centre: the toast owns the centre and this can be on screen
   at the same time as one. Quiet on purpose -- it is a fact worth knowing, not
   an alarm, and a rep mid-call must be able to ignore it without effort. */
.verbar{
  position:fixed;inset-inline-start:18px;bottom:22px;z-index:69;
  display:flex;align-items:center;gap:10px;
  padding:8px 10px 8px 14px;border-radius:var(--r);
  background:var(--panel);color:var(--ink);
  border:1px solid var(--line-strong);
  box-shadow:0 6px 22px rgba(0,0,0,.10);
  font-size:var(--t-body);max-width:min(420px,88vw);
  opacity:0;transform:translateY(6px);
  transition:opacity var(--t) var(--out),transform var(--t) var(--out);
}
.verbar.on{opacity:1;transform:none}
.verbar-go{
  padding:5px 11px;border-radius:var(--r);border:0;cursor:pointer;
  background:var(--s90);color:var(--s0);font:inherit;font-weight:600;
}
:root[data-theme="dark"] .verbar-go{background:var(--s20);color:var(--s90)}
.verbar-x{
  width:24px;height:24px;flex:none;padding:0;line-height:1;
  border:0;background:transparent;color:var(--ink-3);cursor:pointer;
  font-size:16px;border-radius:var(--r);
}
.verbar-x:hover{background:var(--s10);color:var(--ink)}


/* ---- "Belongs to": pick the company, or add one ---------------------------
   A search that has to be READ before it is acted on, so the results are the
   loud thing and Add is quiet underneath them. That ordering is the guard: a
   rep who skims and presses the first button gets the company that already
   exists, not a second copy of it. */
.ed-link-now{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 0}
.ed-link-now b{font-weight:600}
.ed-link-box{display:flex;align-items:center;gap:8px;padding:6px 0}
.ed-link-box input{
  flex:1;min-width:0;padding:7px 10px;border-radius:var(--r);
  border:1px solid var(--line-strong);background:var(--panel);color:var(--ink);
  font:inherit;
}
.ed-link-hits{display:flex;flex-direction:column;gap:4px;margin:4px 0 2px}
.ed-hit{
  display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;width:100%;
  text-align:start;padding:8px 10px;border-radius:var(--r);cursor:pointer;
  border:1px solid var(--line);background:var(--panel);color:var(--ink);font:inherit;
  transition:background var(--t-fast) var(--out),border-color var(--t-fast) var(--out);
}
.ed-hit:hover{background:var(--s10);border-color:var(--line-strong)}
.eh-n{font-weight:600}
.eh-ar{color:var(--ink-2)}
.eh-m{margin-inline-start:auto;color:var(--ink-3);font-size:var(--t-micro)}
/* Quieter than the results above it, and it carries its own sentence about why
   it might be the wrong button. */
.ed-link-add{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;padding:6px 0 2px}
.ed-link-why{color:var(--ink-3);font-size:var(--t-micro);flex:1;min-width:12ch}


/* ---- one order, several machines ----------------------------------------
   Awab asked for a different colour, and the reason it earns one is that it is
   a different KIND of row: everything else in this table is one request, and
   this is a container for several. It is tinted rather than coloured -- the
   status column still has to be the loud thing on the screen. */
/* MEASURED, then strengthened. The first version tinted with --s5 (#fafbfc)
   against a white row and it was invisible at normal viewing distance -- Awab
   asked for a different colour and got one that could only be found by reading
   the CSS. A row that is a CONTAINER for several requests, rather than one
   request, has to be legible as that at a glance. */
.rq-order > td{background:var(--s20)}
.rq-order:hover > td{background:var(--s30)}
.rq-order.on > td{background:var(--s20);border-bottom-color:transparent}
/* Bolder identity too, because the count and the caret are doing the semantic
   work and both were competing with a normal row's weight. */
.rq-order .lead-name{font-weight:600}
.rq-caret{
  display:inline-block;width:14px;margin-inline-end:2px;
  color:var(--ink-3);font-size:11px;line-height:1;
}
/* The count reads as a fact about the order, not as a status, so it is the
   neutral chip rather than one of the outcome tones. */
.bucket.order{
  background:var(--s20);color:var(--ink-2);border:1px solid var(--line-strong);
}
/* The machines inside it. Indented once, on the identity column only -- an
   indent on every cell would break the column alignment that lets a rep
   compare supply and bids down the table, which is the whole reason the
   per-machine rows are worth showing at all. */
.rq-child > td:first-child{padding-inline-start:26px;position:relative}
.rq-child > td:first-child::before{
  content:"";position:absolute;inset-block:0;inset-inline-start:12px;
  width:1px;background:var(--line-strong);
}
.rq-child > td{background:var(--panel)}


/* ---- email and "All details" in the customer strip ----------------------
   Both sit in the same unlabelled strip as the phone and the city, because they
   are the same kind of thing: a value that says what it is by looking like
   itself. An address needs no label reading "Email". */
.idbit-mail{
  display:inline-flex;align-items:center;gap:5px;
  color:var(--ink-2);text-decoration:none;
}
.idbit-mail svg{width:12px;height:12px;flex:none;color:var(--ink-3)}
.idbit-mail:hover{color:var(--ink);text-decoration:underline}
/* Several addresses on one company each get their own chip rather than being
   joined with commas — a rep is choosing one to send to, and a comma-separated
   run of addresses is a thing you have to parse before you can pick. */
.idbit-mail + .idbit-mail{margin-inline-start:10px}
/* The way to the whole record. A button rather than a link because it opens a
   surface rather than navigating, and quiet because it is an offer, not the
   answer to what the strip is showing. */
.idbit-more{
  display:inline-flex;align-items:center;gap:5px;
  padding:2px 8px;border-radius:var(--r-pill);cursor:pointer;
  border:1px solid var(--line);background:transparent;
  color:var(--ink-2);font:inherit;font-size:var(--t-micro);
  transition:background var(--t-fast) var(--out),color var(--t-fast) var(--out),
             border-color var(--t-fast) var(--out);
}
.idbit-more svg{width:12px;height:12px;flex:none}
.idbit-more:hover{background:var(--s10);color:var(--ink);border-color:var(--line-strong)}


/* Disqualify, beside Qualify on an OS row. Quiet at rest and only red on
   hover: it sits next to the two buttons a rep presses all day, and a
   permanently red control in that row would pull the eye away from the move
   they actually came to make. The colour arrives when the pointer does, which
   is the moment it means something. */
.rewind.dq{color:var(--ink-3)}
.rewind.dq:hover{
  background:var(--signal);border-color:var(--signal);color:var(--s0);
}

/* ---- Subscriptions: the product ledger + the OS funnel ------------------ */
#v-subscriptions .sec-h{flex-wrap:wrap;align-items:center}
#v-subscriptions .sec-h .chips{padding:0;margin-inline-start:4px}
#v-subscriptions .sec-h > .dim{margin-inline-start:auto}
#v-subscriptions .stats{
  display:grid;grid-template-columns:repeat(7,minmax(0,1fr));
  border:1px solid var(--line);background:var(--line);gap:1px;
}
#v-subscriptions .stat{background:var(--panel);padding:7px 10px;min-width:0}
#v-subscriptions .stat-n{
  font-family:var(--mono);font-size:var(--t-body);line-height:18px;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
#v-subscriptions .stat-l{
  font-size:10px;line-height:14px;color:var(--ink-3);
  text-transform:uppercase;letter-spacing:.04em;
}
#v-subscriptions .stat.good .stat-n{color:var(--good)}
#v-subscriptions .stat.bad .stat-n{color:var(--signal)}
#v-subscriptions .stat.muted .stat-n{color:var(--ink-3)}
#v-subscriptions .stats.dim .stat-n{color:var(--ink-3)}
#v-subscriptions .sb-sub{
  font-size:10px;line-height:14px;color:var(--ink-3);text-transform:uppercase;
  letter-spacing:.04em;margin:10px 0 4px;
}
#v-subscriptions .sb-bars{display:flex;align-items:flex-end;gap:3px;height:64px;margin-top:10px;overflow-x:auto}
#v-subscriptions .sb-bar{
  flex:1 0 14px;max-width:28px;display:flex;flex-direction:column;align-items:center;
  justify-content:flex-end;height:100%;position:relative;
}
#v-subscriptions .sb-bar i{display:block;width:100%;background:var(--ink-3);border-radius:2px 2px 0 0}
#v-subscriptions .sb-bar b{
  position:absolute;top:0;font-family:var(--mono);font-size:10px;color:var(--good);
}
#v-subscriptions .sb-bar s{
  text-decoration:none;font-size:9px;line-height:12px;color:var(--ink-3);white-space:nowrap;
}
#v-subscriptions .sb-pending{color:var(--signal)}
#v-subscriptions .sb-approved{color:var(--good)}
#v-subscriptions .sb-rejected,#v-subscriptions .sb-cancelled,
#v-subscriptions .sb-cancelled_request,#v-subscriptions .sb-expired{color:var(--ink-3)}
@media (max-width:860px){
  #v-subscriptions .stats{grid-template-columns:repeat(4,minmax(0,1fr))}
}

/* the requester's context on a Subscriptions row + the expanded card */
#v-subscriptions .ctxs{display:flex;flex-wrap:wrap;gap:4px;margin-top:5px}
#v-subscriptions .ctx{font-size:10.5px;line-height:16px;border:1px solid var(--line);border-radius:4px;padding:0 6px;color:var(--ink);white-space:nowrap}
#v-subscriptions .ctx.good{border-color:var(--good);color:var(--good)}
#v-subscriptions .ctx.bad{border-color:var(--signal);color:var(--signal)}
#v-subscriptions .ctx.muted{color:var(--ink-3)}
#v-subscriptions .reason{font-size:11.5px;margin-top:5px;max-width:460px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#v-subscriptions .sb-exp{margin-inline-start:6px;font-size:10px;padding:0 6px}
#v-subscriptions tr.on td{background:color-mix(in srgb,var(--panel) 94%,var(--line))}
#v-subscriptions tr.sb-open td{background:color-mix(in srgb,var(--panel) 92%,var(--line));padding:10px 12px}
#v-subscriptions .card{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px}
#v-subscriptions .grp b{display:block;font-size:10px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3);margin-bottom:4px}
#v-subscriptions .kv{display:flex;gap:6px;font-size:11.5px;line-height:1.35;margin:2px 0}
#v-subscriptions .kv .k{color:var(--ink-3);flex:0 0 96px}
#v-subscriptions .kv .v{min-width:0;overflow:hidden;text-overflow:ellipsis}
#v-subscriptions .logins{font-size:11px;color:var(--ink-3);margin-top:4px}
@media (max-width:900px){#v-subscriptions .card{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* the deal forms inside an expanded Subscriptions row */
#v-subscriptions .sb-form{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:flex-end;margin-bottom:12px;padding-bottom:10px;border-bottom:1px solid var(--line)}
#v-subscriptions .sb-form b{flex:0 0 100%;font-size:12px}
#v-subscriptions .sb-form label{display:flex;flex-direction:column;gap:3px;font-size:11px;color:var(--ink-3)}
#v-subscriptions .sb-form label.wide{flex:1 1 260px}
#v-subscriptions .sb-form .field{min-width:110px}
#v-subscriptions .sb-form-b{flex:0 0 100%}
#v-subscriptions .sb-form-hint{flex:0 0 100%;font-size:11px}
#v-subscriptions .sb-log{margin-top:10px;font-size:11px;color:var(--ink-3)}
#v-subscriptions .sb-log b{display:block;font-size:10px;letter-spacing:.04em;text-transform:uppercase;margin-bottom:3px}
#v-subscriptions a.doc{font-size:10px;border:1px solid var(--line);border-radius:3px;padding:0 4px;font-family:var(--mono);text-decoration:none;color:inherit}
#v-subscriptions .sec-note{font-size:11.5px;margin-top:8px}

/* Add-a-supplier row at the foot of the search dropdown, and the subscription
   marker on an OS row (27 Sep 2026). */
.find-add{border-top:1px solid var(--line);color:var(--ink-2)}
.find-add .find-nm{font-weight:500}
a.lead-hand.os-sub{display:inline-block;text-decoration:none;color:var(--ink-2);
  border-bottom:1px dotted var(--ink-3)}
a.lead-hand.os-sub.paid{color:var(--ok,#1a7f4b)}
a.lead-hand.os-sub:hover{color:var(--ink)}

/* Subscription status column + filter on the OS stages (27 Sep 2026). */
.substat{display:inline-block;font-size:var(--t-micro);padding:2px 8px;border-radius:999px;
  background:var(--s10);color:var(--ink-2);white-space:nowrap}
.substat-paid{background:color-mix(in srgb,var(--ok,#1a7f4b) 14%,transparent);color:var(--ok,#1a7f4b);font-weight:600}
.substat-requested{background:color-mix(in srgb,var(--signal) 12%,transparent);color:var(--ink);font-weight:600}
.substat-trial{color:var(--ink)}
.substat-ended,.substat-lapsed,.substat-rejected{color:var(--ink-3)}
.substat-none{background:transparent;color:var(--ink-3)}
select.chip.subf{appearance:auto;cursor:pointer}
select.chip.subf.on{border-color:var(--ink);color:var(--ink);font-weight:600}

a.substat{text-decoration:none}
a.substat:hover{outline:1px solid currentColor}

/* Came from + Product dropdowns, and the two merged cells (29 Sep 2026). */
#v-subscriptions .sec-h{align-items:center;flex-wrap:wrap}
#v-subscriptions .sb-filter{display:inline-flex;align-items:center;gap:6px;font-size:var(--t-micro);color:var(--ink-3)}
#v-subscriptions .sb-filter .field{width:auto;min-width:0}
#v-subscriptions .sec-h > .dim{margin-inline-start:auto}
#v-subscriptions .sb-prod,#v-subscriptions .sb-ans{margin-top:6px;padding-top:6px;border-top:1px dashed var(--line)}

/* Status actions, payment cell and the decide dialog (29 Sep 2026). */
#v-subscriptions .sb-acts{display:flex;gap:6px;margin-top:6px;flex-wrap:wrap}
#v-subscriptions .sb-go{border-color:var(--good);color:var(--good);font-weight:600}
#v-subscriptions .sb-no{color:var(--signal)}
#v-subscriptions .sb-void{margin-top:4px;color:var(--signal)}
#v-subscriptions .sb-void-f{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.sb-danger{border-top:4px solid var(--signal)}
.sb-warn{display:flex;gap:12px;align-items:flex-start;padding:12px 14px;border-radius:10px;background:var(--signal-soft);color:var(--ink);font-size:var(--t-body);line-height:var(--lh-body)}
.sb-warn svg{width:26px;height:26px;flex:none;color:var(--signal)}
.sb-warn b{color:var(--signal)}
.sb-warn-pay{margin-top:8px;font-size:var(--t-micro);color:var(--ink-2)}
.sb-dec-r{display:flex;flex-direction:column;gap:4px;margin-top:12px;font-size:var(--t-micro);color:var(--ink-3)}
.sb-dec-foot{display:flex;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--line)}
.sb-dec-go{background:var(--signal);border-color:var(--signal);color:#fff;font-weight:600}
.sb-dec-go[disabled]{opacity:.5}

/* Subscriptions card on the Workspace home: full width, the daily bars from the old OS funnel. */
.ws-sec.ws-wide{grid-column:1/-1}
.ws-subs-g{display:block;width:100%}
.ws-subs-g .sb-bars{display:flex;align-items:flex-end;gap:3px;height:64px;margin-top:6px;overflow-x:auto}
.ws-subs-g .sb-bar{flex:1 0 14px;max-width:28px;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%;position:relative}
.ws-subs-g .sb-bar i{display:block;width:100%;background:var(--ink-3);border-radius:2px 2px 0 0}
.ws-subs-g .sb-bar b{position:absolute;top:0;font-family:var(--mono);font-size:10px;color:var(--good)}
.ws-subs-g .sb-bar s{text-decoration:none;font-size:9px;line-height:12px;color:var(--ink-3);white-space:nowrap}
.ws-chip[aria-pressed="true"]{background:var(--ink);color:var(--s0);border-color:var(--ink)}
/* ---- templates ---------------------------------------------------------- */
#v-templates .tp-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:14px;padding:12px 16px 40px;align-items:start}
.tp-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);padding:12px 14px;display:flex;flex-direction:column;gap:8px;min-width:0}
.tp-card.on{border-color:var(--line-strong)}
.tp-card.tp-retired{opacity:.6}
.tp-head{display:flex;flex-direction:column;gap:4px;min-width:0}
.tp-name{font-size:15px;font-weight:600;overflow-wrap:anywhere;line-height:1.3}
.tp-facts{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:2px}
.tp-fact{font-size:var(--t-micro);color:var(--ink-3)}
.tp-fact+.tp-fact::before{content:"·";margin-right:6px;color:var(--line-strong)}
.tp-fact-bad{color:var(--signal)}
.tp-acts .mini-btn,.tp-acts button{border:1px solid var(--line-strong);background:var(--panel);color:var(--ink-2);border-radius:var(--r-pill);padding:4px 11px;font:inherit;font-size:var(--t-micro);cursor:pointer;text-decoration:none;line-height:1.4}
.tp-acts .mini-btn:hover,.tp-acts button:hover{border-color:var(--ink);color:var(--ink)}
.tp-acts{margin-top:2px}
.tp-names{min-width:0;display:flex;flex-direction:column;gap:2px}
.tp-names b{font-size:var(--t-body);font-weight:600;overflow-wrap:anywhere}
.tp-meta{font-size:var(--t-micro);color:var(--ink-3);overflow-wrap:anywhere}
.tp-pills{display:flex;gap:4px;flex-wrap:wrap;justify-content:flex-end;flex:none}
.tp-pill{font-size:var(--t-micro);line-height:1;padding:3px 7px;border-radius:var(--r-pill);border:1px solid var(--line-strong);color:var(--ink-2);white-space:nowrap}
.tp-pill.tp-st-active{border-color:var(--good);color:var(--good)}
.tp-pill.tp-st-retire{border-color:var(--signal);color:var(--signal)}
.tp-pill.tp-st-duplicate,.tp-pill.tp-st-variant{border-color:var(--warn);color:var(--warn)}
.tp-count{font-size:var(--t-micro);line-height:1;padding:3px 7px;border-radius:var(--r-pill);background:var(--ink);color:var(--s0);white-space:nowrap;font-variant-numeric:tabular-nums}
.tp-count .dim{color:var(--s40)}
.tp-count-0{background:transparent;color:var(--ink-3);border:1px dashed var(--line-strong)}
.tp-matches{margin:10px 16px 0;font-size:var(--t-micro);color:var(--ink-3)}
.tp-sel{border:1px solid var(--line-strong);background:var(--panel);color:var(--ink);border-radius:var(--r-pill);padding:4px 10px;font:inherit;font-size:var(--t-body);max-width:220px}
.tp-seg{display:inline-flex;border:1px solid var(--line-strong);border-radius:var(--r-pill);overflow:hidden}
.tp-seg button{border:0;background:var(--panel);color:var(--ink-2);padding:4px 12px;font:inherit;font-size:var(--t-body);cursor:pointer}
.tp-seg button[aria-pressed="true"]{background:var(--ink);color:var(--s0)}
.tp-new{border-color:var(--ink);color:var(--ink);font-weight:600}
.tc{margin:12px 16px 0;background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r);padding:12px 14px;display:flex;flex-direction:column;gap:10px}
.tc-ask textarea,.tc-in{width:100%;box-sizing:border-box;border:1px solid var(--line-strong);border-radius:8px;padding:8px 10px;font:inherit;font-size:var(--t-body);background:var(--s5);color:var(--ink)}
.tc-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:8px}
.tc-go{background:var(--ink);color:var(--s0);border-color:var(--ink)}
.tc-h{font-size:var(--t-micro);color:var(--ink-3);text-transform:uppercase;letter-spacing:.04em;margin-bottom:6px}
.tc-block{border-top:1px solid var(--line);padding-top:10px}
.tc-match{padding:8px 0;border-bottom:1px dashed var(--line)}
.tc-match:last-child{border-bottom:0}
.tc-near{background:var(--warn-soft);margin:0 -8px;padding:8px}
.tc-mbody{font-size:var(--t-body);color:var(--ink-2);margin:4px 0;unicode-bidi:plaintext}
.tc-warn{margin:0;padding:8px 10px;background:var(--warn-soft);border-radius:8px;font-size:var(--t-body)}
.tc-err{margin:4px 0 0;color:var(--signal);font-size:var(--t-body)}
.tc-ok{margin:4px 0 0;color:var(--good);font-size:var(--t-body)}
.tc-notes{font-size:var(--t-micro);margin:6px 0 0}
.tc-lab{display:flex;flex-direction:column;gap:3px;font-size:var(--t-micro);color:var(--ink-3);margin-top:6px}
.tc-langs{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:14px;margin-top:8px}
.tc-lang{display:flex;flex-direction:column;gap:6px}
.tc-body{min-height:120px;resize:vertical}
.tr{margin:12px 16px 0;background:var(--warn-soft);border:1px solid var(--warn);border-radius:var(--r);padding:12px 14px;display:flex;flex-direction:column;gap:10px}
.tr-item{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:6px}
.tr-head{display:flex;flex-wrap:wrap;gap:6px;align-items:baseline}
.tr-reason{flex:1;min-width:180px;width:auto}
.tp-more-row{flex:1 1 100%;display:flex;flex-wrap:wrap;gap:6px;padding-top:6px;border-top:1px dashed var(--line)}
#v-templates mark,.tp-card mark{background:#ffe58a;color:inherit;border-radius:2px;padding:0 1px}
.tp-pill.tp-prod-cw{border-color:#1f8a4c;color:#1f8a4c}
.tp-pill.tp-prod-app{border-color:#3b5bdb;color:#3b5bdb}
.tp-pill.tp-prod-web{border-color:#c2410c;color:#c2410c}
.tp-pill.tp-prod-os{border-color:#6d28d9;color:#6d28d9}
.tp-sum{margin:0;font-size:var(--t-body);line-height:var(--lh-body);color:var(--ink-2)}
.tp-flows{display:flex;gap:4px;flex-wrap:wrap}
.tp-flow{font-size:var(--t-micro);line-height:1;padding:3px 7px;border-radius:var(--r-pill);background:var(--s10);color:var(--ink-2);display:inline-flex;gap:5px;align-items:center}
.tp-flow .n{font-family:var(--mono);opacity:.7}
.tp-flow-dec{background:transparent;border:1px dashed var(--line-strong)}
.tp-flow-none{background:transparent;color:var(--signal)}
.tp-langs{display:flex;gap:4px}
.tp-langs .chip{padding:2px 8px;font-size:var(--t-micro)}
.tp-ph{font-family:var(--mono);font-size:.85em;background:rgba(0,0,0,.07);border-radius:4px;padding:0 4px}
.tp-draft{font-size:var(--t-micro);color:var(--warn);padding:4px 0 0}
.tp-acts{display:flex;gap:6px;flex-wrap:wrap}
.tp-acts .mini-btn{text-decoration:none}
.tp-more{border-top:1px solid var(--line);margin:0 -14px -12px;background:var(--s5)}
.tp-more .facts{grid-template-columns:64px 1fr}
.tp-vers{margin:0;padding-left:16px;display:flex;flex-direction:column;gap:6px}
.tp-vers li div{color:var(--ink-2)}
.tp-clamp{display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;overflow:hidden}
.tp-clamp4{display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}

/* WhatsApp, drawn as the phone draws a received business message: the chat
   wallpaper, a white bubble 300px wide at 15px, image header edge to edge,
   footer in grey, time and ticks bottom-right, buttons as a second card. */
.tp-wa{background:#e5ddd5;padding:12px;border-radius:var(--r);max-width:340px;font-family:-apple-system,"Segoe UI",Roboto,"Noto Sans Arabic",sans-serif}
.tp-wa-bub{background:#fff;border-radius:8px;padding:4px 6px 4px;box-shadow:0 1px 0 rgba(0,0,0,.08);max-width:300px;position:relative}
.tp-wa[dir="ltr"] .tp-wa-bub{border-top-left-radius:0}
.tp-wa[dir="rtl"] .tp-wa-bub{border-top-right-radius:0}
.tp-wa-img{display:block;width:100%;max-height:220px;object-fit:cover;border-radius:6px;margin-bottom:4px}
.tp-wa-img-none{display:flex;align-items:center;justify-content:center;height:120px;background:#eceff1;color:#667;font-size:12px}
.tp-wa-hdr{font-weight:700;color:#111;font-size:15px;line-height:1.35;padding:3px 3px 0;unicode-bidi:plaintext}
.tp-wa-body{color:#111;font-size:15px;line-height:1.35;padding:3px 3px 0;white-space:pre-wrap;overflow-wrap:anywhere;unicode-bidi:plaintext}
.tp-wa-body code{font-family:var(--mono);font-size:.9em}
.tp-wa-more{background:none;border:0;color:#027eb5;font:inherit;font-size:15px;padding:2px 3px;cursor:pointer;text-align:start}
.tp-wa-foot{color:#8696a0;font-size:13px;line-height:1.3;padding:3px 3px 0;unicode-bidi:plaintext}
.tp-wa-time{color:#667781;font-size:11px;text-align:end;padding:2px 3px 0}
.tp-wa-ticks{color:#53bdeb;letter-spacing:-3px}
.tp-wa-btns{max-width:300px;margin-top:2px;display:flex;flex-direction:column;gap:2px}
.tp-wa-btn{background:#fff;border-radius:8px;color:#027eb5;font-size:14px;padding:9px 8px;text-align:center;box-shadow:0 1px 0 rgba(0,0,0,.08);display:flex;gap:6px;justify-content:center;align-items:center}
.tp-wa-btn-ic{font-size:13px}

/* SMS, the plain text bubble under a sender id. */
.tp-sms{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:12px;max-width:340px;font-family:-apple-system,"Segoe UI",Roboto,"Noto Sans Arabic",sans-serif}
.tp-sms-from{text-align:center;font-size:11px;color:#8e8e93;margin-bottom:6px}
.tp-sms-bub{background:#e9e9eb;color:#000;border-radius:18px;padding:8px 12px;font-size:15px;line-height:1.35;max-width:270px;white-space:pre-wrap;overflow-wrap:anywhere;unicode-bidi:plaintext}
.tp-sms-time{font-size:11px;color:#8e8e93;margin-top:4px}

/* Email, the way an inbox opens it: subject, sender line, then the body. */
.tp-mail{background:#fff;border:1px solid var(--line);border-radius:var(--r);overflow:hidden;font-family:-apple-system,"Segoe UI",Roboto,"Noto Sans Arabic",sans-serif}
.tp-mail-head{padding:12px 14px 10px;border-bottom:1px solid #eee}
.tp-mail-subj{font-size:17px;font-weight:600;color:#111;margin-bottom:8px;overflow-wrap:anywhere}
.tp-mail-missing{color:var(--warn);font-weight:400;font-size:13px}
.tp-mail-row{display:flex;gap:10px;align-items:flex-start;font-size:13px;color:#111}
.tp-mail-row>div{flex:1;min-width:0;line-height:1.35}
.tp-mail-av{width:32px;height:32px;border-radius:50%;background:#1d1d1b;color:#fff;display:inline-flex;align-items:center;justify-content:center;font-weight:600;flex:none}
.tp-mail-time{font-size:12px}
.tp-mail-body{padding:14px;font-size:14px;line-height:1.5;color:#222;white-space:pre-wrap;overflow-wrap:anywhere;unicode-bidi:plaintext;max-height:360px;overflow:auto}
.tp-mail-frame{width:100%;height:360px;border:0;background:#fff}
.tp-mail .tp-draft{padding:6px 14px 10px}

/* Push, the lock-screen banner: rounded translucent card, app icon, app name
   and "now", title in bold, body up to four lines before it expands. */
.tp-push{background:#3a4356;padding:22px 14px;border-radius:var(--r);max-width:340px;font-family:-apple-system,"Segoe UI",Roboto,"Noto Sans Arabic",sans-serif}
.tp-push-card{background:rgba(245,245,247,.92);border-radius:18px;padding:10px 12px;display:flex;gap:10px;align-items:flex-start}
.tp-push-icon{width:36px;height:36px;border-radius:9px;flex:none;object-fit:cover;background:#1d1d1b}
.tp-push-text{flex:1;min-width:0}
.tp-push-app{font-size:12px;color:#3c3c43;display:flex;justify-content:space-between}
.tp-push-title{font-size:15px;font-weight:600;color:#000;line-height:1.3;overflow-wrap:anywhere;unicode-bidi:plaintext}
.tp-push-body{font-size:15px;color:#000;line-height:1.3;overflow-wrap:anywhere;unicode-bidi:plaintext;white-space:pre-wrap}
.tp-push .tp-wa-more{font-size:13px;padding:2px 0}
#v-subscriptions .sb-sort{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer;white-space:nowrap}
#v-subscriptions .sb-sort:hover{color:var(--ink)}

/* ── Test requests (Awab, 1 Oct 2026). Drawer at 115/116: above the topbar (100), below the modal veil (120). ─────────────────────────────────────────
   Spec: docs/proto/test-requests-uat.html. Only what the shared primitives
   (.sec, .chip, .act, table.q, .seg) do not already cover. */
#tr-body{position:relative}
.filters.tr-hide{display:none}
.tr-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;padding:12px 16px}
.tr-stats{display:flex;gap:18px;flex-wrap:wrap;font-size:var(--t-body)}
.tr-stats b{font-variant-numeric:tabular-nums;font-weight:600}
.tr-refresh{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.tr-refresh .act{flex:none;padding:6px 12px}
.tr-moved{font-size:var(--t-micro);color:var(--good)}
.tr-cols{display:grid;grid-template-columns:minmax(0,1fr) 340px;align-items:start}
.tr-right{border-inline-start:1px solid var(--line)}
.tr-gen{position:sticky;top:0}
@media (max-width:1000px){.tr-cols{grid-template-columns:1fr}.tr-right{border-inline-start:0}.tr-gen{position:static}}
.tr-input{width:100%;border:1px solid var(--line-strong);border-radius:var(--r);padding:7px 10px;font:inherit;background:var(--panel);color:var(--ink)}
.tr-search{position:relative;margin-bottom:10px}
.tr-dd{position:absolute;z-index:6;left:0;right:0;top:100%;margin-top:4px;background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r);box-shadow:0 8px 24px rgba(0,0,0,.08)}
.tr-dd button{display:grid;grid-template-columns:1fr 1fr auto;gap:10px;width:100%;text-align:start;border:0;background:none;padding:7px 10px;font:inherit;color:var(--ink);cursor:pointer}
.tr-dd button:hover{background:var(--s10)}
.tr-chips{display:flex;flex-wrap:wrap;gap:6px}
.tr-subs{margin-top:10px;padding-top:10px;border-top:1px dashed var(--line)}
.tr-sees-line{font-size:var(--t-body);margin-bottom:8px}
.tr-tiles{display:flex;gap:28px;flex-wrap:wrap}
.tr-tiles b{display:block;font-size:var(--t-head);font-weight:600;line-height:1.1;font-variant-numeric:tabular-nums}
.tr-tiles span{font-size:var(--t-micro);color:var(--ink-3)}
.tr-tg{display:inline-flex;gap:5px;align-items:center;font-size:var(--t-micro);color:var(--ink-2);cursor:pointer;margin-inline-start:14px}
.tr-tablewrap{max-height:460px;overflow:auto;border:1px solid var(--line);border-radius:var(--r);margin-bottom:6px}
.tr-table th{position:sticky;top:0;background:var(--bg);z-index:1}
.tr-table .num{text-align:end;font-variant-numeric:tabular-nums}
.tr-table tr.tr-off td{opacity:.5}
.tr-sort{border:0;background:none;padding:0;font:inherit;color:inherit;cursor:pointer;display:inline-flex;gap:4px;align-items:center}
.tr-sort span{font-size:10px;opacity:.45}
.tr-sort.on{color:var(--ink);font-weight:600}
.tr-sort.on span{opacity:1}
.tr-eye{border:1px solid var(--line-strong);background:var(--panel);border-radius:var(--r);padding:4px 7px;cursor:pointer;display:inline-flex;gap:6px;align-items:center;color:var(--ink-2);font:inherit;font-size:var(--t-micro);white-space:nowrap}
.tr-eye:hover{border-color:var(--ink-3);color:var(--ink)}
.tr-eye svg{display:block}
.tr-eye.busy svg{animation:tr-pulse 1s ease-in-out infinite}
@keyframes tr-pulse{50%{opacity:.25}}
.tr-pill{display:inline-block;font-size:11px;border-radius:999px;padding:2px 8px;margin-inline-end:4px;white-space:nowrap;background:var(--s10);color:var(--ink-2)}
.tr-pill.warn{background:var(--warn-soft);color:var(--warn)}
.tr-pill.good{background:var(--good-soft);color:var(--good)}
.tr-pill.bad{background:var(--signal-soft);color:var(--signal)}
.tr-pill.test{background:transparent;border:1px dashed var(--line-strong);color:var(--ink-3);font-size:10px;padding:1px 6px;vertical-align:middle}
/* Subscription analytics (Awab, 2 Oct): Overview + Paid. */
.sa-tabs{display:inline-flex}
.sa-tabs button{padding:5px 14px}
.sa-row{display:flex;gap:18px;align-items:baseline;flex-wrap:wrap;font-size:var(--t-body);padding:6px 0}
.sa-row b{font-variant-numeric:tabular-nums}
.sa-k{min-width:96px;font-weight:600;color:var(--ink-2)}
.sa-k.paid{color:var(--signal)}
.sa-split{font-size:var(--t-body);color:var(--ink-2);margin-top:6px;padding-top:8px;border-top:1px dashed var(--line)}
.sa-go{flex:none;padding:5px 12px;margin-inline-start:auto}
.sa-co{border:1px solid var(--line);border-radius:8px;padding:10px 12px;margin-bottom:8px;background:var(--panel)}
.sa-co.test{opacity:.6}
.sa-co-h{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;margin-bottom:6px}
.sa-bks{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin-bottom:8px}
@media (max-width:800px){.sa-bks{grid-template-columns:1fr}}
.sa-bk{border:1px solid var(--line-strong);border-radius:8px;padding:10px 12px;background:var(--panel);display:flex;flex-direction:column;gap:2px;font-size:var(--t-body)}
.sa-bk > b{font-size:var(--t-head);font-weight:600;font-variant-numeric:tabular-nums;line-height:1.2}
.sa-bk > b small{font-size:var(--t-body);font-weight:400;color:var(--ink-2)}
.sa-bk.warm .tr-bkn{color:var(--signal)}
.sa-bk.between .tr-bkn{color:var(--warn)}
.sa-bk.quiet .tr-bkn{color:var(--ink-3)}
.sa-bk-l{display:flex;gap:12px;flex-wrap:wrap;padding-top:6px;margin-top:4px;border-top:1px dashed var(--line);font-size:var(--t-micro)}
.sa-bk-l b{font-variant-numeric:tabular-nums}
.sa-trial-t{max-width:760px}
.sa-trial-t .good{color:var(--good)}
.sa-tot td{border-top:2px solid var(--line-strong);font-weight:500}
.sa-ladder{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.sa-step{border:1px solid var(--line);border-radius:8px;padding:6px 12px;background:var(--panel);display:flex;flex-direction:column;min-width:96px}
.sa-step b{font-size:var(--t-mid);font-variant-numeric:tabular-nums}
.sa-step span{font-size:var(--t-micro);color:var(--ink-3)}
.sa-arrow{color:var(--ink-3);font-size:18px}
.sa-reach{margin-inline-start:auto;font-size:var(--t-micro)}
.sa-day{margin-inline-start:12px;font-size:var(--t-micro);color:var(--ink-2);font-variant-numeric:tabular-nums}
.sa-line{display:flex;gap:16px;flex-wrap:wrap;font-size:var(--t-body);padding:3px 0}
.sa-line .sa-k{font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3)}

/* Request health strip: paid-only vs open to all, by bids (Awab, 1 Oct). One line. */
.tr-health{display:flex;gap:8px;align-items:stretch;padding:0 16px 10px;flex-wrap:wrap}
.tr-hl-t{font-size:var(--t-micro);font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-3);align-self:center;margin-inline-end:4px}
.tr-hl{flex:1 1 380px;display:flex;gap:14px;align-items:baseline;flex-wrap:wrap;text-align:start;border:1px solid var(--line-strong);background:var(--panel);border-radius:8px;padding:8px 12px;cursor:pointer;font:inherit;font-size:var(--t-body);color:var(--ink)}
.tr-hl[aria-pressed="true"]{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
.tr-hl b{font-variant-numeric:tabular-nums;font-weight:600}
.tr-hl-k{font-weight:600}
.tr-hl.paid .tr-hl-k{color:var(--signal)}
.tr-hl .warn b{color:var(--signal)}

/* Buckets + supply-vs-demand suggestions (Awab, 1 Oct). */
.tr-bks{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;padding:0 16px 12px}
@media (max-width:700px){.tr-bks{grid-template-columns:1fr}}
.tr-bk{text-align:start;border:1px solid var(--line-strong);background:var(--panel);border-radius:8px;padding:10px 12px;cursor:pointer;font:inherit;color:var(--ink);display:flex;flex-direction:column;gap:1px}
.tr-bk[aria-pressed="true"]{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}
.tr-bk b{font-size:var(--t-head);font-weight:600;font-variant-numeric:tabular-nums;line-height:1.2}
.tr-bk b small{font-size:var(--t-body);font-weight:400;color:var(--ink-2)}
.tr-bk span{font-size:var(--t-body)}
.tr-bk em{font-style:normal;font-size:var(--t-micro);color:var(--ink-3)}
.tr-bkn{font-size:var(--t-micro)!important;font-weight:600;letter-spacing:.05em;text-transform:uppercase}
.tr-bk.warm .tr-bkn{color:var(--signal)}
.tr-bk.between .tr-bkn{color:var(--warn)}
.tr-bk.quiet .tr-bkn{color:var(--ink-3)}
.tr-bkp{font-size:11px;border-radius:999px;padding:2px 8px;white-space:nowrap}
.tr-bkp.warm{background:var(--signal-soft);color:var(--signal)}
.tr-bkp.between{background:var(--warn-soft);color:var(--warn)}
.tr-bkp.quiet{background:var(--s10);color:var(--ink-2)}
.tr-bal-sum{font-size:var(--t-body);color:var(--ink-2);margin:0 0 8px}
.tr-bal{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;margin-bottom:6px}
.tr-bal-h,.tr-bal-r{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr) minmax(0,1fr) 70px;gap:14px;align-items:center;padding:8px 10px}
.tr-bal-h{background:var(--bg);font-size:var(--t-micro);color:var(--ink-3)}
.tr-bal-r{border-top:1px solid var(--line);cursor:pointer;font-size:var(--t-body)}
.tr-bal-r:hover,.tr-bal-r.on{background:var(--s10)}
.tr-bal-r.off{opacity:.55}
.tr-bar-c{display:flex;flex-direction:column;gap:4px;min-width:0}
.tr-bar{height:8px;border-radius:4px;min-width:4px;position:relative;overflow:hidden}
.tr-bar.sup{background:var(--good)}
.tr-bar.dem{background:var(--line-strong)}
.tr-bar.dem i{position:absolute;inset:0 auto 0 0;background:var(--signal)}
.tr-vd{display:inline-block;font-size:11px;border-radius:999px;padding:1px 8px;margin-top:3px}
.tr-vd.needs{background:var(--signal-soft);color:var(--signal)}
.tr-vd.covered{background:var(--good-soft);color:var(--good)}
.tr-vd.few,.tr-vd.none{background:var(--s10);color:var(--ink-2)}
.tr-use{flex:none;padding:4px 10px;font-size:var(--t-micro)}
.tr-linkbtn{border:0;background:none;padding:4px 0;color:var(--ink-2);text-decoration:underline dotted;cursor:pointer;font:inherit;font-size:var(--t-micro)}
.tr-nodemand{background:var(--signal-soft);color:var(--signal);border-radius:var(--r);padding:8px 12px;font-size:var(--t-body)}
.tr-sq{width:240px;flex:none;padding:5px 10px;font-size:var(--t-micro);margin-inline-start:14px}
.tr-pick4d{flex:none;padding:5px 12px;font-size:var(--t-micro);margin-inline-start:6px}
.tr-pick20{flex:none;margin-inline-start:auto;padding:5px 12px;font-size:var(--t-micro)}
.tr-kv{display:grid;grid-template-columns:80px 1fr;gap:8px;align-items:center;font-size:var(--t-body);margin-bottom:8px}
.tr-kv span{color:var(--ink-3);font-size:var(--t-micro)}
.tr-langs{display:inline-flex;margin:4px 0 10px}
.tr-langs button{padding:3px 12px}
.tr-phone{width:250px;margin:0 auto 8px;border-radius:34px;padding:9px;background:#111}
.tr-screen{border-radius:26px;height:250px;padding:22px 10px;background:linear-gradient(160deg,#2c4a3e,#0f2a24 60%,#1d1d26);color:#fff;text-align:center}
.tr-clock{font-size:42px;font-weight:300;line-height:1;margin-bottom:26px}
.tr-notif{text-align:start;background:rgba(245,245,245,.9);color:#111;border-radius:14px;padding:9px 11px}
.tr-n-top{display:flex;gap:6px;align-items:center;font-size:11px;color:#555;margin-bottom:3px}
.tr-n-ico{width:16px;height:16px;border-radius:4px;background:#0f6b3e;color:#fff;font-size:10px;display:grid;place-items:center;font-weight:700}
.tr-n-now{margin-inline-start:auto}
.tr-n-title{font-weight:600;font-size:13px}
.tr-n-body{font-size:12.5px;display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.tr-gen > .act{width:100%;margin-top:10px;padding:9px}
.tr-box{margin-top:10px;border:1px solid var(--line-strong);border-radius:var(--r);padding:12px;font-size:var(--t-body)}
.tr-box > div{margin:3px 0}
.tr-big{font-size:var(--t-mid)}
.tr-row{display:flex;gap:8px;justify-content:flex-end;margin-top:10px}
.tr-row .act{flex:none;padding:6px 14px}
.tr-bar{height:6px;background:var(--s10);border-radius:3px;overflow:hidden;margin-top:6px}
.tr-bar i{display:block;height:100%;background:var(--ink);transition:width .3s}
.tr-crow{cursor:pointer}
.tr-crow:hover td,.tr-crow.on td{background:var(--s10)}
.tr-rtable{width:100%;margin:4px 0 8px}.tr-rtable td,.tr-rtable th{padding:6px 10px}
.tr-recips{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:4px 16px}
.tr-recip{display:flex;justify-content:space-between;gap:8px;font-size:var(--t-body);padding:3px 0;border-bottom:1px dashed var(--line)}
.tr-scrim{position:fixed;inset:0;background:rgba(20,23,27,.25);z-index:115}
.tr-drawer{position:fixed;top:0;right:0;bottom:0;width:min(440px,100vw);background:var(--panel);border-inline-start:1px solid var(--line);padding:16px;overflow:auto;z-index:116;box-shadow:-12px 0 30px rgba(0,0,0,.12)}
.tr-dhead{display:flex;justify-content:space-between;gap:10px;margin-bottom:8px}
.tr-dhead .act{flex:none;padding:6px 12px}
.tr-dcount{font-size:var(--t-body);margin:4px 0 10px}
.ap-phone{border:9px solid #111;border-radius:30px;background:#f6f7f8;overflow:hidden;font-family:'Noto Sans Arabic',system-ui,sans-serif;margin:6px 0}
.ap-top{background:linear-gradient(120deg,#0f6b3e,#0b4f2e);color:#fff;padding:14px;font-size:18px;font-weight:700}
.ap-sec{font-weight:700;font-size:15px;padding:12px 14px 6px;color:#1b2a3a}
.ap-rail{display:flex;gap:10px;overflow-x:auto;padding:2px 14px 12px;scroll-snap-type:x mandatory}
.ap-card{flex:0 0 168px;scroll-snap-align:start;background:#fff;border:1px solid #e3e6ea;border-radius:12px;overflow:hidden;display:flex;flex-direction:column}
.ap-card.unv{border-color:#f1a99a}
.ap-flag{background:#fde4df;color:#c0362c;font-size:11px;padding:3px 8px;font-weight:600}
.ap-flag.dir{background:#e2efe9;color:#1f6b4a}
.ap-img{height:70px;background:linear-gradient(135deg,#d9dde2,#eef0f2);display:flex;gap:4px;align-items:flex-end;padding:5px}
.ap-tag{background:rgba(60,64,70,.8);color:#fff;font-size:10px;border-radius:5px;padding:1px 5px}
.ap-body{padding:7px 9px;flex:1}
.ap-blur{filter:blur(4px)}
.ap-t{font-weight:700;font-size:13px}
.ap-m{font-size:11.5px;color:#555}
.ap-co{font-size:11.5px;color:#333;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ap-d{font-size:11px;color:#999}
.ap-btn{margin:6px 8px 8px;background:#f26b1d;color:#fff;text-align:center;border-radius:8px;padding:5px;font-size:12px;font-weight:600;display:flex;gap:5px;justify-content:center;align-items:center}
.ap-btn.grey{background:#e6e8eb;color:#444}
.ap-none{color:#999;font-size:12px;padding:10px}
.ap-card.sk,.ap-sk{background:linear-gradient(90deg,#e9ecef 25%,#f4f5f7 50%,#e9ecef 75%);background-size:200% 100%;animation:tr-shim 1.2s linear infinite;border:0}
.ap-card.sk{height:190px}
.ap-sk{height:14px;width:35%;border-radius:4px;margin:14px 14px 8px}
@keyframes tr-shim{to{background-position:-200% 0}}
@media (prefers-reduced-motion:reduce){.tr-eye.busy svg,.ap-card.sk,.ap-sk{animation:none}}

/* ===================== Suppliers & equipment, c-hub skin ===================
   Awab, 3 Oct 2026: this page, and every screen it opens, wears c-hub's design
   system; the rest of the Sales Desk keeps its own. c-hub's system is Tailwind's
   gray scale plus a handful of shapes (apps/c-hub/app/globals.css,
   components/shared/DataTable.tsx in the product repo), so the skin is two
   things: the palette, swapped inside this one view, and the shapes below.
   Light only, like c-hub itself -- dark keeps the module's dark palette above and
   takes the shapes. docs/proto/sales-suppliers-equipment-uat.html
   ========================================================================= */
@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]) #v-suppliers{
    --s0:#ffffff; --s5:#f9fafb; --s10:#f3f4f6; --s20:#e5e7eb; --s30:#d1d5db; --s40:#9ca3af;
    --s50:#6b7280; --s60:#4b5563; --s70:#374151; --s80:#1f2937; --s90:#111827;
    --ink:#111827; --ink-2:#4b5563; --ink-3:#6b7280; --line:#e5e7eb; --line-strong:#d1d5db;
    --bg:#f9fafb; --panel:#ffffff;
    --good:#15803d; --good-soft:#f0fdf4; --signal:#dc2626; --signal-soft:#fef2f2;
    --warn:#b45309; --warn-soft:#fffbeb;
  }
}
:root[data-theme="light"] #v-suppliers{
  --s0:#ffffff; --s5:#f9fafb; --s10:#f3f4f6; --s20:#e5e7eb; --s30:#d1d5db; --s40:#9ca3af;
  --s50:#6b7280; --s60:#4b5563; --s70:#374151; --s80:#1f2937; --s90:#111827;
  --ink:#111827; --ink-2:#4b5563; --ink-3:#6b7280; --line:#e5e7eb; --line-strong:#d1d5db;
  --bg:#f9fafb; --panel:#ffffff;
  --good:#15803d; --good-soft:#f0fdf4; --signal:#dc2626; --signal-soft:#fef2f2;
  --warn:#b45309; --warn-soft:#fffbeb;
}
#v-suppliers{
  --r:8px; --r-card:12px;
  --c-blue:#2563eb; --c-blue-soft:#eff6ff; --c-amber:#b45309; --c-amber-soft:#fffbeb;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans Arabic","Arabic UI Text","Geeza Pro",Arial,sans-serif;
  background:var(--bg);-webkit-font-smoothing:antialiased;
}

/* ---- the page frame ---- */
#v-suppliers .se{flex:1;min-height:0;overflow:auto;padding:20px;display:flex;flex-direction:column;gap:14px}
#v-suppliers .se > *{flex:none}
#v-suppliers .se-ph h1{margin:0;font-size:18px;line-height:24px;font-weight:600;letter-spacing:-.01em;color:var(--ink)}
#v-suppliers .se-ph p{margin:2px 0 0;font-size:13px;color:var(--ink-3)}
#v-suppliers .se-card,#v-suppliers .se .af-list{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden}
#v-suppliers .se-pad{padding:16px}
#v-suppliers .se-sub{font-size:12px;line-height:16px;color:var(--ink-3);margin-top:2px;unicode-bidi:plaintext}
#v-suppliers .se-dim{color:var(--ink-3)}
#v-suppliers .se-note{font-size:12px;color:var(--ink-3)}

/* ---- the search panel (the handoff's shape) ---- */
#v-suppliers .se-sp{padding:16px;display:flex;flex-direction:column;gap:12px}
#v-suppliers .se-row{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end}
#v-suppliers .se-fld{display:flex;flex-direction:column;gap:6px;font-size:12px;font-weight:500;color:var(--ink-3)}
#v-suppliers .se-fld.grow{flex:2 1 320px;min-width:0}
#v-suppliers .se-inp{height:46px;display:flex;align-items:center;gap:8px;padding:0 12px;border-radius:10px;
  box-shadow:inset 0 0 0 1px var(--line);background:var(--panel);color:var(--s40)}
#v-suppliers .se-inp:focus-within{box-shadow:inset 0 0 0 2px var(--ink)}
#v-suppliers .se-inp svg{width:16px;height:16px;flex:none}
#v-suppliers .se-inp input{flex:1;min-width:0;border:0;outline:0;background:transparent;font:inherit;font-size:15px;color:var(--ink)}
#v-suppliers .se-fld select{height:46px;min-width:170px;border:0;border-radius:10px;box-shadow:inset 0 0 0 1px var(--line);
  padding:0 10px;font:inherit;font-size:14px;color:var(--ink);background:var(--panel)}
#v-suppliers .se-fld select:focus,#v-suppliers .se-sort select:focus{outline:2px solid var(--ink);outline-offset:0}
#v-suppliers .se-seg{display:inline-flex;height:46px;padding:4px;gap:4px;border-radius:10px;background:var(--s10)}
#v-suppliers .se-seg button{border:0;background:transparent;border-radius:7px;padding:0 14px;font-size:14px;color:var(--ink-2);
  display:flex;align-items:center;gap:6px}
#v-suppliers .se-seg button i{font-style:normal;font-size:12px;color:var(--s40);font-variant-numeric:tabular-nums}
#v-suppliers .se-seg button[aria-pressed="true"]{background:var(--panel);color:var(--ink);font-weight:600;
  box-shadow:0 1px 2px rgba(0,0,0,.06),0 0 0 1px var(--line)}
#v-suppliers .se-ex{display:flex;flex-wrap:wrap;gap:6px;align-items:center;font-size:12px;color:var(--s40)}
#v-suppliers .se-ex button{height:28px;padding:0 12px;border:0;border-radius:999px;box-shadow:inset 0 0 0 1px var(--line);
  background:var(--panel);color:var(--ink-2);font-size:12.5px}
#v-suppliers .se-ex button:hover{box-shadow:inset 0 0 0 1px var(--line-strong);color:var(--ink)}

/* ---- chips, bars, pills ---- */
#v-suppliers .se-bar,#v-suppliers .se .af-strip{display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap;
  padding:12px 16px;border-bottom:1px solid var(--s10)}
#v-suppliers .se-bar.flush{padding:12px 0;border-top:1px solid var(--s10)}
#v-suppliers .se-chips{display:flex;flex-wrap:wrap;gap:6px;flex:1 1 300px}
#v-suppliers .chip{height:30px;padding:0 12px;border:0;border-radius:999px;box-shadow:inset 0 0 0 1px var(--line);
  background:var(--panel);color:var(--ink-2);font-size:12.5px;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
#v-suppliers .chip:hover{box-shadow:inset 0 0 0 1px var(--line-strong);color:var(--ink)}
#v-suppliers .chip[aria-pressed="true"]{background:var(--ink);color:var(--panel);box-shadow:none}
#v-suppliers .chip .n{font-size:12px;color:var(--s40);font-variant-numeric:tabular-nums}
#v-suppliers .chip[aria-pressed="true"] .n{color:inherit;opacity:.7}
#v-suppliers .chip.dash,#v-suppliers .chip.clear{box-shadow:none;border:1px dashed var(--line-strong)}
#v-suppliers .se-pill,#v-suppliers .sup-st,#v-suppliers .src-tag,#v-suppliers .pill{display:inline-flex;align-items:center;gap:4px;
  padding:2px 8px;border-radius:999px;font-size:11px;font-weight:500;line-height:16px;white-space:nowrap;text-decoration:none;
  border:0;background:var(--s5);color:var(--ink-2);box-shadow:inset 0 0 0 1px rgba(107,114,128,.2)}
#v-suppliers .se-pill.green,#v-suppliers .sup-st[data-s="Approved"]{background:var(--good-soft);color:var(--good);box-shadow:inset 0 0 0 1px rgba(22,163,74,.2)}
#v-suppliers .se-pill.red,#v-suppliers .sup-st[data-s="Rejected"]{background:var(--signal-soft);color:var(--signal);box-shadow:inset 0 0 0 1px rgba(220,38,38,.2)}
#v-suppliers .se-pill.amber,#v-suppliers .sup-st[data-s="Pending"]{background:var(--c-amber-soft);color:var(--c-amber);box-shadow:inset 0 0 0 1px rgba(217,119,6,.2)}
#v-suppliers .src-tag.mg{background:var(--c-blue-soft);color:var(--c-blue);box-shadow:inset 0 0 0 1px rgba(29,78,216,.2)}
#v-suppliers a.se-pill:hover{color:var(--ink);box-shadow:inset 0 0 0 1px var(--s40)}
#v-suppliers .src-tag{margin-inline-start:6px}

/* ---- tables: c-hub's DataTable ---- */
#v-suppliers .se .q{table-layout:auto}
#v-suppliers .se .q thead th{background:rgba(249,250,251,.8);border-bottom:1px solid var(--s10);padding:10px 16px;
  font-size:12px;font-weight:500;text-transform:uppercase;letter-spacing:.04em;color:var(--s40)}
#v-suppliers .se .q td,#v-suppliers .se .af-list .q td{padding:12px 16px;border-bottom:1px solid var(--s10);font-size:14px}
#v-suppliers .se .q tbody tr:hover{background:var(--s5)}
#v-suppliers .se .lead-name{font-weight:500;color:var(--ink);unicode-bidi:plaintext}
#v-suppliers .se .num{font-family:inherit;font-variant-numeric:tabular-nums}
#v-suppliers .se .af-count{font-size:13px;color:var(--ink-3)}
#v-suppliers .se .sr-own{height:32px;border:0;border-radius:8px;box-shadow:inset 0 0 0 1px var(--line);padding:0 8px;font:inherit;font-size:13px;background:var(--panel);color:var(--ink)}
#v-suppliers .more{border-top:1px solid var(--s10);color:var(--ink-2);font-size:13px;background:var(--panel)}

/* ---- the Company column ---- */
#v-suppliers .se-cocell{max-width:220px}
#v-suppliers .se-co{display:inline-flex;align-items:center;gap:4px;max-width:100%;color:var(--ink);text-decoration:none;font-weight:500}
#v-suppliers .se-co span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;unicode-bidi:plaintext}
#v-suppliers .se-co:hover{color:var(--c-blue)}
#v-suppliers .se-co.none{color:var(--ink-3);font-weight:400}
#v-suppliers .se-co svg{width:13px;height:13px;flex:none;color:var(--s40)}
#v-suppliers .se-co .v-tick svg{color:var(--c-blue)}
#v-suppliers .pg-co{display:flex;align-items:baseline;gap:8px;margin-top:4px;flex-wrap:wrap}

/* ---- one equipment type ---- */
#v-suppliers .se-tv{padding:16px;display:flex;flex-direction:column;gap:12px}
#v-suppliers .se-back{border:0;background:none;padding:0;font-size:13px;color:var(--ink-3);align-self:flex-start}
#v-suppliers .se-back:hover{color:var(--ink)}
#v-suppliers .se-tvh{display:flex;justify-content:space-between;align-items:flex-end;gap:12px;flex-wrap:wrap}
#v-suppliers .se-tvh h2{margin:0;font-size:18px;font-weight:600;color:var(--ink);unicode-bidi:plaintext}
#v-suppliers .se-sum{font-size:13px;color:var(--ink-2)}
#v-suppliers .se-sort{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--ink-3)}
#v-suppliers .se-sort select{height:32px;border:0;border-radius:8px;box-shadow:inset 0 0 0 1px var(--line);padding:0 8px;font:inherit;font-size:13px;background:var(--panel);color:var(--ink)}
#v-suppliers .se-cards{display:flex;flex-direction:column;gap:8px}
#v-suppliers .se-sc{display:flex;gap:12px;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;padding:14px;
  border:1px solid var(--line);border-radius:var(--r-card);transition:border-color 120ms}
#v-suppliers .se-sc:hover{border-color:var(--line-strong)}
#v-suppliers .se-scm{flex:1 1 320px;min-width:0;display:flex;flex-direction:column;gap:6px}
#v-suppliers .se-yards{display:flex;flex-wrap:wrap;gap:4px}
#v-suppliers .se-facts{display:flex;flex-wrap:wrap;gap:4px 12px;font-size:12.5px;color:var(--ink-2);align-items:center}
#v-suppliers .se-doc{font-family:var(--mono);font-size:11px;color:var(--ink-3)}
#v-suppliers .se-sca{display:flex;gap:6px;flex-wrap:wrap}
#v-suppliers .se-btn,#v-suppliers .act,#v-suppliers .mini-btn,#v-suppliers .back,#v-suppliers .confirm{display:inline-flex;align-items:center;gap:6px;
  height:30px;padding:0 10px;border:0;border-radius:8px;background:var(--panel);box-shadow:inset 0 0 0 1px var(--line);
  color:var(--s70);font-size:12.5px;font-weight:500;white-space:nowrap}
#v-suppliers .se-btn:hover,#v-suppliers .act:hover,#v-suppliers .mini-btn:hover,#v-suppliers .back:hover{box-shadow:inset 0 0 0 1px var(--line-strong);background:var(--s5)}
#v-suppliers .se-btn svg,#v-suppliers .act svg{width:14px;height:14px}
#v-suppliers .se-btn.dark,#v-suppliers .act.primary,#v-suppliers .confirm,#v-suppliers .mini-btn.primary,
#v-suppliers .act.icon.primary{background:var(--ink);color:var(--panel);box-shadow:none}
#v-suppliers .act.icon{width:30px;justify-content:center;padding:0}
#v-suppliers .mini-btn[aria-pressed="true"]{background:var(--ink);color:var(--panel);box-shadow:none}

/* ---- the supplier page, and everything it opens ---- */
#v-suppliers .af-page{height:auto;flex:1;min-height:0;overflow:auto;padding:20px;gap:14px}
#v-suppliers .af-page > *{flex:none}
#v-suppliers .pg-head{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);padding:16px;gap:14px}
#v-suppliers .pg-head h2{font-size:18px;line-height:24px;gap:8px;flex-wrap:wrap}
#v-suppliers .pg-sub{font-size:13px;line-height:18px;margin-top:2px}
#v-suppliers .stats{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;gap:0;
  grid-template-columns:repeat(auto-fit,minmax(96px,1fr))}
#v-suppliers .stat{padding:12px 16px;border-inline-start:1px solid var(--s10)}
#v-suppliers .stat-n{font-family:inherit;font-variant-numeric:tabular-nums;font-size:18px;line-height:24px;font-weight:600}
#v-suppliers .stat-l{font-size:11px;font-weight:500;color:var(--ink-3)}
#v-suppliers .pg-cols{gap:14px;flex:none;min-height:0;align-items:flex-start}
#v-suppliers .rail{width:260px;border:0;padding:0;overflow:visible;display:flex;flex-direction:column;gap:12px}
#v-suppliers .rail-sec{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);padding:12px 14px}
#v-suppliers .rail-sec + .rail-sec{margin-top:0;padding-top:12px;border-top:1px solid var(--line)}
#v-suppliers .rail-sec h3,#v-suppliers .pane-body h3{font-size:11px;letter-spacing:.05em;color:var(--ink-3);margin-bottom:8px}
#v-suppliers .kv{font-size:13px}
#v-suppliers .sr-pane{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;min-height:420px}
#v-suppliers .tabs{padding:8px 12px 0;border-bottom:1px solid var(--s10);gap:4px}
#v-suppliers .tabs button{border:0;border-bottom:2px solid transparent;background:none;padding:8px 10px;font-size:13px;color:var(--ink-3)}
#v-suppliers .tabs button[aria-pressed="true"]{color:var(--ink);border-bottom-color:var(--ink);font-weight:600}
#v-suppliers .pane-body{padding:14px 16px}
#v-suppliers .eq-grid{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px}
#v-suppliers .eq-card{border-radius:10px;border-color:var(--line);background:var(--panel)}
#v-suppliers .eq-card:hover{border-color:var(--line-strong)}
#v-suppliers .img-tile{border-radius:8px;background:var(--s5)}
#v-suppliers .gap-note{font-size:12px;color:var(--ink-3)}
#v-suppliers .warn-box{border-radius:8px;background:var(--c-amber-soft);color:var(--c-amber);border:0}

/* dialogs: machine, edit machine, edit record, survey, report, Compose */
#v-suppliers .modal-veil{background:rgba(17,24,39,.35)}
#v-suppliers .modal{border-radius:var(--r-card);box-shadow:0 20px 40px rgba(0,0,0,.18)}
#v-suppliers .modal-h{padding:14px 16px;border-bottom:1px solid var(--s10)}
#v-suppliers .modal-h b{font-size:15px;font-weight:600}
#v-suppliers .modal-b{padding:14px 16px}
#v-suppliers .modal-x{width:28px;height:28px;border-radius:999px;background:var(--s10);border:0;display:grid;place-items:center}
#v-suppliers .ed input,#v-suppliers .ed select,#v-suppliers .ed textarea,#v-suppliers .cp-req,#v-suppliers .cp-draft{
  border:0;border-radius:8px;box-shadow:inset 0 0 0 1px var(--line);background:var(--panel);font:inherit;font-size:14px}
#v-suppliers .ed input:focus,#v-suppliers .ed select:focus,#v-suppliers .ed textarea:focus,#v-suppliers .cp-draft:focus{outline:2px solid var(--ink);outline-offset:0}
#v-suppliers .cp-prev{border-radius:10px;background:var(--s5);box-shadow:inset 0 0 0 1px var(--line)}
#v-suppliers .se-pre{background:var(--c-blue-soft);color:var(--c-blue);border-radius:8px;padding:8px 10px}
#v-suppliers .se-pre b{color:inherit}
@media (max-width:760px){
  #v-suppliers .se,#v-suppliers .af-page{padding:12px}
  #v-suppliers .pg-cols{flex-direction:column}
  #v-suppliers .rail{width:auto}
}
#v-suppliers .se-scm .lead-name,#v-suppliers .se-scm .se-sub{text-align:left}
#v-suppliers .se-nosize{font-size:13px;color:var(--c-amber);background:var(--c-amber-soft);border-radius:8px;padding:10px 12px}

/* ---- Subscription area in c-hub's look (Awab, 3 Oct 2026: B-2) ----------
   c-hub is the product's admin (RFQ Agent apps/c-hub): gray-50 page, white
   rounded cards with gray-200 borders, gray-900 ink, underlined tabs. Scoped
   to body.ch-dom, which domPaint sets only inside an area, so no other Sales
   Desk page changes. The tokens are re-pointed rather than every rule
   rewritten, so the screens moved in (Subscriptions, Test requests) follow. */
body.ch-dom .main{
  --s0:#ffffff;--s5:#f9fafb;--s10:#f9fafb;--s20:#e5e7eb;--s30:#d1d5db;--s40:#9ca3af;
  --s50:#6b7280;--s60:#4b5563;--s70:#374151;--s80:#1f2937;--s90:#111827;
  --bg:#f9fafb;--panel:#ffffff;--line:#e5e7eb;--line-strong:#d1d5db;
  --ink:#111827;--ink-2:#4b5563;--ink-3:#6b7280;--r:8px;
  --font:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Noto Sans Arabic',Arial,sans-serif;
  background:var(--bg);color:var(--ink);font-family:var(--font)
}
body.ch-dom .main .view.on{padding:0 20px 24px}
body.ch-dom #dom-bar{padding:4px 20px 0}
body.ch-dom .ch-tabs{display:flex;gap:4px;border-bottom:1px solid #e5e7eb;margin:8px 0 16px}
body.ch-dom .ch-tabs button{border:0;background:none;padding:9px 14px;font:inherit;font-size:14px;color:#6b7280;border-bottom:2px solid transparent;margin-bottom:-1px;cursor:pointer}
body.ch-dom .ch-tabs button:hover{color:#111827}
body.ch-dom .ch-tabs button[aria-selected="true"]{color:#111827;font-weight:600;border-bottom-color:#111827}
body.ch-dom .ch-crumb{font-size:13px;color:#6b7280;margin:-6px 0 12px}
body.ch-dom .ch-crumb a{color:#111827}
body.ch-dom .main .sec{background:#fff;border:1px solid #e5e7eb;border-radius:12px;padding:16px 18px;margin:0 0 16px}
body.ch-dom .main .sec-h b{font-weight:600;color:#374151}
body.ch-dom .main .q thead th{background:rgba(249,250,251,.8);color:#6b7280}
body.ch-dom .main .q tbody tr + tr td{border-top-color:#f3f4f6}
body.ch-dom .main .tr-pill{border-radius:999px}
body.ch-dom .main .act[data-primary]{background:#111827;color:#fff;border-color:#111827;border-radius:8px}
/* Analytics top */
.ch-grid{display:grid;grid-template-columns:3fr 2fr;gap:16px;align-items:start}
@media (max-width:900px){.ch-grid{grid-template-columns:1fr}}
.ch-grid .sec{margin:0}
#sa-top .sec-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
#sa-top .sd-days{margin-left:auto}
#sa-top .sb-bars{display:flex;align-items:flex-end;gap:3px;height:96px;margin-top:10px;overflow-x:auto}
#sa-top .sb-bar{flex:1 0 12px;max-width:28px;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%;position:relative}
#sa-top .sb-bar i{display:block;width:100%;background:#9ca3af;border-radius:3px 3px 0 0}
#sa-top .sb-bar b{position:absolute;top:0;font-family:var(--mono);font-size:10px;color:var(--good)}
#sa-top .sb-bar s{text-decoration:none;font-size:9px;line-height:12px;color:#9ca3af;white-space:nowrap}
#sa-top{margin-bottom:16px}
.sd-ask{display:flex;gap:8px;margin-top:8px}
.sd-ask .tr-input{flex:1;min-width:0}
.sd-ans{margin-top:12px;font-size:14px;line-height:1.55;white-space:pre-wrap}
.sd-figs{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:10px;font-size:12px}
/* Plays */
.sp-play{display:flex;gap:20px;align-items:center}
.sp-img{flex:0 0 auto}
.sp-phone{transform:scale(.82);transform-origin:left center;margin-right:-40px}
.sp-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px;align-items:flex-start}
.sp-stats{display:flex;gap:16px;flex-wrap:wrap;font-size:13px;color:var(--ink-2)}
.sp-stats b{color:var(--ink);font-size:16px;margin-right:3px}
.sp-step{border-top:1px solid #f3f4f6;padding:14px 0}
.sp-step:first-of-type{border-top:0}
.sp-step-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.sp-n{width:22px;height:22px;border-radius:50%;background:#111827;color:#fff;font-size:12px;font-weight:600;display:grid;place-items:center}
.sp-empty .sp-n{background:#e5e7eb;color:#6b7280}
.sp-step-b{display:grid;grid-template-columns:minmax(220px,320px) 1fr;gap:16px;align-items:start}
@media (max-width:760px){.sp-step-b{grid-template-columns:1fr}.sp-play{flex-direction:column;align-items:flex-start}}
.sp-wa{background:#e7ddd3;border-radius:10px;padding:10px}
.sp-bubble{background:#fff;border-radius:8px 0 8px 8px;padding:8px 10px;font-size:13px;line-height:1.6;color:#111827;box-shadow:0 1px 1px rgba(0,0,0,.08)}
#sa-top .sd-range{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:4px 0 10px}
#sa-top .sd-range label{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--ink-2)}
#sa-top .sd-range input[type=date]{font:inherit;font-size:13px;padding:5px 8px;border:1px solid var(--line);border-radius:8px;background:var(--panel);color:var(--ink)}
.sp-mode{display:inline-flex;align-items:center;gap:4px;font-size:12px;font-weight:500;border-radius:999px;padding:2px 9px;white-space:nowrap}
.sp-mode.auto{background:#eef2ff;color:#3730a3}
.sp-mode.human{background:#fef3c7;color:#92400e}
.sb-testnote{font-size:12px;padding:0 16px 8px}
.sb-testtag{font-size:11px;border:1px solid var(--line-strong);border-radius:999px;padding:0 6px;color:var(--ink-3);vertical-align:1px}

/* ---- Suppliers table: Listed breakdown, phone line, Excel export (Handoff 4, 13 Oct 2026) ---- */
#v-suppliers .sr-eqtd{white-space:nowrap}
#v-suppliers .sr-eqnew{background:#f8faff}
#v-suppliers thead th.sr-eqnew{background:#f1f5ff}
#v-suppliers .sr-newb{display:inline-block;margin-inline-start:6px;padding:0 5px;border-radius:4px;background:#2f6fed;color:#fff;
  font-size:9.5px;font-weight:600;letter-spacing:.04em;line-height:15px;vertical-align:1px}
#v-suppliers .sr-eqb{display:inline-flex;flex-direction:column;align-items:flex-end;gap:1px;padding:3px 7px;margin:-3px -7px;
  border:1px solid transparent;border-radius:6px;background:transparent;font:inherit;color:var(--ink);cursor:pointer;text-align:end}
#v-suppliers .sr-eqb:hover{border-color:var(--s10);background:var(--panel)}
#v-suppliers .sr-eqb:focus-visible{outline:2px solid #2f6fed;outline-offset:1px}
#v-suppliers .sr-eqb.open{border-color:#2f6fed;background:#fff}
#v-suppliers .sr-eqb.none{cursor:default;color:var(--ink-3)}
#v-suppliers .sr-eqb.none:hover{border-color:transparent;background:transparent}
#v-suppliers .sr-eqn{font-size:13.5px;font-weight:600;font-variant-numeric:tabular-nums}
#v-suppliers .sr-eqs{font-size:10.5px;color:#6b7280;font-weight:400}
#v-suppliers tr.sr-eqrow > td{background:#f8faff;padding:12px 16px 14px}
#v-suppliers tr.sr-eqrow:hover{background:transparent}
#v-suppliers .sr-eqhd{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:10px}
#v-suppliers .sr-eqhd b{display:block;font-size:13.5px;font-weight:600;color:var(--ink)}
#v-suppliers .sr-eqhd span{font-size:12px;color:#6b7280}
#v-suppliers .sr-eqx{border:0;border-radius:6px;padding:4px 10px;background:var(--panel);box-shadow:inset 0 0 0 1px var(--line);
  font:inherit;font-size:12px;color:var(--ink-2);cursor:pointer}
#v-suppliers .sr-eqx:hover{color:var(--ink)}
#v-suppliers .sr-eqchips{display:flex;flex-wrap:wrap;gap:6px}
#v-suppliers .sr-eqchip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:999px;background:#fff;
  box-shadow:inset 0 0 0 1px #e6e8ec;font-size:12px;color:var(--ink);unicode-bidi:plaintext}
#v-suppliers .sr-eqchip b{font-weight:600;font-variant-numeric:tabular-nums}
#v-suppliers .sr-ph{display:inline-flex;align-items:center;gap:5px;margin:2px 0 1px;padding:0;border:0;background:none;cursor:pointer;
  font-family:var(--mono);font-size:11.5px;color:#374151;direction:ltr;unicode-bidi:isolate}
#v-suppliers .sr-ph svg{width:11px;height:11px;flex:none;color:#6b7280}
#v-suppliers .sr-ph:hover,#v-suppliers .sr-ph:hover svg{color:#2f6fed}
#v-suppliers .sr-xl{margin-inline-start:8px;height:32px;padding:0 12px;border:0;border-radius:8px;background:var(--panel);
  box-shadow:inset 0 0 0 1px var(--line);font:inherit;font-size:13px;color:var(--ink);cursor:pointer;white-space:nowrap}
#v-suppliers .sr-xl:hover{box-shadow:inset 0 0 0 1px var(--s40)}
#v-suppliers .sr-xl:disabled{color:var(--ink-3);cursor:default}
