/* ============================================================
   ITEMS — floor emoji, hand slots, drag ghost, loupe
============================================================ */
/* Drawn at its true size. It used to be set at 44px and then squashed with
   transform:scale(0.43), which means the glyph was rasterised big and
   resampled down every frame. On platforms whose emoji are bitmap strikes
   (iOS, most Android) that resampling is a real softening; on Windows, where
   they're vector, it mostly just wastes work. Either way there's no reason
   to paint at 2.3x the size you want. */
.item{
  position:absolute;z-index:6;
  font-size:var(--item-size);line-height:1;
  padding:var(--item-pad);
  cursor:pointer;
  /* text-shadow, NOT filter:drop-shadow.

     WebKit renders a drop-shadow filter on a colour-emoji glyph from the
     element's layer bounds rather than the glyph's alpha, so every item on
     the floor carried a dark SQUARE behind it. Against the near-black outer
     ring of a floor gradient you cannot see it; the moment an item's box
     crosses the wall it shows up as the emoji's black corners, which is
     exactly the two dark triangles at the bottom of a round room.
     text-shadow is computed from the glyph mask, so it cannot do that — and
     it needs no compositing layer per item, which on a Mega floor of 170
     emoji is 170 fewer layers. Keep every item shadow in this file a
     text-shadow. */
  text-shadow:0 2px 1.5px rgba(0,0,0,.35);
  /* Only the pick-up lift animates: dragging moves left/top, which this does
     not touch, and a fling sets its own inline transition. */
  transition:transform .12s ease;
}
/* Held. Bigger, with the shadow of something off the floor — the only signal
   that a tap has become a drag. The scale lives in the inline transform
   (itemTransform() in js/main.js), because that string also carries the item's
   resting rotation. */
.item.held{
  text-shadow:0 7px 7px rgba(0,0,0,.5);
  cursor:grabbing;
}
/* Keys and coins lie UNDER the clutter — buildRoomEl() draws them first, and
   every item shares a z-index, so DOM order is the burial. Dimmed a touch so
   the corner of one poking out of a pile reads as being underneath it rather
   than as the top of the stack. */
.item.buried{opacity:.84;text-shadow:0 1px 1px rgba(0,0,0,.55)}

/* HOMESICK (talent). Everything on this floor with an open home in this room.
   About a quarter of a typical floor, so it has to sit far below the gold of a
   correct placement or it becomes the loudest thing on screen for the whole
   level. A warm halo and nothing else: no ring, no pulse, no lift. It is
   ambient information you read out of the corner of your eye while deciding
   what to carry, not a thing demanding to be tapped — and it deliberately does
   NOT touch transform, which carries the item's resting rotation. */
.item.homesick{
  /* Two stops: a tight near-white rim so the glyph separates from whatever it
     is lying on, then a wider gold bloom that survives being scaled down on a
     phone. One soft 5px shadow was the first attempt and it was invisible at
     the size items are actually drawn — a talent you cannot see is a talent
     that does nothing, which is the whole thing this pass was about. */
  text-shadow:0 2px 1.5px rgba(0,0,0,.35),
              0 0 2px rgba(255,238,190,.95),
              0 0 7px rgba(245,197,66,.85),
              0 0 12px rgba(245,197,66,.55);
}
/* A buried token that is also homesick keeps its dimming — being under a pile
   outranks being near home, because the burial is a gameplay rule. */
.item.buried.homesick{
  opacity:.84;
  text-shadow:0 1px 1px rgba(0,0,0,.55);
}
@media (prefers-reduced-motion: no-preference){
  .item.homesick{transition:text-shadow .25s ease}
}

/* JUST GATHERED — the tail of Cluster's slide (performCluster in js/main.js).
   A brief flare as each one lands, so a room where thirty-two things moved at
   once reads as thirty-two arrivals rather than a blur that has already
   stopped. text-shadow rather than transform, for the same reason .homesick is:
   the item's transform is set inline and carries its resting rotation, which a
   keyframe would throw away. */
