/* LUZ, builder C. Styles for #postcard and #book.
   Every colour comes from the palette custom properties that core writes on :root. */

/* ------------------------------------------------------------ foundations */

.luz-sec {
  --luz-rule: rgba(128, 128, 128, .3);
  --luz-soft: rgba(128, 128, 128, .12);
  --luz-shade: rgba(10, 16, 28, .34);
  --luz-shine: rgba(255, 252, 245, .2);
  --luz-ink-72: var(--ink);
  --luz-ink-55: var(--ink);
  --luz-paper-90: var(--paper);
  --luz-serif: "Instrument Serif", Georgia, "Times New Roman", serif;
  --luz-sans: Manrope, ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --luz-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  position: relative;
  box-sizing: border-box;
  padding: clamp(72px, 9vw, 132px) clamp(18px, 5vw, 56px);
  background-color: var(--paper);
  color: var(--ink);
  font-family: var(--luz-sans);
  overflow: hidden;
}

@supports (color: color-mix(in srgb, red 50%, blue)) {
  .luz-sec {
    --luz-rule: color-mix(in srgb, var(--ink) 22%, transparent);
    --luz-soft: color-mix(in srgb, var(--ink) 8%, transparent);
    /* shade leans on the darkest palette colour and shine on the brightest,
       so light and dark palettes both read the right way round */
    --luz-shade: color-mix(in srgb, var(--sea-deep) 62%, transparent);
    --luz-shine: color-mix(in srgb, var(--sun) 26%, transparent);
    --luz-ink-72: color-mix(in srgb, var(--ink) 72%, transparent);
    /* 55 per cent of a light ink over a dark paper reads at about 6:1, but the
       same 55 per cent of a dark ink over a light paper only reaches 4:1. The
       daylight side of the palette therefore gets a firmer mix, so the small
       labels clear 4.5:1 at every hour without flattening the hierarchy. */
    --luz-ink-55: color-mix(in srgb, var(--ink) calc(55% + (1 - var(--night, 1)) * 12%), transparent);
    --luz-paper-90: color-mix(in srgb, var(--paper) 90%, transparent);
  }
}

.luz-sec *,
.luz-sec *::before,
.luz-sec *::after { box-sizing: border-box; }

.luz-wrap {
  max-width: 1180px;
  margin: 0 auto;
  width: 100%;
}

.luz-kicker {
  margin: 0 0 14px;
  font-family: var(--luz-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--luz-ink-55);
}

.luz-title {
  margin: 0 0 14px;
  font-family: var(--luz-serif);
  font-weight: 400;
  font-size: clamp(32px, 4.6vw, 58px);
  line-height: 1.04;
  letter-spacing: -.01em;
  color: var(--ink);
}

.luz-line {
  margin: 0;
  max-width: 46ch;
  font-size: clamp(14.5px, 1.15vw, 17px);
  font-weight: 300;
  line-height: 1.62;
  color: var(--luz-ink-72);
}

.luz-sr {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* ---------------------------------------------------------------- buttons */

.luz-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  min-height: 44px;
  padding: 0 20px;
  border: 1px solid var(--luz-rule);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font-family: var(--luz-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .25s ease, color .25s ease, border-color .25s ease, opacity .25s ease;
}

.luz-btn-solid {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.luz-btn:hover { border-color: var(--ink); }
.luz-btn-solid:hover { opacity: .86; }
.luz-btn:disabled { opacity: .34; cursor: default; }
.luz-btn:focus-visible,
.luz-input:focus-visible,
.luz-book-stage:focus-visible,
.luz-consent input:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.luz-btn-round {
  min-width: 44px;
  padding: 0;
  font-size: 18px;
  line-height: 1;
}

/* ------------------------------------------------------------- the fields */

.luz-field { margin: 0; display: grid; gap: 8px; position: relative; }

.luz-label {
  font-family: var(--luz-mono);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--luz-ink-55);
}

.luz-input {
  width: 100%;
  max-width: 100%;
  min-height: 46px;
  padding: 8px 2px;
  border: 0;
  border-bottom: 1px solid var(--luz-rule);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--luz-serif);
  font-size: clamp(19px, 2vw, 25px);
  line-height: 1.3;
}

.luz-input::placeholder { color: var(--luz-ink-55); opacity: .7; }
.luz-input:focus { border-bottom-color: var(--ink); }

.luz-count {
  justify-self: end;
  font-family: var(--luz-mono);
  font-size: 11px;
  letter-spacing: .1em;
  color: var(--luz-ink-55);
}

