/* ==========================================================================
   HALLY store hero — faithful rebuild
   Geometry is expressed as % of the stage, measured from the reference frames
   (1500x976 capture space). Type is authored against a 1440px-wide viewport.
   Every animated property is transform or opacity so the swap stays on the
   compositor.
   ========================================================================== */

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  overflow: hidden;                 /* single-screen hero, exactly as the reference */
  background: #c2c1c3;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; margin: 0; padding: 0; }
p, h1 { margin: 0; }
.sr-live {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* ---------- type ---------- */
:root {
  --serif: 'EB Garamond', Garamond, 'Times New Roman', serif;
  --sans: 'Montserrat', 'Segoe UI', Arial, sans-serif;

  /* fluid scale: the reference sizes at 1440 wide, allowed to breathe 1280 -> 1920 */
  --fs-h1:     clamp(2.4rem, 4.24vw, 4.65rem);   /* cap-height 40px @1440 -> 61px in EB Garamond */
  --fs-body:   clamp(0.9rem,  1.39vw, 1.5rem);   /* 20px @1440 */
  --fs-nav:    clamp(0.85rem, 1.39vw, 1.45rem);
  --fs-price:  clamp(1.6rem,  2.71vw, 3rem);     /* 39px @1440 */
  --fs-motto:  clamp(1.4rem,  2.5vw,  2.7rem);   /* 36px @1440 */
  --fs-size:   clamp(0.8rem,  1.32vw, 1.4rem);   /* 19px @1440 */
  --fs-cta:    clamp(0.8rem,  1.25vw, 1.35rem);  /* 18px @1440 */

  /* motion */
  --t-swap: 900ms;
  --ease-fly:  cubic-bezier(0.60, 0, 0.20, 1);
  --ease-outX: cubic-bezier(0.45, 0, 0.55, 1);
  --ease-outY: cubic-bezier(0.55, 0, 0.80, 0.40);
  --ease-tint: cubic-bezier(0.55, 0, 0.45, 1);

  /* Carousel anchors. Hero garment centre (51.5%, 43.1%) derived from the measured
     hook-top 15.0% and hem 71.2%; thumb centre (91.1%, 85.3%).
     These MUST be viewport units, not %: a % inside translate() resolves against the
     element's own box, which would launch the flight from the wrong place. */
  --thumb-dx: 39.4vw;
  --thumb-dy: 42.2vh;
  --thumb-scale: 0.215;

  /* The shirt is sized off viewport HEIGHT, not width. Its vertical band (hook-top
     15% -> hem 71.2% = 56.2vh) is the tight constraint: it must clear the navbar above
     and the motto below at every aspect ratio. Sizing off width instead made the shirt
     11.9%..74.3% tall on 16:9 and it collided with the nav.
     The render carries transparent margin — the garment is 77.8% of the canvas width
     and 61.3% of its height — so slot height 91.6vh yields the 56.2vh garment, and the
     resulting width lands on the measured 29.7vw sleeve span at the authored 1440x900. */
  --slot-w: 61.1vh;
}

/* ==========================================================================
   THEMES
   The background is NOT a radial glow: measured row/column scans show
   brightness varies with x only, peaking at x=50% and falling off
   symmetrically. Hence a mirrored 90deg linear gradient.
   ========================================================================== */
:root {
  --ink: #141414;
  --ink-soft: rgba(17, 17, 17, 0.78);
  --nav-ink: #1f1f1f;
  --cta-bg: #0a0a0a;
  --cta-ink: #ffffff;
  --social-ink: rgba(34, 34, 34, 0.92);

  /* The SIZE pills really are constant on all five themes — sampled off the circle
     edges: active Xl reads #fdfffe..#fffcff and the inactive three read #000101..#030102
     on white, magenta, charcoal, cream and brown alike.
     The active NAV pill is NOT constant — see --cta-bg below; it inverts. */
  --chip-bg: #0a0a0a;
  --chip-ink: #ffffff;
  --chip-on-bg: #ffffff;
  --chip-on-ink: #141414;
  --arrow-bg: rgba(0, 0, 0, 0.50);
  --arrow-ink: #ffffff;
  --badge-bg: #ef2d44;
}
:root[data-theme="white"]    { --g1: #c2c1c3; --g2: #d2d2d4; --g3: #e3e1e6; }
:root[data-theme="magenta"]  { --g1: #830a38; --g2: #b30a4c; --g3: #e20a63; }
:root[data-theme="charcoal"] { --g1: #3a3a3c; --g2: #4c4c4e; --g3: #5d5d5f; }
:root[data-theme="cream"]    { --g1: #bdb28e; --g2: #cec7a6; --g3: #e6dfc3; }
:root[data-theme="brown"]    { --g1: #3d3029; --g2: #635049; --g3: #8a746d; }

/* light-ink themes: magenta, charcoal, brown */
:root[data-theme="magenta"],
:root[data-theme="charcoal"],
:root[data-theme="brown"] {
  --ink: #ffffff;
  --ink-soft: rgba(255, 255, 255, 0.82);
  --nav-ink: rgba(255, 255, 255, 0.92);
  --cta-bg: #ffffff;
  --cta-ink: #141414;
  --social-ink: rgba(255, 255, 255, 0.90);
}

/* the two stacked gradient layers; only opacity animates */
.bg {
  position: fixed;
  inset: 0;
  background: linear-gradient(90deg,
              var(--g1) 0%, var(--g2) 25%, var(--g3) 50%, var(--g2) 75%, var(--g1) 100%);
  will-change: opacity;
}
#bgFront { transition: opacity 700ms var(--ease-tint) 100ms; }

/* every tinted token crossfades natively; the dip is a separate opacity track */
.lede, .buy, .nav__links, .motto, .social, .cta {
  transition: color 700ms var(--ease-tint) 100ms;
}

/* ---------- stage ---------- */
.stage {
  position: relative;
  width: 100vw;
  height: 100vh;
  color: var(--ink);
  font-family: var(--sans);
}

/* ==========================================================================
   NAVBAR — items vertically centred at y = 7.7%
   ========================================================================== */
.nav { position: absolute; inset: 0 0 auto 0; height: 15.4%; }

.logo {
  position: absolute;
  left: 6.1%;
  top: 4.4%;
  width: 5.6%;
  min-width: 62px;
  color: #fff;                      /* the lockup is white on all five themes */
  display: grid;
  justify-items: center;
  line-height: 1;
}
.logo__mark { width: 100%; height: auto; margin-bottom: -19%; }
.logo__word {
  font-family: var(--sans);
  font-weight: 800;
  font-size: clamp(0.95rem, 1.74vw, 1.85rem);
  letter-spacing: 0.055em;
  text-indent: 0.055em;             /* absorb the trailing tracking so it stays optically centred */
}
.logo__tag {
  font-weight: 600;
  font-size: clamp(0.24rem, 0.55vw, 0.55rem);
  letter-spacing: 0.14em;
  text-indent: 0.14em;
  opacity: 0.92;
  margin-top: 0.22em;
}

.nav__links {
  position: absolute;
  left: 50.2%;
  top: 7.7%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 3em;                          /* measured edge-to-edge gap 4.1% of width */
  font-size: var(--fs-nav);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--nav-ink);
  white-space: nowrap;
}
.nav__links a { padding: 0.15em 0; transition: opacity 160ms ease-out; }
.nav__links a:hover { opacity: 0.68; }
/* The active pill INVERTS with the theme, exactly like the "Get the look" button.
   Sampled inside the pill, off the glyphs: white #010408, cream #0c0805 (black pill),
   magenta #fbfffa, charcoal #fefeff, brown #fcfaf9 (white pill). */
.nav__links .is-active {
  background: var(--cta-bg);
  color: var(--cta-ink);
  border-radius: 999px;
  padding: 0.36em 0.72em;
  transition: background-color 700ms var(--ease-tint) 100ms,
              color 700ms var(--ease-tint) 100ms;
}
.nav__links .is-active:hover { opacity: 1; }

.nav__actions {
  position: absolute;
  right: 5.1%;
  top: 7.7%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 1.2vw;
  color: var(--ink);
  transition: color 700ms var(--ease-tint) 100ms;
}
.iconbtn { position: relative; display: block; width: 2.2vw; min-width: 26px; }
.iconbtn svg { width: 100%; height: auto; }
.iconbtn:hover { opacity: 0.72; }
.badge {
  position: absolute;
  top: -14%;
  right: -18%;
  min-width: 1.05em;
  height: 1.05em;
  padding: 0 0.18em;
  border-radius: 999px;
  background: var(--badge-bg);
  color: #fff;
  font-size: clamp(0.42rem, 0.66vw, 0.7rem);
  font-weight: 700;
  line-height: 1.05em;
  text-align: center;
}

/* ==========================================================================
   LEFT COLUMN
   ========================================================================== */
.lede { position: absolute; left: 6.1%; top: 27.6%; width: 28.4%; color: var(--ink); }
.lede__h1 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: var(--fs-h1);
  line-height: 1.2;                  /* measured baseline pitch 73px against a 61px cap-matched size */
  letter-spacing: 0.015em;
  font-feature-settings: 'liga' 1;   /* the fi ligature in Confidence/Define is in the reference */
}
.lede__p {
  margin-top: 1.02em;
  max-width: 21.4em;
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: -0.01em;
  color: var(--ink-soft);
  transition: color 700ms var(--ease-tint) 100ms;
}
.cta {
  display: inline-flex;
  align-items: center;
  gap: 0.85em;
  margin-top: 2.28em;
  padding: 0.78em 1.36em 0.78em 1.5em;
  border-radius: 999px;
  background: var(--cta-bg);
  color: var(--cta-ink);
  font-size: var(--fs-cta);
  font-weight: 600;
  letter-spacing: -0.005em;
  transition: background-color 700ms var(--ease-tint) 100ms,
              color 700ms var(--ease-tint) 100ms,
              transform 180ms ease-out;
}
.cta:hover { transform: translateY(-2px); }
.cta__chev { width: 0.72em; height: 0.72em; flex: none; }

/* ==========================================================================
   RIGHT COLUMN — both price lines and the pill row share the right edge 94.5%
   ========================================================================== */
.buy {
  position: absolute;
  right: 5.5%;
  top: 24.6%;
  text-align: right;
  color: var(--ink);
}
.buy__price {
  font-size: var(--fs-price);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;   /* the two lines column-align in the reference */
}
.buy__price--was { margin-top: 0.44em; text-decoration: line-through; opacity: 0.9; }
.buy__label {
  margin-top: 1.42em;
  font-size: var(--fs-size);
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--ink-soft);
  transition: color 700ms var(--ease-tint) 100ms;
}
.sizes { margin-top: 0.86em; display: flex; gap: 1.05vw; justify-content: flex-end; }
.size {
  width: 3.75vw;
  height: 3.75vw;
  min-width: 42px;
  min-height: 42px;
  border-radius: 999px;
  background: var(--chip-bg);
  color: var(--chip-ink);
  font-size: var(--fs-size);
  font-weight: 600;
  display: grid;
  place-items: center;
  transition: transform 160ms ease-out;
}
.size:hover { transform: scale(1.06); }
.size.is-active { background: var(--chip-on-bg); color: var(--chip-on-ink); }

/* ==========================================================================
   CAROUSEL — the shirt block (image + its own floor shadow) moves as one unit
   ========================================================================== */
.carousel { position: absolute; inset: 0; pointer-events: none; }

.shirtslot {
  position: absolute;
  left: 51.8%;
  top: 43.1%;
  width: var(--slot-w);
  transform: translate(-50%, -50%);
}
.shirtslot.is-idle { visibility: hidden; }
.shirt-x, .shirt-y { will-change: transform; }
.shirt__img { width: 100%; height: auto; }

/* Measured: a separate soft ellipse, centre (51.7%, 73.3%), core 20vw wide and 5.6vh
   tall. It sits INSIDE the moving block so it travels and scales with the shirt —
   proven separate because in trans_13 it has moved up and shrunk along with it.
   Expressed against the slot: 20vw / 38.2vw = 52.4% wide; the garment hem lands at
   80.7% of the slot height and the shadow centre sits ~2.3% lower. */
.shirt__shadow {
  position: absolute;
  left: 50%;
  top: 83%;
  width: 52.4%;
  aspect-ratio: 5.7 / 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.32);
  filter: blur(16px);
  z-index: -1;
}

/* a slow float is present even at rest in the reference (hook top drifts 145 <-> 165) */
.shirtslot:not(.is-swapping) .shirt-y { animation: bob 7s ease-in-out infinite; }
@keyframes bob {
  0%, 100% { transform: translateY(-0.9%); }
  50%      { transform: translateY(0.9%); }
}

/* ---------- arrows: rounded squares, symmetric about the shirt axis ---------- */
.arrow {
  position: absolute;
  top: 78.85%;
  width: 4.27%;
  min-width: 46px;
  aspect-ratio: 1;
  border-radius: 31%;
  background: var(--arrow-bg);
  color: var(--arrow-ink);
  display: grid;
  place-items: center;
  transition: background-color 700ms var(--ease-tint) 100ms, opacity 220ms ease-out;
}
.arrow svg { width: 52%; height: 52%; }
/* No hover state: the two frames that catch the cursor on an arrow (f_004 on prev,
   trans_09 on next) both read the same fill and size as an unhovered arrow. */
/* The arrows are symmetric about the SHIRT axis, not the page centre: measured +/-307px
   from x=777 in a frame where the garment was 445px wide, i.e. +/-0.537 of the slot
   width. Deriving them from the slot keeps that relationship at every aspect ratio —
   at the authored 1440x900 it resolves to exactly the measured 31.3% / 72.3%. */
.arrow--prev { left: calc(51.8% - 0.537 * var(--slot-w)); transform: translateX(-50%); }
.arrow--next { left: calc(51.8% + 0.537 * var(--slot-w)); transform: translateX(-50%); }
/* No hover or press transform either: the vanish below IS the click feedback in the
   reference, and neither hover frame shows a size change. */
.arrow:focus-visible { outline: 2px solid var(--arrow-ink); outline-offset: 3px; }
.is-locked .arrow { pointer-events: none; }

/* The clicked arrow vanishes and stays gone for several seconds — measured across all
   39 frames, it happens four separate times (next absent f_001-003 and f_023-027, prev
   absent f_009-013 and f_034-035), each run lasting 3-5 s, i.e. far longer than the
   swap itself. It fades rather than cuts: the tail samples read 0.97-0.98 of the
   background against 1.07 at full absence.
   Kept clickable while invisible — the frames only evidence opacity, and disabling the
   primary control for three seconds would be a usability regression the video can't
   justify. [JUDGEMENT CALL] 3 s absence, the middle of the observed range. */
.arrow.is-spent { opacity: 0; }
.arrow.is-returning { opacity: 1; transition: opacity 600ms ease-in; }

/* ---------- next-in-line preview ---------- */
.thumb {
  position: absolute;
  left: 91.1%;
  top: 85.3%;
  width: calc(var(--slot-w) * var(--thumb-scale));
  transform: translate(-50%, -50%);
  will-change: opacity, transform;
}
.thumb__img { width: 100%; height: auto; }
.thumb__shadow {
  position: absolute;
  left: 50%;
  top: 83%;
  width: 52.4%;
  aspect-ratio: 5.7 / 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.30);
  filter: blur(5px);
  z-index: -1;
}

/* ==========================================================================
   MOTTO + SOCIAL
   ========================================================================== */
.motto {
  position: absolute;
  left: 51.7%;
  top: 83.6%;
  transform: translateX(-50%);
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--fs-motto);
  line-height: 1.47;                 /* measured baseline pitch 53px on a 36px size */
  letter-spacing: 0.01em;
  text-align: center;
  white-space: nowrap;
  color: var(--ink);
}

