/* ============================================================================
   Video Banner - Fluxr Works
   ----------------------------------------------------------------------------
   Styles for the video banner on services.html (the strip below the large
   FLUXR heading). Loaded after style.css.

   Nothing here touches existing classes, so removing this file and the
   matching block in services.html restores the old image banner.

   Contents:
     1. Banner and video
     2. Control cluster (bottom right)
     3. Buttons
     4. Volume slider (slides open next to the sound button)
     5. Small screens
     6. Reduced motion
     7. Cover variant (index.html intro band, video behind overlaid text)
     8. Inline variant (services.html "Working Together", video in a column)
     9. Glass music controls (index.html banner, no brand colour)
   ========================================================================== */


/* ------------------------------- 1. Banner ------------------------------- */

.video-banner {
    position: relative;
    overflow: hidden;
    background-color: var(--dark-gray, #232323);
}

.video-banner__media {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}


/* ------------------------------ 2. Controls ------------------------------ */

.video-banner__controls {
    position: absolute;
    right: 30px;
    bottom: 30px;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 12px;

    /* Revealed by JS once the video can actually play, so the controls never
       appear next to a still poster that isn't going anywhere. */
    opacity: 0;
    visibility: hidden;
    transition: opacity .4s ease, visibility .4s ease;
}

.video-banner.is-ready .video-banner__controls {
    opacity: 1;
    visibility: visible;
}

.video-banner__sound {
    display: flex;
    align-items: center;
}


/* ------------------------------- 3. Buttons ------------------------------ */

.video-banner__btn {
    /* 44px keeps the tap target at the accessible minimum. */
    width: 44px;
    height: 44px;
    flex: 0 0 44px;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.45);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    color: var(--white, #ffffff);
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .3s ease, border-color .3s ease, color .3s ease;
}

.video-banner__btn:hover,
.video-banner__btn:focus-visible {
    background: var(--orange, #ef534b);
    border-color: var(--orange, #ef534b);
    color: var(--white, #ffffff);
}

.video-banner__btn:focus-visible {
    outline: 2px solid var(--white, #ffffff);
    outline-offset: 3px;
}

/* Sound on: keep the button lit so the state is readable at a glance. */
.video-banner__btn--sound[aria-pressed="true"] {
    background: var(--orange, #ef534b);
    border-color: var(--orange, #ef534b);
}


/* ---------------------------- 4. Volume slider --------------------------- */

/* The slider sits to the LEFT of the sound button and is collapsed until sound
   is switched on. Opening it grows the cluster leftwards, so the sound button
   itself never moves - the visitor's pointer stays on it. */
.video-banner__volume {
    width: 0;
    /* style.css styles every input with padding and a border. Left alone, that
       padding keeps the collapsed slider ~52px wide and shoves the buttons over. */
    min-width: 0;
    padding: 0;
    border: none;
    box-shadow: none;
    margin: 0;
    opacity: 0;
    pointer-events: none;
    height: 4px;
    flex: 0 0 auto;
    border-radius: 4px;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    transition: width .35s ease, opacity .35s ease, margin .35s ease;

    /* Filled portion of the track is painted by JS via --vb-fill. */
    background-image: linear-gradient(to right,
            var(--orange, #ef534b) 0%,
            var(--orange, #ef534b) var(--vb-fill, 60%),
            rgba(255, 255, 255, 0.35) var(--vb-fill, 60%),
            rgba(255, 255, 255, 0.35) 100%);
}

.video-banner__volume.is-open {
    width: 90px;
    opacity: 1;
    pointer-events: auto;
    margin-right: 12px;
}

.video-banner__volume::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--white, #ffffff);
    border: none;
    cursor: pointer;
}

.video-banner__volume::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--white, #ffffff);
    border: none;
    cursor: pointer;
}

.video-banner__volume::-moz-range-track {
    background: transparent;
}

.video-banner__volume:focus-visible {
    outline: 2px solid var(--white, #ffffff);
    outline-offset: 4px;
}


/* ----------------------------- 5. Small screens -------------------------- */

@media screen and (max-width: 991px) {
    .video-banner__controls {
        right: 20px;
        bottom: 20px;
    }

    .video-banner__volume.is-open {
        width: 80px;
    }
}

@media screen and (max-width: 575px) {
    .video-banner__volume.is-open {
        width: 64px;
        margin-right: 8px;
    }
}


/* ---------------------------- 6. Reduced motion -------------------------- */

@media (prefers-reduced-motion: reduce) {

    .video-banner__controls,
    .video-banner__btn,
    .video-banner__volume {
        transition: none;
    }
}


/* ---------------------------- 7. Cover variant --------------------------- */

/* Used by the "creative that performs starts here" band on index.html, where
   the video is a background for text rather than a banner in its own right.

   Layering inside that section, bottom to top:

     background-image  the poster, painted by the data-background handler in
                       scripts.js. Stays visible if autoplay is refused or
                       neither video source can be played.
     .video-banner__media   z-index 0
     [data-overlay-dark]:before  z-index 1, the 40% dark wash from style.css
     .container        z-index 7, the icon and heading

   The section keeps its normal padding, so its height still comes from the
   text. The video just fills whatever that works out to. */

.video-banner--cover {
    position: relative;
    overflow: hidden;

    /* The section's background is the poster, and it has to be framed the same
       way as the video sitting on top of it, or the fallback jumps to a
       different part of the shot. style.css only sets background-size on
       .bg-img, so without these the poster defaults to 0% 0% (top left) while
       the video defaults to centre. */
    background-position: center center;
    background-repeat: no-repeat;
}

.video-banner--cover .video-banner__media {
    z-index: 0;

    /* Safari leaves a hairline of section background along the edges when the
       page is on a fractional zoom or a non-integer device pixel ratio. */
    top: -1px;
    left: -1px;
    width: calc(100% + 2px);
    height: calc(100% + 2px);
}

/* The base .video-banner rule paints a dark grey behind the video. Here the
   poster is doing that job, so let it through. */
.video-banner--cover {
    background-color: transparent;
}


/* --- Keeping the skateboarder in shot on narrow screens ------------------

   The clip is 16:9, but this band turns tall and narrow on phones (roughly
   390x740). Filling that with `cover` scales to height and throws away about
   70% of the frame width, and a centred crop lands on empty sand: the rider
   sits at 65-77% across the frame, well outside the 35-65% a centred crop
   leaves visible.

   Nudging the focal point to 70% pulls the rider back into shot. It cannot be
   100% - that would pin the crop to the right edge and lose the shadow the
   rider is casting, which is most of what makes the shot read.

   Measured against the section's real dimensions, a centred crop starts
   clipping the rider at 600px and below; 640px and up is fine either way. The
   767px breakpoint below sits in that gap with room to spare.

   Both properties have to move together, or the poster and the video frame the
   shot differently and it jumps when playback starts. */

@media screen and (max-width: 767px) {

    .video-banner--cover {
        background-position: 70% center;
    }

    .video-banner--cover .video-banner__media {
        object-position: 70% center;
    }

    /* The shifted crop brings brighter sand in behind the heading, which took
       the worst-case contrast for the white text from 4.3:1 down to 2.5:1 -
       under the 3:1 WCAG AA needs for large text, over about 0.2% of the
       heading area. Ten more points of overlay puts the whole block back above
       the line (worst case 3.3:1) and is barely perceptible on the video.
       Phones only; data-overlay-dark="4" still applies everywhere else. */
    .video-banner--cover[data-overlay-dark]:before {
        opacity: .5;
    }
}


/* Reduced motion: the script holds the video on its poster frame, which is the
   same image as the section background, so the band simply looks like the
   still banner it replaced. */


/* --------------------------- 8. Inline variant --------------------------- */

/* The "Working Together" video on services.html sits in a column where an
   <img> used to be, not in a full-width strip.

   .fit-img only styles `img` children, so the video would otherwise land
   unstyled, and the base .video-banner__media rule above would take it out of
   the flow with position:absolute and collapse the column to nothing. This
   variant puts it back in normal flow and lets it set its own height from its
   aspect ratio, which is how the image it replaced behaved. */

.fit-video video {
    position: static;
    width: 100%;
    height: auto;
    display: block;
    object-fit: cover;
}

/* The clip opens on a white fade-in, so on a light page the block can look
   empty for the first few frames. A faint backdrop keeps the rounded shape
   visible while that happens, and shows through if the video never plays. */
.fit-video {
    background-color: rgba(127, 127, 127, .08);
}


/* ------------------------ 9. Glass music controls ------------------------ */

/* The home banner's music control. Deliberately colourless: frosted glass,
   a hairline border and white marks, so it reads on any frame of the video
   without pulling the brand orange into the hero.

   Everything here is scoped to --glass, so the services and about strips keep
   the original orange treatment. */

/* Section 2 puts the cluster at z-index 3, which clears the dark overlay but
   sits under .container (z-index 7). The container's box reaches down over
   this corner, so at z-index 3 it would swallow the clicks. */
.video-banner--cover .video-banner__controls--glass {
    z-index: 8;
}

.video-banner__controls--glass .video-banner__btn {
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.30);
    -webkit-backdrop-filter: blur(14px) saturate(120%);
    backdrop-filter: blur(14px) saturate(120%);
    color: #ffffff;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.18);
}

/* No colour on hover or when active - just a touch more light in the glass. */
.video-banner__controls--glass .video-banner__btn:hover,
.video-banner__controls--glass .video-banner__btn:focus-visible,
.video-banner__controls--glass .video-banner__btn--sound[aria-pressed="true"] {
    background: rgba(255, 255, 255, 0.22);
    border-color: rgba(255, 255, 255, 0.45);
    color: #ffffff;
}

/* Slider track and fill in white rather than orange. */
.video-banner__controls--glass .video-banner__volume {
    background-image: linear-gradient(to right,
            rgba(255, 255, 255, 0.92) 0%,
            rgba(255, 255, 255, 0.92) var(--vb-fill, 45%),
            rgba(255, 255, 255, 0.28) var(--vb-fill, 45%),
            rgba(255, 255, 255, 0.28) 100%);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
}


/* --- The equaliser mark ------------------------------------------------- */

/* Four bars that rise and fall while the music plays and settle flat when it
   is paused, so the button shows its own state without needing a second icon
   or a colour change. */

.video-banner__eq {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
    width: 16px;
    height: 14px;
}

.video-banner__eq span {
    display: block;
    width: 2px;
    height: 100%;
    border-radius: 1px;
    background: currentColor;

    /* Paused: a flat, low row of bars. */
    transform: scaleY(0.28);
    transform-origin: center;
    transition: transform .25s ease;
}

.video-banner__btn--sound[aria-pressed="true"] .video-banner__eq span {
    animation: vb-eq 1.05s ease-in-out infinite;
}

/* Offset each bar so the row ripples instead of pumping as one block. */
.video-banner__btn--sound[aria-pressed="true"] .video-banner__eq span:nth-child(1) {
    animation-delay: -.9s;
}

.video-banner__btn--sound[aria-pressed="true"] .video-banner__eq span:nth-child(2) {
    animation-delay: -.45s;
}

.video-banner__btn--sound[aria-pressed="true"] .video-banner__eq span:nth-child(3) {
    animation-delay: -.15s;
}

.video-banner__btn--sound[aria-pressed="true"] .video-banner__eq span:nth-child(4) {
    animation-delay: -.65s;
}

@keyframes vb-eq {

    0%,
    100% {
        transform: scaleY(0.28);
    }

    50% {
        transform: scaleY(1);
    }
}

/* Reduced motion: no bouncing bars. The button still shows on/off, just as a
   taller or shorter static row. */
@media (prefers-reduced-motion: reduce) {

    .video-banner__eq span {
        transition: none;
    }

    .video-banner__btn--sound[aria-pressed="true"] .video-banner__eq span {
        animation: none;
        transform: scaleY(0.85);
    }
}


/* ============================================================================
   Mobile compositing fix
   ----------------------------------------------------------------------------
   Symptom: on a phone, everything below the video banner renders white, and
   scrolling back up blanks content that had already been painted.

   Cause: backdrop-filter sampling a playing <video>. To blur what is behind
   the sound controls, the compositor has to read back the video frame every
   time it paints. On iOS and on Android devices with modest GPUs, that
   read-back is expensive enough that under memory pressure the browser gives
   up on painting whole regions, and the casualties are the layers around it
   rather than the blurred element itself. It is not a bug in the layout, and
   nothing in the markup above it is wrong, which is why it survives changes
   to the scroll setup.

   On touch devices the blur is therefore dropped and replaced with a plain
   translucent fill. It looks near enough identical at arm's length and costs
   the compositor nothing.

   Desktop keeps the real glass effect, where there is GPU budget for it.
   ========================================================================== */

@media (hover: none) and (pointer: coarse) {

    .video-banner__btn,
    .video-banner__controls--glass .video-banner__btn,
    .video-banner__controls--glass .video-banner__volume {
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }

    /* Slightly more opaque, since there is no blur doing the work of
       separating the control from the picture behind it. */
    .video-banner__btn {
        background: rgba(0, 0, 0, 0.55);
    }

    .video-banner__controls--glass .video-banner__btn {
        background: rgba(20, 22, 26, 0.55);
        border-color: rgba(255, 255, 255, 0.35);
    }

    .video-banner__controls--glass .video-banner__btn:hover,
    .video-banner__controls--glass .video-banner__btn:focus-visible,
    .video-banner__controls--glass .video-banner__btn--sound[aria-pressed="true"] {
        background: rgba(20, 22, 26, 0.72);
    }

    /* Keep the video's own layer as small and simple as the browser will
       allow: no rounding to clip against, and no promotion of the section
       into a layer of its own that the video then has to composite into. */
    .video-banner__media {
        border-radius: 0;
    }
}

/* Narrow viewports that report as pointer devices (a desktop browser resized
   down, and some Android tablets) get the same treatment. */
@media (max-width: 991px) {

    .video-banner__btn,
    .video-banner__controls--glass .video-banner__btn,
    .video-banner__controls--glass .video-banner__volume {
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
}
