/* ── Opening, which until now was a crossfade with nothing in it that opened ──
   The cover swings left off the spine while the spread rises underneath it. Three
   things move together and none of them is decorative:

   `bookPresent` slides the whole book RIGHT as it opens and takes the resting
   9-degree turn out of it. That is what a book does when you open it -- the spine
   travels to the middle and the covers spread either side of it -- and it is also
   the only reason the swing fits: hinged where it rests, the cover's far edge
   reaches 645px left of centre in a 1060px scene that clips at 530, so it would
   have been sliced off mid-air.

   The easing is weighted rather than symmetric. A cover is lifted against its own
   weight and then falls, so it leaves slowly and arrives fast, and an `ease-in-out`
   -- which is what a crossfade is -- is the one curve a hinge never has. */
@keyframes bookPresent {
  from { transform:translateX(0); }
  to   { transform:translateX(44%); }
}
@keyframes bookRecede {
  from { transform:translateX(44%); }
  to   { transform:translateX(0); }
}
@keyframes coverSwingOpen {
  from { opacity:1; }
  22%  { opacity:1; }
  52%  { opacity:0; }
  to   { opacity:0; }
}
@keyframes coverSwingShut {
  from { opacity:0; }
  48%  { opacity:0; }
  78%  { opacity:1; }
  to   { opacity:1; }
}
/* The flowers belong to the closed cover, so they leave with it. Each stem rests at
   its own opacity, which is why this interpolates FROM the computed value instead
   of naming one. */
@keyframes bookVanish { to { opacity:0; } }
@keyframes bookReturn { from { opacity:0; } }

.book-scene.opening .book-3d          { animation:bookPresent 0.72s cubic-bezier(0.5,0.03,0.24,1) forwards, bookVanish 0.2s 0.24s ease forwards; }
.book-scene.opening .book-cover-hinge { animation:coverSwingOpen 0.72s cubic-bezier(0.5,0.03,0.24,1) forwards; }
.book-scene.opening .book-bloom,
.book-scene.opening .book-bloom-base,
.book-scene.opening .book-user-flower,
.book-scene.opening .book-open-hint   { animation:bookVanish     0.30s ease forwards; }

.book-scene.closing .book-3d          { animation:bookRecede     0.72s cubic-bezier(0.5,0.03,0.24,1) both; }
.book-scene.closing .book-cover-hinge { animation:coverSwingShut 0.72s cubic-bezier(0.5,0.03,0.24,1) both; }
.book-scene.closing .book-bloom,
.book-scene.closing .book-bloom-base,
.book-scene.closing .book-user-flower,
.book-scene.closing .book-open-hint   { animation:bookReturn     0.36s 0.38s ease both; }

/* The opened leaf is deliberately one polygon, not the back of a rectangular
   cover. It leaves the binding as a narrow crease, broadens into paper while it
   crosses the gutter, then lands over the left page. Nothing above it clips the
   movement: `.book-scene` and the section both keep overflow visible. */
