/* Two palettes. The dark values are written once as --d-* and assigned in the
   two places that can select dark - the phone's own setting, and a manual
   choice - so the two can never drift apart. A test checks they match. */
:root {
  --d-bg: #14120F;
  --d-surface: #1D1A16;
  --d-line: #2F2A23;
  --d-text: #EDE8E0;
  --d-muted: #A89E90;
  --d-accent: #4FB89E;
  --d-green: #5CBE79;
  --d-mine: #22322E;
  --d-mine-line: #33463F;
  --d-mine-link: #8FD8C5;
  --d-danger: #EC8779;
  --d-danger-bg: #3A211D;
  --d-badge: #EDE8E0;
  --d-badge-ink: #14120F;

  /* warm daylight */
  --bg: #F7F4EF;
  --surface: #FFFDFA;
  --line: #E6E0D6;
  --text: #23201C;
  --muted: #6B6257;
  --accent: #2E7D6B;
  --green: #3C8C57;
  --mine: #E3EFEA;
  --mine-line: #CBE0D7;
  --mine-link: #1F5C4F;
  --danger: #B23A2E;
  --danger-bg: #F8E6E2;
  --badge: #2B2822;
  --badge-ink: #FFFFFF;

  --pad: 12px;
  color-scheme: light;
}

/* the phone's own setting, unless a light theme was chosen by hand */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: var(--d-bg);
    --surface: var(--d-surface);
    --line: var(--d-line);
    --text: var(--d-text);
    --muted: var(--d-muted);
    --accent: var(--d-accent);
    --green: var(--d-green);
    --mine: var(--d-mine);
    --mine-line: var(--d-mine-line);
    --mine-link: var(--d-mine-link);
    --danger: var(--d-danger);
    --danger-bg: var(--d-danger-bg);
    --badge: var(--d-badge);
    --badge-ink: var(--d-badge-ink);
    color-scheme: dark;
  }
}

/* chosen by hand, which wins in both directions */
:root[data-theme="dark"] {
  --bg: var(--d-bg);
  --surface: var(--d-surface);
  --line: var(--d-line);
  --text: var(--d-text);
  --muted: var(--d-muted);
  --accent: var(--d-accent);
  --green: var(--d-green);
  --mine: var(--d-mine);
  --mine-line: var(--d-mine-line);
  --mine-link: var(--d-mine-link);
  --danger: var(--d-danger);
  --danger-bg: var(--d-danger-bg);
  --badge: var(--d-badge);
  --badge-ink: var(--d-badge-ink);
  color-scheme: dark;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.4 Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* app frame: header / thread / composer, sized to the visual viewport */
#app {
  display: flex;
  flex-direction: column;
  height: 100%;
  height: var(--vh, 100%);
}

/* ---------- header ---------- */
header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: calc(env(safe-area-inset-top) + 10px) var(--pad) 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

#who { max-width: 34%; min-width: 0; }
#name, #sub { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
#name { font-weight: 700; font-size: 17px; line-height: 1.2; }
/* "online", or "last online 3 hrs ago" while they are away */
#sub { font-size: 11px; color: var(--muted); line-height: 1.2; }
#sub.on { color: var(--green); }

/* one dot: whether the other person is connected */
#link { display: flex; align-items: center; }

.dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--line);
  flex: 0 0 auto;
  transition: background .25s ease;
}
.dot.online { background: var(--green); }

#spacer { flex: 1 1 auto; }

.hbtn {
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 22px;
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
  background: var(--surface);
}
.hbtn.on { color: #fff; background: var(--accent); border-color: var(--accent); }
/* icon-only actions stay square so three of them still fit a 320px header */
.hbtn.icon { width: 44px; padding: 0; }
#call-btn:not([disabled]) { color: var(--accent); border-color: var(--accent); }
.hbtn[disabled] { opacity: .4; }

/* ---------- thread ---------- */
#thread {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
  padding: var(--pad);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

#top-loader {
  align-self: center;
  padding: 8px;
  font-size: 13px;
  color: var(--muted);
}
#top-loader[hidden] { display: none !important; }

