/*
 * LOUCHE 2025 — interaction layer.
 *
 * Owns the bento aperture, the external portal dialog, Swup transition states,
 * the utility region, and the reduced-motion policy for all of them. Page and
 * section geometry live in louche.css and the editorial stylesheets; nothing
 * here should be reaching for layout.
 *
 * The reduced-motion rule at the foot of this file removes motion only. It must
 * never hide an element that carries a control, a link, or a message — an
 * earlier version set `display: none` on the overlay, which took the external
 * portal's fallback link, close button and alert down with it and left readers
 * who prefer reduced motion with no way out at all.
 */


/* ────────────────────────────────────────────────────────────────────────
 * Bento aperture
 *
 * The overlay is viewport-sized from the start and revealed by animating a
 * clip-path inset in from the card's rectangle, so no frame of the transition
 * relayouts a full-screen element or reflows its children.
 * ──────────────────────────────────────────────────────────────────────── */

.louche-aperture {
  position: fixed;
  inset: 0;
  z-index: 9999;
  overflow: hidden;
  pointer-events: none;
  box-shadow: 0 24px 80px rgba(26, 26, 26, 0.18);
}

.louche-aperture::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(240, 235, 227, 0.78) 0%, rgba(240, 235, 227, 0.2) 42%, rgba(240, 235, 227, 0) 70%),
    url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.055'/%3E%3C/svg%3E");
  mix-blend-mode: multiply;
  opacity: 0.88;
  pointer-events: none;
}

.louche-aperture.is-waiting::after {
  opacity: 0.94;
}

.louche-aperture-image {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  filter: saturate(0.92) contrast(1.02);
}

.louche-aperture-person  .louche-aperture-image { background-image: var(--louche-bento-person-image);  background-position: 48% 50%; }
.louche-aperture-work    .louche-aperture-image { background-image: var(--louche-bento-work-image);    background-position: 52% 48%; }
.louche-aperture-art     .louche-aperture-image { background-image: var(--louche-bento-art-image);     background-position: 62% 42%; }
.louche-aperture-music   .louche-aperture-image { background-image: var(--louche-bento-music-image);   background-position: 66% 48%; }
.louche-aperture-musings .louche-aperture-image { background-image: var(--louche-bento-musings-image); background-position: right center; }
.louche-aperture-hello   .louche-aperture-image { background-image: var(--louche-bento-hello-image);   background-position: center 42%; }
.louche-aperture-legal   .louche-aperture-image { background-image: var(--louche-bento-legal-image);   background-position: 62% 50%; }

.louche-aperture-panel {
  position: absolute;
  z-index: 2;
  left: clamp(28px, 8vw, 110px);
  bottom: clamp(34px, 10vw, 120px);
  width: min(520px, calc(100vw - 56px));
  color: var(--louche-ink);
  font-family: var(--louche-font-display);
  font-size: clamp(3rem, 8vw, 7.2rem);
  font-weight: 300;
  letter-spacing: -0.045em;
  line-height: 0.86;
}

.louche-aperture-panel .louche-card-title-en {
  display: none;
}

/* The aperture always shows the epigraphical form, upright, never italic. */
.louche-aperture-panel .louche-card-title-la {
  position: static;
  opacity: 1;
  transform: none;
  font-style: normal;
  font-size: 0.72em;
  letter-spacing: 0.015em;
  line-height: 0.94;
}

.louche-aperture-rule {
  display: block;
  width: 4px;
  height: clamp(70px, 16vw, 160px);
  margin-bottom: 18px;
  border-radius: 999px;
  background: var(--louche-section-accent);
}

.louche-aperture-art     .louche-aperture-rule { background: var(--louche-pink); }
.louche-aperture-person  .louche-aperture-rule { background: var(--louche-teal); }
.louche-aperture-work    .louche-aperture-rule { background: var(--louche-ink); }
.louche-aperture-music   .louche-aperture-rule { background: var(--louche-navy); }
.louche-aperture-musings .louche-aperture-rule { background: var(--louche-ink); }
.louche-aperture-hello   .louche-aperture-rule { background: var(--louche-gold); }
.louche-aperture-legal   .louche-aperture-rule { background: var(--louche-teal); }

