/* ==========================================================================
   Polish, comms: sheets that rise and drag, Mail with a folders drawer, and
   Messages sliding a conversation in over the list. Loaded after shell.css;
   a repeated selector here wins over the one there.
   The phone's twins: components/Panel.tsx, components/SideDrawer.tsx,
   components/pages/MailPage.tsx, components/pages/MessagesPage.tsx.
   ========================================================================== */

/* ---- every sheet (ui.js panel()) ----
   It rises from the bottom edge rather than 40px, closes by sliding back down
   (class `closing`, removed when the animation ends), and its grab zone at the
   top follows a drag. The closing keyframes have only a `to`, so they start
   from wherever a drag left the card. */
.panel-card { animation: panel-rise-full 300ms cubic-bezier(.2, .8, .2, 1); }
.panel-back { animation: panel-fade 260ms ease-out; }
.panel-card.closing { animation: panel-sink 200ms cubic-bezier(.4, 0, 1, 1) forwards; pointer-events: none; }
.panel-back.closing { animation: panel-fade-out 200ms ease-in forwards; pointer-events: none; }
@keyframes panel-rise-full { from { transform: translateY(100%); } to { transform: none; } }
@keyframes panel-sink { to { transform: translateY(100%); } }
@keyframes panel-fade-out { to { opacity: 0; } }
.panel-grip {
  flex: none; height: 22px; display: flex; align-items: center; justify-content: center;
  cursor: grab; touch-action: none;
}
.panel-grip:active { cursor: grabbing; }
.panel-grip > .panel-grab { margin: 0; }

/* ---- mail: the top ----
   Row one: the folders button (narrow only), the folder's name and its count,
   compose at the right. Row two: one search row. The chip strips are gone. */
