* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg: #fdf8f2;
  --bg-deep: #f6ede3;
  --surface: #ffffff;
  --surface-edge: #eee2d6;
  --text: #2b2125;
  --muted: #8a7a80;
  --tomato: #e8402f;
  --tomato-soft: #fff0ee;
  --tomato-edge: #ffd4cd;
  --rose: #e84d8a;
  --rose-soft: #fdeef5;
  --rose-edge: #f9cede;
  --gold: #e8a13a;
  --radius: 22px;
  --shadow-card: 0 2px 6px rgba(90, 45, 30, 0.05), 0 14px 34px rgba(90, 45, 30, 0.10);
  --shadow-card-hover: 0 4px 10px rgba(90, 45, 30, 0.07), 0 24px 54px rgba(90, 45, 30, 0.16);
  --font-display: "Bricolage Grotesque", "Segoe UI", system-ui, sans-serif;
  --font-body: "Outfit", "Segoe UI", system-ui, sans-serif;
}

html { scrollbar-color: #d8c8ba var(--bg); }

body {
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  overflow-x: hidden;
}

::selection { background: rgba(232, 77, 138, 0.22); }

/* ---------- warm stage background ---------- */
.bg-glow {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(70rem 36rem at 50% -12%, rgba(255, 214, 170, 0.55), transparent 62%),
    radial-gradient(46rem 26rem at 8% -4%, rgba(232, 64, 47, 0.10), transparent 60%),
    radial-gradient(46rem 26rem at 92% -4%, rgba(232, 77, 138, 0.10), transparent 60%),
    linear-gradient(180deg, #fffdfa 0%, var(--bg) 40%, var(--bg-deep) 100%);
}
.bg-glow::before,
.bg-glow::after {
  content: "";
  position: absolute;
  width: 36rem;
  height: 36rem;
  border-radius: 50%;
  filter: blur(100px);
  opacity: 0.55;
  animation: drift 30s ease-in-out infinite alternate;
}
.bg-glow::before {
  background: radial-gradient(circle, rgba(255, 168, 150, 0.30), transparent 70%);
  top: -14rem; left: -12rem;
}
.bg-glow::after {
  background: radial-gradient(circle, rgba(255, 173, 208, 0.30), transparent 70%);
  bottom: -16rem; right: -12rem;
  animation-delay: -15s;
}
@keyframes drift {
  from { transform: translate(0, 0) scale(1); }
  to   { transform: translate(4rem, 3rem) scale(1.12); }
}
/* fine paper grain */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E");
}

/* ---------- header ---------- */
.site-header {
  text-align: center;
  padding: 64px 16px 16px;
}
.site-header h1 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.4rem, 6vw, 4rem);
  letter-spacing: -0.03em;
  line-height: 1.1;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.32em;
  flex-wrap: wrap;
}
.site-header .grad {
  background: linear-gradient(100deg, var(--tomato) 10%, #f0356b 55%, var(--rose) 90%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.site-header .or {
  color: #b9a8ae;
  font-weight: 400;
  font-style: italic;
  font-size: 0.55em;
}
.emoji-bounce {
  display: inline-block;
  animation: bob 3.4s ease-in-out infinite;
  filter: drop-shadow(0 8px 16px rgba(180, 80, 60, 0.30));
}
.emoji-bounce.delay { animation-delay: -1.7s; }
@keyframes bob {
  0%, 100% { transform: translateY(0) rotate(-4deg); }
  50%      { transform: translateY(-9px) rotate(5deg); }
}
.tagline {
  color: var(--muted);
  margin-top: 14px;
  font-size: 1.08rem;
}

/* ---------- search ---------- */
.search-wrap { margin-top: 26px; }
.search-input {
  width: min(440px, 90vw);
  padding: 14px 22px;
  font-size: 1rem;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--surface-edge);
  border-radius: 99px;
  outline: none;
  box-shadow: 0 2px 10px rgba(90, 45, 30, 0.06);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.search-input::placeholder { color: #b3a4aa; }
.search-input:focus {
  border-color: var(--rose);
  box-shadow: 0 0 0 4px rgba(232, 77, 138, 0.13), 0 4px 18px rgba(232, 77, 138, 0.12);
}

/* ---------- gallery: flex + center so ANY number of cards sits centered ---------- */
.gallery {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 30px;
  max-width: 1180px;
  margin: 42px auto 90px;
  padding: 0 24px;
}
.empty-msg {
  flex-basis: 100%;
  text-align: center;
  color: var(--muted);
  padding: 70px 0;
  font-size: 1.12rem;
}

/* ---------- card ---------- */
.card {
  width: min(350px, 100%);
  background: var(--surface);
  border: 1px solid var(--surface-edge);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-card);
  transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.3, 1.15), box-shadow 0.25s ease;
  animation: card-in 0.55s cubic-bezier(0.2, 0.7, 0.3, 1) both;
  animation-delay: calc(var(--i, 0) * 80ms);
}
@keyframes card-in {
  from { opacity: 0; transform: translateY(22px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.card:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-card-hover);
}
.card[hidden] { display: none; }

.photo-wrap {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: #efe6dc;
}
.photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.5s ease;
}
.card:hover .photo { transform: scale(1.045); }
.photo-wrap.shake { animation: shake 0.4s ease; }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px) rotate(-1deg); }
  40% { transform: translateX(6px) rotate(1deg); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(3px); }
}

