/* =========================================================================
   yourlabel — editorial commerce sample
   White page, black type, one full-bleed scroll-scrubbed film.
   Every fixed overlay is mix-blend-mode: difference, which is the whole
   trick: one set of white UI reads correctly over both the blown-out and
   the near-black frames of the hero without a single colour change in JS.
   ========================================================================= */

:root{
  --bg:#fff;
  --surface:#fff;
  --ink:#000;
  --ink-inverse:#fff;

  --font-sans:"Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-serif-italic:Georgia, "Times New Roman", serif;
  --font-logo:"EB Garamond", Georgia, serif;

  --space-4:1rem;
  --space-5:1.5rem;
  --space-6:2rem;

  --radius-sm:0.375rem;
  --radius-pill:999px;

  --fs-ui:max(11px, 0.6875rem);
  --fs-brand:max(11px, 0.75rem);
}

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

/* Root em is the layout unit for the entire page, so the whole composition
   scales with the viewport instead of only the type. */
html{
  font-size:clamp(11px, 0.833vw, 16px);
}

body{
  margin:0;
  min-height:100dvh;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--font-sans);
  overscroll-behavior:none;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

h1,h2,p,ul{margin:0}
ul{list-style:none;padding:0}
img,video{display:block}
a{color:inherit}

/* Shared uppercase UI voice: tagline, nav, account, product description. */
.tagline-hero,
.menu a,
.account a,
.cta-copy,
.product .desc{
  font-size:var(--fs-ui);
  text-transform:uppercase;
  font-weight:700;
  line-height:1.45;
  letter-spacing:0.01em;
}

/* -------------------------------------------------------------------------
   Fixed header
   ------------------------------------------------------------------------- */
.site-header{
  position:fixed;
  top:0; left:0; right:0;
  z-index:50;
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:var(--space-6);
  padding:var(--space-5) var(--space-6);
  background:transparent;
  color:var(--ink-inverse);
  mix-blend-mode:difference;
  pointer-events:none;
}
.site-header a{pointer-events:auto; text-decoration:none}

/* Tagline clears the fixed chrome mark, which no longer lives in this flex
   row, so the row's first item must not start at the gutter. */
.tagline-hero{
  max-width:21.25rem;
  margin-left:calc(150px + var(--space-6));
}

/* Account row and nav share one right edge. */
.header-right{
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  gap:var(--space-4);
  flex:none;
}

.menu ul{
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  gap:2px;
}
.menu a{
  line-height:1.55;
  letter-spacing:0.02em;
  text-decoration:none;
  text-align:right;
}

/* SHOP and MENU occupy the same cell; JS cross-fades one into the other as
   the secondary links leave. */
/* SHOP and MENU must resolve to the same box, not just the same corner.
   Left as an inline span, SHOP is measured on its glyph box while MENU,
   being absolutely inset, fills the taller line box, and the swap lands two
   pixels high. Making both block-level puts them on one shared baseline. */
.menu-word{
  position:relative;
  display:inline-block;
}
.menu-word__a{
  display:block;
}
.menu-word__b{
  position:absolute;
  inset:0;
  opacity:0;
}

.account{
  display:flex;
  gap:var(--space-5);
}

/* -------------------------------------------------------------------------
   Hero
   Fixed, inset 0, with a resting margin-top of 30vh. Because top and bottom
   are both pinned, that margin shortens the box to 70vh; JS lerps it to 0
   and the film opens to full bleed.
   ------------------------------------------------------------------------- */
.hero{
  position:fixed;
  inset:0;
  z-index:10;
  margin-top:30vh;
  background:#000;
  overflow:hidden;
}
.hero-bg-video{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
  border:0;
  outline:0;
}

/* -------------------------------------------------------------------------
   Hero title
   Sits just above the hero's resting top edge, so it reads on white before
   the film rises to meet it.
   ------------------------------------------------------------------------- */
.hero-title{
  position:fixed;
  z-index:40;
  left:var(--space-6);
  right:var(--space-6);
  bottom:calc(70vh + var(--space-5));
  color:var(--ink-inverse);
  mix-blend-mode:difference;
  pointer-events:none;
  font-size:2.5rem;
  font-weight:500;
  line-height:1.05;
  letter-spacing:-0.01em;
}
.hero-title .italic{
  font-family:var(--font-serif-italic);
  font-style:italic;
  font-weight:400;
}