.mail-top { gap: 6px; padding: 6px 12px 10px; }
.mail-top, .mail-shell > .mail-split:first-child { padding-top: calc(46px + env(safe-area-inset-top)); }
body.embedded .mail-top, body.embedded .mail-shell > .mail-split:first-child { padding-top: 8px; }
.mail-bar { display: flex; align-items: center; gap: 4px; min-height: 36px; }
.mail-bar .icon-btn { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border-radius: 10px; flex: none; }
.mail-bar .icon-btn svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 32; }
.mail-side-btn { color: var(--ink); margin-left: -6px; }
.mail-write { color: var(--accent); margin-right: -6px; }
.mail-title { display: flex; align-items: baseline; gap: 6px; min-width: 0; padding-left: 2px; }
.mail-title .name { font-size: 18px; font-weight: 700; color: var(--ink); overflow-wrap: break-word; }
.mail-title .n { font-size: 13px; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.mail-bar-gap { flex: 1; }
.mail-searchrow { flex: none; height: 38px; border-radius: 19px; padding: 0 12px; }
.mail-search { font-size: 15px; padding: 0; height: 36px; }

/* ---- mail: the rows ----
   Gmail's: the sender's face (a solid circle, a white letter), then three
   lines — who and when, the subject, the newest words with the star at their
   end. Unread is bold ink, read is the quieter ink. No dot, no rules. A click
   on the face picks the row: the face turns into a check. */
.mail-item { gap: 14px; padding: 10px 16px; border-bottom: none; align-items: flex-start; }
.mail-item .avatar { width: 40px; height: 40px; border-radius: 20px; margin-top: 2px; padding: 0; border: none; flex: none;
  display: flex; align-items: center; justify-content: center; color: #fff; font: inherit; font-size: 17px; font-weight: 600; cursor: pointer; }
.mail-item .avatar svg { width: 20px; height: 20px; stroke: #fff; fill: none; stroke-width: 44; }
.mail-item .avatar.picked { background: var(--accent); }
.mail-item.draft .avatar { cursor: default; }
.mail-item.picked, .mail-item.picked:hover { background: var(--accent-soft); }
.mail-item .top, .mail-item .mid, .mail-item .bot { display: flex; align-items: center; gap: 8px; min-width: 0; }
/* Names that run to two lines keep the time, the clip and the dot by their first line. */
.mail-item .top { align-items: flex-start; }
.mail-item .top > :not(.from) { margin-top: 2px; }
.mail-item .from { flex: 1; min-width: 0; font-size: 15.5px; font-weight: 500; color: var(--ink-muted); }
.mail-item.unseen .from { font-weight: 700; color: var(--ink); }
.mail-item .count { color: var(--ink-faint); font-weight: 500; font-size: 13px; }
.mail-item .when { font-size: 12.5px; color: var(--ink-faint); font-weight: 400; font-variant-numeric: tabular-nums; }
.mail-item.unseen .when { color: var(--ink); font-weight: 700; }
.mail-item .subject { flex: 1; min-width: 0; margin-top: 1px; font-size: 14.5px; font-weight: 400; color: var(--ink-muted); }
.mail-item.unseen .subject { font-weight: 700; color: var(--ink); }
.mail-item .snippet { flex: 1; min-width: 0; margin-top: 1px; font-size: 14px; line-height: 20px; color: var(--ink-muted); }
.mail-item .clip { display: flex; flex: none; }
.mail-item .clip svg { width: 15px; height: 15px; stroke: var(--ink-faint); fill: none; stroke-width: 34; }
.mail-item .mail-amt { margin-top: 1px; }
/* Which address it came to: a small bordered chip at the end of the words. */
.mail-item .tag { flex: none; max-width: 40%; margin: 0; padding: 0 6px; border: 1px solid var(--border); border-radius: 6px;
  font-size: 11.5px; font-weight: 600; line-height: 17px; color: var(--ink-faint); overflow-wrap: anywhere; display: block; }
/* The star: always there, a big enough target, gold when on. */
.mail-item .star { flex: none; min-width: 36px; min-height: 32px; padding: 0; margin: -4px -10px -4px -2px; border: none; background: none;
  display: flex; align-items: center; justify-content: center; font-size: 18px; line-height: 1; color: var(--ink-faint); opacity: 0.7; cursor: pointer; }
.mail-item .star:hover { opacity: 1; }
.mail-item .star.on { color: #F59E3C; opacity: 1; }
.mail-item.draft .draft-word { color: var(--danger); font-weight: 600; }
.mail-item.draft .from { color: var(--ink); }
.mail-item .draft-discard { flex: none; width: 34px; height: 30px; margin: -4px -8px -4px 0; display: flex; align-items: center; justify-content: center; color: var(--ink-faint); border-radius: 10px; }
.mail-item .draft-discard:hover { color: var(--danger); background: var(--surface); }
.mail-item .draft-discard svg { width: 17px; height: 17px; }

/* ---- mail: the top while rows are picked ----
   ✕, how many, then what to do with them all. */
.mail-bar.selecting .mail-sel-clear { color: var(--ink); margin-left: -6px; }
.mail-bar.selecting .icon-btn { color: var(--ink-muted); }
.mail-bar.selecting .icon-btn:hover { background: var(--surface); color: var(--ink); }
.mail-bar.selecting .icon-btn svg { width: 21px; height: 21px; }
.mail-bar.selecting .mail-title .name { font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; }
.mail-bar.selecting { gap: 0; }
.mail-bar.selecting .mail-title { flex: none; padding-left: 4px; }
@media (max-width: 360px) {
  .mail-bar.selecting .icon-btn { width: 34px; }
  .mail-bar.selecting .mail-title .name { font-size: 16px; }
}

/* ---- mail: the folders drawer (narrow) and the left column (wide) ---- */
.mail-shell { position: relative; }
.mail-drawer-host { display: none; position: absolute; inset: 0; z-index: 30; }
.mail-drawer-host.shown { display: block; }
.mail-drawer-scrim {
  position: absolute; inset: 0; background: rgba(0, 0, 0, 0.35);
  opacity: 0; transition: opacity 200ms cubic-bezier(.55, .055, .675, .19);
}
.mail-drawer {
  position: absolute; top: 0; bottom: 0; left: 0; width: min(304px, 84%);
  /* The room under the floating top rail is a border, not padding: a
     border does not scroll, so rows never slide up under the rail. */
  border-top: calc(46px + env(safe-area-inset-top)) solid var(--bg);
  display: flex; flex-direction: column;
  background: var(--bg); border-right: 1px solid var(--border);
  border-radius: 0 18px 18px 0; box-shadow: 6px 0 24px rgba(0, 0, 0, 0.12);
  transform: translateX(-100%);
  transition: transform 200ms cubic-bezier(.55, .055, .675, .19);
  /* The whole drawer scrolls, foot included: on a short window a fixed
     foot left the last folders behind it. */
  touch-action: pan-y; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain;
}
body.embedded .mail-drawer { border-top-width: 8px; }
.mail-drawer-host.open .mail-drawer-scrim { opacity: 1; transition: opacity 260ms cubic-bezier(.215, .61, .355, 1); }
.mail-drawer-host.open .mail-drawer { transform: none; transition: transform 260ms cubic-bezier(.215, .61, .355, 1); }
.mail-drawer-head { padding: 14px 20px 12px; flex: none; }
.mail-drawer-head .title { font-size: 20px; font-weight: 700; color: var(--ink); }
.mail-drawer-head .addr { font-size: 13px; color: var(--ink-muted); margin-top: 2px; overflow-wrap: anywhere; }
.mail-drawer-list { flex: 1 0 auto; padding: 0 8px 8px; }
.mail-drawer-row {
  display: flex; align-items: center; gap: 14px; width: 100%; height: 44px; padding: 0 12px;
  border: none; border-radius: 12px; background: none; color: var(--ink); text-align: left;
  font: inherit; cursor: pointer;
}
.mail-drawer-row:hover { background: var(--surface); }
.mail-drawer-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.mail-drawer-row svg { width: 20px; height: 20px; flex: none; stroke: var(--ink-muted); fill: none; stroke-width: 32; }
.mail-drawer-row .label { flex: 1; min-width: 0; font-size: 15px; font-weight: 600; overflow-wrap: break-word; }
.mail-drawer-row .n { font-size: 13px; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.mail-drawer-row .warn {
  width: 18px; height: 18px; border-radius: 9px; flex: none; display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800; color: #fff; background: var(--danger);
}
.mail-drawer-row.on { background: var(--accent-soft); color: var(--accent); }
.mail-drawer-row.on svg { stroke: var(--accent); }
.mail-drawer-row.on .n { color: var(--accent); }
.mail-drawer-section { font-size: 11px; font-weight: 700; letter-spacing: 0.6px; color: var(--ink-faint); padding: 18px 12px 6px; }
.mail-drawer-foot { flex: none; border-top: 1px solid var(--border); padding: 8px 8px calc(10px + env(safe-area-inset-bottom)); }

.mail-wide { flex: 1; min-height: 0; display: flex; }
.mail-side {
  flex: none; width: 220px; display: flex; flex-direction: column;
  border-right: 1px solid var(--border);
  padding-top: calc(46px + env(safe-area-inset-top));
}
body.embedded .mail-side { padding-top: 8px; }
.mail-side .mail-drawer-head { padding: 8px 16px 10px; }
.mail-side .mail-drawer-head .title { font-size: 18px; }
.mail-side .mail-drawer-list { overflow: visible; flex: none; }
.mail-side .mail-drawer-foot { margin-top: auto; padding-bottom: 10px; }
.mail-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* A desktop browser tab gets the room the folders column and the reader
   need, as Messages gets its two panes (shell.css); the phone-shaped column
   would never reach the wide layout. */
@media (min-width: 900px) {
  body[data-page='mail'] .app-shell { max-width: 1100px; }
}

/* ---- mail: the conversation, narrow ----
   A layer over the list that pops up from the bottom (21 Oct 2026, the
   owner: "opening emails the animation should be pop up from the bottom"),
   the same pop as the stationary places (shell.css vt-pop-in / vt-pop-out:
   in from 24px below in 180 ms, away in 130). The list under it stays where
   it is and dims a touch — as Messages does (below) and as the phone does. */
.mail-read-layer {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 20;
  top: calc(46px + env(safe-area-inset-top));
  display: flex; flex-direction: column;
  background: var(--bg);
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -2px 18px rgba(0, 0, 0, 0.10);
  transition: transform 180ms cubic-bezier(.33, 1, .68, 1), opacity 180ms cubic-bezier(.33, 1, .68, 1);
}
body.embedded .mail-read-layer { top: 8px; }
.mail-read-layer.enter { transform: translateY(24px); opacity: 0; }
/* The way back is the pop-ups' own: quicker than the way in. */
.mail-read-layer.out { transform: translateY(24px); opacity: 0; pointer-events: none; transition: transform 130ms cubic-bezier(.25, .46, .45, .94), opacity 130ms cubic-bezier(.25, .46, .45, .94); }
.mail-read-layer > .mail-read { flex: 1; min-height: 0; }
.mail-shell > .mail-top, .mail-shell > .mail-split {
  transition: filter 130ms;
}
.mail-shell.reading > .mail-top, .mail-shell.reading > .mail-split {
  filter: brightness(.92);
  transition: filter 180ms;
}

/* ---- mail: the undo bar at the foot ---- */
.mail-snack {
  position: absolute; z-index: 40; left: 12px; right: 12px; bottom: 12px;
  display: flex; align-items: center; gap: 12px; padding: 12px 8px 12px 16px; border-radius: 12px;
  background: color-mix(in srgb, var(--ink) 92%, var(--bg)); color: var(--bg);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.22); font-size: 14px; line-height: 18px;
  opacity: 0; transform: translateY(8px); transition: opacity 180ms ease, transform 180ms ease; pointer-events: none;
}
.mail-snack.show { opacity: 1; transform: none; pointer-events: auto; }
.mail-snack .text { flex: 1; min-width: 0; overflow-wrap: break-word; }
.mail-snack .undo { flex: none; min-height: 44px; min-width: 44px; margin: -8px 0; border: none; background: none; padding: 6px 10px; border-radius: 8px; font: inherit; font-size: 14px; font-weight: 700;
  color: color-mix(in srgb, var(--accent) 55%, var(--bg)); cursor: pointer; }
.mail-snack .undo:hover { background: color-mix(in srgb, var(--bg) 14%, transparent); }

/* ---- mail: the ⋯ menus ---- */
svg.glyph-more { stroke-width: 76 !important; }
.mail-pop {
  position: fixed; z-index: 1000; min-width: 190px; max-width: min(300px, calc(100vw - 16px)); padding: 6px;
  border: 1px solid var(--border); border-radius: 14px; background: var(--surface-solid, var(--surface));
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.22); animation: mail-pop-in 120ms ease-out;
}
@keyframes mail-pop-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.mail-pop-row { display: block; width: 100%; min-height: 44px; text-align: left; padding: 10px 12px; border: none; border-radius: 9px; background: none;
  font: inherit; font-size: 14.5px; color: var(--ink); cursor: pointer; overflow-wrap: break-word; }
.mail-pop-row:hover, .mail-pop-row:focus-visible { background: var(--accent-soft); outline: none; }
.mail-pop-row.danger { color: var(--danger); }

/* ---- messages, narrow: the conversation slides in over the list ----
   Both panes stay drawn (the list keeps its scroll); these repeat the
   `display: none` rules' selectors from shell.css to override them. The
   wide layout (720 and over) is untouched. */
@media (max-width: 719.98px) {
  .msg-stack { position: relative; overflow: hidden; }
  .msg-stack[data-view='list'] > .msg-convo,
  .msg-stack[data-view='convo'] > .msg-list { display: flex; }
  /* The phone's push and pop (components/pages/MessagesPage.tsx PUSH_MS,
     POP_MS, PUSH_EASE): an ease-out both ways, most of the way at once.
     The way back used to ease IN, which starts slowly. */
  .msg-stack > .msg-convo {
    position: absolute; inset: 0; z-index: 2;
    background: var(--bg);
    box-shadow: -6px 0 22px rgba(0, 0, 0, 0.10);
    transform: translateX(100%); visibility: hidden;
    transition: transform 280ms cubic-bezier(.2, .9, .25, 1), visibility 0s linear 280ms;
  }
  .msg-stack[data-view='convo'] > .msg-convo {
    transform: none; visibility: visible;
    transition: transform 320ms cubic-bezier(.2, .9, .25, 1), visibility 0s;
  }
  .msg-stack > .msg-list {
    transition: transform 280ms cubic-bezier(.2, .9, .25, 1), filter 280ms, visibility 0s;
  }
  .msg-stack[data-view='convo'] > .msg-list {
    transform: translateX(-25%); filter: brightness(.92); visibility: hidden;
    transition: transform 320ms cubic-bezier(.2, .9, .25, 1), filter 320ms, visibility 0s linear 320ms;
  }
}

/* ---- reduced motion: no movement ---- */
@media (prefers-reduced-motion: reduce) {
  .panel-card, .panel-card.closing { animation: none; }
  /* The conversation fades in and out instead of sliding; the list stays put. */
  .mail-read-layer, .mail-read-layer.out { transition: opacity 120ms linear; }
  .mail-read-layer.enter, .mail-read-layer.out { transform: none; opacity: 0; }
  .mail-shell > .mail-top, .mail-shell > .mail-split, .mail-shell.reading > .mail-top, .mail-shell.reading > .mail-split { filter: none; transition: none; }
  .mail-snack, .mail-pop { transition: none; animation: none; }
  .mail-drawer, .mail-drawer-host.open .mail-drawer { transform: none; transition: none; }
  .mail-drawer-host .mail-drawer { opacity: 0; transition: opacity 120ms linear; }
  .mail-drawer-host.open .mail-drawer { opacity: 1; transition: opacity 120ms linear; }
  .msg-stack > .msg-convo, .msg-stack[data-view='convo'] > .msg-convo,
  .msg-stack > .msg-list, .msg-stack[data-view='convo'] > .msg-list { transition: none; }
  .msg-stack[data-view='convo'] > .msg-list { transform: none; filter: none; }
}

/* The left column is narrower than the drawer: its longer rows wrap rather than cut. */
.mail-side .mail-drawer-row { height: auto; min-height: 44px; padding-top: 6px; padding-bottom: 6px; }
.mail-side .mail-drawer-row .label { white-space: normal; line-height: 1.25; }

/* ---- offline, on the pages that keep their own copy (3 Oct 2026) ----
   Messages and Mail draw what they saved when the server cannot be reached,
   under one slim line that says so (pages/messages.js, pages/mail.js); the
   app-wide line is not drawn over them as well (app.js ownOffline). A state,
   not an error — never red. */
.page-offline-line {
  padding: 6px 14px;
  background: var(--accent-soft, var(--surface));
  color: var(--accent, var(--ink));
  border-bottom: 1px solid var(--border);
  font-size: 12.5px; font-weight: 700; text-align: center;
}
.page-offline-line[hidden] { display: none; }
.offline-empty .offline-title { font-weight: 700; color: var(--ink); font-size: 15px; }
.msg-offline-empty { padding: 40px 24px 24px; }
.msg-offline-empty .faint { max-width: 260px; line-height: 1.45; }

/* ==========================================================================
   Messages: chats, communities and mail on one page (6 Oct 2026)
   pages/messages.js draws the head, the search, the pinned shelf and the two
   sideways rows; pages/mail.js draws the mail under them (embed), a mail
   conversation into .msg-mailpane, and its drawer as the page's sidebar;
   pages/community.js draws a community into .msg-spacepane. The phone's
   twin is components/pages/MessagesPage.tsx.
   ========================================================================== */

/* ---- the head (13 Oct 2026): the settings of the page's parts, then the
   pencil at the other end — no ☰, no "Messages" (the rail says it), no
   Friends (it is in the Apps). Round buttons with a border, 44 px. ---- */
.msg-head { gap: 8px; padding: 6px 12px 6px; }
.msg-head .msg-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.msg-head-gap { flex: 1; min-width: 0; }
.msg-top-btn {
  flex: none; width: 44px; height: 44px; border-radius: 22px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: var(--surface); color: var(--ink);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform 120ms ease, background 120ms ease;
}
.msg-top-btn[hidden] { display: none; }
.msg-top-btn svg { width: 21px; height: 21px; stroke: currentColor; fill: none; stroke-width: 34; }
.msg-top-btn:hover { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
.msg-top-btn:active { transform: scale(0.94); }
.msg-top-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.msg-top-btn.msg-compose-btn { color: var(--accent); }
.msg-stack .msg-head .round-btn { background: none; }
.msg-stack .msg-head .round-btn:hover { background: var(--surface); }
.msg-stack .msg-head .round-btn svg { width: 22px; height: 22px; }
/* Its view, where a community opens: one head row, then the feed. */
.msg-friends { background: var(--bg); }
.msg-friends-head { gap: 6px; padding: 6px 10px 6px; }
.msg-friends-head .round-btn { background: none; }
.msg-friends-head .round-btn:hover { background: var(--surface); }
.msg-friends-head .round-btn svg { width: 22px; height: 22px; }
.msg-friends-head .stack-title {
  flex: 1; min-width: 0; text-align: left; padding-left: 4px;
  font-size: 22px; font-weight: 800; letter-spacing: -0.2px;
}
.msg-friends-body { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 6px 14px calc(28px + env(safe-area-inset-bottom)); }
.msg-friends-body > .social-feed { max-width: 620px; margin: 0 auto; padding: 0; }
/* Beside the list the pane has no way back to take: the list is right there. */
@media (min-width: 720px) {
  .msg-friends-head .round-btn { display: none; }
  .msg-friends-head { padding-left: 18px; }
}
/* Under the floating rail, when the page has one; inside the phone's frame, none. */
.msg-stack.with-rail > .screen { padding-top: calc(46px + env(safe-area-inset-top)); }
body.embedded .msg-stack.with-rail > .screen { padding-top: 8px; }

.msg-import { flex: none; padding: 0 16px 6px; }
.msg-import:empty { display: none; }
.msg-scroll { padding-bottom: 28px; }
.msg-list-pane > .msg-rail-wrap:first-child > .msg-rail { padding-top: 10px; }
/* The row of chats: the pinned ones first, a hairline, everyone else. */
.msg-rail-rule { flex: none; align-self: center; width: 2px; height: 64px; border-radius: 1px; background: var(--border); margin: 0 1px; }
.msg-rail .pin-card { width: 104px; min-height: 120px; scroll-snap-align: start; }

/* ---- the sideways rows: chats, communities ---- */
.msg-rail-wrap { position: relative; }
.msg-rail {
  display: flex; gap: 10px; overflow-x: auto; padding: 4px 16px 12px;
  scrollbar-width: none; scroll-snap-type: x proximity; scroll-padding-inline: 16px;
  -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
}
.msg-rail::-webkit-scrollbar { display: none; }
.msg-rail.dragging { scroll-snap-type: none; cursor: grabbing; }
.msg-rail.dragging > * { pointer-events: none; }
.msg-rail img { -webkit-user-drag: none; user-select: none; }
/* ‹ › at the ends, with a mouse, while there is more past them. */
.rail-arrow {
  display: none; position: absolute; top: calc(50% - 6px); transform: translateY(-50%); z-index: 2;
  width: 32px; height: 32px; border-radius: 16px; padding: 0;
  align-items: center; justify-content: center;
  background: var(--surface-solid, var(--bg)); border: 1px solid var(--border); color: var(--ink);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.14); cursor: pointer;
}
.rail-arrow svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 48; }
.rail-arrow:hover { color: var(--accent); }
.rail-arrow.prev { left: 6px; }
.rail-arrow.next { right: 6px; }
.msg-stack.fine .msg-rail-wrap.can-back > .rail-arrow.prev,
.msg-stack.fine .msg-rail-wrap.can-on > .rail-arrow.next { display: flex; }

/* A chat: the face (52) and its dot, a first name, one line. Unread wears the
   accent ring, as a pinned card does. */
.chat-card {
  position: relative; flex: none; width: 104px; min-height: 120px; border-radius: 22px;
  display: flex; flex-direction: column; align-items: center; padding: 12px 8px 10px;
  background: var(--surface-solid, var(--surface)); border: 1px solid var(--border); color: var(--ink);
  font: inherit; text-align: center; cursor: pointer; scroll-snap-align: start;
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
  transition: transform 120ms ease, background 120ms ease;
}
.chat-card:hover { background: var(--surface); }
.chat-card:active { transform: scale(0.96); }
.chat-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.chat-card.unread {
  border: 2px solid var(--accent); padding: 11px 7px 9px;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent), 0 6px 16px color-mix(in srgb, var(--accent) 22%, transparent);
}
.chat-card.active { background: var(--accent-soft); }
.chat-card.active .chat-card-name { color: var(--accent); }
.chat-card-face { position: relative; display: inline-flex; flex: none; }
.chat-card-face .avatar { width: 52px; height: 52px; border-radius: 26px; font-size: 18px; }
/* Names take two lines before they are cut: "Weekend crew", not "Weeken…". */
.chat-card-name {
  margin-top: 8px; max-width: 100%; font-size: 14px; font-weight: 700; line-height: 17px;
  display: block; overflow-wrap: break-word;
}
.chat-card-line {
  margin-top: 2px; max-width: 100%; font-size: 12px; line-height: 16px; color: var(--ink-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; /* preview: a long free-text preview a tap opens in full — the one sanctioned cut */
}
.chat-card-line.live, .chat-card-line.news { color: var(--accent); font-weight: 700; }
.chat-card.start { border-style: dashed; justify-content: center; }
.chat-card.start .chat-card-name { color: var(--accent); }
.start-glyph {
  width: 52px; height: 52px; border-radius: 26px; display: flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--accent);
}
.start-glyph svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 36; }