.item.gathered{ animation:gathered .68s ease-out }
@keyframes gathered{
  0%  { text-shadow:0 0 6px #fff, 0 0 15px var(--gold), 0 0 28px var(--gold) }
  100%{ text-shadow:0 2px 1.5px rgba(0,0,0,.35) }
}
@media (prefers-reduced-motion:reduce){
  .item.gathered{ animation:none }
}

/* Debug: where is the key. Lifted above the clutter it is hiding under, ringed
   and pulsing, so it reads through a pile of forty other emoji. */
.item.revealed{
  z-index:19;
  /* Deliberately NOT animating the item's own transform: that is set inline and
     carries the item's resting rotation, which a keyframe would throw away. */
  text-shadow:0 0 5px #fff, 0 0 11px var(--gold), 0 0 20px var(--gold);
}
.item.revealed::after{
  content:"";position:absolute;inset:-10px;border-radius:50%;
  border:2px solid var(--gold);
  animation:keyring 1.2s ease-out infinite;
}
@keyframes keyring{
  0%{transform:scale(.65);opacity:1}
  100%{transform:scale(2);opacity:0}
}
@media (prefers-reduced-motion: reduce){
  .item.revealed::after{animation:none;opacity:.9}
}

.slot{
  width:56px;height:56px;border-radius:14px;
  background:var(--slot);
  border:2px solid #241c11;
  box-shadow:inset 0 2px 6px rgba(0,0,0,.4);
  display:flex;align-items:center;justify-content:center;
  font-size:30px;cursor:pointer;position:relative;
  transition:transform .1s, box-shadow .15s;
  margin-top:14px;
}
.slot.sel{
  border-color:var(--gold);
  box-shadow:0 0 0 3px rgba(245,197,66,.35), inset 0 2px 6px rgba(0,0,0,.4);
  transform:translateY(-4px);
}
.slot.dragging{opacity:.35}

#dragGhost{
  position:fixed;z-index:200;pointer-events:none;
  font-size:38px;line-height:1;transform:translate(-50%,-60%);
  text-shadow:0 6px 9px rgba(0,0,0,.5);
  display:none;
}

#loupe{
  position:fixed;z-index:210;pointer-events:none;display:none;
  flex-direction:column;align-items:center;gap:3px;
  transform:translate(-50%,-100%);
}
#loupe .lemoji{
  font-size:48px;line-height:1;
  text-shadow:0 5px 8px rgba(0,0,0,.45);
}
#loupe.mouse .lemoji{display:none}
#loupe .lname{
  font-size:11px;font-weight:800;letter-spacing:.06em;
  color:var(--ink);background:var(--panel);
  padding:3px 9px;border-radius:999px;
  box-shadow:0 3px 8px rgba(0,0,0,.4);
  white-space:nowrap;
}

/* ---------- THE PET ----------
   IT WALKS NOW, and this file is half of why it did not before. The transition
   was .9s, matching an action tick that jumped it straight to its destination
   — but renderRoom() destroys and rebuilds every element in the room, so there
   was no previous value for the transition to run FROM. A CSS transition
   cannot animate an element into existence. It appeared where it was going,
   every time.

   js/main.js now moves it about 1.5% of the room per 110ms step and repaints
   only the pet (petRepaint), so the element survives between steps. The
   transition here just has to be long enough to smooth one step into the next
   and short enough not to lag behind it — a hair over the step interval,
   linear, because eased steps read as limping.

   Drawn above the clutter (see buildRoomEl) — the one thing in a room that
   moves on its own must never be behind anything. */
.pet{
  position:absolute;
  font-size:calc(var(--item-size) * 1.15);
  line-height:1;
  transform:translate(-50%,-50%);
  transition:left .13s linear, top .13s linear;
  z-index:6;
  cursor:pointer;
  filter:drop-shadow(0 2px 2px rgba(0,0,0,.45));
  animation:petbob 2.4s ease-in-out infinite;
}
/* Carrying something is worth seeing from across the room: that is when the
   pet is interruptible, and the only time tapping it does anything. */
.pet.carrying{ animation-duration:1.2s }
/* Actually going somewhere. The bob IS the gait — a faster one on the move and
   a slow one standing about is the difference between walking and idling, and
   it costs one class. */
.pet.walking{ animation-duration:.42s }
.petload{
  position:absolute;left:58%;top:-42%;
  font-size:.62em;
  transform:rotate(8deg);
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.4));
}
@keyframes petbob{
  0%,100%{ transform:translate(-50%,-50%) }
  50%    { transform:translate(-50%,-58%) }
}
@media (prefers-reduced-motion:reduce){
  .pet{ animation:none; transition:none }
}

/* ---------- THE HELPER, IN YOUR HANDS ----------
   Dressed as a hand slot because that is what it means, and deliberately NOT
   one: every handler on #invBar reads .slot's dataset.slot as an index into
   G.inv. See petPick() in js/main.js. Ringed, because it is the one thing in
   that row that is not cargo. */
.petchip{
  width:56px;height:56px;border-radius:14px;flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;
  font-size:31px;line-height:1;cursor:pointer;
  background:var(--slot);
  border:2px solid #241c11;
  /* .slot's own margin-top, so the chip sits on the same line as the hand
     slots rather than floating above them (#handLabel needs that 14px). */
  margin-top:14px;
  box-shadow:inset 0 0 0 2px rgba(245,197,66,.55);
  /* Its own keyframes, NOT petbob: that one bobs by rewriting the
     translate(-50%,-50%) a floor pet is positioned with, and the chip is a
     flex child with no such offset to preserve. */
  animation:chipbob 1.6s ease-in-out infinite;
}
@keyframes chipbob{
  0%,100%{ transform:translateY(0) }
  50%    { transform:translateY(-4px) }
}
@media (prefers-reduced-motion:reduce){
  .petchip{ animation:none }
}
