/* trmn — terminal-flavoured interface. Monospace everywhere, no imagery. */

:root {
  --bg:        #0a0b0c;
  --bg-panel:  #0e1011;
  --bg-inset:  #121516;
  --line:      #1e2325;
  --line-soft: #171b1d;
  --fg:        #c9cfca;
  --fg-strong: #eef2ee;
  --dim:       #6d7873;
  --dimmer:    #4a534f;
  --accent:    #d97757;
  --green:     #7bd88f;
  --amber:     #e0b072;
  --red:       #e8737f;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas,
          "DejaVu Sans Mono", "Liberation Mono", monospace;
  --row: 1.55;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}
/*
 * Dynamic viewport units follow the collapsing browser toolbar on a phone. With
 * plain 100% and overflow:hidden the shell is laid out against the *large*
 * viewport, which puts the composer behind the URL bar until you scroll — and
 * the body cannot scroll.
 */
@supports (height: 100dvh) {
  html, body { height: 100dvh; }
}

body {
  background: var(--bg);
  color: var(--fg);
  font: 13px/var(--row) var(--mono);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
  /* faint corner glow so pure black doesn't look flat */
  background-image:
    radial-gradient(1200px 600px at 50% -10%, #12171a 0%, transparent 70%),
    radial-gradient(900px 500px at 110% 110%, #131013 0%, transparent 70%);
}

/* Very light scanlines + vignette. Enough to read as a terminal, not enough to hurt. */
#crt {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 100;
  background:
    repeating-linear-gradient(to bottom,
      rgba(255,255,255,.014) 0 1px, transparent 1px 3px),
    radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,.38) 100%);
}

@media (prefers-reduced-motion: no-preference) {
  #crt::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, transparent, rgba(217,119,87,.035), transparent);
    height: 30%;
    animation: sweep 9s linear infinite;
  }
  @keyframes sweep {
    0%   { transform: translateY(-40%); opacity: 0; }
    12%  { opacity: 1; }
    88%  { opacity: 1; }
    100% { transform: translateY(320%); opacity: 0; }
  }
}

.view { height: 100%; }
[hidden] { display: none !important; }

::selection { background: rgba(217,119,87,.28); }

button, input, textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
}

:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 1px;
}

.btn {
  border: 1px solid var(--line);
  background: var(--bg-inset);
  color: var(--fg);
  padding: 3px 10px;
  cursor: pointer;
  white-space: nowrap;
}
.btn:hover:not(:disabled) { border-color: var(--accent); color: var(--fg-strong); }
.btn:disabled { opacity: .45; cursor: progress; }
.btn.ghost { background: none; color: var(--dim); }
.btn.ghost:hover { color: var(--accent); }

.prompt { color: var(--accent); user-select: none; }
.badge { letter-spacing: -.02em; }

.mascot {
  margin: 0;
  font: inherit;
  line-height: 1.02;
  white-space: pre;
  letter-spacing: 0;
}

/* ─────────────────────────────── auth ─────────────────────────────── */

#auth {
  display: grid;
  place-items: center;
  padding: 20px;
  overflow: auto;
}

