/* =========================================================================
   concierge-assist.css — the session cockpit

   Lifted out of the page's own <style> block unchanged: styles live in a
   stylesheet, not in the document. It loads after chat-dock.css, which is
   where the inline block sat, so nothing about specificity or order moves.
   ========================================================================= */

/* Page-scoped only, authored from app.css tokens. Namespace .co-*.
   V3's .cc- and .ccd- classes, its gold price tint and its navy hero are not
   consulted; this page is authored from the requirement.
   (Do not write a star-slash pair in here: it ends the comment early and the
   next rule is eaten as error recovery. That killed .co-cockpit for a while.) */

/* ---- The open conversations ----------------------------------------------
   One tab per client the rep is in with right now. They are cards rather than
   the usual underlined tab row: each carries a face, a name and a company, and
   a hairline tab strip cannot hold three of those without turning into a list.

   The lit one takes the surface the page itself is on, so the tab and the
   cockpit under it read as one sheet. The quiet ones sit back on the control
   ground — never on the page's own colour, which would leave them with no edge
   at all. */
/* Left-aligned, starting under the title. */
.co-tabs { display: flex; justify-content: flex-start; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.co-tab {
  position: relative; flex: 0 1 260px; min-width: 0;
  display: flex; align-items: center; gap: 9px;
  padding: 9px 11px;
  background: var(--color-control);
  border: 1px solid var(--color-control-border); border-radius: 7px;
  cursor: pointer; text-align: left;
  transition: background 120ms, border-color 120ms, box-shadow 120ms;
}
.co-tab:hover { border-color: var(--color-text-subtle); }
.co-tab.is-on {
  background: var(--color-surface);
  border-color: var(--color-primary);
  box-shadow: inset 0 -3px 0 var(--color-primary);
}
.co-tab .avatar { width: 30px; height: 30px; font-size: 11px; flex: none; }
.co-tab__b { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.co-tab__n { font-size: 13px; font-weight: 600; color: var(--color-text);
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.co-tab__c { font-size: 11px; color: var(--color-text-subtle);
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* THE COUNTER. The same yellow speech bubble the board wears for the same
   fact — a client has spoken and nobody has answered — so the two surfaces are
   saying one thing twice rather than two things. It hangs off the tab's top
   right corner with the tail pointing back down into the tab, and a tab with
   nothing waiting has none at all. */
.co-tabn {
  position: absolute; top: -9px; right: 10px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  min-width: 30px; height: 20px; padding: 0 6px;
  background: #FFD84D; border: 1.5px solid #E9BE2B; border-radius: 5px;
  color: #2B2205; font-size: 10.5px; font-weight: 600; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.co-tabn svg { width: 11px; height: 11px; }
.co-tabn::before, .co-tabn::after { content: ""; position: absolute; width: 0; height: 0; border-style: solid; }
.co-tabn::before { top: 100%; left: 6px; border-width: 8px 7px 0 0;
                   border-color: #E9BE2B transparent transparent transparent; }
.co-tabn::after  { top: calc(100% - 1.5px); left: 7.5px; border-width: 6px 5px 0 0;
                   border-color: #FFD84D transparent transparent transparent; }

@media (max-width: 900px) { .co-tab { flex: 1 1 100%; } }

/* Two columns. Left: where he has been, with the slab he is on right now
   rendered large — the image IS the row. Right: everything about that slab,
   and the conversation underneath it. */
.co-cockpit { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 14px; align-items: start; }
@media (max-width: 1200px) { .co-cockpit { grid-template-columns: 260px minmax(0, 1fr); } }
@media (max-width: 900px) { .co-cockpit { grid-template-columns: 1fr; } }
.co-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

/* The actions belong on the main label's row. app.css bottom-aligns them
   against the whole left block, which on a page with a back link above the
   title and an id line under it drops them a row too low. Same override as
   offer-campaign.html:34. */
.page-header { align-items: center; }

.co-back { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--color-primary-700); text-decoration: none; margin-bottom: 4px; }
.co-back:hover { color: var(--color-primary); text-decoration: none; }
.co-back i { width: 14px; height: 14px; }
.co-idline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 3px; font-size: 12px; color: var(--color-text-muted); }
/* The company is the title, the person sits under it. A rep greets John but
   he is quoting Marbles & Granite, and on a floor where the same buyer turns up for two
   companies the account is what decides the price. His name keeps the weight
   of a name — it is who the rep is typing to — and his number stays beside it. */
.co-co { font-size: 14px; font-weight: 600; color: var(--color-text); }
/* His number, in reach. The chat is the channel until it isn't: a client who
   stops answering in the showroom gets called, and the rep should not have to
   leave the conversation to find out how. */
.co-tel { display: inline-flex; align-items: center; gap: 4px; font-size: 12.5px; font-weight: 600; color: var(--color-text); }
.co-tel i { width: 11px; height: 11px; color: var(--color-text-subtle); }
.co-tel:hover { color: var(--color-primary-700); }
.co-tel:hover i { color: var(--color-primary-700); }
.co-sid { display: inline-flex; align-items: center; gap: 2px; font-size: 11px; color: var(--color-text-subtle); font-variant-numeric: tabular-nums; }
/* Copyable, because the id is only ever wanted somewhere else — a ticket, a
   message to whoever owns the bug. Nobody retypes it correctly. */
.co-copy { width: 22px; height: 22px; }
.co-copy svg { width: 13px; height: 13px; }

/* ---- Presence. FAIL TO OFFLINE, ALWAYS. Default is off; only a landed poll
   turns a dot on. Rep presence is polled at 10-20s — it is NOT on the chat's
   real-time channel, and a stale poll reads offline, never online. ---- */
.co-presence { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; }
.co-livedot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-border-strong); position: relative; flex: none; }
.co-presence--online { color: var(--color-text-muted); }
.co-presence--online .co-livedot { background: var(--color-success); }
.co-presence--online .co-livedot::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--color-success); animation: copulse 1.9s ease-out infinite; }
@keyframes copulse { 0% { transform: scale(1); opacity: .55; } 100% { transform: scale(2.8); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .co-livedot::after { animation: none; } }

/* ================= CHAT =================
   The one real-time surface in this module. Everything else on this page
   polls at 10-20s. Authorship is carried by POSITION — the rep's messages sit
   right, the client's sit left. The primary-50 tint on the rep's own bubble
   reinforces the same meaning primary already carries in six live places
   ("yours / the chosen one"); it is not the carrier. */
.co-chat { display: flex; flex-direction: column; min-height: 448px; }
.co-chat__head { display: flex; align-items: center; gap: 10px; padding: 11px 14px; border-bottom: 1px solid var(--color-border); flex-wrap: wrap; }
.co-chat__who { display: flex; align-items: center; gap: 9px; min-width: 0; }
/* The quote sits at the far end of the client's own header row — the name at
   one edge, the act at the other. .spacer is scoped to toolbars in app.css, so
   the push is made here rather than by borrowing a utility that does not apply. */
.co-quote { margin-left: auto; flex: none; }
.co-chat__name { font-weight: 600; font-size: 14px; }

.co-thread { flex: 1; overflow-y: auto; max-height: 392px; padding: 14px; display: flex; flex-direction: column; gap: 12px; background: var(--color-surface-alt); }

.co-msg { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; align-items: end; }
.co-msg .avatar { width: 30px; height: 30px; font-size: 10px; flex: none; }
.co-msg[data-side="them"] .avatar { grid-column: 1; }
.co-msg[data-side="us"] .avatar { grid-column: 3; }
/* Capped, not just proportional: the chat now sits in a wide column and an
   800px-wide bubble stops reading like speech. */
.co-bubble { grid-column: 2; max-width: min(80%, 540px); padding: 7px 11px 6px; border-radius: 5px; background: var(--color-surface); border: 1px solid var(--color-border); box-shadow: var(--shadow-sm); }
.co-msg[data-side="them"] .co-bubble { justify-self: start; border-top-left-radius: 2px; }
.co-msg[data-side="us"] .co-bubble { justify-self: end; background: var(--color-primary-50); border-color: #D2DFF0; border-top-right-radius: 2px; }
.co-msg__head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 2px; }
.co-msg__from { font-size: 12px; font-weight: 600; color: var(--color-text); }
.co-msg[data-side="them"] .co-msg__from { color: var(--color-primary-700); }
.co-msg__time { margin-left: auto; font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; }
.co-msg__text { font-size: 13.5px; line-height: 1.45; color: var(--color-text); word-wrap: break-word; }

/* Internal notes — STAFF ONLY, and no longer in the thread. A note is not a
   message: it has no recipient, it answers nothing, and mixing the two made
   the composer ask "who is this for?" before every single reply. They live
   behind one button now, on their own surface. */
.co-notes { display: flex; flex-direction: column; }
.co-note { display: flex; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--color-border); }
.co-note:last-child { border-bottom: 0; }
.co-note .avatar { width: 30px; height: 30px; font-size: 10px; flex: none; }
.co-note__b { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.co-note__h { display: flex; align-items: baseline; gap: 8px; }
.co-note__n { font-size: 12.5px; font-weight: 600; color: var(--color-text); }
.co-note__t { margin-left: auto; font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; }
.co-note__x { font-size: 13px; line-height: 1.5; color: var(--color-text); word-wrap: break-word; }
.co-note__p { font-size: 11px; color: var(--color-text-subtle); }

.co-msg--system { grid-template-columns: 1fr; justify-items: center; }
.co-sys { font-size: 11px; color: var(--color-text-subtle); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 999px; padding: 3px 11px; text-align: center; }

/* Voice — same thread as text, and it runs BOTH ways: he leaves one from a
   job site, the rep answers with hands on a slab. Capture and playback are
   mocked in this prototype; a real build is MediaRecorder + storage. */
.co-voice { display: flex; align-items: center; gap: 9px; padding: 3px 0 1px; }
.co-voice__btn { width: 28px; height: 28px; padding: 0; border-radius: 999px; border: 0; background: var(--color-primary); color: #fff; display: grid; place-items: center; cursor: pointer; flex: none; }
.co-voice__btn:hover { background: var(--color-primary-700); }
/* svg, not i — the icon library replaces the tag, so an `i` rule never lands. */
.co-voice__btn svg { width: 13px; height: 13px; }
.co-wave { display: flex; align-items: center; gap: 2px; height: 20px; flex: 1; min-width: 60px; }
.co-wave span { flex: 1; background: var(--color-secondary); border-radius: 5px; min-width: 2px; transition: background 120ms; }
.co-voice__d { font-size: 11px; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
/* Playing: the bars carry it. Nothing else on the bubble moves. */
.co-voice.is-playing .co-wave span { background: var(--color-primary); animation: cowave .8s ease-in-out infinite alternate; }
@keyframes cowave { from { transform: scaleY(.55); } to { transform: scaleY(1); } }
@media (prefers-reduced-motion: reduce) { .co-voice.is-playing .co-wave span { animation: none; } }

/* A product pushed into the conversation. If a price rides along it is the ONE
   resolved price — no base, no tier, no "% off". The staff ladder below does
   not travel with it. */
.co-push { display: flex; gap: 10px; padding: 8px; margin-top: 5px; border: 1px solid var(--color-border); border-radius: 5px; background: var(--color-surface); }
.co-push .thumb { width: 82px; height: 48px; border-radius: 5px; flex: none; }
.co-push .thumb.is-photo { width: 82px; height: 48px; }
.co-push__b { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.co-push__n { font-size: 13px; font-weight: 600; color: var(--color-text); }
.co-push__p { font-size: 13px; font-weight: 600; color: var(--color-primary-700); font-variant-numeric: tabular-nums; }

/* Composer */
.co-composer { border-top: 1px solid var(--color-border); padding: 10px 14px 12px; display: flex; flex-direction: column; gap: 8px; margin-top: auto; }
.co-comptools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.co-comphint { font-size: 11px; color: var(--color-text-subtle); }
.co-comprow { display: flex; align-items: flex-end; gap: 7px; }
.co-comprow textarea { flex: 1; resize: none; font-family: inherit; font-size: 13.5px; line-height: 1.45; }
.co-rec { display: none; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 5px; background: var(--color-danger-50); border: 1px solid var(--color-danger); font-size: 12px; }
.co-rec.is-on { display: flex; }
.co-rec__dot { width: 8px; height: 8px; border-radius: 999px; background: var(--color-danger); animation: copulse2 1.2s ease-in-out infinite; }
@keyframes copulse2 { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
@media (prefers-reduced-motion: reduce) { .co-rec__dot { animation: none; } }

/* ---- Price ladder — STAFF ONLY, AND ON THE YELLOW CARD (2026-09-10).
   It stood in a panel of its own a column away, under a heading that named
   the slab a second time. The numbers price the piece in the photograph, so
   they sit under it. Never renders to the client, and under the showroom's own
   stylesheet it could not: it is built from app.css classes the showroom does
   not load. Three rungs and no "lowest ever sold": no order or transaction
   entity exists anywhere to source one.

   THREE COLUMNS, LABEL UNDER VALUE. It was three stacked rows, on the reading
   that a ~274px block gives a tile less width than its own label. Measured, the
   longest of the three labels sets at 68px and the widest amount at 72px, so a
   third of the block carries both. Across, the three read as one ladder you
   scan left to right rather than three facts listed one after another.
   The value line is given one height for all three rungs, so the emphasised
   middle amount cannot drop its own label below the other two. ---- */
.co-heroprice {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 8px; margin-top: 9px; padding-top: 9px; border-top: 1px solid #E8D5A8;
}
.co-ptier { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.co-ptier__v { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; color: #8A6D1F; line-height: 23px; }
.co-ptier__k { font-size: 11px; font-weight: 600; color: #8A6D1F; line-height: 1.25; }
/* The price he is actually being shown is the one the rep quotes from, so it
   is the one that is readable first — the other two are what it sits between. */
.co-ptier--his .co-ptier__v { font-size: 19px; color: #5C4708; }
.co-ptier--his .co-ptier__k { color: #5C4708; }
/* The floor carries no colour of its own: on a yellow card a red or a blue
   rung would read as an alarm rather than as the bottom of a ladder. Its
   warning is in words, on the line under the three. */
.co-ptier--floor .co-ptier__v { color: #8A6D1F; }
.co-ptier__note { grid-column: 1 / -1; margin-top: 7px; font-size: 10.5px; line-height: 1.45; color: #8A6D1F; }

/* ================= COLUMN 1 — PRODUCTS VIEWED =================
   His path through the showroom, newest first, grouped by the session that
   produced it. Two highlights that mean two different things and must never
   collapse into one: YELLOW = the page he is on right now (a fact about
   him); BLUE RAIL = the product you pulled up to read (a fact about you).
   Both at once is the common case and has to stay legible. */
.co-plist { display: flex; flex-direction: column; padding-bottom: 6px; }
.co-pgroup__h { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 10px 12px 5px; }
.co-pgroup__k { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; font-weight: 600; color: var(--color-text-subtle); }
.co-pgroup__d { font-size: 11px; color: var(--color-text-subtle); font-variant-numeric: tabular-nums; }
.co-prow { display: flex; align-items: center; gap: 9px; width: 100%; padding: 8px 12px; cursor: pointer;
           text-align: left; font-family: inherit; background: none; border: 0; border-left: 2px solid transparent;
           border-bottom: 1px solid var(--color-border); }
.co-prow:last-child { border-bottom: 0; }
.co-prow:hover { background: var(--color-surface-alt); }
.co-prow .thumb { width: 46px; height: 30px; border-radius: 5px; flex: none; }
.co-prow .thumb.is-photo { width: 46px; height: 30px; }
.co-prow__b { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.co-prow__n { font-size: 12.5px; font-weight: 600; color: var(--color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.co-prow__t { font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* ---- Seen before. The same slab turning up in three different sessions is
   the loudest buying signal this page has, and it is invisible when each
   visit is just one more row in a list. The mark carries the TOTAL, not the
   ordinal, so it reads identically wherever the eye lands — you learn "three
   times" from any one of them without assembling the list in your head. ---- */
.co-prow__nr { display: flex; align-items: center; gap: 6px; min-width: 0; }
.co-again { display: inline-flex; align-items: center; gap: 3px; flex: none; font-size: 10px; font-weight: 700;
            padding: 1px 6px 1px 5px; border-radius: 999px; background: var(--color-warn-50); color: #B45309;
            font-variant-numeric: tabular-nums; }
.co-again i, .co-again svg { width: 10px; height: 10px; }
.co-prow__m { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex: none; }
.co-prow__dwell { font-size: 12px; font-weight: 600; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.co-prow__ts { font-size: 10.5px; color: var(--color-text-subtle); font-variant-numeric: tabular-nums; }
.co-prow--now, .co-prow--now:hover { background: #FEF9C3; }
.co-prow.is-sel { border-left-color: var(--color-primary); background: var(--color-primary-50); }
.co-prow--now.is-sel { background: #FEF9C3; box-shadow: inset 0 0 0 2px #FDF0A0; }
.co-nowtag { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: #854D0E; }

/* The slab he is on now: the photo is the row. Big enough to recognise the
   stone from across the desk, which a 46px thumb never was. */
/* THE CARD, AND THE CLICKABLE TOP OF IT. The yellow, the rule that closes the
   card and the selected ring belong to the whole card, because the card is now
   three pieces — the picture and its specs, the Add bar, the price ladder — and
   a ground that stopped at the first of them would read as three rows. */
.co-herocard { background: #FEF9C3; border-bottom: 1px solid var(--color-border); }
.co-herocard:hover { background: #FDF4A8; }
.co-herocard.is-sel { box-shadow: inset 0 0 0 2px #FDF0A0; }
.co-phero { display: block; width: 100%; padding: 11px 12px 0; cursor: pointer; text-align: left;
            font-family: inherit; background: transparent; border: 0; }
/* Out of the button, so it carries the gutter the button used to give it. */
.co-herocard > .co-heroprice { margin-top: 0; padding: 9px 12px 12px; }
.co-phero__img { display: block; width: 100%; aspect-ratio: 1.5 / 1; border-radius: 5px;
                 border: 1px solid #E8D5A8; background: var(--color-surface-alt) center / cover no-repeat; }
.co-phero__r { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-top: 9px; }
.co-phero__b { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.co-phero__n { font-size: 14px; font-weight: 600; color: var(--color-text); }
.co-phero__t { font-size: 11.5px; color: #854D0E; }
.co-phero__d { font-size: 13px; font-weight: 700; color: #854D0E; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* The specs, on the yellow. Divider rather than a box: it is the same panel,
   not a second one. */
.co-herospecs { display: flex; flex-direction: column; gap: 4px; margin-top: 9px; padding-top: 9px; border-top: 1px solid #E8D5A8; }
.co-herostock { align-self: flex-start; font-size: 11px; font-weight: 600; padding: 2px 7px; border-radius: 999px; }
.co-herostock--in { background: var(--color-success-50); color: var(--color-success-700); }
.co-herostock--low { background: var(--color-warn-50); color: #B45309; }
.co-herostock--out { background: var(--color-danger-50); color: var(--color-danger); }
.co-herospecs .co-mline { font-size: 11.5px; line-height: 1.45; color: #8A6D1F; }
.co-herospecs .co-mline b { color: #5C4708; }
.co-herospecs .co-mline--hi { color: #5C4708; }


/* ================= COLUMN 2 — THE PRODUCT + THE CONVERSATION ================= */

/* Facts run together into readable lines. A label + a value per row spent a
   whole row saying "Area" and left the rest of it empty; a slab reads as one
   description, so it is written as one. */
.co-cur { display: flex; gap: 12px; padding: 0 14px 12px; }
.co-curthumb { width: 96px; height: 64px; border-radius: 5px; flex: none;
               background: var(--color-surface-alt) center / cover no-repeat; border: 1px solid var(--color-border); }
.co-cur__b { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.co-cur__top { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.co-cur__n { font-size: 17px; font-weight: 600; color: var(--color-text); }
.co-mline { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--color-text-muted); }
.co-mline b { color: var(--color-text); font-weight: 600; }
.co-mline--hi { color: var(--color-text); }

.co-pick { display: flex; gap: 10px; align-items: center; padding: 9px; border: 1px solid var(--color-border); border-radius: 5px; cursor: pointer; background: var(--color-surface); }
.co-pick:hover { background: var(--color-primary-50); border-color: var(--color-primary); }
.co-pick .thumb { width: 68px; height: 40px; border-radius: 5px; flex: none; }
.co-pick .thumb.is-photo { width: 68px; height: 40px; }
.co-pick__price { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; text-align: right; }
.co-pick__price b { font-size: 13px; font-weight: 600; color: var(--color-primary-700); font-variant-numeric: tabular-nums; }
.co-pick__price span { font-size: 10px; color: var(--color-text-subtle); }

/* ---- The dark themes: the "right now" yellow ------------------------------
   Every surface above that means "he is looking at this at this second" is
   painted with a literal yellow — #FEF9C3 and the deeper golds written on
   it. A literal hex cannot follow a theme, so on Evening and Elegant the
   ground stayed pale while the ink went light and the slab name fell to
   1.51:1 and 1.16:1. These surfaces move into the theme's OWN warn family,
   which is the family that already carries "live, act on this"; repainting
   them in the neutral surface tokens was the obvious alternative and was
   rejected, because a live row that looks like every other row has lost the
   only thing it was for.
   The three steps are the family's gold mixed back into its own ground:
   12% for hover, 22% for a hairline, 40% for the selection ring. The light
   theme spaces those steps 1.05:1, 1.35:1 and 1.08:1 apart, which is a
   separation you can only see near the top of the luminance range, so the
   dark steps are pitched wider (1.7:1, 2.6:1) rather than copied across. */
:is([data-theme="evening"], [data-theme="elegant"]) .co-prow--now,
:is([data-theme="evening"], [data-theme="elegant"]) .co-prow--now:hover,
:is([data-theme="evening"], [data-theme="elegant"]) .co-prow--now.is-sel,
:is([data-theme="evening"], [data-theme="elegant"]) .co-herocard { background: var(--color-warn-50); }
:is([data-theme="evening"], [data-theme="elegant"]) .co-herocard:hover { background: color-mix(in srgb, var(--color-warn) 12%, var(--color-warn-50)); }
:is([data-theme="evening"], [data-theme="elegant"]) .co-prow--now.is-sel,
:is([data-theme="evening"], [data-theme="elegant"]) .co-herocard.is-sel { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--color-warn) 40%, var(--color-warn-50)); }
:is([data-theme="evening"], [data-theme="elegant"]) .co-phero__img,
:is([data-theme="evening"], [data-theme="elegant"]) .co-heroprice,
:is([data-theme="evening"], [data-theme="elegant"]) .co-herospecs { border-color: color-mix(in srgb, var(--color-warn) 22%, var(--color-warn-50)); }
/* The golds themselves. --color-warn is the only amber that can be read on
   an amber ground; --color-text takes the two places the light design made
   DARKER than the prose around them, because on a dark theme the stronger
   ink is the brighter one and a second, deeper gold would read as quieter,
   not louder. */
:is([data-theme="evening"], [data-theme="elegant"]) .co-nowtag,
:is([data-theme="evening"], [data-theme="elegant"]) .co-phero__t,
:is([data-theme="evening"], [data-theme="elegant"]) .co-phero__d,
:is([data-theme="evening"], [data-theme="elegant"]) .co-again,
/* The panel behind it moved to --color-warn-50 too, so at rest the pill and
   its ground are the same value and the pill stops being a pill. Lifted a
   step within the family rather than given a neutral ground, which would
   have said "not stock news". */
:is([data-theme="evening"], [data-theme="elegant"]) .co-herostock--low {
  background: color-mix(in srgb, var(--color-warn) 18%, var(--color-warn-50));
}
:is([data-theme="evening"], [data-theme="elegant"]) .co-herostock--low,
:is([data-theme="evening"], [data-theme="elegant"]) .co-herospecs .co-mline,
:is([data-theme="evening"], [data-theme="elegant"]) .co-ptier__v,
:is([data-theme="evening"], [data-theme="elegant"]) .co-ptier__k,
:is([data-theme="evening"], [data-theme="elegant"]) .co-ptier__note { color: var(--color-warn); }
:is([data-theme="evening"], [data-theme="elegant"]) .co-herospecs .co-mline b,
:is([data-theme="evening"], [data-theme="elegant"]) .co-herospecs .co-mline--hi,
:is([data-theme="evening"], [data-theme="elegant"]) .co-ptier--his .co-ptier__v,
:is([data-theme="evening"], [data-theme="elegant"]) .co-ptier--his .co-ptier__k { color: var(--color-text); }
/* --color-success-700 is not a token in any theme, so the in-stock pill has
   always been an invalid declaration falling back to the button's inherited
   near-black. That was invisible as a fault on the pale green ground and is
   1.39:1 on Evening's. Corrected here rather than in the rule above so the
   light theme keeps the near-black it renders today. */
:is([data-theme="evening"], [data-theme="elegant"]) .co-herostock--in { color: var(--color-success); }

/* ================= ADD TO REQUEST, UNDER THE SELECTED MATERIAL ============
   One bar for the whole column, moved by `coSelect` to sit directly beneath
   whichever row is selected. It reads as part of that row — same left gutter,
   the row's own bottom rule underneath it — so the material it adds is never
   in doubt and never has to be named on the bar itself.

   THE ASK COMES BEFORE THE ADD. Resting, it is one button and the count of
   what the yard has. Pressed, it swaps that line for the quantity field, its
   unit and the two answers — nothing is added until a number has been said.
   The two states swap in one seat, so the column does not jump. */
.co-add {
  padding: 8px 12px;
  background: var(--color-surface-alt);
  border-bottom: 1px solid var(--color-border);
}
.co-add__rest,
.co-add__qty { display: flex; align-items: center; gap: 8px;
  /* The column narrows with the window, and at the narrow end the field and its
     two answers no longer fit one line. They wrap rather than spill: this column
     is 234px at its narrowest and a row that overflows it clips the Add. */
  flex-wrap: wrap; row-gap: 8px; }
/* What the yard has, beside the button that spends it. */
.co-add__avail { font-size: 11px; color: var(--color-text-muted); }
.co-add__lab { font-size: 12px; color: var(--color-text-muted); }
.co-add__unit { font-size: 12px; color: var(--color-text-muted); }
/* THE TWO ANSWERS GET THEIR OWN LINE. The question — how many, of what — and
   the pair that answers it do not fit one line in a 234px column, and a row that
   wraps only sometimes puts Add in a different place depending on the window.
   Kept together and kept below, they are in the same place at every width.
   Right, because the reading ends there. */
.co-add__acts { flex: 1 0 100%; display: flex; justify-content: flex-end; gap: 8px; }
/* A slab count is one or two digits and is read against its unit word, so the
   field is sized for the number rather than for the row. Spinner arrows are off
   platform-wide in app.css. */
.co-add__in { width: 64px; height: 28px; min-width: 0; flex: none; padding: 0 8px; text-align: right; font-size: 13px; }
/* What just happened, in the same seat the control was in. */
.co-add__done { margin: 0; font-size: 11px; color: var(--color-text-muted); }

/* ---- The bar, standing on the live card ---------------------------------
   Inside the yellow it takes the same yellow one shade lighter, so it reads as
   a seat cut into the card rather than a grey band laid across it. The rule
   above it separates it from the specs; the price ladder's own rule separates
   it from the numbers below, so the card divides into three and no line is
   drawn twice. Its text takes the card's brown for the same reason. */
.co-add--hero {
  background: #FEFCE8;
  border-top: 1px solid #E8D5A8;
  border-bottom: 0;
  padding: 9px 12px;
}
.co-add--hero .co-add__avail,
.co-add--hero .co-add__lab,
.co-add--hero .co-add__unit,
.co-add--hero .co-add__done { color: #8A6D1F; }
:is([data-theme="evening"], [data-theme="elegant"]) .co-add--hero {
  background: color-mix(in srgb, var(--color-warn) 6%, var(--color-warn-50));
}
:is([data-theme="evening"], [data-theme="elegant"]) .co-add--hero .co-add__avail,
:is([data-theme="evening"], [data-theme="elegant"]) .co-add--hero .co-add__lab,
:is([data-theme="evening"], [data-theme="elegant"]) .co-add--hero .co-add__unit,
:is([data-theme="evening"], [data-theme="elegant"]) .co-add--hero .co-add__done { color: var(--color-warn); }
