/*
 * くじカス箱。9 枚から 1 枚選んで、それを指でめくる。
 *
 * 組み立ては占いと同じにする。一番くじを引く人が知っている所作は
 * 「選ぶ → めくる」のひとつで、ここを別の形にすると別のゲームの語彙になる。
 * 分けるのは色と文言だけ。占いは赤×金の実券風、こちらは藍×銀にする。
 *
 * 数値は box_controller.js / box_board_controller.js の定数と対になっている。
 * 共通化はしない。占いは本番で動いていて、触ると壊す。2 つ動いてから抜くか決める。
 */

.box-stage {
  --box-navy: #24406f;
  --box-navy-dark: #182c4f;
  --box-ink: #1b2537;
  --box-paper: #fbf8f2;
  --box-gold: #caa03c;

  /* 券の面。藍地に銀の帯を通す。占いの赤×金と対になる */
  --box-face:
    linear-gradient(145deg,
      transparent 0 22%,
      rgb(255 255 255 / .1) 22% 31%,
      transparent 31% 68%,
      rgb(206 216 232 / .82) 68% 76%,
      transparent 76%),
    var(--box-navy-dark);

  position: relative;
  display: grid;
  justify-items: center;
  gap: 14px;
}

/* ---------- 手順1: 9 枚から 1 枚選ぶ ---------- */
.box-board {
  width: 100%;
  max-width: 390px;
  margin: 0 auto;
  padding: 15px 13px 13px;
  border: 1px solid #e6e9ef;
  border-radius: 14px;
  background: #f9fafc;
}

.box-board-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 12px;
  padding: 0 2px;
}

.box-board-head strong { font-size: 13px; font-weight: 900; color: #171717; }
.box-board-head span { font-size: 10px; font-weight: 800; color: #777; }

.box-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.box-pick {
  position: relative;
  aspect-ratio: 1.62 / 1;
  padding: 0;
  border: 0;
  border-radius: 3px;
  overflow: hidden;
  background: var(--box-face);
  box-shadow: 0 2px 6px rgb(0 0 0 / .16);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform .16s cubic-bezier(.2, .9, .25, 1), box-shadow .16s ease, opacity .16s ease;
}

.box-pick::before {
  content: "";
  position: absolute;
  inset: 4px;
  border: 1px solid rgb(255 255 255 / .42);
}

.box-pick-label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #fff;
  font-size: 10px;
  font-weight: 900;
}

.box-pick-num {
  position: absolute;
  right: 5px;
  bottom: 3px;
  color: rgb(255 255 255 / .82);
  font-size: 10px;
  font-weight: 900;
  line-height: 1;
}

.box-pick.is-selected {
  transform: translateY(-5px) scale(1.035);
  box-shadow: 0 9px 18px rgb(0 0 0 / .24);
  outline: 3px solid var(--box-navy);
  outline-offset: 2px;
  z-index: 3;
}

.box-pick.is-dimmed { opacity: .55; }
.box-pick:active { transform: translateY(-2px) scale(.99); }
.box-pick[disabled] { cursor: default; }

/* 押した直後。選ばれなかった券を引いて、選んだ 1 枚だけを残す */
.box-board.is-drawing .box-board-head,
.box-board.is-drawing .box-panel,
.box-board.is-drawing .box-pick:not(.is-selected) {
  opacity: 0;
  transition: opacity .2s ease;
}

.box-board.is-drawing .box-pick.is-selected {
  transform: translateY(-9px) scale(1.06);
  transition: transform .22s cubic-bezier(.2, .9, .25, 1);
}

.box-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 56px;
  margin-top: 13px;
  padding-top: 12px;
  border-top: 1px solid #e6e9ef;
}

