/* ============================================================
   components.css -- Reusable UI: buttons, panels, stats, result cards, modal, desync overlay, avatar, animation polish, donate banner.
   Part of the split from the original single style.css.
   ============================================================ */

/* ---------- BUTTONS ---------- */
.btn {
  font-family: var(--font-term);
  font-weight: 500;
  font-size: 1.05rem;
  padding: 0.6rem 1.3rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  transition: transform 0.18s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.18s cubic-bezier(0.2, 0.8, 0.2, 1);
  box-shadow: 3px 3px 0 var(--ink), var(--shadow-sm);
}

.btn:hover {
  transform: translate(-2px, -2px);
  box-shadow: 5px 5px 0 var(--ink), var(--shadow-md);
}

.btn:active {
  transform: translate(1px, 1px);
  box-shadow: 1px 1px 0 var(--ink);
}

.btn:focus-visible {
  outline: 3px solid var(--cursed-green);
  outline-offset: 2px;
}

.btn-primary {
  background: var(--ink);
  color: var(--fluoro-white);
}

.btn-danger {
  background: var(--danger-red);
  color: var(--fluoro-white);
  border-color: var(--bg-black);
}

.btn-outline {
  background: transparent;
}

.btn-small {
  font-size: 0.95rem;
  padding: 0.4rem 0.9rem;
}

/* ---------- MAIN / PANELS ---------- */
main {
  max-width: 52rem;
  margin: 0 auto;
  padding: 0 1.25rem 3rem;
  display: flex;
  flex-direction: column;
  gap: 2.25rem;
}

/* The level/entity detail pages carry a badge sidebar, vote widget, tabs,
   and images alongside the prose, so the whole page -- not just the
   article card -- gets more breathing room. Without this, <main>'s own
   52rem cap clamped the wide article down before it could ever reach its
   own max-width below. */
main.main-wide {
  max-width: 74rem;
}

main[hidden] {
  display: none;
}

.panel {
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--radius-md);
  padding: 2rem;
  box-shadow: 6px 6px 0 rgba(var(--shadow-rgb), 0.28), var(--shadow-md);
  position: relative;
}

.panel h2 {
  font-weight: 700;
  margin-top: 0;
  font-size: 1.4rem;
}

.panel-desc {
  opacity: 0.8;
  margin-top: -0.5rem;
  font-size: 1.05rem;
}

/* ---------- STATS ---------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1rem;
}

.stat-card {
  background: var(--fluoro-white);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  padding: 1.1rem 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  box-shadow: var(--shadow-sm);
  border-left: 3px solid var(--wall-yellow-dark);
}

.stat-label {
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  opacity: 0.6;
}

.stat-value {
  font-family: var(--font-term);
  font-weight: 700;
  font-size: 2rem;
  line-height: 1.1;
}

.stat-flavor {
  font-size: 0.9rem;
  opacity: 0.7;
  font-style: italic;
}

/* ---------- RESULT CARDS ---------- */
.result-card {
  margin-top: 1.25rem;
  background: var(--fluoro-white);
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--stain-brown);
  border-radius: var(--radius-md);
  padding: 1.25rem 1.4rem;
  box-shadow: var(--shadow-sm);
}

.result-tag {
  font-weight: bold;
  font-size: 1.15rem;
  margin: 0 0 0.5rem;
  color: var(--stain-brown);
}

.result-body {
  margin: 0;
  font-size: 1.1rem;
  line-height: 1.5;
}

.entity-meta {
  margin: 0.6rem 0 0;
  font-size: 0.95rem;
  opacity: 0.7;
}

.wall-text {
  font-size: 1.05rem;
  line-height: 1.6;
  white-space: pre-wrap;
}

/* ---------- MODAL (generic, used by konami egg + shop checkout) ---------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(13, 11, 6, 0.85);
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.modal-overlay[hidden] {
  display: none;
}

.modal-box {
  background: var(--paper);
  border: 3px solid var(--ink);
  border-radius: var(--radius-lg);
  padding: 2rem;
  max-width: 28rem;
  text-align: center;
  box-shadow: 6px 6px 0 rgba(var(--shadow-rgb), 0.28), var(--shadow-lg);
}

.modal-box h2 {
  font-weight: 700;
  font-size: 1.3rem;
}

.modal-box p {
  font-size: 1.05rem;
  line-height: 1.5;
}

.modal-box.glow-green {
  border-color: var(--cursed-green);
  box-shadow: 0 0 40px var(--cursed-green);
}

.modal-box.glow-pink {
  border-color: var(--glitch-pink);
  box-shadow: 0 0 40px var(--glitch-pink);
}

.modal-box.glow-red {
  border-color: var(--danger-red);
  box-shadow: 0 0 40px var(--danger-red);
}

.lives-display {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  color: var(--danger-red);
}

.lives-display .life-icon.spent {
  opacity: 0.25;
}

/* ---------- DESYNC OVERLAY (signature moment) ---------- */
.desync-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 2rem;
  pointer-events: none;
  opacity: 0;
  font-weight: 700;
  font-size: clamp(1.4rem, 5vw, 2.6rem);
  color: var(--fluoro-white);
  background: var(--bg-black);
  text-shadow: 3px 0 var(--glitch-pink), -3px 0 var(--cursed-green);
}

