/* Just Us — screens (docs/ui-spec.md §4–§8). */

/* ---------- onboarding / simple screens ---------- */
.onb {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-block-size: 0;
  inline-size: 100%;
  max-inline-size: 480px;
  margin-inline: auto;
  padding-block-start: env(safe-area-inset-top);
}

.onb__top {
  display: flex;
  align-items: center;
  min-block-size: var(--header-h);
  padding-inline: var(--s-2);
}

.onb__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  flex: 1;
  overflow-y: auto;
  padding-block: var(--s-2) var(--s-5);
  padding-inline: var(--s-5);
}

.onb__body--center {
  justify-content: center;
}

/* a status icon in the hero slot: same visual weight as the brand mark */
.hero-badge {
  display: inline-grid;
  place-items: center;
  inline-size: 72px;
  block-size: 72px;
  border-radius: 50%;
}

.hero-badge--warn {
  background: var(--warning-bg);
  color: var(--warning);
}

.hero-badge--bad {
  background: var(--danger-bg);
  color: var(--danger);
}

/* progress screens: title, lead and spinner share one centred axis */
.onb__body--text-center .onb__hero {
  align-items: center;
  text-align: center;
}

.onb__hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-3);
}

.onb__lead {
  font-size: var(--fs-lg);
  color: var(--text-muted);
}

.onb__actions {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding-block: var(--s-3) calc(var(--s-4) + env(safe-area-inset-bottom));
  padding-inline: var(--s-5);
}

.promises {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.promise {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
}

.promise .icon {
  color: var(--accent-fg);
  margin-block-start: 1px;
}

.steps {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  counter-reset: step;
}

.steps li {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
}

.steps li::before {
  counter-increment: step;
  content: counter(step);
  display: inline-grid;
  place-items: center;
  flex: none;
  inline-size: 28px;
  block-size: 28px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--accent-fg);
  font-weight: 700;
  font-size: var(--fs-sm);
}

.choice {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  inline-size: 100%;
  padding: var(--s-4);
  border: 1px solid var(--control-border);
  border-radius: var(--r-control);
  background: var(--surface);
  text-align: start;
}

.choice:hover {
  background: var(--surface-2);
}

.choice__icon {
  display: grid;
  place-items: center;
  inline-size: 48px;
  block-size: 48px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--accent-fg);
  flex: none;
}

.choice__text {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.choice__title {
  font-weight: 650;
  font-size: var(--fs-lg);
}

.center-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s-3);
}

.countdown {
  font-variant-numeric: tabular-nums;
}

/* ---------- conversation ---------- */
.conv {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-block-size: 0;
  position: relative;
}

.conv__header {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-block-size: calc(var(--header-h) + env(safe-area-inset-top));
  padding-block-start: env(safe-area-inset-top);
  padding-inline: var(--s-2);
  background: var(--accent-soft);
  border-block-end: 1px solid var(--border);
  z-index: 3;
}

.conv__who {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex: 1;
  min-inline-size: 0;
  padding-inline-start: var(--s-2);
}

.conv__names {
  display: flex;
  flex-direction: column;
  min-inline-size: 0;
}

