/* =====================================================================
   $BAG — one screen, one bag, one address.

   Palette is sampled off the drawing rather than chosen: #16fa87 is the
   sack's green, #13f996 the banner's. Everything else is a dilution of
   those on pure black, which is the paper the art was drawn on.
   ===================================================================== */

:root {
  --ink: #16fa87;
  --ink2: #13f996;
  --paper: #000;
  --line: #1c7a52;
  --faint: #2b6b4c;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100svh;
  display: grid;
  place-items: center;

  background: var(--paper);
  color: var(--ink);
  font-family: "Patrick Hand", "Comic Sans MS", cursive;

  /* One soft glow behind the bag so the black reads as space rather than
     a flat void. Cheaper and calmer than the old crosshatch. */
  background-image: radial-gradient(58vmin 58vmin at 50% 40%,
                                    rgba(22, 250, 135, .10), transparent 70%);
}

main {
  display: grid;
  justify-items: center;
  gap: clamp(16px, 3vmin, 28px);
  padding: 7vmin clamp(16px, 4vw, 28px);
  width: 100%;
  max-width: 560px;
}

/* ------------------------------------------------------------------- the bag */

.stage {
  display: grid;
  justify-items: center;
}

/* Vertical travel only. `alternate` is what sells the gravity: an ease-out
   on the way up plays back mirrored on the way down, so it decelerates into
   the apex and accelerates into the floor without a second keyframe set. */
.hopper {
  animation: rise .58s ease-out infinite alternate;
  will-change: transform;
}

.bag {
  display: block;
  /* Sized off width, capped by height. vmin alone made the bag tiny on a
     phone, where the short side is the width; the vh term is what stops it
     overflowing a short landscape window instead. */
  width: clamp(180px, min(52vw, 34vh), 288px);
  height: auto;
  transform-origin: 50% 100%;
  animation: squash 1.16s infinite;
  will-change: transform;
  filter: drop-shadow(0 0 26px rgba(22, 250, 135, .26));
}

.shade {
  margin-top: clamp(8px, 1.5vmin, 14px);
  width: clamp(118px, min(34vw, 22vh), 190px);
  height: clamp(10px, 2.2vmin, 18px);
  border-radius: 50%;
  opacity: .75;
  background: radial-gradient(closest-side,
                              rgba(22, 250, 135, .42), transparent);
  animation: shade .58s ease-out infinite alternate;
}

/* A percentage here resolves against the bag's own height, so the hop stays
   proportional to the bag instead of ballooning on a tall monitor the way a
   vmin distance does. */
@keyframes rise {
  to { transform: translateY(-18%); }
}

/* Runs at double the rise duration so the two squashes land exactly on the
   two moments the bag touches down. */
@keyframes squash {
  0%   { transform: scale(1.10, .90); }
  13%  { transform: scale(1, 1); }
  87%  { transform: scale(1, 1); }
  100% { transform: scale(1.10, .90); }
}

@keyframes shade {
  to { transform: scale(.60); opacity: .30; }
}

/* ---------------------------------------------------------------- the words */

h1 {
  margin: 0;
  font-size: clamp(30px, 7vmin, 52px);
  font-weight: 400;
  letter-spacing: .06em;
  line-height: 1;
}

/* The whole address block is the button, so there is nothing to aim at. */
.ca {
  appearance: none;
  -webkit-appearance: none;
  display: grid;
  gap: 5px;
  justify-items: center;
  width: 100%;
  padding: 14px 18px;
  background: transparent;
  color: inherit;
  font: inherit;
  border: 1.5px dashed var(--faint);
  border-radius: 14px;
  cursor: default;
  transition: border-color .18s ease, background-color .18s ease,
              transform .12s ease;
}

.ca.live {
  border-style: solid;
  border-color: var(--line);
  cursor: pointer;
}

.ca.live:hover {
  border-color: var(--ink2);
  background: rgba(22, 250, 135, .06);
}

.ca.live:active { transform: translateY(1px); }

.ca:focus-visible {
  outline: 2px solid var(--ink2);
  outline-offset: 3px;
}

/* Hex needs a monospace to be checkable at a glance, even on a handwritten
   page. It is the one thing here nobody should have to squint at. */
.addr {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: clamp(11px, 2.5vmin, 15px);
  letter-spacing: .02em;
  line-height: 1.45;
  word-break: break-all;
}

.hint {
  color: var(--faint);
  font-size: clamp(13px, 2.6vmin, 16px);
}

/* ------------------------------------------------------------------ the x */

/* Sits under the address block and stays quiet until pointed at - the bag is
   the page, this is a footnote. The negative margin pulls it against the
   button so the two read as one unit rather than two stacked elements, since
   main's own gap is tuned for the big blocks above. */
.x {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  margin-top: -6px;
  padding: 4px 6px;
  border-radius: 8px;
  color: var(--faint);
  text-decoration: none;
  font-size: clamp(13px, 2.6vmin, 16px);
  transition: color .18s ease;
}

.x:hover { color: var(--ink2); }

.x:focus-visible {
  outline: 2px solid var(--ink2);
  outline-offset: 2px;
}

/* currentColor is what lets the glyph follow the hover without a second rule,
   and em sizing keeps it locked to the handle beside it at every breakpoint. */
.x svg {
  width: .95em;
  height: .95em;
  fill: currentColor;
}

/* -------------------------------------------------------------- motion off */

@media (prefers-reduced-motion: reduce) {
  .hopper, .bag, .shade { animation: none; }
  .shade { opacity: .5; }
}
