/* Load first URL that exists: place Makiba as makibafont13.ttf, Makiba.ttf, or makiba.ttf under assets/fonts/. */
@font-face {
  font-family: 'Makiba';
  src:
    url('assets/fonts/makibafont13.ttf') format('truetype'),
    url('assets/fonts/Makiba.ttf') format('truetype'),
    url('assets/fonts/makiba.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Makiba';
  src:
    url('assets/fonts/makibafont13.ttf') format('truetype'),
    url('assets/fonts/Makiba.ttf') format('truetype'),
    url('assets/fonts/makiba.ttf') format('truetype');
  font-weight: normal;
  font-style: italic;
  font-display: swap;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  background: #EFEFEF;
  font-family: 'Makiba', serif;
}

body.issue-page--scroll {
  overflow-x: visible;
}

/*
 * Reserve space for the vertical scrollbar so width doesn’t jump when scrollability toggles.
 * Homepage shelf uses the same stable gutter (see html:has(.shelf-container)) for L1↔L2 alignment.
 */
html {
  overflow-y: scroll;
  scrollbar-gutter: stable;
  font-family: 'Makiba', ui-serif, serif;
}

/* Issue reader: horizontal strip / shadows extend past layout — avoid root clipping on the right */
html:has(.issue-page--scroll) {
  overflow-x: visible;
}

/* Homepage: no vertical page scroll — horizontal pan only on .shelf-container. */
html:has(.shelf-container) {
  height: 100%;
  overflow: hidden;
  /* Match default html scrollbar-gutter so header/content width matches issue pages (L1↔L2). */
  scrollbar-gutter: stable;
}

body:has(.shelf-container) {
  height: 100%;
  margin: 0;
  overflow: hidden;
  overscroll-behavior: none;
}

/* Canvas: issue pages 1440 max; homepage homescreen 0:3 is wider (dual shelf). */
.wrapper {
  max-width: 1440px;
  min-height: 1080px;
  margin: 0 auto;
  padding: 0 60px;
  position: relative;
}

/* Homepage: full viewport width; horizontal pan lives on .shelf-container (scroll frame). */
.wrapper:has(.shelf-container) {
  max-width: none;
  width: 100%;
  margin-left: auto;
  margin-right: auto;
  /* In-flow space below fixed .header (20px inset + 94px band — same as issue page). */
  padding: 114px 0 0 0;
  min-height: 0;
  height: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-sizing: border-box;
}

/* Title frame: 1320×94 — fixed chrome uses padding in .wrapper:has(.shelf-container) .header / .issue-page--scroll .header */
.header {
  height: 94px;
  padding: 20px 0 0 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  column-gap: 0;
  font-family: 'Makiba', ui-serif, serif;
}

/* Fixed site header — identical geometry on homepage + issue (viewport; L1↔L2). */
.wrapper:has(.shelf-container) .header,
.issue-page--scroll .header {
  position: fixed;
  top: 20px;
  left: 0;
  right: 0;
  z-index: 2000;
  margin: 0;
  padding: 20px 60px 0;
  height: 94px;
  box-sizing: border-box;
  background: transparent;
  width: auto;
  max-width: none;
}

/* When title is wrapped in a link (issue page) — match <h1 class="title"> on index (UA h1 + inline <a> otherwise jog vs shelf) */
.header__title-wrap {
  justify-self: start;
  min-width: 0;
  margin: 0;
  padding: 0;
  font-family: 'Makiba', serif;
  font-size: 40px;
  line-height: normal;
  font-weight: 400;
  letter-spacing: 1.4px;
  text-transform: lowercase;
}

.header__title-wrap > .title {
  display: inline-block;
  width: fit-content;
  max-width: 100%;
}

/* When title is direct child (index page) */
.header > .title {
  justify-self: start;
  min-width: 0;
}

.title {
  font-family: 'Makiba', serif;
  font-weight: 400;
  font-style: normal;
  font-size: 40px;
  line-height: normal;
  letter-spacing: 1.4px;
  text-transform: lowercase;
  margin: 0;
  color: #3D3C3C;
  text-decoration: none;
}

.title:hover {
  color: #000;
}

/* L2: same <h1 class="title"> as homepage; link wraps title-stack */
.header > .title > a {
  color: inherit;
  text-decoration: none;
}

.header > .title > a:hover {
  color: #000;
}

.header-flower {
  grid-column: 2;
  justify-self: center;
  width: 94px;
  height: 94px;
  object-fit: contain;
}

/* Calm, continuous rotation for header flower */
@keyframes header-flower-rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.header-flower {
  animation: header-flower-rotate 16s linear infinite;
  transform-origin: 50% 50%;
}

.datetime-wrap {
  grid-column: 3;
  justify-self: end;
  min-width: 0;
  text-align: right;
}

.datetime-date,
.datetime-time {
  font-family: 'Makiba', serif;
  font-weight: 400;
  font-style: italic;
  font-size: 32px;
  line-height: normal;
  letter-spacing: 1.4px;
  text-transform: lowercase;
  margin: 0 0 0 auto;
  color: #A5A5A5;
  width: fit-content;
  max-width: 100%;
}

/*
 * Outer main: issue pages unchanged. Homepage: content-frame absolutely placed (top 90px, left 160px on artboard).
 */
.shelf-container {
  position: relative;
  min-height: 966px;
  padding: 145px 0 0;
  padding-bottom: 0;
}

.wrapper:has(.shelf-container) .shelf-container {
  width: 100%;
  min-width: 0;
  min-height: 0;
  flex: 1 1 auto;
  padding: 0;
  position: relative;
  /* Below fixed .header (z-index 2000); isolate so inner z-index cannot stack above the header. */
  z-index: 0;
  isolation: isolate;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  overscroll-behavior-y: none;
  touch-action: pan-x;
  cursor: grab;
  /* Web: hide horizontal scrollbar; drag / trackpad / wheel pan unchanged */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.wrapper:has(.shelf-container) .shelf-container::-webkit-scrollbar {
  display: none;
  height: 0;
}

.wrapper:has(.shelf-container) .shelf-container.shelf-container--panning {
  cursor: grabbing;
  user-select: none;
}

/* Matches content-frame offset + width from homepage-spec (160 + 2319). */
.wrapper:has(.shelf-container) .content-frame-scroll-track {
  width: calc(160px + 2319px);
  height: 1px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  visibility: hidden;
  pointer-events: none;
}

/* Single parent: every zine / decor / shelf is a direct child; positioned via JS from spec */
.content-frame {
  position: relative;
  width: 2319px;
  max-width: none;
  height: 789px;
  margin-left: auto;
  margin-right: auto;
  box-sizing: border-box;
  pointer-events: none;
  overflow: visible;
}

.wrapper:has(.shelf-container) .content-frame {
  position: absolute;
  left: 160px;
  top: 90px;
  margin-left: 0;
  margin-right: 0;
}

/*
 * Homepage web (desktop): scale the 2319×789 artboard to fit available viewport height — same svh-based
 * idea as L2 --zine-page-height. Mobile layout (≤768px) uses its own spec + rules; no scale there.
 */
@media (min-width: 769px) {
  .wrapper:has(.shelf-container) {
    /* Header band + shelf top offset (90px) + margin; tune if clip/peek at extremes */
    --homepage-chrome-y: 230px;
    /* Divide by 789px so the result is unitless — required for transform: scale() */
    --homepage-scale: min(
      1,
      max(0.42, calc((100svh - var(--homepage-chrome-y)) / 789px))
    );
  }

  .wrapper:has(.shelf-container) .content-frame {
    transform: scale(var(--homepage-scale));
    transform-origin: top left;
  }

  .wrapper:has(.shelf-container) .content-frame-scroll-track {
    width: calc(160px + 2319px * var(--homepage-scale));
  }
}

.content-frame .layout-item {
  position: absolute;
  margin: 0;
  padding: 0;
  transform: none;
  box-sizing: border-box;
}

/* Shelves sit above all issues (zines / about); decorations use z-index 200+ */
.content-frame .layout-shelf {
  object-fit: contain;
  object-position: bottom;
  pointer-events: none;
  z-index: 50;
}

.content-frame .zine-cover {
  object-fit: contain;
  object-position: center bottom;
  pointer-events: auto;
  user-select: none;
  cursor: pointer;
}

/*
 * Issues (zines + about): z-index 1–9 — always below shelves (50). Relative order preserved.
 * Shelves: 50. Decorations: 200+ (always above shelf). Dragged props: script sets 500+.
 */
.content-frame .zine-cover[data-layout-id="idea-marinade"] {
  z-index: 1;
}
.content-frame .zine-cover[data-layout-id="self-perception"] {
  z-index: 2;
}
.content-frame .zine-cover[data-layout-id="romanticise"] {
  z-index: 3;
}
.content-frame .zine-cover[data-layout-id="observations"] {
  z-index: 6;
}
.content-frame .zine-cover[data-layout-id="collection"] {
  z-index: 7;
}

.content-frame .about-card {
  object-fit: contain;
  object-position: center bottom;
  pointer-events: none;
  user-select: none;
  z-index: 4;
}

.content-frame .about-card.layout-draggable {
  pointer-events: auto;
}

.content-frame .zine-cover--confessions {
  z-index: 9;
}

.content-frame .decoration {
  object-fit: contain;
  object-position: bottom center;
  pointer-events: auto;
  user-select: none;
}

.content-frame .layout-draggable {
  cursor: grab;
  touch-action: none;
}

.content-frame .layout-draggable:active {
  cursor: grabbing;
}

.content-frame .zine-cover.layout-draggable {
  cursor: grab;
}

/*
 * Foreground props (books → … → lamp → coffee): base z-index 200+ (above shelves at 50).
 * Dragging a prop raises it via script (500+). Issues stay below shelf (CSS & drag max 49).
 */
.content-frame .decoration-books {
  z-index: 200;
}

.content-frame .decoration-cat {
  overflow: hidden;
  z-index: 201;
}

.content-frame .decoration-plant {
  z-index: 202;
}

.content-frame .decoration-snake-plant {
  z-index: 203;
}

.content-frame .decoration-chinese-cat {
  z-index: 204;
}

.content-frame .decoration-lamp {
  z-index: 205;
}

/* Web desktop: lamp sits 100px above artboard bottom (sync LAMP_WEB_BOTTOM_OFFSET_PX in script.js); x/width/height + drag from JS */
@media (min-width: 769px) {
  .wrapper:has(.shelf-container) .content-frame .layout-item[data-layout-id='lamp'] {
    top: auto;
    bottom: 100px;
  }
}

.content-frame .decoration-coffee {
  z-index: 206;
}

.content-frame .decoration-cat .decoration-cat__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: bottom center;
  pointer-events: none;
}

.content-frame .decoration-cat .decoration-cat__img--smiling {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.content-frame .decoration-cat:hover .decoration-cat__img--smiling {
  opacity: 1;
}

/* First shelf cluster: wrappers are display:contents on desktop so HOMEPAGE_LAYOUT_SPEC still targets virtual #content-frame children. */
.mobile-first-shelf-group,
.mobile-first-shelf-group__cluster,
.romanticise-cover-wrap {
  display: contents;
}

/* Extra shelves used only in mobile layout (Figma 58:103) */
.layout-shelf--mobile-only {
  display: none !important;
}

/* Two-line title on mobile; one line on desktop */
.title-stack {
  display: inline;
}

.title-stack .title-line {
  display: inline;
}

.title-stack .title-line:first-child::after {
  content: ' ';
}

/*
 * L2 issue reader defaults (desktop). Mobile overrides in @media (max-width: 768px) below — must follow base.
 * --zine-page-height scales with viewport height (svh) so short/tall windows keep a balanced composition.
 */
.issue-page--scroll {
  --zine-stack-gap: -400px;
  /*
   * Vertical space outside the card square (wrapper top pad + frame margin-top + flex spacer min + back +
   * wrapper bottom pad + strip padding). Must track reality or 100svh − chrome overshoots and the page scrolls.
   */
  --issue-l2-chrome-y: 520px;
  --zine-page-height: min(
    520px,
    max(220px, calc(100svh - var(--issue-l2-chrome-y)))
  );
  --zine-open-padding-x: 200px;
}

/* ========== Homepage mobile (Figma node 58:103) ========== */
@media (max-width: 768px) {
  header {
    padding-bottom: 10px;
  }

  .title-stack {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: normal;
  }

  .title-stack .title-line:first-child::after {
    content: none;
  }

  /*
   * Horizontal overflow must stay visible: artboard uses negative x / wide assets.
   * L2: do not use overflow:hidden on .issue-wrapper — it clips both axes and cuts the strip, shadows, and
   * any bleed past the padded box (desktop L2 uses visible on wrapper). Page scroll stays on html.
   */
  html:has(.shelf-container),
  html:has(.issue-page--scroll) {
    height: auto;
    min-height: 100%;
    overflow-y: auto;
    overflow-x: visible;
    /* Same page chrome as desktop body (#EFEFEF). */
    background: #efefef;
    /* Hide vertical scrollbar; scrolling still works (touch / wheel / trackpad). */
    scrollbar-gutter: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }

  html:has(.shelf-container)::-webkit-scrollbar,
  html:has(.issue-page--scroll)::-webkit-scrollbar {
    display: none;
    width: 0;
    height: 0;
  }

  body:has(.shelf-container),
  body:has(.issue-page--scroll) {
    height: auto;
    min-height: 100%;
    overflow-y: visible;
    background: #efefef;
  }

  /*
   * Header sits in normal flow for top offset: main gets padding-top = header outer height so content never scrolls under it.
   * Homepage wrapper only here — L2 .issue-wrapper is split below (no document scroll; min-height 844px).
   */
  .wrapper:has(.shelf-container) {
    /* Matches fixed .header outer height (min-height + padding incl. 10px bottom). */
    --mobile-header-height: 82px;
    margin-left: auto;
    margin-right: auto;
    padding: 0 24px 32px;
    min-height: 0;
    height: auto;
    max-width: 100%;
    overflow-x: visible;
    overflow-y: visible;
    box-sizing: border-box;
  }

  .issue-page--scroll .issue-wrapper {
    --mobile-header-height: 82px;
    margin-left: auto;
    margin-right: auto;
    padding: 0 24px 32px;
    min-height: 844px;
    height: 100%;
    max-height: 100%;
    max-width: 100%;
    overflow-x: visible;
    overflow-y: visible;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
  }

  .wrapper:has(.shelf-container) .header,
  .issue-page--scroll .header {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    /* Must exceed .content-frame z-index (covers/decor ≤206 + drag); match desktop .header. */
    z-index: 2000;
    margin: 0;
    padding: 16px 24px 10px;
    height: auto;
    min-height: 72px;
    box-sizing: border-box;
    background: transparent;
  }

  .wrapper:has(.shelf-container) .header > .title,
  .issue-page--scroll .header > .title {
    font-size: 20px;
    letter-spacing: 1px;
  }

  .wrapper:has(.shelf-container) .header-flower,
  .issue-page--scroll .header-flower {
    width: 52px;
    height: 52px;
  }

  .wrapper:has(.shelf-container) .datetime-date,
  .wrapper:has(.shelf-container) .datetime-time,
  .issue-page--scroll .datetime-date,
  .issue-page--scroll .datetime-time {
    font-size: 20px;
    letter-spacing: 1px;
  }

  .wrapper:has(.shelf-container) .shelf-container {
    padding-top: var(--mobile-header-height);
    z-index: 0;
    isolation: isolate;
    overflow-x: visible;
    overflow-y: visible;
    touch-action: manipulation;
  }

  .wrapper:has(.shelf-container) .shelf-container {
    cursor: default;
    flex: 0 0 auto;
  }

  .wrapper:has(.shelf-container) .shelf-container.shelf-container--panning {
    cursor: default;
  }

  .wrapper:has(.shelf-container) .content-frame-scroll-track {
    width: min(390px, 100%);
    margin-left: auto;
    margin-right: auto;
  }

  .wrapper:has(.shelf-container) .content-frame {
    position: relative;
    left: auto;
    top: auto;
    margin-left: auto;
    margin-right: auto;
    overflow: visible;
  }

  /*
   * First shelf row: one flex column so cover (incl. PNG shadow/backing) + cat + plank center as a unit.
   * JS does not set left/top from spec here; drag on mobile uses transform: translate() from dragOffsets only.
   */
  .wrapper:has(.shelf-container) .mobile-first-shelf-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    position: absolute;
    left: 0;
    top: 51px;
    padding: 0 24px;
    box-sizing: border-box;
    pointer-events: none;
  }

  .wrapper:has(.shelf-container) .mobile-first-shelf-group__cluster {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: flex-end;
    width: 100%;
    position: relative;
    pointer-events: auto;
  }

  .wrapper:has(.shelf-container) .romanticise-cover-wrap {
    display: flex;
    justify-content: center;
    align-items: flex-end;
    position: relative;
    flex: 0 0 auto;
    overflow: visible;
  }

  .wrapper:has(.shelf-container) .romanticise-cover-wrap .zine-cover[data-layout-id='romanticise'] {
    position: relative !important;
    left: auto !important;
    top: auto !important;
    width: auto !important;
    max-width: 242px;
    height: auto !important;
    margin: 0 0 0 -60px;
  }

  .wrapper:has(.shelf-container) .mobile-first-shelf-group__cluster .decoration-cat[data-layout-id='cat'] {
    position: relative !important;
    left: auto !important;
    top: auto !important;
    width: auto !important;
    max-width: 97px;
    aspect-ratio: 97 / 100;
    height: auto !important;
    flex: 0 0 auto;
    /* Desktop cat y is in homepage-spec; mobile uses flex — negative top margin nudges up (sync with spec tweaks). */
    margin: -5px 0 0 -20px;
  }

  .wrapper:has(.shelf-container) .mobile-first-shelf-group .layout-shelf[data-layout-id='shelf'] {
    position: relative !important;
    left: auto !important;
    top: auto !important;
    width: 100% !important;
    max-width: 350px;
    height: auto !important;
    margin: -10px 0 0 -50px;
    /* Drag nudge via inline transform from script — do not use transform:none !important */
    pointer-events: auto;
  }

  .wrapper:has(.shelf-container) .layout-shelf.layout-shelf--mobile-only {
    display: block !important;
  }

  .wrapper:has(.shelf-container) .layout-item[data-layout-id='lamp'] {
    display: none !important;
  }

  .wrapper:has(.shelf-container) .layout-item[data-layout-id='chinese-cat'] {
    display: none !important;
  }

  .wrapper:has(.shelf-container) .content-frame .layout-draggable,
  .wrapper:has(.shelf-container) .content-frame [data-draggable='true'] {
    cursor: default;
    touch-action: manipulation;
  }

  /*
   * L2 issue reader — Figma node 66:89 (mobile-view-L2): cards up to 218×218; height tracks svh on short screens.
   * “back to shelf” fixed to bottom + safe area. Stack gap −167.692px…
   */
  .issue-page--scroll {
    --zine-stack-gap: -167.692px;
    --issue-l2-chrome-y-mobile: 300px;
    --zine-page-height: min(
      218px,
      max(160px, calc(100svh - var(--issue-l2-chrome-y-mobile)))
    );
    --zine-open-padding-x: 84px;
  }

  /* L2: pan-y on main so vertical page scroll works; open strip uses pan-x (CSS + JS swipe → scrollLeft). */
  .issue-page--scroll .issue-scroll-main {
    padding-top: var(--mobile-header-height);
    z-index: 0;
    isolation: isolate;
    touch-action: pan-y;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    gap: 0;
  }

  .issue-page--scroll .issue-zine-frame--scroll.zine-inner {
    flex: 0 1 auto;
    margin-top: 0;
    min-height: 0;
    gap: 0;
    transform: translateY(170px);
  }

  /*
   * Same strip layout as web: full-width .zine-strip--closed + justify-content:center centers the scroller.
   * Touch: horizontal pan needs a scrollable overflow (desktop uses hidden + wheel/JS).
   */
  .issue-page--scroll .zine-inner .zine-strip.zine-strip--open {
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
    overscroll-behavior-x: contain;
  }

  /*
   * “back to shelf”: fixed y=704 matched 844px Figma only — on shorter phones (e.g. SE) it sat below the
   * viewport. Pin to bottom + safe area so it stays visible when deployed.
   */
  .issue-page--scroll .issue-back {
    position: fixed;
    left: 0;
    right: 0;
    top: auto;
    bottom: max(20px, calc(env(safe-area-inset-bottom, 0px) + 16px));
    z-index: 2100;
    width: 100%;
    text-align: center;
    font-size: 20px;
    letter-spacing: 1px;
    pointer-events: auto;
    color: #000;
  }

  .issue-page--scroll .issue-back:hover {
    color: #000;
  }

  .issue-page--scroll .zine-strip__page.zine-strip__page--text {
    min-width: 0;
    max-width: min(320px, calc(100vw - 48px));
    padding: 0.75rem;
    font-size: 14px;
  }

  /*
   * Homepage only: suppress horizontal page scrollbar (do not use bare `body` — L2 needs overflow-x visible).
   */
  body:has(.shelf-container) {
    overflow-x: hidden;
  }
}

/* Issue page scaffold (placeholder sections only) */
.issue-page .issue-wrapper {
  min-height: 100vh;
  padding-top: 20px;
  padding-bottom: 60px;
}

.issue-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 2rem;
}

