/* Hexeria Chat. Same palette as the rest of the family, so the products read
   as siblings without sharing a stylesheet. */

:root {
  --bg: #0b1016;
  --panel: #121821;
  --raised: #1a222d;
  --line: #262f3b;
  --ink: #e8e3d8;
  --dim: #94a0ab;
  --accent: #d8b872;
  --danger: #e5695f;
  --mine: #243244;
  --theirs: #1a222d;
}

* { box-sizing: border-box; }
/* The hidden attribute is UA-stylesheet display:none, which LOSES to any
   author display rule -- our flex/grid containers would all render while
   "hidden" without this. */
[hidden] { display: none !important; }
html, body { height: 100%; }
html { overflow-x: hidden; }
body {
  margin: 0;
  /* App-shell layout: the page itself never scrolls. The only scroll
     container is #messages, which is what keeps the composer on screen no
     matter how long a conversation gets. */
  overflow: hidden;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 ui-sans-serif, -apple-system, "Segoe UI", Roboto, Helvetica,
        Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

#app { height: 100vh; height: 100dvh; }
#app.loading > * { display: none; }

/* --- the signed-out gate -------------------------------------------------- */

#gate, #outage {
  height: 100%;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.gate-card {
  text-align: center;
  max-width: 380px;
}
.gate-card h1 {
  margin: 0 0 6px;
  font: 600 26px/1.2 ui-serif, Georgia, serif;
  letter-spacing: .14em; text-transform: uppercase;
}
.gate-sub { margin: 0 0 26px; color: var(--dim); }
.gate-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

.btn {
  display: inline-block;
  padding: 9px 18px;
  border: 1px solid var(--accent);
  border-radius: 999px;
  color: var(--accent);
  text-decoration: none;
  font-size: 14px;
}
@media (hover: hover) {
  .btn:hover { background: var(--accent); color: #12161b; }
}
.btn.ghost { border-color: var(--line); color: var(--dim); }
.btn.ghost:hover { border-color: var(--ink); color: var(--ink); background: none; }

/* --- the shell ------------------------------------------------------------ */

#shell {
  height: 100%;
  display: grid;
  grid-template-columns: 62px 280px 1fr;
}

#sidebar {
  border-right: 1px solid var(--line);
  background: var(--panel);
  display: flex; flex-direction: column;
  /* Grid items default to min-height:auto too -- without these the
     conversation list pushes the sidebar tall instead of scrolling inside
     it, the same trap as the messages pane. */
  min-width: 0; min-height: 0;
}

#me {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
}
#me-name { font-weight: 600; }
.me-actions {
  display: flex; gap: 12px; align-items: center;
  flex-shrink: 0;
}
#logout-link { color: var(--dim); font-size: 12.5px; text-decoration: none; }
#logout-link:hover { color: var(--ink); }
#notif-enable {
  border: 0; background: none; padding: 0;
  font-size: 14px; cursor: pointer;
  filter: grayscale(1) opacity(.75);
}
#notif-enable:active { filter: none; }

/* Presence dots: green online, red silent, grey away/offline. */
.pdot {
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}
.p-green { background: #43b581; }
.p-red   { background: var(--danger); }
.p-grey  { background: #5d6771; }
#mode-dot {
  width: 11px; height: 11px;
  border: 0; padding: 0;
  flex-shrink: 0;
  cursor: pointer;
}

/* The switcher dresses as the plain name until touched. */
#me-wrap {
  position: relative;
  display: flex; align-items: center; gap: 9px;
  flex: 1; min-width: 0;
}
#me-avatar {
  width: 28px; height: 28px; border-radius: 9px;
  cursor: pointer;
  /* It IS a button; on a pointer screen it needs to look like one. */
  outline: 2px solid transparent; outline-offset: 2px;
  transition: outline-color .15s, filter .15s;
}
@media (hover: hover) {
  #me-avatar:hover { outline-color: var(--accent); filter: brightness(1.12); }
}
#me-avatar:focus-visible { outline-color: var(--accent); }
#context {
  display: flex; align-items: center; gap: 5px;
  border: 0; background: none;
  color: var(--ink);
  font: inherit; font-weight: 600;
  padding: 0;
  flex: 1; min-width: 0;
  text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  cursor: pointer;
}
#context:hover { color: var(--accent); }
.ctx-caret { color: var(--dim); font-size: 10px; flex-shrink: 0; }

/* Same menu as presence, same manners. */
#ctx-menu {
  position: fixed; z-index: 45;
  min-width: 240px; max-width: min(320px, 86vw); padding: 5px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, .5);
}
#ctx-menu .av { flex-shrink: 0; }
#me-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}
#me-wrap.has-orgs::after {
  content: "\25BE";
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  color: var(--accent); font-size: 10px;
  pointer-events: none;
}

/* Tabs: Chats / Friends. */
#tabs {
  display: flex; gap: 4px;
  padding: 10px 12px 0;
}
#tabs button {
  flex: 1;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 7px 0;
  border: 0; border-radius: 8px;
  background: none; color: var(--dim);
  font: inherit; font-size: 13.5px; cursor: pointer;
}
#tabs button.active { background: var(--raised); color: var(--ink); }

#new-group {
  flex-shrink: 0;
  width: 36px;
  border: 1px solid var(--line); border-radius: 8px;
  background: none; color: var(--dim);
  font: inherit; font-size: 18px; line-height: 1; cursor: pointer;
}
#new-group:active { color: var(--accent); border-color: var(--accent); }

#add-friend { padding: 12px 12px 4px; }
#add-friend-name {
  width: 100%; padding: 8px 12px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg); color: var(--ink);
  font: inherit; font-size: 14px;
}
#friends-lists { padding: 8px 12px; overflow-y: auto; min-height: 0; }
.fr-section { margin: 10px 0 4px; font-size: 11.5px; color: var(--dim);
  text-transform: uppercase; letter-spacing: .08em; }
.fr-row {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 6px; border-radius: 8px;
}
.fr-row .frname { flex: 1; font-weight: 600; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  cursor: pointer; }
.fr-row button {
  border: 1px solid var(--line); border-radius: 999px;
  background: none; color: var(--dim);
  font: inherit; font-size: 12px; padding: 3px 10px; cursor: pointer;
}
.fr-row button.yes { border-color: var(--accent); color: var(--accent); }

