/* Oink! Mahjong — tile bodies, sizes, orientations and states.
   Markup (js/ui/tilesvg.js): div.tile > div.tb (body + two-layer edge) > div.tf (face) > img.tile-art
   (a cached SVG image; flowers and seasons use an inline svg.tile-art)
   The box of .tile is the tile's full footprint (face + visible edge). Positioning transforms belong
   to .tile; every state effect below moves or lights .tb only, so the two never fight. */

.tile {
  --tw: 62px;                         /* width */
  --th: 84px;                         /* height incl. the edge */
  --td: 8px;                          /* visible thickness at the bottom */
  --tr: calc(var(--tw) * .13);        /* corner radius */
  --t-lift: 0px;
  --t-shadow: 0 1px 1px rgba(40, 24, 0, .28), 0 calc(var(--td) * .45) calc(var(--td) * 1.1) calc(var(--td) * -.25) rgba(20, 10, 0, .4);
  position: relative;
  display: inline-block;
  flex: none;
  width: var(--tw);
  height: var(--th);
  vertical-align: bottom;
  box-sizing: border-box;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* ---- sizes ---- */
.tile.t-hand  { --tw: 62px; --th: 84px; --td: 8px; }
.tile.t-meld  { --tw: 44px; --th: 60px; --td: 6px; }
.tile.t-river { --tw: 36px; --th: 49px; --td: 5px; }
.tile.t-opp   { --tw: 30px; --th: 41px; --td: 4px; }
.tile.t-wall  { --tw: 26px; --th: 19px; --td: 5px; --tr: 3.5px; }

/* ---- body: ivory face layer over a jade back layer, seen at the bottom edge ---- */
.tile > .tb {
  position: absolute;
  left: 0; top: 0; right: 0; bottom: 0;
  border-radius: var(--tr);
  background: linear-gradient(to top,
    #073f2b 0, #148157 calc(var(--td) * .5),
    #c7b487 calc(var(--td) * .5), #eadfc0 calc(var(--td) * .92), #fff7e4 var(--td));
  box-shadow: var(--t-shadow);
  transform: translateY(var(--t-lift));
  transition: transform .16s cubic-bezier(.3, 1.45, .55, 1), box-shadow .2s ease, opacity .25s ease, filter .25s ease;
}

.tile .tf {
  position: absolute;
  left: 0; top: 0; right: 0; bottom: var(--td);
  border-radius: var(--tr);
  overflow: hidden;
  background:
    radial-gradient(130% 70% at 28% 6%, rgba(255, 255, 255, .95) 0, rgba(255, 255, 255, 0) 62%),
    linear-gradient(to bottom, #fffbf1 0, #f9f0da 62%, #efe1bf 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .95),
    inset 1px 0 0 rgba(255, 255, 255, .6),
    inset 0 -1.5px 1px rgba(150, 118, 58, .28),
    inset -1px 0 1px rgba(150, 118, 58, .16);
}

.tile .tf > .tile-art {
  position: absolute;
  left: 0; top: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  -webkit-user-drag: none;
  object-fit: contain;
}

/* ---- face down: the jade back on top, the ivory layer at the bottom edge ---- */
.tile.t-back > .tb,
.tile.t-edge > .tb {
  background: linear-gradient(to top,
    #b7a172 0, #e6d8b3 calc(var(--td) * .42),
    #0a4a32 calc(var(--td) * .42), #127452 var(--td));
}
.tile.t-back .tf,
.tile.t-edge .tf {
  background:
    radial-gradient(120% 75% at 30% 8%, rgba(190, 255, 220, .38) 0, rgba(190, 255, 220, 0) 58%),
    linear-gradient(to bottom, #2aa574 0, #18875d 55%, #0f6c4a 100%);
  box-shadow:
    inset 0 1px 0 rgba(220, 255, 238, .55),
    inset 1px 0 0 rgba(220, 255, 238, .2),
    inset 0 -1.5px 1px rgba(0, 40, 22, .35);
}

/* ---- standing tile seen from behind (opponents' concealed hands):
        the thick top edge shows both layers, the jade back fills the rest ---- */
.tile.t-edge > .tb {
  background: linear-gradient(to bottom,
    #fffaeb 0, #e5d7b1 calc(var(--td) * .55),
    #3fbd8b calc(var(--td) * .55), #25976a var(--td), #25976a 100%);
  box-shadow: 0 1px 1px rgba(40, 24, 0, .3), 0 calc(var(--td) * .6) calc(var(--td) * 1.2) calc(var(--td) * -.3) rgba(20, 10, 0, .45);
}
.tile.t-edge .tf {
  top: var(--td);
  bottom: 0;
  border-radius: calc(var(--tr) * .5) calc(var(--tr) * .5) var(--tr) var(--tr);
  background:
    linear-gradient(to right, rgba(255, 255, 255, .12) 0, rgba(255, 255, 255, 0) 30%, rgba(0, 0, 0, 0) 70%, rgba(0, 30, 16, .18) 100%),
    linear-gradient(to bottom, #1f9166 0, #147a55 60%, #0c5f41 100%);
}
.tile.t-edge .tf > .tile-art { opacity: .7; }

/* ---- lying sideways (claimed tile in a meld): box is (th - td) x (tw + td), edge stays at the bottom ---- */
.tile.t-side {
  width: calc(var(--th) - var(--td));
  height: calc(var(--tw) + var(--td));
}
.tile.t-side .tf > .tile-art {
  left: 50%;
  top: 50%;
  width: var(--tw);
  height: calc(var(--th) - var(--td));
  transform: translate(-50%, -50%) rotate(-90deg);
}

/* ---- small sizes drop fine detail (ring beads on dots) so faces stay crisp ---- */
.tile.t-opp .pb, .tile.t-wall .pb { display: none; }

/* ---- wall: small face-down tiles seen from above ---- */
.tile.t-wall .tf > .tile-art { opacity: .8; object-fit: fill; }

/* ================= states ================= */

/* hover lift for tiles the player may pick (optional helper class) */
.tile.is-pickable { cursor: pointer; }
@media (hover: hover) {
  .tile.is-pickable:not(.is-selected):not(.is-disabled):hover { --t-lift: calc(var(--th) * -.07); }
}

/* selected: lifted with a warm glow; a soft shadow stays on the table */
.tile.is-selected { --t-lift: calc(var(--th) * -.2); }
.tile.is-selected > .tb {
  box-shadow:
    0 0 0 2px rgba(255, 216, 96, .95),
    0 0 14px 4px rgba(255, 196, 56, .55),
    0 calc(var(--th) * .16) calc(var(--th) * .14) calc(var(--th) * -.06) rgba(20, 10, 0, .38);
}
.tile.is-selected::before {
  content: '';
  position: absolute;
  left: 12%; right: 12%; bottom: -2px;
  height: calc(var(--td) * 1.2);
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0, 0, 0, .35), rgba(0, 0, 0, 0));
  pointer-events: none;
}

/* hint: soft golden pulse */
@keyframes tile-hint {
  0%, 100% { box-shadow: var(--t-shadow), 0 0 0 1.5px rgba(255, 208, 90, .55), 0 0 5px 1px rgba(255, 196, 56, .3); }
  50%      { box-shadow: var(--t-shadow), 0 0 0 2.5px rgba(255, 214, 96, .98), 0 0 18px 6px rgba(255, 196, 56, .62); }
}
.tile.is-hint > .tb { animation: tile-hint 1.5s ease-in-out infinite; }
.tile.is-hint.is-selected > .tb { animation: none; }

/* freshly drawn: drops in, then a glint sweeps the face once */
@keyframes tile-drop {
  0%   { transform: translateY(calc(var(--th) * -.45)) rotate(-4deg); opacity: 0; }
  55%  { transform: translateY(calc(var(--th) * .04)) rotate(.6deg); opacity: 1; }
  78%  { transform: translateY(calc(var(--th) * -.025)); }
  100% { transform: translateY(var(--t-lift)); }
}
@keyframes tile-glint {
  0%   { background-position: 160% 0; opacity: 1; }
  100% { background-position: -60% 0; opacity: 1; }
}
.tile.is-new > .tb { animation: tile-drop .42s cubic-bezier(.25, .8, .35, 1) backwards; }
.tile.is-new.is-hint > .tb { animation: tile-drop .42s cubic-bezier(.25, .8, .35, 1) backwards, tile-hint 1.5s ease-in-out .42s infinite; }
.tile.is-new .tf::before {
  content: '';
  position: absolute;
  left: 0; top: 0; right: 0; bottom: 0;
  z-index: 1;
  background: linear-gradient(110deg, rgba(255, 255, 255, 0) 35%, rgba(255, 255, 255, .85) 50%, rgba(255, 255, 255, 0) 65%);
  background-size: 250% 100%;
  background-position: -60% 0;
  animation: tile-glint .7s ease-out .3s backwards;
  pointer-events: none;
}

/* disabled: greyed out */
.tile.is-disabled { cursor: not-allowed; }
.tile.is-disabled > .tb { filter: saturate(.3) brightness(.8); }

/* wait: tiles that would complete the hand (jade highlight) */
.tile.is-wait > .tb {
  box-shadow: var(--t-shadow), 0 0 0 2px #43d6b1, 0 0 12px 3px rgba(67, 214, 177, .55);
}
.tile.is-wait .tf::after {
  content: '';
  position: absolute;
  left: 0; top: 0; right: 0; bottom: 0;
  z-index: 1;
  background: linear-gradient(to top, rgba(67, 214, 177, .22), rgba(67, 214, 177, 0) 60%);
  pointer-events: none;
}

/* exposed: a piggy flipped it outward — tilted, with a stamp */
@keyframes tile-stamp {
  0%   { transform: translateX(-50%) rotate(-14deg) scale(2); opacity: 0; }
  60%  { transform: translateX(-50%) rotate(8deg) scale(.92); opacity: 1; }
  100% { transform: translateX(-50%) rotate(5deg) scale(1); opacity: 1; }
}
.tile.is-exposed { z-index: 2; }
.tile.is-exposed > .tb {
  transform: translateY(calc(var(--th) * -.26)) rotate(-11deg);
  box-shadow: 0 0 0 2px rgba(255, 110, 140, .9), 0 calc(var(--th) * .18) calc(var(--th) * .16) calc(var(--th) * -.05) rgba(20, 10, 0, .4);
}
.tile.is-exposed::after {
  content: 'EXPOSED!';
  position: absolute;
  left: 50%;
  top: calc(var(--th) * -.62);
  z-index: 3;
  padding: .28em .5em .22em;
  border: 2px solid #fff;
  border-radius: .5em;
  background: #e8364f;
  color: #fff;
  font: 900 calc(var(--tw) * .19)/1 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: .03em;
  white-space: nowrap;
  box-shadow: 0 3px 8px rgba(0, 0, 0, .3);
  transform: translateX(-50%) rotate(5deg);
  animation: tile-stamp .45s cubic-bezier(.3, 1.4, .5, 1) backwards;
  pointer-events: none;
}

/* claimed: the discard went to someone's meld, dimmed in the river */
.tile.is-claimed > .tb { opacity: .4; filter: grayscale(.55); }

/* last discard: a bobbing pink marker above, pink rim */
@keyframes tile-marker {
  0%, 100% { transform: translateY(0) rotate(-45deg); }
  50%      { transform: translateY(calc(var(--tw) * -.12)) rotate(-45deg); }
}
.tile.is-last > .tb {
  box-shadow: var(--t-shadow), 0 0 0 2px #ff6f8e, 0 0 10px 2px rgba(255, 111, 142, .55);
}
.tile.is-last::before {
  content: '';
  position: absolute;
  left: 50%;
  top: calc(var(--tw) * -.56);
  z-index: 3;
  width: calc(var(--tw) * .42);
  height: calc(var(--tw) * .42);
  margin-left: calc(var(--tw) * -.21);
  border: 2px solid #fff;
  border-radius: 50% 50% 50% 0;
  background: #ff5f83;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .3);
  box-sizing: border-box;
  transform: rotate(-45deg);
  animation: tile-marker 1s ease-in-out infinite;
  pointer-events: none;
}

/* winning: golden glow with a shimmer across the face */
@keyframes tile-win {
  0%, 100% { box-shadow: var(--t-shadow), 0 0 0 2px #ffd54a, 0 0 12px 4px rgba(255, 196, 40, .6); }
  50%      { box-shadow: var(--t-shadow), 0 0 0 2.5px #ffe27a, 0 0 22px 8px rgba(255, 196, 40, .8); }
}
@keyframes tile-shimmer {
  0%   { background-position: 170% 0; }
  60%, 100% { background-position: -70% 0; }
}
.tile.is-winning > .tb { animation: tile-win 1.8s ease-in-out infinite; }
.tile.is-winning .tf::after {
  content: '';
  position: absolute;
  left: 0; top: 0; right: 0; bottom: 0;
  z-index: 1;
  background: linear-gradient(110deg, rgba(255, 244, 200, 0) 42%, rgba(255, 244, 200, .38) 50%, rgba(255, 244, 200, 0) 58%);
  background-size: 250% 100%;
  animation: tile-shimmer 2.4s ease-in-out infinite;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .tile > .tb, .tile::before, .tile::after, .tile .tf::before, .tile .tf::after {
    animation: none !important;
    transition: none !important;
  }
}

/* ---- effects: lite (js/ui/perf.js): glows hold still instead of pulsing (a box-shadow animation repaints
   its tile on every frame); the winning shimmer is dropped. */
.fx-lite .tile.is-hint > .tb { animation: none; box-shadow: var(--t-shadow), 0 0 0 2.5px rgba(255, 214, 96, .98), 0 0 12px 4px rgba(255, 196, 56, .5); }
.fx-lite .tile.is-new.is-hint > .tb { animation: tile-drop .42s cubic-bezier(.25, .8, .35, 1) backwards; }
.fx-lite .tile.is-winning > .tb { animation: none; box-shadow: var(--t-shadow), 0 0 0 2.5px #ffe27a, 0 0 16px 6px rgba(255, 196, 40, .7); }
.fx-lite .tile.is-winning .tf::after { animation: none; background: none; }
