/* The cover: the black gatefold envelope, which fills the whole screen on every device (the
   laptop too, where the card behind it is a column on the table).

   The picture (assets/cover/envelope*.webp, one per screen shape, chosen by geometry.css) is
   cut in the page, not in the pictures: each flap is the whole picture clipped to its side of
   the join, and the line through the wax seal is jagged, so the seal breaks in two and each
   half goes with its flap. js/cover.js measures where the join and the seal fall on this screen
   and sets --vw, --jx, --sx, --sy, --sr and --hint-y (px) and the two clip-paths.

   Before it opens: a gleam crosses the gold now and then (masked to the gold by
   assets/cover/gold*.webp), light breathes along the join, and gold dust drifts in the
   lamplight. The flaps are lined with the ivory silk of the paper sections, and inside the
   envelope is the same silk, with the light.
*/

html.is-shut,
html.is-shut body {
  overflow: hidden;
  overscroll-behavior: none;
}

html.is-shut .card {
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}

/* ------------------------------------------------------------ the gate */

.gate {
  position: fixed;
  inset: 0;
  z-index: 50;
  overflow: hidden;
  /* Round the envelope, when the view draws back as it opens: the dark of the room. */
  background: radial-gradient(ellipse 70% 60% at 50% 50%, #1b150e, var(--onyx) 70%, var(--table));
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
}

.gate[hidden] { display: none; }

/* The flaps' own 3D is seen from here: close enough that a flap lifting towards you grows as
   it comes (about twice a flap's width). The stage itself is flat, and draws back and goes in as
   a picture. */
.stage {
  position: absolute;
  inset: 0;
  perspective: calc(var(--vw, 100vw) * 1.1);
}

/* Inside the envelope: the silk, and the light. */
.inside {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: url(../assets/theme/paper-b.webp) 0 0 / max(46vmin, 300px) repeat, var(--ivory);
}

.inside::before {
  content: "";
  position: absolute;
  inset: 0;
  /* the shade of the flaps' folds, along the sides */
  background: linear-gradient(90deg, rgba(40, 26, 10, .45), transparent 14%, transparent 86%, rgba(40, 26, 10, .45));
}

/* The shadows the flaps throw on the silk as they stand up from it. */
.in-shade {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(20, 12, 4, .75), transparent 22%, transparent 78%, rgba(20, 12, 4, .75));
  opacity: 0;
}

.in-light {
  position: absolute;
  inset: -20%;
  background: radial-gradient(circle at 50% 50%, #fffaf0 0%, rgba(255, 226, 160, .92) 16%, rgba(226, 164, 72, .5) 38%, rgba(120, 70, 20, 0) 66%);
  mix-blend-mode: screen;
  opacity: .35;
}

/* The whole envelope, under the two flaps while it is closed, so the hairline where they meet
   shows the envelope and not the silk inside. It goes when the seal breaks. */
.whole {
  position: absolute;
  inset: 0;
}

/* ------------------------------------------------------------ the flaps */

.flap {
  position: absolute;
  top: 0;
  bottom: 0;
  transform-style: preserve-3d;
}

.flap-l { left: 0; width: var(--jx); transform-origin: 0 50%; }
.flap-r { left: var(--jx); right: 0; transform-origin: 100% 50%; }

.face {
  position: absolute;
  top: 0;
  bottom: 0;
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
}

/* The outside: the whole picture, as big as the screen, clipped to this flap's side. */
.front { width: var(--vw); }
.flap-l .front { left: 0; }
.flap-r .front { left: calc(-1 * var(--jx)); }

.env-art {
  position: absolute;
  inset: 0;
  background: var(--onyx) center / cover no-repeat;
}

/* A flap darkens as it lifts away from the lamplight. */
.f-shade {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: 0;
}

/* The initials, pressed into the wax as a seal's monogram: engraved capitals, the "&" in italic. Each flap has them; each shows its own half. */
.seal-initials i { font-style: italic; font-weight: 500; margin: 0 .06em; }

.seal-initials {
  position: absolute;
  left: var(--sx);
  top: var(--sy);
  translate: -50% -52%;
  margin: 0;
  white-space: nowrap;
  font: 600 calc(var(--sr) * .5) / 1 'Cormorant Garamond', Georgia, serif;
  letter-spacing: .04em;
  /* pressed in: dark in the hollow, lit along its lower edge, shaded along its upper */
  color: #5a3b10;
  text-shadow: 0 1.2px 0 rgba(255, 234, 186, .75), 0 -1px 1px rgba(36, 20, 3, .7), 0 0 1px rgba(60, 36, 6, .5);
}

/* The inside: ivory silk, with a gilded edge where the flap folds. */
.back {
  inset: 0;
  width: auto;
  transform: rotateY(180deg);
  background: url(../assets/theme/paper-b.webp) 0 0 / max(46vmin, 300px) repeat, var(--ivory);
}

.back::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(46, 30, 10, .5), transparent 22%, transparent 94%, #c9a24b 97%, #f3dc97 98.5%, #9c7231 100%);
}