.av {
  width: 34px; height: 34px; flex-shrink: 0;
  border-radius: 10px;
  object-fit: contain;   /* letterbox, never distort */
}
.av-sm { width: 22px; height: 22px; border-radius: 7px; }

#new-dm { padding: 12px 12px 4px; display: flex; gap: 8px; }
#new-dm-name {
  flex: 1; min-width: 0;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink);
  font: inherit; font-size: 14px;
}
#new-dm-name:focus { outline: none; border-color: var(--accent); }
.quiet-error {
  margin: 6px 14px 0; font-size: 12.5px; color: var(--danger);
}

#conversations { flex: 1; min-height: 0; overflow-y: auto; padding: 8px; }
.conv {
  display: block; width: 100%;
  text-align: left;
  padding: 10px 10px;
  border: 0; border-radius: 8px;
  background: none; color: var(--ink);
  font: inherit; cursor: pointer;
}
@media (hover: hover) { .conv:hover { background: var(--raised); } }
.conv.active {
  background: var(--raised);
  box-shadow: inset 3px 0 0 var(--accent);
}
.conv { min-width: 0; overflow: hidden;
  display: flex; align-items: center; gap: 10px; }
.conv-main { flex: 1; min-width: 0; }
.conv-top { display: flex; justify-content: space-between; gap: 8px; }
.conv-name {
  font-weight: 600;
  min-width: 0;
  display: inline-flex; align-items: center; gap: 7px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.conv-unread {
  min-width: 20px; padding: 1px 6px;
  border-radius: 999px;
  background: var(--accent); color: #12161b;
  font-size: 11.5px; font-weight: 700; text-align: center;
}
.conv-side {
  display: flex; align-items: center; gap: 6px; flex-shrink: 0;
}
.conv-time { color: var(--dim); font-size: 11.5px; }
.conv-preview {
  /* display:block, or text-overflow is a no-op on an inline span and long
     previews clip out of the frame instead of ellipsising. */
  display: block;
  margin-top: 2px;
  color: var(--dim); font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.conv-preview.typing { color: var(--accent); font-style: italic; }
/* Unread reads as unread before the badge is even parsed. */
.conv.has-unread .conv-preview { color: var(--ink); font-weight: 600; }
.empty { padding: 18px 16px; color: var(--dim); font-size: 13.5px; }

/* --- the conversation pane ------------------------------------------------ */

/* min-height: 0 down the whole chain, or the flex default of min-height:auto
   lets content push each level taller than its parent -- at which point the
   PAGE scrolls, #messages never does, scrollTop writes go nowhere, and the
   composer slides out of view. Both reported bugs were this one line. */
#pane { display: flex; min-width: 0; min-height: 0; }
#pane-empty {
  margin: auto; color: var(--dim); text-align: center;
}
.empty-hex {
  font-size: 64px; line-height: 1;
  color: var(--line);
  margin-bottom: 6px;
}
#conversation {
  flex: 1;
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0;
}
#conv-header {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--line);
}
#conv-header h2 { margin: 0; font-size: 16px; }
#conv-info {
  margin-left: auto;
  border: 0; background: none; color: var(--dim);
  font-size: 20px; cursor: pointer; padding: 0 4px;
}
#conv-panel {
  border-bottom: 1px solid var(--line);
  background: var(--panel);
  padding: 12px 20px;
  max-height: 45vh; overflow-y: auto;
  font-size: 13.5px;
}
#conv-panel .fr-row { padding: 5px 0; }
#conv-panel input, #conv-panel select {
  padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg); color: var(--ink); font: inherit; font-size: 13.5px;
}
#conv-panel .panel-actions { margin-top: 10px; display: flex; gap: 8px;
  flex-wrap: wrap; }
#conv-panel .panel-actions button {
  border: 1px solid var(--line); border-radius: 999px; background: none;
  color: var(--dim); font: inherit; font-size: 12.5px;
  padding: 4px 12px; cursor: pointer;
}
#conv-avatar { width: 30px; height: 30px; border-radius: 9px; }
.conv-head-text { display: flex; flex-direction: column; min-width: 0; }
#conv-status {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--dim);
}

/* Desktop shows both panes, so "back" means nothing there. */
#back-btn { display: none; }

#messages { flex: 1; min-height: 0; overflow-y: auto; padding: 16px 20px; }
#load-earlier {
  display: block; margin: 0 auto 14px;
  padding: 5px 14px;
  border: 1px solid var(--line); border-radius: 999px;
  background: none; color: var(--dim);
  font: inherit; font-size: 12.5px; cursor: pointer;
}
#load-earlier:hover { color: var(--ink); border-color: var(--ink); }

#message-list { list-style: none; margin: 0; padding: 0; }
.msg {
  /* Bubbles hug their content -- a photo or a file chip sits flush on its
     own side instead of floating at the left edge of a mostly-empty
     72%-wide box. min() keeps a short reply from wrapping meta lines. */
  width: fit-content;
  max-width: 72%;
  min-width: 120px;
  margin: 1px 0;
  padding: 7px 12px;
  border-radius: 14px;
  background: var(--theirs);
  overflow-wrap: break-word;
  white-space: pre-wrap;
  position: relative;
}
/* Runs read as one voice: tight within, spaced between, and a subtly
   squarer corner on the speaking side. */
.msg.mine { margin-left: auto; background: var(--mine);
  border-bottom-right-radius: 5px; }
.msg:not(.mine) { border-bottom-left-radius: 5px; }
.msg.first { margin-top: 13px; }
.msg-meta {
  display: block;
  margin-bottom: 2px;
  font-size: 11.5px; color: var(--dim);
}
.msg-via { color: var(--accent); }
.msg-body a { color: var(--accent); }

/* Link cards, the Telegram silhouette: accent spine, site, title, blurb,
   media. */
