/* =====================================================================
   WHEN TO EDIT THIS FILE  (read before adding anything)

   Tailwind on the JSX is the default. This stylesheet is the escape hatch
   for what Tailwind can't reach. DO NOT append new rules to the bottom by
   reflex — most styling belongs on the element in JSX, not here.

   Before adding a rule, ask: "Am I styling our own JSX with plain
   utilities (flex/grid, gap, padding, font, color, radius)?"
     → YES: put Tailwind classes on that element. Nothing goes here.
     → NO, because one of the following: add it here, grouped with the
       related block (never at EOF).

   Legitimate reasons a style lives HERE, not in Tailwind:
   1. It targets stream-chat-react's internal DOM (`.str-chat__*`). We don't
      render that markup, so there's no JSX to put a class on.
   2. Tailwind can't express it: `::before`/`::after` generated content,
      `::backdrop`, `@starting-style`, top-layer dialog transitions, layered
      `backdrop-filter` masks/gradients, SVG-mask data URIs, `oklch(from …)`
      relative color, or gnarly `:has()`/compound-state selectors.

   NOT reasons to add a rule here:
   - "It has variants / state." A variant matrix is plain Tailwind — resolve
     the class list per case in JSX (see the chatbot indicator in
     MessageTag.tsx: base string + a ternary over the resolved variant).
   - "A test asserts on the class name." Don't keep styling-only classes as
     test hooks. Assert on behavior instead — visible copy, roles, child
     order, or a `data-*` attribute — and style with Tailwind.
   - "It must render for a consumer that doesn't scan our source." This
     package REQUIRES consumers to include it in their Tailwind `content` glob
     (see the README's Styling section); JSX utilities — including the
     media-viewer lightbox chrome — depend on that. We don't duplicate
     load-bearing chrome into CSS to sidestep the requirement.

   #gotcha — why Tailwind-on-JSX isn't automatic here: this file has no
   `@tailwind` directives, so the shipped `dist/assets/index.css` contains
   ONLY these hand-written rules (plus the stream import) — NO Tailwind
   utilities. Utility classes in our JSX render only because the consumer's
   Tailwind build scans our `src`/`dist` (a documented requirement). Only the
   reason-#1/#2 rules above ship unconditionally.

   When you DO move a rule to Tailwind: prefer `text-[12px]` over `text-xs`
   when the source sets font-size without a matching line-height — Tailwind's
   `text-xs`/`text-sm` also set line-height and will silently change it.
   ===================================================================== */

/* Stream Chat base styles */
@import 'stream-chat-react/dist/css/v2/index.css';

.str-chat {
  interpolate-size: allow-keywords;

  /* Inherit the host's font instead of stream-chat-react's hardcoded system stack.
   In admin (federation host) this resolves to Link Sans; on linktr.ee profile
   pages it resolves to the creator's profile font. */
  --str-chat__font-family: inherit;

  --str-chat__message-bubble-border-radius: 1.5rem;
  --str-chat__message-bubble-background-color: #f1f0ee;
  --str-chat__message-bubble-color: #000000;

  --str-chat__own-message-bubble-background-color: #1e2330;
  --str-chat__own-message-bubble-color: #fff;
}

/* Channel-header starred badge: grow the name pill open when the star appears.
   @starting-style animates width 0 → auto on insertion (enter only — unstar
   removes the node, which snaps). Chrome/Edge 129+; elsewhere it just appears. */
