/* ============================================================================
   noir.css — landing-page-only layer, loaded LAST (after craft.css).

   The iteration this file carries: one continuous ink ground from masthead
   to footer, no paper bands, and no filled "shapes". Every surface the card
   system used to paint — steel testimonial card, surface cards in the feature
   grid and the blog grid, pill chips, the white proof strip, the cobalt field
   with its stroked marquee — is replaced by typography, photography and
   hairline rules. Cobalt stays the single accent: a tick before each label,
   the emphasised word in a headline, the plate beside the hero photo, the
   arrow on a link.

   Nothing structural changes. Tokens, fonts and motion all come from
   redesign.css / craft.css; this file only re-skins. Where an incumbent rule
   uses !important, the override here must as well — each such case is noted.
   ============================================================================ */

:root {
  --noir-hair: 1px solid var(--border);
  --noir-tick-w: 18px;
  /* One vertical rhythm for every band: the same space above and below. */
  --sec-pad: clamp(72px, 9vw, 120px);
}

/* ---------------------------------------------------------------------------
   0. Ground — one unbroken dark field, sections separated by hairlines only.
   --------------------------------------------------------------------------- */

.what,
.blog-preview,
.walsh-cta-green-wrapper {
  border-top: var(--noir-hair);
}

/* The proof strip keeps its own top rule. The reviews follow it with no
   rule between, so figures and quotation read as one band. */
.proof-strip { border-bottom: 0 !important; }

/* Footer sits on the same ink as the page, not the lifted band. !important
   matches redesign.css §5.5. */
.walsh-content-wrapper-white-2 { background-color: var(--bg) !important; }

/* ---------------------------------------------------------------------------
   1. Label system — one eyebrow for the whole page: mono, tracked, a short
   cobalt rule in front. Replaces the chip/pill tags that were filled shapes.
   --------------------------------------------------------------------------- */

.sec-eyebrow,
.walsh-cta-green-wrapper .walsh-tag-white,
.walsh-cta-green-wrapper .walsh-tag-white div {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 18px;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--fg-subtle);
  background: transparent !important;
  border: 0;
  border-radius: 0;
}

.sec-eyebrow::before,
.walsh-cta-green-wrapper .walsh-tag-white::before {
  content: "";
  display: inline-block;
  width: var(--noir-tick-w);
  height: 2px;
  background: var(--accent);
  flex: 0 0 auto;
}

/* The inner div of the legacy tag carries the text; it must not get a
   second tick or its own margin. */
.walsh-cta-green-wrapper .walsh-tag-white div { margin: 0; gap: 0; }
.walsh-cta-green-wrapper .walsh-tag-white div::before { content: none; }

/* ---------------------------------------------------------------------------
   2. Hero — a dateline above the masthead, a quieter rating line.
   --------------------------------------------------------------------------- */

.hero-kicker {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  margin: 0 0 clamp(18px, 2.4vw, 28px);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-subtle);
}

.hero-kicker > span { display: inline-flex; align-items: center; gap: 14px; }
.hero-kicker > span + span::before {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
}

@media (max-width: 991px) {
  .hero-kicker { justify-content: center; }
}

@media (max-width: 767px) {
  .hero-kicker { gap: 8px 12px; letter-spacing: 0.16em; }
}

.app-rating {
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-subtle);
}
.app-rating__stars {
  font-size: 12px;
  letter-spacing: 0.22em;
  color: var(--accent) !important;
}
.app-rating strong { color: var(--fg); font-weight: 400; }


/* Photo frame shows ink while the first frame decodes, not steel. */
.walsh-ui-image-wrapper { background: var(--c-neutral-50); }

/* -- The hero builds a look as you scroll ------------------------------------
   Left column: the first screen (kicker, headline, lead, badge), then eleven
   steps in large type. Right column: the stage, pinned to the viewport
   while the steps pass. The wrapper that framed a photograph now just
   places the stage: no clip, no frame, no plate (the plate is on .look). */
.walsh-background-darkgreen .walsh-ui-image-wrapper:has(.stage) {
  overflow: visible;
  aspect-ratio: auto;
  height: auto;
  width: auto;
  min-height: 0;
  max-height: none;
  background: transparent;
  border-radius: 0;
  box-shadow: none;
}
/* Polaroids and the share thread hang off the frame; clip (never hidden,
   which would break the sticky stage) keeps the page from scrolling
   sideways. */
.walsh-background-darkgreen:has(.stage) { overflow-x: clip; }

@media (min-width: 992px) {
  .walsh-background-darkgreen:has(.stage) { padding-bottom: var(--sec-pad); }
  /* The left column runs the full height of the steps; the stage column
     is one viewport tall and sticks while the row scrolls past. */
  .walsh-background-darkgreen .walsh-left-hero:has(.hero-steps) {
    align-self: start !important;
    padding-top: 0;
    padding-bottom: 0;
  }
  .walsh-background-darkgreen .walsh-ui-image-wrapper:has(.stage) {
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100dvh;
    padding: 96px 0 24px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    place-self: start end !important;
    /* Start the pinned column at the top of the viewport (under the
       floating nav, 128px, plus the band's top padding) so the frame is
       whole on the first screen and never moves when it pins. */
    margin-top: calc(-1 * var(--hero-pull, 128px));
  }
  /* Step 0: the headline block fills the first screen, as before. */
  .hero-intro {
    min-height: calc(100vh - 140px);
    min-height: calc(100dvh - 140px);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    gap: 2em;
  }
}
@media (min-width: 1200px) {
  /* The stage sizes its own column; the text takes the rest. */
  .walsh-background-darkgreen .walsh-main-grid-no-gap:has(.stage) {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
  }
}
@media (min-width: 1200px) and (max-width: 1499px) {
  /* craft.css runs this column to the viewport edge; the stage needs room
     on its right for the polaroids that hang out of the frame. */
  .walsh-background-darkgreen .walsh-ui-image-wrapper:has(.stage) {
    margin-right: clamp(64px, 6vw, 128px);
  }
}

/* -- The steps: large type scrolling past the stage ------------------------ */
.hero-steps {
  position: relative;
  list-style: none;
  margin: 0 0 30vh;
  padding: 0 0 0 32px;
  width: 100%;
}
.hero-steps::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--border);
}
.hero-steps__progress {
  position: absolute;
  left: -0.5px;
  top: 0;
  width: 2px;
  height: 0;
  background: var(--accent);
  transition: height 600ms var(--craft-ease);
}
.hero-step {
  min-height: 110vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin: 0;
  padding: 24px 0;
  border-top: var(--noir-hair);
}
/* The caption pins while its tall box scrolls through (the box is the
   scroll room for the stage's beats), and only the active step's caption
   shows; the next one fades in over it at the boundary. Without the
   script every step reads in place. */
.walsh-background-darkgreen.is-js .hero-step { justify-content: flex-start; }
.walsh-background-darkgreen.is-js .hero-step__body {
  position: sticky;
  opacity: 0;
  transition: opacity 400ms var(--craft-ease-io);
}
.walsh-background-darkgreen.is-js .hero-step.is-active .hero-step__body { opacity: 1; }
/* With captions pinned, the hairline between step boxes would scroll
   straight through the pinned title; the step boxes drop it and the
   caption carries its own short rule above the folio instead. */
.walsh-background-darkgreen.is-js .hero-step { border-top: 0; }
.walsh-background-darkgreen.is-js .hero-step__body { padding-top: 22px; }
.walsh-background-darkgreen.is-js .hero-step__body::before {
  content: "";
  display: block;
  width: 56px;
  height: 1px;
  background: var(--border);
  margin-bottom: 22px;
}
@media (max-width: 991px) {
  .walsh-background-darkgreen.is-js .hero-step__body::before { margin-inline: auto; }
}
@media (min-width: 992px) {
  /* Centred on the viewport midline; the negative margin keeps it pinned
     a little past its box so the hand-over happens in place. */
  .walsh-background-darkgreen.is-js .hero-step__body {
    top: 50%;
    transform: translateY(-50%);
    margin-bottom: -8rem;
  }
}
/* The stage scrubs each step's beats across its box (js/scrolly.js), so
   the steps with the most to show are the tallest. */
/* Scroll room per step. Pace is distance, not a rate cap (js/scrolly.js):
   at a reading scroll of ~500px/s a 220vh step takes about four seconds,
   and the beats sit in the middle 72% of the box with holds either side. */
.hero-step[data-step="1"] { min-height: 300vh; }
.hero-step[data-step="2"] { min-height: 220vh; }
.hero-step[data-step="3"] { min-height: 240vh; }
.hero-step[data-step="4"] { min-height: 220vh; }
.hero-step[data-step="5"] { min-height: 200vh; }
.hero-step[data-step="6"] { min-height: 180vh; }
.hero-step[data-step="7"] { min-height: 170vh; }
.hero-step[data-step="8"] { min-height: 200vh; }
.hero-step[data-step="9"] { min-height: 280vh; }
.hero-step[data-step="10"] { min-height: 260vh; }
.hero-step[data-step="11"] { min-height: 240vh; }
.hero-step__n {
  display: block;
  margin-bottom: 18px;
  font: 400 11px/1 var(--font-mono);
  letter-spacing: 0.14em;
  color: var(--accent);
}
.hero-step h3 {
  margin: 0 0 18px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.2rem, 3.2vw, 4.2rem);
  line-height: 0.98;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  color: var(--fg);
  text-wrap: balance;
}
.hero-step p {
  margin: 0;
  max-width: 30ch;
  font-family: var(--font-body);
  font-size: clamp(1.15rem, 1.4vw, 1.6rem);
  line-height: 1.45;
  color: color-mix(in srgb, var(--fg) 80%, transparent);
}

/* -- Phones and tablets ------------------------------------------------------
   The hero becomes one column: the headline block, then the stage pinned
   to the top of the screen, then the steps scrolling beneath it. The left
   column dissolves (display: contents) so its two parts can sit either
   side of the stage in one flex column; that column is the stage's sticky
   container. */
@media (max-width: 991px) {
  .walsh-background-darkgreen .walsh-main-grid-no-gap:has(.stage) {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }
  .walsh-background-darkgreen .walsh-left-hero:has(.hero-steps) { display: contents; }
  .hero-intro {
    order: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.5em;
    padding-top: 3em;
  }
  .walsh-background-darkgreen .walsh-ui-image-wrapper:has(.stage) {
    order: 2;
    position: sticky;
    top: 0;
    z-index: 3;
    width: 100%;
    margin-top: 32px;
    padding: 104px 0 14px;
    display: flex;
    justify-content: center;
    place-self: auto !important;
    background: linear-gradient(to bottom, var(--bg) 86%, transparent);
  }
  .hero-steps {
    order: 3;
    padding: 0 var(--content-padding);
    margin: 0 0 40vh;
    margin: 0 0 40dvh;
    box-sizing: border-box;
  }
  .hero-steps::before,
  .hero-steps__progress { display: none; }
  .hero-step {
    min-height: 100vh;
    min-height: 100dvh;
    padding: 0;
    border-top: 0;
    align-items: center;
    text-align: center;
  }
  /* The active step is the one crossing the middle of the screen, which
     sits behind the pinned stage; its caption pins 16px under the stage
     (104px padding + 11px head + 10px gap + frame + 14px = 139px + frame).
     The step changes when its box crosses the midline, above that line, so
     the caption may run past its box by up to (top - 50dvh) + its own
     height; the negative margin allows that. */
  .walsh-background-darkgreen.is-js .hero-step__body {
    align-self: stretch;
    top: calc(155px + min(50vh, 460px, (100vw - 48px) * 1.25));
    top: calc(155px + min(50dvh, 460px, (100vw - 48px) * 1.25));
    margin-bottom: calc(-155px - 12rem);
  }
  .hero-step h3 { font-size: clamp(1.6rem, 7vw, 2rem); margin-bottom: 10px; }
  .hero-step p { font-size: 16px; margin-inline: auto; }
  .hero-step__n { margin-bottom: 10px; }
  .walsh-background-darkgreen:has(.stage) { padding-bottom: 56px; }
}

/* Wide screens: the hero joins the page measure. craft.css lets the hero
   break out to full bleed, which is right on a laptop but on a 2000px
   display left the type at the viewport edge, the nav and every section
   below on a centred 1200px column, and a landscape crop of a portrait
   photograph. Above 1500px the hero sits on the same column as the nav and
   the photo keeps its 4:5 frame. !important matches craft.css, which pins
   the image placement with it. */
