
  /* #archShell = the read-only WhatsApp archive page (templates/archive.html). It borrows the
     palette by SELECTOR rather than copying it, so the archive can never drift from the panel. */
  /* the archive button LEAVES the panel — same size and weight as its neighbours, so the
     rail reads as one set rather than three different glyphs */
  .wa-nav-archive{position:relative;text-decoration:none}
  /* ⭐ the case page's WhatsApp Client CARD joins the palette by selector too (2026-09-22): its bubbles are built
     with these classes and the panel's own helpers (window.RYTChatUI), so the preview IS the chat rather than
     a second renderer that drifts (it showed UTC times and empty bubbles for photos, Sett's screenshot). */
  #waPanel, #archShell, #waCardPreview{
    /* light (default) — WhatsApp Web light palette */
    --wa-header:#FFFFFF; --wa-bg:#F7F3EE; --wa-panel:#FFFFFF;
    --wa-in:#FFFFFF; --wa-out:#D9FDD3; --wa-text:#111B21; --wa-sub:#667781;
    --wa-meta:#667781; --wa-tick:#8696A0; --wa-read:#53BDEB; --wa-line:#E9EDEF;
    --wa-composer:#F0F2F5; --wa-input:#FFFFFF; --wa-send:#00A884;
    --wa-note-bg:#F6E7D6; --wa-note-bd:#E6D0AC; --wa-note-tx:#5c3d1e; --wa-note-h:#8a5a1e;  /* RYT parchment (lightened) — all team/internal bits */
    --wa-priv:#CDC6B4;   /* private (staff-only) message bubble — a darker tint that stands out */
    --wa-privinput:#ECE4CD;  /* the typing area tint while composing a private reply */
    /* nav rail + list chrome (WhatsApp desktop light) */
    --wa-navbg:#F7F5F3; --wa-navic:#54656F; --wa-navhover:rgba(84,101,111,.10);
    --wa-navactic:#0A0A0A; --wa-navactbg:#E7E4DE; --wa-field:#EFF2F5;
    --wa-chipon-bg:#D9FDD3; --wa-chipon-tx:#1DAA61; --wa-chipoff-bd:#E4E7EA; --wa-chipoff-tx:#54656F;
    /* the CLOSED 24-hour window — red, because a message here costs a paid template (Sett) */
    --wa-shut-bg:rgba(192,57,43,.09); --wa-shut-bd:rgba(192,57,43,.28); --wa-shut-tx:#A5342A;
    --wa-shut-btn:#C0392B; --wa-shut-btn-h:#A93226;
  }
  #waPanel[data-wa-theme="dark"], #archShell[data-wa-theme="dark"]{
    /* black header + a near-neutral dark chat bg with a whisper of warmth (halfway: not blue, not brown) */
    --wa-header:#000000; --wa-bg:#141414; --wa-panel:#0E0E0E;
    --wa-in:#1E1E1D; --wa-out:#144D37; --wa-text:#E9EDEF; --wa-sub:#8E8E8A;
    --wa-meta:#93908A; --wa-tick:#93908A; --wa-read:#53BDEB; --wa-line:#2A2621;
    --wa-composer:#000000; --wa-input:#262625; --wa-send:#00A884;
    --wa-note-bg:#3a3320; --wa-note-bd:#6b5a2e; --wa-note-tx:#e7d9ac; --wa-note-h:#d8b25a;
    --wa-priv:#2C2A22;   /* private (staff-only) message bubble — a darker tint that stands out */
    --wa-privinput:#332F22;  /* the typing area tint while composing a private reply */
    /* nav rail + list chrome (WhatsApp desktop dark — black, matching the header) */
    --wa-navbg:#0A0A0A; --wa-navic:#8696A0; --wa-navhover:rgba(134,150,160,.12);
    --wa-navactic:#E9EDEF; --wa-navactbg:#2A2A2A; --wa-field:#202020;
    --wa-chipon-bg:rgba(0,168,132,.22); --wa-chipon-tx:#00A884; --wa-chipoff-bd:#2A2621; --wa-chipoff-tx:#8696A0;
    --wa-shut-bg:rgba(224,84,68,.14); --wa-shut-bd:rgba(224,84,68,.38); --wa-shut-tx:#F0968C;
    --wa-shut-btn:#C0392B; --wa-shut-btn-h:#D3483A;
  }

  #waScrim{position:fixed;inset:0;background:rgba(11,20,26,.5);opacity:0;pointer-events:none;transition:.2s;z-index:1200}
  #waScrim.on{opacity:1;pointer-events:auto}
  /* ⭐⭐ ONE THREAD WIDTH, DERIVED ONCE AND READ BY BOTH PANELS (Sett). The case-page panel is now
     exactly as wide as the THREAD is in the full inbox window -- the same window minus its rail --
     so a conversation is the same shape wherever you opened it from, and the two can never drift
     apart because neither carries its own number. ⚠️ Widening the case panel is also the only thing
     that can give the doctor's name real room: MEASURED, its chrome (avatar + four icons + gaps +
     padding) costs 244px, so at the old 400px floor the name had 156px to live in whatever the C⭐⭐
     did with it. ⚠️ The 400px floor STAYS as a floor: on a very narrow window the derived thread is
     narrower than 400, and this must never come out worse than it was. */
  /* the inbox window and the two columns inside it -- the three numbers the thread width comes from */
    /* ⭐⭐ THE CASE-CARD PANEL IS THE INBOX'S THREAD, TO THE PIXEL (Sett's rule: the full chat
     window "minus the chat rail AND side panel"). The inbox is THREE columns -- the 64px icon
     nav, the 340px conversation rail, then the thread -- so BOTH have to come off.
     ⚠️ I subtracted only the rail at first and the case panel came out 64px too wide (610.4
     against a 546.4 thread). Sett spotted it on screen; a probe built from the CSS variables
     agreed with my arithmetic and was wrong about the page -- measure the real elements.
     ⚠️ `--wa-nav-w` is the SINGLE source: `.wa-nav` reads it too, so widening the icon rail
     moves the case panel with it instead of silently reopening this gap. */