.msg-embed {
  margin-top: 8px;
  padding: 8px 12px;
  border-left: 3px solid var(--accent);
  border-radius: 6px;
  background: rgba(0, 0, 0, .22);
  max-width: min(480px, 66vw);
}
/* The thumb inside a card must not drive the card's intrinsic width. */
.embed-thumb { max-width: min(456px, 62vw); }
.embed-site { display: block; font-size: 11.5px; color: var(--dim); }
.embed-title {
  display: block; margin-top: 2px;
  font-weight: 600; font-size: 14px;
  color: var(--accent); text-decoration: none;
}
.embed-title:hover { text-decoration: underline; }
.embed-desc {
  display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 2px;
  font-size: 13px; color: var(--dim);
}
.embed-thumb {
  display: block; margin-top: 8px;
  border-radius: 6px;
}
.embed-video {
  position: relative; margin-top: 8px;
  cursor: pointer; border-radius: 6px; overflow: hidden;
}
.embed-video img { display: block; width: 100%; }
.embed-video .play {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; color: #fff;
  background: rgba(0, 0, 0, .25);
  text-shadow: 0 1px 8px rgba(0,0,0,.8);
}
/* Bare media: the bubble melts away and the media is the message. */
.msg.media { padding: 4px 0 0; background: none; }
.msg.media .msg-meta { padding: 0 12px; }
.embed-naked {
  display: block; margin-top: 4px;
  /* Fixed units only: a percentage here is circular against a fit-content
     bubble and makes the browser drop the cap entirely. */
  max-width: min(320px, 66vw);
  border-radius: 12px;
}

.msg-embed iframe {
  display: block; width: 100%;
  aspect-ratio: 16 / 9;
  border: 0; border-radius: 6px; margin-top: 8px;
}
.msg.deleted { color: var(--dim); font-style: italic; }
.msg-edited { font-size: 11px; color: var(--dim); margin-left: 6px; }

.msg-actions {
  position: absolute; top: -14px; right: 10px;
  display: none; gap: 2px;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 8px;
  z-index: 2;
}
@media (hover: hover) { .msg:hover .msg-actions { display: flex; } }
.msg:active .msg-actions { display: flex; }
.msg-actions button {
  border: 0; background: none; padding: 0 3px;
  color: var(--dim); font-size: 13px; line-height: 1.4; cursor: pointer;
}
@media (hover: hover) { .msg-actions button:hover { color: var(--ink); } }

#typing-line {
  padding: 2px 20px 0; font-size: 12px; color: var(--dim); font-style: italic;
}
#reply-banner {
  display: flex; align-items: center; gap: 10px;
  margin: 6px 20px 0;
  padding: 6px 12px;
  border-left: 3px solid var(--accent); border-radius: 6px;
  background: var(--raised);
  font-size: 12.5px; color: var(--dim);
}
#reply-banner-text { flex: 1; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
#reply-cancel { border: 0; background: none; color: var(--dim);
  font-size: 16px; cursor: pointer; }

.msg-quote {
  display: block;
  margin-bottom: 4px; padding: 4px 10px;
  border-left: 2px solid var(--accent); border-radius: 4px;
  background: rgba(0, 0, 0, .18);
  font-size: 12.5px; color: var(--dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  cursor: pointer;
}
.msg-quote b { color: var(--ink); }

.msg.pending { opacity: .55; }
.msg-state {
  display: block; margin-top: 2px;
  font-size: 10.5px; color: var(--dim); text-align: right;
}

.rx-row { display: flex; gap: 5px; margin-top: 6px; flex-wrap: wrap; }
.rx-chip {
  border: 1px solid var(--line); border-radius: 999px;
  background: rgba(0,0,0,.18); color: var(--ink);
  font: inherit; font-size: 12.5px; padding: 1px 8px; cursor: pointer;
}
.rx-chip.mine { border-color: var(--accent); }
.rx-pick {
  position: absolute; top: -34px; right: 0;
  display: none; gap: 2px;
  background: var(--raised); border: 1px solid var(--line);
  border-radius: 999px; padding: 3px 6px;
  z-index: 3;
}
.rx-pick button { border: 0; background: none; font-size: 15px;
  cursor: pointer; padding: 1px 3px; }
/* .open persists without hover on purpose: the picker must survive the
   mouse travelling up from the React button, across the neighbouring
   bubble's hover zone, to reach it. */
.rx-pick.open { display: flex; }

#composer {
  /* One height for every control in the row. The round buttons used to be
     38px against a 44px field and, bottom-aligned, sat 3px low -- close
     enough to look like a mistake rather than a choice. */
  --composer-h: 44px;
  display: flex; gap: 10px; align-items: flex-end;
  padding: 14px 20px;
  border-top: 1px solid var(--line);
}
#composer-input {
  flex: 1;
  resize: none;
  /* 22 + 20 + 2 = the shared 44: an explicit line-height makes the field's
     height arithmetic instead of whatever the font decides. */
  line-height: 22px;
  min-height: var(--composer-h);
  padding: 10px 14px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel); color: var(--ink);
  font: inherit;
  max-height: 40vh;
}
#composer-input:focus { outline: none; border-color: var(--accent); }
#composer-send {
  height: var(--composer-h);
  padding: 0 20px;
  border: 1px solid var(--accent); border-radius: 10px;
  background: none; color: var(--accent);
  font: inherit; cursor: pointer;
}
@media (hover: hover) {
  #composer-send:hover { background: var(--accent); color: #12161b; }
}
#composer-send:active { background: var(--accent); color: #12161b; }

/* --- small screens -------------------------------------------------------- */

@media (max-width: 720px) {
  /* The rail and the list share the screen; a conversation takes all of
     it. The column count MUST follow, or the pane -- the only visible
     child left -- lands in the rail's 54px and renders as a sliver. */
  #shell { grid-template-columns: 54px 1fr; }
  #shell.conversing { grid-template-columns: 1fr; }
  #shell.conversing #sidebar { display: none; }
  #shell.conversing #rail { display: none; }
  #shell:not(.conversing) #pane { display: none; }
  .msg { max-width: 88%; }

  #back-btn {
    display: inline-flex; align-items: center; gap: 6px;
    border: 0; background: none; padding: 2px 6px 2px 0;
    color: var(--accent); font: inherit; cursor: pointer;
  }
  .back-chevron { font-size: 26px; line-height: 1; }

  /* iOS auto-zooms any focused input under 16px, and that zoom is what
     turns the X axis into a scroll. 16px on everything focusable kills the
     zoom at the source; the page itself never scrolls sideways. */
  #composer-input, #new-dm-name, #context { font-size: 16px; }
}

/* ------------------------------------------ display names & forwarding -- */

