/* One "group" per sender-turn (avatar/name/timestamp shown once, one or
   more stacked bubbles inside) — matches Figma's real structure (node
   89:4819): each `type` variant is its own standalone example group, never
   chained text+photo in one call. */
/* opacity/transform transition lives here, on the base rule, not on
   --entering below — CSS picks a transition's duration/timing from the
   TARGET state's own rule, and the target when --entering is REMOVED (the
   actual moment this needs to animate) is this base rule. Putting it only
   on --entering would only apply were the class being ADDED, which happens
   synchronously before first paint and is never meant to animate. Harmless
   on every other row too: opacity/transform never change outside this one
   send-entrance case, so the always-on transition never fires elsewhere. */
.message-bubble-row {
  box-sizing: border-box;
  width: 100%;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding-top: 8px;
  padding-right: 40px;
  transition: opacity 200ms ease-out, transform 200ms ease-out;
}

.message-bubble-row--own {
  justify-content: flex-end;
  padding-right: 0;
}

/* Real-time send entrance (js/app.js's wireSendButton): the new bubble
   pops in at its own natural bottom-of-list position — not sliding down
   from above the conversation — while the scroll container animates open
   underneath it over the same 200ms, so the two together read as "the
   message appears at the bottom, then the whole chat lifts to reveal it."
   Toggled via class on the persisting node (added, then removed one frame
   later), never re-rendered, so the transition actually plays. No Figma
   reference for this — it's a live, in-memory-only send, out of scope for
   the designed screens — so both the motion and the 200ms duration are
   authored by me, per explicit instruction. */
.message-bubble-row--entering {
  opacity: 0;
  transform: translateY(10px);
}

.message-bubble-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  max-width: 224px;
}

.message-bubble-group--own {
  align-items: flex-end;
  max-width: 260px;
}

.message-bubble-group__bubbles {
  display: flex;
  flex-direction: column;
  align-items: inherit;
  gap: 6px;
  width: 100%;
}

/* display:table (not the default block, still with width:fit-content/
   max-width:100%) — for MULTI-line wrapped text, fit-content's own sizing
   algorithm only checks whether the content fits on ONE line; once it
   needs to wrap at all, fit-content just falls back to the full max-width
   rather than finding the narrowest box that still wraps into the same
   number of lines, so a two-line message ends up stretched edge-to-edge
   even when neither line actually needs that much room. table's shrink-to-
   fit layout algorithm does solve for that narrower width properly. Doesn't
   affect single-line bubbles (already tight either way) or the --photo
   variant below (fixed 224px, untouched). */
.message-bubble__bubble {
  box-sizing: border-box;
  display: table;
  width: fit-content;
  max-width: 100%;
  border-radius: 12px;
  padding: 10px 12px 12px;
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: var(--message-bubble-glass-blur);
  -webkit-backdrop-filter: var(--message-bubble-glass-blur);
}

.message-bubble-row--own .message-bubble__bubble {
  background: rgba(0, 0, 0, 0.5);
}

.message-bubble__name {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 700;
  font-size: 15px;
  line-height: 20px;
  letter-spacing: -0.15px;
  margin-bottom: 2px;
}

.message-bubble__text {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 400;
  font-size: 15px;
  line-height: 1.4;
  letter-spacing: -0.3px;
  color: var(--text-primary);
  white-space: pre-wrap;
}

.message-bubble-row--own .message-bubble__text {
  color: var(--text-invert-white);
}

.message-bubble__time {
  font-family: "Ubuntu", sans-serif;
  font-weight: 700;
  font-style: italic;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-secondary);
}

.message-bubble__bubble--photo {
  padding: 6px;
  width: 224px;
}

/* Explicit correction: the vertical/portrait photo must be the same size
   on both sides, capped at 212px (224px bubble minus 6px padding each
   side, same as the landscape grid variant above) — not scaled to each
   side's own group max-width (224 other / 260 own), which is what an
   earlier version did from node 455:10815's own-side max-w-[260px]. */
.message-bubble__bubble--photo-vertical {
  display: block;
  padding: 6px;
  width: 224px;
}

