/**
 * @author  Md. Touhiduzzaman Turja
 * @version V1.0.0, 28/7/2026
 * @since   V1.0.0
 */
/* ilzora UI
   mig33's palette and layout language: orange identity, cyan/teal navigation,
   flat high-contrast list rows on tinted paper. Light is the primary theme. */

:root {
  --orange:    #f07818;
  --orange-lt: #ff9433;
  --orange-dk: #d8620a;
  --teal:      #26a9ce;
  --teal-dk:   #1a8cad;
  --teal-soft: #e3f4fa;
  --r-s: 8px; --r-m: 12px; --r-l: 16px; --r-xl: 22px;
  --ease: cubic-bezier(.22,.8,.3,1);
  --tabs: 60px;
  --side: 320px;
  --roster: 226px;
}

/* No pure white anywhere. Surfaces carry mig33's pale cyan cast so the orange and
   teal accents sit on tinted paper rather than on #fff. */
:root {
  --bg:        #d9e9f0;
  --panel:     #f2f9fc;
  --panel-2:   #e6f1f7;
  --line:      #c6dde8;
  --line-soft: #d9eaf2;
  --txt:       #1e3742;
  --txt-dim:   #4d6976;
  --txt-mute:  #7b939f;
  --ink:       #16323d;
  --on-orange: #fffaf4;
  --ok:        #34a03f;
  --warn:      #e0980f;
  --bad:       #d3372f;
  --sect-bg:   #cbe8f3;
  --sect-txt:  #0f6480;
  --shadow:    0 10px 30px -14px #14384a4d;
  --shadow-sm: 0 2px 8px -3px #14384a33;
  color-scheme: light;
}

html[data-theme="dark"] {
  --bg:        #101a1f;
  --panel:     #182429;
  --panel-2:   #1f2d34;
  --line:      #2e424b;
  --line-soft: #23343b;
  --txt:       #e2edf2;
  --txt-dim:   #9db2bd;
  --txt-mute:  #71888f;
  --ink:       #0d171b;
  --on-orange: #fffaf4;
  --sect-bg:   #143038;
  --sect-txt:  #6cc9e4;
  --shadow:    0 12px 32px -14px #000c;
  --shadow-sm: 0 2px 8px -3px #0009;
  color-scheme: dark;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
/* A flex item defaults to min-height:auto and so refuses to shrink below its
   content. Every scrolling pane below therefore states min-height:0 explicitly -
   without it a long transcript grows past its container and pushes the composer
   off the screen. --vh tracks the visual viewport so the on-screen keyboard
   shrinks the layout instead of covering it. */
/* CSS owns the normal height. Script may only *shrink* it, by setting --vh
   inline while an on-screen keyboard is up, and must remove that again when the
   keyboard closes - so a stale scripted value can never outlive the condition
   that justified it. */
:root { --vh: 100vh; }
@supports (height: 100dvh) { :root { --vh: 100dvh; } }

html, body { height: var(--vh); overflow: hidden; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--txt);
  font: 15px/1.5 ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
  overscroll-behavior: none;
}
button, input, textarea, select { font: inherit; color: inherit; }
input, textarea, select { -webkit-appearance: none; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--line); border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: var(--txt-mute); }
::-webkit-scrollbar-track { background: transparent; }

.ic { width: 22px; height: 22px; flex: none; overflow: visible; }
.ic.sm { width: 16px; height: 16px; }
.ic.mini { width: 14px; height: 14px; }