/* The muted @handle after a display name. Inherits size; only fades. */
.handle { color: var(--dim); font-weight: 400; }
.msg-meta .handle { color: inherit; }

.msg-fwd {
  display: block;
  font-size: 12px;
  color: var(--accent);
  opacity: .85;
  margin: 0 0 2px;
}

/* ------------------------------------------------ touch: swipe & sheet -- */

.msg { transition: transform .18s ease; }
.msg.swiping { transition: none; }

@media (hover: none) {
  /* Long-press opens our sheet; the OS text-selection callout would fight
     it. Copy lives in the sheet instead. The guard covers the whole message
     region, not just the bubble: iOS happily starts a selection from the
     meta line or the gap between bubbles and grows it into the text. */
  #messages, #messages * {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
  }
}
/* And during any active touch on a bubble, everywhere -- the JS adds this
   class on touchstart and removes it on settle. */
body.touching-msg, body.touching-msg * {
  -webkit-user-select: none;
  user-select: none;
}

.sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(0, 0, 0, .45);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.sheet-box {
  background: var(--panel);
  border-top: 1px solid var(--line);
  border-radius: 14px 14px 0 0;
  padding: 12px 14px calc(14px + env(safe-area-inset-bottom));
  max-height: 70vh;
  overflow-y: auto;
}

@media (min-width: 700px) {
  /* On a wide screen the same sheet floats as a centred card. */
  .sheet-overlay { justify-content: center; align-items: center; }
  .sheet-box {
    border: 1px solid var(--line);
    border-radius: 14px;
    min-width: 320px;
    max-width: 420px;
  }
}

.sheet-rx {
  display: flex;
  justify-content: space-between;
  gap: 4px;
  margin-bottom: 10px;
}
.sheet-rx button {
  flex: 1;
  font-size: 24px;
  padding: 8px 0;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: 10px;
  cursor: pointer;
}

.sheet-title {
  margin: 0 0 10px;
  font-size: 13px;
  color: var(--dim);
  text-transform: uppercase;
  letter-spacing: .06em;
}

.sheet-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  padding: 12px 10px;
  font-size: 16px;
  color: var(--ink);
  background: none;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
}
.sheet-item:active { background: var(--raised); }
.sheet-glyph { width: 22px; text-align: center; color: var(--dim); }
.sheet-item img { width: 28px; height: 28px; }

.sheet-info {
  margin: 8px 10px 0;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--dim);
}

/* ------------------------------------------------------- attachments UI -- */

#attach {
  width: var(--composer-h); height: var(--composer-h); flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--raised); color: var(--dim);
  font-size: 22px; line-height: 1; cursor: pointer;
  transition: color .15s, border-color .15s, transform .15s;
}
#attach:hover, #attach.open {
  color: var(--accent); border-color: var(--accent);
}
#attach.open { transform: rotate(45deg); } /* + becomes an x while open */

#composer { position: relative; }
#attach-menu {
  position: absolute; left: 16px; bottom: calc(100% + 8px);
  min-width: 180px; padding: 6px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
  z-index: 30;
}
#attach-menu button {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 10px 12px;
  background: none; border: 0; border-radius: 8px;
  color: var(--ink); font-size: 15px; text-align: left; cursor: pointer;
}
#attach-menu button:hover, #attach-menu button:active {
  background: var(--raised);
}
.am-glyph { width: 24px; text-align: center; font-size: 17px; }
.am-gif {
  font-size: 10px; font-weight: 700; letter-spacing: .04em;
  border: 1.5px solid currentColor; border-radius: 5px;
  padding: 1px 0; color: var(--accent);
}

#upload-pill {
  align-self: flex-start;
  margin: 6px 20px 0; padding: 5px 14px;
  background: var(--raised); border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 12.5px; color: var(--dim);
}
#upload-pill.err { color: var(--danger); border-color: var(--danger); }

.msg-image {
  display: block; margin-top: 4px;
  max-width: min(320px, 66vw); max-height: 340px;
  border-radius: 12px; cursor: zoom-in;
}
.msg-file {
  display: inline-flex; align-items: center; gap: 10px;
  margin-top: 4px; padding: 9px 14px;
  background: var(--raised); border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--ink); text-decoration: none; font-size: 14px;
  max-width: 100%;
}
.msg-file:hover { border-color: var(--accent); }
.msg-file .mf-size { color: var(--dim); font-size: 12px; flex-shrink: 0; }
.msg-file .mf-name { overflow: hidden; text-overflow: ellipsis;
                     white-space: nowrap; }

/* --------------------------------------------------------- GIF picker -- */

#gif-picker .sheet-box { width: min(440px, 100%); }
#gif-search {
  width: 100%; padding: 10px 14px; margin-bottom: 10px;
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: 10px;
  font-size: 16px; font-family: inherit;
}
#gif-search:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
#gif-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
  max-height: 46vh; overflow-y: auto;
}
#gif-grid button {
  padding: 0; border: 0; border-radius: 8px; overflow: hidden;
  background: var(--raised); cursor: pointer; aspect-ratio: 1;
}
#gif-grid img { width: 100%; height: 100%; object-fit: cover; display: block; }
#gif-empty { color: var(--dim); font-size: 13.5px; text-align: center;
             padding: 18px 0; }

/* ------------------------------------------------ mute, in the sidebar -- */

.conv-mute { flex-shrink: 0; font-size: 11px; opacity: .8; }
.conv.muted .conv-unread { background: var(--line); color: var(--dim); }

/* -------------------------------------------------- formatting in chat -- */

.msg-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  background: rgba(0, 0, 0, .3);
  border-radius: 5px;
  padding: 1px 5px;
}
.msg-code {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  background: rgba(0, 0, 0, .3);
  border-radius: 8px;
  padding: 8px 10px;
  margin: 4px 0 0;
  max-width: 66vw;
  overflow-x: auto;
  white-space: pre;
}

/* --------------------------------------------------- unread divider -- */

.unread-divider {
  list-style: none;
  display: flex; align-items: center; gap: 10px;
  margin: 12px 0 6px;
  color: var(--accent);
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .08em;
}
.unread-divider::before, .unread-divider::after {
  content: ""; flex: 1; height: 1px;
  background: var(--line);
}

/* -------------------------------------------------------- search bar -- */