.auth-box {
  width: min(440px, 100%);
  border: 1px solid var(--line);
  background: linear-gradient(#0e1112, #0b0d0e);
  padding: 26px 26px 20px;
  box-shadow: 0 0 0 1px #000, 0 24px 60px -20px rgba(0,0,0,.9);
}

.logo {
  margin: 0;
  color: var(--accent);
  font: inherit;
  line-height: 1.05;
  white-space: pre;
  text-shadow: 0 0 18px rgba(217,119,87,.35);
}

.tagline {
  color: var(--dim);
  margin: 8px 0 16px;
  letter-spacing: .04em;
}

.boot {
  margin: 0 0 16px;
  font: inherit;
  color: var(--dimmer);
  white-space: pre-wrap;
  min-height: calc(4 * 1.55em);
}
.boot .ok { color: var(--green); }

.field {
  display: grid;
  grid-template-columns: 7ch 1fr;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.field label { color: var(--dim); }
.field label::after { content: ":"; color: var(--dimmer); }
.field input {
  border: 1px solid var(--line);
  background: var(--bg-inset);
  padding: 6px 8px;
  min-width: 0;
  caret-color: var(--accent);
}
.field input:focus { border-color: var(--accent); outline: none; }
.field input::placeholder { color: var(--dimmer); }

.preview {
  margin: 12px 0 4px;
  font: inherit;
  line-height: 1.02;
  white-space: pre;
  min-height: calc(4 * 1.02em);
  color: var(--dimmer);
}

.auth-msg {
  min-height: 1.55em;
  margin: 6px 0 12px;
  color: var(--amber);
  overflow-wrap: anywhere;
}
.auth-msg.err { color: var(--red); }
.auth-msg.ok  { color: var(--green); }

.auth-actions {
  display: flex;
  gap: 8px;
}
.auth-actions .btn { flex: 1; }
/* The mode toggle sits below the form it is deliberately not part of. */
.auth-alt { margin-top: 8px; }

.auth-note {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
  color: var(--dimmer);
}
.auth-note p { margin: 0 0 6px; }

/*
 * The install offer. Chrome's own mini-infobar is suppressed so the prompt stays
 * reusable, which means this row is the only thing telling anyone the app can be
 * installed — and on iOS, where no prompt exists at all, it is the only route.
 */
.install-row {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 14px;
  color: var(--dim);
}
.install-row .btn { padding: 2px 9px; }
.install-why { color: var(--dimmer); }
/* In the sidebar footer it is a row above the fingerprint, not a banner. */
.pane-foot .install-row { margin-top: 0; margin-bottom: 8px; }

/* ─────────────────────────────── shell ─────────────────────────────── */

/* minmax(0,1fr) keeps the single column from being widened to its content's
   min-content size, which would otherwise push the whole shell past the viewport. */
#app {
  display: grid;
  grid-template-rows: auto 1fr;
  grid-template-columns: minmax(0, 1fr);
}

#topbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-panel);
  min-width: 0;
}
.brand {
  color: var(--accent);
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.brand-sub { color: var(--dimmer); }
.spacer { flex: 1; }
.self-name {
  color: var(--fg-strong);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.net { color: var(--dimmer); white-space: nowrap; }
.net .dot { color: var(--dimmer); font-style: normal; margin-right: 5px; }
.net.online { color: var(--dim); }
.net.online .dot { color: var(--green); }
.net.sync .dot { color: var(--amber); }

#body {
  display: grid;
  grid-template-columns: 250px 1fr;
  min-height: 0;
  min-width: 0;
}

/* ────────────────────────────── sidebar ────────────────────────────── */

#sidebar {
  display: grid;
  grid-template-rows: auto auto 1fr auto auto;
  grid-template-columns: minmax(0, 1fr);
  border-right: 1px solid var(--line);
  background: var(--bg-panel);
  min-height: 0;
}

.pane-head {
  padding: 8px 12px;
  color: var(--dim);
  text-transform: uppercase;
  letter-spacing: .14em;
  border-bottom: 1px solid var(--line-soft);
}

#newconv {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 7px 12px;
  border-bottom: 1px solid var(--line-soft);
}
#newconv input {
  flex: 1;
  min-width: 0;
  caret-color: var(--accent);
}
#newconv input::placeholder { color: var(--dimmer); }

.convs { overflow-y: auto; min-height: 0; }