/* a date between days, so a thread that spans time reads as one */
.day {
  align-self: center;
  margin: 8px 0 2px;
  padding: 3px 10px;
  border-radius: 10px;
  background: var(--line);
  font-size: 11px;
  font-weight: 500;
  color: var(--muted);
}

/* a missed call reads as a note about what happened, not as a message */
.row.callnote { align-self: center; align-items: center; max-width: 100%; }
.callpill {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 14px;
  background: var(--line);
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
}
.callpill.missed { background: var(--danger-bg); color: var(--danger); }
.callpill .when { font-weight: 400; opacity: .75; }

.row { display: flex; flex-direction: column; max-width: 82%; position: relative; }
.row.mine { align-self: flex-end; align-items: flex-end; }
.row.theirs { align-self: flex-start; align-items: flex-start; }

.bubble {
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 8px 12px;
  background: var(--surface);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.row.mine .bubble { background: var(--mine); border-color: var(--mine-line); }

/* Attachment bubbles: the media takes the tap, so the actions live behind a
   small ... button - overlaid on a photo or video, beside the row for a file
   or a pin. Text bubbles need none of this; a tap anywhere on them works. */
.bubble { position: relative; }
.bubble .more {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 44px;
  height: 44px;
  border-radius: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: rgba(0, 0, 0, .45);
}
.bubble.att { padding-right: 56px; }   /* keep a filename or address clear of it */
.bubble.att .more {
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  background: var(--bg);
}
.row.deleted .bubble { color: var(--muted); font-style: italic; background: var(--bg); }
.row.highlight .bubble { border-color: var(--accent); }

.quote {
  display: block;
  width: 100%;
  text-align: left;
  border-left: 2px solid var(--accent);
  padding: 2px 0 2px 8px;
  margin-bottom: 4px;
  font-size: 13px;
  color: var(--muted);
}
.quote b { color: var(--text); font-weight: 700; display: block; }

.bubble img {
  display: block;
  max-width: 100%;
  width: 240px;
  border-radius: 10px;
  margin: -2px 0 0;
  background: var(--bg);
}
.bubble img + .caption { margin-top: 6px; }

.meta {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 6px;
  font-size: 11px;
  color: var(--muted);
}
.edited { color: var(--muted); }
.tick { letter-spacing: -2px; }
.tick.seen { color: var(--accent); }

.progress {
  height: 3px;
  border-radius: 2px;
  background: var(--line);
  margin-top: 6px;
  overflow: hidden;
}
.progress i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .15s linear; }

/* a failed upload has to look failed, not half sent */
.upload-error { margin-top: 6px; font-size: 12px; color: var(--danger); }
.note { margin-top: 6px; font-size: 12px; color: var(--muted); }
.row.failed .bubble { border-color: var(--danger); }

/* The action panel floats over the thread instead of sitting in it, so opening
   it shifts nothing. Anchored above the bubble, because the message being
   tapped is usually the newest one and below it is off the screen. */
.sheet {
  position: absolute;
  bottom: calc(100% - 2px);
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: max-content;
  max-width: 76vw;
  padding: 8px;
  border-radius: 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .16);
}
.row.mine .sheet { right: 0; }
.row.theirs .sheet { left: 0; }
/* no room above - only happens at the very top of the thread */
.sheet.below { bottom: auto; top: calc(100% - 2px); }

.actions {
  display: flex;
  gap: 6px;
  padding: 0;
}
.actions button {
  min-height: 36px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--surface);
  font-size: 14px;
  font-weight: 500;
}
.actions button.danger { color: var(--danger); }

/* ---------- composer ---------- */
#composer {
  flex: 0 0 auto;
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding: 8px var(--pad) calc(env(safe-area-inset-bottom) + 8px);
}

