*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  :root {
    --bg:       #0d0d0d;
    --surface:  #141414;
    --surface2: #1a1a1a;
    --border:   #2a2a2a;
    --muted:    #555;
    --dim:      #888;
    --text:     #e0e0e0;
    --accent:   #4fc3f7;
    --online:   #4caf50;
    --mine:     #1e3a4a;
    --theirs:   #1e1e1e;
    --danger:   #e57373; 
  }

  body { font-family: 'Courier New', monospace; background: var(--bg); color: var(--text); height: 100vh; overflow: hidden; }

  /* ── LOGIN ── */
  #loginScreen { display: flex; align-items: center; justify-content: center; height: 100vh; }
  #loginBox {
    display: flex; flex-direction: column; gap: 12px;
    width: 320px; padding: 40px 32px;
    background: var(--surface); border: 1px solid var(--border);
  }
  #loginBox h2 { font-size: 22px; letter-spacing: 0.3em; color: var(--accent); }
  .subtitle { font-size: 11px; color: var(--muted); letter-spacing: 0.15em; margin-top: -6px; margin-bottom: 8px; }
  #loginBox input {
    background: var(--bg); border: 1px solid var(--border); color: var(--text);
    padding: 10px 12px; font-family: inherit; font-size: 13px; outline: none; transition: border-color 0.2s;
  }
  #loginBox input:focus { border-color: var(--accent); }
  #loginBox button {
    background: var(--accent); color: #000; border: none; padding: 10px;
    font-family: inherit; font-size: 13px; font-weight: bold; letter-spacing: 0.15em;
    cursor: pointer; transition: opacity 0.2s;
  }
  #loginBox button:hover    { opacity: 0.85; }
  #loginBox button:disabled { opacity: 0.4; cursor: default; }
  #loginStatus { font-size: 11px; color: var(--dim); min-height: 16px; letter-spacing: 0.05em; }
  #loginNotice { font-size: 11px; color: var(--muted); line-height: 1.6; padding: 10px; border: 1px solid var(--border); }
  #loginNotice strong { color: var(--dim); }

  /* ── APP ── */
  #appContainer { display: none; height: 100vh; }

  /* ── SIDEBAR ── */
  #sidebar {
    width: 260px; min-width: 260px; display: flex; flex-direction: column;
    background: var(--surface); border-right: 1px solid var(--border);
  }
  #sidebarHeader {
    display: flex; align-items: flex-start; justify-content: space-between;
    padding: 20px 16px 16px; border-bottom: 1px solid var(--border);
  }
  #sidebarTitle { font-size: 14px; letter-spacing: 0.3em; color: var(--accent); }
  #sidebarMeta  { font-size: 10px; color: var(--muted); letter-spacing: 0.05em; margin-top: 4px; }
  #exportBtn {
    background: none; border: 1px solid var(--border); color: var(--dim);
    width: 28px; height: 28px; font-size: 18px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: border-color 0.2s, color 0.2s; flex-shrink: 0;
  }
  #exportBtn:hover { border-color: var(--accent); color: var(--accent); }
  
  #meshLogToggle {
    background: none; border: 1px solid var(--border); color: var(--dim);
    width: 28px; height: 28px; font-size: 18px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: border-color 0.2s, color 0.2s; flex-shrink: 0;
  }
  #meshLogToggle:hover { border-color: var(--accent); color: var(--accent); }
  
  #addContactBtn {
    background: none; border: 1px solid var(--border); color: var(--dim);
    width: 28px; height: 28px; font-size: 18px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: border-color 0.2s, color 0.2s; flex-shrink: 0;
  }
  #addContactBtn:hover { border-color: var(--accent); color: var(--accent); }
  #contactList { list-style: none; flex: 1; overflow-y: auto; }
  #contactList::-webkit-scrollbar { width: 4px; }
  #contactList::-webkit-scrollbar-thumb { background: var(--border); }
  .contactItem {
    display: flex; align-items: center; gap: 10px; padding: 12px 16px; cursor: pointer;
    border-bottom: 1px solid var(--border); transition: background 0.15s;
	position: relative;
  }
  .contactItem:hover  { background: var(--surface2); }
  .contactItem.active { background: var(--surface2); border-left: 2px solid var(--accent); }
  .contactAvatar {
    width: 34px; height: 34px; background: var(--surface2); border: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center;
    font-size: 14px; color: var(--accent); flex-shrink: 0;
  }
  .contactInfo { flex: 1; min-width: 0; }
  .contactName { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .contactId   { font-size: 10px; color: var(--muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .contactStatus {
    width: 7px; height: 7px; border-radius: 50%;
    background: #111; /* default off — JS controls online colour */
    flex-shrink: 0;
  }
  #syncStatus { font-size: 10px; color: var(--muted); padding: 6px 16px; border-top: 1px solid var(--border); letter-spacing: 0.05em; min-height: 26px; }
  #connectionStatus {
    display: flex; align-items: center; gap: 8px; padding: 12px 16px;
    border-top: 1px solid var(--border); font-size: 10px; color: var(--muted); letter-spacing: 0.05em;
  }
  #connDot { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); flex-shrink: 0; transition: background 0.3s; }
  #connDot.connected { background: var(--online); }

  /* ── CHAT ── */
  #chatContainer { flex: 1; display: flex; flex-direction: column; min-width: 0; }
  #chatHeader { padding: 16px 20px; border-bottom: 1px solid var(--border); min-height: 60px; display: flex; flex-direction: column; justify-content: center; }
  #emptyChat      { font-size: 12px; color: var(--muted); letter-spacing: 0.1em; }
  #chatHeaderName { font-size: 14px; letter-spacing: 0.1em; }
  #chatHeaderId   { font-size: 10px; color: var(--muted); margin-top: 3px; }
  #chatMessages { flex: 1; overflow-y: auto; padding: 20px; display: flex; flex-direction: column; gap: 8px; }
  #chatMessages::-webkit-scrollbar { width: 4px; }
  #chatMessages::-webkit-scrollbar-thumb { background: var(--border); }
  .message { position: relative; max-width: 65%; padding: 9px 14px 22px 14px; font-size: 13px; line-height: 1.5; word-break: break-word; white-space: pre-wrap;}
.message.no-reaction-pad { padding-bottom: 9px; align-self: flex-start;}
  .message.mine    { background: var(--mine);   align-self: flex-end;   color: var(--accent); }
  .message.mine.no-reaction-pad {
    align-self: flex-start;
}
  .message.theirs  { background: var(--theirs); align-self: flex-start; border: 1px solid var(--border); }
  .message.invalid { border-color: var(--danger) !important; opacity: 0.6; }
  .msgMeta { font-size: 10px; color: var(--muted); margin-top: 3px; display: flex; align-items: center; gap: 6px; }
.msgStatus { font-size: 10px; opacity: 0.85; letter-spacing: -1px; }
.msgStatus.failed { color: var(--danger); letter-spacing: normal; }
.systemMsgWrap { display: flex; justify-content: center; }
.systemMsg {
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.05em;
  padding: 4px 12px;
  margin: 4px 0;
  text-align: center;
  opacity: 0.85;
}
.systemMsg.invalid { color: var(--danger); opacity: 1; }
  .packetInfoBtn {
    background: none; border: none; color: var(--muted); font-size: 11px;
    cursor: pointer; padding: 0; line-height: 1; opacity: 0.5; transition: opacity 0.15s, color 0.15s;
  }
  .packetInfoBtn:hover { opacity: 1; color: var(--accent); }
  .packetInfoPre {
    margin-top: 4px; padding: 8px 10px; background: var(--bg); border: 1px solid var(--border);
    color: var(--dim); font-size: 10px; line-height: 1.5; white-space: pre-wrap; word-break: break-all;
    max-width: min(480px, 100%);
  }
  #chatInputContainer { display: flex; border-top: 1px solid var(--border); }
  #chatInput {
    flex: 1; background: var(--surface); border: none; color: var(--text);
    padding: 14px 16px; font-family: inherit; font-size: 13px; outline: none;
  }
  #sendButton {
    background: none; border: none; border-left: 1px solid var(--border); color: var(--accent);
    padding: 0 20px; font-family: inherit; font-size: 12px; letter-spacing: 0.15em; cursor: pointer; transition: background 0.2s;
  }
  #sendButton:hover { background: var(--surface2); }
  .chat-action-btn {
    background: none; border: none; border-left: 1px solid var(--border); color: var(--muted);
    padding: 0 14px; font-family: inherit; font-size: 11px; letter-spacing: 0.1em; cursor: pointer; transition: color 0.2s;
  }
  .chat-action-btn:hover { color: var(--accent); }

  /* ── MODALS ── */
  .overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.75); align-items: center; justify-content: center; z-index: 100; }
  .overlay.open { display: flex; }
  .modal-box {
    background: var(--surface); border: 1px solid var(--border);
    padding: 28px; width: 420px; display: flex; flex-direction: column; gap: 12px;
    max-height: 90vh; overflow-y: auto;
  }
  .modal-box h3 { font-size: 14px; letter-spacing: 0.3em; color: var(--accent); margin-bottom: 4px; }
  .modal-box input {
    background: var(--bg); border: 1px solid var(--border); color: var(--text);
    padding: 10px 12px; font-family: inherit; font-size: 13px; outline: none; transition: border-color 0.2s;
  }
  .modal-box input:focus { border-color: var(--accent); }
  .hint { font-size: 11px; color: var(--muted); line-height: 1.6; }
  .modal-btns { display: flex; gap: 8px; margin-top: 4px; }
  .modal-btns button {
    flex: 1; padding: 10px; font-family: inherit; font-size: 12px;
    letter-spacing: 0.15em; cursor: pointer; border: 1px solid var(--border); transition: all 0.2s;
  }
  .btn-cancel  { background: none; color: var(--dim); }
  .btn-confirm { background: var(--accent); color: #000; border-color: var(--accent); font-weight: bold; }
  .btn-alt     { background: none; color: var(--accent); }
  .btn-cancel:hover  { color: var(--text); border-color: var(--dim); }
  .btn-confirm:hover { opacity: 0.85; }
  .btn-alt:hover     { background: var(--surface2); }

  /* ── QR TABS ── */
  #myKeyBox {
    background: var(--bg); border: 1px solid var(--border); padding: 10px 12px;
    font-size: 11px; display: flex; flex-direction: column; gap: 4px;
    color: var(--muted); cursor: pointer; transition: border-color 0.2s;
  }
  #myKeyBox:hover { border-color: var(--accent); }
  #myKeyDisplay { color: var(--text); word-break: break-all; font-size: 10px; letter-spacing: 0.03em; line-height: 1.5; }

  .qr-tabs { display: flex; border: 1px solid var(--border); margin-bottom: 4px; }
  .qr-tab {
    flex: 1; padding: 8px 4px; background: none; border: none; border-right: 1px solid var(--border);
    color: var(--muted); font-family: inherit; font-size: 11px; letter-spacing: 0.1em; cursor: pointer; transition: all 0.2s;
  }
  .qr-tab:last-child { border-right: none; }
  .qr-tab.active { background: var(--surface2); color: var(--accent); }
  .qr-tab:hover:not(.active) { color: var(--text); }

  .qr-panel { display: none; flex-direction: column; align-items: center; gap: 10px; }
  .qr-panel.active { display: flex; }

  #myQrCode { background: white; padding: 12px; margin: 0 auto; }

  #qrReader { width: 100%; border: 1px solid var(--border); }
  #qrReader video { border-radius: 0 !important; }
  #qrReader img   { display: none !important; }

  #scanResult { font-size: 11px; color: var(--online); min-height: 16px; letter-spacing: 0.05em; text-align: center; }

  .scan-btn {
    width: 100%; padding: 9px; background: none; border: 1px solid var(--border);
    color: var(--accent); font-family: inherit; font-size: 11px; letter-spacing: 0.15em; cursor: pointer; transition: all 0.2s;
  }
  .scan-btn:hover   { background: var(--surface2); border-color: var(--accent); }
  .scan-btn.active  { color: var(--danger); border-color: var(--danger); }

  #exportStatus { font-size: 11px; color: var(--dim); min-height: 16px; }

  /* ── CONTACT ACTION MENU ── */
  #chatHeaderRow {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px;
  }
  #chatHeaderInfo { flex: 1; min-width: 0; }
  #contactMenuBtn {
    background: none; border: 1px solid var(--border); color: var(--dim);
    width: 28px; height: 28px; font-size: 16px; cursor: pointer; flex-shrink: 0;
    display: none; align-items: center; justify-content: center;
    transition: border-color 0.2s, color 0.2s;
  }
  #contactMenuBtn:hover { border-color: var(--accent); color: var(--accent); }
  #contactMenuBtn.visible { display: flex; }
  .contact-dropdown {
    position: absolute; top: 52px; right: 16px;
    background: var(--surface); border: 1px solid var(--border);
    display: none; flex-direction: column; z-index: 50; min-width: 140px;
  }
  .contact-dropdown.open { display: flex; }
  .contact-dropdown button {
    background: none; border: none; border-bottom: 1px solid var(--border);
    color: var(--text); padding: 10px 14px; font-family: inherit; font-size: 11px;
    letter-spacing: 0.12em; text-align: left; cursor: pointer; transition: background 0.15s;
  }
  .contact-dropdown button:last-child { border-bottom: none; }
  .contact-dropdown button:hover { background: var(--surface2); color: var(--accent); }
  .contact-dropdown button.danger:hover { color: var(--danger); }

  /* ── BLOCKED CONTACTS ── */
  .contactItem.blocked { opacity: 0.38; }
  .contactItem.blocked .contactName::after {
    content: ' · blocked';
    font-size: 9px; color: var(--danger); letter-spacing: 0.08em;
  }

  /* ── MOBILE ── */
  @media (max-width: 600px) {
    #appContainer { height: 100dvh; }
    #sidebar { width: 100%; min-width: unset; }
    #chatContainer { display: none; height: 100dvh; overflow: hidden; }
    #appContainer.chatOpen #sidebar       { display: none; }
    #appContainer.chatOpen #chatContainer { display: flex; width: 100%; }
    #chatMessages { flex: 1; min-height: 0; }
    #chatInputContainer { flex-shrink: 0; }
    #loginBox  { width: 90vw; padding: 32px 20px; }
    .modal-box { width: 92vw; padding: 20px 14px; }
    #backBtn   { display: block !important; }
  }

  .unreadBadge {
    background: var(--accent);
    color: black;
    font-size: 10px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-left: 6px;
  }

  #chatMessages a {
    color: var(--accent);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: all 0.15s ease;
    word-break: break-word;
  }

  #chatMessages a:hover {
    border-bottom: 1px solid var(--accent);
    filter: brightness(1.2);
  }

  .contactPreview {
    font-size: 10px;
    color: var(--muted);
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  
/* ── in-page log console ── */
#meshLog {
  display: none;
  position: fixed;
  bottom: 40px; left: 0;
  width: 440px; max-width: 100vw;
  max-height: 400px;
  background: #000;
  border: 1px solid #333;
  border-left: none;
  border-bottom: none;
  font-family: monospace;
  font-size: 11px;
  z-index: 9999;
  flex-direction: column;
  box-shadow: 2px -2px 12px rgba(0,0,0,.8);
}
#meshLog.open { display: flex; }
#meshLogHeader {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 8px;
  background: #111;
  color: #555;
  letter-spacing: .12em;
  font-size: 10px;
  border-bottom: 1px solid #222;
  user-select: none;
}
#meshLogHeader span { color: #444; }
#meshLogHeader button {
  background: none; border: none; cursor: pointer;
  color: #444; font-family: monospace; font-size: 10px;
  padding: 0 4px; letter-spacing: .08em;
}
#meshLogHeader button:hover { color: #aaa; }
#meshLogBody {
  overflow-y: auto;
  flex: 1;
  padding: 6px 8px;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.mlog-line       { color: #888; white-space: pre; line-height: 1.5; }
.mlog-line.info  { color: #ccc; }
.mlog-line.warn  { color: #f80; }
.mlog-line.err   { color: #f44; }
#meshLogToggle {

  background: #111;
  border: none; border-right: 1px solid #333; border-top: 1px solid #333;
  color: #444;
  font-family: monospace; font-size: 10px;
  letter-spacing: .12em;
  padding: 3px 10px;
  cursor: pointer;
  z-index: 9999;
}
#meshLogToggle:hover { color: #aaa; background: #1a1a1a; }

/* ── show blocked toggle ── */
#showBlockedToggle {
  padding: 4px 8px;
}
#showBlockedBtn {
  width: 100%;
  background: none;
  border: 1px solid #2a2a2a;
  color: #555;
  font-family: monospace;
  font-size: 10px;
  letter-spacing: .1em;
  padding: 4px 8px;
  cursor: pointer;
  text-align: left;
}
#showBlockedBtn:hover { color: #aaa; border-color: #444; }

#mediaButtons {
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--border);
  flex-shrink: 0;
}
#audioBtn,
#imageBtn {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 14px;
  padding: 0 10px;
  cursor: pointer;
  flex: 1;
  transition: color 0.1s, background 0.1s;
  line-height: 1;
}
#audioBtn {
  border-bottom: 1px solid var(--border);
}
#audioBtn:hover,
#imageBtn:hover {
  color: var(--accent);
  background: var(--surface2);
}
#audioBtn.recording {
  color: #f44;
  border-color: #f44;
  animation: pulse 1s infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.4; }
}
.message.mine img,
.message.theirs img {
  max-width: 200px;
  display: block;
  border-radius: 2px;
}
.reaction-trigger {
  display: block;
  text-align: right;
  font-size: 11px;
  color: var(--muted);
  cursor: pointer;
  margin-top: 4px;
  opacity: 0.5;
  transition: opacity 0.15s;
  user-select: none;
}
.reaction-trigger:hover {
  opacity: 1;
}
.reaction-picker {
  display: flex;
  gap: 4px;
  margin-top: 4px;
  justify-content: flex-end;
}
.reaction-picker button {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 14px;
  padding: 2px 7px;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 0.15s;
}
.reaction-picker button:hover {
  border-color: var(--accent);
}
.reaction-row {
  font-size: 14px;
  margin-top: 2px;
  opacity: 0.85;
}

