/* ---------- Twenty: the comic, a still book you turn. One page on a phone, spreads on a wide screen ---------- */
.twenty { --room: calc(100vw - 2 * var(--gutter)); --pw: min(var(--room), calc((100svh - 150px) * 2 / 3), 560px); --open: .7s cubic-bezier(.45, .05, .25, 1); --shut: .84;
  position: relative; isolation: isolate; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  padding: clamp(80px, 13vh, 150px) var(--gutter) clamp(64px, 10vh, 120px);
  display: grid; justify-items: center; gap: 18px; overflow-x: clip; }
/* the issue's paper under the book: the page's own cream, the grain the recipe sheet carries */
.twenty::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: url(../img/grain.png) 0 0 / 300px; mix-blend-mode: multiply; opacity: .06; }
.tw-stage { position: relative; width: var(--pw); height: calc(var(--pw) * 1.5); perspective: 2400px; touch-action: pan-y pinch-zoom;
  transition: transform var(--open); }
.tw-book { position: relative; width: var(--pw); height: 100%; transform-style: preserve-3d; transition: transform .7s cubic-bezier(.45, .05, .25, 1); }
.tw-half { position: absolute; top: 0; height: 100%; width: var(--pw); background: var(--paper-hi);
  box-shadow: 0 1px 0 var(--rule), 0 18px 40px -12px rgba(42, 12, 26, .28); transition: box-shadow var(--open), border-radius var(--open); }
.tw-half img, .tw-face img { display: block; width: 100%; height: 100%; object-fit: cover; user-select: none; -webkit-user-select: none; -webkit-user-drag: none; -webkit-touch-callout: none;
  transition: opacity .18s ease; }
