/* ==========================================================================
   Technology hero  —  Figma "Technology" (894:7791), the hero band at y 0.
   1920 x 1988 on Mono/Dark: the console bottoms out at 1850 and How it works
   starts at 2052, so the section keeps 138 of its own and --flow-gap adds
   the remaining 64.

   Default -> Animate (paired positionally; Figma renumbers children per
   variant, so ids cannot be matched directly):
     glow / haze / console     rise 188, fade in
     logo                      translateX -170 -> 0
     nav pill                  translateY  +50 -> 0
     Login                     translateY  +50 -> 0
     Book a Demo               translateX +180 -> 0
     all four headline halves  translateY  +70 -> 0
     ONE ON-SITE COMPUTER      translateY  +40 -> 0
     ANY BRAND / ANY AGE       translateY  +20 -> 0
     dot grid                  grows from a 127x79 box to 787.25x492.213
                               about the same centre (927.5, 506.5), fading in
   ========================================================================== */

.tech-hero {
  top: 0;
  height: calc(1988 * var(--s));
  background: var(--c-mono-dark);
  overflow: hidden;
  z-index: 2;
}

.tech-hero__item { position: absolute; }

/* --- backdrop ------------------------------------------------------------ */

/* The glow behind the console.

   It used to fade up and slide in as one piece the instant the page painted,
   which put the whole gradient on screen before the reader had done anything.
   Now it is uncovered from its bottom edge upwards: a gradient mask whose
   stop travels from the foot of the box to above its head, so the image is
   revealed a band at a time and the leading edge stays soft. Nothing about
   the artwork moves -- only how much of it is showing.

   --wipe is that stop: 0 shows nothing, 1 shows all of it. It is registered
   in base.css, which is what makes it animatable at all; an unregistered
   custom property is just a string to the engine and jumps end to end. */