.conv__title {
  font-size: var(--fs-lg);
  font-weight: 650;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conv__presence {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conv__verif {
  font-weight: 650;
}

@media (min-width: 600px) {
  .conv__verif,
  .conv__verif-sep {
    display: none;
  }
}

@media (max-width: 599px) {
  .conv__header .shield__label {
    display: none;
  }

  .conv__header button.shield {
    inline-size: var(--tap);
    padding: 0;
    justify-content: center;
  }

  .conv__header button.shield > span.shield__pill {
    border: 0;
    padding: 0;
  }

  .conv__header button.shield .icon {
    inline-size: 24px;
    block-size: 24px;
  }

  /* the subtitle carries the verification state here: state and presence on their own lines instead of being cut off */
  .conv__presence {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
  }

  .conv__presence > span {
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .conv__verif-sep {
    display: none;
  }

  .conv__title {
    line-height: 1.2;
  }

  .conv__actions {
    gap: 0;
  }
}

.conv__actions {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  color: var(--accent-fg);
}

.conv__main {
  position: relative;
  flex: 1;
  min-block-size: 0;
}

.conv__scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-anchor: none;
  overscroll-behavior: contain;
  /* vertical scrolling and pinch-zoom stay with the browser; horizontal drags reach the swipe-to-reply code (§11.1) */
  touch-action: pan-y pinch-zoom;
}

.msgs {
  display: flex;
  flex-direction: column;
  isolation: isolate;
  inline-size: 100%;
  max-inline-size: var(--col-max);
  margin-inline: auto;
  padding-block: var(--s-3) var(--s-4);
  padding-inline: var(--s-3);
}

.msg {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-block-start: var(--s-3);
}

.msg--out {
  align-items: flex-end;
}

.msg--grouped-prev {
  margin-block-start: 2px;
}

.bubble {
  max-inline-size: min(78%, 560px);
  padding-block: var(--s-2) 6px;
  padding-inline: var(--s-3);
  border-radius: var(--r-bubble);
  background: var(--surface-2);
  color: var(--text);
  overflow-wrap: anywhere;
  box-shadow: var(--shadow-1);
}

/* only while it springs back: a transition (or touch-action) on every bubble cost a third of the scrolling frame rate */
.bubble--spring {
  transition: transform var(--dur-2) var(--ease);
}

/* a long-press opens the message menu (Copy is there), not the text selection */
@media (pointer: coarse) {
  .bubble {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
  }
}

/* the tail on the last bubble of a group: a border triangle (logical sides, so it mirrors in RTL) drawn as an in-flow
   item of the row, tucked under the bubble's bottom corner. A positioned pseudo-element or a mask/gradient image per
   bubble cost scrolling frames (docs/ui-review.md D24). */
.msg > .bubble {
  order: -2;
}

.msg--tail::after {
  content: "";
  order: -1;
  inline-size: 0;
  block-size: 0;
  margin-block-start: -12px;
  border-block-end: 12px solid var(--surface-2);
}

.msg--out.msg--tail::after {
  margin-inline-end: -9px;
  border-block-end-color: var(--accent);
  border-inline-end: 9px solid transparent;
}

.msg--in.msg--tail::after {
  margin-inline-start: -9px;
  border-inline-start: 9px solid transparent;
}

/* the bubble moves during a swipe; the tail would stay behind */
.msg--swipe::after {
  visibility: hidden;
}

.msg--out.msg--tail .bubble {
  border-end-end-radius: 4px;
}

.msg--in.msg--tail .bubble {
  border-end-start-radius: 4px;
}

.msg--in.msg--grouped-next .bubble {
  border-end-start-radius: var(--r-bubble-tail);
}

.msg--in.msg--grouped-prev .bubble {
  border-start-start-radius: var(--r-bubble-tail);
}

.msg--out .bubble {
  background: var(--accent);
  color: var(--on-accent);
}

.msg--out.msg--grouped-next .bubble {
  border-end-end-radius: var(--r-bubble-tail);
}

.msg--out.msg--grouped-prev .bubble {
  border-start-end-radius: var(--r-bubble-tail);
}

.msg--out .bubble :focus-visible {
  outline-color: var(--focus-on-accent);
}

.bubble:focus-visible {
  outline-offset: 3px;
}

.bubble__text {
  white-space: pre-wrap;
  font-size: var(--fs-md);
  line-height: var(--lh);
}

.msg--out .bubble a {
  color: var(--on-accent);
}

/* time and ticks float at the end of the text: on its last line when they fit, else on a line of their own. Floated
   in the UI's direction (the paragraph itself is dir=auto). A spacer copy with an absolute overlay cost a third of the
   scrolling frame rate (docs/ui-review.md D24). */
.bubble__text {
  display: flow-root;
}

.bubble__meta {
  float: right;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  margin-block: 0.5em -2px;
  margin-left: var(--s-2);
  font-size: var(--fs-xs);
  line-height: 1.2;
  color: var(--text-muted);
  white-space: nowrap;
}

/* physical sides on purpose: the float follows the UI's direction, the paragraph may be either */
[dir="rtl"] .bubble__meta {
  float: left;
  margin-left: 0;
  margin-right: var(--s-2);
}

.msg--out .bubble__meta {
  color: var(--on-accent-muted);
}

.msg--emoji .bubble {
  background: transparent;
  box-shadow: none;
  padding-inline: 0;
}

.msg--emoji .bubble__meta {
  float: none;
  display: flex;
  justify-content: flex-end;
  margin: 2px 0 0;
}

.msg--emoji.msg--out .bubble__meta {
  color: var(--text-muted);
}

.msg--emoji .bubble__text {
  font-size: 2.6rem;
  line-height: 1.15;
}

.status {
  display: inline-flex;
  align-items: center;
}

.status .icon {
  inline-size: 16px;
  block-size: 16px;
  stroke-width: 2;
}

.status--read {
  padding-inline: 3px;
  border-radius: var(--r-pill);
  background: var(--on-accent);
  color: var(--accent);
}

.msg--emoji .status--read {
  background: var(--accent);
  color: var(--on-accent);
}

.status--failed {
  color: var(--danger);
}

.failed-note {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  margin-block-start: var(--s-1);
  min-block-size: 32px;
  padding-inline: var(--s-2);
  border: 0;
  border-radius: var(--r-pill);
  background: var(--danger-bg);
  color: var(--text);
  font-size: var(--fs-xs);
  font-weight: 600;
}

.failed-note .icon {
  color: var(--danger);
}

.held-note {
  margin-block-start: var(--s-1);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

/* a button: tapping it jumps to the original (§11.4) */
.reply-quote {
  display: block;
  inline-size: 100%;
  margin-block-end: var(--s-1);
  padding-block: var(--s-1);
  padding-inline: var(--s-2);
  border: 0;
  border-inline-start: 3px solid var(--accent-fg);
  border-radius: 6px;
  background: var(--surface);
  color: inherit;
  font-size: var(--fs-sm);
  text-align: start;
}

.reply-quote__who {
  display: block;
  font-weight: 650;
  color: var(--accent-fg);
}

.reply-quote__text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* on the fill only the ink is guaranteed to contrast: no tint, the ink for text and bar */
.msg--out .reply-quote {
  border-inline-start-color: currentColor;
  background: transparent;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 35%, transparent);
}

.msg--out .reply-quote__who {
  color: inherit;
}

.reactions {
  display: flex;
  gap: 2px;
  margin-block-start: -6px;
  padding-inline: var(--s-2);
  z-index: 1;
}

.reaction {
  padding-block: 1px;
  padding-inline: 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  font-size: var(--fs-sm);
}

.day-sep,
.sys-event {
  display: flex;
  justify-content: center;
  margin-block: var(--s-4) var(--s-1);
}

.day-sep span,
.sys-event span {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  padding-block: 2px;
  padding-inline: var(--s-3);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-align: center;
}

.sys-event--warn span {
  background: var(--warning-bg);
  color: var(--text);
}

.new-divider {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-block: var(--s-4) var(--s-1);
  color: var(--accent-fg);
  font-size: var(--fs-xs);
  font-weight: 700;
}

.new-divider::before,
.new-divider::after {
  content: "";
  flex: 1;
  block-size: 1px;
  background: currentColor;
  opacity: 0.4;
}

/* keeps its height while more history exists and is visible only while a page loads: showing it must not move the
   messages below it (docs/ui-review.md D27) */
.loading-older {
  display: flex;
  justify-content: center;
  padding: var(--s-3);
  color: var(--text-muted);
  visibility: hidden;
}

.loading-older--active {
  visibility: visible;
}

.loading-older:not(.loading-older--active) .spinner {
  animation: none;
}

.empty-conv {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
  margin: auto;
  padding-block: var(--s-7);
  padding-inline: var(--s-5);
  max-inline-size: 360px;
  text-align: center;
  color: var(--text-muted);
}

.empty-conv .icon {
  inline-size: 48px;
  block-size: 48px;
  color: var(--accent-fg);
}

.skeleton {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  max-inline-size: var(--col-max);
  margin-inline: auto;
  padding: var(--s-4);
}

.skeleton div {
  block-size: 40px;
  inline-size: 55%;
  border-radius: var(--r-bubble);
  background: var(--surface-2);
}

.skeleton div:nth-child(even) {
  align-self: flex-end;
  inline-size: 40%;
}

.jump-latest {
  position: absolute;
  inset-inline-end: var(--s-4);
  inset-block-end: var(--s-4);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-1);
  min-inline-size: var(--tap);
  min-block-size: var(--tap);
  padding-inline: var(--s-3);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--accent-fg);
  box-shadow: var(--shadow-2);
  font-weight: 650;
  z-index: 2;
}

