/* ============================================================
   Pachakam — interactive magazine
   A 3D flipbook: closed the cover and spine are visible, opened
   it is a two-page spread you turn through.

   Loaded only by /pachakam/. Consumes the tokens in site.css —
   no colour, type or easing is invented here that isn't already
   part of the system.

   Structure is built by magazine.js from a plain <ol> of pages,
   so with JS off the markup degrades to a readable page grid.
   ============================================================ */

.mag {
  --ratio:  0.7072;                 /* 1536 / 2172 — the artboard ratio */
  --spine:  clamp(14px, 2.2vw, 30px);
  --flip:   900ms;
  --ease:   cubic-bezier(0.62, 0.05, 0.17, 1);
  --paper:  #f4f1ea;

  /* Height leads, width follows — then a width cap so a short, wide
     window can never push the spread past the gutters. */
  --ph-ideal: clamp(300px, 56vh, 560px);
  --pw: min(
          calc(var(--ph-ideal) * var(--ratio)),
          calc((100vw - var(--gutter) * 2 - var(--spine) * 2) / 2)
        );
  --ph: calc(var(--pw) / var(--ratio));
}

/* ---------- 1. Stage ---------- */
.mag__frame {
  position: relative;
  display: grid;
  justify-items: center;
  padding-block: clamp(2rem, 5vw, 4rem);
  border-radius: var(--r-lg);
  background:
    radial-gradient(90% 70% at 50% 38%, rgba(225, 255, 0, 0.05), transparent 62%),
    radial-gradient(120% 100% at 50% 0%, #131313 0%, #070707 68%);
  border: 1px solid var(--line-soft);
  /* NO overflow/filter here — either one flattens the 3D chain below. */
}

.mag__stage {
  position: relative;
  width: calc(var(--pw) * 2);
  height: var(--ph);
  perspective: 2400px;
  perspective-origin: 50% 46%;
}

/* the pool of shadow the book casts on the stage floor */
.mag__stage::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -6%;
  width: 88%;
  height: 9%;
  translate: -50% 0;
  background: radial-gradient(50% 50% at 50% 50%, rgba(0,0,0,0.72), transparent 72%);
  filter: blur(10px);
  transition: width var(--flip) var(--ease), opacity var(--flip) var(--ease);
  pointer-events: none;
  z-index: -1;
}
.mag.is-closed .mag__stage::after,
.mag.is-ended .mag__stage::after { width: 46%; opacity: 0.9; }

.mag__book {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  /* origin sits on the spine: the centre line of the two-page stage */
  transform-origin: 50% 50%;
  transition: transform var(--flip) var(--ease);
}

/* Closed: shift left by half a page so the right-hand stack — the only
   half with anything in it — lands dead centre, then tilt so the spine
   and the block of pages read as a physical object. */
/* The tilt is positive: it swings the fore-edge away and brings the spine
   side toward the viewer, which is the only direction the spine is facing
   us. A negative tilt hides the spine behind the cover. */
.mag.is-closed .mag__book {
  transform:
    translateX(calc(var(--pw) / -2))
    rotateX(7deg)
    rotateY(31deg);
}
.mag.is-closed .mag__stage:hover .mag__book,
.mag.is-closed .mag__stage:focus-within .mag__book {
  transform:
    translateX(calc(var(--pw) / -2))
    rotateX(2deg)
    rotateY(17deg)
    translateZ(30px);
}

/* Read to the end: every sheet is on the left and the right half is bare,
   so mirror the closed offset and centre the back cover. */
.mag.is-ended .mag__book { transform: translateX(calc(var(--pw) / 2)); }

/* ---------- 2. Leaves ---------- */
.mag__leaf {
  position: absolute;
  top: 0;
  right: 0;
  width: 50%;
  height: 100%;
  transform-style: preserve-3d;
  transform-origin: left center;    /* the hinge — the spine */
  transform: rotateY(0deg);
  transition: transform var(--flip) var(--ease);
}
.mag__leaf.is-flipped { transform: rotateY(-180deg); }

/* The sheet in motion rides above both stacks for the whole turn, which
   is what a real page does and sidesteps any mid-flip z-index swap. */
