/* RedDeep — shared style. Link from each work's index.html. */

@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@200;300&display=swap');

:root {
  --rr-bg: #000;
  --rr-fg: #d88a80;
  --rr-glow: rgba(200, 16, 46, 0.35);
  /* vertical space reserved for arrows + padding when capping porthole height */
  --rr-reserve: 17rem;
  /* horizontal space reserved for the maze's fixed left/right doorway arrows,
     so the media never grows into them — arrows always stay on black. */
  --rr-side-reserve: 13rem;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  background: var(--rr-bg);
  color: var(--rr-fg);
  min-height: 100vh;
}

main {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2rem 1.5rem;
  gap: 0.5rem;
}

img,
video {
  max-width: 100%;
  max-height: 70vh;
  height: auto;
  display: block;
}

/* Porthole — wrap an <img> or <video> in <div class="porthole"> ... </div>
   to make it look like it's seen through a riveted oval submarine window. */
.porthole {
  position: relative;
  /* Cap by width AND by available height (minus arrows + padding) so the
     whole piece and both arrows always stay inside the viewport. */
  width: min(95vw, 1080px, (100vh - var(--rr-reserve)) * 5 / 3);
  aspect-ratio: 5 / 3;
  border-radius: 18% / 35%;
  overflow: hidden;
  background: #000;
  /* no frame — just depth */
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.8);
  margin: 0;
}
.porthole img,
.porthole video {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: cover;
  display: block;
}
.porthole::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    /* faint upper-left highlight, kept subtle */
    radial-gradient(ellipse 50% 35% at 28% 22%,
      rgba(255, 255, 255, 0.08) 0%,
      rgba(255, 255, 255, 0) 60%),
    /* light edge vignette — just a hint of recess */
    radial-gradient(ellipse 110% 110% at 50% 50%,
      rgba(0, 0, 0, 0) 60%,
      rgba(0, 0, 0, 0.35) 100%);
  /* soft inner shadow */
  box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.45);
}

/* Comic layout — multiple clips in one work, arranged as comic panels.
   Shares the porthole's footprint so the whole grid + arrows still fit
   the viewport. Markup:
     <div class="rr-comic n2">           // n2 | n3 = number of panels
       <div class="rr-panel"><video ...></video></div> ...
     </div>  */
.rr-comic {
  /* --rr-ar = whole-grid width/height; --rr-ar-mult = that same ratio as a
     number, used in the height cap. n3 overrides both to a taller box (below). */
  --rr-ar: 5 / 3;
  --rr-ar-mult: 1.6667;
  display: grid;
  gap: 0.55rem;
  width: min(95vw, 1080px, (100vh - var(--rr-reserve)) * var(--rr-ar-mult, 1.6667));
  aspect-ratio: var(--rr-ar, 5 / 3);
  /* It's a flex item in <main>; flex items default to min-height: auto and grow
     to their content, which lets the grid balloon past its box (eating the
     black gutter the top/bottom arrows live in). Pin to 0 so aspect-ratio wins. */
  min-height: 0;
}
.rr-comic.n2 { grid-template-columns: 1fr 1fr; }
.rr-comic.n3 {
  grid-template-columns: 1fr 1fr;
  /* Bottom panel spans both columns; give its row 2x the top row and use a
     taller overall box so all three panels sit near the clips' native 16:9 —
     the spanning panel keeps real height instead of becoming a thin strip. */
  grid-template-rows: 1fr 2fr;
  --rr-ar: 6 / 5;
  --rr-ar-mult: 1.2;
}
.rr-comic.n3 .rr-panel:nth-child(3) { grid-column: 1 / -1; }

/* Maze pieces (any .rr-portal present) reserve a horizontal black gutter so the
   fixed left/right doorway arrows never overlap the media — they always sit on
   black, even on very thin / portrait screens. Linear areas (cocoon, dirt-bath)
   have no portals, so they keep the full-width sizing above. */
main:has(.rr-portal) .porthole {
  width: min(100vw - var(--rr-side-reserve), 1080px, (100vh - var(--rr-reserve)) * 5 / 3);
}
main:has(.rr-portal) .rr-comic {
  width: min(100vw - var(--rr-side-reserve), 1080px, (100vh - var(--rr-reserve)) * var(--rr-ar-mult, 1.6667));
}

/* Thin screens: shrink the doorway arrows and the reserve they need, so the
   media isn't squeezed too small while still keeping every arrow on black. */