/* images in bubbles; positioned for the time pill on the image (text bubbles are not: a positioned box per bubble is a
   paint layer of its own, painted again on every history page, docs/ui-review.md D27) */
.bubble--image {
  position: relative;
  padding: 4px;
}

.bubble__image {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: calc(var(--r-bubble) - 4px);
  background: var(--surface-2);
  min-inline-size: 120px;
  max-inline-size: min(64vw, 360px);
  padding: 0;
  border: 0;
}

.bubble__image img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.bubble__image .img-thumb {
  filter: blur(14px);
  transform: scale(1.1);
}

.bubble__image .progress,
.bubble__image .img-state {
  position: absolute;
}

.img-state {
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-pill);
  background: rgb(0 0 0 / 0.6);
  color: #fff;
  font-size: var(--fs-xs);
}

.bubble--image .bubble__meta,
.msg--out .bubble--image .bubble__meta {
  position: absolute;
  float: none;
  margin: 0;
  inset-block-end: 10px;
  inset-inline-end: 10px;
  padding-inline: 6px;
  border-radius: var(--r-pill);
  background: rgb(0 0 0 / 0.6);
  color: #fff;
}

/* composer */
.composer {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding-block: var(--s-2) calc(var(--s-2) + env(safe-area-inset-bottom));
  padding-inline: var(--s-2);
  background: var(--surface);
  border-block-start: 1px solid var(--border);
}