/* --------------------------------------------------------------- postcard */

.luz-pc-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: clamp(26px, 4vw, 60px);
  align-items: center;
}

.luz-pc-stage { min-width: 0; }

.luz-pc-frame {
  position: relative;
  width: 100%;
  border: 1px solid var(--luz-rule);
  background: var(--paper);
  box-shadow: 0 24px 60px -30px var(--luz-shade);
}

.luz-pc-canvas {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  max-width: 100%;
}

.luz-pc-panel {
  min-width: 0;
  display: grid;
  gap: 20px;
  align-content: start;
}

.luz-pc-panel .luz-title { margin-bottom: 0; }
.luz-pc-panel .luz-kicker { margin-bottom: 0; }

.luz-pc-actions { display: flex; flex-wrap: wrap; gap: 12px; }

.luz-share {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding-top: 18px;
  border-top: 1px solid var(--luz-soft);
}

.luz-share-label {
  font-family: var(--luz-mono);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--luz-ink-55);
  margin-right: 4px;
}

.luz-toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  z-index: 60;
  max-width: min(420px, calc(100vw - 32px));
  padding: 12px 18px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--luz-mono);
  font-size: 12px;
  letter-spacing: .08em;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 10px);
  transition: opacity .3s ease, transform .3s ease;
}

.luz-toast.is-on { opacity: 1; transform: translate(-50%, 0); }

@media (max-width: 900px) {
  .luz-pc-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------- the book */

.luz-book { background-image: radial-gradient(120% 62% at 50% 0%, var(--luz-soft), transparent 72%); }

.luz-book-wrap { display: grid; gap: clamp(26px, 3.4vw, 44px); justify-items: center; }
.luz-book-head { max-width: 620px; text-align: center; justify-self: center; }
.luz-book-head .luz-line { margin: 0 auto; }

.luz-book-stage {
  /* How much of its full size the closed book is allowed to take. book.js
     measures the real room and writes the exact value inline the moment the
     section is built, which is before the first paint, so this is only a
     backstop. It is set low enough to be safe at any width where the stage
     fills the column, and the narrow breakpoint below tightens it again. */
  --bk-fit: .775;
  position: relative;
  width: 100%;
  max-width: 760px;
  aspect-ratio: 3 / 2;
  perspective: 2200px;
  perspective-origin: 50% 44%;
  touch-action: pan-y;
  cursor: grab;
  border-radius: 6px;
  -webkit-tap-highlight-color: transparent;
}

.luz-book-stage:active { cursor: grabbing; }

/* Closed, only the right half of the block is a visible page, so the whole
   thing leans a quarter of a stage to the left to sit centred. That lean is
   what used to hang off the left edge of a phone, clipped but still there.
   Scaling about the spine keeps the composition and pulls the hidden half back
   inside. Open, the book is centred already, so it goes back to full size. */
.luz-book-3d {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(9deg) rotateY(-15deg) rotateZ(-1.1deg)
             translateX(calc(-25% * var(--bk-fit, 1))) scale(var(--bk-fit, 1));
  transition: transform .85s cubic-bezier(.22, .72, .18, 1);
}

.luz-book-stage.is-open .luz-book-3d {
  transform: rotateX(5deg) rotateY(0deg) rotateZ(0deg) translateX(0) scale(1);
}

.luz-book-shadow {
  position: absolute;
  left: 6%; right: 6%; bottom: -4%;
  height: 16%;
  background: radial-gradient(50% 50% at 50% 50%, var(--luz-shade), transparent 72%);
  filter: blur(16px);
  transform: translateZ(-40px);
  pointer-events: none;
}

/* the page block under each pile, held back from the spine so it never
   shows through the gutter */
.luz-slab {
  position: absolute;
  top: 1.2%;
  height: 97.6%;
  width: 48.5%;
  transform: translateZ(-9px);
  background: var(--luz-paper-90);
  background-image: repeating-linear-gradient(90deg, var(--luz-soft) 0 1px, transparent 1px 3px);
  box-shadow: 0 10px 24px -14px var(--luz-shade);
  pointer-events: none;
}

.luz-slab-right { left: 51.5%; }
.luz-slab-left { left: 0; opacity: 0; transition: opacity .4s ease; }
.luz-book-stage.is-open .luz-slab-left { opacity: 1; }

.luz-book-cast {
  position: absolute;
  top: 0; bottom: 0;
  width: 50%;
  z-index: 40;
  pointer-events: none;
  opacity: var(--cast, 0);
  background: linear-gradient(90deg, var(--luz-shade), transparent 62%);
}

.luz-book-cast[data-side="right"] { left: 50%; }
.luz-book-cast[data-side="left"] { left: 0; background: linear-gradient(270deg, var(--luz-shade), transparent 62%); }

.luz-leaf {
  position: absolute;
  top: 0;
  left: 50%;
  width: 50%;
  height: 100%;
  transform-origin: left center;
  transform-style: preserve-3d;
  transform: rotateY(calc(var(--a, 0) * -1deg));
}

.luz-leaf-inner {
  position: absolute;
  inset: 0;
  transform-origin: left center;
  transform-style: preserve-3d;
  transform: rotateY(calc(var(--bend, 0) * 1deg));
}

.luz-face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 0 4px 4px 0;
  box-shadow: 0 12px 30px -22px var(--luz-shade);
}