@media (min-width: 1500px) {
  :root {
    --wide-gutter: clamp(48px, 5vw, 200px);
    /* The page measure grows with the screen so sections, nav and hero
       share one left edge on very wide displays. */
    --max-width: min(2000px, calc(100vw - 2 * var(--wide-gutter)));
  }
  .walsh-inner-container-nav-float-2,
  .what__head, .what__grid, .more__head, .more__grid,
  .proof-strip__inner, .testimonials__inner,
  .blog-preview .walsh-container, .walsh-container-2 {
    max-width: var(--max-width);
  }
  .walsh-background-darkgreen > .walsh-container.w-container {
    /* Text column shares its left edge with the nav logo (the 1200px page
       measure); the stage is free to run wide to the right so the viewer
       scales with the screen. Asymmetric on purpose. */
    max-width: none;
    width: 100%;
    margin-inline: auto;
    /* Same left edge as the nav logo: the page measure's margin plus the
       nav container's own 20px inset. */
    padding-inline: calc(max(var(--wide-gutter), (100% - var(--max-width)) / 2) + 20px);
  }
  .walsh-background-darkgreen {
    --hero-pull: calc(128px + clamp(32px, 5vh, 64px));
    padding-top: clamp(32px, 5vh, 64px);
    padding-bottom: clamp(32px, 5vh, 64px);
  }
  .walsh-background-darkgreen .walsh-main-grid-no-gap {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: clamp(48px, 5vw, 110px);
    align-items: center;
  }
  .walsh-background-darkgreen .walsh-left-hero {
    max-width: 24vw;
    min-width: 560px;
    padding: 0;
  }
  /* Everything in the hero grows with the screen: no rem caps, so a 3000px
     display gets a 3000px hero rather than a 1400px one centred in it. */
  .walsh-background-darkgreen .walsh-left-hero .walsh-heading-large-black {
    font-size: clamp(5rem, 5.2vw, 9rem) !important;
  }
  .walsh-background-darkgreen .walsh-hero-p-wrapper .walsh-paragraph-serif-left-hero {
    font-size: clamp(1.125rem, 1.15vw, 1.75rem);
    max-width: 36ch;
  }
  .walsh-background-darkgreen .hero-kicker { font-size: clamp(11px, 0.7vw, 15px); }
  .walsh-background-darkgreen .app-store-badge img { height: clamp(54px, 3.4vw, 76px); }
  .walsh-background-darkgreen .app-rating { font-size: clamp(11px, 0.7vw, 14px); }
  .hero-step h3 { font-size: clamp(2.2rem, 2.6vw, 5rem); }
  .hero-step p { font-size: clamp(1.15rem, 1.1vw, 1.9rem); }
  .walsh-background-darkgreen .walsh-ui-image-wrapper {
    place-self: center end !important;
    aspect-ratio: 4 / 5;
    height: min(78vh, 820px);
    min-height: 0;
    max-height: none;
    width: auto;
    border-radius: 6px;
    box-shadow: 18px 0 0 0 var(--c-accent-500);
    margin-right: 18px;
  }
}

/* ---------------------------------------------------------------------------
   3. Proof strip — four figures in display type, columns divided by
   hairlines. Was a white band with bold sans numbers.
   --------------------------------------------------------------------------- */

.proof-strip__inner {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  padding: 0 var(--content-padding);
  text-align: left;
}

.proof-stat {
  min-width: 0;
  padding: clamp(22px, 3vw, 34px) clamp(18px, 2.6vw, 36px);
  gap: 8px;
}
.proof-stat + .proof-stat { border-left: var(--noir-hair); }

.proof-stat strong {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 3.4vw, 3.1rem);
  line-height: 0.95;
  letter-spacing: 0.005em;
  color: var(--fg) !important;
}

.proof-stat span {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  color: var(--fg-subtle);
}

@media (max-width: 719px) {
  .proof-strip__inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .proof-stat:nth-child(3) { border-left: 0; }
  .proof-stat:nth-child(n + 3) { border-top: var(--noir-hair); }
}

/* ---------------------------------------------------------------------------
   4. Two ingredients — Explore (the magazine) and Dress (the stylist), side
   by side. Each half: a cobalt chapter word, a label, a title and three
   numbered lines beside a phone cycling the mode's real screens. No card
   surface.
   --------------------------------------------------------------------------- */

.what {
  padding: var(--sec-pad) var(--content-padding);
  border-top: var(--noir-hair);
}

.what__head {
  max-width: var(--max-width);
  margin: 0 auto clamp(36px, 5vw, 64px);
}

.what__grid {
  max-width: var(--max-width);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(32px, 5vw, 80px);
}

.what__half {
  min-width: 0;
  overflow: visible;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(240px, 46%);
  grid-template-areas:
    "word word"
    "copy visual";
  column-gap: 28px;
  row-gap: 0;
  align-items: start;
}

.what__word {
  grid-area: word;
  display: block;
  margin: 0 0 28px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(3.4rem, 7vw, 7rem);
  line-height: 0.9;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--accent);
  position: relative;
  z-index: 4;
}

/* Copy (and its label) always sits above the fanned covers. */
.what__copy { grid-area: copy; min-width: 0; position: relative; z-index: 4; }

.what__n {
  display: block;
  white-space: nowrap;
  overflow: visible;
  margin: 0 0 28px;
  font: 400 11px/1 var(--font-mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
}

.what__copy h3 {
  margin: 0 0 36px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.6rem, 2.4vw, 2.3rem);
  line-height: 0.98;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  color: var(--fg);
  text-wrap: balance;
}

/* The features, said loudly: three lines, mono numerals, paper text,
   bold lead-ins, hairlines between. */
.what__list {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: what;
}
.what__list li {
  counter-increment: what;
  position: relative;
  margin: 0;
  padding: 18px 0 18px 36px;
  font: 500 clamp(1.1rem, 1.3vw, 1.35rem)/1.3 var(--font-body);
  color: var(--fg);
}
.what__list li + li { border-top: var(--noir-hair); }
.what__list li:first-child { padding-top: 0; }
.what__list li:first-child::before { top: calc(0.65em - 5.5px); }
.what__list li::before {
  content: counter(what, decimal-leading-zero);
  position: absolute;
  left: 0;
  /* Centred on the first line of text. */
  top: calc(18px + 0.65em - 5.5px);
  font: 400 11px/1 var(--font-mono);
  letter-spacing: 0.08em;
  color: var(--accent);
}
.what__list b { font-weight: 800; }
/* A quiet text link under the list (Dress: to the web outfit generator). */
.what__more {
  display: inline-block;
  margin-top: 22px;
  font: 400 12px/1.4 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg);
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
  padding-bottom: 4px;
  transition: color 200ms var(--craft-ease-io, ease);
}
.what__more:hover, .what__more:focus-visible { color: var(--accent); }

/* One phone per half: a slideshow of the mode's real screens, captioned
   underneath. Screens cross-fade; js/scrolly.js advances them. */
.what__phone {
  grid-area: visual;
  justify-self: end;
  width: min(100%, 360px);
}
.phone {
  position: relative;
  aspect-ratio: 9 / 19;
  width: 100%;
  padding: 10px;
  border-radius: 36px;
  background: var(--c-neutral-0);
  border: 1px solid rgba(244, 242, 237, 0.14);
  box-shadow: 0 50px 110px -40px rgba(0, 0, 0, 0.9);
  box-sizing: border-box;
}
.what__half--explore .phone { transform: rotate(-3deg); }
.what__half--dress .phone { transform: rotate(3deg); }
.phone__screens {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 28px;
  overflow: hidden;
  background: var(--c-neutral-50);
}
.phone__screen {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  transition: opacity 1100ms cubic-bezier(0.65, 0, 0.35, 1);
}
.phone__screen.is-on { opacity: 1; }
/* Every screen is a whole app screen, filling the phone from the top. */
.phone__screen img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: top;
}
/* Centred: the try-on result keeps its close button top-left. */
.phone__chip {
  position: absolute;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  padding: 7px 11px;
  border-radius: 999px;
  background: var(--c-neutral-0);
  color: var(--c-neutral-950);
  font: 400 10px/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.phone__captions {
  position: relative;
  /* Two lines of room: a long caption wraps on a narrow phone. */
  height: 3.2em;
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  font: 400 12px/1.6 var(--font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.phone__captions li {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  margin: 0;
  text-align: center;
  text-wrap: balance;
  color: var(--fg-subtle);
  opacity: 0;
  transition: opacity 600ms cubic-bezier(0.65, 0, 0.35, 1), color 600ms ease;
}
.phone__captions li.is-on { opacity: 1; color: var(--fg); }

/* Two registers. Explore is the magazine: a filled word, an editorial
   serif title, paper labels. Dress is the tool: an outlined word, the
   poster sans, cobalt labels. */
.what__half--explore .what__copy h3 {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(1.7rem, 2.4vw, 2.4rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-transform: none;
}
.what__half--explore .what__n,
.what__half--explore .what__list li::before { color: rgba(244, 242, 237, 0.6); }
.what__half--dress .what__word {
  color: transparent;
  -webkit-text-stroke: 2px var(--accent);
  paint-order: stroke;
}

/* Between 900 and 1200px a half is too narrow for copy beside the
   phone: the halves stay side by side, each stacks word, copy, phone.
   Phones stack the halves too. */
@media (max-width: 1199px) {
  .what__half {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "word" "copy" "visual";
  }
  .what__phone {
    justify-self: center;
    margin-top: 40px;
  }
}

/* Wide screens: the section grew with the viewport (vw-sized word, h2 and
   a 360px phone) until a ~2000px window at 100% no longer fit it on one
   screen. Above 1500px the type stops scaling and the phone is capped. */
@media (min-width: 1500px) {
  .what__word { font-size: clamp(3.4rem, 5.2vw, 6.4rem); }
  .what .walsh-heading-large-black { font-size: clamp(2.6rem, 3.4vw, 4.4rem); }
  .what__phone { width: min(100%, 380px); }
}

@media (max-width: 899px) {
  .what__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(56px, 12vw, 80px);
  }
  .what__phone { width: min(100%, 360px); }
}

/* ---------------------------------------------------------------------------
   5. More things it does — six tiles in a hairline grid. No filled boxes:
   a framed picture, an Anton title, one line.
   --------------------------------------------------------------------------- */

.more {
  padding: var(--sec-pad) var(--content-padding);
  border-top: var(--noir-hair);
}
.more__head {
  max-width: var(--max-width);
  margin: 0 auto clamp(28px, 4vw, 48px);
}
.more__grid {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  border-bottom: var(--noir-hair);
}
.tile {
  min-width: 0;
  margin: 0;
  padding: clamp(24px, 2.6vw, 36px);
  border-top: var(--noir-hair);
}
.tile:nth-child(3n + 2),
.tile:nth-child(3n + 3) { border-left: var(--noir-hair); }

/* Each tile's picture is a small composition of the feature itself, built
   in HTML and sized in cqw of the frame so it scales with the tile. */
.tile__media {
  --paper: #f4f2ed;
  --ink: var(--c-neutral-0);
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: 12px;
  overflow: hidden;
  border: var(--noir-hair);
  background: var(--c-neutral-50);
  container-type: inline-size;
  user-select: none;
  -webkit-user-select: none;
}
.tile__media img { display: block; }

/* A real app screen (images/app/proto), filling the frame from the top. */
.tile__media--screen img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
}

/* 1. Body shape: one look on three shapes, cross-fading (js/scrolly.js). */
.tshape {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  opacity: 0;
  transition: opacity 1300ms ease-in-out;
}
.tshape.is-on { opacity: 1; }
.tchip {
  position: absolute;
  top: 3cqw;
  left: 3cqw;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  padding: 1.2cqw 2.2cqw;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font: 400 max(10px, 2.2cqw)/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.tchip__names { display: inline-grid; }
.tchip__names b {
  grid-area: 1 / 1;
  font-weight: 400;
  opacity: 0;
  transition: opacity 1300ms ease-in-out;
}
.tchip__names b.is-on { opacity: 1; }

/* 2. Weather: the app's own weather sheet. */
.tile__media--weather img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 70%;
}

/* 3. Make your own edit: the prompt card, the feed it makes. */
.tedit {
  position: absolute;
  inset: 0;
  padding: 6cqw;
  background: #0e0e12;
  display: flex;
  flex-direction: column;
}
.tedit__k {
  font: 600 11px/1.2 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(244, 242, 237, 0.55);
}
.tedit__head {
  margin: 2cqw 0 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 9cqw;
  line-height: 0.98;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(244, 242, 237, 0.42);
}
.tedit__row {
  display: flex;
  gap: 3cqw;
  margin-top: 3.4cqw;
  padding-top: 3.4cqw;
  border-top: 1px solid rgba(244, 242, 237, 0.18);
}
.tedit__look {
  flex: 0 0 22cqw;
  aspect-ratio: 3 / 4;
  border-radius: 2cqw;
  background: center top / cover no-repeat;
}
.tedit__cta {
  margin-top: auto;
  align-self: flex-end;
  height: max(34px, 7.4cqw);
  padding: 0 max(16px, 3.6cqw);
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  background: var(--accent);
  color: var(--paper);
  font: 600 max(12px, 2.6cqw)/1 var(--font-body);
  white-space: nowrap;
}

/* 4. Shop only the gaps: the product card, as in the app. A square
   picture beside the name and price; the 4:3 frame has no room for it
   stacked above. */
.tprod {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 72cqw;
  padding: 3cqw;
  box-sizing: border-box;
  transform: translate(-50%, -50%);
  border-radius: 2.4cqw;
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.85);
  display: grid;
  grid-template-columns: 24cqw minmax(0, 1fr);
  grid-template-rows: auto auto 1fr;
  column-gap: 3.4cqw;
}
.tprod__img {
  grid-row: 1 / 4;
  aspect-ratio: 1;
  border-radius: 2cqw;
  background: #fff;
  overflow: hidden;
}
.tprod__img img { width: 100%; height: 100%; object-fit: contain; }
.tprod__brand {
  margin-top: 1cqw;
  font: 600 11px/1.2 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(10, 10, 11, 0.55);
}
.tprod__name {
  margin-top: 1cqw;
  font: 600 max(13px, 3cqw)/1.25 var(--font-body);
  color: var(--ink);
}
.tprod__price {
  align-self: end;
  display: flex;
  flex-direction: column;
  gap: 1cqw;
}
.tprod__price b { font: 800 max(15px, 3.6cqw)/1 var(--font-body); color: var(--ink); }
.tprod__price span {
  font: 400 max(9px, 2cqw)/1.2 var(--font-mono);
  letter-spacing: 0;
  white-space: nowrap;
  color: rgba(10, 10, 11, 0.55);
}
.tprod__cta {
  grid-column: 1 / -1;
  margin-top: 3cqw;
  height: max(34px, 7.4cqw);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--accent);
  color: var(--paper);
  font: 600 max(12px, 2.6cqw)/1 var(--font-body);
}

