/*
 * The Catch-Up room's stream and story circles — RoomFeed.js, FeedUnit.js,
 * PrezzPost.js, PrezzFrame.js, PrezzVotes.js, PrezzStories.js.
 *
 * Everything here lives inside `.prezzbox` (catch-up.css), so --accent is
 * PrezzBox's red and the --pb-* names are its palette. Every item in the
 * stream — a PrezzBox post, or one of Puntrr's own (the snapshot, a
 * highlight, the leaders) — is drawn the way the social feeds it is
 * modelled on draw one: edge to edge on a white band, the account on top
 * (`.feed-unit`), then what it posted — with the room's grey showing between
 * items rather than a card per item, so a scroll of them reads as one feed
 * and not as a stack of tiles or a column of sections.
 */

/* --- The stream ----------------------------------------------------------- */

.room-feed {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.room-feed__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* The head says a first page of snapshots failed, above the posts that
   carried on; the foot is the end of the stream — the next item's shape,
   a later page that failed, or the end. */
.room-feed__head,
.room-feed__foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding-inline: var(--space-4);
}

.room-feed__head:empty,
.room-feed__foot:empty {
  display: none;
}

.room-feed__note {
  margin: 0;
  padding-block: var(--space-4);
  max-width: 32ch;
  text-align: center;
  font-size: var(--text-sm);
  color: var(--pb-muted);
}

.room-feed__retry {
  min-height: var(--control-xs);
  padding: 0 var(--space-4);
  border: 1px solid var(--pb-border-strong);
  border-radius: var(--radius-full);
  background: var(--pb-surface);
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

/* The next item's shape while more of the stream is on its way — about a
   snapshot's height, the item the stream is mostly made of. */
.room-feed__skeleton {
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-lg);
  background: var(--pb-border);
  animation: prezz-pulse 1.4s var(--easing) infinite;
}

.room-feed__sentinel {
  height: 1px;
}

/* --- An item (FeedUnit.js) ------------------------------------------------ */

.feed-unit {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding-block: var(--space-4) var(--space-2);
  background: var(--pb-surface);
  border-block: 1px solid var(--pb-border);
}

.feed-unit[hidden] {
  display: none;
}

/* Puntrr's own items end on their content, with no action row under it, so
   they close with the same breathing room they open with. */
.feed-unit:not(.prezz-post) {
  padding-block-end: var(--space-4);
}

.feed-unit__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-inline: var(--space-4);
}

/* The sections inside Puntrr's items keep their own gutters (the snapshot's
   carousel track, the mini app's --cu-gutter), so the body adds none. */
.feed-unit__body {
  min-width: 0;
}

/* A single highlight is the width of the column, as a post's one chart is;
   in a row (the "more" item) the cards keep the row's width. */
.feed-unit--highlight .cu-hl {
  width: 100%;
}

/* The account's picture. On the disc, the whistle is white: PrezzBox's red
   is the brand's own app avatar (static/brand/avatar-red-*.png on
   PrezzBox); Puntrr's blue is the whistle's own colour
   (assets/puntrr-whistle.svg) — one mark, two accounts. */
.prezz-avatar {
  flex: none;
  display: grid;
  place-items: center;
  width: var(--avatar-size);
  height: var(--avatar-size);
  border-radius: var(--radius-full);
  overflow: hidden;
  background: var(--pb-surface);
}

.prezz-avatar[data-mark] {
  background: var(--pb-red);
  color: var(--pb-surface);
}

.prezz-avatar[data-mark="puntrr"] {
  /* Puntrr's brand blue, as its whistle asset carries it — a literal, like
     --pb-red: one account's livery, not a token the room re-points. */
  background: #0d4ff7;
}

.prezz-avatar__img {
  width: 100%;
  height: 100%;
  background: transparent;
  border: 0;
}

.feed-unit__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.feed-unit__line {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-width: 0;
}

.feed-unit__handle {
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--text);
}

.feed-unit__verified {
  display: inline-grid;
  place-items: center;
  color: var(--accent);
}

.feed-unit__time {
  font-size: var(--text-xs);
  color: var(--pb-muted);
  white-space: nowrap;
}

.feed-unit__time[hidden],
.feed-unit__subject[hidden] {
  display: none;
}

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

.prezz-post__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-inline: var(--space-4);
}

.prezz-post__headline {
  margin: 0;
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--text);
}

/* Folded to --caption-lines (PrezzPost.js) until "more" opens it. */
.prezz-post__caption {
  display: -webkit-box;
  margin: 0;
  overflow: hidden;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--caption-lines, 3);
}

.prezz-post__caption[data-expanded="true"] {
  display: block;
  -webkit-line-clamp: unset;
}