.conv {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 5px 12px;
  cursor: pointer;
  text-align: left;
  border-left: 2px solid transparent;
}
.conv:hover { background: var(--bg-inset); }
.conv.active {
  background: var(--bg-inset);
  border-left-color: var(--accent);
}
.conv .name {
  color: var(--fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.conv.active .name { color: var(--fg-strong); }
.conv .dot { color: var(--dimmer); font-size: 9px; }
.conv .dot.on { color: var(--green); }
.conv .unread {
  color: var(--bg);
  background: var(--accent);
  padding: 0 5px;
  font-size: 11px;
}
.convs .empty { padding: 10px 12px; color: var(--dimmer); }

.newgroup {
  margin: 0;
  border: none;
  border-top: 1px solid var(--line-soft);
  border-radius: 0;
  text-align: left;
  padding: 7px 12px;
  background: none;
}

.conv-sep {
  padding: 8px 12px 3px;
  color: var(--dimmer);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: 11px;
}

.conv .gmark {
  color: var(--accent);
  letter-spacing: -.02em;
}
.conv .members { color: var(--dimmer); font-size: 11px; }
/* A group with a call running gets a live marker in the list. */
.conv .incall { color: var(--green); }

.pane-foot {
  padding: 8px 12px;
  border-top: 1px solid var(--line-soft);
  color: var(--dimmer);
}
.fp-line { overflow-wrap: anywhere; }
.fp-line b { display: block; color: var(--dim); font-weight: 400; }
.fp-line .fp-val { color: var(--dimmer); }
.suite { margin-top: 4px; }
/* Exactly what this tab is running, so "which version am I on?" is answerable. */
.version { margin-top: 4px; color: var(--dimmer); }
.version.stale { color: var(--amber); }

/* ──────────────────────────────── chat ──────────────────────────────── */

/* ──────────────────────────── screen sharing ──────────────────────────── */

.screens {
  display: flex;
  gap: 10px;
  padding: 10px 14px;
  overflow-x: auto;
  border-bottom: 1px solid var(--line);
  background: #0c0e0f;
  min-height: 0;
}
.screens figure {
  margin: 0;
  border: 1px solid var(--line);
  background: #000;
  flex: 0 0 auto;
  max-width: 100%;
}
.screens video {
  display: block;
  max-height: 34vh;
  max-width: min(560px, 100%);
  background: #000;
  cursor: zoom-in;
}
.screens figcaption {
  padding: 3px 7px;
  color: var(--dim);
  border-top: 1px solid var(--line-soft);
  white-space: nowrap;
}
.screens figcaption .who { color: var(--fg-strong); }
.screens figcaption .self { color: var(--amber); }

/*
 * Camera tiles. Narrower than a shared screen because a face needs far less width
 * than a desktop does, which also keeps a six-way call from scrolling off sideways.
 */
.screens figure.cam { border-color: var(--line-soft); }
.screens figure.cam video {
  max-width: min(260px, 100%);
  max-height: 26vh;
}
/* A self-view is mirrored the way every camera app does it; a screen never is. */
.screens video.mirror { transform: scaleX(-1); }

@media (max-width: 720px) {
  /* Wrap instead of scrolling sideways: a phone has no room for a second column,
     and a horizontal scroller hides participants entirely. */
  .screens { flex-wrap: wrap; overflow-x: hidden; }
  .screens figure.cam video { max-width: min(46vw, 100%); max-height: 22vh; }
  .screens video { max-width: 100%; }
}

#viewer video {
  max-width: 100%;
  max-height: calc(100% - 3em);
  border: 1px solid var(--line);
  background: #000;
}

/**
 * Flex column, deliberately not a grid.
 *
 * With positional grid rows, the conditionally hidden call bar and screen-share
 * strip are removed from placement entirely when `display:none`, so every later
 * child shifts up a row — which handed the composer the `1fr` row and turned the
 * input into a 543px empty box whenever no call was in progress. Flex assigns the
 * growth to the log by name, so hiding a sibling cannot rearrange anything.
 */
#chat {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}

/* Only the log grows; everything else keeps its natural height. */
#chat > .chat-head,
#chat > .callbar,
#chat > .screens,
#chat > .typing,
#chat > #composer { flex: 0 0 auto; }
#chat > #log { flex: 1 1 auto; }

/* ─────────────────────────────── call bar ─────────────────────────────── */

.callbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 7px 14px;
  border-bottom: 1px solid var(--line);
  background: #12100f;
  box-shadow: inset 0 0 0 1px rgba(217,119,87,.16);
}
.callbar .state { color: var(--accent); white-space: nowrap; }
.callbar .who { color: var(--fg-strong); white-space: nowrap; }
.callbar .meta { color: var(--dimmer); white-space: nowrap; }
/* Group media is server-relayed, not end-to-end. Marked, not hidden. */
.callbar .meta.relayed { color: var(--amber); }
.callbar .clock { color: var(--fg); font-variant-numeric: tabular-nums; }
.callbar .vu { color: var(--green); white-space: pre; letter-spacing: -.5px; }
.callbar .vu.out { color: var(--amber); }
.callbar .vu.off { color: var(--dimmer); }
.callbar .spacer { flex: 1; min-width: 8px; }
/* The bar's two rebuild zones. `contents` lays them out as if they were not
   there, so splitting the bar in two costs nothing visually. */