/* 5. Stylist notes: a portrait story, sized to the frame's height (a true
   9:16 at that height is too narrow for its caption, so 9:14). The chip
   is a sticker on its foot and may run past the story's edges. */
.tstory {
  position: absolute;
  left: 50%;
  top: 3.5cqw;
  bottom: 3.5cqw;
  aspect-ratio: 9 / 14;
  transform: translateX(-50%);
}
.tstory::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 2.4cqw;
  background:
    linear-gradient(to top, rgba(14, 14, 18, 0.94), rgba(14, 14, 18, 0) 58%),
    url(../images/looks/look-3.webp) center top / cover no-repeat;
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.85);
}
.tstory__bar {
  position: absolute;
  top: 2.4cqw;
  left: 2.4cqw;
  right: 2.4cqw;
  display: flex;
  gap: 0.8cqw;
}
.tstory__bar i {
  flex: 1 1 0;
  height: 2px;
  border-radius: 2px;
  background: rgba(244, 242, 237, 0.5);
}
.tstory__bar i:first-child { background: var(--accent); }
.tstory__play {
  position: absolute;
  left: 50%;
  top: 40%;
  width: max(26px, 6cqw);
  height: max(26px, 6cqw);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--paper);
  box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.8);
}
.tstory__play::after {
  content: "";
  position: absolute;
  left: 54%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 0.32em 0 0.32em 0.52em;
  border-color: transparent transparent transparent var(--ink);
  font-size: max(16px, 3.6cqw);
}
.tstory__foot {
  position: absolute;
  left: 2.6cqw;
  right: 2.6cqw;
  bottom: 2.6cqw;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.tstory__k {
  align-self: stretch;
  text-align: left;
  font: 400 max(9px, 1.9cqw)/1.2 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(244, 242, 237, 0.7);
}
.tstory__line {
  align-self: stretch;
  margin: 1.2cqw 0 2.4cqw;
  text-align: left;
  font: 800 max(13px, 3.2cqw)/1.15 var(--font-body);
  letter-spacing: -0.01em;
  color: var(--paper);
  text-wrap: balance;
}
.tstory__chip {
  padding: 1.4cqw 2.6cqw;
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font: 600 max(10px, 2.2cqw)/1 var(--font-body);
  white-space: nowrap;
  box-shadow: 0 10px 24px -10px rgba(0, 0, 0, 0.8);
}

/* 6. Keep it, share it: the saved look, and the thread it starts. */
.tshare__ground {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 22%;
  opacity: 0.55;
}
.tshare__heart {
  position: absolute;
  top: 3cqw;
  right: 3cqw;
  width: max(30px, 7cqw);
  height: max(30px, 7cqw);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--paper);
}
.tshare__heart svg { width: 50%; height: 50%; fill: var(--accent); }
.tshare {
  position: absolute;
  right: 3.4cqw;
  bottom: 3.4cqw;
  width: 78cqw;
  display: flex;
  flex-direction: column;
  gap: 1.6cqw;
}
.tshare__b {
  margin: 0;
  max-width: 88%;
  padding: 1.6cqw 2.6cqw;
  border-radius: 3cqw;
  font: 400 max(11px, 2.6cqw)/1.35 var(--font-body);
  box-shadow: 0 14px 30px -14px rgba(0, 0, 0, 0.75);
}
.tshare__b--link,
.tshare__b--out {
  align-self: flex-end;
  background: var(--paper);
  color: var(--ink);
  border-bottom-right-radius: 4px;
}
.tshare__b--in {
  align-self: flex-start;
  text-align: left;
  background: var(--accent);
  color: var(--paper);
  border-bottom-left-radius: 4px;
}
.tshare__b--link {
  display: flex;
  align-items: center;
  gap: 2cqw;
  padding: 1.4cqw 2.8cqw 1.4cqw 1.4cqw;
}
.tshare__thumb {
  flex: 0 0 10cqw;
  aspect-ratio: 3 / 4;
  border-radius: 1.5cqw;
  background: url(../images/anatomy/look-sneakers.webp) center top / cover no-repeat;
}
.tshare__b--link b {
  display: block;
  font: 600 max(11px, 2.6cqw)/1.25 var(--font-body);
  color: var(--ink);
}
.tshare__b--link em {
  display: block;
  margin-top: 0.8cqw;
  font: 400 max(8px, 1.8cqw)/1.2 var(--font-mono);
  font-style: normal;
  color: rgba(10, 10, 11, 0.5);
}

.tile > h3 {
  margin: 20px 0 8px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.3rem, 1.7vw, 1.6rem);
  line-height: 1;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  color: var(--fg);
}
.tile > p {
  margin: 0;
  max-width: 34ch;
  font: 400 16px/1.5 var(--font-body);
  color: var(--fg-muted);
}

@media (max-width: 899px) {
  .more__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tile:nth-child(3n + 2),
  .tile:nth-child(3n + 3) { border-left: 0; }
  .tile:nth-child(2n) { border-left: var(--noir-hair); }
}
@media (max-width: 599px) {
  .more__grid { grid-template-columns: minmax(0, 1fr); }
  .tile:nth-child(2n) { border-left: 0; }
  .tile { padding-left: 0; padding-right: 0; }
}

/* The journal's heading sits left with its eyebrow (it inherited centring). */
.blog-preview .walsh-heading-large-black { text-align: left; }

/* ---- Vertical rhythm: every band gets --sec-pad above and below. ------- */
.blog-preview { padding-block: var(--sec-pad); }
.blog-preview__more { margin-bottom: 0; }
.blog-preview__more > :last-child { margin-bottom: 0; }
.walsh-cta-green-wrapper .walsh-container-padding-large { padding-block: var(--sec-pad); }
.site-footer.walsh-content-wrapper-white-2 { padding: 72px 0 40px; }

/* ---------------------------------------------------------------------------
   8. Reviews — the steel card is gone. A large serif quotation on bare ink,
   stars as a small cobalt mark, the reviewer in mono.
   --------------------------------------------------------------------------- */

.testimonials .walsh-heading-large-black { text-align: center; }

/* The reviews close the proof band: no rule above, a shorter run-in. */
.testimonials {
  border-top: 0;
  padding: var(--sec-pad) var(--content-padding);
}
.testimonials .testimonials__inner { padding: 0; }
.testimonials .walsh-heading-large-black { margin-bottom: 0; }
.testimonials .reviews { margin-top: 28px; }
.testimonials .reviews__controls { margin-bottom: 0; }

.reviews.is-enhanced .reviews__viewport { max-width: 860px; }

/* !important: redesign.css §5.6 pins surface/border/radius on the card. */
.testimonial-card,
.reviews.is-enhanced .testimonial-card {
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  padding: clamp(8px, 2vw, 16px) 0 !important;
  transform: none !important;
}

.reviews.is-enhanced .testimonial-card__stars,
.testimonial-card__stars {
  font-size: 13px;
  letter-spacing: 0.3em;
  color: var(--accent) !important;
}

.reviews.is-enhanced .testimonial-card blockquote,
.testimonial-card blockquote {
  /* webflow.css gives every blockquote a 5px grey left bar and padding. */
  border: 0;
  padding: 0;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(1.45rem, 2.9vw, 2.3rem);
  line-height: 1.28;
  letter-spacing: -0.012em;
  color: var(--fg);
  margin: 0;
}

.testimonial-card__who {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-subtle);
}
.testimonial-card__who strong { color: var(--fg); font-weight: 400; }

.reviews__nav {
  border-color: var(--border);
  color: var(--fg-muted);
}
.reviews__nav:hover {
  background: transparent;
  border-color: var(--accent);
  color: var(--accent);
}

/* ---------------------------------------------------------------------------
   9. From the journal — the four cards become an index: tag, serif title and
   dek in columns, a cobalt arrow at the end of each row, hairlines between.
   --------------------------------------------------------------------------- */

.blog-preview .features__grid {
  display: block;
  border-top: var(--noir-hair);
  margin-top: clamp(20px, 3vw, 32px);
}

/* !important: redesign.css §5.6 pins surface/border/radius on the card. */
.blog-preview__card {
  display: grid;
  grid-template-columns: 170px minmax(0, 1fr) auto;
  grid-template-areas:
    "tag title arrow"
    "tag dek   arrow";
  column-gap: clamp(20px, 3vw, 40px);
  row-gap: 6px;
  align-items: start;
  padding: clamp(22px, 2.6vw, 30px) 0 !important;
  background: transparent !important;
  border: 0 !important;
  border-bottom: var(--noir-hair) !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  transform: none !important;
  text-decoration: none;
}

.blog-preview__card .walsh-label-tag {
  grid-area: tag;
  display: block;
  margin: 0;
  padding: 0.35em 0 0;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-subtle);
  background: transparent !important;
  border: 0;
  border-radius: 0;
}

.blog-preview__card h3 {
  grid-area: title;
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(1.3rem, 2vw, 1.7rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--fg) !important;
  transition: color 240ms ease;
}

.blog-preview__card p {
  grid-area: dek;
  margin: 0;
  max-width: 62ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--fg-muted);
}

.blog-preview__card::after {
  content: "→";
  grid-area: arrow;
  align-self: center;
  font-family: var(--font-mono);
  font-size: 20px;
  color: var(--accent);
  transition: transform 320ms var(--craft-ease);
}

@media (hover: hover) {
  .blog-preview__card:hover h3 { color: var(--accent) !important; }
  .blog-preview__card:hover::after { transform: translateX(8px); }
}

.blog-preview__more {
  margin-top: clamp(22px, 3vw, 32px);
  text-align: left;
}
.blog-preview__more p {
  margin: 0 0 14px;
  font-size: 15px;
  color: var(--fg-muted);
}
.blog-preview__more p a { color: var(--fg); }
.blog-preview__more .walsh-nav-link-black {
  padding: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400 !important;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg);
}

@media (max-width: 719px) {
  .blog-preview__card {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "tag" "title" "dek";
  }
  .blog-preview__card::after { display: none; }
  .blog-preview__card .walsh-label-tag { padding-top: 0; }
}

/* ---------------------------------------------------------------------------
   10. Closing — the cobalt field and its stroked marquee are retired. The
   page ends the way it began: ink, poster type, one cobalt word, and a low
   cobalt bloom rising from the foot of the band.
   --------------------------------------------------------------------------- */