.prezz-post__more {
  align-self: flex-start;
  padding: 0;
  color: var(--pb-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

/* One chart takes the post's full width, edge to edge, the way a photo
   post runs: no gutter, no border, no corner — the post's own white band
   is its ground, and the chart's title lines up with the post's text. */
.prezz-post__single .prezz-frame {
  border: 0;
  border-radius: 0;
}

/* The carousel's track leaves room for card shadows above and below; the
   frames cast none, so the post keeps its own rhythm instead. */
.prezz-post__media .carousel__track {
  padding-block: 0;
}

/* Several charts: each card nearly the width of the post, with a sliver of
   the next one to say there is more (the room's peeking carousel gives 88%,
   which left the charts narrower than they needed to be). */
.prezz-post__media.carousel[data-peek="true"] .carousel__track > * {
  width: 92%;
}

/* Cards the app draws itself (an eleven, WeekTeamsPost.js `XiCard`) are the
   room's cards, not frames: they keep the carousel's room for their shadow
   and its own peek, exactly as the weekly teams' post shows them — and one
   alone sits in the gutter that post gives its single card. */
.prezz-post__media[data-native] .carousel__track {
  padding-block: var(--space-1) var(--space-3);
}

.prezz-post__media.carousel[data-native][data-peek="true"] .carousel__track > * {
  width: 88%;
}

.prezz-post__single[data-native] {
  padding-inline: var(--space-4);
  padding-block: var(--space-1) var(--space-3);
}

/* --- A chart (PrezzFrame.js) ---------------------------------------------- */

.prezz-frame {
  position: relative;
  aspect-ratio: var(--frame-aspect, 0.8);
  overflow: hidden;
  border: 1px solid var(--pb-border);
  border-radius: var(--radius-lg);
  background: var(--pb-surface);
  isolation: isolate;
}

/* Once its chart has said how tall it is (PrezzPost.js `cardHeight`), the
   card takes that height instead of the placeholder shape. */
.prezz-frame[data-sized] {
  aspect-ratio: auto;
  height: var(--frame-height);
}

.prezz-frame__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--duration) var(--easing);
}

.prezz-frame[data-state="ready"] .prezz-frame__frame {
  opacity: 1;
}

/* The room's grey with the whistle, until PrezzBox has drawn. */
.prezz-frame__veil {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--pb-bg);
  color: var(--pb-border-strong);
  transition: opacity var(--duration) var(--easing);
}

.prezz-frame[data-state="loading"] .prezz-frame__veil .prezzbox-mark {
  animation: prezz-pulse 1.4s var(--easing) infinite;
}

.prezz-frame[data-state="ready"] .prezz-frame__veil {
  opacity: 0;
  pointer-events: none;
}

/* A frame that never said it drew: the veil stays as the card's picture,
   and the iframe behind it (a refusal, an error page) is never shown. */
.prezz-frame[data-state="silent"] .prezz-frame__frame {
  visibility: hidden;
}

/* The whole card is the tap: the iframe under it takes none. */
.prezz-frame__hit {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: transparent;
  border: 0;
  border-radius: inherit;
}

.prezz-frame__hit:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: -2px;
}

/* --- Actions -------------------------------------------------------------- */

/* A post's row, and the same row under one of Puntrr's own items that has
   one (the weekly teams' Share, FeedUnit.js `actions`). */
.prezz-post__actions,
.feed-unit__actions {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding-inline: var(--space-4);
}

/* Such an item closes on its row, as a post does. */
.feed-unit.feed-unit--actions {
  padding-block-end: var(--space-2);
}

.prezz-post__action,
.feed-unit__action {
  display: grid;
  place-items: center;
  width: var(--tap-floor);
  height: var(--tap-floor);
  border-radius: var(--radius-full);
  color: var(--text);
}

.prezz-post__full {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--control-xs);
  margin-left: auto;
  padding: 0 var(--space-3);
  border-radius: var(--radius-full);
  background: var(--accent-tint);
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
}

/* --- Votes (PrezzVotes.js) -------------------------------------------------- */

/*
 * Reddit's pill: up, the score, down. At rest it is a quiet grey; once the
 * reader has voted, the whole pill takes the vote's colour and the text on
 * it goes white. Up is PrezzBox's red; down is Reddit's periwinkle, which
 * the room's palette has no word for.
 */
.prezz-vote {
  --vote-up: var(--pb-red);
  --vote-down: #6a5cff;
  display: inline-flex;
  align-items: center;
  height: var(--control-sm);
  border-radius: var(--radius-full);
  background: var(--pb-border);
  color: var(--text);
  transition:
    background-color var(--duration) ease,
    color var(--duration) ease;
}

.prezz-vote[data-mine="up"] {
  background: var(--vote-up);
  color: var(--pb-surface);
}

.prezz-vote[data-mine="down"] {
  background: var(--vote-down);
  color: var(--pb-surface);
}

.prezz-vote__arrow {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--control-sm);
  height: 100%;
  border-radius: var(--radius-full);
  color: inherit;
  transition: background-color var(--duration) ease;
}

/* The pill is drawn under the 44pt floor; the arrows' hit areas are not. */
.prezz-vote__arrow::after {
  content: "";
  position: absolute;
  inset: calc((var(--control-sm) - var(--tap-floor)) / 2) 0;
}

/* A vote cast lands with a small pop — the arrow, not the pill. */
.prezz-vote__arrow[data-pop] > .icon {
  animation: prezz-pop var(--spring-duration) var(--spring);
}

@media (hover: hover) {
  .prezz-vote__arrow:hover {
    background: rgb(var(--text-rgb) / 0.08);
  }

  /* At rest an arrow warms to its own colour under the pointer. */
  .prezz-vote[data-mine=""] .prezz-vote__arrow[data-arrow="up"]:hover {
    color: var(--vote-up);
  }

  .prezz-vote[data-mine=""] .prezz-vote__arrow[data-arrow="down"]:hover {
    color: var(--vote-down);
  }
}

.prezz-vote__score {
  min-width: 2ch;
  text-align: center;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-none);
}

/* --- Story circles (PrezzStories.js) -------------------------------------- */

.prezz-stories[hidden] {
  display: none;
}

/* --- Motion --------------------------------------------------------------- */

@keyframes prezz-pulse {
  50% {
    opacity: 0.45;
  }
}

@keyframes prezz-pop {
  40% {
    transform: scale(1.3);
  }
}

@media (prefers-reduced-motion: reduce) {
  .room-feed__skeleton,
  .prezz-frame[data-state="loading"] .prezz-frame__veil .prezzbox-mark,
  .prezz-vote__arrow[data-pop] > .icon {
    animation: none;
  }
}
