/* Baryta — the product page. One stylesheet, no frameworks, no imports, no
   web fonts. The frames change under a few dozen lines of plain script at
   the foot of the page; without it, a reader gets the same frames and the
   same words as an ordinary page, in order.

   The ground is the application's own (#0b0b0d, the padding the store shots
   were flattened onto), so every frame reads as the application rather than
   as a picture of it. Type is the operating system's own: New York for the
   headlines, the interface face for everything else. The one colour is the
   horizon from the application icon, kept for the button. */

:root {
  color-scheme: dark;

  --ground:       #0b0b0d;
  --ground-2:     #131316;
  --rule:         #26262b;
  --bezel:        #1a1a1e;
  --bezel-edge:   #2c2c31;

  --paper:        #f2efe8;
  --paper-soft:   #b7b2ab;
  --paper-faint:  #857f79;

  --horizon:      #e89c57;
  --horizon-ink:  #1a1208;

  --serif: ui-serif, "New York", "Iowan Old Style", Palatino, Georgia, serif;
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui,
          "Segoe UI", Roboto, sans-serif;

  --shell: 80rem;
  --gutter: clamp(1rem, 4vw, 3rem);

  --step-0: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
  --step-1: clamp(1.25rem, 1.1rem + 0.6vw, 1.625rem);
  --step-2: clamp(1.625rem, 1.2rem + 1.7vw, 2.5rem);
  --step-3: clamp(2rem, 1.2rem + 3vw, 3.75rem);
}

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  background: var(--ground);
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--paper);
  font-family: var(--sans);
  font-size: var(--step-0);
  line-height: 1.5;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; height: auto; }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--horizon);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--paper);
  color: var(--ground);
  padding: 0.6em 1em;
  font-size: 0.9rem;
  z-index: 20;
}

.skip:focus { left: 0.5rem; top: 0.5rem; }

/* ---- The bar ---------------------------------------------------------- */

.bar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
  padding: 0.8rem var(--gutter);
  background: color-mix(in srgb, var(--ground) 78%, transparent);
  -webkit-backdrop-filter: saturate(160%) blur(18px);
  backdrop-filter: saturate(160%) blur(18px);
  border-bottom: 1px solid color-mix(in srgb, var(--rule) 70%, transparent);
}

.wordmark {
  font-family: var(--serif);
  font-size: 1.25rem;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--paper);
}

.bar nav {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 2.5vw, 1.75rem);
  font-size: 0.875rem;
}

.bar nav a {
  color: var(--paper-soft);
  text-decoration: none;
}

.bar nav a:hover { color: var(--paper); }

.bar nav a.pill {
  color: var(--paper);
  border: 1px solid var(--bezel-edge);
  border-radius: 999px;
  padding: 0.35em 0.9em;
}

.bar nav a.pill:hover { border-color: var(--paper-faint); }

/* ---- Words ------------------------------------------------------------ */

h1, h2 {
  font-family: var(--serif);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -0.012em;
  text-wrap: balance;
  margin: 0;
}

h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }

p { margin: 0; }

.lede {
  font-size: var(--step-1);
  line-height: 1.4;
  color: var(--paper-soft);
  text-wrap: pretty;
}

.button {
  display: inline-block;
  background: var(--horizon);
  color: var(--horizon-ink);
  font-size: 1rem;
  font-weight: 500;
  line-height: 1;
  padding: 0.9em 1.5em;
  border-radius: 999px;
  text-decoration: none;
  white-space: nowrap;
}

.button:hover { background: #f0ab6c; }

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

/* The words first, then the family: the television at the back on its
   stand, the Mac on a display with a stand, the iPad and the iPhone in
   front, all with their feet on one floor line, front-on, at their true
   relative sizes. The family is as wide as the page and runs past the
   bottom of the first screen, so the eye follows it down. */

.hero {
  min-height: calc(100svh - 3.5rem);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: clamp(1.5rem, 4vh, 3.25rem);
  padding: clamp(2rem, 6vh, 4rem) var(--gutter) 0;
}

.montage {
  position: relative;
  width: min(100%, 96rem);
  aspect-ratio: 16 / 8.4;
  margin: 0 auto;
  align-self: end;
}

/* The floor: a faint band the feet stand on. */
.montage::after {
  content: "";
  position: absolute;
  left: -4%;
  right: -4%;
  bottom: -1.5%;
  height: 16%;
  background: linear-gradient(to top, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0));
  pointer-events: none;
}

.device { position: absolute; }