/* A community: its emoji on its colour in a rounded square (community.js's tile). */
.space-glyph {
  flex: none; display: inline-flex; align-items: center; justify-content: center; line-height: 1;
  background: var(--accent-soft); color: var(--accent);
}
.space-glyph.home { background: var(--ink); color: var(--bg); }
.space-glyph.tile { width: 56px; height: 56px; border-radius: 17px; font-size: 27px; }
.space-glyph.pin { width: 50px; height: 50px; border-radius: 15px; font-size: 24px; }
.space-glyph.side { width: 22px; height: 22px; border-radius: 7px; font-size: 12px; }
.space-glyph.find { background: var(--surface); color: var(--ink-muted); border: 1.5px dashed var(--border); }
.space-glyph.find svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 40; }
.space-tile {
  flex: none; width: 84px; display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 6px 3px 6px; border: none; border-radius: 16px; background: none; color: var(--ink); font: inherit; cursor: pointer;
  scroll-snap-align: start; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
}
.space-tile:focus-visible { outline: none; }
.space-tile:focus-visible .space-glyph { outline: 2px solid var(--accent); outline-offset: 2px; }
.space-tile:active .space-glyph { transform: scale(0.95); }
.space-tile-face { position: relative; display: inline-flex; }
/* News wears the accent ring; the one open stands on the soft accent, as an open chat card does. */
.space-tile.unread .space-glyph.tile { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent); }
.space-tile.active { background: var(--accent-soft); }
.space-tile-name {
  max-width: 100%; font-size: 12px; font-weight: 600; line-height: 15px; text-align: center;
  display: block; overflow-wrap: break-word;
}
.space-tile.unread .space-tile-name { font-weight: 800; }
.space-tile.active .space-tile-name { color: var(--accent); }
.space-tile.find .space-tile-name { color: var(--ink-muted); }
.space-badge {
  position: absolute; top: -6px; right: -8px; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--on-accent, #fff); border: 2px solid var(--bg);
  font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums;
}
/* A pinned name takes two lines too; the card grows to hold them. */
.msg-list-pane .pin-card { width: 96px; height: auto; min-height: 108px; padding-left: 4px; padding-right: 4px; padding-bottom: 9px; }
.msg-list-pane .pin-card .pin-name {
  white-space: normal; text-align: center; line-height: 15px; font-size: 12px;
  display: block; overflow-wrap: break-word;
}
/* The pinned shelf holds communities too: the tile for a face. */
.pin-card.space .pin-face { padding: 0; }
.pin-card.active .space-glyph { box-shadow: 0 0 0 2px var(--accent); }
/* The sidebar's community rows: the small tile where a glyph stands. */
.mail-drawer-row > .space-glyph.side { margin: 0 -1px; }