#conv-search {
  background: none; border: 0; cursor: pointer;
  font-size: 15px; padding: 4px 8px; color: var(--dim);
}
#conv-search:hover { color: var(--ink); }
#search-bar {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  padding: 8px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}
#search-input {
  flex: 1; padding: 8px 12px;
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: 8px;
  font-size: 16px; font-family: inherit;
}
#search-input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
#search-close {
  background: none; border: 0; color: var(--dim);
  font-size: 20px; cursor: pointer; padding: 0 4px;
}
#search-results {
  position: absolute; left: 20px; right: 20px; top: calc(100% + 2px);
  max-height: 50vh; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 0 0 10px 10px;
  box-shadow: 0 14px 30px rgba(0, 0, 0, .5);
  z-index: 25;
}
.sr-row {
  display: block; width: 100%; text-align: left;
  padding: 9px 14px; background: none; border: 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink); font-size: 13.5px; cursor: pointer;
}
.sr-row:last-child { border-bottom: 0; }
.sr-row:hover { background: var(--raised); }
.sr-when { color: var(--dim); font-size: 11.5px; margin-right: 8px; }
.sr-none { padding: 12px 14px; color: var(--dim); font-size: 13px; }

#load-newer {
  display: block; margin: 8px auto;
  background: var(--raised); color: var(--dim);
  border: 1px solid var(--line); border-radius: 999px;
  padding: 5px 16px; font-size: 12.5px; cursor: pointer;
}
#load-newer:hover { color: var(--ink); }

.msg.hilite { animation: hilite 2.2s ease-out; }
@keyframes hilite {
  0%, 35% { box-shadow: 0 0 0 2px var(--accent); }
  100% { box-shadow: 0 0 0 2px transparent; }
}

/* mute controls in the details panel */
.mute-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
            margin: 8px 0 4px; }
.mute-row .lbl { font-size: 12.5px; color: var(--dim); margin-right: 4px; }

/* --------------------------------------------- staged attachment strip -- */

#stage-strip {
  display: flex; align-items: center; gap: 10px;
  margin: 6px 20px 0;
  padding: 6px 10px;
  background: var(--raised); border: 1px solid var(--line);
  border-radius: 10px;
  font-size: 13px;
  align-self: flex-start;
}
#stage-thumb {
  width: 44px; height: 44px; object-fit: cover; border-radius: 8px;
}
#stage-name { color: var(--dim); max-width: 240px;
              overflow: hidden; text-overflow: ellipsis;
              white-space: nowrap; }
#stage-cancel {
  background: none; border: 0; color: var(--dim);
  font-size: 18px; cursor: pointer; padding: 0 2px;
}
#stage-cancel:hover { color: var(--danger); }

#settings-link {
  color: var(--dim); text-decoration: none; font-size: 15px;
}
#settings-link:hover { color: var(--ink); }

/* ------------------------------------------------------ profile cards -- */

.pf-click { cursor: pointer; }
@media (hover: hover) { .pf-click:hover { text-decoration: underline; } }
img.pf-click:hover, #conv-avatar.pf-click:hover { text-decoration: none;
  filter: brightness(1.15); }

.pf-anchor-ov { position: fixed; inset: 0; z-index: 40; }
.profile-card.pf-pop {
  position: fixed;
  width: 300px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 16px 44px rgba(0, 0, 0, .55);
  padding: 16px;
}
.pf-head { display: flex; align-items: center; gap: 14px; }
.pf-face { width: 64px; height: 64px; border-radius: 16px;
           object-fit: contain; flex-shrink: 0; }
.pf-who { min-width: 0; }
.pf-name { font-size: 17px; font-weight: 600; overflow-wrap: anywhere; }
.pf-name .handle { font-weight: 400; font-size: 14px; }
.pf-presence { margin-top: 3px; font-size: 12.5px; color: var(--dim); }
.pf-since {
  margin-top: 12px; padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 12.5px; color: var(--dim);
}
.pf-actions { display: flex; flex-direction: column; gap: 8px;
              margin-top: 12px; }
.pf-btn {
  display: block; width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--raised); color: var(--ink);
  font-size: 14px; font-family: inherit;
  text-align: center; text-decoration: none; cursor: pointer;
}
.pf-btn:disabled { color: var(--dim); cursor: default; }
.pf-btn.primary { background: var(--accent); color: #17130a;
                  border: 0; font-weight: 600; }
.pf-btn.danger { color: var(--danger); }
@media (hover: hover) {
  .pf-btn:not(:disabled):hover { border-color: var(--accent); }
  .pf-btn.primary:hover { filter: brightness(1.08); }
}

/* ---------------------------------------------------------- group icon -- */

.grp-icon-row { display: flex; align-items: center; gap: 10px;
                margin-bottom: 12px; }
.grp-icon { position: relative; display: inline-block; margin: 0; }
.grp-icon img { width: 52px; height: 52px; border-radius: 14px;
                object-fit: contain; background: var(--bg); }
.grp-icon input[type="file"] { display: none; }
.grp-icon.editable { cursor: pointer; }
.grp-icon .ae-glyph {
  position: absolute; right: -4px; bottom: -4px;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(11, 16, 22, .85); color: var(--ink);
  border: 1px solid var(--line); border-radius: 999px;
  font-size: 11px; line-height: 1;
}
.grp-icon.editable:hover img { filter: brightness(.6); }
.grp-icon.editable:hover .ae-glyph { background: var(--accent);
                                     color: #17130a;
                                     border-color: var(--accent); }

/* ---------------------------------------------------------- mentions -- */

.mention {
  color: var(--accent);
  background: rgba(216, 184, 114, .14);
  border-radius: 5px;
  padding: 0 4px;
  cursor: pointer;
}
.mention.me { background: rgba(216, 184, 114, .3); font-weight: 600; }
/* A message that names you keeps a quiet accent spine, so it is findable
   while scrolling a busy group. */
.msg.mentions-me { box-shadow: inset 3px 0 0 var(--accent); }

#mention-pop {
  position: absolute; left: 20px; bottom: calc(100% + 6px);
  min-width: 220px; max-width: min(360px, 80vw);
  padding: 4px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, .5);
  z-index: 30;
}
.mp-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 7px 10px;
  background: none; border: 0; border-radius: 8px;
  color: var(--ink); font-size: 14px; text-align: left; cursor: pointer;
}
.mp-row.sel, .mp-row:hover { background: var(--raised); }