/* ── reactions ── */
.reaction-row {
  /* positioned absolutely inside .message — see JS */
}
.reaction-emoji {
  font-size: 13px;
  background: none;
  border: none;
  cursor: default;
  padding: 0 2px;
  line-height: 1;
  opacity: 0.75;
}
.mine-emoji {
  cursor: pointer;
  opacity: 0.9;
  transition: opacity 0.15s, transform 0.1s;
}
.mine-emoji:hover {
  opacity: 1;
  transform: scale(1.2);
}
.reaction-trigger-btn {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 11px;
  cursor: pointer;
  padding: 0 2px;
  opacity: 0.35;
  transition: opacity 0.15s, color 0.15s;
  line-height: 1;
  font-family: inherit;
}
.reaction-trigger-btn:hover {
  opacity: 1;
  color: var(--accent);
}
.reaction-picker-popup {
  display: flex;
  gap: 2px;
  margin-top: 2px;
}
.reaction-picker-popup button {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 14px;
  padding: 2px 7px;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 0.15s, transform 0.1s;
  line-height: 1.4;
}
.reaction-picker-popup button:hover {
  border-color: var(--accent);
  transform: scale(1.15);
}
.deviceInfoBtn {
  position: absolute;
  bottom: 4px;
  right: 6px;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 9px;
  cursor: pointer;
  padding: 0 2px;
  opacity: 0.3;
  transition: opacity 0.15s, color 0.15s;
  line-height: 1;
}
.deviceInfoBtn:hover { opacity: 1; color: var(--accent); }

