/*
 * DEAD DROP — "chrome" skin (M5): the website + everything OUTSIDE the chat terminal. Original
 * design in the mid-90s beveled-dark-OS genre, dialed up: a thick glossy double-bevel window
 * frame in a cool blue-gray "platinum" tone, content recessed into a well, a beveled scrollbar
 * (arrows + raised thumb), a bottom-right grow box, a pronounced raised menu bar, a faint-texture
 * title bar with a centered plate and rounded widgets, and a Chicago-inspired bitmap font. Our
 * palette, tied to the chat blue. An homage to the era, not a copy of any product's design.
 *
 * Chicago is Apple's proprietary font; the chrome uses an openly-licensed classic-bitmap face
 * (Silkscreen). Load it at the app entry:
 *   <link href="https://fonts.googleapis.com/css2?family=Silkscreen:wght@400;700&display=swap" rel="stylesheet">
 */

:root {
  --dd-desk: #07070c;
  --dd-grid: rgba(64, 196, 208, 0.16);
  --dd-grid-strong: rgba(64, 196, 208, 0.30);

  --dd-chrome-ink: #dfe3ee;
  --dd-chrome-dim: #8e93a6;
  --dd-select: #2a52d6;
  --dd-select-ink: #eef2ff;

  --dd-radius: 18px;
  --dd-radius-sm: 9px;

  /* Cool blue-gray platinum surfaces. */
  --dd-face: linear-gradient(180deg, #353a4b 0%, #2c3040 14%, #252836 60%, #1c1e29 100%);
  --dd-face-hot: linear-gradient(180deg, #3f4456 0%, #313646 16%, #282c3a 100%);
  --dd-rim: #07070c;

  /* Sharp specular gradient for the menu + title bars: a bright highlight band across the top
     that drops crisply (the 14%->15% step) into a dark body. Glossy extruded-metal look. */
  --dd-bar: linear-gradient(180deg, #5b6079 0%, #474c60 14%, #2c3142 15%, #232735 60%, #181b25 100%);

  /* Thick glossy convex bevel. */
  --dd-bevel: inset 0 2px 0 rgba(255, 255, 255, 0.28),
    inset 0 -3px 5px rgba(0, 0, 0, 0.65),
    inset 2px 0 0 rgba(255, 255, 255, 0.08),
    inset -2px 0 0 rgba(0, 0, 0, 0.5),
    0 4px 11px rgba(0, 0, 0, 0.55);
  --dd-bevel-pressed: inset 0 2px 5px rgba(0, 0, 0, 0.65), inset 0 -1px 0 rgba(255, 255, 255, 0.1);
  --dd-well: inset 0 3px 6px rgba(0, 0, 0, 0.7), inset 0 -1px 0 rgba(255, 255, 255, 0.06);
  /* Inner groove between frame sections (the second bevel). */
  --dd-groove: inset 0 1px 0 rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.08);
  --dd-texture: repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 4px);

  /* Match the chat terminal's monospace so chrome and chat share one typeface (clean, not pixelated). */
  --dd-chrome-font: ui-monospace, "Cascadia Mono", "DejaVu Sans Mono", "Courier New", monospace;
}

.dd-raised {
  border-radius: var(--dd-radius);
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel);
}
.dd-well {
  border-radius: var(--dd-radius-sm);
  background: #12121a;
  box-shadow: var(--dd-well);
}

/* Desktop. */
.dd-desk {
  position: relative;
  display: flex;
  flex-direction: column;
  /* Exactly the viewport, never taller: this gives the stage a definite height so a window can cap itself
     at the viewport and scroll its own content (the conversation log) instead of growing off-screen. */
  height: 100dvh;
  min-height: 0;
  background: var(--dd-desk);
  color: var(--dd-chrome-ink);
  font-family: var(--dd-chrome-font);
  overflow: hidden;
}
/* The area the window(s) sit in, below the menu bar. */
.dd-stage {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 16px 14px calc(env(safe-area-inset-bottom) + 16px);
}
.dd-desk::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  background:
    repeating-linear-gradient(90deg, var(--dd-grid) 0 1px, transparent 1px 44px),
    repeating-linear-gradient(0deg, var(--dd-grid) 0 1px, transparent 1px 44px);
  -webkit-mask-image: linear-gradient(transparent 0%, rgba(0, 0, 0, 0.5) 60%, #000 100%);
  mask-image: linear-gradient(transparent 0%, rgba(0, 0, 0, 0.5) 60%, #000 100%);
}
.dd-desk::after {
  content: "";
  position: fixed;
  left: -25%;
  right: -25%;
  bottom: 0;
  height: 46vh;
  pointer-events: none;
  background:
    repeating-linear-gradient(90deg, var(--dd-grid-strong) 0 1px, transparent 1px 56px),
    repeating-linear-gradient(0deg, var(--dd-grid-strong) 0 1px, transparent 1px 56px);
  transform: perspective(340px) rotateX(62deg);
  transform-origin: center bottom;
  -webkit-mask-image: linear-gradient(transparent, #000 70%);
  mask-image: linear-gradient(transparent, #000 70%);
}

/* Menu bar — pronounced raised platinum bar with a bottom groove. */
.dd-menubar {
  position: relative;
  z-index: 2;
  display: flex;
  /* Wraps so minimized-window chips get a second row on a phone instead of being crushed to blank
     slivers and shoving the connection label off the bar (the nav items cannot shrink). */
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin: calc(env(safe-area-inset-top) + 8px) 8px 0;
  padding: 6px 10px;
  background: var(--dd-bar);
  border: 1px solid var(--dd-rim);
  border-radius: 18px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5), inset 0 -2px 4px rgba(0, 0, 0, 0.55), 0 3px 9px rgba(0, 0, 0, 0.55);
  font-size: 13px;
}
.dd-menu-item {
  padding: 3px 12px;
  border-radius: var(--dd-radius-sm);
  color: var(--dd-chrome-ink);
  cursor: default;
  white-space: nowrap;
}
.dd-menu-item:hover { background: var(--dd-select); color: var(--dd-select-ink); }
.dd-menu-spacer { flex: 1; min-width: 4px; }
/* A window minimized to the menu bar (the AIM taskbar): a small raised chip; click restores it.
   flex:none keeps the LABEL readable — a shrinkable chip crushed to an 18px blank pill on phones;
   with the bar wrapping, an unshrinkable chip moves to the next row instead. */
.dd-menu-chip {
  font: inherit; font-size: 11px; flex: none; max-width: 11rem; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; padding: 2px 8px; margin-left: 4px; cursor: pointer;
  border-radius: var(--dd-radius-sm); border: 1px solid var(--dd-rim);
  background: var(--dd-face); box-shadow: var(--dd-bevel); color: var(--dd-chrome-ink);
}
.dd-menu-chip:hover { background: var(--dd-face-hot); }
.dd-menu-chip:active { box-shadow: var(--dd-bevel-pressed); }
.dd-menu-conn {
  padding: 3px 8px;
  color: var(--dd-chrome-dim);
  font-size: 11px;
  letter-spacing: 0.06em;
  white-space: nowrap;
  flex: none; /* the connection status stays intact; it never wraps or overflows off the bar */
}
/* Narrow screens: tighten the bar so the nav plus the connection status fit without running off. */
@media (max-width: 480px) {
  .dd-menubar { gap: 2px; padding: 5px 7px; font-size: 12px; }
  .dd-menu-item { padding: 3px 7px; }
  .dd-menu-conn { padding: 3px 4px; font-size: 10px; letter-spacing: 0.02em; }
  /* Buddy list: let the roster use the full width. In Setup, each buddy row carries a group picker, so on
     a phone let the name and its picker wrap to a second line instead of running off the right edge. */
  .dd-buddies { max-width: none; }
  .dd-setup-add { flex-wrap: wrap; }
  .dd-setup-add .dd-input { flex: 1 1 100%; }
  .dd-setup-row { flex-wrap: wrap; }
  .dd-setup-row .dd-tree-buddy { flex: 1 1 100%; }
  .dd-buddy-group-sel { flex: 1 1 auto; max-width: none; }
}

/* DEAD DROP app menu dropdown. */
.dd-menu-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 10;
  min-width: 168px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 4px;
  background: var(--dd-bar);
  border: 1px solid var(--dd-rim);
  border-radius: 12px;
  box-shadow: var(--dd-bevel), 0 10px 24px rgba(0, 0, 0, 0.55);
}
.dd-menu-dropdown[hidden] { display: none; } /* the panel sets display:flex, which would override the hidden attribute */
.dd-menu-dropitem {
  font: inherit;
  font-size: 13px;
  text-align: left;
  padding: 7px 12px;
  border: 0;
  border-radius: var(--dd-radius-sm);
  background: transparent;
  color: var(--dd-chrome-ink);
  cursor: pointer;
  white-space: nowrap;
}
.dd-menu-dropitem:hover { background: var(--dd-select); color: var(--dd-select-ink); }
/* Self Destruct is set apart at the bottom of the menu: a divider above it and danger-red text, so it
   never reads as an ordinary navigation item. */
.dd-menu-destruct {
  margin-top: 4px;
  border-top: 1px solid var(--dd-chrome-edge, rgba(0, 0, 0, 0.25));
  color: var(--dd-danger, #b00020);
  font-weight: 700;
  text-align: center;
}
.dd-menu-destruct:hover { background: var(--dd-danger, #b00020); color: #fff; }

/* Window — thick glossy frame; content in a recessed well; grow box bottom-right. */
.dd-window {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  /* Windows are absolutely positioned on the stage (AIM19), so 100% resolves against the stage PADDING
     box; subtracting the stage's 14px side gutters keeps the old flow-layout width on narrow screens.
     border-box so the 1px frame is inside the width (and a stored resize re-applies exactly). */
  box-sizing: border-box;
  width: min(30rem, 100% - 28px);
  /* Never taller than the stage. A short form still sizes to its content; a conversation that would run
     past the viewport caps here so its log (flex:1, overflow-y:auto) scrolls, AIM-style, rather than the
     whole window growing off-screen. min-height:0 lets the inner flex column shrink to enable that scroll. */
  max-height: 100%;
  min-height: 0;
  border-radius: var(--dd-radius);
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel), 0 18px 38px rgba(0, 0, 0, 0.6);
  overflow: hidden;
}
.dd-titlebar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--dd-texture), var(--dd-bar);
  border-bottom: 1px solid var(--dd-rim);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5), inset 0 -2px 4px rgba(0, 0, 0, 0.6);
  font-size: 13px;
}
.dd-title {
  max-width: 90%;
  padding: 3px 18px;
  border-radius: var(--dd-radius-sm);
  background: var(--dd-bar);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5), inset 0 -2px 3px rgba(0, 0, 0, 0.55);
  color: var(--dd-chrome-ink);
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Connection status in the BUDDY LIST titlebar: absolutely positioned just left of the window controls,
   so the centered .dd-title (the only in-flow child) is undisturbed. Dim, small, single-line. */