/* !important: craft.css §7 pins the cobalt field with !important. */
.walsh-cta-green-wrapper {
  background-color: var(--bg) !important;
  background-image: radial-gradient(
    70% 60% at 50% 110%,
    color-mix(in srgb, var(--c-accent-500) 30%, transparent),
    transparent 70%
  );
}

.craft-marquee { display: none !important; }

.walsh-cta-green-wrapper .walsh-heading-large-white { color: var(--fg) !important; }
.walsh-cta-green-wrapper .walsh-heading-large-white em {
  font-style: normal;
  color: var(--accent);
}
.walsh-cta-green-wrapper .walsh-main-paragraph-white { color: var(--fg-muted); }

/* ---------------------------------------------------------------------------
   11. Reduced motion — the only transition this file adds is the arrow slide.
   --------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .blog-preview__card::after { transition: none; }
}

/* ---------------------------------------------------------------------------
   12. Formatting — poster headlines must not leave a one-word last line.
   --------------------------------------------------------------------------- */

.walsh-heading-large-black,
.walsh-heading-large-white,
.blog-preview__card h3 {
  text-wrap: balance;
}

/* ---------------------------------------------------------------------------
   13. The stage — how a look is built: one canvas, eleven states, in the
   hero's right column, scrubbed by scroll. js/scrolly.js writes data-step
   on .stage and .look, .is-on on every layer carrying data-at / data-until
   (these gate whole states), and per frame --p (0..1 through the list)
   and --p1..--p11 (0..1 through each step's own box) on .stage. Every beat
   inside a step is a paused keyframe animation whose delay is that
   progress (see "The scrub" below): scrolling plays it, stopping holds
   it, scrolling back rewinds it. Generic rules own opacity only, as short
   fades at step boundaries. Reduced motion pins every beat to its last
   frame. Without the script the stage rests on the step-3 cover (colour
   photo, dateline, masthead, heart).

   Step <-> layer (data-at..data-until):
     0  .look__mono duotone over the photo (also under step 1)
     1  .look__profile                       1..1  taste, colour, wardrobe
     2  .look__wall + .wall__folio chip      2..3  wall drifts, 6 of 20 ring
     3  .look__wall zooms into the hero tile; .look__shape[pear] under it
        .look__ink, .look__dateline,         3..6  rise after the zoom
        .look__masthead                      3..6
        .look__heart                         3..   (fills at 11)
     4  .look__model chip; four shapes       4..4  (dateline fades for it)
     5  .look__pieces polaroids              5..6
     6  .look__product                       6..6  (masthead steps aside)
     7  .look__sheet styling tip             7..7
     8  .look__advice                        8..8
     9  .look__you photo -> avatar -> on you 9..9
    10  .look__ask, .look__spot, .look__wipe 10..10; .look__edited 10..
    11  .look__mat, .look__ghost, .look__share 11.. (tilts onto the mat)

   Type inside the stage follows the app (v2.4.0): Anton titles, Space Mono
   for dates and numbers only, Inter for labels, captions and body.
   --------------------------------------------------------------------------- */

.stage {
  --look-h: min(calc(100vh - 290px), 56vw);
  --look-h: min(calc(100dvh - 290px), 56vw);
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: calc(var(--look-h) * 0.8);
  max-width: 100%;
  perspective: 1200px;
  scroll-margin-top: 90px;
  --p: 0;
  --p1: 0; --p2: 0; --p3: 0; --p4: 0; --p5: 0; --p6: 0;
  --p7: 0; --p8: 0; --p9: 0; --p10: 0; --p11: 0;
}

/* Head: just the eyebrow above the frame; the step text is on the left. */
.stage__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}
.stage__head .sec-eyebrow { margin: 0; }

/* -- The scrub ------------------------------------------------------------
   Every beat is a 1s keyframe animation held paused, its negative delay
   the scroll position: delay = -((progress - a) / (b - a)) s. An element
   names its step's progress (--k: var(--pN)) and the slice of that step
   it plays across (--a..--b); a delay past -1s holds the last frame and a
   positive one the first, so a beat rests at its start before --a and at
   its end after --b, and a later step sees every earlier beat finished.
   Rules below set animation-name (and timing) only; an element with two
   beats lists both names and both delays. Zero specificity, so any rule
   below wins. ------------------------------------------------------------- */
:where(.stage .look, .stage .look *),
:where(.stage .look *)::before,
:where(.stage .look *)::after {
  --scrub: calc((var(--k, 0) - var(--a, 0)) / (var(--b, 1) - var(--a, 0)) * -1s);
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-play-state: paused;
  animation-delay: var(--scrub);
}
@keyframes noir-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* -- The canvas ------------------------------------------------------------ */
.look {
  --paper: #f4f2ed;
  --ink: var(--c-neutral-0);
  --ink-glass: rgba(14, 14, 18, 0.78);
  --folio: 400 10px/1.3 var(--font-mono);
  --glow: 0 0 max(18px, 3.4cqw) max(3px, 0.6cqw) color-mix(in srgb, var(--c-accent-500) 70%, transparent);
  position: relative;
  flex: 0 0 auto;
  height: var(--look-h);
  aspect-ratio: 4 / 5;
  transition: box-shadow 300ms var(--craft-ease-io);
  max-width: 100%;
  border-radius: 18px;
  overflow: visible;
  container-type: inline-size;
  isolation: isolate;
  font-family: var(--font-body);
  color: var(--paper);
  transform-origin: 50% 45%;
}
/* The cobalt plate the hero photo used to carry: outboard on a laptop,
   inboard from 1200px (the polaroids hang out on the right), none on
   phones, and none once the page lifts onto its mat at step 11.
   !important: redesign.css styles an unrelated .look (another page's
   card) with a surface, a border and no shadow, all !important. */
.stage .look {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
}
@media (min-width: 992px) {
  .stage .look { box-shadow: 18px 0 0 0 var(--c-accent-500) !important; }
}
@media (min-width: 1200px) {
  .stage .look { box-shadow: -18px 0 0 0 var(--c-accent-500) !important; }
}
.stage .look[data-step="11"] { box-shadow: none !important; }

/* Every layer: hidden until .is-on. Opacity only here — each layer owns its
   transform further down. Short fades, so a step boundary is soft; the
   beats themselves are scrubbed. */
.look [data-at] {
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms cubic-bezier(0.65, 0, 0.35, 1), transform 300ms var(--craft-ease);
}
.look [data-at].is-on { opacity: 1; }

/* -- 1. Photo: four body shapes; a cobalt duotone over them at step 0 ----- */
.look__photo {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 18px;
  background: #0e0e12;
  box-shadow: 0 50px 120px -40px rgba(0, 0, 0, 0.9);
}
.look__photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
}
.look__shape { opacity: 0; }
.look__shape[data-shape="pear"] { opacity: 1; }
/* Step 4: pear rests underneath; each next shape fades in over the last
   (which then drops out, covered), and inverted fades away back to pear:
   hourglass 0.10-0.35, rectangle 0.40-0.60, inverted 0.65-0.85, pear
   0.90-1.00 of the step. */
.look[data-step="4"] .look__shape { --k: var(--p4); }
.look[data-step="4"] .look__shape[data-shape="hourglass"] { animation-name: noir-shape-hourglass; }
.look[data-step="4"] .look__shape[data-shape="rectangle"] { animation-name: noir-shape-rectangle; }
.look[data-step="4"] .look__shape[data-shape="inverted"]  { animation-name: noir-shape-inverted; }
@keyframes noir-shape-hourglass {
  0%, 10% { opacity: 0; animation-timing-function: ease-in-out; }
  35%, 60% { opacity: 1; }
  60.1%, 100% { opacity: 0; }
}
@keyframes noir-shape-rectangle {
  0%, 40% { opacity: 0; animation-timing-function: ease-in-out; }
  60%, 85% { opacity: 1; }
  85.1%, 100% { opacity: 0; }
}
@keyframes noir-shape-inverted {
  0%, 65% { opacity: 0; animation-timing-function: ease-in-out; }
  85% { opacity: 1; }
  90% { opacity: 1; animation-timing-function: ease-in-out; }
  100% { opacity: 0; }
}

.look__mono {
  position: absolute;
  inset: 0;
  isolation: isolate;
  clip-path: inset(0 0 100% 0);
}
.look__mono img { filter: grayscale(1) contrast(1.15) brightness(0.85); }
.look__duo {
  position: absolute;
  inset: 0;
  background: var(--accent);
  mix-blend-mode: color;
}
/* The model rests as a faint duotone before the steps and under the
   profile (steps 0-1); from step 2 the wall covers it and it clears. */
.look:is([data-step="0"], [data-step="1"]) .look__mono { clip-path: inset(0); }
.look[data-step="2"] .look__mono {
  --k: var(--p2); --a: 0; --b: 0.12;
  animation-name: noir-mono-out;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-mono-out {
  from { clip-path: inset(0); }
  to   { clip-path: inset(0 0 100% 0); }
}
.stage:not(.is-js) .look .look__mono { clip-path: inset(0 0 100% 0); }

.look__ink {
  position: absolute;
  inset: 0;
  /* Bottom: the masthead's scrim. Top: a faint band so the dateline reads
     on a pale wall. */
  background:
    linear-gradient(to top, rgba(14, 14, 18, 0.92), rgba(14, 14, 18, 0) 58%),
    linear-gradient(to bottom, rgba(14, 14, 18, 0.5), rgba(14, 14, 18, 0) 18%);
}

/* -- 2. "Modelled on" chip (step 4): names the shape on show --------------- */
.look .look__model {
  position: absolute;
  top: max(12px, 2.6cqw);
  left: max(12px, 2.6cqw);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  padding: max(6px, 1.2cqw) max(10px, 2cqw);
  border-radius: 999px;
  background: var(--c-neutral-0);
  color: var(--paper);
  font: 400 max(10px, 2cqw)/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.look__model-name { display: inline-grid; }
.look__model-name b {
  grid-area: 1 / 1;
  font-weight: 400;
  opacity: 0;
}
.look__model-name b[data-shape="pear"] { opacity: 1; }
/* The name swaps just before each photo is half in. */
.look[data-step="4"] .look__model-name b { --k: var(--p4); }
.look[data-step="4"] .look__model-name b[data-shape="pear"]      { animation-name: noir-chip-pear; }
.look[data-step="4"] .look__model-name b[data-shape="hourglass"] { animation-name: noir-chip-hourglass; }
.look[data-step="4"] .look__model-name b[data-shape="rectangle"] { animation-name: noir-chip-rectangle; }
.look[data-step="4"] .look__model-name b[data-shape="inverted"]  { animation-name: noir-chip-inverted; }
@keyframes noir-chip-pear      { 0%, 19% { opacity: 1; } 23%, 92% { opacity: 0; } 96%, 100% { opacity: 1; } }
@keyframes noir-chip-hourglass { 0%, 19% { opacity: 0; } 23%, 45% { opacity: 1; } 49%, 100% { opacity: 0; } }
@keyframes noir-chip-rectangle { 0%, 45% { opacity: 0; } 49%, 70% { opacity: 1; } 74%, 100% { opacity: 0; } }
@keyframes noir-chip-inverted  { 0%, 70% { opacity: 0; } 74%, 92% { opacity: 1; } 96%, 100% { opacity: 0; } }

/* -- 5. Dateline, top left ---------------------------------------------------- */
.look__dateline {
  position: absolute;
  top: max(18px, 3.4cqw);
  left: max(18px, 3.4cqw);
  right: calc(max(34px, 7cqw) + 2 * max(12px, 2.6cqw));
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.look__dateline span {
  display: block;
  width: max-content;
  max-width: 100%;
  font: var(--folio);
  font-size: max(10px, 2cqw);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--paper);
  text-shadow: 0 1px 6px rgba(14, 14, 18, 0.5);
  clip-path: inset(0 100% 0 0);
}
.look__dateline span + span { color: rgba(244, 242, 237, 0.62); }
.look__dateline.is-on span {
  clip-path: inset(0);
  --k: var(--p3); --a: 0.6; --b: 0.68;
  animation-name: noir-dateline;
  animation-timing-function: var(--craft-ease);
}
.look__dateline.is-on span + span { --a: 0.63; --b: 0.72; }
@keyframes noir-dateline {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0); }
}