.desync-overlay.active {
  opacity: 1;
  animation: desyncFlicker 1.3s steps(2, jump-none);
}

.shake-wrapper.desync-shake {
  animation: shakeIt 0.4s steps(2, jump-none) 3;
}

@keyframes desyncFlicker {
  0%, 100% { opacity: 0; }
  10%, 85% { opacity: 1; }
  20% { opacity: 0.4; }
  30% { opacity: 1; }
}

@keyframes shakeIt {
  0% { transform: translate(0, 0) skew(0deg); }
  50% { transform: translate(4px, -3px) skew(0.5deg); }
  100% { transform: translate(-3px, 2px) skew(-0.5deg); }
}

.desync-overlay.idiot {
  color: var(--glitch-pink);
  text-shadow: none;
  font-weight: bold;
  flex-direction: column;
  gap: 1rem;
}

.desync-overlay img#idiotGif {
  max-width: min(85vw, 440px);
  height: auto;
  border-radius: var(--radius-md);
  border: 3px solid var(--glitch-pink);
  animation: idiotPop 0.4s ease;
}

@keyframes idiotPop {
  0% { transform: scale(0.4); opacity: 0; }
  60% { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

.shake-wrapper.idiot-shake {
  animation: idiotShake 0.5s steps(2, jump-none) 3;
}

@keyframes idiotShake {
  0% { transform: translate(0, 0) rotate(0deg); }
  20% { transform: translate(-6px, 4px) rotate(-1deg); }
  40% { transform: translate(6px, -4px) rotate(1deg); }
  60% { transform: translate(-4px, -6px) rotate(-1deg); }
  80% { transform: translate(4px, 6px) rotate(1deg); }
  100% { transform: translate(0, 0) rotate(0deg); }
}

/* ---------- AVATAR ---------- */
.avatar-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

.avatar-preview, .avatar-placeholder {
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  border: 2px solid var(--ink);
  object-fit: cover;
}

.avatar-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--fluoro-white);
  font-size: 1.6rem;
  color: var(--stain-brown);
}

.avatar-placeholder[hidden], .avatar-preview[hidden] {
  display: none;
}

.avatar-preview.large, .avatar-placeholder.large {
  width: 6rem;
  height: 6rem;
  font-size: 2.4rem;
  margin: 0 auto 0.75rem;
}

.profile-header {
  text-align: center;
  max-width: 32rem;
  width: 100%;
  margin: 0 auto 1.5rem;
}

/* ---------- ANIMATION POLISH ---------- */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.hero, .page-hero, main {
  animation: fadeInUp 0.5s ease both;
}

@keyframes temptPulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.035); }
}

/* .btn-danger no longer pulses -- a delete/destructive button should read
   as "be careful", not "click me". temptPulse is still used deliberately
   for the typing minigame's critical threat-meter (see minigames.css),
   which is exactly the kind of "deliberate call to action" moment it
   should be reserved for. */

@keyframes softGlow {
  0%, 100% { box-shadow: 6px 6px 0 rgba(var(--shadow-rgb), 0.35); }
  50% { box-shadow: 6px 6px 0 rgba(var(--shadow-rgb), 0.35), 0 0 18px rgba(239, 45, 118, 0.25); }
}

.featured-level {
  animation: softGlow 4s ease-in-out infinite;
}

.current-level-banner {
  max-width: 780px;
  width: 100%;
  margin: 0 auto 1.5rem;
  border-color: var(--stain-brown);
  text-align: center;
}

.current-level-banner .result-tag {
  font-size: 1.2rem;
}

.current-level-banner p {
  margin: 0.35rem 0;
}

.current-level-banner .btn {
  margin-top: 0.75rem;
}

/* ---------- DONATE BANNER ---------- */
.site-notice {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-banner);
  background: var(--paper);
  border-top: 2px solid var(--ink);
  padding: 0.85rem 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.25rem;
  flex-wrap: wrap;
  box-shadow: 0 -3px 10px rgba(0, 0, 0, 0.25);
  animation: donateSlideUp 0.4s ease;
}

.site-notice.dismissed {
  animation: donateSlideDown 0.35s ease forwards;
}

@keyframes donateSlideUp {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

@keyframes donateSlideDown {
  from { transform: translateY(0); opacity: 1; }
  to { transform: translateY(100%); opacity: 0; }
}

.site-notice-close {
  position: absolute;
  top: 0.3rem;
  right: 0.6rem;
  background: transparent;
  border: none;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  color: var(--ink);
  padding: 0.2rem 0.5rem;
}

.site-notice-close:hover { color: var(--stain-brown); }
.site-notice-close:focus-visible { outline: 3px solid var(--cursed-green); outline-offset: 2px; }

.site-notice-text {
  font-family: var(--font-term);
  font-size: 1rem;
  margin: 0;
  max-width: 32rem;
  text-align: center;
}

#pp-widget-holder {
  flex-shrink: 0;
}

/* Keeps the fixed banner from covering footer content, form buttons, or
   the last lines of an article while it's visible. Sized generously since
   actual banner height varies with PayPal widget load state and text
   wrapping. */
body.has-site-notice {
  padding-bottom: 6rem;
}

@media (max-width: 700px) {
  .site-notice {
    padding: 1.5rem 1rem 0.85rem;
    text-align: center;
  }

  body.has-site-notice {
    padding-bottom: 9rem;
  }
}