.messaging-header-star-badge {
  width: calc-size(auto, size);
  transition: width 250ms;
}
@starting-style {
  .messaging-header-star-badge {
    width: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .messaging-header-star-badge {
    transition: none;
  }
}

.messaging-channel-message-list--floating .str-chat__message-list-scroll {
  padding-bottom: calc(var(--messaging-composer-height, 9rem) + 1.25rem);
}

/* Chat-area side gutter. Figma's `chat-area` frame is `pad 16/32/16/32` across
   every desktop attachment frame (`1962:24885`, `1973:12771`, `2032:22657` and
   five more), so the gutter is a flat 32px.

   stream-chat-react does set an inline padding, and it is neither absent nor
   8px on desktop: `.str-chat__list .str-chat__message-list-scroll` is
   `padding: 0 var(--str-chat__spacing-2)` (8px) at base, then
   `padding: 0 min(var(--str-chat__spacing-10), 4%)` inside
   `@media only screen and (min-device-width: 768px)` — which measures 40px on
   any screen wide enough for the 2.5rem cap to win. So this rule *narrows*
   40px to the specified 32px; it does not add spacing where there was none.

   Both stream selectors are two-class, i.e. specificity (0,2,0). A bare
   `.str-chat__message-list-scroll` is (0,1,0) and loses outright, so the
   ancestors below are load-order-independent and deliberate — the same
   technique, for the same reason, as the bubble-radius block further down.

   Each `.str-chat__li` carries `margin-inline: calc(-1 * <that padding>)` plus
   an equal `padding-inline`, which cancel exactly, so content lands on the
   container's padding edge and rows can still paint full-bleed. Nothing here
   needs to compensate for it.

   Deliberately keyed to viewport width while stream keys to *device* width.
   A real 393px phone keeps stream's 8px base, matching the 393px frames; only
   a desktop window narrowed below 767px keeps 40px, which is stream's quirk
   and not worth a second override. Those frames are admin mobile-web anyway,
   and this stylesheet also dresses the visitor sheet in linktr.ee-profiles,
   whose spacing comes from a different Figma page.
   Block padding is untouched — the floating rule above owns padding-bottom. */
@media (min-width: 767px) {
  .str-chat .str-chat__list .str-chat__message-list-scroll {
    padding-inline: 32px;
  }
}

.messaging-composer-chrome--floating {
  position: relative;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 20;
}

.messaging-channel-layout > .messaging-composer-chrome--floating {
  position: absolute;
}

.messaging-composer-chrome--floating .messaging-composer-backdrop {
  position: absolute;
  inset: 0;
  overflow: hidden;
  isolation: isolate;
  pointer-events: none;
}

.messaging-composer-backdrop-blur {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Figma progressive background blur: (50%, 0%) → (50%, 100%), 0 → 16.
   CSS has no spatially-varying blur, so five evenly spaced masked layers
   approximate the linear ramp across the full parent height. */
.messaging-composer-backdrop-blur:nth-child(1) {
  --messaging-composer-blur-mask: linear-gradient(
    to bottom,
    transparent 0%,
    black 20%,
    transparent 40%
  );
  backdrop-filter: blur(3.2px);
  -webkit-backdrop-filter: blur(3.2px);
  mask: var(--messaging-composer-blur-mask);
  -webkit-mask: var(--messaging-composer-blur-mask);
}

.messaging-composer-backdrop-blur:nth-child(2) {
  --messaging-composer-blur-mask: linear-gradient(
    to bottom,
    transparent 20%,
    black 40%,
    transparent 60%
  );
  backdrop-filter: blur(6.4px);
  -webkit-backdrop-filter: blur(6.4px);
  mask: var(--messaging-composer-blur-mask);
  -webkit-mask: var(--messaging-composer-blur-mask);
}

.messaging-composer-backdrop-blur:nth-child(3) {
  --messaging-composer-blur-mask: linear-gradient(
    to bottom,
    transparent 40%,
    black 60%,
    transparent 80%
  );
  backdrop-filter: blur(9.6px);
  -webkit-backdrop-filter: blur(9.6px);
  mask: var(--messaging-composer-blur-mask);
  -webkit-mask: var(--messaging-composer-blur-mask);
}

.messaging-composer-backdrop-blur:nth-child(4) {
  --messaging-composer-blur-mask: linear-gradient(
    to bottom,
    transparent 60%,
    black 80%,
    transparent 100%
  );
  backdrop-filter: blur(12.8px);
  -webkit-backdrop-filter: blur(12.8px);
  mask: var(--messaging-composer-blur-mask);
  -webkit-mask: var(--messaging-composer-blur-mask);
}

.messaging-composer-backdrop-blur:nth-child(5) {
  --messaging-composer-blur-mask: linear-gradient(
    to bottom,
    transparent 80%,
    black 100%
  );
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  mask: var(--messaging-composer-blur-mask);
  -webkit-mask: var(--messaging-composer-blur-mask);
}

.messaging-composer-backdrop-gradient {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(251, 250, 249, 0) 0%,
    #fbfaf9 100%
  );
}

/* Dialog component styles - used by messaging components */
/* Note: Dialogs get moved to the top layer when opened with .showModal() */
.mes-dialog {
  --transition-duration: 0.2s;

  border: none;
  padding: 0;
  margin: 0;
  background: transparent;
  max-height: 100vh;
  width: 100%;
  height: 100vh;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: auto;

  /* Mobile: full width */
  max-width: 100%;

  /* Desktop (md and up): constrained width respecting sidebar */
  @media (min-width: 767px) {
    max-width: min(500px, calc(100% - var(--sidebar-width, 0px)));
  }

  /* Transitions for slide-in effect */
  transition:
    translate var(--transition-duration) cubic-bezier(0.4, 0, 0.2, 1),
    overlay var(--transition-duration) allow-discrete,
    display var(--transition-duration) allow-discrete;

  /* Start off-screen to the right */
  translate: 100% 0;
}

.mes-dialog[open] {
  translate: 0 0;
}

.mes-dialog::backdrop {
  transition:
    display var(--transition-duration) allow-discrete,
    overlay var(--transition-duration) allow-discrete,
    background-color var(--transition-duration) linear;
  background-color: rgba(0, 0, 0, 0);
}

.mes-dialog[open]::backdrop {
  background-color: rgba(0, 0, 0, 0.5);
}

/* Starting style for smooth entry animation */
@starting-style {
  .mes-dialog[open] {
    translate: 100% 0;

    &::backdrop {
      background-color: rgba(0, 0, 0, 0);
    }
  }
}

/* Full-screen media viewer dialog (ImageViewer / VideoViewer / PdfViewer).
   Only the `<dialog>` surface, backdrop, and open/close transitions live here
   — they use `::backdrop` / `@starting-style`, which Tailwind can't express.
   The chrome inside (buttons, counter, body, media) is Tailwind on the JSX. */
.mes-media-viewer {
  --transition-duration: 0.15s;

  border: none;
  padding: 0;
  margin: 0;
  background: transparent;
  color: white;
  width: 100vw;
  height: 100dvh;
  max-width: 100vw;
  max-height: 100dvh;
  position: fixed;
  inset: 0;
  overflow: hidden;

  transition:
    opacity var(--transition-duration) ease,
    overlay var(--transition-duration) allow-discrete,
    display var(--transition-duration) allow-discrete;

  opacity: 0;
}

.mes-media-viewer[open] {
  opacity: 1;
}

.mes-media-viewer::backdrop {
  transition:
    display var(--transition-duration) allow-discrete,
    overlay var(--transition-duration) allow-discrete,
    background-color var(--transition-duration) linear;
  background-color: rgba(0, 0, 0, 0);
}

.mes-media-viewer[open]::backdrop {
  background-color: rgba(0, 0, 0, 0.92);
}

@starting-style {
  .mes-media-viewer[open] {
    opacity: 0;

    &::backdrop {
      background-color: rgba(0, 0, 0, 0);
    }
  }
}

/* Textarea composer focus styles */
.mes-textarea-composer-container:has(.mes-textarea-composer:focus) {
  outline: 2px solid black;

  .mes-textarea-composer {
    outline: none;
  }
}

/* Custom Stream Chat message bubble styles */

.str-chat__channel {
  background-color: transparent;
}

.str-chat__message.str-chat__message--me {
  .str-chat__attachment-list .str-chat__message-attachment--card {
    color: white;
  }
}

.str-chat__unread-messages-separator {
  background-color: transparent;
}

.str-chat__date-separator-line {
  display: none;
}

.str-chat__date-separator {
  font-size: 0.75rem;

  .str-chat__date-separator-date {
    margin: 0 auto;
  }
}

.str-chat__list {
  background: transparent;
}

.str-chat__li .str-chat__message--me {
  position: relative;
}

.str-chat__li .str-chat__message-inner {
  grid-column-gap: 4px;
}

/* Outer grid for other (incoming) messages — add footer row after message */
.str-chat__li .str-chat__message--other {
  grid-template-areas:
    '. message-reminder'
    'avatar message'
    '. footer'
    '. replies'
    '. translation-notice'
    '. custom-metadata'
    '. metadata';
  grid-template-columns: 28px 1fr;
  justify-items: flex-start;

  /* Reserve ~1/6 of the channel width on the open side of text-only bubbles
     (MES-1278). Scoped to messages with a single `.str-chat__message-bubble`
     that carries `.str-chat__message-text` — other media still use fixed
     widths and need to go fluid before the same spacing can apply generally. */
  &:has(.str-chat__message-bubble:only-child .str-chat__message-text) {
    padding-inline-end: calc(100% / 6);
  }
}

.str-chat__message.str-chat__message--other {
  column-gap: 0.25rem;
}

/* Outer grid for me (outgoing) messages — footer + delivery-status rows
   after message. `delivery-status` carries the "Delivered" receipt on the
   last sent message (MES-1036); the row collapses to 0 height on messages
   that don't render it. */
.str-chat__li .str-chat__message--me {
  --sent-message-delivery-status-font-size: 11px;
  grid-template-areas:
    'message-reminder'
    'message'
    'footer'
    'delivery-status'
    'replies'
    'translation-notice'
    'custom-metadata'
    'metadata';
  justify-items: end;

  /* Same open-side reserve as --other (see above). */
  &:has(.str-chat__message-bubble:only-child .str-chat__message-text) {
    padding-inline-start: calc(100% / 6);
  }
}

/* Avatar: proper grid item aligned to bottom of its row */
.str-chat__li .str-chat__message--other .str-chat__message-sender-avatar {
  grid-area: avatar;
  align-self: end;
}

/* message-inner sits in the message grid area */
.str-chat__li .str-chat__message-inner {
  grid-area: message;
}

/* Inner grid: bubble beside options only (no footer row) */
.str-chat__li .str-chat__message--other .str-chat__message-inner {
  grid-template-areas: 'message-bubble options';
  grid-template-columns: auto auto;
}

.str-chat__li .str-chat__message--me .str-chat__message-inner {
  grid-template-areas: 'options message-bubble';
  grid-template-columns: auto auto;
}

/* Bubble wrapper occupies the message-bubble grid area */
.str-chat__li .str-chat__message-inner > .str-chat__message-bubble-wrapper {
  grid-area: message-bubble;
}

/* Actions button centers vertically with the bubble */
.str-chat__li .str-chat__message-inner .str-chat__message-options {
  align-self: center;
}

/* Footer: tag then vote buttons stacked, in outer grid footer area */
.str-chat__li .str-chat__message-footer {
  grid-area: footer;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.str-chat__li .str-chat__message--other .str-chat__message-footer {
  align-items: flex-start;
}

.str-chat__li .str-chat__message--me .str-chat__message-footer {
  align-items: flex-end;
}

/* Message delivery status under sent messages (MES-1036/MES-1296).
   `SentMessageDeliveryStatus` renders stream's `.str-chat__message-status`
   directly when there is no outbound label. When an outbound label is
   present, `.sent-message-status-row` is the grid item and contains the
   stream status span. Both cases are right-aligned via the outer grid's
   `justify-items: end`; stream's empty status span collapses when no state is
   active (i.e. not the last sent message). */
.str-chat__li .str-chat__message--me .str-chat__message-status {
  grid-area: delivery-status;
  justify-content: flex-end;
  gap: 4px;
  padding-block-start: 4px;
  padding-inline-end: 16px;
  font-size: var(--sent-message-delivery-status-font-size);
  line-height: 1.4;
  color: var(--str-chat__text-low-emphasis-color, rgba(0, 0, 0, 0.5));
}
.str-chat__li .str-chat__message--me .sent-message-status-row {
  --sent-message-outbound-badge-color: var(
    --str-chat__message-outbound-badge-color,
    #ed007c
  );
  --sent-message-outbound-name-color: var(
    --str-chat__message-outbound-name-color,
    rgba(4, 4, 3, 0.898)
  );
  display: inline-flex;
  grid-area: delivery-status;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  padding-block-start: 4px;
  padding-inline-end: 16px;
  font-size: var(--sent-message-delivery-status-font-size);
  line-height: 1.4;
  color: var(--str-chat__text-low-emphasis-color, rgba(0, 0, 0, 0.5));
}
.str-chat__li
  .str-chat__message--me
  .sent-message-status-row
  .str-chat__message-status {
  grid-area: auto;
  justify-content: inherit;
  gap: inherit;
  padding: 0;
  font: inherit;
  line-height: inherit;
  color: inherit;
}
.str-chat__li .str-chat__message-status:empty {
  display: none;
}
/* Match the check icon to the label size/colour (overrides stream's default
   per-state icon sizing and status-colour fill). */
.str-chat__li .str-chat__message--me .str-chat__message-status svg {
  width: 14px;
  height: 14px;
}
.str-chat__li .str-chat__message--me .str-chat__message-status svg path {
  fill: currentColor;
}
.str-chat__li .str-chat__message--me .sent-message-status-row svg {
  width: 14px;
  height: 14px;
}
.str-chat__li .str-chat__message--me .sent-message-status-row svg path {
  fill: currentColor;
}
.str-chat__li
  .str-chat__message--me
  .sent-message-status-row
  .sent-message-outbound-badge {
  display: inline-flex;
  width: 16px;
  height: 16px;
  align-items: center;
  justify-content: center;
  flex: 0 0 16px;
  border-radius: 50%;
  background: var(--sent-message-outbound-badge-color);
  color: #fff;
}
.str-chat__li
  .str-chat__message--me
  .sent-message-status-row
  .sent-message-outbound-badge
  svg {
  width: 10px;
  height: 10px;
}
.str-chat__li
  .str-chat__message--me
  .sent-message-status-row
  .sent-message-outbound-badge
  svg
  path {
  fill: currentColor;
}
.str-chat__li
  .str-chat__message--me
  .sent-message-status-row
  .sent-message-outbound-name {
  color: var(--sent-message-outbound-name-color);
}
.str-chat__li .str-chat__message--me .sent-message-status--failed {
  color: var(--str-chat__message-error-color, #d92d20);
}

/* Channel list load-more button overrides */
.str-chat__channel-list .str-chat__load-more-button__button {
  background-color: #121110;
  color: #fff;
  border-radius: 0.75rem;
  padding-inline: 1rem;
  font-size: 0.875rem;
  height: 40px;
}

.str-chat__channel-list .str-chat__load-more-button__button:disabled {
  background-color: #121110;
  color: #fff;
}

.str-chat__channel-list-react .str-chat__channel-list-messenger-react {
  padding: 0;
}

.str-chat__message
  .str-chat__message-inner
  .str-chat__message-bubble
  .str-chat__message-text {
  padding: 0.75rem 1rem;
}

.str-chat__message .str-chat__message-bubble {
  font-size: 0.875rem;
  line-height: 1.3125rem;
  letter-spacing: 0.14px;
}

/* Keep every bubble a full pill regardless of its position in a same-author
   run. stream-chat-react's default theme flattens the inner corners of
   grouped bubbles (bottom-/top-inline-end for `--me`, inline-start for
   `--other`) via `.str-chat__li--{top,middle,bottom} .str-chat__message--{me,other}
   .str-chat__message-bubble` rules at specificity (0,3,0). We prepend the
   `.str-chat` root class to reach (0,4,0) so this wins independently of
   stylesheet load order and restores the fully-rounded pill from the Figma
   spec — only the trailing bubble's rendered `MessageTail` breaks the pill. */
.str-chat
  .str-chat__li--single
  .str-chat__message--me
  .str-chat__message-bubble,
.str-chat .str-chat__li--top .str-chat__message--me .str-chat__message-bubble,
.str-chat
  .str-chat__li--middle
  .str-chat__message--me
  .str-chat__message-bubble,
.str-chat
  .str-chat__li--bottom
  .str-chat__message--me
  .str-chat__message-bubble,
.str-chat
  .str-chat__li--single
  .str-chat__message--other
  .str-chat__message-bubble,
.str-chat
  .str-chat__li--top
  .str-chat__message--other
  .str-chat__message-bubble,
.str-chat
  .str-chat__li--middle
  .str-chat__message--other
  .str-chat__message-bubble,
.str-chat
  .str-chat__li--bottom
  .str-chat__message--other
  .str-chat__message-bubble {
  border-radius: var(--str-chat__message-bubble-border-radius);
}

/* Chatbot reply markdown — restore semantics that consumer Tailwind preflight
   (or other resets) strip from the body of `.str-chat__message-text-inner`. */
.str-chat__message-text-inner :where(h1, h2, h3, h4, h5, h6) {
  font-weight: 600;
  margin: 0.5rem 0 0.25rem;
  line-height: 1.3;
  text-wrap: balance;
}
.str-chat__message-text-inner h1 {
  font-size: 1.5rem;
}
.str-chat__message-text-inner h2 {
  font-size: 1.25rem;
}
.str-chat__message-text-inner h3 {
  font-size: 1.0625rem;
}
.str-chat__message-text-inner :where(h1, h2, h3, h4, h5, h6):first-child {
  margin-top: 0;
}
/* Bold. Consumer Tailwind preflight resets `b, strong` to `font-weight: bolder`,
   which computes to 700 against the regular body and over-bolds relative to the
   design's emphasized weight — pin it to 500 (medium). */
.str-chat__message-text-inner :where(b, strong) {
  font-weight: 500;
}

.str-chat__message-text-inner ul {
  list-style-type: disc;
  padding-inline-start: 1.25rem;
  margin: 0.25rem 0;
}
.str-chat__message-text-inner ol {
  list-style-type: decimal;
  padding-inline-start: 1.25rem;
  margin: 0.25rem 0;
}
.str-chat__message-text-inner li {
  display: list-item;
  margin: 0.125rem 0;
}
.str-chat__message-text-inner ul ul,
.str-chat__message-text-inner ol ol,
.str-chat__message-text-inner ul ol,
.str-chat__message-text-inner ol ul {
  margin: 0;
}

.str-chat__message-text-inner a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.15em;
  word-break: break-word;
}

/* Keep mentions readable by inheriting the message bubble's ink color. */
.str-chat__message-text-inner .str-chat__message-mention {
  color: inherit;
}

.str-chat__message
  .str-chat__message-inner
  .str-chat__message-bubble
  .str-chat__message-text
  .str-chat__message-text-inner
  p,
.str-chat__quoted-message-preview
  .str-chat__message-inner
  .str-chat__message-bubble
  .str-chat__message-text
  .str-chat__message-text-inner
  p {
  margin: 0;
}

.str-chat__message
  .str-chat__message-inner
  .str-chat__message-bubble
  .str-chat__message-text
  .str-chat__message-text-inner
  > p:first-child,
.str-chat__quoted-message-preview
  .str-chat__message-inner
  .str-chat__message-bubble
  .str-chat__message-text
  .str-chat__message-text-inner
  > p:first-child {
  margin-top: 0;
}

.str-chat__message
  .str-chat__message-inner
  .str-chat__message-bubble
  .str-chat__message-text
  .str-chat__message-text-inner
  > p:last-child,
.str-chat__quoted-message-preview
  .str-chat__message-inner
  .str-chat__message-bubble
  .str-chat__message-text
  .str-chat__message-text-inner
  > p:last-child {
  margin-bottom: 0;
}

.str-chat__message-text-inner p {
  text-wrap: pretty;
}
.str-chat__message-text-inner > :first-child {
  margin-top: 0;
}
.str-chat__message-text-inner > :last-child {
  margin-bottom: 0;
}

/* Trailing bubble of a same-author run gets extra spacing. The bubble tail
   itself is now a rendered `MessageTail` element (see CustomMessage /
   StreamAttachmentMessage), not a pseudo-element. */
.str-chat__li--single .str-chat__message,
.str-chat__li--bottom .str-chat__message {
  margin-block-end: 0.875rem;
}

/* Derived accent surface for `LinkAttachment` cards. `--accent` is the raw
   colour extracted from the attachment image; the card keeps its hue and swaps
   the lightness to this side's `--surface-l` stop. Only paints where the browser
   resolves relative colour syntax and an accent is set — otherwise the card's
   `bg-[…]` fallback fill shows through. The stops clear 4.5:1 against each side's
   ink at every hue.

   `[data-variant]` is repeated in the accent selector purely for specificity:
   the `bg-[…]` fallback is a consumer-generated Tailwind utility, and a consumer
   that scopes its utilities under a wrapper class (e.g. admin's `.mes`) emits it
   as `.mes .bg-[…]` at (0,2,0) — tying a bare `.messaging-link-card[style*=…]`
   and, loading later, winning. The extra attribute lifts this rule to (0,3,0) so
   the accent reliably outranks one scoping ancestor. */
.messaging-link-card[data-variant='dark'] {
  --surface-l: 0.3;
}
.messaging-link-card[data-variant='light'] {
  --surface-l: 0.9;
}

@supports (background: oklch(from red l c h)) {
  .messaging-link-card[style*='--accent'][data-variant] {
    background: oklch(from var(--accent) var(--surface-l) c h);
  }
}

/* Bubble tail for `LinkAttachment` cards. Same 20x23 geometry and mask path as
   the text-bubble tails above; the fill is the card's accent surface, derived
   below from its own `--accent`.

   Hand-written here rather than as a toolkit-only Tailwind utility on purpose:
   `styles.css` ships as a built stylesheet that every consumer imports, whereas
   a utility declared only in this package's tailwind config compiles to nothing
   against a consumer's theme, silently. */
.messaging-link-card-tail {
  position: absolute;
  inset-block-end: 0;
  inset-inline-end: calc(-1 * 0.3125rem);
  /* Behind the card: the inner 15px of the mask tucks under the card's own
     opaque background and only the outward curve shows. Negative z-index
     paints below in-flow block backgrounds, which is what makes the seam
     disappear. */
  z-index: -1;
  width: 1.25rem;
  height: 1.4375rem;
  pointer-events: none;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='23' fill='none'%3E%3Cpath fill='black' d='M0 0H15C15 10.1934 15.859 15.2345 19.168 21.4893C19.527 22.168 19.039 22.9917 18.274 22.9178C5.176 21.6506 0.32 6.0737 0 0Z'/%3E%3C/svg%3E")
    no-repeat center / 100% 100%;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='23' fill='none'%3E%3Cpath fill='black' d='M0 0H15C15 10.1934 15.859 15.2345 19.168 21.4893C19.527 22.168 19.039 22.9917 18.274 22.9178C5.176 21.6506 0.32 6.0737 0 0Z'/%3E%3C/svg%3E")
    no-repeat center / 100% 100%;
}

.messaging-link-card-tail--received {
  inset-inline-end: auto;
  inset-inline-start: calc(-1 * 0.3125rem);
  transform: scaleX(-1);
  transform-origin: center;
}

/* The tail paints outside the shell's box, so it can't inherit the shell's
   computed background — it runs the same derivation itself off its own
   `--accent`, and falls back to this side's plain bubble fill. Keep these fills
   in sync with the shell's `bg-[…]` classes and the `--str-chat` bubble vars. */
.messaging-link-card-tail[data-variant='dark'] {
  --surface-l: 0.3;
  background-color: #1e2330;
}
.messaging-link-card-tail[data-variant='light'] {
  --surface-l: 0.9;
  background-color: #f1f0ee;
}

@supports (background: oklch(from red l c h)) {
  .messaging-link-card-tail[style*='--accent'] {
    background-color: oklch(from var(--accent) var(--surface-l) c h);
  }
}

/* Locked attachment wrapper: stack card + text bubble in the correct direction */
.str-chat__li .str-chat__message--me .str-chat__message-bubble-wrapper {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

.str-chat__li .str-chat__message--other .str-chat__message-bubble-wrapper {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

/* Gap between a wrapper's stacked bubbles (e.g. StreamAttachmentMessage's
   media + caption, MediaMessage's card + text) */
.str-chat__message-bubble-wrapper
  > .str-chat__message-bubble:not(:first-child) {
  margin-top: 4px;
}

/* Tighter gap for the locked-attachment card + text bubble and the tip
   pill + text bubble — same margin-top mechanism, smaller value. Must come
   after the rule above: equal specificity, so source order decides. */
.message-locked-attachment-wrapper
  > .str-chat__message-bubble:not(:first-child),
.message-tip-wrapper > .str-chat__message-bubble:not(:first-child) {
  margin-top: 2px;
}

/** Remove padding from the text inside the locked attachment text shell,
    and inherit TextShell's explicit colour — stream-chat-react's own
    `MessageText` sets its own (black) colour that only gets overridden by
    `.str-chat`'s CSS vars, which the Composer preview doesn't have. */
.message-locked-attachment-text .str-chat__message-text {
  padding: 0rem !important;
}

.message-locked-attachment-text .str-chat__message-text-inner {
  color: inherit;
}
