/* ============================================================================
   FOUNDER CHECKOUT, built to the BOE AAA detail standard
   Every surface is a hue-shifted ramp with a shine seam and depth chrome.
   Loaded after aaa.css. Additive, deleting the link reverts to disabled stubs.
   ========================================================================== */

/* ------------------------------------------------------------- pay buttons */
.pay__row { grid-template-columns: repeat(2, 1fr); }
.pay__row:has(.pay__btn:nth-child(5)) { grid-template-columns: repeat(2, 1fr); }
.pay__row .pay__btn:nth-child(5) { grid-column: span 2; }

.pay__btn {
  position: relative;
  cursor: pointer;
  opacity: 1;
  color: #fff3d6;
  border: 3px solid #241405;
  background:
    linear-gradient(180deg,
      #8a8272 0%,
      #6f6858 41%,
      #7c7565 42%,
      #5b5445 100%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 236, 190, 0.16),
    inset 0 2px 0 rgba(255, 246, 214, 0.28),
    inset 0 -3px 0 rgba(0, 0, 0, 0.4),
    0 3px 0 #2f1d0a,
    0 5px 0 #180d04,
    0 7px 9px rgba(0, 0, 0, 0.34);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.62);
  transition: transform 0.09s ease, box-shadow 0.09s ease, filter 0.15s ease;
}
.pay__btn::before {
  content: '';
  position: absolute;
  inset: 2px;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(255, 244, 214, 0.20) 0 1px, transparent 1px),
    linear-gradient(0deg, rgba(0, 0, 0, 0.3) 0 1px, transparent 1px);
}
.pay__btn::after {
  content: '';
  position: absolute;
  inset: 4px;
  pointer-events: none;
  background:
    linear-gradient(45deg, rgba(255, 236, 190, 0.5) 0 3px, transparent 3px) top left / 8px 8px no-repeat,
    linear-gradient(-45deg, rgba(255, 236, 190, 0.5) 0 3px, transparent 3px) top right / 8px 8px no-repeat,
    linear-gradient(135deg, rgba(0, 0, 0, 0.35) 0 3px, transparent 3px) bottom left / 8px 8px no-repeat,
    linear-gradient(-135deg, rgba(0, 0, 0, 0.35) 0 3px, transparent 3px) bottom right / 8px 8px no-repeat;
}
.pay__btn:hover {
  filter: brightness(1.12);
  transform: translateY(-1px);
}
.pay__btn:active {
  transform: translateY(3px);
  box-shadow:
    inset 0 0 0 1px rgba(255, 236, 190, 0.16),
    inset 0 3px 0 rgba(0, 0, 0, 0.34),
    0 1px 0 #180d04;
}
.pay__btn[data-rail="mon"] {
  background: linear-gradient(180deg, #8f6bd4 0%, #6f4fb0 41%, #7c5cbe 42%, #4d3382 100%);
}
.pay__btn[data-rail="usdc"] {
  background: linear-gradient(180deg, #5aa5e0 0%, #3d81bd 41%, #4a8fcb 42%, #2a5c8c 100%);
}
.pay__btn[data-rail="eth"] {
  background: linear-gradient(180deg, #8d93b8 0%, #6a708f 41%, #767d9d 42%, #474c66 100%);
}
.pay__btn[data-rail="sol"] {
  background: linear-gradient(180deg, #4fc9a8 0%, #2f9c81 41%, #3aab8e 42%, #1f6e5a 100%);
}
.pay__btn.is-soon { filter: saturate(0.35) brightness(0.86); }
.pay__soon.is-live {
  color: var(--teal);
  text-shadow: 0 0 10px rgba(79, 184, 158, 0.5);
}

/* ------------------------------------------------------------------ shell */
body.ck-open { overflow: hidden; }

.ck {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.ck[hidden] { display: none; }

.ck__scrim {
  position: absolute;
  inset: 0;
  background:
    repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.06) 0 4px, transparent 4px 8px),
    radial-gradient(ellipse 90% 70% at 50% 45%, rgba(26, 14, 8, 0.78), rgba(10, 5, 2, 0.93));
  backdrop-filter: blur(2px);
  animation: ck-fade 0.18s ease both;
}

.ck__card {
  position: relative;
  width: min(520px, 100%);
  max-height: calc(100vh - 40px);
  display: flex;
  flex-direction: column;
  background:
    repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.022) 0 5px, transparent 5px 10px),
    linear-gradient(180deg, var(--parchment-lt) 0%, var(--parchment) 46%, var(--parchment-dk) 100%);
  border: 6px solid var(--wood-deep);
  box-shadow:
    inset 0 0 0 2px var(--parchment-edge),
    inset 0 4px 0 rgba(255, 255, 255, 0.42),
    inset 0 -5px 0 rgba(0, 0, 0, 0.14),
    0 10px 0 var(--wood-black),
    0 18px 40px rgba(0, 0, 0, 0.55);
  animation: ck-rise 0.22s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
@keyframes ck-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ck-rise {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

/* -------------------------------------------------------------------- head */
.ck__head {
  position: relative;
  padding: 18px 54px 16px 20px;
  background:
    linear-gradient(180deg, var(--wood-light) 0%, var(--wood) 40%, var(--wood-dark) 41%, var(--wood-deep) 100%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 214, 138, 0.16),
    inset 0 2px 0 rgba(255, 226, 170, 0.24),
    0 4px 0 rgba(0, 0, 0, 0.34);
}
.ck__head::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -4px;
  height: 4px;
  background: repeating-linear-gradient(90deg, var(--gold-deep) 0 4px, var(--wood-black) 4px 8px);
  opacity: 0.7;
}
.ck__title {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--gold-bright);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.7);
}
.ck__sub {
  margin-top: 7px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.05em;
  color: var(--parchment-dk);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.55);
}
.ck__x {
  position: absolute;
  top: 14px; right: 14px;
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  font-size: 0.68rem;
  color: var(--parchment-lt);
  background: linear-gradient(180deg, #a04a34 0%, #8a2828 45%, #5a1818 100%);
  border: 3px solid var(--wood-black);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.2), 0 3px 0 var(--wood-black);
  cursor: pointer;
}
.ck__x:hover { filter: brightness(1.16); }
.ck__x:active { transform: translateY(2px); box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.3); }

/* -------------------------------------------------------------------- body */
.ck__body {
  padding: 20px;
  overflow-y: auto;
  color: var(--ink);
}
.ck__lead {
  font-size: 0.92rem;
  line-height: 1.62;
  color: var(--ink-soft);
}

/* A second, quieter paragraph. Used for the note telling an Ethereum payer
   that the address they already have works, which is reassurance rather than
   instruction and should not compete with the instruction above it. */
.ck__lead--soft {
  margin-top: 10px;
  padding-left: 10px;
  border-left: 3px solid var(--parchment-edge);
  font-size: 0.86rem;
  opacity: 0.9;
}

/* The 0x in the copy. Monospace makes it read as a literal thing to look for
   rather than a word. */
.ck__lead code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.95em;
  padding: 0 3px;
  background: rgba(0, 0, 0, 0.08);
  border-radius: 2px;
}
.ck__center { text-align: center; }

.ck__rows {
  margin: 16px 0 0;
  border: 3px solid var(--parchment-edge);
  background:
    repeating-linear-gradient(45deg, rgba(120, 85, 40, 0.05) 0 5px, transparent 5px 10px),
    linear-gradient(180deg, rgba(255, 255, 255, 0.4), rgba(0, 0, 0, 0.035));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), inset 0 -2px 0 rgba(0, 0, 0, 0.08);
}
.ck__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 14px;
  padding: 10px 12px;
  border-bottom: 1px solid rgba(120, 85, 40, 0.22);
}
.ck__row:last-child { border-bottom: 0; }
.ck__row dt {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
  flex: none;
  padding-top: 2px;
}
.ck__row dd {
  margin: 0;
  text-align: right;
  font-size: 0.9rem;
  color: var(--ink);
  word-break: break-word;
}
.ck__row dd b { color: var(--copper-deep); }
.ck__row dd a { color: var(--blue-deep); text-decoration: underline; }

/* ------------------------------------------------------------------- qty */
.ck__qty {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 12px;
  border: 3px solid var(--parchment-edge);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.42), rgba(0, 0, 0, 0.04));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.ck__qty-label {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.46rem;
  color: var(--ink-faint);
  margin-right: auto;
}
.ck__step {
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.6rem;
  color: var(--wood-deep);
  background: linear-gradient(180deg, var(--gold-bright) 0%, var(--gold) 44%, var(--gold-dark) 45%, var(--gold-deep) 100%);
  border: 3px solid var(--wood-deep);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.5), 0 3px 0 var(--wood-black);
  cursor: pointer;
}
.ck__step:hover { filter: brightness(1.1); }
.ck__step:active { transform: translateY(2px); box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.25); }
.ck__qty-n {
  min-width: 26px;
  text-align: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.7rem;
  color: var(--ink);
}
.ck__qty-max {
  width: 100%;
  font-size: 0.74rem;
  color: var(--ink-faint);
}

/* ----------------------------------------------------------------- field */
.ck__field { display: block; margin-top: 16px; }
.ck__field span {
  display: block;
  margin-bottom: 7px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
}
.ck__input {
  width: 100%;
  padding: 12px 12px;
  font-family: 'Pixelify Sans', monospace;
  font-size: 0.95rem;
  color: var(--ink);
  background: linear-gradient(180deg, #fff8e6 0%, #f2e0bb 100%);
  border: 3px solid var(--wood-deep);
  box-shadow: inset 0 3px 0 rgba(0, 0, 0, 0.14), inset 0 -2px 0 rgba(255, 255, 255, 0.55);
}
.ck__input:focus {
  outline: none;
  box-shadow: inset 0 3px 0 rgba(0, 0, 0, 0.14), 0 0 0 3px var(--gold);
}

.ck__note {
  margin-top: 12px;
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--ink-faint);
}
.ck__note.is-warn { color: var(--red-deep); }
.ck__note.is-ok { color: var(--teal-deep); }
.ck__note a { color: var(--blue-deep); text-decoration: underline; }

.ck__err {
  margin-top: 16px;
  padding: 10px 12px;
  font-size: 0.85rem;
  color: #ffe4dc;
  background: linear-gradient(180deg, #a03428 0%, #7a2418 100%);
  border: 3px solid var(--wood-black);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.16);
}

.ck__links { margin: 14px 0 0; padding-left: 18px; }
.ck__links li { margin-bottom: 7px; }
.ck__links a { color: var(--blue-deep); text-decoration: underline; }

/* ------------------------------------------------------------ spin / ok */
.ck__spin {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin: 12px 0 20px;
}
.ck__spin i {
  width: 12px; height: 12px;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold-dark));
  border: 2px solid var(--wood-deep);
  animation: ck-pulse 0.9s ease-in-out infinite;
}
.ck__spin i:nth-child(2) { animation-delay: 0.15s; }
.ck__spin i:nth-child(3) { animation-delay: 0.3s; }
@keyframes ck-pulse {
  0%, 100% { transform: translateY(0); opacity: 0.45; }
  50%      { transform: translateY(-7px); opacity: 1; }
}

.ck__ok {
  width: 58px; height: 58px;
  margin: 6px auto 16px;
  display: grid;
  place-items: center;
  font-size: 1.5rem;
  color: #0f3a2c;
  background: linear-gradient(180deg, #7ee0c0 0%, #4fb89e 44%, #3aa88e 45%, #2d8a72 100%);
  border: 4px solid var(--wood-deep);
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, 0.5),
    0 5px 0 var(--wood-black),
    0 0 22px rgba(79, 184, 158, 0.45);
  animation: ck-pop 0.34s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes ck-pop {
  from { transform: scale(0.5); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* -------------------------------------------------------------------- foot */
/* THE FOOTER BUTTONS, AND WHY THIS IS A GRID
   ----------------------------------------------------------------------------
   It was `display: flex` with `.ck__act { flex: 1 }`, which looks right and is
   a trap. `flex: 1` means `flex-basis: 0`, so both buttons are forced to the
   same width whatever their labels say, and `.btn` carries `overflow: hidden`,
   which makes a flex item's automatic minimum size resolve to zero. Together
   those let a button shrink smaller than its own text with nothing to stop it.
   `.btn` also has `white-space: nowrap` and a `clip-path`, so the text neither
   wraps nor spills, it is simply cut: "GET MY PAYMENT ADDRESS" was rendered as
   "T MY PAYMENT ADDRES", missing 44px off each end.

   A grid of `auto-fit` columns with a real minimum cannot do that. Two buttons
   sit side by side while both fit in 10.5rem, and drop to one per row when they
   do not, at whatever width that happens to be rather than at a viewport
   breakpoint somebody guessed. Wrapping is re-enabled below so a long label
   takes two lines instead of being trimmed. */
.ck__foot {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  gap: 10px;
  padding: 16px 20px 20px;
  border-top: 3px solid var(--parchment-edge);
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.05), transparent);
}
.ck__foot:empty { display: none; }

.ck__act {
  text-align: center;
  justify-content: center;

  /* `.btn` sets nowrap for buttons that sit in a row of their own. In here a
     label has a column to fit into, so let it use two lines. */
  white-space: normal;
  line-height: 1.45;
  min-width: 0;

  /* 28px each side is a lot of the width when the width is a grid column. */
  padding-left: 14px;
  padding-right: 14px;
}

/* ------------------------------------------------------------------ mobile */
@media (max-width: 600px) {
  .ck { padding: 10px; }
  .ck__card { max-height: calc(100vh - 20px); }
  .ck__body { padding: 16px; }
  /* One column, primary action last, closest to the thumb. The grid above
     already stacks them when they do not fit; this fixes the order. */
  .ck__foot { grid-template-columns: 1fr; padding: 14px 16px 16px; }
  .ck__foot > :first-child { order: 2; }
  .ck__row { flex-direction: column; gap: 3px; }
  .ck__row dd { text-align: left; }
}

@media (prefers-reduced-motion: reduce) {
  .ck__scrim, .ck__card, .ck__ok { animation: none; }
  .ck__spin i { animation-duration: 1.6s; }
  .pay__btn { transition: none; }
}

/* ============================================================================
   WALLET CHIP, VAULT AND PACK REVEAL
   ========================================================================== */

/* ------------------------------------------------------------- nav chip */
.nav__wallet { display: flex; align-items: center; }

.wchip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 13px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.04em;
  color: var(--parchment-lt);
  cursor: pointer;
  border: 3px solid var(--wood-black);
  background: linear-gradient(180deg, #7a5630 0%, #5f421f 42%, #6b4a25 43%, #3d2811 100%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 214, 138, 0.16),
    inset 0 2px 0 rgba(255, 226, 170, 0.24),
    0 3px 0 var(--wood-black),
    0 5px 8px rgba(0, 0, 0, 0.3);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.6);
  transition: filter 0.14s ease, transform 0.09s ease;
}
.wchip:hover { filter: brightness(1.14); }
.wchip:active { transform: translateY(2px); box-shadow: inset 0 2px 0 rgba(0,0,0,0.3); }
.wchip:disabled { opacity: 0.6; cursor: wait; }

