/* ───────────────────────────────────────────────────────────────
   HERO

   .hero-wrap supplies the scroll distance; .hero sticks to the top and
   transforms in place while that distance is consumed.

   The room is a rendered plate. .hero__frame keeps the plate's aspect ratio
   and is sized to cover the viewport, and every tool is positioned as a
   percentage of that same frame — so the tools stay planted on the pedestal
   at any window shape. Change the plate and only PEDESTAL in Hero.js moves.
   ─────────────────────────────────────────────────────────────── */

.hero-wrap {
  position: relative;
  height: 240vh;
  background: #050607;
  --hero-ink: #ffffff;
  --plate-aspect: 1.5;
}

.hero {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  display: grid;
  align-items: center;
  isolation: isolate;
  padding-top: var(--nav-height);
  --tool-px: 0px;
  --stand: 40vh;   /* replaced by the measured value as soon as JS runs */
}

/* ── The room ─────────────────────────────────────────────────── */
.hero__scene {
  position: absolute;
  inset: 0;
  overflow: hidden;
  display: grid;
  place-items: center;
  z-index: 0;
  will-change: filter;
}

/* Cover the viewport without ever distorting the plate: whichever axis is
   short gets overflowed, never stretched. */
.hero__frame {
  position: relative;
  width: max(100vw, calc(100svh * var(--plate-aspect)));
  height: max(100svh, calc(100vw / var(--plate-aspect)));
  --px: 0%;
  --py: 0%;
  --shift: 0%;          /* pushes the pedestal right on narrow screens */
  --zoom: 1;
  /* The plate starts at the screen's left edge, so a shift can only ever move
     it left (up to its overflow) without exposing bare background. The 4% and
     8% nudges on laptop widths used to leave a 51–92px empty strip down the
     left of the hero; clamping keeps the photo edge to edge. */
  transform: translate3d(calc(var(--px) + clamp(calc(100vw - 100%), var(--shift), 0px)), var(--py), 0) scale(var(--zoom));
  transform-origin: 59.95% 60%;   /* push in toward the pedestal */
  will-change: transform;
}

.hero__plate,
.hero__plate img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Cross-fade between the night and day plates on theme change. Both are in
   the document, so the swap is instant and never shows the wrong room. */
.hero__plate { transition: opacity 320ms var(--ease-out); }
.hero__plate--light { opacity: 0; }
.hero__plate--dark  { opacity: 1; }
[data-theme='light'] .hero__plate--light { opacity: 1; }
[data-theme='light'] .hero__plate--dark  { opacity: 0; }

/* ── Glows pinned to the plate's own light sources ── */
.hero__glow {
  position: absolute;
  pointer-events: none;
  mix-blend-mode: screen;
  will-change: opacity, transform;
}
.hero__glow--forge {
  left: 71.2%; top: 43.5%;
  width: 42%; height: 46%;
  translate: -50% -50%;
  background: radial-gradient(closest-side, rgba(255, 150, 60, 0.40), rgba(255, 90, 20, 0.14) 45%, transparent 72%);
  animation: forge-breathe 3.4s ease-in-out infinite alternate;
}
.hero__glow--ring {
  left: 58.5%; top: 63%;
  width: 46%; height: 18%;
  translate: -50% -50%;
  background: radial-gradient(closest-side, rgba(255, 30, 40, 0.42), rgba(225, 20, 28, 0.12) 55%, transparent 75%);
  animation: ring-breathe 2.6s ease-in-out infinite alternate;
}
@keyframes forge-breathe {
  from { opacity: 0.72; transform: scale(0.96); }
  to   { opacity: 1;    transform: scale(1.05); }
}
@keyframes ring-breathe {
  from { opacity: 0.68; }
  to   { opacity: 1; }
}

/* ── Tools standing on the pedestal ── */
/* Tools sit directly on the frame, not inside a zero-sized wrapper.
   A percentage height resolves against the containing block, and a positioned
   wrapper with height:0 made that zero — every tool rendered invisible. The
   frame has a real height, so the percentages mean what they say. */
.hero__tool {
  position: absolute;
  left: var(--x);
  /* --y is measured from the top of the plate; bottom anchors the tool's base
     there so it stands on the pedestal rather than hanging from it. */
  bottom: calc(100% - var(--y));
  height: calc(var(--ratio) * var(--stand));
  aspect-ratio: var(--aspect);
  --sx: 0px; --sy: 0px; --sr: 0deg; --ss: 1;
  /* translateX(-50%) centres the tool on its slot; the rest is the scatter. */
  transform:
    translateX(-50%)
    translate3d(calc(var(--sx) + var(--tool-px)), var(--sy), 0)
    rotate(calc(var(--lean) + var(--sr)))
    scale(var(--ss));
  transform-origin: 50% 100%;
  will-change: transform, opacity;
  /* These are set dressing, not the subject. Knocking back the brightness and
     saturation, adding a whisper of blur and letting a little of the room
     through settles them into the plate instead of sitting on top of it. */
  opacity: 0.88;
  filter:
    brightness(0.72)
    saturate(0.8)
    contrast(0.95)
    blur(0.35px)
    drop-shadow(0 12px 16px rgba(0, 0, 0, 0.75));
}
.hero__tool picture,
.hero__tool img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: bottom;
}