/* -------------------------------------------------------------------------
   Hero footer / CTA
   ------------------------------------------------------------------------- */
.hero-footer{
  position:fixed;
  bottom:var(--space-6);
  left:var(--space-6);
  right:var(--space-6);
  z-index:20;
  display:flex;
  align-items:flex-end;
  gap:var(--space-5);
  color:var(--ink-inverse);
  mix-blend-mode:difference;
  pointer-events:none;
}

.cta{
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  text-align:right;
  margin-left:auto;
  max-width:34rem;
  position:relative;
}
/* difference blending computes |255 - backdrop|, so it collapses to nothing
   when the backdrop sits near mid-grey, which is exactly what this corner of
   the film does. Measured 1.19:1 unaided. Darkening the backdrop pushes it
   off the midpoint and the blend resolves again. */
.cta::before{
  content:"";
  position:absolute;
  left:-2rem;
  right:-2rem;
  top:-1.25rem;
  bottom:-1.25rem;
  z-index:-1;
  pointer-events:none;
  background:radial-gradient(115% 130% at 78% 45%,
    rgba(0,0,0,0.74) 0%,
    rgba(0,0,0,0.58) 44%,
    rgba(0,0,0,0.24) 70%,
    rgba(0,0,0,0) 87%);
  filter:blur(12px);
}
.cta-copy{
  margin-bottom:var(--space-4);
}

.shop-now{
  pointer-events:auto;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:3rem;
  padding:0 2.5rem;
  background:var(--surface);
  color:var(--ink-inverse);
  border-radius:var(--radius-pill);
  text-decoration:none;
  font-size:var(--fs-brand);
  font-weight:700;
  letter-spacing:0.06em;
}
/* Second difference pass, this time against the white pill, so the label
   resolves to black no matter what the pill itself is doing. */
.shop-now__label{
  mix-blend-mode:difference;
}

/* -------------------------------------------------------------------------
   Product
   ------------------------------------------------------------------------- */
.product{
  position:fixed;
  bottom:var(--space-6);
  left:var(--space-6);
  z-index:20;
  display:flex;
  gap:var(--space-4);
  color:var(--ink-inverse);
  opacity:0;
}

.product-thumb{
  position:relative;
  flex:none;
  width:calc(7rem * var(--card-scale, 1));
  height:calc(7rem * var(--card-scale, 1));
  background:var(--surface);
  border-radius:var(--radius-sm);
}
.product-thumb img{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
  border-radius:inherit;
}

/* The film behind this text is mostly dark, so the average contrast looked
   fine, but roughly a third of the pixels behind it are lit skin and
   highlights where white drops to about 1.2:1 and the type disappears. A
   diffuse scrim darkens only those bright patches; it is blurred and has no
   hard edge, so it reads as shadow in the film rather than a panel. The
   shadow underneath catches whatever the scrim misses. */
.product-info{
  display:flex;
  flex-direction:column;
  position:relative;
  text-shadow:0 1px 2px rgba(0,0,0,0.55), 0 0 14px rgba(0,0,0,0.45);
}
.product-info::before{
  content:"";
  position:absolute;
  left:-1.25rem;
  right:-2rem;
  top:-1rem;
  bottom:-1rem;
  z-index:-1;
  pointer-events:none;
  background:radial-gradient(115% 130% at 22% 55%,
    rgba(0,0,0,0.74) 0%,
    rgba(0,0,0,0.58) 44%,
    rgba(0,0,0,0.24) 70%,
    rgba(0,0,0,0) 87%);
  filter:blur(12px);
}
.product-info h2{
  font-size:1.375rem;
  font-weight:500;
  line-height:1.15;
  letter-spacing:-0.01em;
  margin-bottom:0.625rem;
}
.product .desc{
  max-width:34rem;
  margin-bottom:0.875rem;
}
.product .price{
  font-size:1.375rem;
  font-weight:400;
  letter-spacing:-0.01em;
  margin-top:auto;
}

/* -------------------------------------------------------------------------
   Add button
   Vertically fixed here; its left edge is measured off the product card
   every frame in JS, because the card grows to 1.9x under it.
   ------------------------------------------------------------------------- */