#replybar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 0 8px;
  font-size: 13px;
  color: var(--muted);
}
#replybar[hidden] { display: none !important; }
#replybar span { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#replybar button { min-width: 44px; min-height: 32px; color: var(--muted); }

#editbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 0 8px;
  font-size: 13px;
  color: var(--accent);
}
#editbar[hidden] { display: none !important; }
#editbar span { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
#editbar button { min-width: 44px; min-height: 32px; color: var(--muted); }

/* recording replaces nothing: it sits above the input like the reply bar, so
   the composer stays where the thumb expects it */
#recbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 0 8px;
  font-size: 14px;
}
#recbar[hidden] { display: none !important; }
#recdot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--danger);
  flex: 0 0 auto;
  animation: recpulse 1.2s ease-in-out infinite;
}
@keyframes recpulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { #recdot { animation: none; } }
#rectime { flex: 1 1 auto; font-variant-numeric: tabular-nums; font-weight: 500; }
#recbar button {
  min-height: 40px;
  padding: 0 16px;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: 14px;
  font-weight: 500;
}
#recsend { background: var(--accent); border-color: var(--accent); color: #fff; }

.bubble audio { display: block; width: 240px; max-width: 100%; }

#inputrow { display: flex; align-items: flex-end; gap: 8px; }

#text {
  flex: 1 1 auto;
  min-height: 44px;
  max-height: 120px;
  resize: none;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: 22px;
  background: var(--bg);
  font: inherit;
  color: inherit;
}
#text:focus { outline: none; border-color: var(--accent); }

.iconbtn {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  color: var(--muted);
}
#send { background: var(--accent); border-color: var(--accent); color: #fff; }

/* ---------- call ---------- */
/* Sized to the VISIBLE viewport, not the layout one. `inset: 0` spans the
   layout viewport, which on a phone includes the strip behind the address bar:
   the video is then laid out taller than the screen and the picture is cropped
   until something collapses the bar. The rest of the app already uses --vh for
   exactly this; the call screen was the one place that did not. */
#call {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--vh, 100%);
  background: #000;
  z-index: 20;
}
#call[hidden] { display: none !important; }

#minimize {
  position: absolute;
  z-index: 4;
  left: 6px;
  top: calc(env(safe-area-inset-top) + 6px);
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: none;
  color: #fff;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .6));
}

/* Minimised: the same element, shrunk. Nothing is torn down and no stream is
   re-attached, so the call carries on exactly as it was - a <video> keeps
   playing at any size. Sits above the composer so it never covers the box you
   are typing into. */
#call.mini {
  inset: auto 12px calc(env(safe-area-inset-bottom) + 84px) auto;
  touch-action: none;   /* dragging the tile must not scroll the thread */
  width: 108px;
  height: 152px;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .35);
}
#call.mini #local,
#call.mini #callbar,
#call.mini #minimize,
#call.mini #diag { display: none; }
#call.mini #callstate {
  top: auto;
  bottom: 6px;
  font-size: 10px;
  padding: 2px;
  pointer-events: none;   /* on the tile every tap means "come back" */
}
/* the whole tile is the way back into the call */
#call.mini #remote { cursor: pointer; }

#remote { width: 100%; height: 100%; object-fit: cover; background: #000; }

/* The self-view is mirrored, the way a mirror is: an unmirrored front camera
   reads as backwards to the person looking at it. This is display only - what
   we transmit is untouched, so the other side still sees you the right way
   round. The rear camera is not mirrored; nobody expects a mirrored world. */
#local { transform: scaleX(-1); }
#local.rear { transform: none; }

#local {
  position: absolute;
  width: 104px;
  height: 150px;
  right: 14px;
  top: calc(env(safe-area-inset-top) + 14px);
  object-fit: cover;
  border-radius: 12px;
  background: #111;
  touch-action: none;
}