/* ---------------------------------------------------------- lightbox -- */

.embed-naked { cursor: zoom-in; }

.lb-overlay {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .88);
  padding: 24px;
}
.lb-img {
  max-width: 92vw;
  max-height: 84vh;
  border-radius: 10px;
  object-fit: contain;
  cursor: default;
  transition: transform .12s ease-out;
}
.lb-close {
  position: absolute;
  top: calc(12px + env(safe-area-inset-top)); right: 14px;
  width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(26, 34, 45, .85); color: var(--ink);
  border: 1px solid var(--line); border-radius: 999px;
  font-size: 22px; line-height: 1; cursor: pointer;
}
.lb-close:hover { border-color: var(--accent); color: var(--accent); }
.lb-bar {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(14px + env(safe-area-inset-bottom));
  display: flex; align-items: center; justify-content: center;
  gap: 14px; padding: 0 20px;
  font-size: 12.5px; color: var(--dim);
}
.lb-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
           max-width: 60vw; }
.lb-orig { color: var(--accent); text-decoration: none; }
.lb-orig:hover { text-decoration: underline; }

/* -------------------------------------------------------- voice notes -- */

#mic {
  width: var(--composer-h); height: var(--composer-h); flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--raised); color: var(--dim);
  font-size: 16px; line-height: 1; cursor: pointer;
}
#mic:hover { color: var(--accent); border-color: var(--accent); }
#mic.recording { color: var(--danger); border-color: var(--danger); }

#rec-bar {
  display: flex; align-items: center; gap: 10px;
  align-self: flex-start;
  margin: 6px 20px 0; padding: 6px 12px;
  background: var(--raised); border: 1px solid var(--danger);
  border-radius: 999px; font-size: 13px;
}
.rec-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--danger);
  animation: recpulse 1.1s ease-in-out infinite;
}
@keyframes recpulse { 0%, 100% { opacity: 1 } 50% { opacity: .25 } }
#rec-time { font-variant-numeric: tabular-nums; color: var(--ink); }
.rec-hint { color: var(--dim); }
#rec-bar button {
  background: none; border: 1px solid var(--line); border-radius: 999px;
  color: var(--dim); font-size: 12px; padding: 3px 10px; cursor: pointer;
}
#rec-bar button.yes { color: var(--accent); border-color: var(--accent); }

.msg-voice { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.msg-voice audio { height: 36px; max-width: min(260px, 60vw); }
.voice-len { font-size: 11.5px; color: var(--dim);
             font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ drop ----- */

#drop-veil {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  background: rgba(11, 16, 22, .8);
  border: 2px dashed var(--accent);
  color: var(--accent); font-size: 17px;
  pointer-events: none;      /* the drop must reach the window beneath */
}

/* ------------------------------------------------------ community rail -- */

#rail {
  background: var(--bg);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column; align-items: center;
  gap: 8px; padding: 10px 0;
  overflow-y: auto; min-height: 0;
}
.rail-btn {
  position: relative;
  width: 42px; height: 42px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  background: var(--raised); color: var(--dim);
  border: 1px solid var(--line); border-radius: 14px;
  font-size: 18px; cursor: pointer;
  transition: border-radius .15s, border-color .15s;
}
.rail-btn img { width: 100%; height: 100%; border-radius: 13px;
                object-fit: contain; }
.rail-btn:hover { border-radius: 999px; border-color: var(--accent); }
.rail-btn.active { border-color: var(--accent); }
/* The spine Discord taught everyone to read as "you are here". */
.rail-btn.active::before {
  content: ""; position: absolute; left: -11px;
  width: 3px; height: 22px; border-radius: 0 3px 3px 0;
  background: var(--accent);
}
.rail-unread {
  position: absolute; right: -3px; top: -3px;
  min-width: 16px; height: 16px; padding: 0 4px;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #17130a;
  border-radius: 999px; font-size: 10px; font-weight: 700;
}
.rail-sep { width: 24px; height: 1px; background: var(--line);
            flex-shrink: 0; }

#community-head {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
}
#community-name { flex: 1; min-width: 0; font-weight: 600; font-size: 15px;
                  overflow: hidden; text-overflow: ellipsis;
                  white-space: nowrap; }
#community-info { background: none; border: 0; color: var(--dim);
                  font-size: 16px; cursor: pointer; padding: 2px 6px; }
#community-info:hover { color: var(--ink); }
/* Settings, as their own thing over the app. Wider than the action sheets
   this shares a shell with, because a form with permissions in it is not a
   list of four buttons. */
.settings-box { width: min(560px, 100%); }
@media (min-width: 700px) {
  .settings-box { min-width: 480px; max-width: 560px; }
}
.set-head { display: flex; align-items: center; gap: 10px; }
.set-head .sheet-title { flex: 1; margin-bottom: 0; }
.set-x {
  background: none; border: 0; color: var(--dim);
  font-size: 22px; line-height: 1; cursor: pointer; padding: 0 4px;
}
.set-x:hover { color: var(--ink); }
.set-body { margin-top: 12px; }
.set-body .fr-row { padding: 5px 0; }
.set-input {
  flex: 1; min-width: 0;
  font: inherit; font-size: 14px;
  color: var(--ink); background: var(--raised);
  border: 1px solid var(--line); border-radius: 8px;
  padding: 7px 10px;
}
.set-body button.danger { color: var(--danger); border-color: var(--line); }
.set-body button.danger:hover { border-color: var(--danger); }

/* A channel row: the conversation button, and the gear beside it. Two
   controls, so two elements -- one nested in the other would be invalid
   markup and one confused control to a screen reader. */
.conv-row { display: flex; align-items: center; }
.conv-row .conv { flex: 1; min-width: 0; }
/* Hidden until the row is hovered or the gear itself has focus, so the list
   stays a list -- but always faintly present on a touchscreen, which has no
   hover to reveal it with. */
.chan-gear {
  flex-shrink: 0;
  margin-left: 2px;
  padding: 4px 6px;
  background: none; border: 0; border-radius: 6px;
  color: var(--dim);
  font: inherit; font-size: 13px; line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s ease, color .12s ease;
}
.conv-row:hover .chan-gear,
.chan-gear:focus-visible { opacity: 1; }
.chan-gear:hover { color: var(--accent); background: var(--raised); }
@media (hover: none) {
  .chan-gear { opacity: .5; }
}