.add-btn{
  position:fixed;
  bottom:var(--space-6);
  z-index:20;
  display:flex;
  align-items:center;
  justify-content:center;
  width:3.375rem;
  height:3.375rem;
  padding:0;
  border:0;
  border-radius:50%;
  background:var(--surface);
  color:var(--ink-inverse);
  font-family:var(--font-sans);
  font-size:1.625rem;
  line-height:1;
  cursor:pointer;
  mix-blend-mode:difference;
  opacity:0;
  pointer-events:none;
}
.add-btn__label{
  mix-blend-mode:difference;
  padding-bottom:0.1875rem;
}

/* -------------------------------------------------------------------------
   Chrome b/p mark
   Four stacked copies of the same glyphs on the Z axis: three dark depth
   layers and one gradient-filled face. Under rotateY the depth layers are
   what stop it reading as a flat sticker.
   ------------------------------------------------------------------------- */
.bp-logo{
  position:fixed;
  top:var(--space-5);
  left:var(--space-6);
  z-index:55;
  display:block;
  perspective:600px;
  text-decoration:none;
  -webkit-tap-highlight-color:transparent;
}

.bp-logo__stage{
  display:block;
  position:relative;
  transform-style:preserve-3d;
  transform:rotateY(0deg);
  will-change:transform;
}
/* One full turn per hover, driven by a class so it always completes instead
   of snapping back when the cursor leaves mid-rotation. */
.bp-logo.is-spinning .bp-logo__stage{
  animation:bpSpin 1.5s cubic-bezier(0.62, 0.03, 0.28, 1);
}
@keyframes bpSpin{
  from{ transform:rotateY(0deg) }
  to  { transform:rotateY(360deg) }
}

.bp-logo__mark{
  display:block;
  font-family:var(--font-logo);
  font-style:italic;
  font-weight:400;
  font-size:27px;
  letter-spacing:.02em;
  line-height:1;
  white-space:nowrap;
  letter-spacing:0;
  backface-visibility:visible;
}
/* Depth layers sit behind the face and are progressively darker, so the
   extrusion reads as a solid billet rather than an outline. */
.bp-logo__mark--d1,
.bp-logo__mark--d2,
.bp-logo__mark--d3{
  position:absolute;
  inset:0;
  color:#2b2f33;
}
.bp-logo__mark--d1{ transform:translateZ(-2px); color:#4a4f54 }
.bp-logo__mark--d2{ transform:translateZ(-5px); color:#33373b }
.bp-logo__mark--d3{ transform:translateZ(-8px); color:#1c1f22 }

/* The face. Alternating light and dark bands read as reflected environment;
   a single soft gradient reads as plastic, not metal. */
.bp-logo__mark--face{
  position:relative;
  background:linear-gradient(100deg,
    #74797e 0%, #cdd2d7 10%, #ffffff 20%, #9ca2a8 29%,
    #55595d 38%, #e9edf0 50%, #ffffff 58%, #8d9399 68%,
    #5f6367 78%, #dfe4e8 89%, #8a9096 100%);
  background-size:240% 100%;
  background-position:12% 50%;
  -webkit-background-clip:text;
  background-clip:text;
  color:transparent;
  -webkit-text-fill-color:transparent;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,0.45)) drop-shadow(0 8px 18px rgba(0,0,0,0.3));
  transition:background-position 1.5s cubic-bezier(0.62, 0.03, 0.28, 1);
}
/* The highlight travels across the metal as it turns. */
.bp-logo:hover .bp-logo__mark--face{
  background-position:92% 50%;
}

@media (prefers-reduced-motion:reduce){
  .bp-logo.is-spinning .bp-logo__stage{animation:none}
  .bp-logo__mark--face{transition:none}
}

/* -------------------------------------------------------------------------
   Preloader
   The mark arrives too wide, too light and out of focus, then tightens: it
   reads as type being set rather than a logo fading in. The panel then drains
   downward on a clip-path rather than fading, so the hero is revealed by a
   moving edge instead of appearing through a haze.
   ------------------------------------------------------------------------- */

/* Scroll is locked until the film is in memory. Scrubbing a half-buffered
   file seeks to frames that have not arrived yet. */
html.is-locked, body.is-loading{
  overflow:hidden;
  height:100%;
}

#loading{
  position:fixed;
  inset:0;
  z-index:60;
  display:flex;
  align-items:center;
  justify-content:center;
  background:var(--bg);
  clip-path:inset(0 0 0 0);
  transition:clip-path 1.25s cubic-bezier(0.76, 0, 0.24, 1);
}
html.ready #loading{
  clip-path:inset(100% 0 0 0);
  pointer-events:none;
}