.device--tv    { left: 13%;  bottom: 7.5%; width: 74%;  z-index: 1; }
.device--mac   { left: 1%;   bottom: 8%;   width: 44%;  z-index: 2; }
.device--ipad  { right: 2%;  bottom: 0;    width: 27%;  z-index: 3; }
.device--phone { right: 24%; bottom: 0;    width: 9.5%; z-index: 4; }

.device img { position: relative; z-index: 1; }

/* Stands, drawn under the television and the display. */
.device--tv::before,
.device--mac::before {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  background: linear-gradient(to bottom, #2a2a2f, #131316);
}

.device--tv::before  { width: 16%; height: 8%; }
.device--mac::before { width: 14%; height: 12%; }

.device--tv::after,
.device--mac::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  border-radius: 999px;
  background: #2c2c31;
}

.device--tv::after  { top: calc(100% + 8%);  width: 34%; height: 1.4%; }
.device--mac::after { top: calc(100% + 12%); width: 30%; height: 2%; }

.device--tv img {
  border-radius: 0.3rem;
  box-shadow: 0 0 0 0.35rem #121215, 0 0 0 calc(0.35rem + 1px) var(--bezel-edge),
              0 2rem 4rem rgba(0, 0, 0, 0.7);
}

.device--mac img {
  border-radius: 0.6rem;
  box-shadow: 0 0 0 0.5rem var(--bezel), 0 0 0 calc(0.5rem + 1px) var(--bezel-edge),
              0 1.6rem 3rem rgba(0, 0, 0, 0.7);
}

.device--ipad img {
  border-radius: 0.8rem;
  box-shadow: 0 0 0 0.5rem var(--bezel), 0 0 0 calc(0.5rem + 1px) var(--bezel-edge),
              0 1.6rem 3rem rgba(0, 0, 0, 0.7);
}

.device--phone img {
  border-radius: 1.2rem;
  box-shadow: 0 0 0 0.3rem var(--bezel), 0 0 0 calc(0.3rem + 1px) var(--bezel-edge),
              0 1.2rem 2.4rem rgba(0, 0, 0, 0.7);
}

@media (max-height: 48rem) {
  .hero h1 { font-size: clamp(1.9rem, 1rem + 2.4vw, 2.9rem); }
  .hero .lede { font-size: clamp(1rem, 0.9rem + 0.4vw, 1.2rem); }
  .hero__copy { gap: 0.7rem; }
}

@media (max-width: 45rem) {
  .montage { aspect-ratio: 4 / 3.4; width: 100%; }
  .device--tv    { left: 0; width: 100%; bottom: 14%; }
  .device--ipad  { display: none; }
  .device--mac   { width: 62%; bottom: 8%; }
  .device--phone { right: 3%; width: 20%; }
  .device--tv::before { height: 9%; }
}

.hero__copy { gap: 0.7rem; }
}

@media (max-width: 45rem) {
  .montage { aspect-ratio: 4 / 3; height: auto; width: 100%; }
  .device--tv    { left: 0; bottom: 18%; width: 100%; }
  .device--ipad  { display: none; }
  .device--mac   { width: 68%; }
  .device--phone { right: 0; width: 19%; }
}

.hero__copy {
  max-width: 54rem;
  margin: 0 auto;
  text-align: center;
  display: grid;
  gap: 1rem;
  justify-items: center;
}

.hero__copy .lede { max-width: 40rem; }

.cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.75rem 1.25rem;
  margin-top: 0.5rem;
  color: var(--paper-soft);
  font-size: 0.95rem;
}

/* ---- The stories ------------------------------------------------------ */

/* Each story is one screen and a run of frames that differ by one thing,
   with a few words beside each. Frames and words are interleaved in the
   markup so that, laid out as an ordinary page, each frame is followed by
   its own words. The scroll-driven layout below stacks them instead. */

.story { position: relative; }

.stage {
  max-width: var(--shell);
  margin: 0 auto;
  padding: clamp(2rem, 6vh, 4rem) var(--gutter);
  display: grid;
  gap: 1.25rem 0;
}

.frame { width: 100%; }

.beat {
  max-width: 30rem;
  margin-bottom: clamp(2rem, 6vh, 4rem);
}

.beat h2 { margin-bottom: 0.55rem; }

.beat p {
  font-size: var(--step-0);
  line-height: 1.5;
  color: var(--paper-soft);
  text-wrap: pretty;
}