.mag__leaf.is-turning { z-index: 60 !important; }

.mag__face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  background: var(--paper);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
}
.mag__face--front { transform: translateZ(0.5px); }
.mag__face--back  { transform: rotateY(180deg) translateZ(0.5px); }

/* front faces live on the right of the gutter, backs on the left, so
   each curves away from the spine on its own side */
.mag__face--front { border-radius: 0 3px 3px 0; }
.mag__face--back  { border-radius: 3px 0 0 3px; }

/* Each face's content gets its own compositing layer.
   Without this, Chrome lays the page images out correctly but never
   rasters them — a face inside preserve-3d, clipped by overflow and
   flagged backface-visibility:hidden, drops its contents on the floor
   at dpr 2. The page then shows bare paper where the artwork should be.
   Reproducible at 375px/dpr 2; the promotion is what fixes it. */
.mag__face img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}

/* paper shading: a gutter crease that deepens toward the spine, plus the
   travelling shadow a sheet throws while it is mid-turn */
.mag__shade {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.mag__face--front .mag__shade {
  background: linear-gradient(
    to right,
    rgba(0,0,0,0.34) 0%, rgba(0,0,0,0.13) 2.5%,
    rgba(0,0,0,0.03) 7%, transparent 16%);
}
.mag__face--back .mag__shade {
  background: linear-gradient(
    to left,
    rgba(0,0,0,0.34) 0%, rgba(0,0,0,0.13) 2.5%,
    rgba(0,0,0,0.03) 7%, transparent 16%);
}

.mag__turnshade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(to right, rgba(0,0,0,0.55), rgba(0,0,0,0.05));
}
.mag__face--back .mag__turnshade {
  background: linear-gradient(to left, rgba(0,0,0,0.55), rgba(0,0,0,0.05));
}
.mag__leaf.is-turning .mag__turnshade { animation: magTurn var(--flip) var(--ease); }
@keyframes magTurn {
  0%   { opacity: 0; }
  45%  { opacity: 0.85; }
  100% { opacity: 0; }
}

/* ---------- 3. Closed-book furniture ---------- */
/* The spine: a panel hinged on the stage centre line, folded back 90°
   so it recedes behind the cover. Only rendered while closed. */
.mag__spine,
.mag__block {
  position: absolute;
  /* above every leaf (max resting z is the leaf count) so the panels are
     never painted under the cover they are attached to */
  z-index: 20;
  transition: opacity 0.35s var(--ease);
  pointer-events: none;
  backface-visibility: hidden;
}
.mag.is-open .mag__spine,
.mag.is-open .mag__block { opacity: 0; }

/* Hinged on its own right edge and folded back 90°, so it recedes from
   the spine line instead of poking out in front of the cover. */