/* ── Atmosphere ── */
.hero__layer { position: absolute; inset: 0; pointer-events: none; }
.hero__layer--embers { z-index: 1; }
.hero__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero__layer--grain {
  z-index: 2;
  background-image: radial-gradient(rgba(255, 255, 255, 0.5) 0.5px, transparent 0.5px);
  background-size: 3px 3px;
  opacity: 0.03;
  mix-blend-mode: overlay;
}
.hero__layer--veil { z-index: 6; background: #000; opacity: 0; }

/* ── Copy ─────────────────────────────────────────────────────── */
.hero__content {
  position: relative;
  z-index: 3;
  /* Anchored to the site's left gutter, not centred.
     .shell applies margin-inline:auto, which pushed this column into the
     middle of the frame and straight across the tools — so the hero copy
     places itself instead of borrowing that class. */
  justify-self: start;
  width: min(31rem, 38vw);
  margin-left: max(var(--shell-pad), calc((100% - var(--shell-max)) / 2 + var(--shell-pad)));
  will-change: transform, opacity, filter;
  /* The plate is darkest at the left, which is where the text sits. */
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.6);
}

.hero__tagline {
  display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center;
  font-size: var(--size-xs); letter-spacing: var(--tracking-wide);
  text-transform: uppercase; color: var(--steel-200);
  margin-bottom: var(--space-5);
}
.hero__sep { color: var(--red-text); }

