/* ==========================================================================
   The carnet.

   The leaf that turns is a real curved surface: a chain of strips whose
   tangent sweeps through an arc, so the page bends the way paper bends
   instead of pivoting like a flat door.

   The strips are SIBLINGS, each one placed on the arc by carnet.js. They
   used to be nested, which meant a custom property written on the first one
   invalidated every one after it, and a page turn spent half its frame
   budget in style recalculation.

   The loupe lives OUTSIDE .sb-tilt, on the desk, so leaning the book never
   drags the glass with it.
   ========================================================================== */

.sb-wrap{display:grid;justify-items:center;gap:clamp(14px,2vh,22px);width:100%;
  position:relative;z-index:2}
.sb-wrap,.sb-wrap *{-webkit-user-select:none;-moz-user-select:none;user-select:none}
.sb-wrap img{-webkit-user-drag:none;user-drag:none}

.sb-stage{
  display:flex;align-items:center;justify-content:center;width:100%;
  position:relative;touch-action:pan-y;
}
.sb-arrow{
  flex:none;display:inline-flex;align-items:center;justify-content:center;
  padding:10px 8px;color:var(--ink-4);
  transition:color var(--t-fast) var(--e-out),transform .34s var(--e-back),
             opacity var(--t-fast) var(--e-out);
  z-index:8;
}
/* An inline svg with a viewBox and no width or height gets its size from its
   containing block, and inside an inline-flex button that resolves to nothing.
   Both arrows had been rendering at zero by zero since the port: the hit area
   was there, the chevron was not. */
.sb-arrow svg{width:13px;height:41px;
  transition:transform .34s var(--e-back)}
/* A thirteen pixel chevron with eight pixels either side is a twenty nine
   pixel target, which is a cursor's size, not a thumb's. On a tablet the
   book is still a spread and these arrows are still how you turn it. */
@media (pointer:coarse){
  .sb-arrow{padding:12px 16px}
}
/* A touch device has no pointer to leave, so an unguarded :hover here is not a
   hover at all: it is a state a tap switches on and nothing switches off. A
   tapped chevron kept full ink and a 4px offset for as long as the page lived.
   Every hover on the book is answered only where a real pointer exists. */
@media (hover:hover){
  .sb-arrow:hover{color:var(--ink)}
  .sb-arrow.left:hover{transform:translateX(-4px)}
  .sb-arrow.right:hover{transform:translateX(4px)}
  .sb-arrow:hover svg{transform:scaleY(1.14)}
}
.sb-arrow:active{transform:scale(.92)}

.sb-3d{
  position:relative;flex:1 1;min-width:0;max-width:940px;
  perspective:1750px;perspective-origin:50% 46%;
}
/* carnet.js writes this transform onto the element itself, once a frame. It
   was assembled here out of five custom properties set on .sb-3d, and a
   custom property inherits: moving the book by a pixel re-resolved every
   node inside it. */
.sb-tilt{
  position:relative;transform-style:preserve-3d;
  transform:translate3d(0,0,0);
  will-change:transform;
}
.sb-book{position:relative;width:100%;aspect-ratio:2000/1410;
  transform-style:preserve-3d;z-index:1}

/* The book sits on a surface, so its shadow is a pool underneath: no box,
   no filter on the artwork, nothing with an edge of its own. Both blobs
   ease off while a leaf is in the air; carnet.js writes those opacities
   straight onto them rather than through an inherited property that every
   strip in the chain would have to be re-resolved against. */
.sb-cast{position:absolute;pointer-events:none;z-index:0;will-change:opacity;
  opacity:calc(1 - var(--castk,0))}
.sb-cast.ambient{
  left:5%;right:5%;top:27%;bottom:2%;
  background:radial-gradient(50% 50% at 50% 58%,
    rgba(58,44,26,.30) 0%,rgba(58,44,26,.17) 40%,rgba(58,44,26,0) 74%);
  filter:blur(26px);
}
.sb-cast.contact{
  left:9%;right:9%;top:62%;bottom:10%;
  background:radial-gradient(50% 44% at 50% 42%,
    rgba(44,32,14,.36) 0%,rgba(44,32,14,.15) 48%,rgba(44,32,14,0) 78%);
  filter:blur(11px);
}
.sb-cast.hair{
  left:12%;right:12%;top:70%;bottom:17%;
  background:radial-gradient(50% 52% at 50% 40%,
    rgba(40,28,10,.3) 0%,rgba(40,28,10,0) 76%);
  filter:blur(4px);
}

