/* here-chat.css — extracted VERBATIM from glass/room/room-test.html.
   The contract for every value in here is ROOM-DESIGN.md. Edit that first.
   Do not hand-edit this file: re-extract, so the prototype stays the
   source and the two cannot drift. */
/* THE PACKAGE SAYS WHAT COLOUR ITS WORDS ARE — and until now it did not.
   Every text tier was a token and the BASE was left to whatever host page the package
   was dropped into. Invisible here, because this file's own body rule sets
   color:#f9f9f9. Not invisible on the live /rooms host, which sets a background and a
   font and no colour at all, and no color-scheme either: a browser in DARK mode falls
   back to its LIGHT default and paints every room name black on the dark rail.
   Measured on the deployed surface — 1.24:1. Half the audience, and no screenshot ever
   caught it because every screenshot was taken in daylight.

   --faint is the fourth tier ROOM-DESIGN.md names in the same breath as the other
   three — "primary 1.0 (--ink), secondary .85 (--dim), muted .55 (--soft), dim .28
   (--faint)" — and it was written into the law and then defined only inside
   here-chat-light.css's light block. So in dark every var(--faint) was an INVALID
   value: the declaration dropped, the element inherited, and what it inherited was the
   black above. Two tokens, one root cause, and the rail was the surface that showed
   it. */