.social {
  position: absolute;
  left: calc(6.7% - 0.8vw);          /* 6.7% is the FIRST ICON's centre, so back off half an icon */
  top: 87.4%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 2.1%;
  color: var(--social-ink);
}
.social a { display: block; width: 1.6vw; min-width: 17px; }
.social svg { width: 100%; height: auto; }
.social a:hover { opacity: 0.65; }

/* ==========================================================================
   SWAP CHOREOGRAPHY
   Timeline (t=0 is the click): bg fade 100/700; token tint 100/700;
   copy dip 100/800 bottoming at 45%; shirts 120/680-700; thumb 280/450.
   ========================================================================== */
.dip { animation: dip 800ms linear 100ms both; }
@keyframes dip {
  0%   { opacity: 1; }
  45%  { opacity: 0.55; }
  100% { opacity: 1; }
}

.thumb.is-arriving { animation: thumbIn 450ms cubic-bezier(0.22, 1, 0.36, 1) 280ms both; }
@keyframes thumbIn {
  from { opacity: 0; transform: translate(-50%, -50%) scale(0.85); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .shirtslot:not(.is-swapping) .shirt-y { animation: none; }
  #bgFront { transition-duration: 300ms; transition-delay: 0ms; }
  .lede, .buy, .nav__links, .motto, .social, .cta, .lede__p, .buy__label, .nav__actions {
    transition-duration: 250ms;
  }
  .dip, .thumb.is-arriving { animation: none; }
}

/* ==========================================================================
   Below the authored range the single-screen composition stops holding.
   Kept deliberately minimal: the reference is a desktop-only hero.
   ========================================================================== */
@media (max-width: 1100px) {
  .nav__links { display: none; }
  .lede { width: 46%; }
  :root { --slot-w: 80vh; }
}
