:root {
  --bg: #0e0e0e;
  --fg: #d4d4d4;
  --muted: #6b6b6b;
  --rule: #262626;
  --field: #161616;
  --ok: #4ade80;
  --down: #ef4444;
  --warn: #eab308;
}
* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0; background: var(--bg);
  overflow-x: hidden; /* prevent any stray child from forcing a horizontal scroll on mobile */
}
body {
  color: var(--fg);
  font: 14px/1.55 ui-monospace, "SF Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
main {
  width: 100%;
  max-width: 780px;
  margin: 0 auto;
  padding: 2rem clamp(1rem, 4vw, 2rem) 1rem;
  flex: 1 1 auto;
}
h1 {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--fg);
}
h1 .path { color: var(--muted); font-weight: 400; }
.rule {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 0.75rem 0 1.25rem;
}
p { margin: 0 0 1rem; }
.about, .help { color: var(--muted); max-width: 60ch; }

dl.kv {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: 0.35rem 1rem;
  margin: 0 0 1.25rem;
}
dl.kv dt { color: var(--muted); }
dl.kv dd { margin: 0; color: var(--fg); }

.dot {
  display: inline-block;
  width: 0.55em; height: 0.55em;
  background: var(--ok);
  margin-right: 0.55em;
  vertical-align: 0.08em;
}
.dot.down { background: var(--down); }
.dot.stale { background: var(--warn); }

.num { font-variant-numeric: tabular-nums; }
.num .slash, .num .max { color: var(--muted); }

