/* dropzone.css — the file drop zone, shared by `/import` and `/create`.
 *
 * ⚠️ Permanently linked in `index.html` (like `app.css` and `v3.css`) instead of going
 *    through `pagecss.js`. That loader keeps **exactly one** `[data-page-css]` sheet in the
 *    head at a time, so a second permanent sheet is only safe if it cannot collide with a
 *    page sheet. Every selector here is `dz-` prefixed for that reason — do not add an
 *    unprefixed one, that turns this into a tenth sheet that fights the other nine.
 *
 * ⚠️ Effects are CSS-only (conic-gradient ring, radial spotlight, transform tilt). No
 *    library: the component libraries this is modelled on ship Tailwind + framer-motion,
 *    and neither is in this build.
 *
 * ⚠️⚠️ Every animation here is decoration and every one of them is switched off under
 *    `prefers-reduced-motion`. A drop zone is a *control*: if the motion makes someone
 *    queasy they still have to be able to hand us their artwork.
 */

.dz {
  position: relative;
  border-radius: 22px;
  padding: 1.5px;                       /* the ring lives in this padding */
  background: var(--line-s);            /* fallback ring when the beam is off */
  overflow: hidden;
  isolation: isolate;
  transform: perspective(900px) rotateX(var(--dz-rx, 0deg)) rotateY(var(--dz-ry, 0deg));
  transition: transform .18s ease, box-shadow .22s ease;
  box-shadow: 0 10px 30px rgba(var(--sh), .05);
}
.dz:hover { box-shadow: 0 18px 46px rgba(var(--sh), .09); }

/* ── the beam: a conic gradient spinning behind the 1.5px padding ring ────────── */
.dz::before {
  content: ''; position: absolute; z-index: 0;
  /* ⚠️ Must be square and far larger than the box, or the conic sweep visibly
     stretches along the long edge instead of travelling round it. */
  top: 50%; left: 50%; width: 160%; aspect-ratio: 1; translate: -50% -50%;
  background: conic-gradient(from 0deg,
    transparent 0 62%, var(--lime-mid) 74%, var(--lime) 82%, transparent 92%);
  opacity: 0;
  animation: dz-spin 4.5s linear infinite;
  transition: opacity .25s ease;
}
.dz:hover::before, .dz.over::before, .dz.busy::before { opacity: 1; }
.dz.over::before { animation-duration: 1.4s; }
.dz.busy::before { animation-duration: 2s; opacity: 1; }
@keyframes dz-spin { to { rotate: 360deg; } }