#community-panel { padding: 10px 14px;
                   border-bottom: 1px solid var(--line); }
#new-channel {
  margin: 10px 14px 2px; padding: 7px 10px;
  background: none; border: 1px dashed var(--line); border-radius: 8px;
  color: var(--dim); font-size: 13px; cursor: pointer;
}
#new-channel:hover { border-color: var(--accent); color: var(--accent); }
.chan-hash { color: var(--dim); margin-right: 5px; }

/* the community settings panel borrows the friends-row look, but its own
   form input needs the same dressing the other search boxes have */
#community-panel .fr-row { padding: 5px 0; }
#community-panel #add-member { margin: 8px 0 10px; }
#community-panel #add-member input {
  width: 100%; padding: 7px 10px;
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: 8px;
  font-size: 16px; font-family: inherit;
}
#community-panel #add-member input:focus {
  outline: 2px solid var(--accent); outline-offset: -1px;
}
#community-panel .grp-icon-row { margin-bottom: 10px; }

/* ---------------------------------------------------------- invites -- */

.invite-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
}
.invite-row:last-child { border-bottom: 0; }
.invite-code {
  flex: 1; min-width: 140px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; color: var(--accent);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.invite-meta { font-size: 11px; color: var(--dim); }
.hint-line { margin: 4px 0; font-size: 12.5px; color: var(--dim); }
.invite-card.pf-pop { position: static; width: min(340px, 92vw); }

/* -------------------------------------------------- invite in a message -- */

.invite-embed {
  margin-top: 8px; padding: 10px 12px;
  max-width: min(340px, 70vw);
  background: rgba(0, 0, 0, .22);
  border-left: 3px solid var(--accent);
  border-radius: 6px;
}
.ie-label {
  font-size: 11px; color: var(--dim);
  text-transform: uppercase; letter-spacing: .07em;
  margin-bottom: 8px;
}
.ie-row { display: flex; align-items: center; gap: 10px; min-height: 34px; }
.ie-row .av { width: 40px; height: 40px; border-radius: 12px; }
.ie-who { flex: 1; min-width: 0; }
.ie-name { font-weight: 600; font-size: 14.5px;
           overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ie-sub { font-size: 12px; color: var(--dim); }
.ie-dead { font-size: 12.5px; color: var(--dim); }
.ie-join {
  flex-shrink: 0; padding: 7px 14px;
  background: var(--accent); color: #17130a;
  border: 0; border-radius: 8px;
  font-size: 13px; font-weight: 600; font-family: inherit; cursor: pointer;
}
.ie-join.in { background: none; color: var(--accent);
              border: 1px solid var(--accent); }
.ie-join:hover { filter: brightness(1.08); }

/* ------------------------------------------------------- presence menu -- */

#mode-menu {
  position: fixed; z-index: 45;
  min-width: 230px; padding: 5px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, .5);
}
.mm-row {
  display: flex; align-items: flex-start; gap: 10px;
  width: 100%; padding: 8px 10px;
  background: none; border: 0; border-radius: 8px;
  color: var(--ink); text-align: left; cursor: pointer;
}
.mm-row:hover { background: var(--raised); }
.mm-row.sel { background: var(--raised); }
.mm-row .pdot { margin-top: 5px; flex-shrink: 0; }
.mm-name { display: block; font-size: 14px; }
.mm-hint { display: block; font-size: 11.5px; color: var(--dim);
           margin-top: 1px; }

/* ------------------------------------------------------ video messages -- */

/* A pointy-top hexagon, the same silhouette as every crest in the family:
   vertices every 60 degrees from straight up, at half the box. */
.hexed {
  clip-path: polygon(50% 0%, 93.3% 25%, 93.3% 75%,
                     50% 100%, 6.7% 75%, 6.7% 25%);
}

#cam {
  width: var(--composer-h); height: var(--composer-h); flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--raised); color: var(--dim);
  font-size: 16px; line-height: 1; cursor: pointer;
}
#cam:hover { color: var(--accent); border-color: var(--accent); }

.msg-video {
  position: relative; display: inline-block; margin-top: 4px;
  width: 220px; height: 220px;
}
.msg-video video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  background: #000;
  clip-path: polygon(50% 0%, 93.3% 25%, 93.3% 75%,
                     50% 100%, 6.7% 75%, 6.7% 25%);
}
.mv-play {
  position: absolute; inset: 0; margin: auto;
  width: 52px; height: 52px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .5); color: #fff;
  border: 0; border-radius: 999px;
  font-size: 17px; cursor: pointer;
  transition: opacity .18s;
}
.msg-video.playing .mv-play { opacity: 0; }
.msg-video:hover .mv-play { opacity: 1; }
.mv-len {
  position: absolute; bottom: 14px; left: 0; right: 0;
  text-align: center;
  font-size: 11px; color: #fff;
  text-shadow: 0 1px 4px rgba(0, 0, 0, .9);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.vid-overlay {
  align-items: center; justify-content: center;
  flex-direction: column; gap: 18px;
}
.vid-stage { position: relative; width: min(280px, 74vw);
             aspect-ratio: 1; }
.vid-preview {
  width: 100%; height: 100%; object-fit: cover; background: #000;
  transform: scaleX(-1);          /* a mirror, the way a camera should read */
  clip-path: polygon(50% 0%, 93.3% 25%, 93.3% 75%,
                     50% 100%, 6.7% 75%, 6.7% 25%);
}
.vid-ring {
  position: absolute; inset: -3px;
  clip-path: polygon(50% 0%, 93.3% 25%, 93.3% 75%,
                     50% 100%, 6.7% 75%, 6.7% 25%);
  background: var(--danger);
  z-index: -1;
  animation: recpulse 1.1s ease-in-out infinite;
}
.vid-bar { display: flex; align-items: center; gap: 12px; }
.vid-time { color: var(--ink); font-variant-numeric: tabular-nums;
            font-size: 15px; }
.vid-bar .pf-btn { width: auto; padding: 9px 18px; }

/* --------------------------------------------- the composer gives way -- */

/* Nothing to send yet: offer the ways to make something, and no Send. */
#composer:not(.sending) #composer-send { display: none; }
/* Something to send: the makers step aside. */
#composer.sending #cam,
#composer.sending #mic { display: none; }

@media (max-width: 720px) {
  /* On a phone the keyboard being up is reason enough -- the field wants
     the whole bar while you are writing in it. */
  #composer.focused #cam,
  #composer.focused #mic { display: none; }
}

/* ------------------------------------------------ which deployment -- */

/* Which deployment am I looking at? A thin strip, only ever present
   when an environment names itself -- production sets nothing and the
   markup is absent entirely. */
.envbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  height: 22px; line-height: 22px;
  background: var(--accent); color: #17130a;
  font-size: 11px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  text-align: center;
}
body.has-envbar { padding-top: 22px; }
/* The app measures itself against the viewport, so it has to give the
   strip its height back or the composer falls off the bottom. */
