/* BJOY — the brand guide translated to a page.
   Warm Ivory is 60 per cent of the identity, so it is the ground and it never leaves. */

/* ---------- the brand's own fonts, as supplied ---------- */
@font-face {
  font-family: "Cairo";
  src: url("/assets/fonts/cairo.otf") format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Cairo";
  src: url("/assets/fonts/cairo oblique.otf") format("opentype");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Jakarta";
  src: url("/assets/fonts/PlusJakartaSans-ExtraLight.ttf") format("truetype");
  font-weight: 200;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Jakarta";
  src: url("/assets/fonts/PlusJakartaSans-Light.ttf") format("truetype");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Jakarta";
  src: url("/assets/fonts/PlusJakartaSans-VariableFont_wght.ttf") format("truetype");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

:root {
  --ivory: #f4efe6;
  --olive: #2f3424;
  --sage: #8a9079;
  --charcoal: #2b2a27;
  --blush: #dcc4b4;
  --taupe: #bfb3a3;
  --rose-clay: #c47772;

  --ink: var(--charcoal);
  --quiet: #6d6a62;

  --display: "Cairo", Georgia, serif;
  --text: "Jakarta", "Helvetica Neue", Arial, sans-serif;

  --gut: clamp(20px, 5vw, 76px);
  --maxw: 1560px;
  --rule: rgba(43, 42, 39, 0.16);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* never smooth on html: a router reset animates as if the reader asked for it */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ivory);
  color: var(--ink);
  font-family: var(--text);
  font-weight: 300;
  font-size: clamp(16px, 1.05vw, 18px);
  line-height: 1.62;
  letter-spacing: 0.004em;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: inherit;
  text-decoration: none;
}

h1,
h2,
h3 {
  font-family: var(--display);
  font-weight: 400;
  margin: 0;
  letter-spacing: -0.012em;
  line-height: 1.04;
}

/* Guide pp31-33: heading 24 to 72pt. 72pt is 96px. */
.d1 {
  font-size: clamp(38px, 7vw, 96px);
}
.d2 {
  font-size: clamp(30px, 4.4vw, 62px);
  line-height: 1.08;
}
.d3 {
  font-size: clamp(23px, 2.2vw, 34px);
  line-height: 1.18;
}

.lede {
  font-size: clamp(18px, 1.5vw, 24px);
  font-weight: 200;
  line-height: 1.5;
  color: #4a4740;
}

.small {
  font-size: 13.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--quiet);
  font-weight: 400;
}

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding-inline: var(--gut);
}

/* ---------- corner furniture, not a bar ----------
   The references pin their navigation to the corners of the screen.
   It reads what is behind it and switches ink on its own. */
.corners {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  mix-blend-mode: normal;
}
.corners > * {
  pointer-events: auto;
}
/* Content scrolls under fixed furniture. On an ivory page an ivory fade is
   invisible and still stops a line of body copy running through the nav. */
.corners::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: clamp(74px, 9vh, 108px);
  background: linear-gradient(var(--ivory) 58%, rgba(244, 239, 230, 0));
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}
.corners.is-veiled::before {
  opacity: 1;
}
/* over a photograph there is no veil: a scrim on a picture is the picture's job.
   Over a solid dark ground the veil takes that ground's colour. */
.corners.on-dark::before {
  opacity: 0;
}
.corners.on-dark.is-veiled::before {
  background: linear-gradient(var(--olive) 56%, rgba(47, 52, 36, 0));
  opacity: 1;
}
.c-mark {
  position: absolute;
  top: clamp(20px, 2.6vw, 36px);
  left: var(--gut);
  display: block;
}
/* the wordmark is the supplied artwork, never set as live type */
.c-mark img {
  width: clamp(84px, 8.4vw, 128px);
  height: auto;
}
.c-mark .ivory {
  display: none;
}
.corners.on-dark .c-mark .olive {
  display: none;
}
.corners.on-dark .c-mark .ivory {
  display: block;
}
.c-nav {
  position: absolute;
  top: clamp(20px, 2.6vw, 38px);
  right: var(--gut);
  display: flex;
  gap: clamp(16px, 2vw, 34px);
}
.c-nav a {
  font-size: 13.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  padding-bottom: 3px;
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s;
}
.c-nav a:hover,
.c-nav a[aria-current="page"] {
  border-bottom-color: currentColor;
}

/* on a dark chapter the furniture turns ivory */
.corners.on-dark {
  color: var(--ivory);
}

/* ---------- the opening ---------- */
.opening {
  min-height: 100svh;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 18vh var(--gut) 12vh;
}
.opening h1 {
  max-width: 17ch;
  margin-inline: auto;
}
.opening .sub {
  margin-top: 22px;
  color: var(--quiet);
  font-size: clamp(15px, 1.15vw, 18px);
  letter-spacing: 0.02em;
}
.cue {
  margin-top: clamp(44px, 7vh, 90px);
  font-size: 12.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--quiet);
}
.cue::after {
  content: "";
  display: block;
  width: 1px;
  height: 52px;
  margin: 14px auto 0;
  background: linear-gradient(var(--sage), transparent);
}

/* ---------- THE APERTURE ----------
   The brand symbol is the window. Its two lobes open as the page is scrolled.
   Warm ivory is never covered: the picture is only ever seen through the mark. */
.aperture {
  position: relative;
  /* height set inline from the beat count */
}
.aperture__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--ivory);
  --ap-top: clamp(76px, 10vh, 120px);
  --ap-bottom: clamp(148px, 23vh, 232px);
}
/* The window is INSET, so warm ivory frames the picture on all four sides and
   nothing the reader must read ever sits on a photograph: the corner furniture
   lives in the band above it, the copy in the band below it. */
.aperture__window {
  position: absolute;
  top: var(--ap-top);
  bottom: var(--ap-bottom);
  left: 0;
  right: 0;
  -webkit-mask-image: var(--mask);
  mask-image: var(--mask);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--ap, 130px) auto;
  mask-size: var(--ap, 130px) auto;
  will-change: mask-size;
}
.aperture__pic {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.9s ease;
}
.aperture__pic.is-live {
  opacity: 1;
}
.aperture__pic img,
.aperture__film {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.aperture__pic img {
  transform: scale(1.06);
  animation: drift 26s ease-in-out infinite alternate;
}
/* the film carries its own motion, so it is not drifted as well */
.aperture__film {
  display: block;
}
@keyframes drift {
  from {
    transform: scale(1.06) translate3d(0, 0, 0);
  }
  to {
    transform: scale(1.15) translate3d(-1.2%, -1.4%, 0);
  }
}

/* the copy sits on the ivory, never on the product */
.aperture__beat {
  position: absolute;
  left: 50%;
  bottom: clamp(68px, 11.5vh, 124px);
  transform: translateX(-50%);
  width: min(760px, calc(100% - 2 * var(--gut)));
  text-align: center;
  font-family: var(--display);
  font-size: clamp(21px, 2.3vw, 37px);
  line-height: 1.18;
  color: var(--olive);
  opacity: 0;
  transition: opacity 0.6s ease, transform 0.6s ease;
  pointer-events: none;
}
.aperture__beat.is-live {
  opacity: 1;
}
.aperture__rail {
  position: absolute;
  left: 50%;
  bottom: clamp(26px, 5vh, 54px);
  transform: translateX(-50%);
  width: min(330px, 46vw);
  height: 1px;
  background: rgba(43, 42, 39, 0.14);
}
.aperture__rail i {
  position: absolute;
  inset: 0 auto 0 0;
  display: block;
  width: 0%;
  background: var(--olive);
}

/* ---------- reading bands: heading narrow left, prose wider right ---------- */
.band {
  padding-block: clamp(80px, 13vh, 180px);
}
.band__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.76fr) minmax(0, 1.24fr);
  gap: clamp(26px, 5vw, 96px);
  align-items: start;
}
.band__grid > p {
  margin: 0;
  max-width: 62ch;
}
.band p + p {
  margin-top: 1.1em;
}