/* The decorative "opening in a new tab" line, shown only when a popup opened. */
.louche-aperture-note {
  position: absolute;
  z-index: 3;
  right: clamp(24px, 6vw, 86px);
  bottom: clamp(26px, 7vw, 86px);
  max-width: min(360px, calc(100vw - 48px));
  margin: 0;
  color: var(--louche-ink);
  font-family: var(--louche-font-mark);
  font-size: 11px;
  letter-spacing: 1.6px;
  line-height: 1.5;
  text-transform: uppercase;
}


/* ────────────────────────────────────────────────────────────────────────
 * External portal
 *
 * Shown only when the browser blocked the new tab, which makes it the reader's
 * only remaining route to the destination. It is a native <dialog>, so focus
 * containment, Escape, the inert background and the top layer are the
 * platform's job rather than something reimplemented here.
 * ──────────────────────────────────────────────────────────────────────── */

.louche-portal {
  width: min(420px, calc(100vw - 40px));
  padding: 0;
  border: 1px solid rgba(26, 26, 26, 0.12);
  border-radius: 18px;
  background: var(--louche-cream);
  color: var(--louche-ink);
  box-shadow: 0 30px 90px rgba(26, 26, 26, 0.24);
}

.louche-portal::backdrop {
  background: rgba(26, 26, 26, 0.42);
  backdrop-filter: blur(6px);
}

.louche-portal-notice {
  padding: 26px 26px 22px;
  border-left: 4px solid var(--louche-pink);
  border-radius: 18px;
}

.louche-portal-kicker {
  margin: 0;
  font-family: var(--louche-font-mark);
  font-size: 11px;
  letter-spacing: 1.7px;
  line-height: 1.5;
  text-transform: uppercase;
}

.louche-portal-destination {
  display: block;
  margin: 9px 0 10px;
  font-family: var(--louche-font-display);
  font-size: clamp(1.7rem, 4vw, 2.4rem);
  font-style: italic;
  font-weight: 300;
  letter-spacing: -0.035em;
  line-height: 0.95;
}

.louche-portal-help {
  margin: 0 0 18px;
  font-size: 0.94rem;
  line-height: 1.6;
}

.louche-portal-link {
  display: inline-block;
  margin-right: 12px;
  padding: 10px 18px;
  border-radius: 999px;
  background: var(--louche-ink);
  color: var(--louche-cream);
  font-family: var(--louche-font-mark);
  font-size: 12px;
  letter-spacing: 1.4px;
  text-decoration: none;
  text-transform: uppercase;
}

.louche-portal-link:hover,
.louche-portal-link:focus-visible {
  background: var(--louche-teal);
  color: var(--louche-cream);
}

.louche-portal-close {
  padding: 10px 16px;
  border: 1px solid rgba(26, 26, 26, 0.2);
  border-radius: 999px;
  background: transparent;
  color: var(--louche-ink);
  font-family: var(--louche-font-mark);
  font-size: 12px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  cursor: pointer;
}

.louche-portal-close:hover,
.louche-portal-close:focus-visible {
  border-color: var(--louche-ink);
  background: rgba(26, 26, 26, 0.06);
}


/* ────────────────────────────────────────────────────────────────────────
 * Swup transition states and the entrance choreography
 *
 * CSS owns the staggered entrance of inner-page elements. GSAP owns the
 * aperture and the main-container transition, and does not duplicate this.
 * ──────────────────────────────────────────────────────────────────────── */