.wchip__dot {
  width: 8px; height: 8px;
  flex: none;
  background: var(--stone-dark);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.wchip.is-on { border-color: var(--gold-deep); }
.wchip.is-on .wchip__dot {
  background: var(--teal);
  box-shadow: 0 0 8px rgba(79, 184, 158, 0.85), inset 0 1px 0 rgba(255,255,255,0.5);
}
.wchip.is-warn .wchip__dot { background: var(--copper-light); box-shadow: 0 0 8px rgba(217,122,74,0.8); }
.wchip__warn {
  font-style: normal;
  font-size: 0.42rem;
  color: var(--gold-bright);
  border-left: 1px solid rgba(255, 214, 138, 0.3);
  padding-left: 7px;
}

.wmenu {
  position: absolute;
  z-index: 950;
  width: 218px;
  padding: 8px;
  background: linear-gradient(180deg, var(--parchment-lt), var(--parchment-dk));
  border: 4px solid var(--wood-deep);
  box-shadow: inset 0 0 0 2px var(--parchment-edge), 0 8px 0 var(--wood-black), 0 14px 26px rgba(0,0,0,0.45);
}
.wmenu__addr {
  padding: 7px 8px 9px;
  font-size: 0.72rem;
  word-break: break-all;
  color: var(--ink-faint);
  border-bottom: 2px solid var(--parchment-edge);
  margin-bottom: 6px;
}
.wmenu button {
  display: block;
  width: 100%;
  padding: 9px 8px;
  text-align: left;
  font-size: 0.86rem;
  color: var(--ink);
  background: transparent;
  border: 0;
  cursor: pointer;
}
.wmenu button:hover { background: rgba(120, 85, 40, 0.14); }
.wmenu button.is-danger { color: var(--red-deep); }

/* --------------------------------------------------------------- toast */
.wtoast {
  position: fixed;
  left: 50%; bottom: 26px;
  transform: translateX(-50%);
  z-index: 1000;
  max-width: min(460px, calc(100vw - 32px));
  padding: 12px 16px;
  font-size: 0.88rem;
  color: var(--parchment-lt);
  background: linear-gradient(180deg, #5f421f 0%, #3d2811 100%);
  border: 3px solid var(--wood-black);
  box-shadow: inset 0 2px 0 rgba(255, 226, 170, 0.22), 0 6px 0 var(--wood-black), 0 12px 24px rgba(0,0,0,0.45);
  animation: ck-rise 0.2s ease both;
}
.wtoast.is-out { opacity: 0; transition: opacity 0.5s ease; }

/* -------------------------------------------------------- tier price block */
.tier__price { line-height: 1.3; }
.tier__usd {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 1rem;
  color: var(--copper);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.16);
}
.tier__crypto {
  display: block;
  margin-top: 8px;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

/* ---------------------------------------------------------- checkout total */
.ck__total {
  margin-top: 16px;
  padding: 16px 14px;
  text-align: center;
  border: 3px solid var(--wood-deep);
  background:
    repeating-linear-gradient(45deg, rgba(0,0,0,0.035) 0 5px, transparent 5px 10px),
    linear-gradient(180deg, #fff6e0 0%, #f2ddb0 52%, #e2c78e 100%);
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.7), inset 0 -3px 0 rgba(0,0,0,0.1), 0 4px 0 var(--wood-black);
}
.ck__total-crypto {
  font-family: 'Press Start 2P', monospace;
  font-size: 1.1rem;
  color: var(--ink);
  text-shadow: 0 2px 0 rgba(255, 255, 255, 0.6);
}
.ck__total-crypto b { color: var(--copper-deep); }
.ck__total-usd { margin-top: 10px; }
.ck__usd {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.76rem;
  color: var(--teal-deep);
}
.ck__usd.is-off { color: var(--ink-faint); font-size: 0.55rem; }
.ck__usd-src {
  display: block;
  margin-top: 7px;
  font-size: 0.74rem;
  color: var(--ink-faint);
}

/* ---------------------------------------------------------------- vault */
.vault__head { margin-bottom: 34px; }

.vault__state {
  padding: 26px 22px;
  text-align: center;
  border: 4px solid var(--wood-deep);
  background:
    repeating-linear-gradient(45deg, rgba(120,85,40,0.045) 0 5px, transparent 5px 10px),
    linear-gradient(180deg, var(--parchment-lt), var(--parchment-dk));
  box-shadow: inset 0 0 0 2px var(--parchment-edge), inset 0 3px 0 rgba(255,255,255,0.5), 0 6px 0 var(--wood-black);
}
.vault__state h2 {
  font-size: 0.95rem;
  margin-bottom: 12px;
}
.vault__state p { max-width: 620px; margin: 0 auto 18px; color: var(--ink-soft); }
.vault__state .ck__links { display: inline-block; text-align: left; }

.vault__id {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 16px 18px;
  border: 4px solid var(--wood-deep);
  background: linear-gradient(180deg, var(--parchment-lt), var(--parchment-dk));
  box-shadow: inset 0 0 0 2px var(--parchment-edge), inset 0 3px 0 rgba(255,255,255,0.5), 0 6px 0 var(--wood-black);
}
.vault__avatar {
  width: 46px; height: 46px;
  flex: none;
  display: grid;
  place-items: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.7rem;
  color: var(--wood-deep);
  background: linear-gradient(180deg, var(--gold-bright) 0%, var(--gold) 44%, var(--gold-dark) 45%, var(--gold-deep) 100%);
  border: 3px solid var(--wood-deep);
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.55), 0 3px 0 var(--wood-black);
}
.vault__id-text { margin-right: auto; }
.vault__addr {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.68rem;
  color: var(--ink);
}
.vault__meta { margin-top: 7px; font-size: 0.8rem; color: var(--ink-faint); }

.vault__h {
  margin: 42px 0 18px;
  font-size: 0.9rem;
  padding-bottom: 12px;
  border-bottom: 3px solid var(--parchment-edge);
}
.vault__lead { color: var(--ink-soft); max-width: 720px; }

.vault__empty {
  padding: 30px 22px;
  text-align: center;
  border: 3px dashed var(--parchment-edge);
  background: repeating-linear-gradient(45deg, rgba(120,85,40,0.05) 0 6px, transparent 6px 12px);
}
.vault__empty h3 { font-size: 0.75rem; margin-bottom: 10px; }
.vault__empty p { color: var(--ink-faint); max-width: 560px; margin: 0 auto; }
.vault__cta { margin-top: 18px; text-align: center; }

.vault__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: 18px;
}
.packcard {
  padding: 16px;
  text-align: center;
  border: 4px solid var(--wood-deep);
  background: linear-gradient(180deg, var(--parchment-lt), var(--parchment-dk));
  box-shadow: inset 0 0 0 2px var(--parchment-edge), inset 0 3px 0 rgba(255,255,255,0.5), 0 6px 0 var(--wood-black);
}
.packcard__art { aspect-ratio: 3 / 4; margin-bottom: 14px; }
.packcard__name { font-family: 'Press Start 2P', monospace; font-size: 0.72rem; color: var(--ink); }
.packcard__sub { margin-top: 9px; font-size: 0.82rem; color: var(--ink-faint); min-height: 2.4em; }
.packcard__qty {
  margin: 12px 0 14px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  color: var(--copper);
}
.packcard__open { width: 100%; justify-content: center; text-align: center; }

.vault__cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 14px;
}
.minicard {
  position: relative;
  padding: 10px;
  border: 3px solid var(--wood-deep);
  background: linear-gradient(180deg, var(--parchment-lt), var(--parchment-dk));
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.5), 0 4px 0 var(--wood-black);
}
.minicard__art { aspect-ratio: 3 / 4; }
.minicard__id {
  margin-top: 9px;
  text-align: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.44rem;
  color: var(--ink-faint);
}
.minicard__qty {
  position: absolute;
  top: 6px; right: 6px;
  padding: 3px 6px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.42rem;
  color: var(--wood-deep);
  background: var(--gold);
  border: 2px solid var(--wood-deep);
}

.vault__link { margin-top: 18px; }
.vault__code {
  margin-top: 18px;
  padding: 18px;
  text-align: center;
  border: 3px solid var(--wood-deep);
  background: linear-gradient(180deg, #fff6e0, #e2c78e);
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.7), 0 4px 0 var(--wood-black);
}
.vault__code-value {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  color: var(--copper-deep);
  word-break: break-all;
}
.vault__raw { margin-top: 14px; text-align: left; }
.vault__raw summary { cursor: pointer; font-size: 0.82rem; color: var(--blue-deep); }
.vault__raw pre {
  margin-top: 10px;
  padding: 12px;
  overflow-x: auto;
  font-size: 0.74rem;
  color: var(--parchment-lt);
  background: var(--wood-black);
  border: 2px solid var(--wood-deep);
}

/* --------------------------------------------------------- pack reveal */
.rv { position: fixed; inset: 0; z-index: 940; display: flex; align-items: center; justify-content: center; padding: 20px; }
.rv[hidden] { display: none; }
.rv__scrim {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse 80% 65% at 50% 45%, rgba(26,14,8,0.8), rgba(8,4,2,0.95));
  animation: ck-fade 0.2s ease both;
}
.rv__card {
  position: relative;
  width: min(660px, 100%);
  padding: 30px 24px 26px;
  text-align: center;
  border: 6px solid var(--wood-deep);
  background:
    repeating-linear-gradient(45deg, rgba(0,0,0,0.022) 0 5px, transparent 5px 10px),
    linear-gradient(180deg, var(--parchment-lt) 0%, var(--parchment) 48%, var(--parchment-dk) 100%);
  box-shadow: inset 0 0 0 2px var(--parchment-edge), inset 0 4px 0 rgba(255,255,255,0.45), 0 10px 0 var(--wood-black), 0 18px 40px rgba(0,0,0,0.55);
  animation: ck-rise 0.24s cubic-bezier(0.22,0.61,0.36,1) both;
}
.rv__title {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.9rem;
  color: var(--copper-deep);
  margin-bottom: 16px;
}
.rv__msg { color: var(--ink-soft); margin-top: 10px; }
.rv__msg a { color: var(--blue-deep); text-decoration: underline; }

.rv__pack { display: flex; justify-content: center; gap: 10px; margin: 22px 0 8px; }
.rv__pack span {
  /* 4 Sep 2026: per the pack_drawing_screen_rework mock, the drawing
     animation shakes the REAL pack art, not a gold rectangle. */
  width: 64px; height: 90px;
  background: url('assets/pack_card_main.png') center / contain no-repeat;
  border: none;
  box-shadow: none;
  filter: drop-shadow(0 0 10px rgba(244, 199, 94, 0.55));
  image-rendering: pixelated;
  animation: rv-shake 0.7s ease-in-out infinite;
}
.rv__pack span:nth-child(2) { animation-delay: 0.1s; }
.rv__pack span:nth-child(3) { animation-delay: 0.2s; }
@keyframes rv-shake {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50%      { transform: translateY(-8px) rotate(2deg); }
}

.rv__cards {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 14px;
  margin: 24px 0 22px;
}
.rv__c {
  width: 124px;
  padding: 8px;
  border: 3px solid var(--wood-deep);
  background: linear-gradient(180deg, var(--parchment-lt), var(--parchment-dk));
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.5), 0 5px 0 var(--wood-black), 0 0 22px rgba(244,199,94,0.35);
  animation: rv-flip 0.5s cubic-bezier(0.34, 1.4, 0.64, 1) both;
}
.rv__c-art { aspect-ratio: 3 / 4; }
.rv__c-id {
  margin-top: 8px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.42rem;
  color: var(--ink-faint);
}
@keyframes rv-flip {
  from { opacity: 0; transform: rotateY(90deg) translateY(14px); }
  to   { opacity: 1; transform: none; }
}
.rv__close { margin-top: 6px; }

@media (max-width: 700px) {
  .wchip span { display: none; }
  .wchip { padding: 9px 10px; }
  .vault__id { justify-content: center; text-align: center; }
  .vault__id-text { margin-right: 0; width: 100%; }
  .rv__c { width: 100px; }
}

@media (prefers-reduced-motion: reduce) {
  .rv__pack span, .rv__c, .rv__scrim, .rv__card, .wtoast { animation: none; }
}