.flap-l .back::after { transform: scaleX(-1); }

/* ------------------------------------------------------------ the life of the closed envelope */

/* Light breathing through the join, above and below the seal. */
.join-glow {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--jx) - 9px);
  width: 18px;
  background: linear-gradient(90deg, transparent, rgba(255, 180, 90, .35) 38%, rgba(255, 236, 196, .8) 50%, rgba(255, 180, 90, .35) 62%, transparent);
  -webkit-mask-image: linear-gradient(180deg, #000 calc(var(--sy) - var(--sr) * 1.15), transparent calc(var(--sy) - var(--sr) * .95), transparent calc(var(--sy) + var(--sr) * .95), #000 calc(var(--sy) + var(--sr) * 1.15));
          mask-image: linear-gradient(180deg, #000 calc(var(--sy) - var(--sr) * 1.15), transparent calc(var(--sy) - var(--sr) * .95), transparent calc(var(--sy) + var(--sr) * .95), #000 calc(var(--sy) + var(--sr) * 1.15));
  animation: breathe 4.2s ease-in-out infinite;
  pointer-events: none;
}

@keyframes breathe {
  0%, 100% { opacity: .2; }
  50%      { opacity: .7; }
}

/* A gleam crossing the gold now and then, like a lamp carried past. */
.gleam {
  position: absolute;
  inset: 0;
  background: linear-gradient(104deg, transparent 40%, rgba(255, 246, 222, .0) 44%, rgba(255, 246, 222, .8) 50%, rgba(255, 246, 222, 0) 56%, transparent 60%) 0 0 / 300% 100% no-repeat;
  -webkit-mask-size: cover;
          mask-size: cover;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  animation: gleam 6.5s cubic-bezier(.45, 0, .35, 1) 1.2s infinite;
  pointer-events: none;
}

@keyframes gleam {
  0%        { background-position: 100% 0; }
  38%, 100% { background-position: 0% 0; }
}

/* Gold dust in the lamplight (js/cover.js scatters it). */
.dust {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.dust i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--s);
  height: var(--s);
  border-radius: 50%;
  background: radial-gradient(circle, #fff3cf 0%, rgba(245, 205, 120, .85) 35%, rgba(230, 170, 70, 0) 70%);
  opacity: 0;
  animation: mote var(--d) linear var(--delay) infinite;
}

@keyframes mote {
  0%   { opacity: 0; transform: translate(0, 0); }
  18%  { opacity: var(--o); }
  80%  { opacity: calc(var(--o) * .7); }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)); }
}

/* The crack running through the wax, and the light in it. */
.crack {
  position: absolute;
  left: calc(var(--jx) - var(--sr) * 1.2);
  top: calc(var(--sy) - var(--sr) * 1.2);
  width: calc(var(--sr) * 2.4);
  height: calc(var(--sr) * 2.4);
  overflow: visible;
  pointer-events: none;
}