.tech-hero__glow {
  left: calc(49 * var(--s));
  top: calc(660 * var(--s));
  width: calc(1822 * var(--s));
  height: calc(1135 * var(--s));
  overflow: hidden;
  mix-blend-mode: screen;
  --wipe: 0;
  -webkit-mask-image: linear-gradient(to top,
    #000 calc(var(--wipe) * 100% - 22%), transparent calc(var(--wipe) * 100%));
          mask-image: linear-gradient(to top,
    #000 calc(var(--wipe) * 100% - 22%), transparent calc(var(--wipe) * 100%));
  /* Slow and eased: this is the one thing the reader should not catch
     moving. */
  transition: --wipe 2600ms var(--rv-ease);
}
.tech-hero.is-stage-in .tech-hero__glow { --wipe: 1.25; }

.tech-hero__glow img {
  position: absolute;
  left: -19.7%;
  top: -5.17%;
  width: 138.2%;
  height: 110.35%;
  max-width: none;
}

.tech-hero__haze {
  left: calc(-147 * var(--s));
  top: calc(313 * var(--s));
  width: calc(2207.172 * var(--s));
  height: calc(1694 * var(--s));
  pointer-events: none;
  transform: translateY(calc(188 * var(--s)));
  transition: transform calc(var(--rv-dur) * 1.2) var(--rv-ease);
}
.tech-hero.is-in .tech-hero__haze { transform: none; }
/* Figma exports blurred backdrop layers with negative-inset bleed. Written out
   as left/top/width/height rather than `inset` + width:auto: an <img> is a
   replaced element, so with auto width it keeps its intrinsic aspect and the
   `right`/`bottom` insets are simply dropped — the layer renders undersized. */
.tech-hero__haze img {
  position: absolute;
  left: -12.46%;
  top: -16.24%;
  width: 124.92%;
  height: 132.48%;
  /* the reset caps img at 100%; a bleed layer must opt out */
  max-width: none;
}

/* --- masthead ------------------------------------------------------------ */

.tech-hero__logo {
  left: calc(48 * var(--s));
  top: calc(36 * var(--s));
  width: calc(162.633 * var(--s));
  height: calc(40 * var(--s));
}
.tech-hero__logo img { width: 100%; height: 100%; }

.tech-hero__nav {
  left: calc(16.67% + 15 * var(--s));
  top: calc(32 * var(--s));
  width: calc(533 * var(--s));
  height: calc(48 * var(--s));
}
.tech-hero__nav-inner {
  display: flex;
  align-items: flex-start;
  gap: calc(24 * var(--s));
  padding: calc(14 * var(--s)) calc(24 * var(--s)) calc(15 * var(--s));
  background: var(--c-light-dark);
}

.tech-hero__login {
  left: calc(75% + 115.69 * var(--s));
  top: calc(32 * var(--s));
  width: calc(120.312 * var(--s));
  height: calc(48 * var(--s));
}
.tech-hero__cta {
  left: calc(83.33% + 100 * var(--s));
  top: calc(32 * var(--s));
  width: calc(172 * var(--s));
  height: calc(48 * var(--s));
}
.tech-hero__login .rv,
.tech-hero__cta .rv { height: 100%; }
.tech-hero__login .btn,
.tech-hero__cta .btn { width: 100%; height: 100%; }

/* --- split headline ------------------------------------------------------ */

.tech-hero__h {
  height: calc(86 * var(--s));
}
.tech-hero__h span {
  display: block;
  font-weight: 300;
  font-size: calc(72 * var(--s));
  line-height: 1.2;
  letter-spacing: calc(-2.88 * var(--s));
  color: var(--c-mono-light);
  white-space: nowrap;
}
.tech-hero__h--l1 { left: calc(8.33% + 22 * var(--s)); top: calc(419 * var(--s)); width: calc(312 * var(--s)); }
.tech-hero__h--l2 { left: calc(8.33% + 22 * var(--s)); top: calc(504 * var(--s)); width: calc(201 * var(--s)); }
.tech-hero__h--r1 { left: calc(66.67% + 69 * var(--s)); top: calc(419 * var(--s)); width: calc(389 * var(--s)); }
.tech-hero__h--r2 { left: calc(66.67% + 69 * var(--s)); top: calc(504 * var(--s)); width: calc(389 * var(--s)); }
.tech-hero__h--r1 span,
.tech-hero__h--r2 span { text-align: right; }

/* The phone frame's copy of the right-hand pair -- see tech-hero.php. It is
   off everywhere except inside the 376 layout, which turns the other pair
   off in its place. */
.tech-hero__h--narrow { display: none; }

/* Phone-only, like the pair above: the 1920 canvas shapes its bloom with the
   haze layer, the 376 frame lays two dark cut-outs over it instead. */
.tech-hero__shade { display: none; }

/* --- dot grid between the halves ----------------------------------------
   Grows about its own centre, so both boxes share the centre (927.5, 506.5). */

.tech-hero__dotgrid {
  left: calc(50% - 32.4 * var(--s));      /* centre 927.6 of 1920 */
  top: calc(506.7 * var(--s));
  width: calc(787.25 * var(--s));
  height: calc(492.213 * var(--s));
  transform: translate(-50%, -50%) scale(0.161);
  opacity: 0;
  transform-origin: center;
  transition:
    transform calc(var(--rv-dur) * 1.25) var(--rv-ease),
    opacity calc(var(--rv-dur) * 0.9) var(--rv-ease);
  pointer-events: none;
}
.tech-hero.is-in .tech-hero__dotgrid { transform: translate(-50%, -50%) scale(1); opacity: 1; }
/* The canvas fills the box exactly as the <img> did. It carries the reveal
   scale from its parent, so dotfield.js sizes the backing store from the
   element's layout width rather than its transformed bounding box. */
.tech-hero__dotgrid canvas { display: block; width: 100%; height: 100%; }

/* --- mono labels --------------------------------------------------------- */

.tech-hero__label--a {
  left: calc(16.67% + 15 * var(--s));
  top: calc(812 * var(--s));
  width: calc(91 * var(--s));
  height: calc(38 * var(--s));
}
.tech-hero__label--b {
  left: calc(25% + 20 * var(--s));
  top: calc(812 * var(--s));
  width: calc(163 * var(--s));
  height: calc(19 * var(--s));
  white-space: nowrap;
}

/* --- the review console -------------------------------------------------- */

/* Figma "Group 40041" (948:8662): x 240, y 970, 1440 x 880 — two panels,
   1093.6 and 328.64 wide, with 17.77 of hero between them. Both rects are
   their fill at 80%, which is the point: the glow behind has to read through
   them, so neither panel can be a flat image. */
/* --- the panel plates ----------------------------------------------------
   Each of the three panels is a rounded, TRANSLUCENT card in the frame --
   #030C1B at 0.75 for the console and 0.6 for the other two, radius 32, with
   a half-pixel #0087FF hairline at 0.4. The glow behind is meant to come
   through them.

   Figma bakes that fill flat when it exports a group: every panel arrived as
   an opaque rectangle of #030C1B with square corners, which is why the
   corners read as hard lines against the glow and why the panels sat heavier
   than the design. So the flat colour is keyed back out of each export (the
   assets carry alpha now) and the fill, the hairline and the radius are drawn
   here instead -- on the img itself, so its transparent areas show the plate
   and the plate shows the glow. */
.thero__console,
.thero__w--security,
.thero__w--actions {
  border: calc(0.5 * var(--s)) solid rgba(0, 135, 255, 0.4);
  border-radius: calc(32 * var(--s));
}
.thero__console       { background: rgba(3, 12, 27, 0.75); }
.thero__w--security,
.thero__w--actions    { background: rgba(3, 12, 27, 0.6); }

/* Figma 1064:146277. Positions are the frame's own, measured from the stage
   box that encloses all five pieces (180,970 to 1780,1931).

   They arrive in sequence rather than together. The console rises first and
   the four panels follow it, each a little later and each moving a little
   less than the one before -- 18 design px at most, a nudge rather than a
   flight.

   The whole thing waits for a small scroll: .is-stage-in is put on the
   section by tech-stage.js, not by the reveal engine, because the hero is
   already on screen at load and any viewport test would fire at once. */
.tech-hero__stage {
  left: calc(180 * var(--s));
  top: calc(970 * var(--s));
  width: calc(1600 * var(--s));
  height: calc(961 * var(--s));
}

.tech-hero__stage img { position: absolute; }

.thero__console {
  z-index: 2;
  left: calc(250 * var(--s));
  top: 0;
  width: calc(1100 * var(--s));
  height: calc(961 * var(--s));
  opacity: 0;
  transform: translateY(calc(34 * var(--s)));
  transition:
    opacity calc(var(--rv-dur) * 0.9) var(--rv-ease),
    transform calc(var(--rv-dur) * 1.15) var(--rv-ease);
}
.tech-hero.is-stage-in .thero__console { opacity: 1; transform: none; }

/* Everything drawn over the console arrives with it. */
.thero__feed, .thero__feed-cam, .thero__feed-scrim, .thero__feed-ui, .thero__strip {
  opacity: 0;
  transform: translateY(calc(34 * var(--s)));
  transition:
    opacity calc(var(--rv-dur) * 0.9) var(--rv-ease),
    transform calc(var(--rv-dur) * 1.15) var(--rv-ease);
}
.tech-hero.is-stage-in .thero__feed,
.tech-hero.is-stage-in .thero__feed-cam,
.tech-hero.is-stage-in .thero__feed-scrim,
.tech-hero.is-stage-in .thero__feed-ui,
.tech-hero.is-stage-in .thero__strip { opacity: 1; transform: none; }

/* --- the feed and the filmstrip ------------------------------------------
   The console export has one frame and four thumbnails baked into it. These
   sit exactly over them, at the frame's own coordinates (main camera 462,1050
   1036x594; thumbs at 486 / 618.1 / 798.4 / 1196.4, y 1745.5), so the
   filmstrip can be clicked and the frame it selects can change.

   The controls are the export's own, lifted off the baked video by luminance
   -- white glyphs survive the threshold, the footage under them does not --
   so they can sit on whichever frame is showing rather than on one. The dark
   band under them is redrawn as a gradient. */
.thero__feed {
  z-index: 2;
  left: calc(282 * var(--s));      /* 462 - 180, the stage's origin */
  top: calc(80 * var(--s));        /* 1050 - 970 */
  width: calc(1036 * var(--s));
  height: calc(594 * var(--s));
  object-fit: cover;
  border-radius: calc(6 * var(--s));
}
.thero__feed-cam {
  position: absolute;
  z-index: 2;
  left: calc(305 * var(--s));
  top: calc(101 * var(--s));
  font-size: max(11px, calc(14 * var(--s)));
  letter-spacing: 0;
  color: var(--c-mono-light);
  text-shadow: 0 calc(1 * var(--s)) calc(3 * var(--s)) rgba(0, 0, 0, 0.55);
  pointer-events: none;
}
.thero__feed-scrim {
  position: absolute;
  z-index: 2;
  left: calc(282 * var(--s));
  top: calc(544 * var(--s));
  width: calc(1036 * var(--s));
  height: calc(130 * var(--s));
  background: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.5));
  border-radius: 0 0 calc(6 * var(--s)) calc(6 * var(--s));
  pointer-events: none;
}
.thero__feed-ui {
  z-index: 2;
  left: calc(282 * var(--s));
  top: calc(589 * var(--s));       /* 1050 + 594 - 85 - 970 */
  width: calc(1036 * var(--s));
  height: calc(85 * var(--s));
  pointer-events: none;
}

