/* Beonyx — Image Grid
   A photograph under a hairline grid that draws itself on scroll.

   The grid is measured off the Figma export: three vertical lines at 25 / 50 /
   75%, two horizontal at 33 / 67%, white at 18%, one pixel thick. None of those
   numbers are written here — PHP spreads the lines evenly and hands each one its
   position, so the same stylesheet serves any count.

   A line is a plain 1px box scaled along its own length. That is the whole
   trick, and it is why there is no SVG here: scaleX / scaleY run on the
   compositor, they never touch layout, and setting transform-origin to the top,
   the bottom or the middle of the box is what gives every draw pattern its
   direction. Five choreographies, one animated property.

   Everything below paints the FINISHED state. The script adds .is-armed to
   collapse the lines before it plays them, so a visitor with no JavaScript — or
   a crawler — still gets the complete composition rather than a bare photo. */

/* Pinned rather than inherited: a line's thickness is a border-free pixel width,
   and the frame carries a radius. Both misbehave under content-box on themes
   that do not set border-box globally. */
.bnxg,
.bnxg *,
.bnxg *::before,
.bnxg *::after { box-sizing: border-box; }

.bnxg {
  --bnxg-line: #ffffff;
  --bnxg-line-op: 0.18;
  --bnxg-w: 1px;
  --bnxg-radius: 0px;

  --bnxg-draw: 1100ms;
  --bnxg-reveal: 700ms;
  --bnxg-ease: cubic-bezier(0.16, 1, 0.3, 1);

  --bnxg-pos-x: 50%;
  --bnxg-pos-y: 50%;

  /* frame height as a fraction of its width — 508.286 / 759 */
  --bnxg-ratio-n: 0.6697;

  position: relative;
  width: 100%;
  max-width: 759px;
  /* centre in containers wider than the cap, instead of leaving all the
     leftover space on the right */
  margin-left: auto;
  margin-right: auto;
}

/* ---------- the frame ---------- */
/* The frame stays in normal flow, and this is load-bearing. Elementor lays a
   widget out as a flex item sized to its content, and a box whose children are
   all absolutely positioned has a content width of zero — so a widget built that
   way collapses to 0 x 0 on the front end while looking fine in the editor.
   Keeping the frame and the photograph in flow gives it a real intrinsic size,
   exactly the way Elementor's own Image widget gets one. */

.bnxg-frame {
  position: relative;
  width: 100%;
  /* literal first, so a browser that will not take the calc keeps the design
     shape rather than collapsing the box to nothing */
  aspect-ratio: 759 / 508;
  aspect-ratio: calc(1 / var(--bnxg-ratio-n));
  overflow: hidden;
  border-radius: var(--bnxg-radius);
}

.bnxg-photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--bnxg-pos-x) var(--bnxg-pos-y);
}

/* ---------- the grid ---------- */

.bnxg-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Colour and strength live on the line rather than in an rgba(), so the colour
   control can stay a plain colour picker and still take a global from the site
   kit. Opacity here is free — it is a separate compositor property from the
   transform doing the drawing, so the two never fight. */

.bnxg-line {
  position: absolute;
  background: var(--bnxg-line);
  opacity: var(--bnxg-line-op);
  /* The line is repainted every frame while it grows. Promoting it keeps that
     on the compositor instead of forcing a paint of the photograph underneath. */
  will-change: transform;
}

/* --p is where the line sits; the negative margin pulls it back by half its own
   thickness so the line is CENTRED on that position rather than starting there.
   Doing it with a margin leaves the transform free for the animation alone.

   --o is the end the line grows from, as a percentage along its own length:
   0 the top or left, 100 the bottom or right, 50 the middle — which grows both
   ways at once. It is the only difference between four of the five patterns. */

.bnxg-line--v {
  top: 0;
  bottom: 0;
  left: var(--p, 50%);
  width: var(--bnxg-w);
  margin-left: calc(var(--bnxg-w) / -2);
  transform-origin: 50% var(--o, 0%);
}

.bnxg-line--h {
  left: 0;
  right: 0;
  top: var(--p, 50%);
  height: var(--bnxg-w);
  margin-top: calc(var(--bnxg-w) / -2);
  transform-origin: var(--o, 0%) 50%;
}

/* ---------- the draw ---------- */
/* .is-armed is added by the script; without it everything above is already in
   its final state. */

/* Arming runs with transitions OFF, so the lines snap to nothing instead of
   animating down into it. The script switches them on afterwards by adding
   .is-ready in a separate style flush. Without that split, a visitor who lands
   already scrolled to this section would watch the grid retract before it drew —
   the arming change would animate too. */

.bnxg.is-armed .bnxg-line {
  transition: none;
}

.bnxg.is-armed .bnxg-line--v { transform: scaleY(0); }
.bnxg.is-armed .bnxg-line--h { transform: scaleX(0); }

/* Note the 0ms delay here, and --d only on .is-shown. A transition uses whatever
   delay is in force at the moment the value changes, so the stagger applies on
   the way in and not on the way out. That only matters with Replay on, but it
   matters a lot: without it the grid would retract in slow motion, one line at a
   time, every time the section left the viewport. */

.bnxg.is-armed.is-ready .bnxg-line {
  transition: transform var(--bnxg-draw) var(--bnxg-ease) 0ms;
}

.bnxg.is-armed.is-ready.is-shown .bnxg-line {
  transition-delay: var(--d, 0ms);
}

.bnxg.is-armed.is-shown .bnxg-line--v { transform: scaleY(1); }
.bnxg.is-armed.is-shown .bnxg-line--h { transform: scaleX(1); }

/* ---------- the photograph's own fade ---------- */

.bnxg.is-armed.is-reveal .bnxg-frame {
  opacity: 0;
  transition: none;
}

.bnxg.is-armed.is-reveal.is-ready .bnxg-frame {
  transition: opacity var(--bnxg-reveal) ease;
}

.bnxg.is-armed.is-reveal.is-shown .bnxg-frame { opacity: 1; }

/* ---------- accessibility ---------- */
/* The script does not arm at all when the OS asks for reduced motion, so this is
   only a backstop for a stylesheet that outlives it. */

@media (prefers-reduced-motion: reduce) {
  .bnxg.is-armed .bnxg-line,
  .bnxg.is-armed.is-shown .bnxg-line {
    transform: none;
    transition: none;
  }

  .bnxg.is-armed.is-reveal .bnxg-frame {
    opacity: 1;
    transition: none;
  }
}