/* Bezels. The Mac capture carries its own window; the others are the bare
   panel and get a ring drawn as a spread shadow, which follows the corner
   radius on its own. Every frame in a stage has the same size, so in the
   scroll-driven layout the first frame (always opaque, at the bottom of the
   stack) carries the ring and the drop shadow for all of them. */

.frame {
  --ring: 0 0 0 0 transparent;
  --drop: 0 2.5rem 5rem rgba(0, 0, 0, 0.7);
  box-shadow: var(--ring), var(--drop);
}

[data-device="tv"] .frame {
  border-radius: 0.35rem;
  --ring: 0 0 0 1px var(--bezel-edge);
}

[data-device="ipad"] .frame {
  border-radius: 0.9rem;
  --ring: 0 0 0 0.7rem var(--bezel), 0 0 0 calc(0.7rem + 1px) var(--bezel-edge);
}

[data-device="phone"] .frame {
  border-radius: 1.6rem;
  --ring: 0 0 0 0.45rem var(--bezel), 0 0 0 calc(0.45rem + 1px) var(--bezel-edge);
  width: auto;
  max-width: 100%;
  max-height: 80svh;
  justify-self: start;
}

[data-device="ipad"] .stage,
[data-device="phone"] .stage { padding-top: clamp(3rem, 8vh, 5rem); }

/* The pinned layout. With script running (html.js), the stage sticks for
   the length of the story and the script turns frames and beats on and off
   as the reader scrolls; the frames cross-dissolve with a plain transition.
   Without script the frames and words lay out as an ordinary page, in
   order. Reduce Motion keeps the pin and cuts instead of dissolving. */

/* How many frames each story holds. It lives here and not in a style
   attribute on the markup because the site's Content-Security-Policy
   (style-src 'self') refuses inline style attributes, and a story with no
   count collapses to one screen and never pins. */
[data-device="mac"]   { --n: 8; }
[data-device="tv"]    { --n: 4; }
[data-device="ipad"]  { --n: 4; }
[data-device="phone"] { --n: 2; }

/* Each beat is 0.62 of a screen of scrolling: one trackpad swipe, in
   practice. Page Down and Space are stepped to exactly one beat by the
   script while a story is pinned, so they do not skip. */
.js .story {
  --beat: 0.5;
  height: calc((var(--n) * var(--beat) + 1) * 100svh);
}

/* Scroll snapping is what stops a gesture at the next beat. The page is
   the snap container; every beat of a story is a snap point that no
   gesture may pass, plus one where the pin lets go. The hero's two
   screens are snap points a gesture may pass, and the tail of the page is
   one snap area taller than the screen, which the spec lets the reader
   rest anywhere inside. */
html.js { scroll-snap-type: y mandatory; }

.js .hero__copy,
.js .montage { scroll-snap-align: start; }

.js .facts, .js .buy, .js .sheet { scroll-snap-align: start; }
.js .colophon { scroll-snap-align: end; }

.js .snap {
  position: absolute;
  left: 0;
  width: 1px;
  height: 1px;
  top: calc(var(--k) * var(--beat) * 100svh);
  scroll-snap-align: start;
  scroll-snap-stop: always;
  pointer-events: none;
}

.snap:nth-of-type(1) { --k: 0; }
.snap:nth-of-type(2) { --k: 1; }
.snap:nth-of-type(3) { --k: 2; }
.snap:nth-of-type(4) { --k: 3; }
.snap:nth-of-type(5) { --k: 4; }
.snap:nth-of-type(6) { --k: 5; }
.snap:nth-of-type(7) { --k: 6; }
.snap:nth-of-type(8) { --k: 7; }
.snap:nth-of-type(9) { --k: 8; }

.js .stage {
  position: sticky;
  top: 0;
  height: 100svh;
  padding-top: 4.5rem;
  padding-bottom: 1.5rem;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, auto) minmax(9.5rem, auto);
  grid-template-areas: "screen" "words";
  align-content: center;
  row-gap: 1.75rem;
}

/* Every frame in a stage gets the same explicit width, computed from the
   room available and the device's own aspect ratio, so no frame's size
   ever depends on which image file the browser chose or whether it has
   loaded yet (an unloaded lazy image and a loaded one can differ in
   natural size, and a stack of frames must not). */
[data-device="mac"]   { --ar: 1.5625; }
[data-device="tv"]    { --ar: 1.7778; }
[data-device="ipad"]  { --ar: 1.3333; }
[data-device="phone"] { --ar: 0.46; }