.devicePopover {
  display: none;
  position: absolute;
  bottom: 22px;
  right: 6px;
  background: var(--surface2);
  border: 1px solid var(--border);
  z-index: 20;
  min-width: 130px;
  padding: 4px 0;
}
.devicePopover.open { display: block; }
.devicePopoverRow {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 4px 12px;
  font-size: 10px;
  color: var(--dim);
  white-space: nowrap;
  gap: 10px;
}
.devicePopoverDate {
  font-size: 9px;
  color: var(--muted);
  letter-spacing: 0.05em;
}
.devicePopoverRow.unknown {
  color: var(--muted);
  font-style: italic;
}

#callBtn {
  background: none; border: 1px solid var(--border); color: var(--online);
  width: 28px; height: 28px; font-size: 14px; cursor: pointer;
  display: none; align-items: center; justify-content: center;
  transition: border-color 0.2s, color 0.2s, background 0.2s;
  flex-shrink: 0; margin-right: 8px;
}
#callBtn.visible { display: flex; }
#callBtn:hover { border-color: var(--online); background: var(--surface2); }
#callBtn.state-calling, #callBtn.state-ringing, #callBtn.state-negotiating {
  color: var(--accent); border-color: var(--accent); animation: pulse 1s infinite;
}
#callBtn.state-connected { color: var(--danger); border-color: var(--danger); animation: none; }
#callBtn.state-failed { color: var(--danger); border-color: var(--danger); animation: none; }
#callBtn:disabled { opacity: 0.5; cursor: default; animation: none; }