/* Nothing to show in a row: one line, or one thing to do. */
.msg-none { padding: 2px 16px 14px; font-size: 14px; color: var(--ink-faint); }
.msg-kid-empty { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; padding: 2px 16px 14px; }
.msg-kid-empty .msg-empty-text { flex: 1 1 180px; text-align: left; font-size: 14px; }
.msg-kid-empty .msg-empty-btn { margin-top: 0; min-height: 40px; padding: 0 18px; border-radius: 20px; font-size: 14px; }
.msg-list-pane .msg-offline-empty { padding: 8px 24px 16px; }

/* ---- the mail, under the communities ---- */
.msg-mail-list .mail-piles { padding: 2px 16px 6px; margin: 0; }
.msg-mail-list .mail-list-wrap { display: block; }
.msg-mail-list .mail-list { width: auto; }
/* The picked ones' bar stays at the top of the page while you scroll through the mail. */
.msg-mail-sel { position: sticky; top: 0; z-index: 3; background: var(--bg); padding: 4px 10px; border-bottom: 1px solid var(--border); }
.msg-mail-list .setup { padding: 18px 24px 10px !important; gap: 8px; }
.msg-mail-list .setup > div:first-child:has(> svg) { display: none; }
.msg-mail-list .setup p { margin: 0; font-size: 14px; color: var(--ink-muted); }
.msg-mail-claim h2 { margin: 0; font-size: 17px; }
.msg-mail-list .offline-empty { padding: 16px 24px; }
.msg-mail-list .mail-more { margin-top: 4px; }

