/* αBook public website — visual language
   Ground, paper and accent are sampled from the actual photographs of the
   worn copy of The New Digital Age and from the αBook app itself. */

:root {
  /* the dark table the book is photographed on */
  --slate: #16171a;
  --slate-lift: #1f2126;
  --slate-line: #33353b;

  /* the aged, stained paper of the worn copy */
  --paper: #efe7d8;
  --paper-dim: #c9bda8;
  --paper-faint: #9c9488;

  /* the app's own Add Annotation brown, and the physical label's vermilion */
  --tan: #a0521c;
  --label: #e8622d;

  /* the yellow the app puts behind an annotated term */
  --mark: #f7e4a8;

  --ink: #1c1815;
  --ink-soft: #5b5045;

  --display: 'EB Garamond', Iowan Old Style, Palatino, Georgia, serif;
  --ui: 'Instrument Sans', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif;

  --gutter: clamp(20px, 5vw, 72px);
  --measure: 1320px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  min-width: 320px;
  margin: 0;
  color: var(--paper);
  background: var(--slate);
  font-family: var(--ui);
  font-size: 17px;
  line-height: 1.55;
  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

img, video { display: block; max-width: 100%; }
a { color: inherit; }

:where(a, button):focus-visible {
  outline: 2px solid var(--label);
  outline-offset: 4px;
  border-radius: 2px;
}

.shell {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.u-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: fixed;
  z-index: 30;
  top: 10px; left: 10px;
  padding: 10px 16px;
  color: var(--slate);
  background: var(--paper);
  border-radius: 3px;
  font-size: 15px;
  text-decoration: none;
  transform: translateY(-200%);
}
.skip:focus { transform: none; }

/* Match the film wordmark: Inter SemiBold Italic for α, Instrument Sans Bold for Book. */
.wordmark {
  display: inline-flex;
  align-items: baseline;
  color: inherit;
  font-size: inherit;
  letter-spacing: 0;
}

.wordmark__alpha {
  color: inherit;
  font-family: 'Inter', sans-serif;
  font-size: 1em;
  font-style: italic;
  font-weight: 600;
  line-height: 1;
}

.wordmark__name {
  margin-left: .015em;
  color: inherit;
  font-family: var(--ui);
  font-size: 1em;
  font-style: normal;
  font-weight: 700;
  letter-spacing: -.045em;
  line-height: 1;
}

.wordmark--brand .wordmark__alpha {
  color: #f94d00;
}

/* ---------------------------------------------------------------- hero */

.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100svh;
  padding-block: clamp(20px, 4vh, 40px) clamp(40px, 8vh, 88px);
  overflow: hidden;
  background: var(--slate);
}

.hero__video {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: .82;
}

/* Weighted to the lower left so the headline sits on ground, not on picture. */
.hero__wash {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(to top, rgba(22,23,26,.94) 0%, rgba(22,23,26,.62) 34%, rgba(22,23,26,.12) 68%, rgba(22,23,26,.5) 100%),
    linear-gradient(to right, rgba(22,23,26,.72) 0%, rgba(22,23,26,.1) 55%, rgba(22,23,26,0) 100%);
}

.hero__top,
.hero__foot { position: relative; z-index: 2; }

/* The wordmark and the language control share the hero's top line: the mark on
   the left where it has always been, the control hard right against it. */
.hero__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.hero__foot { margin-top: auto; }

.hero__mark {
  font-size: clamp(21px, 2.4vw, 26px);
  color: var(--paper);
}

.hero__title {
  max-width: 15ch;
  margin: 0 0 clamp(28px, 4vh, 44px);
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.65rem, 7.4vw, 6rem);
  line-height: 1.03;
  letter-spacing: -.012em;
  text-wrap: balance;
}

/* Store badges. Official artwork, so the art itself is left alone — but the
   two assets are not built alike: Apple's fills its box edge to edge, while
   Google ships clear space baked in and its button is only 67% of the asset's
   height. Matched boxes therefore give mismatched buttons, so the Google asset
   is scaled up until the two buttons read the same size, and its built-in
   clear space becomes part of the gap. */