/* the fill that the ring surrounds */
.dz-in {
  position: relative; z-index: 1;
  border-radius: 20.5px;
  background: var(--white);
  padding: 34px 26px 28px;
  text-align: center;
  transition: background .2s ease;
}
.dz.over .dz-in { background: linear-gradient(180deg, #FBFEF2, var(--white) 70%); }

/* ── spotlight that follows the cursor ───────────────────────────────────────── */
.dz-glow {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  border-radius: 20.5px;
  opacity: 0; transition: opacity .3s ease;
  background: radial-gradient(320px circle at var(--dz-mx, 50%) var(--dz-my, 50%),
                              rgba(201, 231, 80, .28), transparent 62%);
}
.dz:hover .dz-glow, .dz.over .dz-glow { opacity: 1; }

/* ── drifting specks, only while the pointer is over ─────────────────────────── */
.dz-sparks { position: absolute; inset: 0; z-index: 2; pointer-events: none;
             opacity: 0; transition: opacity .35s ease; }
.dz:hover .dz-sparks, .dz.over .dz-sparks { opacity: 1; }
.dz-spark { position: absolute; width: 4px; height: 4px; border-radius: 50%;
            background: var(--lime-mid); animation: dz-drift 5.5s ease-in-out infinite; }
@keyframes dz-drift {
  0%, 100% { transform: translateY(0) scale(.7); opacity: .25; }
  50%      { transform: translateY(-18px) scale(1); opacity: .85; }
}

/* ── content ─────────────────────────────────────────────────────────────────── */
.dz-mark {
  width: 58px; height: 58px; margin: 0 auto; border-radius: 17px;
  display: flex; align-items: center; justify-content: center;
  font-size: 25px; color: var(--lime-deep);
  background: var(--lime-soft); border: 1px solid var(--lime);
  transition: transform .25s cubic-bezier(.34, 1.56, .64, 1), border-radius .25s ease;
}
.dz:hover .dz-mark { transform: translateY(-3px) rotate(-6deg); }
.dz.over .dz-mark { transform: scale(1.12) rotate(6deg); border-radius: 22px; }

.dz-t { font-size: 15.5px; font-weight: 800; margin-top: 14px; }
.dz-p { margin: 9px auto 0; width: 100%; max-width: 430px; font-size: 12.5px;
        line-height: 1.6; color: var(--muted-d); }

.dz-btns { display: flex; gap: 10px; justify-content: center; margin-top: 15px;
           flex-wrap: wrap; }
.dz-btn {
  font: 600 12.5px var(--sans); cursor: pointer;
  padding: 9px 17px; border-radius: 999px;
  border: 1px solid var(--line-d); background: var(--white); color: var(--ink);
  transition: background .16s ease, border-color .16s ease, transform .16s ease;
}
.dz-btn:hover { background: var(--hover); border-color: var(--muted); transform: translateY(-1px); }
.dz-btn.key { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.dz-btn.key:hover { background: var(--ink-h); }
.dz-btn:disabled { opacity: .5; cursor: default; transform: none; }

/* ⚠️ `width: 100%` alongside `max-width` is the house rule (see the sentinel in
   `regress.py`): in normal flow it changes nothing, and as a flex item it is the
   difference between "centred at 430px" and "squeezed to the content width". */
.dz-hint { margin: 9px auto 0; width: 100%; max-width: 430px; font-size: 11.5px;
           line-height: 1.55; color: var(--muted-d); }
.dz-fmt { margin-top: 12px; font-family: var(--mono); font-size: 10.5px;
          letter-spacing: .04em; color: var(--faint); }

/* ── picked files ────────────────────────────────────────────────────────────── */
.dz-chips { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;
            margin-top: 15px; }
.dz-chip { display: flex; align-items: center; gap: 7px; max-width: 190px;
           padding: 5px 11px 5px 5px; border-radius: 999px;
           background: var(--fill-c); border: 1px solid var(--line-s);
           font-size: 11.5px; }
.dz-chip img { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.dz-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── busy / error ────────────────────────────────────────────────────────────── */
.dz-busy { margin-top: 14px; font-size: 12.5px; font-weight: 700; color: var(--lime-deep); }
.dz-busy i { display: inline-block; width: 7px; height: 7px; border-radius: 50%;
             background: var(--lime-mid); margin-right: 7px;
             animation: dz-pulse 1s ease-in-out infinite; }
@keyframes dz-pulse { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }

/* ⚠️⚠️ The failure has to land **inside the drop zone**, where the eye already is.
   It used to be a bare English `upload failed` in the far column, so a 401 read
   as "clicking the button does nothing at all". */
.dz-err {
  margin-top: 15px; padding: 11px 14px; border-radius: 13px; text-align: left;
  background: var(--err-bg); border: 1px solid var(--err-bd); color: var(--err-t);
  font-size: 12.5px; line-height: 1.55;
}
.dz-err.warn { background: var(--warn-bg); border-color: var(--warn-bd); color: var(--warn-t); }
.dz-err b { display: block; margin-bottom: 3px; font-size: 13px; }

/* ── compact variant (`/create` reference images) ────────────────────────────── */
.dz.mini { border-radius: 15px; }
.dz.mini .dz-in { border-radius: 13.5px; padding: 13px 15px;
                  display: flex; align-items: center; gap: 12px; text-align: left; }
.dz.mini .dz-glow { border-radius: 13.5px; }
.dz.mini .dz-mark { width: 34px; height: 34px; border-radius: 11px; font-size: 15px; margin: 0; }
.dz.mini .dz-t { margin-top: 0; font-size: 13px; }
.dz.mini .dz-p { margin: 2px 0 0; font-size: 11px; }
.dz.mini .dz-chips { margin: 0 0 0 auto; }

@media (max-width: 900px) {
  .dz-in { padding: 26px 16px 22px; }
  .dz.mini .dz-in { flex-wrap: wrap; }
}

/* ⚠️⚠️ Decoration off, control intact. Tilt is dropped too — it is transform-driven
   motion tied to pointer movement, which is the worst kind for vestibular triggers. */
@media (prefers-reduced-motion: reduce) {
  .dz { transform: none !important; transition: none; }
  .dz::before, .dz-spark, .dz-busy i { animation: none; }
  .dz::before { opacity: 0; }
  .dz.over { background: var(--lime); }
  .dz-mark { transition: none; }
  .dz:hover .dz-mark, .dz.over .dz-mark { transform: none; }
}
