/*
 * munchterm plus: the stash drop pages (Plus 79). Owned by the drops flow.
 *
 *   .reveal-*    /drops/:id, opening a drop: the stage, its three styles, the opened item
 *   .drop-choice "next time?", on the reveal page and /account/drops
 *   .drops-*     /drops, the public page: totals, odds, recent drops
 *
 * THE STAGE IS A SWISS POSTER. A square. Sealed, an ink block with the plus mark and a hairline
 * inset. Open, the pink field with thin squares drifting out from behind the item's own cutout
 * (stash product images are transparent PNGs). No gradients, no confetti, no glow, no spin, no
 * slot machine. Square corners, like everything else here.
 *
 * MOTION. This is the one place plus moves for more than 250ms, on purpose: the reveal IS the
 * moment. It is still transform and opacity only, it never loops on the item itself, and under
 * prefers-reduced-motion every animation here is off: the item is simply there.
 *
 * Phases are classes on the page root (useReveal.ts): reveal--sealed, reveal--opening,
 * reveal--open, reveal--landed. Styles: reveal--hatch (the egg), reveal--hold, reveal--wipe.
 * data-tier (0 to 3) is the drop's rarity rank: rarer, the rings move a little faster.
 */

/* --- layout -------------------------------------------------------------------------------- */

.reveal {
  --stage-max: 440px;
  --reveal-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --reveal-in-out: cubic-bezier(0.7, 0, 0.2, 1);
}

.reveal__layout {
  display: grid;
  gap: var(--s5);
  margin-top: var(--s3);
}

.reveal__text {
  display: grid;
  gap: var(--s4);
  align-content: start;
}

.reveal__text .section-head {
  margin-bottom: 0;
}

.reveal__form {
  margin: 0;
}

@media (min-width: 900px) {
  .reveal.wrap--narrow {
    max-width: var(--wide);
  }

  .reveal__layout {
    grid-template-columns: minmax(0, var(--stage-max)) minmax(0, 1fr);
    gap: var(--s7);
    align-items: center;
  }
}

/* --- the stage ----------------------------------------------------------------------------- */