.crack path { fill: none; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.crack .c-dark { stroke: #2a1806; stroke-width: .05; }
.crack .c-light { stroke: #fff1c8; stroke-width: .022; filter: drop-shadow(0 0 .04px #ffd98a); opacity: 0; }

/* ------------------------------------------------------------ the seal, the words and the buttons */

.seal-btn {
  position: absolute;
  left: calc(var(--sx) - var(--sr));
  top: calc(var(--sy) - var(--sr));
  width: calc(var(--sr) * 2);
  height: calc(var(--sr) * 2);
  z-index: 2;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

.seal-btn:disabled { cursor: default; }

/* A ring of light that goes out from the seal: the way in. */
.s-ring {
  position: absolute;
  inset: -4%;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 228, 160, .8);
  box-shadow: 0 0 14px rgba(255, 210, 130, .45);
  opacity: 0;
  animation: s-ring 3s cubic-bezier(.2, .6, .3, 1) 2s infinite;
  pointer-events: none;
}

@keyframes s-ring {
  0%   { opacity: .85; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.55); }
}

.seal-btn:focus-visible { outline: none; }
.seal-btn:focus-visible .s-ring { opacity: 1; animation: none; transform: scale(1.12); border-color: #fff4d6; }
.gate.is-pressed .s-ring { opacity: 1; animation: none; transform: scale(1.04); border-color: #fff4d6; box-shadow: 0 0 22px rgba(255, 220, 150, .8); }

/* Tapping the envelope anywhere but the seal points to it. */
.gate.is-nudged .s-ring { animation: s-ring 900ms cubic-bezier(.2, .6, .3, 1) 2; }
.gate.is-nudged .gate-hint { animation: hint-flash 900ms ease; }

.gate-hint {
  position: absolute;
  left: 50%;
  top: var(--hint-y, 72%);
  z-index: 2;
  width: max-content;
  max-width: 86vw;
  margin: 0;
  padding: 9px 18px 9px calc(18px + .26em);
  translate: -50% 0;
  border: 1px solid rgba(201, 162, 75, .5);
  border-radius: 999px;
  background: rgba(10, 8, 6, .6);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  color: var(--gold-hi);
  font: 600 12px/1 'Cormorant Garamond', Georgia, serif;
  letter-spacing: .26em;
  text-transform: uppercase;
  animation: hint-pulse 3.2s ease-in-out 1.4s infinite;
  pointer-events: none;
}

@keyframes hint-pulse {
  0%, 100% { opacity: .9; }
  50%      { opacity: .6; }
}

@keyframes hint-flash {
  0%, 100% { opacity: .9; }
  30%      { opacity: 1; background: rgba(60, 42, 14, .85); }
}

/* The light filling the view, as it goes into the envelope. */
.flood {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 50%, #fffef9, #fff8e4 45%, #f6e2b0 90%);
  opacity: 0;
  pointer-events: none;
}

.sound-toggle {
  position: absolute;
  top: max(14px, env(safe-area-inset-top));
  right: max(14px, env(safe-area-inset-right));
  z-index: 3;
  width: 40px;
  height: 40px;
  padding: 9px;
  border: 1px solid rgba(240, 217, 156, .4);
  border-radius: 50%;
  background: rgba(10, 8, 6, .5);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  color: var(--gold-hi);
  cursor: pointer;
}

.sound-toggle svg { width: 100%; height: 100%; display: block; }
.sound-toggle path { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.sound-toggle .spk { fill: currentColor; }
.sound-toggle[aria-pressed="true"] .mute,
.sound-toggle[aria-pressed="false"] .wave { display: none; }
.sound-toggle:focus-visible { outline: 2px solid var(--gold-hi); outline-offset: 2px; }

/* ------------------------------------------------------------ arriving */

html.is-loading .stage,
html.is-loading .gate-hint,
html.is-loading .sound-toggle { opacity: 0; }

html.is-arriving .stage        { animation: arrive-env 1300ms cubic-bezier(.2, .7, .2, 1) both; }
html.is-arriving .gate-hint    { animation: arrive-fade 900ms ease 900ms both, hint-pulse 3.2s ease-in-out 1.8s infinite; }
html.is-arriving .sound-toggle { animation: arrive-fade 700ms ease 1100ms both; }

@keyframes arrive-env {
  from { opacity: 0; transform: scale(1.04); filter: brightness(.45); }
  to   { opacity: 1; transform: none; filter: none; }
}

@keyframes arrive-fade { from { opacity: 0; } to { opacity: 1; } }

.gate.is-opening .gate-hint,
.gate.is-opening .s-ring { animation: none; opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .gleam, .dust, .s-ring { display: none; }
  .join-glow, .gate-hint { animation: none !important; }
  .join-glow { opacity: .5; }
}
