/* ============================================================
   ACT I — THE SEAL   |   ACT II — THE THRESHOLD
   ============================================================ */

/* ---------- ACT I : the mark resolves, holds, dissipates ---- */

#act-seal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: var(--ink);
  transition: opacity 1.5s var(--ease-vault), visibility 1.5s;
}

.seal-mark {
  width: min(78vw, 620px);
  opacity: 0;
  filter: blur(14px);
  transform: scale(1.06);
  animation: sealIn 2.1s var(--ease-vault) 0.35s forwards;
}

/* A slow specular sweep across the metal, once. */
.seal-mark::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255,232,190,0.16) 50%, transparent 62%);
  transform: translateX(-120%);
  animation: sheen 2.4s var(--ease-vault) 1.9s forwards;
  pointer-events: none;
}
.seal-mark { position: relative; }

@keyframes sealIn {
  to { opacity: 1; filter: blur(0); transform: scale(1); }
}
@keyframes sheen {
  to { transform: translateX(120%); }
}

/* The dissipation — it does not fade, it disperses. */
body.is-threshold #act-seal,
body.is-collection #act-seal {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
body.is-threshold .seal-mark {
  animation: sealOut 1.6s var(--ease-vault) forwards;
}
@keyframes sealOut {
  to { opacity: 0; filter: blur(22px); transform: scale(1.14); letter-spacing: 0.3em; }
}

/* Logo internals */
.logo { width: 100%; height: auto; overflow: visible; }
.logo .mono-v,
.logo .mono-c {
  font-family: var(--serif);
  font-size: 190px;
  font-weight: 400;
}
.logo .word {
  font-family: var(--sans);
  font-weight: 300;
  font-size: 46px;
  letter-spacing: 0.17em;
}
.logo .tag {
  font-family: var(--sans);
  font-weight: 300;
  font-size: 11px;
  letter-spacing: 0.2em;
  fill: var(--gold);
}
.logo .rule { stroke: var(--gold-deep); stroke-width: 1; }


/* ---------- ACT II : the wall that is not a wall ------------ */

#act-threshold {
  position: fixed;
  inset: 0;
  z-index: 150;
  overflow: hidden;
  background: #050403;
  opacity: 0;
  visibility: hidden;
  transition: opacity 1.6s var(--ease-vault), visibility 1.6s;
}
body.is-threshold #act-threshold,
body.is-opening  #act-threshold {
  opacity: 1;
  visibility: visible;
}

/* Room light falling across the case from the upper left */
/* A single warm source high on the left, and a heavy vignette. Without the
   vignette the shelving reads as pattern instead of as a dark room. */
.room-ambient {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(90% 70% at 20% 4%, rgba(255,190,110,0.20), transparent 58%),
    radial-gradient(120% 100% at 50% 50%, transparent 26%, rgba(0,0,0,0.55) 62%, rgba(0,0,0,0.92) 100%),
    linear-gradient(180deg, rgba(0,0,0,0.45), transparent 22%, transparent 62%, rgba(0,0,0,0.8));
  pointer-events: none;
  z-index: 3;
}

.bookcase {
  position: absolute;
  inset: 0;
  perspective: 1600px;
  perspective-origin: 50% 48%;
  transform: scale(1.02);
  transition: transform 2.6s var(--ease-door);
}
/* The push through the doorway */
body.is-opening .bookcase { transform: scale(2.35); }
body.is-opening #act-threshold { opacity: 0; transition-delay: 1.1s; }

/* --- the two halves --- */
.case-half {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50.2%;
  background:
    /* vertical stile shading */
    linear-gradient(90deg, rgba(0,0,0,0.55), transparent 12%, transparent 88%, rgba(0,0,0,0.65)),
    linear-gradient(180deg, #2a1c0f, #1a1109 55%, #120b06);
  box-shadow: inset 0 0 120px rgba(0,0,0,0.85);
  transform-style: preserve-3d;
  transition: transform 2.4s var(--ease-door), filter 2.4s var(--ease-door);
  z-index: 2;
}
.case-left  { left: 0;  transform-origin: left center;  }
.case-right { right: 0; transform-origin: right center; }

/* The leading edge of each door catches the light from the opening — this is
   what sells the swing as 3D rather than a slide. */
.case-half::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  opacity: 0;
  transition: opacity 2.4s var(--ease-door);
}
.case-left::after  { background: linear-gradient(90deg, transparent 60%, rgba(255,198,130,0.30)); }
.case-right::after { background: linear-gradient(270deg, transparent 60%, rgba(255,198,130,0.30)); }
body.is-opening .case-half::after { opacity: 1; }

/* Idle: a breath of movement, as though it were never quite shut */
body.is-threshold .case-left  { transform: rotateY(-2.2deg); }
body.is-threshold .case-right { transform: rotateY( 2.2deg); }

/* Open */
body.is-opening .case-left  { transform: rotateY(-72deg); filter: brightness(0.45); }
body.is-opening .case-right { transform: rotateY( 72deg); filter: brightness(0.45); }

/* Shelf carcass — injected rows */
.shelf {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 2px;
  padding: 0 clamp(10px, 3vw, 40px);
  border-bottom: 3px solid #0d0805;
  background: linear-gradient(180deg, transparent 60%, rgba(0,0,0,0.5));
}
/* The board itself, catching light on its front edge */
.shelf::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -3px;
  height: 3px;
  background: linear-gradient(90deg, transparent, rgba(198,161,91,0.5), transparent);
  opacity: 0.5;
}