.issue-back,
.issue-nav {
  font-family: 'Makiba', serif;
  font-size: 28px;
  letter-spacing: 1.4px;
  text-transform: lowercase;
  color: #3D3C3C;
  text-decoration: none;
}

.issue-back:hover,
.issue-nav:hover {
  color: #000;
}

.issue-back {
  font-size: 32px;
}

.issue-title {
  font-family: 'Makiba', serif;
  font-weight: 400;
  font-size: 28px;
  letter-spacing: 1.4px;
  text-transform: lowercase;
  margin: 0;
  text-align: center;
  color: #A5A5A5;
}

.issue-main {
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

.issue-zine-frame {
  display: flex;
  width: 520px;
  max-width: 100%;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 40px;
  margin-top: 120px;
}

/* ========== Horizontal zine reader (issue-scroll only, no leakage) ========== */
.issue-page--scroll .issue-title {
  color: #3D3C3C;
}

/* Fill viewport below fixed .header (20px inset + 94px band — same as homepage .wrapper) */
.issue-page--scroll .issue-wrapper {
  display: flex;
  flex-direction: column;
  /* Let expanded strip use full viewport width (minus padding); 1440 cap was clipping the open row */
  max-width: none;
  width: 100%;
}

@media (min-width: 769px) {
  /*
   * L2 desktop: one viewport tall — no document vertical scroll. Strip height uses --zine-page-height from svh;
   * flex spacer keeps ≥122px between strip block and “back to shelf”, which sits at the bottom when space allows.
   */
  html:has(.issue-page--scroll) {
    overflow-y: hidden;
    height: 100%;
    min-height: 100dvh;
  }

  body.issue-page--scroll {
    height: 100dvh;
    max-height: 100dvh;
    min-height: 100dvh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }

  .issue-page--scroll .issue-wrapper {
    padding-top: 114px;
    padding-bottom: 32px;
    padding-left: 0;
    padding-right: 0;
    min-height: 0;
    flex: 1 1 auto;
    max-height: 100%;
    overflow: visible;
  }

  .issue-page--scroll .issue-scroll-main {
    gap: 0;
  }

  /*
   * Vertical centering vs 100svh: equal flex above and below the zine frame so issues stay mid-band as
   * --zine-page-height changes. ::after keeps ≥122px breathing room before “back to shelf”.
   * Flex order: ::before → frame → ::after → link (DOM: ::before, frame, back, ::after).
   */
  .issue-page--scroll .issue-scroll-main::before {
    content: '';
    order: 1;
    flex: 1 1 0;
    min-height: 0;
    min-width: 0;
    width: 100%;
  }

  .issue-page--scroll .issue-scroll-main::after {
    content: '';
    order: 3;
    flex: 1 1 0;
    min-height: 122px;
    min-width: 0;
    width: 100%;
  }

  .issue-page--scroll .issue-zine-frame--scroll {
    order: 2;
  }

  .issue-page--scroll .issue-back {
    order: 4;
    position: relative;
    z-index: 1;
    transform: translateY(-40px);
  }

  /* main branch L2 link treatment (mobile uses fixed + black in max-width block) */
  .issue-page--scroll .issue-back {
    color: #a5a5a5;
  }

  .issue-page--scroll .issue-back:hover {
    color: #3d3c3c;
  }
}

.issue-page--scroll .issue-scroll-main {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  min-width: 0;
  min-height: 0;
  width: 100%;
  /* No clip on main — strip shadows / horizontal fan can extend (L2 mobile wrapper uses visible overflow too). */
  overflow-x: visible;
  overflow-y: visible;
}

/*
 * Figma zine-page-step2 (node 15:2): cards track --zine-page-height from svh.
 * Desktop: twin flex spacers on .issue-scroll-main vertically center the frame; no fixed 118px top offset.
 */
.issue-page--scroll .issue-zine-frame--scroll {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  flex: 1 1 auto;
  width: 100%;
  max-width: none;
  min-width: 0;
  min-height: 0;
  overflow-x: visible;
  overflow-y: visible;
}

@media (min-width: 769px) {
  .issue-page--scroll .issue-zine-frame--scroll {
    margin-top: 0;
    flex: 0 1 auto;
  }
}

.issue-page--scroll .zine-strip-wrap {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  min-width: 0;
  min-height: 0;
  width: 100%;
  overflow-x: visible;
  overflow-y: visible;
}

/*
 * Single full-width cell: stretch the strip; align-content:start so open/closed share the same top edge (Figma y=252).
 */
.issue-page--scroll .zine-strip-root {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  justify-items: stretch;
  align-items: start;
  align-content: start;
  width: 100%;
  margin-left: 0;
  min-width: 0;
  min-height: 0;
  position: relative;
  overflow-x: visible;
  overflow-y: visible;
}

/* Back to shelf: anchored to page layout, not to strip width */
.issue-page--scroll .issue-back {
  display: block;
  width: 100%;
  text-align: center;
}

/*
 * Outer: overflow visible on both axes so drop-shadow / strip aren’t clipped by scroll pairing.
 * Inner .zine-strip: overflow hidden; scrollLeft is driven by JS/wheel (no overflow auto/scroll).
 */
.issue-page--scroll .zine-strip-outer {
  grid-column: 1;
  grid-row: 1;
  justify-self: stretch;
  align-self: start;
  overflow: visible;
  width: 100%;
  min-width: 0;
}

/* Strip: closed stack is shrink-to-content + centered in #zine-strip-root; open uses full width to scroll */
.issue-page--scroll .zine-strip {
  min-width: 0;
  pointer-events: none;
  outline: none;
  /* Room below cards so filter: drop-shadow isn’t clipped at the bottom edge */
  padding-bottom: 40px;
  box-sizing: border-box;
  overflow: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.issue-page--scroll .zine-strip::-webkit-scrollbar {
  display: none;
  height: 0;
}

.issue-page--scroll .zine-strip.zine-strip--closed {
  /* Same outer rectangle as open: full width; top-align stack (no Y shift on toggle) */
  display: flex;
  align-items: flex-start;
  justify-content: center;
  width: 100%;
  max-width: 100%;
  min-width: 0;
}

.issue-page--scroll .zine-strip.zine-strip--open {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  width: 100%;
  max-width: none;
  min-width: 0;
}

/* Interactive + a11y focus live on content-sized scroller (stack / strip row) */
.issue-page--scroll .zine-strip__scroller {
  pointer-events: auto;
  outline: none;
}

.issue-page--scroll .zine-strip__scroller:focus-visible {
  box-shadow: 0 0 0 2px rgba(61, 60, 60, 0.35);
  border-radius: 4px;
}

/* —— Closed: stacked deck — horizontal track space matches expanded (no Y jump when toggling) —— */
.issue-page--scroll .zine-strip--closed {
  overflow: hidden;
  overscroll-behavior-x: none;
  touch-action: pan-y;
}

/* Hidden overflow: no scrollbar pseudo-elements needed */

/*
 * Stacked deck: same page box + image rules as open; only position/overlap differs.
 * --stack-left + scroller width come from JS (open-equivalent widths + −400px advance).
 */
.issue-page--scroll .zine-strip--closed .zine-strip__scroller {
  display: block;
  position: relative;
  overflow: visible;
  --zine-stack-lift: 2px;
  width: auto;
  min-width: 200px;
  /* Same band height as open — avoids Y jump when toggling; stack overlap paints within this box */
  min-height: var(--zine-page-height);
  height: var(--zine-page-height);
  margin: 0;
  /* Horizontal only — vertical padding would change closed vs open alignment */
  padding: 0 14px;
  box-sizing: content-box;
  cursor: pointer;
  touch-action: manipulation;
}

/* Soft lift on all issue pages (filter paints outside the box; no box-shadow) */
.issue-page--scroll .zine-strip .zine-strip__page {
  filter: drop-shadow(0px 4px 12px rgba(0, 0, 0, 0.06));
}

/* Same intrinsic sizing as open row: width auto, max-width none */
.issue-page--scroll .zine-strip--closed .zine-strip__page {
  position: absolute;
  left: var(--stack-left, 0px);
  top: calc(var(--page-index) * var(--zine-stack-lift) * -1);
  flex: none;
  width: auto;
  max-width: none;
  min-width: 0;
  height: var(--zine-page-height);
  margin: 0;
  padding: 0;
  z-index: calc(var(--stack-total) - var(--page-index));
  border-radius: 2px;
  overflow: visible;
  transform: none;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(250, 250, 250, 0.95);
}

.issue-page--scroll .zine-strip--closed .zine-strip__page:nth-child(even) {
  background: rgba(236, 236, 236, 0.98);
}

.issue-page--scroll .zine-strip--closed .zine-strip__page.zine-strip__page--text {
  padding: 1rem;
  text-align: center;
  font-family: 'Makiba', serif;
  font-style: italic;
  font-size: 18px;
  color: #8a8a8a;
}

/* Images: identical rules stacked & open — natural aspect at 520px height */
.issue-page--scroll .zine-strip__page .zine-strip__image {
  height: 100%;
  width: auto;
  max-width: none;
  display: block;
  object-fit: contain;
}

/* Text pages: same min width as open strip */
.issue-page--scroll .zine-strip__page.zine-strip__page--text {
  min-width: 320px;
  height: var(--zine-page-height);
}

/* —— Open: horizontal spread + scroll —— */
.issue-page--scroll .zine-strip--open {
  overflow: hidden;
  touch-action: pan-x pan-y;
  -webkit-overflow-scrolling: touch;
  cursor: default;
  overscroll-behavior-x: contain;
}

.issue-page--scroll .zine-strip--open .zine-strip__scroller {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-start;
  position: static;
  width: max-content;
  /* Match closed: one row tall as cards */
  min-height: var(--zine-page-height);
  height: var(--zine-page-height);
  margin: 0;
  padding-left: var(--zine-open-padding-x);
  padding-right: var(--zine-open-padding-x);
  gap: 0;
}

/* During FLIP only: keep deck order (cover on top) so pages don’t paint “back over front” */
.issue-page--scroll .zine-strip--animating .zine-strip__page {
  z-index: calc(var(--stack-total) - var(--page-index)) !important;
}

.issue-page--scroll .zine-strip--open .zine-strip__page {
  position: relative;
  left: auto;
  top: auto;
  flex: 0 0 auto;
  width: auto;
  max-width: none;
  height: var(--zine-page-height);
  margin: 0;
  z-index: auto;
  transform: none;
  border-radius: 0;
  overflow: visible;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.04);
  border: 1px solid rgba(0, 0, 0, 0.06);
  box-sizing: border-box;
  font-family: 'Makiba', serif;
  font-style: italic;
  font-size: 18px;
  color: #A5A5A5;
}

/* Image drives page width; fixed height (open strip — natural aspect) */
.issue-page--scroll .zine-strip--open .zine-strip__page .zine-strip__image {
  height: 100%;
  width: auto;
  max-width: none;
  display: block;
  object-fit: contain;
}

.issue-viewer-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;
  width: 100%;
}

.issue-arrow {
  flex-shrink: 0;
  padding: 8px;
  border: none;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.issue-arrow img {
  display: block;
  width: 48px;
  height: 48px;
  object-fit: contain;
}

.issue-arrow:hover:not(:disabled) {
  opacity: 0.85;
}

.issue-arrow:disabled {
  cursor: default;
  opacity: 0.4;
}