#callbar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(env(safe-area-inset-bottom) + 24px);
  display: flex;
  justify-content: center;
  gap: 18px;
}
#callbar button {
  width: 60px;
  height: 60px;
  border-radius: 30px;
  background: rgba(255, 255, 255, .16);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(6px);
}
#callbar #hangup { background: #C1372F; }   /* call overlay: fixed, not themed */

/* mute swaps its own icon, so no JS has to touch the markup */
#mute .off { display: none; }
#mute.muted { background: #fff; color: #111; }
#mute.muted .on { display: none; }
#mute.muted .off { display: block; }
#callbar[hidden] { display: none !important; }

/* ---------- header overflow menu ---------- */
#menu {
  position: absolute;
  z-index: 15;
  right: var(--pad);
  top: calc(env(safe-area-inset-top) + 58px);
  min-width: 210px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  display: flex;
  flex-direction: column;
}
#menu[hidden] { display: none !important; }
#menu button {
  min-height: 48px;
  padding: 0 14px;
  text-align: left;
  border-radius: 10px;
  font-size: 15px;
}
#menu button:active { background: var(--bg); }
#menu #logout-btn { color: var(--danger); }
/* so "is the new version actually on this phone?" is a one-glance answer */
#build {
  padding: 8px 14px 4px;
  font-size: 11px;
  color: var(--muted);
  border-top: 1px solid var(--line);
  margin-top: 4px;
}

/* ---------- file and video bubbles ---------- */
.bubble video {
  display: block;
  width: 240px;
  max-width: 100%;
  border-radius: 10px;
  background: #000;
}

.file {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  text-decoration: none;
  color: inherit;
}
.file svg { flex: 0 0 auto; color: var(--accent); }
.file .fmeta { min-width: 0; }
.file .fname {
  display: block;
  font-weight: 500;
  overflow-wrap: anywhere;
}
.file .fsize { display: block; font-size: 12px; color: var(--muted); }

/* ---------- links in messages ---------- */
/* a URL is one long unbreakable word; without this it stretches the bubble */
.link {
  color: var(--accent);
  overflow-wrap: anywhere;
}
.row.mine .link { color: var(--mine-link); }

/* a message that is only a link: the address itself is rarely the useful part */
.linkcard {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  text-decoration: none;
  color: inherit;
}
.linkcard svg { flex: 0 0 auto; color: var(--accent); }
.linkcard .txt { min-width: 0; }
.linkcard .t1 {
  display: block;
  font-weight: 500;
}
.linkcard .t2 {
  display: block;
  font-size: 12px;
  color: var(--muted);
  overflow-wrap: anywhere;
  /* a long address stays one line rather than making a tall card */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- reactions ---------- */
.reacts { display: flex; gap: 4px; padding: 3px 6px 0; flex-wrap: wrap; }
.reacts button {
  display: flex;
  align-items: center;
  gap: 3px;
  min-height: 26px;
  padding: 0 8px;
  border: 1px solid var(--line);
  border-radius: 13px;
  background: var(--surface);
  font-size: 13px;
  line-height: 1;
}
.reacts button.mine { border-color: var(--accent); background: var(--mine); }
.reacts .n { font-size: 11px; color: var(--muted); }

.emoji-row { display: flex; gap: 2px; padding: 0; flex-wrap: wrap; }
.emoji-row button {
  width: 44px;
  height: 44px;
  border-radius: 22px;
  font-size: 20px;
  line-height: 1;
}
.emoji-row button:active { background: var(--bg); }
.emoji-row button.mine { background: var(--mine); }

/* ---------- attach sheet ---------- */
#attach-sheet {
  position: absolute;
  z-index: 15;
  left: var(--pad);
  bottom: calc(env(safe-area-inset-bottom) + 68px);
  min-width: 232px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  display: flex;
  flex-direction: column;
}
#attach-sheet[hidden] { display: none !important; }
#attach-sheet button {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  padding: 0 12px;
  border-radius: 10px;
  font-size: 15px;
  text-align: left;
}
#attach-sheet button:active { background: var(--bg); }
#attach-sheet svg { color: var(--accent); flex: 0 0 auto; }