/* -- 6. Masthead over the ink scrim ------------------------------------------ */
.look__masthead {
  position: absolute;
  left: max(20px, 3.8cqw);
  right: max(20px, 3.8cqw);
  bottom: max(20px, 3.8cqw);
}
.look__head {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: max(26px, 9cqw);
  line-height: 0.98;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  color: var(--paper);
}
.look__head .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.04em;
}
.look .w { display: inline-block; }
.look__dot { color: var(--accent); }
/* Step 3: word by word over 0.65-0.90; step 10: over 0.10-0.37. */
.look__masthead.is-on .w,
.look__ask.is-on .w {
  --k: var(--p3);
  --a: calc(0.65 + var(--i) * 0.025);
  --b: calc(0.775 + var(--i) * 0.025);
  animation-name: noir-word;
  animation-timing-function: var(--craft-ease);
}
.look__ask.is-on .w {
  --k: var(--p10);
  --a: calc(0.1 + var(--i) * 0.03);
  --b: calc(0.25 + var(--i) * 0.03);
}
@keyframes noir-word {
  from { transform: translateY(105%) rotate(2deg); }
  to   { transform: none; }
}

/* Heart, top right — fills cobalt when the look is saved. */
.look .look__heart {
  position: absolute;
  top: max(12px, 2.6cqw);
  right: max(12px, 2.6cqw);
  width: max(34px, 7cqw);
  height: max(34px, 7cqw);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(14, 14, 18, 0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  z-index: 5;
}
/* Rises last on step 3 (0.85-0.95); pops cobalt on step 11 (0.25-0.35). */
.look .look__heart.is-on {
  --k: var(--p3); --a: 0.85; --b: 0.95;
  animation-name: noir-fade-in;
}
.look__heart svg {
  width: 47%;
  height: 47%;
  fill: transparent;
  stroke: var(--paper);
  stroke-width: 1.6;
}
.look[data-step="11"] .look__heart { background: rgba(244, 242, 237, 0.92); }
.look[data-step="11"] .look__heart.is-on {
  animation-name: noir-fade-in, noir-heart-bg;
  animation-delay: var(--scrub), calc((var(--p11) - 0.25) / 0.1 * -1s);
}
.look[data-step="11"] .look__heart svg {
  fill: var(--accent);
  stroke: var(--accent);
  --k: var(--p11); --a: 0.25; --b: 0.35;
  animation-name: noir-heart-pop;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-heart-bg {
  from { background-color: rgba(14, 14, 18, 0.55); }
  to   { background-color: rgba(244, 242, 237, 0.92); }
}
@keyframes noir-heart-pop {
  0%   { transform: scale(1); fill: transparent; stroke: var(--paper); }
  1%   { transform: scale(0.6); fill: var(--accent); stroke: var(--accent); }
  55%  { transform: scale(1.35); fill: var(--accent); stroke: var(--accent); }
  100% { transform: scale(1); fill: var(--accent); stroke: var(--accent); }
}
/* -- 7. Pieces: pins on the garments, polaroids dealt to the right edge ---- */
.look__pieces { position: absolute; inset: 0; z-index: 2; }
.look__pin,
.look__spot > i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: max(10px, 2cqw);
  height: max(10px, 2cqw);
  margin: 0;
  translate: -50% -50%;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px rgba(244, 242, 237, 0.95);
}

.pol {
  --w: max(90px, 24cqw);
  position: absolute;
  width: var(--w);
  padding: max(6px, 1.2cqw) max(6px, 1.2cqw) max(22px, 4.8cqw);
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.8);
  opacity: 0;
  /* Dealt from the middle of the figure. */
  transform: translate(var(--dx, -44cqw), var(--dy, 0)) scale(0.6) rotate(0deg);
}
.pol--dress  { right: -6%;  top: 14%; --r: -7deg; --dy: 24cqw; }
.pol--tote   { right: -10%; top: 40%; --r: 5deg;  --dy: -8cqw; }
.pol--wedges { right: -4%;  top: 66%; --r: -3deg; --dy: -40cqw; }
/* Step 5: dealt one after another over 0.10-0.60; the pins pop on the
   garments over 0.50-0.75. */
.look__pieces.is-on .pol {
  opacity: 1;
  transform: rotate(var(--r));
  --k: var(--p5);
  --a: calc(0.1 + var(--i) * 0.15);
  --b: calc(0.3 + var(--i) * 0.15);
  animation-name: noir-deal;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-deal {
  from { opacity: 0; transform: translate(var(--dx, -44cqw), var(--dy, 0)) scale(0.6) rotate(0deg); }
  to   { opacity: 1; transform: translate(0, 0) scale(1) rotate(var(--r)); }
}
.look__pieces.is-on .look__pin {
  --k: var(--p5); --a: 0.5; --b: 0.6;
  animation-name: noir-pin-in;
  animation-timing-function: var(--craft-ease);
}
.look__pieces.is-on .look__pin:nth-child(2) { --a: 0.575; --b: 0.675; }
.look__pieces.is-on .look__pin:nth-child(3) { --a: 0.65; --b: 0.75; }
@keyframes noir-pin-in {
  from { opacity: 0; scale: 0; }
  to   { opacity: 1; scale: 1; }
}
/* Step 6: the tote steps back (0.10-0.30) while its product card rises. */
.look[data-step="6"] .look__pieces.is-on .pol--tote {
  opacity: 0.35;
  animation-name: noir-deal, noir-dim;
  animation-delay: var(--scrub), calc((var(--p6) - 0.1) / 0.2 * -1s);
}
@keyframes noir-dim {
  from { opacity: 1; }
  to   { opacity: 0.35; }
}
.pol__img {
  aspect-ratio: 1;
  background-image: url(../images/anatomy/look-pear.webp);
  background-size: 320%;
  background-repeat: no-repeat;
}
.pol__cap {
  position: absolute;
  left: max(6px, 1.2cqw);
  right: max(6px, 1.2cqw);
  bottom: max(6px, 1.3cqw);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px;
}
.pol__name {
  font: 400 max(9px, 1.8cqw)/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.pol__stamp {
  font: 600 max(8px, 1.6cqw)/1 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
}
.pol__stamp--shop { color: var(--accent); }

/* -- 8. Shop: the missing piece rises from its polaroid to a product card - */
.look .look__product {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 4;
  width: max(220px, 62cqw);
  padding: max(12px, 2.6cqw);
  border-radius: max(10px, 2.4cqw);
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.85);
  display: flex;
  flex-direction: column;
  transform: translate(-50%, -50%) translate(36cqw, -4%) scale(0.6);
}
/* Step 6: the card grows out of the tote's polaroid over 0.10-0.40. */
.look .look__product.is-on {
  transform: translate(-50%, -50%) translate(0, 0) scale(1);
  --k: var(--p6); --a: 0.1; --b: 0.4;
  animation-name: noir-product-in;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-product-in {
  from { opacity: 0; transform: translate(-50%, -50%) translate(36cqw, -4%) scale(0.6); }
  30%  { opacity: 1; }
  to   { opacity: 1; transform: translate(-50%, -50%) translate(0, 0) scale(1); }
}
/* The masthead would peek out either side of the card; it steps aside. */
.look[data-step="6"] .look__masthead.is-on {
  --k: var(--p6); --a: 0.05; --b: 0.2;
  animation-name: noir-fade-out;
}
.look__product-img {
  aspect-ratio: 1;
  border-radius: max(8px, 1.6cqw);
  background: #fff;
  overflow: hidden;
}
.look__product-img img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.look__product-brand {
  margin-top: max(10px, 2.2cqw);
  font: 600 max(10px, 2cqw)/1.2 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(10, 10, 11, 0.55);
}
.look__product-name {
  margin-top: max(3px, 0.6cqw);
  font: 600 max(14px, 2.9cqw)/1.25 var(--font-body);
  color: var(--ink);
}
.look__product-price {
  margin-top: max(6px, 1.4cqw);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.look__product-price b { font: 800 max(16px, 3.6cqw)/1 var(--font-body); color: var(--ink); }
.look__product-price span {
  font: 400 max(9px, 1.8cqw)/1.2 var(--font-mono);
  letter-spacing: 0.04em;
  color: rgba(10, 10, 11, 0.55);
}
.look__product-cta {
  margin-top: max(10px, 2.2cqw);
  height: max(36px, 7.4cqw);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--accent);
  color: var(--paper);
  font: 600 max(12px, 2.5cqw)/1 var(--font-body);
}

/* -- 9. Frosted sheet: the styling tip (step 7) ---------------------------- */
.look__clip {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 18px;
  pointer-events: none;
  z-index: 2;
}
.look .look__sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: max(16px, 3.6cqw) max(16px, 3.6cqw) max(18px, 4cqw);
  border-radius: 18px 18px 0 0;
  background: var(--ink-glass);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  transform: translateY(100%);
}
/* Step 7: the sheet slides up over 0.05-0.35, its rule grows 0.35-0.50. */
.look .look__sheet.is-on {
  transform: none;
  --k: var(--p7); --a: 0.05; --b: 0.35;
  animation-name: noir-sheet-up;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-sheet-up {
  from { transform: translateY(100%); }
  to   { transform: none; }
}
.look__k {
  display: block;
  margin-bottom: max(8px, 1.6cqw);
  font: 600 max(10px, 2cqw)/1.2 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-accent-300);
}
.look__tip {
  position: relative;
  padding-left: max(14px, 2.8cqw);
}
.look__tip::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: top;
}
.look__sheet.is-on .look__tip::before {
  transform: scaleY(1);
  --a: 0.35; --b: 0.5;
  animation-name: noir-bracket;
  animation-timing-function: var(--craft-ease);
}
.look__tip p {
  margin: 0;
  font: 800 max(17px, 4.2cqw)/1.15 var(--font-body);
  letter-spacing: -0.01em;
  color: var(--paper);
  text-wrap: pretty;
}