.composer__inner {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  inline-size: 100%;
  max-inline-size: var(--col-max);
  margin-inline: auto;
}

.composer__row {
  display: flex;
  align-items: flex-end;
  gap: var(--s-2);
}

/* the pill holds the emoji button, the text and the attach button */
.composer__field {
  flex: 1;
  display: flex;
  align-items: flex-end;
  min-inline-size: 0;
  border: 1px solid var(--control-border);
  border-radius: 23px;
  background: var(--bg);
}

.composer__field:has(.composer__input:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.composer__input {
  flex: 1;
  min-inline-size: 0;
  min-block-size: var(--tap);
  max-block-size: calc(6 * 1.45em + 22px);
  padding-block: 10px;
  padding-inline: var(--s-1);
  border: 0;
  background: transparent;
  color: var(--text);
  font-size: 1rem;
  line-height: 1.45;
  resize: none;
  overflow-y: auto;
}

.composer__input:focus-visible {
  outline: none;
}

.composer__emoji {
  color: var(--accent-fg);
}

.composer__panel {
  margin-inline: calc(-1 * var(--s-2));
  border-block-start: 1px solid var(--border);
  overflow: hidden;
}

.composer__send {
  background: var(--accent);
  color: var(--on-accent);
}

.composer__send:hover:not(:disabled) {
  background: var(--accent) !important;
}

.composer__send:disabled {
  background: var(--surface-2);
  color: var(--text-muted);
  opacity: 1;
}

.composer__attach {
  color: var(--accent-fg);
}

.composer__hint {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  text-align: end;
}

.composer__hint--over {
  color: var(--danger);
}

.reply-chip {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding-block: var(--s-1);
  padding-inline: var(--s-3) var(--s-1);
  border-inline-start: 3px solid var(--accent-fg);
  border-radius: 8px;
  background: var(--surface-2);
  font-size: var(--fs-sm);
}

.reply-chip__text {
  flex: 1;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.return-call {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-block-size: var(--tap);
  border: 0;
  background: var(--success);
  color: var(--on-success);
  font-weight: 650;
}

/* image viewer */
.viewer {
  display: flex;
  flex-direction: column;
  background: #000;
  color: #fff;
}

.viewer__bar {
  display: flex;
  justify-content: space-between;
  padding-block-start: env(safe-area-inset-top);
  padding-inline: var(--s-2);
}

.viewer__bar .btn {
  color: #fff;
}

.viewer__stage {
  flex: 1;
  display: grid;
  place-items: center;
  overflow: auto;
  touch-action: pinch-zoom pan-x pan-y;
}

.viewer__stage img {
  max-inline-size: 100%;
  max-block-size: 100%;
}

/* ---------- calls ---------- */
.call {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--call-bg);
  color: var(--call-text);
  z-index: 40;
}

.call__remote {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  background: #000;
}

.call__remote--contain {
  object-fit: contain;
}

.call__local {
  position: absolute;
  inline-size: min(28vw, 150px);
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: 14px;
  background: #000;
  box-shadow: 0 6px 20px rgb(0 0 0 / 0.5);
  touch-action: none;
  z-index: 3;
  inset-block-start: calc(var(--s-7) + env(safe-area-inset-top));
  inset-inline-end: var(--s-4);
}

.call__local--mirror {
  transform: scaleX(-1);
}

.call__top {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  justify-content: center;
  padding-block: calc(var(--s-3) + env(safe-area-inset-top)) var(--s-2);
  padding-inline: var(--s-3);
  z-index: 2;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  padding-block: 4px;
  padding-inline: var(--s-3);
  border-radius: var(--r-pill);
  background: rgb(18 16 18 / 0.72);
  color: var(--call-text);
  font-size: var(--fs-xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.call__center {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  padding: var(--s-5);
  text-align: center;
  z-index: 2;
}

.call__center h1 {
  font-size: var(--fs-2xl);
}

.call__status {
  color: var(--call-muted);
  font-size: var(--fs-lg);
}

.call .avatar {
  background: var(--accent);
  color: var(--on-accent);
}

.call__controls {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-2);
  padding-block: var(--s-4) calc(var(--s-5) + env(safe-area-inset-bottom));
  padding-inline: var(--s-4);
  z-index: 2;
  transition: opacity var(--dur-3) var(--ease), transform var(--dur-3) var(--ease);
}

.call--controls-hidden .call__controls,
.call--controls-hidden .call__top {
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
}

/* fixed-height icon row so every label starts on the same line, whatever the button size */
.call-btn {
  display: grid;
  grid-template-rows: 64px auto;
  justify-items: center;
  align-items: center;
  gap: var(--s-1);
  inline-size: 76px;
  font-size: var(--fs-xs);
  line-height: 1.25;
  text-align: center;
  color: var(--call-text);
}

.call-btn > span {
  align-self: start;
}

.call-btn .btn {
  inline-size: 56px;
  block-size: 56px;
  border-radius: 50%;
  background: var(--call-control);
  color: var(--call-text);
}

.call-btn .btn[aria-pressed="true"] {
  background: var(--call-text);
  color: var(--call-bg);
}

.call-btn--end .btn,
.call-btn--decline .btn {
  background: var(--danger);
  color: var(--on-danger);
}

.call-btn--accept .btn {
  background: var(--success);
  color: var(--on-success);
}

.call-btn--big .btn {
  inline-size: 64px;
  block-size: 64px;
}

.call__reconnecting {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgb(0 0 0 / 0.55);
  z-index: 4;
  font-size: var(--fs-lg);
}

.call__error {
  max-inline-size: 420px;
  padding: var(--s-4);
  border-radius: var(--r-control);
  background: var(--call-control);
  color: var(--call-text);
  text-align: start;
  font-size: var(--fs-sm);
}

@media (min-width: 600px) {
  .onb__body {
    padding-inline: var(--s-6);
  }

  .onb__actions {
    padding-inline: var(--s-6);
  }
}

@media (min-width: 900px) {
  .onb {
    justify-content: center;
    max-block-size: 860px;
    margin-block: auto;
  }

  /* on large screens the content and its actions form one centred group (the button sits under the text, not at the window edge) */
  .onb__body {
    flex: 0 1 auto;
  }

  .composer {
    padding-inline: var(--s-4);
  }

  .bubble {
    max-inline-size: min(70%, 560px);
  }
}

@media (forced-colors: active) {
  .bubble,
  .msg--out .bubble {
    border: 1px solid CanvasText;
  }

  .switch[aria-checked="true"]::after {
    background: Highlight;
  }
}

.diag__actions {
  display: grid;
  margin-block-start: var(--s-4);
}

/* ---------- chat polish: motion (§11.7), reactions (§11.2), swipe (§11.1), picker (§11.3) ---------- */
.msg--enter {
  animation: msg-in 180ms var(--ease) both;
}

@keyframes msg-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
}

.msg--beat .bubble__text {
  transform-origin: 50% 60%;
  animation: beat 900ms var(--ease) var(--fx-delay, 0ms) both;
}

@keyframes beat {
  15% {
    transform: scale(1.28);
  }

  30% {
    transform: scale(0.96);
  }

  45% {
    transform: scale(1.14);
  }

  60% {
    transform: scale(1);
  }
}

.burst {
  position: absolute;
  inset-block-end: 6px;
  color: var(--heart);
  pointer-events: none;
  z-index: 2;
}

.msg--out .burst {
  inset-inline-end: 28px;
}

.msg--in .burst {
  inset-inline-start: 28px;
}

.burst__heart {
  position: absolute;
  inset: -9px;
  inline-size: 18px;
  block-size: 18px;
  animation: burst 700ms var(--ease) var(--fx-delay, 0ms) both;
}

.burst__heart .icon {
  inline-size: 18px;
  block-size: 18px;
}

@keyframes burst {
  from {
    opacity: 1;
    transform: translate(0, 0) scale(0.3);
  }

  60% {
    opacity: 1;
  }

  to {
    opacity: 0;
    transform: translate(var(--dx), var(--dy)) scale(1);
  }
}

.msg--highlight,
.msg--fx,
.msg--swipe {
  position: relative;
}

.msg--highlight::before {
  content: "";
  position: absolute;
  inset-block: -3px;
  inset-inline: calc(-1 * var(--s-3));
  background: var(--accent-soft);
  z-index: -1;
  animation: fade-out 1200ms ease-in both;
}

@keyframes fade-out {
  to {
    opacity: 0;
  }
}

.reaction--mine {
  border-color: var(--accent-fg);
}

.jump-latest--count {
  border-color: transparent;
  background: var(--accent);
  color: var(--on-accent);
}

.swipe-reply {
  position: absolute;
  display: grid;
  place-items: center;
  inline-size: 32px;
  block-size: 32px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--accent-fg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-1), background-color var(--dur-1);
}