.luz-face-back { transform: rotateY(180deg); }

.luz-gloss {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: var(--gloss, 0);
  background:
    linear-gradient(90deg, var(--luz-shade), transparent 34%),
    linear-gradient(272deg, var(--luz-shine), transparent 48%);
}

/* ---------------------------------------------------------------- pages */

.luz-page {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background-color: var(--paper);
  background-repeat: no-repeat;
  background-size: 200% 100%;
  background-position: center;
}

.luz-page[data-half="left"] { background-position: left center; }
.luz-page[data-half="right"] { background-position: right center; }

.luz-page-gen {
  background-image: linear-gradient(var(--pg-ang, 172deg),
      var(--sky-top) 0%,
      var(--sky-bottom) calc(var(--pg-h, 45%) - 4%),
      var(--sea) calc(var(--pg-h, 45%) + 2%),
      var(--sea-deep) 100%);
}

.luz-page::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 40%, transparent 40%, var(--luz-shade) 130%);
  opacity: .55;
}

.luz-page::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  width: 15%;
  z-index: 2;
  pointer-events: none;
}

.luz-page[data-half="right"]::before { left: 0; background: linear-gradient(90deg, var(--luz-shade), transparent); }
.luz-page[data-half="left"]::before { right: 0; background: linear-gradient(270deg, var(--luz-shade), transparent); }

.luz-page-cap {
  position: absolute;
  left: 7%;
  right: 7%;
  bottom: 7%;
  z-index: 3;
  padding: .62em .7em .68em;
  background: var(--luz-paper-90);
  color: var(--ink);
}

.luz-page-title {
  margin: 0;
  font-family: var(--luz-serif);
  font-weight: 400;
  font-size: calc(var(--luz-pw, 300px) * .092);
  line-height: 1.05;
}

.luz-page-line {
  margin: 0;
  font-size: calc(var(--luz-pw, 300px) * .042);
  font-weight: 300;
  line-height: 1.45;
  color: var(--luz-ink-72);
}

.luz-page-meta {
  margin: .5em 0 0;
  font-family: var(--luz-mono);
  font-size: calc(var(--luz-pw, 300px) * .03);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--luz-ink-55);
}

.luz-page-cover {
  background-color: var(--ink);
  background-image: radial-gradient(80% 60% at calc(var(--sun-x, .5) * 100%) calc(var(--sun-y, .4) * 100%), var(--glow), transparent 70%);
  background-size: auto;
}

.luz-page-cover::after { opacity: .3; }

.luz-cover-sun {
  position: absolute;
  z-index: 2;
  width: calc(var(--luz-pw, 300px) * .14);
  height: calc(var(--luz-pw, 300px) * .14);
  left: calc(var(--sun-x, .5) * 74% + 13%);
  top: calc(var(--sun-y, .4) * 46% + 12%);
  border-radius: 50%;
  background: var(--sun);
  opacity: .9;
}

.luz-cover-box {
  position: absolute;
  z-index: 3;
  left: 9%;
  right: 9%;
  bottom: 9%;
}

.luz-page-cover .luz-cover-box { color: var(--paper); }
.luz-page-photo .luz-cover-box,
.luz-page-back .luz-cover-box {
  padding: .7em .8em;
  background: var(--luz-paper-90);
  color: var(--ink);
}

.luz-cover-kicker {
  margin: 0 0 .4em;
  font-family: var(--luz-mono);
  font-size: calc(var(--luz-pw, 300px) * .03);
  letter-spacing: .2em;
  text-transform: uppercase;
  opacity: .75;
}