/* ---- the row over the mail (13 Oct 2026; pages/mail.js mailRow, the
   phone's components/mail/MailRow.tsx): Clean up on the buddy's yellow, the
   piles in their colours, a hairline, the folders, the mailboxes. Icons in
   bordered 44 px buttons; the one you are on wears its name on its colour,
   on a lip, the arcade's way (games/look.mjs). Sideways where it is wider
   than the list. ---- */
.mail-tools {
  display: flex; align-items: center; gap: 8px; overflow-x: auto; overflow-y: visible;
  padding: 10px 16px 8px; scrollbar-width: none; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
}
.mail-tools::-webkit-scrollbar { display: none; }
.mail-tool {
  position: relative; flex: none; height: 44px; min-width: 44px; padding: 0; border-radius: 15px;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid var(--border); background: var(--surface); color: var(--chip-tint, var(--ink-muted));
  font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform 120ms ease, background 120ms ease;
}
.mail-tool svg { width: 19px; height: 19px; flex: none; stroke: currentColor; fill: none; stroke-width: 34; }
.mail-tool:hover { background: var(--accent-soft); }
.mail-tool:active { transform: scale(0.96); }
.mail-tool:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mail-tool.on {
  padding: 0 14px; background: var(--chip); color: var(--chip-ink);
  border-color: var(--chip-lip); border-bottom-width: 3px;
}
.mail-tool.on:active { transform: translateY(1px) scale(0.96); }
.mail-tool .label { font-size: 14.5px; font-weight: 800; letter-spacing: 0.1px; white-space: nowrap; }
.mail-tool .label .n { font-weight: 700; margin-left: 7px; font-variant-numeric: tabular-nums; }
.mail-tool.tidy { width: 44px; background: var(--chip); color: var(--chip-ink); border-color: var(--chip-lip); border-bottom-width: 3px; }
.mail-tool.tidy svg { fill: currentColor; stroke: none; }
.mail-tool.warn { color: var(--danger); }
.mail-tools-rule { flex: none; width: 2px; height: 26px; border-radius: 1px; background: var(--border); margin: 0 2px; }
/* The row stands in the page's scroller, a little clear of the chats above it. */
.msg-mail-list > .mail-tools { margin-top: 2px; }