.swipe-reply--armed {
  background: var(--accent);
  color: var(--on-accent);
}

.swipe-reply .icon {
  inline-size: 18px;
  block-size: 18px;
}

.reaction-bar {
  display: flex;
  gap: 2px;
  padding: var(--s-1);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  box-shadow: var(--shadow-2);
  animation: pop var(--dur-1) var(--ease);
}

@keyframes pop {
  from {
    opacity: 0;
    transform: scale(0.92);
  }
}

.reaction-bar__btn,
.emoji-btn,
.emoji-picker__cat {
  display: grid;
  place-items: center;
  block-size: var(--tap);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  font-family: var(--emoji-font);
  font-size: 1.5rem;
  line-height: 1;
}

.reaction-bar__btn {
  inline-size: var(--tap);
}

.reaction-bar__btn[aria-pressed="true"],
.menu__reaction.is-current {
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 2px var(--accent-fg);
}

.reaction-bar__more {
  color: var(--accent-fg);
}

.reaction-bar__btn:hover,
.emoji-btn:hover,
.emoji-btn:focus-visible,
.emoji-picker__cat:hover {
  background: var(--surface-2);
}

.emoji-picker {
  display: flex;
  flex-direction: column;
  block-size: 100%;
  min-block-size: 0;
  background: var(--surface);
}