.callbar .zone { display: contents; }
.callbar .btn { padding: 2px 9px; }
.callbar.ringing { background: #14110d; }

@media (prefers-reduced-motion: no-preference) {
  .callbar.ringing .state { animation: blink 1.05s steps(2, start) infinite; }
  @keyframes blink { to { opacity: .35; } }
}

.chat-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-panel);
  min-height: 0;
}
.chat-head .who { min-width: 0; }
.chat-head .peer {
  color: var(--fg-strong);
  font-size: 14px;
}
.chat-head .meta { color: var(--dimmer); overflow-wrap: anywhere; }
.chat-head .meta .lock { color: var(--green); }
.chat-head .meta .off { color: var(--dimmer); }
.chat-head .meta .on { color: var(--green); }
/* Header controls sit hard right, so the conversation title can take the slack. */
.chat-head .actions {
  margin-left: auto;
  display: flex;
  gap: 8px;
  align-items: center;
  flex: 0 0 auto;
}
.chat-head .actions .btn { padding: 2px 9px; white-space: nowrap; }

.log {
  overflow-y: auto;
  padding: 12px 14px 16px;
  min-height: 0;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.log::-webkit-scrollbar { width: 9px; }
.log::-webkit-scrollbar-thumb { background: var(--line); }

/* Fixed columns so every row's icon and name line up like real terminal output. */
.line {
  display: grid;
  grid-template-columns: 9ch 18ch 1fr;
  gap: 8px;
  padding: 1px 0;
  overflow-wrap: anywhere;
}
.line .ts { color: var(--dimmer); user-select: none; }
.line .who { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.line .who .nm { color: var(--dim); }
.line .text { white-space: pre-wrap; color: var(--fg); }
/*
 * Per-line affordances stay out of the way until the line is hovered. `rowbtn`
 * carries that behaviour and `del` / `edit` carry the meaning — they used to share
 * the `del` class, which made `querySelector('.btn.del')` return the *edit* button
 * and quietly turned one suite's "delete this" into "start editing this".
 */
.line .btn.rowbtn {
  margin-left: 8px;
  padding: 0 6px;
  font-size: 11px;
  opacity: 0;
  transition: opacity .12s;
  vertical-align: baseline;
}
.line:hover .btn.rowbtn,
.line .btn.rowbtn:focus-visible { opacity: 1; }
.line .btn.del:hover { color: var(--red); border-color: var(--red); }
/* Editing is not destructive, so it must not borrow delete's red. */
.line .btn.edit:hover { color: var(--accent); border-color: var(--accent); }
@media (hover: none) {
  .line .btn.rowbtn { opacity: .55; }   /* no hover on touch, so keep it visible */
}
.line.mine .text { color: var(--fg-strong); }
.line.bad .text { color: var(--red); }
.line:hover { background: rgba(255,255,255,.018); }
.line .edited {
  color: var(--dimmer);
  font-size: 11px;
  user-select: none;
}
/* The message the composer is currently rewriting. */
.line.editing {
  background: rgba(217,119,87,.09);
  box-shadow: inset 2px 0 0 var(--accent);
}

.sys {
  color: var(--dimmer);
  padding: 3px 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.sys.warn { color: var(--amber); }
.sys.err { color: var(--red); }
.sys.hi { color: var(--fg); }
.sys .k { color: var(--accent); }
.sys .rule { color: var(--line); }

/* Transfer progress: a block-glyph bar plus counters, on one monospace line. */
.sys.transfer { white-space: pre; overflow-x: auto; }
.sys.transfer .bar { color: var(--accent); letter-spacing: -.5px; }
.sys.transfer .txt { color: var(--dim); }
.sys.transfer.err .bar { color: var(--red); }
.sys.transfer.warn .bar { color: var(--amber); }

.more {
  display: block;
  margin: 0 auto 10px;
  color: var(--dim);
}

/* ───────────────────────────── attachments ───────────────────────────── */

.attach {
  display: inline-block;
  max-width: min(420px, 100%);
  border: 1px solid var(--line);
  background: var(--bg-inset);
  padding: 5px 8px;
  margin: 2px 0;
}
.attach .kind { color: var(--accent); }
.attach .name { color: var(--fg-strong); overflow-wrap: anywhere; }
.attach .meta { color: var(--dimmer); }
.attach .row { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.attach .btn { padding: 1px 8px; }
.attach.bad { border-color: var(--red); }
.attach.bad .name { color: var(--red); }

.attach .shot {
  display: block;
  margin-top: 6px;
  max-width: 100%;
  max-height: 320px;
  border: 1px solid var(--line-soft);
  background: #000;
  cursor: zoom-in;
  image-rendering: auto;
}
.attach .placeholder {
  margin-top: 6px;
  padding: 14px 10px;
  border: 1px dashed var(--line);
  color: var(--dimmer);
  text-align: center;
}

/* Video: a poster carrying a play marker, swapped for the player on demand. */
.attach .stage { display: block; }
.attach .poster {
  position: relative;
  display: inline-block;
  margin-top: 6px;
  cursor: pointer;
  line-height: 0;
}
.attach .poster .shot { margin-top: 0; cursor: pointer; }
.attach .poster .playmark {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 34px;
  line-height: 1;
  color: var(--fg-strong);
  text-shadow: 0 0 10px rgba(0,0,0,.85);
  pointer-events: none;   /* the click belongs to the poster underneath */
}
.attach .poster:hover .playmark { color: var(--accent); }
/* The player has its own controls, so it must not keep the poster's zoom cursor. */
.attach video.shot {
  width: 100%;
  max-height: 360px;
  margin-top: 6px;
  cursor: default;
}

/* Full-size viewer */
#viewer {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  gap: 10px;
  background: rgba(4,5,6,.94);
  padding: 24px;
}
#viewer img {
  max-width: 100%;
  max-height: calc(100% - 3em);
  border: 1px solid var(--line);
}
#viewer .bar { color: var(--dim); display: flex; gap: 12px; align-items: center; }

/* Drag-and-drop target */
#chat.dropping::after {
  content: "release to attach";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(217,119,87,.10);
  border: 1px dashed var(--accent);
  color: var(--accent);
  pointer-events: none;
  z-index: 30;
}
#chat { position: relative; }

.empty-chat {
  display: grid;
  place-content: center;
  gap: 10px;
  height: 100%;
  color: var(--dimmer);
  text-align: center;
}
.empty-chat pre { margin: 0; font: inherit; line-height: 1.02; color: var(--accent); opacity: .8; }

.typing {
  padding: 0 14px;
  height: 1.7em;
  color: var(--dimmer);
}

#composer {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 9px 14px;
  border-top: 1px solid var(--line);
  background: var(--bg-panel);
}
#composer .prompt { padding-top: 2px; }