:root{--wa-inbox-w:clamp(min(calc(860*var(--wa-u,1px)),96vw),66vw,calc(1200*var(--wa-u,1px)));
        --wa-rail-w:clamp(calc(250*var(--wa-u,1px)),calc(var(--wa-inbox-w) * .36),calc(340*var(--wa-u,1px)));
        --wa-nav-w:calc(64*var(--wa-u,1px))}
  #waPanel{position:fixed;top:0;right:0;height:100%;width:calc(var(--wa-inbox-w) - var(--wa-rail-w) - var(--wa-nav-w));min-width:calc(400*var(--wa-u,1px));max-width:96vw;background:var(--wa-panel);
    box-shadow:-12px 0 40px rgba(11,20,26,.28);transform:translateX(100%);
    transition:transform .26s cubic-bezier(.2,.8,.2,1);z-index:1201;display:flex;flex-direction:column;
    font-family:"Helvetica Neue","Helvetica","Lucida Grande","Arial","Ubuntu","Cantarell","Fira Sans",sans-serif;
    -webkit-font-smoothing:antialiased;color:var(--wa-text)}
  #waPanel.on{transform:none}

  /* header — WhatsApp bar */
  .wa-head{display:flex;align-items:center;gap:calc(9*var(--wa-u,1px));padding:calc(10*var(--wa-u,1px)) calc(12*var(--wa-u,1px));background:var(--wa-header);flex:none;border-bottom:1px solid var(--wa-line)}
  .wa-av{width:calc(40*var(--wa-u,1px));height:calc(40*var(--wa-u,1px));border-radius:50%;flex:none;display:grid;place-items:center;font-weight:700;font-size:calc(14*var(--wa-u,1px));color:#fff;background:#6a7f8a}
  .wa-ht{min-width:0;flex:1 1 auto}   /* the clinic name gets the leftover width, not the controls */
  /* the window pill sits on the SECOND line with the number, so the clinic name has the whole first row.
     Beside the name it cost ~95px and the name was reduced to "KLINI…" in the case-page panel. */
  /* ⚠⚠ WRAPS. In the pop-out window the row is ~900px and the number sits right after the name; in the
     case-page panel the title block is only ~195px, and a name at its floor (83px) plus a number (119px)
     does not fit — unwrapped, the number ran 14px past a row that clips, so the last digits were simply
     GONE. A number cut in half is unreadable, which is the whole reason it never shrinks; dropping to its
     own line keeps it whole. `overflow:hidden` stays as the belt for one unbreakable word. */
  .wa-nmrow{display:flex;align-items:baseline;gap:calc(7*var(--wa-u,1px));min-width:0;overflow:hidden;flex-wrap:wrap}
  /* ⚠️⚠️ THE NAME USED TO COLLAPSE TO NOTHING — "D..." beside a clinic chip showing 17 characters.
     MEASURED at a 400px panel: this row rendered 0px wide while the four header buttons kept their
     full size. Cause: `.wa-hbtn` never declared `flex`, so it defaulted to shrink:1 and competed with
     the text block; the text block has by far the largest basis, so it absorbed nearly all the shrink.
     The buttons are fixed now (below), and the name carries a floor so it can never reach zero. */
  /* ⭐⭐ `flex:1 1 auto` -- IT GROWS. A floor alone only stops the name reaching zero; it does not
     hand it the spare width, so on the case-page panel it sat at its floor with room to its right.
     MEASURED there (panel 400): the row gets 156px once the avatar, four icons and gaps are paid for,
     and the name was taking 89px of it. Growing, with the chip and the repair link both yielding
     first, it takes the lot. The floor stays as the backstop for a panel narrower than any we ship. */
  /* ⚠️ `flex:0 1 auto`, NOT `1 1 auto` (Sett, 2026-09-22: "move the phone number and case number to
     after the display name rather than far right"). A growing name fills the row and shoves whatever
     follows it to the far edge, which read as two unrelated things at opposite ends rather than one line
     about one person. It still SHRINKS (ellipsis) when the panel narrows — the number never does. */
  .wa-nm{font-size:calc(15*var(--wa-u,1px));font-weight:600;color:var(--wa-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:0 1 auto;min-width:5.5em}
  /* ⚠️ the number beside the name: `flex:none` so the NAME is what trims when the panel narrows (a half-shown
     number is unreadable, a trimmed name is still recognisable), and the digits line up as they do everywhere. */
  .wa-nmph{flex:none;font-size:calc(12*var(--wa-u,1px));color:var(--wa-sub);font-variant-numeric:tabular-nums;white-space:nowrap}
  /* the clinic behind a DOCTOR's personal line. ⭐⭐ ITS SHRINK IS 1000 AGAINST THE NAME'S 1, so a
     narrow panel trims the clinic first — losing the person you are talking to would be worse.
     ⚠️ This comment used to describe that priority while BOTH carried shrink:1, i.e. it documented a
     rule the code never implemented — which is worse than no comment, because it stops anyone
     re-checking. The number is written out here so the claim and the code can be compared. */
  /* the way back from a mis-click on the capture prompt. Hidden until the header is hovered:
     unlinking is a repair, not part of the daily flow. */
  /* ⚠️⚠️ IT USED TO BE `flex:none` AND HELD 53px OF A 156px ROW -- a THIRD of the space, for a
     control that is invisible until you hover the header. It yields with the clinic chip now: the
     person you are talking to is worth more than a repair link, and unlinking is not the daily flow. */
  .wa-unlink{flex:0 1000 auto;margin-left:auto;min-width:0;overflow:hidden;font-size:calc(11*var(--wa-u,1px));color:var(--wa-sub);
             background:none;border:0;padding:0 calc(2*var(--wa-u,1px));
             cursor:pointer;opacity:0;transition:opacity .15s;white-space:nowrap}
  .wa-head:hover .wa-unlink{opacity:.62}
  .wa-unlink:hover{opacity:1;text-decoration:underline}
  .wa-clrow{display:flex;min-width:0;margin-top:calc(2*var(--wa-u,1px));gap:calc(5*var(--wa-u,1px));flex-wrap:wrap}
  .wa-clchip{flex:0 1 auto;min-width:0;max-width:100%;display:inline-flex;align-items:center;gap:calc(5*var(--wa-u,1px));font-size:calc(12*var(--wa-u,1px));font-weight:600;
             color:var(--wa-text);background:var(--wa-field);border-radius:calc(999*var(--wa-u,1px));padding:calc(2*var(--wa-u,1px)) calc(9*var(--wa-u,1px));line-height:1.25;
             white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .wa-clchip.has-logo{padding-left:calc(3*var(--wa-u,1px))}
  .wa-clchip-logo{width:calc(18*var(--wa-u,1px));height:calc(18*var(--wa-u,1px));border-radius:50%;object-fit:cover;flex:none;background:#fff}
  .wa-clchip-nm{min-width:0;overflow:hidden;text-overflow:ellipsis}
  /* number + case count on ONE line — it used to wrap to three in the narrow case-page panel and shove the
     name and controls out of shape */
  .wa-ph{font-size:calc(12*var(--wa-u,1px));color:var(--wa-sub);margin-top:1px;font-variant-numeric:tabular-nums;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* ⚠️⚠️ `flex:none` IS THE ROOT FIX, not tidiness. Without it these icons default to shrink:1 and
     compete with the name block for the header's width — and because they are small they give up almost
     nothing while the text collapses. An icon has no text to ellipsis, so shrinking it buys nothing. */
  .wa-hbtn{flex:none;border:none;background:transparent;color:var(--wa-sub);cursor:pointer;padding:calc(5*var(--wa-u,1px)) calc(8*var(--wa-u,1px));border-radius:calc(8*var(--wa-u,1px));font-size:calc(16*var(--wa-u,1px));line-height:1}
  .wa-hbtn:hover{background:rgba(134,150,160,.15);color:var(--wa-text)}

  /* case chips row */
  .wa-cases{display:flex;align-items:center;gap:calc(6*var(--wa-u,1px));flex-wrap:wrap;padding:calc(7*var(--wa-u,1px)) calc(14*var(--wa-u,1px));background:var(--wa-header);border-bottom:1px solid var(--wa-line)}
  .wa-cases .lab{font-size:calc(10*var(--wa-u,1px));color:var(--wa-sub);font-weight:700;text-transform:uppercase;letter-spacing:.05em}
  .wa-chip{font-size:calc(11*var(--wa-u,1px));font-weight:700;color:var(--wa-send);background:rgba(0,168,132,.12);border:1px solid rgba(0,168,132,.4);border-radius:calc(7*var(--wa-u,1px));padding:calc(2*var(--wa-u,1px)) calc(8*var(--wa-u,1px))}

  /* inbox — WhatsApp-style conversation list */
  .wa-inbox-list{flex:1;overflow:auto;background:var(--wa-panel)}
  .wa-conv{position:relative;display:flex;align-items:center;gap:calc(11*var(--wa-u,1px));width:100%;text-align:left;border:none;background:transparent;cursor:pointer;padding:calc(9*var(--wa-u,1px)) calc(14*var(--wa-u,1px));color:var(--wa-text)}
  /* inset rounded highlight (margins from the edge, like the search box) — hover + selected */
  .wa-conv::before{content:"";position:absolute;inset:calc(2*var(--wa-u,1px)) calc(8*var(--wa-u,1px));border-radius:calc(11*var(--wa-u,1px));background:transparent;z-index:0}
  .wa-conv-av,.wa-conv-mid,.wa-conv-rt{position:relative;z-index:1}
  .wa-conv:hover::before{background:var(--wa-navhover)}
  .wa-conv-av{width:calc(44*var(--wa-u,1px));height:calc(44*var(--wa-u,1px));border-radius:50%;flex:none;display:grid;place-items:center;font-weight:700;font-size:calc(13*var(--wa-u,1px));color:#fff;background:#6a7f8a}
  .wa-conv-mid{flex:1;min-width:0}
  .wa-conv-nm{font-size:calc(14*var(--wa-u,1px));font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--wa-text)}
  .wa-conv-pv{font-size:calc(12.5*var(--wa-u,1px));color:var(--wa-sub);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px}
  .wa-conv.un .wa-conv-nm{font-weight:700}
  .wa-conv.un .wa-conv-pv{color:var(--wa-text);font-weight:500}
  .wa-conv-rt{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:calc(4*var(--wa-u,1px));padding-left:calc(4*var(--wa-u,1px))}
  .wa-conv-tm{font-size:calc(11*var(--wa-u,1px));color:var(--wa-sub);white-space:nowrap}
  .wa-cbadge{min-width:calc(18*var(--wa-u,1px));height:calc(18*var(--wa-u,1px));padding:0 calc(5*var(--wa-u,1px));border-radius:calc(9*var(--wa-u,1px));background:#25D366;color:#fff;font-size:calc(11*var(--wa-u,1px));font-weight:700;display:grid;place-items:center}
  .wa-cbadge.note{background:#C4956A;margin-right:calc(4*var(--wa-u,1px))}   /* internal note for you — gold, not client-green */
  /* WAITING dot — a client still has no answer. Separate from the badge on purpose: the badge means
     NEW (clears on reading), this means UNANSWERED (clears only on a reply / Mark handled), so a chat
     you have read but not replied to still shows here. Same tiers as the floating icon. */
  .wa-waitdot{width:calc(8*var(--wa-u,1px));height:calc(8*var(--wa-u,1px));border-radius:50%;flex:none;display:inline-block}
  .wa-waitdot.new{background:#25D366}
  .wa-waitdot.escalating{background:#F59E0B}
  .wa-waitdot.urgent{background:#EF4444;animation:waWaitPulse 1.5s infinite ease-in-out}
  @keyframes waWaitPulse{0%,100%{opacity:1}50%{opacity:.35}}
  @media (prefers-reduced-motion:reduce){.wa-waitdot.urgent{animation:none}}

  /* WhatsApp-desktop layout: nav rail + chat list on the LEFT, selected thread on the RIGHT */
  #waPanel.wa-inbox{width:var(--wa-inbox-w);min-width:min(calc(860*var(--wa-u,1px)),96vw);max-width:calc(1200*var(--wa-u,1px));flex-direction:row}
  /* The rail was a FIXED 334px that never shrank, while the panel IS responsive (96vw once the
     window is narrow). So the narrower the window, the bigger a share the list took — at a 760px
     window it was 334 vs 332, an even split, and the thread wrapped every message onto several
     lines. Proportional instead, with a floor so the list stays readable and a ceiling so it never
     sprawls on a wide screen. 36% is chosen to land on ~333px at the panel's usual width, i.e.
     the wide layout is left exactly as it was. */
  .wa-rail{width:var(--wa-rail-w);flex:none;min-width:0;display:flex;flex-direction:column;border-right:1px solid var(--wa-line);background:var(--wa-panel);position:relative}
  /* ⚠️ min-height, or THE HEADER'S HEIGHT DEPENDS ON WHICH BUTTONS IT HAPPENS TO CARRY. This row
     is 38px tall when it holds the compose button (an SVG) and only 26px when it holds just the text
     ✕ -- so the rail header shrinks by 12px and its search bar stops lining up with the thread header
     beside it. Team chat has no compose button by design, which is why it showed there first, but the
     client panel has the same flaw for anyone WITHOUT office chat: no compose button, same 12px drop.
     Reserving the height fixes both and keeps the two columns level whatever the row contains. */
  .wa-lh-actions{display:flex;align-items:center;gap:calc(2*var(--wa-u,1px));min-height:calc(38*var(--wa-u,1px))}
  /* "New chat" panel (slides over the chat list) — search a client → start/open their conversation */
  .wa-newchat{position:absolute;inset:0;z-index:20;background:var(--wa-panel);display:flex;flex-direction:column}
  .wa-nc-head{display:flex;align-items:center;gap:calc(10*var(--wa-u,1px));padding:calc(14*var(--wa-u,1px)) calc(14*var(--wa-u,1px)) calc(8*var(--wa-u,1px))}
  .wa-nc-title{font-size:calc(17*var(--wa-u,1px));font-weight:500;color:var(--wa-text)}
  /* what 'start chats' gives, said where it is used — a DT opening New chat reads this, office never sees it */
  .wa-nc-hint{padding:0 calc(16*var(--wa-u,1px)) calc(8*var(--wa-u,1px));font-size:calc(12*var(--wa-u,1px));line-height:1.45;color:var(--wa-sub)}
  .wa-nc-list{flex:1;overflow:auto}
  /* the capture prompt — an unrecognised number, sitting above the thread until somebody says who it
     is. Deliberately quiet: it is a standing question, not an alarm, and it will be there every time
     a new number writes in. */
  .wa-idbar{display:flex;align-items:center;gap:calc(10*var(--wa-u,1px));padding:calc(8*var(--wa-u,1px)) calc(14*var(--wa-u,1px));background:var(--wa-note-bg);
    border-bottom:1px solid var(--wa-note-bd);font-size:calc(12*var(--wa-u,1px));color:var(--wa-note-tx)}
  .wa-id-txt{flex:1;min-width:0}
  .wa-id-btn{flex:none;border:1px solid var(--wa-note-bd);background:transparent;color:var(--wa-note-h);
    font-weight:600;font-size:calc(11.5*var(--wa-u,1px));border-radius:calc(14*var(--wa-u,1px));padding:calc(4*var(--wa-u,1px)) calc(11*var(--wa-u,1px));cursor:pointer;font-family:inherit}
  .wa-id-btn:hover{background:rgba(0,0,0,.05)}
  /* section header in New chat — Clinics / Doctors. Quiet: it separates two lists, it is not a
     thing you can click, so it must not compete with the rows themselves. */
  .wa-nc-sec{padding:calc(10*var(--wa-u,1px)) calc(14*var(--wa-u,1px)) calc(4*var(--wa-u,1px));font-size:calc(10.5*var(--wa-u,1px));font-weight:700;letter-spacing:.09em;
    text-transform:uppercase;color:var(--wa-sub);opacity:.85}
  .wa-main{flex:1;min-width:0;display:flex;flex-direction:column;background:var(--wa-bg);position:relative}
  .wa-main-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:var(--wa-sub);font-size:calc(13*var(--wa-u,1px));padding:calc(20*var(--wa-u,1px))}
  .wa-conv.active::before{background:var(--wa-bg)}
  /* dark: the beige base is near-black on the near-black list, so lift the selection just enough to read */
  #waPanel[data-wa-theme="dark"] .wa-conv.active::before{background:#262625}

  /* ── nav rail (leftmost, WhatsApp-desktop) — Dent Ryt brand + Chats/Calls + theme + me ── */
  .wa-nav{width:var(--wa-nav-w);flex:none;display:flex;flex-direction:column;align-items:center;gap:calc(6*var(--wa-u,1px));
    padding:calc(13*var(--wa-u,1px)) 0 calc(14*var(--wa-u,1px));border-right:1px solid var(--wa-line);
    background-color:var(--wa-bg);background-image:url('/static/img/wa_doodle.png?v=6');
    background-repeat:repeat;background-size:calc(1720*var(--wa-u,1px))}
  #waPanel[data-wa-theme="dark"] .wa-nav{
    background-image:linear-gradient(rgba(20,20,20,.66),rgba(20,20,20,.66)),url('/static/img/wa_doodle_dark.png?v=1');
    background-repeat:no-repeat,repeat;background-size:cover,calc(1720*var(--wa-u,1px))}
  /* ⭐ THE POP-OUT (Sett, 2026-09-21): /chat/window is nothing but this panel, so it fills the window —
     no slide-in, no scrim, no width arithmetic (the inbox's rails still share the space by their own rules).
     ⚠️ Placed AFTER every rule it overrides (#waPanel, .wa-inbox, .wa-rail, .wa-nav) — older guards read the FIRST
     `#waPanel{` / `.wa-rail{` / `.wa-nav{` in the file, and this block must never be what they find. */
  body.wa-popout{margin:0;overflow:hidden}
  body.wa-popout #waPanel.wa-inbox,body.wa-popout #waPanel{position:fixed;inset:0;width:auto;min-width:0;max-width:none;height:100%;transform:none;transition:none;box-shadow:none}
  body.wa-popout #waScrim{display:none}
  /* ⭐ THE FOLDING RAIL (Sett, 2026-09-21, "option C"): the window is ALWAYS the full panel, but the full
     layout needs ~860px and a chat beside a case wants ~540. Below 760px the list folds away, the thread
     takes the window, and a ≡ in the nav strip's slot right under the brand mark (Sett: the strip then
     looks the same in both states and the thread head never shifts) slides the list in as a drawer over
     the thread. Both panels: team mode borrows every `.wa-*` class. */
  .wa-nav .wa-railbtn{display:none}   /* two classes: `.wa-nav-btn{display:flex}` is declared later and would win at equal specificity */
  @media (max-width:759px){
    body.wa-popout .wa-nav .wa-railbtn{display:flex}
    /* ⭐ THE EDGE (Sett): with the list folded the strip and the thread share one doodle and nothing marks where
       one ends — the folded strip takes a warm tint over its doodle (its own hairline border stays; Sett dropped
       the soft shadow: "keep the clean minimalist feel") */
    body.wa-popout #waPanel.wa-inbox .wa-nav{
      background-image:linear-gradient(rgba(61,42,20,.055),rgba(61,42,20,.055)),url('/static/img/wa_doodle.png?v=6');
      background-repeat:no-repeat,repeat;background-size:cover,calc(1720*var(--wa-u,1px))}
    body.wa-popout #waPanel.wa-inbox[data-wa-theme="dark"] .wa-nav{
      background-image:linear-gradient(rgba(255,255,255,.05),rgba(255,255,255,.05)),linear-gradient(rgba(20,20,20,.66),rgba(20,20,20,.66)),url('/static/img/wa_doodle_dark.png?v=1');
      background-repeat:no-repeat,no-repeat,repeat;background-size:cover,cover,calc(1720*var(--wa-u,1px))}
    body.wa-popout #waPanel.wa-inbox .wa-rail{position:absolute;left:var(--wa-nav-w);top:0;bottom:0;z-index:6;
      width:min(calc(360*var(--wa-u,1px)),calc(100% - var(--wa-nav-w)));transition:transform .2s;box-shadow:12px 0 30px rgba(0,0,0,.18);
      transform:translateX(calc(-100% - var(--wa-nav-w) - calc(24*var(--wa-u,1px))))}   /* its own width + the nav strip + the shadow: nothing peeks */
    body.wa-popout[data-rail="open"] #waPanel.wa-inbox .wa-rail{transform:none}
    /* the list head's ✕ closes the WINDOW (as the team rail's does); inside a drawer that reads as "close the
       drawer" — so it is not offered there: the drawer closes by the ≡, a pick, or the dimmed thread */
    body.wa-popout #waPanel.wa-inbox .wa-rail .wa-lh-actions button[aria-label="Close"]{display:none}
    body.wa-popout[data-rail="open"] #waPanel.wa-inbox .wa-main::before{content:"";position:absolute;inset:0;background:rgba(11,20,26,.28);z-index:5}
  }
  @media (prefers-reduced-motion:reduce){ body.wa-popout #waPanel.wa-inbox .wa-rail{transition:none} }
  .wa-nav-brand{width:calc(44*var(--wa-u,1px));height:calc(44*var(--wa-u,1px));margin-bottom:calc(8*var(--wa-u,1px));background:transparent;display:grid;place-items:center}
  .wa-brand-btn{cursor:pointer;border-radius:calc(12*var(--wa-u,1px))}
  .wa-brand-btn:hover{background:var(--wa-navhover)}
  /* ⭐ The corner told you both have traffic; this says where the other one is. Only ever in that
     one state, so it stays meaningful — a permanent glow is just decoration.
     ⚠️ `filter: drop-shadow`, NOT `box-shadow`. A box-shadow follows the element's BOX, so it drew a
     rounded-square halo around the WhatsApp mark — a glow with a shape of its own, sitting near the
     logo rather than on it. drop-shadow follows the rendered ALPHA, so it traces the silhouette:
     the WhatsApp bubble's own outline, and the DR tile's own circle. Nothing new is drawn.
     ⭐⭐ THE COLOUR IS THE LOGO'S OWN — green light on the WhatsApp mark, gold on the DR mark.
     ⚠️ I had it the other way round first, colouring the glow by DESTINATION (the WhatsApp mark
     leads to team, so gold). Sett caught it immediately and he is right: a glow is the object
     LIGHTING UP, so a green logo wearing a gold halo simply reads as wrong, whatever it is meant
     to encode. The destination is already obvious from the mark you are looking at; the halo does
     not need to carry it, and carrying it cost legibility for nothing. */
  #waPanel .wa-brand-btn.wa-switch-glow{animation:waGlowGreen 1.9s ease-in-out infinite}
  #waPanel .tm-brand.wa-switch-glow{animation:waGlowGold 1.9s ease-in-out infinite}
  @keyframes waGlowGold{
    0%,100%{filter:drop-shadow(0 0 2px rgba(196,149,106,.85)) drop-shadow(0 0 5px rgba(196,149,106,.35))}
    50%    {filter:drop-shadow(0 0 4px rgba(196,149,106,1))   drop-shadow(0 0 11px rgba(196,149,106,.6))}}
  /* ⭐ The WhatsApp halo opens WIDER than the DR one (Sett) — but with ONE soft layer, not two, and
     that difference is the whole fix. ⚠️⚠️ THE TWO MARKS ARE NOT THE SAME KIND OF SHAPE. DR is a
     solid disc, so a tight shadow can only ever land outside it. The WhatsApp mark is a ring with a
     handset floating inside it, and a 3px shadow at .9 alpha is cast by BOTH edges of every stroke —
     so the light met itself across the gaps and the logo read as a filled green blob rather than a
     lit one. Sett: "the green glow still very dense till it fills up the logo". A single wide,
     low-alpha layer has no radius small enough to bridge those gaps, so the glyph stays open. */
  @keyframes waGlowGreen{
    0%,100%{filter:drop-shadow(0 0 6px rgba(37,211,102,.36))}
    50%    {filter:drop-shadow(0 0 15px rgba(37,211,102,.58))}}
  /* ⚠️ The hover fill would give the WhatsApp mark a background, and drop-shadow would then trace
     that rounded square instead of the logo — the exact thing this replaced. Suppress it while lit. */
  #waPanel .wa-brand-btn.wa-switch-glow:hover{background:transparent}
  @media (prefers-reduced-motion: reduce){
    #waPanel .wa-brand-btn.wa-switch-glow{animation:none;
      filter:drop-shadow(0 0 10px rgba(37,211,102,.5))}
    #waPanel .tm-brand.wa-switch-glow{animation:none;
      filter:drop-shadow(0 0 3px rgba(196,149,106,.95)) drop-shadow(0 0 8px rgba(196,149,106,.5))}}
  .wa-nav-brand svg{width:calc(31*var(--wa-u,1px));height:calc(31*var(--wa-u,1px))}
  .wa-nav-btn{position:relative;width:calc(46*var(--wa-u,1px));height:calc(46*var(--wa-u,1px));border:none;background:transparent;color:var(--wa-navic);
    cursor:pointer;border-radius:calc(14*var(--wa-u,1px));display:flex;align-items:center;justify-content:center;padding:0}
  .wa-nav-btn:hover{background:var(--wa-navhover)}
  .wa-nav-btn.active{color:var(--wa-navactic);background:var(--wa-navactbg)}
  .wa-ic{display:flex;align-items:center;justify-content:center;line-height:0}
  .wa-ic-fill{display:none}
  .wa-nav-btn.active .wa-ic-out{display:none}
  .wa-nav-btn.active .wa-ic-fill{display:flex}
  .wa-nav-sp{flex:1}
  .wa-nav-me{width:calc(34*var(--wa-u,1px));height:calc(34*var(--wa-u,1px));border-radius:50%;background:#6a7f8a;color:#fff;font-size:calc(12*var(--wa-u,1px));font-weight:700;
    display:grid;place-items:center;margin-top:calc(2*var(--wa-u,1px))}

  /* chat-list header + search + filter chips */
  .wa-listhead{display:flex;align-items:center;justify-content:space-between;padding:calc(15*var(--wa-u,1px)) calc(16*var(--wa-u,1px)) calc(8*var(--wa-u,1px));background:var(--wa-panel)}
  .wa-lh-title{font-size:calc(20*var(--wa-u,1px));font-weight:500;color:var(--wa-text);letter-spacing:-.01em}
  .wa-searchbar{display:flex;align-items:center;gap:calc(11*var(--wa-u,1px));margin:0 calc(12*var(--wa-u,1px)) calc(9*var(--wa-u,1px));padding:calc(8*var(--wa-u,1px)) calc(16*var(--wa-u,1px));border-radius:calc(999*var(--wa-u,1px));
    background:var(--wa-bg);color:var(--wa-sub)}
  .wa-searchbar input{flex:1;min-width:0;border:none;background:transparent;outline:none;font-size:calc(13*var(--wa-u,1px));color:var(--wa-text);font-family:inherit}
  .wa-searchbar input::placeholder{color:var(--wa-sub)}
  .wa-chips{display:flex;gap:calc(7*var(--wa-u,1px));padding:0 calc(12*var(--wa-u,1px)) calc(9*var(--wa-u,1px));flex-wrap:wrap;background:var(--wa-panel)}
  .wa-fchip{font-size:calc(13*var(--wa-u,1px));font-weight:500;padding:calc(5*var(--wa-u,1px)) calc(13*var(--wa-u,1px));border-radius:calc(16*var(--wa-u,1px));cursor:pointer;
    background:transparent;color:var(--wa-chipoff-tx);border:1px solid var(--wa-chipoff-bd)}
  .wa-fchip:hover{background:var(--wa-navhover)}
  .wa-fchip.on{background:var(--wa-chipon-bg);color:var(--wa-chipon-tx);border-color:transparent;font-weight:600}

  /* thread — tinted background (our own solid tint, NOT WhatsApp's doodle art) */
  /* tinted background + faint dental-doodle wallpaper (WhatsApp-style, our own art) */
  /* overflow-x:hidden is a hard safety net: no floating action button (react / menu / note-reply) can ever poke
     past the thread and over the composer, and there is never a horizontal scrollbar — regardless of geometry. */
  /* ⚠️ position:relative is LOAD-BEARING, not tidiness. Opening at the unread line reads
     `bar.offsetTop`, which is measured against the nearest POSITIONED ancestor — without this the
     thread is not it, and the scroll lands hundreds of pixels off. The archive cost four attempts
     to that exact bug: rect arithmetic was tried twice and neither worked; positioning the
     scroller and using plain offsetTop is what fixed it.
     ⚠️ Safe here because every absolutely-positioned thing INSIDE the thread (react button, menu,
     reactions, video expand) is anchored to `.wa-msg`, which is already relative — and the
     lightbox is appended to #waPanel, not to the thread. Both checked before this was added. */
  .wa-thread{flex:1;overflow-y:auto;overflow-x:hidden;background-color:var(--wa-bg);position:relative;
    background-image:url('/static/img/wa_doodle.png?v=6');background-repeat:repeat;background-size:calc(1720*var(--wa-u,1px));
    padding:calc(16*var(--wa-u,1px)) calc(28*var(--wa-u,1px)) calc(18*var(--wa-u,1px));display:flex;flex-direction:column;gap:calc(3*var(--wa-u,1px))}

  /* The floating date pill, WhatsApp-style: it says which day you are looking at while you scroll
     back. ⭐ BOTH exist, deliberately (Sett, 2026-09-18, third look — "bring back the floating date
     day pill for easier referencing when user is scrolling through the thread searching"): the fixed
     day dividers (.wa-daybar, below) say the DATE above the first message of every day, on screen all
     the time, so a short chat that cannot scroll still says which day it is; this pill floats while
     you scroll a LONG thread and says the DAY as well ("Wednesday, 17 Sep") — what you orient by when
     searching. Its words come from _waFloatLabel, the divider's from _waDayLabel, one clock for both.
     ⚠️ STICKY AND IN THE MARKUP, deliberately. Anything held as a class or a node stuck on AFTER a
     paint has been eaten by this panel's 3-second repaint five separate times — the load-earlier
     button, the search bar's open state, the landing flash, the jump scroll and the match tint.
     Being part of what the renderer emits means a repaint RE-CREATES it rather than removing it;
     only its text is set from script, and the scroll handler sets that again immediately. */
  .wa-datepill{position:sticky;top:calc(2*var(--wa-u,1px));align-self:center;z-index:3;pointer-events:none;
               background:var(--wa-panel);color:var(--wa-sub);font-size:calc(11.5*var(--wa-u,1px));font-weight:600;
               padding:calc(4*var(--wa-u,1px)) calc(11*var(--wa-u,1px));border-radius:calc(999*var(--wa-u,1px));box-shadow:0 1px 3px rgba(0,0,0,.14);
               opacity:0;margin-bottom:calc(-22*var(--wa-u,1px))}
  /* ⚠️ NO TRANSITION, and that is a decision rather than an omission. A CSS fade could not be made
     to run on this element: measured with the .on class applied AND inline opacity:0.96 present,
     computed opacity still read 0 — while forcing transition:none jumped it straight to .96. The
     transition was swallowing it every time. An instant pill that works beats a fading one that
     does not, and the phone-like fade is not worth an element the 3s repaint keeps re-creating.
     ⚠️ The SHOW is therefore set INLINE by script; an inline value cannot get stuck on a start
     frame. `.on` stays as the state flag the scroll handler — and a test — can read. */
  .wa-datepill.on{opacity:.96}
  /* ⚠️ THE EMPTY PILL MUST BE AS TALL AS A FILLED ONE. Every repaint renders it with no text until
     the next scroll tick (or the once-per-paint observer) names the day, and an empty box was 8px
     against a filled 25px — so the content below moved 17px the moment the day was written in.
     Chrome's scroll anchoring hid that; a height compared across a repaint (the team panel's
     keepScroll sum) did not, and Safari would not. A no-break space gives the empty pill its line
     box at any font scale. MEASURED: the empty pill 8px → 25px, the same as with "Today" in it. */
  .wa-datepill:empty::before{content:"\00a0"}

  /* ⭐⭐ JUMP TO LATEST — WhatsApp's round button, lower-right of the thread, only while you have
     scrolled up. Uses the SAME chevron as the per-message menu (Sett's ask), so the panel keeps one
     down-arrow rather than two that nearly match.
     ⚠️ `position:sticky` inside the scroller — a sibling of the
     thread cannot be used, because the composer sits between the thread and the bottom of .wa-main,
     so `bottom:0` there would put the button underneath the reply box.
     ⚠️ `display:none` when hidden, NOT opacity: it is a flex item in the thread's column, so an
     invisible one would still reserve a row and leave a gap under the last message. */
  .wa-jumpbtn{position:sticky;bottom:calc(8*var(--wa-u,1px));align-self:flex-end;z-index:3;display:none;
    width:calc(38*var(--wa-u,1px));height:calc(38*var(--wa-u,1px));border-radius:50%;border:1px solid var(--wa-line);cursor:pointer;
    background:var(--wa-panel);color:var(--wa-sub);align-items:center;justify-content:center;
    box-shadow:0 2px 8px rgba(0,0,0,.16);transition:color .12s,transform .12s;
    margin-top:calc(4*var(--wa-u,1px));flex:0 0 auto;padding:0}
  .wa-jumpbtn.on{display:flex}
  .wa-jumpbtn:hover{color:var(--wa-text);transform:translateY(-1px)}
  .wa-jumpbtn svg{width:calc(20*var(--wa-u,1px));height:calc(20*var(--wa-u,1px));display:block}
  /* the faint doodle shows in BOTH themes (like WhatsApp); dark lightens + softens it */
  /* dark: dim the doodle with a dark veil so the lines sit back (darker, less obvious) */
  #waPanel[data-wa-theme="dark"] .wa-thread{
    background-image:linear-gradient(rgba(20,20,20,.66),rgba(20,20,20,.66)),url('/static/img/wa_doodle_dark.png?v=1');
    background-repeat:no-repeat,repeat;background-size:cover,calc(1720*var(--wa-u,1px))}
  .wa-empty{margin:auto;text-align:center;color:var(--wa-sub);font-size:calc(13*var(--wa-u,1px));max-width:calc(230*var(--wa-u,1px));line-height:1.5;
    background:var(--wa-in);padding:calc(10*var(--wa-u,1px)) calc(14*var(--wa-u,1px));border-radius:calc(9*var(--wa-u,1px));box-shadow:0 1px 1px rgba(11,20,26,.12)}

  /* bubbles */
  .wa-msg{max-width:74%;padding:calc(6*var(--wa-u,1px)) calc(9*var(--wa-u,1px)) calc(8*var(--wa-u,1px));border-radius:calc(7.5*var(--wa-u,1px));font-size:calc(14.2*var(--wa-u,1px));line-height:1.32;position:relative;
    box-shadow:0 1px .5px rgba(11,20,26,.13);word-wrap:break-word;margin-top:calc(2*var(--wa-u,1px))}
  .wa-msg .t{font-size:calc(11*var(--wa-u,1px));color:var(--wa-meta);float:right;margin:calc(6*var(--wa-u,1px)) 0 calc(-2*var(--wa-u,1px)) calc(10*var(--wa-u,1px));position:relative;top:calc(4*var(--wa-u,1px));white-space:nowrap}
  .wa-ampm{text-transform:lowercase;margin-left:calc(2*var(--wa-u,1px))}   /* plain lowercase am/pm at the normal timestamp size */
  .wa-conv-tm .wa-ampm{margin-left:1px}
  .wa-in{align-self:flex-start;background:var(--wa-in);color:var(--wa-text)}
  .wa-out{align-self:flex-end;background:var(--wa-out);color:var(--wa-text)}
  /* run grouping — only the FIRST message of a run (wa-ghead) has the notch + tail; continuations are fully
     rounded, sit closer together, and drop the tail. (⚠️ class is wa-ghead NOT wa-head — .wa-head is the
     thread HEADER which is display:flex; reusing it made head bubbles flex and broke stacking.) */
  .wa-in.wa-ghead{border-top-left-radius:0}
  .wa-out.wa-ghead{border-top-right-radius:0}
  .wa-msg.wa-ghead{margin-top:calc(9*var(--wa-u,1px))}
  .wa-msg.wa-gcont{margin-top:calc(2*var(--wa-u,1px))}
  /* the sharp WhatsApp tail (exact triangle via clip-path) — head only */
  .wa-in.wa-ghead::before{content:"";position:absolute;top:0;left:calc(-8*var(--wa-u,1px));width:calc(9*var(--wa-u,1px));height:calc(13*var(--wa-u,1px));background:var(--wa-in);clip-path:polygon(100% 0,100% 100%,0 0)}
  .wa-out.wa-ghead::before{content:"";position:absolute;top:0;right:calc(-8*var(--wa-u,1px));width:calc(9*var(--wa-u,1px));height:calc(13*var(--wa-u,1px));background:var(--wa-out);clip-path:polygon(0 0,100% 0,0 100%)}
  .wa-msg .snd{font-size:calc(12.5*var(--wa-u,1px));font-weight:600;margin-bottom:1px;color:var(--wa-send)}
  .wa-fwd-lbl{font-style:italic;font-size:calc(12*var(--wa-u,1px));color:var(--wa-meta);margin-bottom:calc(2*var(--wa-u,1px))}   /* "↱ Forwarded" */
  .wa-tk{color:var(--wa-tick);margin-left:calc(3*var(--wa-u,1px));display:inline-flex;vertical-align:calc(-3*var(--wa-u,1px))}
  .wa-tk.read{color:var(--wa-read)}
  .wa-tk.fail{color:#c0392b;font-weight:700;vertical-align:0}
  /* the reason a message did not go — inside the bubble, because it is a fact ABOUT that
     message and a toast would be gone by the time anyone wondered */
  .wa-failnote{margin:calc(5*var(--wa-u,1px)) 0 0;padding:calc(6*var(--wa-u,1px)) calc(8*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));font-size:calc(10.5*var(--wa-u,1px));
    line-height:1.45;color:#8a2b2b;background:rgba(214,74,74,.10);
    border:1px solid rgba(214,74,74,.35);white-space:normal;word-break:break-word}
  .wa-failraw{opacity:.72}
  .wa-tk svg{display:block}

  /* internal note — deliberately NOT WhatsApp (parchment + the amber INTERNAL header keep it distinct). It is
     LEFT-aligned (like a received bubble) and capped ≤78% so its RIGHT MARGIN always has room for the outside
     reply button — exactly how a client message's react button floats into its margin (no overflow, no feedback
     loop, no horizontal scrollbar, so nothing can ever poke over the composer). */
  /* internal system line (X joined / X left) — centered, italic, subtle; no box, just a muted shade */
  .wa-sysmsg{align-self:center;text-align:center;font-style:italic;font-size:calc(12*var(--wa-u,1px));color:var(--wa-meta);
    margin:calc(7*var(--wa-u,1px)) auto;max-width:84%;line-height:1.35}
  /* ⭐ A REFUSAL, SPOKEN IN THE THREAD (Sett, 2026-09-28: "place it in the chat thread... like it's
     part of the message... but dissappears after a while"). Same centred, italic voice as the
     `X joined the conversation` line beside it, because it is the same kind of thing: something
     that just happened in THIS conversation. Warmer than a system line and a touch heavier, so it
     reads as "this did not work" rather than "this happened", and it fades itself out. */
  /* ⭐⭐ THE SAME LIGHT RED AND MAROON AS `.wa-failnote`, THE PANEL'S OWN "Not delivered" BOX
     (Sett, 2026-09-28: "make it light red/maroon color info box... it's more obvious that it didnt
     sent through"). Deliberately the SAME colours rather than a new red: a refused file and a
     failed message are the same news, and a team that has learned to read one should not have to
     learn a second palette for the other. It was a warm peach, which read as a hint. */
  .wa-thnote{align-self:center;text-align:center;max-width:78%;margin:calc(8*var(--wa-u,1px)) auto;padding:calc(8*var(--wa-u,1px)) calc(12*var(--wa-u,1px));
    border-radius:calc(10*var(--wa-u,1px));color:#8a2b2b;background:rgba(214,74,74,.10);
    border:1px solid rgba(214,74,74,.35);
    font-size:calc(11.5*var(--wa-u,1px));line-height:1.45;font-weight:600;word-break:break-word;
    animation:waThNoteIn .18s ease-out, waThNotePulse 2.4s ease-in-out .18s infinite;
    transition:opacity .5s ease, transform .5s ease}
  .wa-thnote.wa-thnote-go{opacity:0;transform:translateY(calc(-4*var(--wa-u,1px)))}
  @keyframes waThNoteIn{from{opacity:0;transform:translateY(calc(6*var(--wa-u,1px)))}to{opacity:1;transform:none}}
  /* ⭐ A SLOW PULSE, AND IT PULSES THE RING — NOT THE OPACITY (Sett asked for the pulse and whether
     it is costly: it is not — one element, seven seconds, and a box-shadow ring is the same trick
     `waPickPulse` already uses on the pickable pills).
     ⚠️⚠️ OPACITY WAS THE OBVIOUS CHOICE AND WOULD HAVE BROKEN THE FADE-OUT. A CSS animation beats a
     transition on the same property, so an opacity pulse would have overridden `transition:opacity`
     and the note would have pulsed forever instead of leaving after its 7 seconds. The ring leaves
     opacity free for the exit. */
  @keyframes waThNotePulse{
    0%,100%{box-shadow:0 0 0 0 rgba(214,74,74,.30)}
    50%    {box-shadow:0 0 0 6px rgba(214,74,74,0)}}
  /* the house convention (three other places here do the same): a pulse is emphasis, never meaning */
  @media (prefers-reduced-motion:reduce){ .wa-thnote{animation:waThNoteIn .18s ease-out} }
  /* internal note = a "sticky note": gold rail down the left, LEFT-aligned body a touch larger than the chat
     bubbles (it was centred + the smallest text in the thread, which made it the hardest thing to read). */
  .wa-note{position:relative;align-self:center;width:50%;max-width:50%;background:var(--wa-note-bg);
    border:1px solid var(--wa-note-bd);border-left:4px solid #C4956A;border-radius:calc(8*var(--wa-u,1px));text-align:left;
    padding:calc(9*var(--wa-u,1px)) calc(12*var(--wa-u,1px)) calc(10*var(--wa-u,1px));font-size:calc(13.5*var(--wa-u,1px));line-height:1.45;color:var(--wa-note-tx);margin:calc(5*var(--wa-u,1px)) 0;
    box-shadow:0 1px 2px rgba(11,20,26,.13)}
  .wa-note .h{display:flex;align-items:center;gap:calc(6*var(--wa-u,1px));flex-wrap:wrap;margin-bottom:calc(5*var(--wa-u,1px))}
  /* whispered label + an unbold "sender → recipient" line under it */
  .wa-note-lbl{font-size:calc(9*var(--wa-u,1px));font-weight:600;color:var(--wa-note-h);opacity:.55;text-transform:uppercase;letter-spacing:.11em}
  .wa-note-who{font-size:calc(11.5*var(--wa-u,1px));font-weight:400;color:var(--wa-note-tx);opacity:.8;margin:1px 0 calc(6*var(--wa-u,1px))}
  .wa-note-who .arw{opacity:.5;margin:0 calc(3*var(--wa-u,1px))}
  .wa-note-bd{display:block;overflow-wrap:anywhere;word-break:break-word}   /* a bare url in a note has no break point — it ran past the
     note (found by the case-card test, 2026-09-22); .wa-body already wrapped, the note body did not */
  .wa-note-t{display:block;text-align:right;font-size:calc(10*var(--wa-u,1px));color:var(--wa-note-h);opacity:.75;margin-top:calc(5*var(--wa-u,1px))}
  /* click-to-reply on a teammate's note — floats OUTSIDE the box on hover, exactly like the react button. */
  .wa-note-reply{position:absolute;top:50%;right:calc(-38*var(--wa-u,1px));transform:translateY(-50%);width:calc(30*var(--wa-u,1px));height:calc(30*var(--wa-u,1px));border:none;
    border-radius:50%;background:var(--wa-panel);color:var(--wa-sub);box-shadow:0 1px 6px rgba(0,0,0,.22);cursor:pointer;
    display:grid;place-items:center;opacity:0;transition:opacity .12s;padding:0;z-index:5}
  .wa-note-reply svg{width:calc(16*var(--wa-u,1px));height:calc(16*var(--wa-u,1px))}
  /* kept pointer-events:auto (easy hover→click, no gap flicker) — the thread's overflow clipping keeps it off the composer */
  .wa-note:hover .wa-note-reply{opacity:1}
  .wa-note-reply:hover{color:var(--wa-text);transform:translateY(-50%) scale(1.09)}

  /* composer */
  /* composer floats on the SAME doodle background as the thread (no grey box) */
  .wa-compose{padding:calc(8*var(--wa-u,1px)) calc(12*var(--wa-u,1px)) calc(10*var(--wa-u,1px));flex:none;position:relative;background-color:var(--wa-bg);
    background-image:url('/static/img/wa_doodle.png?v=6');background-repeat:repeat;background-size:calc(1720*var(--wa-u,1px))}
  /* emoji picker — a grid of common emojis (native OS emoji still works). Its button is the team composer's (the
     client's emoji is a line of the ＋ menu, below) */
  .wa-inputwrap{flex:1;min-width:0;position:relative;display:flex;align-items:center}
  .wa-row .wa-inputwrap input{padding-left:calc(74*var(--wa-u,1px))}   /* room for the ＋ and template buttons INSIDE the pill */
  .wa-emojibtn{position:absolute;left:calc(71*var(--wa-u,1px));top:50%;transform:translateY(-50%);width:calc(33*var(--wa-u,1px));height:calc(33*var(--wa-u,1px));flex:none;border:none;background:transparent;cursor:pointer;line-height:0;padding:0;opacity:.78;border-radius:50%;color:var(--wa-sub);z-index:2;display:flex;align-items:center;justify-content:center}
  .wa-emojibtn:hover{opacity:1;background:rgba(0,0,0,.07)}
  /* ⭐ TEMPLATES ARE A THING YOU INSERT, LIKE AN EMOJI OR A FILE (Sett, 2026-09-11) — so the button lives
     with those, right of the ＋ that holds the other two, and opens the SAME picker the closed-window band does.
     One list, both states; what differs is only what the band around it says. Its own button, never a line of the
     ＋ menu (Sett, 2026-10-06: "1 template (important and always use)") — on a shut window it is the only way out. */
  .wa-tplbtn{position:absolute;left:calc(38*var(--wa-u,1px));top:50%;transform:translateY(-50%);width:calc(33*var(--wa-u,1px));height:calc(33*var(--wa-u,1px));flex:none;border:none;background:transparent;cursor:pointer;line-height:0;padding:0;opacity:.78;border-radius:50%;color:var(--wa-sub);z-index:2;display:flex;align-items:center;justify-content:center}
  .wa-tplbtn:hover{opacity:1;background:rgba(0,0,0,.07)}
  .wa-tplbtn svg{width:calc(22*var(--wa-u,1px));height:calc(22*var(--wa-u,1px))}
  .wa-emoji{display:none;position:absolute;bottom:calc(60*var(--wa-u,1px));left:calc(12*var(--wa-u,1px));right:calc(12*var(--wa-u,1px));max-height:calc(236*var(--wa-u,1px));overflow-y:auto;
    background:var(--wa-panel);border:1px solid var(--wa-line);border-radius:calc(12*var(--wa-u,1px));padding:calc(6*var(--wa-u,1px));
    flex-wrap:wrap;gap:calc(2*var(--wa-u,1px));box-shadow:0 8px 26px rgba(0,0,0,.2);z-index:6}
  .wa-emoji.open{display:flex}
  .wa-emoji button{border:none;background:transparent;cursor:pointer;line-height:0;padding:0;border-radius:calc(8*var(--wa-u,1px));width:calc(42*var(--wa-u,1px));height:calc(42*var(--wa-u,1px));display:flex;align-items:center;justify-content:center}
  .wa-emoji button:hover{background:rgba(0,0,0,.08)}
  /* in-thread message search — matches WhatsApp's header search: filter + highlight within the open chat */
  .wa-searchbar2{display:flex;align-items:center;gap:calc(8*var(--wa-u,1px));padding:calc(7*var(--wa-u,1px)) calc(12*var(--wa-u,1px));border-bottom:1px solid var(--wa-line);background:var(--wa-panel)}
  .wa-searchbar2 input{flex:1;border:none;background:rgba(0,0,0,.05);border-radius:calc(16*var(--wa-u,1px));padding:calc(7*var(--wa-u,1px)) calc(12*var(--wa-u,1px));font-size:calc(13*var(--wa-u,1px));font-family:inherit;color:var(--wa-text)}
  .wa-searchbar2 input:focus{outline:none}
  #waPanel[data-wa-theme="dark"] .wa-searchbar2 input{background:rgba(255,255,255,.08)}
  /* ⭐⭐ SEARCH SHOWS THE CONVERSATION, NOT A FILTERED LIST (Sett): "user need to see a few message
     thread to get the right idea of the conversation, not just one text bubble". Every match is
     marked and the arrows step between them, so a hit is always read IN CONTEXT.
     ⚠ The message currently stepped to is tinted so it is findable among several on one screen. */
  .wa-msg.wa-mark-on, .wa-note.wa-mark-on{box-shadow:0 0 0 2px #E9A100}
  /* ⚠️ THE TAIL NEEDS ITS OWN RING. `box-shadow` follows the element's own box, and the sharp
     WhatsApp tail is a `::before` triangle sitting OUTSIDE that box (left:-8px) — so the ring
     stopped dead at the corner and left the tail bare. Sett spotted it on prod.
     ⚠⚠ MY FIRST FIX WAS INVISIBLE AND I REPORTED IT WORKING. It drew the gold triangle behind the
     real one with `z-index:-1` — but a negative-z pseudo paints behind BLOCK BACKGROUNDS in the
     ancestor stacking context, and `.wa-thread` paints a background colour AND the doodle
     wallpaper. The ring was hidden behind the wallpaper. Sett saw it on prod; a scaled screenshot
     did not.
     ⭐ NO Z-INDEX AT ALL NOW — the two layers use natural paint order instead. Pseudo-elements
     paint in DOM order, so when a bubble is the current match its `::before` becomes the ENLARGED
     GOLD triangle and its `::after` re-draws the real tail ON TOP of it. What is left showing
     around the edge is the ring. */
  /* ⚠⚠ SECOND CORRECTION. Making the ring a BIGGER triangle was wrong: scaling it grew every
     edge, so its right and bottom edges landed INSIDE the bubble and read as a thin line cutting
     into it. Sett: "should be just around it, not in it."
     ⭐ THE RING IS THE SAME TRIANGLE, SHIFTED PERPENDICULAR TO ITS DIAGONAL. That is what an
     outline actually is — an offset, not a scale. The diagonal runs (9,13), so the outward normal
     is (-13,9) normalised. But a pure shift left the tail's TOP edge bare, and an arbitrary resize
     made the band TAPER — thin at one end, wide at the other — because the two diagonals then have
     different slopes and the gap between them varies along their length.
     ⭐ THE NUMBERS ARE SOLVED, NOT EYEBALLED — and my first attempt at solving them was wrong in
     two ways that Sett saw immediately.
     ⚠ It scaled the triangle and THEN lifted it 2px. The lift also moves the diagonal, back INWARD
     by 1.14px along its own normal, so a band computed as 2px rendered as 0.85 — visibly thinner
     than the ring on the rest of the bubble.
     ⚠ And the scaled triangle's bottom corner reached 1.5px BELOW the tail while its right edge sat
     at x=+1, i.e. one pixel INSIDE the bubble — where nothing covers it, so it poked in as a nub.
     ⭐ Solved directly instead. The tail's diagonal is 13x − 9y + 104 = 0 (|n| = √250). The ring is
     the same line pushed out by exactly 2px (c = 104 + 2√250), its top edge 2px above the tail's,
     and — the part that matters — its right edge ON THE BUBBLE'S LEFT EDGE rather than inside it,
     so anything below the tail lands outside the bubble where the box-shadow already paints.
     Same slope by construction (0.6923), so the band cannot taper. */
  .wa-in.wa-ghead.wa-mark-on::before{left:calc(-11.8*var(--wa-u,1px));top:calc(-2*var(--wa-u,1px));width:calc(11.8*var(--wa-u,1px));height:calc(17.1*var(--wa-u,1px));background:#E9A100}
  .wa-out.wa-ghead.wa-mark-on::before{right:calc(-11.8*var(--wa-u,1px));top:calc(-2*var(--wa-u,1px));width:calc(11.8*var(--wa-u,1px));height:calc(17.1*var(--wa-u,1px));background:#E9A100}
  .wa-in.wa-ghead.wa-mark-on::after{content:"";position:absolute;top:0;left:calc(-8*var(--wa-u,1px));width:calc(9*var(--wa-u,1px));height:calc(13*var(--wa-u,1px));
    background:var(--wa-in);clip-path:polygon(100% 0,100% 100%,0 0)}
  .wa-out.wa-ghead.wa-mark-on::after{content:"";position:absolute;top:0;right:calc(-8*var(--wa-u,1px));width:calc(9*var(--wa-u,1px));height:calc(13*var(--wa-u,1px));
    background:var(--wa-out);clip-path:polygon(0 0,100% 0,0 100%)}
  .wa-searchnav{display:flex;align-items:center;gap:calc(2*var(--wa-u,1px));flex:0 0 auto}
  .wa-searchnav b{font-size:calc(11*var(--wa-u,1px));font-weight:600;color:var(--wa-sub);min-width:calc(34*var(--wa-u,1px));text-align:center;
    font-variant-numeric:tabular-nums}
  /* ⭐ The SAME chevron the per-message menu uses — same 21px glyph, same weight — so the search
     arrows read as part of this panel rather than as stray text glyphs (Sett's ask). */
  .wa-searchnav button{background:none;border:0;cursor:pointer;color:var(--wa-sub);padding:1px calc(2*var(--wa-u,1px));
    line-height:0;border-radius:calc(4*var(--wa-u,1px));display:flex;align-items:center;justify-content:center}
  .wa-searchnav button:hover:not([disabled]){background:var(--wa-bubble-in)}
  .wa-searchnav button[disabled]{opacity:.3;cursor:default}
  .wa-msg mark, .wa-note mark{background:#FEE38A;color:#3a2f00;border-radius:calc(2*var(--wa-u,1px));padding:0 1px}
  /* Twemoji — render emoji as WhatsApp-style flat images so RYT looks the same on every staff device */
  img.emoji{width:1.28em;height:1.28em;vertical-align:-.28em;margin:0 .04em;display:inline-block}
  .wa-emoji img.emoji{width:calc(35*var(--wa-u,1px));height:calc(35*var(--wa-u,1px));vertical-align:middle;margin:0}
  /* emoji-only message = big, floating (no bubble), timestamp only */
  .wa-msg.wa-jumbo{background:transparent;padding:1px calc(2*var(--wa-u,1px));box-shadow:none}
  .wa-msg.wa-jumbo::before{display:none}
  .wa-msg.wa-jumbo .snd{display:none}
  .wa-msg.wa-jumbo .wa-menubtn{background:transparent}   /* jumbo has no bubble → no colour fade behind the V */
  .wa-msg.wa-jumbo .wa-body img.emoji{width:calc(65*var(--wa-u,1px));height:calc(65*var(--wa-u,1px));vertical-align:middle;margin:1px}   /* body emoji only, NOT the reaction pill (jumbo +30%) */
  /* quick-react SMILEY — floats OUTSIDE the bubble on its INNER side (a small circle, appears on hover) */
  .wa-reactbtn{position:absolute;top:50%;transform:translateY(-50%);width:calc(33*var(--wa-u,1px));height:calc(33*var(--wa-u,1px));border:none;border-radius:50%;
    background:var(--wa-panel);color:var(--wa-sub);box-shadow:0 1px 6px rgba(0,0,0,.22);cursor:pointer;
    display:grid;place-items:center;opacity:0;transition:opacity .12s;padding:0;z-index:5}
  .wa-reactbtn svg{width:calc(20*var(--wa-u,1px));height:calc(20*var(--wa-u,1px))}
  /* "Mark handled" tick — same floating treatment as the react smiley, one slot further in */
  .wa-tickbtn{position:absolute;top:50%;transform:translateY(-50%);width:calc(33*var(--wa-u,1px));height:calc(33*var(--wa-u,1px));border:none;
    border-radius:50%;background:var(--wa-panel);color:var(--wa-note-h);box-shadow:0 1px 6px rgba(0,0,0,.22);
    cursor:pointer;display:grid;place-items:center;padding:0;opacity:0;transition:opacity .12s;z-index:5}
  .wa-msg:hover .wa-tickbtn{opacity:1}
  .wa-tickbtn:hover{color:#fff;background:var(--wa-note-h);transform:translateY(-50%) scale(1.08)}
  .wa-in .wa-tickbtn{right:calc(-78*var(--wa-u,1px))}    /* client bubble: smiley at -41, tick just beyond it */
  .wa-out .wa-tickbtn{left:calc(-78*var(--wa-u,1px))}
  /* the BIN — the same floating disc as the smiley, one slot beyond it on OUR bubbles (the -78 slot the handled-tick uses on
     the client's): 'Undo send' while the hold lasts, then gone (Sett, 2026-09-22: no button, subtle). Client chat ONLY —
     team chat keeps Delete in its dropdown (a team delete withdraws what everyone already has; a hover bin invited slips). */
  .wa-binbtn{position:absolute;top:50%;transform:translateY(-50%);width:calc(33*var(--wa-u,1px));height:calc(33*var(--wa-u,1px));border:none;
    border-radius:50%;background:var(--wa-panel);color:var(--wa-sub);box-shadow:0 1px 6px rgba(0,0,0,.22);
    cursor:pointer;display:grid;place-items:center;padding:0;opacity:0;transition:opacity .12s;z-index:5}
  .wa-binbtn svg{width:calc(17*var(--wa-u,1px));height:calc(17*var(--wa-u,1px))}
  .wa-msg:hover .wa-binbtn{opacity:1}
  .wa-binbtn:hover{color:#fff;background:#c0392b;transform:translateY(-50%) scale(1.08)}
  .wa-out .wa-binbtn{left:calc(-78*var(--wa-u,1px))}
  .wa-mm-ic svg{width:calc(15*var(--wa-u,1px));height:calc(15*var(--wa-u,1px));display:inline-block;vertical-align:calc(-3*var(--wa-u,1px))}
  .wa-out .wa-reactbtn{left:calc(-41*var(--wa-u,1px))}    /* our reply is right-aligned → smiley floats OUTSIDE on its LEFT */
  .wa-in .wa-reactbtn{right:calc(-41*var(--wa-u,1px))}    /* client reply is left-aligned → smiley floats OUTSIDE on its RIGHT */
  .wa-msg:hover .wa-reactbtn{opacity:1}   /* pointer-events stays auto → easy hover→click; thread clipping keeps it contained */
  .wa-reactbtn:hover{color:var(--wa-text);transform:translateY(-50%) scale(1.09)}
  /* chevron (bold V) — INSIDE the bubble, top-right. TRANSPARENT background so it never clashes with the
     bubble colour (normal / private / light / dark); a soft drop-shadow keeps it legible over text. */
  /* the V button: a CIRCULAR fade in the bubble's OWN colour (per type, auto light/dark) — covers the text
     under the chevron cleanly (no smudge) instead of blurring it, and matches every background/theme */
  .wa-menubtn{position:absolute;top:0;right:0;width:calc(34*var(--wa-u,1px));height:calc(30*var(--wa-u,1px));border:none;cursor:pointer;padding:calc(2*var(--wa-u,1px)) calc(3*var(--wa-u,1px)) 0 0;
    color:var(--wa-meta);opacity:0;transition:opacity .12s;display:grid;place-items:start end;z-index:4;
    background:radial-gradient(circle at 78% 30%, var(--wa-out) 42%, transparent 72%)}
  .wa-in .wa-menubtn{background:radial-gradient(circle at 78% 30%, var(--wa-in) 42%, transparent 72%)}
  .wa-priv .wa-menubtn{background:radial-gradient(circle at 78% 30%, var(--wa-priv) 42%, transparent 72%)}
  .wa-msg:hover .wa-menubtn{opacity:1}   /* pointer-events stays auto → easy hover→click; it sits inside the bubble anyway */
  .wa-menubtn:hover{color:var(--wa-text)}
  .wa-menubtn svg{width:calc(18*var(--wa-u,1px));height:calc(18*var(--wa-u,1px))}
  /* the reaction pill on the bubble corner */
  .wa-reacts{position:absolute;bottom:calc(-18*var(--wa-u,1px));background:var(--wa-panel);border:1px solid var(--wa-line);
    border-radius:calc(11*var(--wa-u,1px));padding:0 calc(6*var(--wa-u,1px));height:calc(22*var(--wa-u,1px));font-size:calc(13*var(--wa-u,1px));box-shadow:0 1px 3px rgba(0,0,0,.15);
    cursor:pointer;display:inline-flex;align-items:center;gap:1px;white-space:nowrap;z-index:3}
  .wa-in .wa-reacts{left:calc(8*var(--wa-u,1px))}    /* client reply (left-aligned) → reaction on its LEFT */
  .wa-out .wa-reacts{right:calc(8*var(--wa-u,1px))}  /* our reply (right-aligned) → reaction on its RIGHT */
  .wa-msg.wa-has-react{margin-bottom:calc(23*var(--wa-u,1px))}   /* reserve room for the hanging pill so it can't hit the next chevron */
  /* (no coloured border on your own reaction — plain white pill) */
  .wa-reacts i{font-style:normal;font-size:calc(11*var(--wa-u,1px));color:var(--wa-meta);margin-left:1px}
  .wa-reacts img.emoji{width:calc(15*var(--wa-u,1px));height:calc(15*var(--wa-u,1px));vertical-align:calc(-2*var(--wa-u,1px));margin:0}
  .wa-reacts img.emoji.wa-local{width:calc(20*var(--wa-u,1px));height:calc(20*var(--wa-u,1px));vertical-align:calc(-5*var(--wa-u,1px))}  /* our bought tiles fill the pill more */
  /* the floating quick-react bar (from the smiley) — MUST sit above the panel (z 1201) */
  .wa-reactbar{position:fixed;z-index:1300;background:var(--wa-panel);border:1px solid var(--wa-line);
    border-radius:calc(18*var(--wa-u,1px));padding:calc(2*var(--wa-u,1px)) calc(5*var(--wa-u,1px));box-shadow:0 6px 24px rgba(0,0,0,.28);display:flex;gap:calc(2*var(--wa-u,1px));align-items:center}
  .wa-reactbar button{width:calc(31*var(--wa-u,1px));height:calc(31*var(--wa-u,1px));border:none;background:transparent;border-radius:50%;cursor:pointer;
    font-size:calc(21*var(--wa-u,1px));display:grid;place-items:center;transition:transform .1s,background .1s;padding:0}
  .wa-reactbar button:hover{transform:scale(1.2);background:rgba(0,0,0,.06)}
  .wa-reactbar img.emoji{width:calc(26*var(--wa-u,1px));height:calc(26*var(--wa-u,1px))}                 /* Twemoji size (~75% of the bar) */
  .wa-reactbar img.emoji.wa-local{width:calc(28*var(--wa-u,1px));height:calc(28*var(--wa-u,1px))}        /* our tiles have more padding → a touch bigger so faces match */
  .wa-reactbar .wa-react-more{font-size:calc(18*var(--wa-u,1px));color:var(--wa-sub);border:none;margin-left:1px}
  .wa-reactbar .wa-react-more:hover{transform:none;background:var(--wa-line)}
  /* the full emoji picker opened from the ＋ (our whole set) */
  .wa-reactpick{position:fixed;z-index:1304;background:var(--wa-panel);border:1px solid var(--wa-line);border-radius:calc(14*var(--wa-u,1px));
    box-shadow:0 10px 30px rgba(0,0,0,.3);padding:calc(8*var(--wa-u,1px));display:grid;grid-template-columns:repeat(7,calc(42*var(--wa-u,1px)));gap:1px;
    width:calc(316*var(--wa-u,1px));max-height:calc(270*var(--wa-u,1px));overflow-y:auto}
  .wa-reactpick button{width:calc(42*var(--wa-u,1px));height:calc(42*var(--wa-u,1px));border:none;background:transparent;border-radius:calc(8*var(--wa-u,1px));cursor:pointer;
    font-size:calc(28*var(--wa-u,1px));display:grid;place-items:center;padding:0}
  .wa-reactpick button:hover{background:rgba(0,0,0,.06)}
  .wa-reactpick img.emoji{width:calc(35*var(--wa-u,1px));height:calc(35*var(--wa-u,1px))}
  .wa-reactpick img.emoji.wa-local{width:calc(38*var(--wa-u,1px));height:calc(38*var(--wa-u,1px))}
  /* the actions menu (Reply / Copy / Forward / make-private) — above the panel too */
  .wa-msgmenu{position:fixed;z-index:1302;background:var(--wa-panel);border:1px solid var(--wa-line);border-radius:calc(12*var(--wa-u,1px));
    box-shadow:0 8px 28px rgba(0,0,0,.26);overflow:hidden;min-width:calc(149*var(--wa-u,1px))}   /* 20% narrower */
  .wa-mm-list{padding:calc(4*var(--wa-u,1px))}
  .wa-mm-list button{display:flex;align-items:center;gap:calc(9*var(--wa-u,1px));width:100%;border:none;background:transparent;cursor:pointer;
    padding:calc(9*var(--wa-u,1px)) calc(10*var(--wa-u,1px));font-size:calc(13.5*var(--wa-u,1px));color:var(--wa-text);border-radius:calc(7*var(--wa-u,1px));text-align:left;font-family:inherit}
  .wa-mm-list button:hover{background:var(--wa-hover,rgba(0,0,0,.06))}
  .wa-mm-ic{width:calc(17*var(--wa-u,1px));text-align:center;color:var(--wa-sub);font-size:calc(15*var(--wa-u,1px))}
  /* reply quote INSIDE a bubble (the message being replied to) */
  /* the reply quote is a full-width block ON TOP of the reply (never beside it) */
  .wa-quote{display:block;width:100%;box-sizing:border-box;border-left:3px solid var(--wa-send);
    background:rgba(0,0,0,.05);border-radius:calc(5*var(--wa-u,1px));padding:calc(4*var(--wa-u,1px)) calc(8*var(--wa-u,1px));margin-bottom:calc(4*var(--wa-u,1px));
    font-size:calc(12.5*var(--wa-u,1px));line-height:1.3;overflow:hidden}
  .wa-fwd-lbl{display:block}
  .wa-fwd-ic{display:inline-block;vertical-align:calc(-3*var(--wa-u,1px));margin-right:calc(4*var(--wa-u,1px));width:calc(15*var(--wa-u,1px));height:calc(15*var(--wa-u,1px))}   /* inline, before the word */
  /* ⚠️⚠️ `pre-wrap` IS WHAT MAKES A NUMBERED LIST SURVIVE. The composer already turns Shift+Enter
     into real newlines and the DB stores them (prod message 195 has them) — but the bubble had no
     white-space rule, so every line ran together into one paragraph. Exactly the S82 bug, which was
     fixed in the case Team Chat and never here.
     ⚠️ It goes on `.wa-body`, NOT `.wa-msg`: the bubble also holds the quote, the sender name and the
     reaction row, and `pre-wrap` there would render the markup's own indentation as blank space.
     ⭐ `.wa-body` is shared with the team panel, so one rule fixes both. */
  .wa-body{display:block;white-space:pre-wrap;overflow-wrap:anywhere}   /* text + timestamp — a block sibling so the quote/label stay ON TOP */
  .wa-quote .wa-q-name{display:block;font-weight:600;color:var(--wa-send);font-size:calc(12*var(--wa-u,1px))}
  .wa-quote .wa-q-snip{display:block;color:var(--wa-sub);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* reply quote BAR above the composer (what you're about to reply to) */
  .wa-replyquote{display:flex;align-items:center;gap:calc(8*var(--wa-u,1px));background:var(--wa-input);border-left:3px solid var(--wa-send);
    border-radius:calc(7*var(--wa-u,1px));padding:calc(6*var(--wa-u,1px)) calc(10*var(--wa-u,1px));margin:0 0 calc(8*var(--wa-u,1px))}
  .wa-rq-body{flex:1;min-width:0}
  .wa-rq-name{font-size:calc(12.5*var(--wa-u,1px));font-weight:600;color:var(--wa-send)}
  .wa-rq-snip{font-size:calc(12.5*var(--wa-u,1px));color:var(--wa-sub);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .wa-rq-x{border:none;background:transparent;color:var(--wa-sub);cursor:pointer;font-size:calc(15*var(--wa-u,1px));padding:calc(2*var(--wa-u,1px)) calc(4*var(--wa-u,1px));flex:none}
  /* forward picker (choose a chat to forward to) */
  .wa-fwd{position:fixed;inset:0;z-index:1305;background:rgba(0,0,0,.4);display:flex;align-items:center;justify-content:center}
  /* ⭐ IMAGE VIEWER — opens INSIDE the panel, the way WhatsApp does. A picture used to open in a new
     browser TAB, which threw you out of the conversation to look at something that belongs to it.
     ⚠️ z-index sits above the panel's own 1201 and above the message menu's 1302: the S94 rule is
     that a floating layer inside this panel renders BEHIND it otherwise. Attached to #waPanel too,
     so it inherits the --wa-* variables and follows light/dark with everything else. */
  /* ⚠️ ABSOLUTE, NOT FIXED — the viewer belongs to the CHAT PANEL, not the browser window (Sett).
     `#waPanel` is position:fixed, so `inset:0` here fills exactly the panel and nothing beyond it:
     the rest of RYT stays visible and usable behind, and the picture never blacks out the whole
     screen to show something that belongs to one conversation. */
  .wa-lb{position:absolute;inset:0;z-index:1320;background:rgba(11,20,26,.92);display:none;
    align-items:center;justify-content:center}
  .wa-lb.on{display:flex}
  .wa-lb img, .wa-lb video{max-width:84%;max-height:78%;border-radius:calc(4*var(--wa-u,1px));object-fit:contain;
    box-shadow:0 10px 40px rgba(0,0,0,.5)}
  /* ⭐ A VIDEO OPENS IN THE PANEL, NOT THE BROWSER (Sett). `.wa-lb` is `position:absolute;
     inset:0` inside #waPanel, so this viewer is already bounded by the chat window — the same
     frame a picture opens in. Native fullscreen is suppressed on the inline player instead of
     being intercepted: there is no reliable way to catch the button, and a video that escapes
     to the whole screen is precisely what he did not want. */
  /* ⭐ AN EXPIRED ATTACHMENT SAYS SO (Sett's call). The object is gone but the row remembers what
     it was, so the bubble names the file instead of showing nothing. Silence reads as the app
     having lost something; this reads as policy. The message TEXT is never swept. */
  .wa-gone{display:flex;align-items:baseline;gap:calc(6*var(--wa-u,1px));padding:calc(7*var(--wa-u,1px)) calc(9*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));
    background:rgba(0,0,0,.05);font-size:calc(12*var(--wa-u,1px));opacity:.72;max-width:calc(340*var(--wa-u,1px))}
  .wa-gone b{font-weight:600;font-size:calc(12*var(--wa-u,1px));word-break:break-all}
  .wa-gone i{font-style:normal;opacity:.8;white-space:nowrap}
  .wa-vidwrap{position:relative;display:inline-block;max-width:100%}
  .wa-vidwrap .wa-vidx{position:absolute;top:calc(6*var(--wa-u,1px));right:calc(6*var(--wa-u,1px));width:calc(26*var(--wa-u,1px));height:calc(26*var(--wa-u,1px));border:0;
    border-radius:calc(5*var(--wa-u,1px));display:grid;place-items:center;cursor:pointer;color:#fff;
    background:rgba(0,0,0,.42);opacity:.62;transition:opacity .13s}
  /* ⚠️ VISIBLE WITHOUT HOVER. The picture chevron can hide until hover because a picture opens
     on a plain click; a video cannot — clicking it toggles play — so this button IS the only way
     to open one bounded. THE BENCH TABLETS HAVE NO HOVER, so a hover-only control would leave a
     DT with no way to expand a video at all. Quiet at .62, full on hover. */
  .wa-vidwrap:hover .wa-vidx{opacity:1}
  .wa-vidwrap .wa-vidx:hover{background:rgba(0,0,0,.62)}
  .wa-lb-bar{position:absolute;top:0;left:0;right:0;height:calc(52*var(--wa-u,1px));display:flex;align-items:center;
    justify-content:space-between;padding:0 calc(12*var(--wa-u,1px));color:#fff;
    background:linear-gradient(180deg,rgba(0,0,0,.45),transparent)}
  .wa-lb-name{font-size:calc(13*var(--wa-u,1px));opacity:.9;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    max-width:60%}
  .wa-lb-acts{display:flex;align-items:center;gap:calc(4*var(--wa-u,1px))}
  .wa-lb-btn{background:transparent;border:0;color:#fff;cursor:pointer;padding:calc(7*var(--wa-u,1px)) calc(9*var(--wa-u,1px));border-radius:50%;
    font-size:calc(17*var(--wa-u,1px));line-height:1;opacity:.85}
  /* ⭐ the SAVE button carries a filled circle the way WhatsApp's does — it is the one action here you
     reach for deliberately, so it reads as a button rather than as decoration. The ✕ stays bare,
     which is also what WhatsApp does. */
  .wa-lb-dlbtn{display:inline-grid;place-items:center;width:calc(34*var(--wa-u,1px));height:calc(34*var(--wa-u,1px));padding:0;
    background:rgba(255,255,255,.16);opacity:1}
  .wa-lb-dlbtn:hover{background:rgba(255,255,255,.28)}
  .wa-lb-btn:hover{background:rgba(255,255,255,.14);opacity:1}
  /* the step arrows sit off the picture, so they never cover what you came to look at */
  /* sized for a 400px-wide panel rather than a full screen — full-window arrows would crowd the
     picture out of the very space it is being shown in */
  .wa-lb-nav{position:absolute;top:50%;transform:translateY(-50%);background:rgba(0,0,0,.35);
    border:0;color:#fff;cursor:pointer;font-size:calc(22*var(--wa-u,1px));line-height:1;padding:calc(9*var(--wa-u,1px)) calc(11*var(--wa-u,1px));border-radius:50%}
  .wa-lb-nav:hover{background:rgba(0,0,0,.55)}
  .wa-lb-prev{left:calc(8*var(--wa-u,1px))}
  .wa-lb-next{right:calc(8*var(--wa-u,1px))}
  .wa-lb-count{position:absolute;bottom:calc(16*var(--wa-u,1px));left:50%;transform:translateX(-50%);color:#fff;
    font-size:calc(12*var(--wa-u,1px));opacity:.75}
  .wa-fwd-card{background:var(--wa-panel);border-radius:calc(14*var(--wa-u,1px));width:calc(340*var(--wa-u,1px));max-width:90vw;max-height:70vh;overflow:hidden;
    display:flex;flex-direction:column;box-shadow:0 12px 40px rgba(0,0,0,.35)}
  .wa-fwd-h{display:flex;align-items:center;justify-content:space-between;padding:calc(13*var(--wa-u,1px)) calc(15*var(--wa-u,1px));font-weight:600;font-size:calc(15*var(--wa-u,1px));
    color:var(--wa-text);border-bottom:1px solid var(--wa-line)}
  .wa-fwd-list{overflow-y:auto;padding:calc(6*var(--wa-u,1px))}
  .wa-fwd-list button{display:flex;align-items:center;gap:calc(11*var(--wa-u,1px));width:100%;border:none;background:transparent;cursor:pointer;
    padding:calc(9*var(--wa-u,1px)) calc(10*var(--wa-u,1px));border-radius:calc(8*var(--wa-u,1px));font-size:calc(14*var(--wa-u,1px));color:var(--wa-text);font-family:inherit;text-align:left}
  .wa-fwd-list button:hover{background:var(--wa-hover,rgba(0,0,0,.06))}
  .wa-fwd-av{width:calc(34*var(--wa-u,1px));height:calc(34*var(--wa-u,1px));flex:none;border-radius:50%;display:grid;place-items:center;font-size:calc(12.5*var(--wa-u,1px));font-weight:700}
  .wa-fwd-nm{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* tiny toast (Copied / Forwarded / You've left this chat).
     ⚠️ NAMED wa-ptoast, NOT wa-toast: base.html already owns `.wa-toast` for the NOTIFICATION card (white,
     green left border, pointer-events:auto) and it loads AFTER this panel, so it won this cascade — the panel
     toast rendered as a white "empty box", and because it kept pointer-events:auto even at opacity 0 it sat
     invisibly over the composer and swallowed clicks on the DR / emoji / attach buttons. Same class-collision
     trap as wa-head → wa-ghead. Keep panel class names panel-unique. */
  .wa-ptoast{position:fixed;bottom:calc(26*var(--wa-u,1px));left:50%;transform:translateX(-50%) translateY(calc(12*var(--wa-u,1px)));z-index:1310;
    background:rgba(30,30,30,.92);color:#fff;padding:calc(9*var(--wa-u,1px)) calc(18*var(--wa-u,1px));border-radius:calc(22*var(--wa-u,1px));font-size:calc(13*var(--wa-u,1px));font-weight:600;
    opacity:0;pointer-events:none;transition:opacity .18s,transform .18s}
  .wa-ptoast.on{opacity:1;transform:translateX(-50%) translateY(0)}
  #waPanel[data-wa-theme="dark"] .wa-compose{
    background-image:linear-gradient(rgba(20,20,20,.66),rgba(20,20,20,.66)),url('/static/img/wa_doodle_dark.png?v=1');
    background-repeat:no-repeat,repeat;background-size:cover,calc(1720*var(--wa-u,1px))}
  /* 24h window status = a pill that lives in the chat HEADER (larger, easy to read at a glance) */
  .wa-win{font-size:calc(11.5*var(--wa-u,1px));font-weight:600;padding:calc(4*var(--wa-u,1px)) calc(10*var(--wa-u,1px));border-radius:calc(20*var(--wa-u,1px));display:inline-flex;align-items:center;
    gap:calc(4*var(--wa-u,1px));white-space:nowrap;flex:none}
  .wa-win.ok{background:rgba(0,168,132,.14);color:var(--wa-send);align-self:center}
  /* CLOSED window — a full-bleed band across the whole thread width, sitting between the conversation and
     the composer so it reads as a barrier rather than a label. RED (Sett, 2026-09-11): the green chip is
     the open state, and this is the one that costs a paid template — the colour says which side of the
     line you are on before the words do. */
  .wa-winbar{background:var(--wa-shut-bg);border-top:1px solid var(--wa-shut-bd);
    border-bottom:1px solid var(--wa-shut-bd);padding:calc(9*var(--wa-u,1px)) calc(16*var(--wa-u,1px));font-size:calc(11.5*var(--wa-u,1px));line-height:1.45;
    color:var(--wa-shut-tx);flex:none;text-align:center}
  .wa-winbar b{font-weight:700}
  .wa-winbar-sub{opacity:.75}
  .wa-winbar-btn{margin-left:calc(10*var(--wa-u,1px));background:var(--wa-shut-btn);border:0;color:#fff;font-size:calc(11*var(--wa-u,1px));
    font-weight:700;padding:calc(4*var(--wa-u,1px)) calc(11*var(--wa-u,1px));border-radius:calc(999*var(--wa-u,1px));cursor:pointer;white-space:nowrap}
  .wa-winbar-btn:hover{background:var(--wa-shut-btn-h)}
  /* the purpose line is set exactly like the state before the button — same size, same weight, no fade
     (Sett): "24-hour window closed" and "to initiate conversation" are two halves of one sentence */
  .wa-winbar-hint{margin-left:calc(7*var(--wa-u,1px));font-weight:700}
  /* the number is the fact people scan for, so it is set a size above the sentence around it */
  .wa-winbar-n{font-size:calc(14*var(--wa-u,1px))}

  /* THE TEMPLATE PICKER — it IS the thread area while it is open, not a card floating over the
     panel (Sett, 2026-09-10: "the pop up window is too small to see and manage" — then: "fill up
     the chat thread only"). Choosing a template, filling three blanks and reading the finished
     sentence back is composing, not confirming, and the preview is the only guard against sending
     a grammatical message full of the wrong facts — so it has to be comfortably readable.
     ⭐ It is a FLEX ITEM of the chat column, not an absolute overlay, which is what keeps the
     conversation header — and with it the client's name — visible above it. You must be able to
     see WHO you are about to message while you compose. The nav rail and the conversation rail
     are outside this column entirely, so they are untouched by construction. */
  .wa-tpl{display:none;flex:1;min-height:0;background:var(--wa-panel)}
  .wa-tpl.on{display:flex;flex-direction:column}
  .wa-tpl-card{background:var(--wa-panel);border:0;border-radius:0;
    width:100%;flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden;
    box-shadow:none}
  /* …and while it is up, the conversation's own controls stand down: the thread it replaces, the
     closed-window barrier whose button opened it, and a composer that cannot reach the client
     anyway. Scoped with `>` to this column, so a nested thread elsewhere is never caught. */
  .wa-tpl-mode > .wa-thread,
  .wa-tpl-mode > .wa-winbar,
  .wa-tpl-mode > .wa-compose{display:none}
  /* ⭐ THE HEADER IS THE STATE (Sett, 2026-09-11): one banner — title, the window state, ↻, ✕ — painted
     green or red as a whole. The long explanatory strip that used to sit in the body is gone; the
     colour and three words carry it. ⚠️ Repainted on every render, so the 3s poll's flip shows. */
  .wa-tpl-head{display:flex;align-items:center;justify-content:space-between;gap:calc(10*var(--wa-u,1px));
    padding:calc(11*var(--wa-u,1px)) calc(14*var(--wa-u,1px));border-bottom:1px solid var(--wa-line);flex:none;color:var(--wa-text)}
  /* the OPEN colour is the ✓ 24h chip's (`.wa-win.ok`), to the digit — Sett: "use back the same green" */
  .wa-tpl-head.open{background:rgba(0,168,132,.14);border-bottom-color:rgba(0,168,132,.32);color:var(--wa-send)}
  .wa-tpl-head.shut{background:var(--wa-shut-bg);border-bottom-color:var(--wa-shut-bd);color:var(--wa-shut-tx)}
  .wa-tpl-headl{display:flex;align-items:baseline;gap:calc(10*var(--wa-u,1px));min-width:0}
  .wa-tpl-title{font-size:calc(13*var(--wa-u,1px));font-weight:700;color:inherit;flex:none}
  .wa-tpl-hstate{font-size:calc(11.5*var(--wa-u,1px));font-weight:600;color:inherit;opacity:.9;white-space:nowrap;
    overflow:hidden;text-overflow:ellipsis}
  .wa-tpl-headr{display:flex;align-items:center;gap:calc(2*var(--wa-u,1px));flex:none}
  .wa-tpl-refresh{background:transparent;border:0;color:inherit;font-size:calc(14*var(--wa-u,1px));
    cursor:pointer;padding:calc(2*var(--wa-u,1px)) calc(7*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));line-height:1;opacity:.75}
  .wa-tpl-refresh:hover{background:rgba(0,0,0,.06);opacity:1}
  .wa-tpl-x{background:transparent;border:0;color:inherit;font-size:calc(15*var(--wa-u,1px));cursor:pointer;
    padding:calc(2*var(--wa-u,1px)) calc(7*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));line-height:1;opacity:.75}
  .wa-tpl-x:hover{background:rgba(0,0,0,.06);opacity:1}
  .wa-tpl-scroll{overflow-y:auto;padding:calc(16*var(--wa-u,1px)) calc(20*var(--wa-u,1px)) calc(20*var(--wa-u,1px));display:flex;flex-direction:column;gap:calc(15*var(--wa-u,1px));
    flex:1}
  .wa-tpl-lbl{font-size:calc(10*var(--wa-u,1px));font-weight:700;letter-spacing:.06em;text-transform:uppercase;
    color:var(--wa-sub);margin-bottom:calc(5*var(--wa-u,1px))}
  .wa-tpl-case{width:100%;font-size:calc(12*var(--wa-u,1px));padding:calc(6*var(--wa-u,1px)) calc(8*var(--wa-u,1px));border:1px solid var(--wa-line);
    border-radius:calc(8*var(--wa-u,1px));background:var(--wa-field);color:var(--wa-text)}
  /* ⭐ ONE TEMPLATE ROW PER LINE, AND ONLY THE CHOSEN ONE OPENS. With every body shown in full the
     list ran 341px past the fold, so the message itself — the thing most worth reading before Send
     — was the part you had to scroll for. Collapsed rows keep their first line as an ellipsis so
     the list is still choosable. */
  .wa-tpl-row{border:1px solid var(--wa-line);border-radius:calc(10*var(--wa-u,1px));background:var(--wa-field);
    margin-bottom:calc(7*var(--wa-u,1px));overflow:hidden}
  .wa-tpl-row.on{border-color:rgba(214,138,43,.75);background:rgba(214,138,43,.07)}
  .wa-tpl-pickbtn{display:flex;align-items:center;gap:calc(9*var(--wa-u,1px));width:100%;min-width:0;background:transparent;
    border:0;text-align:left;padding:calc(9*var(--wa-u,1px)) calc(11*var(--wa-u,1px));cursor:pointer;color:inherit;font:inherit}
  .wa-tpl-pickbtn:hover{background:var(--wa-hover)}
  .wa-tpl-row.on .wa-tpl-pickbtn:hover{background:transparent}
  .wa-tpl-dot{width:calc(12*var(--wa-u,1px));height:calc(12*var(--wa-u,1px));border-radius:50%;border:1.5px solid var(--wa-sub);flex:none}
  .wa-tpl-row.on .wa-tpl-dot{border-color:#C4956A;background:#C4956A;
    box-shadow:inset 0 0 0 2.5px var(--wa-panel)}
  .wa-tpl-nm{font-size:calc(12*var(--wa-u,1px));font-weight:700;color:var(--wa-text);flex:none}
  /* (the wording preview that trailed each title was removed 2026-09-11 — Sett: cluttered; the
     search box still matches on the wording through data-q) */
  .wa-tpl-under{padding:0 calc(11*var(--wa-u,1px)) calc(11*var(--wa-u,1px))}
  .wa-tpl-bd{font-size:calc(11*var(--wa-u,1px));line-height:1.45;color:var(--wa-sub);margin-top:calc(2*var(--wa-u,1px))}
  /* the no-case note sits ON the Linked Cases row as a pill, in the same amber it had as a box */
  .wa-tpl-lblrow{display:flex;align-items:center;gap:calc(8*var(--wa-u,1px));flex-wrap:wrap;margin-bottom:calc(5*var(--wa-u,1px))}
  .wa-tpl-lblrow .wa-tpl-lbl{margin-bottom:0}
  .wa-tpl-none{font-size:calc(10.5*var(--wa-u,1px));font-weight:600;line-height:1.4;color:var(--wa-note-h);border-radius:calc(999*var(--wa-u,1px));
    background:rgba(214,138,43,.10);border:1px solid var(--wa-line);padding:calc(2*var(--wa-u,1px)) calc(9*var(--wa-u,1px))}
  /* (the fact chips — Doctor · You · Patient … — and their "click a blank, then a chip" line were
     removed 2026-09-11: Sett found the picker cluttered; mapped blanks fill themselves, the rest
     are typed) */
  /* ⭐⭐ THE SENTENCE IS THE FORM — dressed as the outgoing bubble it becomes, with the blanks
     edited where the words go. ⚠️ line-height is generous because an input is taller than the text
     around it; tighten it and the lines of a wrapped template collide. */
  .wa-tpl-sent{background:var(--wa-out);border-radius:calc(8*var(--wa-u,1px));margin:0 calc(11*var(--wa-u,1px)) calc(9*var(--wa-u,1px));padding:calc(11*var(--wa-u,1px)) calc(14*var(--wa-u,1px));
    font-size:calc(13*var(--wa-u,1px));line-height:2.05;color:var(--wa-text);white-space:pre-wrap;word-break:break-word}
  /* an input that grows with what is typed into it. The ::after mirror carries the same text in the
     same grid cell and is what sets the width — so there is no measuring code to drift out of step,
     and no resize observer (which a hidden preview pane would not run anyway).
     ⚠️ the mirror and the input MUST share font, padding and border width or the box lies. */
  .wa-tpl-grow{display:inline-grid;vertical-align:baseline;max-width:100%}
  /* ⚠️ the blank inherits the sentence's 2.05 line-height unless told otherwise — that is what made it
     33px tall (Sett: "reduce it to slightly bigger than the font size"). Mirror and input share it. */
  .wa-tpl-grow::after{content:attr(data-v);visibility:hidden;white-space:pre;grid-area:1/1;
    font:inherit;line-height:1.25;padding:1px calc(6*var(--wa-u,1px));border:1px solid transparent;min-width:2.6em}
  .wa-tpl-slot{grid-area:1/1;width:100%;min-width:0;font:inherit;line-height:1.25;color:var(--wa-text);
    background:var(--wa-panel);border:1px solid var(--wa-line);border-radius:calc(6*var(--wa-u,1px));padding:1px calc(6*var(--wa-u,1px))}
  .wa-tpl-slot:focus{outline:none;border-color:rgba(214,138,43,.85);
    box-shadow:0 0 0 2px rgba(214,138,43,.18)}
  .wa-tpl-slot.miss{border-color:rgba(214,74,74,.7);background:rgba(214,74,74,.07)}
  .wa-tpl-slot::placeholder{color:var(--wa-sub);opacity:.75}
  .wa-tpl-foot{display:flex;align-items:center;gap:calc(8*var(--wa-u,1px));padding:calc(10*var(--wa-u,1px)) calc(14*var(--wa-u,1px));flex:none;
    border-top:1px solid var(--wa-line)}
  .wa-tpl-err{flex:1;font-size:calc(11*var(--wa-u,1px));line-height:1.4;color:#c0392b}
  .wa-tpl-cancel{background:transparent;border:0;color:var(--wa-sub);font-size:calc(12*var(--wa-u,1px));cursor:pointer;padding:calc(6*var(--wa-u,1px)) calc(9*var(--wa-u,1px))}
  .wa-tpl-send{background:var(--wa-send);border:0;color:#fff;font-size:calc(12*var(--wa-u,1px));font-weight:700;
    padding:calc(7*var(--wa-u,1px)) calc(16*var(--wa-u,1px));border-radius:calc(999*var(--wa-u,1px));cursor:pointer}
  .wa-tpl-send[disabled]{opacity:.45;cursor:default}
  /* ── THE STAGED TEMPLATE — where the composer is, drawn as the bubble the dentist receives (2026-09-22) ── */
  .wa-stage{flex:none;background:var(--wa-composer);border-top:1px solid var(--wa-line);padding:calc(8*var(--wa-u,1px)) calc(12*var(--wa-u,1px)) calc(10*var(--wa-u,1px))}
  .wa-stage-h{display:flex;align-items:baseline;gap:calc(8*var(--wa-u,1px));font-size:calc(11*var(--wa-u,1px));color:var(--wa-sub);margin-bottom:calc(6*var(--wa-u,1px))}   /* the title alone (Sett: keep it clean) */
  .wa-stage-t{font-weight:700;color:var(--wa-text)}
  .wa-stage-wrap{display:flex;justify-content:flex-end}
  /* the whole width of the stage (Sett, 2026-10-05: "the preview green color area should fill up the entire grey area
     window") — it was a bubble of 55-88% at the right, as in the thread */
  .wa-stage-bub{flex:1;min-width:0;background:var(--wa-out);color:var(--wa-text);border-radius:calc(7.5*var(--wa-u,1px));border-top-right-radius:0;
    box-shadow:0 1px .5px rgba(11,20,26,.13);font-size:calc(14.2*var(--wa-u,1px));line-height:1.32}
  .wa-stage-text{padding:calc(7*var(--wa-u,1px)) calc(10*var(--wa-u,1px)) calc(8*var(--wa-u,1px));white-space:pre-wrap;overflow-wrap:anywhere;min-height:1.4em;outline:none}
  .wa-stage-text[contenteditable="true"]:focus{background:rgba(255,255,255,.35);border-radius:calc(7*var(--wa-u,1px))}
  .wa-stage-text.locked{line-height:2.05}   /* the blanks are fields here — the picker's own slot sizing */
  .wa-stage-btn{border-top:1px solid rgba(11,20,26,.12);padding:calc(7*var(--wa-u,1px)) calc(10*var(--wa-u,1px));text-align:center;color:var(--wa-send);font-weight:600;font-size:calc(13*var(--wa-u,1px))}
  .wa-stage-btn-ic{margin-right:calc(5*var(--wa-u,1px))}
  .wa-stage-btn.astext{text-align:left;color:var(--wa-text);font-weight:500}   /* an edited wording carries the link as text */
  /* the file a template goes out with (Sett, 2026-10-05) — at the TOP of the bubble, where WhatsApp shows a template's
     header to the dentist: a dashed slot to attach it, then the PDF's name and size, or the image itself */
  .wa-stage-att{position:relative;display:flex;align-items:center;gap:calc(9*var(--wa-u,1px));margin:calc(4*var(--wa-u,1px)) calc(4*var(--wa-u,1px)) 0;padding:calc(8*var(--wa-u,1px)) calc(10*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));background:rgba(11,20,26,.06)}
  .wa-stage-att.empty{border:1.5px dashed var(--wa-sub);background:transparent;cursor:pointer}
  .wa-stage-att.empty:hover{background:rgba(11,20,26,.04)}
  /* the file input inside is invisible, so the slot shows where the keyboard is (CodeRabbit, PR #296) */
  .wa-stage-att.empty:focus-within{outline:2px solid var(--wa-send);outline-offset:2px}
  .wa-stage-att input[type=file]{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
  .wa-stage-att-ic{flex:none;font-size:calc(22*var(--wa-u,1px));line-height:1}
  .wa-stage-att-txt{display:flex;flex-direction:column;flex:1;min-width:0}
  .wa-stage-att-cta{font-weight:700;font-size:calc(13*var(--wa-u,1px));color:var(--wa-send)}
  .wa-stage-att-nm{font-weight:600;font-size:calc(13*var(--wa-u,1px));overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .wa-stage-att-why{font-size:calc(11*var(--wa-u,1px));color:var(--wa-sub)}
  .wa-stage-att.img{display:block;padding:0;background:transparent}
  .wa-stage-att.img img{display:block;width:100%;max-height:calc(220*var(--wa-u,1px));object-fit:cover;border-radius:calc(6*var(--wa-u,1px))}
  .wa-stage-att-x{flex:none;border:0;background:rgba(11,20,26,.55);color:#fff;width:calc(24*var(--wa-u,1px));height:calc(24*var(--wa-u,1px));border-radius:50%;cursor:pointer;font-size:calc(12*var(--wa-u,1px));line-height:1}
  .wa-stage-att.img .wa-stage-att-x{position:absolute;top:calc(6*var(--wa-u,1px));right:calc(6*var(--wa-u,1px))}
  /* the note is for a FAILURE only (Sett, 2026-09-22 evening: "remove all the small instructions around the green reply
     box") — empty it takes no room; a refusal from the send still has to be said, and this is where it is said */
  .wa-stage-note{font-size:calc(11*var(--wa-u,1px));line-height:1.4;color:var(--wa-shut-tx);font-weight:600;margin:calc(7*var(--wa-u,1px)) 0 calc(2*var(--wa-u,1px))}
  .wa-stage-note:empty{display:none}
  .wa-stage-shut{font-weight:600;color:var(--wa-shut-tx);margin-left:calc(8*var(--wa-u,1px))}   /* the head IS the state (S129 round 3) */
  .wa-stage-foot{display:flex;align-items:center;gap:calc(6*var(--wa-u,1px));margin-top:calc(6*var(--wa-u,1px))}
  .wa-stage-sp{flex:1}
  /* a PILL you can see (Sett: "there's outline but it's too transparent.. make it obvious"): the muted-text colour as the
     border, in both themes, not the hairline the composer's own borders use */
  .wa-stage-b{background:transparent;border:1.5px solid var(--wa-sub);color:var(--wa-text);font-size:calc(12*var(--wa-u,1px));font-weight:600;cursor:pointer;padding:calc(5*var(--wa-u,1px)) calc(12*var(--wa-u,1px));border-radius:calc(999*var(--wa-u,1px))}
  .wa-stage-b:hover{background:rgba(11,20,26,.06)}
  .wa-stage-send{background:var(--wa-send);border:0;color:#fff;font-size:calc(12*var(--wa-u,1px));font-weight:700;padding:calc(7*var(--wa-u,1px)) calc(16*var(--wa-u,1px));border-radius:calc(999*var(--wa-u,1px));cursor:pointer}
  .wa-stage-send[disabled]{opacity:.45;cursor:default}
  .wa-tpl-empty{font-size:calc(11.5*var(--wa-u,1px));line-height:1.55;color:var(--wa-sub);text-align:center;padding:calc(14*var(--wa-u,1px)) calc(4*var(--wa-u,1px))}
  /* ⭐⭐ THE PICKER SAYS WHICH STATE IT IS SENDING IN. The same list serves an open window and a
     shut one, and only the shut one is billed as a business-initiated message — so the state is
     the first thing on the screen, in the band's own colours, and the Send button repeats it. */
  /* a template's Meta category rides on its row: UTILITY is quiet, anything else is marked as billed
     regardless of the window — the one thing a person cannot tell from the wording */
  .wa-tpl-cat{font-size:calc(9.5*var(--wa-u,1px));font-weight:700;letter-spacing:.05em;text-transform:uppercase;
    padding:calc(2*var(--wa-u,1px)) calc(7*var(--wa-u,1px));border-radius:calc(999*var(--wa-u,1px));flex:none;line-height:1.4}
  .wa-tpl-cat.util{color:var(--wa-sub);border:1px solid var(--wa-chipoff-bd)}
  .wa-tpl-cat.other{background:rgba(214,138,43,.16);color:var(--wa-note-h)}
  /* the file a template goes out with, as its icon (Sett, 2026-10-05: "place the PDF icon and Image Icon instead.. it's
     more obvious") — beside the name in the list, before the picker's line about it, and in the stage's attach slot */
  /* the category chips over the list (Sett, 2026-10-05: "categorizing... for easier selection") */
  .wa-tpl-grps{display:flex;flex-wrap:wrap;gap:calc(6*var(--wa-u,1px));margin:calc(2*var(--wa-u,1px)) 0 calc(10*var(--wa-u,1px))}
  .wa-tpl-grp{display:inline-flex;align-items:center;gap:calc(6*var(--wa-u,1px));border:1px solid var(--wa-chipoff-bd);background:transparent;
    color:var(--wa-text);font-size:calc(12*var(--wa-u,1px));font-weight:600;padding:calc(5*var(--wa-u,1px)) calc(12*var(--wa-u,1px));
    border-radius:calc(999*var(--wa-u,1px));cursor:pointer;line-height:1.2}
  .wa-tpl-grp:hover{background:rgba(11,20,26,.05)}
  .wa-tpl-grp i{font-style:normal;font-weight:600;color:var(--wa-sub);font-size:calc(11*var(--wa-u,1px))}
  .wa-tpl-grp.on{background:var(--wa-send);border-color:var(--wa-send);color:#fff}
  .wa-tpl-grp.on i{color:rgba(255,255,255,.85)}
  /* superadmin's "As" row: whose list is on screen — quieter than the category chips, dark when on */
  .wa-tpl-roles{display:flex;flex-wrap:wrap;align-items:center;gap:calc(5*var(--wa-u,1px));margin:0 0 calc(8*var(--wa-u,1px))}
  .wa-tpl-roles-lab{font-size:calc(10.5*var(--wa-u,1px));font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--wa-sub);margin-right:calc(2*var(--wa-u,1px))}
  .wa-tpl-role{border:1px solid var(--wa-chipoff-bd);background:transparent;color:var(--wa-sub);font-size:calc(11.5*var(--wa-u,1px));font-weight:600;
    padding:calc(3*var(--wa-u,1px)) calc(10*var(--wa-u,1px));border-radius:calc(999*var(--wa-u,1px));cursor:pointer;line-height:1.3}
  .wa-tpl-role:hover{background:rgba(11,20,26,.05)}
  .wa-tpl-role.on{background:#3d2a14;border-color:#3d2a14;color:#fff}
  .wa-tpl-hdr{display:inline-flex;align-items:center;flex:none}
  .wa-tpl-hico{display:block;width:calc(22*var(--wa-u,1px));height:calc(22*var(--wa-u,1px))}
  .wa-tpl-bd .wa-tpl-hico{display:inline-block;vertical-align:-.3em;width:calc(17*var(--wa-u,1px));height:calc(17*var(--wa-u,1px));margin-right:calc(5*var(--wa-u,1px))}
  .wa-stage-att-ic .wa-tpl-hico{width:calc(32*var(--wa-u,1px));height:calc(32*var(--wa-u,1px))}
  /* ⭐ templates by ROLE (S129): a section per group, a search box once the list is long, and one
     quiet line saying that other roles' templates exist but are not offered here */
  .wa-tpl-sec{display:flex;align-items:baseline;justify-content:space-between;margin:calc(12*var(--wa-u,1px)) 0 calc(5*var(--wa-u,1px))}
  .wa-tpl-sec:first-child{margin-top:0}
  .wa-tpl-sec b{font-size:calc(11*var(--wa-u,1px));font-weight:700;color:var(--wa-text)}
  .wa-tpl-sec i{font-style:normal;font-size:calc(10.5*var(--wa-u,1px));color:var(--wa-sub)}
  .wa-tpl-search{width:100%;box-sizing:border-box;border:1px solid var(--wa-line);border-radius:calc(8*var(--wa-u,1px));
    background:var(--wa-panel);color:var(--wa-text);font:inherit;font-size:calc(12*var(--wa-u,1px));padding:calc(6*var(--wa-u,1px)) calc(9*var(--wa-u,1px));margin-top:calc(9*var(--wa-u,1px))}
  .wa-tpl-search::placeholder{color:var(--wa-sub)}
  .wa-tpl-hint{font-size:calc(10.5*var(--wa-u,1px));color:var(--wa-sub);text-align:center;margin-top:calc(8*var(--wa-u,1px))}
  .wa-tpl-row.wa-tpl-q{display:none}
  /* …and the composer is closed for business: it cannot reach the client, so it does not pretend to.
     ⚠️ DIMMED PER CONTROL, NOT ON THE WRAPPER: a child can never be brighter than its parent, and the
     template button must stay live and undimmed — it is the one thing in the pill that still reaches
     the client. ⚠️ The ＋ and emoji never do their job on a shut window — before PR #217 the ＋ opened
     the file picker there, letting a DT stage a file and write a caption the server would then refuse.
     They were made inert; since 2026-10-05 (Sett: "some info for attachment + and emoticon") a tap on
     either, by mouse, finger or keyboard, opens the shut-window sheet instead (`_waAttachOpen` /
     `_waEmojiOpen`, which read the LIVE payload) — still dim, so the state reads before the tap. Since
     2026-10-06 they are lines of the ＋ menu, dim there; the ＋ itself is not (the tablet's Take photos
     still has a road on a shut window: the case's Design Files). */
  .wa-row.wa-win-shut .wa-ce,
  .wa-row.wa-win-shut :is(.wa-pm-attach, .wa-pm-emoji){opacity:.5}
  .wa-row.wa-win-shut .wa-ce{cursor:not-allowed}
  /* the 24h chip sits INSIDE the input on the far right, mirroring the emoji/attach buttons on the left */
  .wa-inputwrap{position:relative}
  .wa-inputwrap .wa-win{position:absolute;right:calc(10*var(--wa-u,1px));top:50%;transform:translateY(-50%);pointer-events:none}
  /* three selectors deep on purpose: `.wa-row .wa-ce` sets the padding later in the file with the same
     specificity, so a two-part selector loses and the text runs under the chip. */
  .wa-row .wa-inputwrap .wa-ce{padding-right:calc(70*var(--wa-u,1px))}
  .wa-notebox{margin-bottom:calc(8*var(--wa-u,1px));background:var(--wa-note-bg);border:1px solid var(--wa-note-bd);border-radius:calc(10*var(--wa-u,1px));padding:calc(9*var(--wa-u,1px));text-align:center}
  .wa-notebox .h{font-size:calc(12*var(--wa-u,1px));font-weight:700;color:var(--wa-note-h);margin-bottom:calc(6*var(--wa-u,1px));text-align:center}
  /* Invite Teammates — no text field, so the two buttons sit right instead of stretching a phantom input */
  .wa-inviterow{justify-content:flex-end;margin-top:calc(7*var(--wa-u,1px))}
  .wa-note-top{display:flex;align-items:center;justify-content:center;gap:calc(10*var(--wa-u,1px));flex-wrap:wrap;margin-bottom:calc(6*var(--wa-u,1px))}
  .wa-note-top .h{margin-bottom:0}
  .wa-row{display:flex;gap:calc(8*var(--wa-u,1px));align-items:center}
  .wa-row input{flex:1;min-width:0;border:none;border-radius:calc(20*var(--wa-u,1px));padding:calc(10*var(--wa-u,1px)) calc(15*var(--wa-u,1px));font-size:calc(14*var(--wa-u,1px));font-family:inherit;
    color:var(--wa-text);background:var(--wa-input);outline:none}
  .wa-row input::placeholder{color:var(--wa-sub)}
  /* rich-text composer (contenteditable) — shows emoji tiles inline as you build the message */
  .wa-row .wa-ce{flex:1;min-width:0;border:none;border-radius:calc(20*var(--wa-u,1px));padding:calc(10*var(--wa-u,1px)) calc(15*var(--wa-u,1px)) calc(10*var(--wa-u,1px)) calc(74*var(--wa-u,1px));font-size:calc(14*var(--wa-u,1px));
    font-family:inherit;color:var(--wa-text);background:var(--wa-input);outline:none;line-height:1.45;
    max-height:calc(118*var(--wa-u,1px));overflow-y:auto;white-space:pre-wrap;word-break:break-word}
  .wa-ce:empty:before{content:attr(data-ph);color:var(--wa-sub);pointer-events:none}
  .wa-ce img.emoji{width:calc(20*var(--wa-u,1px));height:calc(20*var(--wa-u,1px));vertical-align:calc(-5*var(--wa-u,1px));margin:0 1px}
  .wa-priv-on .wa-row .wa-ce{background:var(--wa-priv)}
  .wa-noteopen{width:calc(40*var(--wa-u,1px));height:calc(40*var(--wa-u,1px));flex:none;border-radius:50%;border:none;padding:0;cursor:pointer;
    background:#FDE0BF url('/static/img/background.jpg') center/cover;box-shadow:0 0 0 1px rgba(196,149,106,.5);display:grid;place-items:center}
  .wa-noteopen img{width:calc(32*var(--wa-u,1px));height:calc(32*var(--wa-u,1px));object-fit:contain;display:block}   /* the DR monogram (transparent) sits on the parchment-filled circle */
  /* a button's icon must never be DRAGGABLE — dragging the DR badge into the composer used to "upload" the
     logo file itself. pointer-events:none also keeps the click on the button, not the image. */
  #waPanel button img{-webkit-user-drag:none;user-drag:none;user-select:none;pointer-events:none}
  .wa-noteopen:hover{filter:brightness(.94)}
  .wa-send{width:calc(40*var(--wa-u,1px));height:calc(40*var(--wa-u,1px));flex:none;border-radius:50%;background:var(--wa-send);color:#fff;border:none;
    display:grid;place-items:center;cursor:pointer}
  .wa-send svg{width:calc(20*var(--wa-u,1px));height:calc(20*var(--wa-u,1px))}
  .wa-nbtn{flex:none;border:none;border-radius:calc(9*var(--wa-u,1px));padding:calc(9*var(--wa-u,1px)) calc(13*var(--wa-u,1px));font-size:calc(12.5*var(--wa-u,1px));font-weight:700;cursor:pointer}
  .wa-nbtn.add{background:var(--wa-note-h);color:#fff}
  .wa-nbtn.cancel{background:transparent;color:var(--wa-sub);border:1px solid var(--wa-line)}
  .wa-nbtn.add + .wa-nbtn.cancel{margin-left:calc(2*var(--wa-u,1px))}
  .wa-notebox .wa-row input{border:1px solid var(--wa-note-bd);border-radius:calc(9*var(--wa-u,1px));background:var(--wa-panel)}
  /* office routing + scope (only rendered for admin/finance/marketing) */
  .wa-route{position:relative}
  .wa-asg-chip{display:inline-block;margin-left:calc(8*var(--wa-u,1px));font-size:calc(10.5*var(--wa-u,1px));font-weight:600;color:var(--wa-note-h);
    background:var(--wa-note-bg);border:1px solid var(--wa-note-bd);border-radius:calc(8*var(--wa-u,1px));padding:1px calc(7*var(--wa-u,1px));vertical-align:middle}
  .wa-asg-menu{position:absolute;bottom:calc(46*var(--wa-u,1px));left:0;z-index:30;width:calc(236*var(--wa-u,1px));max-width:78vw;background:var(--wa-panel);
    border:1px solid var(--wa-line);border-radius:calc(12*var(--wa-u,1px));box-shadow:0 12px 34px rgba(0,0,0,.28);padding:calc(6*var(--wa-u,1px));max-height:calc(320*var(--wa-u,1px));overflow:auto}
  .wa-asg-h{font-size:calc(10*var(--wa-u,1px));font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--wa-sub);padding:calc(6*var(--wa-u,1px)) calc(8*var(--wa-u,1px)) calc(4*var(--wa-u,1px))}
  .wa-asg-search{position:sticky;top:0;z-index:1;width:100%;box-sizing:border-box;border:none;border-bottom:1px solid var(--wa-line);
    background:var(--wa-panel);padding:calc(5*var(--wa-u,1px)) calc(10*var(--wa-u,1px));font-size:calc(12*var(--wa-u,1px));color:var(--wa-text);font-family:inherit;outline:none;margin-bottom:calc(4*var(--wa-u,1px))}
  .wa-asg-search::placeholder{color:var(--wa-sub)}
  .wa-asg-empty{padding:calc(10*var(--wa-u,1px)) calc(9*var(--wa-u,1px));font-size:calc(12*var(--wa-u,1px));color:var(--wa-sub);text-align:center}
  /* invite-a-teammate picker INSIDE the internal-note box (office only) — merges Assign into the DR/note button */
  .wa-note-invite{margin:calc(2*var(--wa-u,1px)) 0 calc(6*var(--wa-u,1px))}
  .wa-note-inv-add{border:1px dashed var(--wa-note-bd);background:transparent;color:var(--wa-note-h);font-size:calc(13*var(--wa-u,1px));font-weight:600;
    border-radius:calc(16*var(--wa-u,1px));padding:calc(3*var(--wa-u,1px)) calc(10*var(--wa-u,1px));cursor:pointer;font-family:inherit}
  .wa-note-inv-add:hover{background:var(--wa-note-bg)}
  .wa-note-inv-pop{margin-top:calc(5*var(--wa-u,1px));border:1px solid var(--wa-line);border-radius:calc(10*var(--wa-u,1px));overflow:hidden;max-height:calc(220*var(--wa-u,1px));
    display:flex;flex-direction:column;background:var(--wa-panel)}
  .wa-note-inv-pop .wa-asg-list{max-height:calc(168*var(--wa-u,1px));overflow-y:auto}
  .wa-note-hint{font-size:calc(11*var(--wa-u,1px));color:var(--wa-note-h);opacity:.85;text-align:center;margin:calc(-2*var(--wa-u,1px)) 0 calc(7*var(--wa-u,1px))}
  /* goodbye screen — shown to someone removed from a chat: the parting note only, no message history */
  .wa-ended{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:calc(12*var(--wa-u,1px));
    padding:calc(26*var(--wa-u,1px)) calc(20*var(--wa-u,1px));text-align:center}
  .wa-ended-h{font-size:calc(15*var(--wa-u,1px));font-weight:700;color:var(--wa-text)}
  .wa-ended-btn{border:none;background:var(--wa-note-h);color:#fff;font-size:calc(13*var(--wa-u,1px));font-weight:700;
    border-radius:calc(20*var(--wa-u,1px));padding:calc(8*var(--wa-u,1px)) calc(22*var(--wa-u,1px));cursor:pointer;font-family:inherit;margin-top:calc(4*var(--wa-u,1px))}
  .wa-ended-btn:hover{filter:brightness(1.08)}
  .wa-ended-sub{font-size:calc(12*var(--wa-u,1px));color:var(--wa-sub);max-width:34ch;line-height:1.5}
  /* teammate pills act as the note's RECIPIENT PICKER while the note box is open:
     pulsing = waiting to be picked · picked = tick + steady glow + ✕ · closing the box reverts them. */
  @keyframes waPickPulse{0%,100%{box-shadow:0 0 0 0 rgba(196,149,106,.55)}50%{box-shadow:0 0 0 5px rgba(196,149,106,0)}}
  .wa-pickable{cursor:pointer;animation:waPickPulse 1.7s ease-in-out infinite}
  .wa-pickable:hover{filter:brightness(.97)}
  .wa-picked{animation:none;background:#C4956A !important;border-color:#C4956A !important;color:#fff !important;
    box-shadow:0 0 0 3px rgba(196,149,106,.30)}
  .wa-picked .wa-asg-x,.wa-picked .wa-lead-tag{color:#fff}
  .wa-picked .wa-lead-tag{background:rgba(0,0,0,.22)}
  .wa-pillopen{cursor:pointer}
  .wa-pillopen:hover{filter:brightness(.96)}
  .wa-pill-add{flex:none;border:1px dashed var(--wa-note-bd);background:transparent;color:var(--wa-note-h);
    font-size:calc(12*var(--wa-u,1px));font-weight:800;line-height:1;border-radius:calc(20*var(--wa-u,1px));padding:calc(4*var(--wa-u,1px)) calc(9*var(--wa-u,1px));cursor:pointer;font-family:inherit}
  .wa-pill-add:hover{background:var(--wa-note-bg)}
  @keyframes waPickNudge{0%,100%{box-shadow:0 0 0 0 rgba(196,149,106,.75);transform:none}
    35%{box-shadow:0 0 0 11px rgba(196,149,106,0);transform:scale(1.09)}}
  .wa-nudge{animation:waPickNudge 1.24s ease-out 2 !important}
  @keyframes waHintFlash{0%,100%{color:var(--wa-note-h);opacity:.85;transform:none}
    35%{color:#c0392b;opacity:1;transform:scale(1.045)}}
  .wa-hint-flash{animation:waHintFlash 1.24s ease-out 2;font-weight:700}
  @media (prefers-reduced-motion:reduce){.wa-pickable,.wa-nudge{animation:none}
    .wa-hint-flash{animation:none;color:#c0392b}}
  /* "N unread messages" divider — a full-width band with a centered pill, like WhatsApp */
  /* ⚠️ THE NEGATIVE MARGINS ARE WHAT MAKE IT FULL-WIDTH (Sett, 2026-08-26).
     `align-self:stretch` only fills the thread's CONTENT box, so the band stopped 28px short on
     each side and read as a floating pill rather than a divider across the conversation.
     `.wa-thread` carries `padding:16px 28px 18px`, so −28px cancels exactly that — keep the two
     in step if that padding ever changes. */
  .wa-unreadbar{align-self:stretch;display:flex;align-items:center;justify-content:center;
    margin:calc(8*var(--wa-u,1px)) calc(-28*var(--wa-u,1px)) calc(4*var(--wa-u,1px));background:rgba(0,0,0,.045);padding:calc(5*var(--wa-u,1px)) calc(28*var(--wa-u,1px))}
  .wa-unreadbar span{background:var(--wa-panel);color:var(--wa-sub);font-size:calc(11.5*var(--wa-u,1px));font-weight:600;
    padding:calc(4*var(--wa-u,1px)) calc(12*var(--wa-u,1px));border-radius:calc(14*var(--wa-u,1px));box-shadow:0 1px 2px rgba(0,0,0,.10)}
  #waPanel[data-wa-theme="dark"] .wa-unreadbar{background:rgba(255,255,255,.05)}
  /* ⭐ THE DAY DIVIDER (Sett, 2026-09-18): the first message of every day opens with the day's name —
     "Today", else the date — as a fixed, centred pill in the thread, the way the phone marks a day.
     ⚠️ Why it exists: a colleague who opened a NEW, short chat a week late could not scroll, so the
     old scrolling pill never appeared and nothing on screen said which day the messages were from.
     The pill is the unread divider's pill (same size, colours, shadow) WITHOUT its band — Sett's
     second look: "lose the grey transparent banner, keep the fixed date pill" — so the unread band
     stays the one thing that spans the thread. */
  .wa-daybar{align-self:stretch;display:flex;align-items:center;justify-content:center;margin:calc(10*var(--wa-u,1px)) 0 calc(4*var(--wa-u,1px))}
  .wa-daybar span{background:var(--wa-panel);color:var(--wa-sub);font-size:calc(11.5*var(--wa-u,1px));font-weight:600;
    padding:calc(4*var(--wa-u,1px)) calc(12*var(--wa-u,1px));border-radius:calc(14*var(--wa-u,1px));box-shadow:0 1px 2px rgba(0,0,0,.10)}
  .wa-asg-row{display:flex;justify-content:space-between;align-items:center;gap:calc(8*var(--wa-u,1px));width:100%;text-align:left;
    background:transparent;border:none;border-radius:calc(8*var(--wa-u,1px));padding:calc(8*var(--wa-u,1px)) calc(9*var(--wa-u,1px));font-size:calc(13*var(--wa-u,1px));color:var(--wa-text);cursor:pointer}
  .wa-asg-row:hover{background:var(--wa-input)}
  .wa-asg-row .wa-asg-role{font-size:calc(10*var(--wa-u,1px));color:var(--wa-sub);text-transform:capitalize}
  .wa-asg-row.on{color:#fff;font-weight:700;background:#C4956A;border-radius:calc(8*var(--wa-u,1px))}
  .wa-asg-row.on .wa-asg-role{color:rgba(255,255,255,.85)}
  .wa-asg-row.on:hover{background:#b8875c}
  .wa-asg-row.clear{color:var(--wa-note-h);font-weight:600;margin-top:calc(2*var(--wa-u,1px));border-top:1px solid var(--wa-line)}
  /* composer tools row — Private toggle + Assign, grouped together */
  /* composer tools row — Assign ▾ on the LEFT, one pill per assignee, 24h window pill on the right */
  .wa-toolsrow{display:flex;align-items:center;gap:calc(7*var(--wa-u,1px));margin:0 0 calc(8*var(--wa-u,1px));flex-wrap:wrap}
  .wa-toolsrow .wa-route{margin-left:0}
  /* ⭐ the pill GROUPS are not boxes (Sett, 2026-09-22 evening): a wrapping group is a block that spans its line, so the
     ＋ that follows it landed on a line of its own the moment the names wrapped. With the groups flattened into the row
     (display:contents) every pill and the ＋ are items of ONE wrapping flow — the ＋ follows the last name wherever
     that is. The spans stay in the DOM: _waRefreshPills repaints them by class. */
  .wa-asg-pills,.wa-lead-pills,.wa-desk-pill{display:contents}
  /* ALL pills are one size — a row of ragged widths reads as clutter, and "Office" was much the narrowest.
     Names longer than the box ellipsis rather than stretching it, so the row stays even however people are
     named. min-width is the floor, max-width the ceiling; short names centre inside it. */
  .wa-asg-pill,.wa-lead-pill{min-width:calc(124*var(--wa-u,1px));max-width:calc(124*var(--wa-u,1px));justify-content:center}
  .wa-asg-pill>span:not(.wa-lead-tag),.wa-lead-pill>span:not(.wa-lead-tag){overflow:hidden;text-overflow:ellipsis}
  .wa-asg-pill{display:inline-flex;align-items:center;gap:calc(4*var(--wa-u,1px));font-size:calc(11*var(--wa-u,1px));font-weight:600;color:var(--wa-note-h);
    background:var(--wa-note-bg);border:1px solid var(--wa-note-bd);border-radius:calc(20*var(--wa-u,1px));padding:calc(2*var(--wa-u,1px)) calc(5*var(--wa-u,1px)) calc(2*var(--wa-u,1px)) calc(9*var(--wa-u,1px));
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* OFFICE pills — an admin who has actually replied, plus the standing "Office" desk. Cooler than the gold
     assignee pills so the desk reads as a different kind of thing from the people assigned to the case. */
  /* the OFFICE DESK is blue — it is a mailbox, not a person. Everyone who is actually ON the chat, admin or
     DT, wears the same gold pill: joining by replying is the same kind of thing as being assigned. */
  .wa-asg-pill.wa-deskpill{color:#33496B;background:#EFF3F9;border-color:#9FB6D4;padding:calc(2*var(--wa-u,1px)) calc(9*var(--wa-u,1px))}
  .wa-asg-pill.wa-deskpill.wa-picked{background:#DCE7F5}
  /* "Cyris is replying…" — two admins may BOTH answer (blocking one is how a client ends up waiting on
     someone who has gone home), so the collision is made visible instead of prevented. */
  /* chat list: WhatsApp's green "typing" line, in place of the (now stale) message preview */
  .wa-conv-pv.wa-typingline{color:#25D366;font-weight:600}
  /* thread: a three-dot bubble on OUR side, shaped like the message that is about to land there */
  .wa-typebubble{align-self:flex-end;background:var(--wa-out);border-radius:calc(7*var(--wa-u,1px));padding:calc(9*var(--wa-u,1px)) calc(12*var(--wa-u,1px));
    display:flex;align-items:center;gap:calc(4*var(--wa-u,1px));box-shadow:0 1px .5px rgba(11,20,26,.13);margin-top:calc(2*var(--wa-u,1px))}
  .wa-typebubble .dot{display:inline-block;width:calc(6*var(--wa-u,1px));height:calc(6*var(--wa-u,1px));border-radius:50%;background:var(--wa-sub);
    animation:waTypeDot 1.2s infinite ease-in-out}
  .wa-typebubble .dot:nth-child(2){animation-delay:.18s} .wa-typebubble .dot:nth-child(3){animation-delay:.36s}
  @keyframes waTypeDot{0%,60%,100%{opacity:.25;transform:translateY(0)}30%{opacity:1;transform:translateY(calc(-2*var(--wa-u,1px)))}}
  @media (prefers-reduced-motion:reduce){.wa-typebubble .dot{animation:none;opacity:.6}}
  /* the ✕ fills the whole END of the pill so it's comfortably clickable (it was a ~13px sliver) */
  .wa-asg-x{border:none;background:transparent;color:var(--wa-note-h);cursor:pointer;font-size:calc(11*var(--wa-u,1px));line-height:1;
    align-self:stretch;display:flex;align-items:center;opacity:.7;
    padding:0 calc(10*var(--wa-u,1px)) 0 calc(6*var(--wa-u,1px));margin:calc(-2*var(--wa-u,1px)) calc(-5*var(--wa-u,1px)) calc(-2*var(--wa-u,1px)) 0;border-radius:0 calc(20*var(--wa-u,1px)) calc(20*var(--wa-u,1px)) 0}
  .wa-asg-x:hover{opacity:1;background:rgba(0,0,0,.08)}
  /* "I'm done — leave" (the assignee ends their own part) */
  .wa-leave-btn{margin-left:auto;border:1px solid var(--wa-note-bd);background:var(--wa-note-bg);color:var(--wa-note-h);
    font-size:calc(11*var(--wa-u,1px));font-weight:600;border-radius:calc(20*var(--wa-u,1px));padding:calc(3*var(--wa-u,1px)) calc(10*var(--wa-u,1px));cursor:pointer;white-space:nowrap;font-family:inherit}
  .wa-leave-btn:hover{background:var(--wa-note-h);color:#fff}
  /* in-panel confirm (never the browser confirm) — appended to #waPanel so --wa-* vars apply. (Toast styling
     lives with the copy/forward toast above — one .wa-ptoast rule, no duplicate.) */
  .wa-confirm{position:absolute;inset:0;z-index:1400;background:rgba(0,0,0,.4);display:flex;align-items:center;justify-content:center}
  .wa-confirm-card{background:var(--wa-panel);border-radius:calc(14*var(--wa-u,1px));width:calc(280*var(--wa-u,1px));max-width:88%;padding:calc(18*var(--wa-u,1px));
    box-shadow:0 12px 40px rgba(0,0,0,.35)}
  .wa-confirm-msg{font-size:calc(13.5*var(--wa-u,1px));color:var(--wa-text);line-height:1.45;margin-bottom:calc(16*var(--wa-u,1px))}
  .wa-confirm-note{width:100%;box-sizing:border-box;border:1px solid var(--wa-line);border-radius:calc(8*var(--wa-u,1px));
    padding:calc(7*var(--wa-u,1px)) calc(9*var(--wa-u,1px));font-size:calc(12.5*var(--wa-u,1px));font-family:inherit;color:var(--wa-text);background:var(--wa-input);
    resize:vertical;margin-bottom:calc(12*var(--wa-u,1px));outline:none}
  .wa-confirm-note:focus{border-color:var(--wa-note-bd)}
  .wa-confirm-btns{display:flex;gap:calc(8*var(--wa-u,1px));justify-content:flex-end}
  .wa-confirm-btns button{border:none;border-radius:calc(8*var(--wa-u,1px));padding:calc(7*var(--wa-u,1px)) calc(14*var(--wa-u,1px));font-size:calc(13*var(--wa-u,1px));font-weight:600;cursor:pointer;font-family:inherit}
  .wa-confirm-no{background:var(--wa-line);color:var(--wa-text)}
  .wa-confirm-yes{background:#c0392b;color:#fff}
  /* PRIVATE SESSION — start pill (tools row) + the running banner (above the thread) */
  .wa-ps-start{border:1px solid var(--wa-note-bd);background:var(--wa-note-bg);color:var(--wa-note-h);font-size:calc(11*var(--wa-u,1px));font-weight:600;
    border-radius:calc(20*var(--wa-u,1px));padding:calc(3*var(--wa-u,1px)) calc(10*var(--wa-u,1px));cursor:pointer;white-space:nowrap;font-family:inherit}
  .wa-ps-start:hover{background:var(--wa-note-h);color:#fff}
  /* private-conversation banner — a clean centered label (the EYE button toggles it, so no lock/End controls) */
  .wa-psbanner{display:flex;align-items:center;justify-content:center;padding:calc(9*var(--wa-u,1px)) calc(14*var(--wa-u,1px));background:var(--wa-priv);
    color:var(--wa-note-h);border-bottom:1px solid var(--wa-line)}
  .wa-ps-txt{font-size:calc(14*var(--wa-u,1px));font-weight:600;letter-spacing:.02em;text-align:center}
  /* CASE LEAD pills — auto from active cases, locked (no ✕), a distinct green vs the amber ad-hoc pills */
  .wa-lead-pill{display:inline-flex;align-items:center;gap:calc(5*var(--wa-u,1px));font-size:calc(11*var(--wa-u,1px));font-weight:600;color:var(--wa-note-h);
    background:var(--wa-note-bg);border:1px solid var(--wa-note-bd);border-radius:calc(20*var(--wa-u,1px));padding:calc(2*var(--wa-u,1px)) calc(8*var(--wa-u,1px));white-space:nowrap}
  .wa-lead-tag{font-size:calc(8*var(--wa-u,1px));font-weight:700;text-transform:uppercase;letter-spacing:.3px;color:#fff;
    background:var(--wa-note-h);border-radius:calc(20*var(--wa-u,1px));padding:1px calc(5*var(--wa-u,1px))}
  /* click-a-message to flip its privacy (reveals on hover of the outgoing bubble) */
  .wa-out .wa-convbtn{position:absolute;top:calc(-9*var(--wa-u,1px));right:calc(6*var(--wa-u,1px));opacity:0;transition:opacity .12s;font-size:calc(9.5*var(--wa-u,1px));font-weight:700;
    border:none;border-radius:calc(20*var(--wa-u,1px));padding:calc(2*var(--wa-u,1px)) calc(8*var(--wa-u,1px));cursor:pointer;background:var(--wa-note-h);color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);white-space:nowrap}
  .wa-out:hover .wa-convbtn{opacity:1}
  /* PRIVATE button in the typing row (same size as the note button) + reply-area tint when active */
  .wa-privbtn{width:calc(40*var(--wa-u,1px));height:calc(40*var(--wa-u,1px));flex:none;border-radius:50%;border:none;padding:0;cursor:pointer;
    background:var(--wa-input);color:var(--wa-sub);display:grid;place-items:center}
  .wa-privbtn svg{width:calc(20*var(--wa-u,1px));height:calc(20*var(--wa-u,1px))}   /* smaller glyph in the circle (minimalist, matches the assign icon) */
  .wa-privbtn:hover{color:var(--wa-text)}
  .wa-privbtn.on{background:var(--wa-note-h);color:#fff;box-shadow:0 0 0 3px var(--wa-priv)}
  /* private typing area = the SAME darker shade as the private message bubbles */
  .wa-priv-on .wa-row input{background:var(--wa-priv)}
  .wa-priv-on .wa-row input::placeholder{color:var(--wa-meta)}
  /* …but NOT the internal-note box: a note is team-only by definition and can never be private, so it keeps
     its normal look even while a private session is running. Higher specificity, so order can't undo it. */
  .wa-priv-on .wa-notebox .wa-row input{background:var(--wa-panel)}
  .wa-priv-on .wa-notebox .wa-row input::placeholder{color:var(--wa-sub)}
  /* private (staff-only) message — a darker tinted bubble that stands out among the normal chat */
  .wa-out.wa-priv,.wa-in.wa-priv{background:var(--wa-priv)}
  .wa-out.wa-priv::before{background:var(--wa-priv)}
  .wa-in.wa-priv::before{background:var(--wa-priv)}
  .wa-conv .wa-asg-tag{display:inline-block;margin-left:calc(6*var(--wa-u,1px));font-size:calc(9.5*var(--wa-u,1px));font-weight:600;color:var(--wa-note-h);
    background:var(--wa-note-bg);border-radius:calc(6*var(--wa-u,1px));padding:0 calc(5*var(--wa-u,1px));vertical-align:middle}
  /* ── MEDIA bubbles (a file sent to the client) — image thumb / video / audio / document card ── */
  .wa-media{display:block;margin-bottom:calc(3*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));overflow:hidden}
  /* ⭐⭐ THE CHEVRON OVER A PICTURE -- WhatsApp's own treatment (Sett's reference screenshot).
     `.wa-menubtn` normally fades in the BUBBLE's colour, which is right over a bubble and wrong over a
     photo: a green blob sitting on the picture. WhatsApp instead darkens a TRIANGULAR WEDGE in the
     picture's top-right corner and puts a white chevron on it -- so the control is legible over an
     image whose colours nobody can know in advance, and it reads as a shadow rather than as a colour.
     ⚠️ THE WEDGE GOES ON THE PICTURE, NOT ON THE BUTTON. The button is pinned to the BUBBLE's
     top-right, and the picture is inset by the bubble's 9px padding -- so a gradient on the button
     would spill a dark corner onto the green padding beside the photo. As a child of `.wa-media-img`
     it is clipped by that element's own `overflow:hidden` + 6px radius, so it follows the picture's
     rounded corner exactly.
     ⚠️ Revealed on hover, WITH the chevron. A permanent wedge with no chevron under it (our
     chevron is opacity:0 until hover, unlike WhatsApp's) would read as a rendering fault. */
  .wa-media-img{position:relative}
  .wa-media-img::after{content:"";position:absolute;top:0;right:0;width:calc(112*var(--wa-u,1px));height:calc(58*var(--wa-u,1px));
    pointer-events:none;opacity:0;transition:opacity .12s;
    /* ⚠️ A GRADIENT ALONE IS NOT A TRIANGLE. The first cut relied on a diagonal fade inside a
       rectangle -- but the top and right edges stayed at full strength for most of their length, so it
       read as a dark BLOCK with one soft corner. `clip-path` gives the actual wedge: right angle at the
       picture's top-right, hypotenuse falling away to the left. Wide and shallow, matching the shape
       WhatsApp uses -- a tall triangle would crowd the picture. */
    clip-path:polygon(0 0, 100% 0, 100% 100%);
    /* ⚠️ AND MUCH LIGHTER. .52 alpha put the darkest point at roughly mid-grey, which on the white
       logos a lab actually sends looked like damage to the image rather than a control resting on it.
       .26 is enough to carry a white chevron and still read as a shadow. The fade reaches transparent
       at 78%, comfortably before the hypotenuse, so the clip never shows as a hard cut. */
    background:linear-gradient(212deg, rgba(0,0,0,.26) 0%, rgba(0,0,0,.11) 44%, transparent 78%)}
  .wa-msg:hover .wa-media-img::after{opacity:1}
  /* on the wedge the glyph goes white; the bubble-colour fade behind it is dropped */
  .wa-msg:not(:has(.snd)):not(:has(.wa-quote)):not(:has(.wa-replyquote)):has(.wa-media-img) .wa-menubtn{
    background:transparent;color:#fff}
  /* ⚠️ A VIDEO CANNOT CARRY THE WEDGE: `.wa-media-vid` is a bare <video>, a REPLACED element, and
     replaced elements generate no ::after. It keeps the transparent background and earns its
     legibility from a white halo on the usual grey glyph instead. */
  .wa-msg:not(:has(.snd)):not(:has(.wa-quote)):not(:has(.wa-replyquote)):has(.wa-media-vid) .wa-menubtn{
    background:transparent;
    filter:drop-shadow(0 0 1px rgba(255,255,255,.95)) drop-shadow(0 0 3px rgba(255,255,255,.75))}
  .wa-media-img img{display:block;max-width:100%;width:auto;max-height:calc(280*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));cursor:pointer}
  .wa-media-vid{display:block;max-width:100%;max-height:calc(300*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));background:#000}
  /* ⭐ "Load earlier" — shared, because the two panels are one panel in two modes and a `.tm-`
     copy is how they drift (S106). Quiet: it is a way back through history, not an action. */
  .wa-loadmore{display:flex;justify-content:center;padding:calc(6*var(--wa-u,1px)) 0 calc(10*var(--wa-u,1px))}
  .wa-loadmore button{font-size:calc(12*var(--wa-u,1px));color:var(--wa-sub);background:var(--wa-bubble-in);
    border:1px solid var(--wa-line);border-radius:calc(13*var(--wa-u,1px));padding:calc(5*var(--wa-u,1px)) calc(14*var(--wa-u,1px));cursor:pointer}
  .wa-loadmore button:hover{filter:brightness(.97)}
  .wa-loadmore button[disabled]{opacity:.55;cursor:default}
  .wa-media-aud{display:block;width:calc(230*var(--wa-u,1px));max-width:100%;margin-bottom:calc(3*var(--wa-u,1px))}
  .wa-media-doc{display:flex;align-items:center;gap:calc(9*var(--wa-u,1px));text-decoration:none;color:inherit;
    background:rgba(0,0,0,.05);border-radius:calc(8*var(--wa-u,1px));padding:calc(8*var(--wa-u,1px)) calc(10*var(--wa-u,1px));margin-bottom:calc(3*var(--wa-u,1px));min-width:calc(180*var(--wa-u,1px));max-width:100%}
  #waPanel[data-wa-theme="dark"] .wa-media-doc{background:rgba(255,255,255,.07)}
  .wa-media-doc:hover{background:rgba(0,0,0,.09)}
  .wa-doc-ic{flex:none;width:calc(30*var(--wa-u,1px));height:calc(30*var(--wa-u,1px));display:grid;place-items:center;color:var(--wa-send)}
  .wa-doc-ic svg{width:calc(26*var(--wa-u,1px));height:calc(26*var(--wa-u,1px))}
  .wa-doc-nm{flex:1;min-width:0;font-size:calc(13*var(--wa-u,1px));font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--wa-text)}
  .wa-doc-dl{flex:none;color:var(--wa-sub);display:grid;place-items:center}
  .wa-doc-dl svg{width:calc(18*var(--wa-u,1px));height:calc(18*var(--wa-u,1px))}
  /* ＋ — sits INSIDE the reply pill, leftmost: the team composer's attach, and the client composer's menu (below) */
  .wa-attachbtn, .wa-plusbtn{position:absolute;left:calc(5*var(--wa-u,1px));top:50%;transform:translateY(-50%);width:calc(33*var(--wa-u,1px));height:calc(33*var(--wa-u,1px));flex:none;
    border:none;background:transparent;cursor:pointer;line-height:0;padding:0;opacity:.78;border-radius:50%;
    color:var(--wa-sub);z-index:2;display:flex;align-items:center;justify-content:center}
  .wa-attachbtn:hover, .wa-plusbtn:hover, .wa-plusbtn[aria-expanded="true"]{opacity:1;background:rgba(0,0,0,.07)}
  .wa-attachbtn svg, .wa-plusbtn svg{width:calc(25*var(--wa-u,1px));height:calc(25*var(--wa-u,1px))}
  /* ⭐⭐ THE ＋ MENU (Sett, 2026-10-06: "the +, photo+, template and emoticon buttons on the reply bar is too clutter..
     group them together become 2 buttons, 1 template (important and always use) and another consist of attachments,
     photo+ and emoticon.... this will be + icon"). The pill holds two buttons, ＋ and Templates; the ＋ opens this —
     WhatsApp's own attach menu, a card over the bar with a coloured glyph and a word a line, the ＋ turning into ×
     while it is open. Each line calls the handler its old button did, so a shut window explains itself as before. */
  .wa-plusbtn svg{transition:transform .18s ease}
  .wa-plusbtn[aria-expanded="true"] svg{transform:rotate(45deg)}
  .wa-plusmenu{display:none;position:absolute;left:0;bottom:calc(100% + 10*var(--wa-u,1px));z-index:7;min-width:calc(196*var(--wa-u,1px));
    background:var(--wa-panel);border:1px solid var(--wa-line);border-radius:calc(14*var(--wa-u,1px));box-shadow:0 8px 28px rgba(0,0,0,.22);
    padding:calc(6*var(--wa-u,1px))}
  .wa-plusmenu.open{display:block}
  .wa-plusmenu button{display:flex;align-items:center;gap:calc(13*var(--wa-u,1px));width:100%;border:none;background:transparent;cursor:pointer;
    padding:calc(10*var(--wa-u,1px)) calc(12*var(--wa-u,1px));font-size:calc(14.5*var(--wa-u,1px));color:var(--wa-text);border-radius:calc(9*var(--wa-u,1px));
    text-align:left;font-family:inherit;white-space:nowrap;line-height:1.2}
  .wa-plusmenu button:hover{background:var(--wa-hover,rgba(0,0,0,.06))}
  .wa-plusmenu svg{width:calc(23*var(--wa-u,1px));height:calc(23*var(--wa-u,1px));flex:none}
  .wa-pm-attach svg{color:#7F66FF}
  .wa-pm-cam svg{color:#FF2E74}
  .wa-pm-emoji svg{color:#E8590C}
  /* …and what it says when the 24-hour window is closed: WhatsApp will not take photos, so take them into Design Files */
  .wa-camsheet{position:absolute;inset:0;z-index:1400;background:rgba(0,0,0,.38);display:flex;align-items:center;justify-content:center;padding:calc(18*var(--wa-u,1px))}
  .wa-camsheet-box{background:var(--wa-panel);color:var(--wa-text);border-radius:calc(16*var(--wa-u,1px));padding:calc(20*var(--wa-u,1px)) calc(22*var(--wa-u,1px));
    max-width:calc(440*var(--wa-u,1px));display:grid;gap:calc(12*var(--wa-u,1px));font-size:calc(14*var(--wa-u,1px));line-height:1.5}
  .wa-camsheet-box b{font-size:calc(16*var(--wa-u,1px))}
  .wa-camsheet-acts{display:flex;flex-wrap:wrap;gap:calc(8*var(--wa-u,1px));justify-content:flex-end}
  .wa-camsheet-acts button{font-size:calc(14*var(--wa-u,1px));font-weight:600;padding:calc(9*var(--wa-u,1px)) calc(14*var(--wa-u,1px));
    border-radius:calc(10*var(--wa-u,1px));border:1px solid var(--wa-line);background:transparent;color:var(--wa-text);cursor:pointer}
  .wa-camsheet-acts button.go{background:var(--wa-send);border-color:var(--wa-send);color:#fff}
  /* drag-and-drop overlay — the WhatsApp look: the WHOLE conversation area turns into a green (chat-bubble
     green) rounded dashed zone with big "Drag file here" text. `top` is set in JS to sit below the header.
     pointer-events:none so drag events pass through to the panel's handlers (no flicker). */
  .wa-dropzone{position:absolute;left:0;right:0;bottom:0;top:0;z-index:1350;display:none;padding:calc(12*var(--wa-u,1px));pointer-events:none}
  .wa-dropzone.on{display:flex}
  .wa-dropzone .wa-dropbox{flex:1;display:flex;align-items:center;justify-content:center;
    border:2px dashed #55b37f;border-radius:calc(18*var(--wa-u,1px));background:var(--wa-out)}
  .wa-dropzone .tx{font-size:calc(30*var(--wa-u,1px));font-weight:400;color:#5c8f6f;letter-spacing:.01em}
  #waPanel[data-wa-theme="dark"] .wa-dropzone .wa-dropbox{border-color:#2f7d5b}
  #waPanel[data-wa-theme="dark"] .wa-dropzone .tx{color:#9cc7ac}
  /* an OPTIMISTIC "uploading…" bubble while the file transfers */
  .wa-msg.wa-uploading{opacity:.72}
  .wa-uploading .wa-upspin{display:inline-block;width:calc(12*var(--wa-u,1px));height:calc(12*var(--wa-u,1px));border:2px solid var(--wa-meta);
    border-top-color:transparent;border-radius:50%;animation:waSpin .7s linear infinite;vertical-align:calc(-2*var(--wa-u,1px));margin-right:calc(5*var(--wa-u,1px))}
  @keyframes waSpin{to{transform:rotate(360deg)}}
  /* ── MULTI-SELECT (bulk Forward / Copy) — a top action bar + a check on each bubble ── */
  .wa-selbar{display:flex;align-items:center;gap:calc(10*var(--wa-u,1px));padding:calc(9*var(--wa-u,1px)) calc(14*var(--wa-u,1px));background:var(--wa-header);border-bottom:1px solid var(--wa-line)}
  .wa-selbar .n{font-size:calc(14*var(--wa-u,1px));font-weight:600;color:var(--wa-text);flex:1}
  .wa-selact{border:none;background:transparent;color:var(--wa-send);font-size:calc(13*var(--wa-u,1px));font-weight:600;cursor:pointer;
    padding:calc(6*var(--wa-u,1px)) calc(10*var(--wa-u,1px));border-radius:calc(8*var(--wa-u,1px));font-family:inherit}
  .wa-selact:hover{background:var(--wa-navhover)}
  .wa-selact[disabled]{color:var(--wa-sub);cursor:default;background:transparent}
  /* multi-select: each message becomes a FULL-WIDTH row with a left checkbox gutter; a selected row gets a green
     band across the whole thread, and the bubbles shift right to make room for the checkboxes. */
  .wa-selrow{display:flex;align-items:center;width:100%;padding:calc(2*var(--wa-u,1px)) 0 calc(2*var(--wa-u,1px)) calc(6*var(--wa-u,1px));cursor:pointer;transition:background .12s}
  .wa-selrow.sel{background:#D9FDD3}
  #waPanel[data-wa-theme="dark"] .wa-selrow.sel{background:rgba(0,168,132,.16)}
  .wa-selbox{flex:none;width:calc(22*var(--wa-u,1px));height:calc(22*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));border:2px solid var(--wa-sub);background:var(--wa-panel);
    margin-right:calc(8*var(--wa-u,1px));display:grid;place-items:center}
  .wa-selrow.sel .wa-selbox{background:var(--wa-send);border-color:var(--wa-send)}
  .wa-selrow.sel .wa-selbox::after{content:"✓";color:#fff;font-size:calc(13*var(--wa-u,1px));font-weight:700;line-height:1}
  .wa-selrow-in{flex:1;min-width:0;display:flex;flex-direction:column}
  .wa-selrow a,.wa-selrow button,.wa-selrow img,.wa-selrow video,.wa-selrow audio{pointer-events:none}
  /* in select mode, pull the thread's side padding in so the checkbox sits near the left edge and the green
     band spans wide across the chat (like WhatsApp). :has() is supported in the Chromium the team uses. */
  .wa-thread:has(.wa-selrow){padding-left:calc(8*var(--wa-u,1px));padding-right:2.5%}
  /* a file (document) message gets a STANDARD wider width so cards don't vary with the filename length; the
     max-width is raised above the usual 74% text cap so the standard width shows on more panel sizes */
  .wa-msg.wa-hasdoc{width:calc(340*var(--wa-u,1px));max-width:94%;padding:calc(4*var(--wa-u,1px)) calc(4*var(--wa-u,1px)) calc(6*var(--wa-u,1px))}   /* slim inner margin around the preview/doc card */
  /* document card gets a two-line info block + a View / Save-as action row (WhatsApp) */
  .wa-doc-info{flex:1;min-width:0;display:flex;flex-direction:column}
  .wa-doc-sub{font-size:calc(11*var(--wa-u,1px));color:var(--wa-sub)}
  /* first-page preview thumbnail above a PDF card (small, non-interactive; lazy so off-screen PDFs don't render).
     The iframe is a touch wider than the box so Chrome's PDF-viewer scrollbar sits past the clipped right edge. */
  .wa-doc-prev{height:calc(95*var(--wa-u,1px));border-radius:calc(8*var(--wa-u,1px)) calc(8*var(--wa-u,1px)) 0 0;overflow:hidden;background:#fff;margin-bottom:calc(3*var(--wa-u,1px))}
  .wa-doc-prev img{width:100%;display:block}   /* first page rendered by PDF.js; the box height crops it to the top */
  .wa-doc-ic.pdf svg{width:calc(29*var(--wa-u,1px));height:calc(29*var(--wa-u,1px))}
  /* the file card's meta line: type · size on the left, timestamp on the right — both INSIDE the grey box.
     The size gets a fixed right-padding so it can never butt up against the timestamp; the timestamp is pushed
     fully right (margin-left:auto) and never wraps. margin-top gives a gap below the file NAME. */
  /* size text on its own line (small, left); the timestamp drops to the line BELOW it, right-aligned (WhatsApp) */
  .wa-doc-meta{display:flex;flex-direction:column;margin-top:calc(4*var(--wa-u,1px))}
  .wa-doc-meta .wa-doc-sub{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:calc(9*var(--wa-u,1px))}
  .wa-doc-meta .t{float:none;position:static;top:0;margin:1px 0 0 0;align-self:flex-end;white-space:nowrap;color:var(--wa-meta)}
  .wa-doc-acts{display:flex;margin-top:calc(4*var(--wa-u,1px));border-top:1px solid rgba(0,0,0,.10)}
  #waPanel[data-wa-theme="dark"] .wa-doc-acts{border-top-color:rgba(255,255,255,.12)}
  .wa-doc-btn{flex:1;text-align:center;padding:calc(7*var(--wa-u,1px)) calc(4*var(--wa-u,1px));font-size:calc(13*var(--wa-u,1px));font-weight:600;color:var(--wa-send);
    text-decoration:none;cursor:pointer}
  .wa-doc-btn:hover{background:rgba(0,0,0,.05);border-radius:calc(4*var(--wa-u,1px))}
  /* ── ATTACH-COMPOSE OVERLAY — preview the file + type a caption before sending ── */
  .wa-attach-ov{position:absolute;inset:0;z-index:1360;background:var(--wa-panel);display:flex;flex-direction:column}
  .wa-atv-head{display:flex;align-items:center;gap:calc(8*var(--wa-u,1px));padding:calc(12*var(--wa-u,1px)) calc(14*var(--wa-u,1px))}
  .wa-atv-title{flex:1;text-align:center;font-size:calc(14*var(--wa-u,1px));font-weight:500;color:var(--wa-text);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .wa-atv-body{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;padding:calc(8*var(--wa-u,1px)) calc(24*var(--wa-u,1px));overflow:auto}
  .wa-atv-img{max-width:100%;max-height:100%;object-fit:contain;border-radius:calc(6*var(--wa-u,1px))}
  /* PDF preview = the first page rendered by PDF.js → a crisp image, whole page, on a white sheet with a shadow */
  .wa-atv-pdfimg{max-width:100%;max-height:100%;object-fit:contain;background:#fff;border-radius:calc(3*var(--wa-u,1px));
    box-shadow:0 3px 20px rgba(0,0,0,.26);display:block}
  .wa-atv-pdfloading{color:var(--wa-sub);font-size:calc(14*var(--wa-u,1px))}
  .wa-atv-none{background:var(--wa-bg);border-radius:calc(14*var(--wa-u,1px));padding:calc(44*var(--wa-u,1px)) calc(40*var(--wa-u,1px));text-align:center;display:flex;
    flex-direction:column;align-items:center;gap:calc(8*var(--wa-u,1px));width:80%;max-width:calc(520*var(--wa-u,1px))}
  .wa-atv-none svg{width:calc(74*var(--wa-u,1px));height:calc(74*var(--wa-u,1px));color:#c7ccd1}
  .wa-atv-nt{font-size:calc(22*var(--wa-u,1px));color:var(--wa-sub);font-weight:400}
  .wa-atv-meta{font-size:calc(13*var(--wa-u,1px));color:var(--wa-sub)}
  .wa-atv-cap{position:relative;display:flex;align-items:center;gap:calc(6*var(--wa-u,1px));margin:0 auto calc(10*var(--wa-u,1px));width:min(calc(560*var(--wa-u,1px)),86%);
    background:var(--wa-input);border-radius:calc(22*var(--wa-u,1px));padding:calc(2*var(--wa-u,1px)) calc(8*var(--wa-u,1px))}
  .wa-atv-cap input{flex:1;border:none;background:transparent;outline:none;font-size:calc(14*var(--wa-u,1px));color:var(--wa-text);
    padding:calc(11*var(--wa-u,1px)) calc(8*var(--wa-u,1px)) calc(11*var(--wa-u,1px)) calc(2*var(--wa-u,1px));font-family:inherit}
  .wa-atv-emojibtn{flex:none;width:calc(34*var(--wa-u,1px));height:calc(34*var(--wa-u,1px));border:none;background:transparent;cursor:pointer;padding:0;
    color:var(--wa-sub);opacity:.7;border-radius:50%;display:grid;place-items:center}
  .wa-atv-emojibtn:hover{opacity:1;background:rgba(0,0,0,.07)}
  .wa-atv-emojibtn svg{width:calc(23*var(--wa-u,1px));height:calc(23*var(--wa-u,1px))}
  .wa-atv-emoji{display:none;position:absolute;bottom:calc(50*var(--wa-u,1px));left:0;max-height:calc(230*var(--wa-u,1px));overflow-y:auto;width:calc(300*var(--wa-u,1px));
    background:var(--wa-panel);border:1px solid var(--wa-line);border-radius:calc(12*var(--wa-u,1px));padding:calc(6*var(--wa-u,1px));flex-wrap:wrap;gap:calc(2*var(--wa-u,1px));
    box-shadow:0 8px 26px rgba(0,0,0,.2);z-index:6}
  .wa-atv-emoji.open{display:flex}
  .wa-atv-emoji button{border:none;background:transparent;cursor:pointer;padding:0;border-radius:calc(8*var(--wa-u,1px));width:calc(40*var(--wa-u,1px));height:calc(40*var(--wa-u,1px));
    display:flex;align-items:center;justify-content:center;font-size:calc(22*var(--wa-u,1px))}
  .wa-atv-emoji button:hover{background:rgba(0,0,0,.08)}
  .wa-atv-emoji img.emoji{width:calc(32*var(--wa-u,1px));height:calc(32*var(--wa-u,1px))}
  .wa-atv-bottom{position:relative;display:flex;align-items:center;justify-content:center;gap:calc(12*var(--wa-u,1px));padding:calc(10*var(--wa-u,1px)) calc(18*var(--wa-u,1px)) calc(18*var(--wa-u,1px))}
  .wa-atv-strip{display:flex;align-items:center;gap:calc(8*var(--wa-u,1px));flex-wrap:wrap}
  .wa-atv-th{position:relative;width:calc(52*var(--wa-u,1px));height:calc(52*var(--wa-u,1px));border-radius:calc(9*var(--wa-u,1px));border:2px solid transparent;
    background:var(--wa-bg);cursor:pointer;overflow:hidden;padding:0;display:grid;place-items:center}
  .wa-atv-th.on{border-color:var(--wa-send)}
  .wa-atv-th img{width:100%;height:100%;object-fit:cover}
  .wa-atv-thdoc{color:var(--wa-send);display:grid;place-items:center}
  .wa-atv-thdoc svg{width:calc(26*var(--wa-u,1px));height:calc(26*var(--wa-u,1px))}
  .wa-atv-thx{position:absolute;top:calc(-6*var(--wa-u,1px));right:calc(-6*var(--wa-u,1px));width:calc(17*var(--wa-u,1px));height:calc(17*var(--wa-u,1px));border-radius:50%;background:#5b6b73;
    color:#fff;font-size:calc(10*var(--wa-u,1px));line-height:1;display:none;place-items:center;border:none;cursor:pointer}
  .wa-atv-th:hover .wa-atv-thx{display:grid}
  .wa-atv-add{width:calc(52*var(--wa-u,1px));height:calc(52*var(--wa-u,1px));border-radius:calc(9*var(--wa-u,1px));border:1.5px solid var(--wa-line);background:transparent;
    color:var(--wa-sub);font-size:calc(26*var(--wa-u,1px));cursor:pointer;display:grid;place-items:center}
  .wa-atv-add:hover{background:var(--wa-navhover)}
  .wa-atv-send{position:absolute;right:calc(18*var(--wa-u,1px));bottom:calc(14*var(--wa-u,1px));width:calc(52*var(--wa-u,1px));height:calc(52*var(--wa-u,1px));flex:none;border-radius:50%;
    background:var(--wa-send);color:#fff;border:none;display:grid;place-items:center;cursor:pointer}
  .wa-atv-send svg{width:calc(24*var(--wa-u,1px));height:calc(24*var(--wa-u,1px))}


  /* Team mode borrows every `.wa-*` class. These are the few things that are genuinely different. */
  .tm-presence{width:calc(10*var(--wa-u,1px));height:calc(10*var(--wa-u,1px));border-radius:50%;position:absolute;right:-1px;bottom:-1px;
    border:2px solid var(--wa-panel);box-sizing:content-box}
  .tm-presence.in{background:#25D366}                 /* at their desk */
  .tm-presence.idle{background:#F0B232}               /* signed in, quiet a while */
  .tm-presence.out{background:#C4C9CC}                /* not clocked in */
  .tm-av-wrap{position:relative;flex:none}
  /* ⭐ DIM THE WHOLE AVATAR WHEN SOMEONE IS OUT (Sett) — the 10px dot is accurate but you have to go
     looking for it, whereas a greyed face reads at a glance across a list. Same treatment Who's In
     already uses, so "away" looks the same wherever the app draws a person.
     ⚠️ Deliberately NOT applied to `idle`: signed in but quiet is still AT WORK, and dimming it
     would say they had left. Only a real 'out' is dimmed. */
  .tm-av-wrap.out{opacity:.45;filter:grayscale(1)}
  .tm-av-wrap.out .tm-presence{opacity:1;filter:none}   /* the dot stays legible on a dimmed face */
  /* The unread pip. GOLD, never green — green means a CLIENT is waiting, and a teammate must never
     be able to borrow that signal. See the FAB rule in the design note. */
  .tm-badge{min-width:calc(19*var(--wa-u,1px));height:calc(19*var(--wa-u,1px));border-radius:calc(10*var(--wa-u,1px));background:#8a5a1e;color:#fff;font-size:calc(11*var(--wa-u,1px));
    font-weight:700;display:grid;place-items:center;padding:0 calc(5*var(--wa-u,1px))}
  .tm-deleted{opacity:.55;font-style:italic}
  /* ⭐ Sett: the words and the time sit on ONE row. `.wa-body` is display:block, so a floated
     timestamp placed AFTER it can only start below it.
     ⚠️⚠️ THIS COMMENT USED TO CLAIM THAT WAS "fine for a real message, where the text fills the
     bubble and the time tucks into its last line". IT WAS NOT — that was an assumption, never
     checked, and it hid the same gap on EVERY team message for months until Sett photographed it.
     The real message is fixed at the source now (the `<span class="t">` is built INSIDE `.wa-body`,
     the way the client does it); this rule stays only for the deleted tombstone, whose timestamp is
     still a sibling.
     ⚠ Scoped to the BUBBLE: `.tm-deleted` is also the rail's preview style, and making that inline
     would break its ellipsis. */
  .wa-msg-del .wa-body{display:inline}
  /* ⭐ The role, beside the name. Muted and smaller so the NAME still reads first — it is context,
     not a second title, and at equal weight it would compete with the person. */
  .tm-role{font-size:calc(11*var(--wa-u,1px));font-weight:400;color:var(--wa-sub);margin-left:calc(6*var(--wa-u,1px));white-space:nowrap}
  /* ── team desks (the role group chats pinned at the top of the rail) ─────────────────────── */
  /* ⭐ The desk avatar is the DR parchment, same in both themes — Sett's S114 call for the DR tile:
     a brand mark that changes shade between themes reads as two different marks. */
  /* ⚠️ position:relative + z-index:1 — the ACTIVE row paints its highlight as a `::before` layer at
     z-index 0, and an unpositioned span sits UNDER it: the icon vanished the moment a desk was
     selected (Sett's first look). A person's avatar never did, because `.tm-av-wrap` is positioned. */
  .tm-deskav{position:relative;z-index:1;width:calc(40*var(--wa-u,1px));height:calc(40*var(--wa-u,1px));border-radius:calc(10*var(--wa-u,1px));flex:none;display:grid;place-items:center;background:#EDCFAD;color:#3d2a14}
  .tm-more{color:var(--wa-send);font-weight:600;cursor:pointer;text-decoration:none;white-space:nowrap}
  .tm-more:hover{text-decoration:underline}
  .tm-deskav svg{width:calc(22*var(--wa-u,1px));height:calc(22*var(--wa-u,1px))}
  .tm-in{font-size:calc(11*var(--wa-u,1px));font-weight:500;color:#1DAA61;margin-left:calc(6*var(--wa-u,1px));white-space:nowrap;flex:none}
  .tm-sect{font-size:calc(10.5*var(--wa-u,1px));font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--wa-sub);padding:calc(10*var(--wa-u,1px)) calc(14*var(--wa-u,1px)) calc(3*var(--wa-u,1px))}
  /* ⭐ THE TICK IS A CONTROL: tap it for who has read it. ⚠️⚠️ It MUST out-stack `.wa-menubtn` — the
     message-menu chevron is `position:absolute; 34×30; z-index:4; opacity:0` until hover, and on a
     one-line bubble that box blankets the timestamp and the tick. A real click on the tick landed on
     the invisible chevron and opened the MENU (Sett: "not clickable") — a scripted `.click()` on the
     tick could never see that, because it dispatches straight to the element. The S94 click-trap
     class, one layer in. z-index 5 puts the tick above; the negative-margin padding widens a 12×11
     glyph to a ~20×19 target without moving it. */
  .wa-msg .t .tm-tkbtn{cursor:pointer;position:relative;z-index:5;padding:calc(4*var(--wa-u,1px));margin:calc(-4*var(--wa-u,1px)) calc(-4*var(--wa-u,1px)) calc(-4*var(--wa-u,1px)) -1px;border-radius:calc(6*var(--wa-u,1px))}
  .wa-msg .t .tm-tkbtn:hover{background:rgba(0,0,0,.06)}
  .tm-tkinfo{position:absolute;z-index:1300;background:var(--wa-panel);color:var(--wa-text);border:1px solid var(--wa-line);border-radius:calc(10*var(--wa-u,1px));box-shadow:0 8px 24px rgba(0,0,0,.18);padding:calc(9*var(--wa-u,1px)) calc(12*var(--wa-u,1px));font-size:calc(12*var(--wa-u,1px));line-height:1.45;min-width:calc(170*var(--wa-u,1px));max-width:calc(240*var(--wa-u,1px));font-family:inherit}
  .tm-tkinfo h6{margin:0 0 1px;font-size:calc(10.5*var(--wa-u,1px));letter-spacing:.06em;text-transform:uppercase;color:var(--wa-sub);font-weight:700}
  .tm-tkinfo h6.rd{color:var(--wa-read)}
  .tm-tkinfo div+h6{margin-top:calc(6*var(--wa-u,1px))}
  .wa-conv.un .tm-role{font-weight:400}
  /* ⚠️ The name row must be allowed to shrink or a long role pushes the timestamp out of the row. */
  .wa-conv-nm{display:flex;align-items:baseline;gap:0;min-width:0}
  .wa-conv-nm > span.tm-role{flex:none}
  /* ⭐ The logo sits on the panel's own parchment, like every other mark in the nav strip, rather
     than floating on nothing. --wa-bg is the same tone the thread and nav use, so it reads as part
     of the surface instead of a sticker placed on top of it. */
  /* ⚠️ `--wa-panel` (white), NOT `--wa-bg`. --wa-bg is #F7F3EE — the nav strip's OWN colour — so a
     circle filled with it was invisible against the background it sat on, which is why this still
     read as transparent after the last attempt. The mark needs to contrast with its surface, not
     match it. */
  /* ⭐ RYT's own parchment, the same texture the app sidebar uses — Sett's call. Flat white read as
     a sticker; --wa-bg read as nothing at all because it IS the nav's colour. The texture is the one
     background that belongs to the brand rather than to the panel. */
  .tm-brand{cursor:pointer;border-radius:50%;width:calc(40*var(--wa-u,1px));height:calc(40*var(--wa-u,1px));display:grid;place-items:center;
    background-image:url('/static/img/background.jpg?v=2');background-size:calc(220*var(--wa-u,1px));
    background-position:center;box-shadow:0 0 0 1px rgba(0,0,0,.10)}
  .tm-brand:hover{background:var(--wa-navhover)}
  /* ⭐ THE TILE IS THE SAME IN BOTH THEMES — SETT'S CALL, AND IT REVERSES AN EARLIER DECISION OF
     MINE. S106 dimmed the parchment 66% in dark mode on a luminance measurement: ~0.75 against a
     0.90 nav rail in light (it blends), but the rail drops to 0.007 in dark, so the same cream
     tile measured as a headlight on near-black. He looked at it on prod and preferred the bright
     one. The measurement was right about the CONTRAST and wrong about what he wanted from it:
     the mark is the brand, and a brand mark that changes shade between themes reads as two
     different marks. Kept here rather than deleted so the reasoning is not re-derived later. */
  /* ⚠️ The menu now borrows `.wa-msgmenu` + `.wa-mm-list` + `.wa-mm-ic` wholesale. My own version
     had no icon column, so the glyphs sat flush against the words — `.wa-mm-list button` supplies
     the flex row and the 9px gap, and `.wa-mm-ic` the fixed 17px icon slot. */
  /* == TEAM-ONLY STYLES =======================================================================
     EVERYTHING ELSE COMES FROM THE CLIENT PANEL'S STYLESHEET, DELIBERATELY. Quotes, the reply
     bar, document cards, the search bar, the forward picker, the send button, reaction pills and
     the emoji picker ALL already exist as `.wa-*` classes. Re-declaring them as `.tm-*` is exactly
     how the two panels drifted apart: every copy was close enough to look right on its own and
     wrong beside the original -- a 20px reaction clearance where the client reserves 23px, a 15px
     reaction tile where the client bumps our own tiles to 20px, a reply bar with no background at
     all, a search bar on the wrong surface colour.
     RULE FOR ANYONE EDITING THIS FILE: before writing a `.tm-*` rule, grep `_wa_chat.html` for an
     existing `.wa-*` that already does the job -- it usually exists, and it is already the tested
     one. Only what Meta's API cannot do (editing, deleting, presence, a person's role) genuinely
     has no client counterpart and belongs below. */
  .wa-searchbar2.hidden{display:none}   /* the client's search bar is always mounted; ours toggles */
  .wa-send.hidden{display:none}         /* beats `.wa-send`'s own display:grid */
  /* ⭐ `.wa-send` is the client panel's own send button — a 40px round green disc with a white
     arrow. Borrowing the class rather than restyling means the two composers cannot drift.
     ⚠️ The size still has to be stated: SEND_SVG carries a viewBox and no width/height, so
     with no CSS it renders 0x0 — which is why the button once looked like it never appeared. */
  /* ⚠️ THE COMPOSER PILL. The client's input is a contenteditable styled by `.wa-row .wa-ce`;
     ours is a plain <input>, so none of that applied and the box came out a different height and
     radius. Same numbers, stated for the element we actually use. */
  /* No #teamInput rule: the composer IS the client panel's `.wa-ce` now, which already carries
     pre-wrap, auto-grow-then-scroll, the data-ph placeholder and emoji sizing. */
  .tm-editbox{margin-top:calc(2*var(--wa-u,1px))}
  .tm-upl{padding:calc(6*var(--wa-u,1px)) calc(12*var(--wa-u,1px)) calc(8*var(--wa-u,1px));background:var(--wa-input);border-top:1px solid var(--wa-line)}
  .tm-upl-t{font-size:calc(11*var(--wa-u,1px));color:var(--wa-sub);margin-bottom:calc(5*var(--wa-u,1px))}
  .tm-upl-bar{height:calc(4*var(--wa-u,1px));border-radius:calc(3*var(--wa-u,1px));background:var(--wa-line);overflow:hidden}
  .tm-upl-bar > i{display:block;height:100%;width:0;border-radius:calc(3*var(--wa-u,1px));background:var(--wa-send);
    transition:width .15s linear}
  .tm-editin{width:100%;box-sizing:border-box;border:1px solid var(--wa-send);border-radius:calc(6*var(--wa-u,1px));
    padding:calc(5*var(--wa-u,1px)) calc(8*var(--wa-u,1px));font-size:calc(14.2*var(--wa-u,1px));font-family:inherit;color:var(--wa-text);background:var(--wa-input);outline:none}
  .tm-edithint{font-size:calc(10.5*var(--wa-u,1px));color:var(--wa-meta);margin-top:calc(3*var(--wa-u,1px))}
  /* ⭐ MESSAGE A TEAM (Sett, 2026-09-20) — the tag under a request copy, the "is handling" line, and the sheet */
  .tm-asktag{clear:both;font-size:calc(11*var(--wa-u,1px));color:var(--wa-meta);margin-top:calc(5*var(--wa-u,1px));padding-top:calc(4*var(--wa-u,1px));border-top:1px dashed rgba(0,0,0,.12)}
  .wa-out .tm-asktag{border-top-color:rgba(0,0,0,.14)}
  /* A2 (Sett's pick, 2026-09-20): the "is handling" status is a green pill with a dot — a status badge, not a footnote */
  .tm-askline{display:inline-flex;align-items:center;gap:calc(6*var(--wa-u,1px));margin-top:calc(6*var(--wa-u,1px));padding:calc(3*var(--wa-u,1px)) calc(9*var(--wa-u,1px)) calc(3*var(--wa-u,1px)) calc(7*var(--wa-u,1px));border-radius:calc(999*var(--wa-u,1px));
    background:rgba(29,170,97,.15);color:#0f6b3d;font-size:calc(11*var(--wa-u,1px));font-weight:600;line-height:1.3}
  .tm-askline i{width:calc(8*var(--wa-u,1px));height:calc(8*var(--wa-u,1px));border-radius:50%;background:#1DAA61;flex:none}
  #waPanel[data-wa-theme="dark"] .tm-askline{background:rgba(29,170,97,.24);color:#7be0a8}
  /* B3 (Sett's pick): a thread a request is still WAITING on is washed warm and breathes, with a "Team request"
     chip where the time sits — until somebody answers; then the wash and the chip go and the preview names the handler */
  .wa-conv.tm-askwait:not(.active)::before{background:rgba(176,124,73,.16);animation:tmBreathe 2.4s ease-in-out infinite}
  #waPanel[data-wa-theme="dark"] .wa-conv.tm-askwait:not(.active)::before{background:rgba(196,149,106,.2)}
  @keyframes tmBreathe{0%,100%{opacity:1}50%{opacity:.3}}
  .tm-askchip{font-size:calc(10*var(--wa-u,1px));font-weight:600;color:#7a4e1f;background:var(--wa-input);border:1px solid #B07C49;border-radius:calc(999*var(--wa-u,1px));
    padding:1px calc(7*var(--wa-u,1px));white-space:nowrap;line-height:1.5}
  #waPanel[data-wa-theme="dark"] .tm-askchip{color:#e8bf8a}
  /* a RECIPIENT's chip is the number badge's twin: brown, white text, under the time (Sett, second look) */
  .tm-askchip.tm-askchip-in{background:#8a5a1e;color:#fff;border-color:#8a5a1e;font-size:calc(10.5*var(--wa-u,1px));padding:calc(2*var(--wa-u,1px)) calc(8*var(--wa-u,1px))}
  #waPanel[data-wa-theme="dark"] .tm-askchip.tm-askchip-in{color:#fff}
  @media (prefers-reduced-motion:reduce){.wa-conv.tm-askwait:not(.active)::before{animation:none}}
  .tm-ask{padding:calc(16*var(--wa-u,1px)) calc(18*var(--wa-u,1px));overflow-y:auto;flex:1;min-height:0}
  .tm-ask-lbl{font-size:calc(10.5*var(--wa-u,1px));font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--wa-sub);margin:0 0 calc(8*var(--wa-u,1px))}
  .tm-ask-teams{display:flex;flex-wrap:wrap;gap:calc(8*var(--wa-u,1px));margin-bottom:calc(14*var(--wa-u,1px))}
  .tm-ask-chip{border:1px solid rgba(0,0,0,.14);background:var(--wa-input);color:var(--wa-text);border-radius:calc(999*var(--wa-u,1px));
    padding:calc(7*var(--wa-u,1px)) calc(14*var(--wa-u,1px));font-size:calc(13*var(--wa-u,1px));font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:calc(8*var(--wa-u,1px));font-family:inherit}
  .tm-ask-chip b{font-weight:500;font-size:calc(11*var(--wa-u,1px));color:var(--wa-meta)}
  .tm-ask-chip.on{background:#3d2a14;color:#F5EAD8;border-color:#3d2a14}
  .tm-ask-chip.on b{color:#EDCFAD}
  .tm-ask-who{font-size:calc(13*var(--wa-u,1px));color:var(--wa-text);margin-bottom:calc(4*var(--wa-u,1px));line-height:1.45}
  .tm-ask-note{font-size:calc(11.5*var(--wa-u,1px));color:var(--wa-meta);margin-bottom:calc(14*var(--wa-u,1px));line-height:1.45}
  .tm-ask-body{width:100%;box-sizing:border-box;min-height:calc(96*var(--wa-u,1px));resize:vertical;border:1px solid rgba(0,0,0,.14);border-radius:calc(10*var(--wa-u,1px));
    padding:calc(10*var(--wa-u,1px)) calc(12*var(--wa-u,1px));font-size:calc(14.2*var(--wa-u,1px));font-family:inherit;color:var(--wa-text);background:var(--wa-input);outline:none;line-height:1.4}
  .tm-ask-body:focus{border-color:var(--wa-send)}
  .tm-ask-actions{display:flex;justify-content:flex-end;align-items:center;gap:calc(10*var(--wa-u,1px));margin-top:calc(10*var(--wa-u,1px))}
  .tm-ask-send{background:var(--wa-send);color:#fff;border:0;border-radius:calc(999*var(--wa-u,1px));padding:calc(9*var(--wa-u,1px)) calc(18*var(--wa-u,1px));font-size:calc(13.5*var(--wa-u,1px));font-weight:600;
    cursor:pointer;font-family:inherit}
  .tm-ask-send:disabled{opacity:.45;cursor:default}
  /* ⭐⭐ THE BROADCAST (Sett, 2026-10-02 — the mock-up he locked). The sheet above keeps its look; under the
     pills sits EVERYONE on staff with a tick box, the pills only pre-tick a group. On the People page the
     people already in are grey locked ticks and "Make lead" shows on HOVER over a ticked name (Sett) — the
     tablet has no hover, so a long-press shows it there (the panel's message-actions rule). */
  /* three columns, banded like My Team (Sett, 2026-10-02): a band's small heading spans the row, so each band starts
     on a fresh line — Management, the bench, Production, the test logins */
  .tm-bc-grp{grid-column:1/-1;font-size:calc(10.5*var(--wa-u,1px));font-weight:600;letter-spacing:.06em;text-transform:uppercase;
    color:var(--wa-sub);padding:calc(7*var(--wa-u,1px)) calc(3*var(--wa-u,1px)) calc(1*var(--wa-u,1px))}
  .tm-bc-grp:first-child{padding-top:calc(1*var(--wa-u,1px))}
  .tm-bc-people{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:calc(2*var(--wa-u,1px)) calc(10*var(--wa-u,1px));
    background:var(--wa-input);border:1px solid var(--wa-line);border-radius:calc(10*var(--wa-u,1px));padding:calc(7*var(--wa-u,1px)) calc(9*var(--wa-u,1px));margin-bottom:calc(10*var(--wa-u,1px))}
  .tm-bc-pp{display:flex;align-items:center;gap:calc(7*var(--wa-u,1px));min-width:0;padding:calc(4*var(--wa-u,1px)) calc(3*var(--wa-u,1px));border-radius:calc(6*var(--wa-u,1px));
    font-size:calc(13*var(--wa-u,1px));color:var(--wa-text);cursor:pointer;user-select:none;position:relative}
  .tm-bc-pp:hover{background:rgba(0,0,0,.035)}
  .tm-bc-pp .bx{flex:none;width:calc(16*var(--wa-u,1px));height:calc(16*var(--wa-u,1px));border-radius:calc(4*var(--wa-u,1px));border:1.5px solid #B4B2A9;display:grid;place-items:center;background:var(--wa-input)}
  .tm-bc-pp.on .bx{background:#3d2a14;border-color:#3d2a14}
  .tm-bc-pp.on .bx::after{content:"";width:calc(8*var(--wa-u,1px));height:calc(4*var(--wa-u,1px));border-left:2px solid #F5EAD8;border-bottom:2px solid #F5EAD8;transform:translateY(-1px) rotate(-45deg)}
  .tm-bc-pp.locked{cursor:default}
  .tm-bc-pp.locked .bx{background:#B4B2A9;border-color:#B4B2A9}
  .tm-bc-pp .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
  .tm-bc-tagl{flex:none;font-size:calc(10*var(--wa-u,1px));font-weight:600;border-radius:calc(999*var(--wa-u,1px));padding:0 calc(6*var(--wa-u,1px));line-height:1.6}
  .tm-bc-tagl.lead{background:#854F0B;color:#FAEEDA}
  .tm-bc-tagl.add{background:#E1F5EE;color:#085041}
  .tm-bc-tagl.newlead{background:#FAEEDA;color:#633806;border:1px solid #BA7517}
  .tm-bc-mk{display:none;flex:none;font-size:calc(10.5*var(--wa-u,1px));color:#854F0B;text-decoration:underline;background:none;border:0;padding:0;cursor:pointer;font-family:inherit}
  .tm-bc-pp.on:hover .tm-bc-mk, .tm-bc-pp.locked:hover .tm-bc-mk, .tm-bc-pp.show-mk .tm-bc-mk{display:inline}
  .tm-bc-mk[hidden]{display:none!important}   /* `hidden` must win over the hover rule above */
  .tm-bc-topic{width:100%;box-sizing:border-box;border:1px solid rgba(0,0,0,.14);border-radius:calc(10*var(--wa-u,1px));padding:calc(8*var(--wa-u,1px)) calc(12*var(--wa-u,1px));
    font-size:calc(13.5*var(--wa-u,1px));font-family:inherit;color:var(--wa-text);background:var(--wa-input);outline:none;margin-bottom:calc(10*var(--wa-u,1px))}
  .tm-bc-topic:focus{border-color:var(--wa-send)}
  #waPanel[data-wa-theme="dark"] .tm-bc-pp:hover{background:rgba(255,255,255,.05)}
  /* in the thread: the Lead badge beside a name, the grey step lines, the request's two buttons, and a
     private reply's "From your broadcast" card */
  .tm-bc-lead{display:inline-block;font-size:calc(10*var(--wa-u,1px));font-weight:600;background:#854F0B;color:#FAEEDA;border-radius:calc(999*var(--wa-u,1px));padding:0 calc(6*var(--wa-u,1px));margin-left:calc(5*var(--wa-u,1px));vertical-align:1px;line-height:1.6}
  .tm-bc-acts{clear:both;display:flex;gap:calc(6*var(--wa-u,1px));flex-wrap:wrap;margin-top:calc(8*var(--wa-u,1px))}
  .tm-bc-act{display:inline-flex;align-items:center;gap:calc(5*var(--wa-u,1px));border:1px solid rgba(0,0,0,.16);background:var(--wa-input);color:var(--wa-text);border-radius:calc(999*var(--wa-u,1px));
    padding:calc(5*var(--wa-u,1px)) calc(12*var(--wa-u,1px));font-size:calc(12.5*var(--wa-u,1px));font-weight:600;cursor:pointer;font-family:inherit}
  .tm-bc-act.go{background:#3d2a14;color:#F5EAD8;border-color:#3d2a14}
  .tm-bc-act:disabled{opacity:.5;cursor:default}
  .tm-bc-ref{border:1px dashed rgba(0,0,0,.25);border-radius:calc(8*var(--wa-u,1px));padding:calc(4*var(--wa-u,1px)) calc(8*var(--wa-u,1px));margin-bottom:calc(5*var(--wa-u,1px));
    font-size:calc(11.5*var(--wa-u,1px));color:var(--wa-meta);cursor:pointer}
  .tm-bc-ref b{font-weight:600;color:var(--wa-text)}
  .tm-bc-refbar .wa-rq-name{color:#854F0B}
  .tm-bc-headbtn{flex:none;border:1px solid rgba(0,0,0,.14);background:var(--wa-input);color:#3d2a14;border-radius:calc(999*var(--wa-u,1px));padding:calc(4*var(--wa-u,1px)) calc(11*var(--wa-u,1px));
    font-size:calc(12.5*var(--wa-u,1px));font-weight:600;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:calc(5*var(--wa-u,1px));margin-left:calc(4*var(--wa-u,1px))}
  .tm-bc-headbtn.done{background:#3d2a14;color:#F5EAD8;border-color:#3d2a14}
  /* ⭐ THE TEAM COMPOSER HAS NO TEMPLATES BUTTON (Sett, 2026-10-02: "a gap between attached file + sign and the
     emoticon icon"). The shared composer seats the emoji at 71, after the client's ＋ AND its Templates button, and
     pads the text to 107 to clear all three; the team's has only the ＋, so both move up one 33-wide slot. */
  #teamMain .wa-emojibtn{left:calc(38*var(--wa-u,1px))}
  #teamMain .wa-row .wa-ce{padding-left:calc(74*var(--wa-u,1px))}
  #waPanel[data-wa-theme="dark"] .tm-bc-headbtn:not(.done){color:#e8bf8a}
  .tm-bc-closed{padding:calc(12*var(--wa-u,1px)) calc(16*var(--wa-u,1px));text-align:center;font-size:calc(12.5*var(--wa-u,1px));color:var(--wa-meta);border-top:1px solid var(--wa-line);background:var(--wa-composer)}
  .tm-bcav{background:#EDCFAD;color:#3d2a14}
  .tm-bcav.team{background:#E1F5EE;color:#085041}
  /* a broadcast closed while you still had something unread: grey until you open it once (agreed) */
  .wa-conv.tm-bc-closedrow .wa-conv-nm, .wa-conv.tm-bc-closedrow .wa-conv-pv{color:var(--wa-meta)}
  .wa-conv.tm-bc-closedrow .tm-bcav{background:#D3D1C7;color:#444441}
  .tm-askchip.tm-bc-chip-closed{background:#F1EFE8;color:#444441;border-color:#B4B2A9}
  /* the 48-hour reminder — the sender's row pulses harder than a waiting request breathes */
  .wa-conv.tm-bc-remind:not(.active)::before{background:rgba(186,117,23,.28);animation:tmBreathe 1.3s ease-in-out infinite}
  @media (prefers-reduced-motion:reduce){.wa-conv.tm-bc-remind:not(.active)::before{animation:none}}
  /* ⚠️ NO OVERRIDES ON `.wa-reactbtn`. It is already a 33px white disc with a shadow, vertically
     centred and floated 41px outside the bubble — my overrides replaced all of that with a bare
     transparent glyph pinned to the top corner, which is why it sat in the wrong place. */