.mag__spine {
  top: 0;
  left: calc(50% - var(--spine));
  width: var(--spine);
  height: 100%;
  transform-origin: 100% 50%;
  transform: rotateY(-90deg);
  background: linear-gradient(to right, #a8240f 0%, #e03a22 42%, #c22f16 100%);
  box-shadow: inset 0 0 12px rgba(0,0,0,0.5);
  display: grid;
  place-items: center;
  border-radius: 2px 0 0 2px;
}
/* the title running down the spine */
.mag__spine span {
  font-family: var(--f-ui);
  font-weight: 700;
  font-size: clamp(6px, 0.85vw, 10px);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #ffe70a;
  white-space: nowrap;
  writing-mode: vertical-rl;
  text-orientation: mixed;
}

/* The block of paper seen from above: hinged on its own bottom edge and
   folded back, so it lies flat on top of the closed book. */
.mag__block {
  top: calc(var(--spine) * -1);
  left: 50%;
  width: 50%;
  height: var(--spine);
  transform-origin: 50% 100%;
  transform: rotateX(90deg);
  background:
    linear-gradient(to right, #a8240f 0 3%, transparent 3%),
    repeating-linear-gradient(
      to bottom,
      #f2ede3 0px, #f2ede3 1px,
      #c9c2b4 1px, #c9c2b4 2px);
  box-shadow: inset 0 -6px 10px -4px rgba(0,0,0,0.4);
}

/* ---------- 4. The gutter of an open spread ---------- */
.mag__gutter {
  position: absolute;
  top: 0;
  left: 50%;
  width: clamp(30px, 5vw, 64px);
  height: 100%;
  translate: -50% 0;
  z-index: 70;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s var(--ease) 0.25s;
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(0,0,0,0.30) 44%,
    rgba(0,0,0,0.52) 50%,
    rgba(0,0,0,0.30) 56%,
    transparent 100%);
}
.mag.is-open .mag__gutter { opacity: 1; }
/* the last turn leaves the right half empty — drop the crease with it */
.mag.is-ended .mag__gutter { opacity: 0; transition-delay: 0s; }

/* ---------- 5. Click zones over the open book ---------- */
.mag__zones {
  position: absolute;
  inset: 0;
  z-index: 80;
  display: none;
}
.mag.is-open .mag__zones { display: block; }

.mag__zone {
  position: absolute;
  top: 0;
  width: 50%;
  height: 100%;
  border: 0;
  background: none;
  cursor: pointer;
}
.mag__zone--prev { left: 0;  cursor: w-resize; }
.mag__zone--next { right: 0; cursor: e-resize; }
.mag__zone[disabled] { cursor: default; }

/* ---------- 6. The "open me" affordance ---------- */
.mag__open {
  position: absolute;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: end center;
  padding-bottom: clamp(1rem, 3vw, 2rem);
  border: 0;
  background: none;
  cursor: pointer;
}
.mag.is-open .mag__open { display: none; }

.mag__open span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.75rem;
  border-radius: var(--r-pill);
  background: rgba(8, 8, 8, 0.82);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(225, 255, 0, 0.32);
  font-family: var(--f-ui);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--acid);
  transition: transform var(--d-fast) var(--e-spring), background var(--d-fast) var(--e-out);
}
.mag__open:hover span { transform: translateY(-3px); background: rgba(20, 20, 12, 0.9); }

/* ---------- 7. Controls ---------- */
/* Deliberately quiet: the magazine is the thing on this page, so the
   controls sit at caption scale and stay out of its way. */
.mag__ui {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: clamp(1rem, 2vw, 1.5rem);
}

.mag__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--fg-muted);
  transition:
    border-color var(--d-fast) var(--e-out),
    color var(--d-fast) var(--e-out),
    background var(--d-fast) var(--e-out),
    opacity var(--d-fast) var(--e-out);
}
.mag__btn:hover:not(:disabled) { border-color: var(--acid); color: var(--acid); }
.mag__btn:disabled { opacity: 0.25; cursor: default; }
.mag__btn--ghost { border-color: transparent; }
.mag__btn--ghost:hover { color: var(--acid); }

.mag__counter {
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
  color: var(--fg-meta);
  min-width: 7ch;
  text-align: center;
}

.mag__dots { display: flex; gap: 0.3rem; }
.mag__dot {
  width: 14px;
  height: 2px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.16);
  transition: background var(--d-fast) var(--e-out), transform var(--d-fast) var(--e-out);
}
.mag__dot:hover { background: rgba(255, 255, 255, 0.38); }
.mag__dot[aria-current="true"] { background: var(--acid); transform: scaleY(2); }

.mag__note {
  margin-top: var(--s-2);
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  color: var(--fg-meta);
  text-align: center;
}

/* ---------- 8. The CSS cover (placeholder for the flat artwork) ---------- */
.cover {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: linear-gradient(178deg, #efe016 0%, #eddc12 38%, #e8a02a 62%, #e03a22 88%, #c62d18 100%);
  color: #1b1206;
  font-family: var(--f-ui);
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: 7% 7% 6%;
  gap: 4%;
}
.cover__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  font-size: clamp(5px, 0.75vw, 8px);
  font-weight: 700;
  letter-spacing: 0.16em;
  line-height: 1.75;
  text-transform: uppercase;
}
.cover__top span { display: block; }
.cover__top div:last-child { text-align: right; }