@media (max-width: 560px) {
  :root { --rr-side-reserve: 8.5rem; }
  .rr-portal { width: 48px; height: 62px; }
  .rr-portal.left  { left: 0.5rem; }
  .rr-portal.right { right: 0.5rem; }
}
.rr-panel {
  position: relative;
  overflow: hidden;
  /* Grid items default to min-height/min-width: auto, which lets the video's
     intrinsic size blow the grid past its aspect-ratio box (overflowing the
     height cap and pushing the top arrow over the media). Pin to 0 so the
     panel shrinks to the grid box and the video clips via object-fit. */
  min-width: 0;
  min-height: 0;
  background: #000;
  border-radius: 8px;
  border: 1px solid rgba(216, 138, 128, 0.16);
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.8);
}
.rr-panel video,
.rr-panel img {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: cover;
  display: block;
}

/* Navigation — graffiti arrows above the porthole.
   Markup:
     <nav class="rr-nav">
       <a class="rr-arrow back"    href="../piece-x/" aria-label="back"></a>
       <a class="rr-arrow forward" href="../piece-y/" aria-label="forward"></a>
     </nav>
   Dead end: omit the forward.  Branching: add multiple .forward arrows.
*/
.rr-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 2.75rem;
  min-height: 32px;
  margin-bottom: 0.25rem;
  opacity: 0;
  transition: opacity 1.4s ease;
}
.rr-nav.revealed { opacity: 1; }

/* Generic delayed reveal — add data-delay="MS" to any element.
   Words drift in from a soft blur, like something resolving out of air.
   Each span carries its own gradient so opacity/blur don't get eaten
   by the parent's background-clip:text rendering. */
[data-delay] {
  display: inline-block;
  background: linear-gradient(to bottom right,
    #d88a80 30%,
    rgba(216, 138, 128, 0.12) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  opacity: 0;
  filter: blur(10px);
  will-change: opacity, filter;
}
[data-delay].revealed {
  opacity: 1;
  filter: blur(0);
  animation: rr-fade-in 2.6s ease;
}
@keyframes rr-fade-in {
  from { opacity: 0; filter: blur(10px); }
  to   { opacity: 1; filter: blur(0); }
}

/* Fade-to-black veil for auto-advance tours (Cocoon). Injected by reddeep.js
   only on pages that opt into auto-advance (body[data-rr-next]). Opaque = black. */
.rr-fade-veil {
  position: fixed;
  inset: 0;
  background: #000;
  opacity: 0;
  pointer-events: none;
  z-index: 9999;
  transition: opacity 0.65s ease;
}
.rr-fade-veil.show { opacity: 1; }
.rr-arrow {
  display: inline-block;
  width: 72px;
  height: 28px;
  background-color: var(--rr-fg);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 40'><g fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M6 22 C 28 10, 62 30, 112 18'/><path d='M92 5 L 112 18 L 94 32'/></g></svg>") no-repeat center / contain;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 40'><g fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M6 22 C 28 10, 62 30, 112 18'/><path d='M92 5 L 112 18 L 94 32'/></g></svg>") no-repeat center / contain;
  filter: drop-shadow(0 0 10px var(--rr-glow));
  opacity: 0.82;
  transition: filter 0.25s ease, opacity 0.25s ease;
  cursor: pointer;
}
.rr-arrow.forward { transform: rotate(-18deg); }
.rr-arrow.back    { transform: scaleX(-1) rotate(-18deg); }
/* For branching: add .down on a .forward to angle it down-right instead. */
.rr-arrow.forward.down { transform: rotate(18deg); }
.rr-arrow.back.down    { transform: scaleX(-1) rotate(18deg); }
.rr-arrow:hover {
  filter: drop-shadow(0 0 18px var(--rr-glow));
  opacity: 1;
}

/* Scratched graffiti arrow — shared. The SVG is injected by reddeep.js.
   Usage:
     <a class="rr-scratch-arrow up"   href="../piece-N/"></a>   // go forward
     <a class="rr-scratch-arrow down" href="../piece-N/"></a>   // go back
*/
.rr-scratch-arrow {
  display: block;
  width: 60px;
  height: 78px;
  margin: 0 auto;
  text-decoration: none;
  opacity: 0;
  cursor: pointer;
  transition: opacity 1.4s ease, transform 0.25s ease;
}
.rr-scratch-arrow.revealed { opacity: 1; }
.rr-scratch-arrow svg {
  width: 100%;
  height: 100%;
  display: block;
  filter: drop-shadow(0 0 6px rgba(216, 60, 50, 0.45));
}
.rr-scratch-arrow.up   { margin-bottom: 1rem; }
.rr-scratch-arrow.down { margin-top: 1rem; transform: rotate(180deg); }
.rr-scratch-arrow.down.revealed { transform: rotate(180deg); }
.rr-scratch-arrow.up:hover   { transform: translateY(-3px); }
.rr-scratch-arrow.down:hover { transform: rotate(180deg) translateY(-3px); }