/* ---------- the ritual index, with the product shown large beside it ---------- */
.ritual__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(24px, 4vw, 72px);
  align-items: center;
}
.ritual__stage {
  position: relative;
  aspect-ratio: 600 / 760;
  background: var(--olive);
  overflow: hidden;
}
.ritual__stage img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.04);
  transition: opacity 0.6s ease, transform 1.2s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.ritual__stage img.is-live {
  opacity: 1;
  transform: none;
}
.ritual__list {
  border-top: 1px solid var(--rule);
}
.ritual__row {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto;
  gap: clamp(12px, 1.8vw, 26px);
  align-items: baseline;
  padding-block: clamp(18px, 2.4vh, 28px);
  border-bottom: 1px solid var(--rule);
  /* the resting rows were Soft Taupe on ivory, which measures 1.8:1 and is
     too faint to read. Quiet grey reads at about 5:1 and still steps back. */
  color: var(--quiet);
  transition: color 0.38s ease;
}
.ritual__row:hover,
.ritual__row:focus-visible,
.ritual__row.is-live {
  color: var(--olive);
}
.ritual__n {
  font-family: var(--display);
  font-size: clamp(15px, 1.2vw, 19px);
}
.ritual__name {
  font-family: var(--display);
  font-size: clamp(25px, 3.2vw, 48px);
  line-height: 1.06;
}
.ritual__kind {
  font-size: clamp(14px, 1vw, 16px);
  font-weight: 200;
  text-align: right;
  white-space: nowrap;
}
/* ---------- products shown larger than life ---------- */
.pband {
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  background: var(--olive);
  color: var(--ivory);
  align-items: stretch;
}
.pband:nth-of-type(even) .pband__pic {
  order: 2;
}
.pband__pic {
  position: relative;
  overflow: hidden;
  min-height: 56svh;
}
/* cover crops the cap and the base, never the label: the bottle runs taller
   than the band, which is the point */
.pband__pic img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 46%;
  transform: scale(1.12);
}
.pband__text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(32px, 6vw, 104px);
  border-left: 1px solid rgba(244, 239, 230, 0.14);
}
.pband:nth-of-type(even) .pband__text {
  border-left: 0;
  border-right: 1px solid rgba(244, 239, 230, 0.14);
}
.pband__n {
  font-family: var(--display);
  font-size: clamp(14px, 1.1vw, 18px);
  color: rgba(244, 239, 230, 0.5);
}
.pband__text h2 {
  font-size: clamp(42px, 7vw, 118px);
  line-height: 0.98;
  margin-top: 12px;
}
.pband__kind {
  font-size: clamp(15px, 1.3vw, 21px);
  font-weight: 200;
  color: rgba(244, 239, 230, 0.74);
  margin: 14px 0 0;
}
.pband__line {
  font-size: clamp(17px, 1.5vw, 25px);
  font-weight: 200;
  margin: clamp(22px, 3vh, 38px) 0 0;
  max-width: 26ch;
}
.pband__spec {
  margin: clamp(26px, 4vh, 48px) 0 0;
  padding-top: 18px;
  border-top: 1px solid rgba(244, 239, 230, 0.2);
  display: grid;
  gap: 9px;
}
.pband__spec div {
  display: flex;
  gap: 16px;
  justify-content: space-between;
  font-size: 14.5px;
  font-weight: 200;
  color: rgba(244, 239, 230, 0.78);
}
.pband__spec dt,
.pband__spec b {
  font-weight: 400;
  color: rgba(244, 239, 230, 0.52);
  letter-spacing: 0.06em;
  font-size: 12.5px;
  text-transform: uppercase;
  flex: none;
}

/* ---------- one oversized moment, and no more ---------- */
.statement {
  padding-block: clamp(110px, 20vh, 260px);
  text-align: center;
}
.statement p {
  font-family: var(--display);
  font-size: clamp(34px, 6.4vw, 104px);
  line-height: 1.02;
  letter-spacing: -0.016em;
  margin: 0 auto;
  max-width: 15ch;
  color: var(--olive);
}

/* ---------- the balance, drawn at its real proportion ---------- */
.balance {
  display: flex;
  height: clamp(190px, 34vh, 360px);
  width: 100%;
  overflow: hidden;
  border-block: 1px solid var(--rule);
}
.balance__part {
  position: relative;
  display: flex;
  align-items: flex-end;
  padding: clamp(14px, 1.8vw, 26px);
  min-width: 0;
  overflow: hidden;
}
.balance__part + .balance__part {
  border-left: 1px solid rgba(43, 42, 39, 0.12);
}
.balance__part b {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(16px, 1.6vw, 26px);
  display: block;
}
.balance__part span {
  display: block;
  font-size: 12.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.8;
  margin-top: 2px;
}

/* ---------- products ---------- */
.pgrid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 28px);
}
@media (max-width: 1240px) {
  .pgrid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@media (max-width: 760px) {
  .pgrid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 460px) {
  .pgrid {
    grid-template-columns: minmax(0, 1fr);
  }
}
.pcard {
  background: var(--olive);
  color: var(--ivory);
  display: flex;
  flex-direction: column;
}
.pcard__pic {
  aspect-ratio: 600 / 980;
  overflow: hidden;
}
.pcard__pic img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.8s ease;
}
.pcard:hover .pcard__pic img {
  transform: scale(1.035);
}
.pcard__body {
  padding: clamp(18px, 1.8vw, 28px);
  border-top: 1px solid rgba(244, 239, 230, 0.16);
  display: flex;
  flex-direction: column;
  flex: 1;
}
/* push the LAST element down so the five meta rows share a line,
   never push the heading */
.pcard__body .meta {
  margin-top: auto;
}
.pcard__body h3 {
  font-size: clamp(21px, 1.9vw, 29px);
}
.pcard__body .kind {
  font-size: 14px;
  font-weight: 200;
  color: rgba(244, 239, 230, 0.76);
  margin-top: 3px;
}
.pcard__body .meta {
  margin-top: 15px;
  padding-top: 13px;
  border-top: 1px solid rgba(244, 239, 230, 0.14);
  font-size: 13px;
  letter-spacing: 0.055em;
  color: rgba(244, 239, 230, 0.66);
  display: flex;
  justify-content: space-between;
  gap: 14px;
}

/* ---------- ingredients ---------- */
.ing {
  border-top: 1px solid var(--rule);
}
.ing__row {
  display: grid;
  grid-template-columns: minmax(0, 0.5fr) minmax(0, 1fr) minmax(0, 0.55fr);
  gap: clamp(16px, 3vw, 54px);
  padding-block: clamp(20px, 2.4vh, 30px);
  border-bottom: 1px solid var(--rule);
  align-items: baseline;
}
.ing__name {
  font-family: var(--display);
  font-size: clamp(22px, 2.4vw, 36px);
  line-height: 1.1;
}
.ing__note {
  font-weight: 200;
  margin: 0;
}
.ing__in {
  font-size: 13px;
  letter-spacing: 0.05em;
  color: var(--quiet);
}

/* ---------- a full picture, contained, never cropped by the page ---------- */
.plate {
  position: relative;
  height: clamp(320px, 62vh, 680px);
  overflow: hidden;
}
.plate img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Type on a photograph gets a scrim that is solid where the copy sits and gone
   where the picture is. Never a global darken, and never a colour change. */
.plate::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 68%;
  background: linear-gradient(
    to top,
    rgba(43, 42, 39, 0.76),
    rgba(43, 42, 39, 0.42) 34%,
    rgba(43, 42, 39, 0) 100%
  );
  pointer-events: none;
}
.plate__line {
  position: absolute;
  z-index: 2;
  left: var(--gut);
  right: var(--gut);
  bottom: clamp(22px, 4vh, 44px);
  color: var(--ivory);
  font-family: var(--display);
  font-size: clamp(22px, 2.6vw, 42px);
  max-width: 18ch;
  line-height: 1.1;
}

/* ---------- footer, composed ---------- */
.foot {
  background: var(--olive);
  color: var(--ivory);
  /* top padding clears the fixed corner mark, so the two never collide */
  padding-block: clamp(104px, 14vh, 150px) clamp(24px, 3vh, 40px);
  margin-top: clamp(60px, 10vh, 140px);
}
.foot__mark {
  width: clamp(190px, 26vw, 400px);
  height: auto;
}
.foot__say {
  font-family: var(--display);
  font-size: clamp(19px, 2vw, 30px);
  margin-top: 18px;
  color: rgba(244, 239, 230, 0.88);
}
.foot__cols {
  margin-top: clamp(40px, 7vh, 84px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr));
  gap: clamp(20px, 3vw, 40px);
  padding-top: clamp(22px, 3vh, 34px);
  border-top: 1px solid rgba(244, 239, 230, 0.2);
}
.foot__cols h4 {
  margin: 0 0 11px;
  font-size: 12.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 400;
  color: rgba(244, 239, 230, 0.56);
}
.foot__cols a,
.foot__cols p {
  display: block;
  margin: 0 0 7px;
  font-size: 14.5px;
  font-weight: 200;
  color: rgba(244, 239, 230, 0.92);
}
.foot__cols a:hover {
  color: #fff;
}
.foot__base {
  margin-top: clamp(34px, 5vh, 60px);
  padding-top: 18px;
  border-top: 1px solid rgba(244, 239, 230, 0.2);
  display: flex;
  flex-wrap: wrap;
  gap: 12px 26px;
  justify-content: space-between;
  font-size: 12.5px;
  color: rgba(244, 239, 230, 0.58);
}

