/* poidh reel — full-bleed vertical snap scroll.
   Dark-only by design: the photo is the product, and a light chrome competes with it. */

:root {
  --ink: #f4f4f5;
  --ink-dim: rgba(244, 244, 245, 0.62);
  --paid: #4ade80;
  --rejected: #f87171;
  --pending: #fbbf24;
  --open: #60a5fa;
  --pad: clamp(16px, 4vw, 28px);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: #08080a;
  color: var(--ink);
  font: 400 16px/1.45 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  overscroll-behavior: none;
}

/* The scroller. Cards are absolutely positioned inside it and a single tall spacer
   establishes the scroll height, so the DOM holds a handful of cards rather than 2,800. */
.reel {
  position: fixed;
  inset: 0;
  overflow-y: scroll;
  overflow-x: hidden;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
  outline: none;
}
.reel::-webkit-scrollbar { display: none; }

.spacer { width: 1px; }
.cards { position: absolute; inset: 0 0 auto 0; }

.card {
  position: absolute;
  left: 0;
  width: 100%;
  height: 100dvh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  overflow: hidden;
}

/* Blurred fill behind the photo, so any aspect ratio fills the screen without distortion
   or letterbox bars. */
.card-backdrop {
  position: absolute;
  inset: -8%;
  background-size: cover;
  background-position: center;
  filter: blur(38px) saturate(1.5) brightness(0.55);
  transform: scale(1.15);
  z-index: 0;
}

.card-photo {
  position: absolute;
  inset: 0;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  z-index: 1;
}

/* Blurhash stand-in: fill the frame. A blur has no detail to protect, and `contain` leaves it
   sitting in an obvious letterboxed band. Stays underneath the real photo permanently, so any
   `contain` letterbox gap around the real image shows blurred colour rather than empty space. */
.card-photo.is-placeholder {
  background-size: cover;
  aspect-ratio: auto;
}

/* Real IPFS photo (Phase 4). Transparent and non-interactive until it loads, then crossfades
   in over the blurhash. `contain` so the photo itself is never cropped. */
.card-photo-real {
  position: absolute;
  inset: 0;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  z-index: 1;
  opacity: 0;
  transition: opacity 240ms ease;
}
.card-photo-real.is-loaded { opacity: 1; }

/* Top scrim only — the HUD (fixed above the reel, no background of its own) needs this for
   legibility against an arbitrary photo. The bottom is handled by .card-info's own background
   now, sized to its actual content instead of a fixed fraction of the card. */
.card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 34%;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(0,0,0,.78), transparent);
}

/* Everything about a claim lives here, bottom-anchored, tap to unfold. Collapsed it's just the
   ask and the verdict — enough to read at a glance without competing with the photo above it;
   busier than that read as clutter on a phone. The background is on this element rather than a
   fixed-height card-level scrim so it grows exactly as tall as .info-more does when expanded,
   never leaving unfolded text sitting over unscrimmed photo. */
.card-info {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  padding: var(--pad);
  padding-top: 28px;
  background: linear-gradient(to top, rgba(8,8,10,.94) 45%, rgba(8,8,10,.7) 75%, transparent);
  cursor: pointer;
}

.info-title {
  font-size: clamp(18px, 4.8vw, 24px);
  font-weight: 640;
  line-height: 1.22;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin: 0 0 6px;
  text-shadow: 0 1px 12px rgba(0,0,0,.5);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(255,255,255,.13);
  backdrop-filter: blur(8px);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink);
}

.verdict-line {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex-wrap: wrap;
  font-size: clamp(15px, 4vw, 18px);
  font-weight: 600;
}

.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
  align-self: center;
}
.v-paid .dot { background: var(--paid); box-shadow: 0 0 12px var(--paid); }
.v-rejected .dot { background: var(--rejected); }
.v-pending .dot { background: var(--pending); }
.v-open .dot { background: var(--open); box-shadow: 0 0 12px var(--open); }

.v-paid .verdict-what { color: var(--paid); }
.v-rejected .verdict-what { color: var(--rejected); }
.v-pending .verdict-what { color: var(--pending); }
.v-open .verdict-what { color: var(--open); }

/* A small "tap for more" affordance — without it, nothing on a collapsed card signals it's
   interactive. Hidden once expanded. */
.info-summary::after {
  content: "tap for more ⌄";
  display: block;
  margin-top: 8px;
  font-size: 11px;
  color: var(--ink-dim);
  opacity: .8;
}
.card.is-expanded .info-summary::after { content: none; }

/* Everything beyond the collapsed summary: full description, who/chain/time, the claim's own
   caption, and the link out. Height-animated via max-height rather than display, so it's a
   reveal rather than a jump cut. */
.info-more {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height 280ms ease, opacity 200ms ease;
}
.card.is-expanded .info-more {
  max-height: 55vh;
  opacity: 1;
  overflow-y: auto;
}

.info-desc {
  margin: 10px 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(244,244,245,.9);
}

.info-meta {
  margin-top: 10px;
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--ink-dim);
}

.verdict-note {
  margin-top: 8px;
  font-size: 13px;
  color: var(--ink-dim);
}

.info-caption {
  margin-top: 9px;
  font-size: 14px;
  color: rgba(244,244,245,.82);
}

.info-link {
  margin-top: 14px;
  display: inline-block;
  padding: 9px 18px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,.28);
  background: rgba(255,255,255,.1);
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
}

/* Open-bounty card (Phase 5): the conversion path, spliced in every ~10 cards. No claim, no
   photo, so the background stays a distinct gradient rather than reusing the backdrop/photo
   layers — everything else (.card-info, tap-to-unfold, the link out) is shared with claim
   cards, so the two only differ where they actually need to. */
.card--open-bounty {
  background:
    radial-gradient(120% 60% at 50% 100%, rgba(96,165,250,.25), transparent 65%),
    linear-gradient(165deg, #0d1a2e 0%, #08080a 65%);
}

/* The one deliberate visual difference from a claim card — everything else uses the exact same
   .card-info/.verdict-line/.info-* styling. */
.live-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--open);
  margin-bottom: 8px;
}
.live-badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--open);
  box-shadow: 0 0 8px var(--open);
}

/* Top chrome */
.hud {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px var(--pad);
  pointer-events: none;
  font-size: 12px;
}
.hud-mark { font-weight: 680; letter-spacing: -.01em; }
.hud-open { color: var(--open); font-weight: 560; }

/* Boot veil, removed once the first card is painted */
.boot {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: grid;
  place-items: center;
  background: #08080a;
  transition: opacity .35s ease;
}
.boot.gone { opacity: 0; pointer-events: none; }
.boot-inner { text-align: center; }
.boot-mark { font-size: 22px; font-weight: 680; letter-spacing: -.02em; }
.boot-note { margin-top: 7px; font-size: 13px; color: var(--ink-dim); }

@media (prefers-reduced-motion: reduce) {
  .reel { scroll-behavior: auto; }
  .boot { transition: none; }
}