.reveal__stage {
  position: relative;
  width: 100%;
  max-width: var(--stage-max);
  margin-inline: auto;
  aspect-ratio: 1;
  overflow: hidden;
  isolation: isolate;
  background: var(--pink);
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.reveal__stage[data-tappable] {
  cursor: pointer;
}

.reveal__field {
  position: absolute;
  inset: 0;
  background: var(--pink);
}

/* Three thin squares, centred, drifting outwards one after another once the drop is open. */
.reveal__ring {
  position: absolute;
  inset: 27%;
  border: 2px solid rgba(250, 250, 250, 0.7);
  opacity: 0;
}

.reveal__flash {
  position: absolute;
  inset: 0;
  background: var(--on-pink);
  opacity: 0;
}

.reveal__item {
  position: absolute;
  inset: 13%;
  display: grid;
  place-items: center;
  opacity: 0;
}

.reveal__item img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.reveal__item-blank {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  color: var(--on-pink);
}

/* The sealed block. */
.reveal__seal {
  position: absolute;
  inset: 0;
  z-index: 2;
}

.reveal__seal--solid,
.reveal__half {
  display: grid;
  place-items: center;
  background: var(--dark);
}

.reveal__seal--solid::after,
.reveal__half::after {
  content: "";
  position: absolute;
  inset: 12px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  pointer-events: none;
}

.reveal__half {
  position: absolute;
  inset: 0;
}

/* The egg's two halves: one block cut on the diagonal from top right to bottom left. Sealed, the
   ink behind them hides the seam, so it reads as one block. */
.reveal__half--a {
  clip-path: polygon(0 0, 100% 0, 0 100%);
}

.reveal__half--b {
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}

/* The egg's mark sits over both halves, whole, and the crack draws through it. */
.reveal--hatch .reveal__seal > .reveal__mark {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.reveal--hatch.reveal--open .reveal__seal > .reveal__mark {
  animation: reveal-fade-out 0.16s ease-out forwards;
}

.reveal__crack {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 142%;
  height: 2px;
  background: var(--pink);
  transform: translate(-50%, -50%) rotate(-45deg) scaleX(0);
}

/* The plus mark in its white tile, as on the membership pass: the mark is drawn for white. */
.reveal__mark {
  position: relative;
  display: inline-flex;
  padding: 10px 12px;
  background: #fff;
}

.reveal__mark img {
  height: 40px;
  width: calc(40px * 623 / 256);
  object-fit: contain;
}

/* --- the egg ------------------------------------------------------------------------------- */

/* The egg sits on the pink ground, inset, so its wobble reads as an object, not a frame. */
.reveal--hatch .reveal__seal {
  inset: 11%;
}

/* Ink behind the two halves while sealed, so their diagonal seam never shows the field. */
.reveal--hatch.reveal--sealed .reveal__seal,
.reveal--hatch.reveal--opening .reveal__seal {
  background: var(--dark);
}

/* Sealed: a small wobble every few seconds, so it looks like something is in there. */
.reveal--hatch.reveal--sealed .reveal__seal {
  transform-origin: 50% 85%;
  animation: reveal-idle 3.6s var(--ease) 1.2s infinite;
}

/* Opening: three proper wobbles while the answer comes back, then the crack draws. */
.reveal--hatch.reveal--opening .reveal__seal {
  transform-origin: 50% 85%;
  animation: reveal-shake 0.9s var(--ease) infinite;
}

.reveal--hatch.reveal--opening .reveal__crack {
  animation: reveal-crack 0.32s var(--reveal-out) 0.72s forwards;
}

/* Open: the halves come apart along the crack, and the item rises out of the gap. */
.reveal--hatch.reveal--open .reveal__crack {
  transform: translate(-50%, -50%) rotate(-45deg) scaleX(1);
  animation: reveal-fade-out 0.2s ease-out forwards;
}

.reveal--hatch.reveal--open .reveal__half--a {
  animation: reveal-split-a 0.7s var(--reveal-out) forwards;
}

.reveal--hatch.reveal--open .reveal__half--b {
  animation: reveal-split-b 0.7s var(--reveal-out) forwards;
}

/* --- hold to open -------------------------------------------------------------------------- */

.reveal__hold {
  position: relative;
  overflow: hidden;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* The fill runs left to right while held, and drains when let go. */
.reveal__hold-fill {
  position: absolute;
  inset: 0;
  background: var(--dark);
  transform-origin: left center;
  transform: scaleX(var(--p, 0));
  transition: transform var(--slow) var(--ease);
}

.reveal__hold.is-holding .reveal__hold-fill {
  transition: none;
}

.reveal__hold-label {
  position: relative;
}

/* The stage keeps time with the button: a pink line along the foot of the block, filling as the
   press is held (--p, set on the stage by RevealPage), draining if it is let go. */
.reveal--hold .reveal__seal::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  height: 4px;
  background: var(--pink);
  transform-origin: left center;
  transform: scaleX(var(--p, 0));
  transition: transform var(--slow) var(--ease);
}

.reveal--hold.is-holding .reveal__seal::before {
  transition: none;
}

/* Opening: the mark breathes while the answer comes back. */
.reveal--hold.reveal--opening .reveal__mark,
.reveal--wipe.reveal--opening .reveal__mark {
  animation: reveal-breathe 0.7s ease-in-out infinite alternate;
}

/* Open: the block drops away like a slip of paper, and the item comes up. */
.reveal--hold.reveal--open .reveal__seal {
  animation: reveal-drop 0.62s var(--reveal-in-out) forwards;
}

/* The value counts up in the facts (useCountUp); the figure gets the weight of a headline. */
.reveal--hold .reveal__value {
  font-family: var(--font-heading);
  font-weight: 700;
}

/* --- the curtain --------------------------------------------------------------------------- */


.reveal--wipe.reveal--open .reveal__seal {
  animation: reveal-wipe 0.62s var(--reveal-in-out) forwards;
}

/* --- open, every style --------------------------------------------------------------------- */

.reveal--open .reveal__item {
  animation: reveal-rise 0.72s var(--reveal-out) 0.14s both;
}

.reveal--landed .reveal__item {
  opacity: 1;
  animation: reveal-land 0.45s var(--ease) both;
}

.reveal--open .reveal__ring,
.reveal--landed .reveal__ring {
  animation: reveal-ring 4.2s linear infinite;
}

.reveal--open .reveal__ring:nth-child(2),
.reveal--landed .reveal__ring:nth-child(2) {
  animation-delay: -1.4s;
}

.reveal--open .reveal__ring:nth-child(3),
.reveal--landed .reveal__ring:nth-child(3) {
  animation-delay: -2.8s;
}

.reveal[data-tier="1"] .reveal__ring {
  animation-duration: 3.6s;
}

.reveal[data-tier="2"] .reveal__ring,
.reveal[data-tier="3"] .reveal__ring {
  animation-duration: 2.8s;
}

/* A rarer drop gets one soft flash of the field as it opens. Once, never a strobe. */
.reveal--open[data-tier="2"] .reveal__flash,
.reveal--open[data-tier="3"] .reveal__flash {
  animation: reveal-flash 0.5s ease-out 0.1s both;
}

/* The words arrive just after the item. */
.reveal--open .reveal__opened {
  animation: reveal-land 0.45s var(--ease) 0.5s both;
}

.reveal--open .reveal__later {
  animation: reveal-land 0.45s var(--ease) 1.1s both;
}

/* --- the opened drop ----------------------------------------------------------------------- */

.reveal__opened {
  display: grid;
  gap: var(--s3);
  justify-items: start;
}

.reveal__opened .eyebrow {
  margin: 0;
}

.reveal__title {
  margin: 0;
  font-size: var(--size-h1);
  line-height: 1.1;
}

.reveal__title:focus {
  outline: none;
}

.reveal__facts {
  width: 100%;
  margin: var(--s2) 0 0;
}

.reveal__actions {
  display: grid;
  gap: var(--s2);
  width: 100%;
  margin-top: var(--s2);
}

.reveal__links,
.reveal__change {
  margin: 0;
}

.reveal__change {
  margin-top: var(--s5);
}

.reveal__extra {
  margin-top: var(--s6);
}

/* --- next time? ---------------------------------------------------------------------------- */

.drop-choice {
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid var(--line-strong);
  display: grid;
  gap: var(--s4);
}

.drop-choice .section-head {
  margin-bottom: 0;
}

.drop-choice__form {
  display: grid;
  gap: var(--s4);
  justify-items: start;
}

.drop-choice__form .fieldset {
  width: 100%;
}

.drop-settings .drop-choice {
  margin-top: var(--s4);
  padding-top: 0;
  border-top: 0;
}

.drop-settings__text {
  margin-top: var(--s6);
}

/* --- keyframes ----------------------------------------------------------------------------- */

@keyframes reveal-idle {
  0%,
  78%,
  100% {
    transform: rotate(0);
  }
  82% {
    transform: rotate(-2deg);
  }
  87% {
    transform: rotate(2deg);
  }
  92% {
    transform: rotate(-1deg);
  }
}

@keyframes reveal-shake {
  0%,
  100% {
    transform: rotate(0);
  }
  8% {
    transform: rotate(-4deg);
  }
  17% {
    transform: rotate(4deg);
  }
  26% {
    transform: rotate(-2deg);
  }
  36% {
    transform: rotate(0);
  }
  42% {
    transform: rotate(-5deg) translateY(-1%);
  }
  52% {
    transform: rotate(5deg) translateY(-1%);
  }
  62% {
    transform: rotate(-3deg);
  }
  72% {
    transform: rotate(0);
  }
  78% {
    transform: rotate(-6deg) translateY(-2%);
  }
  88% {
    transform: rotate(6deg) translateY(-2%);
  }
}

@keyframes reveal-crack {
  from {
    transform: translate(-50%, -50%) rotate(-45deg) scaleX(0);
  }
  to {
    transform: translate(-50%, -50%) rotate(-45deg) scaleX(1);
  }
}

@keyframes reveal-split-a {
  to {
    transform: translate(-34%, -34%) rotate(-8deg);
    opacity: 0;
  }
}

@keyframes reveal-split-b {
  to {
    transform: translate(34%, 34%) rotate(8deg);
    opacity: 0;
  }
}

@keyframes reveal-drop {
  to {
    transform: translateY(104%);
  }
}

@keyframes reveal-wipe {
  to {
    transform: translateY(-101%);
  }
}

@keyframes reveal-breathe {
  from {
    opacity: 1;
  }
  to {
    opacity: 0.45;
  }
}

@keyframes reveal-rise {
  from {
    opacity: 0;
    transform: translateY(14%) scale(0.86);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes reveal-land {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes reveal-ring {
  0% {
    opacity: 0;
    transform: scale(0.55);
  }
  15% {
    opacity: 0.8;
  }
  100% {
    opacity: 0;
    transform: scale(2.6);
  }
}

@keyframes reveal-flash {
  from {
    opacity: 0.4;
  }
  to {
    opacity: 0;
  }
}

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

/* Reduced motion: nothing moves. Opened, the item is just there. */
@media (prefers-reduced-motion: reduce) {
  .reveal *,
  .reveal *::before,
  .reveal *::after {
    animation: none !important;
    transition: none !important;
  }

  .reveal--open .reveal__seal {
    display: none;
  }

  .reveal--open .reveal__item,
  .reveal--landed .reveal__item {
    opacity: 1;
    transform: none;
  }

  .reveal--open .reveal__ring,
  .reveal--landed .reveal__ring {
    opacity: 0.35;
  }

  .reveal--open .reveal__ring:nth-child(2),
  .reveal--landed .reveal__ring:nth-child(2) {
    inset: 18%;
  }

  .reveal--open .reveal__ring:nth-child(3),
  .reveal--landed .reveal__ring:nth-child(3) {
    inset: 9%;
  }
}

/* --- /drops -------------------------------------------------------------------------------- */

.drops-intro--lead {
  padding-block: var(--s7) var(--s6);
}

.drops-intro .section-head {
  margin-bottom: var(--s4);
  max-width: 44rem;
}

.drops-intro__notice {
  margin-top: var(--s4);
  max-width: 44rem;
}

/* Three big numbers on one grid. */
.drops-totals__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 0 0 var(--s3);
  border-top: 2px solid var(--ink);
}

.drops-totals__grid > div {
  display: flex;
  flex-direction: column-reverse;
  justify-content: flex-end;
  gap: var(--s1);
  padding: var(--s3) var(--s3) var(--s3) 0;
}

.drops-totals__grid > div + div {
  padding-left: var(--s3);
  border-left: 1px solid var(--line-strong);
}

.drops-totals__grid dd {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(1.25rem, 6vw, 2.75rem);
  line-height: 1.05;
  color: var(--ink);
  overflow-wrap: anywhere;
}

.drops-totals__grid dt {
  color: var(--ink-muted);
  font-size: var(--size-small);
  line-height: 1.3;
}

/* Drop types: plain links, the current one underlined in ink. */
.drops-types {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s5);
  margin-bottom: var(--s5);
  border-bottom: 1px solid var(--line-strong);
}

.drops-types__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  color: var(--ink-muted);
  font-weight: 600;
  text-decoration: none;
}

.drops-types__link:hover {
  color: var(--ink);
}

.drops-types__link[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.drops-pools {
  display: grid;
  gap: var(--s6);
}

.drops-pools__detail {
  margin: 0;
}

.drops-pool__head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  justify-content: space-between;
  align-items: flex-end;
  padding-bottom: var(--s3);
  border-bottom: 2px solid var(--ink);
}

.drops-pool__title {
  margin: 0;
  font-size: var(--size-h3);
}

.drops-pool__detail {
  margin: var(--s1) 0 0;
}

.drops-odds__cols {
  display: none;
}

.drops-odds__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* One item. Phones: picture, name and rarity, odds on the right, the worth under the name, and a
   hairline bar across the bottom drawn to the item's real share. */
.drops-odds__row {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) auto;
  grid-template-areas:
    "thumb item odds"
    "thumb value odds"
    "bar bar bar";
  gap: var(--s1) var(--s3);
  align-items: center;
  padding-top: var(--s3);
  border-bottom: 1px solid var(--line);
}

.drops-odds__row--out {
  color: var(--ink-muted);
}

.drops-odds__row--out .drops-odds__thumb {
  opacity: 0.5;
}

.drops-odds__thumb {
  grid-area: thumb;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--ink-muted);
}