/* ---------- location bubble ---------- */
.place {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  width: 100%;
  text-align: left;
  padding: 0;
}
.place svg { color: var(--accent); flex: 0 0 auto; }
.place .pname { display: block; font-weight: 500; }
.place .pmeta { display: block; font-size: 12px; color: var(--muted); }

/* ---------- map view ---------- */
#mapview {
  position: fixed;
  inset: 0;
  z-index: 26;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}
#mapview[hidden] { display: none !important; }

#map-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: calc(env(safe-area-inset-top) + 10px) var(--pad) 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
#map-close {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
}
#map-title { font-weight: 700; font-size: 17px; }

#map-frame { flex: 1 1 auto; width: 100%; border: 0; background: var(--line); }

#map-foot {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px var(--pad) calc(env(safe-area-inset-bottom) + 10px);
  background: var(--surface);
  border-top: 1px solid var(--line);
}
#map-coords { flex: 1 1 auto; font-size: 13px; color: var(--muted); }
#map-open {
  min-height: 44px;
  display: flex;
  align-items: center;
  padding: 0 16px;
  border-radius: 22px;
  background: var(--accent);
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
}

/* ---------- deleted messages (archive user only) ---------- */
#deleted {
  position: fixed;
  inset: 0;
  z-index: 26;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}
#deleted[hidden] { display: none !important; }
#del-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: calc(env(safe-area-inset-top) + 10px) var(--pad) 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
#del-close {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
}
#del-title { font-weight: 700; font-size: 17px; }
#del-body {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--pad) var(--pad) calc(env(safe-area-inset-bottom) + var(--pad));
  display: flex;
  flex-direction: column;
  gap: 8px;
}
#del-body .empty { color: var(--muted); text-align: center; padding: 40px 12px; font-size: 14px; }
#del-body .more {
  display: block;
  width: 100%;
  min-height: 44px;
  margin-top: 4px;
  border: 1px solid var(--line);
  border-radius: 22px;
  background: var(--surface);
  font-size: 14px;
  font-weight: 500;
  color: var(--accent);
}
.del-item {
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  padding: 10px 12px;
}
.del-item .head {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 6px;
}
.del-item .who { font-weight: 700; color: var(--text); }
.del-item .content { white-space: pre-wrap; overflow-wrap: anywhere; }
.del-item img {
  display: block;
  max-width: 100%;
  width: 200px;
  border-radius: 10px;
  background: var(--bg);
}
.del-item .kindtag { font-size: 12px; color: var(--muted); }

/* ---------- live location ---------- */
#live {
  position: fixed;
  inset: 0;
  z-index: 26;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}
#live[hidden] { display: none !important; }
#live-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: calc(env(safe-area-inset-top) + 10px) var(--pad) 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
#live-close {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
}
#live-title { font-weight: 700; font-size: 17px; }
#live-map { flex: 1 1 auto; background: var(--line); }
#live-foot {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px var(--pad) calc(env(safe-area-inset-bottom) + 10px);
  background: var(--surface);
  border-top: 1px solid var(--line);
}
#live-status { font-size: 13px; color: var(--muted); min-height: 18px; }
#live-toggle {
  min-height: 48px;
  border-radius: 24px;
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: 15px;
  font-weight: 500;
  color: var(--accent);
}
#live-toggle.on { background: var(--accent); border-color: var(--accent); color: #fff; }

/* pins are plain HTML, so no marker images have to be shipped */
.live-pin { background: none; border: 0; }
.live-pin span {
  display: inline-block;
  transform: translate(-50%, -100%);
  padding: 4px 9px;
  border-radius: 12px 12px 12px 2px;
  background: var(--accent);
  color: #fff;
  font: 500 12px/1.2 Inter, -apple-system, sans-serif;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
}
.live-pin.mine span { background: var(--green); }
.live-pin.stale span { opacity: .55; }