/* action row */
.actions {
  margin: 1.5rem 0;
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  align-items: center;
}
.actions .badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--muted);
  flex-wrap: wrap;     /* long names wrap under the avatar on narrow screens */
  min-width: 0;
}
a.btn, button {
  font: inherit;
  color: var(--fg);
  background: var(--field);
  border: 1px solid var(--rule);
  padding: 0.55rem 1rem;
  min-height: 2.25rem;
  text-decoration: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
a.btn:hover, button:hover { border-color: var(--fg); color: var(--fg); }
a.btn.primary, button.primary { border-color: var(--fg); }
button:focus-visible, a.btn:focus-visible, input:focus-visible {
  outline: 1px solid var(--fg);
  outline-offset: 1px;
}

/* form */
form { margin: 1rem 0; }
form > * + * { margin-top: 0.85rem; }
label {
  display: block;
  color: var(--muted);
}
label .req { color: var(--fg); }
input[type="text"], input:not([type]) {
  font: inherit;
  width: 100%;
  max-width: 22rem;
  background: var(--field);
  color: var(--fg);
  border: 1px solid var(--rule);
  padding: 0.55rem 0.75rem;
  margin-top: 0.25rem;
}
input:focus { border-color: var(--fg); }
.token-input { letter-spacing: 0.25em; text-transform: uppercase; font-size: 1.1em; }

.err { color: var(--down); }
.ok { color: var(--ok); }

a { color: var(--fg); text-decoration: underline; text-underline-offset: 2px; text-decoration-color: var(--rule); }
a:hover { text-decoration-color: var(--fg); }

code.kbd {
  font-family: inherit;
  background: var(--field);
  border: 1px solid var(--rule);
  padding: 0.05rem 0.35rem;
}

footer {
  max-width: 780px;
  width: 100%;
  margin: 0 auto;
  padding: 1rem clamp(1rem, 4vw, 2rem) 1.5rem;
  color: var(--muted);
  border-top: 1px solid var(--rule);
}

@media (max-width: 480px) {
  dl.kv { grid-template-columns: 5.5rem 1fr; }
  main { padding-top: 1.25rem; }
  input[type="text"], input:not([type]) { max-width: 100%; }
}

/* ─── Avatars ──────────────────────────────────────────────────────── */
.avatar {
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  display: inline-block;
  vertical-align: middle;
  background: var(--field);
  flex: 0 0 auto;
}
.actions .avatar { margin-right: 0.1rem; }

/* ─── Chat page ───────────────────────────────────────────────────── */
/* Mobile-native app shell. The .app container is position: fixed and
   pinned to (visualViewport.offsetTop, visualViewport.height) via the
   --app-y / --app-h custom props that chat()'s setupViewport() keeps
   fresh. This survives every iOS-Safari keyboard quirk we care about:
   - iOS 17+ shrinks the layout viewport with interactive-widget
     (good, but we still need --app-y when the visual viewport pans).
   - iOS 16/earlier don't shrink at all, and pan the visual viewport
     up to keep the focused input in frame. Without the pin, our
     header would scroll above the visible area and the composer
     would slide beneath the keyboard.
   With the pin, the header is always at the top of the visible area
   and the composer is always at the bottom. */
body.chat-body {
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
}

.app {
  position: fixed;
  top: var(--app-y, 0);
  left: 0;
  right: 0;
  margin-inline: auto;
  width: 100%;
  max-width: 1040px;
  height: var(--app-h, 100dvh);
  /* Notch + rounded-corner safe areas. inset-bottom is handled by
     .composer so the send bar sits above the home indicator. */
  padding-top: env(safe-area-inset-top);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
  box-sizing: border-box;
  /* Flex column — the scroll pane is the one thing that grows and
     shrinks with the viewport. The composer stays content-sized and
     naturally pins to the bottom as the last flex child. (Grid was
     wrong here: with an optional bridge-notice, auto-placement
     dropped the composer into the 1fr track and it stretched.) */
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* App bar — sticky, translucent, iOS-style */
.app-bar {
  flex: 0 0 auto;
  position: relative;
  z-index: 10;
  background: rgba(14, 14, 14, 0.82);
  backdrop-filter: saturate(1.3) blur(12px);
  -webkit-backdrop-filter: saturate(1.3) blur(12px);
}
.app-bar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.55rem 0.85rem 0.45rem;
  gap: 0.75rem;
  min-height: 2.75rem;
}
.brand-wrap {
  position: relative;
  min-width: 0;
}
.brand {
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  margin: 0;
  color: var(--fg);
  background: transparent;
  border: 0;
  padding: 0.25rem 0.4rem;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  letter-spacing: 0.01em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  min-height: 0;
}
.brand:hover { background: rgba(255, 255, 255, 0.04); }
.brand.is-open { background: rgba(255, 255, 255, 0.06); }
.brand .path { color: var(--muted); font-weight: 400; }
.brand-caret {
  color: var(--muted);
  font-size: 0.7em;
  transition: transform 120ms ease;
  margin-left: 0.1rem;
}
.brand.is-open .brand-caret { transform: rotate(-180deg); }

/* Presence dropdown — anchored under the brand. Uses backdrop-filter
   to feel like part of the app bar. */
.presence-dropdown {
  position: absolute;
  top: calc(100% + 0.25rem);
  left: 0;
  z-index: 20;
  min-width: 16rem;
  max-width: min(22rem, calc(100vw - 1.5rem));
  padding: 0.35rem;
  background: rgba(22, 22, 22, 0.96);
  border: 1px solid var(--rule);
  border-radius: 12px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
  backdrop-filter: saturate(1.2) blur(14px);
  -webkit-backdrop-filter: saturate(1.2) blur(14px);
}
.presence-header {
  color: var(--muted);
  font-size: 0.72em;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 0.3rem 0.5rem 0.25rem;
}
.presence-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 60vh;
  overflow-y: auto;
}
.presence-list li {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.35rem 0.5rem;
  border-radius: 8px;
  line-height: 1.2;
}
.presence-list li .n {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--fg);
}
.presence-list li.muted {
  opacity: 0.45;
}
.presence-list li.muted .avatar { filter: grayscale(0.6); }
.presence-list li.muted .n { text-decoration: line-through; color: var(--muted); }
.presence-list li .left-badge {
  font-size: 0.68em;
  color: var(--muted);
  background: var(--field);
  border: 1px solid var(--rule);
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  text-transform: lowercase;
}
.presence-list li.empty {
  color: var(--muted);
  font-style: italic;
  justify-content: center;
  padding: 0.9rem 0.5rem;
}

