/* Read reveal ownership: frontier control, charge, and section-open motion. */

/* ---------- §2: the frontier reveal control ----------
   ONE full-width, enticing target that sits where the read currently ends. It is
   the only thing below the last revealed card — nothing beyond the frontier leaks.
   It carries no section name or verdict, just a generic invitation. The whole
   surface is the click target (the <button> resets to a block region). A gold
   level sits coiled at the foot of the control; on click JS adds .is-charging and
   the level RISES, bubbling/shimmering, then releases into the section open. */
.reveal-frontier {
  align-items: center;
  appearance: none;
  background: color-mix(in srgb, var(--surface) 70%, var(--gold-wash) 30%);
  border: 0;
  border-top: 2px solid var(--border-strong);
  border-bottom: 2px solid var(--border-strong);
  color: inherit;
  cursor: pointer;
  display: grid;
  font: inherit;
  gap: clamp(14px, 3vw, 30px);
  grid-template-columns: minmax(0, 1fr) auto;
  margin: 0;
  overflow: hidden;
  padding: clamp(26px, 4vw, 40px) clamp(18px, 3vw, 30px);
  position: relative;
  scroll-margin-top: 112px;
  text-align: left;
  transition: background 220ms var(--ease), box-shadow 220ms var(--ease);
  width: 100%;
}

.reveal-frontier:hover {
  background: color-mix(in srgb, var(--surface) 56%, var(--gold-wash) 44%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gold) 40%, transparent);
}

.reveal-frontier:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
}

/* The charge layer fills the control from the bottom — invisible at rest, the
   signature gold "filling up" while charging. It sits behind the copy. Its children
   are structural (no bespoke classes): the FILL is the first span, the SHIMMER the
   last span, and the percolating BUBBLES are the <i> set between them. */
.reveal-charge {
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  position: absolute;
  z-index: 0;
}

/* Fill — the rising gold level. */
.reveal-charge > span:first-child {
  background: linear-gradient(
    to top,
    color-mix(in srgb, var(--gold) 38%, transparent),
    color-mix(in srgb, var(--gold-wash) 75%, transparent)
  );
  bottom: 0;
  height: 100%;
  left: 0;
  position: absolute;
  transform: translateY(100%);
  width: 100%;
}

.reveal-charge > i {
  background: color-mix(in srgb, var(--gold) 60%, var(--surface));
  border-radius: 999px;
  bottom: -12px;
  height: 9px;
  opacity: 0;
  position: absolute;
  width: 9px;
}

.reveal-charge > i:nth-of-type(1) { left: 12%; height: 7px; width: 7px; }
.reveal-charge > i:nth-of-type(2) { left: 28%; height: 12px; width: 12px; }
.reveal-charge > i:nth-of-type(3) { left: 44%; height: 6px; width: 6px; }
.reveal-charge > i:nth-of-type(4) { left: 61%; height: 10px; width: 10px; }
.reveal-charge > i:nth-of-type(5) { left: 77%; height: 8px; width: 8px; }
.reveal-charge > i:nth-of-type(6) { left: 90%; height: 11px; width: 11px; }

/* Shimmer — the diagonal sweep across the fill. */
.reveal-charge > span:last-child {
  background: linear-gradient(
    105deg,
    transparent 38%,
    color-mix(in srgb, var(--surface) 80%, transparent) 50%,
    transparent 62%
  );
  inset: 0;
  opacity: 0;
  position: absolute;
  transform: translateX(-120%);
}

/* The copy + cue sit above the charge layer. */
.reveal-frontier-copy,
.reveal-cue {
  position: relative;
  z-index: 1;
}

.reveal-frontier-copy {
  display: grid;
  gap: 6px;
}

.reveal-frontier-copy .cl-heading {
  margin: 0;
}

.reveal-frontier-copy .cl-text {
  margin: 0;
  max-width: 52ch;
}