.book-turn-leaf {
  --leaf-travel:-430px;
  display:none; position:absolute; z-index:4; pointer-events:none;
  background:
    repeating-linear-gradient(112deg, rgba(92,61,46,0.045) 0 1px, transparent 1px 7px),
    linear-gradient(150deg,#F5EDD8 0%,#EDE8DC 58%,#F0E8D0 100%);
  box-shadow:inset 0 0 38px rgba(92,61,46,0.18), inset 0 0 0 1px rgba(92,61,46,0.06), -8px 8px 18px rgba(92,61,46,0.16);
  transform-origin:right center;
  will-change:transform,clip-path,opacity;
}
.book-turn-leaf-content {
  position:absolute; inset:0; padding:clamp(1.35rem,3vw,2.3rem);
  display:flex; flex-direction:column; justify-content:center;
  color:var(--brown); opacity:0;
}
.book-turn-leaf-content p {
  margin:0 0 0.45rem; font-family:'Dancing Script',cursive;
  font-size:clamp(0.88rem,1.35vw,1.1rem); color:var(--pink-d);
}
.book-turn-leaf-content h3 {
  margin:0; font-family:'Cormorant Garamond',serif; font-size:clamp(1.7rem,3.3vw,2.7rem);
  font-weight:300; line-height:1.02;
}
.book-turn-leaf-content em { color:var(--pink-d); }
@keyframes leafSweepOpen {
  0%   { opacity:0; transform:translateX(0) skewY(0deg) scaleX(0.025); clip-path:polygon(96% 0,100% 0,100% 100%,96% 100%); }
  10%  { opacity:1; }
  48%  { transform:translateX(calc(var(--leaf-travel) * 0.38)) skewY(-2.2deg) scaleX(0.72); clip-path:polygon(18% 0,100% 0,91% 100%,0 100%); }
  82%  { opacity:1; transform:translateX(calc(var(--leaf-travel) * 0.88)) skewY(-0.6deg) scaleX(0.98); clip-path:polygon(5% 0,100% 0,97% 100%,0 100%); }
  100% { opacity:0; transform:translateX(var(--leaf-travel)) skewY(0deg) scaleX(1); clip-path:polygon(0 0,100% 0,100% 100%,0 100%); }
}
@keyframes leafSweepClose {
  0%   { opacity:0; transform:translateX(var(--leaf-travel)) skewY(0deg) scaleX(1); clip-path:polygon(0 0,100% 0,100% 100%,0 100%); }
  18%  { opacity:1; transform:translateX(calc(var(--leaf-travel) * 0.88)) skewY(-0.6deg) scaleX(0.98); clip-path:polygon(5% 0,100% 0,97% 100%,0 100%); }
  52%  { transform:translateX(calc(var(--leaf-travel) * 0.38)) skewY(-2.2deg) scaleX(0.72); clip-path:polygon(18% 0,100% 0,91% 100%,0 100%); }
  90%  { opacity:1; }
  100% { opacity:0; transform:translateX(0) skewY(0deg) scaleX(0.025); clip-path:polygon(96% 0,100% 0,100% 100%,96% 100%); }
}
@keyframes leafContentOpen {
  0%, 54% { opacity:0; transform:translateX(14px); }
  64%, 74% { opacity:1; transform:translateX(0); }
  84%, 100% { opacity:0; transform:translateX(-8px); }
}
@keyframes leafContentClose {
  0%, 20% { opacity:0; transform:translateX(-8px); }
  32%, 44% { opacity:1; transform:translateX(0); }
  56%, 100% { opacity:0; transform:translateX(14px); }
}
.book-scene.opening .book-turn-leaf { display:block; animation:leafSweepOpen 0.72s cubic-bezier(0.5,0.03,0.24,1) both; }
.book-scene.closing .book-turn-leaf { display:block; animation:leafSweepClose 0.72s cubic-bezier(0.5,0.03,0.24,1) both; }
.book-scene.opening .book-turn-leaf-content { animation:leafContentOpen 0.72s cubic-bezier(0.5,0.03,0.24,1) both; }
.book-scene.closing .book-turn-leaf-content { animation:leafContentClose 0.72s cubic-bezier(0.5,0.03,0.24,1) both; }

/* Open book spread */
.book-open-wrap {
  display:none; opacity:0; width:100%; max-width:870px; margin:0 auto;
  transition:opacity 0.16s ease;
}
.book-open-wrap.showing { display:block; }
.book-open-wrap.visible { opacity:1; }

/* THE PAGE BLOCK, which is the thickness the spread did not have. Two rectangles
   side by side are a card no matter how they are lit; what says book is that there
   are several hundred more leaves under the one you are reading. The spread sits
   inset on this, so a few of them show past every edge -- more at the foot, because
   that is the edge a block sags over.

   `--gutter-x` is declared here and nowhere else. It is the index page's width AND
   the position of the binding shadow AND where the ribbon comes out, and the reason
   it is one number is that when it was three, they disagreed: see the gutter. */
.book-block {
  /* A spread has equal leaves. Two screens let the campaign page keep that proportion. */
  --gutter-x:50%;
  --paper-grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)' opacity='0.3'/%3E%3C/svg%3E");
  position:relative; border-radius:8px; padding:2px 5px 8px;
  background:
    repeating-linear-gradient(to bottom, #FAF5EC 0 1px, rgba(92,61,46,0.15) 1px 2px) bottom / 100% 8px no-repeat,
    repeating-linear-gradient(to bottom, #FAF5EC 0 1px, rgba(92,61,46,0.11) 1px 2px) top / 100% 2px no-repeat,
    repeating-linear-gradient(to right,  #FAF5EC 0 1px, rgba(92,61,46,0.15) 1px 2px) left / 5px 100% no-repeat,
    repeating-linear-gradient(to right,  #FAF5EC 0 1px, rgba(92,61,46,0.15) 1px 2px) right / 5px 100% no-repeat,
    linear-gradient(to right, #EDE8DC 0%, #F5EDD8 6%, #F5EDD8 94%, #EDE8DC 100%);
  /* One wide symmetric blur is how a card floats. An object resting on a surface has
     a tight dark contact edge under it and a soft ambient one well beyond. */
  box-shadow:
    0 1px 2px rgba(92,61,46,0.34),
    0 16px 38px -12px rgba(92,61,46,0.34),
    0 44px 92px -34px rgba(92,61,46,0.26);
}
/* There was a bookmark ribbon here and it is deliberately gone. A ribbon is read as
   one by its TAIL -- the length of it against the page and the swallowtail cut into
   the end -- and this layout has nowhere to put one: the scallop divider that starts
   the next section overlaps the foot of the book, so anything hanging below it is
   painted over at 24px. A gold stub 24px long is not a bookmark, it is a rectangle
   sticking out from under a book, and somebody would rightly file it as a bug. The
   thickness, the binding and the grain are what make this read as an object; the
   ribbon was the one part that was standing in for them rather than being one. */
.book-spread {
  display:flex; border-radius:6px;
  position:relative; overflow:hidden; z-index:1;
  min-height:clamp(500px,56vw,680px);
}
/* THE GUTTER, and it is at the gutter now. It was pinned to `left: 50%` while the
   index page is a fixed 250px of a spread up to 1060 wide, so the single shadow
   that tells you a book is bound ran down the middle of the right-hand PAGE, four
   hundred pixels from the seam it was drawing. Reading it as flat was reading it
   correctly.

   The stops are the shape of paper rather than a symmetric fade. Every leaf bows up
   out of the sewing, so it catches light a centimetre out and only falls into
   shadow at the binding itself: dark centre, bright shoulders, nothing at the ends.
   Even either side of a dark line is a line PRINTED on a flat sheet. */
.book-spread::after {
  content:''; position:absolute; left:var(--gutter-x); top:0; bottom:0;
  width:96px; transform:translateX(-50%);
  background:linear-gradient(to right,
    rgba(255,255,255,0)   0%,
    rgba(255,255,255,0.5) 15%,
    rgba(92,61,46,0.03)   33%,
    rgba(92,61,46,0.20)   45%,
    rgba(92,61,46,0.34)   50%,
    rgba(92,61,46,0.20)   55%,
    rgba(92,61,46,0.03)   67%,
    rgba(255,255,255,0.5) 85%,
    rgba(255,255,255,0)  100%
  );
  z-index:3; pointer-events:none;
}
/* Page base */
.bpage {
  position:relative; overflow:hidden;
}
/* Left page - narrow fixed nav.
   Three background layers, and the order is the physics: grain on the surface, then
   the bow, then the stock. The grain is a `feTurbulence` in a data URI rather than
   an imported fibre tile, because a picture of paper is 40kB to say what one filter
   says in a line and this page's decode budget is a measured number. It sits in the
   BACKGROUND and not over the spread, so the screenshots stay clean: paper has
   grain, a photograph printed on it does not gain any.
   The bow is the light: a leaf lifts away from the binding, so it darkens toward
   the gutter and nowhere else. A page lit evenly corner to corner is a rectangle. */
.bpage-l {
  flex: 0 0 var(--gutter-x);
  background:
    var(--paper-grain) 0 0 / 180px 180px,
    linear-gradient(to right, rgba(92,61,46,0) 60%, rgba(92,61,46,0.075) 100%),
    linear-gradient(160deg,#F5EDD8 0%,#FAF5EC 55%,#F0E8D0 100%);
  border-radius:6px 0 0 6px;
  padding:2rem 1.4rem 1.6rem 2rem;
  display:flex; flex-direction:column;
}
/* Right page - takes all remaining space */
.bpage-r { flex: 1; }
/* Ruled lines */
.bpage-l::before {
  content:''; position:absolute; inset:0;
  background:repeating-linear-gradient(
    transparent,transparent 30px,
    rgba(139,99,85,0.07) 30px, rgba(139,99,85,0.07) 31px
  );
  pointer-events:none;
}
.bpage-l-content { position:relative; z-index:1; display:flex; flex-direction:column; height:100%; }
.bpage-chapter-tag {
  font-family:'Dancing Script',cursive; font-size:0.88rem;
  color:var(--pink-d); margin-bottom:0.5rem; letter-spacing:0.06em;
}
.bpage-chapter-h {
  font-family:'Cormorant Garamond',serif; font-weight:300;
  font-size:clamp(1.5rem,3vw,2.2rem); color:var(--brown); line-height:1.15;
  margin-bottom:0.5rem;
}
.bpage-chapter-h em { font-style:italic; color:var(--pink-d); }
.bpage-chapter-sub {
  font-family:'Inter',sans-serif; font-weight:300; font-size:0.75rem;
  color:var(--brown2); line-height:1.65; margin-bottom:1.4rem;
}
.bpage-nav { display:flex; flex-direction:column; gap:0.35rem; }
.bpage-btn {
  display:flex; align-items:center; gap:0.7rem;
  padding:0.5rem 0.7rem; border-radius:4px;
  background:none; border:none; cursor:pointer; text-align:left;
  font-family:'Cormorant Garamond',serif; font-size:1rem; color:var(--brown);
  transition:background 0.2s, color 0.2s; position:relative;
}
.bpage-btn:hover { background:rgba(139,99,85,0.07); }
.bpage-btn.active {
  background:rgba(200,168,75,0.09); font-weight:600;
}
.bpage-btn.active::before {
  content:'▶'; position:absolute; left:0.1rem;
  font-size:0.45rem; color:var(--pink-d); top:50%; transform:translateY(-50%);
}
.bpage-btn-num {
  font-family:'Inter',sans-serif; font-size:0.58rem;
  letter-spacing:0.15em; color:var(--brown2); min-width:1.6rem;
}
.bpage-close {
  margin-top:auto; padding-top:1rem;
  font-family:'Dancing Script',cursive; font-size:0.82rem;
  color:var(--brown2); opacity:0.55; cursor:pointer;
  background:none; border:none; transition:opacity 0.2s; text-align:left;
}
.bpage-close:hover { opacity:1; }
/* Right page */
.bpage-r {
  background:
    var(--paper-grain) 0 0 / 180px 180px,
    linear-gradient(to left, rgba(92,61,46,0) 60%, rgba(92,61,46,0.075) 100%),
    linear-gradient(160deg,#FAF5EC 0%,#F7F0E3 55%,#F5EDD8 100%);
  border-radius:0 6px 6px 0;
  transform-origin:left center;
  transition:transform 0.0s;
  min-width:0;
}
.bpage-r.turn-out {
  animation: turnOut 0.2s ease-in forwards;
}
.bpage-r.turn-in {
  animation: turnIn 0.2s ease-out forwards;
}
@keyframes turnOut {
  from { transform: perspective(800px) rotateY(0deg); }
  to   { transform: perspective(800px) rotateY(-90deg); }
}
@keyframes turnIn {
  from { transform: perspective(800px) rotateY(-90deg); }
  to   { transform: perspective(800px) rotateY(0deg); }
}
.bpage-r-inner { padding:1.2rem 1.6rem 1.6rem; height:100%; display:flex; flex-direction:column; }
.bpage-label {
  font-family:'Dancing Script',cursive; font-size:1rem;
  color:var(--brown2); text-align:center; margin-bottom:0.9rem;
  letter-spacing:0.06em;
}
.bpage-phones {
  display:grid; grid-template-columns:repeat(2,1fr);
  gap:1.2rem; flex:1; align-items:start;
}
/* The chassis is cut off these now, so the shape IS the screen's own alpha: a
   box-shadow would draw a rectangle around a rounded thing. */
.bpage-phone {
  transition:transform 0.3s, filter 0.3s; cursor:pointer;
  filter:drop-shadow(3px 6px 16px rgba(92,61,46,0.26));
  background:transparent;
  aspect-ratio:420/910;
  width:100%;
}
.bpage-phone:hover { transform:translateY(-4px) scale(1.02); filter:drop-shadow(6px 12px 28px rgba(92,61,46,0.32)); }
.bpage-phone img { width:100%; height:100%; object-fit:contain; display:block; }
/* A dog-ear, not a triangle. The old one was a 45-degree wedge in one flat cream,
   which is a SHAPE where a fold is two facts: the sheet below shows in the notch,
   and the turned flap catches light from the other direction because it is facing
   the other way. */
.page-corner-fold {
  position:absolute; bottom:0; right:0; width:44px; height:44px; z-index:2;
  background:linear-gradient(135deg, rgba(92,61,46,0.14) 0%, rgba(92,61,46,0.05) 46%, transparent 47%);
}
.page-corner-fold::after {
  content:''; position:absolute; right:0; bottom:0; width:44px; height:44px;
  background:linear-gradient(315deg,#FAF5EC 0%,#F0E8D0 58%,#EDE8DC 100%);
  clip-path:polygon(100% 0, 100% 100%, 0 100%);
  box-shadow:-2px -2px 7px rgba(92,61,46,0.22);
}
/* Responsive */
@media (max-width:860px) {
  .book-block { --gutter-x:50%; }
  .bpage-l { padding: 1.6rem 1.2rem 1.4rem 1.6rem; }
  .bpage-phones { grid-template-columns: repeat(2,1fr); }
}
@media (max-width:700px) {
  .book-3d { transform:none; }
  /* A real book remains a spread on a phone. The whole 870px composition scales
     together, preserving the two equal leaves and the horizontal binding. */
  .book-open-wrap {
    --mobile-book-scale:0.4;
    width:870px; max-width:none; margin:0; left:50%; position:relative;
    transform:translateX(-50%) scale(var(--mobile-book-scale)); transform-origin:top center;
  }
  /* A transform changes pixels, never an element's flow box. Once the spread
     is open it is a visual layer inside the measured scene; the opener gives
     that scene the real scaled height instead of reserving an invisible
     desktop-sized book underneath it. */
  .book-open-wrap.showing { position:absolute; top:0; }
  .book-spread { flex-direction:row; min-height:680px; }
  .bpage-l { flex:0 0 50%; border-radius:6px 0 0 6px; padding:1.6rem 1.2rem 1.4rem 1.6rem; }
  .bpage-r { border-radius:0 6px 6px 0; }
  .bpage-r-inner { padding:1.6rem 1.6rem 1.8rem; }
  .bpage-phones { grid-template-columns:repeat(2,1fr); gap:1.2rem; }
  /* The whole spread is deliberately scaled to retain a horizontal book on a
     phone. Its controls must counter-scale in their own layout so the final
     hit areas still meet the 24px mobile floor. */
  .bpage-btn, .bpage-close { min-height:calc(24px / var(--mobile-book-scale)); }
  .bpage-chapter-sub { display:block; }
  .book-spread::after { display:block; }
  .book-block { padding:2px 5px 8px; }
}
/* Reduced motion: the book still opens, it just does not swing. What is left is the
   crossfade this interaction was before the hinge existed, which is the right
   fallback precisely because it was never a lie about the content -- only about the
   object. */
@media (prefers-reduced-motion: reduce) {
  .book-scene.opening .book-3d, .book-scene.closing .book-3d,
  .book-scene.opening .book-cover-hinge, .book-scene.closing .book-cover-hinge,
  .book-scene.opening .book-turn-leaf, .book-scene.closing .book-turn-leaf { animation:none; }
  .book-bloom-base { animation:none; }
  .book-user-flower { animation:none; }
  .book-scene.opening .book-turn-leaf, .book-scene.closing .book-turn-leaf { display:none; }
  .book-scene.opening .book-closed-wrap { opacity:0; transition:opacity 0.2s; }
  .book-scene.opening .book-bloom, .book-scene.closing .book-bloom,
  .book-scene.opening .book-open-hint, .book-scene.closing .book-open-hint {
    animation-duration:0.2s; animation-delay:0s;
  }
  .book-open-hint { animation:none; }
  .bpage-r.turn-out, .bpage-r.turn-in { animation-duration:0.01s; }
}