/* ---- what opens beside the list: a mail conversation, a community ---- */
.msg-stack { position: relative; }
.msg-mailpane > .mail-read { flex: 1; min-height: 0; }
.msg-mailpane > .mail-read > .mail-reply-bar { bottom: 10px; }
.msg-space-host { flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* Inside Messages nothing floats at a community's corners: its heads start at the edge. */
.cm-embedded .page-head.cm-head { padding-left: 10px; padding-right: 12px; padding-top: 6px; }
.cm-embedded .cm-rail-head,
.cm-embedded .cm-space:not(.wide) .cm-rail-head,
.cm-embedded .cm-space.wide .cm-rail-head { padding-left: 10px; padding-right: 8px; padding-top: 8px; }
/* Its round buttons as big as the page's other ways back (40). */
.cm-embedded .cm-round:not(.sm) { width: 40px; height: 40px; }
/* Its column's foot on one row: Inbox, Members, Mod. */
.cm-embedded .cm-rail-foot { flex-wrap: nowrap; }
.cm-embedded .cm-rail-tool { min-width: 0; white-space: nowrap; }
.cm-embedded .cm-room-head,
.cm-embedded .cm-space:not(.wide) .cm-room-head,
.cm-embedded .cm-space.wide .cm-room-head { padding-left: 10px; padding-right: 12px; }
@media (min-width: 720px) {
  .msg-stack > .msg-list { flex: 0 0 min(372px, 42%); }
  /* The box at the bottom is the page's search (13 Oct 2026), so side by
     side it stays — under the list it searches, the width of the list, and
     not under the conversation, which has its own composer (the reason the
     bar was hidden here: two inputs stacked). The list keeps room for it
     (--msg-bar-h, measured by pages/messages.js). */
  body[data-page='messages']:not(.cm-ask) .app-shell > .shell-bar.cmd-wrap {
    display: block; position: absolute; left: 0; bottom: 0; z-index: 6;
    width: min(372px, 42%); box-sizing: border-box; padding-right: 1px;
  }
  body[data-page='messages'] .msg-stack > .msg-list { padding-bottom: var(--msg-bar-h, 0px); }
  .msg-stack[data-view] > .msg-side { display: none; }
  .msg-stack[data-view][data-pane='mail'] > .msg-mailpane,
  .msg-stack[data-view][data-pane='space'] > .msg-spacepane { display: flex; flex: 1; min-width: 0; }
  .msg-stack[data-view][data-pane='mail'] > .msg-convo,
  .msg-stack[data-view][data-pane='space'] > .msg-convo { display: none; }
}
/* A phone: a community slides in over the list from the right, as a chat
   does — in 230 ms, and away in 160 (the Shmangus feel: closing is never
   the slower one), on an ease-out cubic. A mail pops up from the bottom
   instead (21 Oct 2026, the owner: "opening emails the animation should be
   pop up from the bottom … rather than page swiping to the right"): the
   pop-ups' own 180 ms in from 24px below and 130 out, the list under it
   still. The list under either dims with an overlay's opacity, not a
   filter: a filter repainted the whole list on every frame of the motion,
   which is what made leaving a mail stutter (13 Oct 2026). A finger can
   drag the mail back down (pages/mail.js): the list is drawn under it then
   (.pop-drag), and comes back on the close's own time ([data-left]). */
@media (max-width: 719.98px) {
  .msg-stack > .msg-side {
    position: absolute; inset: 0; z-index: 2;
    background: var(--bg);
    box-shadow: -6px 0 22px rgba(0, 0, 0, 0.10);
    transform: translateX(100%); visibility: hidden;
    transition: transform 160ms cubic-bezier(.33, 1, .68, 1), visibility 0s linear 160ms;
  }
  .msg-stack[data-view='space'] > .msg-spacepane {
    transform: none; visibility: visible;
    transition: transform 230ms cubic-bezier(.33, 1, .68, 1), visibility 0s;
  }
  .msg-stack[data-view='space'] > .msg-list {
    transform: translateX(-25%); filter: none; visibility: hidden;
    transition: transform 230ms cubic-bezier(.33, 1, .68, 1), visibility 0s linear 230ms;
  }
  .msg-stack > .msg-mailpane {
    transform: translateY(24px); opacity: 0;
    border-radius: 16px 16px 0 0; box-shadow: 0 -2px 18px rgba(0, 0, 0, 0.10);
    transition: transform 130ms cubic-bezier(.25, .46, .45, .94), opacity 130ms cubic-bezier(.25, .46, .45, .94), visibility 0s linear 130ms;
  }
  .msg-stack[data-view='mail'] > .msg-mailpane {
    transform: none; opacity: 1; visibility: visible;
    transition: transform 180ms cubic-bezier(.33, 1, .68, 1), opacity 180ms cubic-bezier(.33, 1, .68, 1), visibility 0s;
  }
  .msg-stack[data-view='mail'] > .msg-list {
    transform: none; filter: none; visibility: hidden;
    transition: visibility 0s linear 180ms;
  }
  /* The grip at the mail's top: it says the mail goes back down, and a drag on it does. */
  .msg-mailpane > .mail-grip { display: flex; flex: 0 0 auto; height: 20px; align-items: center; justify-content: center; touch-action: none; cursor: grab; }
  .msg-mailpane > .mail-grip::before { content: ''; width: 38px; height: 5px; border-radius: 3px; background: var(--border); }
  .msg-stack[data-left='side'] > .msg-list { transition: transform 160ms cubic-bezier(.33, 1, .68, 1), visibility 0s; }
  /* Its own stacking context: the dim over the list (z 5 inside it) stays
     under the mail standing over it (z 2), never greying the mail as it pops. */
  .msg-stack > .msg-list { position: relative; isolation: isolate; }
  .msg-stack > .msg-list::after {
    content: ''; position: absolute; inset: 0; z-index: 5; pointer-events: none;
    background: #000; opacity: 0; transition: opacity 160ms linear;
  }
  .msg-stack[data-view='mail'] > .msg-list::after { opacity: 0.08; transition-duration: 180ms; }
  .msg-stack[data-view='space'] > .msg-list::after { opacity: 0.08; transition-duration: 230ms; }
  /* After the dim it lightens: a finger pulling the mail down brings the list back up to full. */
  .msg-stack.pop-drag > .msg-list { visibility: visible !important; }
  .msg-stack.pop-drag > .msg-list::after { opacity: calc(0.08 * (1 - var(--pop-pull, 0))); transition: none; }
  .msg-stack.pop-drag > .msg-mailpane { will-change: transform; }
  /* At its top a drag down is the mail's way back (pages/mail.js), not an overscroll. */
  .msg-stack > .msg-mailpane > .mail-read { overscroll-behavior-y: contain; }
}
/* Side by side there is nothing to pull down: no grip. */
.mail-grip { display: none; }
@media (prefers-reduced-motion: reduce) {
  .msg-stack > .msg-side, .msg-stack[data-view='mail'] > .msg-mailpane, .msg-stack[data-view='space'] > .msg-spacepane { transition: none; }
  .msg-stack > .msg-mailpane { transform: none; }
  .msg-stack[data-view='mail'] > .msg-list, .msg-stack[data-view='space'] > .msg-list { transform: none; filter: none; transition: none; }
  .msg-stack > .msg-list::after { display: none; }
}

/* A profile with no address of its own shows Personal's mail: one quiet line over the rows (pages/mail.js). */
.mail-borrowed { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 10px 16px; font-size: 14px; color: var(--ink-muted); }
.mail-borrowed .linkish { font-size: 14px; font-weight: 700; }

/* ---- the mail row's words, 14 Oct 2026 (pages/mail.js threadRow, mailGist.mjs) ----
   What a mail says sits under its subject in up to three lines — the
   on-device summary or the description made by code — never cut to one line
   with an ellipsis; the address it came to is a dot by the time, not a chip. */
.mail-item .snippet.words { /* preview: what a mail says, four lines at most; the click opens it whole. */ display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; line-clamp: 4;
  overflow: hidden; white-space: normal; text-overflow: clip; overflow-wrap: anywhere; margin-top: 2px; }
/* In italics, so it never reads as more of the subject (the user: "its hard to differentiate between subject and the summary"). */
.mail-item .snippet.words { font-style: italic; }
.mail-item .addr-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; }
.mail-item .mid .star { margin-top: -6px; margin-bottom: -6px; }