.stores {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.stores a { display: block; border-radius: 7px; }

.badge { height: 46px; width: auto; }
.badge--play { height: 68px; }

/* ------------------------------------------------------------- memory */

.memory {
  position: relative;
  padding-block: clamp(72px, 13vh, 152px);
  overflow: clip;
  background: var(--slate);
}

.memory__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  gap: clamp(36px, 6vw, 88px);
  align-items: center;
}

.memory__photo {
  position: relative;
  margin: 0;
  /* the photograph is already shot on a dark table — let it meet the ground
     rather than sit on it in a card */
  -webkit-mask-image: radial-gradient(78% 74% at 52% 48%, #000 42%, transparent 96%);
  mask-image: radial-gradient(78% 74% at 52% 48%, #000 42%, transparent 96%);
}
.memory__photo img { width: 100%; height: auto; }

.memory__title {
  max-width: 16ch;
  margin: 0 0 clamp(28px, 4vh, 40px);
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2rem, 4.2vw, 3.4rem);
  line-height: 1.1;
  letter-spacing: -.01em;
}

.memory__lede {
  max-width: 34ch;
  margin: 0 0 clamp(30px, 5vh, 46px);
  color: var(--paper-dim);
  font-size: clamp(16px, 1.35vw, 18px);
}

/* ----------------------------------------- the annotation (signature)

   Rendered in the app's own grammar: the page strip with one page taken,
   the term on its yellow mark, the note, the page reference. This is the
   thing αBook does, shown rather than described. */

.note {
  max-width: 460px;
  padding: 22px 24px 20px;
  color: var(--ink);
  background: linear-gradient(168deg, #f6efe2 0%, #ece2cf 100%);
  border-radius: 14px;
  box-shadow: 0 26px 60px -18px rgba(0,0,0,.75);
}

.note__pages {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(28,24,21,.13);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}

.note__page {
  padding: 3px 9px;
  border-radius: 7px;
}

.note__page[data-current] {
  color: var(--tan);
  font-weight: 600;
  background: #fffdf7;
  border: 1px solid rgba(160,82,28,.55);
}

.note__body { padding-top: 18px; }

.note__term {
  display: inline-block;
  margin-bottom: 10px;
  padding: 3px 10px;
  background: var(--mark);
  border-radius: 5px;
  font-weight: 600;
  font-size: 16px;
}

.note__quote {
  margin: 0 0 12px;
  font-family: var(--display);
  font-size: 21px;
  line-height: 1.36;
}

.note__meta {
  margin: 0;
  color: var(--ink-soft);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------- reading life & friends

   The page turns from the dark table into daylight here. The first two scenes
   are one person with one book at night; these two are the reading life around
   it, so they sit on paper rather than on the table. It goes dark again for the
   label and the closing library. */

.daylight {
  color: var(--ink);
  background: var(--paper);
}

.lead {
  margin: 0 0 clamp(14px, 2vh, 20px);
  color: var(--ink-soft);
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(19px, 2vw, 25px);
}

/* reading life — a headline and then a full-width plate, the way a book puts
   a picture across the spread */

.life { padding-top: clamp(72px, 12vh, 140px); }

.life__title {
  max-width: 26ch;
  margin: 0 0 clamp(44px, 7vh, 80px);
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.1rem, 5.2vw, 4.4rem);
  line-height: 1.08;
  letter-spacing: -.012em;
}

/* A window onto a picture that stays put. The background is sized to the
   viewport, not to this element, so scrolling moves the frame across a fixed
   image rather than moving the image. */

.life__window {
  height: clamp(300px, 62vh, 640px);
  background-image: url('/assets/media/book/reading-life.webp');
  background-size: cover;
  background-position: 50% 55%;
  background-attachment: fixed;
}

/* Touch browsers do not honour a fixed attachment reliably — iOS in particular
   paints it once and never repaints. Give them an ordinary picture instead. */
@media (hover: none), (prefers-reduced-motion: reduce) {
  .life__window {
    background-attachment: scroll;
    background-size: cover;
  }
}

/* close friends — mirrors the memory scene, so the two halves of the story
   read as a pair rather than a repeat */

.friends {
  padding-block: 0;
  overflow: clip;
}

.friends__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
  gap: clamp(36px, 6vw, 88px);
  align-items: center;
}

.friends__title {
  max-width: 14ch;
  margin: 0 0 clamp(18px, 2.5vh, 26px);
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2rem, 4.2vw, 3.4rem);
  line-height: 1.1;
  letter-spacing: -.01em;
}