/* Connection status (AIM21): a clickable headline between the title and the window buttons, with a
   plain-words detail popover. Per-state colors put E2E readiness first: green only when the end-to-end
   session is live, amber while SECURING, dim otherwise. */
/* AIM26: the connection status rides the far right of the buddy-list header (renderConnStatus). flex:none
   holds its width so the username column (.dd-blhead-txt, flex:1 min-width:0) shrinks first and the label
   never overflows when the list is resized narrow; position:relative anchors its popover. */
.dd-blhead-conn { flex: 0 1 auto; min-width: 0; position: relative; align-self: flex-start; margin-top: 3px; max-width: 55%; }
.dd-title-conn {
  font: inherit;
  font-size: 11px;
  letter-spacing: 0.06em;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--dd-chrome-dim);
  background: transparent;
  border: 0;
  padding: 2px 5px;
  border-radius: var(--dd-radius-sm);
  cursor: pointer;
}
.dd-title-conn:hover { background: rgba(255, 255, 255, 0.08); }
.dd-conn-secure { color: var(--dd-secure, #74f0a8); }
.dd-conn-live { color: var(--dd-warn, #ffce5e); }
/* AIM26: the popover must paint OVER the away bubble (.dd-blhead-status). It wins because it is
   emitted after the away bubble in the header DOM and carries a positive z-index (the away bubble is
   z-index:auto). Keep the conn control co-located here in .dd-blhead-conn — never anchor it back in the
   titlebar, whose stacking context would trap the popover beneath the away bubble again. */
.dd-conn-pop {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 30;
  width: 232px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
  border-radius: var(--dd-radius);
  box-shadow: var(--dd-bevel), 0 12px 24px rgba(0, 0, 0, 0.5);
  color: var(--dd-chrome-ink);
  font-size: 12px;
  letter-spacing: normal;
  white-space: normal;
  text-align: left;
  cursor: default;
}
.dd-conn-pop[hidden] { display: none; }
.dd-connp-state { font-weight: 700; letter-spacing: 0.06em; }
.dd-connp-exp { color: var(--dd-chrome-dim); line-height: 1.45; }
.dd-connp-gw, .dd-connp-time { color: var(--dd-chrome-dim); font-size: 11px; }
.dd-connp-now { margin-top: 2px; font-size: 12px; padding: 5px 10px; align-self: flex-start; }
/* AIM-style window controls (minimize / close), pinned to the titlebar's right edge so the title stays
   centered. Only the message window shows them (a way to back out of a conversation). */
.dd-winctl { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); display: flex; gap: 5px; }
.dd-winbtn {
  width: 20px; height: 18px; line-height: 1; font-size: 12px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 4px; border: 1px solid var(--dd-rim); background: var(--dd-face);
  box-shadow: var(--dd-bevel); color: var(--dd-chrome-ink); cursor: pointer;
}
.dd-winbtn:hover { background: var(--dd-face-hot); }
.dd-winbtn:active { box-shadow: var(--dd-bevel-pressed); }
.dd-winbtn-close:hover { background: #7a2a2a; color: #ffe0e0; border-color: #a03a3a; }

/* The DEAD DROP app menu in the titlebar's top-left corner (classic Mac): the app icon opens the
   dropdown. Mirrors .dd-winctl on the right so the centered title stays centered. */
.dd-winmenu { position: absolute; left: 8px; top: 50%; transform: translateY(-50%); display: flex; z-index: 20; }
.dd-winbtn-app { width: 24px; }
.dd-winbtn-app .dd-logo-ic { width: 12px; height: 12px; }
.dd-winmenu .dd-menu-dropdown { top: calc(100% + 6px); }

/* The DEAD DROP mark (inline SVG, filled via currentColor so it takes each context's ink). */
.dd-logo-ic { width: 14px; height: 14px; fill: currentColor; flex: none; vertical-align: -2px; }
.dd-menu-app { position: relative; display: inline-flex; }
/* The brand is a <button> (the other menu items are <span>s), so it must shed the native button chrome
   (UA background + border) or it renders as a light box that hides the light chrome-ink text until a
   hover/active state repaints it. Transparent + no border makes it read exactly like the span items;
   .dd-menu-item still supplies the color and .dd-menu-item:hover the select highlight. */
.dd-menu-brand { display: inline-flex; align-items: center; gap: 6px; letter-spacing: 0.08em; cursor: pointer; font: inherit; background: transparent; border: 0; -webkit-appearance: none; appearance: none; }
/* The unlock screen's hero brand: the mark large over the wordmark, glowing like the CRT it fronts. */
.dd-logo-hero { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.dd-logo-mark {
  width: 74px;
  height: 74px;
  fill: var(--dd-chrome-ink);
  filter: drop-shadow(0 0 14px rgba(90, 155, 224, 0.55)) drop-shadow(0 0 3px rgba(90, 155, 224, 0.8));
}
.dd-logo-word {
  font-size: 24px;
  letter-spacing: 0.32em;
  padding-left: 0.32em; /* balances the trailing letter-space so the wordmark centers optically */
  text-shadow: 0 0 12px rgba(90, 155, 224, 0.6);
}

/* Windows drag by the titlebar and resize by the native grow box in the bottom-right corner (the
   classic Mac grow box). The drag positions land via the CSSOM (see applyWindowGeometry). */
.dd-titlebar { cursor: grab; touch-action: none; }
.dd-titlebar:active { cursor: grabbing; }
.dd-window { resize: both; min-width: 240px; min-height: 180px; }
/* A conversation window carries fixed chrome (transmit bar, peer line, compose, IM toolbar) plus the
   AIM23 buddy-icon column (peer icon at the top, your icon at the bottom by the compose). Hold a minimum
   tall enough that the grow box can never shrink the chat body below the two 48px icons + their padding
   (~150px) — otherwise the bottom (your) icon would clip into the toolbar. Open at a FIXED default size so
   typing scrolls the log rather than growing the window; the default yields to a stored size via the CSSOM. */
.dd-window:has(.dd) { min-height: 430px; height: min(560px, 82dvh); }
/* On phones pin the chat window to the visual viewport so the on-screen keyboard shrinks ONLY the .dd-log
   (the history scrolls under a fixed compose), instead of the whole window resizing/jumping per message. */
@media (max-width: 480px) {
  .dd-window:has(.dd) { height: 100%; max-height: 100%; min-height: 0; }
}
/* The two-pane Channels window is WIDER (list + chat) and holds a consistent size whether or not a chat
   is open, so selecting the first channel does not jump the window from a short list to conversation size.
   It carries MORE fixed chrome than a standalone chat (the list pane header + the two-pane frame), so its
   embedded chat pane hits the icon-column floor later — hold 500px so the bottom (your) icon never clips
   into the toolbar even when dragged to the minimum. (This rule is more specific in intent than the generic
   :has(.dd) 430px above and comes later, so it wins for the Channels window.) */
.dd-window:has(.dd-channels-2pane) { width: min(52rem, 100% - 28px); min-height: 500px; height: min(600px, 84dvh); }
/* The Appearance preferences is a two-pane window (categories + controls); hold a comfy size. */
.dd-window:has(.dd-appear-2pane) { width: min(46rem, 100% - 28px); min-height: 360px; height: min(560px, 84dvh); }

/* Multi-window desktop: the focused window sits above the parked ones; parked windows are dimmed, their
   content non-interactive (a click brings the window forward). Windows are absolutely positioned once
   dragged; before that they stack in the centered flow, so the stage lays them out top-down. */
.dd-stage { justify-content: flex-start; }
.dd-stage .dd-window:not(.dd-window-parked) { z-index: 10; }
.dd-window-parked { z-index: 1; filter: brightness(0.82) saturate(0.9); }
.dd-window-parked .dd-window-body { pointer-events: none; }
.dd-window-parked .dd-titlebar { cursor: pointer; }
.dd-window-parked .dd-titlebar button { pointer-events: none; }
.dd-window-body {
  flex: 1;
  min-height: 0;
  display: flex;
  padding: 6px;
  box-shadow: var(--dd-groove);
}
.dd-content-well {
  flex: 1;
  min-height: 0;
  display: flex;
  border-radius: 12px;
  box-shadow: var(--dd-well);
  /* The conversation manages its own scroll (the .dd log + decorative scrollbar sit inside and fit), so
     this stays quiet there; for a form taller than the now-capped window, it scrolls the form into reach
     instead of clipping it. overflow-x stays hidden so nothing bleeds past the rounded well horizontally. */
  overflow: hidden auto;
}

/* Classic beveled scrollbar (decorative): up/down arrows + raised thumb on an inset track. */
.dd-scrollbar {
  width: 17px;
  display: flex;
  flex-direction: column;
  background: #14141c;
  border-left: 1px solid var(--dd-rim);
  box-shadow: inset 2px 0 4px rgba(0, 0, 0, 0.5);
}
.dd-sb-arrow {
  height: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 8px;
  color: var(--dd-chrome-dim);
  background: var(--dd-face-hot);
  box-shadow: inset 0 1.5px 0 rgba(255, 255, 255, 0.28), inset 0 -1.5px 2px rgba(0, 0, 0, 0.55);
}
.dd-sb-track { flex: 1; position: relative; }
.dd-sb-thumb {
  position: absolute;
  left: 2px;
  right: 2px;
  top: 28%;
  height: 34%;
  border-radius: 3px;
  background: var(--dd-face-hot);
  box-shadow: inset 0 1.5px 0 rgba(255, 255, 255, 0.28), inset 0 -1.5px 2px rgba(0, 0, 0, 0.55), 0 0 0 1px var(--dd-rim);
}
/* Beveled button. */
.dd-btn {
  font: inherit;
  font-size: 13px;
  padding: 7px 18px;
  border-radius: var(--dd-radius-sm);
  color: var(--dd-chrome-ink);
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel);
  cursor: pointer;
}
.dd-btn:hover { background: var(--dd-face-hot); }
.dd-btn:active { box-shadow: var(--dd-bevel-pressed); }
.dd-btn-primary {
  color: var(--dd-select-ink);
  background: linear-gradient(180deg, #4168ec 0%, #2a52d6 30%, #1f40b0 100%);
  /* The classic Mac default-button ring: an extra rounded border with a small gap, marking the
     affirmative action (Save / OK / Send). Secondary buttons (Cancel / Back) stay ringless. The
     outline follows the border-radius, so the ring is rounded like the button. */
  outline: 2px solid var(--dd-rim);
  outline-offset: 2px;
}
.dd-btn-primary:hover { background: linear-gradient(180deg, #5578ff 0%, #3a62e6 30%, #2a50c0 100%); }
.dd-btn-primary:focus-visible { outline-color: var(--dd-select-ink); }
/* The ring extends 4px beyond the button; stacked full-width forms need the extra headroom. */
.dd-stack .dd-btn-primary { margin-top: 6px; }

/* Status / notification bubble. */
.dd-bubble {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 18px;
  border-radius: 18px;
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel);
  color: var(--dd-chrome-dim);
  font-size: 12px;
}

/* --- forms (unlock) --- */
.dd-form {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* `safe center` keeps the form centered when it fits, but falls back to top-aligned (reachable) the
     moment its content is taller than the now viewport-bounded window; plain `center` would push the
     first rows ABOVE the scroll origin where no scrollbar can reach them. overflow-y lets a tall form
     (e.g. Create account, with the recovery warning) scroll on a short screen instead of clipping. */
  justify-content: safe center;
  overflow-y: auto;
  gap: 14px;
  padding: 24px;
  text-align: center;
  color: var(--dd-chrome-ink);
}
.dd-form-title { font-size: 20px; letter-spacing: 0.12em; }
.dd-form-sub { font-size: 13px; color: var(--dd-chrome-dim); }
.dd-form-note { max-width: 30ch; font-size: 11px; line-height: 1.5; color: var(--dd-chrome-dim); margin-top: 6px; overflow-wrap: break-word; }
/* The away editor's special-character legend: each token definition on its own indented line. */
.dd-specials-line { padding-left: 14px; margin-top: 1px; }
/* In the left-aligned settings/identity windows, notes use the full window width instead of a narrow measure. */
.dd-settings .dd-form-note { max-width: none; }
.dd-form-error { font-size: 12px; color: #ff8f8f; }
/* The login/register toggle: a quiet text button under the form, not a primary action. */
.dd-link {
  margin-top: 4px;
  padding: 2px 0;
  font: inherit;
  font-size: 12px;
  color: var(--dd-chrome-dim);
  background: none;
  border: none;
  text-decoration: underline;
  cursor: pointer;
}
.dd-link:hover { color: var(--dd-chrome-ink); }
/* A notice banner above a screen (e.g. the multi-device active-device note). */
.dd-notice {
  margin: 0 0 10px;
  padding: 8px 12px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--dd-chrome-ink);
  background: rgba(120, 140, 200, 0.10);
  border: 1px solid var(--dd-rim);
  border-radius: var(--dd-radius-sm);
}
/* Settings -> Devices screen: a column of device cards + the inline revoke confirm. The 4px padding
   is headroom for the default-button ring (it paints 4px outside a primary button and these screens
   sit flush inside the content well's overflow clip, which was cutting the ring's top/bottom arc). */
.dd-settings { display: flex; flex-direction: column; gap: 10px; width: 100%; min-width: 0; box-sizing: border-box; padding: 4px; }
.dd-device-actions { margin-top: 6px; }
.dd-confirm { font-size: 12px; color: var(--dd-chrome-dim); display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.dd-btn-danger { color: #ffd7d7; border-color: #7a2a2a; background: #3a1414; }
.dd-btn-danger:hover { background: #4a1a1a; }

/* The saved-away-message library in the away editor: one row per message with Load + Delete. */
.dd-away-lib { display: flex; flex-direction: column; gap: 5px; margin-top: 4px; }
.dd-away-lib-row {
  display: flex; align-items: center; gap: 7px;
  padding: 5px 7px;
  border-radius: var(--dd-radius-sm);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.07);
}
.dd-away-lib-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.dd-away-lib-load { flex: none; padding: 3px 10px; font-size: 12px; }
.dd-away-lib-del { flex: none; padding: 3px 9px; font-size: 12px; line-height: 1; }
/* Saved-away-message dropdown row: the select grows, the Delete button stays snug beside it. */
.dd-away-pickrow { margin-bottom: 2px; }
.dd-away-pick { flex: 1; min-width: 0; }
.dd-field { display: flex; gap: 8px; align-items: center; }
/* A centered row of action buttons (Save / Cancel / Back), so the editor screens' footers line up. */
.dd-form-actions { justify-content: center; flex-wrap: wrap; }
/* Device Keys: every button row is centered (the screen is reached from the menu and reads as a panel). */
.dd-settings .dd-field { justify-content: center; flex-wrap: wrap; }
.dd-input {
  font: inherit;
  font-size: 14px;
  padding: 7px 12px;
  width: 12rem;
  max-width: 60vw;
  border-radius: var(--dd-radius-sm);
  border: 1px solid var(--dd-rim);
  background: #11111a;
  box-shadow: var(--dd-well);
  color: var(--dd-chrome-ink);
}
.dd-input:focus { outline: 2px solid var(--dd-select); outline-offset: 1px; }
/* Unlock: username, passphrase, and the button stacked at one width so their edges line up. */
.dd-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 16rem;
  max-width: 72vw;
}
.dd-stack .dd-input,
.dd-stack .dd-btn {
  width: 100%;
  box-sizing: border-box;
}
.dd-stack .dd-btn { margin-top: 2px; text-align: center; }
/* The readonly contact string: wraps the long copy-pasteable token legibly. */
.dd-contact {
  width: 22rem;
  max-width: 72vw;
  resize: none;
  font-size: 11px;
  line-height: 1.45;
  letter-spacing: 0.01em;
  word-break: break-all;
}
.dd-fp-label { font-size: 11px; letter-spacing: 0.12em; color: var(--dd-chrome-dim); text-transform: uppercase; }
.dd-fingerprint {
  font-size: 20px;
  letter-spacing: 0.08em;
  padding: 10px 18px;
  border-radius: var(--dd-radius-sm);
  background: #11111a;
  box-shadow: var(--dd-well);
  color: var(--dd-chrome-ink);
}
/* The one-time recovery secret is a 64-char unbroken hex string: it must WRAP inside the box so the whole
   key stays visible on a narrow phone (otherwise it overflows ~800px wide off both edges and you can only
   read the middle). Bounded to the viewport, broken anywhere, in a mono face so each character is clear. */
.dd-recovery-secret {
  max-width: min(26rem, 84vw);
  box-sizing: border-box;
  word-break: break-all;
  overflow-wrap: anywhere;
  font-family: var(--dd-font-msg);
  font-size: 17px;
  line-height: 1.6;
  letter-spacing: 0.04em;
}

/* --- channel list --- */
.dd-list {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  overflow-y: auto;
}
.dd-channel {
  display: block;
  width: 100%;
  box-sizing: border-box; /* so width:100% + padding fits the list; the right corner stays rounded */
  text-align: left;
  font: inherit;
  padding: 9px 12px;
  border-radius: var(--dd-radius-sm);
  color: var(--dd-chrome-ink);
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel);
  cursor: pointer;
}
.dd-channel:active { box-shadow: var(--dd-bevel-pressed); }
/* The selected channel's row, highlighted (its chat is "flowing" into the right pane). */
.dd-channel-active, .dd-channel-active:active { background: rgba(42, 82, 214, 0.32); border-color: rgba(120, 150, 240, 0.55); box-shadow: none; }
/* Two-pane (master-detail) Channels: the list is a fixed-width LEFT column, the chat fills the RIGHT. */
.dd-channels-2pane { flex: 1; min-height: 0; display: flex; }
.dd-chan-list { flex: 0 0 clamp(170px, 34%, 280px); min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden auto; border-right: 1px solid var(--dd-rim); }
.dd-chan-list .dd-list { padding: 8px; gap: 6px; }
.dd-chan-detail { flex: 1; min-width: 0; min-height: 0; display: flex; position: relative; }
/* The chat pane's way back to the list; only phones need it (the wide layout shows both panes). */
.dd-chan-back { display: none; }
/* PHONE: two side-by-side panes cannot fit, so show ONE at a time. With no open chat the list fills the
   window; opening a chat swaps to it full-width (with the back button above), like every mobile
   messenger. The chat window itself is pinned to 100% so the keyboard shrinks only the log. */
@media (max-width: 640px) {
  .dd-window:has(.dd-channels-2pane) { width: calc(100% - 12px); min-height: 0; height: 100%; max-height: 100%; }
  .dd-chan-list { flex: 1 1 auto; border-right: none; }
  .dd-channels-2pane:has(.dd-chan-detail .dd) .dd-chan-list { display: none; }
  .dd-chan-detail { display: none; }
  .dd-channels-2pane:has(.dd-chan-detail .dd) .dd-chan-detail { display: flex; flex-direction: column; }
  .dd-channels-2pane:has(.dd-chan-detail .dd) .dd-chan-back {
    display: block; flex: 0 0 auto; text-align: left; font: inherit; font-size: 14px;
    padding: 8px 12px; color: var(--dd-chrome-ink); background: var(--dd-face);
    border: 0; border-bottom: 1px solid var(--dd-rim); cursor: pointer;
  }
  .dd-chan-detail .dd { flex: 1; min-height: 0; }
}
.dd-detail-empty { flex: 1; display: flex; align-items: center; justify-content: center; padding: 20px; color: var(--dd-chrome-dim); font-size: 13px; text-align: center; }
.dd-channel-top { display: flex; align-items: center; gap: 8px; font-size: 15px; }
.dd-channel-name { flex: 1; min-width: 0; overflow-wrap: break-word; }
.dd-channel-preview { font-size: 12px; color: var(--dd-chrome-dim); margin-top: 3px; overflow-wrap: break-word; }
.dd-channel-meta { font-size: 10px; color: var(--dd-chrome-dim); margin-top: 4px; letter-spacing: 0.05em; overflow-wrap: break-word; }
.dd-status-dot { width: 9px; height: 9px; border-radius: 50%; box-shadow: 0 0 6px currentColor; }
.dd-status-secure { background: #74f0a8; color: #74f0a8; }
.dd-status-pending { background: var(--dd-warn, #ffce5e); color: #ffce5e; }
.dd-status-blocked { background: #ff8f8f; color: #ff8f8f; }

/* ── Appearance dialog (AIM18): two-pane preferences — categories on the left, controls on the right ── */
.dd-appear-2pane { flex: 1; min-height: 0; display: flex; }
.dd-appear-cats { flex: 0 0 clamp(140px, 32%, 210px); min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 6px; padding: 8px; overflow: hidden auto; border-right: 1px solid var(--dd-rim); }
.dd-appear-cat {
  display: block; width: 100%; box-sizing: border-box; text-align: left; font: inherit;
  padding: 8px 11px; border-radius: var(--dd-radius-sm); color: var(--dd-chrome-ink);
  background: var(--dd-face); border: 1px solid var(--dd-rim); box-shadow: var(--dd-bevel); cursor: pointer;
}
.dd-appear-cat:active { box-shadow: var(--dd-bevel-pressed); }
.dd-appear-cat-active, .dd-appear-cat-active:active { background: rgba(42, 82, 214, 0.32); border-color: rgba(120, 150, 240, 0.55); box-shadow: none; }
.dd-appear-cat-label { display: block; font-size: 14px; }
.dd-appear-cat-blurb { display: block; font-size: 11px; color: var(--dd-chrome-dim); margin-top: 2px; }
.dd-appear-detail { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.dd-appear-body { flex: 1; min-height: 0; overflow: hidden auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; }
.dd-appear-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 14px; border-top: 1px solid var(--dd-rim); }

/* Theme picker: stacked cards, the active one highlighted like a selected channel. */
.dd-appear-themes { display: flex; flex-direction: column; gap: 8px; }
.dd-appear-theme {
  display: block; width: 100%; box-sizing: border-box; text-align: left; font: inherit;
  padding: 10px 13px; border-radius: var(--dd-radius-sm); color: var(--dd-chrome-ink);
  background: var(--dd-face); border: 1px solid var(--dd-rim); box-shadow: var(--dd-bevel); cursor: pointer;
}
.dd-appear-theme:active { box-shadow: var(--dd-bevel-pressed); }
.dd-appear-theme-active, .dd-appear-theme-active:active { background: rgba(42, 82, 214, 0.32); border-color: rgba(120, 150, 240, 0.55); box-shadow: none; }
.dd-appear-theme-name { display: block; font-size: 15px; }
.dd-appear-theme-blurb { display: block; font-size: 12px; color: var(--dd-chrome-dim); margin-top: 3px; }

/* AIM-prefs picker rows (Font / Size / Color …): a fixed label + a dropdown trigger showing the current
   pick; the popup panel reuses the rich-text toolbar chrome (.dd-rt-pop / .dd-rt-fontopt / .dd-rt-sw). */
.dd-appear-row { display: flex; align-items: center; gap: 10px; }
.dd-appear-lbl { flex: none; min-width: 82px; font-size: 13px; color: var(--dd-chrome-dim); text-align: right; }
.dd-appear-popbtn { min-width: 130px; justify-content: space-between; }
.dd-appear-cur { font-size: 13px; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-appear-pop { min-width: 176px; }
.dd-appear-sizes { max-height: 200px; overflow-y: auto; }
.dd-appear-sw-on { outline: 2px solid var(--dd-select-ink); outline-offset: 1px; }

/* The live preview boxes, wrapped in an ISOLATE (all appearance tokens set to 'initial' on it via the
   CSSOM, so the saved look on the root cannot inherit in) and a THEMEBOX carrying the DRAFT theme's class
   (its token values + the .dd-appear-themebox.dd-theme-* surface rules in themes.css apply inside). The
   buddy preview mirrors the real .dd-tree surface but deliberately is NOT a .dd-tree, so the saved root
   theme's descendant rules (.dd-theme-x .dd-tree) cannot reach it. */
.dd-appear-isolate { margin-top: 4px; }
.dd-appear-themebox { display: block; }
.dd-appear-prevbl {
  padding: 8px;
  border-radius: var(--dd-radius-sm);
  background: #0f0f17; /* the stock .dd-tree surface */
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-well);
  font-family: var(--dd-buddy-font, inherit);
  font-size: var(--dd-buddy-size, 13px); /* mirrors the real .dd-tree-buddy stock size */
  color: var(--dd-buddy-ink, var(--dd-chrome-ink));
}
.dd-apb { display: flex; align-items: center; gap: 7px; padding: 3px 6px; }
.dd-apb-enter { font-weight: 700; }
.dd-apb-depart { font-style: italic; opacity: 0.55; }
.dd-appear-prevmsg {
  padding: 12px 14px;
  border: 1px solid var(--dd-rim);
  border-radius: var(--dd-radius-sm);
  box-shadow: var(--dd-well);
  background: var(--dd-field);
  color: var(--dd-ink);
  font-family: var(--dd-font-msg);
  font-size: var(--dd-msg-user-size, 15px);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.dd-apm-sys { color: var(--dd-secure); opacity: 0.85; font-size: 0.82em; letter-spacing: 0.06em; }
.dd-apm-you { color: var(--dd-secure); }
.dd-apm-peer { color: var(--dd-ink-dim, var(--dd-ink)); }
.dd-appear-foot-btns { display: flex; gap: 10px; align-items: center; }

/* Theme-pack import/export. */
.dd-appear-json {
  width: 100%; box-sizing: border-box; min-height: 120px; resize: vertical; font: inherit;
  font-family: ui-monospace, "Cascadia Mono", "Courier New", monospace; font-size: 12px; padding: 8px;
  color: var(--dd-ink); background: var(--dd-field-flat, #0a18a8); border: 1px solid var(--dd-rim);
  border-radius: var(--dd-radius-sm); box-shadow: var(--dd-well);
}
.dd-appear-packbtns { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.dd-appear-file { position: relative; overflow: hidden; }
.dd-appear-file input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.dd-badge {
  min-width: 18px;
  padding: 1px 6px;
  border-radius: 9px;
  font-size: 11px;
  text-align: center;
  color: var(--dd-select-ink);
  background: var(--dd-select);
}

/* --- Identity view (buddy icon, profile, away message) --- */
.dd-id { max-width: none; text-align: left; align-items: stretch; gap: 4px; overflow-y: auto; }
.dd-id .dd-form-title { text-align: center; }
.dd-id-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.dd-id-row { display: flex; gap: 12px; align-items: flex-start; }
/* Shareable contact QR on the Profile screen. */
.dd-qr-section { align-items: center; }
.dd-qr { display: inline-flex; padding: 10px; background: #ffffff; border-radius: 8px; box-shadow: var(--dd-bevel); }
.dd-qr-svg { display: block; }
.dd-qr-link { max-width: 100%; }
.dd-qr-link code {
  display: inline-block;
  max-width: 100%;
  font-size: 11px;
  color: var(--dd-chrome-dim);
  word-break: break-all;
  overflow-wrap: anywhere;
}
/* Add-a-device camera scan + the new device's shown code. */
.dd-scan { display: flex; justify-content: center; margin: 10px 0; }
.dd-scan-video {
  width: 100%;
  max-width: 280px;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: #000000;
  border-radius: 8px;
  box-shadow: var(--dd-bevel);
}
.dd-scan-canvas { display: none; }
.dd-id-preview {
  width: 56px;
  height: 56px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
  line-height: 1;
  border-radius: var(--dd-radius-sm);
  background: #11111a;
  box-shadow: var(--dd-well);
  color: var(--dd-select-ink);
  overflow: hidden;
}
.dd-id-preview-empty { color: var(--dd-chrome-dim); font-size: 22px; }
.dd-id-img { width: 100%; height: 100%; object-fit: cover; }
/* Emoji/initials icon backgrounds as CSP-safe classes (one per ICON_COLORS entry in app.ts), so the
   palette color is applied without an inline style= that the strict CSP would strip. */
.dd-ic-0 { background: #2a52d6; }
.dd-ic-1 { background: #1f9d6b; }
.dd-ic-2 { background: #b0431f; }
.dd-ic-3 { background: #6b3fb0; }
.dd-ic-4 { background: #0b7d8e; }
.dd-ic-5 { background: #8e7a0b; }
.dd-ic-6 { background: #444a5e; }
.dd-id-palette { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.dd-id-emoji-row,
.dd-id-swatch-row { display: flex; flex-wrap: wrap; gap: 4px; }
.dd-id-emoji {
  font: inherit;
  font-size: 18px;
  width: 30px;
  height: 30px;
  line-height: 1;
  border-radius: 7px;
  border: 1px solid var(--dd-rim);
  background: var(--dd-face);
  box-shadow: var(--dd-bevel);
  cursor: pointer;
}
.dd-id-emoji:active { box-shadow: var(--dd-bevel-pressed); }
.dd-id-swatch {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel);
  cursor: pointer;
}
.dd-id-initials { width: 4rem; text-transform: uppercase; }
.dd-id-area {
  width: 100%;
  max-width: none;
  box-sizing: border-box;
  resize: vertical;
  font-size: 13px;
  line-height: 1.4;
}
.dd-id-check { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--dd-chrome-ink); }
.dd-id-upload { display: inline-flex; align-items: center; cursor: pointer; }
.dd-id .dd-form-note { max-width: none; }

/* WYSIWYG rich-text editor: toolbar + contenteditable for away, profile, and the message compose.
   Applied formatting (color/highlight/font) uses these CSS classes, never an inline style, so it renders
   under the strict `style-src 'self'` CSP. The palettes are fixed (see RT_TEXT_COLORS/HL/FONTS in app.ts). */
.dd-c-wh { color: #ffffff; } .dd-c-sl { color: #c8ccd8; } .dd-c-gy { color: #9aa0b0; }
.dd-c-dg { color: #555a68; } .dd-c-bk { color: #000000; } .dd-c-rd { color: #e0504a; }
.dd-c-mr { color: #a02828; } .dd-c-or { color: #e0883b; } .dd-c-br { color: #8a5a2b; }
.dd-c-yl { color: #e8c84a; } .dd-c-gd { color: #d4af37; } .dd-c-lm { color: #a8e05a; }
.dd-c-gn { color: #54c878; } .dd-c-tl { color: #1f9d8e; } .dd-c-cy { color: #48c0d0; }
.dd-c-bl { color: #5a9be0; } .dd-c-nv { color: #3a55b0; } .dd-c-pu { color: #b07ad0; }
.dd-c-mg { color: #d04ad0; } .dd-c-pk { color: #e088c0; }
[class^="dd-hl-"], [class*=" dd-hl-"] { border-radius: 3px; padding: 0 2px; }
/* Legacy 12-swatch highlight keys (single letter): kept so text saved before the palette switch renders. */
.dd-hl-y { background: #e8c84a; color: #11131a; } .dd-hl-o { background: #e0883b; color: #11131a; }
.dd-hl-r { background: #c0403a; color: #ffffff; } .dd-hl-k { background: #e088c0; color: #11131a; }
.dd-hl-m { background: #b03ab0; color: #ffffff; } .dd-hl-p { background: #8e5ab0; color: #ffffff; }
.dd-hl-b { background: #3a63c0; color: #ffffff; } .dd-hl-c { background: #2a9aaa; color: #11131a; }
.dd-hl-g { background: #54c878; color: #11131a; } .dd-hl-s { background: #6b7280; color: #ffffff; }
.dd-hl-w { background: #e8eaf2; color: #11131a; } .dd-hl-d { background: #11131a; color: #e8e8ee; }
/* Highlight palette mirroring the text colors (2-letter keys), each with a legible ink. */
.dd-hl-wh { background: #ffffff; color: #11131a; } .dd-hl-sl { background: #c8ccd8; color: #11131a; }
.dd-hl-gy { background: #9aa0b0; color: #11131a; } .dd-hl-dg { background: #555a68; color: #ffffff; }
.dd-hl-bk { background: #000000; color: #ffffff; } .dd-hl-rd { background: #e0504a; color: #ffffff; }
.dd-hl-mr { background: #a02828; color: #ffffff; } .dd-hl-or { background: #e0883b; color: #11131a; }
.dd-hl-br { background: #8a5a2b; color: #ffffff; } .dd-hl-yl { background: #e8c84a; color: #11131a; }
.dd-hl-gd { background: #d4af37; color: #11131a; } .dd-hl-lm { background: #a8e05a; color: #11131a; }
.dd-hl-gn { background: #54c878; color: #11131a; } .dd-hl-tl { background: #1f9d8e; color: #ffffff; }
.dd-hl-cy { background: #48c0d0; color: #11131a; } .dd-hl-bl { background: #5a9be0; color: #ffffff; }
.dd-hl-nv { background: #3a55b0; color: #ffffff; } .dd-hl-pu { background: #b07ad0; color: #ffffff; }
.dd-hl-mg { background: #d04ad0; color: #ffffff; } .dd-hl-pk { background: #e088c0; color: #11131a; }
.dd-ft-s { font-family: Georgia, "Times New Roman", serif; }
.dd-ft-m { font-family: "Courier New", monospace; }
.dd-ft-r { font-family: "Comic Sans MS", "Comic Sans", cursive; }
.dd-ft-w { font-family: "Arial Black", Impact, sans-serif; }
.dd-ft-h { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
.dd-ft-v { font-family: Verdana, Geneva, sans-serif; }
.dd-ft-b { font-family: "Trebuchet MS", "Lucida Grande", sans-serif; }
.dd-ft-g { font-family: Garamond, "Apple Garamond", "Palatino Linotype", serif; }
.dd-ft-d { font-family: Didot, "Bodoni MT", "Times New Roman", serif; }
.dd-ft-k { font-family: Baskerville, "Palatino Linotype", Palatino, serif; }
.dd-ft-n { font-family: Rockwell, "Courier Bold", "Courier New", serif; }
.dd-ft-t { font-family: "American Typewriter", "Courier New", monospace; }
.dd-ft-f { font-family: Futura, "Century Gothic", "Trebuchet MS", sans-serif; }
.dd-ft-o { font-family: Copperplate, "Copperplate Gothic Light", fantasy; }
.dd-ft-p { font-family: Papyrus, fantasy; }
.dd-ft-c { font-family: "Chalkboard SE", Chalkboard, "Comic Sans MS", cursive; }
.dd-ft-y { font-family: "Marker Felt", "Comic Sans MS", cursive; }
.dd-ft-u { font-family: "Snell Roundhand", "Brush Script MT", cursive; }
/* Extended font bench (2-letter keys). All web-safe system stacks; a missing face falls through. */
.dd-ft-ti { font-family: "Times New Roman", Times, serif; }
.dd-ft-pa { font-family: Palatino, "Palatino Linotype", "Book Antiqua", serif; }
.dd-ft-bo { font-family: "Bookman Old Style", "URW Bookman L", serif; }
.dd-ft-ce { font-family: "Century Gothic", "URW Gothic L", sans-serif; }
.dd-ft-gi { font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif; }
.dd-ft-op { font-family: Optima, "Segoe UI", Candara, sans-serif; }
.dd-ft-ta { font-family: Tahoma, Geneva, sans-serif; }
.dd-ft-se { font-family: "Segoe UI", Segoe, Tahoma, sans-serif; }
.dd-ft-ca { font-family: Calibri, Candara, "Segoe UI", sans-serif; }
.dd-ft-cm { font-family: Cambria, Georgia, serif; }
.dd-ft-co { font-family: Consolas, "Lucida Console", monospace; }
.dd-ft-lu { font-family: "Lucida Sans", "Lucida Grande", sans-serif; }
.dd-ft-mo { font-family: Monaco, Menlo, "Lucida Console", monospace; }
.dd-ft-me { font-family: Menlo, Monaco, monospace; }
.dd-ft-im { font-family: Impact, Haettenschweiler, "Arial Narrow", sans-serif; }
.dd-ft-fr { font-family: "Franklin Gothic Medium", "Arial Narrow", sans-serif; }
.dd-ft-an { font-family: "Arial Narrow", Arial, sans-serif; }
.dd-ft-ho { font-family: "Hoefler Text", Georgia, serif; }
.dd-ft-ch { font-family: Cochin, Georgia, serif; }
.dd-ft-bc { font-family: "Big Caslon", "Book Antiqua", serif; }
.dd-ft-ac { font-family: "Apple Chancery", "Snell Roundhand", cursive; }
.dd-ft-za { font-family: Zapfino, "Snell Roundhand", cursive; }
.dd-ft-bh { font-family: "Bradley Hand", "Comic Sans MS", cursive; }
.dd-ft-nw { font-family: Noteworthy, "Comic Sans MS", cursive; }
.dd-ft-he { font-family: Herculanum, Papyrus, fantasy; }

.dd-rt { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.dd-rt-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 3px; position: relative; }
.dd-rt-btn {
  font: inherit; font-size: 13px; min-width: 26px; height: 26px; line-height: 1; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center; gap: 2px;
  border-radius: 6px; border: 1px solid var(--dd-rim); background: var(--dd-face);
  box-shadow: var(--dd-bevel); color: var(--dd-chrome-ink); cursor: pointer;
}
.dd-rt-btn:active { box-shadow: var(--dd-bevel-pressed); }
.dd-rt-sep { width: 1px; height: 18px; background: var(--dd-rim); margin: 0 3px; }
.dd-rt-A { font-weight: 700; }
.dd-rt-A-sm { font-size: 10px; } .dd-rt-A-lg { font-size: 17px; }
.dd-rt-A-hl { background: #e8c84a; color: #11131a; border-radius: 2px; padding: 0 2px; }
.dd-rt-Ff { font-weight: 700; font-style: italic; }
/* Insert-image toolbar button: a framed-picture glyph sized to sit on the compact compose toolbar. */
.dd-rt-imgbtn svg { width: 15px; height: 15px; fill: currentColor; display: block; }
.dd-compose-rich .dd-rt-imgbtn svg { width: 13px; height: 13px; }
.dd-rt-life-cur { font-size: 12px; white-space: nowrap; }
.dd-rt-caret { font-size: 9px; opacity: 0.7; }
.dd-rt-popwrap { position: relative; display: inline-flex; }
.dd-rt-pop {
  position: absolute; top: 30px; left: 0; z-index: 30; padding: 6px;
  border: 1px solid var(--dd-rim); border-radius: 8px; background: var(--dd-face); box-shadow: var(--dd-well);
}
.dd-rt-pop[hidden] { display: none; }
/* The wide popup (font) anchors to the toolbar BAR's right edge and opens below it, not to its
   own button. The bar spans the full editor width and its edges are always on-screen, so the popup
   stays in view no matter where the button wrapped on a narrow window (anchoring to the button, whose
   wrapped position is unpredictable, was overflowing off either edge). */
.dd-rt-popwrap-font { position: static; }
.dd-rt-pop[data-rt-popid="font"] {
  top: 100%; margin-top: 2px; left: auto; right: 0;
}
/* In the message compose the toolbar sits at the BOTTOM of the window, so every popup opens UPWARD
   (a downward popup would fall off the window edge). Covers button-anchored and bar-anchored pops. */
.dd-compose-rich .dd-rt-pop { top: auto; bottom: calc(100% + 4px); margin-top: 0; }
/* The lifetime list stays SHORT (and scrolls) so the upward pop cannot poke past the terminal's top
   clip on a short/landscape-phone window, which made its top options unreachable. */
.dd-rt-lifetimes { max-height: 7.5rem; min-width: 8rem; }
/* The compose toolbar stays ONE line whenever it fits (wider phones and desktop) and wraps to a second
   row only on the narrowest phones where it physically cannot, instead of overflowing its controls on
   top of the Send button. `wrap` self-gates: a single line when there is room, a second row only when
   forced. Not overflow-x: the toolbar popups (color/font/timer) open upward and would be clipped. */
.dd-compose-rich .dd-rt-bar { flex-wrap: wrap; gap: 2px; }
.dd-compose-rich .dd-rt-btn { min-width: 20px; height: 22px; font-size: 11px; padding: 0 3px; flex: 0 1 auto; }
.dd-compose-rich .dd-rt-life-cur { font-size: 10px; }
.dd-compose-rich .dd-rt-sep { margin: 0 1px; height: 14px; flex: none; }
/* Rich-text sizes render PROPORTIONALLY to their context. The UA maps font[size] to ABSOLUTE sizes,
   so "larger" (size 5 ≈ 24px) was invisible in the CRT compose/log whose base text is already ~24px;
   em units scale with wherever the text appears (compose, log, away bubble, profile). Seven steps around
   the size-4 baseline: three smaller (3/2/1) and three larger (5/6/7), so the toolbar's smaller/larger
   buttons keep moving on every press. Size 4 equals the surrounding text, so "default" reads as unstyled. */
font[size="1"] { font-size: 0.6em; }
font[size="2"] { font-size: 0.72em; }
font[size="3"] { font-size: 0.85em; }
font[size="4"] { font-size: 1em; }
font[size="5"] { font-size: 1.2em; }
font[size="6"] { font-size: 1.45em; }
font[size="7"] { font-size: 1.72em; }
/* Bold has to clear an already-heavy baseline: the CRT log and chrome text run at weight 600, where the
   UA default bold (700) is almost invisible, so pressing B looked like it did nothing. Lift it well clear
   wherever formatted text renders (log messages, the compose + away/profile editors, and the read-only
   away/profile displays). Scoped to CONTENT — .dd-msg not .dd — so it does not restyle the toolbar's own
   <strong>B</strong> button glyph. */
.dd-msg b, .dd-msg strong,
.dd-rt-edit b, .dd-rt-edit strong,
.dd-gi-bio b, .dd-gi-bio strong,
.dd-gi-away b, .dd-gi-away strong,
.dd-blhead-status b, .dd-blhead-status strong { font-weight: 900; }
.dd-rt-swrow { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; }
.dd-rt-sw {
  width: 26px; height: 24px; line-height: 1; font-weight: 700; cursor: pointer;
  border-radius: 5px; border: 1px solid var(--dd-rim); background: var(--dd-bg-well, #11111a); box-shadow: var(--dd-bevel);
}
.dd-rt-fonts { display: flex; flex-direction: column; gap: 3px; min-width: 9rem; max-height: 13rem; overflow-y: auto; }
.dd-rt-fontopt {
  font-size: 14px; text-align: left; padding: 4px 8px; cursor: pointer;
  border-radius: 5px; border: 1px solid var(--dd-rim); background: var(--dd-face); color: var(--dd-chrome-ink);
}
.dd-rt-edit {
  min-height: 3.4em; max-width: none; width: 100%; box-sizing: border-box; padding: 7px 9px;
  border-radius: var(--dd-radius-sm); border: 1px solid var(--dd-rim); background: var(--dd-input-bg, #0d0d14);
  box-shadow: var(--dd-well); color: var(--dd-input-ink, #e8e8ee); overflow-wrap: anywhere;
  font: inherit; outline: none;
}
.dd-rt-edit-1 { min-height: 1.7em; }
.dd-rt-edit-tall { min-height: 6.8em; } /* the away message editor: double the default box height */
.dd-rt-edit:focus { border-color: var(--dd-accent, #5a9be0); }
.dd-rt-edit:empty::before { content: attr(data-rt-ph); color: var(--dd-chrome-dim); pointer-events: none; }
.dd-compose-rich { display: flex; align-items: flex-end; gap: 6px; }
.dd-compose-rich .dd-rt { flex: 1; min-width: 0; }

/* Peer Get-Info panel: buddy cards kept de-emphasized (the fingerprint is the trust anchor). */
.dd-gi { max-width: none; text-align: left; align-items: stretch; }
.dd-gi .dd-form-title,
.dd-gi > .dd-form-sub { text-align: center; }
.dd-gi-card {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 10px;
  margin-top: 8px;
  border-radius: var(--dd-radius-sm);
  background: rgba(120, 140, 200, 0.06);
  box-shadow: var(--dd-well);
  opacity: 0.92;
}
.dd-gi-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.dd-gi-bio { font-size: 13px; line-height: 1.4; color: var(--dd-chrome-ink); word-break: break-word; }
.dd-gi-status { font-size: 12px; color: var(--dd-chrome-dim); }
.dd-gi-away { font-size: 13px; color: var(--dd-chrome-ink); word-break: break-word; }
.dd-gi .dd-form-note { max-width: none; }
/* The Get Info affordance in the conversation header. */
.dd-getinfo { margin-left: 8px; }

/* Buddy list: an AIM-style tree of group folders and plain buddy names, with a "Blocked" drop. The main
   list is read-only; editing lives on the Buddy List Setup screen (.dd-buddysetup). */
.dd-buddies { max-width: none; text-align: left; align-items: stretch; margin-inline: auto; }
.dd-buddies .dd-form-title { text-align: center; }
/* The read-only Buddy List centers its loose text (title, hint, empty state); the tree rows keep their
   own left alignment so folders and names still read as a tree. */
.dd-buddytree { text-align: center; flex: 1; min-height: 0; }
/* On a taller window the tree fills the extra height (so the list grows, AIM-style, instead of leaving
   dead space) and scrolls internally; the toolbar then pins to the window floor. Mirrors the transmit
   window's .dd/.dd-log flex chain. Scoped to .dd-buddytree so the Setup + scan screens are untouched. */
.dd-buddytree .dd-tree { flex: 1; min-height: 0; overflow-y: auto; }
.dd-buddytree .dd-tbar { margin-top: auto; }

/* The recessed list box that holds the tree. */
.dd-tree {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px;
  margin: 4px 0;
  border-radius: var(--dd-radius-sm);
  background: #0f0f17;
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-well);
  /* The user's Buddy List Appearance (AIM19). Unset tokens inherit, so the stock look is untouched;
     group headers keep their own explicit chrome type below. */
  font-family: var(--dd-buddy-font, inherit);
  font-size: var(--dd-buddy-size, inherit);
  color: var(--dd-buddy-ink, inherit);
}
.dd-tree-node { display: flex; flex-direction: column; }
/* A group folder header: a full-width gradient BAR (AIM-style) holding the collapse triangle, folder
   glyph, name, and count. The gradient + top highlight + bottom rim give each group a raised bar that
   stands apart from the plain buddy names indented beneath it. */
.dd-tree-group {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  box-sizing: border-box;
  text-align: left;
  font: inherit;
  font-size: 13px;
  padding: 5px 8px;
  border: 1px solid var(--dd-rim);
  border-radius: var(--dd-radius-sm);
  /* Same raised chrome as a channel card / toolbar button, so the group bars read as one family with
     the rest of the app instead of a darker, flatter one-off gradient. */
  background: var(--dd-face);
  box-shadow: var(--dd-bevel);
  color: var(--dd-chrome-ink);
  cursor: pointer;
}
.dd-tree-group:hover { background: var(--dd-face-hot); }
.dd-tree-group:active { box-shadow: var(--dd-bevel-pressed); }
.dd-tree-static { cursor: default; }
.dd-tree-static:hover { background: var(--dd-face); }
.dd-tree-tri { flex: none; width: 11px; font-size: 9px; color: var(--dd-chrome-dim); }
.dd-tree-folder { flex: none; font-size: 13px; }
.dd-tree-name { flex: 1; min-width: 0; overflow-wrap: break-word; font-weight: 600; }
.dd-tree-count { flex: none; font-size: 11px; color: var(--dd-chrome-dim); }
/* The children of a group are indented under the folder. */
.dd-tree-kids { display: flex; flex-direction: column; gap: 1px; padding: 1px 0 3px 22px; }
/* A buddy is a plain, clickable NAME row (not a chunky button): transparent until hovered. */
.dd-tree-buddy {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  box-sizing: border-box;
  text-align: left;
  font: inherit;
  /* Buddy List Appearance tokens (AIM19); the fallbacks ARE the stock values, so unset = unchanged. */
  font-size: var(--dd-buddy-size, 13px);
  padding: 3px 7px;
  border: 0;
  border-radius: var(--dd-radius-sm);
  background: transparent;
  color: var(--dd-buddy-ink, var(--dd-chrome-ink));
  cursor: pointer;
}
.dd-tree-buddy:hover { background: rgba(42, 82, 214, 0.16); } /* a hint of the app's select blue */
.dd-tree-buddy .dd-status-dot { flex: none; }
.dd-tree-label { min-width: 0; overflow-wrap: break-word; }
/* AIM-style away subtitle: the name + a dim, single-line, ellipsized away-message preview stack in a
   column beside the icon (which stays vertically centered on the whole block). Class-only, CSP-safe. */
.dd-tree-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.dd-tree-sub {
  color: var(--dd-chrome-dim);
  font-size: 11px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Offline (or unknown-status) buddies stay in place, just dimmed so the online ones read first. */
.dd-tree-buddy-off .dd-tree-label { color: var(--dd-chrome-dim); }
.dd-status-offline { background: #6b7280; color: #6b7280; box-shadow: none; }
/* A div-based buddy row (the read-only Blocked drop) is not interactive. */
div.dd-tree-buddy { cursor: default; }
div.dd-tree-buddy:hover { background: transparent; }

/* --- AIM-style buddy list header: your icon, handle, status control, and talk bubble (all local) --- */
.dd-blhead { display: flex; align-items: flex-start; gap: 10px; margin: 2px 0 10px; }
/* The header reuses the identity icon preview at a smaller, list-appropriate size. */
.dd-blhead .dd-id-preview { width: 44px; height: 44px; font-size: 24px; }
.dd-blhead .dd-id-preview-empty { font-size: 18px; }
/* min-width reserves room for the ◆ status control so a very narrow list never squeezes it out; the handle
   truncates on one line rather than wrapping a long name to one character per line beside the conn (AIM26). */
.dd-blhead-txt { flex: 1; min-width: 48px; }
.dd-blhead-name { display: flex; align-items: center; gap: 6px; font-weight: 700; font-size: 14px; }
.dd-blhead-handle { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The little ◆ status control (the AIM running-man of this app): gold while online, dimmed with the
 * away-red caret while away. Clicking it opens the Online / Away dropdown. */
.dd-blhead-st { position: relative; display: inline-flex; flex: none; }
/* A prominent, obviously-clickable status pill: a raised button with a big ◆ presence light. Green
 * (online), dimmed with a red caret (away). Bigger than the handle so it reads as the primary control. */
.dd-blhead-stbtn {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 7px;
  border: 1px solid var(--dd-rim);
  border-radius: var(--dd-radius-sm);
  background: var(--dd-face);
  box-shadow: var(--dd-bevel);
  font: inherit;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.dd-blhead-stbtn:hover { background: var(--dd-face-hot); }
.dd-blhead-stbtn:active { box-shadow: var(--dd-bevel-pressed); }
.dd-blhead-stbtn.dd-st-online { color: #37d05a; text-shadow: 0 0 7px rgba(55, 208, 90, 0.6); }
.dd-blhead-stbtn.dd-st-away { color: var(--dd-chrome-dim); }
.dd-blhead-stbtn.dd-st-away .dd-blhead-caret { color: #e64b4b; }
.dd-blhead-caret { font-size: 11px; color: var(--dd-chrome-dim); }
/* The status dropdown anchors under the ◆ and reuses the app-menu panel styling. */
.dd-st-menu { top: 100%; left: 0; }
/* The talk bubble: the away message while away is on, the profile text otherwise. Its tail points LEFT
 * at your buddy icon, AIM-style, so the bubble reads as the icon "saying" your status. Solid colors so
 * the pseudo-element tail matches exactly. */
.dd-blhead-status {
  position: relative;
  margin-top: 5px;
  margin-left: 4px;
  padding: 5px 8px;
  font-size: 11px;
  line-height: 1.35;
  color: var(--dd-chrome-ink);
  background: #262b3d;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 10px;
  overflow-wrap: anywhere;
}
.dd-blhead-status::before,
.dd-blhead-status::after {
  content: '';
  position: absolute;
  top: 8px;
  width: 0;
  height: 0;
  border-style: solid;
}
/* Two stacked triangles: the outer one draws the border, the inner one fills with the bubble color. */
.dd-blhead-status::before { left: -8px; border-width: 6px 8px 6px 0; border-color: transparent rgba(255, 255, 255, 0.16) transparent transparent; }
.dd-blhead-status::after { left: -6px; border-width: 5px 7px 5px 0; border-color: transparent #262b3d transparent transparent; }
/* A buddy row's small icon: the cached E2E icon, or the initials placeholder. Palette backgrounds come
 * from the shared .dd-ic-N classes (CSP: no inline styles). */
.dd-bic {
  flex: none;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  line-height: 1;
  border-radius: 4px;
  overflow: hidden;
  color: var(--dd-select-ink);
  background: #11111a;
}
.dd-bic-img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* --- Buddy List Setup: selectable rows + Add Buddy / Add Group / Delete --- */
.dd-tree-selectable { cursor: pointer; }
/* A selected row highlights in the app's select BLUE (the same --dd-select the menus use), so the
   buddy list matches the rest of the app instead of a one-off gold. */
.dd-tree-sel, .dd-tree-group.dd-tree-sel:hover {
  background: linear-gradient(180deg, #3a63c0 0%, #2a52d6 55%, #1f3ea8 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 1px 0 rgba(0, 0, 0, 0.45);
}
.dd-tree-buddy.dd-tree-sel, .dd-tree-buddy.dd-tree-sel:hover { background: rgba(42, 82, 214, 0.32); box-shadow: none; }
.dd-tree-sel .dd-tree-name, .dd-tree-sel .dd-tree-label, .dd-tree-sel .dd-tree-count, .dd-tree-sel .dd-tree-tri { color: var(--dd-select-ink); }
.dd-tree-sel .dd-tree-sub { color: var(--dd-select-ink); opacity: 0.75; } /* dim relative to the name, but legible on the select fill */
.dd-setup-row { display: flex; align-items: center; gap: 8px; }
.dd-setup-row .dd-tree-buddy { flex: 1; min-width: 0; }
.dd-buddy-group-sel {
  flex: none;
  font: inherit;
  font-size: 11px;
  max-width: 9rem;
  padding: 4px 6px;
  border-radius: var(--dd-radius-sm);
  color: var(--dd-chrome-ink);
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
}
.dd-setup-add { margin: 8px 0; display: flex; gap: 8px; }
.dd-setup-add .dd-input { flex: 1; max-width: none; }
.dd-setup-btn { flex: none; }
.dd-setup-delete[disabled] { opacity: 0.5; cursor: default; box-shadow: var(--dd-bevel); }

/* --- bottom buddy-list toolbar (AIM-style icon buttons) --- */
.dd-tbar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
  padding: 8px;
  border-radius: var(--dd-radius-sm);
  background: var(--dd-bar);
  border: 1px solid var(--dd-rim);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), var(--dd-well);
}
.dd-tbar-row { display: flex; gap: 6px; align-items: stretch; }
.dd-tbar-btn {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 7px 4px;
  font: inherit;
  border-radius: var(--dd-radius-sm);
  color: var(--dd-chrome-ink);
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel);
  cursor: pointer;
}
.dd-tbar-btn:hover { background: var(--dd-face-hot); }
.dd-tbar-btn:active { box-shadow: var(--dd-bevel-pressed); }
.dd-tbar-btn[disabled] { opacity: 0.4; cursor: default; box-shadow: var(--dd-bevel); background: var(--dd-face); }
/* The buddy-list toolbar buttons wear the same primary blue as the app's action buttons (Save /
   Unlock), so the buddy list matches the rest of the chrome. Scoped to the main buddy list; the
   conversation's IM bar keeps the plain face (its Block button reads danger-red on it). Disabled
   buttons stay the dim gray face so an unavailable action never reads as a live blue button. */
.dd-buddytree .dd-tbar-btn {
  color: var(--dd-select-ink);
  background: linear-gradient(180deg, #4168ec 0%, #2a52d6 30%, #1f40b0 100%);
}
.dd-buddytree .dd-tbar-btn:hover { background: linear-gradient(180deg, #5578ff 0%, #3a62e6 30%, #2a50c0 100%); }
.dd-buddytree .dd-tbar-btn .dd-tbar-ico svg { fill: var(--dd-select-ink); }
.dd-buddytree .dd-tbar-btn .dd-tbar-cap { color: #ccd9ff; }
.dd-buddytree .dd-tbar-btn[disabled] { background: var(--dd-face); color: var(--dd-chrome-ink); }
.dd-buddytree .dd-tbar-btn[disabled] .dd-tbar-ico svg { fill: var(--dd-chrome-dim); }
.dd-buddytree .dd-tbar-btn[disabled] .dd-tbar-cap { color: var(--dd-chrome-dim); }
/* Row 2 (Away, Setup) is horizontal icon + caption, like the AIM buddy-list footer. */
.dd-tbar-wide { flex-direction: row; gap: 7px; padding: 8px 10px; }
.dd-tbar-ico { display: inline-flex; }
.dd-tbar-ico svg { display: block; width: 22px; height: 22px; fill: var(--dd-chrome-ink); }
.dd-tbar-btn[disabled] .dd-tbar-ico svg { fill: var(--dd-chrome-dim); }
/* Captions never wrap; on a narrow phone (4 buttons in a row) they truncate with an ellipsis inside the
   shrunken button instead of spilling out. The full label stays on the button's title/aria-label. */
.dd-tbar-cap { font-size: 10px; letter-spacing: 0.02em; color: var(--dd-chrome-dim); white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.dd-tbar-wide .dd-tbar-cap { font-size: 12px; }
/* The away button's check badge: red when away is on, grey when off. */
.dd-away-on .dd-tbar-check { fill: #e64b4b; }
.dd-away-off .dd-tbar-check { fill: var(--dd-chrome-dim); }

/* --- The IM action bar at the bottom of a conversation (Profile / Add Buddy / Attach File / Call /
 * Video / Block), the AIM bottom-toolbar layout. It reuses the buddy-list toolbar chrome; buttons
 * wrap on a narrow window rather than crushing their captions. Block's icon reads danger-red. --- */
.dd-imbar { margin-top: 10px; }
.dd-imbar .dd-tbar-row { flex-wrap: wrap; }
.dd-imbar .dd-tbar-btn { flex: 1 1 72px; }
.dd-im-block .dd-tbar-ico svg { fill: #e64b4b; }
.dd-im-block .dd-tbar-cap { color: #e64b4b; }

/* In-app notification toast. */
.dd-toast {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom) + 16px);
  transform: translateX(-50%);
  z-index: 50;
  max-width: 80vw;
  padding: 10px 18px;
  border-radius: 18px;
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel);
  color: var(--dd-chrome-ink);
  font-size: 13px;
  animation: dd-toast-in 0.2s ease-out;
}
@keyframes dd-toast-in {
  from { opacity: 0; transform: translate(-50%, 10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

/* Incoming-file accept/decline prompt (P1): a small centered card; accepting goes direct and reveals IP. */
.dd-file-prompt {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom) + 16px);
  transform: translateX(-50%);
  z-index: 60;
  max-width: 88vw;
  width: 360px;
  padding: 14px 16px;
  border-radius: 14px;
  background: var(--dd-face);
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel);
  color: var(--dd-chrome-ink);
  animation: dd-toast-in 0.2s ease-out;
}
.dd-file-prompt-title { font-weight: 600; font-size: 13px; margin-bottom: 4px; }
.dd-file-prompt-name { font-size: 13px; word-break: break-all; margin-bottom: 6px; }
.dd-file-prompt-note { font-size: 11px; opacity: 0.8; margin-bottom: 10px; }
.dd-file-prompt-row { display: flex; gap: 8px; justify-content: flex-end; }

/* In-call overlay (P2): full-screen stage with remote video, a small self-view, and controls. Audio-only
   calls hide the video and show a single large initial. The media is peer-to-peer and never on the server. */
.dd-call {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.82);
}
.dd-call-stage {
  position: relative;
  width: min(92vw, 720px);
  height: min(80vh, 520px);
  border-radius: 16px;
  overflow: hidden;
  background: #0b0e14;
  border: 1px solid var(--dd-rim);
  box-shadow: var(--dd-bevel);
}
.dd-call-remote { width: 100%; height: 100%; object-fit: cover; background: #0b0e14; }
.dd-call-local {
  position: absolute;
  right: 12px;
  bottom: 76px;
  width: 132px;
  height: 99px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--dd-rim);
  background: #11151d;
  transform: scaleX(-1); /* mirror the self-view like a mirror, as call apps do */
}
.dd-call-avatar {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  font-size: 72px;
  color: var(--dd-chrome-ink);
  opacity: 0.7;
}
.dd-call-stage.dd-call-audio .dd-call-remote,
.dd-call-stage.dd-call-audio .dd-call-local { display: none; }
.dd-call-stage.dd-call-audio .dd-call-avatar { display: flex; }
.dd-call-bar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  padding: 10px 14px;
  font-size: 13px;
  color: #fff;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0));
}
.dd-call-controls {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  gap: 8px;
  justify-content: center;
  padding: 12px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}

/* --- AIM-style motion: buddy sign-on/off flashes + window minimize/close. All one-shot (no `forwards`
   fill on the row flashes, so the row returns to its resting style), and all disabled under
   prefers-reduced-motion below. --- */
/* A buddy signing on: a brief green highlight sweep across the row, and the status dot pops. */
@keyframes dd-signon {
  0%   { background: rgba(55, 208, 90, 0); }
  18%  { background: rgba(55, 208, 90, 0.4); }
  100% { background: rgba(55, 208, 90, 0); }
}
@keyframes dd-dotpop {
  0%   { transform: scale(0.2); }
  55%  { transform: scale(1.35); }
  100% { transform: scale(1); }
}
.dd-tree-signon { animation: dd-signon 1.1s ease-out 1; }
.dd-tree-signon .dd-status-dot { animation: dd-dotpop 0.5s ease-out 1; }
/* A buddy signing off: a brief warm dim as the row settles into its grayed offline style. */
@keyframes dd-signoff {
  0%   { background: rgba(224, 80, 74, 0); }
  18%  { background: rgba(224, 80, 74, 0.26); }
  100% { background: rgba(224, 80, 74, 0); }
}
.dd-tree-signoff { animation: dd-signoff 1.1s ease-out 1; }
/* Minimize: the window shrinks and slides up toward the menu-bar chip (both fill keeps it hidden until
   the navigation re-renders, so there is no flash back to full size). */
@keyframes dd-win-min {
  0%   { transform: scale(1) translateY(0); opacity: 1; }
  100% { transform: scale(0.5) translateY(-38%); opacity: 0; }
}
.dd-win-minimizing { animation: dd-win-min 0.24s ease-in 1 both; transform-origin: top center; will-change: transform, opacity; }
/* Close: the window shrinks in place and fades out. */
@keyframes dd-win-close {
  0%   { transform: scale(1); opacity: 1; }
  100% { transform: scale(0.82); opacity: 0; }
}
.dd-win-closing { animation: dd-win-close 0.2s ease-in 1 both; transform-origin: center; will-change: transform, opacity; }

@media (prefers-reduced-motion: reduce) {
  .dd-desk::after { transform: none; opacity: 0.5; }
  .dd-tree-signon, .dd-tree-signoff, .dd-tree-signon .dd-status-dot,
  .dd-win-minimizing, .dd-win-closing { animation: none; }
}

/* ============================ NATIVE DESKTOP SHELL (dd-native) ============================
 * Applied ONLY when the app runs inside the Electron desktop shell (desktop/preload.js sets
 * window.__ddShell, so isNativeShell() adds .dd-native to the root); it is never present in a browser,
 * making this whole block dead for web users. It presents the app as ONE frameless native window with our
 * own chrome: the live window fills the OS frame, the simulated-desktop background + menu bar are dropped,
 * and the titlebar is the window's drag handle. The titlebar's minimize/close buttons drive the OS window
 * (re-targeted in app.ts: minimize -> OS minimize; close -> OS close on the unlock/buddy-list root, or
 * back-out on a sub-window). */
.dd-native .dd-desk::before,
.dd-native .dd-desk::after { display: none !important; }
.dd-native .dd-menubar { display: none; }
.dd-native .dd-stage { padding: 0; }
/* Only the one live window shows; parked snapshots (the simulated multi-window desktop) are hidden. */
.dd-native .dd-window.dd-window-parked { display: none !important; }
.dd-native .dd-window:not(.dd-window-parked) {
  position: fixed !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  max-width: none !important;
  max-height: none !important;
  min-width: 0 !important;
  min-height: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  transform: none !important;
  margin: 0 !important;
  resize: none !important;
}
/* The app titlebar is the frameless window's drag region; interactive children opt out so they still click. */
.dd-native .dd-titlebar { -webkit-app-region: drag; }
.dd-native .dd-titlebar button,
.dd-native .dd-titlebar a,
.dd-native .dd-titlebar input,
.dd-native .dd-titlebar .dd-menu-dropdown,
.dd-native .dd-titlebar .dd-winctl,
.dd-native .dd-titlebar .dd-winmenu { -webkit-app-region: no-drag; }

/* ── Landing page: attribution, the desktop downloads, and the Signal comparison (AIM27) ─────────
   These sit under the login form on the WEB only; renderUnlock omits the last two inside the native
   shell. Everything is class-driven (the strict CSP forbids inline styles), and the measure widens
   past .dd-form-note's 30ch because a comparison table needs the room. */
.dd-attrib { max-width: none; margin-top: 10px; text-align: center; }
.dd-extlink { color: var(--dd-accent, #5a9be0); text-decoration: underline; }
.dd-extlink:hover { color: var(--dd-ink); }

.dd-compare {
  box-sizing: border-box;
  width: 100%;
  max-width: 560px;
  margin-top: 18px;
  padding: 12px 14px;
  border: 1px solid var(--dd-rim);
  border-radius: var(--dd-radius-sm);
  background: var(--dd-face);
  box-shadow: var(--dd-bevel);
}
.dd-compare-title {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dd-chrome-ink);
  margin-bottom: 8px;
}
/* The table scrolls inside its own box on a narrow phone so the page body never scrolls sideways. */
.dd-compare-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 11px;
  line-height: 1.45;
  color: var(--dd-chrome-dim);
  display: block;
  overflow-x: auto;
}
.dd-compare-table th,
.dd-compare-table td {
  padding: 5px 8px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--dd-rim);
}
.dd-compare-table thead th { color: var(--dd-chrome-ink); font-weight: 700; white-space: nowrap; }
.dd-compare-table tbody th { color: var(--dd-chrome-ink); font-weight: 400; white-space: nowrap; }
.dd-compare-table tbody tr:last-child th,
.dd-compare-table tbody tr:last-child td { border-bottom: none; }
.dd-compare-note { margin-top: 10px; font-size: 11px; line-height: 1.5; color: var(--dd-chrome-dim); }

/* Phones: STACK the comparison instead of scrolling it sideways. Three columns plus nowrap row headers
   give the table a ~352px intrinsic width, and at 375px there are only ~255px inside the box, so the
   Signal column sat off the edge and read as cut off. Here each row becomes a labelled block: the
   feature is a heading, and each cell prints its column name from data-col. The form's side padding
   also comes down, which hands the whole landing column another ~24px. */
@media (max-width: 560px) {
  .dd-form { padding-left: 12px; padding-right: 12px; }
  .dd-compare-table { display: block; overflow-x: visible; }
  .dd-compare-table thead { display: none; }
  .dd-compare-table tbody,
  .dd-compare-table tr,
  .dd-compare-table th,
  .dd-compare-table td { display: block; width: auto; }
  .dd-compare-table tr { padding: 8px 0; border-bottom: 1px solid var(--dd-rim); }
  .dd-compare-table tr:last-child { border-bottom: none; }
  .dd-compare-table tbody th {
    padding: 0 0 4px;
    border-bottom: none;
    white-space: normal; /* the nowrap that widened the table is exactly what must not apply here */
    font-weight: 700;
  }
  .dd-compare-table tbody td { padding: 0 0 4px; border-bottom: none; }
  .dd-compare-table tbody tr td:last-child { padding-bottom: 0; }
  .dd-compare-table tbody td::before {
    content: attr(data-col);
    display: block;
    font-size: 10px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--dd-chrome-ink);
  }
}

.dd-downloads { width: 100%; max-width: 560px; margin-top: 14px; text-align: center; }
.dd-downloads-title {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dd-chrome-ink);
  margin-bottom: 8px;
}
.dd-downloads-row { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.dd-dl { text-decoration: none; text-align: center; flex: 1 1 200px; }
.dd-downloads .dd-form-note { max-width: none; margin-top: 8px; text-align: center; }

/* The landing-page pitch, above the comparison. Web only (renderUnlock omits it in the native shell). */
.dd-pitch { width: 100%; max-width: 560px; margin-top: 18px; text-align: left; }
.dd-pitch-lead {
  font-size: 15px;
  line-height: 1.35;
  color: var(--dd-chrome-ink);
  margin-bottom: 8px;
  text-align: center;
}
.dd-pitch-p {
  margin: 0 0 8px;
  font-size: 11px;
  line-height: 1.6;
  color: var(--dd-chrome-dim);
  overflow-wrap: break-word;
}
.dd-pitch-p:last-child { margin-bottom: 0; }

/* ── Contact verification (Verify Buddy panel + buddy-list badge) ─────────────────────────────────
   The panel reuses .dd-sas-words for the six words. Framed panels size border-box and take the theme
   radius so the retro themes square them (the R13 review's lesson, applied from the start). */
.dd-verify {
  box-sizing: border-box;
  width: 100%;
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px solid var(--dd-rim);
  border-radius: var(--dd-radius-sm);
  background: rgba(120, 140, 200, 0.06);
}
.dd-verify-title {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dd-chrome-ink);
  margin-bottom: 6px;
}
.dd-verify-ok .dd-verify-title { color: #74f0a8; }
.dd-verify-changed { border-color: #7a2a2a; background: rgba(122, 42, 42, 0.12); }
.dd-verify-changed .dd-verify-title { color: #ff8f8f; }
.dd-verify-warn { font-size: 12px; line-height: 1.5; color: #ffd7d7; margin-bottom: 6px; }
.dd-verify-words { margin: 6px 0; }
.dd-verify .dd-form-note { max-width: none; }
.dd-verify .dd-field { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }

/* The list badge rides inside the name label: a quiet check, or a loud changed marker. */
.dd-tree-verify {
  margin-left: 4px;
  font-size: 10px;
  color: #74f0a8;
}
/* Pinned but not currently checkable: a hollow, dim marker. Deliberately not green and not the check
   glyph, so it can never be misread as a live confirmation. */
.dd-tree-verify-stale { color: var(--dd-chrome-dim); }
.dd-tree-verify-bad {
  color: #ff8f8f;
  font-weight: 700;
  padding: 0 4px;
  border: 1px solid #7a2a2a;
  border-radius: var(--dd-radius-sm);
  background: rgba(122, 42, 42, 0.25);
}

/* Two phrases, side by side on a wide window and stacked on a narrow one. */
.dd-verify-pair { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0; }
.dd-verify-half { flex: 1 1 220px; min-width: 0; }
.dd-verify-label {
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dd-chrome-dim);
  margin-bottom: 2px;
}
.dd-verify-stale { border-style: dashed; }
.dd-verify-stale .dd-verify-title { color: var(--dd-chrome-dim); }