.me {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--muted);
  font-size: 0.82em;
  min-width: 0;
}
.me .me-name {
  color: var(--fg);
  max-width: 9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.logout-form { margin: 0; }

.icon-btn {
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--muted);
  font: inherit;
  min-height: 0;
  padding: 0.35rem 0.5rem;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.icon-btn:hover, .icon-btn:focus-visible {
  color: var(--fg);
  border-color: var(--fg);
}

/* Connection dot — subtle pulse when reconnecting */
.conn-dot {
  display: inline-block;
  width: 0.55em;
  height: 0.55em;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.5);
}
.conn-dot.down {
  background: var(--down);
  animation: pulse 1.4s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.5); }
  50%      { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); }
}

/* Segmented tab control — iOS-style pill. Capped on desktop so two
   channels don't stretch the whole 1040px column; centred via auto
   margins. */
.segmented {
  padding: 0 0.6rem 0.55rem;
}
.segmented-inner {
  display: flex;
  gap: 0.2rem;
  background: var(--field);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 0.22rem;
  max-width: 28rem;
  margin: 0 auto;
}
.segmented button {
  flex: 1 1 0;
  background: transparent;
  border: 0;
  color: var(--muted);
  font: inherit;
  font-size: 0.9em;
  padding: 0.45rem 0.5rem;
  min-height: 2rem;
  border-radius: 8px;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
  -webkit-tap-highlight-color: transparent;
}
.segmented button:not(.active):hover { color: var(--fg); }
.segmented button.active {
  background: #1c1c1c;
  color: var(--fg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.02);
}

/* Bridge notice */
.bridge-notice {
  flex: 0 0 auto;
  color: var(--warn);
  background: rgba(234, 179, 8, 0.06);
  font-size: 0.78em;
  text-align: center;
  padding: 0.35rem 0.9rem;
  border-bottom: 1px solid var(--rule);
}
.bridge-notice code {
  background: transparent;
  border: 0;
  color: inherit;
  font-weight: 600;
}

/* Scroll pane — the only scrolling region on the page, and the only
   flex child that grows. Sits between the header and the composer
   and absorbs whatever viewport room is left. */
.scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 0.5rem 0.85rem 0.75rem;
  display: flex;
  flex-direction: column;
}
.scroll-inner {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

/* Message row — avatar pinned to the top so it doesn't drift to the
   vertical centre as the bubble grows while typing or on multi-line
   messages. */
.msg {
  display: flex;
  align-items: flex-start;
  gap: 0.45rem;
  max-width: 100%;
}
.msg .avatar {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  align-self: flex-start;
  border-radius: 4px;
  /* Nudge down slightly so the avatar aligns with the name header
     line rather than sitting above the bubble. */
  margin-top: 2px;
}

/* Bubble — card-ish. Chamfer points at the avatar (top-left).
   Width cap keeps long lines readable on desktop; the 82% fallback
   is for narrow viewports. */
.msg .bubble {
  background: #181818;
  border: 1px solid var(--rule);
  border-radius: 14px;
  border-top-left-radius: 4px;
  padding: 0.35rem 0.65rem 0.3rem;
  max-width: min(82%, 36rem);
  min-width: 0;
  line-height: 1.45;
}
.msg .from {
  font-size: 0.72em;
  font-weight: 600;
  color: var(--fg);
  opacity: 0.85;
  margin-bottom: 0.1em;
  word-break: break-word;
}
.msg .body {
  word-break: break-word;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.msg .t {
  display: block;
  font-size: 0.66em;
  color: var(--muted);
  text-align: right;
  margin-top: 0.15rem;
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}

/* Own chat messages — right-aligned, subtly tinted */
.msg.mine { justify-content: flex-end; }
.msg.mine .bubble {
  background: #16251c;
  border-color: #223528;
  border-radius: 14px;
  border-top-right-radius: 4px;
}

/* Joined / left / system — centered caption pill */
.msg.kind-joined,
.msg.kind-left,
.msg.kind-system {
  justify-content: center;
  margin: 0.15rem 0;
}
.msg.kind-joined .bubble,
.msg.kind-left   .bubble,
.msg.kind-system .bubble {
  background: transparent;
  border: 0;
  padding: 0.1rem 0.5rem;
  max-width: 90%;
  text-align: center;
}
.msg.kind-joined .body,
.msg.kind-left   .body,
.msg.kind-system .body {
  color: var(--muted);
  font-style: italic;
  font-size: 0.86em;
}
.msg.kind-joined .body::before { content: "→ "; }
.msg.kind-left   .body::before { content: "← "; }
.msg.kind-joined .t,
.msg.kind-left   .t,
.msg.kind-system .t { display: none; }

.empty-notice {
  color: var(--muted);
  text-align: center;
  padding: 2rem 1rem;
  font-style: italic;
}

/* Composer — floating input with circular send. Content-sized; does
   not grow or shrink, so it's always pinned at the bottom of .app.
   Bottom padding: tight base (0.15rem) + safe-area-inset-bottom so
   the input hugs the keyboard when it's open (inset=0) and sits
   just above the home indicator when it's not (inset≈34px on iOS).
   The visible gap below the input was the old 0.45rem base; most
   of it was dead space. */
.composer {
  flex: 0 0 auto;
  margin: 0;
  padding: 0.4rem 0.75rem 0.15rem;
  padding-bottom: calc(0.15rem + env(safe-area-inset-bottom));
  background: rgba(14, 14, 14, 0.92);
  backdrop-filter: saturate(1.2) blur(10px);
  -webkit-backdrop-filter: saturate(1.2) blur(10px);
  /* Anchor for the @mention popup, which absolutes itself upward
     from the composer's top edge. */
  position: relative;
}
.composer-inner {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
}
.composer input {
  flex: 1 1 auto;
  margin: 0;
  max-width: unset;
  /* 16px minimum avoids iOS auto-zoom on focus */
  font-size: 16px;
  line-height: 1.3;
  padding: 0.6rem 0.95rem;
  min-height: 2.5rem;
  border-radius: 999px;
  background: var(--field);
  border: 1px solid var(--rule);
  color: var(--fg);
}
.composer input::placeholder { color: var(--muted); }
.composer input:focus {
  border-color: #3a3a3a;
  outline: none;
}

/* @mention popup — rises above the composer, width-matched to the
   visible composer interior, scrolls internally when the list is
   long. mousedown on an item uses .prevent so the input keeps
   focus across the click. */
.mention-popup {
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  bottom: 100%;
  margin-bottom: 0.35rem;
  max-height: 14rem;
  overflow-y: auto;
  padding: 0.25rem;
  background: rgba(22, 22, 22, 0.97);
  border: 1px solid var(--rule);
  border-radius: 12px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
  backdrop-filter: saturate(1.2) blur(14px);
  -webkit-backdrop-filter: saturate(1.2) blur(14px);
  z-index: 15;
}
.mention-item {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  padding: 0.35rem 0.5rem;
  background: transparent;
  border: 0;
  border-radius: 8px;
  color: var(--fg);
  font: inherit;
  text-align: left;
  cursor: pointer;
  min-height: 0;
  -webkit-tap-highlight-color: transparent;
}
.mention-item .n {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mention-item.active {
  background: rgba(0, 215, 175, 0.12);
  color: var(--fg);
}
.mention-item:hover { color: var(--fg); }

.send-btn {
  flex: 0 0 auto;
  margin: 0;
  padding: 0;
  width: 2.5rem;
  height: 2.5rem;
  min-height: 0;
  border-radius: 999px;
  background: var(--fg);
  color: var(--bg);
  border: 1px solid var(--fg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 80ms ease, opacity 120ms ease;
  -webkit-tap-highlight-color: transparent;
}
.send-btn:active { transform: scale(0.94); }
.send-btn:disabled {
  background: var(--field);
  color: var(--muted);
  border-color: var(--rule);
  cursor: not-allowed;
  opacity: 0.7;
}
.send-btn:disabled:hover {
  color: var(--muted);
  border-color: var(--rule);
}
.send-btn svg { display: block; }

@media (max-width: 480px) {
  .app-bar-row { padding: 0.45rem 0.7rem 0.4rem; }
  .segmented   { padding: 0 0.55rem 0.5rem; }
  .scroll      { padding: 0.4rem 0.65rem 0.65rem; }
  .composer    { padding-left: 0.6rem; padding-right: 0.6rem; }
  .me .me-name { max-width: 6.5rem; }
  .msg .bubble { max-width: 88%; }
}

@media (max-width: 360px) {
  .me .me-name { display: none; }
}