.hero__title { font-size: clamp(2.1rem, 4.4vw, 4.4rem); line-height: 0.94; }
.hero__title-line { display: block; white-space: nowrap; }
.hero__title-line--light  { font-weight: 600; color: var(--hero-ink); opacity: 0.94; }
.hero__title-line--accent { font-weight: 900; color: #ff2630; }
.hero__title-line--heavy  { font-weight: 900; color: var(--hero-ink); }

.hero__desc {
  margin-block: var(--space-5) var(--space-6);
  max-width: 32rem; color: var(--steel-200); font-size: var(--size-md);
}

.hero__scroll {
  position: absolute; right: var(--shell-pad); bottom: var(--space-6); z-index: 5;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
  font-size: var(--size-xs); letter-spacing: var(--tracking-wide);
  text-transform: uppercase; color: var(--steel-300);
}
.hero__scroll-line {
  width: 1px; height: 52px;
  background: linear-gradient(var(--steel-300), transparent);
  transform-origin: 50% 0;
  animation: hero-cue 2.4s var(--ease-inout) infinite;
}
@keyframes hero-cue {
  0%, 100% { transform: scaleY(0.35); opacity: 0.4; }
  50%      { transform: scaleY(1);    opacity: 1; }
}

/* ── Entrance ── */
.hero__reveal { opacity: 0; transform: translate3d(0, 26px, 0); }
.hero.is-ready .hero__reveal {
  opacity: 1; transform: none;
  transition:
    opacity 900ms var(--ease-out) var(--delay, 0ms),
    transform 900ms var(--ease-out) var(--delay, 0ms);
}

/* ── Light theme ──
   A genuine daylight plate of the same room, not a filter over the night one.
   The copy flips to dark ink because the wall behind it is now pale, and the
   glows drop back since the room no longer needs them to carry the frame. */
[data-theme='light'] .hero-wrap { background: #ffffff; --hero-ink: #0e1113; }
[data-theme='light'] .hero__content { text-shadow: 0 1px 16px rgba(255, 255, 255, 0.75); }
[data-theme='light'] .hero__tagline,
[data-theme='light'] .hero__desc { color: #2c3238; }
[data-theme='light'] .hero__title-line--accent { color: #c8101a; }
[data-theme='light'] .hero__scroll { color: #2c3238; text-shadow: 0 0 10px rgba(255, 255, 255, 0.95), 0 0 2px rgba(255, 255, 255, 0.9); }
/*
 * Readability over the daylight photo. The dark theme's copy sits on the
 * darkest part of the night plate; the daylight plate is mid-grey and busy
 * behind the headline, so the dark copy measured 1.3–3.9:1 there. A soft
 * white wash behind the copy only (not the tools or the room) brings every
 * line above 4.5:1. It lives inside .hero__content, so it fades, lifts and
 * blurs away with the copy when the hero dissolves on scroll.
 */
[data-theme='light'] .hero__content::before {
  content: '';
  position: absolute; z-index: -1; pointer-events: none;
  /* A box centred on the copy; closest-side makes the wash reach zero
     exactly at the box edge, so it never shows a hard line. */
  top: 50%; left: 42%;
  width: 190%; height: 175%;
  translate: -50% -50%;
  background: radial-gradient(closest-side,
    rgba(255, 255, 255, 0.88) 0%, rgba(255, 255, 255, 0.8) 38%, rgba(255, 255, 255, 0.5) 66%, rgba(255, 255, 255, 0.16) 86%, rgba(255, 255, 255, 0) 100%);
  /* The copy occupies 28–81% of this box across and 21–79% down, at every
     screen size. Past its right and bottom edges the wash only fogged the
     tools on the pedestal, so it fades out there. Inside the copy's own box
     nothing changes, so the text contrast measured above is untouched. */
  -webkit-mask-image: linear-gradient(to right, #000 81%, transparent 90%), linear-gradient(to bottom, #000 79%, transparent 90%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to right, #000 81%, transparent 90%), linear-gradient(to bottom, #000 79%, transparent 90%);
  mask-composite: intersect;
}
[data-theme='light'] .hero__scroll-line { background: linear-gradient(#2c3238, transparent); }
[data-theme='light'] .hero__glow--forge { opacity: 0.55; }
[data-theme='light'] .hero__glow--ring { opacity: 0.7; }
[data-theme='light'] .hero__layer--grain { opacity: 0.015; }
[data-theme='light'] .hero__layer--veil { background: #ffffff; }
/*
 * Tools in daylight. At 92% brightness with a faint shadow the chrome and red
 * glared against the pale room and the tools looked pasted on. Toned to sit
 * in the same light as the plate: chrome keeps its highlights without
 * clipping, the red deepens, and a firmer shadow grounds them on the pedestal.
 */
[data-theme='light'] .hero__tool {
  opacity: 0.94;
  filter:
    brightness(0.74) saturate(0.72) contrast(1.06) blur(0.3px)
    drop-shadow(0 12px 18px rgba(18, 22, 26, 0.55));
}

/* ── Narrow screens ──
   The pedestal sits right of centre in the plate, so on a phone the frame is
   nudged to keep it in view while the copy takes the upper half. */
/* As the window narrows the copy column and the tools converge. Rather than
   shrink the type further, the scene slides right so the pedestal keeps clear
   of the headline — the plate is wider than the viewport at these sizes, so
   there is spare image to move into. */
@media (max-width: 1366px) {
  .hero__frame { --shift: 4%; }
  .hero__content { width: min(28rem, 34vw); }
}

@media (max-width: 1100px) {
  .hero__frame { --shift: 8%; }
  .hero__content { width: min(26rem, 33vw); }
}

@media (max-width: 900px) {
  .hero-wrap { height: 215vh; }
  .hero { align-content: start; padding-top: calc(var(--nav-height) + 4vh); }
  .hero__content { width: auto; margin-inline: var(--shell-pad); }
  .hero__title { font-size: clamp(2rem, 8.5vw, 3.1rem); }
  /* On a phone the plate is three times wider than the screen and starts at
     its left edge, so the pedestal (about 60% across) landed off-screen: no
     tool was visible at 390px wide, and only three of five on a tablet. The
     old fixed -10% assumed the plate was centred, which it is not.

     This slides the plate so the middle of the tool line-up (--lineup-x, set
     by Hero.js) is the middle of the screen — `50vw - x%`, where % is the
     plate's own width — clamped so the plate always still covers the screen
     edge to edge. */
  .hero__frame {
    --shift: clamp(calc(100vw - 100%), calc(50vw - var(--lineup-x, 61.5%)), 0px);
    transform-origin: var(--lineup-x, 59.95%) 64%;
    /* --frame-h (set by Hero.js) is the plate height that lands the pedestal
       under the stacked copy; the width follows so the photo is never stretched. */
    height: max(100svh, calc(100vw / var(--plate-aspect)), var(--frame-h, 0px));
    width: max(100vw, calc(max(100svh, var(--frame-h, 0px)) * var(--plate-aspect)));
  }
  /* Height comes from --stand, which Hero.js fits to the space under the copy. */
  /* A phone held sideways has no room under the copy; the tools stand behind
     it, dimmed so the headline and description stay readable. */
  .hero--tools-behind .hero__tool { opacity: 0.45; }
  .hero__scroll { display: none; }
}

@media (max-width: 560px) {
  .hero__desc { font-size: var(--size-base); }
}

/* ── Reduced motion: no pinning, no drift, no pulse. ── */
@media (prefers-reduced-motion: reduce) {
  .hero-wrap { height: auto; }
  .hero { position: relative; height: 100svh; }
  .hero__glow, .hero__scroll-line { animation: none; }
  .hero__reveal { opacity: 1; transform: none; }
}