/* -- 10. Why it suits you: an advice card in the look's own blue (step 8) - */
.look .look__advice {
  position: absolute;
  left: max(12px, 2.4cqw);
  right: max(12px, 2.4cqw);
  bottom: max(12px, 2.4cqw);
  top: 38%;
  z-index: 3;
  padding: max(14px, 3cqw);
  border-radius: max(10px, 2.4cqw);
  background: #cfdde6;
  color: var(--ink);
  border: 1px solid rgba(0, 0, 0, 0.16);
  box-shadow: 0 30px 70px -30px rgba(0, 0, 0, 0.8);
  display: grid;
  grid-template-columns: minmax(0, 1fr) max(80px, 20cqw);
  gap: max(12px, 2.6cqw);
  align-items: stretch;
  transform: translateY(24px);
}
/* Step 8: the card 0.05-0.30, the rows 0.30-0.70, the bracket 0.70-0.90. */
.look .look__advice.is-on {
  transform: none;
  --k: var(--p8); --a: 0.05; --b: 0.3;
  animation-name: noir-advice-in;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-advice-in {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}
.look__advice-text {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.look__advice-text .adv { flex: 1 1 auto; align-content: center; }
.look__advice-k {
  display: block;
  margin-bottom: 4px;
  font: 600 max(10px, 2cqw)/1.2 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(10, 10, 11, 0.6);
}
.adv {
  margin: 0;
  padding: max(10px, 2cqw) 0;
  display: grid;
  grid-template-columns: max(56px, 11cqw) minmax(0, 1fr);
  gap: max(10px, 2cqw);
  align-items: baseline;
}
.adv + .adv { border-top: 1px solid rgba(10, 10, 11, 0.14); }
.adv b {
  font: 400 max(9px, 1.9cqw)/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}
.adv span {
  font: 500 max(13px, 2.8cqw)/1.4 var(--font-body);
  color: var(--ink);
}
.look__advice.is-on .adv {
  --a: calc(0.3 + var(--i) * 0.13);
  --b: calc(0.44 + var(--i) * 0.13);
  animation-name: noir-adv;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-adv {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.look__advice-crop {
  position: relative;
  align-self: start;
  width: 100%;
  aspect-ratio: 4 / 5;
  border-radius: max(8px, 1.8cqw);
  background: url(../images/anatomy/look-pear.webp) 50% 38% / 300% no-repeat;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.16);
}
/* A tailor's bracket from the waist to the hem: two cobalt rules joined on
   the right, drawn top to bottom after the rows. */
.look__advice-crop::before {
  content: "";
  position: absolute;
  left: 22%;
  right: 8px;
  top: 30%;
  height: 42%;
  border: 2px solid var(--accent);
  border-left: 0;
  transform-origin: top;
}
.look__advice-crop::after {
  content: "";
  position: absolute;
  right: 3px;
  top: calc(51% - 1px);
  width: 5px;
  height: 2px;
  background: var(--accent);
}
.look__advice.is-on .look__advice-crop::before {
  --a: 0.7; --b: 0.85;
  animation-name: noir-bracket;
  animation-timing-function: var(--craft-ease);
}
.look__advice.is-on .look__advice-crop::after {
  --a: 0.82; --b: 0.9;
  animation-name: noir-adv;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-bracket {
  from { transform: scaleY(0); }
  to   { transform: scaleY(1); }
}

/* -- 11. See it on you: photo -> avatar -> outfit (step 9) ---------------- */
.look .look__you {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  border-radius: 18px;
  background: rgba(14, 14, 18, 0.55);
}
.you__avatar,
.you__fit {
  position: absolute;
  inset: 0;
}
.you__avatar { background: #efebe4; }
.you__avatar img,
.you__fit img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}
.you__scan {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 2px;
  margin-top: -1px;
  background: var(--accent);
  box-shadow: var(--glow);
  opacity: 0;
}
.you__photo {
  position: absolute;
  left: 8%;
  top: 12%;
  width: 44cqw;
  margin: 0;
  padding: max(8px, 1.6cqw) max(8px, 1.6cqw) max(26px, 5cqw);
  background: var(--paper);
  box-shadow: 0 24px 50px -20px rgba(0, 0, 0, 0.8);
  transform: rotate(-6deg);
  opacity: 0;
}
.you__photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 846 / 1024;
  object-fit: cover;
}
.you__photo figcaption {
  position: absolute;
  left: max(10px, 2cqw);
  bottom: max(8px, 1.7cqw);
  font: 400 max(9px, 1.8cqw)/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(10, 10, 11, 0.6);
}
.you__chip {
  position: absolute;
  top: max(12px, 2.6cqw);
  left: max(12px, 2.6cqw);
  z-index: 2;
  display: grid;
  padding: max(6px, 1.2cqw) max(10px, 2cqw);
  border-radius: 999px;
  background: var(--c-neutral-0);
  color: var(--paper);
  font: 400 max(10px, 2cqw)/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.you__chip > span { grid-area: 1 / 1; opacity: 0; }
.you__chip > span:nth-child(3) { opacity: 1; }

/* Step 9, as slices of the step: the photo drops 0.00-0.15; scan one
   0.18-0.38 while the avatar fades in 0.20-0.40 and the photo leaves
   0.35-0.42; the outfit wipes on 0.50-0.80 under scan two. The chip
   reads Your photo, then Your avatar from 0.40, then On you from 0.80. */
.look .look__you.is-on { --k: var(--p9); }
.look__you.is-on .you__photo  { --a: 0; --b: 0.42; animation-name: you-photo; }
.look__you.is-on .you__avatar { --a: 0.2; --b: 0.4; animation-name: you-avatar; animation-timing-function: ease-in-out; }
.look__you.is-on .you__fit    { --a: 0.5; --b: 0.8; animation-name: you-fit; animation-timing-function: var(--craft-ease-io); }
.look__you.is-on .you__scan   { animation-name: you-scan; }
.look__you.is-on .you__chip > span:nth-child(1) { animation-name: you-chip-1; }
.look__you.is-on .you__chip > span:nth-child(2) { animation-name: you-chip-2; }
.look__you.is-on .you__chip > span:nth-child(3) { animation-name: you-chip-3; }

@keyframes you-photo {
  0%    { opacity: 0; transform: translateY(-30px) rotate(-6deg) scale(1); animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); }
  35.7% { opacity: 1; transform: translateY(0) rotate(-6deg) scale(1); }
  83.3% { opacity: 1; transform: translateY(0) rotate(-6deg) scale(1); }
  100%  { opacity: 0; transform: translateY(0) rotate(-6deg) scale(0.96); }
}
@keyframes you-avatar {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes you-fit {
  from { clip-path: inset(0 0 100% 0); }
  to   { clip-path: inset(0); }
}
@keyframes you-scan {
  0%, 17.9%  { top: 0; opacity: 0; }
  18%        { top: 0; opacity: 1; animation-timing-function: ease-in-out; }
  38%        { top: 100%; opacity: 1; }
  38.1%      { top: 100%; opacity: 0; }
  49.9%      { top: 0; opacity: 0; }
  50%        { top: 0; opacity: 1; animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
  80%        { top: 100%; opacity: 1; }
  80.1%, 100% { top: 100%; opacity: 0; }
}
@keyframes you-chip-1 { 0%, 39% { opacity: 1; } 41%, 100% { opacity: 0; } }
@keyframes you-chip-2 { 0%, 39% { opacity: 0; } 41%, 79% { opacity: 1; } 81%, 100% { opacity: 0; } }
@keyframes you-chip-3 { 0%, 79% { opacity: 0; } 81%, 100% { opacity: 1; } }

/* -- 12. Edit by talking: your words, then the edit lands (step 10) ------ */
.look .look__ask {
  position: absolute;
  inset: 0;
  z-index: 4;
  padding: max(22px, 4.2cqw);
  border-radius: 18px;
  background: rgba(14, 14, 18, 0.86);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  display: flex;
  flex-direction: column;
  transform: scale(0.98);
}
/* Step 10: the card comes up 0.00-0.12, holds while the words rise
   (0.10-0.37) and fades 0.50-0.60; the sneakers wipe on 0.55-0.85 behind a
   travelling line; the pin and its tag land 0.88-0.98. */
.look .look__ask.is-on {
  transform: none;
  --k: var(--p10);
  animation-name: noir-ask;
}
@keyframes noir-ask {
  0%   { opacity: 0; transform: scale(0.98); }
  12%  { opacity: 1; transform: none; }
  50%  { opacity: 1; }
  60%, 100% { opacity: 0; visibility: hidden; }
}
.look__ask > .look__k { color: rgba(244, 242, 237, 0.55); }
.look__ghosthead {
  margin: 6px 0 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: max(28px, 9cqw);
  line-height: 0.98;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  color: rgba(244, 242, 237, 0.42);
}
.look__ghosthead .m {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: 0.04em;
}
.look__ask-row {
  margin-top: auto;
  padding-top: max(16px, 3cqw);
  border-top: 1px solid rgba(244, 242, 237, 0.18);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: max(12px, 2.4cqw);
  font: 400 max(13px, 2.8cqw)/1.3 var(--font-body);
  color: rgba(244, 242, 237, 0.66);
}
.look__restyle {
  flex: 0 0 auto;
  height: max(36px, 7.4cqw);
  padding: 0 max(16px, 3.4cqw);
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  background: var(--accent);
  color: var(--paper);
  font: 600 max(12px, 2.5cqw)/1 var(--font-body);
}

/* The edited look wipes up from the hem, a cobalt line riding the edge. It
   stays for step 11, so the saved look is the edited one. */
.look__edited {
  position: absolute;
  inset: 0;
  clip-path: inset(100% 0 0 0);
}
.look .look__edited.is-on {
  clip-path: inset(0);
  --k: var(--p10); --a: 0.55; --b: 0.85;
  animation-name: noir-edit;
  animation-timing-function: var(--craft-ease-io);
}
@keyframes noir-edit {
  from { clip-path: inset(100% 0 0 0); }
  to   { clip-path: inset(0); }
}
.look .look__wipe {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  margin-bottom: -1px;
  background: var(--accent);
  box-shadow: var(--glow);
}
.look .look__wipe.is-on {
  --k: var(--p10);
  animation-name: noir-wipe-line;
}
@keyframes noir-wipe-line {
  0%, 54.9%  { bottom: 0; opacity: 0; }
  55%        { bottom: 0; opacity: 1; animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
  85%        { bottom: 100%; opacity: 1; }
  88%, 100%  { bottom: 100%; opacity: 0; }
}
@keyframes noir-fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

.look .look__spot {
  position: absolute;
  inset: 0;
  z-index: 3;
}
.look__spot > i { z-index: 1; }
.look__tag {
  position: absolute;
  right: calc(100% - var(--x) + max(16px, 3cqw));
  top: var(--y);
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: max(4px, 0.8cqw);
  padding: max(9px, 1.8cqw) max(12px, 2.4cqw);
  border-radius: max(10px, 2.4cqw);
  background: var(--ink-glass);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  white-space: nowrap;
}
.look__tag b { font: 700 max(12px, 2.6cqw)/1.1 var(--font-body); color: var(--paper); }
.look__tag em {
  font: 600 max(9px, 1.9cqw)/1.2 var(--font-body);
  font-style: normal;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(244, 242, 237, 0.62);
}
.look .look__spot.is-on {
  --k: var(--p10); --a: 0.88; --b: 0.98;
  animation-name: noir-tag-in;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-tag-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* -- 13. Saved and shared: the page lifts onto a paper mat (step 11) ------ */
/* Step 11: the frame tilts onto its mat 0.00-0.30, the heart pops
   0.25-0.35, the two earlier favourites slide in 0.30-0.50 and the thread
   arrives bubble by bubble 0.50-0.90. */
.look[data-step="11"] {
  transform: scale(0.8) rotate(-4deg) translateY(-4%);
  animation-name: noir-tilt;
  animation-timing-function: var(--craft-ease);
  animation-delay: calc(var(--p11) / 0.3 * -1s);
}
@keyframes noir-tilt {
  from { transform: scale(1) rotate(0deg) translateY(0); }
  to   { transform: scale(0.8) rotate(-4deg) translateY(-4%); }
}
.look .look__mat.is-on {
  --k: var(--p11); --a: 0; --b: 0.2;
  animation-name: noir-fade-in;
}
.look__mat,
.look .look__ghost {
  position: absolute;
  inset: calc(-1 * max(14px, 2.6cqw)) calc(-1 * max(14px, 2.6cqw)) calc(-1 * max(58px, 11cqw));
  border-radius: 6px;
  background: var(--paper);
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.85);
}
.look__mat { z-index: -1; }
.look__mat-cap {
  position: absolute;
  left: max(18px, 3.4cqw);
  bottom: max(20px, 3.9cqw);
  font: var(--folio);
  font-size: max(9px, 1.9cqw);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
}
.look .look__ghost {
  z-index: -2;
  transform: var(--g) translateY(40px);
}
.look .look__ghost.is-on {
  opacity: 0.9;
  transform: var(--g) translateY(0);
  --k: var(--p11); --a: 0.3; --b: 0.42;
  animation-name: noir-ghost-in;
  animation-timing-function: var(--craft-ease);
}
.look .look__ghost--b.is-on { --a: 0.38; --b: 0.5; }
@keyframes noir-ghost-in {
  from { opacity: 0; transform: var(--g) translateY(40px); }
  to   { opacity: 0.9; transform: var(--g) translateY(0); }
}
.look__ghost--a { --g: rotate(7deg) translate(10%, 6%); }
.look__ghost--b { --g: rotate(-10deg) translate(-9%, 9%); }
.look__ghost i {
  position: absolute;
  inset: max(14px, 2.6cqw) max(14px, 2.6cqw) max(58px, 11cqw);
  border-radius: 2px;
  background-size: cover;
  background-position: center top;
}

/* The message thread hangs off the right edge, outside the frame, and
   stops above the hem so the swapped sneakers on the saved card stay in
   view. It lives inside .look (so the engine drives it) and undoes the
   mat's tilt and scale so the bubbles sit level and at full size. */
.look .look__share {
  position: absolute;
  right: -12%;
  bottom: 13%;
  width: min(72%, 60cqw);
  z-index: 6;
  display: flex;
  flex-direction: column;
  gap: max(6px, 1.2cqw);
  transform: rotate(4deg) scale(1.25);
  transform-origin: 100% 100%;
}
.share__b {
  margin: 0;
  max-width: 88%;
  padding: max(9px, 1.8cqw) max(13px, 2.6cqw);
  border-radius: max(18px, 3.4cqw);
  font: 400 max(12px, 2.7cqw)/1.35 var(--font-body);
  box-shadow: 0 14px 30px -14px rgba(0, 0, 0, 0.75);
}
.share__b--link,
.share__b--out {
  align-self: flex-end;
  background: var(--paper);
  color: var(--ink);
  border-bottom-right-radius: 4px;
}
.share__b--in {
  align-self: flex-start;
  background: var(--accent);
  color: var(--paper);
  border-bottom-left-radius: 4px;
}
.share__b--link {
  display: flex;
  align-items: center;
  gap: max(10px, 2cqw);
  padding: max(8px, 1.6cqw) max(14px, 2.8cqw) max(8px, 1.6cqw) max(8px, 1.6cqw);
}
.share__thumb {
  flex: 0 0 auto;
  width: max(44px, 10cqw);
  height: auto;
  aspect-ratio: 4 / 5;
  border-radius: max(8px, 1.6cqw);
  background: url(../images/anatomy/look-sneakers.webp) center top / cover no-repeat;
}
.share__b--link b {
  display: block;
  font: 600 max(12px, 2.6cqw)/1.25 var(--font-body);
  color: var(--ink);
}
.share__b--link em {
  display: block;
  margin-top: max(4px, 0.8cqw);
  font: 400 max(9px, 1.8cqw)/1.2 var(--font-mono);
  font-style: normal;
  color: rgba(10, 10, 11, 0.5);
}
.look__share.is-on > * {
  --k: var(--p11); --a: 0.5; --b: 0.64;
  animation-name: noir-bubble;
  animation-timing-function: var(--craft-ease);
}
.look__share.is-on > :nth-child(2) { --a: 0.63; --b: 0.77; }
.look__share.is-on > :nth-child(3) { --a: 0.76; --b: 0.9; }
@keyframes noir-bubble {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* -- 14. Your style profile (step 1): a frosted panel over the faint model,
   built in three beats across the step. Taste (0.06-0.56): five looks
   slide in and are judged one by one. Colour (0.54-0.90): a scan reads
   the selfie and the palette flies out of it. Wardrobe (0.88-1.00): what
   you own, what you never wear, and your shape. Every part animates from
   its first frame to its un-animated end state. --------------------------- */
.look .look__profile {
  position: absolute;
  inset: 4cqw;
  z-index: 4;
  padding: 4.4cqw 4cqw;
  border-radius: max(12px, 3cqw);
  background: rgba(14, 14, 18, 0.84);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid rgba(244, 242, 237, 0.12);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 3cqw;
  overflow: hidden;
  transform: translateY(14px) scale(0.985);
}
.look .look__profile.is-on {
  transform: none;
  --k: var(--p1); --a: 0; --b: 0.08;
  animation-name: noir-prof-in;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-prof-in {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
.prof__row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.6cqw;
}
.prof__folio {
  font: 400 max(10px, 2cqw)/1.3 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(244, 242, 237, 0.6);
  white-space: nowrap;
}
.prof__k {
  display: block;
  font: 600 max(9px, 2cqw)/1.2 var(--font-body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(244, 242, 237, 0.55);
  white-space: nowrap;
}
.look__profile.is-on :is(.prof__head, .prof__k, .prof__note, .colour__pill, .prof__shape) {
  animation-name: noir-prof-row;
  animation-timing-function: var(--craft-ease);
}
.look__profile.is-on .prof__head                  { --a: 0.06; --b: 0.12; }
.look__profile.is-on .prof__row--taste .prof__k   { --a: 0.08; --b: 0.14; }
.look__profile.is-on .prof__row--taste .prof__note { --a: 0.52; --b: 0.56; }
.look__profile.is-on .prof__row--colour .prof__k  { --a: 0.53; --b: 0.58; }
.look__profile.is-on .colour__out .prof__note     { --a: 0.84; --b: 0.87; }
.look__profile.is-on .colour__pill                { --a: 0.86; --b: 0.9; }
.look__profile.is-on .prof__row--own .prof__k     { --a: 0.88; --b: 0.91; }
.look__profile.is-on .prof__shape                 { --a: 0.96; --b: 1; }
@keyframes noir-prof-row {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* Beat A: taste. Cards slide in from the right (0.10-0.30), then each is
   judged in turn (--ja..--jb, 0.30-0.52): loved ones lift under a cobalt
   heart, passed ones sink under a paper cross and a strike. */
.taste {
  display: flex;
  gap: 1cqw;
}
.taste__card {
  --ja: calc(0.3 + var(--i) * 0.04);
  --jb: calc(0.36 + var(--i) * 0.04);
  position: relative;
  flex: 0 0 16cqw;
}
.taste__img {
  display: block;
  aspect-ratio: 3 / 4;
  border-radius: 1.2cqw;
  background: #1a1a20 center top / cover no-repeat;
  box-shadow: 0 10px 20px -12px rgba(0, 0, 0, 0.9);
  transform: translateY(-2px);
}
.taste__card--no .taste__img { transform: none; opacity: 0.35; }
/* The strike: a 1px paper diagonal over the passed card (and the "never" crops). */
.taste__card--no::after,
.own__never::after {
  content: "";
  position: absolute;
  left: -20%;
  width: 140%;
  top: calc(50% - 0.5px);
  height: 1px;
  background: var(--paper);
  transform: rotate(45deg);
}
.taste__badge {
  position: absolute;
  top: -0.8cqw;
  right: -0.8cqw;
  z-index: 1;
  width: max(16px, 4cqw);
  height: max(16px, 4cqw);
  display: grid;
  place-items: center;
  border-radius: 50%;
  box-shadow: 0 4px 10px -4px rgba(0, 0, 0, 0.8);
}
.taste__badge svg { width: 56%; height: 56%; }
.taste__badge--yes { background: var(--accent); }
.taste__badge--yes svg { fill: var(--paper); }
.taste__badge--no { background: var(--paper); }
.taste__badge--no svg { fill: none; stroke: var(--ink); stroke-width: 2.8; stroke-linecap: round; }

.look__profile.is-on .taste__card {
  --a: calc(0.1 + var(--i) * 0.025);
  --b: calc(0.2 + var(--i) * 0.025);
  animation-name: noir-taste-in;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-taste-in { from { opacity: 0; transform: translateX(36cqw); } }
.look__profile.is-on .taste__card--yes .taste__img {
  --a: var(--ja); --b: var(--jb);
  animation-name: noir-taste-yes;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-taste-yes { from { transform: none; } }
.look__profile.is-on :is(.taste__card--no .taste__img, .own__never .own__img) {
  --a: var(--ja); --b: var(--jb);
  animation-name: noir-taste-no;
  animation-timing-function: var(--craft-ease-io);
}
@keyframes noir-taste-no { from { opacity: 1; } }
.look__profile.is-on :is(.taste__card--no, .own__never)::after {
  --a: var(--ja); --b: var(--jb);
  animation-name: noir-strike;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-strike { from { transform: rotate(45deg) scaleX(0); } }
.look__profile.is-on :is(.taste__badge, .own__check) {
  --a: var(--ja); --b: var(--jb);
  animation-name: noir-badge;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-badge {
  0%   { opacity: 0; transform: scale(0.6); }
  1%   { opacity: 1; transform: scale(0.6); }
  55%  { opacity: 1; transform: scale(1.35); }
  100% { opacity: 1; transform: scale(1); }
}

/* Beat B: colour. The selfie drops in, a cobalt scan reads it top to
   bottom, and five swatches fly from the face to their row. */
.colour {
  display: flex;
  align-items: center;
  gap: 4cqw;
}
.colour__pol {
  flex: 0 0 26cqw;
  box-sizing: border-box;
  padding: 1.2cqw 1.2cqw 4cqw;
  background: var(--paper);
  box-shadow: 0 16px 30px -16px rgba(0, 0, 0, 0.9);
  transform: rotate(-4deg);
}
.colour__shot {
  position: relative;
  display: block;
  aspect-ratio: 1;
  overflow: hidden;
}
/* The selfie is a full-length mirror shot; scaled about the face so the
   square reads as a face, not a room. */
.colour__shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 12%;
  transform: scale(2.4);
  transform-origin: 50.6% 25%;
}
.colour__scan {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 2px;
  margin-top: -1px;
  background: var(--accent);
  box-shadow: var(--glow);
  opacity: 0;
}
.colour__out {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.8cqw;
  min-width: 0;
}
.colour__sw { display: flex; gap: 1.6cqw; }
.colour__sw i {
  width: max(18px, 5cqw);
  height: max(18px, 5cqw);
  border-radius: 50%;
  background: var(--c);
  box-shadow: 0 0 0 1px rgba(244, 242, 237, 0.25);
}
.colour__pill {
  padding: 1.2cqw 2.4cqw;
  border: 1px solid rgba(244, 242, 237, 0.16);
  border-radius: 999px;
  background: var(--c-neutral-0);
  color: var(--paper);
  font: 500 max(10px, 2.3cqw)/1.2 var(--font-body);
  white-space: nowrap;
}
/* Selfie 0.55-0.62, scan 0.62-0.74, swatches 0.70-0.84. */
.look__profile.is-on .colour__pol {
  --a: 0.55; --b: 0.62;
  animation-name: noir-pol-in;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-pol-in { from { opacity: 0; transform: translateY(-14px) rotate(-8deg); } }
.look__profile.is-on .colour__scan {
  --a: 0.62; --b: 0.74;
  animation-name: noir-scan;
  animation-timing-function: var(--craft-ease-io);
}
@keyframes noir-scan {
  0%   { top: 0; opacity: 0; }
  6%   { opacity: 1; }
  92%  { opacity: 1; }
  100% { top: 100%; opacity: 0; }
}
.look__profile.is-on .colour__sw i {
  --a: calc(0.7 + var(--i) * 0.025);
  --b: calc(0.74 + var(--i) * 0.025);
  animation-name: noir-swatch;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-swatch { from { opacity: 0; transform: translate(-24cqw, 0) scale(0.3); } }

/* Beat C: already yours, and never. Three owned pieces as polaroids with a
   cobalt check (0.90-0.96), two crops you never wear, struck through, and
   the shape (0.95-1.00). */
.own__head {
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2cqw;
}
.own {
  display: flex;
  align-items: flex-start;
  gap: 1.5cqw;
}
.own__pol,
.own__never {
  position: relative;
  flex: 0 0 auto;
}
.own__pol   { --ja: calc(0.915 + var(--i) * 0.01); --jb: calc(0.94 + var(--i) * 0.01); }
.own__never { --ja: calc(0.94 + var(--i) * 0.01);  --jb: calc(0.96 + var(--i) * 0.01); }
.own__pol {
  box-sizing: content-box;
  width: 14cqw;
  border: solid var(--paper);
  border-width: 1cqw 1cqw 3cqw;
  background: #e9e5dd;
  box-shadow: 0 12px 24px -12px rgba(0, 0, 0, 0.85);
  transform: rotate(var(--r));
}
.own__img {
  display: block;
  aspect-ratio: 1;
  background-color: #e9e5dd;
  background-repeat: no-repeat;
}
.own__check {
  position: absolute;
  top: -1.4cqw;
  right: -1.4cqw;
  width: max(12px, 3cqw);
  height: max(12px, 3cqw);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent);
}
.own__check svg {
  width: 64%;
  height: 64%;
  fill: none;
  stroke: var(--paper);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.own__never {
  width: 14cqw;
  display: flex;
  flex-direction: column;
  gap: 1cqw;
}
.own__pol + .own__never { margin-left: 2cqw; }
.own__never .own__img { border-radius: 1.2cqw; opacity: 0.5; }
.own__never::after { top: 7cqw; }
.own__never em { font-style: normal; }
.look__profile.is-on .own__pol {
  --a: calc(0.9 + var(--i) * 0.01);
  --b: calc(0.93 + var(--i) * 0.01);
  animation-name: noir-own-in;
  animation-timing-function: var(--craft-ease);
}
.look__profile.is-on .own__never {
  --a: calc(0.905 + var(--i) * 0.015);
  --b: calc(0.93 + var(--i) * 0.015);
  animation-name: noir-own-in;
  animation-timing-function: var(--craft-ease);
}
@keyframes noir-own-in { from { opacity: 0; transform: translateY(12px); } }
.prof__shape {
  display: inline-flex;
  align-items: center;
  gap: max(6px, 1.4cqw);
  padding: 1.2cqw 2.4cqw;
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font: 600 max(11px, 2.4cqw)/1.2 var(--font-body);
  white-space: nowrap;
}
.prof__shape i {
  width: max(6px, 1.3cqw);
  height: max(6px, 1.3cqw);
  border-radius: 50%;
  background: var(--accent);
}

/* -- 15. The library (step 2) and the zoom into one look (step 3). Step 2:
   a wall of twenty looks drifts up, the six that fit the profile ring
   cobalt and the rest dim. Step 3: the camera zooms into the hero tile,
   the same photo as the stage, until it covers the frame; the full-res
   photo then cross-fades in under it (the wall fades) for sharpness.
   The grid's column count and the hero cell's place are custom
   properties, set per frame size: cell = (100 - 2 x 3 padding -
   (cols - 1) x 1.6 gap) / cols cqw, 3:4 tall. The zoom scales the grid
   (not the wall, which clips it to the frame) about the hero cell's
   centre and moves that centre to the frame's (50cqw, 62.5cqw); the
   scale is frame width / cell width. The drift runs the length of step 2,
   so the zoom starts from the cell's final place. Step 2: the wall fades
   in 0.00-0.10 and drifts 0.00-1.00; the matches ring and the rest dim
   0.35-0.50; the chip 0.40-0.45. ------------------------------------------ */
.look .look__wall {
  --wall-cols: 4;
  --wall-cell-n: 22.3;
  --wall-cell: calc(var(--wall-cell-n) * 1cqw);
  --wall-hero-row: 2;
  --wall-hero-col: 3;
  --wall-hero-x: 50.8cqw;   /* 3 + 2 x (22.3 + 1.6) */
  --wall-hero-y: 34.33cqw;  /* 3 + 1 x (22.3 x 4/3 + 1.6) */
  --wall-drift: 9cqw;       /* the drift across step 2 */
  --wall-cx: calc(var(--wall-hero-x) + var(--wall-cell) / 2);
  --wall-cy: calc(var(--wall-hero-y) + var(--wall-cell) * 2 / 3);
  --wall-zoom: calc(100 / var(--wall-cell-n));
  position: absolute;
  inset: 0;
  z-index: 4;
  overflow: hidden;
  border-radius: 18px;
  background: #0e0e12;
}
.look[data-step="2"] .look__wall.is-on {
  --k: var(--p2); --a: 0; --b: 0.1;
  animation-name: noir-fade-in;
}
.wall__grid {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: grid;
  grid-template-columns: repeat(var(--wall-cols), minmax(0, 1fr));
  gap: 1.6cqw;
  padding: 3cqw;
  transform: translateY(calc(-1 * var(--wall-drift)));
  transform-origin: var(--wall-cx) var(--wall-cy);
}
.look__wall.is-on .wall__grid {
  --k: var(--p2); --a: 0; --b: 1;
  animation-name: noir-wall-drift;
}
@keyframes noir-wall-drift { from { transform: none; } }
.wall__tile {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: center top;
  border-radius: max(4px, 1.2cqw);
  background: #1a1a20;
  opacity: 0.28;
}
.wall__tile--match {
  opacity: 1;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.wall__tile--hero {
  grid-row: var(--wall-hero-row);
  grid-column: var(--wall-hero-col);
}
.look__wall.is-on .wall__tile {
  --k: var(--p2); --a: 0.35; --b: 0.5;
  animation-name: noir-wall-dim;
  animation-timing-function: var(--craft-ease);
}
.look__wall.is-on .wall__tile--match { animation-name: noir-wall-ring; }
@keyframes noir-wall-dim { from { opacity: 1; } }
@keyframes noir-wall-ring { from { outline-color: transparent; } }
/* Sits where the "Modelled on" chip arrives at step 4. */
.wall__folio {
  position: absolute;
  top: max(12px, 2.6cqw);
  left: max(12px, 2.6cqw);
  z-index: 2;
  padding: max(6px, 1.2cqw) max(10px, 2cqw);
  border-radius: 999px;
  background: var(--c-neutral-0);
  color: var(--paper);
  font: 400 max(9px, 1.9cqw)/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.look__wall.is-on .wall__folio {
  --k: var(--p2); --a: 0.4; --b: 0.45;
  animation-name: noir-prof-row;
  animation-timing-function: var(--craft-ease);
}

/* Step 3: the zoom, 0.00-0.55 (the folio leaves 0.00-0.10, the hero's
   ring 0.10-0.40). The wall fades 0.45-0.65 and the photo under it
   (scaled to match the tile, 133.3 / 125) settles to its own size; the
   scrim 0.50-0.65, the dateline 0.60-0.72, the masthead word by word
   0.65-0.90, the heart 0.85-0.95. */
.look[data-step="3"] .look__wall.is-on {
  --k: var(--p3); --a: 0.45; --b: 0.65;
  animation-name: noir-fade-out;
}
.look[data-step="3"] .look__wall.is-on .wall__grid {
  --k: var(--p3); --a: 0; --b: 0.55;
  animation-name: noir-wall-zoom;
  animation-timing-function: var(--craft-ease-io);
}
@keyframes noir-wall-zoom {
  from { transform: translate(0, calc(-1 * var(--wall-drift))) scale(1); }
  to {
    transform: translate(calc(50cqw - var(--wall-cx)), calc(62.5cqw - var(--wall-cy))) scale(var(--wall-zoom));
  }
}
.look[data-step="3"] .look__wall.is-on .wall__tile--hero {
  --k: var(--p3); --a: 0.1; --b: 0.4;
  animation-name: noir-ring-out;
  animation-timing-function: var(--craft-ease-io);
}
@keyframes noir-ring-out { to { outline-color: transparent; } }
.look[data-step="3"] .look__wall.is-on .wall__folio {
  --k: var(--p3); --a: 0; --b: 0.1;
  animation-name: noir-fade-out;
}
.look[data-step="3"] .look__shape[data-shape="pear"] {
  --k: var(--p3); --a: 0.45; --b: 0.65;
  animation-name: noir-photo-settle;
  animation-timing-function: var(--craft-ease-io);
}
@keyframes noir-photo-settle { from { transform: scale(1.0667); } }
.look .look__ink.is-on {
  --k: var(--p3); --a: 0.5; --b: 0.65;
  animation-name: noir-fade-in;
}
/* Step 4: the "Modelled on" chip takes the dateline's corner. */
.look[data-step="4"] .look__dateline.is-on { opacity: 0; }

/* -- Small stage (phones, narrow columns) ---------------------------------- */
@container (max-width: 420px) {
  /* Small frames: the product card shows a shorter picture and sits under
     the dateline; the advice card stacks each key over its line. */
  .look .look__product { top: 55%; }
  .look__product-img { aspect-ratio: 16 / 10; }
  .look .look__advice {
    top: auto;
    grid-template-columns: minmax(0, 1fr) 62px;
  }
  .adv { grid-template-columns: minmax(0, 1fr); gap: 3px; padding: 7px 0; }
  .look__advice-text .adv { flex: 0 0 auto; }
  .look__tag { white-space: normal; width: max-content; max-width: 46cqw; }
  /* The library: three columns; the hero look is tile 5, row 2 col 2. */
  .look .look__wall {
    --wall-cols: 3;
    --wall-cell-n: 30.27;     /* (100 - 6 - 3.2) / 3 */
    --wall-hero-row: 2;
    --wall-hero-col: 2;
    --wall-hero-x: 34.87cqw;  /* 3 + 1 x (30.27 + 1.6) */
    --wall-hero-y: 44.96cqw;  /* 3 + 1 x (30.27 x 4/3 + 1.6) */
  }
}

/* -- Without the script: the step-3 cover ----------------------------------- */
.stage:not(.is-js) .look :is(.look__ink, .look__dateline, .look__masthead, .look__heart) { opacity: 1; }
.stage:not(.is-js) .look__dateline span { clip-path: none; }

/* -- Phones and tablets: the hero stacks, the stage sits under the text -- */
@media (max-width: 991px) {
  .stage {
    --look-h: min(50vh, 460px, calc((100vw - 48px) * 1.25));
    --look-h: min(50dvh, 460px, calc((100vw - 48px) * 1.25));
    gap: 10px;
  }

  .pol { --dx: -36cqw; padding-bottom: 28px; }
  .pol--dress  { right: 2%; }
  .pol--tote   { right: 0; }
  .pol--wedges { right: 4%; }
  .pol__cap { flex-direction: column; align-items: flex-start; gap: 3px; bottom: 4px; }
  .look__mat-cap { letter-spacing: 0.1em; }
  .look .look__share {
    right: 2%;
    bottom: 14%;
  }
}

/* The stage is a picture, not text to select. */
.look, .look * { user-select: none; -webkit-user-select: none; }

/* ---------------------------------------------------------------------------
   14. The rest of the page arrives the same way — scroll-driven, no script.
   Everything is visible by default; only browsers with view() timelines
   get the travel, and reduced-motion users never do.
   --------------------------------------------------------------------------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    @keyframes noir-rise {
      from { opacity: 0; transform: translateY(32px); }
      to   { opacity: 1; transform: none; }
    }
    @keyframes noir-wipe {
      from { clip-path: inset(0 100% 0 0); transform: translateX(-12px); }
      to   { clip-path: inset(0 0 0 0); transform: none; }
    }
    @keyframes noir-draw {
      from { transform: scaleX(0); }
      to   { transform: scaleX(1); }
    }



    /* Section hairlines draw themselves left to right as they enter. */
    .what, .more, .blog-preview, .walsh-cta-green-wrapper {
      border-top: 0;
      position: relative;
    }
    .what::before, .more::before, .blog-preview::before, .walsh-cta-green-wrapper::before {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 1px;
      background: var(--border);
      transform-origin: left center;
      animation: noir-draw linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 18%;
    }

    /* Section furniture rises. */
    .what__head > *,
    .testimonials__inner > *,
    .blog-preview .walsh-container > :not(.features__grid) {
      animation: noir-rise both;
      animation-timeline: view();
      animation-range: entry 8% cover 24%;
    }

    /* Each half: the chapter word wipes in, the phone rises, the copy
       follows. */
    .what__word {
      animation: noir-wipe both;
      animation-timeline: view();
      animation-range: entry 5% cover 30%;
    }
    .what__phone {
      animation: noir-rise both;
      animation-timeline: view();
      animation-range: entry 6% cover 30%;
    }
    /* The tiles rise in reading order. */
    .more__head > *,
    .tile {
      animation: noir-rise both;
      animation-timeline: view();
      animation-range: entry 4% cover 26%;
    }
    .tile:nth-child(3n + 2) { animation-range: entry 4% cover 32%; }
    .tile:nth-child(3n + 3) { animation-range: entry 4% cover 38%; }
    /* Inside the tiles: the edit's looks and the share thread arrive one
       after another. */
    .tedit__look,
    .tshare__b {
      animation: noir-rise both;
      animation-timeline: view();
      animation-range: entry 0% cover 20%;
    }
    .tedit__look:nth-child(2),
    .tshare__b:nth-child(2) { animation-range: entry 0% cover 26%; }
    .tedit__look:nth-child(3),
    .tshare__b:nth-child(3) { animation-range: entry 0% cover 32%; }
    .what__copy {
      animation: noir-rise both;
      animation-timeline: view();
      animation-range: entry 10% cover 34%;
    }

    /* Journal rows trail one another. */
    .blog-preview__card {
      animation: noir-rise both;
      animation-timeline: view();
      animation-range: entry 4% cover 26%;
    }
    .blog-preview__card:nth-child(2) { animation-range: entry 4% cover 32%; }
    .blog-preview__card:nth-child(3) { animation-range: entry 4% cover 38%; }
    .blog-preview__card:nth-child(4) { animation-range: entry 4% cover 44%; }

    /* The blog arrow slides in after its row. */
    .blog-preview__card::after {
      animation: noir-wipe both;
      animation-timeline: view();
      animation-range: entry 20% cover 40%;
    }

    /* Figures in the proof strip count up in JS; the labels rise. */
    .proof-stat span {
      animation: noir-rise both;
      animation-timeline: view();
      animation-range: entry 10% cover 40%;
    }
  }
}

/* Reduced motion: the steps still switch, but nothing is scrubbed — every
   beat of the current step shows its last frame, and states cut. */
@media (prefers-reduced-motion: reduce) {
  .look,
  .look [data-at],
  .look *,
  .look *::before,
  .look *::after,
  .stage__head {
    transition: none !important;
  }
  .stage .look,
  .stage .look *,
  .stage .look *::before,
  .stage .look *::after {
    animation-delay: -1s !important;
  }
}

/* ---------------------------------------------------------------------------
   15. Phones: section headings stay left with their eyebrow. Webflow's
   legacy phone rule centres .walsh-heading-large-black; only the reviews
   heading is centred by design.
   --------------------------------------------------------------------------- */
@media (max-width: 991px) {
  .what .walsh-heading-large-black,
  .more .walsh-heading-large-black,
  .blog-preview .walsh-heading-large-black {
    text-align: left !important;
  }
}

/* ---------------------------------------------------------------------------
   16. Crawler and very tall viewports. A scroll-driven reveal needs scroll
   overflow to run; a renderer that sizes its viewport to the whole page
   (Googlebot, full-page capture tools) has none, so every view()-timeline
   animation sits on its first keyframe and the copy renders at opacity 0.
   No real display is taller than 1500 CSS px, so above that every keyframe
   animation becomes instantaneous and the page is static and complete.
   --------------------------------------------------------------------------- */
@media (min-height: 1501px) {
  *, *::before, *::after {
    animation-timeline: auto !important;
    animation-duration: 0s !important;
    animation-delay: 0s !important;
  }
}