/* The cue — a mono verb + descending arrow that bobs to invite the click. */
.reveal-cue {
  align-items: center;
  color: var(--gold);
  display: grid;
  font-family: var(--brand);
  font-size: var(--fs-slug);
  font-weight: var(--fw-bold);
  gap: 4px;
  justify-items: center;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* The descending arrow (the cue's last span). */
.reveal-cue > span:last-child {
  font-size: var(--fs-h3);
  line-height: 1;
}

.reveal-frontier:not(.is-charging) .reveal-cue > span:last-child {
  animation: reveal-cue-bob 1900ms var(--ease) infinite;
}

/* ---------- §3: the charge build (the signature percolate) ----------
   On .is-charging the gold level RISES while bubbles percolate up through it and a
   shimmer sweeps across; the copy dims and the cue pulses, so the whole control
   reads as "filling up." The fill keyframe's animationend is what JS waits on to
   commit the reveal — so this is the ~1.1s beat that gates the open. */
.reveal-frontier.is-charging {
  cursor: progress;
}

.reveal-frontier.is-charging .reveal-charge > span:first-child {
  animation: reveal-charge-rise 1100ms cubic-bezier(0.45, 0.05, 0.2, 1) forwards;
}

.reveal-frontier.is-charging .reveal-charge > i {
  animation: reveal-bubble-up 1100ms ease-in forwards;
}

.reveal-frontier.is-charging .reveal-charge > i:nth-of-type(2) { animation-delay: 120ms; }
.reveal-frontier.is-charging .reveal-charge > i:nth-of-type(3) { animation-delay: 240ms; }
.reveal-frontier.is-charging .reveal-charge > i:nth-of-type(4) { animation-delay: 80ms; }
.reveal-frontier.is-charging .reveal-charge > i:nth-of-type(5) { animation-delay: 320ms; }
.reveal-frontier.is-charging .reveal-charge > i:nth-of-type(6) { animation-delay: 180ms; }

.reveal-frontier.is-charging .reveal-charge > span:last-child {
  animation: reveal-shimmer-sweep 1100ms ease-in-out 220ms forwards;
}

.reveal-frontier.is-charging .reveal-frontier-copy {
  animation: reveal-copy-dim 1100ms var(--ease) forwards;
}

.reveal-frontier.is-charging .reveal-cue {
  animation: reveal-cue-pulse 360ms var(--ease) infinite alternate;
}

@keyframes reveal-charge-rise {
  0% { transform: translateY(100%); }
  82% { transform: translateY(6%); }
  /* the "pop": a small overshoot release at the top of the fill */
  92% { transform: translateY(-4%); }
  100% { transform: translateY(0); }
}

@keyframes reveal-bubble-up {
  0% { opacity: 0; transform: translateY(0) scale(0.6); }
  18% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(-160px) scale(1.1); }
}

@keyframes reveal-shimmer-sweep {
  0% { opacity: 0; transform: translateX(-120%); }
  30% { opacity: 1; }
  100% { opacity: 0; transform: translateX(120%); }
}

@keyframes reveal-copy-dim {
  0% { opacity: 1; }
  70% { opacity: 0.45; }
  100% { opacity: 0.7; }
}

@keyframes reveal-cue-pulse {
  from { transform: scale(1); }
  to { transform: scale(1.14); }
}

@keyframes reveal-cue-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(4px); }
}

/* ---------- The OPEN — the newly revealed card unfolds ----------
   JS adds .is-opening to the just-revealed slot card (read/read-reveal.js
   openRevealed). The card scales/fades up while a clip wipes it open
   top-to-bottom, so a reveal lands as a satisfying unfold. The stamp inside
   still lands on top. */
.gate-card.is-opening {
  animation: reveal-open 700ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

.gate-card.is-opening .cl-stamp {
  animation: read-stamp-land 640ms var(--ease) 220ms both;
}

@keyframes reveal-open {
  0% {
    clip-path: inset(0 0 100% 0);
    opacity: 0;
    transform: translateY(14px) scale(0.985);
  }
  60% { opacity: 1; }
  100% {
    clip-path: inset(0 0 0 0);
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes read-stamp-land {
  0% {
    opacity: 0;
    transform: rotate(-8deg) scale(1.35);
  }
  58% {
    opacity: 1;
    transform: rotate(-2deg) scale(0.96);
  }
  100% {
    opacity: 1;
    transform: rotate(-3.5deg) scale(1);
  }
}

@keyframes read-stamp-land-mobile {
  0% {
    opacity: 0;
    transform: translateY(-4px) scale(0.96);
  }
  100% {
    opacity: 1;
    transform: none;
  }
}

@media (max-width: 32rem) {
  .gate-card.is-opening .cl-stamp {
    animation-name: read-stamp-land-mobile;
  }
}

@media (max-width: 700px) {
  .reveal-frontier {
    grid-template-columns: 1fr;
  }
  .reveal-cue {
    flex-direction: row;
    grid-auto-flow: column;
    justify-content: start;
  }
}

/* §3: prefers-reduced-motion — instant reveal, no charge, no unfold, no bob. */
@media (prefers-reduced-motion: reduce) {
  .reveal-frontier:not(.is-charging) .reveal-cue > span:last-child,
  .reveal-frontier.is-charging .reveal-charge > span:first-child,
  .reveal-frontier.is-charging .reveal-charge > i,
  .reveal-frontier.is-charging .reveal-charge > span:last-child,
  .reveal-frontier.is-charging .reveal-frontier-copy,
  .reveal-frontier.is-charging .reveal-cue,
  .gate-card.is-opening,
  .gate-card.is-opening .cl-stamp {
    animation: none;
  }
}