.cover__title {
  align-self: start;
  margin: 0;
  font-family: var(--f-display);
  font-size: clamp(1.9rem, 4.6vw, 3.4rem);
  line-height: 0.82;
  letter-spacing: -0.045em;
  text-transform: uppercase;
  color: #cf2c12;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.28);
}
.cover__sub {
  margin-top: 0.5em;
  font-family: var(--f-case);
  font-size: clamp(0.55rem, 1vw, 0.8rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: 0.01em;
  max-width: 22ch;
  color: rgba(27, 18, 6, 0.78);
}
.cover__foot {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  font-size: clamp(5px, 0.75vw, 8px);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 240, 220, 0.92);
}
.cover__issue {
  font-variant-numeric: tabular-nums;
  border: 1px solid rgba(255, 240, 220, 0.55);
  border-radius: 2px;
  padding: 0.3em 0.5em;
}

/* back cover: the same object seen from behind */
.cover--back {
  background: linear-gradient(178deg, #c62d18 0%, #a8240f 100%);
  color: rgba(255, 240, 220, 0.9);
  place-content: center;
  text-align: center;
  gap: 1rem;
}
.cover--back .cover__title { color: #ffe70a; font-size: clamp(1.1rem, 2.4vw, 1.8rem); }

/* ---------- 9. Full-screen page reader ---------- */
.mag__lightbox {
  --ratio: 0.7072;
  /* Height available to a page once the bar, the nav and the padding
     have taken their share. Kept explicit: a percentage max-height does
     not resolve against a grid area whose item is centred rather than
     stretched, so the page would overflow the dialog. */
  --lb-h: calc(100vh - 11rem);

  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--s-2);
  padding: var(--s-3) var(--gutter);
  background: rgba(4, 4, 4, 0.96);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--d-mid) var(--e-out), visibility 0s linear var(--d-mid);
}
.mag__lightbox.is-open { opacity: 1; visibility: visible; transition-delay: 0s; }

.mag__lb-bar { display: flex; justify-content: space-between; align-items: center; gap: var(--s-2); }
.mag__lb-label {
  font-family: var(--f-ui);
  font-size: var(--t-sm);
  color: var(--fg-muted);
}
.mag__lb-stage { display: grid; place-items: center; min-height: 0; overflow: hidden; }
.mag__lb-stage > * {
  max-width: 100%;
  max-height: var(--lb-h);
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: var(--r-sm);
  box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.9);
}
/* a CSS cover has no intrinsic size — give it the page ratio */
.mag__lb-stage .cover {
  height: var(--lb-h);
  width: auto;
  aspect-ratio: var(--ratio);
}
.mag__lb-nav { display: flex; justify-content: center; gap: var(--s-2); }

body.mag-locked { overflow: hidden; }

/* ---------- 10. No-JS / pre-upgrade fallback ---------- */
.mag__source {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}
.mag__source li {
  aspect-ratio: var(--ratio, 0.7072);
  overflow: hidden;
  border-radius: var(--r-sm);
  background: #0c0c0c;
}
.mag__source img { width: 100%; height: 100%; object-fit: cover; }
/* once JS has lifted the pages into the book, the list is empty scaffolding */
.mag__source.is-consumed { display: none; }

/* ---------- 11. Responsive ---------- */
@media (max-width: 900px) {
  .mag { --ph-ideal: clamp(260px, 48vh, 420px); }
  .mag__ui { gap: 0.6rem; }
  .mag__dots { order: 3; width: 100%; justify-content: center; }
}

@media (max-width: 620px) {
  .mag { --ph-ideal: clamp(220px, 42vh, 340px); }
  .mag__frame { padding-inline: 0.5rem; border-radius: var(--r-md); }
  .mag__lightbox { padding-inline: 0.75rem; }
}

/* ---------- 12. Reduced motion ---------- */
/* The book still works — it just stops swinging through 3D space.
   Pages cut between spreads instead of turning. */
@media (prefers-reduced-motion: reduce) {
  .mag { --flip: 1ms; }
  .mag__book,
  .mag__leaf { transition: none !important; }
  .mag.is-closed .mag__book { transform: translateX(calc(var(--pw) / -2)); }
  .mag.is-closed .mag__stage:hover .mag__book,
  .mag.is-closed .mag__stage:focus-within .mag__book { transform: translateX(calc(var(--pw) / -2)); }
  .mag__spine, .mag__block { display: none; }
  .mag__turnshade { display: none; }
}