.thero__strip {
  position: absolute;
  z-index: 2;
  left: 0;
  top: calc(775.5 * var(--s));     /* 1745.5 - 970 */
  width: 100%;
  height: calc(65 * var(--s));
}
.thero__thumb {
  position: absolute;
  top: 0;
  height: calc(65 * var(--s));
  padding: 0;
  overflow: hidden;
  border-radius: calc(4 * var(--s));
  /* Held clear of the image so the ring never crops the picture. */
  outline: calc(2 * var(--s)) solid transparent;
  outline-offset: calc(2 * var(--s));
  transition: outline-color var(--ui-dur) var(--ui-ease), opacity var(--ui-dur) var(--ui-ease);
  opacity: 0.65;
  cursor: pointer;
}
.thero__thumb img { width: 100%; height: 100%; object-fit: cover; }
.thero__thumb:hover { opacity: 0.85; }
.thero__thumb.is-on {
  opacity: 1;
  outline-color: var(--c-accent-yellow);
}
.thero__thumb:focus-visible { outline-color: var(--c-accent-yellow); }

/* The four panels. The security card tucks under the console's left edge;
   the actions card and the two bars sit over it, which is the frame's own
   stacking order. */
.thero__w {
  opacity: 0;
  transform: translateY(var(--rise, calc(18 * var(--s))));
  transition:
    opacity calc(var(--rv-dur) * 0.75) var(--rv-ease) var(--wait, 0ms),
    transform calc(var(--rv-dur) * 0.95) var(--rv-ease) var(--wait, 0ms);
}
.tech-hero.is-stage-in .thero__w { opacity: 1; transform: none; }

