/* What every shop tab shares, whichever platform's colours it wears: the buy
   button's purchase animation, a crossed out price, and the logo above the
   IshraqMC tab. Loaded after the tab's own stylesheet on every page.

   The animation is Omar's, 1 October 2026: his three rounded stars hop in the
   button like loading dots while a purchase goes through, then the button
   says Successful! in green for a few seconds and fades back to Buy. On
   2 October he asked for more life in the stars, so they now spin, squash
   and glint as they hop. The page script drives it by adding is-buying,
   is-done and is-settling in turn. */

/* The confirmation line is always on the page, empty and hidden until a
   purchase fills it, so the script has somewhere to write. Every theme gives
   .notice a display of its own, which would otherwise beat [hidden]. */
.notice[hidden] {
  display: none;
}

.buy-button {
  position: relative;
  transition: background-color 0.9s ease, border-color 0.9s ease, color 0.9s ease;
}

/* The stars sit over the word, which keeps its space so the button never
   changes size while they hop. */
.buy-stars {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  gap: 6px;
  pointer-events: none;
}
.buy-stars img {
  width: 15px;
  height: 15px;
  animation: buy-hop 0.95s ease-in-out infinite;
}
.buy-stars img:nth-child(2) {
  animation-delay: 0.13s;
}
.buy-stars img:nth-child(3) {
  animation-delay: 0.26s;
}

/* One after another, like loading dots: each star crouches, jumps turning a
   fifth of the way round, catches the light at the top, and lands with a
   squash. A fifth of a turn is where a five pointed star looks the same
   again, so every hop starts exactly where the last one landed. The soft
   shadow keeps the white stars readable on Kick's bright green. */
@keyframes buy-hop {
  0% {
    transform: translateY(0) scale(1, 1) rotate(0deg);
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
  }
  14% {
    transform: translateY(1px) scale(1.16, 0.82) rotate(0deg);
    animation-timing-function: cubic-bezier(0.25, 0.6, 0.4, 1);
  }
  46% {
    transform: translateY(-8px) scale(0.94, 1.1) rotate(40deg);
    filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.95));
    animation-timing-function: cubic-bezier(0.6, 0, 0.75, 0.4);
  }
  76% {
    transform: translateY(1px) scale(1.14, 0.84) rotate(72deg);
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
  }
  88%,
  100% {
    transform: translateY(0) scale(1, 1) rotate(72deg);
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
  }
}

.buy-button.is-buying,
.buy-button.is-done,
.buy-button.is-settling {
  pointer-events: none;
}
.buy-button.is-buying .buy-word {
  visibility: hidden;
}
.buy-button.is-buying .buy-stars {
  display: flex;
}

/* Successful!, in green, whatever colour the tab's buttons are. Quick to turn
   green; the slow part is the fade back, which takes the button's own 0.9s
   once this class comes off. */
.buy-button.is-done {
  border-color: #23a55a !important;
  background-color: #23a55a !important;
  color: #ffffff !important;
  transition-duration: 0.25s;
  animation: buy-pop 0.4s ease-out;
}

/* A small bump as it turns green, so the moment it lands is felt. */
@keyframes buy-pop {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(1.06);
  }
  100% {
    transform: scale(1);
  }
}

/* Back to Buy: the colour eases back by itself once is-done comes off, and the
   word dips out and in while the script swaps it halfway. */
.buy-button.is-settling .buy-word {
  animation: buy-word-swap 0.9s ease both;
}
@keyframes buy-word-swap {
  0% {
    opacity: 1;
  }
  45%,
  55% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

/* Omar's discount: the old price crossed out, the new one under it. */
.item-card .price.discounted {
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}
.price .was,
.price .now {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.price .was {
  color: var(--faint);
  font-size: 0.86em;
  font-weight: 600;
  text-decoration: line-through;
  text-decoration-color: #da373c;
  text-decoration-thickness: 2px;
}
.price .was img {
  width: 14px;
  height: 14px;
  opacity: 0.55;
}

/* The IshraqMC logo above its tab, glowing the way it does on ishraqmc.net. */
.hero {
  display: flex;
  justify-content: center;
  padding: 4px 0 8px;
}
.hero img {
  width: min(240px, 56vw);
  height: auto;
  filter: drop-shadow(0 0 26px rgba(255, 170, 0, 0.45));
}

/* ---- Redeem Code, Omar's of 14 October 2026 --------------------------------
   A button directly above the member box, the same on every tab, that opens
   upward into a box with the Husky Coin, the code and a Redeem button. It sits
   at the bottom of the sidebar, so growing taller pushes it up rather than
   down. Built only from names every theme defines, so it wears Discord's,
   Twitch's, Kick's or IshraqMC's colours by itself; Kick has no --brand, so
   the accent falls back to its green. */
.redeem {
  margin-top: auto;
  padding: 0 8px 8px;
}
.redeem + .member {
  margin-top: 0;
}

.redeem-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 40px;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius, 4px);
  background: var(--raised);
  color: var(--heading);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, background-color 0.15s;
}
.redeem-toggle:hover {
  background: var(--hover, var(--deepest));
}
.redeem-toggle:focus-visible,
.redeem.is-open .redeem-toggle {
  border-color: var(--brand, var(--green));
}
.redeem-toggle-icon {
  width: 20px;
  height: 20px;
}

/* Shut is a row of no height, so it opens by growing; visibility keeps the box
   out of the Tab order while it is shut, and waits for the fold to finish. */