#incomingCallBanner {
  display: none;
  position: fixed; top: 0; left: 50%; transform: translateX(-50%);
  background: var(--surface2); border: 1px solid var(--accent); border-top: none;
  padding: 14px 20px; z-index: 500;
  flex-direction: column; align-items: center; gap: 10px;
  box-shadow: 0 4px 16px rgba(0,0,0,.6);
}
#incomingCallBanner.open { display: flex; }
#incomingCallName { font-size: 13px; letter-spacing: 0.1em; color: var(--accent); }
.incomingCallBtns { display: flex; gap: 8px; }
.incomingCallBtns button {
  padding: 8px 16px; font-family: inherit; font-size: 11px; letter-spacing: 0.1em;
  border: 1px solid var(--border); cursor: pointer;
}
#answerCallBtn  { background: var(--online); color: #000; border-color: var(--online); font-weight: bold; }
#declineCallBtn { background: none; color: var(--danger); border-color: var(--danger); }
/* ── SHELL ESCALATION — prep only, dormant until script.js wires it.
   Mirrors #callBtn's states exactly; nothing sets .visible on this yet. ── */
#shellBtn {
  background: none; border: 1px solid var(--border); color: var(--accent);
  width: 28px; height: 28px; font-size: 14px; cursor: pointer;
  display: none; align-items: center; justify-content: center;
  transition: border-color 0.2s, color 0.2s, background 0.2s;
  flex-shrink: 0; margin-right: 8px;
}
#shellBtn.visible { display: flex; }
#shellBtn:hover { border-color: var(--accent); background: var(--surface2); }
#shellBtn.state-calling, #shellBtn.state-negotiating {
  color: var(--accent); border-color: var(--accent); animation: pulse 1s infinite;
}
#shellBtn.state-connected { color: var(--danger); border-color: var(--danger); animation: none; }
#shellBtn.state-failed    { color: var(--danger); border-color: var(--danger); animation: none; }
#shellBtn:disabled { opacity: 0.5; cursor: default; animation: none; }