/* a page still decoding waits as blank paper, then fades in */
.tw-half img.tw-wait, .tw-face img.tw-wait { opacity: 0; transition: none; }
/* the pages under the one you're on: two thin edges at the fore-edge, so it reads as a book from the first look */
.tw-right { left: 0; }
.tw-right::before { content: ""; position: absolute; inset: 3px -3px -3px 3px; z-index: -1; background: #E7DDCB;
  box-shadow: 3px 3px 0 #DFD3BE, 3px 3px 0 1px rgba(62, 20, 40, .08); }
.tw-left { display: none; }
.tw-half:empty::before { display: none; }

.twenty.spread .tw-stage { width: calc(var(--pw) * 2); }
.twenty.spread .tw-book { width: calc(var(--pw) * 2); }
.twenty.spread .tw-book.closed { transform: translateX(calc(var(--pw) * -.5)); }
.twenty.spread .tw-book.back { transform: translateX(calc(var(--pw) * .5)); }
.twenty.spread .tw-left { display: block; left: 0; }
.twenty.spread .tw-right { left: var(--pw); }
.twenty.spread .tw-left::before { content: ""; position: absolute; inset: 3px 3px -3px -3px; z-index: -1; background: #E7DDCB;
  box-shadow: -3px 3px 0 #DFD3BE; }
/* the gutter: a soft shade either side of the spine */
.twenty.spread .tw-half::after { content: ""; position: absolute; top: 0; bottom: 0; width: 7%; pointer-events: none; }
.twenty.spread .tw-left::after { right: 0; background: linear-gradient(to left, rgba(42, 12, 26, .2), transparent); }
.twenty.spread .tw-right::after { left: 0; background: linear-gradient(to right, rgba(42, 12, 26, .2), transparent); }
.twenty.spread .tw-half:empty { visibility: hidden; }

/* the turning leaf */
.tw-leaf { position: absolute; top: 0; height: 100%; width: var(--pw); transform-style: preserve-3d; z-index: 3; will-change: transform; }
.tw-face { position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; overflow: hidden; background: var(--paper-hi); }
.tw-face.back { transform: rotateY(180deg); }
.tw-face::after { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: var(--shade, 0); transition: opacity .7s;
  background: linear-gradient(to right, rgba(42, 12, 26, .32), rgba(42, 12, 26, 0) 60%); }

.tw-hit { position: absolute; top: 0; bottom: 0; width: 50%; background: none; border: 0; padding: 0; margin: 0; z-index: 5; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.tw-hit.prev { left: 0; cursor: w-resize; }
.tw-hit.next { right: 0; cursor: e-resize; }
.tw-hit[disabled] { cursor: default; }
.tw-hit:focus-visible { outline: 2px solid var(--rust); outline-offset: -4px; }

.tw-ctl { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 13px; line-height: 1; font-variant-numeric: tabular-nums; }
.tw-ctl button { width: 44px; height: 44px; display: grid; place-items: center; background: none; border: 0; padding: 0; color: var(--ink); cursor: pointer; transition: opacity .3s ease; -webkit-tap-highlight-color: transparent; }
.tw-ctl button[disabled] { opacity: .25; cursor: default; }
.tw-ctl svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.4; }
.tw-where { min-width: 11em; text-align: center; }

@media (min-width: 760px) and (orientation: landscape) {
  .twenty { --pw: min(calc(var(--room) / 2), calc((100svh - 200px) * 2 / 3), 620px); --shut: .92;
    padding-block: clamp(48px, 7vh, 88px);
    /* a link here lands the book's top 6 px below the band under the corner box (drop.css .topfade), not under it */
    scroll-margin-top: calc(var(--top) + var(--box) + 28px - clamp(48px, 7vh, 88px)); }
  /* closed on a wide screen: the book a touch larger, the same room above and below it, none kept for controls it doesn't show yet */
  .twenty.shut { row-gap: 0; }
  .twenty.shut .tw-ctl { height: 0; }
}
/* the room is the section's own width inside its gutters, where the browser can measure it: 100vw counts a desktop
   scrollbar too, which made the book 15 px wider than its room and left it flush against the right edge */
@supports (width: 1cqw) { .twenty { container-type: inline-size; --room: 100cqw; } }
/* ---------- shut: the issue lying closed, a thing to pick up. Smaller, a heavier shadow, a spine and a block of pages;
   one tap opens it, and the book grows to reading size as the cover turns ---------- */
.twenty.shut .tw-stage { transform: scale(var(--shut)); cursor: pointer; }
.twenty.shut .tw-right { border-radius: 1px 3px 3px 1px;
  box-shadow: 0 1px 1px rgba(42, 12, 26, .22), 0 14px 22px -12px rgba(42, 12, 26, .42), 0 40px 70px -28px rgba(42, 12, 26, .5); }
.twenty.shut .tw-right::before { inset: 2px -5px -4px 2px; border-radius: 0 3px 3px 0; background: #EFE7D8;
  box-shadow: inset -1px 0 0 #DCCFB8, inset -3px 0 0 #F4EEE2, inset -4px 0 0 #DCCFB8, 0 1px 0 #D3C5AC; }
/* the hinge: a soft crease a few millimetres in from the spine */
.twenty.shut .tw-right::after { content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 7%; pointer-events: none; border-radius: 1px 0 0 1px;
  background: linear-gradient(to right, rgba(42, 12, 26, .28), rgba(42, 12, 26, .06) 28%, rgba(255, 250, 240, .22) 46%, rgba(42, 12, 26, .1) 62%, transparent); }
.tw-ctl { transition: opacity .45s ease .35s, visibility 0s; }
.twenty.shut .tw-ctl { opacity: 0; visibility: hidden; transition: opacity .2s ease, visibility 0s .2s; }
@media (hover: hover) {
  .twenty.shut .tw-stage:hover { transform: scale(var(--shut)) translateY(-4px); }
  .twenty.shut .tw-stage:hover .tw-right { box-shadow: 0 1px 1px rgba(42, 12, 26, .2), 0 18px 26px -12px rgba(42, 12, 26, .4), 0 52px 80px -30px rgba(42, 12, 26, .5); }
  .twenty.shut .tw-stage { transition: transform .5s var(--ease); }
}

/* the trip from In the box (twenty.js) is set from the scroll, frame by frame, with no transition of its own;
   only a change the scroll didn't make eases in */
.tw-stage.tw-settle { transition: transform var(--open), translate .45s var(--ease), scale .45s var(--ease), rotate .45s var(--ease); }
/* on a phone, until the strip In the box rests on the comic, the little one shows there and the book waits out of sight;
   one that has to catch up with the thumb fades in on its way */
.twenty.tw-held .tw-stage { visibility: hidden; }
.twenty.tw-late .tw-book { animation: tw-late .3s ease backwards; }
@keyframes tw-late { from { opacity: 0; } }
/* on its way down from the box the book passes over the row it left, never under it */
@media (min-width: 1101px) { .twenty { z-index: 1; } }

@media (prefers-reduced-motion: reduce) { .tw-book, .tw-stage, .tw-half, .tw-ctl, .tw-half img, .tw-face img { transition: none; } }