.splat-layer { position: absolute; inset: 0; pointer-events: none; z-index: 2; }
.splat {
  position: absolute;
  font-size: 2.2rem;
  transform: translate(-50%, -50%) scale(0.3);
  animation: splat-pop 1.6s ease forwards;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.35));
}
@keyframes splat-pop {
  0%   { transform: translate(-50%, -50%) scale(0.3); opacity: 1; }
  15%  { transform: translate(-50%, -50%) scale(1.5); }
  25%  { transform: translate(-50%, -50%) scale(1.1); }
  75%  { opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }
}

.card-body {
  padding: 20px 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 13px;
  /* fill the remaining card height so the vote row can be pinned to the bottom */
  flex: 1 1 auto;
}
.person-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.45rem;
  letter-spacing: -0.01em;
}
.person-action {
  color: var(--muted);
  line-height: 1.55;
  font-size: 0.98rem;
}

/* ---------- verdict bar ---------- */
/* margin-top:auto absorbs all leftover space, so the bar, the vote buttons and
   the voted note sit flush with the bottom of the card no matter how long or
   short the description is. Cards in a row are equal height already (flex
   stretch), so this lines the controls up across the whole row. */
.verdict-bar {
  margin-top: auto;
  height: 10px;
  border-radius: 99px;
  background: linear-gradient(90deg, #d8372a, #ff6a55);
  overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.18);
}
.verdict-rose {
  height: 100%;
  background: linear-gradient(90deg, #f0568f, #ff9ec4);
  width: 50%;
  margin-left: auto;
  border-radius: 0 99px 99px 0;
  transition: width 0.6s cubic-bezier(0.3, 0.8, 0.3, 1);
}

/* ---------- vote buttons ---------- */
.vote-row { display: flex; gap: 12px; }
.vote-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 13px 0;
  font-size: 1.1rem;
  font-family: inherit;
  font-weight: 500;
  border-radius: 14px;
  border: 1.5px solid var(--surface-edge);
  cursor: pointer;
  color: var(--text);
  background: #fbf7f2;
  transition: transform 0.12s ease, border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
}
.vote-btn:hover { transform: translateY(-2px) scale(1.03); }
.vote-btn:active { transform: scale(0.94); }
.tomato-btn:hover {
  border-color: var(--tomato);
  background: var(--tomato-soft);
  box-shadow: 0 8px 20px rgba(232, 64, 47, 0.18);
}
.rose-btn:hover {
  border-color: var(--rose);
  background: var(--rose-soft);
  box-shadow: 0 8px 20px rgba(232, 77, 138, 0.18);
}
.btn-emoji { font-size: 1.5rem; }
.count { font-weight: 700; font-variant-numeric: tabular-nums; }

/* ---------- only-love posts: the card dodges tomatoes ---------- */
/* The tomato button stays visible and clickable — throwing one is the joke.
   No vote is ever recorded, so the verdict bar is pure rose. */