/* ---------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 16px; border: 1px solid var(--line); border-radius: var(--r-m);
  background: var(--panel); cursor: pointer; font-weight: 600;
  transition: transform .12s var(--ease), filter .15s, background .15s, border-color .15s;
}
.btn:hover { filter: brightness(.98); }
.btn:active { transform: scale(.98); }
.btn.primary {
  background: var(--orange); border-color: var(--orange); color: var(--on-orange);
  box-shadow: 0 6px 16px -8px var(--orange);
}
.btn.primary:hover { background: var(--orange-dk); }
.btn.ghost { background: transparent; color: var(--txt-dim); }
.btn.ghost:hover { color: var(--bad); border-color: var(--bad); }
.btn.wide { width: 100%; }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn + .btn { margin-top: 9px; }

.icon-btn {
  display: grid; place-items: center; width: 38px; height: 38px; flex: none;
  border: 0; border-radius: 10px; background: transparent; color: var(--txt-dim);
  cursor: pointer; transition: background .15s, color .15s, transform .12s var(--ease);
}
.icon-btn:hover { background: var(--panel-2); color: var(--txt); }
.icon-btn:active { transform: scale(.9); }
.icon-btn.sm { width: 30px; height: 30px; }
.icon-btn.sm .ic { width: 18px; height: 18px; }
.icon-btn.send { background: var(--orange); color: var(--on-orange); }
.icon-btn.send:hover { background: var(--orange-dk); color: var(--on-orange); }
.icon-btn.call-btn:hover { background: #26a9ce1f; color: var(--teal-dk); }

.pill {
  font-size: 11.5px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
  background: var(--teal-soft); color: var(--sect-txt); flex: none;
}

/* ---------------------------------------------------------- fields */
.field { display: block; margin-bottom: 12px; }
.field > span {
  display: block; font-size: 11.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--txt-mute); margin-bottom: 5px;
}
.field input, .field select {
  width: 100%; padding: 11px 13px; border-radius: var(--r-m);
  border: 1px solid var(--line); background: var(--panel); outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.field input:focus, .field select:focus {
  border-color: var(--teal); box-shadow: 0 0 0 3px #26a9ce2e;
}

/* ---------------------------------------------------------- sign in */
.gate { height: var(--vh); display: grid; place-items: center; padding: 20px; overflow-y: auto;
  background: linear-gradient(160deg, var(--teal-soft), var(--bg) 55%); }
html[data-theme="dark"] .gate { background: linear-gradient(160deg, #16333d, var(--bg) 55%); }
.gate-card {
  width: min(392px, 100%); padding: 26px; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r-xl); box-shadow: var(--shadow);
  animation: rise .4s var(--ease) both;
}
@keyframes rise { from { opacity: 0; transform: translateY(14px); } }
.brand { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.brand-mark svg, .brand-mark img { width: 46px; height: 46px; display: block; }
.brand h1 { margin: 0; font-size: 25px; letter-spacing: -.02em; color: var(--orange); }
.brand p { margin: 1px 0 0; font-size: 12.5px; color: var(--txt-mute); }

.seg {
  display: grid; grid-template-columns: 1fr 1fr; gap: 3px; padding: 3px;
  background: var(--panel-2); border-radius: var(--r-m); margin-bottom: 16px;
  border: 1px solid var(--line-soft);
}
.seg button {
  padding: 9px; border: 0; border-radius: 9px; background: transparent;
  color: var(--txt-dim); font-weight: 600; cursor: pointer; transition: .16s var(--ease);
}
.seg button.on { background: var(--panel); color: var(--orange); box-shadow: var(--shadow-sm); }

.gate-err {
  margin: 0 0 12px; padding: 10px 12px; border-radius: var(--r-s);
  background: #d93a341a; color: var(--bad); font-size: 13.5px; border: 1px solid #d93a3440;
}
.gate-foot {
  margin: 15px 0 0; display: flex; align-items: center; justify-content: center; gap: 6px;
  font-size: 12px; color: var(--txt-mute);
}

/* ---------------------------------------------------------- shell */
.app { height: var(--vh); min-height: 0; display: grid; grid-template-columns: var(--side) 1fr; overflow: hidden; }
.side {
  display: flex; flex-direction: column; min-height: 0; min-width: 0; overflow: hidden;
  background: var(--panel); border-right: 1px solid var(--line);
}

/* profile banner, mig33's orange identity block */
.banner {
  display: flex; align-items: center; gap: 11px; padding: 11px 13px;
  background: linear-gradient(120deg, var(--orange-lt), var(--orange) 65%, var(--orange-dk));
  color: var(--on-orange); flex: none;
}
.banner-av { border: 0; background: none; padding: 0; cursor: pointer; flex: none; }
.banner-id { flex: 1; min-width: 0; }
.banner-id strong {
  display: block; font-size: 16px; font-weight: 700; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.banner-id span {
  display: block; font-size: 12.5px; color: #fffaf4d1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.quota-chip {
  display: flex; align-items: center; gap: 5px; flex: none; cursor: pointer;
  padding: 5px 10px; border-radius: 999px; border: 1px solid #fffaf45c;
  background: #fffaf42b; color: var(--on-orange); font-size: 12px; font-weight: 700;
}
.quota-chip:hover { background: #fffaf43d; }

/* tab strip, teal like mig33's tab bar */
/* five tabs now, so the columns are derived rather than counted: with a fixed
   four the fifth wrapped onto a second row */
.tabs {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  background: var(--teal); flex: none;
}
.tab {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 7px 2px 6px; border: 0; background: transparent; color: #fffaf4c9;
  cursor: pointer; transition: background .16s, color .16s;
}
.tab em {
  font-style: normal; font-size: 10.5px; font-weight: 700; letter-spacing: .01em;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 420px) { .tab em { font-size: 9.5px; } }
.tab:hover { background: #fffaf424; color: var(--on-orange); }
.tab.on { background: var(--panel); color: var(--orange); }
.tab .badge {
  position: absolute; top: 3px; right: calc(50% - 20px); min-width: 16px; height: 16px;
  padding: 0 4px; border-radius: 8px; background: var(--bad); color: var(--on-orange);
  font-size: 10px; font-weight: 800; line-height: 16px; text-align: center;
}

.pane { display: none; flex-direction: column; min-height: 0; flex: 1 1 0; overflow: hidden; }
.pane.on { display: flex; }

.searchbar {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  border-bottom: 1px solid var(--line-soft); color: var(--txt-mute); flex: none;
}
.searchbar input {
  flex: 1; min-width: 0; border: 1px solid var(--line); border-radius: var(--r-m);
  background: var(--panel-2); padding: 8px 11px; outline: none;
}
.searchbar input:focus { border-color: var(--teal); background: var(--panel); }
.searchbar > .ic { display: none; }

.list { flex: 1 1 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.empty { padding: 26px 22px; color: var(--txt-mute); font-size: 13.5px; text-align: center; line-height: 1.7; }

/* section header, mig33's pale cyan group bar */
.sect {
  display: flex; align-items: center; gap: 7px; padding: 6px 14px;
  background: var(--sect-bg); color: var(--sect-txt);
  font-size: 11.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .07em;
  position: sticky; top: 0; z-index: 2;
}
.sect span { margin-left: auto; font-weight: 700; }

/* flat chunky rows */
.row {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 9px 13px; border: 0; border-bottom: 1px solid var(--line-soft);
  background: var(--panel); text-align: left; cursor: pointer; color: inherit;
  transition: background .13s;
}
.row:hover { background: var(--panel-2); }
.row.on { background: #f0781814; box-shadow: inset 3px 0 0 var(--orange); }
html[data-theme="dark"] .row.on { background: #f078181f; }
.row-body { flex: 1; min-width: 0; }
.row-top { display: flex; align-items: center; gap: 6px; }
.row-name { font-weight: 650; font-size: 14.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row-sub { font-size: 12.5px; color: var(--txt-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row .ic.mini { color: var(--warn); }
.row-count {
  font-size: 11.5px; font-weight: 700; color: var(--txt-mute);
  background: var(--panel-2); border: 1px solid var(--line-soft);
  border-radius: 999px; padding: 1px 8px; flex: none;
}
.row-count.live { color: var(--on-orange); background: var(--ok); border-color: var(--ok); }
.row-count.unread { color: var(--on-orange); background: var(--bad); border-color: var(--bad); }

.rtile {
  width: 38px; height: 38px; flex: none; border-radius: 9px;
  display: grid; place-items: center; font-weight: 800; font-size: 15px;
  color: var(--on-orange); letter-spacing: -.02em;
}

/* avatars */
.av { position: relative; width: 38px; height: 38px; flex: none; }
.av img, .av .gen { width: 100%; height: 100%; border-radius: 50%; display: block; object-fit: cover; }
.av .gen { display: grid; place-items: center; font-weight: 800; color: var(--on-orange); font-size: 15px; }
.av .dot {
  position: absolute; right: -1px; bottom: -1px; width: 12px; height: 12px;
  border-radius: 50%; border: 2.5px solid var(--panel); background: var(--txt-mute);
}
.av .dot.online { background: var(--ok); }
.av .dot.away   { background: var(--warn); }
.av .dot.busy   { background: var(--bad); }
.banner .av .dot { border-color: var(--orange); }
.av.sm { width: 30px; height: 30px; }
.av.sm .gen { font-size: 12px; }
.av.md { width: 44px; height: 44px; }
.av.md .gen { font-size: 18px; }
.av.lg { width: 84px; height: 84px; }
.av.lg .gen { font-size: 33px; }
.av.xl { width: 104px; height: 104px; }
.av.xl .gen { font-size: 40px; }

/* ---------------------------------------------------------- stage */
.stage {
  position: relative; display: grid; grid-template-columns: 1fr auto;
  min-width: 0; min-height: 0; overflow: hidden; background: var(--bg);
}

.welcome {
  grid-column: 1 / -1; display: grid; place-content: center; justify-items: center;
  text-align: center; padding: 30px; gap: 3px;
}
.welcome-art svg { width: 196px; height: 130px; margin-bottom: 8px; }
.welcome-art .w1 { fill: none; stroke: var(--orange); stroke-width: 3; opacity: .8; }
.welcome-art .w2 { fill: none; stroke: var(--teal); stroke-width: 3; opacity: .75; }
.welcome-art .wd { fill: var(--orange); }
.welcome-art .wd2 { fill: var(--teal); }
.welcome h2 { margin: 6px 0 0; font-size: 21px; }
.welcome p { margin: 0; color: var(--txt-mute); max-width: 36ch; }

.chat {
  display: flex; flex-direction: column; min-width: 0; min-height: 0;
  height: 100%; overflow: hidden; background: var(--panel);
}
.chat-head {
  display: flex; align-items: center; gap: 6px; padding: 9px 11px;
  border-bottom: 1px solid var(--line); background: var(--panel); flex: none;
}
.chat-title { flex: 1; min-width: 0; }
.chat-title h2 {
  margin: 0; font-size: 16.5px; display: flex; align-items: center; gap: 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-title p { margin: 0; font-size: 12.5px; color: var(--txt-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.log {
  flex: 1 1 0; min-height: 0; overflow-y: auto; padding: 14px 16px 6px;
  display: flex; flex-direction: column; gap: 2px;
  scroll-behavior: smooth; overscroll-behavior: contain; background: var(--bg);
}

/* Own messages on the right, everyone else's on the left, each in a bubble
   that grows to its content and stops well short of the far edge so the two
   sides never meet in the middle. */
.msg { display: flex; gap: 8px; padding: 2px 0; align-items: flex-end; }
.msg.them { justify-content: flex-start; }
.msg.mine { justify-content: flex-end; }
.msg.cont .av { visibility: hidden; height: 0; }

.bubble {
  position: relative;
  max-width: min(76%, 560px);
  min-width: 0;
  padding: 7px 11px 5px;
  border-radius: 14px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-sm);
}
.msg.them .bubble { border-bottom-left-radius: 5px; }
.msg.mine .bubble {
  border-bottom-right-radius: 5px;
  background: var(--teal-soft);
  border-color: #b9dfec;
}
html[data-theme="dark"] .msg.mine .bubble { background: #21505f; border-color: #2f6a7c; }
/* a run from one speaker keeps square inner corners, as one block of talk */
.msg.cont.them .bubble { border-top-left-radius: 5px; }
.msg.cont.mine .bubble { border-top-right-radius: 5px; }

.msg-who {
  display: block; font-weight: 700; font-size: 12.5px; margin-bottom: 2px;
  cursor: pointer; color: var(--teal-dk);
}
html[data-theme="dark"] .msg-who { color: #6fcbe6; }
.msg-who:hover { text-decoration: underline; }
.msg-text { font-size: 14.5px; line-height: 1.5; overflow-wrap: anywhere; white-space: pre-wrap; }
.msg-text a { color: var(--teal-dk); }

/* time, delivery state and the way in to the details, under the message */
.msg-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 5px;
  margin-top: 2px; line-height: 1;
}
.msg-when { font-size: 10.5px; color: var(--txt-mute); }
.msg-info {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--txt-mute); opacity: .75;
}
.msg-info:hover { opacity: 1; color: var(--teal-dk); }
.msg-info .ic { width: 13px; height: 13px; }

.msg.sys { justify-content: center; padding: 6px 0; }
.msg.sys .msg-text {
  font-size: 12px; color: var(--txt-mute); background: var(--panel);
  padding: 3px 12px; border-radius: 999px; border: 1px solid var(--line-soft);
}
.msg.emote .msg-text { color: var(--orange-dk); font-style: italic; }
html[data-theme="dark"] .msg.emote .msg-text { color: var(--orange-lt); }

.att {
  display: inline-flex; align-items: center; gap: 10px; margin-top: 4px;
  padding: 9px 12px; border-radius: var(--r-m); text-decoration: none;
  background: var(--panel); border: 1px solid var(--line); color: inherit;
  max-width: 330px; transition: border-color .15s;
}
.att:hover { border-color: var(--teal); }
.att-name { font-weight: 600; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-size { font-size: 11.5px; color: var(--txt-mute); }
.att .ic { color: var(--teal); }
.att.gone { border-style: dashed; opacity: .7; }
.att.gone .ic { color: var(--txt-mute); }
.shot {
  display: block; margin-top: 5px; max-width: min(320px, 74%); border-radius: var(--r-m);
  border: 1px solid var(--line); cursor: zoom-in;
}

.typing { height: 17px; padding: 0 18px 2px; font-size: 12px; color: var(--txt-mute); font-style: italic; flex: none; }

.composer {
  display: flex; align-items: flex-end; gap: 5px;
  padding: 9px 11px calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line); background: var(--panel);
  flex: 0 0 auto; z-index: 3;
}
.composer textarea {
  flex: 1; resize: none; max-height: 128px; padding: 9px 13px;
  border-radius: var(--r-l); border: 1px solid var(--line);
  background: var(--panel-2); outline: none; line-height: 1.45;
  transition: border-color .15s, box-shadow .15s;
}
.composer textarea:focus { border-color: var(--teal); background: var(--panel); box-shadow: 0 0 0 3px #26a9ce24; }

.emoji-pop {
  position: absolute; left: 11px; bottom: 68px; z-index: 6;
  width: min(296px, calc(100% - 22px)); padding: 9px;
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-l); box-shadow: var(--shadow);
}
.emoji-pop button { border: 0; background: transparent; font-size: 20px; padding: 5px; border-radius: 8px; cursor: pointer; line-height: 1; }
.emoji-pop button:hover { background: var(--panel-2); }

.roster {
  width: var(--roster); border-left: 1px solid var(--line); background: var(--panel);
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
}

/* ---------------------------------------------------------- account */
.me-wrap { flex: 1 1 0; min-height: 0; padding: 0 0 20px; overflow-y: auto; overscroll-behavior: contain; }
.me-av { position: relative; display: block; width: 84px; margin: 18px auto 8px; cursor: pointer; }
.me-av em {
  position: absolute; inset: auto 0 -2px; text-align: center; font-size: 10px;
  font-style: normal; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  background: #0d1f26bd; color: var(--on-orange); border-radius: 0 0 42px 42px; padding: 3px 0 5px;
  opacity: 0; transition: opacity .16s;
}
.me-av:hover em { opacity: 1; }
.me-id { text-align: center; margin-bottom: 14px; }
.me-id strong { display: block; font-size: 17px; }
.me-id span { font-size: 13px; color: var(--txt-mute); }
.me-fields { padding: 12px 14px 14px; }
.me-fields .field { margin-bottom: 12px; }
.me-fields .field:last-of-type { margin-bottom: 0; }
.quota-box { padding: 12px 14px 14px; }

.save-row { display: grid; grid-template-columns: auto 1fr; gap: 8px; margin-top: 14px; }
.save-row .btn { margin-top: 0; }
.about { margin: 18px 14px 0; }


.quota-bar { height: 8px; border-radius: 999px; background: var(--panel-2); border: 1px solid var(--line-soft); overflow: hidden; }
.quota-bar i { display: block; height: 100%; width: 0; background: var(--teal); transition: width .4s var(--ease), background .3s; }
.quota-bar i.warn { background: var(--warn); }
.quota-bar i.full { background: var(--bad); }
.quota-box p { margin: 7px 0 0; font-size: 12.5px; color: var(--txt-dim); }
.quota-box .quota-note { font-size: 11.5px; color: var(--txt-mute); line-height: 1.5; }

/* ---------------------------------------------------------- modal */
.modal {
  position: fixed; inset: 0; z-index: 40; display: grid; place-items: center;
  padding: 18px; background: #0f172a99; backdrop-filter: blur(4px);
}
.modal-card {
  width: min(392px, 100%); max-height: 88vh; overflow-y: auto; padding: 22px;
  background: var(--panel); border-radius: var(--r-xl); box-shadow: var(--shadow);
  animation: rise .2s var(--ease) both;
}
.modal-card h3 { margin: 0 0 4px; font-size: 18px; }
.modal-card .sub { margin: 0 0 16px; color: var(--txt-mute); font-size: 13.5px; }
.modal-actions { display: flex; gap: 8px; margin-top: 14px; }
.modal-actions .btn { flex: 1; margin-top: 0; }

.profile-head { display: flex; flex-direction: column; align-items: center; gap: 7px; margin-bottom: 14px; }
.profile-head .status { color: var(--txt-dim); font-size: 13.5px; text-align: center; margin: 0; }
.kv { display: flex; justify-content: space-between; padding: 8px 0; border-top: 1px solid var(--line-soft); font-size: 13.5px; }
.kv span { color: var(--txt-mute); }
.call-row { display: flex; gap: 8px; margin-top: 14px; }
.call-row .btn { flex: 1; margin-top: 0; }

.shotview { display: grid; place-items: center; }
.shotview img { max-width: 100%; max-height: 78vh; border-radius: var(--r-m); }

/* ---------------------------------------------------------- notices */
/* Centred and shown one at a time, so a burst reads as a sequence instead of a
   stack sliding down from the corner. */
.toasts {
  position: fixed; inset: 0; z-index: 90; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; padding: 20px;
}
.toast {
  display: flex; align-items: center; gap: 9px;
  padding: 13px 20px; border-radius: var(--r-l);
  font-size: 14px; font-weight: 600; line-height: 1.4;
  background: var(--panel); color: var(--txt);
  border: 1px solid var(--line); box-shadow: var(--shadow);
  max-width: min(420px, 88vw); text-align: left;
  animation: noticeIn .22s var(--ease) both;
}
.toast.out { animation: noticeOut .2s var(--ease) both; }
@keyframes noticeIn  { from { opacity: 0; transform: translateY(10px) scale(.96); } }
@keyframes noticeOut { to   { opacity: 0; transform: translateY(-6px) scale(.98); } }

.toast .ic { flex: none; }
.toast.bad  { border-color: var(--bad); color: var(--bad); }
.toast.good { border-color: var(--ok); color: var(--ok); }
.toast.busy { color: var(--txt-dim); }

.spin {
  width: 15px; height: 15px; flex: none; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--orange);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .spin { animation-duration: 2s; }
}

/* ---------------------------------------------------------- calling */
.ring {
  position: fixed; inset: 0; z-index: 70; display: grid; place-items: center;
  padding: 20px; background: #0f172acc; backdrop-filter: blur(5px);
}
.ring-card {
  width: min(320px, 100%); padding: 26px 22px; text-align: center;
  background: var(--panel); border-radius: var(--r-xl); box-shadow: var(--shadow);
  animation: rise .22s var(--ease) both;
}
.ring-card > div:first-child { display: flex; justify-content: center; margin-bottom: 12px; }
.ring-card strong { display: block; font-size: 19px; }
.ring-card p { margin: 3px 0 0; color: var(--txt-mute); font-size: 13.5px; }
.ring-actions { display: flex; justify-content: center; gap: 40px; margin-top: 24px; }

.round {
  display: grid; place-items: center; width: 56px; height: 56px; flex: none;
  border: 0; border-radius: 50%; cursor: pointer; color: var(--on-orange);
  background: #e8f4f92e; transition: transform .12s var(--ease), background .16s;
}
.round:active { transform: scale(.9); }
.round.accept  { background: var(--ok); animation: pulse 1.6s infinite; }
.round.decline { background: var(--bad); }
.round.off { background: var(--panel); color: var(--txt); }
@keyframes pulse { 0%,100% { box-shadow: 0 0 0 0 #37a74566; } 50% { box-shadow: 0 0 0 13px #37a74500; } }

.call { position: fixed; inset: 0; z-index: 72; background: #0d1013; display: grid; }
.call video { grid-area: 1/1; }
#remoteVid { width: 100%; height: 100%; object-fit: contain; background: #0d1013; }
#localVid {
  position: absolute; right: 14px; top: 14px; width: 116px; height: 87px;
  object-fit: contain; border-radius: var(--r-m); background: #1c2024;
  border: 2px solid #fffaf43d; z-index: 3;
}
#localVid.hide { display: none; }
.call-idle {
  grid-area: 1/1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 9px; color: var(--on-orange); z-index: 2;
}
.call-idle > div:first-child { display: flex; }
.call-idle.hide { display: none; }
.call-idle strong { font-size: 21px; }
.call-idle p { margin: 0; color: #fffaf4ad; font-size: 14px; }
.call-top {
  position: absolute; top: 16px; left: 16px; z-index: 4; display: flex; gap: 8px; align-items: center;
  color: var(--on-orange); font-size: 13px; font-weight: 700;
  background: #0d1f2673; padding: 4px 11px; border-radius: 999px;
}
.call-q {
  font-weight: 600; color: #fffaf4b3; cursor: pointer; user-select: none;
  padding: 1px 7px; margin: -1px -5px -1px 0; border-radius: 999px;
  transition: background .15s, color .15s;
}
.call-q:hover { background: #fffaf42b; color: var(--on-orange); }
.call-q:active { transform: scale(.96); }
.call-bar {
  position: absolute; left: 0; right: 0; bottom: calc(26px + env(safe-area-inset-bottom));
  z-index: 4; display: flex; justify-content: center; gap: 22px;
}

.only-mobile { display: none; }

/* ---------------------------------------------------------- responsive */
@media (max-width: 1100px) { :root { --side: 288px; --roster: 204px; } }

@media (max-width: 880px) {
  .app { grid-template-columns: 1fr; }
  .side { border-right: 0; }
  .stage {
    position: fixed; inset: 0; height: var(--vh); z-index: 20; grid-template-columns: 1fr;
    transform: translateX(100%); transition: transform .24s var(--ease); visibility: hidden;
  }
  .stage.open { transform: none; visibility: visible; }
  .welcome { display: none; }
  .only-mobile { display: grid; }
  .roster { position: absolute; inset: 0 0 0 auto; width: min(272px, 84%); z-index: 5; box-shadow: -16px 0 40px -18px #0006; }
  .shot { max-width: 82%; }
  #localVid { width: 96px; height: 72px; }
  .ring-actions { gap: 34px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  .log { scroll-behavior: auto; }
}

/* ---------------------------------------------------------- credit */
.credit {
  margin: 10px 0 0; text-align: center; font-size: 11.5px; color: var(--txt-mute);
}
.credit strong { color: var(--txt-dim); font-weight: 700; }

.about {
  margin: 22px 14px 0; padding: 16px 12px 14px; text-align: center;
  border-top: 1px solid var(--line-soft);
}
.about-mark img, .about-mark svg {
  width: 36px; height: 36px; display: block; margin: 0 auto 8px; border-radius: 9px;
}
.about strong { display: block; font-size: 14px; }
.about strong span { color: var(--txt-mute); font-weight: 600; }
.about p { margin: 2px 0 0; font-size: 12px; color: var(--txt-mute); }

/* ---------------------------------------------------------- messages, extras */
.msg-acts { display: none; gap: 8px; margin-left: 4px; }
.msg:hover .msg-acts { display: inline-flex; }
.msg-acts button {
  border: 0; background: none; padding: 0; cursor: pointer;
  font-size: 11.5px; font-weight: 700; color: var(--txt-mute);
}
.msg-acts button:hover { color: var(--orange-dk); text-decoration: underline; }
.gone-text { color: var(--txt-mute); font-style: italic; }

.player {
  display: flex; flex-direction: column; gap: 5px; margin-top: 5px;
  padding: 9px 11px; border-radius: var(--r-m);
  background: var(--panel-2); border: 1px solid var(--line); max-width: 330px;
}
.player audio { width: 100%; height: 34px; }
video.shot { background: #0d1013; }

.typing.flash { color: var(--sect-txt); font-style: normal; font-weight: 600; }

.emoji-pop { display: block; }
.emoji-tabs {
  display: flex; gap: 2px; padding-bottom: 7px; margin-bottom: 7px;
  border-bottom: 1px solid var(--line-soft); overflow-x: auto;
}
.emoji-tabs button {
  flex: none; border: 0; background: transparent; font-size: 17px;
  padding: 4px 7px; border-radius: 8px; cursor: pointer; line-height: 1;
}
.emoji-tabs button.on { background: var(--panel-2); box-shadow: inset 0 -2px 0 var(--orange); }
.emoji-grid {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px;
  max-height: 232px; overflow-y: auto;
}
.emoji-grid button {
  border: 0; background: transparent; font-size: 20px; padding: 5px;
  border-radius: 8px; cursor: pointer; line-height: 1;
}
.emoji-grid button:hover { background: var(--panel-2); }

/* ---------------------------------------------------------- group calls */
.group { position: fixed; inset: 0; z-index: 74; background: #0d1013; display: flex; flex-direction: column; }
.g-top {
  position: absolute; top: 14px; left: 50%; transform: translateX(-50%); z-index: 5;
  display: flex; gap: 7px; align-items: center; color: var(--on-orange);
  font-size: 13px; font-weight: 700; background: #0d1f2673;
  padding: 5px 13px; border-radius: 999px;
}
.g-sep { opacity: .45; }
#gQuality { font-weight: 600; color: #fffaf4b3; }

.g-grid {
  flex: 1; display: grid; gap: 6px; padding: 58px 8px 96px;
  grid-template-columns: 1fr; align-content: center;
}
.g-grid[data-n="2"], .g-grid[data-n="3"], .g-grid[data-n="4"] { grid-template-columns: repeat(2, 1fr); }
.g-grid[data-n="5"], .g-grid[data-n="6"] { grid-template-columns: repeat(3, 1fr); }

.g-tile {
  position: relative; background: #182429; border-radius: var(--r-m);
  overflow: hidden; display: grid; place-items: center; min-height: 120px;
}
.g-tile video { width: 100%; height: 100%; display: block; }
.g-tile.no-video video { display: none; }
.g-face { position: absolute; display: grid; place-items: center; }
.g-name {
  position: absolute; left: 8px; bottom: 6px; z-index: 2;
  font-size: 12px; font-weight: 700; color: var(--on-orange);
  background: #0d1f2699; padding: 2px 8px; border-radius: 999px;
  max-width: calc(100% - 16px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.g-self {
  position: absolute; right: 12px; top: 52px; width: 112px; height: 84px; z-index: 4;
  object-fit: contain; border-radius: var(--r-m); background: #182429;
  border: 2px solid #fffaf43d;
}
.g-self.audio-only { display: none; }

.plus-badge { width: 12px; height: 12px; margin-left: -6px; align-self: flex-start; }
#groupBtn { position: relative; }

.pick-list { max-height: 46vh; overflow-y: auto; margin-bottom: 4px; }
.pick {
  display: flex; align-items: center; gap: 10px; padding: 8px 6px;
  border-bottom: 1px solid var(--line-soft); cursor: pointer;
}
.pick:hover { background: var(--panel-2); }
.pick input { width: 17px; height: 17px; accent-color: var(--orange); }
.pick span { font-weight: 600; font-size: 14px; }

@media (max-width: 880px) {
  .g-grid[data-n="5"], .g-grid[data-n="6"] { grid-template-columns: repeat(2, 1fr); }
  .g-self { width: 88px; height: 66px; }
}

/* ---------------------------------------------------------- encryption */
.lock-on { color: var(--ok); }
.locked-text {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--txt-mute); font-style: italic; font-size: 13.5px;
}
.plain-note { color: var(--warn); font-weight: 600; }
.fp {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; letter-spacing: .02em; color: var(--txt-dim);
  background: var(--panel-2); border: 1px solid var(--line-soft);
  border-radius: var(--r-s); padding: 8px 10px; margin-top: 6px; word-spacing: 4px;
}

/* ---------------------------------------------------------- status feedback */
.linkbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 80;
  padding: 7px 14px calc(7px + env(safe-area-inset-top));
  font-size: 12.5px; font-weight: 700; text-align: center;
  color: var(--on-orange); background: var(--bad);
}
.linkbar.ok { display: none; }
.composer.blocked { opacity: .6; }
.composer.blocked textarea { cursor: not-allowed; }

.receipt { display: inline-flex; align-items: center; }
.tick { font-size: 11px; letter-spacing: -1px; line-height: 1; color: var(--txt-mute); }
.tick.delivered { color: var(--txt-dim); }
.tick.seen { color: var(--teal); }

/* ---------------------------------------------------------- presence editor */
.banner-id {
  border: 0; background: none; padding: 4px 6px; margin: -4px -6px;
  text-align: left; cursor: pointer; border-radius: var(--r-s);
  color: inherit; font: inherit; transition: background .15s;
}
.banner-id:hover { background: #fffaf424; }

.mood-pick { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
.mood {
  display: flex; align-items: center; gap: 9px; padding: 11px 12px;
  border: 1px solid var(--line); border-radius: var(--r-m);
  background: var(--panel); cursor: pointer; font-weight: 600; font-size: 13.5px;
  transition: border-color .15s, background .15s;
}
.mood:hover { background: var(--panel-2); }
.mood.on { border-color: var(--orange); background: #f078181a; color: var(--orange-dk); }
html[data-theme="dark"] .mood.on { color: var(--orange-lt); }
.mood .dot {
  width: 11px; height: 11px; border-radius: 50%; flex: none;
  background: var(--txt-mute); border: 1px solid var(--line);
}
.mood .dot.online { background: var(--ok); }
.mood .dot.away   { background: var(--warn); }
.mood .dot.busy   { background: var(--bad); }

.you {
  font-size: 11.5px; font-weight: 700; letter-spacing: .02em;
  opacity: .75; vertical-align: middle;
}
.me-id .you { color: var(--txt-mute); opacity: 1; }
.enc-note { color: var(--ok); font-weight: 600; }

/* ---------------------------------------------------------- attachments */
.shot-wrap { position: relative; display: inline-block; margin-top: 5px; }
.shot-wrap .shot { margin-top: 0; }
.att-save {
  position: absolute; right: 7px; bottom: 7px;
  display: grid; place-items: center; width: 32px; height: 32px;
  border-radius: 9px; background: #0d1f26bf; color: var(--on-orange);
  text-decoration: none; opacity: 0; transition: opacity .15s, background .15s;
}
.shot-wrap:hover .att-save, .player .att-save { opacity: 1; }
.att-save:hover { background: var(--orange); }
.player { position: relative; padding-right: 46px; }
.player .att-save { position: absolute; right: 8px; top: 50%; margin-top: -16px; }
@media (hover: none) { .att-save { opacity: 1; } }

/* the photo picker is a button now, so it needs the button defaults removed */
button.me-av { border: 0; background: none; padding: 0; cursor: pointer; display: block; }
button.me-av:focus-visible { outline: 2px solid var(--teal); outline-offset: 3px; border-radius: 50%; }

/* close control inside a section header */
.sect-close {
  margin-left: auto; display: grid; place-items: center;
  width: 24px; height: 24px; padding: 0; border: 0; border-radius: 7px;
  background: transparent; color: inherit; cursor: pointer; opacity: .7;
}
.sect-close:hover { opacity: 1; background: #0f648022; }
.sect .sect-close + span { margin-left: 0; }

/* Controls sit on the message, not in the timestamp row, so a message that
   continues a run still has them. Hover reveals them on a pointer device, and
   a press reveals them anywhere - which is the only way in on a touch screen,
   where there is no hover at all.
   These used to be left permanently on show for touch instead. That was
   tolerable while the row held only edit and delete, which appear on a handful
   of messages inside a five minute window. Replying and forwarding are offered
   on every message, so the same rule would put two icons under every line of
   the conversation and leave them there. */
.msg-acts {
  display: none; align-items: center; gap: 10px; margin-top: 2px;
  justify-content: flex-end;
}
.msg.them .msg-acts { justify-content: flex-start; }
.msg:hover .msg-acts, .msg.acts-open .msg-acts, .msg-acts.pinned { display: inline-flex; }
.acts-left { font-style: normal; font-size: 10.5px; color: var(--txt-mute); opacity: .8; }


/* ---------------------------------------------------------- call orientation */
/* The remote picture is contained rather than cropped, so a portrait caller and a
   landscape caller both arrive whole instead of having their heads cut off. */
#remoteVid { object-fit: contain; }

/* The self-view follows the shape the camera is actually producing, and that is
   set from script after measuring the stream - see sizePreview. Fixed sizes per
   orientation used to live here and fought both the measured shape and the
   media queries below, which is what made the picture jump to a wrong size when
   the orientation was changed mid-call. */

/* A phone held sideways has almost no vertical room: the controls shrink and sit
   closer to the edge so they do not cover the person being spoken to. */
@media (max-height: 480px) and (orientation: landscape) {
  .call-bar { bottom: 10px; gap: 14px; }
  .round { width: 46px; height: 46px; }
  .round .ic { width: 19px; height: 19px; }
  #localVid { top: 8px; right: 8px; }
  .call-top { top: 8px; left: 8px; padding: 3px 9px; font-size: 12px; }
  .g-grid { padding: 44px 6px 68px; }
  .g-self { top: 42px; right: 8px; }
}

/* Portrait phones give the grid more vertical room to work with. */
@media (max-width: 880px) and (orientation: portrait) {
  .g-grid[data-n="2"] { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------- signal bars */
.bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 13px; margin-right: 7px; }
.bars i {
  width: 3px; border-radius: 1px; background: currentColor;
  opacity: .22; transition: opacity .2s, background .2s;
}
.bars i:nth-child(1) { height: 4px; }
.bars i:nth-child(2) { height: 7px; }
.bars i:nth-child(3) { height: 10px; }
.bars i:nth-child(4) { height: 13px; }
.bars i.on { opacity: 1; }
.bars.ok   { color: #3ecf6a; }
.bars.mid  { color: #e8a317; }
.bars.bad  { color: #ff5d4d; }
.bars.dead { color: #8a8a8a; }
.q-text { vertical-align: middle; }

/* ---------------------------------------------------------- mixed feed sizes */
/* Six participants can each send a different size and orientation: a 4K webcam, a
   phone held upright, an old 480p camera, an ultrawide. Letting every tile take
   the shape of its own picture tears the grid apart - a portrait feed grows
   taller than the row and pushes everything out of view.
   
   So the cells stay uniform and the picture is fitted inside one. `contain`
   rather than `cover`, because in a call seeing the whole of someone matters
   more than filling the rectangle, and cover would slice the top off anyone
   sending portrait. */
/* The rows divide the available height between them, so the cells are whatever
   size the call needs and every one of them is the same. Aspect ratio is left to
   the picture inside rather than imposed on the cell: setting both a ratio and a
   stretch on the same box makes it collapse. */
/* min-height:0 is what makes the rows actually divide the available height. A
   flex item defaults to min-height:auto and refuses to shrink below its content,
   so without it the grid grows past the window and the far participants end up
   below the fold - the same default that once pushed the message composer off
   the screen. */
.g-grid { align-content: stretch; grid-auto-rows: 1fr; min-height: 0; }
.g-tile { min-height: 0; }
.g-tile video { width: 100%; height: 100%; object-fit: contain; background: #11181c; }

/* One-to-one already contains rather than crops; make the letterbox deliberate
   rather than an accident of the background colour. */
#remoteVid { background: #0d1013; }

.field-hint {
  margin: 5px 0 0; font-size: 11.5px; color: var(--warn); font-weight: 600;
}

/* ---------------------------------------------------------------- recovery key */

.modal-note {
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--txt-dim);
}

/* Monospaced and spaced out: this gets copied by hand off a screen, so every
   character has to be separable from the next. */
.recovery-key {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 15px;
  letter-spacing: .1em;
  line-height: 1.9;
  text-align: center;
  word-break: break-all;
  user-select: all;
  padding: 14px 12px;
  margin-bottom: 14px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--sect-bg);
  color: var(--txt);
}

.check {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  font-size: 13px;
  color: var(--txt-dim);
  cursor: pointer;
}

/* A global reset strips appearance from inputs, which collapses a checkbox to
   nothing. This one gates the button that closes the dialog, so it has to be
   both visible and hittable. */
.check input[type="checkbox"] {
  appearance: auto;
  -webkit-appearance: checkbox;
  accent-color: var(--orange);
  width: 16px;
  height: 16px;
  min-width: 16px;
  margin: 0;
  flex: none;
  cursor: pointer;
}


/* ---------------------------------------------------------------- message details */

.info-list { margin: 0 0 14px; }
.info-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  padding: 8px 0; border-bottom: 1px solid var(--line-soft);
}
.info-row:last-child { border-bottom: 0; }
.info-row dt { font-size: 12.5px; color: var(--txt-dim); font-weight: 600; }
.info-row dd { margin: 0; font-size: 13px; color: var(--txt); text-align: right; }
.info-row dd em { color: var(--txt-mute); font-style: normal; }

/* ---------------------------------------------------------------- pinned bar */

.pinbar {
  display: flex; align-items: center; gap: 9px; flex: none;
  padding: 7px 14px; cursor: pointer;
  background: var(--sect-bg); color: var(--sect-txt);
  border-bottom: 1px solid var(--line);
  font-size: 12.5px;
}
.pinbar:hover { filter: brightness(1.04); }
.pinbar #pinText {
  flex: 1; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.pin-close {
  border: 0; background: none; cursor: pointer; padding: 0 4px;
  color: inherit; font-size: 19px; line-height: 1; opacity: .8;
}
.pin-close:hover { opacity: 1; }

/* ---------------------------------------------------------------- moderation */

/* the row splits so the name still opens a profile while the control beside it
   opens the moderation actions */
.roster-row { display: flex; align-items: stretch; gap: 0; padding: 0; }
.row-main {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px;
  padding: 8px 6px 8px 12px; border: 0; background: none;
  cursor: pointer; text-align: left; color: inherit; font: inherit;
}
.row-mod {
  flex: none; width: 34px; border: 0; background: none; cursor: pointer;
  color: var(--txt-mute); font-size: 17px; line-height: 1; letter-spacing: 1px;
}
.row-mod:hover { color: var(--orange-dk); background: var(--sect-bg); }

.mod-actions { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.mod-actions .btn { width: 100%; justify-content: center; }
.btn.danger { color: var(--bad); border-color: var(--bad); }
.btn.danger:hover { background: var(--bad); color: var(--on-orange); }

/* ---------------------------------------------------------------- reactions */

.reacts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 4px; }
/* with nothing on the message the control only appears on approach, so a bare
   conversation is not littered with plus signs */
.empty-reacts .react-add { opacity: 0; }
.msg:hover .empty-reacts .react-add,
.msg.acts-open .empty-reacts .react-add,
.empty-reacts .react-add:focus-visible { opacity: .7; }

.react {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line); background: var(--panel-2);
  font-size: 12px; line-height: 1.6;
}
.react:hover { border-color: var(--teal); }
.react.on { background: var(--teal-soft); border-color: var(--teal); }
html[data-theme="dark"] .react.on { background: #1d4652; }
.react em { font-style: normal; font-size: 11px; color: var(--txt-dim); font-weight: 700; }

.react-add {
  width: 22px; height: 22px; border-radius: 999px; cursor: pointer;
  border: 1px dashed var(--line); background: none; color: var(--txt-mute);
  font-size: 13px; line-height: 1; padding: 0;
  transition: opacity .15s, color .15s, border-color .15s;
}
.react-add:hover { color: var(--teal-dk); border-color: var(--teal); opacity: 1; }

.react-pick {
  position: fixed; z-index: 90; display: flex; gap: 2px;
  padding: 5px; border-radius: 999px;
  background: var(--panel); border: 1px solid var(--line); box-shadow: var(--shadow);
}
.react-pick button {
  width: 34px; height: 34px; border: 0; border-radius: 999px; background: none;
  cursor: pointer; font-size: 18px; line-height: 1;
  transition: transform .12s var(--ease), background .15s;
}
.react-pick button:hover { background: var(--panel-2); transform: scale(1.18); }

/* ---------------------------------------------------------------- storage list */

.file-list {
  max-height: min(46vh, 340px); overflow-y: auto; overscroll-behavior: contain;
  border: 1px solid var(--line); border-radius: var(--r-m); margin-bottom: 12px;
}
.file-row {
  display: grid; grid-template-columns: auto 1fr auto auto; align-items: center; gap: 10px;
  padding: 9px 11px; cursor: pointer; border-bottom: 1px solid var(--line-soft);
  font-size: 13px;
}
.file-row:last-child { border-bottom: 0; }
.file-row:hover { background: var(--panel-2); }
.file-pick {
  appearance: auto; -webkit-appearance: checkbox;
  width: 15px; height: 15px; margin: 0; accent-color: var(--orange); flex: none;
}
.file-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-where { font-size: 11.5px; color: var(--txt-mute); white-space: nowrap; }
.file-size { font-size: 11.5px; color: var(--txt-dim); font-variant-numeric: tabular-nums; }
.file-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-bottom: 14px; font-size: 12.5px; color: var(--txt-dim);
}
.file-foot .check { margin: 0; }

/* ---------------------------------------------------------------- devices */

.device-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--line-soft);
}
.device-row:last-child { border-bottom: 0; }
.device-what { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.device-what strong { font-size: 13.5px; }
.device-what span { font-size: 11.5px; color: var(--txt-mute); }
.device-here {
  font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 999px;
  background: var(--teal-soft); color: var(--sect-txt); flex: none;
}
.btn.sm { padding: 6px 12px; font-size: 12.5px; flex: none; }

/* ---------------------------------------------------------------- ilzora share */

.share-wrap { padding: 14px; overflow-y: auto; min-height: 0; flex: 1 1 0; }

.share-hero { text-align: center; padding: 26px 10px 20px; color: var(--txt-dim); }
.share-hero .ic { width: 40px; height: 40px; color: var(--teal); }
.share-hero h3 { margin: 10px 0 6px; font-size: 17px; color: var(--txt); }
.share-hero p { margin: 0 auto; max-width: 34ch; font-size: 13px; line-height: 1.6; }

.share-drop {
  margin: 12px 0; padding: 22px 14px; text-align: center;
  border: 2px dashed var(--line); border-radius: var(--r-l);
  color: var(--txt-mute); font-size: 13px;
  transition: border-color .15s, background .15s;
}
.share-drop.over { border-color: var(--orange); background: #f078181a; color: var(--orange-dk); }
.share-drop p { margin: 0; }
.linkish {
  border: 0; background: none; padding: 0; cursor: pointer;
  color: var(--teal-dk); text-decoration: underline; font: inherit;
}

.share-peer {
  padding: 10px 0; border-bottom: 1px solid var(--line-soft);
}
.share-peer:last-child { border-bottom: 0; }
.share-peer-top { display: flex; align-items: center; gap: 10px; }
.share-peer-who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.share-peer-who strong {
  font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.share-peer-who span { font-size: 11.5px; color: var(--txt-mute); }
.share-pct {
  font-size: 12px; font-weight: 700; color: var(--teal-dk);
  font-variant-numeric: tabular-nums; flex: none;
}

.share-bar {
  height: 5px; margin-top: 7px; border-radius: 999px;
  background: var(--panel-2); overflow: hidden;
}
.share-bar i {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--teal), var(--orange));
  transition: width .18s var(--ease);
}
.share-stats {
  display: flex; justify-content: space-between; gap: 10px; margin-top: 4px;
  font-size: 11px; color: var(--txt-mute); font-variant-numeric: tabular-nums;
}

.share-got {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 0; border-bottom: 1px solid var(--line-soft);
}
.share-got:last-child { border-bottom: 0; }

/* the one place a warning should actually look like one */
.warn-note {
  padding: 10px 12px; border-radius: var(--r-s);
  background: #e0980f1a; border: 1px solid #e0980f55; color: var(--txt);
}

/* ---------------------------------------------------------------- verification */

.check-field .human-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.check-field img {
  display: block; border-radius: var(--r-s); border: 1px solid var(--line);
  background: var(--panel-2); max-width: 100%; height: auto;
}
.check-field input { text-transform: uppercase; letter-spacing: .12em; }

/* ---------------------------------------------------------------- send later */

.sched-row {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px; border-bottom: 1px solid var(--line-soft);
}
.sched-row:last-child { border-bottom: 0; }
.sched-when {
  font-size: 11px; color: var(--orange-dk); font-weight: 650; margin-top: 2px;
}
html[data-theme="dark"] .sched-when { color: var(--orange-lt); }
.sched-row .row-body { flex: 1; min-width: 0; }
.sched-row .row-sub {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sched-row .row-sub em { color: var(--txt-mute); font-style: normal; }

/* ---------------------------------------------------------------- call layout
   by orientation

   The column counts above are written for a wide window. Applied to a phone held
   upright they are actively wrong: two people side by side on a portrait screen
   are two thin slivers with the faces too small to read, while the height above
   and below them goes unused. Which way the tiles should divide depends on the
   shape of the space, not only on how many people are in it. */

@media (orientation: portrait) {
  /* upright: divide the tall axis first */
  .g-grid[data-n="2"] { grid-template-columns: 1fr; }
  .g-grid[data-n="3"], .g-grid[data-n="4"],
  .g-grid[data-n="5"], .g-grid[data-n="6"] { grid-template-columns: repeat(2, 1fr); }
  .g-grid { padding-left: 6px; padding-right: 6px; }

  /* the self view stands upright instead of forcing a landscape box onto a
     portrait frame and letterboxing it down both sides.
     Both dimensions are stated rather than one being auto with an aspect-ratio:
     on a replaced element auto resolves against the intrinsic size, which is
     zero until a stream arrives, so the preview collapses before the call
     connects and never recovers. */
  .g-self { width: 84px; height: 112px; }
}

@media (orientation: landscape) {
  .g-grid[data-n="2"] { grid-template-columns: repeat(2, 1fr); }
  .g-grid[data-n="3"] { grid-template-columns: repeat(3, 1fr); }
  .g-grid[data-n="4"] { grid-template-columns: repeat(2, 1fr); }
  .g-grid[data-n="5"], .g-grid[data-n="6"] { grid-template-columns: repeat(3, 1fr); }
  .g-self { width: 112px; height: 84px; }
}

/* A short landscape window - a phone on its side - has no room for the header
   inset the tall layout leaves, and three rows of tiles would each be a band a
   few pixels high. */
@media (orientation: landscape) and (max-height: 480px) {
  .g-grid { padding-top: 46px; padding-bottom: 68px; }
  .g-grid[data-n="5"], .g-grid[data-n="6"] { grid-template-columns: repeat(3, 1fr); }
  .g-self { width: 88px; height: 66px; top: 44px; }
}

/* ---------------------------------------------------------------- moving the
   self view, and giving one person the window */

.g-self { cursor: grab; touch-action: none; user-select: none; }
.g-self.dragging { cursor: grabbing; opacity: .92; transform: scale(1.03); z-index: 6; }
.g-tile { cursor: pointer; }

/* Spotlight: the chosen tile takes the whole area and the others sit along the
   bottom. They are placed rather than flowed, because a grid that reflows on
   every join would move the person you were looking at out from under the
   pointer. --i is each small tile's place in the strip. */
.g-grid.spot { display: block; position: relative; }
.g-grid.spot .g-tile {
  position: absolute;
  width: 104px; height: 78px;
  bottom: 74px;
  left: calc(8px + var(--i, 0) * 110px);
  z-index: 3;
  transition: left .18s var(--ease);
}
.g-grid.spot .g-tile.spot-main {
  position: absolute;
  inset: 52px 8px 156px;
  width: auto; height: auto;
  left: 8px;
  z-index: 1;
}
.g-grid.spot .g-tile .g-name { font-size: 10px; padding: 1px 6px; }
.g-grid.spot .g-tile.spot-main .g-name { font-size: 12px; padding: 2px 8px; }

/* on a short landscape window the strip has to sit tighter or it eats the view */
@media (orientation: landscape) and (max-height: 480px) {
  .g-grid.spot .g-tile { width: 84px; height: 62px; bottom: 60px;
                         left: calc(8px + var(--i, 0) * 90px); }
  .g-grid.spot .g-tile.spot-main { inset: 46px 8px 128px; }
}

/* ---------------------------------------------------------------- links */

/* an external link is marked, so it is clear before clicking that it leaves */
.msg-text a.external::after {
  content: "↗";
  font-size: .82em; margin-left: 2px; opacity: .7;
}
.link-host {
  font-size: 15px; letter-spacing: .02em; word-break: break-all;
  text-align: center; user-select: all;
}

/* a link something was found against is marked where it sits, so it is visible
   before it is clicked rather than only in the dialog afterwards */
.msg-text a.suspect {
  color: var(--bad);
  text-decoration-style: wavy;
  text-underline-offset: 3px;
}
.msg-text a.suspect::after { content: " ⚠"; font-size: .9em; opacity: .9; }

/* ---------------------------------------------------------------- call swap

   Tapping either picture exchanges them. Only the classes change: the video
   elements stay exactly where they are in the document, because a video element
   moved in the DOM loses its stream and comes back black mid-call. */

#localVid, #remoteVid { cursor: pointer; touch-action: none; }

.call.swapped #remoteVid {
  position: absolute; right: 14px; top: 14px; left: auto; bottom: auto;
  width: 116px; height: 87px; object-fit: contain;
  border-radius: var(--r-m); background: #1c2024;
  border: 2px solid #fffaf43d; z-index: 3;
}
.call.swapped #localVid {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: contain;
  border: 0; border-radius: 0; background: #0d1013; z-index: 1;
}

/* the one being dragged rises above the other and shrinks back on release */
#localVid.dragging, #remoteVid.dragging {
  opacity: .92; transform: scale(1.03); z-index: 6; cursor: grabbing;
}



/* who reacted, inside the message details */
/* the list is inside the card, which already scrolls at 88vh; this keeps one
   very popular emoji from pushing the others off the top of it */
#whoReacted { max-height: 46vh; overflow-y: auto; overscroll-behavior: contain; }
.who-row {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--line-soft);
}
.who-count {
  margin-left: auto; flex: none; font-size: 12px; font-weight: 700;
  color: var(--txt-dim); font-variant-numeric: tabular-nums;
}
.who-names em { color: var(--txt-mute); font-style: normal; }
.who-row:last-child { border-bottom: 0; }
.who-emoji { font-size: 17px; line-height: 1.3; flex: none; }
.who-names { font-size: 13px; color: var(--txt); line-height: 1.5; }

/* ------------------------------------------------------------ reply, forward */

.reply-bar {
  display: flex; align-items: center; gap: 9px;
  margin: 0 11px; padding: 7px 9px;
  background: var(--panel-2); border-left: 3px solid var(--teal);
  border-radius: var(--r-s); color: var(--txt-mute);
}
.reply-bar .ic { flex: none; color: var(--teal); }
.reply-bar-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.reply-bar-text strong { font-size: 12px; color: var(--teal-dk); }
.reply-bar-text span {
  font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* the quoted original inside a bubble */
.quote {
  display: block; width: 100%; text-align: left; cursor: pointer;
  margin: 0 0 5px; padding: 5px 8px; border: 0;
  border-left: 3px solid var(--teal); border-radius: var(--r-s);
  background: #26a9ce1f; color: inherit; font: inherit;
}
.quote:hover { background: #26a9ce33; }
.quote strong { display: block; font-size: 11.5px; color: var(--teal-dk); }
.quote span {
  display: block; font-size: 12.5px; opacity: .82;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msg.mine .quote { background: #ffffff2b; border-left-color: #ffffff8c; }
.msg.mine .quote:hover { background: #ffffff3d; }
.msg.mine .quote strong { color: inherit; opacity: .9; }

/* the message a quote was pointing at, once it has been scrolled to */
.msg.found .bubble { animation: found 1.6s ease; }
@keyframes found {
  0%, 70% { box-shadow: 0 0 0 3px var(--teal); }
  100% { box-shadow: 0 0 0 0 transparent; }
}

.fwd-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11.5px; font-style: italic; opacity: .7; margin-bottom: 3px;
}
.fwd-tag .ic { width: 12px; height: 12px; }

.act-ic {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 2px; border: 0; background: transparent;
  color: var(--txt-mute); cursor: pointer; border-radius: 6px;
}
.act-ic:hover { color: var(--teal-dk); background: var(--panel-2); }
.act-ic .ic { width: 14px; height: 14px; }

.fwd-preview {
  margin: 0 0 12px; padding: 9px 11px; border-radius: var(--r-s);
  background: var(--panel-2); color: var(--txt-mute); font-size: 13px;
}
.pick-list { max-height: 300px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.pick-row {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 9px; border: 0; border-radius: var(--r-s);
  background: transparent; color: inherit; font: inherit;
  text-align: left; cursor: pointer;
}
.pick-row:hover { background: var(--panel-2); }
.pick-row[disabled] { opacity: .5; cursor: default; }
.pick-row .pick-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-row em { font-size: 11.5px; color: var(--txt-mute); font-style: normal; }
.pick-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex: none;
  border-radius: 50%; background: var(--panel-2); color: var(--txt-mute);
}


/* --------------------------------------------------------- group call roster */

.ring-roster {
  width: 100%; margin: 4px 0 2px; display: flex; flex-direction: column; gap: 10px;
  max-height: 190px; overflow-y: auto;
}
.ring-label {
  display: block; font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--txt-mute); margin-bottom: 6px;
}
.ring-group.asked .ring-face { opacity: .62; }
.ring-faces { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.ring-face {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  width: 58px; min-width: 0;
}
.ring-face em {
  font-style: normal; font-size: 11px; color: var(--txt-dim);
  max-width: 58px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ring-alone { font-size: 12px; color: var(--txt-mute); margin: 0; }

/* ------------------------------------------------------------- person tools */

.person-tools {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-soft);
  display: flex; flex-direction: column; gap: 7px;
}
.tools-label {
  font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--txt-mute); margin-bottom: 1px;
}
.person-tools .btn { justify-content: flex-start; gap: 9px; }

/* ------------------------------------------------------- gate requirements */

.gate-needs {
  list-style: none; margin: 2px 0 10px; padding: 10px 12px;
  background: var(--panel-2); border-radius: var(--r-s);
  display: flex; flex-direction: column; gap: 5px;
}
.gate-needs .needs-title {
  font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--txt-mute); margin-bottom: 1px;
}
.gate-needs li { font-size: 12.5px; display: flex; align-items: flex-start; gap: 7px; }
.gate-needs li.met, .gate-needs li.unmet { padding-left: 0; }
.gate-needs li.met::before,
.gate-needs li.unmet::before {
  flex: none; width: 14px; text-align: center; line-height: 1.35;
}
.gate-needs li.met { color: var(--txt-mute); }
.gate-needs li.met::before { content: "\2713"; color: var(--teal); }
.gate-needs li.unmet { color: var(--txt-dim); }
.gate-needs li.unmet::before { content: "\2022"; color: var(--orange); }

.gate .field input[aria-invalid="true"]:not(:placeholder-shown) {
  border-color: var(--orange);
}