.drops-odds__thumb img {
  width: 46px;
  height: 46px;
  object-fit: contain;
}

.drops-odds__item {
  grid-area: item;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s1) var(--s2);
  min-width: 0;
}

.drops-odds__title {
  font-weight: 600;
  color: var(--ink);
}

.drops-odds__row--out .drops-odds__title {
  color: var(--ink-muted);
}

.drops-odds__value {
  grid-area: value;
  color: var(--ink-muted);
  font-size: var(--size-small);
}

.drops-odds__odds {
  grid-area: odds;
  display: grid;
  justify-items: end;
  text-align: right;
}

.drops-odds__main {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--ink);
}

.drops-odds__row--out .drops-odds__main {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--size-small);
  color: var(--ink-muted);
}

.drops-odds__sub {
  font-size: var(--size-small);
  color: var(--ink-muted);
}

.drops-odds__bar {
  grid-area: bar;
  position: relative;
  height: 2px;
  margin-top: var(--s2);
}

.drops-odds__bar > span {
  position: absolute;
  inset: 0;
  background: var(--pink);
  transform-origin: left center;
}

/* A pool past its first 10 items: the rest behind a native <details>. The summary is a quiet
   hairline row, and once open it goes, so the rest reads straight on from the first 10. */
.drops-odds__more-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  min-height: var(--tap);
  border-bottom: 1px solid var(--line);
  color: var(--ink-muted);
  font-size: var(--size-small);
  cursor: pointer;
  list-style: none;
}