@keyframes louche-rise {
  from { opacity: 0; transform: translate3d(0, 22px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes louche-image-arrive {
  from { opacity: 0; filter: blur(2px); transform: translate3d(26px, 16px, 0) scale(0.988); }
  to   { opacity: 1; filter: blur(0);   transform: translate3d(0, 0, 0) scale(1); }
}

:where(
  .louche-editorial-panel,
  .louche-editorial-meta,
  .louche-editorial-rail,
  .louche-editorial-copy,
  .louche-page-hero,
  .louche-single-hero,
  .louche-gallery-hero,
  .louche-gallery-stream
) {
  animation: louche-rise 0.72s var(--louche-ease-out) backwards;
}

.louche-editorial-hero-image {
  animation: louche-image-arrive 0.82s var(--louche-ease-out) 0.1s backwards;
}

.louche-editorial-meta,
.louche-editorial-rail,
.louche-gallery-stream {
  animation-delay: 0.18s;
}

.louche-editorial-copy {
  animation-delay: 0.28s;
}

.louche-query .louche-post-card {
  animation: louche-rise 0.64s var(--louche-ease-out) backwards;
}

.louche-query .louche-post-card:nth-child(2) { animation-delay: 0.06s; }
.louche-query .louche-post-card:nth-child(3) { animation-delay: 0.12s; }
.louche-query .louche-post-card:nth-child(4) { animation-delay: 0.18s; }
.louche-query .louche-post-card:nth-child(5) { animation-delay: 0.24s; }
.louche-query .louche-post-card:nth-child(6) { animation-delay: 0.3s; }

/*
 * Hold the incoming page's entrance while a bento aperture is still covering
 * it, so the reader does not watch the new page animate in behind the overlay.
 * The aperture state machine removes this class on every exit path, including
 * cancellation and navigation failure.
 */
.louche-hold :where(
  .louche-editorial-panel,
  .louche-editorial-hero-image,
  .louche-editorial-meta,
  .louche-editorial-rail,
  .louche-editorial-copy,
  .louche-page-hero,
  .louche-single-hero,
  .louche-gallery-hero,
  .louche-gallery-stream,
  .louche-query .louche-post-card
) {
  animation-play-state: paused;
}


/* ────────────────────────────────────────────────────────────────────────
 * Utility region
 *
 * One landmark per page for plugin-owned sharing and Like controls.
 * ──────────────────────────────────────────────────────────────────────── */

.louche-utility {
  width: min(100%, 760px);
  margin: clamp(34px, 6vw, 70px) 0 0;
  padding-top: 22px;
  border-top: 1px solid rgba(26, 26, 26, 0.1);
  color: var(--louche-ink-light);
  font-size: 0.92rem;
}

.louche-utility:empty {
  display: none;
}

.louche-utility > :first-child {
  margin-top: 0;
}

.louche-utility h3,
.louche-utility .sd-title {
  font-family: var(--louche-font-mark);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 1.5px;
  text-transform: uppercase;
}


/* ────────────────────────────────────────────────────────────────────────
 * Responsive
 * ──────────────────────────────────────────────────────────────────────── */

@media (max-width: 640px) {
  .louche-aperture-panel {
    left: 24px;
    bottom: 34px;
    font-size: clamp(2.8rem, 14vw, 4.8rem);
  }

  .louche-aperture-panel .louche-card-title-la {
    font-size: 0.56em;
    line-height: 1;
  }

  .louche-aperture-note {
    right: 18px;
    bottom: 20px;
  }

  .louche-portal-notice {
    padding: 22px 20px 18px;
  }
}


/* ────────────────────────────────────────────────────────────────────────
 * Reduced motion
 *
 * Motion off, function intact. Nothing below hides an interactive element.
 * ──────────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  :where(
    .louche-editorial-panel,
    .louche-editorial-hero-image,
    .louche-editorial-meta,
    .louche-editorial-rail,
    .louche-editorial-copy,
    .louche-page-hero,
    .louche-single-hero,
    .louche-gallery-hero,
    .louche-gallery-stream,
    .louche-query .louche-post-card
  ) {
    animation: none;
  }

  /*
   * The aperture is decorative and JS does not build one under reduced motion.
   * The portal dialog is deliberately absent from this block: it is the only
   * route to the destination when a popup is blocked, so it stays visible and
   * operable — it simply arrives without animation.
   */
  .louche-aperture {
    animation: none;
    transition: none;
  }
}