.lo-center{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:1.75rem;
  transition:opacity 0.5s ease, transform 0.8s cubic-bezier(0.22, 0.8, 0.3, 1);
}
html.ready .lo-center{
  opacity:0;
  transform:translateY(-14px);
}

.lo-wm{
  display:inline-block;
  font-family:var(--font-logo);
  font-style:italic;
  font-weight:400;
  font-size:clamp(66px, 11vw, 106px);
  line-height:1;
  letter-spacing:0;
  white-space:nowrap;
  color:var(--ink);
  animation:settle 2s cubic-bezier(0.16, 0.86, 0.24, 1) 0.2s both;
}
.lo-wm .s{opacity:0.6}

@keyframes settle{
  0%   { letter-spacing:0.42em; opacity:0; filter:blur(4px) }
  55%  { opacity:1 }
  100% { letter-spacing:0; opacity:1; filter:blur(0) }
}

/* The initials are spelled out underneath, so the mark is taught on first
   load rather than left as an unexplained pair of letters. */
.lo-name{
  font-family:var(--font-sans);
  font-weight:500;
  font-size:11px;
  letter-spacing:0.3em;
  text-transform:uppercase;
  color:var(--ink);
  opacity:0;
  animation:loName 0.9s ease 1.4s forwards;
}
@keyframes loName{ to{ opacity:0.55 } }

.lo-meter{
  width:104px;
  height:1px;
  background:rgba(0, 0, 0, 0.14);
  overflow:hidden;
}
.lo-meter i{
  display:block;
  height:100%;
  width:0;
  background:var(--ink);
  transition:width 0.5s cubic-bezier(0.22, 0.8, 0.3, 1);
}

/* Tabular figures so the counter does not jitter as digits change width. */
.lo-pct{
  font-family:var(--font-sans);
  font-weight:700;
  font-size:var(--fs-ui);
  letter-spacing:0.16em;
  color:var(--ink);
  opacity:0;
  font-variant-numeric:tabular-nums;
  animation:loName 0.9s ease 1.4s forwards;
}
.lo-pct::after{content:"%"}

/* The hairline that rides the draining edge downward. */
.lo-surface{
  position:fixed;
  left:0; right:0; top:0;
  height:1px;
  z-index:61;
  opacity:0;
  pointer-events:none;
  background:linear-gradient(90deg, transparent, rgba(0,0,0,0.55) 28%, rgba(0,0,0,0.55) 72%, transparent);
}
html.ready .lo-surface{
  opacity:1;
  transform:translateY(100vh);
  transition:transform 1.25s cubic-bezier(0.76, 0, 0.24, 1), opacity 0.3s ease;
}

.lo-sr{
  position:absolute;
  width:1px; height:1px;
  margin:-1px; padding:0; border:0;
  overflow:hidden;
  clip:rect(0 0 0 0);
  white-space:nowrap;
}

@media (prefers-reduced-motion:reduce){
  .lo-wm{animation:none}
  .lo-name, .lo-pct{animation:none; opacity:0.55}
  .lo-surface{display:none}
  #loading{transition:opacity 0.4s ease}
  html.ready #loading{clip-path:none; opacity:0}
  html.ready .lo-center{transform:none}
}

/* -------------------------------------------------------------------------
   End card
   Same fixed-overlay architecture as everything else on this page, driven by
   scroll progress rather than sitting in flow, so it cannot disturb the
   scrub maths. Styled in the page's own language: bone ground, Helvetica UI
   type, the pill borrowed from SHOP NOW.
   ------------------------------------------------------------------------- */
/* Above the header (50) and the chrome mark (55), below the preloader (60):
   the close belongs to the studio, so the client's furniture clears out.
   It arrives by sliding up from the bottom rather than cross-fading, and it
   lands on the film's own last frame, defocused. A hard cut to flat white was
   the weakest moment in the piece. */
.endcard{
  position:fixed;
  inset:0;
  z-index:58;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden;
  background:#0b0b0c;
  opacity:0;
  transform:translate3d(0, 100%, 0);
  pointer-events:none;
  will-change:transform;
}