/* ---- Messages is one list (14 Oct 2026, late; commsHub.mjs, pages/mail.js
   mailRow/listPane, pages/messages.js chatRow — the phone's MailRow.tsx and
   MailPage.tsx the same) ----
   The buttons over the list never scroll sideways: the tools (Clean up, the
   folders, the mailboxes) as round keys, as many as fit, the rest behind
   "More"; the five piles share a line, each its glyph and a short name. */
.mail-rows { display: flex; flex-direction: column; gap: 8px; padding: 8px 16px 6px; }
.mail-rows > .mail-tools { padding: 0; overflow: visible; flex-wrap: nowrap; gap: 6px; }
.mail-tool.round { width: 44px; height: 44px; border-radius: 50%; padding: 0; border-bottom-width: 3px; color: var(--ink-muted); }
.mail-tool.round.on { padding: 0; background: var(--accent); color: var(--on-accent, #fff); border-color: color-mix(in srgb, var(--accent) 72%, #000); }
.mail-tool.round.more svg { stroke-width: 48; }
.mail-tool.tidy { border-radius: 50%; }
.mail-piles2 { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.mail-pile2 {
  height: 50px; min-width: 0; padding: 0 2px; border-radius: 15px; cursor: pointer; font: inherit;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border: 1px solid var(--border); border-bottom-width: 3px; background: var(--surface); color: var(--ink-muted);
  transition: transform 120ms ease; -webkit-tap-highlight-color: transparent;
}
.mail-pile2 .top { display: inline-flex; align-items: center; gap: 4px; }
.mail-pile2 svg { width: 18px; height: 18px; stroke: var(--chip-tint, currentColor); fill: none; stroke-width: 34; }
.mail-pile2 .name { /* fixed: five equal keys whose names code keeps short (Primary … Social), stepping down at 320; the cut is only a safety net. */ font-size: 11.5px; font-weight: 800; letter-spacing: 0.1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
/* A 320 phone: five keys of ~52px each — the names step down so "Primary" and "Receipts" stay whole. */
@media (max-width: 359px) {
  .mail-piles2 { gap: 4px; }
  .mail-pile2 { padding: 0 1px; }
  .mail-pile2 .name { font-size: 10px; letter-spacing: -0.2px; }
}
.mail-pile2 .n { font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums; }
.mail-pile2:hover { background: var(--accent-soft); }
.mail-pile2:active { transform: translateY(1px) scale(0.97); }
.mail-pile2:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mail-pile2.on { background: var(--chip); color: var(--chip-ink); border-color: var(--chip-lip); }
.mail-pile2.on svg { stroke: var(--chip-ink); }
/* The subject whole, on as many lines as it needs; a hairline, then what it
   says in italics in a quieter tint of its own. */
.mail-item .mid { align-items: flex-start; }
.mail-item .subject { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: break-word; color: var(--ink); font-weight: 500; }
.mail-item.unseen .subject { font-weight: 700; }
.mail-item .words-rule { height: 1px; margin: 6px 24px 5px 0; background: var(--border); }
.mail-item .snippet.words {
  margin-top: 0; font-style: italic;
  color: color-mix(in srgb, var(--ink-muted) 75%, var(--accent));
}
.mail-item .list-pin, .mail-item .row-kind, .chat-row .list-pin, .chat-row .row-kind { display: inline-flex; flex: none; }
.mail-item .list-pin svg, .chat-row .list-pin svg { width: 13px; height: 13px; stroke: var(--ink-faint); fill: none; stroke-width: 36; }
.mail-item .row-kind svg { width: 13px; height: 13px; stroke: var(--ink-faint); fill: none; stroke-width: 36; }
/* "View the rest": a key at the foot of the list. */
.mail-rest {
  display: flex; align-items: center; justify-content: center; gap: 6px; width: calc(100% - 32px); margin: 10px 16px 18px; height: 46px;
  border-radius: 15px; border: 1px solid var(--border); border-bottom-width: 3px; background: var(--surface); color: var(--ink);
  font: inherit; font-size: 15px; font-weight: 800; cursor: pointer;
}
.mail-rest svg { width: 18px; height: 18px; stroke: var(--ink-muted); fill: none; stroke-width: 40; }
.mail-rest:active { transform: translateY(1px); }
/* A chat as a row of the one list: the mail row's shape. */
.chat-row {
  display: flex; align-items: flex-start; gap: 14px; width: 100%; padding: 10px 16px; border: 0; background: none; text-align: left;
  font: inherit; color: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.chat-row:hover { background: var(--surface); }
.chat-row.active { background: var(--accent-soft); }
.chat-row .chat-row-face { position: relative; flex: none; width: 46px; height: 46px; }
.chat-row .chat-row-body { flex: 1; min-width: 0; }
.chat-row .chat-row-top { display: flex; align-items: center; gap: 6px; min-width: 0; }
.chat-row .chat-row-name { flex: 1; min-width: 0; font-size: 15.5px; font-weight: 600; color: var(--ink-muted); white-space: normal; overflow-wrap: break-word; }
.chat-row.unread .chat-row-name { font-weight: 700; color: var(--ink); }
.chat-row .row-kind.chat svg { width: 13px; height: 13px; stroke: var(--accent); fill: none; stroke-width: 36; }
.chat-row .chat-row-when { font-size: 12.5px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.chat-row.unread .chat-row-when { color: var(--ink); font-weight: 700; }
.chat-row .chat-row-line { margin-top: 2px; font-size: 14px; line-height: 19px; color: var(--ink-muted);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; /* preview: a long free-text preview a tap opens in full — the one sanctioned cut */ }
.chat-row .chat-row-line.news, .chat-row .chat-row-line.live { color: var(--accent); font-weight: 600; }
/* Over the one list: the first chat to start; and, where there is no mail to put them among, the chats as rows. */
.msg-start-row {
  display: inline-flex; align-items: center; gap: 8px; margin: 8px 16px 4px; height: 44px; padding: 0 14px;
  border-radius: 14px; border: 1.5px dashed var(--accent); background: none; color: var(--accent); font: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
.msg-start-row svg { width: 19px; height: 19px; stroke: currentColor; fill: none; stroke-width: 34; }
.msg-chat-rows { display: flex; flex-direction: column; }
/* "All messages": the key between the first few chats and the mail (14 Oct 2026, night). */
.msg-chats-key {
  display: flex; align-items: center; justify-content: center; gap: 6px; width: calc(100% - 32px); margin: 4px 16px 10px; height: 44px;
  border-radius: 15px; border: 1px solid var(--border); border-bottom-width: 3px; background: var(--surface); color: var(--ink);
  font: inherit; font-size: 15px; font-weight: 800; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.msg-chats-key .more { font-size: 14px; font-weight: 600; color: var(--ink-muted); }
.msg-chats-key svg { width: 18px; height: 18px; stroke: var(--ink-muted); fill: none; stroke-width: 40; }
.msg-chats-key:active { transform: translateY(1px); }

/* The communities' line under the chats, over the mail (21 Oct 2026; commsHub.mjs spacesLine, SPACE_KEY 44,
   SPACES_GAP 8, SPACES_END 88): each community's tile on its lip — its emoji on its colour, what is new on its corner —
   as many as fit, then All or Find. One line, never sideways. The phone's MessagesPage spacesLine is the same. */
.msg-spaces { display: flex; align-items: center; gap: 8px; margin: 2px 16px 12px; overflow: visible; }
.space-key {
  position: relative; flex: none; width: 44px; height: 44px; box-sizing: border-box; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 14px; border: 1px solid var(--border); border-bottom-width: 3px; background: var(--accent-soft);
  font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.space-key.tinted { background: var(--space-key); border-color: color-mix(in srgb, var(--space-key) 72%, #000); }
.space-key:active { transform: translateY(1px); }
.space-key:focus-visible, .space-end:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.space-key.active { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent); }
.space-key-emoji { font-size: 21px; line-height: 1; }
.space-key-count {
  position: absolute; top: -7px; right: -7px; min-width: 20px; height: 20px; padding: 0 4px; box-sizing: border-box;
  border-radius: 10px; border: 2px solid var(--bg); background: var(--accent); color: var(--on-accent);
  display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 800; line-height: 1;
}
.space-end {
  flex: none; min-width: 88px; height: 44px; box-sizing: border-box; padding: 0 12px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border-radius: 14px; border: 1px solid var(--border); border-bottom-width: 3px; background: var(--surface); color: var(--ink);
  font: inherit; font-size: 15px; font-weight: 700; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.space-end:active { transform: translateY(1px); }
.space-end.active { background: var(--accent-soft); }
.space-end svg { width: 19px; height: 19px; flex: none; stroke: var(--accent); fill: none; stroke-width: 36; }
/* Beside tiles the last key keeps to the rule's width (SPACES_END 132), so the tiles before it were counted right. */
.space-end.beside { max-width: 132px; gap: 5px; padding: 0 10px; }
.space-end-more { flex: none; font-size: 13px; font-weight: 600; color: var(--ink-muted); }
.msg-spaces { position: relative; }
/* A held tile's name, laid over the line beside it for a moment: nothing moves. */
.space-tip {
  position: absolute; top: 0; min-height: 44px; box-sizing: border-box; z-index: 2; pointer-events: none;
  display: flex; align-items: center; gap: 8px; padding: 4px 12px 4px 7px;
  border-radius: 14px; border: 1px solid var(--border); background: var(--surface-solid, var(--surface));
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18); animation: space-tip-in 140ms ease-out both;
}
.space-tip .space-glyph.key { width: 30px; height: 30px; border-radius: 10px; font-size: 16px; }
.space-tip-name { min-width: 0; font-size: 15px; font-weight: 700; line-height: 19px; color: var(--ink); overflow-wrap: anywhere; }
.space-tip-new { flex: none; font-size: 13px; font-weight: 700; color: var(--accent); }
@keyframes space-tip-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .space-tip { animation: none; } }
/* The search's community rows: a chat's row, the tile for a face, the people glyph for its kind. */
.space-glyph.row { width: 46px; height: 46px; border-radius: 15px; font-size: 23px; }
.chat-row .row-kind.space svg { width: 14px; height: 14px; stroke: var(--accent); fill: none; stroke-width: 36; }

/* A box at the bottom of a chat or a room on the narrowest phones (21 Oct 2026, the review: "Messag" cut behind the
   smiley at 320): the empty box's word drawn a size down so it fits whole — never cut. What is typed keeps its 16.5px
   (iOS zooms into a field under 16px). */
@media (max-width: 380px) {
  .composer-dock .cmd-bar textarea.msg-input::placeholder { font-size: 15px; }
}