/* ── AGENT CONTACTS — prep only. Nothing currently adds "agent-contact"
   to a .contactItem or an .agentBadge span; renderContactList() still
   only ever emits the markup it emits today. Dormant until wired. ── */
.contactItem.agent-contact .contactAvatar {
  border-color: var(--accent);
  color: var(--accent);
}
.agentBadge {
  font-size: 9px;
  color: var(--accent);
  letter-spacing: 0.06em;
  margin-left: 4px;
  opacity: 0.85;
}/* ============================================================
   C64 THEME LAYER  ·  losse overlay (c64-theme.css)
   ------------------------------------------------------------
   Wordt door meshchat_update.sh ACHTER de verse upstream
   static/style.css geplakt. Bevat UITSLUITEND onze toevoegingen:
   pixelfont, C64-palet, font-override, CRT-laag en alle iconen.
   Upstream-styling blijft dus leidend en krijgt z'n updates;
   deze laag overruled enkel wat nodig is. Géén bevroren kopie meer.
   ============================================================ */

@font-face {
  font-family: 'PixelChat C64';
  src: url('data:font/woff2;base64,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') format('woff2');
  font-weight: normal; font-style: normal; font-display: swap;
}

/* ── C64 (VIC-II) palet — overschrijft upstream :root (donker → C64) ── */
:root {
  --bg:       #40318d;
  --surface:  #4838a4;
  --surface2: #5a4cc0;
  --border:   #7d70d4;
  --muted:    #7a6fc9;
  --dim:      #9b91ea;
  --text:     #c8c1ff;
  --accent:   #74e0d6;
  --online:   #6fce6f;
  --mine:     #2f2480;
  --theirs:   #4a3bb0;
  --danger:   #d97c80;
}