/*
 * iOS Safari zooms the whole page whenever a focused control's font-size is under
 * 16px, and never zooms back. The app's base is 13px. 16px is a threshold, not a
 * taste: 15.9px still triggers it.
 *
 * Deliberately *not* inside the layout breakpoint. What triggers it is a touch
 * keyboard, not how wide the window is — and gating it on a width query meant
 * anything that stopped that query matching silently dropped the fix, which is why
 * the installed app still zoomed while Safari had stopped.
 *
 * The prompts move with the fields. They share a line with the input, and leaving a
 * prompt at 13px beside a 16px field is what put the message text a little below
 * the username next to it: same padding, but a shorter line box.
 */
@media (pointer: coarse), (max-width: 720px) {
  #input, #u, #p, #p2, #newconv-input,
  #composer .prompt, #newconv .prompt { font-size: 16px; }
}

/*
 * A single-glyph button. It must be exactly as tall as the button beside it, so it
 * inherits every vertical metric from .btn and changes only its width — an earlier
 * version set its own font-size and line-height and ended up a different height
 * from `send`.
 */
.btn.icon {
  padding-left: 0;
  padding-right: 0;
  width: 2.4em;
  text-align: center;
}
#input {
  flex: 1;
  min-width: 0;
  resize: none;
  max-height: 9em;
  padding: 2px 0;
  caret-color: var(--accent);
  overflow-y: auto;
}
#input::placeholder { color: var(--dimmer); }
#input:focus { outline: none; }
/*
 * Both composer buttons sit on the bottom edge. The container is flex-start so the
 * prompt lines up with the first line of the message, and send used to be the only
 * thing overriding that — which left it and the attach button on different lines as
 * soon as they were side by side.
 */