/* ---------- reveal on enter ----------
   Only hidden once the script has set .js on the document, so a failed script
   leaves a readable page rather than an empty one. */
.js .rv {
  opacity: 0;
  transform: translateY(16px);
  filter: blur(5px);
}
.js .rv.is-in {
  opacity: 1;
  transform: none;
  filter: none;
  transition: opacity 0.8s cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 0.8s cubic-bezier(0.22, 0.61, 0.36, 1), filter 0.8s ease;
}
.js .rv-stagger > * {
  opacity: 0;
  transform: translateY(14px);
}
.js .rv-stagger.is-in > * {
  opacity: 1;
  transform: none;
  transition: opacity 0.7s ease calc(var(--i, 0) * 80ms),
    transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) calc(var(--i, 0) * 80ms);
}

/* ---------- phones ---------- */
@media (max-width: 900px) {
  .band__grid {
    grid-template-columns: 1fr;
    gap: 18px;
  }
  .ritual__grid {
    grid-template-columns: 1fr;
    gap: 26px;
  }
  .ritual__stage {
    order: -1;
    aspect-ratio: 4 / 3;
  }
  .ritual__row {
    grid-template-columns: 34px minmax(0, 1fr);
    gap: 14px;
  }
  .ritual__kind {
    display: none;
  }
  .pband {
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .pband__pic {
    aspect-ratio: 4 / 3;
    min-height: 0;
  }
  .pband:nth-of-type(even) .pband__pic {
    order: 0;
  }
  .pband__text {
    border-left: 0 !important;
    border-right: 0 !important;
    padding-block: clamp(30px, 6vh, 56px);
  }
  .ing__row {
    grid-template-columns: 1fr;
    gap: 7px;
  }
  .balance {
    flex-direction: column;
    height: auto;
  }
  .balance__part {
    min-height: 76px;
  }
}

@media (max-width: 640px) {
  .c-mark span {
    display: none;
  }
  .c-nav {
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--ivory);
    border-top: 1px solid var(--rule);
    justify-content: space-between;
    padding: 11px var(--gut);
    overflow-x: auto;
    scrollbar-width: none;
    color: var(--ink);
  }
  .c-nav::-webkit-scrollbar {
    display: none;
  }
  .c-nav a {
    white-space: nowrap;
    font-size: 12.5px;
  }
  .corners.on-dark .c-nav {
    color: var(--ink);
  }
  body {
    padding-bottom: 46px;
  }
  .aperture__beat {
    bottom: clamp(92px, 17vh, 150px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .aperture__pic img {
    animation: none;
    transform: scale(1.06);
  }
  .js .rv,
  .js .rv-stagger > * {
    opacity: 1;
    transform: none;
    filter: none;
  }
  * {
    transition-duration: 0.01ms !important;
  }
}

/* ============================================================
   THE GRID: the brand's own structural device.
   The guide measures the mark in hairline square cells, lays its
   contents out as square cells, and builds its icons on a 32x32
   grid. That grammar is the brand's, so it outranks the house
   rule against decorative rules.
   ============================================================ */
.gridlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(to right, var(--rule) 1px, transparent 1px),
    linear-gradient(to bottom, var(--rule) 1px, transparent 1px);
  background-size: var(--cell, 96px) var(--cell, 96px);
  opacity: 0.55;
}
.gridlines--light {
  background-image: linear-gradient(to right, rgba(244, 239, 230, 0.16) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(244, 239, 230, 0.16) 1px, transparent 1px);
}

/* ---------- the preloader: the mark assembles on its own grid ---------- */
.boot {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--ivory);
  display: grid;
  place-items: center;
  transition: opacity 0.7s ease, visibility 0.7s;
}
.js .boot[data-done] {
  opacity: 0;
  visibility: hidden;
}
.boot__stage {
  position: relative;
  width: min(360px, 62vw);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
}
.boot__grid {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: repeat(6, 1fr);
}
.boot__grid i {
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  opacity: 0;
  transform: scale(0.82);
}
.js .boot__grid i {
  animation: cell 0.5s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
  animation-delay: calc(var(--d) * 22ms);
}
@keyframes cell {
  to {
    opacity: 1;
    transform: none;
  }
}
/* the clear-space cells light in the brand's own sage, as the guide draws them */
.js .boot__grid i.lit {
  background: rgba(138, 144, 121, 0.22);
}
.boot__mark {
  position: relative;
  width: 58%;
  color: var(--olive);
  opacity: 0;
}
.js .boot__mark {
  animation: markin 0.9s cubic-bezier(0.22, 0.61, 0.36, 1) 0.62s forwards;
}
@keyframes markin {
  from {
    opacity: 0;
    transform: scale(0.9);
    filter: blur(6px);
  }
  to {
    opacity: 1;
    transform: none;
    filter: none;
  }
}
.boot__bar {
  position: absolute;
  left: 50%;
  bottom: -46px;
  transform: translateX(-50%);
  width: 150px;
  height: 1px;
  background: var(--rule);
}
.boot__bar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: var(--olive);
  transition: width 0.3s linear;
}

/* ---------- the hero film ---------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: end;
  overflow: hidden;
  background: var(--charcoal);
}
.hero__film,
.hero__film video,
.hero__film img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
      to top,
      rgba(43, 42, 39, 0.74) 0%,
      rgba(43, 42, 39, 0.26) 42%,
      rgba(43, 42, 39, 0) 68%
    ),
    linear-gradient(to right, rgba(43, 42, 39, 0.4), rgba(43, 42, 39, 0) 56%);
  pointer-events: none;
}
.hero__body {
  position: relative;
  z-index: 2;
  padding: var(--gut);
  padding-bottom: clamp(56px, 12vh, 130px);
  max-width: 1200px;
}
.hero__body h1 {
  color: var(--ivory);
  max-width: 15ch;
}
.hero__body p {
  color: rgba(244, 239, 230, 0.86);
  font-size: clamp(16px, 1.3vw, 21px);
  font-weight: 200;
  margin: 18px 0 0;
  max-width: 44ch;
}

/* ---------- products, travelled through sideways ---------- */
.travel {
  position: relative;
}
.travel__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--olive);
  color: var(--ivory);
}
.travel__track {
  display: flex;
  height: 100%;
  will-change: transform;
}
.travel__item {
  flex: 0 0 100vw;
  height: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
}
.travel__pic {
  position: relative;
  overflow: hidden;
}
.travel__pic img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.04);
}
.travel__text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(30px, 5vw, 92px);
  border-left: 1px solid rgba(244, 239, 230, 0.14);
}
.travel__rail {
  position: absolute;
  left: var(--gut);
  right: var(--gut);
  bottom: clamp(20px, 3.4vh, 38px);
  display: flex;
  gap: 10px;
  z-index: 3;
}
.travel__rail b {
  flex: 1;
  height: 2px;
  background: rgba(244, 239, 230, 0.22);
  position: relative;
  overflow: hidden;
}
.travel__rail b i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: var(--ivory);
}

/* ---------- the palette, applied rather than swatched ---------- */
.applied {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(236px, 100%), 1fr));
  border-top: 1px solid var(--rule);
  border-left: 1px solid var(--rule);
}
.applied__cell {
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  position: relative;
  display: flex;
  flex-direction: column;
}
.applied__swatch {
  aspect-ratio: 4 / 3;
  position: relative;
  overflow: hidden;
}
.applied__swatch img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.applied__chip {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 46%;
  height: 46%;
}
.applied__meta {
  padding: 16px 18px 20px;
}
.applied__meta b {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(16px, 1.3vw, 21px);
  display: block;
}
.applied__meta span {
  display: block;
  font-size: 12.5px;
  letter-spacing: 0.07em;
  color: var(--quiet);
  margin-top: 5px;
}
.applied__meta em {
  display: block;
  font-style: normal;
  font-size: 13.5px;
  font-weight: 200;
  margin-top: 9px;
  color: #4a4740;
}