.js .frame {
  grid-area: screen;
  align-self: center;
  justify-self: center;
  width: min(100%, calc((100svh - 17rem) * var(--ar)));
  max-width: 100%;
  height: auto;
  opacity: 0;
  transition: opacity 0.5s ease;
}

.js .frame.is-on,
.js .frame:first-of-type { opacity: 1; }

.js .frame:not(:first-of-type) { box-shadow: none; }

.js .beat {
  grid-area: words;
  align-self: start;
  margin: 0;
  opacity: 0;
  transform: translateY(0.6rem);
  transition: opacity 0.35s ease, transform 0.35s ease;
}

.js .beat.is-on {
  opacity: 1;
  transform: none;
}



@media (min-width: 60rem) {
  .js .stage {
    max-width: 92rem;
    grid-template-columns: minmax(0, 2.3fr) minmax(15rem, 1fr);
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "screen words";
    column-gap: clamp(2rem, 5vw, 5rem);
    align-items: center;
    padding-top: 3.5rem;
    padding-bottom: 3.5rem;
  }

  .js .frame { width: min(100%, calc((100svh - 8rem) * var(--ar))); }

  .js .beat { align-self: center; }
}

@media (prefers-reduced-motion: reduce) {
  .js .frame, .js .beat { transition: none; }
}

/* ---- Facts ------------------------------------------------------------ */

.facts {
  max-width: var(--shell);
  margin: 0 auto;
  padding: clamp(4rem, 10vh, 7rem) var(--gutter);
  border-top: 1px solid var(--rule);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 2.5rem clamp(2rem, 5vw, 4rem);
}

.facts h2 {
  font-size: var(--step-1);
  margin-bottom: 0.6rem;
}

.facts p {
  color: var(--paper-soft);
  text-wrap: pretty;
}

/* ---- Buy -------------------------------------------------------------- */

.buy {
  border-top: 1px solid var(--rule);
  padding: clamp(4rem, 12vh, 8rem) var(--gutter);
  text-align: center;
  display: grid;
  gap: 1.25rem;
  justify-items: center;
}

.buy h2 { font-size: var(--step-3); }

.buy p {
  max-width: 34rem;
  color: var(--paper-soft);
  text-wrap: pretty;
}

.buy .small {
  font-size: 0.9rem;
  color: var(--paper-faint);
}

.buy .button { margin-top: 0.75rem; }

/* ---- The sheet -------------------------------------------------------- */

.sheet {
  max-width: 52rem;
  margin: 0 auto;
  padding: clamp(3rem, 8vh, 5rem) var(--gutter) clamp(4rem, 10vh, 6rem);
}

.sheet h2 {
  font-size: 0.8rem;
  font-family: var(--sans);
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--paper-faint);
  margin-bottom: 1rem;
}

.sheet dl {
  margin: 0;
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0 2rem;
  font-size: 0.95rem;
}

.sheet dt,
.sheet dd {
  margin: 0;
  padding: 0.8rem 0;
  border-top: 1px solid var(--rule);
}

.sheet dt { color: var(--paper-faint); }

.sheet dd { color: var(--paper-soft); }

.sheet dd .sep { color: var(--paper-faint); padding: 0 0.35em; }

@media (max-width: 34rem) {
  .sheet dl { grid-template-columns: 1fr; }
  .sheet dt { padding-bottom: 0.15rem; }
  .sheet dd { border-top: 0; padding-top: 0; }
}

/* ---- Footer ----------------------------------------------------------- */

.colophon {
  border-top: 1px solid var(--rule);
  padding: 2rem var(--gutter) clamp(2.5rem, 6vh, 3.5rem);
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--paper-faint);
}

.colophon > * {
  max-width: var(--shell);
  margin-inline: auto;
}

.colophon ul {
  display: flex;
  flex-wrap: wrap;
  gap: 1.35rem;
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}

.colophon a { color: var(--paper-soft); }

.colophon p { max-width: min(var(--shell), 48rem); margin: 0 auto 0.45em; }

/* ---- Print ------------------------------------------------------------ */

@media print {
  :root { --ground: #fff; --paper: #000; --paper-soft: #333; --paper-faint: #555; --rule: #999; }
  .bar, .skip { display: none; }
  .story { height: auto; }
  .stage { position: static; height: auto; display: block; }
  .frame, .beat { opacity: 1; transition: none; page-break-inside: avoid; margin-bottom: 1rem; }
  .frame { box-shadow: none; border: 1px solid #999; }
}