.luz-cover-title {
  margin: 0;
  font-family: var(--luz-serif);
  font-weight: 400;
  font-size: calc(var(--luz-pw, 300px) * .3);
  line-height: .92;
  letter-spacing: .02em;
}

.luz-cover-sub {
  margin: .2em 0 0;
  font-family: var(--luz-mono);
  font-size: calc(var(--luz-pw, 300px) * .034);
  letter-spacing: .3em;
  text-transform: uppercase;
  opacity: .78;
}

.luz-page-back { background-color: var(--ink); }
.luz-page-back::after { opacity: .25; }
.luz-page-back .luz-page-line { font-size: calc(var(--luz-pw, 300px) * .04); }

/* -------------------------------------------------------------- controls */

.luz-book-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
}

.luz-book-count {
  margin: 0 0 0 6px;
  min-width: 7ch;
  font-family: var(--luz-mono);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--luz-ink-55);
}

.luz-book-hint {
  margin: 0;
  font-family: var(--luz-mono);
  font-size: 11px;
  letter-spacing: .12em;
  color: var(--luz-ink-55);
  text-align: center;
}

/* ---------------------------------------------------------- flat carousel */

.luz-book-flat {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1px solid var(--luz-soft);
  box-shadow: 0 18px 44px -30px var(--luz-shade);
}

.luz-flat-page {
  position: relative;
  overflow: hidden;
}

/* with no book to sit in, the gutter only needs a hint of a fold */
.luz-book-flat .luz-page::before { width: 9%; opacity: .38; }
.luz-book-flat .luz-page::after { opacity: .32; }

/* ------------------------------------------------------------- the waitlist */

.luz-wait {
  width: 100%;
  max-width: 620px;
  margin-top: clamp(16px, 3vw, 34px);
  padding: clamp(22px, 3vw, 38px);
  border: 1px solid var(--luz-rule);
  background: var(--luz-paper-90);
}

.luz-wait-title {
  margin: 0 0 10px;
  font-family: var(--luz-serif);
  font-weight: 400;
  font-size: clamp(23px, 2.4vw, 30px);
  line-height: 1.1;
}

.luz-wait-line {
  margin: 0 0 22px;
  font-size: 14.5px;
  font-weight: 300;
  line-height: 1.6;
  color: var(--luz-ink-72);
}

.luz-wait-form { display: grid; gap: 18px; }
.luz-wait-form .luz-input { font-size: clamp(17px, 1.6vw, 21px); }

.luz-honey {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.luz-consent {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0;
}

.luz-consent input {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  accent-color: var(--ink);
}

.luz-consent-text {
  font-size: 12.5px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--luz-ink-72);
}

.luz-error {
  margin: 0;
  min-height: 1em;
  font-family: var(--luz-mono);
  font-size: 11.5px;
  letter-spacing: .06em;
  color: var(--ink);
}

.luz-error:empty { display: none; }

.luz-error-mail {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.luz-error-mail:hover { text-decoration-thickness: 2px; }

.luz-wait-form .luz-btn { justify-self: start; }

.luz-wait-done {
  margin: 0;
  font-family: var(--luz-serif);
  font-size: clamp(19px, 2vw, 24px);
  line-height: 1.35;
  color: var(--ink);
}

/* ------------------------------------------------------------------ small */

@media (max-width: 620px) {
  .luz-sec { padding-left: 16px; padding-right: 16px; }
  .luz-book-stage { max-width: 100%; --bk-fit: .74; }
  .luz-page-line { display: none; }
  .luz-page-title { font-size: calc(var(--luz-pw, 160px) * .13); }
  .luz-page-meta { font-size: calc(var(--luz-pw, 160px) * .046); letter-spacing: .12em; }
  .luz-page-cap { left: 6%; right: 6%; bottom: 6%; }
  /* with the line hidden the right page keeps only its mark, so let the
     block shrink to it instead of running the width of the page */
  .luz-page[data-half="right"] .luz-page-cap { left: auto; }
  .luz-book-count { margin-left: 0; width: 100%; text-align: center; }
  .luz-share { gap: 8px; }
  .luz-btn { padding: 0 15px; font-size: 11px; }
}

/* ---------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  .luz-sec *,
  .luz-sec *::before,
  .luz-sec *::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
  }

  .luz-toast { transform: translate(-50%, 0); }
  .luz-book-stage { perspective: none; cursor: default; }
}