.friends__body {
  max-width: 36ch;
  margin: 0;
  color: var(--ink-soft);
  font-size: clamp(16px, 1.35vw, 18px);
}

.friends__photo { margin: 0; }

.friends__photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

/* the picture sets the height of the band; the words centre against it */
.friends__grid { align-items: center; }
.friends__copy { padding-block: clamp(28px, 4vh, 48px); }

/* ---------------------------------------------------------------- history

   What one copy goes through, in order: the label, the scan that registers it,
   the hands it passes to, the record that keeps. Photograph and app screen
   alternate down the row, so the physical and the digital read as one sequence
   rather than as two kinds of picture. */

.history {
  padding-block: clamp(72px, 13vh, 152px);
  background: var(--slate);
}

/* The sentence sits beside the headline rather than under it, so the four
   steps start higher up the screen and the row is what you look at. */
.history__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
  gap: clamp(24px, 4vw, 72px);
  align-items: end;
  margin-bottom: clamp(40px, 6vh, 76px);
}

.history__title {
  max-width: 14ch;
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2rem, 4.2vw, 3.4rem);
  line-height: 1.1;
  letter-spacing: -.01em;
}

.history__body {
  max-width: 42ch;
  margin: 0;
  color: var(--paper-dim);
  font-size: clamp(16px, 1.35vw, 18px);
}

/* One height for all four, natural widths. Each item grows in proportion to its
   own aspect ratio (--ar, set on the element beside the image it describes), so
   with a zero basis the widths land in that same proportion and every picture
   comes out exactly as tall as its neighbours — no cropping needed to make the
   row line up. The screenshots stay whole phones; the photographs stay wide. */
/* The thing itself, next to the sentence that describes it. It is a cut-out
   with real transparency, so the shadow has to follow the alpha rather than the
   image's box — hence drop-shadow instead of box-shadow. */
.history__label {
  width: clamp(112px, 12vw, 168px);
  height: auto;
  filter: drop-shadow(0 18px 32px rgba(0, 0, 0, .55));
}

.steps {
  display: flex;
  align-items: flex-start;
  gap: clamp(12px, 1.5vw, 20px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.steps > li {
  flex: var(--ar) 1 0;
  min-width: 0;
}

.step { margin: 0; }

.step__img {
  width: 100%;
  aspect-ratio: var(--ar);
  height: auto;
  object-fit: cover;
  border-radius: 10px;
  background: var(--slate-lift);
}

.step__caption {
  margin-top: 14px;
  color: var(--paper-dim);
  font-size: clamp(13px, 1.05vw, 15px);
  line-height: 1.4;
  text-wrap: balance;
}

/* ---------------------------------------------------------------- ending

   Back to a shelf, the way the page opened — but this one is somebody's own,
   packed and mismatched, rather than a shop's. */

.ending {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: clamp(520px, 82vh, 820px);
  padding-block: clamp(48px, 8vh, 96px);
  overflow: hidden;
  background: var(--slate);
}

.ending__photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .8;
}

.ending__wash {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(to top, rgba(22,23,26,.93) 0%, rgba(22,23,26,.6) 38%, rgba(22,23,26,.14) 78%),
    linear-gradient(to right, rgba(22,23,26,.7) 0%, rgba(22,23,26,.08) 58%, rgba(22,23,26,0) 100%);
}

.ending__content { position: relative; z-index: 2; }

.ending__title {
  max-width: 16ch;
  margin: 0 0 clamp(10px, 1.5vh, 16px);
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.2rem, 5.4vw, 4.4rem);
  line-height: 1.04;
  letter-spacing: -.012em;
}