/* Real fetched shape (node 447:10749 "Other" / 447:10681 "Own") — overrides
   the base bubble's display:table/padding (both are for the plain-text
   layout only), stacking the quote preview above the reply's own content
   with the real fetched 6px padding/gap. The outer background itself is
   untouched (this modifier adds no background of its own) — both fetched
   variants' outer bubble colors already exactly match the existing
   own/other split above. */
.message-bubble__bubble--reply {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 6px;
}

.message-bubble__quote {
  box-sizing: border-box;
  width: 100%;
  max-width: 224px;
  border-radius: 8px;
  padding: 4px 6px 6px;
  background: rgba(255, 255, 255, 0.2);
  overflow: hidden;
}

.message-bubble__quote-name {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 700;
  font-size: 12px;
  line-height: 20px;
  letter-spacing: -0.12px;
}

.message-bubble__quote-text {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 400;
  font-size: 12px;
  line-height: 1.4;
  letter-spacing: -0.24px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 200px;
}

.message-bubble__reply-content {
  box-sizing: border-box;
  width: 100%;
  padding: 6px;
}

.message-bubble__photo-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
}

/* A lone photo takes Figma's landscape aspect and spans both columns —
   there's no pure 1-photo example in the fetched variants (every real
   Figma state shows >=2 tiles), so this is a reasonable generalization of
   the same grid system rather than a fabricated Figma value.
   Explicit px height, not aspect-ratio — aspect-ratio on a grid item
   inside a `1fr` track asks the browser to resolve a circular sizing
   dependency (the track's width feeds the item's aspect-ratio height,
   but track sizing can also consider the item's own preferred size), and
   mobile WebKit was resolving that differently than desktop, rendering
   these cells at an inconsistent size — a different object-fit:cover
   crop window on the same source photo, and a taller-than-intended grid
   leaving a gap before the caption below it. 224px bubble width, 6px
   padding, 6px gap, 2 columns: (224 - 2*6 - 6) / 2 = 103px per cell,
   deterministic in any browser. */
.message-bubble__photo-grid--1 .message-bubble__photo {
  grid-column: span 2;
  height: 159px;
}

.message-bubble__photo-grid--2 .message-bubble__photo,
.message-bubble__photo-grid--3 .message-bubble__photo,
.message-bubble__photo-grid--4 .message-bubble__photo {
  height: 103px;
}

.message-bubble__photo {
  position: relative;
  border-radius: 8px;
  overflow: hidden;
}

/* Matches the real photo's own 477x636 proportions (3:4) exactly, so
   object-fit:cover above shows the whole image with no actual crop —
   not a grid item (js/components/message-bubble.js's own
   messageBubbleVerticalPhotoBody), so aspect-ratio here doesn't hit the
   circular grid-track sizing bug documented on .message-bubble__photo-
   grid--1 above. */
.message-bubble__photo--vertical {
  width: 100%;
  aspect-ratio: 3 / 4;
}

.message-bubble__photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.message-bubble__photo--blurred .message-bubble__photo-img {
  filter: blur(2px);
}

/* ::after generated content paints after all of an element's real DOM
   children (per spec), so without a z-index it sat ON TOP of the real
   .message-bubble__photo-overlay child below — the dark tint was painting
   over the white "+N" text instead of behind it, muddying it. z-index:1 on
   the overlay (its parent .message-bubble__photo is already position:relative,
   so this is a real stacking comparison, not a no-op) puts the text back on
   top where Figma shows it. */
.message-bubble__photo--blurred::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(39, 6, 65, 0.8);
}

.message-bubble__photo-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Ubuntu", sans-serif;
  font-weight: 700;
  font-style: italic;
  font-size: 24px;
  letter-spacing: -0.48px;
  color: var(--text-primary);
}

/* Real total: 18px above the name/text, 6px on its left/right/bottom,
   matching every fetched photo-message variant (nodes 89:4837, 109:2289,
   106:2079, 231:13372) — was padding-top only, so the caption's own
   left/right/bottom padding was silently missing and it sat flush against
   the bubble's outer 6px edge instead of properly inset. */
.message-bubble__caption {
  padding: 18px 6px 6px;
}