.drops-odds__more-toggle::-webkit-details-marker {
  display: none;
}

.drops-odds__more-toggle:hover {
  color: var(--ink);
}

.drops-odds__more-toggle .icon {
  transform: rotate(90deg);
}

.drops-odds__more[open] > .drops-odds__more-toggle {
  display: none;
}

.drops-pool__foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s5);
  padding-top: var(--s3);
}

@media (min-width: 700px) {
  .drops-odds__cols,
  .drops-odds__row {
    grid-template-columns: 48px minmax(0, 1fr) 7rem 10rem;
  }

  .drops-odds__cols {
    display: grid;
    gap: var(--s3);
    padding-top: var(--s3);
    color: var(--ink-muted);
    font-size: var(--size-small);
  }

  .drops-odds__cols span:first-child {
    grid-column: 1 / 3;
  }

  .drops-odds__cols span:not(:first-child) {
    text-align: right;
  }

  .drops-odds__row {
    grid-template-areas:
      "thumb item value odds"
      "bar bar bar bar";
  }

  .drops-odds__value {
    text-align: right;
    font-size: var(--size-body);
    color: var(--ink);
  }
}

/* Recent drops: a date column and what went out. */
.drops-recent__list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 2px solid var(--ink);
}

.drops-recent__cycle {
  display: grid;
  gap: var(--s3);
  padding-block: var(--s4);
  border-bottom: 1px solid var(--line);
}

.drops-recent__when {
  display: grid;
  gap: var(--s1);
}

.drops-recent__date {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--ink);
}

.drops-recent__items {
  display: grid;
  gap: var(--s2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.drops-recent__item {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) auto;
  gap: var(--s3);
  align-items: center;
}

.drops-recent__item .drops-odds__thumb {
  grid-area: auto;
}

.drops-recent__name {
  min-width: 0;
}

.drops-recent__count {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--ink);
}

@media (min-width: 900px) {
  .drops-recent__cycle {
    grid-template-columns: 14rem minmax(0, 1fr);
    gap: var(--s6);
  }

  .drops-recent__items {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s3) var(--s6);
  }
}

.drops-banner {
  padding-block: var(--s6);
}