.here-chat{color:var(--ink);--ink:#f9f9f9;--dim:rgba(249,249,249,.85);--soft:rgba(249,249,249,.55);--faint:#939399;--line:#262625;--tint:#0a6fd8;--tint-hi:#7ab8ff;--ember:#0a6fd8;--good:#30d158;--warm:#ffd60a;--bad:#ff6b6b;--smooth:cubic-bezier(.22,1,.36,1);--spring:cubic-bezier(.34,1.4,.5,1);--sqmask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><path d='M0 50C0 10 10 0 50 0s50 10 50 50-10 50-50 50S0 90 0 50z'/></svg>")}

*{box-sizing:border-box}

.aurora{position:fixed;inset:-20%;z-index:-1;pointer-events:none;opacity:.85;
  background:radial-gradient(42% 46% at 78% 6%,rgba(88,130,255,.10),transparent 62%),radial-gradient(40% 44% at 10% 96%,rgba(96,110,225,.11),transparent 60%),radial-gradient(30% 36% at 90% 90%,rgba(70,190,180,.07),transparent 62%);
  animation:drift 26s ease-in-out infinite alternate}
@keyframes drift{from{transform:translate3d(-2%,-1%,0) scale(1.02)}to{transform:translate3d(2%,2%,0) scale(1.08)}}

.panel{position:relative;border-radius:22px;padding:18px 16px;background:rgba(28,28,33,.66);border:1px solid rgba(255,255,255,.09);
  backdrop-filter:blur(24px) saturate(1.35);-webkit-backdrop-filter:blur(24px) saturate(1.35);
  box-shadow:0 20px 50px -24px rgba(0,0,0,.7),inset 0 1px 0 rgba(255,255,255,.06)}

.panel.hfull{position:fixed;inset:10px;z-index:70;display:flex;flex-direction:column;max-width:none;margin:0;overflow:hidden}

.panel.hfull #hmsgs{flex:1}
@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes popin{from{opacity:0;transform:translateY(8px) scale(.97)}to{opacity:1;transform:none}}

.muted{color:var(--soft);font-size:13px}

.rows{margin-top:4px}

#hmsgs{overflow-x:hidden;mask-image:linear-gradient(180deg,transparent 0,#000 22px);-webkit-mask-image:linear-gradient(180deg,transparent 0,#000 22px)}

/* AN ASIDE — igni saying something to ONE person while the room carries on.
   A third thing, deliberately, and not `.note`. A note is a machine receipt: it folds
   away by default (display:none until .show) because 1,206 of 1,540 of them are machine
   and a room buried in receipts is unreadable. An aside is the opposite case — someone
   meant it for you and you are meant to see it.

   It borrows the note's VOICE and refuses its silence: no bubble, no tail, indented,
   quieter — "it did not speak", because it did not speak to the room. But it stays on
   screen, because a private word you never see is not privacy, it is a message that was
   never delivered.

   The reader must be able to tell at a glance that the room did not see this. If they
   cannot, they will answer as though it were public, or hold back believing it was — and
   either way the room lied to them about who was listening. */
.msgrow.aside .bub{background:none!important;border:0;border-radius:0;
  border-left:2px solid rgba(255,255,255,.14);padding:1px 0 1px 9px;
  color:var(--dim);font-size:13.5px;max-width:none}

.msgrow.aside .bub::before{content:none}

.msgrow.aside .who{color:var(--soft)}

/* DAYLIGHT IS ONE SWITCH, NOT FIVE OPINIONS.
   These rules used to fire on @media (prefers-color-scheme:light) alone, while the
   package's master light sheet (here-chat-light.css) ships media="not all" by the
   standing decision of 2026-07-31 — "daylight is an explicit act, never the OS's
   choice". So a member on a light-mode OS got THIS object turned to paper inside a
   room that stayed night, with the package's light-on-dark text still on it.
   Measured 2026-08-24 on /rooms at 1280x800: an aside's rule went to a dark-on-dark border.

   Gated on the explicit pick instead, which is the door the page's own comment
   already names. Nothing is deleted: when [data-theme=light] is wired, every one of
   these comes on together with the master sheet, which is the only way a theme has
   ever worked. */
[data-theme=light] .msgrow.aside .bub{border-left-color:rgba(0,0,0,.16)}


/* A ROW THAT COULD NOT BE OPENED IS A STATE, NOT SPEECH. Without this it arrives with an
   avatar, a name and a bubble, so "this could not be opened" reads as something a person
   said — the exact confusion sealed chats exist to prevent. Centred, quiet, wearing none of
   the chrome that means somebody spoke. */
.msgrow[data-sealfail]{justify-content:center;opacity:.72}

.msgrow[data-sealfail] .who,.msgrow[data-sealfail] .av{display:none}

.msgrow[data-sealfail] .bub{background:none;border:1px dashed currentColor;border-radius:10px;
  font-style:italic;max-width:34em;text-align:center;opacity:.9}

.msgrow{position:relative;display:flex;flex-direction:column;align-items:flex-start;margin-top:12px;padding:0 6px;opacity:0;animation:fade .5s var(--smooth) both}

.msgrow.cont{margin-top:3px}

.msgrow.me{align-items:flex-end}

.msgrow.pop{animation:popin .26s var(--spring) both}

.who{font-size:11px;color:var(--soft);margin:0 0 3px 14px;letter-spacing:.01em}

.who.igni{color:var(--soft)}

.bub{position:relative;max-width:75%;padding:8px 14px;border-radius:19px;font-size:15px;letter-spacing:-.01em;line-height:1.35;color:var(--ink);background:#26262a;border:none;overflow-wrap:anywhere}

.bub.igni{}

.me .bub{background:#0a6fd8;color:#fff}

.msgrow.cont:not(.me) .bub{border-top-left-radius:5px}

.msgrow.cont.me .bub{border-top-right-radius:5px}

.msgrow.pending .bub{filter:opacity(.6) saturate(.7)}

.dlv{font-size:11px;color:var(--soft);margin:3px 4px 0 0}

.xn{display:inline-block;margin-left:8px;padding:1px 6px;background:rgba(255,255,255,.08);border-radius:4px;font-size:10px;font-weight:500;color:var(--soft);vertical-align:1px}

.me .bub .xn{background:rgba(255,255,255,.22);color:rgba(255,255,255,.9)}

.hday{display:flex;align-items:center;justify-content:center;margin:22px 0 8px;color:var(--soft);font-size:11px;font-weight:500;letter-spacing:.02em}

.hunread{color:var(--tint-hi);opacity:.9}

.hnew{position:sticky;bottom:4px;display:block;margin:8px auto 0;width:max-content;padding:5px 13px;border-radius:999px;background:rgba(30,30,36,.78);backdrop-filter:blur(16px) saturate(1.3);-webkit-backdrop-filter:blur(16px) saturate(1.3);border:1px solid rgba(255,255,255,.10);color:var(--ink);font-size:12px;cursor:pointer;letter-spacing:.02em;box-shadow:0 8px 30px rgba(0,0,0,.5),inset 0 1px 0 rgba(255,255,255,.08);transition:transform .15s var(--smooth);animation:fade .3s var(--smooth) both}

.ghost{color:var(--soft);font-size:12px;padding:6px 4px;animation:fade .4s var(--smooth) both}

.tdots{display:inline-flex;gap:3px;margin-right:7px;vertical-align:-1px}

.tdots i{width:5px;height:5px;border-radius:50%;background:var(--soft);animation:tblink 1.2s ease-in-out infinite}

.tdots i:nth-child(2){animation-delay:.15s}
.tdots i:nth-child(3){animation-delay:.3s}


/* WAY-002 thinking face — one primary cognitive face for igni agent turns (never people) */
#hthink{display:none;align-items:center;gap:10px;margin-top:8px;min-height:28px}

#hthink.on{display:flex}

#hthink .cogface{width:28px;height:28px;flex:none;border-radius:8px;overflow:hidden;
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08)}

#hthink .cogface canvas{display:block;width:28px;height:28px}

#hthink .coglab{font:11px/1.3 -apple-system,system-ui,sans-serif;color:var(--soft);letter-spacing:.01em}

#hthink .coglab b{color:var(--ink);font-weight:500}
@media (prefers-reduced-motion: reduce){
  #hthink .cogface{background:rgba(255,255,255,.08)}}
@keyframes tblink{0%,60%,100%{opacity:.25}30%{opacity:1}}

#htyping{min-height:16px;font-size:12px;color:var(--soft);margin-top:8px}

.rxrow{display:flex;gap:4px;margin:-7px 0 0 12px;z-index:2}

.msgrow.me .rxrow{margin:-7px 12px 0 0}

.rx{font-size:12px;line-height:1;padding:4px 8px;border-radius:999px;background:rgba(30,30,36,.9);border:1px solid rgba(255,255,255,.10);box-shadow:0 2px 8px rgba(0,0,0,.4)}

.rx.mine{border-color:rgba(10,132,255,.5);background:rgba(10,132,255,.16)}

.rxbar{position:absolute;top:-44px;left:8px;display:flex;gap:2px;padding:5px 7px;border-radius:999px;background:rgba(30,30,36,.85);backdrop-filter:blur(16px) saturate(1.3);-webkit-backdrop-filter:blur(16px) saturate(1.3);border:1px solid rgba(255,255,255,.12);box-shadow:0 10px 30px rgba(0,0,0,.5);animation:popin .22s var(--spring) both;z-index:6}

.msgrow.me .rxbar{left:auto;right:8px}

.rxbar button{border:none;background:transparent;font-size:17px;line-height:1;padding:4px 6px;cursor:pointer;border-radius:10px;transition:transform .15s var(--spring)}

.rxbar button:hover{transform:scale(1.28)}

.rxbar button:active{transform:scale(.9)}

.btime{position:absolute;right:2px;bottom:12px;font-size:10.5px;color:var(--soft);opacity:0;transition:opacity .18s var(--smooth);pointer-events:none}

.msgrow.me .btime{right:auto;left:2px}

.msgrow:hover .btime{opacity:1}

.bub.tail-l::before,.bub.tail-r::before{content:'';position:absolute;bottom:0;width:11px;height:17px;background:inherit}

.bub.tail-r::before{right:-5.5px;clip-path:path('M0 0 C 2 9 6.5 14.5 11 17 C 5 17 1.5 15 0 12 Z')}

.bub.tail-l::before{left:-5.5px;clip-path:path('M11 0 C 9 9 4.5 14.5 0 17 C 6 17 9.5 15 11 12 Z')}

.bub.wbub{max-width:92%;width:min(92%,430px);padding:0;background:transparent}

.bub.wbub.tail-l::before,.bub.wbub.tail-r::before{content:none}

.wcap{font-size:13px;color:var(--soft);margin-bottom:8px}

.wg .wgt{font-size:14px;font-weight:590;color:var(--ink);margin-bottom:6px}

.wgk{font-size:11px;color:var(--soft);letter-spacing:.03em}

.wgv{font-size:20px;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}

.wgs{font-size:11px;color:var(--soft);margin-top:2px}

.wgg{display:grid;grid-template-columns:repeat(auto-fit,minmax(90px,1fr));gap:10px}

.wgc{background:rgba(255,255,255,.05);border-radius:10px;padding:8px 10px}

.wgi{padding:6px 0;border-top:1px solid rgba(255,255,255,.05);font-size:13.5px}

.wgi:first-of-type{border-top:none}

.wgl{color:var(--tint-hi);text-decoration:none;font-weight:500}

.wgb{font-size:13.5px;color:var(--dim);line-height:1.45}

.wgic{font-size:22px;margin-bottom:4px}

.wgbar{height:5px;border-radius:999px;background:rgba(255,255,255,.08);overflow:hidden;margin:8px 0 2px}

.wgbar i{display:block;height:100%;border-radius:999px;background:var(--tint)}

.wgch{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}

/* --tint-hi, not --ember: ember is an alias of tint (#0a6fd8 night / #0a66c8 light) and
   .wgo sits on a DARK widget card even on the default ground, where that measured
   3.11:1. --tint-hi is the pair's contrast-safe half in both grounds — #7ab8ff for a
   dark card, #0a52a0 where its own comment says 'text-on-light variant'. */
.wgo{border:1px solid rgba(10,132,255,.4);background:rgba(10,132,255,.10);color:var(--tint-hi);border-radius:999px;padding:6px 12px;font-size:13px;cursor:pointer;transition:transform .15s var(--spring)}

.wgo:active{transform:scale(.94)}

.wgim{max-width:100%;border-radius:12px;display:block}

/* #36 image pipeline: a blurhash-ish gradient placeholder holds the box (no
   reflow) until the real bytes decode, then fade in. */
.imgwrap{position:relative;border-radius:14px;overflow:hidden;max-width:260px}

.imgph{position:absolute;inset:0;filter:saturate(1.2)}

.imgwrap img{display:block;width:100%;height:auto;opacity:0;transition:opacity .4s var(--smooth);position:relative}

.imgwrap img.on{opacity:1}

/* #55 tapback tip button in the react bar */
.rxtip{border-left:1px solid rgba(255,255,255,.14);margin-left:3px;padding-left:6px !important;font-size:15px !important}

.wg{background:#1c1c1e;border-radius:22px;padding:14px;box-shadow:0 10px 30px -14px rgba(0,0,0,.65)}

.wcap{margin:0 0 6px 4px}

.wghead{display:flex;align-items:center;gap:8px;margin-bottom:10px}

.wgapp{width:26px;height:26px;display:flex;align-items:center;justify-content:center;font-size:15px;color:#fff;background:rgba(255,255,255,.09);-webkit-mask-image:var(--sqmask);mask-image:var(--sqmask);-webkit-mask-size:100% 100%;mask-size:100% 100%;overflow:hidden}

.wgapp img,.ai2 img{width:72%;height:72%;object-fit:contain;display:block}

/* 22px with the letter at 11px: the audit holds anything carrying DATA to an
   11px floor, and this letter was set at 8px -- the mark that tells one member
   from another, below the floor everything else obeys. 590 rather than 700 and
   positive tracking at small size is the SF idiom; iOS almost never sets a list
   name at 700. The package's ground is dark, so night is the default and day
   arrives by query -- the mark stays right on whichever ground it lands on. */
.wavi{width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:590;letter-spacing:.004em;background:var(--avf);color:var(--avi);vertical-align:-6px;margin-right:6px;overflow:hidden}

/* DAYLIGHT IS ONE SWITCH, NOT FIVE OPINIONS.
   These rules used to fire on @media (prefers-color-scheme:light) alone, while the
   package's master light sheet (here-chat-light.css) ships media="not all" by the
   standing decision of 2026-07-31 — "daylight is an explicit act, never the OS's
   choice". So a member on a light-mode OS got THIS object turned to paper inside a
   room that stayed night, with the package's light-on-dark text still on it.
   Measured 2026-08-24 on /rooms at 1280x800: avatar initials took the light palette's fill on the dark one's ground.

   Gated on the explicit pick instead, which is the door the page's own comment
   already names. Nothing is deleted: when [data-theme=light] is wired, every one of
   these comes on together with the master sheet, which is the only way a theme has
   ever worked. */
[data-theme=light] .wavi{background:var(--avfd);color:var(--avid)}

.wavi img{width:100%;height:100%;object-fit:cover}

.emo{display:inline-flex;align-items:center;justify-content:center;height:1.35em;width:1.35em;vertical-align:-0.28em;overflow:hidden}

.emo img{height:100%;width:100%;object-fit:contain;display:block}

.emo.emg{font-size:1.15em;width:auto;height:auto;vertical-align:-0.08em}

.emo.hasarg{width:auto;gap:3px;padding:0 5px 0 3px;border-radius:999px;background:rgba(10,132,255,.10);overflow:visible}

.earg{font-size:.8em;font-weight:600;letter-spacing:-.01em;color:var(--tint-hi);white-space:nowrap}

.bub.ejumbo .emo.hasarg{width:auto;background:rgba(10,132,255,.14);padding:0 9px 0 4px;border-radius:16px}

.bub.ejumbo .earg{font-size:19px}

/* ── LINK-PREVIEW CARDS — a person's pasted link, attached to THEIR message.
   NOT a widget (widgets are igni's hands): own chrome, own class, own census. */
.lpk{background:#1c1c1e;border-radius:22px;box-shadow:0 10px 30px -14px rgba(0,0,0,.65);padding:0;overflow:hidden;cursor:pointer;transition:transform .18s var(--spring)}

.lpk:hover{transform:translateY(-1px)}

.lpk:active{transform:scale(.975)}

.lpk:focus-visible{outline:2px solid var(--tint);outline-offset:2px}

.lpthumb{position:relative;height:168px;overflow:hidden;background:#161b22}

.lpthumb img{width:100%;height:100%;object-fit:cover;display:block}

.lpthumb .hglyph{position:absolute;right:-12px;top:-10px;font-size:120px;line-height:1;opacity:.28;transform:rotate(-12deg)}

.lpmeta{display:flex;align-items:center;gap:9px;padding:11px 13px}

.lpmtext{flex:1;min-width:0}

.lptitle{font-size:14px;font-weight:600;color:var(--ink);line-height:1.3;letter-spacing:-.01em;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

.lpdom{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--soft);margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.lpmeta .wgapp{width:16px;height:16px;font-size:9px;flex:none}

.lpport{flex:none;color:var(--tint-hi);font-size:15px;align-self:center}

.lpafter{width:min(92%,430px);max-width:92%;margin-top:4px}

/* ── #91 density mode: compact spacing + collapsed app-emission bursts ── */
body.dense .msgrow{margin-top:6px}

body.dense .msgrow.cont{margin-top:1px}

body.dense .who{margin-bottom:1px}

body.dense .bub{padding:6px 13px;line-height:1.3}

body.dense .hday{margin:12px 0 5px}

.burstrow{display:flex;align-items:center;gap:9px;margin-top:8px;padding:8px 12px;border-radius:12px;background:rgba(255,255,255,.04);cursor:pointer;font-size:12.5px;color:var(--soft);animation:fade .3s var(--smooth) both}

.burstrow .bstile{width:22px;height:22px;flex:none;-webkit-mask-image:var(--sqmask);mask-image:var(--sqmask);-webkit-mask-size:100% 100%;mask-size:100% 100%;overflow:hidden;display:flex;align-items:center;justify-content:center;color:#fff;font-size:12px}

.burstrow .bstile img{width:72%;height:72%;object-fit:contain}

.burstrow b{color:var(--dim);font-weight:600}

.burstrow .bsx{margin-left:auto;color:var(--tint-hi);font-weight:600}

/* ── #16 disambiguation chooser (one word, N subjects) ── */
.dzrow{display:flex;align-items:center;gap:10px;padding:8px 4px;border-top:1px solid rgba(255,255,255,.05);cursor:pointer}

.dzrow:first-of-type{border-top:none}

.dzk{flex:none;font-size:11px;font-weight:700;color:var(--soft);width:52px;text-transform:uppercase;letter-spacing:.05em}

.dzn{flex:1;min-width:0;color:var(--ink);font-size:14px}

.dzs{font-size:11.5px;color:var(--soft)}

.dzgo{color:var(--tint-hi)}

/* ── #92 full-text search → recall cards (link-preview anatomy, pointed INWARD) ── */
.rcard{background:#1c1c1e;border-radius:16px;box-shadow:0 10px 30px -14px rgba(0,0,0,.65);padding:11px 13px;margin-top:6px;cursor:pointer;transition:transform .18s var(--spring)}

.rcard:active{transform:scale(.98)}

.rcard:focus-visible{outline:2px solid var(--tint);outline-offset:2px}

.rcard .rcw{font-size:11px;color:var(--soft);display:flex;gap:6px}

.rcard .rcw b{color:var(--dim);font-weight:600}

.rcard .rcb{font-size:14px;color:var(--ink);line-height:1.35;margin-top:3px;overflow-wrap:anywhere}

.rcard .rcb mark{background:rgba(10,132,255,.28);color:#fff;border-radius:3px;padding:0 2px}

.rcard .rcgo{float:right;color:var(--tint-hi);font-size:14px}

/* ── #94 swipe-to-reply: the bubble translates under the gesture ── */
.msgrow.swiping{transition:none}

.msgrow .bub{transition:transform .18s var(--spring)}

/* ── #95 global ⌘K palette ── */
#kbg{position:fixed;inset:0;z-index:78;background:rgba(0,0,0,.5);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}

#kbar{position:fixed;z-index:79;left:50%;top:14%;transform:translateX(-50%);width:min(460px,92vw);border-radius:16px;overflow:hidden;background:rgba(28,28,34,.94);backdrop-filter:blur(24px) saturate(1.35);-webkit-backdrop-filter:blur(24px) saturate(1.35);border:1px solid rgba(255,255,255,.12);box-shadow:0 24px 70px -18px rgba(0,0,0,.8)}

#kbar input{width:100%;border:none;outline:none;background:transparent;color:var(--ink);font-size:16px;padding:15px 16px;border-bottom:1px solid rgba(255,255,255,.08)}

.kres{max-height:min(52vh,380px);overflow-y:auto;padding:6px}

.kres button{display:flex;align-items:center;gap:10px;width:100%;text-align:left;border:none;background:transparent;color:var(--dim);border-radius:10px;padding:9px 11px;cursor:pointer;font-size:14px}

.kres button.sel,.kres button:hover{background:rgba(10,132,255,.16)}

.kres .kk{flex:none;font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--soft);width:38px}

.kres .kn{flex:1;min-width:0;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.kres .kd{flex:none;font-size:11px;color:var(--soft)}

/* ── #93 thread drawer over re_mid chains ── */
.threadn{display:inline-flex;align-items:center;gap:4px;margin:2px 4px 0;padding:2px 9px;border-radius:999px;background:rgba(10,132,255,.12);color:var(--tint-hi);font-size:11px;font-weight:600;cursor:pointer;border:none}

.msgrow.me .threadn{align-self:flex-end}

.thread .shh{font-size:14px}

.thline{display:flex;flex-direction:column;gap:2px;padding:8px 10px;border-radius:12px;margin-top:6px;background:rgba(255,255,255,.04);cursor:pointer}

.thline.root{border-left:2.5px solid var(--tint)}

.thline .thw{font-size:11px;color:var(--soft)}

.thline .thb{font-size:14px;color:var(--dim);white-space:pre-wrap;overflow-wrap:anywhere}

/* ── #100 print/export — a day as a clean document ── */
@media print{.aurora,.ask,.hint,#state,#htyping,#hthink,.hfullbtn,#hbud,.chips{display:none !important}
 .panel{background:#fff !important;box-shadow:none !important;border:none !important;max-width:none !important}
 .bub{background:#eee !important;color:#111 !important}.me .bub{background:#d6e6ff !important}}

/* ── anchored replies — the quote (additive re_mid) ── */
#hpins{border-bottom:1px solid var(--line);padding:6px 10px;display:flex;flex-direction:column;gap:4px}

.pinrow{display:flex;align-items:baseline;gap:7px;font-size:12px;color:var(--soft);cursor:pointer;text-align:left;background:none;border:0;padding:2px 0;width:100%}

.pinrow:hover{color:var(--dim)}

.pinrow b{flex:none;color:var(--dim);font-weight:600}

.pinrow span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.pinrow i{flex:none;color:var(--faint);font-style:normal}

.pinrow:focus-visible{outline:2px solid var(--tint);outline-offset:1px}

.rxdel{color:var(--bad,#ff453a)}

#hatts{display:flex;flex-wrap:wrap;gap:6px;padding:6px 10px 0}

.pend{display:inline-flex;align-items:center;gap:6px;max-width:210px;padding:5px 8px;border:1px solid var(--line);border-radius:9px;background:rgba(255,255,255,.04);font-size:11.5px;color:var(--soft)}

.pend span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.pend.up{opacity:.55}

.pend button{flex:none;border:0;background:none;color:var(--faint);font:inherit;line-height:1;cursor:pointer;padding:0 1px}

.pend button:hover{color:var(--dim)}

.clip{flex:none;width:34px;height:34px;border:0;border-radius:50%;background:none;color:var(--dim);font-size:17px;line-height:1;cursor:pointer;transform:rotate(-45deg)}

.clip:hover{color:var(--ink)}

.clip:focus-visible{outline:2px solid var(--tint);outline-offset:2px}

.panel.dragging{outline:2px dashed var(--tint-hi);outline-offset:-6px}

.attchip{display:inline-flex;align-items:center;gap:7px;max-width:75%;margin:3px 4px 0;padding:6px 11px;border:1px solid var(--line);border-radius:9px;background:rgba(255,255,255,.04);font-size:12px;color:var(--soft);cursor:pointer;text-decoration:none;overflow:hidden}

.attchip:hover{background:rgba(255,255,255,.07);color:var(--dim)}

.attchip b{flex:none;color:var(--dim);font-weight:600}

.attchip span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.attchip:focus-visible{outline:2px solid var(--tint);outline-offset:1px}

.msgrow.me .attchip{align-self:flex-end}

.attwrap{display:flex;flex-direction:column;align-items:flex-start}

.msgrow.me .attwrap{align-items:flex-end}

.qchip{display:flex;align-items:center;gap:8px;max-width:75%;margin:0 4px 3px;padding:5px 10px;border-left:2.5px solid var(--tint);border-radius:8px;background:rgba(255,255,255,.05);font-size:12px;color:var(--soft);cursor:pointer;overflow:hidden}

.qchip b{flex:none;color:var(--dim);font-weight:600}

.qchip span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.qchip:focus-visible{outline:2px solid var(--tint);outline-offset:1px}

.msgrow.me .qchip{align-self:flex-end}

.qstrip{display:flex;align-items:center;gap:10px;margin-top:10px;padding:8px 12px;border-left:2.5px solid var(--tint);border-radius:10px;background:rgba(255,255,255,.05);animation:fade .2s var(--smooth) both}

.qstrip .qsm{flex:1;min-width:0;font-size:12.5px;color:var(--soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.qstrip .qsm b{color:var(--dim);font-weight:600;margin-right:6px}

.qstrip .qsx{flex:none;width:24px;height:24px;border-radius:50%;border:none;background:rgba(255,255,255,.10);color:var(--dim);font-size:11px;cursor:pointer;line-height:1}
@keyframes qflash{0%,100%{box-shadow:none}30%{box-shadow:0 0 0 3px rgba(10,132,255,.45)}}

.bub.qflash{animation:qflash 1.4s var(--smooth) 2}

.rxreply{border-left:1px solid rgba(255,255,255,.14);margin-left:3px;padding-left:5px !important;font-size:14px !important;color:var(--dim)}

/* ══ calls & voice ══ */
/* call-door rail (widget). green stays SEMANTIC (identity tile + presence pill);
   every interaction control is tint or the sanctioned red for end/decline. */
.callav{font-size:18px}

.callpill{display:inline-block;margin-left:8px;padding:2px 8px;border-radius:999px;font-size:10px;font-weight:600;letter-spacing:.03em;vertical-align:2px;background:rgba(52,199,89,.16);color:#5fe08a}

.callpill.ringing{animation:callpulse 1.4s ease-in-out infinite}
@keyframes callpulse{0%,100%{opacity:1}50%{opacity:.45}}

.callwho{display:flex;margin-top:10px;padding-left:6px}

.callcirc{width:26px;height:26px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;color:#fff;margin-right:-6px;border:2px solid #1c1c1e;overflow:hidden;background:#3a3a3f}

.callcirc img{width:100%;height:100%;object-fit:cover}

.callact{margin-top:12px}

/* the call sheet (reuses .appsheet) */
.callbody{flex-direction:column;justify-content:space-between;align-items:stretch;padding:0}

.callstage{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:24px;padding:24px}

.callparts{display:flex;flex-wrap:wrap;gap:22px;align-items:flex-end;justify-content:center}

.callpartw{display:flex;flex-direction:column;align-items:center;gap:8px}

.callpart{width:74px;height:74px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:28px;font-weight:700;color:#fff;overflow:hidden;background:#3a3a3f;box-shadow:0 12px 34px -12px rgba(0,0,0,.65)}

.callpart img{width:100%;height:100%;object-fit:cover}

.callpn{font-size:13px;color:var(--dim)}

.callstatus{min-height:24px;font-size:15px;color:var(--soft);display:flex;align-items:center;gap:10px;justify-content:center}

.calltime{font-variant-numeric:tabular-nums;color:var(--ink);font-size:17px}

.callmock{font-size:11px;color:var(--soft);opacity:.7}

.calldots{display:inline-flex;gap:3px}

.calldots i{width:6px;height:6px;border-radius:50%;background:var(--soft);animation:tblink 1.2s ease-in-out infinite}

.calldots i:nth-child(2){animation-delay:.15s}
.calldots i:nth-child(3){animation-delay:.3s}

.callctl{display:flex;gap:28px;justify-content:center;padding:18px 24px 42px}

.cbtn{display:flex;flex-direction:column;align-items:center;gap:7px;border:none;background:transparent;cursor:pointer;color:var(--dim);font-size:11px}

.cbtn .cbg{width:60px;height:60px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:24px;background:rgba(255,255,255,.12);transition:transform .15s var(--spring),background .2s}

.cbtn:active .cbg{transform:scale(.92)}

.cbtn:focus-visible{outline:2px solid var(--tint);outline-offset:3px;border-radius:14px}

.cbtn.join .cbg{background:var(--tint);color:#fff}

.cbtn.end .cbg{background:#ff453a;color:#fff}

.cbtn.mute.on .cbg{background:#fff;color:#111}

/* voice-note bubble */
.vbub{overflow:visible}

.vnote{display:flex;align-items:center;gap:10px;min-width:184px}

.vplay{flex:none;width:34px;height:34px;border-radius:50%;border:none;background:rgba(255,255,255,.16);color:#fff;font-size:12px;cursor:pointer;transition:transform .15s var(--spring)}

.me .vplay{background:rgba(255,255,255,.28)}

.vplay:active{transform:scale(.9)}

.vplay:focus-visible{outline:2px solid var(--tint-hi);outline-offset:2px}

.vwave{position:relative;flex:1;display:flex;align-items:center;gap:2px;height:26px}

.vwave i{flex:1;min-width:2px;border-radius:2px;background:var(--soft);opacity:.65}

.me .vwave i{background:rgba(255,255,255,.72);opacity:.85}

.vprog{position:absolute;left:0;top:0;bottom:0;width:100%;transform:scaleX(0);transform-origin:left;background:rgba(122,184,255,.28);border-radius:3px;pointer-events:none;transition:transform .06s linear}

.me .vprog{background:rgba(255,255,255,.26)}

.vdur{flex:none;font-size:11px;color:var(--soft);font-variant-numeric:tabular-nums}

.me .vdur{color:rgba(255,255,255,.8)}

/* inline voice recorder (chrome/glass, .uppanel material) */
.vrec{padding:0}

.vrbar{display:flex;align-items:center;gap:10px;padding:10px 12px}

.vrdot{flex:none;width:11px;height:11px;border-radius:50%;background:#ff453a;animation:callpulse 1.1s ease-in-out infinite}

.vrtime{flex:none;font-size:12px;color:var(--dim);font-variant-numeric:tabular-nums;min-width:34px}

.vrwave{flex:1;display:flex;align-items:center;gap:2px;height:26px;overflow:hidden}

.vrwave i{flex:none;width:3px;border-radius:2px;background:var(--tint-hi)}

.vrcancel,.vrsend{flex:none;width:32px;height:32px;border-radius:50%;border:none;cursor:pointer;font-size:14px;line-height:1}

.vrcancel{background:rgba(255,255,255,.10);color:var(--dim)}

.vrsend{background:linear-gradient(180deg,#fdfdfe,#dfdfe6 42%,#c9c9d2 58%,#efeff3);color:#0a0a0a;font-weight:700;box-shadow:inset 0 1px 0 rgba(255,255,255,.95),inset 0 -1px 0 rgba(0,0,0,.22)}

/* in-sheet completing gesture: the filled words + a real send, since the
   fullscreen sheet covers the composer it filled */
.callsend{display:flex;align-items:center;gap:10px;min-height:36px}

.callphrase{font-size:14px;color:var(--ink);background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.10);border-radius:999px;padding:8px 14px}

.callgo{width:36px;height:36px;font-size:15px}

/* motion is a courtesy, never a requirement (ROOM-DESIGN law 7) */
@media (prefers-reduced-motion:reduce){
  .aurora,.callpill.ringing,.vrdot,.tdots i,.calldots i,.rxbar{animation:none}
  .msgrow,.msgrow.pop,.ghost,.hnew{animation:none;opacity:1}
  .vprog{transition:none}
  *{scroll-behavior:auto !important}
}

.bub.ejumbo{background:transparent !important;border:none;padding:2px 4px;box-shadow:none}

.bub.ejumbo .emo{height:44px;width:44px;vertical-align:middle;margin:0 3px 0 0}

.bub.ejumbo .emo.emg{font-size:38px}

.eprow .emo{height:22px;width:22px;vertical-align:middle}

.emo[data-glyph]{cursor:pointer;transition:transform .15s var(--spring)}

.emo[data-glyph]:hover{transform:scale(1.18)}

.emo[data-glyph]:active{transform:scale(.94)}

.emo[data-glyph]:focus-visible{outline:2px solid var(--tint);outline-offset:2px;border-radius:8px}

.pmention{color:var(--tint-hi,#7ab8ff);font-weight:600;cursor:pointer;border-radius:6px;transition:opacity .12s}

.pmention:hover{opacity:.75}

.pmention:focus-visible{outline:2px solid var(--tint);outline-offset:1px}

.pmention.grp{background:rgba(10,132,255,.14);padding:0 6px;border-radius:6px}

.pmention.grp::before{content:'⛌ ';opacity:.7;font-size:.85em}

#pcardbg{position:fixed;inset:0;background:rgba(0,0,0,.45);backdrop-filter:blur(6px);z-index:59}

#pcard{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);z-index:60;width:min(320px,86vw)}

#pcard .pacts{display:flex;gap:8px;margin-top:10px}

#pcard .pacts button{flex:1;padding:11px;border-radius:12px;border:1px solid rgba(255,255,255,.14);background:rgba(28,28,33,.86);color:#f9f9f9;font-weight:600;font-size:14px;cursor:pointer}

#pcard .pacts button.pri{background:var(--tint);border-color:transparent}

.bub.ejumbo .emo[data-glyph]:hover{transform:scale(1.06)}

.wgname{font-size:11px;font-weight:590;letter-spacing:.04em;color:var(--soft)}

.wgact{display:flex;gap:8px;margin-top:12px}

.wga{flex:1;border:none;border-radius:12px;padding:9px 12px;font-size:13px;font-weight:600;background:rgba(255,255,255,.09);color:var(--ink);cursor:pointer;transition:transform .15s var(--spring)}

.wga.p{background:linear-gradient(115deg,rgba(255,255,255,0) 30%,rgba(255,255,255,.34) 43%,rgba(255,255,255,.10) 50%,rgba(255,255,255,0) 62%),linear-gradient(180deg,#4ba3ff,#0a84ff 45%,#0765cf 58%,#2a90ff);color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.35),inset 0 -1px 0 rgba(0,0,0,.28)}

.wga:active{transform:scale(.96)}

.wg.hero{position:relative;padding:0;overflow:hidden;min-height:300px;display:flex;flex-direction:column;justify-content:flex-end;transition:transform .18s var(--spring)}

.wg.hero:active{transform:scale(.975)}

.hart{position:absolute;inset:0}

.hart img{width:100%;height:100%;object-fit:cover;display:block}

.hart::after{content:'';position:absolute;inset:0;background:radial-gradient(120% 80% at 18% 0%,rgba(255,255,255,.14),transparent 55%)}

.hglyph{position:absolute;right:-18px;top:-12px;font-size:150px;line-height:1;opacity:.3;transform:rotate(-12deg)}

.hglyph.s{font-size:84px;right:-10px;top:-16px;opacity:.35}

.hscrim{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 30%,rgba(0,0,0,.64) 80%)}

.hcontent{position:relative;padding:16px 16px 12px}

.heyebrow{font-size:11px;font-weight:600;letter-spacing:.08em;color:rgba(255,255,255,.75);text-transform:uppercase;margin-bottom:4px}

.htitle{font-size:23px;font-weight:700;letter-spacing:-.02em;color:#fff;line-height:1.15}

.hsub{font-size:13px;color:rgba(255,255,255,.82);margin-top:4px}

.hfoot{position:relative;display:flex;align-items:center;gap:10px;padding:12px 14px;background:rgba(18,18,22,.6);backdrop-filter:blur(18px) saturate(1.3);-webkit-backdrop-filter:blur(18px) saturate(1.3);border-top:1px solid rgba(255,255,255,.06)}

.hfoot .wgapp{width:32px;height:32px;font-size:18px;background:rgba(255,255,255,.12)}

.hfmeta{flex:1;min-width:0}

.hfn{font-size:13px;font-weight:600;color:#fff}

.hfs{font-size:11px;color:rgba(255,255,255,.72)}

.hfoot .wga{flex:none;min-width:76px;padding:7px 14px;border-radius:999px;font-size:13px;font-weight:700}

.wgmedia{position:relative;height:110px;border-radius:14px;margin-bottom:10px;overflow:hidden}

.wgmedia img{width:100%;height:100%;object-fit:cover;display:block}

.crow{display:flex;align-items:center;gap:10px;margin-bottom:8px}

.wgav{width:38px;height:38px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;color:#fff;flex:none}

.cmeta{flex:1;min-width:0}

.cname{font-size:15px;font-weight:600;color:var(--ink);display:flex;align-items:center;gap:6px}

.cdot{width:7px;height:7px;border-radius:50%;background:var(--good);display:inline-block;box-shadow:0 0 6px var(--good)}

.csub{font-size:11.5px;color:var(--soft)}

.cfrow{display:flex;gap:10px;align-items:baseline;padding:5px 0;border-top:1px solid rgba(255,255,255,.05);font-size:13px}

.cfk{flex:none;width:60px;font-size:10px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;color:var(--soft)}

.cfv{color:var(--dim);min-width:0}

.cfv.mono{font-family:ui-monospace,'SF Mono',monospace;font-size:11px;color:var(--soft)}

.cfrow.cry .cfk,.cfrow.cry .cfv{color:var(--tint-hi)}

.wgpill{display:inline-block;margin-left:8px;padding:2px 8px;border-radius:999px;background:rgba(255,255,255,.08);font-size:10px;font-weight:600;letter-spacing:.03em;color:var(--soft);vertical-align:2px}

.wgpill.ok{background:rgba(48,209,88,.15);color:#5fe08a}

.payv{font-size:30px;font-weight:700;letter-spacing:-.02em;color:var(--ink);font-variant-numeric:tabular-nums;margin:2px 0}

.cryrow{display:flex;align-items:center;gap:8px;padding:7px 0;border-top:1px solid rgba(255,255,255,.05);font-size:13px;color:var(--dim)}

.cryrow>span{flex:1}

.wgo.cry{flex:none;padding:4px 10px;font-size:12px}

.strk{font-size:30px;line-height:1;flex:none}

.plus{width:32px;height:32px;flex:none;border-radius:50%;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.07);color:var(--dim);font-size:17px;line-height:1;padding:0;cursor:pointer;transition:transform .18s var(--spring),background .2s,color .2s}

.plus:active{transform:scale(.9)}

/* THE COMPOSER'S OWN CONTROL, on the surface where the composer is the whole point.
   32x32 clears the AA floor (WCAG 2.2 SC 2.5.8 wants 24) and misses the phone rule
   (SC 2.5.5 and the HIG want 44). Only under 760px: on a desk this is a pointer
   target beside a text field and 32 is the right weight for it. Measured 2026-08-24. */
@media (pointer:coarse){.plus{width:44px;height:44px;font-size:20px}}

.plus.on{background:var(--tint);border-color:transparent;color:#fff;transform:rotate(45deg)}

.uppanel{position:absolute;left:0;right:0;bottom:calc(100% + 10px);border-radius:18px;background:rgba(28,28,34,.9);backdrop-filter:blur(24px) saturate(1.35);-webkit-backdrop-filter:blur(24px) saturate(1.35);border:1px solid rgba(255,255,255,.10);box-shadow:0 18px 50px -18px rgba(0,0,0,.75),inset 0 1px 0 rgba(255,255,255,.07);z-index:12;animation:popin .24s var(--spring) both;overflow:hidden}

.atray{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;padding:12px}

.atile{display:flex;flex-direction:column;align-items:center;gap:6px;padding:9px 4px;border:none;background:transparent;cursor:pointer;border-radius:12px;transition:transform .15s var(--spring),background .2s}

.atile:hover{background:rgba(255,255,255,.05)}

.atile:active{transform:scale(.92)}

.atile .ai2{width:46px;height:46px;display:flex;align-items:center;justify-content:center;font-size:22px;color:#fff;background:rgba(255,255,255,.09);-webkit-mask-image:var(--sqmask);mask-image:var(--sqmask);-webkit-mask-size:100% 100%;mask-size:100% 100%;overflow:hidden}

.atile .an2{font-size:10px;color:var(--soft)}

.cpal{max-height:240px;overflow-y:auto;padding:6px}

.cprow{display:flex;gap:10px;align-items:baseline;width:100%;text-align:left;padding:9px 12px;border:none;background:transparent;border-radius:12px;cursor:pointer;font-size:14px}

.cprow:hover,.cprow.sel{background:rgba(10,132,255,.16)}

.cprow b{color:var(--ink);font-weight:600}

.cprow span{color:var(--soft);font-size:12px}

#hbud{display:flex;gap:8px;justify-content:flex-end;align-items:center}

/* 11px: the last thing on this surface under the scale it declares 46 times. */
.budcap{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:999px;background:rgba(255,255,255,.05);font-size:11px;letter-spacing:.02em;color:var(--soft)}

.budcap b{color:var(--dim);font-weight:590;font-variant-numeric:tabular-nums}

.budbar{width:34px;height:3px;border-radius:2px;background:rgba(255,255,255,.10);overflow:hidden}

.budbar i{display:block;height:100%;background:var(--tint);border-radius:2px}

.budcap.low .budbar i{background:var(--warm)}

.budcap.zero .budbar i{background:#ff453a}

/* Under the floor in every ground at rgba(255,69,58,.8) — 3.34:1 night, 2.52 light —
   and this is the line that says you have run out of words, so it was the least
   readable thing on the page. Opaque #ff453a still only reaches 4.47:1 on the rooms
   card; --bad carries 5.58:1 night and 4.87:1 light, which one colour cannot. */
.budcap.zero{color:var(--bad)}

.appsheet{position:fixed;inset:0;z-index:90;background:rgba(9,9,12,.97);display:flex;flex-direction:column;animation:sheetup .3s var(--spring) both}
@keyframes sheetup{from{opacity:0;transform:translateY(3%)}to{opacity:1;transform:none}}

.apphead{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid rgba(255,255,255,.07)}

.apphead .wgapp{width:30px;height:30px;font-size:17px}

.apphead .an{font-size:15px;font-weight:600;color:var(--ink)}

.apphead .ax{margin-left:auto;width:32px;height:32px;border-radius:50%;border:none;background:rgba(255,255,255,.09);color:var(--ink);font-size:14px;cursor:pointer}

.appbody{flex:1;overflow:auto;display:flex;align-items:center;justify-content:center;padding:20px}

.tq{max-width:340px;width:100%;text-align:center}

.tglyph{font-size:64px;margin:10px 0 18px}

.topt{display:grid;grid-template-columns:1fr 1fr;gap:10px}

.topt button{border:none;border-radius:14px;padding:14px;font-size:15px;font-weight:600;background:#1c1c1e;color:var(--ink);cursor:pointer;transition:transform .15s var(--spring)}

.topt button:active{transform:scale(.96)}

.topt button.ok{background:#30d158;color:#04150b}

.topt button.no{background:#ff453a;color:#fff}

.tscore{margin-top:16px;font-size:13px;color:var(--soft)}

.wdgrid{display:grid;grid-template-rows:repeat(6,1fr);gap:6px;margin-bottom:18px}

.wdrow{display:grid;grid-template-columns:repeat(5,1fr);gap:6px}

.wdt{width:52px;height:52px;border-radius:8px;background:#1c1c1e;border:1px solid rgba(255,255,255,.10);display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:700;color:var(--ink)}

.wdt.g{background:#30d158;border-color:transparent;color:#04150b}

.wdt.y{background:#ffd60a;border-color:transparent;color:#211a00}

.wdt.x{background:#3a3a3c;border-color:transparent}

.wdkb{display:flex;flex-direction:column;gap:6px;align-items:center}

.wdkr{display:flex;gap:5px}

.wdk{min-width:30px;padding:10px 8px;border:none;border-radius:8px;background:#2c2c2e;color:var(--ink);font-size:13px;font-weight:600;cursor:pointer;transition:transform .12s var(--spring)}

.wdk:active{transform:scale(.9)}

.wdk.g{background:#30d158;color:#04150b}

.wdk.y{background:#ffd60a;color:#211a00}

.wdk.x{background:#1a1a1c;color:rgba(249,249,249,.35)}

.wdk.wide{padding:10px 12px}

.hfullbtn{position:absolute;top:10px;right:10px;z-index:8;width:30px;height:30px;border-radius:10px;border:1px solid rgba(255,255,255,.12);background:rgba(30,30,36,.7);color:var(--soft);font-size:14px;cursor:pointer;transition:transform .15s var(--spring),color .2s}

.hfullbtn:hover{color:var(--ink)}
.hfullbtn:active{transform:scale(.92)}

.ask{position:relative;display:flex;gap:9px;margin-top:10px;align-items:center}

/* THE COMPOSER IS THE LAST THING ABOVE THE HOME INDICATOR. On a host that asked for
   viewport-fit=cover the panel runs to the physical bottom of the screen, and this is
   what ends up under the bar the reader swipes to leave the app. --sab is offered by
   the host and is 0px when it is not, so the studio and the door are untouched. */
@media (max-width:760px){.ask{padding-bottom:var(--sab,0px)}}

.ask .field{position:relative;flex:1;display:flex}

.ask input{flex:1;font-size:16px;color:var(--ink);background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.10);border-radius:999px;padding:10px 46px 10px 16px;outline:none;transition:border-color .2s,box-shadow .2s}

/* EVERY placeholder in the package, one rule. A placeholder is the only instruction
   inside its field, so it is text and owes 4.5:1. --soft is specified against the
   CARD (its comment says 7.94:1 there) and these fields sit on lighter washes, where
   it measured 4.15:1 light / 3.35:1 default; the rail's fields named no placeholder
   at all and inherited the browser's, at 3.93:1. Narrow selectors missed .shsealbox
   twice, so the scope is the package: --dim, everywhere, in both grounds. */
.here-chat input::placeholder,.here-chat textarea::placeholder,
.ask input::placeholder,.ask textarea::placeholder{color:var(--dim)}

.ask input:focus{border-color:rgba(10,132,255,.55);box-shadow:0 0 0 3px rgba(10,132,255,.16)}

.ask input:disabled{opacity:.5}

.ask .field>button{position:absolute;right:5px;top:50%;width:32px;height:32px;flex:none;font-size:16px;font-weight:700;line-height:1;padding:0;border-radius:50%;border:none;background:linear-gradient(115deg,rgba(255,255,255,0) 30%,rgba(255,255,255,.5) 43%,rgba(255,255,255,.12) 50%,rgba(255,255,255,0) 62%),linear-gradient(180deg,#fdfdfe,#dfdfe6 42%,#c9c9d2 58%,#efeff3);color:#0a0a0a;cursor:pointer;box-shadow:inset 0 1px 0 rgba(255,255,255,.95),inset 0 -1px 0 rgba(0,0,0,.22),0 2px 8px -2px rgba(0,0,0,.4);opacity:0;pointer-events:none;transform:translateY(-50%) scale(.6);transition:transform .22s var(--spring),opacity .18s}

.ask .field>button.ready{opacity:1;pointer-events:auto;transform:translateY(-50%) scale(1)}

.ask .field>button.ready:active{transform:translateY(-50%) scale(.88)}

.ask button:disabled{opacity:0;pointer-events:none}

#hbud{font-size:12px;color:var(--soft);margin-top:8px}

#state{margin-top:14px;font-size:11px;color:var(--soft);white-space:pre-line}

.hint{margin-top:12px;font-size:11px;color:var(--soft)}


/* WHAT EMPHASIS LOOKS LIKE HERE. Borrowed weight and a rule, never a second colour:
   a bubble already carries meaning in its background and a coloured `code` would
   compete with the one thing the tint is for. */
.bub code{font:0.92em/1.45 ui-monospace,SFMono-Regular,Menlo,monospace;background:rgba(127,127,127,.16);border-radius:5px;padding:.08em .32em}

.bub pre{margin:.35em 0;padding:.5em .6em;background:rgba(127,127,127,.14);border-radius:9px;overflow-x:auto}

.bub pre code{background:none;padding:0}

.bub .mdq{display:block;padding-left:.62em;border-left:2px solid rgba(127,127,127,.45);opacity:.82}

.bub .spoil{background:currentColor;border-radius:4px;cursor:pointer;transition:color .12s}

.bub .spoil.shown{background:rgba(127,127,127,.16)}

.bub .spoil:not(.shown){color:inherit}

.bub .spoil:not(.shown) *{visibility:hidden}

/* ── THE SHELF ────────────────────────────────────────────────────────────────
   State beside the thread. At desk width the panel becomes two columns and the
   shelf takes the second; below 1024px it sits between the pins and the
   transcript, in document order, because a phone has no second column.

   .lsurface is put back across BOTH columns explicitly. It is position:absolute
   with inset:0, and an absolutely positioned child of a grid container is laid
   out against its GRID AREA when it has one -- so the blanket rule below would
   have quietly shrunk the launcher's full-panel app frame to the thread column.
   ──────────────────────────────────────────────────────────────────────────── */
.shelf{display:flex;flex-direction:column;gap:10px;min-width:0;margin:6px 0 2px}

.shelf[hidden]{display:none}

.shhead{display:flex;align-items:center;gap:7px;font:600 10px/1 system-ui;
  letter-spacing:.14em;text-transform:uppercase;color:var(--faint)}

.shhead .shn{margin-right:auto}

.stile{position:relative;border-radius:16px;border:1px solid rgba(255,255,255,.09);
  background:rgba(255,255,255,.035);padding:10px 11px 11px}

.stile .sthead{display:flex;align-items:center;gap:8px;margin-bottom:8px}

.stile .stn{font:600 12px/1 system-ui;color:var(--dim)}

.stile .stage{margin-left:auto;font:500 10px/1 ui-monospace,Menlo,monospace;color:var(--faint)}

.stile .stx,.stile .stmv{width:22px;height:22px;border-radius:50%;
  border:1px solid rgba(255,255,255,.14);background:none;color:var(--faint);
  font:400 12px/1 system-ui;cursor:pointer;flex:none}

.stile .stx:hover,.stile .stx:focus-visible,
.stile .stmv:not(:disabled):hover,.stile .stmv:not(:disabled):focus-visible{
  color:var(--ink);border-color:var(--tint)}

/* An end-of-row tile has nowhere to move to. Dimmed and disabled rather than removed, so
   the header does not reflow every time a tile changes place. */
.stile .stmv:disabled{opacity:.25;cursor:default}

/* The move controls are for an arrangement, and in the rail there is nothing to arrange:
   one column, and order is the only axis, which the rail already shows by stacking. */
.shelf:not([data-mode=spread]) .stmv{display:none}

/* Sits between the label and the mode button, so the button keeps its place on the right
   whether or not anybody is looking. Truncates rather than wrapping: the shelf header is
   one line and a room with nine people in it must not push the tiles down. */
.sheyes{margin-left:auto;font:500 10px/1.4 system-ui;letter-spacing:.02em;
  color:var(--tint-hi);max-width:60%;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;text-transform:none}

.sheyes[hidden]{display:none}

.shmode{margin-left:8px;width:22px;height:22px;border-radius:6px;
  border:1px solid rgba(255,255,255,.14);background:none;color:var(--faint);
  font:400 12px/1 system-ui;cursor:pointer;flex:none}

.shmode:hover,.shmode:focus-visible{color:var(--ink);border-color:var(--tint)}

.stile .wg{margin:0}

/* A tile whose source stopped answering keeps its last reading and says so by
   going quiet, rather than blanking or -- worse -- holding a stale number at
   full confidence. */
.stile.stale{opacity:.5}
@media (max-width:1023px){
  /* One column, shared with the transcript: the shelf takes at most a third of the
     viewport and scrolls inside itself, so the conversation never leaves the screen. */
  .shelf{max-height:34vh;overflow-y:auto;-webkit-overflow-scrolling:touch;
    padding-right:2px;scrollbar-width:thin}}
@media (min-width:1024px){
  /* A GUTTER, NOT A GRID. The first version made .panel a grid and it never took:
     here-rail.css says `.here-chat.railed > .panel {display:flex}
` -- (0,3,0), in a
     stylesheet that loads AFTER this one -- so `display:grid` at (0,2,0) lost, the
     grid-column values were assigned and inert, and every child stacked in one column
     while `grid-template-columns` computed exactly as authored. A layout that is half
     applied reads, from the outside, as a layout that was never written.

     So the shelf stops asking the panel to be anything. It takes a gutter: padding on
     the right, and the shelf absolutely positioned into it. The panel is already
     position:relative for .lsurface, and this holds whether the panel is flex, block or
     grid -- which is the point of doing it this way rather than winning the argument.

     The selector list climbs to (0,4,0) only where it has to. .lsurface keeps inset:0
     and so still covers the gutter too: an app frame should hide the shelf behind it. */
  .panel.hasshelf,
  .here-chat .panel.hasshelf,
  .here-chat.railed>.panel.hasshelf{padding-right:332px}

  .panel.hasshelf>.shelf,
  .here-chat.railed>.panel.hasshelf>.shelf{position:absolute;top:18px;right:16px;
    width:300px;margin:0;max-height:calc(100% - 36px);overflow-y:auto;scrollbar-width:thin}}


/* ── SPREAD ───────────────────────────────────────────────────────────────────
   The rail is ambient: a readout you glance at while the conversation runs. Spread is
   the other thing LNK asked for -- everything you have open, at once, arranged. It takes
   the panel the way .lsurface does, because "manage what is running" is a place you go
   and come back from, not a strip you squint at. The thread is not destroyed, only
   covered; leaving spread puts it back exactly as it was.

   --shcols is set from the panel width in JS and --shspan per tile, both already clamped,
   so this file never has to guess how many columns exist. Below 720px shelfCols() returns
   1 and every span collapses with it -- the media query would be a second opinion on a
   question already answered.
   ──────────────────────────────────────────────────────────────────────────── */
/* THE SELECTOR LIST IS THE POINT, NOT DECORATION. Spread has to REPLACE the rail rule
   above, which is `.here-chat.railed>.panel.hasshelf>.shelf` at (0,4,0). Written plainly
   as `.shelf[data-mode=spread]` -- (0,2,0) -- it lost: data-mode flipped, --shcols was
   set, the grid computed, and the shelf stayed a 300px column with two 128px tracks in
   it. That is the second time in one afternoon that a layout applied HALF and read from
   outside as a layout nobody wrote, so the rule now climbs past every rail selector it
   has to beat, in the same order they were written. */
.panel.hasshelf.shelfspread,
.here-chat .panel.hasshelf.shelfspread,
.here-chat.railed>.panel.hasshelf.shelfspread{padding-right:16px}

.panel.hasshelf>.shelf[data-mode=spread],
.here-chat.railed>.panel.hasshelf>.shelf[data-mode=spread]{
  position:absolute;inset:0;z-index:9;margin:0;padding:14px 16px 16px;
  width:auto;max-height:none;overflow-y:auto;
  border-radius:22px;
  /* OPAQUE, AND SAID SO. At .97 the transcript stayed legible through the spread, which
     made it read as a scrim over the room rather than a place you went to. Spread is a
     mode with a way back, not a translucent hover -- the blur keeps the room's own light
     under it without offering it as something to read. */
  background:#131317;
  backdrop-filter:blur(18px) saturate(1.2);-webkit-backdrop-filter:blur(18px) saturate(1.2);
  display:grid;grid-template-columns:repeat(var(--shcols,1),minmax(0,1fr));
  grid-auto-rows:min-content;gap:12px;align-content:start}

.shelf[data-mode=spread]>.shhead{grid-column:1/-1;padding-bottom:2px}

.shelf[data-mode=spread]>.stile{grid-column:span var(--shspan,1);margin:0}

.shelf[data-mode=spread]>.stile.tall{grid-row:span 2}

/* ── SOMEBODY ELSE, IN THIS TILE ──────────────────────────────────────────────
   The dot is parented to the tile and placed by percentage, so it lands on the same part
   of the same readout whatever glass it is drawn on. pointer-events:none throughout: a
   thing that shows you where somebody is must never stop you clicking through it.
   ──────────────────────────────────────────────────────────────────────────── */
.stile{overflow:hidden}

.pcur{position:absolute;z-index:6;pointer-events:none;transform:translate(-2px,-2px);
  transition:left .09s linear,top .09s linear}
@media (prefers-reduced-motion:reduce){.pcur{transition:none}}

.pcur i{display:block;width:9px;height:9px;border-radius:50% 50% 50% 2px;
  background:var(--tint-hi);box-shadow:0 1px 4px rgba(0,0,0,.55)}

.pcur b{position:absolute;left:11px;top:8px;white-space:nowrap;
  font:600 9px/1.5 system-ui;letter-spacing:.02em;color:#0b0b0f;
  background:var(--tint-hi);border-radius:4px;padding:1px 4px}

/* How many other people have this same readout standing on their own shelf. */
.stshare{margin-left:6px;font:600 9px/1 ui-monospace,Menlo,monospace;color:var(--tint-hi);
  border:1px solid var(--tint-hi);border-radius:4px;padding:2px 4px;opacity:.8}

/* ── THE SEALED HANDOVER'S ONE CONTROL ────────────────────────────────────────
   `.hoo` is emitted into `.wgch` and had no rule in any stylesheet — a browser-default
   button in the middle of a styled card, on both lineages, live.

   Shape and colour are `.wgo`'s, because this is a control in the same container on the
   same dark card, and `.wgo`'s comment two screens up records the measurement behind that
   colour: --tint-hi and not --ember, which came out at 3.11:1 there. Inheriting a measured
   answer, not copying a preference.

   :disabled IS THE OPPOSITE OF UNAVAILABLE HERE, and it is the reason this needed writing
   rather than a one-line borrow. hoReveal disables the button to say "touch your key" —
   the single moment the person must act, on hardware, now. The browser default greys it
   out and drops the cursor, which reads as "this has stopped working" at precisely the
   instant it is asking for a hand. So the waiting state KEEPS its colour, gains a little
   weight, and breathes on the room's own blink idiom; only the cursor says you cannot
   press it again.

   The other two states are text swaps on an ENABLED button — "this browser cannot open it"
   and "it would not open" — and both are right in the resting style, because both are
   things a person may act on again. Nothing here greys them.
   ──────────────────────────────────────────────────────────────────────────── */
.hoo{border:1px solid rgba(10,132,255,.4);background:rgba(10,132,255,.10);color:var(--tint-hi);
  border-radius:999px;padding:6px 12px;font:600 13px/1.2 system-ui;cursor:pointer;
  transition:background .16s var(--smooth),border-color .16s var(--smooth)}

.hoo:hover:not(:disabled),.hoo:focus-visible{background:rgba(10,132,255,.18);
  border-color:rgba(10,132,255,.7)}

.hoo:active:not(:disabled){transform:scale(.94)}

/* Waiting on the key: lit, not dimmed. opacity stays 1 on purpose — a UA sets it to ~.5
   and that is the whole misreading this rule exists to prevent. */
.hoo:disabled{cursor:progress;opacity:1;background:rgba(10,132,255,.2);
  color:var(--tint-hi);animation:hoowait 1.5s ease-in-out infinite}
@keyframes hoowait{0%,100%{border-color:rgba(10,132,255,.35)}50%{border-color:var(--tint-hi)}}
@media (prefers-reduced-motion:reduce){
  .hoo:disabled{animation:none;border-color:var(--tint-hi)}

  .hoo{transition:none}}