.book {
  flex: 0 0 auto;
  border-radius: 1px 1px 0 0;
  background-image: linear-gradient(180deg, rgba(255,255,255,0.09), transparent 22%, rgba(0,0,0,0.42));
  box-shadow: inset -1px 0 0 rgba(0,0,0,0.5), inset 1px 0 0 rgba(255,255,255,0.05);
  position: relative;
}
/* Gilt banding on the spine */
.book::before {
  content: '';
  position: absolute;
  left: 12%; right: 12%;
  top: 18%;
  height: 1px;
  background: rgba(198,161,91,0.55);
  box-shadow: 0 6px 0 rgba(198,161,91,0.35);
}
.book.is-tilted { transform: rotate(-6deg) translateY(2px); transform-origin: bottom left; }

/* An object on the shelf instead of a book — a decanter, a box */
.objet {
  flex: 0 0 auto;
  align-self: flex-end;
  border-radius: 2px;
  background: linear-gradient(180deg, rgba(198,161,91,0.34), rgba(80,60,30,0.5));
  box-shadow: 0 0 14px rgba(255,190,110,0.16);
}

/* --- the interior behind the case --- */
.interior {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(80% 70% at 50% 55%, #3a2513, #150d06 60%, #060403);
  z-index: 1;
}
.interior-glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(45% 60% at 50% 52%, rgba(255,193,116,0.85), rgba(255,160,70,0.18) 45%, transparent 72%);
  opacity: 0;
  transition: opacity 2.2s var(--ease-door);
}
body.is-opening .interior-glow { opacity: 1; }

/* The blade of light that widens as the doors part.
   Radial, not linear — a linear fill blurs only at its edges and reads as a
   solid painted panel rather than as light falling out of a doorway. */
.interior-lightbeam {
  position: absolute;
  top: -10%; bottom: -10%; left: 50%;
  width: 2px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side ellipse at 50% 50%,
              rgba(255,226,182,0.95) 0%,
              rgba(255,196,124,0.55) 38%,
              rgba(255,170,90,0.18) 66%,
              transparent 100%);
  opacity: 0;
  transition: width 2.4s var(--ease-door), opacity 1.4s ease;
}
body.is-opening .interior-lightbeam {
  width: 78%;
  opacity: 1;
}

/* The seam — the only tell that the wall opens at all */
.seam {
  position: absolute;
  top: 0; bottom: 0; left: 50%;
  width: 1px;
  transform: translateX(-50%);
  background: linear-gradient(180deg, transparent, rgba(255,206,148,0.55) 25%, rgba(255,206,148,0.55) 75%, transparent);
  z-index: 4;
  opacity: 0;
  animation: seamBreathe 4.5s ease-in-out infinite;
}
body.is-threshold .seam { opacity: 1; }
body.is-opening  .seam { opacity: 0; transition: opacity 0.6s; }

@keyframes seamBreathe {
  0%, 100% { box-shadow: 0 0 12px 1px rgba(255,190,120,0.30); }
  50%      { box-shadow: 0 0 26px 3px rgba(255,190,120,0.60); }
}

/* --- the invitation --- */
.threshold-ui {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 6;
  text-align: center;
  opacity: 0;
  animation: uiIn 1.6s var(--ease-vault) 1.1s forwards;
  padding: 4rem clamp(2rem, 10vw, 8rem);
}
/* Pool of darkness so the type is never fighting the book spines. */
.threshold-ui::before {
  content: '';
  position: absolute;
  inset: -30% -10%;
  z-index: -1;
  background: radial-gradient(closest-side ellipse at 50% 50%,
              rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.72) 45%, transparent 100%);
  pointer-events: none;
}
body.is-opening .threshold-ui {
  animation: uiOut 0.8s var(--ease-vault) forwards;
}
@keyframes uiIn  { to { opacity: 1; } }
@keyframes uiOut { to { opacity: 0; transform: translate(-50%, -50%) scale(1.3); } }

.threshold-kicker { margin-bottom: 1.6rem; opacity: 0.75; }

.enter {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  padding: 1.1rem 2.2rem;
  position: relative;
}
.enter-rule {
  display: block;
  width: clamp(26px, 7vw, 64px);
  height: 1px;
  background: var(--gold);
  opacity: 0.55;
  transition: width 0.9s var(--ease-vault), opacity 0.9s;
}
.enter-label {
  font-family: var(--serif);
  font-size: clamp(1.7rem, 4.4vw, 2.7rem);
  font-weight: 300;
  letter-spacing: 0.16em;
  color: var(--bone);
  text-shadow: 0 0 34px rgba(255,196,122,0.45);
  white-space: nowrap;
  transition: color 0.7s, text-shadow 0.7s;
}
.enter:hover .enter-rule { width: clamp(40px, 10vw, 96px); opacity: 1; }
.enter:hover .enter-label { color: var(--gold-lit); text-shadow: 0 0 46px rgba(255,196,122,0.85); }

.threshold-hint {
  margin-top: 1.4rem;
  font-size: 0.7rem;
  font-weight: 200;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--bone-faint);
}

.skip {
  position: absolute;
  bottom: 2rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 7;
  font-size: 0.62rem;
  font-weight: 300;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--bone-faint);
  padding: 0.8rem 1.2rem;
  transition: color 0.5s;
  opacity: 0;
  animation: uiIn 1s ease 2.4s forwards;
}
.skip:hover { color: var(--gold); }
/* A finished animation with fill:forwards outranks a plain declaration, so the
   exit has to be an animation too rather than just `opacity: 0`. */
body.is-opening .skip { animation: fadeOut 0.5s ease forwards; }
@keyframes fadeOut { to { opacity: 0; } }

@media (max-width: 640px) {
  .bookcase { perspective: 900px; }
  body.is-opening .bookcase { transform: scale(1.9); }
}