.sb-full{position:absolute;inset:0}
.sb-full img{width:100%;height:auto}
.sb-half{position:absolute;top:0;bottom:0;width:50%;overflow-x:clip;overflow-y:visible}
.sb-half.left{left:0}
.sb-half.right{left:50%}
.sb-half-img{width:200%;max-width:none;height:auto}
.sb-half-img.right{margin-left:-100%}

/* the shadow the lifting leaf throws onto the page beneath it */
.gutter-shade{
  position:absolute;top:var(--pg,21.8%);bottom:var(--pg,21.8%);width:46%;
  pointer-events:none;opacity:0;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 5.2%,#000 94.8%,transparent 100%);
  mask-image:linear-gradient(180deg,transparent 0,#000 5.2%,#000 94.8%,transparent 100%);
}
.gutter-shade.left{right:0;background:linear-gradient(270deg,rgba(52,38,20,.3),rgba(52,38,20,0) 82%)}
.gutter-shade.right{left:0;background:linear-gradient(90deg,rgba(52,38,20,.24),rgba(52,38,20,0) 82%)}

/* ---- the turning leaf: sibling strips forming a curved surface ----
   Nothing here takes a pointer. The leaf is IN FRONT of the page it is
   lifting off, and inside a preserve-3d context the hit test follows the
   depth sort rather than z-index, so once the arc was corrected the leaf
   started swallowing every touch aimed at the tap zones underneath it: a
   reader who swiped twice in a second lost the second swipe for 336 of the
   355ms the leaf was in the air. It is a picture, and the tap zones are the
   control. */
.curl,.curl *,.sb-full,.sb-full img,.sb-half,.sb-half-img{pointer-events:none}
.curl{
  position:absolute;top:0;height:100%;
  width:calc(var(--bw,0px) * var(--span));
  transform-style:preserve-3d;z-index:6;
}
.curl.next{left:50%;transform-origin:left center}
.curl.prev{right:50%;transform-origin:right center}
.strip{
  position:absolute;top:0;height:100%;
  width:calc(var(--bw,0px) * var(--span) / var(--n));
  transform-style:preserve-3d;
}
.curl.next .strip{transform-origin:left center;left:0}
.curl.prev .strip{transform-origin:right center;right:0}

.face{
  position:absolute;top:0;bottom:0;left:0;right:-1.1px;
  backface-visibility:hidden;-webkit-backface-visibility:hidden;
  background-repeat:no-repeat;background-size:var(--bw,0px) auto;
}
.face.back{transform:rotateY(180deg)}
.face .sh,.face .gl{
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 5.2%,#000 94.8%,transparent 100%);
  mask-image:linear-gradient(180deg,transparent 0,#000 5.2%,#000 94.8%,transparent 100%);
}
/* the outermost strip carries the page's own outer edge, so its shading is
   feathered off before it reaches that edge */
.strip.edge .face .sh,.strip.edge .face .gl{
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 9%,#000 91%,transparent 100%),var(--hf);
  mask-image:linear-gradient(180deg,transparent 0,#000 9%,#000 91%,transparent 100%),var(--hf);
  -webkit-mask-composite:source-in;mask-composite:intersect;
}
.curl.next .strip.edge .face.front,.curl.prev .strip.edge .face.back{
  --hf:linear-gradient(90deg,#000 0 22%,transparent 96%);
}
.curl.next .strip.edge .face.back,.curl.prev .strip.edge .face.front{
  --hf:linear-gradient(270deg,#000 0 22%,transparent 96%);
}
.face .sh{position:absolute;left:0;right:0;top:var(--pg,21.8%);bottom:var(--pg,21.8%);
  pointer-events:none}
.curl.next .face.front .sh,.curl.prev .face.back .sh{
  background:linear-gradient(90deg,rgba(58,43,20,var(--a1,0)),rgba(58,43,20,var(--a2,0)));
}
.curl.next .face.back .sh,.curl.prev .face.front .sh{
  background:linear-gradient(90deg,rgba(58,43,20,var(--a2,0)),rgba(58,43,20,var(--a1,0)));
}
.face .gl{
  position:absolute;left:0;right:0;top:var(--pg,21.8%);bottom:var(--pg,21.8%);
  pointer-events:none;background:#fffaf0;
  /* carnet.js writes --glo onto this node every frame. It used to write it
     onto the STRIP, where it inherited down and re-resolved all six nodes
     below it; on the leaf that actually reads it, nothing cascades. */
  opacity:var(--glo,0);
}

/* ---------------------------------------------------------- the loupe --
   A real jeweller's glass lying on the page. Pick it up and drag it; it
   stays where you put it. On a phone, press and hold instead. */
.loupe{
  position:absolute;left:0;top:0;
  width:var(--lr,270px);height:var(--lr,270px);
  pointer-events:none;z-index:80;opacity:0;
  transition:opacity .25s var(--e-out);
  will-change:transform;
}
.loupe.on{opacity:1}
.loupe .ring,.loupe .grip{transition:transform .2s var(--e-out)}
.loupe.held .ring,.loupe.held .grip{cursor:grabbing}
.loupe.held .ring{transform:scale(1.015)}
.loupe .ring{
  position:absolute;inset:0;border-radius:50%;
  pointer-events:auto;cursor:grab;
  padding:calc(var(--lr,270px) * .058);
  box-shadow:
    0 1px 2px rgba(58,44,26,.3),
    0 10px 18px rgba(58,44,26,.24),
    0 26px 40px rgba(58,44,26,.2),
    0 48px 66px rgba(58,44,26,.13);
}
/* the bezel is an annulus, so the glass really is see-through */
.loupe .ring:before{
  content:"";position:absolute;inset:0;border-radius:50%;pointer-events:none;
  background:linear-gradient(146deg,
    #fdf7e9 0%,#e6d7b4 14%,#b69d70 32%,#7d6740 50%,
    #cdbb92 66%,#f4ead3 80%,#9b8459 100%);
  box-shadow:
    inset 0 1px 1px rgba(255,255,255,.8),
    inset 0 -2px 3px rgba(70,52,26,.5);
  -webkit-mask-image:radial-gradient(circle closest-side at 50% 50%,transparent 0 88.2%,#000 89.8% 100%);
  mask-image:radial-gradient(circle closest-side at 50% 50%,transparent 0 88.2%,#000 89.8% 100%);
}
/* the handle, drawn before the bezel so the ring covers its inner end */
.loupe .grip{
  position:absolute;left:50%;top:50%;
  width:calc(var(--lr,270px) * .74);height:calc(var(--lr,270px) * .125);
  transform-origin:0 50%;
  transform:rotate(40deg) translate(calc(var(--lr,270px) * .33),-50%);
  border-radius:calc(var(--lr,270px) * .06);
  pointer-events:auto;cursor:grab;
  background:
    linear-gradient(180deg,rgba(255,255,255,.46) 0 13%,rgba(255,255,255,0) 44%,
                    rgba(0,0,0,.26) 100%),
    linear-gradient(90deg,#d9bd82 0 14%,#a9884e 14% 20%,#6d4c2b 20% 62%,
                    #5a3d22 62% 92%,rgba(122,86,49,.5) 92% 100%);
  box-shadow:0 8px 15px rgba(58,44,26,.26),0 18px 26px rgba(58,44,26,.14);
}
.lens{
  position:relative;display:block;width:100%;height:100%;border-radius:50%;
  overflow:hidden;
  box-shadow:
    inset 0 0 0 1px rgba(52,40,22,.55),
    inset 0 4px 12px rgba(40,30,14,.28),
    inset 0 -7px 16px rgba(255,250,240,.14);
}
.lens:before,.lens:after{content:"";position:absolute;inset:0;border-radius:50%;
  pointer-events:none}
/* the glass bends and darkens toward its rim, with a faint colour fringe */
.lens:before{
  z-index:1;
  background:radial-gradient(circle at 50% 50%,
    rgba(0,0,0,0) 54%,rgba(58,44,26,.1) 76%,rgba(46,34,16,.34) 100%);
  box-shadow:
    inset 0 0 0 2px rgba(130,162,196,.26),
    inset 0 0 0 4px rgba(206,158,112,.15);
}
/* the dome: one broad specular and a tight crescent opposite it */
.lens:after{
  z-index:2;
  background:
    radial-gradient(36% 26% at 29% 19%,rgba(255,255,255,.3),rgba(255,255,255,0) 76%),
    radial-gradient(24% 16% at 74% 86%,rgba(255,255,255,.12),rgba(255,255,255,0) 80%),
    linear-gradient(150deg,rgba(255,255,255,.06) 0 18%,rgba(255,255,255,0) 42%);
}
/* the light travels across the dome when the glass is picked up */
.loupe.held .lens:after{animation:lens-glint .7s var(--e-out)}
@keyframes lens-glint{
  0%{transform:translate3d(-6%,-4%,0)}
  100%{transform:none}
}
/* A second copy of the page, sitting beside the glass outside the tilt, and
   scaled about whichever page point the glass is currently over. */
.zoomwrap{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:2;
  opacity:0;transition:opacity .2s var(--e-out)}
.zoominner{position:absolute;inset:0;transform-origin:0 0}
.sb-clone{position:absolute;left:0;top:0}

/* -------------------------------------------------------- the controls
   Floating on the desk at the bottom right of the BOOK, in the band of bare
   paper below it, instead of a row of its own that pushed the price off the
   fold. Anchored to the book and not to the stage, or on a wide screen it
   drifts off on its own halfway to the edge. */
.sb-tools{
  position:absolute;left:0;bottom:1%;z-index:12;
  display:flex;align-items:center;gap:6px;
  border:1px solid var(--hair);border-radius:999px;
  padding:5px 7px;background-color:rgba(250,246,238,.72);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  opacity:0;transform:translateY(6px);
  transition:opacity .5s var(--e-out) .3s,transform .5s var(--e-out) .3s;
}
.sb-wrap.ready .sb-tools{opacity:1;transform:none}
@media (hover:hover){
  .sb-stage:hover .sb-tools{background-color:rgba(253,250,244,.9)}
}
.tool{
  width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;
  border-radius:50%;background-color:transparent;color:var(--ink-3);
  transition:background-color var(--t-fast) var(--e-out),color var(--t-fast) var(--e-out),
             transform .3s var(--e-back);
}
@media (hover:hover){
  .tool:hover:not([disabled]){background-color:rgba(255,252,244,.9);color:var(--ink)}
}
.tool:active:not([disabled]){transform:scale(.88)}
.tool[aria-pressed="true"]{background-color:rgba(166,124,69,.16);color:var(--gold)}
.tool[disabled]{opacity:.3;cursor:default}
.tool svg{width:15px;height:15px}
.tool-sep{width:1px;height:17px;background:var(--hair);margin:0 2px}
.zoom-read{font-size:10.5px;letter-spacing:.09em;color:var(--ink-4);
  min-width:42px;text-align:center}

/* ------------------------------------------------------------- the pips
   Twelve marks under the book: which plate you are on, and how many are
   left. A book tells you that for nothing just by being an object.  */
.sb-pips{
  position:absolute;left:50%;bottom:1%;transform:translateX(-50%);z-index:11;
  display:flex;align-items:center;gap:0;padding:2px 0;
  opacity:0;transition:opacity .5s var(--e-out) .34s;
}
.sb-wrap.ready .sb-pips{opacity:1;pointer-events:auto}
/* A five pixel dot was a five pixel target, twelve of them at a twelve pixel
   pitch, which is a quarter of the 24px minimum in every direction. The mark
   on the desk is still five pixels; the BUTTON around it is twenty four, and
   the dot is drawn inside it. Nothing about the drawing changed, only the
   size of the thing a thumb has to find. */
.pip{
  width:24px;height:24px;border-radius:50%;padding:0;flex:none;
  position:relative;background-color:transparent;
}
.pip:before{
  content:"";position:absolute;left:50%;top:50%;
  width:5px;height:5px;margin:-2.5px 0 0 -2.5px;border-radius:50%;
  background-color:var(--ink-4);opacity:.4;
  transition:transform .38s var(--e-back),opacity .3s var(--e-out),
             background-color .3s var(--e-out);
}
@media (hover:hover){
  /* a tapped-but-unselected pip used to keep .85 opacity and a 1.4 scale,
     so the plate you had just left went on claiming to be the live one */
  .pip:hover:before{opacity:.85;transform:scale(1.4)}
}
.pip.on:before{background-color:var(--gold);opacity:1;transform:scale(1.7)}

.sb-zone{position:absolute;top:16.5%;bottom:16.5%;cursor:grab;z-index:60;
  -webkit-tap-highlight-color:transparent}
.sb-zone:active{cursor:grabbing}
.sb-prev{left:0;width:50%}
.sb-next{right:0;width:50%}

/* ------------------------------------------------- the museum label ----
   Name, what it is, what it costs, and the two things you can do about it,
   in one object directly under the plate. */
.sb-label{
  position:relative;z-index:5;
  display:grid;justify-items:center;gap:clamp(10px,1.6vh,16px);width:100%;
  padding-inline:18px;
}
.sb-captions{display:grid;justify-items:center;width:100%}
.sb-captions>*{grid-area:1/1;margin:0}
.sb-caption{display:grid;justify-items:center;gap:6px;text-align:center;
  animation:cap-in .46s var(--e-out) both}
.sb-caption.live{animation:none}
@keyframes cap-in{0%{opacity:0;transform:translateY(6px)}}
.sb-caption h3{font-family:var(--display);font-weight:300;
  font-size:clamp(26px,2.7vw,38px);line-height:1.1}
.sb-caption h3 a{
  position:relative;display:inline-block;padding-bottom:3px;
  transition:color var(--t-fast) var(--e-out);
}
.sb-caption h3 a:after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--gold);transform:scaleX(0);transform-origin:right center;
  transition:transform .46s var(--e-out);
}
@media (hover:hover){
  .sb-caption h3 a:hover{color:var(--gold-deep)}
  .sb-caption h3 a:hover:after{transform:scaleX(1);transform-origin:left center}
}
/* the keyboard half is not a hover and must answer on every device */
.sb-caption h3 a:focus-visible:after{transform:scaleX(1);transform-origin:left center}
.sb-caption .sb-meta{
  display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:9px;
  font-size:11px;letter-spacing:var(--tr-caps);
  text-transform:uppercase;color:var(--ink-3);
}
.sb-meta i{width:3px;height:3px;border-radius:50%;background:var(--ink-4);flex:none}
.sb-meta .sb-price{color:var(--ink);letter-spacing:.08em}

.sb-buy{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:10px;
  transition:opacity .3s var(--e-out),transform .3s var(--e-out);
}
.sb-buy.is-away{opacity:0;transform:translateY(4px);pointer-events:none}
.sb-stock{
  font-size:10px;letter-spacing:var(--tr-caps);text-transform:uppercase;
  color:var(--ink-4);display:inline-flex;align-items:center;gap:6px;
}
.sb-stock:before{content:"";width:4px;height:4px;border-radius:50%;
  background:var(--ink-4)}
.sb-stock.on{color:var(--sage)}
.sb-stock.on:before{background:var(--sage);
  animation:stock-pulse 2.6s ease-in-out infinite}
@keyframes stock-pulse{0%,100%{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.35)}}

.sb-hint{
  position:relative;z-index:5;
  margin:0;font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-4);transition:opacity .4s var(--e-out);text-align:center;
  padding-inline:18px;
}
.sb-hint.gone{opacity:0}

/* -------------------------------------------------------------- shut ----
   While the loading screen still has its cover over the right half, the book
   is clipped to that same half, so the desk beside it is bare the way a shut
   book leaves it. Opening runs the clip out to the full spread on the cover's
   own curve, which reads as the left page being laid down. */
/* Out of sight until there is a cover over it. The loading screen carries the
   closed carnet across the desk before it opens, and a spread showing through
   beside a book that has not been opened yet is the whole illusion undone. */
.sb-wrap.sealed .sb-book{opacity:0}
body.book-under .sb-wrap.sealed .sb-book{opacity:1}

/* Measured onto the spread: the clip runs out of the gutter on the cover's own
   curve, so the left page reads as being laid down by it. */
body[data-opening="fit"] .sb-wrap.sealed .sb-book{clip-path:inset(-2px 0 -2px 50%)}
body[data-opening="fit"] .sb-wrap.unsealing .sb-book{
  clip-path:inset(-2px 0 -2px 0%);
  transition:clip-path .62s cubic-bezier(.58,.03,.22,1);
}
/* Where it could not be measured on, there is nothing for a clip to unfold out
   of, so the spread simply comes up under the cover as it swings. */
body[data-opening="plain"] .sb-wrap.unsealing .sb-book{
  opacity:1;transition:opacity .44s var(--e-out) .16s;
}
/* Everything around the book stays away until the book is finished moving,
   so nothing arrives twice: no caption that names a plate that is not settled
   yet, no glass that appears and then hides again.

   INVISIBLE IS NOT INERT. These were held at opacity 0 and nothing else, so
   for the whole of the opening they still took clicks and still took Tab: an
   eighteen thousand euro ring really could be put in the bag by clicking a
   button nobody could see. visibility:hidden takes them out of hit testing
   and out of the tab order together, and the class is dropped the instant
   the cover starts to swing, so the fade in is unaffected. */
.sb-wrap.sealed .sb-cast{opacity:0}
.sb-wrap.sealed .sb-arrow,
.sb-wrap.sealed .sb-label,
.sb-wrap.sealed .sb-hint,
.sb-wrap.sealed .sb-tools,
.sb-wrap.sealed .sb-pips{opacity:0;visibility:hidden;pointer-events:none}
.sb-wrap.sealed .loupe,
.sb-wrap.unsealing .loupe{opacity:0}
.sb-wrap.sealed .sb-zone,.sb-wrap.unsealing .sb-zone{pointer-events:none}
.sb-wrap.sealed .zoomwrap,.sb-wrap.unsealing .zoomwrap{display:none}
.sb-arrow,.sb-label,.sb-hint{transition:opacity .5s var(--e-out) .2s}
.loupe{transition:opacity .5s var(--e-out) .16s}
@media (prefers-reduced-motion:reduce){
  .sb-wrap.unsealing .sb-book{transition:none}
}

/* ------------------------------------------------- fitting the viewport --
   The book is sized by the height it is allowed, not just the width, so the
   label and the price stay above the fold on a short laptop. The reserve
   used to be 300px against a label that measured 200, which is how the one
   button anybody needs ended up under the edge of every 768px screen. */
/* The reserve is what the label and the scroll cue need under the book. On
   a phone held sideways there is only 390px of height in the first place, so
   the arithmetic came out at 77px of book: a floor, or the sum goes negative
   on every short viewport there is. */
.sb-3d{max-width:min(940px, max(320px, calc((100svh - 336px) * 1.418)))}
/* and a short screen stops pretending the hero is a screenful */
@media (max-height:560px){
  .hero{min-height:auto}
}

/* ==================================================== the whole spread ==
   A phone used to magnify ONE page to 2.13x and pan sideways to the other.
   It put 51 per cent of the spread on the screen, it cost two taps to reach
   the next plate because the gutter had to be crossed first, and it meant a
   second coordinate system that every other part of this file had to know
   about. It is gone. A phone gets the whole spread, edge to edge, and one
   gesture is one plate.

   A spread is 2.26:1 of paper against a screen that is 0.46:1, so the plate
   lands about 350 by 155 on a 390px phone. The way to make that read as
   deliberate rather than stranded is to give it every pixel of the width and
   real air above and below it, which is what the rules below do. */
@media (max-width:760px){
  /* The chevrons come out of the flex row and lie on the book. In the row
     they were eating 60px of a 390px screen, which is 15 per cent of the
     plate spent on two arrows. */
  .sb-arrow{
    position:absolute;top:50%;transform:translateY(-50%);z-index:70;
    padding:15px 17px;margin-inline:2px;
    color:var(--ink-3);
    background-color:rgba(250,246,238,.55);
    -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
    border-radius:999px;
  }
  .sb-arrow svg{width:11px;height:30px}
  .sb-arrow.left{left:0}
  .sb-arrow.right{right:0}
  @media (hover:hover){ .sb-arrow:hover{transform:translateY(-50%)} }
  .sb-arrow:active{transform:translateY(-50%) scale(.9)}

  /* The desktop clamp sizes the book off the height a laptop has left under
     the label. A phone has a different reserve and a much shorter book, and
     that arithmetic came out at 77px of carnet on a phone held sideways.
     Width rules here; the height only clamps a genuinely short viewport, and
     there is a 300px floor under it so the sum can never go negative. */
  .sb-3d{
    max-width:max(300px, calc((100svh - 220px) * 1.418));
    perspective:1150px;
    /* KEPT deliberately. The glass is a 130px disc drawn at a fingertip and
       the zoom control still exists on a narrow pointer window, so the book
       can still be pushed past this box; a mobile browser is entitled to
       widen its layout viewport to fit overflow, and Chrome does, which is
       how the header once came out 796px wide on a 390px phone. Clipping here
       makes no scroll container and does not flatten the 3D inside it, and
       overflow-y stays visible so the shadow can fall out of the bottom. */
    overflow-x:clip;overflow-y:visible;overflow-clip-margin:0px;
  }
  /* Zoom is a pointer control and the glass is the zoom on a phone, so there
     is nothing left for a toolbar to hold. */
  .sb-tools{display:none}
  .sb-pips{bottom:0}
  .pip:before{width:6px;height:6px;margin:-3px 0 0 -3px}

  /* THE PAPER gets the full width, not the image the paper is printed in.
     The spread is composited on a desk and the painted sheet only spans
     0.051 to 0.949 of it, so a book laid out at exactly the screen width put
     the plate 350px wide inside a 390px phone and lost 20px of picture down
     each side to bare desk that nobody needs to see. The book is widened
     until the sheet reaches both edges and the desk hangs over them, where
     the clip on .sb-3d above takes it. 100 / (0.949 - 0.051) = 111.359. */
  .sb-book{width:111.359%;margin-inline:-5.6795%}

  .sb-wrap{gap:clamp(10px,2.2svh,20px)}
  .sb-hint{font-size:9.5px;letter-spacing:.09em}
  .sb-label{gap:9px;padding-inline:14px}
  .sb-caption{gap:5px}
  .sb-caption h3{font-size:clamp(26px,8vw,36px)}
  .sb-buy{gap:8px;width:100%}
  .sb-buy .btn{flex:1 1 auto;min-width:0}
}
@media (pointer:coarse){
  .sb-tools{display:none}
}
/* the smallest phones still in use are 320 wide and 568 tall, and the price
   and the button have to be on that screen without scrolling */
@media (max-width:360px),(max-height:600px){
  .sb-wrap{gap:8px}
  .sb-caption h3{font-size:26px}
  .sb-caption .sb-meta{font-size:10px;gap:7px}
  .sb-buy .btn{min-height:42px;font-size:10px;padding-inline:10px}
}
/* on a coarse pointer the glass is summoned by a press and hold, so it is
   never sitting on the page waiting to be dragged by accident */
@media (pointer:coarse){
  .loupe .grip{display:none}
  .loupe .ring{pointer-events:none}
  /* and the zoom pair is dead weight there: a touch device has the glass,
     and at 40px a target the toolbar was 200px of pill lying across a book
     that is 320px wide on a phone held sideways */
  .sb-tools .tool[data-zin],.sb-tools .tool[data-zout],
  .sb-tools .zoom-read,.sb-tools .tool-sep{display:none}
}