.card.love-only .verdict-bar {
  background: linear-gradient(90deg, #f0568f, #ff9ec4);
}

/* float above the rest of the gallery while it is out of position */
.card.love-only {
  transition: transform 0.34s cubic-bezier(0.22, 1.4, 0.36, 1);
  will-change: transform;
}
.card.dodging { z-index: 40; }

/* the brief crouch before it springs away */
.card.ducking {
  transition: transform 0.16s ease-in, opacity 0.16s ease-in;
  transform: scale(0.82) rotate(-3deg) !important;
  opacity: 0.35;
}

.taunt {
  position: absolute;
  left: 50%;
  top: 44%;
  z-index: 5;
  transform: translate(-50%, -50%) rotate(var(--tilt, 0deg));
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.15rem, 4.2vw, 1.7rem);
  white-space: nowrap;
  color: #fff;
  padding: 10px 20px;
  border-radius: 99px;
  background: linear-gradient(135deg, var(--tomato), var(--rose));
  box-shadow: 0 10px 26px rgba(190, 60, 80, 0.4);
  pointer-events: none;
  animation: taunt-pop 1.5s cubic-bezier(0.2, 1.5, 0.4, 1) forwards;
}
/* --taunt-scale is set by app.js to 1/cardScale: when the card shrinks to make
   room to dodge on a small screen, this keeps the taunt at a readable size. */
@keyframes taunt-pop {
  0%   { transform: translate(-50%, -50%) rotate(var(--tilt, 0deg)) scale(calc(0.4 * var(--taunt-scale, 1))); opacity: 0; }
  18%  { transform: translate(-50%, -50%) rotate(var(--tilt, 0deg)) scale(calc(1.14 * var(--taunt-scale, 1))); opacity: 1; }
  32%  { transform: translate(-50%, -60%) rotate(var(--tilt, 0deg)) scale(calc(1 * var(--taunt-scale, 1))); }
  75%  { opacity: 1; }
  100% { transform: translate(-50%, -130%) rotate(var(--tilt, 0deg)) scale(calc(0.95 * var(--taunt-scale, 1))); opacity: 0; }
}

/* a missed tomato splats on the page, not on a card */
.splat-loose {
  position: fixed;
  z-index: 30;
  pointer-events: none;
}

/* locked state after voting */
.card.voted .vote-btn {
  opacity: 0.4;
  cursor: not-allowed;
}
.card.voted .vote-btn:hover {
  transform: none;
  border-color: var(--surface-edge);
  background: #fbf7f2;
  box-shadow: none;
}
.card.voted .vote-btn.chosen {
  opacity: 1;
  border-color: var(--rose);
  background: var(--rose-soft);
  box-shadow: 0 4px 16px rgba(232, 77, 138, 0.16);
}
.card.voted .tomato-btn.chosen {
  border-color: var(--tomato);
  background: var(--tomato-soft);
  box-shadow: 0 4px 16px rgba(232, 64, 47, 0.16);
}
/* On a dodging card the tomato button is never spent, so it must not look
   disabled even after this visitor has given their rose. */
.card.voted.love-only .tomato-btn {
  opacity: 1;
  cursor: pointer;
}
.card.voted.love-only .tomato-btn:hover {
  transform: translateY(-2px) scale(1.03);
  border-color: var(--tomato);
  background: var(--tomato-soft);
  box-shadow: 0 8px 20px rgba(232, 64, 47, 0.18);
}

.voted-note {
  align-self: center;
  color: #937f37;
  font-size: 0.88rem;
  padding: 6px 14px;
  border-radius: 99px;
  background: #fdf5df;
  border: 1px solid #f3e4b8;
}
.voted-note.wiggle { animation: wiggle 0.4s ease; color: var(--tomato); }
@keyframes wiggle {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  50% { transform: translateX(5px); }
  75% { transform: translateX(-3px); }
}

/* flying projectile */
.projectile {
  position: fixed;
  font-size: 2rem;
  z-index: 999;
  pointer-events: none;
  will-change: transform;
  filter: drop-shadow(0 6px 10px rgba(120, 50, 35, 0.35));
}

/* ---------- person-name links to per-person pages ---------- */
.person-name a {
  color: inherit;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.person-name a:hover,
.person-name a:focus-visible {
  color: var(--tomato);
  border-bottom-color: var(--rose);
}

/* single-person page */
.gallery-single { margin-bottom: 30px; }
.crumb { margin-bottom: 10px; }
.single-extra {
  max-width: 640px;
  margin: 0 auto 60px;
  padding: 0 24px;
  text-align: center;
  color: var(--muted);
}
.single-extra h2 {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--text);
  margin-bottom: 8px;
}
.single-extra p { margin-bottom: 8px; }