.ending__line {
  margin: 0 0 clamp(28px, 4vh, 44px);
  color: var(--paper-dim);
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(19px, 2vw, 25px);
}

/* --------------------------------------------------------------- motion

   The paper book arrives from the left and its digital note from the right,
   and they meet. The movement is tied to the scroll itself, so the reader's
   own scrolling is what brings them together. The book settles first — it was
   always there — and the note comes to meet it.

   Default state is the finished position, so a browser without scroll-linked
   animation simply shows the scene at rest. */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .meets {
      --travel: -50%;
      animation: meet-in linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 46%;
    }

    .meets--right {
      --travel: 50%;
      animation-range: entry 0% cover 58%;
    }

    /* starts clear of its own right edge rather than half-overlapping it */
    .meets--edge {
      --travel: 100%;
      animation-range: entry 0% cover 62%;
    }

    /* Arrived. A scroll timeline is scrubbed both ways, so the animation has
       to be taken off the element or it would slide back out on the way up.
       The resting style is the position it just reached, so nothing moves. */
    .meets[data-settled] { animation: none; }
  }
}

/* Each starts outside its resting place, so it genuinely travels in rather
   than nudging into position. The fade finishes early — most of what you
   watch is the travel itself, not an element appearing. */

@keyframes meet-in {
  from { opacity: 0; transform: translateX(var(--travel)); }
  28%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------- footer */

.foot {
  padding-block: 56px 64px;
  color: var(--paper-faint);
  background: var(--slate);
  border-top: 1px solid var(--slate-line);
  font-size: 14px;
}

.foot__inner {
  display: flex;
  flex-wrap: wrap;
  gap: 28px 56px;
  justify-content: space-between;
  align-items: flex-end;
}

.foot__mark { font-size: 20px; color: var(--paper-dim); }

.foot__links { display: flex; flex-wrap: wrap; gap: 12px 26px; }
.foot__links a { text-decoration-color: var(--slate-line); text-underline-offset: 4px; }
.foot__links a:hover { text-decoration-color: var(--paper-faint); }

.foot p { margin: 0; }

.foot__address {
  font-style: normal;
  line-height: 1.7;
  text-align: right;
}

/* -------------------------------------------------------------- narrow */

@media (max-width: 899px) {
  .foot__address { text-align: left; }

  /* Stacked, the words come first and the picture runs the full width of the
     screen underneath them, cropped wider so it does not eat a whole screen. */
  .friends__grid { grid-template-columns: 1fr; gap: 30px; }
  .friends__copy { padding-block: clamp(40px, 7vh, 64px) 0; }
  .friends__photo { margin-inline: calc(var(--gutter) * -1); }
  .friends__photo img {
    aspect-ratio: 16 / 9;
    object-position: 50% 46%;
  }

  .history__head { grid-template-columns: 1fr; gap: 18px; align-items: start; }
  .history__label { width: clamp(104px, 26vw, 140px); }

  /* Side by side the phones would be a couple of centimetres wide here, so the
     four steps stack and each is shown at the full width of the column. */
  .steps { flex-direction: column; gap: 28px; }
  .steps > li { flex: none; }
  .step__img { max-width: 420px; }

  .meets       { --travel: -32%; }
  .meets--right { --travel: 32%; }
  .meets--edge  { --travel: 60%; }

  .memory__grid { grid-template-columns: 1fr; gap: 40px; }
  .memory__photo { max-width: 420px; }
  .note { max-width: none; }
}

@media (max-width: 520px) {
  .badge { height: 42px; }
  .badge--play { height: 62px; }
  .note { padding: 18px 18px 16px; }
  .note__pages { font-size: 13px; }
  .note__page { padding: 3px 6px; }
}




/* Touch targets. A finger needs about 44px to hit reliably; these links sit at
   16-22px, which is a miss waiting to happen. Only coarse pointers get the
   padding — a mouse does not need it and the footer stays compact on desktop. */
@media (pointer: coarse) {
  .foot__links a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* --------------------------------------------------------------- lightbox

   Native <dialog>, so the browser supplies the top layer, the focus trap, the
   inert background and Escape — all of it more correctly than a hand-rolled
   overlay, and for no bytes. The pictures open fitted to the viewport, which is
   already near native size for the phone screenshots; clicking one toggles it
   to 1:1 for a closer look. */

.step__open {
  display: block;
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 10px;
  cursor: zoom-in;
}

.step__open:focus-visible {
  outline: 2px solid var(--label);
  outline-offset: 4px;
}

/* the tile lifts very slightly, enough to read as "this opens" */
.step__open img { transition: transform .35s var(--ease, cubic-bezier(.2,.8,.2,1)); }
@media (hover: hover) {
  .step__open:hover img { transform: translateY(-3px); }
}

/* the page must not scroll behind the open picture */
html.lb-open { overflow: hidden; }

.lb {
  width: 100vw;
  max-width: 100vw;
  height: 100dvh;
  max-height: 100dvh;
  margin: 0;
  padding: 0;
  color: var(--paper);
  background: rgba(10, 11, 13, .96);
  border: 0;
  overscroll-behavior: contain;
}

.lb::backdrop { background: rgba(10, 11, 13, .96); }

.lb__frame {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  padding: clamp(44px, 7vh, 72px) clamp(12px, 4vw, 88px) clamp(64px, 10vh, 92px);
  overflow: auto;
  overscroll-behavior: contain;
}

.lb__img {
  /* Sized against the viewport, not the parent: the frame scrolls, so a
     percentage max-height would resolve against a row that grows to fit the
     very image it is meant to constrain, and the picture opens at full size. */
  max-width: 100%;
  max-height: calc(100dvh - clamp(108px, 17vh, 164px));
  width: auto;
  height: auto;
  border-radius: 8px;
  cursor: zoom-in;
  /* the swipe handler reads horizontal drags; let the browser keep the rest */
  touch-action: pan-y pinch-zoom;
}

/* 1:1. The frame scrolls, so a picture larger than the screen can be panned. */
.lb__frame.is-zoomed { place-items: start; }
.lb__frame.is-zoomed .lb__img {
  max-width: none;
  max-height: none;   /* 1:1, panned by scrolling the frame */
  cursor: zoom-out;
}

.lb__x,
.lb__nav {
  position: fixed;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  padding: 0;
  color: var(--paper);
  background: rgba(255, 255, 255, .08);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  transition: background-color .15s ease;
}

.lb__x:hover,
.lb__nav:hover { background: rgba(255, 255, 255, .18); }

.lb__x svg { width: 20px; height: 20px; }
.lb__nav svg { width: 22px; height: 22px; }

.lb__x { top: clamp(10px, 2vh, 20px); right: clamp(10px, 2vw, 20px); }
.lb__nav { top: 50%; transform: translateY(-50%); }
.lb__nav--prev { left: clamp(8px, 1.6vw, 20px); }
.lb__nav--next { right: clamp(8px, 1.6vw, 20px); }

.lb__cap {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  align-items: baseline;
  justify-content: center;
  padding: 16px 20px calc(16px + env(safe-area-inset-bottom));
  font-size: 14px;
  line-height: 1.4;
  text-align: center;
  background: linear-gradient(to top, rgba(10,11,13,.92), rgba(10,11,13,0));
}

.lb__count { color: var(--paper-faint); font-variant-numeric: tabular-nums; }

/* On a phone the arrows would sit on top of the picture, and swiping is the
   natural gesture there anyway. */
@media (max-width: 640px), (hover: none) {
  .lb__nav { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .step__open img { transition: none; }
}