#composer .btn.send,
#composer #attach { align-self: flex-end; }

/* ───────────────────────────── responsive ───────────────────────────── */

.only-narrow { display: none; }
/* Both are narrow-screen navigation only, and never both at once; see below. */
#btn-back, #btn-term { display: none; }

@media (max-width: 720px) {
  /*
   * Two screens rather than one screen plus a drawer.
   *
   * A drawer that slides over the conversation is a desktop idea shrunk down: it
   * leaves both panes alive, so the hidden one still takes layout and the back
   * gesture has nothing to act on. Here exactly one pane is in the document's
   * flow at a time, chosen by #app[data-pane], and the platform back gesture
   * moves between them because opening a conversation pushes a history entry.
   */
  #body { grid-template-columns: minmax(0, 1fr); }
  #app[data-pane="list"] #chat { display: none; }
  #app[data-pane="chat"] #sidebar { display: none; }
  #app[data-pane="chat"] #btn-back { display: inline-block; }
  #app[data-pane="list"] #btn-term { display: inline-block; }

  /* Full width now, so the divider it used to need would just be a stray line. */
  #sidebar { border-right: none; }

  .only-narrow { display: inline-block; }
  .brand-sub { display: none; }
  /* Keep the connection dot, drop the word, so the bar always fits. */
  .net .net-label { display: none; }
  .net .dot { margin-right: 0; }
  #topbar { gap: 8px; }
  .line { grid-template-columns: 14ch 1fr; }
  .line .ts { display: none; }
  /* Send stays: enter works, but on a touch keyboard a visible button is the
     obvious way to send, and hiding it left the composer looking unfinished.
     Both composer buttons keep .btn's padding so they stay the same height. */

  /*
   * Notch and home indicator. viewport-fit=cover lets the shell reach the screen
   * edges, which is what an installed app should do — but then the insets have to
   * be paid back, or the top bar sits under the status bar and the composer under
   * the home indicator. max() keeps the ordinary padding when the inset is 0.
   */
  #topbar {
    padding-top: max(7px, env(safe-area-inset-top));
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
  }
  #composer {
    padding-bottom: max(9px, env(safe-area-inset-bottom));
    padding-left: max(14px, env(safe-area-inset-left));
    padding-right: max(14px, env(safe-area-inset-right));
  }
  /* The list is the bottom-most pane when it is the one on screen. */
  #sidebar { padding-bottom: env(safe-area-inset-bottom); }
  .chat-head {
    padding-left: max(14px, env(safe-area-inset-left));
    padding-right: max(14px, env(safe-area-inset-right));
  }
}