/* ---------- prose pages (privacy) ---------- */
.prose {
  max-width: 720px;
  margin: 0 auto 70px;
  padding: 0 24px;
  line-height: 1.65;
}
.prose h2 {
  font-family: var(--font-display);
  font-size: 1.35rem;
  margin: 32px 0 10px;
}
.prose p { margin-bottom: 14px; color: #4a3d43; }
.prose a { color: var(--rose-deep); }
.prose code {
  background: #f4ece3;
  border: 1px solid var(--surface-edge);
  border-radius: 6px;
  padding: 1px 6px;
  font-size: 0.92em;
}
.prose-table {
  width: 100%;
  border-collapse: collapse;
  margin: 12px 0 18px;
  font-size: 0.95rem;
  display: block;
  overflow-x: auto;
}
.prose-table th, .prose-table td {
  border: 1px solid var(--surface-edge);
  padding: 9px 12px;
  text-align: left;
  vertical-align: top;
}
.prose-table th { background: #f8f1e9; font-weight: 600; }
.prose-meta { color: var(--muted); font-size: 0.88rem; margin-top: 28px; }

/* screen-reader-only label */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.site-footer { text-align: center; padding: 24px; }
.admin-link { color: var(--muted); text-decoration: none; font-size: 0.9rem; }
.admin-link:hover { color: var(--text); }

/* ---------- admin page ---------- */
.admin-wrap { max-width: 660px; margin: 0 auto 90px; padding: 0 20px; }
.panel {
  background: var(--surface);
  border: 1px solid var(--surface-edge);
  border-radius: var(--radius);
  padding: 30px;
  margin-top: 26px;
  box-shadow: var(--shadow-card);
}
.panel h2 { font-family: var(--font-display); font-weight: 700; margin-bottom: 18px; }
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.field label { color: var(--muted); font-size: 0.92rem; }
.field input[type="text"],
.field input[type="password"],
.field input[type="file"],
.field textarea {
  background: #fbf7f2;
  border: 1px solid var(--surface-edge);
  border-radius: 12px;
  color: var(--text);
  padding: 12px 14px;
  font-size: 1rem;
  font-family: inherit;
}
.field textarea { resize: vertical; min-height: 84px; }
.checkbox-field label {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  font-size: 0.98rem;
  cursor: pointer;
}
.checkbox-field input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--rose);
  cursor: pointer;
}
.love-tag {
  margin-left: 8px;
  font-size: 0.78rem;
  font-weight: 600;
  color: #b03c6d;
  padding: 2px 8px;
  border-radius: 99px;
  background: var(--rose-soft);
  border: 1px solid var(--rose-edge);
}
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--rose);
  box-shadow: 0 0 0 3px rgba(232, 77, 138, 0.13);
}

.btn {
  background: linear-gradient(135deg, var(--tomato), var(--rose));
  color: #fff;
  border: none;
  border-radius: 12px;
  padding: 13px 24px;
  font-size: 1rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  box-shadow: 0 8px 22px rgba(232, 70, 90, 0.30);
  transition: filter 0.15s ease, transform 0.12s ease;
}
.btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
.btn:active { transform: scale(0.97); }
.btn.secondary {
  background: #f1e9e0;
  color: var(--text);
  box-shadow: none;
}

.msg { margin-top: 12px; font-size: 0.95rem; }
.msg.error { color: var(--tomato); }
.msg.ok { color: #2f9e5f; }

.admin-list { list-style: none; margin-top: 8px; display: flex; flex-direction: column; gap: 12px; }
.admin-list li {
  display: flex;
  align-items: center;
  gap: 14px;
  background: #fbf7f2;
  border: 1px solid var(--surface-edge);
  border-radius: 14px;
  padding: 10px 14px;
}
.admin-list img { width: 56px; height: 56px; object-fit: cover; border-radius: 12px; }
.admin-list .info { flex: 1; min-width: 0; }
.admin-list .info .nm { font-weight: 600; }
.admin-list .info .ac {
  color: var(--muted);
  font-size: 0.88rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.admin-list .stats { color: var(--muted); font-size: 0.9rem; white-space: nowrap; }
.del-btn {
  background: none;
  border: 1px solid var(--surface-edge);
  color: var(--muted);
  border-radius: 9px;
  padding: 6px 11px;
  font-family: inherit;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.del-btn:hover { color: var(--tomato); border-color: var(--tomato); }
.topbar-row { display: flex; justify-content: space-between; align-items: center; gap: 16px; }
.whoami { color: var(--muted); font-size: 0.88rem; margin-top: 2px; }

/* ---------- accessibility ---------- */
@media (prefers-reduced-motion: reduce) {
  .emoji-bounce, .bg-glow::before, .bg-glow::after, .card { animation: none; }
  .card { opacity: 1; }
}