/* ── lettertype: upstream gebruikt 'Courier New'/'monospace' — overal de pixelfont ── */
body { font-family: 'PixelChat C64', 'Courier New', monospace; }
#meshLog, #meshLogToggle, #meshLogHeader button, #showBlockedBtn {
  font-family: 'PixelChat C64', monospace;
}

/* ============================================================
   C64 THEME LAYER
   ============================================================ */

/* crisp pixels + faint phosphor warmth on the screen text */
body {
  text-rendering: geometricPrecision;
  -webkit-font-smoothing: none;
}

/* --- TV bezel: a chunky light-blue frame around the screen --- */
body::before {
  content: "";
  position: fixed; inset: 0;
  border: 13px solid var(--border);
  box-shadow: inset 0 0 0 2px #2a2080,
              inset 0 0 140px rgba(0,0,0,0.35);
  pointer-events: none;
  z-index: 40;
}

/* --- CRT scanlines + gentle flicker --- */
body::after {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 41;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0,0,0,0.14) 0 1px,
    rgba(0,0,0,0)    1px 3px
  );
  animation: crtFlicker 5s steps(60) infinite;
}
@keyframes crtFlicker {
  0%,100% { opacity: 0.55; }
  50%     { opacity: 0.40; }
}

/* --- everything is blocky on a C64: kill rounded corners --- */
.contactStatus, #connDot { border-radius: 0 !important; }
.unreadBadge,
.message.mine img, .message.theirs img { border-radius: 0 !important; }

/* keep QR crisp when scaled */
#myQrCode, #myQrCode img, #myQrCode canvas { image-rendering: pixelated; }

/* --- SHOUTING LABELS (PETSCII was upper-case) --- */
#loginBox h2, .subtitle, #loginStatus,
#sidebarTitle, #chatHeaderName, #emptyChat,
#syncStatus, #connectionStatus,
.modal-box h3, .qr-tab, .scan-btn,
#loginBox button, #sendButton, .chat-action-btn,
.modal-btns button, .contact-dropdown button {
  text-transform: uppercase;
}

/* --- accent glow + blinking block cursor on the headings --- */
#loginBox h2, #sidebarTitle, .modal-box h3 {
  text-shadow: 0 0 6px rgba(116,224,214,0.35);
}
#loginBox h2::after,
#emptyChat::after {
  content: "\2588";          /* solid block, the C64 cursor */
  margin-left: 0.15em;
  color: var(--accent);
  animation: c64blink 1s steps(1) infinite;
}
@keyframes c64blink { 50% { opacity: 0; } }