/* The four blurred plates -- Figma Rectangles 4679, 4680, 4681, 4682.

   Each sits BETWEEN two pieces in the frame's z-order rather than over the
   top of everything, which is what makes them read: 4679 is under the
   console and takes the hard edge off the security card where the console
   laps over it, 4680 does the same between the console and the actions card,
   and the last two are the soft dark and blue smudges the frame carries
   beside the Live Monitoring pill and the Events bar.

   Values are the frame's own: fill, radius, layer blur, blend mode and
   opacity, each verbatim. They are `i` elements because they are pure paint
   -- no box, no content, nothing to read out. */
.thero__veil {
  position: absolute;
  display: block;
  opacity: 0;
  transition: opacity calc(var(--rv-dur) * 0.75) var(--rv-ease) var(--wait, 0ms);
}
/* Each plate fades to ITS OWN opacity, not to 1 -- that number is part of
   the design, so it cannot be the generic reveal's end state. */
.tech-hero.is-stage-in .thero__veil { opacity: var(--o); }

/* #040c1b, 40 blur, 68%, radius 330. Under the console, over the security
   card. */
.thero__veil--a {
  z-index: 1;
  left: calc(210 * var(--s));
  top: calc(104 * var(--s));
  width: calc(128 * var(--s));
  height: calc(699 * var(--s));
  border-radius: calc(330 * var(--s));
  background: #040c1b;
  filter: blur(calc(40 * var(--s)));
  --o: 0.68;
  --wait: 260ms;
}
/* rgba(10,33,76,.85), 40 blur, multiply, 32%, radius 236. */
.thero__veil--b {
  z-index: 3;
  left: calc(1214 * var(--s));
  top: calc(515 * var(--s));
  width: calc(224 * var(--s));
  height: calc(310 * var(--s));
  border-radius: calc(236 * var(--s));
  background: rgba(10, 33, 76, 0.85);
  filter: blur(calc(40 * var(--s)));
  mix-blend-mode: multiply;
  --o: 0.32;
  --wait: 400ms;
}
/* #5098cc, 13.75 blur, multiply, 81%. */
.thero__veil--c {
  z-index: 5;
  left: calc(1463 * var(--s));
  top: calc(110 * var(--s));
  width: calc(214 * var(--s));
  height: calc(37 * var(--s));
  background: #5098cc;
  filter: blur(calc(13.75 * var(--s)));
  mix-blend-mode: multiply;
  --o: 0.81;
  --wait: 540ms;
}
/* #030c1b, 13.75 blur, fully opaque. */
.thero__veil--d {
  z-index: 7;
  left: calc(613 * var(--s));
  top: calc(905 * var(--s));
  width: calc(499 * var(--s));
  height: calc(37 * var(--s));
  background: #030c1b;
  filter: blur(calc(13.75 * var(--s)));
  --o: 1;
  --wait: 660ms;
}