/* gallery-home doorway in linear areas — gold in-flow scratch arrow back to the foyer.
   Sits in normal flow above/below the porthole, so the porthole's --rr-reserve
   spacing keeps it clear of the image (same as the red nav arrows). */
.rr-scratch-arrow.home svg g    { stroke: #e0b34a; }
.rr-scratch-arrow.home svg      { filter: drop-shadow(0 0 8px rgba(224, 179, 74, 0.55)); }
.rr-scratch-arrow.home:hover svg { filter: drop-shadow(0 0 16px rgba(224, 179, 74, 0.8)); }

/* Default text treatment for RedDeep works.
   Wrap copy in <p class="rr-text"> ... </p> */
.rr-text {
  font-family: "Manrope", sans-serif;
  font-weight: 300;
  font-size: 0.95rem;
  line-height: 2;
  letter-spacing: 0.24em;
  word-spacing: 0.6em;
  text-align: center;
  text-transform: lowercase;
  background: linear-gradient(to bottom right,
    #d88a80 30%,
    rgba(216, 138, 128, 0.12) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  filter: drop-shadow(0 0 14px var(--rr-glow));
}

/* Short viewports: shrink the chrome (arrows + padding) so the porthole keeps
   most of the height instead of being squeezed by a fixed reserve. */
@media (max-height: 640px) {
  main { padding: 1rem 1.5rem; }
  .rr-scratch-arrow { width: 44px; height: 56px; }
  .rr-scratch-arrow.up   { margin-bottom: 0.4rem; }
  .rr-scratch-arrow.down { margin-top: 0.4rem; }
  :root { --rr-reserve: 11rem; }
}

/* ── Maze portals ───────────────────────────────────────────────────────────
   Directional doorways pinned to the four screen edges, for the dressing-room
   maze. Click the edge that points the way you want to go; the room you enter
   has the opposite-edge arrow back (right ↔ left, up ↔ down). reddeep.js
   injects the scratched SVG and reveals them after 5s (same as .rr-scratch-arrow).
   Gold (.home) = a doorway back to the gallery landing page.
   Markup: <a class="rr-portal right" href="../piece-8/index.html" aria-label="right"></a>
*/
.rr-portal {
  position: fixed;
  z-index: 20;
  width: 64px;
  height: 84px;
  text-decoration: none;
  opacity: 0;
  cursor: pointer;
  transition: opacity 1.4s ease, filter 0.25s ease;
}
/* Dark halo behind the stroke so the arrow stays readable over bright clips,
   then the coloured glow on top. */
.rr-portal svg {
  width: 100%;
  height: 100%;
  display: block;
  filter:
    drop-shadow(0 0 2px rgba(0, 0, 0, 0.95))
    drop-shadow(0 0 7px rgba(0, 0, 0, 0.85))
    drop-shadow(0 0 11px rgba(216, 60, 50, 0.55));
}
.rr-portal.revealed { opacity: 1; }
.rr-portal.revealed:hover { opacity: 1; }
.rr-portal:hover svg {
  filter:
    drop-shadow(0 0 2px rgba(0, 0, 0, 0.95))
    drop-shadow(0 0 7px rgba(0, 0, 0, 0.85))
    drop-shadow(0 0 18px rgba(216, 60, 50, 0.9));
}

.rr-portal.up    { top: 1.5rem;    left: 50%;  transform: translateX(-50%) rotate(0deg); }
.rr-portal.down  { bottom: 1.5rem; left: 50%;  transform: translateX(-50%) rotate(180deg); }
.rr-portal.left  { left: 1.5rem;   top: 50%;   transform: translateY(-50%) rotate(-90deg); }
.rr-portal.right { right: 1.5rem;  top: 50%;   transform: translateY(-50%) rotate(90deg); }

/* gallery-home doorway — gold instead of red */
.rr-portal.home svg g { stroke: #e0b34a; }
.rr-portal.home svg   {
  filter:
    drop-shadow(0 0 2px rgba(0, 0, 0, 0.95))
    drop-shadow(0 0 7px rgba(0, 0, 0, 0.85))
    drop-shadow(0 0 11px rgba(224, 179, 74, 0.6));
}
.rr-portal.home:hover svg {
  filter:
    drop-shadow(0 0 2px rgba(0, 0, 0, 0.95))
    drop-shadow(0 0 7px rgba(0, 0, 0, 0.85))
    drop-shadow(0 0 18px rgba(224, 179, 74, 0.9));
}

@media (max-height: 640px) {
  .rr-portal { width: 48px; height: 62px; }
  .rr-portal.up    { top: 0.6rem; }
  .rr-portal.down  { bottom: 0.6rem; }
  .rr-portal.left  { left: 0.6rem; }
  .rr-portal.right { right: 0.6rem; }
}

/* ── Solos layout override (scoped) ─────────────────────────────────────────
   Solos pieces (body.rr-solos) keep their up/down scratch arrows as page
   siblings of <main>, which by default pins them to the top/bottom edges far
   from the centered porthole. Here we make the BODY the centering flex column
   so the up-arrow + frame + down-arrow stack as one tight group, then nudge
   the whole group up a little. Only affects Solos — dirt-bath, Cocoon, and the
   dressing room are untouched. */
body.rr-solos {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding-bottom: 5rem;   /* with justify-center, biases the group upward ~2.5rem */
}
body.rr-solos main {
  min-height: 0;          /* stop main from eating the full viewport */
  flex: 0 0 auto;
  padding: 0;
}
body.rr-solos .rr-scratch-arrow.up   { margin-bottom: 0.6rem; }
body.rr-solos .rr-scratch-arrow.down { margin-top: 0.6rem; }

@media (max-height: 640px) {
  body.rr-solos { padding-bottom: 3rem; }
  body.rr-solos .rr-scratch-arrow.up   { margin-bottom: 0.4rem; }
  body.rr-solos .rr-scratch-arrow.down { margin-top: 0.4rem; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Deep Voice — "Experiencing the Deep" content module.
   A first-person mystic passage that can be dropped into any work. Drop in:
     <aside class="rr-deep-voice" data-level="3"></aside>
   and include deep-voice.js (it fills the aside with a passage for that level).
   Or hand-write the text inside the <aside> for a fixed passage.
   Modifiers: add class "center" to center under the work, "corner" to tuck it
   low; default flows in normal document order. ────────────────────────────── */
.rr-deep-voice {
  max-width: min(46ch, 88vw);
  margin: 1.6rem auto 0;
  font-family: 'Manrope', system-ui, serif;
  font-weight: 200;
  font-style: italic;
  font-size: clamp(0.95rem, 1.7vh, 1.18rem);
  line-height: 1.7;
  letter-spacing: 0.01em;
  color: var(--rr-fg);
  text-align: center;
  text-wrap: balance;
  text-shadow: 0 0 18px var(--rr-glow);
  opacity: 0;
  transition: opacity 2.4s ease;
}
.rr-deep-voice.revealed { opacity: 0.92; }
.rr-deep-voice p { margin: 0; }
.rr-deep-voice p + p { margin-top: 0.6rem; }
/* The opening capital glows a touch hotter, like an illuminated initial. */
.rr-deep-voice p:first-of-type::first-letter {
  color: #e9a59c;
  text-shadow: 0 0 26px var(--rr-glow);
}
.rr-deep-voice.corner {
  position: fixed;
  left: 50%;
  bottom: 1.4rem;
  transform: translateX(-50%);
  margin: 0;
  z-index: 4;
  pointer-events: none;
}
@media (max-height: 640px) {
  .rr-deep-voice { font-size: 0.92rem; line-height: 1.55; margin-top: 1rem; }
}

/* Deep Voice, form-by-level. As the human dissolves (6,8), the writing thins,
   spaces out, and goes quiet on the page, enacting the arc it describes. */
.rr-deep-voice.rr-lvl-6 { line-height: 2.0; letter-spacing: 0.03em; opacity: 0; }
.rr-deep-voice.rr-lvl-6.revealed { opacity: 0.85; }
.rr-deep-voice.rr-lvl-7 {
  font-size: clamp(1.1rem, 2.6vh, 1.55rem);
  line-height: 2.2;
  letter-spacing: 0.08em;
  font-style: normal;
  font-weight: 300;
}
.rr-deep-voice.rr-lvl-8 {
  font-size: clamp(1.7rem, 5.5vh, 3rem);
  line-height: 1.4;
  letter-spacing: 0.14em;
  font-style: normal;
  font-weight: 300;
  max-width: min(20ch, 80vw);
}
.rr-deep-voice.rr-lvl-8.revealed { opacity: 0.8; }