/* caret + selection in C64 cyan */
input { caret-color: var(--accent); }
::selection { background: var(--accent); color: #000; }

/* scrollbars in-theme */
#contactList::-webkit-scrollbar-thumb,
#chatMessages::-webkit-scrollbar-thumb { background: var(--border); }


/* ============================================================
   C64 ICON-SET  (toevoeging onderaan style.css — vervangt niets)
   Verbergt de emoji-tekens die je pixelfont niet kent en tekent
   er C64-pixeliconen overheen. Puur CSS; script.js en index.html
   blijven onaangeraakt, dus dit overleeft elke auto-update.
   Afgestemd op je BESTAANDE knop-styling (flex/hover/recording).
   ============================================================ */

/* 1. "backup stored"-indicator naast contactnaam */
.contactName span[title="backup stored"] {
  font-size: 0 !important;
  display: inline-block;
  width: 12px; height: 12px;
  vertical-align: -1px;
  image-rendering: pixelated;
  background: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20shape-rendering='crispEdges'%3E%3Cpath%20d='M1%201%20H11%20L15%205%20V15%20H1%20Z'%20fill='%2374e0d6'/%3E%3Crect%20x='4'%20y='2'%20width='6'%20height='4'%20fill='%2340318d'/%3E%3Crect%20x='8'%20y='2'%20width='2'%20height='4'%20fill='%235a4cc0'/%3E%3Crect%20x='3'%20y='9'%20width='10'%20height='5'%20fill='%2340318d'/%3E%3Crect%20x='4'%20y='10'%20width='8'%20height='1'%20fill='%2374e0d6'/%3E%3Crect%20x='4'%20y='12'%20width='8'%20height='1'%20fill='%2374e0d6'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* verberg de emoji-tekst op de icoonknoppen */
#exportBtn, #audioBtn, #imageBtn, #contactMenuBtn, .reaction-trigger-btn {
  font-size: 0;
}

/* gedeeld ::before-icoon (erft de bestaande flex-centrering of krijgt die hieronder) */
#contactMenuBtn::before, .reaction-trigger-btn::before {
  content: "";
  display: block;
  image-rendering: pixelated;
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
}

/* deze twee waren niet gecentreerd -> hier wel (raakt hover/recording/border niet) */
/* media-knoppen (mic/camera): icoon als ACHTERGROND i.p.v. ::before.
   Robuust op smal mobiel: een achtergrond wordt over de hele knop geschilderd
   en kan niet door flex/krappe hoogte weggeknipt worden. min-height garandeert
   ruimte voor het 18px-icoon; !important zodat de upstream :hover-achtergrond
   het icoon niet wegveegt. */
#audioBtn, #imageBtn {
  min-height: 26px;
  background-repeat: no-repeat !important;
  background-position: center !important;
  background-size: 18px 18px !important;
  image-rendering: pixelated;
}
#audioBtn { background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20shape-rendering='crispEdges'%3E%3Crect%20x='7'%20y='1'%20width='2'%20height='1'%20fill='%2374e0d6'/%3E%3Crect%20x='6'%20y='2'%20width='4'%20height='6'%20fill='%2374e0d6'/%3E%3Crect%20x='7'%20y='3'%20width='2'%20height='1'%20fill='%2340318d'/%3E%3Crect%20x='7'%20y='5'%20width='2'%20height='1'%20fill='%2340318d'/%3E%3Crect%20x='4'%20y='7'%20width='1'%20height='2'%20fill='%2374e0d6'/%3E%3Crect%20x='11'%20y='7'%20width='1'%20height='2'%20fill='%2374e0d6'/%3E%3Crect%20x='4'%20y='9'%20width='8'%20height='1'%20fill='%2374e0d6'/%3E%3Crect%20x='7'%20y='10'%20width='2'%20height='3'%20fill='%2374e0d6'/%3E%3Crect%20x='5'%20y='13'%20width='6'%20height='1'%20fill='%2374e0d6'/%3E%3C/svg%3E") !important; }
#imageBtn { background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20shape-rendering='crispEdges'%3E%3Crect%20x='4'%20y='2'%20width='4'%20height='2'%20fill='%2374e0d6'/%3E%3Crect%20x='1'%20y='4'%20width='14'%20height='9'%20fill='%2374e0d6'/%3E%3Crect%20x='6'%20y='6'%20width='4'%20height='4'%20fill='%2340318d'/%3E%3Crect%20x='7'%20y='7'%20width='2'%20height='2'%20fill='%235a4cc0'/%3E%3Crect%20x='12'%20y='5'%20width='2'%20height='1'%20fill='%2340318d'/%3E%3C/svg%3E") !important; }
.reaction-trigger-btn {
  display: inline-flex; align-items: center; justify-content: center;
}
/* LET OP: #exportBtn en #contactMenuBtn krijgen GEEN display-regel,
   zodat jouw 'display:none -> .visible' gedrag intact blijft. */