.box-panel-copy { min-width: 0; }
.box-panel-copy span { display: block; font-size: 9px; font-weight: 800; color: #777; line-height: 1.4; }
.box-panel-copy strong { display: block; margin-top: 2px; font-size: 14px; font-weight: 900; color: #171717; line-height: 1.4; }

.box-confirm {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 16px;
  border: 0;
  border-radius: 10px;
  background: var(--box-navy);
  color: #fff;
  font: inherit;
  font-size: 12px;
  font-weight: 900;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity .16s ease, transform .16s ease;
}

.box-confirm[disabled] { opacity: .25; cursor: default; }
.box-confirm:not([disabled]):active { transform: scale(.97); }

/* ---------- 手順2: 選んだその券を、自分の指でめくる ---------- */
.box-holder {
  position: relative;
  width: 100%;
  max-width: 340px;
  aspect-ratio: 1.62 / 1;
  perspective: 1100px;
}

.box-stage.is-drawn .box-holder {
  animation: box-appear .4s ease both;
}

@keyframes box-appear {
  from { transform: translateY(-8px) scale(1.04); opacity: 0; }
  to   { transform: translateY(0) scale(1); opacity: 1; }
}

.box-ticket {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  border-radius: 6px;
  background: var(--box-face);
  box-shadow: 0 10px 22px -12px rgb(0 0 0 / .65);
  transform-style: preserve-3d;

  /* 指で引っぱる操作なので、券の文字が選択されないようにする */
  user-select: none;
  -webkit-user-select: none;
}

/* 券の外枠。めくれるのは内側だけ */
.box-outer {
  position: absolute;
  inset: 0;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: .18em;
  color: rgb(255 255 255 / .5);
  pointer-events: none;
}

.box-outer-tl { position: absolute; left: 12px; top: 10px; }
.box-outer-tr { position: absolute; right: 12px; top: 10px; }
.box-outer-bl { position: absolute; left: 12px; bottom: 9px; }

/* ---------- めくれる窓 ---------- */
.box-window {
  position: absolute;
  inset: 26px 15px 24px;
  border-radius: 2px;
  background: var(--box-ink);
  transform-style: preserve-3d;
  z-index: 2;
}

/* 結果の面。めくった端から見える */
.box-face {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 3px;
  border-radius: 2px;
  background: var(--box-paper);
  color: var(--box-ink);
  z-index: 1;
  /* 走りの帯を面の外へ逃がしたとき、藍の枠の上に残らないよう切る */
  overflow: hidden;
}

.box-face .box-result { font-size: 30px; font-weight: 700; letter-spacing: .14em; }
.box-face .box-result-note { font-size: 10px; font-weight: 600; letter-spacing: .12em; color: #86868e; }

/* 当たりだけ色がつく。ハズレは紙のままなので、色が出た瞬間に分かる */
.box-face.is-won {
  /* 放射の筋を薄く敷いて箔の券にする。中央は白まで飛ばさない。文字が読めなくなる */
  background:
    repeating-conic-gradient(from 0deg at 50% 46%, rgb(255 255 255 / .14) 0deg 5deg, transparent 5deg 10deg),
    radial-gradient(circle at 50% 44%, #fcf0c8 0%, #f3dca0 48%, #e6c476 100%);
  /* 金の細い二重罫。賞状の縁 */
  box-shadow:
    inset 0 0 0 1px var(--box-gold),
    inset 0 0 0 4px rgb(252 240 200 / .9),
    inset 0 0 0 5px rgb(202 160 60 / .55);
}

/* 文字も箔押しにする。上から下へ濃くなる金に、白い縁で浮かせる */
.box-face.is-won .box-result {
  background: linear-gradient(180deg, #b27b1f 0%, #7d4c0b 58%, #a8731c 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 1px 0 rgb(255 255 255 / .75));
}
.box-face.is-won .box-result-note { color: #a57c2c; }

/* 欧文は字間を開けないと券面で締まらない */
.box-result-note.is-won { font-size: 9px; letter-spacing: .3em; text-indent: .3em; }

/* 閉じている面。めくるぶんだけ左から削れていく。
   券の外枠と同じ面を敷いて、めくるまでは 1 枚の券に見えるようにする */
.box-closed {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 5px;
  border-radius: 2px;
  background: var(--box-face);
  will-change: clip-path;
}

.box-closed::before {
  content: "";
  position: absolute;
  inset: 6px;
  border: 1px solid rgb(255 255 255 / .3);
}

.box-closed strong { font-size: 14px; font-weight: 900; letter-spacing: .1em; color: #fff; }
.box-closed span { font-size: 9px; font-weight: 700; letter-spacing: .06em; color: rgb(255 255 255 / .7); }

/* 券らしさを出すだけの飾り */
.box-barcode {
  margin-top: 4px;
  width: 96px;
  height: 14px;
  background: repeating-linear-gradient(90deg,
    #fff 0 2px, transparent 2px 4px, #fff 4px 5px, transparent 5px 8px);
  opacity: .5;
}

/* めくれて立ち上がる紙 */
.box-paper {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  z-index: 12;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  transform-origin: right center;
  transform-style: preserve-3d;
  will-change: width, transform;
  filter: drop-shadow(5px 3px 6px rgb(0 0 0 / .22));
}

.box-paper-front,
.box-paper-back { position: absolute; inset: 0; }
.box-paper-front { background: var(--box-face); }
/* めくれて裏返った側は紙の地 */
.box-paper-back {
  opacity: 0;
  background: repeating-linear-gradient(90deg, #f6f6f4 0 1px, #e7e7e4 1px 3px, #faf9f6 3px 6px);
}

/* めくれ目 */
.box-curl {
  position: absolute;
  top: -2px;
  bottom: -2px;
  left: 0;
  width: 22px;
  z-index: 13;
  opacity: 0;
  pointer-events: none;
  background: linear-gradient(90deg,
    rgb(255 255 255 / .1) 0%,
    rgb(255 255 255 / .96) 30%,
    rgb(182 182 182 / .72) 52%,
    rgb(255 255 255 / .88) 72%,
    rgb(0 0 0 / .17) 100%);
  filter: drop-shadow(4px 0 5px rgb(0 0 0 / .2));
}

/* つまみ。めくれ目についていく */
.box-handle {
  position: absolute;
  left: 0;
  top: 22%;
  width: 48px;
  height: 56%;
  z-index: 15;
  display: flex;
  align-items: center;
  padding: 0 0 0 6px;
  border: 0;
  background: #fff;
  clip-path: polygon(0 0, 68% 0, 100% 50%, 68% 100%, 0 100%);
  box-shadow: 2px 0 4px rgb(0 0 0 / .18);
  font: inherit;
  color: #444;
  cursor: grab;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}

.box-handle span { font-size: 8px; font-weight: 700; letter-spacing: .04em; line-height: 1.15; }
.box-ticket.is-dragging .box-handle { cursor: grabbing; }

/* めくり終わったら、めくり紙・めくれ目・つまみは要らない。
   これらは px で実寸を持つので、残しておくと画面幅が変わったとき古い寸法のまま
   横にあふれてページが横スクロールする */
.box-stage.is-revealed .box-paper,
.box-stage.is-revealed .box-curl,
.box-stage.is-revealed .box-handle {
  display: none;
}

/* ---------- めくる途中の演出 ----------
 * 一番くじONLINE の「ペ」「リ」にならう。めくり始めて is-effect が付くと、券の上に 2 つの文字が
 * 1 つずつ飛び出す。3 つとも動きは同じで、変わるのは文字と色だけ。派手さの差はつけない。
 *   ペリ    赤の「ペ」「リ」
 *   ドキドキ 桃色の「ドキ」「ドキ」
 *   ゴクリ   青の「ゴク」「リ」（藍の券に沈まない青。金は当たりの色なので使わない）
 * 開き切ったら文字は引っ込める。結果の面に被ったままだと読めない */
.box-fx-front {
  position: absolute;
  inset: 0;
  z-index: 30;
  pointer-events: none;
  opacity: 0;
}

.box-stage.is-effect .box-fx-front { opacity: 1; }

.box-stage.is-revealed .box-fx-front {
  opacity: 0;
  transition: opacity .35s .5s;
}

/* 白い縁と影で、券の藍の上でも読める */
.box-fx-char {
  position: absolute;
  font-size: 60px;
  font-weight: 900;
  line-height: 1;
  color: #e11d48;
  -webkit-text-stroke: 3px #fff;
  paint-order: stroke fill;
  filter: drop-shadow(0 3px 0 rgb(0 0 0 / .25));
  transform: scale(0) rotate(-12deg);
}

.box-fx-char-first { left: 8%; top: -14%; }
.box-fx-char-second { right: 10%; top: -6%; }

/* 2 文字の語は、1 文字ぶんの大きさに揃える */
.box-fx-doki .box-fx-char,
.box-fx-gokuri .box-fx-char { font-size: 44px; }

.box-fx-doki .box-fx-char { color: #db2777; }
.box-fx-gokuri .box-fx-char { color: #2563eb; }

.box-stage.is-effect .box-fx-char-first { animation: box-fx-pop .5s cubic-bezier(.2, 1.6, .4, 1) forwards; }
.box-stage.is-effect .box-fx-char-second { animation: box-fx-pop .5s .28s cubic-bezier(.2, 1.6, .4, 1) forwards; }

@keyframes box-fx-pop {
  from { transform: scale(0) rotate(-12deg); }
  to   { transform: scale(1) rotate(-6deg); }
}

/* 当たりだけ、開き切った瞬間に金の光が弾ける */
.box-flash {
  position: absolute;
  inset: -30%;
  z-index: 26;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(closest-side, #fff 0 20%, rgb(255 230 160 / .85) 45%, transparent 75%);
}

.box-stage.is-drawn.is-revealed .box-flash { animation: box-flash .9s ease-out both; }

@keyframes box-flash {
  0%   { opacity: 0; transform: scale(.6); }
  25%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.3); }
}

/* ---------- 案内 ---------- */
.box-hint {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 700;
  color: #64646d;
}

.box-hint b { animation: box-nudge 1.1s ease-in-out infinite; font-style: normal; }

@keyframes box-nudge {
  0%, 100% { transform: translateX(0); opacity: .55; }
  50%      { transform: translateX(5px); opacity: 1; }
}

/* めくっている間は薄くするだけ。場所を空けておかないと、触った瞬間に下が跳ねる */
.box-stage.is-peeling .box-hint {
  opacity: 0;
  transition: opacity .18s;
}

/* めくり終わったら場所ごと消す。opacity だけだと、券と結果の間に空白が残り続ける */
.box-stage.is-revealed .box-hint { display: none; }

/* ---------- 当たりの演出 ---------- */
/* 金の走り。走り終わったら必ず面の外へ出す。
   fill-mode を付けないと、終わったあと白い帯が券の真ん中に居座って文字が読めなくなる */
.box-stage.is-revealed .box-face.is-won::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 2px;
  background: linear-gradient(105deg, transparent 38%, rgb(255 255 255 / .7) 50%, transparent 62%);
  transform: translateX(-130%);
  animation: box-sheen 4.2s .1s ease-in-out infinite;
}

/* 最初の 3 割で横切り、あとは面の外で待つ。いつ撮っても帯が文字に被り続けることはない */
@keyframes box-sheen {
  0%        { transform: translateX(-130%); }
  30%, 100% { transform: translateX(130%); }
}

/* 当たりの券は、めくったあとも金の縁で光らせておく。めくる前に付けると結果が分かる */
.box-stage.is-revealed .box-ticket.is-won {
  box-shadow:
    0 0 0 2px #e7c56a,
    0 0 24px 3px rgb(231 197 106 / .5),
    0 10px 22px -12px rgb(0 0 0 / .65);
}

/* キラキラ。演出が終わったあとも瞬き続ける。
   消え切らずに小さく残る形にしておくと、いつスクショを撮っても星が写る */
.box-twinkle {
  position: absolute;
  left: var(--x);
  top: var(--y);
  z-index: 6;
  width: var(--s);
  height: var(--s);
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(.4);
  background: radial-gradient(closest-side,
    #fff 0 14%, rgb(255 255 255 / .92) 30%, rgb(255 238 186 / .45) 55%, transparent 76%);
  clip-path: polygon(50% 0%, 56% 44%, 100% 50%, 56% 56%, 50% 100%, 44% 56%, 0% 50%, 44% 44%);
  /* 明るい金の上でも白が飛ばないよう、金色の光で縁取る */
  filter: drop-shadow(0 0 4px rgb(222 168 48 / .95));
}

.box-stage.is-revealed .box-twinkle {
  animation: box-twinkle 2.6s var(--d) ease-in-out infinite both;
}

/* 小さくなっても半分より下には縮めない。いちばん小さい瞬間に撮られても、星と分かる大きさを残す */
@keyframes box-twinkle {
  0%, 100% { transform: translate(-50%, -50%) scale(.55) rotate(0deg);  opacity: .8; }
  45%      { transform: translate(-50%, -50%) scale(1.1) rotate(22deg); opacity: 1; }
  70%      { transform: translate(-50%, -50%) scale(.75) rotate(36deg); opacity: .9; }
}

/* キラーン。当たりの面の上で、四方に伸びる光が 2 つ順に走る */
.box-glint {
  position: absolute;
  z-index: 6;
  width: 86px;
  height: 86px;
  opacity: 0;
  pointer-events: none;
  /* 芯を白のまま残す。ぼかし切ると明るい金の面で飛ぶ */
  background: radial-gradient(closest-side,
    #fff 0 11%, rgb(255 255 255 / .96) 26%, rgb(255 236 176 / .55) 48%, transparent 76%);
  clip-path: polygon(50% 0%, 56% 44%, 100% 50%, 56% 56%, 50% 100%, 44% 56%, 0% 50%, 44% 44%);
  filter: drop-shadow(0 0 7px rgb(255 205 96 / .95));
}

/* 窓の角にかけて、藍の枠にも重ねる */
.box-glint-a { left: 2px; top: 6px; }
.box-glint-b { right: 4px; bottom: 8px; width: 62px; height: 62px; }

.box-stage.is-revealed .box-glint-a { animation: box-glint .85s .25s ease-out both; }
.box-stage.is-revealed .box-glint-b { animation: box-glint .8s .62s ease-out both; }

@keyframes box-glint {
  0%   { transform: scale(.2) rotate(-18deg); opacity: 0; }
  35%  { transform: scale(1.1) rotate(6deg); opacity: 1; }
  70%  { transform: scale(.85) rotate(16deg); opacity: .8; }
  100% { transform: scale(.35) rotate(26deg); opacity: 0; }
}

.box-confetti {
  position: absolute;
  inset: 0 0 auto;
  height: 300px;
  overflow: hidden;
  pointer-events: none;
  z-index: 20;
}

.box-confetti i {
  position: absolute;
  top: -16px;
  left: var(--x);
  width: 7px;
  height: 11px;
  background: var(--c);
  opacity: 0;
}

.box-stage.is-revealed .box-confetti i {
  animation: box-fall 1.7s var(--d) cubic-bezier(.25, .6, .5, 1) forwards;
}

@keyframes box-fall {
  from { transform: translateY(0) rotate(var(--r)); opacity: 1; }
  to   { transform: translateY(300px) rotate(calc(var(--r) + 480deg)); opacity: 0; }
}

/* 動きを切っている人には、出た状態と開いた状態だけを見せる */
@media (prefers-reduced-motion: reduce) {
  .box-stage.is-effect .box-fx-char,
  .box-stage.is-revealed .box-flash,
  .box-stage.is-drawn .box-holder,
  .box-hint b,
  .box-stage.is-revealed .box-twinkle,
  .box-stage.is-revealed .box-face.is-won::after,
  .box-stage.is-revealed .box-glint-a,
  .box-stage.is-revealed .box-glint-b,
  .box-stage.is-revealed .box-confetti i {
    animation: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .box-stage.is-revealed .box-twinkle {
    opacity: .9;
    transform: translate(-50%, -50%) scale(.7);
  }

  /* 動かさずに、出た状態だけを見せる */
  .box-stage.is-effect .box-fx-char { transform: scale(1) rotate(-6deg); }
}