/* code entry on the vault */
.vault__codein {
  max-width: 260px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-align: center;
  text-transform: uppercase;
}
.vault__link .ck__field { margin-top: 0; margin-bottom: 16px; }

/* ============================================================================
   TESTNET BAND
   Injected by wallet.js on every page while network is not 'mainnet'. It sits
   above everything, including the sticky nav, because a buyer who misses it
   might think they bought something real.
   ========================================================================== */
.tnet {
  position: relative;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px 14px;
  padding: 9px 18px;
  text-align: center;
  font-size: 0.8rem;
  line-height: 1.5;
  color: #2a1a06;
  background:
    repeating-linear-gradient(45deg,
      rgba(0, 0, 0, 0.13) 0 10px, transparent 10px 20px),
    linear-gradient(180deg, #ffcf5e 0%, #e9a92c 55%, #c9871a 100%);
  border-bottom: 3px solid var(--wood-black, #1c1109);
  box-shadow: inset 0 2px 0 rgba(255, 246, 214, 0.55), 0 3px 0 rgba(0, 0, 0, 0.22);
}
.tnet b {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  padding: 4px 8px;
  color: #ffe9b8;
  background: #3d2811;
  border: 2px solid #1c1109;
  box-shadow: inset 0 2px 0 rgba(255, 226, 170, 0.2);
}
.tnet span { max-width: 84ch; }
.tnet a {
  color: #2a1a06;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.tnet a:hover { color: #000; }

/* the nav sticks under the band instead of over it */
body.has-tnet .nav { top: 0; }

@media (max-width: 620px) {
  .tnet { font-size: 0.74rem; padding: 8px 12px; }
  .tnet b { font-size: 0.58rem; }
}

/* ============================================================================
   WALLET PICKER
   Only appears when the buyer has more than one wallet installed and has not
   chosen yet. Built by wallet.js so every page gets it, not just checkout.
   ========================================================================== */
.wpick {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.wpick__scrim {
  position: absolute;
  inset: 0;
  background: rgba(20, 12, 4, 0.72);
  backdrop-filter: blur(2px);
}
.wpick__card {
  position: relative;
  width: min(400px, 100%);
  padding: 22px 22px 18px;
  background:
    repeating-linear-gradient(45deg, rgba(0,0,0,0.03) 0 5px, transparent 5px 10px),
    linear-gradient(180deg, #fff6e0 0%, #f2ddb0 55%, #e2c78e 100%);
  border: 4px solid var(--wood-black, #1c1109);
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, 0.7),
    inset 0 -4px 0 rgba(0, 0, 0, 0.12),
    0 8px 0 var(--wood-black, #1c1109),
    0 18px 36px rgba(0, 0, 0, 0.5);
  animation: ck-rise 0.18s ease both;
}
.wpick__title {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.82rem;
  color: var(--wood-deep, #3d2811);
  margin-bottom: 12px;
}
.wpick__lead {
  font-size: 0.84rem;
  line-height: 1.55;
  color: var(--ink-faint, #6b5636);
  margin: 0 0 16px;
}
.wpick__list { display: grid; gap: 8px; }
.wpick__opt {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 13px;
  text-align: left;
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  color: var(--wood-deep, #3d2811);
  background: linear-gradient(180deg, #fffaf0 0%, #f0dcb4 100%);
  border: 3px solid var(--wood-deep, #3d2811);
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.8), 0 3px 0 var(--wood-black, #1c1109);
}
.wpick__opt:hover {
  background: linear-gradient(180deg, #fff, #f7e7c4);
  transform: translateY(-1px);
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.9), 0 4px 0 var(--wood-black, #1c1109);
}
.wpick__opt:active { transform: translateY(2px); box-shadow: inset 0 2px 0 rgba(255,255,255,0.6), 0 1px 0 var(--wood-black, #1c1109); }
.wpick__opt img,
.wpick__blank {
  width: 28px; height: 28px;
  flex: 0 0 28px;
  border: 2px solid var(--wood-deep, #3d2811);
  image-rendering: auto;
  background: #e8d4a8;
}
.wpick__x {
  display: block;
  margin: 16px auto 0;
  padding: 7px 16px;
  font: inherit;
  font-size: 0.82rem;
  cursor: pointer;
  color: var(--ink-faint, #6b5636);
  background: none;
  border: 2px solid transparent;
}
.wpick__x:hover { color: var(--wood-deep, #3d2811); border-color: var(--wood-deep, #3d2811); }

/* ============================================================================
   THE ODDS TABLE
   On the card pack page. Publishing the odds next to the supply is the point:
   the two numbers are the same claim checked twice, and anyone can verify the
   second one on chain.
   ========================================================================== */
.odds {
  max-width: 720px;
  margin: 34px auto 22px;
  border: 4px solid var(--wood-black, #1c1109);
  box-shadow: inset 0 3px 0 rgba(255, 255, 255, 0.5), 0 6px 0 var(--wood-black, #1c1109);
  background: linear-gradient(180deg, #fff6e0 0%, #f2ddb0 60%, #e2c78e 100%);
}
.odds__row {
  display: grid;
  grid-template-columns: 1.2fr 0.8fr 1fr 1fr;
  gap: 10px;
  align-items: center;
  padding: 12px 16px;
  font-size: 0.9rem;
  color: var(--wood-deep, #3d2811);
  border-bottom: 2px solid rgba(61, 40, 17, 0.18);
}
.odds__row:last-child { border-bottom: 0; }
.odds__row span:not(:first-child) {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.72rem;
  text-align: right;
}
.odds__row--head {
  background: linear-gradient(180deg, #5f421f 0%, #3d2811 100%);
  color: var(--parchment-lt, #f4e4c1);
  border-bottom: 4px solid var(--wood-black, #1c1109);
}
.odds__row--head span {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.04em;
  text-align: right;
}
.odds__row--head span:first-child { text-align: left; }

/* a colour flag per rarity, matching the card frames */
.odds__row span:first-child { position: relative; padding-left: 18px; font-weight: 700; }
.odds__row:not(.odds__row--head) span:first-child::before {
  content: '';
  position: absolute;
  left: 0; top: 50%;
  width: 10px; height: 10px;
  transform: translateY(-50%);
  border: 2px solid var(--wood-black, #1c1109);
}
.odds__row.is-common    span:first-child::before { background: #b8b2a6; }
.odds__row.is-uncommon  span:first-child::before { background: #6fbf73; }
.odds__row.is-rare      span:first-child::before { background: #5a9ede; }
.odds__row.is-legendary span:first-child::before { background: #f0b23c; }

/* the card pack page has one product, so do not stretch it across the grid */
.tiers--single {
  display: flex;
  justify-content: center;
}
.tiers--single .tier { max-width: 380px; width: 100%; }

@media (max-width: 620px) {
  .odds__row { grid-template-columns: 1.1fr 0.7fr 0.9fr 0.9fr; padding: 10px 11px; font-size: 0.8rem; gap: 6px; }
  .odds__row span:not(:first-child) { font-size: 0.58rem; }
  .odds__row--head span { font-size: 0.5rem; }
}

/* one product in the vault, so do not stretch it across a full grid */
.vault__grid--single { display: flex; justify-content: center; }
.vault__grid--single .packcard { max-width: 340px; width: 100%; }
.packcard .btn + .btn { margin-top: 8px; }
.vault__cta { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

/* ============================================================================
   THE EMAIL FIELD
   One field, asked once, on the review screen. Copy explains why it is being
   asked, because "give us your email" with no reason is where people leave.
   ========================================================================== */
.ck__email {
  display: block;
  margin-top: 16px;
  padding: 13px 14px;
  border: 3px solid var(--wood-deep, #3d2811);
  background: linear-gradient(180deg, #fffaf0 0%, #f4e2ba 100%);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.75);
}
.ck__email-label {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  color: var(--wood-deep, #3d2811);
  margin-bottom: 8px;
}
.ck__email input {
  display: block;
  width: 100%;
  padding: 10px 11px;
  font: inherit;
  font-size: 0.95rem;
  color: var(--wood-deep, #3d2811);
  background: #fffdf6;
  border: 3px solid var(--wood-deep, #3d2811);
  box-shadow: inset 0 2px 4px rgba(61, 40, 17, 0.16);
}
.ck__email input:focus {
  outline: none;
  border-color: var(--copper, #b5711f);
  box-shadow: inset 0 2px 4px rgba(61,40,17,0.16), 0 0 0 3px rgba(181, 113, 31, 0.28);
}
.ck__email input.is-bad {
  border-color: #a33c2e;
  box-shadow: inset 0 2px 4px rgba(61,40,17,0.16), 0 0 0 3px rgba(163, 60, 46, 0.25);
}
.ck__email-note {
  display: block;
  margin-top: 8px;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--ink-faint, #6b5636);
}
/* `display: block` beats the browser's own [hidden] rule, so an error message
   set up to be revealed later would sit there from the moment the form loaded.
   Anything that toggles with [hidden] needs this. */
.ck__email-err[hidden],
.ck__signed[hidden] { display: none !important; }

.ck__email-err {
  display: block;
  margin-top: 7px;
  font-size: 0.8rem;
  font-weight: 700;
  color: #a33c2e;
}

/* ============================================================================
   PAYING FROM ANOTHER CHAIN
   ----------------------------------------------------------------------------
   The buyer is about to send real money to an address by hand. Everything here
   is sized and spaced so the two things that matter, the amount and the
   address, are the two things impossible to misread.
   ========================================================================== */

/* pick-a-destination buttons on the recipient screen */
.ck__pick {
  display: block;
  width: 100%;
  margin-bottom: 10px;
  padding: 12px 14px;
  text-align: left;
  font: inherit;
  cursor: pointer;
  color: var(--wood-deep, #3d2811);
  background: linear-gradient(180deg, #fffaf0 0%, #f0dcb4 100%);
  border: 3px solid var(--wood-deep, #3d2811);
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.8), 0 3px 0 var(--wood-black, #1c1109);
}
.ck__pick:hover { background: linear-gradient(180deg, #fff, #f7e7c4); transform: translateY(-1px); }
.ck__pick:active { transform: translateY(2px); box-shadow: inset 0 2px 0 rgba(255,255,255,0.6), 0 1px 0 var(--wood-black, #1c1109); }
.ck__pick b { display: block; font-size: 0.95rem; }
.ck__pick span { display: block; margin-top: 3px; font-size: 0.78rem; color: var(--ink-faint, #6b5636); }

/* the address field wants to be monospace, it is going to be checked by eye */
.ck__evm input {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.86rem;
  letter-spacing: 0.02em;
}

/* the payment card: amount, then address, nothing competing with them */
.ck__pay {
  margin: 16px 0 10px;
  padding: 18px 16px;
  text-align: center;
  border: 4px solid var(--wood-black, #1c1109);
  background:
    repeating-linear-gradient(45deg, rgba(0,0,0,0.035) 0 5px, transparent 5px 10px),
    linear-gradient(180deg, #fff6e0 0%, #f2ddb0 55%, #e2c78e 100%);
  box-shadow: inset 0 3px 0 rgba(255,255,255,0.7), 0 5px 0 var(--wood-black, #1c1109);
}
.ck__pay-amt {
  font-family: 'Press Start 2P', monospace;
  font-size: 1.15rem;
  line-height: 1.4;
  color: var(--wood-deep, #3d2811);
  word-break: break-all;
}
.ck__pay-amt b { color: var(--copper, #b5711f); }
.ck__pay-short {
  margin-top: 7px;
  font-size: 0.82rem;
  font-weight: 700;
  color: #a33c2e;
}
.ck__pay-to {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding: 9px 10px;
  background: #fffdf6;
  border: 3px solid var(--wood-deep, #3d2811);
  box-shadow: inset 0 2px 4px rgba(61,40,17,0.16);
}
.ck__pay-to code {
  flex: 1 1 auto;
  min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78rem;
  line-height: 1.5;
  word-break: break-all;
  text-align: left;
  color: var(--wood-deep, #3d2811);
}
.ck__pay-to .btn { flex: 0 0 auto; }
.ck__pay-net {
  margin-top: 9px;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint, #6b5636);
}

@media (max-width: 520px) {
  .ck__pay-amt { font-size: 0.92rem; }
  .ck__pay-to { flex-direction: column; align-items: stretch; }
  .ck__pay-to .btn { width: 100%; }
}

/* ============================================================================
   THE DRAW REEL
   ----------------------------------------------------------------------------
   The chain genuinely needs a block produced before a card can be known, and
   the relayer needs a second to finish. That is real waiting. A spinner makes a
   second feel like five; a reel makes the same second feel like the good part.
   It is also honest: it spins because the outcome is not decided yet.
   ========================================================================== */
.rv__reel {
  position: relative;
  overflow: hidden;
  margin: 22px 0 14px;
  padding: 10px 0;
  border: 4px solid var(--wood-black, #1c1109);
  background: linear-gradient(180deg, #2a1d10 0%, #16100a 100%);
  box-shadow: inset 0 3px 10px rgba(0,0,0,0.6);
}
/* fade the ends so tiles arrive and leave rather than popping */
.rv__reel::before,
.rv__reel::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  width: 64px;
  z-index: 2;
  pointer-events: none;
}
.rv__reel::before { left: 0;  background: linear-gradient(90deg, #16100a, transparent); }
.rv__reel::after  { right: 0; background: linear-gradient(270deg, #16100a, transparent); }

.rv__reel-track {
  display: flex;
  gap: 8px;
  will-change: transform;
}
.rv__cell {
  flex: 0 0 auto;
  width: 58px;
  aspect-ratio: 3 / 4;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 5px;
  border: 3px solid var(--wood-black, #1c1109);
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.22);
}
.rv__cell span {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.44rem;
  color: rgba(0, 0, 0, 0.55);
}
.rv__cell.is-common    { background: linear-gradient(180deg, #cfc9bd, #a8a294); }
.rv__cell.is-uncommon  { background: linear-gradient(180deg, #8bd48f, #56a95c); }
.rv__cell.is-rare      { background: linear-gradient(180deg, #7fb8ec, #4a86c9); }
.rv__cell.is-legendary { background: linear-gradient(180deg, #ffd97a, #e0a12a); }

/* the fixed marker the reel lands under */
.rv__reel-marker {
  position: absolute;
  top: -2px; bottom: -2px;
  left: 50%;
  width: 66px;
  transform: translateX(-50%);
  z-index: 3;
  border: 3px solid var(--gold, #f4c75e);
  box-shadow: 0 0 14px rgba(244, 199, 94, 0.55), inset 0 0 14px rgba(244, 199, 94, 0.2);
  pointer-events: none;
}
.rv__reel-marker::before,
.rv__reel-marker::after {
  content: '';
  position: absolute;
  left: 50%;
  margin-left: -6px;
  border: 6px solid transparent;
}
.rv__reel-marker::before { top: -14px; border-top-color: var(--gold, #f4c75e); }
.rv__reel-marker::after  { bottom: -14px; border-bottom-color: var(--gold, #f4c75e); }

/* the card landing, once the reel stops */
.rv__c.is-landed { animation: rv-land 0.5s cubic-bezier(0.2, 1.5, 0.4, 1) both; }
@keyframes rv-land {
  0%   { opacity: 0; transform: scale(0.6) translateY(14px); }
  60%  { opacity: 1; transform: scale(1.06) translateY(0); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .rv__reel-track { transform: none !important; }
  .rv__c.is-landed { animation: none; }
}
@media (max-width: 520px) {
  .rv__cell { width: 46px; }
  .rv__reel-marker { width: 54px; }
}

/* the six digit code field, sized so the digits are the whole point */
.ck__code {
  text-align: center;
  font-family: 'Press Start 2P', monospace !important;
  font-size: 1.1rem !important;
  letter-spacing: 0.35em;
  text-indent: 0.35em;
}

/* already signed in, so the checkout states the account rather than asking */
.ck__signed {
  margin-top: 16px;
  padding: 13px 14px;
  border: 3px solid var(--wood-deep, #3d2811);
  background: linear-gradient(180deg, #f0f7ec 0%, #dcecd2 100%);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.75);
}
.ck__signed b {
  display: block;
  margin: 4px 0 6px;
  font-size: 0.98rem;
  color: var(--wood-deep, #3d2811);
  word-break: break-all;
}

/* the sign-in chip, quieter than the wallet chip until it has something to say */
.wchip--ghost {
  background: linear-gradient(180deg, #4a3520 0%, #2f2011 100%) !important;
  color: var(--parchment-lt, #f4e4c1) !important;
}

/* ============================================================================
   POLISH PASS
   Ketema on the 13 Aug call: "UI wise, this could use some work." These are the
   things that read as unfinished rather than as style choices.
   ========================================================================== */

/* 1. The tier cards were all the same weight, so nothing led the eye. The
      featured one now sits forward, and the flag reads as a ribbon rather than
      a floating word. */
.tier { transition: transform 0.16s ease, box-shadow 0.16s ease; }
.tier:hover { transform: translateY(-3px); }
.tier--featured { position: relative; }
.tier__flag {
  position: absolute;
  /* Fully clear of the card, not straddling it. The card has a heavy 5px
     border and the ribbon has its own 3px one, so overlapping them puts two
     thick dark lines through each other and reads as a collision rather than
     a label. */
  /* `top: auto` is load-bearing. styles.css sets `top: -16px` on this same
     element, and when an absolutely positioned box has BOTH top and bottom
     with a real height, top wins and bottom is ignored. Without this the
     ribbon quietly kept its old position. */
  top: auto;
  bottom: 100%; left: 50%;
  /* bottom:100% lands on the card's PADDING box, which is inside its 5px
     border, and the ribbon has a 3px drop shadow of its own below it. Both
     have to be cleared or it still touches. */
  margin-bottom: 14px;
  transform: translateX(-50%);
  z-index: 3;
  padding: 6px 16px 5px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.1em;
  white-space: nowrap;
  color: #2a1a06;
  background: linear-gradient(180deg, #ffd97a 0%, #e0a12a 100%);
  border: 3px solid var(--wood-black, #1c1109);
  box-shadow: 0 3px 0 var(--wood-black, #1c1109);
}
.tier--featured .tier__slot { margin-top: 6px; }

/* 2. The price block ran together. The dollar figure is the decision, the
      crypto amount is the detail, so they should not be the same size. */
.tier__usd { font-size: 1.35rem !important; line-height: 1.35; }
.tier__crypto { font-size: 0.76rem !important; opacity: 0.85; }
.tier__tbd { font-size: 0.72rem; font-style: italic; opacity: 0.8; }

/* 3. The reward list had no rhythm. Ticks and a hanging indent make it scan. */
.tier__list { margin: 16px 0 18px; }
.tier__list li {
  position: relative;
  padding-left: 19px;
  margin-bottom: 7px;
  line-height: 1.5;
}
.tier__list li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.42em;
  width: 9px; height: 5px;
  border-left: 2.5px solid var(--copper, #b5711f);
  border-bottom: 2.5px solid var(--copper, #b5711f);
  transform: rotate(-45deg);
}
/* the headline reward of each tier, called out */
.tier__list li b:first-child { color: var(--copper, #b5711f); }

/* 4. The pay row had no label hierarchy and the buttons were timid. */
.pay__label {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.12em;
  opacity: 0.7;
  margin-bottom: 7px;
}
.pay__row { gap: 7px; }
.pay__btn { min-width: 62px; font-weight: 700; }
.pay__btn:not(.is-soon):hover { filter: brightness(1.07); transform: translateY(-1px); }
.pay__soon.is-live {
  color: #2f7d43;
  font-weight: 700;
}
.pay__soon.is-live::before {
  content: '';
  display: inline-block;
  width: 7px; height: 7px;
  margin-right: 6px;
  border-radius: 50%;
  background: #3ea55b;
  box-shadow: 0 0 0 3px rgba(62, 165, 91, 0.25);
  animation: pay-pulse 1.8s ease-in-out infinite;
}
@keyframes pay-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(62,165,91,0.25); }
  50%      { box-shadow: 0 0 0 6px rgba(62,165,91,0.08); }
}

/* 5. The vault's empty state was a grey box with no way forward. */
.vault__empty {
  padding: 34px 22px;
  text-align: center;
  border: 3px dashed var(--wood-deep, #3d2811);
  background: rgba(255, 246, 224, 0.55);
}
.vault__empty h3 {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.8rem;
  margin-bottom: 12px;
  color: var(--wood-deep, #3d2811);
}
.vault__empty p { max-width: 46ch; margin: 0 auto; color: var(--ink-faint, #6b5636); }
.vault__cta { margin-top: 20px; }

/* 6. Modal buttons were the same size as body text and easy to miss. */
.ck__act { min-width: 132px; }
.ck__foot { gap: 9px; }

@media (prefers-reduced-motion: reduce) {
  .tier:hover, .pay__btn:hover { transform: none; }
  .pay__soon.is-live::before { animation: none; }
}
@media (max-width: 620px) {
  .tier__usd { font-size: 1.1rem !important; }
  .ck__act { min-width: 0; flex: 1 1 auto; }
}


/* A warning that is not an error. Used where getting it wrong costs money but
   nothing has gone wrong yet, such as sending on the wrong Solana network. */
.ck__warn {
  margin: 10px 0 0;
  padding: 9px 12px;
  border: 3px solid var(--wine, #7a3b3b);
  background: rgba(122, 59, 59, 0.10);
  color: var(--ink);
  font-size: 0.82rem;
  line-height: 1.5;
}


/* A second, quieter line under a vault message. Used for the explanation of
   why a wallet connection is unavoidable, which is worth saying once and not
   worth shouting. */
.vault__hint {
  margin-top: 8px;
  font-size: 0.86rem;
  opacity: 0.82;
}

/* A 42 character address has no spaces in it, so it will not wrap on its own
   and pushes the whole page sideways on a phone. It is shown in full on
   purpose, because a shortened one cannot be checked against a wallet, so the
   answer is to let it break rather than to hide half of it. */
.vault__hint code,
.vault__state code,
.ck__note code,
.ck__lead code {
  overflow-wrap: anywhere;
  word-break: break-all;
}

/* The buy panel on the trading card page. It sits inside the wood hero rather
   than on parchment, so the label needs the light treatment. */
.pack-hero__pay { margin: 22px 0 10px; }
.pack-hero__pay .pay__label { color: var(--gold-bright, #f0c674); }
.pack-hero__note {
  margin: 0 0 18px;
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--cream-soft, #e8dcc8);
  opacity: 0.9;
}
.pack-hero__note a { color: var(--gold-bright, #f0c674); }

/* ============================================================================
   THE CARD SET, AND THE RULES THAT GOVERN IT
   ========================================================================== */

/* ---------------------------------------------------------------- equip rules */
.rules { display: grid; gap: 14px; margin-top: 32px; }
.rules__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 16px;
  align-items: start;
  padding: 18px 20px;
  background: var(--parchment-lt);
  border: 4px solid var(--parchment-edge);
  box-shadow: inset 0 4px 0 rgba(255, 255, 255, 0.45);
}
/* Rule three is the one that costs somebody $25 if they miss it. */
.rules__item--warn { border-color: var(--copper, #a5642e); }
.rules__n {
  font-family: 'Press Start 2P', monospace;
  font-size: 1rem;
  line-height: 1;
  padding: 10px 12px;
  color: var(--wood-deep);
  background: var(--gold);
  border: 3px solid var(--wood-deep);
  box-shadow: inset 0 3px 0 var(--gold-bright), inset 0 -3px 0 var(--gold-dark);
}
.rules__item--warn .rules__n {
  background: var(--copper, #a5642e);
  color: var(--cream, #f4e9d2);
  box-shadow: inset 0 3px 0 var(--copper-light, #c2803f), inset 0 -3px 0 var(--copper-deep, #7d4820);
}
.rules__body h3 {
  margin: 2px 0 6px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--ink);
}
.rules__body p { margin: 0 0 6px; font-size: 0.92rem; line-height: 1.65; color: var(--ink-soft); }
.rules__body p:last-child { margin-bottom: 0; }
.rules__note {
  padding-left: 12px;
  border-left: 3px solid var(--parchment-edge);
  font-size: 0.86rem !important;
}

/* ------------------------------------------------------------------ the set */
.cset__loading { color: var(--ink-soft); font-size: 0.9rem; }

.cset__bar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  align-items: center;
  margin: 28px 0 10px;
  padding-bottom: 14px;
  border-bottom: 3px solid var(--parchment-edge);
}
.cset__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.cset__chip {
  padding: 7px 11px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.46rem;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  background: var(--parchment-dk);
  border: 2px solid var(--parchment-edge);
  cursor: pointer;
}
.cset__chip:hover { background: var(--parchment-lt); }
.cset__chip.is-on {
  color: var(--wood-deep);
  background: var(--gold);
  border-color: var(--wood-deep);
}
.cset__search { flex: 1 1 200px; min-width: 0; }
.cset__search input {
  width: 100%;
  padding: 9px 12px;
  font-family: 'Pixelify Sans', sans-serif;
  font-size: 0.92rem;
  color: var(--ink);
  background: var(--parchment-lt);
  border: 3px solid var(--parchment-edge);
}
.cset__count-line { margin: 0 0 20px; font-size: 0.84rem; color: var(--ink-soft); }

.cset__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }

.cset__cat {
  background: var(--parchment-lt);
  border: 4px solid var(--parchment-edge);
  box-shadow: inset 0 4px 0 rgba(255, 255, 255, 0.45);
  align-self: start;
}
.cset__head {
  display: grid;
  /* The thumb column and the thumb itself are the same number, said once.
     They were two hardcoded 52s, and when the thumb grew to fit real card art
     the column did not, so the picture spilled over the category name. */
  grid-template-columns: var(--cset-thumb, 52px) 1fr auto;
  gap: 12px;
  align-items: center;
  width: 100%;
  padding: 12px;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.cset__head:hover { background: rgba(0, 0, 0, 0.03); }
.cset__art { width: 52px; height: 52px; font-size: 0.38rem; padding: 4px; border-width: 3px; }
.cset__id { min-width: 0; }
.cset__name {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.62rem;
  line-height: 1.4;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.cset__sub { margin-top: 5px; font-size: 0.8rem; color: var(--ink-soft); }
.cset__meta { display: grid; gap: 4px; justify-items: end; text-align: right; }
.cset__count { font-size: 0.74rem; color: var(--ink-soft); white-space: nowrap; }
.cset__best .tcard__rar { font-size: 0.4rem; white-space: nowrap; }

.cset__blurb {
  margin: 0;
  padding: 0 14px 12px;
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--ink-soft);
  font-style: italic;
}

/* The ladder is the point of opening a category, so it is hidden until then. */
.cset__ladder { display: none; padding: 0 12px 12px; }
.cset__cat.is-open .cset__ladder { display: grid; gap: 8px; }

.cset__rung {
  padding: 10px 12px;
  background: var(--parchment-dk);
  border-left: 5px solid var(--parchment-edge);
}
.cset__rung.tcard--common   { border-left-color: #8a8474; }
.cset__rung.tcard--uncommon { border-left-color: var(--teal-deep); }
.cset__rung.tcard--rare     { border-left-color: var(--blue-deep); }
.cset__rung.tcard--legend   { border-left-color: var(--gold-dark); }

.cset__rung-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
}
.cset__rung-head b {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.54rem;
  line-height: 1.4;
  color: var(--ink);
}
.cset__buff { font-size: 0.9rem; line-height: 1.5; color: var(--ink); }
.cset__flavour { margin-top: 5px; font-size: 0.82rem; line-height: 1.5; color: var(--ink-soft); font-style: italic; }
.cset__supply { margin-top: 6px; font-size: 0.74rem; color: var(--ink-soft); }

@media (max-width: 520px) {
  .cset__grid { grid-template-columns: 1fr; }
  .rules__item { grid-template-columns: 1fr; }
}

/* An open category takes the full row.
   Left in its own column it pushed its neighbours' heights around and left a
   tall blank gap beside it, which reads as a broken grid rather than as a
   panel. Spanning makes it obvious that it is the thing you opened. */
.cset__cat.is-open {
  grid-column: 1 / -1;
  border-color: var(--wood-dark);
}
.cset__cat.is-open .cset__ladder {
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.cset__cat.is-open .cset__head { background: rgba(0, 0, 0, 0.04); }

/* The nav is sticky, so anything scrolled to by an anchor or by script lands
   underneath it unless it reserves the room. */
html { scroll-padding-top: 92px; }
.cset__bar, .cset__cat { scroll-margin-top: 92px; }

/* The wiki is unfinished and out of the nav until it is not. Anyone who still
   has the URL should be told that rather than left guessing. */
.wiki-preview-note {
  max-width: 900px;
  margin: 18px auto 0;
  padding: 12px 16px;
  background: rgba(122, 59, 59, 0.12);
  border: 3px solid var(--wine, #7a3b3b);
  color: var(--cream, #f4e9d2);
  font-size: 0.88rem;
  line-height: 1.6;
}
.foot__soon { color: var(--cream-soft, #e8dcc8); opacity: 0.55; }

/* ============================================================================
   THE CARD ART
   ----------------------------------------------------------------------------
   The pictures arrived, and they are not illustrations sitting inside a frame
   the page draws. Each one IS the whole card: border, title, buff, flavour,
   rarity banner. So the page's job changed from decorating a card to getting
   out of its way.

   That is why the rung keeps its text next to the picture rather than under
   it. The text is a duplicate of what is printed on the card for the 140 that
   are drawn, and it is the ONLY copy for the 68 that are not, so it cannot be
   deleted and it should not be centre stage either.
   ========================================================================== */

/* --- the thumb on a category row --------------------------------------- */
.cset__head { --cset-thumb: 84px; }
.cset__art {
  /* 52px was the placeholder's size, and a placeholder only had to say "art
     goes here". A real card has a title, a buff and a rarity banner printed on
     it, and at 52px all three are mud. 84 is the smallest width where the
     picture reads as a specific card rather than a coloured rectangle.

     `padding: 0` is not tidiness. The old .cset__art rule further up sets
     padding: 4px for the dashed placeholder, and with border-box that ate
     14 of the 52 pixels: the image inside was rendering at 38 wide while the
     box measured 52. Left alone it would quietly do the same thing at 84. */
  width: var(--cset-thumb);
  aspect-ratio: 100 / 140;
  height: auto;
  padding: 0;
  overflow: hidden;
  border: 3px solid var(--parchment-edge);
  background: var(--parchment-dk);
}
.cset__art-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  image-rendering: pixelated;
}

/* --- a rung in an opened ladder ---------------------------------------- */
.cset__rung { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start; }
.cset__rung-body { min-width: 0; }
.cset__rung-art { width: 92px; flex: 0 0 92px; }
.cset__rung-img {
  display: block;
  width: 92px;
  height: auto;
  image-rendering: pixelated;   /* it is pixel art, do not smooth it */
}

/* A card that has a picture is clickable, and has to look it. Cards without
   art are not clickable, so they deliberately get none of this. */
.cset__rung.has-art { cursor: pointer; }
.cset__rung.has-art:hover .cset__rung-img,
.cset__rung.has-art:focus-visible .cset__rung-img {
  transform: translateY(-2px);
  filter: brightness(1.06);
}
.cset__rung-img { transition: transform 0.12s ease, filter 0.12s ease; }
.cset__rung.has-art:focus-visible { outline: 3px solid var(--gold-dark); outline-offset: 2px; }

/* --- the back, for the 68 not yet drawn --------------------------------- */
.tback {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  aspect-ratio: 100 / 140;
  background:
    repeating-linear-gradient(45deg,
      rgba(0, 0, 0, 0.05) 0 6px, transparent 6px 12px),
    var(--parchment-dk);
  border: 2px solid var(--parchment-edge);
  color: var(--ink-soft);
}
.cset__rung-art .tback { width: 92px; }
.tback__mark { font-size: 1rem; line-height: 1; color: var(--gold-dark); }
.tback__word {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.3rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.cset__art .tback { width: 100%; height: 100%; border: 0; aspect-ratio: auto; }
.cset__art .tback__mark { font-size: 1.1rem; }
.cset__art .tback__word { font-size: 0.28rem; }

/* --- the lightbox ------------------------------------------------------- */
.tlb {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.tlb.is-on { display: flex; }
.tlb__scrim { position: absolute; inset: 0; background: rgba(12, 7, 3, 0.82); }
.tlb__frame {
  position: relative;
  margin: 0;
  /* The art is 400x560. Never scale it up past that: an upscaled pixel card
     looks worse than a small crisp one, and there is nothing to gain. */
  width: min(400px, 100%, calc((100vh - 96px) * 0.714));
}
.tlb__img {
  display: block;
  width: 100%;
  height: auto;
  image-rendering: pixelated;
}
.tlb__x {
  position: absolute;
  top: -14px;
  right: -14px;
  width: 34px;
  height: 34px;
  padding: 0;
  cursor: pointer;
  font: inherit;
  font-size: 0.9rem;
  color: var(--cream);
  background: var(--wood-dark);
  border: 3px solid var(--wood-deep);
}
.tlb__x:hover { background: var(--rust); }

@media (max-width: 520px) {
  .cset__rung { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .cset__rung-head { justify-content: center; }
  .cset__rung-art { width: 140px; flex-basis: 140px; }
  .cset__rung-img, .cset__rung-art .tback { width: 140px; }
}

/* The vault and the reveal show the same card faces as the set browser, so
   they get the same treatment: never smoothed, never upscaled past the file. */
.minicard__art.is-art, .rv__c-art.is-art {
  display: block;
  width: 100%;
  height: auto;
  image-rendering: pixelated;
  border: 0;
  padding: 0;
  background: none;
}

/* An include slot holding real art rather than a placeholder. The placeholder
   draws its own dashed box; a picture should not sit inside one. */
.incl__slot--img {
  /* --art is the asset's native pixel size, set inline where the slot is
     written. The box never grows past it, so the picture is shown at 1:1 or
     smaller and never upscaled to a fractional factor, which is the thing
     that makes pixel art look cheap. */
  display: grid;
  place-items: stretch;
  width: 100%;
  max-width: var(--art, 200px);
  aspect-ratio: 1 / 1;
  margin: 0 auto 12px;
  background: var(--parchment-dk);
  border: 3px solid var(--parchment-edge);
}
.incl__slot--img img {
  display: block;
  /* Fill the box, which is already capped at the asset's native size.

     This was `width: auto; height: auto; max-height: 100%` and every icon
     computed to zero. The box is a centred grid, so the item is sized to its
     content, and an image that has not loaded yet HAS no content: intrinsic
     size zero. A zero-sized image never intersects the viewport, so lazy
     loading never fired, so it never loaded, so it stayed zero. The bug held
     itself up. Sizing from the box rather than from the image breaks it. */
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
}

/* The sealed pack in the vault. It was a dashed box printing its own intended
   filename; it is now the pack. */
img.packcard__art {
  display: block;
  width: 100%;
  max-width: 240px;
  height: auto;
  margin: 0 auto 14px;
  padding: 0;
  border: 0;
  background: none;
  aspect-ratio: auto;
  image-rendering: pixelated;
}

/* THE THREE-STEP SEQUENCE
   ----------------------------------------------------------------------------
   Was four steps with a paragraph each: buy, open, equip, trade. Buying is not
   a step in what a card DOES, it is the price of admission, and four
   paragraphs of explanation on a page about a picture is the opposite of what
   the section is for. Three steps, numbered, no prose. */
.steps--three {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
  max-width: 720px;
  margin-inline: auto;
}
.steps--three .step {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
}
.steps--three .step h3 { margin: 0; }
.step__n {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.7rem;
  color: var(--wood-deep);
  background: var(--gold-bright);
  border: 3px solid var(--wood-deep);
}

/* CODEX CARDS THAT DO NOT GO ANYWHERE YET
   ----------------------------------------------------------------------------
   These were nine <a href="#"> links. Same defect as the dead footer links in
   ticket 92, just louder: each one names a specific quantity of content that
   does not exist yet, and then charges a click to discover that.

   They are still worth showing, because they say what the codex will hold.
   They are not links until there is somewhere to go, and they should not look
   like links either: a cursor that changes on hover is a promise. */
.wiki-card.is-soon { cursor: default; }
.wiki-card.is-soon:hover { transform: none; }
.wiki-card.is-soon::after {
  content: 'After launch';
  display: block;
  margin-top: 10px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.36rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: 0.75;
}

/* THE BUY BUTTON AND THE TWO-STEP CHOOSER
   ----------------------------------------------------------------------------
   One button on the page, then chain, then coin. The old row of four rail
   buttons asked two questions at once of somebody who had not yet agreed to
   buy anything, and it grew by one button every time a rail was added. */
.pay__btn--buy {
  width: 100%;
  padding: 16px 20px;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
}

.ck__choose {
  display: grid;
  gap: 10px;
  margin: 18px 0 6px;
}
.ck__choice {
  display: grid;
  gap: 5px;
  width: 100%;
  padding: 16px 18px;
  /* P2-94: the chains stack, they are not a wide row, and each box is a real
     thumb target on a phone. 44px is the floor everyone quotes; the padding
     already clears it, this is here so a later copy change cannot drop below
     it without somebody noticing. */
  min-height: 56px;
  align-content: center;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: var(--ink);
  background: var(--parchment-lt);
  border: 3px solid var(--parchment-edge);
  /* A choice is a target, and a target that only reacts on hover is a target
     that does not exist on a phone. The border does the work. */
  transition: border-color 0.12s ease, transform 0.12s ease;
}
.ck__choice:hover, .ck__choice:focus-visible {
  border-color: var(--gold-dark);
  transform: translateY(-1px);
  outline: none;
}
.ck__choice-name {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.7rem;
  color: var(--wood-deep);
}
.ck__choice-sub { font-size: 0.86rem; color: var(--ink-soft); }

/* ── P2-106 odds bar + pity guarantee ────────────────────────────────
   The bar is decoration on top of the table below it, not a substitute:
   it is aria-hidden and the table carries the same numbers for anyone
   reading with assistive tech or with CSS off.                        */
.oddsbar {
  display: flex;
  width: 100%;
  height: 22px;
  margin-top: 30px;
  border-radius: 5px;
  overflow: hidden;
  border: 1px solid rgba(0, 0, 0, 0.22);
}
.oddsbar__seg { flex: 0 0 var(--w); display: block; }
.oddsbar__seg.is-common    { background: #b8b2a6; }
.oddsbar__seg.is-uncommon  { background: #6f9a63; }
.oddsbar__seg.is-rare      { background: #4f7fb5; }
.oddsbar__seg.is-legendary { background: #c9962f; }

.pity {
  margin-top: 34px;
  padding: 22px 24px;
  border: 1px solid rgba(0, 0, 0, 0.16);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.05);
}
.pity__title {
  font-family: var(--font-display, inherit);
  font-size: 1.12rem;
  letter-spacing: 0.03em;
  margin-bottom: 8px;
}
.pity__copy { margin: 0 0 18px; font-size: 0.95rem; line-height: 1.6; }

.pity__ex { border-top: 1px solid rgba(0, 0, 0, 0.14); }
.pity__row {
  display: grid;
  grid-template-columns: 78px 1fr 150px;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  font-size: 0.92rem;
}
.pity__row:last-child { border-bottom: 0; }
.pity__row--head {
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.66;
}
.pity__row span:last-child { text-align: right; }
/* The two rows the whole rule turns on. Marked so a reader skimming the
   table sees "no reset" and "resets" without reading the prose above. */
.pity__row.is-lucky      { font-weight: 700; color: #8a6a12; }
.pity__row.is-guaranteed { font-weight: 700; color: #7a4a12; }

@media (max-width: 560px) {
  .pity__row { grid-template-columns: 54px 1fr 108px; font-size: 0.84rem; }
}

/* ── P2-107 two-column sequence + equip panel ────────────────────────
   The old version was three grey plates in a row with a paragraph under
   each. The complaint was that it read flat and dull, so: the steps lose
   their prose and become a numbered spine down the left, and the right
   column carries real card art at size.                                */
/* 2 Sep 2026 review video: one column - the slots panel on top, the three
   steps under it reading left to right. The vertical spine went with the
   vertical list. */
.seq {
  display: grid;
  grid-template-columns: 1fr;
  gap: 30px;
  align-items: center;
  justify-items: center;
  text-align: left;
}
.seq__art { width: 100%; max-width: 640px; }

.seq__steps {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
  display: flex;
  justify-content: center;
  gap: 40px;
  flex-wrap: wrap;
}
.seq__step {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 6px 0;
}
.seq__step h3 { margin: 0; font-size: 1.05rem; }
.seq__n {
  position: relative;
  z-index: 1;
  flex: 0 0 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.72rem;
  color: #2b1d0b;
  background: var(--gold, #E8C169);
  box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.18);
}

/* 31 Aug review video (detailed pass corrects the rough one): the slots
   frame wears the game's brown border like the hero sections; only the
   CARD SLOTS label is white. */
.equip {
  border: 3px solid var(--wood-deep, #3d2811);
  border-radius: 12px;
  padding: 14px;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(232, 193, 105, 0.16), transparent 70%),
    rgba(0, 0, 0, 0.22);
}
.equip__bar {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  display: flex;
  justify-content: space-between;
  padding: 0 4px 12px;
  color: #ffffff;
  opacity: 0.95;
}
.equip__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.equip__slot {
  aspect-ratio: 5 / 7;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 8px;
  border: 2px dashed rgba(255, 255, 255, 0.22);
  background: rgba(0, 0, 0, 0.25);
}
.equip__slot img { width: 100%; height: 100%; object-fit: contain; }
.equip__slot.is-filled { border-style: solid; }
/* Rarity colour on the slot frame, so the panel is not four identical boxes.
   Same hues as the odds bar, so a reader who saw that recognises them here. */
.equip__slot.is-legendary { border-color: #c9962f; box-shadow: 0 0 18px rgba(201, 150, 47, 0.4); }
.equip__slot.is-rare      { border-color: #4f7fb5; box-shadow: 0 0 14px rgba(79, 127, 181, 0.32); }
.equip__empty {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  opacity: 0.4;
}
@media (max-width: 480px) {
  .equip__grid { gap: 6px; }
  .equip__bar { font-size: 0.5rem; }
}

/* ── P2-108 Your Legacy ──────────────────────────────────────────────
   Four real cards, one per rarity that actually exists, then the copy.
   The old version put the text in a fixed box it did not fit; there is
   no box here at all, just flow with a ch-based measure, so the copy
   cannot overflow or clip at any width.                                */
.legacy {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
  max-width: 900px;
  margin: 32px auto 0;
}
.legacy__card { margin: 0; text-align: center; }
.legacy__card img {
  width: 100%;
  height: auto;
  border-radius: 9px;
  border: 3px solid var(--rr, rgba(255, 255, 255, 0.22));
  box-shadow: 0 0 20px var(--rg, transparent);
  /* Cards are portrait and the grid column is narrow on a phone. Letting
     them scale by width keeps all four on one row down to about 380px,
     which is what makes the rarity ladder readable as a ladder. */
  display: block;
}
.legacy__card figcaption {
  margin-top: 9px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.52rem;
  letter-spacing: 0.06em;
  color: var(--rr, inherit);
}
/* Same four hues as the odds bar and the equip panel. One rarity, one colour,
   everywhere on the page. */
.legacy__card.is-common    { --rr: #b8b2a6; --rg: rgba(184, 178, 166, 0.28); }
.legacy__card.is-uncommon  { --rr: #6f9a63; --rg: rgba(111, 154, 99, 0.30); }
.legacy__card.is-rare      { --rr: #4f7fb5; --rg: rgba(79, 127, 181, 0.34); }
.legacy__card.is-legendary { --rr: #c9962f; --rg: rgba(201, 150, 47, 0.45); }

.legacy__copy {
  /* ch, not px: the measure follows the font, so the paragraph holds its
     shape if the type scale ever changes. */
  max-width: 68ch;
  margin: 34px auto 0;
  font-size: 1.02rem;
  line-height: 1.72;
}
@media (max-width: 620px) {
  .legacy { gap: 10px; }
  .legacy__card figcaption { font-size: 0.44rem; }
  .legacy__copy { font-size: 0.96rem; }
}

/* ── P2-115 two-signature guidance ───────────────────────────────────
   Shown only on rails that really need two wallet prompts. The bar is
   the thing somebody glances at to know a second prompt is expected,
   so it has to be legible before the text is read.                    */
.ck__sig {
  margin: 14px 0 8px;
  text-align: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.06em;
  color: var(--gold-dark, #a9822f);
}
.ck__sigbar {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-bottom: 14px;
}
.ck__sigbar i {
  width: 54px;
  height: 6px;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.16);
}
.ck__sigbar i.is-on { background: var(--gold, #E8C169); }

/* ── P2-105 fanned card art ──────────────────────────────────────────
   Four real cards behind the pack. Rotations and offsets are fixed, not
   random, so the composition is the same for everyone and can be judged
   once. The pack sits on top and is the only thing at full opacity.   */
.fan { position: relative; display: grid; place-items: center; }
.fan__pack { position: relative; z-index: 5; width: 100%; height: auto; }
.fan__card {
  position: absolute;
  top: 12%;
  width: 42%;
  height: auto;
  border-radius: 7px;
  border: 2px solid rgba(61, 40, 17, 0.9);
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.45);
  transform-origin: 50% 100%;
}
.fan__card--a { z-index: 1; transform: translateX(-72%) rotate(-19deg); }
.fan__card--b { z-index: 2; transform: translateX(-30%) rotate(-8deg); }
.fan__card--c { z-index: 3; transform: translateX(30%)  rotate(8deg); }
.fan__card--d { z-index: 4; transform: translateX(72%)  rotate(19deg); }
/* Narrow columns cannot hold a four-card spread without the outer two leaving
   the container, so the fan tightens rather than overflowing. */
@media (max-width: 900px) {
  .fan__card--a { transform: translateX(-52%) rotate(-14deg); }
  .fan__card--b { transform: translateX(-22%) rotate(-6deg); }
  .fan__card--c { transform: translateX(22%)  rotate(6deg); }
  .fan__card--d { transform: translateX(52%)  rotate(14deg); }
}

/* ── P2-105 on-page buy block ────────────────────────────────────────
   Order is fixed by the ticket: quantity, then BUY NOW underneath, then
   the description under that.                                         */
.buy { margin: 26px 0 18px; }
.buy__qty { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.buy__qty-label {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.08em;
  opacity: 0.8;
}
.buy__qty-btns { display: flex; gap: 8px; }
.buy__qty-btn {
  min-width: 60px;
  min-height: 44px;                  /* tap floor, P2-95 */
  padding: 0 14px;
  cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.62rem;
  color: var(--cream, #f5f1e0);
  background: rgba(0, 0, 0, 0.25);
  border: 3px solid rgba(232, 193, 105, 0.45);
  border-radius: 8px;
}
.buy__qty-btn.is-on {
  color: #2b1d0b;
  background: var(--gold, #E8C169);
  border-color: var(--gold, #E8C169);
}
.buy__desc { margin: 16px 0 0; line-height: 1.7; max-width: 56ch; }

/* ── P2-114 vault ────────────────────────────────────────────────────
   The sealed-pack pile is gone. What is here instead only ever shows
   when a purchase minted a pack and the open step then failed, which
   is the case P2-110 says must never cost somebody their cards.

   Styled as a warm notice, not as an inventory card, so it does not
   read as "you own an unopened pack".                                */
.vault__recover { margin-bottom: 30px; }
.recover {
  padding: 20px 22px;
  border-left: 5px solid var(--gold, #E8C169);
  border-radius: 8px;
  background: rgba(232, 193, 105, 0.10);
}
.recover__h {
  margin: 0 0 8px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.72rem;
  line-height: 1.6;
}
.recover__p { margin: 0 0 16px; line-height: 1.7; max-width: 62ch; }
.recover__btns { display: flex; gap: 12px; flex-wrap: wrap; }

/* P2-114 asks for two columns at mobile widths. 132px minimum with a 14px gap
   fits two columns from 278px of content box, which every phone clears, so
   auto-fill already lands on two. Pinned explicitly below 420px so a later
   change to the minimum cannot silently drop it to one. */
@media (max-width: 420px) {
  .vault__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
}

/* ── P2-110 reveal ───────────────────────────────────────────────────
   Cards land face down and turn over one at a time. The old version
   showed every face at once, which is fine for one card and pointless
   for ten: the thing being paid for is the moment before you know.   */
.rv__cards--many {
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  max-height: 46vh;
  overflow-y: auto;
}

.rv__c { perspective: 900px; background: none; border: 0; padding: 0; }
.rv__flip {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.55s cubic-bezier(0.3, 1.4, 0.5, 1);
  aspect-ratio: 3 / 4;
}
.rv__c.is-up .rv__flip { transform: rotateY(180deg); }
/* Reveal all: no transition, so ten cards do not each spend half a second. */
.rv__c.is-instant .rv__flip { transition: none; }

.rv__back, .rv__front {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  border-radius: 8px;
  overflow: hidden;
}
.rv__back {
  border: 3px solid var(--wood-deep);
  background:
    repeating-linear-gradient(45deg,
      rgba(232, 193, 105, 0.16) 0 9px, transparent 9px 18px),
    linear-gradient(180deg, #4a3316, #2b1d0b);
}
.rv__front {
  transform: rotateY(180deg);
  display: grid;
  align-content: start;
  border: 3px solid var(--wood-deep);
  background: var(--wood-black, #1c1208);
}
.rv__front .rv__c-art { width: 100%; height: auto; }
.rv__c-r {
  padding: 3px 0 5px;
  text-align: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Rarity has to be FELT, per the ticket. The rarity comes from the minted id,
   never from a guess, so the glow is telling the truth about what was drawn.
   Common gets nothing on purpose: if every card celebrates, none of them do. */
.rv__c.r-uncommon  .rv__front { box-shadow: 0 0 16px rgba(111, 154, 99, 0.55); }
.rv__c.r-uncommon  .rv__c-r { color: #6f9a63; }
.rv__c.r-rare      .rv__front { box-shadow: 0 0 22px rgba(79, 127, 181, 0.7); }
.rv__c.r-rare      .rv__c-r { color: #4f7fb5; }
.rv__c.r-legendary .rv__front {
  box-shadow: 0 0 34px rgba(232, 193, 105, 0.9), 0 0 70px rgba(232, 193, 105, 0.45);
  border-color: #c9962f;
}
.rv__c.r-legendary .rv__c-r { color: #E8C169; }
.rv__c.r-legendary.is-up:not(.is-instant) { animation: rv-legend 0.9s ease-out 0.4s both; }
@keyframes rv-legend {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.11); }
  100% { transform: scale(1); }
}

.rv__actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 18px; }
.rv__pref {
  margin: 12px 0 0;
  text-align: center;
  font-size: 0.86rem;
  opacity: 0.75;
}
.rv__replay {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font: inherit;
  color: var(--gold, #E8C169);
  text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
  .rv__flip { transition: none; }
  .rv__c.r-legendary.is-up { animation: none; }
}

/* ── P2-95 mobile ────────────────────────────────────────────────────
   The fanned hero art pushed the page 6 to 8px wide at every phone
   size. The outer two cards are rotated and translated, and a
   transform does not shrink the box it started from, so the media
   query that "tightened" the fan did not actually pull it back inside.

   Two fixes, both needed:
     the fan gets its own overflow boundary, so a rotated corner can
     never widen the document, and
     the cards get smaller and sit closer on narrow screens, so nothing
     is being clipped in the first place.                              */
.pack-hero__art { max-width: 100%; }
.fan {
  max-width: 100%;
  /* clip, not hidden: hidden on a grid parent can create a scroll container
     of its own. This just stops the rotated corners escaping. */
  overflow: clip;
}
@media (max-width: 640px) {
  .fan__card { width: 34%; top: 16%; }
  .fan__card--a { transform: translateX(-40%) rotate(-12deg); }
  .fan__card--b { transform: translateX(-17%) rotate(-5deg); }
  .fan__card--c { transform: translateX(17%)  rotate(5deg); }
  .fan__card--d { transform: translateX(40%)  rotate(12deg); }
}

/* Tap targets. The audit found controls at 27, 32, 33, 38 and 40px tall
   across five components. 44px is the floor the ticket sets, so it is set
   once here per component rather than hoped for. */
@media (max-width: 900px) {
  .wchip { min-height: 44px; padding-inline: 12px; }
  .cset__chip { min-height: 44px; }
}

/* P2-133: Genesis adds Mythic above Legendary. Purple, so it cannot be
   mistaken for the gold Legendary at a glance. */
.oddsbar__seg.is-mythic { background: #8b5cf6; min-width: 3px; }
.odds__row.is-mythic span:first-child::before { background: #8b5cf6; }
.rarity--mythic .rarity__chip { background: #8b5cf6; color: #fff; }

/* ============================================================================
   P2-163. WHAT YOU GET, and the receipt that greets you.

   Both screens draw from the same tier `perks` array, so they cannot describe
   different packs, and both use the same tile so a buyer recognises on the
   receipt the thing they agreed to on the review screen.
   ========================================================================== */
.ck__gets { margin: 20px 0 18px; }
.ck__gets-h {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.56rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint, #7a6a52);
  margin-bottom: 12px;
}
.ck__gets-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.ck__get {
  padding: 12px 10px;
  text-align: left;
  background: rgba(28, 17, 9, 0.05);
  border: 2px solid rgba(61, 40, 17, 0.28);
}
.ck__get b {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.62rem;
  line-height: 1.45;
  color: var(--ink, #2f2213);
  margin-bottom: 6px;
  overflow-wrap: anywhere;
}
.ck__get span {
  display: block;
  font-size: 0.82rem;
  line-height: 1.35;
  color: var(--ink-faint, #7a6a52);
}
/* The head start is the only perk that expires. It is the reason to buy today
   rather than next week, so it is the one that is coloured. */
.ck__get.is-hot {
  background: rgba(196, 74, 58, 0.12);
  border-color: rgba(196, 74, 58, 0.55);
}
.ck__get.is-hot b { color: #a8341f; }

.ck__welcome { text-align: center; margin: 4px 0 20px; }
.ck__signet {
  width: 58px; height: 58px;
  margin: 0 auto 14px;
  display: grid; place-items: center;
  border-radius: 50%;
  font-family: 'Press Start 2P', monospace;
  font-size: 1rem;
  color: #2a1a06;
  background: var(--gold, #e8c169);
  border: 3px solid var(--wood-deep, #3d2811);
  box-shadow: inset 0 3px 0 var(--gold-bright, #ffe9a8),
              inset 0 -3px 0 var(--gold-dark, #b98f36),
              0 4px 0 rgba(0, 0, 0, 0.2);
}
.ck__welcome-t {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--ink, #2f2213);
}
.ck__welcome-s {
  margin: 10px 0 0;
  font-size: 0.95rem;
  color: var(--ink-soft, #4a3a24);
}

@media (max-width: 560px) {
  .ck__gets-grid { grid-template-columns: repeat(2, 1fr); }
  .ck__welcome-t { font-size: 0.76rem; }
}

/* ==================================================================
   P2-164. THE BUY BUTTON.

   The one control on the page whose whole job is to be pressed was
   drawn on the same grey plate as the secondary rail buttons. On a
   page where "Sale is live" sits directly under it, a grey primary
   reads as disabled, and a buyer who thinks the button is dead does
   not press it to find out.

   It takes the gold plate, which is what every other primary on the
   site uses. The rail buttons keep the grey, and now the difference
   between "buy" and "pick a coin" is visible before you read either.
   ================================================================== */
.pay__btn--buy {
  color: #2a1a06;
  background: linear-gradient(180deg,
    #ffe9a8 0%, #f0c45c 41%, #f6d179 42%, #c99a2e 100%);
  text-shadow: 0 2px 0 rgba(255, 246, 214, 0.6);
  box-shadow:
    inset 0 0 0 1px rgba(255, 249, 226, 0.5),
    inset 0 2px 0 rgba(255, 252, 236, 0.7),
    inset 0 -3px 0 rgba(140, 100, 24, 0.5),
    0 3px 0 #2f1d0a,
    0 5px 0 #180d04,
    0 7px 9px rgba(0, 0, 0, 0.34);
}
.pay__btn--buy::before {
  background:
    linear-gradient(180deg, rgba(255, 252, 236, 0.5) 0 1px, transparent 1px),
    linear-gradient(0deg, rgba(120, 84, 18, 0.4) 0 1px, transparent 1px);
}
.pay__btn--buy::after {
  background:
    linear-gradient(45deg, rgba(255, 252, 236, 0.85) 0 3px, transparent 3px) top left / 8px 8px no-repeat,
    linear-gradient(-45deg, rgba(255, 252, 236, 0.85) 0 3px, transparent 3px) top right / 8px 8px no-repeat,
    linear-gradient(135deg, rgba(120, 84, 18, 0.5) 0 3px, transparent 3px) bottom left / 8px 8px no-repeat,
    linear-gradient(-135deg, rgba(120, 84, 18, 0.5) 0 3px, transparent 3px) bottom right / 8px 8px no-repeat;
}


/* ==================================================================
   P2-168. A LONE BUY BUTTON SAT IN THE LEFT HALF OF ITS CARD.

   `.pay__row` is `grid-template-columns: repeat(2, 1fr)`, which is
   right for the rail buttons: they come in pairs and want a 2x2 grid.
   It is wrong for the single Buy now button that replaced them, which
   took column one and left column two empty, so the button was
   half-width and hard against the left edge of the tier card.

   Fixed by giving the row one column when it holds one button. The
   two-column rule still applies the moment a second appears.
   ================================================================== */
.pay__row:has(.pay__btn--buy) { grid-template-columns: 1fr; }
.pay__row:has(.pay__btn--buy) .pay__btn--buy { justify-self: stretch; }
.pay__soon, .pay__live { text-align: center; }

/* ==================================================================
   P2-169. THE CARD FAN WAS BEING SLICED AT BOTH ENDS.

   `.fan` is `overflow: clip`, which is deliberate: without it the
   rotated corners escape and, on a grid parent, `hidden` would create
   a scroll container of its own. The problem was that the composition
   was built to exactly the width of its own clip box. The outer cards
   translate 72% of their own width and rotate 19 degrees, so their
   far corners land outside the box and were being cut off square.

   The fix is room, not a bigger box: horizontal padding on `.fan`.
   The pack is `width: 100%` of the content box, so padding scales the
   whole arrangement down together, cards, translations and all, and
   the padding becomes the margin the rotated corners needed. Nothing
   about the layout of the page around it changes.
   ================================================================== */
/* The first attempt at this padded `.fan` and did nothing, for a reason
   worth writing down: the cards are `position: absolute`, so their
   containing block is the fan's PADDING box, not its content box. Padding
   shrank the pack, which is in flow, and left the cards exactly the size
   they were. The composition came apart instead of scaling down.

   The room has to come from a parent the fan actually sizes against. So
   `.pack-hero__art` takes the padding, which narrows `.fan` itself, which
   scales the pack, the cards and their translations together. And the clip
   comes off, because with the arrangement now smaller than the space it is
   given there is nothing left to clip; the page's own no-sideways-scroll
   test is what guards the thing `overflow: clip` was here to prevent. */
.fan { overflow: visible; padding: 0; }
.pack-hero__art { padding: 0 11%; }
@media (max-width: 980px) { .pack-hero__art { padding: 0 8%; } }
@media (max-width: 640px) { .pack-hero__art { padding: 0 6%; } }

/* == 2 Sep 2026 review video: the cards hero sits on the ship-voyage
   backdrop, so its descriptive copy goes pure white for contrast. Scoped to
   .section-backdrop so the rules only bite once the backdrop actually
   loads - without the art the section stays wood and keeps its own ink. */
.section-backdrop .buy__desc,
.section-backdrop .pack-hero__note,
.section-backdrop .buy__qty-label {
  color: #ffffff;
}

/* == 31 Aug review video (detailed pass): the cards hero is one centred
   column - title, packs-remaining, pack art, price, quantity + Open Now,
   utility paragraph, pay-with hint. The old two-column grid is overridden
   only when the --stack modifier is present. */
.pack-hero--stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
}
.pack-hero--stack .pack-hero__art { width: 100%; max-width: 460px; padding: 0 6%; }
.pack-hero--stack .pack-hero__body { max-width: 640px; }
.pack-hero--stack .buy__qty { justify-content: center; }
.pack-hero--stack .buy__desc { margin-left: auto; margin-right: auto; }
.pack-hero__remaining {
  margin: 0;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--gold, #E8C169);
}
.pack-hero__price { line-height: 1.3; }
.pack-hero__price b {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 1.6rem;
  color: #ffffff;
}
.pack-hero__price span { font-size: 0.95rem; color: rgba(255, 255, 255, 0.85); }
.pack-hero__rails {
  margin: 14px 0 0;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.75);
}
/* a preset above the contract's per-transaction cap renders locked instead
   of hidden (review video: "ten is locked, so it can be like transparent") */
.buy__qty-btn.is-locked {
  opacity: 0.35;
  cursor: not-allowed;
}

/* == 31 Aug review video (detailed pass): the odds module. One bordered
   box: "Each pack contains 1 card", the rarity bar with a label row whose
   spans share the bar's own segment widths, the single supply line, then
   the pity strip joined on with a rule - not a second border. The strip's
   own frame is stripped when it lives inside the box, and both the bar and
   the strip's boxes span the same width, so their edges align. */
.oddsbox {
  max-width: 760px;
  margin: 0 auto;
  padding: 22px 24px;
  border: 3px solid var(--wood-deep, #3d2811);
  border-radius: 10px;
  background: rgba(28, 17, 9, 0.05);
  box-shadow: 0 6px 0 rgba(0, 0, 0, 0.16);
}
.oddsbox__title {
  margin: 0 0 16px;
  text-align: center;
  font-size: 1.15rem;
}
.oddsbox .oddsbar { margin: 0; }
.oddsbar__labels {
  display: flex;
  margin-top: 8px;
  position: relative;
}
.oddsbar__labels span {
  flex: 0 0 var(--w);
  min-width: 0;
  font-size: 0.8rem;
  line-height: 1.35;
  color: var(--ink-soft, #5a4632);
  white-space: nowrap;
}
/* The Legendary segment is ~5% wide - far narrower than its own label - so
   the last label anchors to the bar's right edge and grows LEFTWARD,
   staying inside the box while still sitting under its segment, which ends
   at that same edge. */
.oddsbar__labels span:last-child {
  position: absolute;
  right: 0;
  top: 0;
  flex: none;
  text-align: right;
}
.oddsbar__labels b { display: block; font-size: 0.78rem; }
.oddsbox__line {
  margin: 14px 0 0;
  text-align: center;
  font-size: 0.95rem;
  color: var(--ink-soft, #5a4632);
}
.oddsbox .pitytrack {
  max-width: none;
  margin: 18px 0 0;
  padding: 16px 0 0;
  border: none;
  box-shadow: none;
  background: transparent;
  border-top: 3px solid var(--wood-deep, #3d2811);
}
@media (max-width: 640px) {
  .oddsbar__labels span { font-size: 0.62rem; }
  .oddsbar__labels b { font-size: 0.6rem; }
}

/* the Your Legacy copy over its backdrop reads white */
.section-backdrop .legacy__copy { color: #ffffff; }

/* == 31 Aug review video: tier card polish. The check tick becomes a gold
   diamond (game iconography), any divider rules between rows are gone, and
   the rows tighten up so a card fits one screen. */
.tier__list li::before {
  content: '\25C6';
  width: auto; height: auto;
  border: none;
  transform: none;
  top: 0.18em;
  font-size: 0.62rem;
  color: var(--gold-dark, #b98f36);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
}
.tier__list li { border: none !important; padding-top: 6px; padding-bottom: 6px; }
.tier__list { margin: 14px 0 10px; }
/* guarantee line now closes the card instead of preceding the price */
.tier__guarantee { margin-top: 10px; }

/* == 31 Aug review video: the Trading Cards slot shows three real cards,
   and the "Your packs open on the spot" section shows three big ones on
   its own in-game backdrop. */
.incl__cards { display: flex; gap: 6px; align-items: center; justify-content: center; }
.incl__cards img { width: 50px; height: 70px; border-radius: 4px; }
.openspot__lead { color: #ffffff; }
.section-backdrop .openspot__lead { color: #ffffff; }
.openspot__cards {
  display: flex;
  justify-content: center;
  gap: 26px;
  margin: 30px 0 28px;
  flex-wrap: wrap;
}
.openspot__cards img {
  width: 200px;
  height: auto;
  border-radius: 10px;
  box-shadow: 0 10px 0 rgba(0, 0, 0, 0.25);
}

/* == 31 Aug review video part 2: tight vault hero, and the wallet note as
   a small notification under the cards instead of a hero-sized box. */
.vault-hero { padding: 30px 0 26px; }
.vault__state--mini {
  margin-top: 26px;
  padding: 14px 18px;
  text-align: left;
}
.vault__state--mini h2 {
  font-size: 0.72rem;
  margin: 0 0 6px;
}
.vault__state--mini p { margin: 0 0 6px; font-size: 0.88rem; max-width: none; }

/* == follow-up on the 31 Aug odds module: inside the box the strip is ONLY
   the ten boxes and the line under them, like the reference - the widget's
   own header, count chip and storage note stay hidden here. And the tier
   card text gets the bolder, easier-read weight the client asked for. */
.oddsbox .pitytrack__head,
.oddsbox .pitytrack__note { display: none; }
.oddsbox .pitytrack__line { text-align: center; }
.tier__li-t { font-weight: 700; }
.tier__li-d { font-size: 0.84rem; }

/* == 3 Sep 2026: expeditions per reference v2 ============================
   Copy on a dark scrim with generous padding; the capture in the same
   game-UI frame as the In-the-Alpha tiles; four pips under the frame. */
.exp-scrim {
  /* 6 Sep 2026 notes: same width and edges as the frame below (both sit on
     the 940px .exp column), balanced padding, and a tight gap so the two
     read as one joined section. */
  max-width: 940px;
  margin: 0 auto 14px;
  background: rgba(16, 24, 38, 0.88);
  border-radius: 10px;
  padding: 32px 28px;
}
.exp-scrim .section__lead { margin-bottom: 0; }
.exp-scrim .section__title { margin-bottom: 12px; }
.exp { margin-top: 0; }
.exp-scrim .section__title { color: var(--cream, #f4e9d0); }
.exp-scrim .section__lead { color: rgba(244, 233, 208, 0.75); }
.exp__shot {
  aspect-ratio: 21 / 9;
  overflow: hidden;
  border-radius: 0;
  position: relative;
  border: 4px solid #2b1d0b;
  box-shadow: inset 0 0 0 3px var(--gold, #E8C169);
  background: var(--wood-deep);
  padding: 12px;
}
.exp__shot::after {
  content: '';
  position: absolute;
  inset: 5px;
  pointer-events: none;
  background:
    linear-gradient(var(--gold, #E8C169), var(--gold, #E8C169)) 0 0 / 10px 10px no-repeat,
    linear-gradient(var(--gold, #E8C169), var(--gold, #E8C169)) 100% 0 / 10px 10px no-repeat,
    linear-gradient(var(--gold, #E8C169), var(--gold, #E8C169)) 0 100% / 10px 10px no-repeat,
    linear-gradient(var(--gold, #E8C169), var(--gold, #E8C169)) 100% 100% / 10px 10px no-repeat;
}
.exp__pips { display: flex; justify-content: center; gap: 10px; margin-top: 16px; }
.exp__pip {
  width: 38px; height: 10px;
  border-radius: 3px;
  background: rgba(16, 24, 38, 0.65);
  border: 2px solid #2b1d0b;
}
.exp__pip.is-open { background: var(--gold, #E8C169); }

/* == 3 Sep 2026 notes, cards page ======================================= */
/* Fan: bigger cards, two left and two right, sticking out past the pack. */
.fan__card { width: 240px; }
.fan__card--a { transform: translateX(-108%) rotate(-14deg); }
.fan__card--b { transform: translateX(-66%)  rotate(-6deg); }
.fan__card--c { transform: translateX(66%)   rotate(6deg); }
.fan__card--d { transform: translateX(108%)  rotate(14deg); }

/* Early-access countdown: red box, white text. */
.early-window {
  display: inline-block;
  margin-left: 10px;
  padding: 8px 14px;
  background: #b3261e;
  border: 2px solid #7a120d;
  border-radius: 6px;
  color: #ffffff;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* Odds box interior goes home-page wood brown. */
.oddsbox--wood {
  background: var(--wood, #8b5a3c);
  border-color: var(--wood-deep, #3d2811);
}
.oddsbox--wood .oddsbox__title,
.oddsbox--wood .oddsbar__labels span { color: var(--cream, #f4e9d0); }
.oddsbox--wood .oddsbar__labels span b { color: #ffffff; }

/* Supply line in its new home under the Collect, Equip, and Trade title. */
.legacy__supply {
  margin: 6px 0 0;
  color: var(--gold, #E8C169);
  font-weight: 700;
}

/* == 3 Sep 2026 notes, founder in-game icons: every icon slot gets the
   game-UI backdrop (the skin/title one "looks weird, no border behind
   it"), and the art centres inside it. == */
.incl__slot--img {
  border: 3px solid #2b1d0b;
  box-shadow: inset 0 0 0 2px var(--gold, #E8C169);
  background: rgba(20, 12, 6, 0.45);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.incl__slot--img img { object-fit: contain; object-position: center; }

/* Cards hero: the paragraph under Open Now widens to two lines. */
.buy__desc { max-width: 78ch; }

/* == 3 Sep 2026: circular tier badges (client-approved art) crown each
   founder tier card, per the mockup. == */
.tier__badge {
  display: block;
  width: 88px;
  height: 88px;
  margin: 0 auto 10px;
  image-rendering: pixelated;
  filter: drop-shadow(0 4px 0 rgba(0, 0, 0, 0.25));
}

/* == 3 Sep 2026: the tier contents showcases are landscape panels, so
   they take the card's full width instead of the old pack-art column. == */
.tier__img--wide {
  max-width: 100%;
  border: 3px solid #2b1d0b;
  border-radius: 6px;
}

/* == 4 Sep 2026: the red head-start ribbons from the founder mockup, as a
   straight banner strip over each tier's contents image. == */
.tier__ribbon {
  display: block;
  margin: 0 auto 8px;
  width: max-content;
  padding: 7px 16px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.06em;
  color: #ffffff;
  background: #b3261e;
  border: 2px solid #7a120d;
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.25);
}

/* == 4 Sep 2026: responsive guards for the new components. The hero fan's
   outer cards would push past small viewports; the scrim and badges scale
   down instead of crowding. == */
@media (max-width: 720px) {
  .fan__card { width: 150px; }
  .fan__card--a { transform: translateX(-80%) rotate(-12deg); }
  .fan__card--d { transform: translateX(80%)  rotate(12deg); }
  .exp-scrim { padding: 26px 16px 22px; }
  .tier__badge { width: 68px; height: 68px; }
  .early-window { display: block; margin: 10px auto 0; width: max-content; }
}

/* ========================================================================
   4 Sep 2026 - SUBJECTIVE COLOR PASS, APPROVAL REQUIRED.
   The client flagged the tier cell colouring as an open decision ("color
   is important if you want to sell... we have to think about that"). This
   block gives each tier an identity from the site's own base palette -
   Farmer earthy copper, Noble deep sky-blue, King gold - as a coloured
   top rule, a matching price, and a soft glow on the featured tiers.
   It is deliberately the LAST commit of the round so `git revert` removes
   exactly this and nothing else.
   ===================================================================== */
.tiers .tier:nth-child(1) { border-top: 6px solid var(--copper); }
.tiers .tier:nth-child(1) .tier__rank,
.tiers .tier:nth-child(1) .tier__price .tier__usd { color: var(--copper-deep); }

.tiers .tier:nth-child(2) { border-top: 6px solid var(--sky-deep); }
.tiers .tier:nth-child(2) .tier__rank,
.tiers .tier:nth-child(2) .tier__price .tier__usd { color: var(--sky-deep); }
.tiers .tier:nth-child(2) { box-shadow: 0 0 24px rgba(74, 122, 153, 0.28); }

.tiers .tier:nth-child(3) { border-top: 6px solid var(--gold-dark); }
.tiers .tier:nth-child(3) .tier__rank,
.tiers .tier:nth-child(3) .tier__price .tier__usd { color: var(--gold-deep); }
.tiers .tier:nth-child(3) { box-shadow: 0 0 24px rgba(200, 154, 47, 0.35); }

.tiers .tier .tier__flag { background: var(--copper); color: #fff; }


/* == 6 Sep 2026 notes, cards page ======================================= */
/* the line under Open Now holds two lines: no cap on its width */
.buy__desc { max-width: none; }

/* Odds box, gilt scheme: deep wine field, ornate gold double border with
   corner studs (the client's dragon-frame reference, stylised for the site),
   white copy. Replaces the brown interior. */
.oddsbox--gilt {
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(232, 193, 105, 0.14), transparent 70%),
    linear-gradient(180deg, #5a1818 0%, #3d1010 100%);
  border: 4px solid var(--gold-dark, #c89a2f);
  border-radius: 0;
  position: relative;
  box-shadow:
    inset 0 0 0 3px #2b1d0b,
    inset 0 0 0 6px var(--gold, #f4c75e),
    0 8px 0 rgba(0, 0, 0, 0.3);
  padding: 30px 32px;
}
.oddsbox--gilt::after {
  content: '';
  position: absolute;
  inset: 8px;
  pointer-events: none;
  background:
    linear-gradient(var(--gold-bright, #fde08a), var(--gold-bright, #fde08a)) 0 0 / 12px 12px no-repeat,
    linear-gradient(var(--gold-bright, #fde08a), var(--gold-bright, #fde08a)) 100% 0 / 12px 12px no-repeat,
    linear-gradient(var(--gold-bright, #fde08a), var(--gold-bright, #fde08a)) 0 100% / 12px 12px no-repeat,
    linear-gradient(var(--gold-bright, #fde08a), var(--gold-bright, #fde08a)) 100% 100% / 12px 12px no-repeat;
}
.oddsbox--gilt .oddsbox__title { color: var(--gold-bright, #fde08a); }
.oddsbox--gilt .oddsbar__labels span { color: rgba(255, 255, 255, 0.82); }
.oddsbox--gilt .oddsbar__labels span b { color: #ffffff; }
.oddsbox--gilt .pitytrack__line { color: #ffffff; }
.oddsbox--gilt .oddsbar { box-shadow: 0 0 0 2px var(--gold-dark, #c89a2f); }
/* ========================================================================
   7 SEP 2026 - LAUNCH DAY PASS
   ===================================================================== */

/* -- Trailer, waiting state -------------------------------------------
   The frame used to hold a painted castle still. It now holds a question
   mark and a countdown to the moment the trailer lands, which is the honest
   version of "coming soon". Nothing here is clickable, so the frame drops
   the pointer cursor and the hover nudge it inherited from the clickable
   version. */
.trailer--soon { cursor: default; }
.trailer--soon:hover { transform: none; }
.trailer-soon {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  text-align: center;
  padding: 18px;
  background:
    radial-gradient(120% 90% at 50% 30%, rgba(232, 193, 105, 0.10), transparent 70%),
    linear-gradient(180deg, #1b2436 0%, #0e1420 100%);
}
.trailer-soon__mark {
  font-family: 'Press Start 2P', monospace;
  font-size: clamp(2.6rem, 7vw, 4.4rem);
  line-height: 1;
  color: var(--gold-bright, #fde08a);
  text-shadow:
    -3px -3px 0 #14100a,  0   -3px 0 #14100a,  3px -3px 0 #14100a,
    -3px  0   0 #14100a,                       3px  0   0 #14100a,
    -3px  3px 0 #14100a,  0    3px 0 #14100a,  3px  3px 0 #14100a,
     0    8px 0 rgba(0, 0, 0, 0.45);
}
.trailer-soon__clock {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}
.trailer-soon__unit {
  min-width: 62px;
  padding: 8px 6px 6px;
  background: rgba(10, 14, 22, 0.85);
  border: 2px solid var(--gold-dark, #c89a2f);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.6);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
}
.trailer-soon__unit b {
  font-family: 'Press Start 2P', monospace;
  font-size: 1rem;
  line-height: 1;
  color: #ffffff;
  font-variant-numeric: tabular-nums;
}
.trailer-soon__unit i {
  font-style: normal;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.42rem;
  letter-spacing: 0.08em;
  color: rgba(244, 233, 208, 0.6);
}
.trailer-soon__note {
  margin: 0;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.52rem;
  line-height: 1.7;
  letter-spacing: 0.05em;
  color: rgba(244, 233, 208, 0.78);
}
.trailer--soon.is-done .trailer-soon__mark { color: var(--copper-light, #d98d54); }

@media (max-width: 560px) {
  .trailer-soon { gap: 10px; padding: 10px; }
  .trailer-soon__unit { min-width: 48px; padding: 6px 4px 5px; }
  .trailer-soon__unit b { font-size: 0.76rem; }
  .trailer-soon__note { font-size: 0.42rem; }
}

/* -- CTA card hand (Ketama, 7 Sep) -------------------------------------
   Same game-UI frame as the In-the-Alpha tiles so it reads as part of the
   page. Capped well under the CTA block width so the buttons under it stay
   the thing the eye lands on last. */
.cta-shot {
  margin: 0 auto 28px;
  max-width: 620px;
  border: 4px solid #2b1d0b;
  box-shadow: inset 0 0 0 3px var(--gold, #E8C169), 0 8px 0 rgba(0, 0, 0, 0.22);
  padding: 8px;
  background: var(--wood-deep, #3d2811);
  line-height: 0;
}
.cta-shot img { width: 100%; height: auto; display: block; }


/* ========================================================================
   7 SEP 2026 - LAUNCH LOCK, PUBLIC BUILD ONLY
   This block does NOT exist in the testnet build. It is the visible half of
   the lock; the functional half is in the markup (hrefs removed) and in the
   script tags that are commented out. Nothing here is load-bearing: strip
   this block and the site is still locked, just less obviously.
   ===================================================================== */

/* Nav links that lost their href. Dimmed, cursor unchanged from text, and a
   hover tip saying when they come back. */
.nav__link.is-locked {
  opacity: 0.42;
  cursor: default;
  pointer-events: auto;      /* keep the title tooltip reachable */
}
.nav__link.is-locked:hover { color: inherit; }

/* The two static header chips. Same shape as the live ones session.js and
   wallet.js used to paint, with the dot drained of colour so they do not
   read as connected. */
.wchip.is-locked {
  opacity: 0.45;
  cursor: default;
  pointer-events: none;
}
.wchip.is-locked .wchip__dot {
  background: #7c705c;
  box-shadow: none;
}

/* Locked buttons that carry a second line ("this weekend"). The existing
   .btn.is-locked rules already dim and stack; this only stops the pointer. */
.btn.is-locked { cursor: default; }
a.btn.is-locked:hover { transform: none; filter: none; }

/* Inline text that used to be a link. */
span.is-locked[aria-disabled="true"] {
  opacity: 0.5;
  text-decoration: line-through;
}


/* == 7 Sep 2026, second pass ==========================================
   The card hand read as soft. Two causes, both fixed: the file was a 1600px
   re-encode at q86 (a second lossy pass over an already-lossy screenshot),
   and the frame was 620px wide, so the browser was minifying pixel art to
   0.39 of its size. The asset is now the full 1920x1080 at q95 and the frame
   is wider, which puts the minification at a much gentler ratio. */
.cta-shot { max-width: 880px; }


/* == 7 Sep 2026, second pass: LOCKED BUTTONS MUST LOOK LOCKED ==========
   Enter Estova and Founder Packs were already inert - no href, and on the
   public build no checkout code is even loaded - but they still rendered in
   full gold and copper, so they read as the two live things on the page and
   people kept pressing them.

   Desaturated and dimmed, with the press animation and the hover lift taken
   off, so the button does not answer the pointer at all. The "this weekend"
   sub-label keeps its own contrast, because that line is the one thing here
   worth reading. PUBLIC BUILD ONLY: none of this exists on testnet, where
   the same buttons are meant to work. */
.btn.is-locked,
a.btn.is-locked,
span.btn.is-locked {
  filter: grayscale(0.72) brightness(0.78);
  opacity: 0.72;
  cursor: default;
  box-shadow: none;
  transform: none !important;
}
.btn.is-locked:hover,
.btn.is-locked:active,
.btn.is-locked:focus {
  filter: grayscale(0.72) brightness(0.78);
  opacity: 0.72;
  transform: none !important;
  box-shadow: none;
}
/* The sub-label stays legible against the dimmed plate. */
.btn.is-locked .btn__lock {
  opacity: 1;
  filter: none;
  color: #fff;
}