/* ---------- the footer mark answers the cursor ---------- */
.foot__mark {
  width: clamp(190px, 26vw, 400px);
  height: auto;
  display: block;
  color: var(--ivory);
}
.foot__wings {
  display: block;
  width: clamp(120px, 15vw, 210px);
  margin-bottom: clamp(18px, 3vh, 34px);
  color: var(--ivory);
  overflow: visible;
}
.foot__wings .lobe {
  transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
  transform-box: fill-box;
  transform-origin: center;
}

/* the dive needs the window edge to edge, so the film can take the whole page */
.aperture__stage {
  --ap-top: 0px;
  --ap-bottom: 0px;
}
.aperture__pic img,
.aperture__film {
  transform: scale(var(--dive, 1.2));
  transform-origin: center;
}
.aperture__pic img {
  animation: none;
}
/* the copy arrives only once the film has taken the screen, on its own scrim */
.aperture__scrim {
  position: absolute;
  inset: auto 0 0 0;
  height: 46%;
  background: linear-gradient(to top, rgba(43, 42, 39, 0.72), rgba(43, 42, 39, 0) 100%);
  opacity: 0;
  transition: opacity 0.5s ease;
  pointer-events: none;
  z-index: 2;
}
.aperture__scrim.is-live {
  opacity: 1;
}
.aperture__beat {
  color: var(--ivory);
  z-index: 3;
  bottom: clamp(74px, 13vh, 150px);
}
.aperture__rail {
  z-index: 3;
  background: rgba(244, 239, 230, 0.26);
}
.aperture__rail i {
  background: var(--ivory);
}

/* ============================================================
   THE DIVE, done properly.
   Scaling a mask can never reach full bleed: the gap between the
   two lobes is a fixed FRACTION of the mask, so it grows with it
   and a seam of ivory never leaves the screen. So the film is
   never masked. Instead an ivory cover sits ON it with a
   mark-shaped hole cut out, the hole grows, and then the cover
   fades out entirely: the reader passes through the mark and the
   film is the whole page, with nothing cutting it.
   ============================================================ */
.aperture__window {
  -webkit-mask-image: none !important;
  mask-image: none !important;
}
.aperture__cover {
  position: absolute;
  inset: 0;
  background: var(--ivory);
  -webkit-mask-image: url("/brand/aperture-mask.png"), linear-gradient(#000, #000);
  mask-image: url("/brand/aperture-mask.png"), linear-gradient(#000, #000);
  -webkit-mask-repeat: no-repeat, no-repeat;
  mask-repeat: no-repeat, no-repeat;
  -webkit-mask-position: center, center;
  mask-position: center, center;
  -webkit-mask-size: var(--ap, 240px) auto, 100% 100%;
  mask-size: var(--ap, 240px) auto, 100% 100%;
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: var(--cover, 1);
  z-index: 1;
  pointer-events: none;
  will-change: mask-size, opacity;
}

/* the veil must mask a 104px statement scrolling under the bar, so it is
   solid for most of its height and only softens at its foot */
.corners::before {
  height: clamp(88px, 10.5vh, 120px);
  background: linear-gradient(var(--ivory) 74%, rgba(244, 239, 230, 0));
}
.corners.on-dark.is-veiled::before {
  background: linear-gradient(var(--olive) 74%, rgba(47, 52, 36, 0));
}

/* The veil must actually hide what passes under the bar. A long gradient left
   the lower half of a 104px statement legible through it, so the ground is
   solid for nearly its whole height and softens only at the very foot. */
.corners::before {
  height: clamp(94px, 11vh, 126px);
  background: linear-gradient(var(--ivory) 0, var(--ivory) 88%, rgba(244, 239, 230, 0) 100%);
}
.corners.on-dark.is-veiled::before {
  background: linear-gradient(var(--olive) 0, var(--olive) 88%, rgba(47, 52, 36, 0) 100%);
}

/* the applied palette reads better upright, and each cell needs room */
.applied__swatch {
  aspect-ratio: 3 / 4;
}
.applied__chip {
  width: 100%;
  height: 34%;
}
.applied__meta {
  padding: 18px 20px 24px;
}

/* each bottle is focused on its own measured centre, not on a shared guess */
.travel__pic img {
  object-position: center var(--focus, 50%);
}
.ritual__stage img {
  object-position: center var(--focus, 50%);
}

/* Over a PICTURE the furniture cannot be fixed by changing its colour, because
   a film runs from dark leaf to pale petal within one chapter. It gets a scrim,
   which is the same answer the copy gets. */
.corners.on-picture::before {
  background: linear-gradient(rgba(43, 42, 39, 0.52), rgba(43, 42, 39, 0.22) 62%, rgba(43, 42, 39, 0));
  opacity: 1;
  height: clamp(104px, 13vh, 150px);
}

/* ============================================================
   THE FOOTER MARK
   Technique taken from Hover Reveal on 21st.dev (a soft circle
   that follows the pointer over a second layer) and rebuilt in
   plain CSS, because this page already spends its frame budget
   on film and a React motion library to light a logo costs more
   than every film on it.
   Here the second layer is the brand's own botanical picture,
   seen THROUGH the wordmark: two masks intersected, the mark
   and the circle.
   ============================================================ */
.footmark {
  position: relative;
  display: block;
  width: clamp(240px, 34vw, 520px);
  aspect-ratio: 966.8 / 374.4;
  isolation: isolate;
}
.footmark__base,
.footmark__reveal {
  position: absolute;
  inset: 0;
}
.footmark__base {
  background: var(--ivory);
  -webkit-mask-image: url("/brand/lockup-mask.svg");
  mask-image: url("/brand/lockup-mask.svg");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  transition: opacity 0.4s ease;
}
.footmark__reveal {
  background-image: var(--reveal-pic);
  background-size: cover;
  background-position: center 42%;
  -webkit-mask-image: url("/brand/lockup-mask.svg"),
    radial-gradient(circle var(--fx-r, 0px) at var(--fx-x, 50%) var(--fx-y, 50%), #000 58%, transparent 100%);
  mask-image: url("/brand/lockup-mask.svg"),
    radial-gradient(circle var(--fx-r, 0px) at var(--fx-x, 50%) var(--fx-y, 50%), #000 58%, transparent 100%);
  -webkit-mask-repeat: no-repeat, no-repeat;
  mask-repeat: no-repeat, no-repeat;
  -webkit-mask-position: center, 0 0;
  mask-position: center, 0 0;
  -webkit-mask-size: contain, 100% 100%;
  mask-size: contain, 100% 100%;
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
  pointer-events: none;
}
/* the mark softens a touch while the picture blooms through it */
.footmark[data-live] .footmark__base {
  opacity: 0.44;
  filter: blur(1.4px);
}
@media (prefers-reduced-motion: reduce) {
  .footmark__reveal {
    display: none;
  }
  .footmark[data-live] .footmark__base {
    opacity: 1;
    filter: none;
  }
}

/* ============================================================
   THE RANGE, STEPPED THROUGH BY SCROLLING
   The index read as a hover toy because all five rows sat on one
   screen. Pinned, with a viewport of scroll per product, the
   reader actually arrives at each one.
   ============================================================ */
.seq {
  position: relative;
}
.seq__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--ivory);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
}
.seq__pic {
  position: relative;
  height: 78svh;
  margin-left: var(--gut);
  background: var(--olive);
  overflow: hidden;
}
.seq__pic img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center var(--focus, 50%);
  opacity: 0;
  transform: scale(1.05);
  transition: opacity 0.65s ease, transform 1.1s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.seq__pic img.is-live {
  opacity: 1;
  transform: none;
}
.seq__side {
  padding: 0 var(--gut) 0 clamp(26px, 4vw, 72px);
}
.seq__slide {
  display: none;
}
.seq__slide.is-live {
  display: block;
  animation: seqin 0.6s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
@keyframes seqin {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
}
.seq__n {
  font-family: var(--display);
  font-size: clamp(14px, 1.1vw, 18px);
  color: var(--quiet);
}
.seq__slide h3 {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(34px, 4.6vw, 72px);
  line-height: 1.02;
  margin: 10px 0 0;
  color: var(--olive);
}
.seq__kind {
  font-size: clamp(14px, 1.2vw, 19px);
  font-weight: 200;
  color: var(--quiet);
  margin: 10px 0 0;
}
.seq__line {
  font-size: clamp(16px, 1.4vw, 23px);
  font-weight: 200;
  margin: clamp(16px, 2.4vh, 30px) 0 0;
  max-width: 26ch;
}
.seq__spec {
  margin: clamp(20px, 3vh, 36px) 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--rule);
  display: grid;
  gap: 8px;
  max-width: 34ch;
}
.seq__spec div {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 14px;
  font-weight: 200;
}
.seq__spec b {
  font-weight: 400;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--quiet);
}
.seq__rail {
  position: absolute;
  left: var(--gut);
  bottom: clamp(18px, 3vh, 34px);
  display: flex;
  gap: 8px;
}
.seq__rail b {
  width: 40px;
  height: 2px;
  background: rgba(43, 42, 39, 0.16);
  position: relative;
  overflow: hidden;
}
.seq__rail b i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: var(--olive);
}