/* ---------- library ---------- */
#library {
  position: fixed;
  inset: 0;
  z-index: 25;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}
#library[hidden] { display: none !important; }

#lib-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: calc(env(safe-area-inset-top) + 10px) var(--pad) 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
#lib-close {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
}
#lib-title { font-weight: 700; font-size: 17px; }

#lib-tabs {
  flex: 0 0 auto;
  display: flex;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.lib-tab {
  flex: 1 1 0;
  min-height: 44px;
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
  border-bottom: 2px solid transparent;
}
.lib-tab.on { color: var(--accent); border-bottom-color: var(--accent); }

#lib-body {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--pad) var(--pad) calc(env(safe-area-inset-bottom) + var(--pad));
}
#lib-body .empty { color: var(--muted); text-align: center; padding: 40px 12px; font-size: 14px; }
#lib-body .more {
  display: block;
  width: 100%;
  min-height: 44px;
  margin-top: 10px;
  border: 1px solid var(--line);
  border-radius: 22px;
  background: var(--surface);
  font-size: 14px;
  font-weight: 500;
  color: var(--accent);
}

.lib-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
}
/* photo tiles are buttons, video tiles are divs; both must look identical */
.lib-grid > * {
  position: relative;
  aspect-ratio: 1;
  padding: 0;
  border-radius: 8px;
  overflow: hidden;
  background: var(--line);
}
.lib-grid img,
.lib-grid video { width: 100%; height: 100%; object-fit: cover; display: block; }

.lib-list { display: flex; flex-direction: column; gap: 8px; }
.lib-list a, .lib-list .row-item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 56px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  text-decoration: none;
  color: inherit;
}
.lib-list button.row-item { width: 100%; text-align: left; }
.lib-list .row-item svg { color: var(--accent); flex: 0 0 auto; }
.lib-list .txt { min-width: 0; flex: 1 1 auto; }
.lib-list .t1 { display: block; font-weight: 500; overflow-wrap: anywhere; }
.lib-list .t2 { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }

/* ---------- incoming call ---------- */
#incoming {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 26px;
  padding: 24px calc(env(safe-area-inset-right) + 24px)
           calc(env(safe-area-inset-bottom) + 24px) calc(env(safe-area-inset-left) + 24px);
  background: #0B0D11;
  color: #fff;
  text-align: center;
}
#incoming[hidden] { display: none !important; }
#incoming-who { font-size: 22px; font-weight: 700; }
#incoming-sub { font-size: 14px; color: #9AA3B0; margin-top: -18px; }

.incoming-actions { display: flex; gap: 18px; flex-wrap: wrap; justify-content: center; }
.incoming-actions button {
  min-width: 130px;
  min-height: 52px;
  padding: 0 20px;
  border-radius: 26px;
  font-size: 16px;
  font-weight: 700;
  color: #fff;
}
#accept { background: var(--green); }
#decline { background: #C1372F; }   /* call overlay: fixed, not themed */

#callstate {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(env(safe-area-inset-top) + 24px);
  text-align: center;
  color: #fff;
  font-size: 14px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
  /* it is a button now, but it has to keep looking like a caption */
  background: none;
  border: 0;
  padding: 8px 12px;
  font-family: inherit;
  -webkit-appearance: none;
}
#callstate:empty { display: none; }

#diag {
  position: absolute;
  left: 12px;
  right: 12px;
  top: calc(env(safe-area-inset-top) + 58px);
  z-index: 3;
  background: rgba(0, 0, 0, .82);
  border-radius: 12px;
  padding: 12px;
  max-height: 46vh;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}
#diagtext {
  margin: 0 0 10px;
  color: #d8f5c8;
  font: 12px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap;
  word-break: break-word;
}
#diagcopy {
  width: 100%;
  min-height: 44px;
  border: 0;
  border-radius: 10px;
  background: #fff;
  color: #111;
  font: 500 15px/1 inherit;
}