.redeem-panel {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  visibility: hidden;
  transition: grid-template-rows 0.25s ease, opacity 0.2s ease, visibility 0s linear 0.25s;
}
.redeem.is-open .redeem-panel {
  grid-template-rows: 1fr;
  opacity: 1;
  visibility: visible;
  transition: grid-template-rows 0.25s ease, opacity 0.2s ease, visibility 0s;
}
.redeem-form {
  min-height: 0;
  overflow: hidden;
}
.redeem-inner {
  margin-bottom: 8px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius, 6px);
  background: var(--raised);
}
.redeem-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.redeem-coin {
  flex: none;
  width: 28px;
  height: 28px;
}
.redeem-input {
  flex: 1;
  min-width: 0;
  height: 36px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius, 4px);
  background: var(--deepest);
  color: var(--heading);
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.redeem-input::placeholder {
  color: var(--faint);
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
}
.redeem-input:focus {
  outline: 2px solid var(--brand, var(--green));
  outline-offset: 1px;
}
.redeem-submit {
  width: 100%;
  margin-top: 10px;
}
.redeem-error {
  margin-top: 8px;
  color: #f23f43;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
}
.redeem-error[hidden] {
  display: none;
}

/* On a phone the sidebar is a bar across the top and the member box is
   hidden, so Redeem Code sits under the tabs and opens downward instead. */
@media (max-width: 760px) {
  .redeem {
    display: flex;
    flex-direction: column-reverse;
    margin-top: 0;
  }
  .redeem-inner {
    margin: 8px 0 0;
  }

  /* The tabs, on a phone: a row that scrolls sideways under the finger, the way
     an app's tab bar does, rather than six squeezed tabs pushing the whole page
     wider than the screen. Omar's ask, 14 October 2026. Every theme carries the
     same squeezed rules, so this one override fixes all four. The page script
     scrolls the open tab into view, and the tab cut off at the edge is the cue
     that there is more to swipe to. */
  .channel-nav {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .channel-nav::-webkit-scrollbar {
    display: none;
  }
  .channel-nav a {
    flex: none;
    padding: 6px 12px;
    white-space: nowrap;
  }
}

/* The popup: Omar's sentence, one of his heart emoji, confetti and Okay. */
.redeem-pop {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(0, 0, 0, 0.62);
  animation: redeem-fade 0.2s ease;
}
.redeem-pop[hidden] {
  display: none;
}
.redeem-confetti {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.confetti-bit {
  position: absolute;
  top: -16px;
  left: var(--x);
  width: 8px;
  height: 14px;
  border-radius: 2px;
  opacity: 0;
  animation: confetti-fall var(--fall) cubic-bezier(0.3, 0.6, 0.5, 1) var(--delay) forwards;
}
.confetti-bit.round {
  width: 9px;
  height: 9px;
  border-radius: 50%;
}
@keyframes confetti-fall {
  0% {
    opacity: 1;
    transform: translate(0, 0) rotate(0deg);
  }
  85% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translate(var(--drift), 105vh) rotate(var(--spin));
  }
}
.redeem-card {
  position: relative;
  z-index: 1;
  width: min(420px, 100%);
  padding: 28px 24px 22px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--secondary);
  text-align: center;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
  animation: redeem-in 0.45s cubic-bezier(0.2, 1.4, 0.4, 1);
}
.redeem-card-coin {
  width: 64px;
  height: 64px;
  animation: redeem-coin 1.2s ease-out;
}
.redeem-said {
  margin: 14px 0 20px;
  color: var(--heading);
  font-size: 17px;
  font-weight: 600;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.redeem-emoji {
  width: 28px;
  height: 28px;
  vertical-align: -7px;
}
.redeem-card .button {
  min-width: 128px;
}
@keyframes redeem-fade {
  from {
    opacity: 0;
  }
}
@keyframes redeem-in {
  from {
    opacity: 0;
    transform: scale(0.8) translateY(12px);
  }
}
/* The coin flips once as the popup lands. */
@keyframes redeem-coin {
  0% {
    transform: rotateY(0deg) scale(0.6);
  }
  60% {
    transform: rotateY(360deg) scale(1.12);
  }
  100% {
    transform: rotateY(360deg) scale(1);
  }
}

/* No reduced motion version, on purpose. This used to stop the stars and the
   fades for anyone whose system asks for less motion, and Omar's own Windows
   does (Animation effects off), so he saw stars that never moved. It is a
   small loading sign inside one button, there for the seconds a purchase
   takes, so it plays for everyone. Omar, 2 October 2026. */

/* ---- stream rewards on the Twitch and Kick tabs, 18 October 2026 ----
   A reward card has no icon row; its price and form sit at the bottom, and a reward that needs words has the Redeem Code box's text field above
   its button, in sentence case rather than the code box's capitals. */
/* Omar's descriptions keep the line breaks he typed on Twitch. */
.reward-card p {
  white-space: pre-line;
}

.reward-card form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  /* The price above already takes the card's spare height (margin-top: auto). */
  margin-top: 0;
}
.reward-input {
  width: 100%;
  min-width: 0;
  height: 36px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius, 4px);
  background: var(--deepest);
  color: var(--heading);
  font: inherit;
  font-size: 14px;
}
.reward-input::placeholder {
  color: var(--faint);
}
.reward-input:focus {
  outline: 2px solid var(--brand, var(--green));
  outline-offset: 1px;
}
.buy-button[data-state="offline"],
.buy-button[data-state="cooldown"] {
  opacity: 0.65;
}
