/* ============================================================
   HERO B — the desktop hero.
   ============================================================ */

/* the hero is mobile-first; this file is the desktop hero */
.hero-b { display: none; }

@media (min-width: 761px) {

  .hero-b { display: block; }

  /* The hero page no longer holds a scaled .page__scene, so it must not
     shrink with the stack-mode scaling that sizes the other sections —
     it is a self-contained, exactly-one-viewport stage. */
  .page--hero { height: 100dvh; min-height: 100dvh; overflow: hidden; }
  .portfolio[data-scroll-mode="stack"] .page--hero {
    height: 100dvh; min-height: 100dvh; overflow: hidden;
  }

  /* ---- the hero itself ---- */
  /* pinned to the top of the hero page and exactly one viewport tall —
     .page can be taller than the screen, which would drop the figure
     below the fold if we used inset:0 */
  .hero-stage {
    position: absolute; top: 0; left: 0; right: 0; z-index: 2;
    height: 100dvh; min-height: 560px;
    overflow: hidden;
    background: var(--ink-850, #050608);
    /* one unit drives the whole hero. It is a straight proportion of the
       fold — not "viewport minus a fixed 300px" — so every part of the
       composition grows and shrinks at the same rate as the window
       instead of accelerating away from it on tall screens. */
    --hb-stack-w: 54dvh;
  }

  /* the figure, pulled in off the right edge */
  .hero-b__media { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
  .hero-b__media img {
    position: absolute; bottom: 0; right: clamp(24px, 4.6vw, 96px);
    height: 90%; width: auto; max-width: none;
    object-fit: contain; object-position: bottom center;
    filter: drop-shadow(-20px 30px 74px rgba(0, 0, 0, 0.95));
  }

  /* WEB DESIGNER set large behind everything: it starts where the
     slides end and runs off the right edge of the screen */
  .hero-b__word {
    /* above the grade, below the figure: he breaks the letters */
    position: absolute; z-index: 2; pointer-events: none;
    left: var(--hb-word-left, calc(clamp(28px, 4vw, 64px) + min(100% - 120px, var(--hb-stack-w)) + clamp(22px, 2.6vw, 44px)));
    /* sits on the same baseline as the bottom of the second slide:
       the slide stack is centred in the grid, so its lower edge is
       112px up from the bottom, offset by half the padding difference */
    bottom: var(--hb-word-b, calc(112px - (clamp(84px, 10.5vh, 116px) - clamp(44px, 8vh, 84px)) / 2));
    /* same type as the name, set large enough that the final R clears
       the figure's legs and runs almost to the screen edge */
    font-family: var(--font-display); font-weight: 800;
    font-size: var(--hb-word-size, clamp(4rem, 8.62vw, 11rem)); line-height: 0.9; letter-spacing: -0.015em;
    text-transform: uppercase; white-space: nowrap;
    color: rgba(255, 255, 255, 0.78);
  }
  /* the reflection: WEB only, laid down on the ground behind the letters —
     not a flat mirror but a surface running away from the viewer, so the
     shape foreshortens and its edges converge toward a horizon, the way a
     road does. Almost no hue, almost no light: it reads as a property of
     the floor, not as a second word. */
  .hero-b__word-mirror {
    position: absolute; z-index: 1; pointer-events: none; user-select: none;
    left: var(--hb-word-left, calc(clamp(28px, 4vw, 64px) + min(100% - 120px, var(--hb-stack-w)) + clamp(22px, 2.6vw, 44px)));
    bottom: var(--hb-mirror-b, -9999px);
    font-family: var(--font-display); font-weight: 800;
    font-size: var(--hb-word-size, clamp(4rem, 8.62vw, 11rem));
    line-height: 0.9; letter-spacing: -0.015em;
    text-transform: uppercase; white-space: nowrap;
    /* a cool near-grey at a fraction of the word's own opacity */
    color: rgba(214, 222, 232, 0.085);
    /* hinged on the line where the letters meet the floor. past 90deg the
       copy is flipped, and the remaining tilt pushes its far end into the
       screen — perspective then squeezes that end toward the vanishing
       point, which is what sells the ground plane. */
    /* the trailing translate runs along the tilted plane itself, sliding the
       copy up it until its ink meets the real letters' feet — the box has a
       descent gap under the glyphs that the projection would otherwise show
       as a seam. */
    transform: perspective(400px) rotateX(138deg) translateY(var(--hb-mirror-lift, 0px));
    transform-origin: bottom;
    filter: blur(1.8px);
    /* strongest at the letters' feet, gone before it reaches the horizon.
       the plane is flipped, so "to top" runs away from the viewer. */
    -webkit-mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.44) 34%, rgba(0, 0, 0, 0) 78%);
    mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.44) 34%, rgba(0, 0, 0, 0) 78%);
  }
  .hero-b__glow {
    position: absolute; right: 0; bottom: 0; width: 70%; height: 88%; z-index: 0;
    pointer-events: none;
    background: radial-gradient(60% 70% at 62% 82%, rgba(255, 255, 255, 0.05), transparent 70%);
  }
  /* grade only under the type — the figure stays visible, like on mobile */
  .hero-b__scrim {
    position: absolute; inset: 0; z-index: 1; pointer-events: none;
    background:
      linear-gradient(180deg, rgba(5, 6, 8, 0.42) 0%, rgba(5, 6, 8, 0) 20%, rgba(5, 6, 8, 0) 40%, rgba(5, 6, 8, 0.72) 72%, rgba(5, 6, 8, 0.96) 100%),
      radial-gradient(70% 52% at 22% 88%, rgba(5, 6, 8, 0.78), rgba(5, 6, 8, 0) 72%);
  }

  /* top bar — brand left, connect right (mirrors the mobile bar) */
  .hero-b__bar {
    position: absolute; top: 0; left: 0; right: 0; z-index: 4;
    display: flex; align-items: center; justify-content: space-between;
    padding: 28px clamp(28px, 4vw, 64px) 0;
  }
  .hero-b__brand {
    font-family: var(--font-mono); font-size: 0.74rem; letter-spacing: 0.18em;
    text-transform: uppercase; color: var(--cream-100, #f3ece0); text-decoration: none;
  }
  .hero-b__connect-wrap { position: relative; }
  .hero-b__connect.ds-cta--frame {
    color: var(--fg, #fff); cursor: pointer;
    padding: 14px 22px; font-size: 0.88rem; letter-spacing: 0.05em; gap: 12px;
  }
  .hero-b__connect.ds-cta--frame .frame-c { width: 12px; height: 12px; }
  /* the resized corners above tie with the base :hover rule on specificity and
     win on order, which was pinning them open-shut. Restate the sweep here. */
  .hero-b__connect.ds-cta--frame:hover .frame-c { width: 100%; height: 100%; }
  .hero-b-pop {
    position: absolute; top: calc(100% + 12px); right: 0; z-index: 12;
    min-width: 268px; padding: 6px;
    background: #14161c; border: 1px solid var(--line-mid, rgba(255, 255, 255, 0.16));
    border-radius: 14px; box-shadow: 0 26px 54px -20px rgba(0, 0, 0, 0.8);
    display: flex; flex-direction: column; gap: 2px;
    transform-origin: top right; animation: hero-b-pop-in 0.2s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .hero-b-pop[hidden] { display: none; }
  .hero-b-pop a { display: flex; flex-direction: column; gap: 2px; padding: 11px 12px; text-decoration: none; border-radius: 9px; }
  .hero-b-pop a:hover { background: rgba(255, 255, 255, 0.06); }
  .hero-b-pop__k { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--cream-300, rgba(255, 255, 255, 0.55)); }
  .hero-b-pop__v { font-family: var(--font-sans); font-size: 0.94rem; color: var(--fg, #fff); }
  @keyframes hero-b-pop-in { from { opacity: 0; transform: translateY(-6px) scale(0.98); } to { opacity: 1; transform: none; } }

  /* one grid holds the words and the work on a shared centre line, so the
     two never drift apart. the figure lives in the third track. */
  .hero-b__grid {
    position: absolute; inset: 0; z-index: 4;
    display: grid;
    grid-template-columns: minmax(340px, 1.16fr) minmax(280px, 0.9fr);
    align-items: center;
    column-gap: clamp(22px, 2.6vw, 44px);
    /* the figure is 90% of the hero height and ~0.41 as wide as it is tall,
       so reserving 36.8dvh on the right lands the copy right against it at
       any window size instead of drifting with a fr track */
    padding: clamp(84px, 10.5vh, 116px) max(clamp(28px, 4vw, 64px), calc(36.8dvh + clamp(24px, 4.6vw, 96px) + 8px))
             clamp(44px, 8vh, 84px) clamp(28px, 4vw, 64px);
    pointer-events: none;
  }
  .hero-b__grid > * { pointer-events: auto; grid-row: 1; }
  /* work on the left, words on the right — the block shrinks to its own
     text and sits hard against the figure instead of filling the track */
  /* left edge comes from the measured ink of the D in DESIGNER */
  .hero-b__copy {
    position: absolute; left: var(--hb-dx, 56%); top: 50%;
    transform: translateY(calc(-50% + var(--hb-copy-shift, 0px)));
    width: max-content;
    /* width comes from the boy's real outline, measured in JS */
    max-width: var(--hb-copy-max, min(24ch, calc(100vw - var(--hb-dx, 56%) - 40px)));
  }

  /* same order as the mobile hero: role, then name, then the button */
  .hero-stage .hero-b__k {
    display: block; margin-bottom: clamp(14px, 2vh, 24px);
    font-family: var(--font-mono); font-size: clamp(0.86rem, 1.05vw, 1.02rem);
    letter-spacing: 0.14em; text-transform: uppercase; color: var(--cream-100, #f3ece0);
  }
  .hero-stage .hero-b__title {
    margin: 0;
    font-family: var(--font-display); font-weight: 800;
    font-size: var(--hb-title-size, clamp(2.9rem, 5.8vw, 5.4rem)); line-height: 0.92; letter-spacing: -0.012em;
    color: var(--fg, #fff);
  }
  .hero-stage .hero-b__title span { display: block; white-space: nowrap; }
  /* each line shorter than the last: a right triangle whose vertical edge
     is the left margin and whose taper walks the eye down to the button */

  .hero-stage .hero-b__sub {
    margin: clamp(18px, 2.4vh, 28px) 0 0; max-width: 86%;
    font-family: var(--font-sans); font-weight: 300;
    font-size: clamp(1rem, 1.2vw, 1.16rem); line-height: 1.5;
    color: var(--cream-100, #f3ece0);
  }
  .hero-b__actions { display: flex; align-items: center; margin-top: clamp(26px, 3.6vh, 42px); }
  /* the site's own crop-mark button */
  .hero-b__cta.ds-cta--frame {
    color: var(--fg, #fff);
    padding: 18px 30px; font-size: 1.02rem; gap: 14px;
    font-weight: var(--weight-bold, 700);
  }
  .hero-b__cta.ds-cta--frame .frame-c { width: 14px; height: 14px; }
  /* same story as the connect button: the sized corners outrank the base
     hover rule, so the sweep has to be restated at this specificity */
  .hero-b__cta.ds-cta--frame:hover .frame-c { width: 100%; height: 100%; }
  .hero-stage.is-tight .hero-b__cta.ds-cta--frame { padding: 15px 22px; font-size: 0.92rem; gap: 11px; }

  /* ---- the work: one large landscape panel, upper right, no labels.
     websites are landscape — a tall crop would show nothing readable ---- */
  /* two screens in the middle track, centred against the words */
  .hero-b__shows {
    grid-column: 1; align-self: center;
    display: flex; flex-direction: column;
    gap: clamp(18px, 3vh, 32px);
    /* as wide as the column allows, but never taller than the fold:
       two 16:10 screens + their captions + the gap have to fit */
    width: min(100%, var(--hb-stack-w));
  }
  /* BEFORE / AFTER marked above each screen, over each half */
  .hero-b__show-cap {
    display: flex; justify-content: space-between; align-items: baseline;
    margin-bottom: 9px; padding: 0 2px;
    font-family: var(--font-mono); font-size: 0.64rem; letter-spacing: 0.2em;
    text-transform: uppercase;
  }
  .hero-b__show-cap b { font-weight: 400; color: var(--cream-300, rgba(255, 255, 255, 0.48)); }
  .hero-b__show-cap i { font-style: normal; color: #fff; }
  /* hover blows a screen up to 2x so you can actually read the site.
     origin is pinned to the corner nearest the stack so it never
     runs off the top or bottom of the fold. */
  .hero-b__show {
    position: relative; margin: 0; width: 100%;
    transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
    transform-origin: left top;
  }
  .hero-b__shows .hero-b__show:last-child { transform-origin: left bottom; }
  .hero-stage.is-armed .hero-b__shows .hero-b__show:hover { transform: scale(2); z-index: 9; }
  /* the entrance animation makes .hero-b__shows a stacking context, so the
     stack itself has to rise or the name would paint over the zoom */
  .hero-stage.is-armed .hero-b__shows:hover { z-index: 9; }
  /* clicked = frozen, so the wipe holds still while you look */
  .hero-b__show.is-locked .hero-b__screen { outline: 1px solid rgba(255, 255, 255, 0.5); outline-offset: 2px; }

  .hero-b__screen {
    position: relative; width: 100%; aspect-ratio: 16 / 10;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 2px; overflow: hidden;
    box-shadow: 0 44px 90px -44px rgba(0, 0, 0, 1);
  }
  .hero-b__ba {
    position: relative; overflow: hidden; height: 100%; width: 100%;
    cursor: ew-resize; touch-action: none;
  }
  /* only the very bottom sinks into the canvas, so it sits in the scene
     without ever dimming the "before" half on the left */
  .hero-b__show-fade {
    position: absolute; inset: 0; z-index: 4; pointer-events: none;
    background: linear-gradient(180deg, rgba(5, 6, 8, 0) 72%, rgba(5, 6, 8, 0.55) 100%);
  }
  .hero-b__ba-img {
    position: absolute; inset: 0;
    width: 100%; height: 100%; object-fit: cover; object-position: center top;
    user-select: none; -webkit-user-drag: none;
  }
  /* clip-path (not width) so the "before" image keeps its own scale */
  .hero-b__ba-clip {
    position: absolute; inset: 0;
    clip-path: inset(0 calc(100% - var(--pos, 50%)) 0 0);
  }
  /* the "before" half is knocked back so the difference reads instantly,
     without needing a single word of explanation */
  .hero-b__ba-clip .hero-b__ba-img { filter: grayscale(0.55) brightness(0.7) contrast(0.92); }

  .hero-b__ba-line {
    position: absolute; top: 0; bottom: 0; left: var(--pos, 50%);
    width: 2px; margin-left: -1px; z-index: 3;
    background: var(--fg, #fff); box-shadow: 0 0 18px rgba(0, 0, 0, 0.7);
  }
  /* a real grab handle with arrows — reads as "drag me" on sight */
  .hero-b__ba-line::after {
    content: "‹ ›"; position: absolute; left: 50%; top: 50%;
    width: 34px; height: 34px; margin: -17px 0 0 -17px;
    border-radius: 50%; background: var(--fg, #fff); color: #050608;
    display: grid; place-items: center;
    font-family: var(--font-sans); font-size: 15px; font-weight: 700; letter-spacing: 1px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.6);
  }

  /* ---- motion: staggered entrance only. the hero does not react to the
     pointer — nothing here drifts with the mouse ---- */

  @keyframes hero-b-rise {
    from { opacity: 0; transform: translateY(22px); filter: blur(9px); }
    to   { opacity: 1; transform: translateY(0);    filter: blur(0); }
  }
  @keyframes hero-b-figure-in {
    from { opacity: 0; transform: translateY(34px) scale(1.03); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
  }
  .hero-b-on .hero-b__bar,
  .hero-b-on .hero-b__k,
  .hero-b-on .hero-b__title span,
  .hero-b-on .hero-b__sub,
  .hero-b-on .hero-b__actions,
  .hero-b-on .hero-b__shows {
    animation: hero-b-rise 0.85s cubic-bezier(0.22, 1, 0.36, 1) both;
  }
  .hero-b-on .hero-b__media img { animation: hero-b-figure-in 1.05s cubic-bezier(0.22, 1, 0.36, 1) both; }
  .hero-b-on .hero-b__bar         { animation-delay: 0.05s; }
  .hero-b-on .hero-b__media img   { animation-delay: 0.08s; }
  .hero-b-on .hero-b__k           { animation-delay: 0.18s; }
  .hero-b-on .hero-b__title span:nth-child(1) { animation-delay: 0.26s; }
  .hero-b-on .hero-b__title span:nth-child(2) { animation-delay: 0.34s; }
  .hero-b-on .hero-b__sub         { animation-delay: 0.44s; }
  .hero-b-on .hero-b__actions     { animation-delay: 0.52s; }
  .hero-b-on .hero-b__shows       { animation-delay: 0.62s; }

  /* narrower desktops: pull the figure in, let type breathe */
  /* (the copy's width is measured against the figure now — an override here
     would fight it, so this breakpoint only nudges the figure) */
  @media (max-width: 1180px) {
    .hero-b__media img { right: clamp(8px, 2vw, 40px); height: 82%; }
  }
  /* short screens: the stack shrinks with the fold instead of disappearing —
     the padding gives way first, then the screens scale down with it */
  @media (max-height: 760px) {
    .hero-b__grid {
      padding-top: clamp(64px, 9vh, 84px);
      padding-bottom: clamp(30px, 5.5vh, 44px);
    }
    .hero-b__shows { gap: clamp(12px, 2vh, 18px); }
    .hero-b__show-cap { margin-bottom: 6px; font-size: 0.58rem; }
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-b__scroll i { animation: none; }
  .hero-b-pop { animation: none; }
  .hero-b-on .hero-b__bar,
  .hero-b-on .hero-b__k,
  .hero-b-on .hero-b__title span,
  .hero-b-on .hero-b__sub,
  .hero-b-on .hero-b__actions,
  .hero-b-on .hero-b__shows,
  .hero-b-on .hero-b__media img { animation: none; }
  .hero-b__media img, .hero-b__show { transition: none; transform: none; }
}