/* ---------- lightbox ---------- */
#lightbox {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: rgba(0, 0, 0, .94);
  display: flex;
  align-items: center;
  justify-content: center;
}
#lightbox[hidden] { display: none !important; }
#lightbox img { max-width: 100%; max-height: 100%; }

/* ---------- login ---------- */
#login {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 12px;
  max-width: 340px;
  margin: 0 auto;
  padding: 24px;
  height: 100%;
}
#login h1 { font-size: 22px; font-weight: 700; margin: 0 0 4px; }
#login input {
  min-height: 48px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  font: inherit;
  color: inherit;
}
#login input:focus { outline: none; border-color: var(--accent); }
#login button {
  min-height: 48px;
  border-radius: 12px;
  background: var(--accent);
  color: #fff;
  font-weight: 700;
}
#login .err { color: var(--danger); font-size: 14px; min-height: 20px; }

/* ---------- message effects ---------- */
/* Above everything, including a call, and transparent to the pointer so it can
   never swallow a tap on whatever is underneath it. */
#fx {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  overflow: hidden;
}
#fx span {
  position: absolute;
  bottom: -40px;
  line-height: 1;
  opacity: 0;
  will-change: transform, opacity;
  animation: rise var(--dur) ease-in forwards;
}
@keyframes rise {
  0%   { transform: translate3d(0, 0, 0) scale(.5) rotate(0deg); opacity: 0; }
  15%  { opacity: 1; }
  80%  { opacity: 1; }
  100% {
    transform: translate3d(var(--drift), calc(-1 * var(--climb)), 0) scale(1.1) rotate(var(--spin));
    opacity: 0;
  }
}

/* "I miss you" comes down from the top instead - same geometry, opposite sign,
   and slower, so the two are told apart without having to read them. */
#fx span.fall {
  bottom: auto;
  top: -40px;
  animation-name: drop;
}
@keyframes drop {
  0%   { transform: translate3d(0, 0, 0) scale(.5) rotate(0deg); opacity: 0; }
  15%  { opacity: 1; }
  80%  { opacity: 1; }
  100% {
    transform: translate3d(var(--drift), var(--climb), 0) scale(1.1) rotate(var(--spin));
    opacity: 0;
  }
}

/* ---------- stealth ---------- */
/* Only ever visible to the person who is hidden, and always visible to them:
   forgetting which mode you are in is the one way this becomes a nasty
   surprise. */
#stealth-flag, #stealth-denied { display: none; }
body.stealth-denied #stealth-denied {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--danger);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
}
body.stealth #stealth-flag {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--badge);
  color: var(--badge-ink);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .02em;
}

/* the same signal on the sign-in page, worded for what it can actually know */
#stealth-note {
  margin: -4px 0 14px;
  padding: 6px 10px;
  border-radius: 10px;
  background: var(--badge);
  color: var(--badge-ink);
  font-size: 12px;
  font-weight: 500;
  text-align: center;
}
#stealth-note[hidden] { display: none; }

/* Hidden is read-only, so the interface offers nothing that would be refused:
   no composer, no call button, no action panel. */
#readonly {
  flex: 0 0 auto;
  padding: 12px var(--pad) calc(env(safe-area-inset-bottom) + 12px);
  background: var(--surface);
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 13px;
  text-align: center;
}
#readonly[hidden] { display: none; }
body.stealth #composer { display: none; }
body.stealth #call-btn { display: none; }
body.stealth .bubble .more { display: none; }

/* ---------- fullscreen ---------- */
/* one icon at a time, the way the mute button works */
#fullscreen .out { display: none; }
#fullscreen.on .in { display: none; }
#fullscreen.on .out { display: block; }
#fullscreen[hidden] { display: none !important; }

/* The overlay is already inset:0, but in fullscreen it is the fullscreen
   element itself and has to fill it rather than the viewport it came from. */
#call:fullscreen,
#call:-webkit-full-screen {
  width: 100%;
  height: 100%;
}
