/* ==========================================================================
   UPDATES — the ring, the tray, the composer, the player
   Tokens declared locally: this file is used on pages that may or may not
   carry .page-cmp, and an undefined custom property invalidates the whole
   declaration silently. That has cost three bugs in this project already.
   ========================================================================== */
.upWrap, .upNew, .upView {
  --cmx-hair:  rgb(255 255 255 / .09);
  --cmx-pane:  rgb(255 255 255 / .04);
  --cmx-pane2: rgb(255 255 255 / .07);
}

/* ── THE RING ───────────────────────────────────────────────────────────────
   Wraps ANY avatar, anywhere. Padding plus a gradient border rather than an
   outline, because an outline cannot hold a gradient and a box-shadow ring
   cannot have a gap between it and the photo — and the gap is what makes it
   read as a ring rather than a coloured edge on the picture.
   ══════════════════════════════════════════════════════════════════════════ */
.upRing {
  position: relative; display: inline-grid; place-items: center;
  padding: 3px; border-radius: 50%; line-height: 0;
  background: var(--cmx-pane2);
}
.upRing::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  padding: 2px;
  /* The two-mask trick: paint the gradient, then cut the middle out of it so
     only the 2px border remains. -webkit-mask is required — Safari and Chrome
     both still want the prefix here. */
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
}
.upRing--new::before    { background: conic-gradient(from 210deg, #f0c64a, #e8544a, #a855f7, #f0c64a); }
.upRing--seen::before   { background: rgb(255 255 255 / .22); }
.upRing--add::before    { background: rgb(255 255 255 / .16); }
.upRing[data-up-open]   { cursor: pointer; }
.upRing .ycAv           { display: block; }

/* ── page ───────────────────────────────────────────────────────────────── */
.upWrap { position: relative; z-index: 1; max-width: 60rem; margin-inline: auto;
  padding: var(--s-8) var(--gutter) var(--s-20); }
.upHead { display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-4); flex-wrap: wrap; margin-bottom: var(--s-6); }
.upHead h1 { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 500;
  color: var(--text-hi); margin: 0; }
.upHead p { margin: .3rem 0 0; color: var(--text-lo); font-size: var(--fs-sm); }
.upHead__nav { display: flex; gap: var(--s-4); }

.upTray {
  display: flex; gap: var(--s-4); overflow-x: auto; padding: var(--s-4) var(--s-2) var(--s-5);
  scrollbar-width: thin; scrollbar-color: rgb(240 198 74 / .4) transparent;
  border-bottom: 1px solid var(--cmx-hair);
}
.upTray::-webkit-scrollbar { height: 6px; }
.upTray::-webkit-scrollbar-track { background: transparent; }
.upTray::-webkit-scrollbar-thumb { border-radius: 99px; background: rgb(240 198 74 / .35); }

.upTray__me, .upTray__one, .upTray__add {
  flex: none; width: 4.6rem; display: grid; justify-items: center; gap: .45rem;
  border: 0; background: none; cursor: pointer; font: inherit; padding: 0;
}
.upTray__me { position: relative; cursor: default; }
.upTray__add { width: 100%; }
/* Your own ring: gold, so it is distinguishable at a glance from other
   people's unwatched updates — you already know you have posted. */
.upRing--mine::before { background: conic-gradient(from 210deg, #f0c64a, #fde68a, #f0c64a); }
.upTray__me b, .upTray__one b {
  font-size: .68rem; font-weight: 500; color: var(--text-mid);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The + is its own button when you already have updates — the avatar plays
   them, this adds another. Positioned against .upTray__me, which is the
   positioned ancestor. */
.upTray__plus {
  position: absolute; right: .25rem; top: 2.4rem; z-index: 3;
  width: 1.45rem; height: 1.45rem; display: grid; place-items: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: var(--y-yellow); color: var(--y-black);
  font-size: .95rem; font-weight: 700; line-height: 1;
  box-shadow: 0 0 0 3px var(--surface-0);
  transition: scale var(--dur) var(--ease-spring);
}
.upTray__plus:hover { scale: 1.12; }
/* Inside the "Add yours" variant it is decoration, not a second target. */
.upTray__plus.is-static { position: absolute; right: -1px; bottom: -1px; top: auto;
  pointer-events: none; }
.upTray__empty { align-self: center; margin: 0; font-size: var(--fs-sm); color: var(--text-lo); }

.upRule { margin: var(--s-5) 0 0; padding: var(--s-4);
  border-radius: var(--radius); border: 1px dashed var(--cmx-hair);
  font-size: var(--fs-sm); color: var(--text-lo); line-height: var(--lh-body); }
.upRule b { color: var(--text-mid); }

/* ── composer ───────────────────────────────────────────────────────────── */
.upNew, .upView { position: fixed; inset: 0; z-index: 430;
  display: grid; place-items: center; animation: cmxFadeIn .2s var(--ease-out); }
.upNew[hidden], .upView[hidden] { display: none; }
.upNew__veil, .upView__veil { position: absolute; inset: 0; border: 0; cursor: pointer;
  background: rgb(3 3 5 / .88); backdrop-filter: blur(12px); }

.upNew { padding: clamp(.5rem, 3vw, 2rem); }
.upNew__box {
  position: relative; z-index: 1; width: min(46rem, 100%); max-height: 92dvh;
  display: grid; grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
  border-radius: var(--radius-lg); overflow: hidden;
  border: 1px solid var(--cmx-hair); background: var(--surface-1);
  box-shadow: 0 50px 130px -40px rgb(0 0 0 / .95);
  animation: cmxPeekIn .26s var(--ease-out);
}
.upNew__box > header, .upNew__box > footer {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4) var(--s-5); background: var(--cmx-pane);
}
.upNew__box > header { justify-content: space-between; border-bottom: 1px solid var(--cmx-hair); }
.upNew__box > footer { justify-content: flex-end; border-top: 1px solid var(--cmx-hair); }
.upNew__box h2 { margin: 0; font-family: var(--font-display); font-size: var(--fs-h3);
  font-weight: 500; color: var(--text-hi); }

/* TWO COLUMNS. The preview is fixed-width because it is a phone screen and a
   phone screen does not stretch; the controls take the rest. */
.upNew__body {
  padding: var(--s-5); overflow-y: auto; min-height: 0;
  display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: var(--s-6);
  align-items: start;
  scrollbar-width: thin; scrollbar-color: rgb(240 198 74 / .45) transparent;
}
.upNew__preview { display: grid; gap: var(--s-3); }
.upNew__controls { display: grid; gap: var(--s-5); align-content: start; }
.upNew__err { margin: 0; font-size: var(--fs-sm); color: var(--y-red); }
.upNew__err[hidden] { display: none; }
.upNew__hint { margin: 0; text-align: center; font-family: var(--font-mono);
  font-size: .6rem; color: var(--text-lo); }

/* THE PREVIEW IS THE INPUT. Typing into a plain field and imagining the result
   is how people post something that looks wrong. */
.upCanvas {
  position: relative; aspect-ratio: 9 / 16; width: 100%;
  border-radius: 1.1rem;
  display: grid; place-items: center; padding: var(--s-5); overflow: hidden;
  background: linear-gradient(160deg, var(--a, #f0c64a), var(--b, #c2410c));
  box-shadow: 0 18px 40px -18px rgb(0 0 0 / .8), inset 0 0 0 1px rgb(255 255 255 / .12);
}
/* A faint sheen, so a flat gradient reads as a surface rather than a swatch. */
.upCanvas::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(120% 70% at 50% 0%, rgb(255 255 255 / .18), transparent 60%);
}
.upCanvas img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.upCanvas img[hidden] { display: none; }
.upCanvas textarea {
  position: relative; z-index: 1; width: 100%; resize: none; border: 0; outline: none;
  background: none; text-align: center; color: #fff; font: inherit;
  font-size: 1.15rem; font-weight: 600; line-height: 1.35;
  text-shadow: 0 2px 14px rgb(0 0 0 / .5);
}
.upCanvas textarea::placeholder { color: rgb(255 255 255 / .62); }
.upCanvas.has-img textarea { font-size: .95rem; }
.upCanvas__drop {
  position: absolute; top: .5rem; right: .5rem; z-index: 3;
  width: 1.9rem; height: 1.9rem; display: grid; place-items: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgb(0 0 0 / .55); color: #fff; backdrop-filter: blur(6px);
}
.upCanvas__drop[hidden] { display: none; }
.upCanvas__drop svg { width: .9rem; height: .9rem; }

/* ── controls ───────────────────────────────────────────────────────────── */
.upField { display: grid; gap: var(--s-2); }
.upField__label {
  font-size: .6rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-lo);
}
.upField__note { margin: 0; font-size: var(--fs-xs); color: var(--text-lo);
  line-height: var(--lh-body); }
.upField__note b { color: var(--accent-ink); }
[data-colours][hidden] { display: none; }

/* Labelled, not a lone paperclip. This is the most consequential control on
   the dialog and it was reading as decoration in the corner of a colour row. */
.upAttach {
  display: flex; align-items: center; gap: var(--s-3);
  padding: .8rem 1rem; border-radius: var(--radius); cursor: pointer;
  border: 1px dashed var(--cmx-hair); background: var(--cmx-pane);
  font-size: var(--fs-sm); font-weight: 600; color: var(--text-mid);
  transition: border-color var(--dur) var(--ease-out), background-color var(--dur) var(--ease-out),
              color var(--dur) var(--ease-out);
}
.upAttach:hover { border-color: rgb(240 198 74 / .5); color: var(--accent-ink);
  background: var(--cmx-pane2); }
.upAttach svg { width: 1.15rem; height: 1.15rem; flex: none; }

.upSwatches { display: flex; gap: .5rem; flex-wrap: wrap; }
.upSwatch {
  width: 2rem; height: 2rem; border-radius: 50%; cursor: pointer;
  border: 2px solid transparent; position: relative;
  background: linear-gradient(160deg, var(--a), var(--b));
  transition: scale var(--dur) var(--ease-spring);
}
.upSwatch:hover { scale: 1.12; }
/* A ring OUTSIDE the swatch, so the colour is not eaten by its own selected
   state — a border drawn on top shrinks the thing you are choosing. */
.upSwatch.is-on { box-shadow: 0 0 0 2px var(--surface-1), 0 0 0 4px var(--y-yellow); }

/* A segmented control. Two radio cards with a paragraph each made the audience
   setting larger than the post it applies to. */
.upSeg {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: .2rem;
  padding: .25rem; border-radius: var(--radius-pill);
  border: 1px solid var(--cmx-hair); background: var(--cmx-pane);
}
.upSeg__opt { position: relative; }
.upSeg__opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.upSeg__opt span {
  display: block; padding: .45rem .6rem; border-radius: var(--radius-pill);
  text-align: center; cursor: pointer;
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-lo);
  transition: background-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.upSeg__opt:hover span { color: var(--text-hi); }
.upSeg__opt input:checked + span { background: var(--y-yellow); color: var(--y-black); }
.upSeg__opt input:focus-visible + span { outline: 2px solid var(--y-yellow); outline-offset: 2px; }

/* ── player ─────────────────────────────────────────────────────────────── */
.upView { padding: clamp(0px, 2vw, 1.5rem); }
.upView__box {
  position: relative; z-index: 1;
  width: min(26rem, 100%); height: min(46rem, 94dvh);
  display: grid; grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  border-radius: var(--radius-lg); overflow: hidden;
  background: #08090c; border: 1px solid var(--cmx-hair);
  box-shadow: 0 50px 130px -40px rgb(0 0 0 / .95);
}

.upView__bars { display: flex; gap: 3px; padding: var(--s-3) var(--s-3) 0; }
.upBar { flex: 1; height: 2.5px; border-radius: 99px; background: rgb(255 255 255 / .25);
  overflow: hidden; }
.upBar i { display: block; height: 100%; width: 0; background: #fff; }
.upBar.is-done i { width: 100%; }

.upView__top { display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); }
.upView__id { flex: 1; min-width: 0; display: grid; }
.upView__id b { font-size: var(--fs-sm); color: #fff;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upView__id time { font-family: var(--font-mono); font-size: .58rem; color: rgb(255 255 255 / .6); }
.upView__top .cmxIcon { background: rgb(255 255 255 / .1); border-color: transparent; color: #fff; }
.upView__top .cmxIcon svg { width: 1rem; height: 1rem; }

.upView__stage { position: relative; display: grid; place-items: center; overflow: hidden;
  min-height: 0; }
.upView__stage img { width: 100%; height: 100%; object-fit: contain; }
.upView__stage img[hidden] { display: none; }
.upView__text {
  position: relative; z-index: 1; margin: 0; padding: var(--s-6); text-align: center;
  color: #fff; font-size: var(--fs-h3); font-weight: 600; line-height: 1.35;
  text-shadow: 0 2px 12px rgb(0 0 0 / .45); overflow-wrap: anywhere;
}
.upView__text.is-caption {
  position: absolute; bottom: 0; left: 0; right: 0; z-index: 2;
  font-size: var(--fs-sm); font-weight: 500; padding: var(--s-5) var(--s-4);
  background: linear-gradient(to top, rgb(0 0 0 / .75), transparent);
}

/* Half the screen each. The tap target has to be the whole side or people miss
   it — a small arrow in a corner is a desktop idea. */
.upView__half { position: absolute; top: 0; bottom: 0; width: 42%; z-index: 3;
  border: 0; background: none; cursor: pointer; }
.upView__half--prev { left: 0; }
.upView__half--next { right: 0; }

.upView__foot { display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); background: rgb(0 0 0 / .35); }
.upView__left { font-family: var(--font-mono); font-size: .58rem; color: rgb(255 255 255 / .5); }
.upView__react { display: flex; gap: .2rem; margin-left: auto; }
.upView__react[hidden] { display: none; }
.upReact {
  width: 2rem; height: 2rem; border: 0; border-radius: 50%; cursor: pointer;
  background: rgb(255 255 255 / .08); font-size: .95rem; line-height: 1;
  transition: background-color var(--dur) var(--ease-out), scale var(--dur) var(--ease-spring);
}
.upReact:hover { background: rgb(255 255 255 / .18); scale: 1.12; }
.upReact.is-sent { background: var(--y-yellow); scale: 1.25; }
.upView__views { color: rgb(255 255 255 / .75); font-size: var(--fs-xs); }

@media (max-width: 52rem) {
  /* One column. Two 15rem panes side by side on a phone is two cramped
     columns, not a layout. */
  .upNew__body { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
  .upNew__preview { justify-self: center; width: min(15rem, 100%); }
}

@media (max-width: 46rem) {
  .upWrap { padding: var(--s-5) var(--s-3) var(--s-16); }
  .upView { padding: 0; }
  .upView__box { width: 100%; height: 100dvh; border-radius: 0; border: 0; }
  .upNew { padding: 0; }
  .upNew__box { width: 100%; height: 100dvh; max-height: none; border-radius: 0; border: 0; }
  .upCanvas textarea { font-size: 1rem; }
}
@media (prefers-reduced-motion: reduce) {
  .upNew, .upView, .upNew__box { animation: none; }
  .upBar i { transition: none !important; }
}

/* ── REPLY ──────────────────────────────────────────────────────────────── */
.upReply {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-3) var(--s-4); background: rgb(0 0 0 / .55);
  border-top: 1px solid rgb(255 255 255 / .08);
}
.upReply[hidden], .upReply__gate[hidden] { display: none; }
.upReply input {
  flex: 1; min-width: 0; padding: .6rem 1rem; border-radius: var(--radius-pill);
  border: 1px solid rgb(255 255 255 / .18); background: rgb(255 255 255 / .06);
  color: #fff; font: inherit; font-size: var(--fs-sm); outline: none;
}
.upReply input::placeholder { color: rgb(255 255 255 / .5); }
.upReply input:focus { border-color: var(--y-yellow); }
.upReply .cmxSend { width: 2.2rem; height: 2.2rem; flex: none; }

.upReply__gate {
  display: flex; align-items: center; gap: var(--s-3); margin: 0;
  padding: var(--s-3) var(--s-4); background: rgb(0 0 0 / .55);
  border-top: 1px solid rgb(255 255 255 / .08);
  font-size: var(--fs-xs); color: rgb(255 255 255 / .7); line-height: var(--lh-body);
}
.upReply__gate span { flex: 1; }

/* The player grows a fifth row for the reply bar. Declared here rather than
   left to auto-placement — an implicit row would size to max-content and push
   the stage off the bottom. */
.upView__box { grid-template-rows: auto auto minmax(0, 1fr) auto auto; }

/* A DM that quotes an update. It deliberately stores no copy of the update, so
   once the 24 hours are up this reads "replied to an update" and nothing more —
   the quote must not outlive the thing it quotes. */
.dmQuote {
  display: block; margin-bottom: .3rem; padding: .35rem .6rem;
  border-left: 2px solid rgb(240 198 74 / .6); border-radius: 4px;
  background: rgb(255 255 255 / .05);
  font-size: var(--fs-xs); color: var(--text-lo); font-style: italic;
}

/* ── PERSON-TO-PERSON ────────────────────────────────────────────────────────
   Outside the card, unlike the tap-halves inside it. One moves an update, the
   other moves a person; putting them in the same place is what makes people
   press the wrong one.
   ══════════════════════════════════════════════════════════════════════════ */
.upHop {
  position: absolute; top: 50%; translate: 0 -50%; z-index: 5;
  width: 2.8rem; height: 2.8rem; display: grid; place-items: center;
  border-radius: 50%; cursor: pointer;
  border: 1px solid rgb(255 255 255 / .16); background: rgb(255 255 255 / .07);
  backdrop-filter: blur(8px); color: #fff;
  transition: background-color var(--dur) var(--ease-out), scale var(--dur) var(--ease-spring);
}
.upHop[hidden] { display: none; }
.upHop:hover { background: rgb(255 255 255 / .18); scale: 1.06; }
.upHop svg { width: 1.15rem; height: 1.15rem; }
.upHop--prev { left: max(1rem, calc(50% - 16rem)); }
.upHop--next { right: max(1rem, calc(50% - 16rem)); }

@media (max-width: 46rem) {
  /* No room beside a full-bleed card, and swiping already moves between
     people on touch. */
  .upHop { display: none; }
}