#exportBtn { background: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20shape-rendering='crispEdges'%3E%3Cpath%20d='M1%201%20H11%20L15%205%20V15%20H1%20Z'%20fill='%2374e0d6'/%3E%3Crect%20x='4'%20y='2'%20width='6'%20height='4'%20fill='%2340318d'/%3E%3Crect%20x='8'%20y='2'%20width='2'%20height='4'%20fill='%235a4cc0'/%3E%3Crect%20x='3'%20y='9'%20width='10'%20height='5'%20fill='%2340318d'/%3E%3Crect%20x='4'%20y='10'%20width='8'%20height='1'%20fill='%2374e0d6'/%3E%3Crect%20x='4'%20y='12'%20width='8'%20height='1'%20fill='%2374e0d6'/%3E%3C/svg%3E") center / 18px 18px no-repeat; image-rendering: pixelated; }
#contactMenuBtn::before   { width: 18px; height: 18px; background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20shape-rendering='crispEdges'%3E%3Crect%20x='2'%20y='7'%20width='2'%20height='2'%20fill='%2374e0d6'/%3E%3Crect%20x='7'%20y='7'%20width='2'%20height='2'%20fill='%2374e0d6'/%3E%3Crect%20x='12'%20y='7'%20width='2'%20height='2'%20fill='%2374e0d6'/%3E%3C/svg%3E"); }
.reaction-trigger-btn::before { width: 14px; height: 14px; background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20shape-rendering='crispEdges'%3E%3Crect%20x='11'%20y='3'%20width='2'%20height='5'%20fill='%2374e0d6'/%3E%3Crect%20x='4'%20y='6'%20width='9'%20height='2'%20fill='%2374e0d6'/%3E%3Crect%20x='4'%20y='4'%20width='2'%20height='2'%20fill='%2374e0d6'/%3E%3Crect%20x='2'%20y='6'%20width='2'%20height='2'%20fill='%2374e0d6'/%3E%3Crect%20x='4'%20y='8'%20width='2'%20height='2'%20fill='%2374e0d6'/%3E%3C/svg%3E"); }

/* 7. "known devices"-knop naast contacten  (was: kale + ) */
.deviceInfoBtn {
  font-size: 0;
  background: none;
  border: 1px solid var(--border);
  color: var(--accent);
  width: 24px; height: 24px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; border-radius: 0; cursor: pointer;
  transition: border-color 0.2s;
}
.deviceInfoBtn:hover { border-color: var(--accent); }
.deviceInfoBtn::before {
  content: ""; display: block; width: 16px; height: 16px;
  image-rendering: pixelated;
  background: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20shape-rendering='crispEdges'%3E%3Crect%20x='0'%20y='2'%20width='10'%20height='7'%20fill='%2374e0d6'/%3E%3Crect%20x='1'%20y='3'%20width='8'%20height='4'%20fill='%2340318d'/%3E%3Crect%20x='4'%20y='9'%20width='2'%20height='1'%20fill='%2374e0d6'/%3E%3Crect%20x='2'%20y='10'%20width='6'%20height='1'%20fill='%2374e0d6'/%3E%3Crect%20x='11'%20y='4'%20width='5'%20height='11'%20fill='%2374e0d6'/%3E%3Crect%20x='12'%20y='5'%20width='3'%20height='7'%20fill='%2340318d'/%3E%3Crect%20x='13'%20y='13'%20width='1'%20height='1'%20fill='%2340318d'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ── invoerrij vrijhouden van de CRT-bezel ──
   body::before tekent een ~15px frame (13px rand + 2px binnenlijn) over de
   schermranden. De media-knoppen (Hold to record / Send image) rechtsonderin
   vielen daar deels onder. We duwen de hele onderste invoerrij met MARGE naar binnen (niet padding!):
   marge houdt de rij vrij van het frame ZONDER interne hoogte weg te nemen,
   zodat de verticaal gestapelde mic/camera-icoontjes op elk scherm — ook smal
   mobiel — hun volle formaat houden. De bezel blijft volledig intact. */
#chatInputContainer { margin-right: 15px; margin-bottom: 15px; }

/* textarea mag volledig krimpen (standaard min-width van een form-veld
   maakt de rij anders te breed, waardoor de media-knoppen onder de
   rechter-bezel geduwd worden). */
#chatInput { min-width: 0; }


/* ============================================================
   KLEINE-SCHERMEN-POLISH  ·  bv. Commodore CallBack 8020 (480x640)
   ============================================================ */

/* Korte schermen: login-scherm mag scrollen en lijnt bovenaan uit, zodat een
   login-box die hoger is dan het scherm (incl. de hint-tekst) niet meer wordt
   afgekapt. body blijft overflow:hidden -- we scrollen binnen #loginScreen zelf. */
@media (max-height: 720px) {
  #loginScreen {
    align-items: flex-start;
    overflow-y: auto;
    padding: 18px 0;
    scrollbar-width: none;             /* Firefox/Gecko (SailfishOS WebView): balk weg */
  }
  /* scrollbalk verbergen zodat hij de rechter-bezel niet bedekt; scrollen blijft werken */
  #loginScreen::-webkit-scrollbar { width: 0; height: 0; }
}

/* Smalle schermen: de CRT-bezel proportioneel dunner (13px is fors op 480px),
   en de invoerrij-marge navenant kleiner zodat er meer ruimte overblijft. */
@media (max-width: 600px) {
  body::before {
    border-width: 7px;
    box-shadow: inset 0 0 0 1px #2a2080, inset 0 0 70px rgba(0,0,0,0.28);
  }
  #chatInputContainer { margin-right: 9px; margin-bottom: 9px; }
}

