
:root{
  --bg:#17212b; --panel:#1d2733; --in:#182533; --out:#2b5278;
  --text:#e9eef2; --dim:#7d8e9e; --line:#0f171e; --accent:#5eb5f7;
  --warn:#e8a33d; --bad:#e2596c; --gone:#3a1d24;
}
*{box-sizing:border-box}
/* The hidden attribute must always win. A browser hides [hidden] via
   its own [hidden]{display:none} rule, which has the same specificity
   as any class here and loses to it on document order — so .gate's
   display:flex silently kept the loading spinner on screen after the
   data had already arrived. Anything given display: later in this file
   would reintroduce that, hence !important rather than a per-rule fix. */
[hidden]{display:none !important}
html,body{margin:0;height:100%}
body{background:var(--bg);color:var(--text);
  font:15px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}
/* The 404 is styled like a server default, not like this app: white
   page, Times, centred. Anything else would look designed. */
#dead{background:#fff;color:#000;font-family:"Times New Roman",serif;
  position:fixed;inset:0;margin:0;padding-top:0}
#dead h1{font-size:2em;margin:.67em 0;font-weight:bold}
#dead hr{border:0;border-top:1px solid #000;margin:.5em 0}
.gate{position:fixed;inset:0;display:flex;flex-direction:column;gap:14px;
  align-items:center;justify-content:center;color:var(--dim);padding:24px;
  text-align:center}
.gate.bad{color:var(--bad)}
.spin{width:26px;height:26px;border:3px solid #2b3a4a;
  border-top-color:var(--accent);border-radius:50%;animation:s .8s linear infinite}
.gate.bad .spin{display:none}
@keyframes s{to{transform:rotate(360deg)}}
header{position:sticky;top:0;z-index:5;display:flex;gap:10px;align-items:center;
  background:var(--bg);border-bottom:1px solid var(--line);padding:14px 16px}
#back{background:none;border:none;color:var(--accent);font-size:26px;
  line-height:1;cursor:pointer;padding:0 4px}
#title{font-weight:600}
.sub{color:var(--dim);font-size:12px}
.search{width:calc(100% - 32px);margin:12px 16px 0;padding:9px 12px;
  border-radius:8px;border:1px solid var(--line);background:var(--panel);
  color:var(--text)}
main{padding:12px 16px 40px;max-width:900px;margin:0 auto}
.chat{display:flex;gap:12px;align-items:center;padding:10px 12px;
  border-radius:10px;margin-bottom:6px;background:var(--panel);cursor:pointer}
.chat:active{background:#243447}
.ava{flex:0 0 44px;height:44px;border-radius:50%;display:flex;
  align-items:center;justify-content:center;font-weight:600;color:#fff}
.meta{flex:1;min-width:0}
.nm{font-weight:600;display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.pv{color:var(--dim);font-size:13px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.cnt{color:var(--dim);font-size:11px;text-align:right;white-space:nowrap;
  display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:0 0 auto}
.when{font-size:12px;color:var(--dim)}
/* Telegram's unread pill. Ours counts messages held, and turns red
   when the chat contains something Telegram no longer has — the one
   number in this app worth drawing the eye to. */
.pill{min-width:20px;padding:1px 7px;border-radius:11px;background:#2b3a4a;
  color:var(--dim);font-size:11px;font-weight:600;text-align:center}
.pill.rec{background:var(--bad);color:#fff}
/* The sender prefix in the list preview, as Telegram renders it. */
.pvfrom{color:#8aa4bd}
.pv{display:flex;gap:0}
.gonetag{font-size:10px;font-weight:700;letter-spacing:.03em;
  color:var(--bad);margin-bottom:4px}
.tag{font-size:10px;padding:1px 7px;border-radius:20px;background:#2b3a4a;
  color:var(--dim);font-weight:600}
.tag.svc{background:#3a2f16;color:var(--warn)}
.tag.priv{background:#16303a;color:var(--accent)}
.tag.rec{background:#3a1d24;color:var(--bad)}
.day{text-align:center;margin:20px 0 12px}
.day span{background:var(--panel);color:var(--dim);font-size:12px;
  padding:4px 12px;border-radius:20px}
.msg{max-width:80%;margin:0 0 8px;padding:8px 12px;border-radius:12px;
  background:var(--in);word-wrap:break-word;overflow-wrap:anywhere}
.msg.out{margin-left:auto;background:var(--out)}
.msg.svc{background:#2a2214;border:1px solid #4a3a1a;max-width:100%}
.msg.gone{background:var(--gone);border:1px solid #6b2b38}
.who{font-size:11px;color:var(--accent);font-weight:600;margin-bottom:3px;
  display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.wa{width:20px;height:20px;border-radius:50%;object-fit:cover;flex:0 0 20px}
.uname{color:var(--dim);font-weight:400}
.sflag{font-size:9px;font-weight:700;padding:1px 5px;border-radius:4px;
  background:#2b3a4a;color:var(--dim);letter-spacing:.04em}
.sflag.scam,.sflag.fake{background:var(--bad);color:#fff}
.sflag.restricted{background:var(--warn);color:#241a06}
.msg.svc .who{color:var(--warn)}
.msg.gone .who{color:var(--bad)}
.body{white-space:pre-wrap}
.time{font-size:10px;color:var(--dim);margin-top:4px;text-align:right;
  opacity:.75}
.msg.out .time{color:#b6d4f0}
.msg img{max-width:100%;border-radius:8px;margin-top:6px;display:block}
.file{display:inline-block;margin-top:6px;padding:5px 10px;border-radius:8px;
  background:rgba(0,0,0,.28);font-size:13px}
.gonebar{font-size:11px;color:var(--bad);font-weight:600;margin-top:6px;
  padding-top:5px;border-top:1px dashed #6b2b38}
.evt{text-align:center;color:var(--dim);font-size:12px;margin:10px 0}
.banner{background:#22303c;border:1px solid #2f4152;border-radius:10px;
  padding:10px 12px;margin-bottom:14px;font-size:13px;color:var(--dim)}
.banner b{color:var(--bad)}
.empty{color:var(--dim);text-align:center;padding:40px 0}
#keybox{max-width:340px;width:100%}
#keybox .search{width:100%;margin:0 0 10px;text-align:center}
.btn{width:100%;padding:10px;border-radius:8px;border:none;cursor:pointer;
  background:var(--accent);color:#06121c;font-weight:600;font-size:15px}
.btn:active{opacity:.8}
.hint{color:var(--dim);font-size:12px;margin-top:12px;line-height:1.5}
.hint code{background:var(--panel);padding:1px 5px;border-radius:4px}
