/*
  The Formula Deck.

  The site's tokens, re-declared rather than imported. `/draft/styles.css` is
  56KB of homepage — a header that hides on scroll, a 3D viewer, twenty section
  layouts — and this page uses none of it. Eighteen lines of duplication buys a
  stylesheet that is a fifth of the size and cannot be broken by a change to the
  homepage. The fonts are the same two files, so they are already in the cache
  for anyone arriving from the site.

  If the palette ever moves, it moves in both places. That is the deal.
*/
@font-face { font-family: 'Formula Oswald'; src: url('/draft/assets/formula-oswald.woff2') format('woff2'); font-style: normal; font-weight: 300 700; font-display: swap; }
@font-face { font-family: 'Formula Inter'; src: url('/draft/assets/formula-inter.woff2') format('woff2'); font-style: normal; font-weight: 300 700; font-display: swap; }

:root {
  --ink: #11100f;
  --ink-soft: #1a1917;
  --cream: #e9dfcf;
  --cream-muted: rgba(233, 223, 207, .64);
  --paper: #f0ebe2;
  --bronze: #9b7251;
  --display: 'Formula Oswald', 'Arial Narrow', sans-serif;
  --text: 'Formula Inter', Inter, Arial, sans-serif;
  --ease: cubic-bezier(.22, 1, .36, 1);

  /* The size of one page, in px. Set by the script once it has measured the
     stage; everything in the book is laid out from these two numbers. */
  --pw: 420px;
  --ph: 595px;
  --bar: 60px;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body { height: 100%; }
body {
  margin: 0;
  color: var(--cream);
  /* A single soft pool of light behind the book, so the paper is the brightest
     thing on screen and the edges of the room fall away. */
  background:
    radial-gradient(120% 90% at 50% 38%, #221f1c 0%, var(--ink) 62%) fixed,
    var(--ink);
  font-family: var(--text);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img { display: block; width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button, a { -webkit-tap-highlight-color: transparent; }
::selection { background: var(--bronze); color: var(--paper); }
:focus-visible { outline: 2px solid var(--bronze); outline-offset: 3px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.skip-link {
  position: fixed; top: .75rem; left: .75rem; z-index: 100;
  padding: .8rem 1rem; color: var(--ink); background: var(--cream);
  transform: translateY(-150%);
}
.skip-link:focus { transform: translateY(0); }

/* ---------------------------------------------------------------- the bar */

.deck-bar {
  position: fixed; inset: 0 0 auto; z-index: 20;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  height: calc(var(--bar) + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) max(1rem, env(safe-area-inset-right)) 0 max(1rem, env(safe-area-inset-left));
}
/* A zoomed page fills the screen and is mostly cream, which leaves the bar's own
   type — cream on nothing — unreadable against it. The bar earns a ground of its
   own for as long as the zoom is open. */
html[data-zoomed] .deck-bar {
  background: rgba(17, 16, 15, .92);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
.deck-brand { display: inline-flex; width: fit-content; opacity: .9; transition: opacity .25s ease; }
.deck-brand:hover { opacity: 1; }
.deck-brand img { width: auto; height: 26px; }

.deck-heading {
  margin: 0; justify-self: center;
  font-family: var(--display); font-size: .82rem; font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase; color: var(--cream-muted);
}

.deck-tools { display: flex; justify-self: end; align-items: center; gap: .35rem; }
.deck-readout {
  margin: 0 .5rem 0 0;
  font-family: var(--display); font-size: .82rem; font-weight: 400;
  letter-spacing: .14em; color: var(--cream-muted); font-variant-numeric: tabular-nums;
}
/* 44px targets. The bar is 60px tall and these are the only things in it worth
   hitting, so there is room to make them properly hittable. */
.deck-tool {
  display: inline-flex; align-items: center; gap: .4rem;
  min-width: 44px; min-height: 44px; padding: 0 .6rem;
  border: 0; border-radius: 10px;
  color: var(--cream-muted); background: none; font: inherit; cursor: pointer;
  transition: color .25s ease, background .25s ease;
}
.deck-tool:hover, .deck-tool[aria-pressed="true"] { color: var(--cream); background: rgba(233, 223, 207, .08); }
.deck-tool svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.deck-tool--pdf { font-family: var(--display); font-size: .78rem; letter-spacing: .16em; }

/* --------------------------------------------------------------- the book */

.deck {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  height: 100dvh;
  /* The bar above, and below it the strip the arrows and the hint live in — the
     book is sized against what is left, so neither ever lands on a page. */
  padding:
    calc(var(--bar) + env(safe-area-inset-top)) 0
    calc(2.4rem + env(safe-area-inset-bottom));
}
html.js body { overflow: hidden; overscroll-behavior: none; }
html:not(.js) .deck, html:not(.js) .deck-step, html:not(.js) .deck-hint { display: none; }

.deck-stage {
  position: relative;
  /* The flap of a turning page leaves the book — on a phone it swings right off
     the side of it — so nothing between here and the viewport may clip. */
  overflow: visible;
  touch-action: none;
  /* Duration is written per turn by the script, so the book opening out and the
     page going over are one movement rather than two. */
  transition: transform 0ms var(--ease);
}

.book {
  position: relative;
  width: calc(var(--pw) * var(--leaves, 2));
  height: var(--ph);
}

.book__page { position: absolute; top: 0; width: var(--pw); height: var(--ph); }
.book__page--left { left: 0; }
.book__page--right { left: calc(var(--pw) * (var(--leaves, 2) - 1)); }
.book__page img, .fold__layer img {
  width: 100%; height: 100%;
  object-fit: fill;               /* the box is cut to the page's own ratio */
  background: var(--paper);       /* so a page that has not decoded yet is paper, not a hole */
  -webkit-user-drag: none; user-select: none;
}
.book__page img:not([src]), .fold__layer img:not([src]) { visibility: hidden; }

/* The book's own weight: a soft pool underneath, and the gutter where the two
   pages meet. Both sit under the fold layer so a turning page passes over them. */
.book::before {
  content: ''; position: absolute; inset: 2% -2% -3%;
  background: radial-gradient(60% 50% at 50% 100%, rgba(0, 0, 0, .55), transparent 70%);
  filter: blur(18px); z-index: -1;
}
.book[data-spread="1"][data-single="0"]::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: 50%; z-index: 3;
  width: 74px; margin-left: -37px; pointer-events: none;
  background: linear-gradient(90deg,
    transparent 0%, rgba(0, 0, 0, .16) 34%, rgba(0, 0, 0, .34) 50%, rgba(0, 0, 0, .16) 66%, transparent 100%);
}

/* ---------------------------------------------------------------- the fold */

/*
  Three layers, all the size of the turning page, all stacked on the half of the
  book that page occupies:

    under   the page being revealed underneath
    front   the part of the turning page that has not lifted yet, clipped to the
            flat side of the fold
    flap    the back of the same sheet, clipped to the folded side and reflected
            across the fold line — which is the whole trick, and why the back of
            the page reads mirrored while it is in the air

  The script writes `clip-path` and `transform` on these every frame. Nothing
  here transitions: a transition on a dragged value fights the pointer.
*/
/* Sits exactly over the right-hand page: the sheet that turns is always the one
   on the right, whichever direction the reader is going. */
.fold {
  position: absolute; top: 0; z-index: 4;
  left: calc(var(--pw) * (var(--leaves, 2) - 1));
  width: var(--pw); height: var(--ph);
}
.fold__layer { position: absolute; inset: 0; will-change: clip-path, transform; }
.fold__under { z-index: 1; }
.fold__front { z-index: 2; }
.fold__flap {
  z-index: 3;
  transform-origin: 0 0;
  /* Follows the clip path exactly, which is what makes the lifted corner sit
     above the page rather than on it. Two shadows: a tight one that reads as
     the thickness of the sheet, and a wide soft one for the height it has been
     lifted to. */
  filter:
    drop-shadow(0 1px 1px rgba(0, 0, 0, .45))
    drop-shadow(-6px 6px 24px rgba(0, 0, 0, calc(.30 + .35 * var(--lift, 0))));
}

/* Both gradients are written per frame by the script, anchored to the crease —
   see `anchored()`. The fallbacks here only matter for the instant before the
   first paint. */
.fold__sheen, .fold__crease { position: absolute; inset: 0; pointer-events: none; }
.fold__sheen { background-image: linear-gradient(90deg, rgba(255, 255, 255, .3), rgba(0, 0, 0, .3)); }
.fold__crease { background-image: none; }

/* --------------------------------------------------------------- controls */

.deck-step {
  position: absolute; top: 50%; z-index: 10;
  display: grid; place-items: center;
  width: 56px; height: 56px; margin-top: -28px;
  border: 0; border-radius: 50%;
  color: var(--cream-muted); background: rgba(17, 16, 15, .5); cursor: pointer;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  transition: color .3s var(--ease), background .3s var(--ease), opacity .3s var(--ease);
}
.deck-step--prev { left: max(.9rem, env(safe-area-inset-left)); }
.deck-step--next { right: max(.9rem, env(safe-area-inset-right)); }
.deck-step:hover { color: var(--cream); background: rgba(17, 16, 15, .8); }
.deck-step[disabled] { opacity: 0; pointer-events: none; }
.deck-step svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }

.deck-hint {
  position: absolute; left: 50%; bottom: max(1.1rem, env(safe-area-inset-bottom));
  margin: 0; transform: translateX(-50%);
  font-size: .78rem; letter-spacing: .06em; color: rgba(233, 223, 207, .34);
  pointer-events: none; transition: opacity .6s var(--ease);
}
.deck-hint[data-spent] { opacity: 0; }

/* ------------------------------------------------------------------- zoom */

/* Fixed, not absolute: the stage slides sideways when the book opens on a single
   page, and a zoom anchored to it would inherit that offset. */
.zoom {
  position: fixed; inset: 0; z-index: 12;
  overflow: hidden; background: rgba(17, 16, 15, .94);
  cursor: grab; touch-action: none;
}
.zoom[data-panning] { cursor: grabbing; }
.zoom img {
  position: absolute; top: 0; left: 0;
  width: var(--pw); height: var(--ph);
  transform-origin: 0 0; will-change: transform;
}

/* ------------------------------------------- the brochure without a script */

.deck-source { display: grid; justify-items: center; gap: 2rem; padding: calc(var(--bar) + 2rem) 1rem 3rem; }
html.js .deck-source { display: none; }
.deck-source__page { max-width: 640px; margin: 0; }
.deck-source__page img { box-shadow: 0 26px 60px -26px rgba(0, 0, 0, .9); }
.deck-source__page figcaption {
  margin-top: .6rem; font-family: var(--display); font-size: .74rem;
  letter-spacing: .18em; text-transform: uppercase; color: var(--cream-muted);
}

/*
  The words. Off screen for a reader who has the book, and the whole of the page
  for a reader who has a screen reader or is a search engine — the brochure is
  ten flattened images and says nothing on its own.
*/
.deck-text {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
html:not(.js) .deck-text {
  position: static; width: auto; height: auto;
  max-width: 44rem; margin: 0 auto; padding: 0 1rem 4rem;
  clip: auto; white-space: normal;
}

/* --------------------------------------------------------------- narrower */

@media (max-width: 820px) {
  /* Out of sight, not out of the page: it is the document's only h1. */
  .deck-heading { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .deck-bar { grid-template-columns: auto 1fr; }
  .deck-tools { grid-column: 2; }

  /* One page fills the width of a phone, so there is no room beside it for the
     arrows — they drop into the space under the book instead, with the hint
     between them. */
  .deck-step {
    top: auto; margin-top: 0;
    bottom: max(.5rem, env(safe-area-inset-bottom));
    width: 46px; height: 46px;
  }
  .deck-hint { bottom: max(1.35rem, calc(env(safe-area-inset-bottom) + .85rem)); font-size: .74rem; }
}

@media (prefers-reduced-motion: reduce) {
  .deck-step, .deck-hint { transition: none; }
}