/* ============================================================
   THE COLOUR WORLD
   No hex, no percentages. Each colour is shown as the world it
   belongs to: a picture it lives in, the colour as a field, and
   what it is for in plain words.
   ============================================================ */
.world {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.world__cell {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
}
.world__cell img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.2s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.world__cell:hover img {
  transform: scale(1.04);
}
.world__field {
  position: absolute;
  inset: auto 0 0 0;
  height: 42%;
  background: var(--tone);
  transition: height 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.world__cell:hover .world__field {
  height: 58%;
}
.world__say {
  position: relative;
  padding: clamp(18px, 2.2vw, 34px);
  color: var(--tone-ink);
}
.world__say b {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(19px, 1.9vw, 30px);
  line-height: 1.05;
}
.world__say span {
  display: block;
  font-size: clamp(13px, 1vw, 15px);
  font-weight: 200;
  margin-top: 8px;
  max-width: 24ch;
  opacity: 0.86;
}

@media (max-width: 900px) {
  .seq__stage {
    grid-template-columns: 1fr;
    align-content: center;
    gap: 18px;
  }
  .seq__pic {
    height: 38svh;
    margin: 0 var(--gut);
  }
  .seq__side {
    padding: 0 var(--gut);
  }
  .seq__spec {
    display: none;
  }
  .world {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 560px) {
  .world {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* the colour carries its own name; the sentence sits on the page ground,
   because sage cannot carry small text at any ink (measured 4.34:1) */
.world__cell {
  display: block;
  aspect-ratio: auto;
  position: relative;
  overflow: visible;
}
.world__pic {
  display: block;
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
}
.world__pic img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.2s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.world__cell:hover .world__pic img {
  transform: scale(1.04);
}
.world__field {
  position: absolute;
  left: 0;
  right: 0;
  top: 58%;
  bottom: auto;
  height: auto;
  background: var(--tone);
  color: var(--tone-ink);
  display: flex;
  align-items: flex-end;
  padding: clamp(16px, 2vw, 30px);
  min-height: 42%;
  transition: top 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.world__cell:hover .world__field {
  top: 44%;
}
.world__field b {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(20px, 2vw, 32px);
  line-height: 1.04;
}
.world__cell figcaption {
  padding: 16px clamp(16px, 2vw, 30px) clamp(26px, 3vw, 40px);
  font-size: 14.5px;
  font-weight: 200;
  color: #4a4740;
  max-width: 30ch;
}
.world {
  gap: 0;
}

/* ============================================================
   THE DIVE, SECOND PASS
   When the mark is small it must BE the mark: olive, solid, on
   ivory. It only becomes a window as it opens. So a solid olive
   layer in the symbol's own shape sits exactly in the cover's
   hole and fades out as the hole grows, and fades back in as it
   closes. Scaling a hole alone never showed the brand colour at
   all.
   ============================================================ */
.aperture__mark {
  position: absolute;
  inset: 0;
  background: var(--olive);
  -webkit-mask-image: url("/brand/aperture-mask.png");
  mask-image: url("/brand/aperture-mask.png");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: var(--ap, 240px) auto;
  mask-size: var(--ap, 240px) auto;
  opacity: var(--markop, 1);
  z-index: 1;
  pointer-events: none;
  will-change: mask-size, opacity;
}
.aperture__cover {
  z-index: 2;
}
.aperture__scrim {
  z-index: 3;
}
.aperture__beat,
.aperture__rail {
  z-index: 4;
}

/* the stills breathe: the dive scale rides on the frame, the drift on the
   picture, so the two do not fight over one transform */
.aperture__pic {
  transform: scale(var(--dive, 1.2));
  transform-origin: center;
}
.aperture__pic img,
.aperture__film {
  transform: none;
}
.aperture__pic img {
  animation: breathe 22s ease-in-out infinite alternate;
}
@keyframes breathe {
  from {
    transform: scale(1.02) translate3d(0, 0, 0);
  }
  to {
    transform: scale(1.1) translate3d(-1.1%, -1.3%, 0);
  }
}
/* the first thing inside the mark arrives with a small pop, so going in
   lands rather than crossfades */
.aperture__pic.is-live.pop {
  animation: pop 0.72s cubic-bezier(0.18, 0.86, 0.3, 1) both;
}
@keyframes pop {
  0% {
    transform: scale(calc(var(--dive, 1.2) * 1.12));
    opacity: 0;
  }
  38% {
    opacity: 1;
  }
  100% {
    transform: scale(var(--dive, 1.2));
    opacity: 1;
  }
}
@media (prefers-reduced-motion: reduce) {
  .aperture__pic img {
    animation: none;
  }
  .aperture__pic.is-live.pop {
    animation: none;
  }
}

/* ============================================================
   THE PRELOADER IS THE STUDIO'S OWN LOGO ANIMATION
   Rendered out of their After Effects project (Animation A Reel,
   1080x1920, 60fps, work area 4.37s) on its own ground, which
   measures #2e3523, the brand's Olive Green. So the loading
   screen takes that ground and the film sits on it whole.
   ============================================================ */
.boot {
  background: #2e3523;
}
.boot__film {
  /* cropped to the lockup band, so it reads large rather than as a
     small mark in the middle of a tall frame */
  width: min(760px, 78vw);
  height: auto;
  display: block;
}
.boot .boot__stage {
  width: auto;
  aspect-ratio: auto;
}
.boot__bar {
  bottom: -40px;
  background: rgba(244, 239, 230, 0.2);
}
.boot__bar i {
  background: rgba(244, 239, 230, 0.9);
}

/* ============================================================
   THE RANGE: A FULL SCREEN VIEW OF THE PRODUCT, TEXT AT THE RIGHT
   ============================================================ */
.seq__stage {
  display: block;
  background: var(--olive);
  color: var(--ivory);
}
.seq__pic {
  position: absolute;
  inset: 0;
  height: auto;
  margin: 0;
  background: var(--olive);
}
.seq__pic img {
  /* the whole bottle, full height, standing in the left of the screen */
  object-fit: contain;
  object-position: 26% center;
  padding: clamp(18px, 4vh, 54px) 0;
}
.seq__side {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: min(46%, 640px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(28px, 5vw, 86px) var(--gut) clamp(28px, 5vw, 86px) 0;
}
.seq__n {
  color: rgba(244, 239, 230, 0.56);
}
.seq__slide h3 {
  color: var(--ivory);
}
.seq__kind {
  color: rgba(244, 239, 230, 0.76);
}
.seq__line {
  color: rgba(244, 239, 230, 0.92);
}
.seq__spec {
  border-top-color: rgba(244, 239, 230, 0.22);
}
.seq__spec div {
  color: rgba(244, 239, 230, 0.82);
}
.seq__spec b {
  color: rgba(244, 239, 230, 0.52);
}
.seq__rail b {
  background: rgba(244, 239, 230, 0.22);
}
.seq__rail b i {
  background: var(--ivory);
}

/* ============================================================
   THE FOOTER MARK SITS LAST, AND LARGE
   ============================================================ */
.foot__cols {
  margin-top: clamp(30px, 5vh, 62px);
}
.footmark {
  width: min(92%, 1100px);
  margin: clamp(46px, 8vh, 104px) auto 0;
}

@media (max-width: 900px) {
  .seq__pic img {
    object-position: center 38%;
    padding: clamp(14px, 3vh, 30px) 0 42%;
  }
  .seq__side {
    width: 100%;
    top: auto;
    bottom: 0;
    height: 46%;
    justify-content: flex-end;
    padding: 0 var(--gut) clamp(42px, 8vh, 70px);
    background: linear-gradient(to top, var(--olive) 62%, rgba(47, 52, 36, 0));
  }
}

/* ============================================================
   THE STATEMENT LIGHTS AS YOU SCROLL THROUGH IT
   The words start quiet and take the brand olive one after
   another as the section passes, so the line is read rather
   than merely seen.
   ============================================================ */
.statement[data-fill] p span {
  color: var(--taupe);
  transition: color 0.45s ease, opacity 0.45s ease;
  opacity: 0.55;
}
.statement[data-fill] p span.lit {
  color: var(--olive);
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .statement[data-fill] p span {
    color: var(--olive);
    opacity: 1;
  }
}

/* the products are cut out now, so they sit on the page's own ground and
   no tile rectangle can show a slightly different olive, and nothing can
   be cut by a tile edge */
.seq__pic {
  background: transparent;
}
.travel__pic {
  background: transparent;
}
.travel__pic img {
  object-fit: contain;
  object-position: center;
  transform: none;
  padding: clamp(16px, 4vh, 48px) 0;
}

/* the picture inside the footer mark reads clearly: a brighter crop, lifted,
   so the leaf is legible through the letterforms rather than a dark smudge */
.footmark__reveal {
  background-size: 150% auto;
  background-position: center 40%;
  filter: saturate(1.12) brightness(1.5) contrast(1.06);
}

/* the product keeps to its own half: the hand cream jar is wide and ran under
   the heading when the picture box spanned the whole screen */
.seq__pic {
  right: 44%;
  left: 0;
}
.seq__pic img {
  object-position: center center;
  padding: clamp(20px, 5vh, 64px) clamp(10px, 2vw, 30px);
}
@media (max-width: 900px) {
  .seq__pic {
    right: 0;
  }
}

/* the resting words of a statement were Soft Taupe on ivory, which measures
   1.8:1 and cannot be read at all; quiet grey reads at about 5:1 and still
   steps back from the words already lit */
.statement[data-fill] p span {
  color: var(--quiet);
  opacity: 0.72;
}

/* The embossed mark sat under the colour field and was cut by it. Lift the
   subject into the visible part of the cell and let the field start lower. */
.world__field {
  top: 64%;
  min-height: 36%;
}
.world__cell:hover .world__field {
  top: 54%;
}
.world__pic img {
  object-position: center 34%;
}
/* the name must clear the small-text floor at every width, because sage
   carries large text at 4.34:1 but cannot carry small text at any ink */
.world__field b {
  font-size: clamp(24px, 2vw, 32px);
}

/* ============================================================
   THE PRODUCTS, SMALLER
   At full panel height the hand cream jar filled the screen and
   crowded its own text. The bottle now sits at a measured share
   of the viewport, centred in its half, with real air round it.
   ============================================================ */
.seq__pic {
  right: 46%;
  display: grid;
  place-items: center;
}
.seq__pic img {
  position: relative;
  inset: auto;
  width: auto;
  max-width: 78%;
  height: auto;
  max-height: 62svh;
  padding: 0;
  object-fit: contain;
}
.seq__side {
  width: min(50%, 660px);
}

/* the travel gallery takes the same measure */
.travel__pic {
  display: grid;
  place-items: center;
}
.travel__pic img {
  position: relative;
  inset: auto;
  width: auto;
  max-width: 74%;
  height: auto;
  max-height: 64svh;
  padding: 0;
}

@media (max-width: 900px) {
  .seq__pic img {
    max-height: 34svh;
    max-width: 62%;
  }
  .travel__pic img {
    max-height: 36svh;
  }
}

/* ============================================================
   THE FOOTER MARK CATCHES LIGHT
   A photograph seen through letterforms is never read as a
   photograph: at this size it is a patch of colour. The brand's
   own stationery is EMBOSSED, so the mark behaves like a raked
   surface instead: a warm highlight follows the pointer across
   the letterforms, with a cool edge trailing it, and the whole
   mark lifts a little. No picture, nothing to load.
   ============================================================ */
.footmark__reveal {
  background-image: radial-gradient(
      circle var(--fx-r, 0px) at var(--fx-x, 50%) var(--fx-y, 50%),
      #ffffff 0%,
      #fbf6ea 26%,
      #e7e0cf 52%,
      rgba(231, 224, 207, 0) 78%
    ),
    radial-gradient(
      circle calc(var(--fx-r, 0px) * 1.5) at calc(var(--fx-x, 50%) + 26px) calc(var(--fx-y, 50%) + 18px),
      rgba(138, 144, 121, 0.55) 0%,
      rgba(138, 144, 121, 0) 70%
    );
  background-size: auto;
  background-position: 0 0;
  filter: none;
  -webkit-mask-image: url("/brand/lockup-mask.svg");
  mask-image: url("/brand/lockup-mask.svg");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-composite: source-over;
  mask-composite: add;
}
.footmark[data-live] .footmark__base {
  opacity: 1;
  filter: none;
  background: rgba(244, 239, 230, 0.76);
}
.footmark {
  transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.footmark[data-live] {
  transform: translateY(-3px);
}

/* ============================================================
   THE FILM RUNS INSIDE THE MARK
   A still seen through letterforms reads as a patch of colour.
   The same water-on-leaf film that the dive uses, masked to the
   lockup, reads as a picture because it moves, and it ties the
   footer back to the chapter above it. The light sweep then
   rakes across the top of it with the pointer.
   ============================================================ */
.footmark__film {
  position: absolute;
  inset: 0;
  -webkit-mask-image: url("/brand/lockup-mask.svg");
  mask-image: url("/brand/lockup-mask.svg");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  overflow: hidden;
}
.footmark__film video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* lifted so the leaf reads clearly inside the letterforms rather than
     going to a dark smudge at this scale */
  filter: brightness(1.42) saturate(1.1) contrast(0.96);
}
/* the ivory face sits over the film and lifts away under the pointer, so the
   film is quiet at rest and comes forward where the light falls */
.footmark__base {
  background: var(--ivory);
  transition: opacity 0.55s ease;
}
.footmark[data-live] .footmark__base {
  opacity: 0.2;
}
.footmark__reveal {
  mix-blend-mode: soft-light;
}
@media (prefers-reduced-motion: reduce) {
  .footmark__base {
    opacity: 1 !important;
  }
}

/* the statement holds: it is the one oversized line on the page, so it is
   given real scroll distance rather than passing in a few notches */
.statement[data-fill] {
  min-height: 190svh;
  display: grid;
  align-items: center;
  padding-block: 0;
}
.statement[data-fill] .wrap {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  place-items: center;
}
@media (max-width: 900px) {
  .statement[data-fill] {
    min-height: 150svh;
  }
}

/* the light on the footer mark is warm, not white: Sunlit Nectar into
   Botanical Gold, which belongs to the palette and sits well on the green
   film running underneath */
.footmark__reveal {
  background-image: radial-gradient(
      circle var(--fx-r, 0px) at var(--fx-x, 50%) var(--fx-y, 50%),
      #f6da87 0%,
      #e8c069 30%,
      #c39a4a 58%,
      rgba(195, 154, 74, 0) 80%
    ),
    radial-gradient(
      circle calc(var(--fx-r, 0px) * 1.5) at calc(var(--fx-x, 50%) + 26px) calc(var(--fx-y, 50%) + 18px),
      rgba(53, 100, 92, 0.5) 0%,
      rgba(53, 100, 92, 0) 70%
    );
  mix-blend-mode: normal;
  opacity: 0.92;
}

/* the line on a full picture sits centred, not pinned to a corner */
.plate__line {
  left: var(--gut);
  right: var(--gut);
  bottom: clamp(44px, 9vh, 96px);
  max-width: none;
  text-align: center;
}
.plate__line > span {
  display: inline-block;
  max-width: 22ch;
}

/* nothing on this page is smaller than the readable floor */
.seq__spec b,
.pband__spec b,
.pband__spec dt {
  font-size: 13px;
}

/* The colour world no longer resizes on hover: growing the colour field made
   the cells jump about. The picture breathes very slightly instead and the
   field stays exactly where it is. */
.world__field,
.world__cell:hover .world__field {
  top: 62%;
  min-height: 38%;
  transition: none;
}
.world__pic img {
  transition: transform 1.4s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.world__cell:hover .world__pic img {
  transform: scale(1.025);
}

/* the light on the footer mark is green: pale leaf into sage, which sits with
   the film running underneath rather than against it */
.footmark__reveal {
  background-image: radial-gradient(
      circle var(--fx-r, 0px) at var(--fx-x, 50%) var(--fx-y, 50%),
      #e4f0d8 0%,
      #b8da84 28%,
      #8a9079 58%,
      rgba(138, 144, 121, 0) 80%
    ),
    radial-gradient(
      circle calc(var(--fx-r, 0px) * 1.5) at calc(var(--fx-x, 50%) + 26px) calc(var(--fx-y, 50%) + 18px),
      rgba(47, 52, 36, 0.5) 0%,
      rgba(47, 52, 36, 0) 70%
    );
}

/* The five product pictures must OVERLAP, one shown at a time. Putting them in
   normal flow to centre them stacked them instead, so every product after the
   first was off screen and its panel looked empty.
   Absolute with inset 0 and margin auto centres an element that has its own
   intrinsic size, which is what a capped image has. */
.seq__pic {
  display: block;
}
.seq__pic img {
  position: absolute;
  inset: 0;
  margin: auto;
  width: auto;
  height: auto;
  max-width: 76%;
  max-height: 60svh;
}
.travel__pic {
  display: block;
}
.travel__pic img {
  position: absolute;
  inset: 0;
  margin: auto;
  width: auto;
  height: auto;
  max-width: 72%;
  max-height: 62svh;
}
@media (max-width: 900px) {
  .seq__pic img {
    max-height: 32svh;
    max-width: 58%;
  }
  .travel__pic img {
    max-height: 34svh;
  }
}

/* back to a warm white light on the footer mark: it read better on the film
   than the green did, which sat too close to the leaf underneath */
.footmark__reveal {
  background-image: radial-gradient(
      circle var(--fx-r, 0px) at var(--fx-x, 50%) var(--fx-y, 50%),
      #ffffff 0%,
      #fbf6ea 26%,
      #e7e0cf 52%,
      rgba(231, 224, 207, 0) 78%
    ),
    radial-gradient(
      circle calc(var(--fx-r, 0px) * 1.5) at calc(var(--fx-x, 50%) + 26px) calc(var(--fx-y, 50%) + 18px),
      rgba(47, 52, 36, 0.45) 0%,
      rgba(47, 52, 36, 0) 70%
    );
  opacity: 1;
}

/* ============================================================
   THE COLOUR WORLD, THIRD PASS
   Two earlier passes moved the colour field on hover and both
   were wrong: growing it made the cells jump, and pinning it
   with a percentage min-height let a long name stretch the
   block down over the caption under it.
   So the field now lives INSIDE the picture with a height of
   its own in pixels, which nothing can stretch, and the hover
   does not move anything at all. Instead the colour RISES
   through the picture, carrying the brand mark up with it, and
   the cell ends as the thing the section is named for: the
   colour, held as a world, with its name still on it.
   ============================================================ */
.world__cell {
  display: block;
  position: relative;
  aspect-ratio: auto;
  overflow: visible;
}
.world__pic {
  display: block;
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  isolation: isolate;
}
.world__pic img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: none;
  transition: none;
}
.world__cell:hover .world__pic img {
  transform: none;
}
.world__wash {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--tone);
  -webkit-clip-path: inset(100% 0 0 0);
  clip-path: inset(100% 0 0 0);
  transition: clip-path 0.9s cubic-bezier(0.22, 0.61, 0.36, 1),
    -webkit-clip-path 0.9s cubic-bezier(0.22, 0.61, 0.36, 1);
}
/* the mark is drawn by the rising edge itself, so it arrives with the colour */
.world__wash::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: clamp(88px, 9.5vw, 136px);
  background: var(--tone-ink);
  opacity: 0.9;
  -webkit-mask-image: url("/brand/symbol.svg");
  mask-image: url("/brand/symbol.svg");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: auto 42%;
  mask-size: auto 42%;
}
.world__cell:hover .world__wash,
.world__cell:active .world__wash {
  -webkit-clip-path: inset(0 0 0 0);
  clip-path: inset(0 0 0 0);
}
/* fixed height in pixels: a long colour name wraps inside it, it never grows */
.world__field,
.world__cell:hover .world__field {
  position: absolute;
  left: 0;
  right: 0;
  top: auto;
  bottom: 0;
  z-index: 3;
  height: clamp(88px, 9.5vw, 136px);
  min-height: 0;
  max-height: none;
  background: var(--tone);
  color: var(--tone-ink);
  display: flex;
  align-items: flex-end;
  padding: clamp(14px, 1.6vw, 24px);
  transition: none;
  overflow: hidden;
}
.world__field b {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(18px, 1.8vw, 28px);
  line-height: 1.04;
}

/* ============================================================
   WHAT IS IN THEM
   The same rise, one line high. Each botanical fills with the
   brand's own olive from the baseline up and reads back in
   ivory, so running the eye down the list lights one row at a
   time. Nothing moves: the fill is behind the row, the row
   keeps its box.
   ============================================================ */
.ing__row {
  position: relative;
  isolation: isolate;
  transition: color 0.4s ease, border-color 0.4s ease;
}
.ing__row::before {
  content: "";
  position: absolute;
  left: calc(clamp(10px, 1.4vw, 22px) * -1);
  right: calc(clamp(10px, 1.4vw, 22px) * -1);
  top: 0;
  bottom: 0;
  z-index: -1;
  background: var(--olive);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform 0.52s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.ing__row:hover::before,
.ing__row:active::before {
  transform: scaleY(1);
}
.ing__row:hover,
.ing__row:active {
  color: var(--ivory);
  border-bottom-color: transparent;
}
.ing__row:hover .ing__in,
.ing__row:active .ing__in {
  color: rgba(244, 239, 230, 0.74);
}

@media (prefers-reduced-motion: reduce) {
  .world__wash,
  .ing__row::before,
  .ing__row {
    transition: none;
  }
}

/* The five products now share ONE frame, taken from the guide's own placed
   images, so their sizes are in proportion to each other: the hand cream jar
   is 39 per cent of the body lotion's height because that is how the brand
   drew them. Only the height is capped, since every frame is the same tall
   shape and the height is always what binds. */
.travel__pic img {
  max-width: 86%;
  max-height: 72svh;
}
@media (max-width: 900px) {
  .travel__pic img {
    max-height: 40svh;
    max-width: 78%;
  }
}

/* ============================================================
   WHAT IS IN THEM, SECOND PASS
   Filling each row with olive was a highlight bar and read as
   one. The list now answers its own question instead: moving
   down it carries the bottles that botanical is actually in,
   at the scale the brand draws them, so aloe pulls up three
   and chamomile pulls up one. The words never move and never
   depend on the pointer, so a reader on a phone loses nothing.
   ============================================================ */
.ing__row::before {
  content: none;
}
.ing__row {
  position: relative;
  isolation: auto;
  transition: color 0.35s ease, opacity 0.35s ease;
}
.ing__row:hover,
.ing__row:active {
  color: inherit;
  border-bottom-color: var(--rule);
}
.ing__row:hover .ing__in,
.ing__row:active .ing__in {
  color: var(--quiet);
}
/* the rest of the list stands back while one row is being read */
.ing[data-ing].is-reading .ing__row {
  opacity: 0.4;
}
.ing[data-ing].is-reading .ing__row.is-read {
  opacity: 1;
}
.ing__row.is-read .ing__name {
  color: var(--olive);
}

.ing {
  position: relative;
}
.ingplate {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 8;
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: clamp(150px, 20vw, 248px);
  padding: 0 10px;
  pointer-events: none;
  opacity: 0;
  transform: translate3d(var(--px, 0px), var(--py, 0px), 0) scale(0.94);
  transform-origin: 0 100%;
  transition: opacity 0.32s ease, transform 0.32s cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform;
}
.ingplate.is-on {
  opacity: 1;
  transform: translate3d(var(--px, 0px), var(--py, 0px), 0) scale(1);
}
.ingplate img {
  display: none;
  height: 100%;
  width: auto;
  object-fit: contain;
  filter: drop-shadow(0 18px 26px rgba(31, 35, 24, 0.22));
}
.ingplate img.is-on {
  display: block;
}
@media (hover: none), (max-width: 900px) {
  .ingplate {
    display: none;
  }
  .ing[data-ing].is-reading .ing__row {
    opacity: 1;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ingplate {
    transition: opacity 0.2s linear;
    transform: translate3d(var(--px, 0px), var(--py, 0px), 0);
  }
  .ingplate.is-on {
    transform: translate3d(var(--px, 0px), var(--py, 0px), 0);
  }
}

/* a little more presence now that the frame carries 6 per cent of air of its
   own: the tallest product reaches about 69svh of real bottle, the hand cream
   jar about 27svh, which is the proportion the guide draws them in */
.travel__pic img {
  max-height: 78svh;
}

/* Sage carries its own name at 4.34:1, which passes only as large text. The
   name was shrinking to 18px at tablet and phone and the gate caught it, so
   its floor is 24px: the size at which that ratio is allowed to be read. */
.world__field b {
  font-size: clamp(24px, 1.9vw, 30px);
}

/* ============================================================
   WHAT IS IN THEM, THIRD PASS
   The bottles answered the wrong question. Running down the
   list now carries the BOTANICAL: the chamomile, the green fig,
   the honeycomb, so the reader meets the thing the row names
   instead of the package it ends up in. One square photograph,
   floating clear of the row being read.
   ============================================================ */
.ingplate {
  display: block;
  width: clamp(168px, 19vw, 268px);
  height: clamp(168px, 19vw, 268px);
  padding: 0;
  gap: 0;
  overflow: hidden;
  box-shadow: 0 26px 46px -18px rgba(31, 35, 24, 0.45);
}
.ingplate img {
  display: none;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: none;
}
.ingplate img.is-on {
  display: block;
}

/* The footer carries 90px of page ground above it, which is the air between an
   ivory page and the dark footer. The products page now ends on the dark
   gallery, and that air became an ivory seam between two dark fields. Where the
   last section is dark the footer butts straight onto it. */
main:has(> *:last-child[data-dark]) + footer {
  margin-top: 0;
}

/* The footer lost its third column with the line it carried. Two columns at
   auto width would each have taken half the footer and left the links adrift in
   it, so the tracks are capped and set from the left instead. */
.foot__cols {
  grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 232px));
  justify-content: start;
}

/* ============================================================
   THE PHONE
   Two things were broken at 390px and neither is a gate's job.
   The bottom nav overflowed, so CONTACT was sliced to a "C".
   And the product gallery still travelled sideways, which put
   two columns into 390px and let the next panel cut the names
   in half: "Blu Chile", "olden oney".
   A sideways scrub is a desktop pleasure. On a phone the five
   products simply stack, a screen each, read by scrolling the
   way everything else on the page is read.
   ============================================================ */
@media (max-width: 640px) {
  .c-nav {
    gap: 0;
    padding: 11px 14px;
    overflow-x: visible;
  }
  .c-nav a {
    font-size: 11px;
    letter-spacing: 0.035em;
  }
}

@media (max-width: 760px) {
  /* the inline height is the scroll budget for the sideways travel, and there
     is no travel here, so the stack decides its own height */
  .travel {
    height: auto !important;
  }
  .travel__stage {
    position: static;
    height: auto;
    overflow: visible;
  }
  .travel__track {
    display: block;
    height: auto;
    transform: none !important;
  }
  .travel__item {
    width: 100%;
    height: auto;
    min-height: 100svh;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto;
    align-content: center;
    padding: clamp(84px, 13vh, 120px) 0 clamp(60px, 9vh, 92px);
  }
  .travel__pic {
    position: relative;
    height: 44svh;
  }
  .travel__text {
    border-left: 0;
    border-top: 1px solid rgba(244, 239, 230, 0.14);
    margin: 26px var(--gut) 0;
    padding: 26px 0 0;
  }
  .travel__rail {
    display: none;
  }
}

/* On a phone a full-bleed plate is short, so its line crosses the header on the
   way up and two ivory things meet: the wordmark and the sentence. The scrim
   over a picture is deeper and taller here, so anything passing under it is
   plainly behind the furniture rather than fighting it. */
@media (max-width: 760px) {
  .corners.on-picture::before {
    background: linear-gradient(
      rgba(31, 35, 24, 0.82),
      rgba(31, 35, 24, 0.58) 54%,
      rgba(31, 35, 24, 0)
    );
    height: clamp(132px, 19vh, 168px);
  }
}

/* ============================================================
   THE LOADING SCREEN, ON A REAL PHONE
   The film's ground is #2E3523 and so is the page under it,
   measured with ffmpeg on the decoded frame and read off the
   stylesheet. They still do not land on the same pixel: the
   browser's video pipeline renders that value darker, so the
   film shows as a rectangle. Reading the painted pixel back off
   a canvas fixes it in Chrome and fails silently in WebKit,
   where the read is refused, so the phone kept the mismatch.
   The seam is removed instead of matched: the film fades out at
   its own edges, so any difference becomes a gradient nobody
   can see rather than a hard border. The mark sits well inside
   the solid core.
   ============================================================ */
.boot__film {
  -webkit-mask-image: radial-gradient(
    ellipse 74% 74% at 50% 50%,
    #000 46%,
    rgba(0, 0, 0, 0.6) 72%,
    transparent 100%
  );
  mask-image: radial-gradient(
    ellipse 74% 74% at 50% 50%,
    #000 46%,
    rgba(0, 0, 0, 0.6) 72%,
    transparent 100%
  );
}

/* ============================================================
   THE COLOUR WORLD, ON TOUCH
   A phone has no hover, so the tide never rose and each colour
   was left as a band under a photograph. Warm Ivory on an ivory
   page is then nothing at all: the user could not see the
   colours. Every cell now fills with its own colour as it is
   scrolled to, which is the same move the pointer makes.
   ============================================================ */
@media (hover: none) {
  .world__cell.is-shown .world__wash {
    -webkit-clip-path: inset(0 0 0 0);
    clip-path: inset(0 0 0 0);
  }
}

/* ============================================================
   THE PRODUCT CAP, LAST WORD
   A later `max-height: 78svh` appended for the desktop gallery
   overrode the phone cap set earlier in this file: same
   specificity, later rule wins. The image was then allowed to
   be 626px tall inside a 371px box with overflow hidden, and
   every product was cropped on a phone.
   On a phone the image is bound to its OWN BOX rather than to a
   viewport unit, so it cannot be cut however the caps above are
   edited later. tools/check.js now fails the build if a product
   image is taller than the box that clips it.
   ============================================================ */
@media (max-width: 760px) {
  .travel__pic img {
    max-height: 100%;
    max-width: 84%;
  }
}

/* Warm Ivory measures 1.02:1 against the page it sits on, so its filled cell
   has no edge and reads as the mark floating on the paper. Only a tone that
   close to the ground gets a boundary; every other cell is bounded by its own
   colour. */
.world__cell[data-near-page] .world__pic {
  box-shadow: inset 0 0 0 1px rgba(43, 42, 39, 0.16);
}

/* ============================================================
   THE LOADING SCREEN, LAST WORD: NO CSS COLOUR BESIDE VIDEO
   A flat colour encoded in a video and the same flat colour
   written in CSS do not render the same, and the difference is
   not constant: the phone rendered the film DARKER than the
   page and the MacBook rendered it LIGHTER. It is the display's
   own colour handling of video, so no hex, no canvas sample and
   no mask can make the two agree on every machine.
   So they are never shown side by side. The film fills the
   screen, cover-fitted, and the whole of the loading screen is
   film pixels. There is nothing left to mismatch.
   A portrait cut, padded with the film's OWN ground (proved by
   decoding a frame: the pad and the film both read rgb(45,52,34)),
   keeps the lockup whole on a phone, where covering the landscape
   cut would have sliced it.
   ============================================================ */
.boot__stage,
.boot .boot__stage {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
}
.boot__film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  min-width: 0;
  max-width: none;
  object-fit: cover;
  /* the edge mask is gone with the edge: there is no edge any more */
  -webkit-mask-image: none;
  mask-image: none;
}
.boot__bar {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: clamp(70px, 12vh, 130px);
  z-index: 2;
}