.emoji-picker__search {
  inline-size: auto;
  min-block-size: 40px;
  margin: var(--s-2) var(--s-2) 0;
}

.emoji-picker__cats {
  display: flex;
  overflow-x: auto;
  scrollbar-width: none;
  border-block-end: 1px solid var(--border);
}

.emoji-picker__cat {
  flex: 1 0 var(--tap);
  border-radius: 8px;
  font-size: 1.2rem;
}

.emoji-picker__scroll {
  flex: 1;
  min-block-size: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-inline: var(--s-1);
  padding-block-end: var(--s-2);
}

.emoji-section__title {
  margin: var(--s-3) var(--s-1) var(--s-1);
  font-size: var(--fs-xs);
  font-weight: 650;
  color: var(--text-muted);
}

.emoji-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--tap), 1fr));
}

.emoji-btn {
  border-radius: 8px;
  font-size: 1.6rem;
}

.emoji-picker__status {
  padding: var(--s-3);
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

.emoji-picker__status:empty {
  display: none;
}

.emoji-sheet {
  block-size: min(72dvh, 560px);
}

.emoji-sheet__inner {
  display: flex;
  flex-direction: column;
  block-size: 100%;
  padding-block-start: var(--s-4);
}

.emoji-sheet .dlg__title {
  padding-inline: var(--s-4);
  font-size: var(--fs-lg);
}

@media (prefers-reduced-motion: reduce) {
  .msg--highlight::before {
    animation: none;
  }
}