/* Inset past the edges so the blur has no soft border to give itself away. */
.endcard__bg{
  position:absolute;
  inset:-8%;
  background:url("media/end-still.jpg") center/cover no-repeat;
  filter:blur(30px) saturate(0.8);
  transform:scale(1.06);
  opacity:0.5;
}
.endcard__bg::after{
  content:"";
  position:absolute;
  inset:0;
  background:radial-gradient(72% 72% at 50% 44%,
    rgba(0,0,0,0.28) 0%,
    rgba(0,0,0,0.68) 62%,
    rgba(0,0,0,0.88) 100%);
}

.endcard__inner{
  position:relative;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--space-5);
  padding:0 var(--space-6);
  text-align:center;
}

.end-rule{
  width:104px;
  height:1px;
  background:var(--ink-inverse);
  opacity:0.28;
}

.end-note{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:0.875rem;
  color:var(--ink-inverse);
}
.end-note > span{
  font-size:var(--fs-ui);
  text-transform:uppercase;
  font-weight:700;
  letter-spacing:0.16em;
  opacity:0.62;
}

/* Same chrome as the logo, so the piece closes on the mark it opened with. */
.end-mark{
  font-family:var(--font-logo);
  font-style:italic;
  font-weight:400;
  font-size:clamp(52px, 7vw, 78px);
  line-height:1;
  text-decoration:none;
  background:linear-gradient(100deg,
    #74797e 0%, #cdd2d7 10%, #ffffff 20%, #9ca2a8 29%,
    #55595d 38%, #e9edf0 50%, #ffffff 58%, #8d9399 68%,
    #5f6367 78%, #dfe4e8 89%, #8a9096 100%);
  background-size:240% 100%;
  background-position:12% 50%;
  -webkit-background-clip:text;
  background-clip:text;
  color:transparent;
  -webkit-text-fill-color:transparent;
  filter:drop-shadow(0 2px 10px rgba(0,0,0,0.6));
  transition:background-position 1.6s cubic-bezier(0.62, 0.03, 0.28, 1);
}
.end-mark:hover{background-position:92% 50%}

.end-actions{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--space-4);
  margin-top:0.5rem;
}

/* The SHOP NOW pill, inverted for the dark ground. */
.end-btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:3rem;
  padding:0 2.5rem;
  background:var(--ink-inverse);
  color:var(--ink);
  border-radius:var(--radius-pill);
  text-decoration:none;
  font-size:var(--fs-brand);
  font-weight:700;
  letter-spacing:0.06em;
  transition:transform 0.25s cubic-bezier(0.22,0.8,0.3,1), box-shadow 0.25s ease;
  box-shadow:0 2px 24px rgba(0,0,0,0.35);
}
.end-btn:hover{
  transform:translateY(-2px);
  box-shadow:0 8px 32px rgba(0,0,0,0.45);
}

.end-link{
  font-size:var(--fs-ui);
  text-transform:uppercase;
  font-weight:700;
  letter-spacing:0.06em;
  color:var(--ink-inverse);
  opacity:0.62;
  text-decoration:underline;
  text-underline-offset:0.35em;
  text-decoration-thickness:1px;
  transition:opacity 0.25s ease;
}
.end-link:hover{opacity:1}

@media (prefers-reduced-motion:reduce){
  .end-mark{transition:none}
  .end-btn{transition:none}
}

/* -------------------------------------------------------------------------
   Scrub track
   Longer than the spec's 220vh because the page now has an ending to play.
   At 220vh with the film running to 88% of the track, the close had roughly
   12vh of scroll to arrive in, which reads as a jump cut to a white screen
   rather than an ending. See B_END in script.js for the other half of this.
   ------------------------------------------------------------------------- */
.scroll-spacer{
  height:380vh;
  pointer-events:none;
}

/* -------------------------------------------------------------------------
   Narrow viewports
   The composition is built for a wide frame. Below that, the two bottom
   columns stop competing for the same row.
   ------------------------------------------------------------------------- */
@media (max-width:60rem){
  .tagline-hero{display:none}
  /* the tagline was the header's first flex child; without it,
     space-between parks the nav on the LEFT, on top of the chrome mark.
     Pin the remaining column to the right edge where it belongs. */
  .site-header{justify-content:flex-end}
  .hero-title{font-size:2rem}
  .cta{max-width:24rem}
  .product .desc{max-width:20rem}
  .bp-logo__mark{font-size:23px}
}