body.has-envbar #app { height: calc(100vh - 22px);
                       height: calc(100dvh - 22px); }

/* --------------------------------------------------------- reports ----- */

/* The moderation queue reuses the sheet, but a report needs more room than
   a list of actions: the message, the reason and three buttons per row. */
.reports-box { width: min(620px, 100%); }
@media (min-width: 700px) {
  .reports-box { min-width: 520px; max-width: 620px; }
}

.rep-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 12px;
}
.rep-tabs button,
.rep-acts button {
  padding: 5px 10px;
  font-size: 12.5px;
  color: var(--dim);
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
}
.rep-tabs button.yes,
.rep-acts button.yes { border-color: var(--accent); color: var(--accent); }
.rep-tabs button:hover,
.rep-acts button:hover { color: var(--ink); }

.rep-row {
  padding: 10px 0;
  border-top: 1px solid var(--line);
}
.rep-row:first-of-type { border-top: 0; }
.rep-who { font-size: 12.5px; color: var(--dim); }
.rep-body {
  margin: 4px 0;
  font-size: 14px;
  color: var(--ink);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.rep-why {
  margin-bottom: 6px;
  font-size: 12.5px;
  color: var(--accent);
  overflow-wrap: anywhere;
}
.rep-acts { display: flex; gap: 6px; flex-wrap: wrap; }

/* The window either side of the reported message. Numbered so a moderator
   can say "the third line" to somebody looking at the same screen. */
.rep-context {
  margin: 0;
  padding: 0 0 0 4px;
  list-style: none;
  max-height: 46vh;
  overflow-y: auto;
}
.rep-line {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 5px 8px;
  border-radius: 8px;
}
.rep-line-who { font-size: 11.5px; color: var(--dim); }
.rep-line-body {
  font-size: 14px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* The one being judged, so it is not hunted for among its neighbours. */
.rep-line.flagged {
  background: rgba(216, 184, 114, .12);
  box-shadow: inset 2px 0 0 var(--accent);
}

.rail-btn.rail-mod { color: var(--accent); }

/* A message deleted after being reported still shows its text -- the row
   keeps it for a day precisely so deleting cannot outrun a report -- so
   the fact of the deletion has to be said rather than implied by absence. */
.rep-deleted {
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--dim);
  font-style: italic;
}

/* An attachment whose sender deleted it from their drive. Chat keeps no
   copy of its own any more, so this is the honest end state rather than a
   broken image icon. */
.msg-gone {
  display: inline-block;
  padding: 7px 11px;
  border: 1px dashed var(--line);
  border-radius: 10px;
  color: var(--dim);
  font-size: 13px;
  font-style: italic;
}

/* The page a deleted attachment's own URL serves, for anyone who follows
   the link directly rather than seeing it in a conversation. */
.gone-page {
  max-width: 30rem;
  margin: 18vh auto 0;
  padding: 0 20px;
  text-align: center;
  color: var(--dim);
}
.gone-page h1 { color: var(--ink); font-size: 20px; margin: 0 0 8px; }

/* --- jump to the latest ---------------------------------------------- */

/* Zero height and sticky: it pins to the bottom of the scrollport without
   adding a line to the end of the conversation, and without anything here
   needing to know how tall the composer happens to be. */
#to-bottom-wrap {
  position: sticky;
  bottom: 0;
  height: 0;
  display: flex;
  justify-content: flex-end;
  pointer-events: none;
  z-index: 5;
}
#to-bottom {
  pointer-events: auto;
  transform: translateY(-46px);
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 38px;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--raised);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}
#to-bottom:hover { border-color: var(--accent); color: var(--accent); }
.tb-arrow { font-size: 15px; line-height: 1; }
/* A count only when something actually arrived while you were up reading;
   otherwise the button is just an arrow and says nothing it cannot back up. */
#to-bottom-count {
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  font-weight: 600;
}
#to-bottom.unread { border-color: var(--accent); }

@media (max-width: 700px) {
  #to-bottom { transform: translateY(-14px); }
}

/* Unverified, on a deployment that asks for it. A standing strip rather
   than a passing toast: it describes a state, not an event, and it stops
   being shown when it stops being true.

   Fixed and full width, like .envbar, and for the same reason -- #shell is
   a three-column grid, so anything placed inside it becomes a grid item
   and steals a column. */
#gate-note {
  position: fixed; left: 0; right: 0; z-index: 90;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  height: 34px;
  padding: 0 16px;
  background: rgba(216, 184, 114, .12);
  border-bottom: 1px solid var(--accent);
  color: var(--ink);
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
}
#gate-note a { color: var(--accent); font-weight: 600; }
/* Both strips can be present at once, so each has to know about the other:
   the env bar sits at the top and this one under it. */
body.has-envbar #gate-note { top: 22px; }
body.has-gate { padding-top: 34px; }
body.has-gate #app { height: calc(100vh - 34px);
                     height: calc(100dvh - 34px); }
body.has-envbar.has-gate { padding-top: 56px; }
body.has-envbar.has-gate #app { height: calc(100vh - 56px);
                                height: calc(100dvh - 56px); }

@media (max-width: 700px) {
  #gate-note { font-size: 12px; gap: 6px; }
}

/* No communities for this account, so no rail: the grid loses its first
   column rather than keeping an empty one. */
#shell.no-rail { grid-template-columns: 280px 1fr; }
@media (max-width: 700px) {
  #shell.no-rail { grid-template-columns: 1fr; }
}