.thero__w--security {
  z-index: 0;
  left: 0;
  top: calc(127 * var(--s));
  width: calc(320 * var(--s));
  height: calc(629 * var(--s));
  --wait: 260ms;
  --rise: calc(18 * var(--s));
}
.thero__w--actions {
  z-index: 4;
  left: calc(1280 * var(--s));
  top: calc(528 * var(--s));
  width: calc(320 * var(--s));
  height: calc(300 * var(--s));
  --wait: 400ms;
  --rise: calc(15 * var(--s));
}
.thero__w--live {
  z-index: 6;
  left: calc(1238 * var(--s));
  top: calc(102 * var(--s));
  width: calc(217 * var(--s));
  height: calc(32 * var(--s));
  --wait: 540ms;
  --rise: calc(11 * var(--s));
}
.thero__w--events {
  z-index: 8;
  left: calc(104 * var(--s));
  top: calc(901 * var(--s));
  width: calc(503 * var(--s));
  height: calc(28 * var(--s));
  --wait: 660ms;
  --rise: calc(8 * var(--s));
}

@media (prefers-reduced-motion: reduce) {
  .tech-hero__haze, .thero__console, .thero__w, .tech-hero__dotgrid {
    opacity: 1 !important; transform: none !important; transition: none;
  }
  .thero__veil { opacity: var(--o) !important; transition: none; }
  .tech-hero__glow { --wipe: 1.25; transition: none; }
  .tech-hero__dotgrid { transform: translate(-50%, -50%) !important; }
}

/* ==========================================================================
   Reflow
   ========================================================================== */

@media (max-width: 1500px) {
  .tech-hero__h span { font-size: calc(56 * var(--s)); }
}

@media (max-width: 1023px), (max-width: 1200px) and (orientation: portrait) {
  .tech-hero { height: auto; padding: 24px 20px 48px; }
  .tech-hero__item { position: static; width: auto; height: auto; }
  .tech-hero__glow, .tech-hero__haze, .tech-hero__dotgrid { display: none; }

  .tech-hero__masthead {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
  }
  .tech-hero__logo { width: 132px; height: 32px; flex: none; }
  .tech-hero__nav, .tech-hero__login { display: none; }
  .tech-hero__cta { width: auto; }
  .tech-hero__cta .btn { font-size: 14px; padding: 10px 16px; width: auto; height: auto; }

  .tech-hero__h { margin-top: 12px; }
  /* The phone pair is off in this band, and its own layout right-aligns it,
     so it is held out of the !important rather than made to fight it. */
  .tech-hero__h:not(.tech-hero__h--narrow) span {
    font-size: clamp(34px, 10vw, 52px);
    letter-spacing: -0.04em;
    white-space: normal;
    text-align: left !important;
  }
  .tech-hero__h--l1 { margin-top: 40px; }

  .tech-hero__label--a { margin-top: 24px; font-size: 12px; }
  .tech-hero__label--b { margin-top: 8px; font-size: 12px; }

  /* The console is a fixed 1440-wide composition of absolutely-placed layers,
     so it cannot reflow — it scales. Redefining --s on the wrapper rescales
     every child at once, since that is the unit all of them are written in. */
  /* The stage is a fixed 1600-wide composition of absolutely-placed layers,
     so it cannot reflow -- it scales. Redefining --s on the wrapper rescales
     every child at once, since that is the unit all of them are written in. */
  .tech-hero__stage {
    position: relative;
    /* left/top are the desktop frame's coordinates. position: relative makes
       them OFFSETS rather than positions, so left alone they shove the stage
       180 * --s to the right of the padding and 970 down -- it left the
       column by 39px at 390 and 111px at 1024. */
    left: auto;
    top: auto;
    --s: calc((100vw - 40px) / 1600);
    width: calc(1600 * var(--s));
    height: calc(961 * var(--s));
    margin-top: 32px;
  }

  .o-page--tech .dots { top: auto; }
}
