/* ==========================================================================
   Videos listing page (Figma: QF - BilAraby - WebsiteDesign-Concept-2,
   node 40001286:70250 "Videos"). Reuses the --hr-* tokens declared globally
   in layout-revamp.css and follows the same page-pattern established by
   bilaraby-talks-revamp.css: an "Innerpage-hero" (breadcrumb + diamond
   divider) followed by a featured carousel and a filterable grid.

   No photo banner here — per request, the hero is the same flat coral
   "liquid" gradient wash as .tlkd-revamp (BilAraby Talk details page),
   bleeding from behind the header down through the hero.

   The hero is otherwise the shared "Innerpage-hero/Without" treatment the
   Events, Speakers, Annual Gatherings and Search heroes already carry — a tiled
   grain over the wash, Figma's two corner wedges
   (innerpage-hero/hero-pattern-nobanner-{left,right}.svg) and the 20px diamond
   divider. The wash's own paint is read off the component (see below). */
.video-revamp .hr-accent { color: var(--hr-yellow-400); }

/* ---------- Hero ---------- */
.video-revamp {
    /* The pill shadow from Figma's Button component in its cream-50 state —
       three drop layers plus a white inset highlight along the top edge. Two
       states share it, the active filter tab and a hovered inactive one, and
       they must not drift apart. Restated here rather than reached for across
       pages: it is --srp-pill-shadow on the Search page, whose filter row this
       page's tabs are the twin of. Figma's ramp opens with two layers at alpha 0
       (7px 63px 18px and 4px 40px 16px); they paint nothing, so they are
       documented, not emitted. */
    --vid-pill-shadow:
        2px 23px 14px rgba(0, 0, 0, .02),
        1px 10px 10px rgba(0, 0, 0, .03),
        0 3px 6px rgba(0, 0, 0, .03),
        inset 0 4px 6.1px rgba(255, 255, 255, .23);
    /* Hero height as a variable so the wash derives from it instead of the two
       drifting apart — same pattern as events-revamp.css / speakers-revamp.css
       / summit-listing-revamp.css. */
    /* One source of truth for the side gutter — the three sections' padding, the
       carousel's bleed and the slide widths all derive from it, so they cannot
       drift apart across breakpoints. Same approach as --sml-gutter. */
    --vid-gutter: 160px;
    /* The content column: exactly how wide .vid-featured-inner ends up. Slide
       widths are taken from THIS, not from the swiper's own box, because the
       swiper now bleeds past the gutter — sizing off the bled box would grow the
       cards past the design's 1000/600. */
    --vid-track-w: min(1600px, 100vw - 2 * var(--vid-gutter));
    --vid-hero-h: 256px;
    /* Hero + 80px, the same value the Events, Speakers and Annual Gatherings
       washes carry, and for the same reason: Figma puts this page's first
       section 120px below the hero (frame 40001286:70253 begins at the hero's
       256px edge, its heading row at y=120), so the h1 sits at 376px — exactly
       those pages' geometry — and +80 leaves the shared 40px of clearance under
       the wash. .vid-featured's padding-top is pinned to that 120px below. */
    --vid-wash-h: calc(var(--vid-hero-h) + 80px);
    position: relative;
    /* Figma's fill for the shared "Innerpage-hero/Without" instance (node
       40001286:70252), read off its own paint panel: a linear gradient at 89%
       opacity whose three stops are red/red-500 at 100%, #EE3B33 at 50% and
       #EE3B33 at 0%, over a solid #F9EAEA.
       The red is #ee3b33 — red/red-500's actual token value. This carried
       238,58,50 (#ee3a32), one off in every channel.
       89% x (1 / .5 / 0) gives the .89 / .445 / 0 alphas below, replacing the
       seven-stop About Us falloff this borrowed: a reasonable stand-in before the
       real paint was available, but not what the component uses.
       #F9EAEA is its own layer rather than the page's background-color, because
       that colour paints every section down to the footer — putting it there
       would tint the whole page pink.
       That layer needs its OWN falloff, though. As a flat fill cut to the wash's
       height it ended on a hard line: the red above it fades to zero, so the
       band's last pixels were pure #F9EAEA butting straight into cream-400, and
       those two differ by 15 in green — a visible edge. So its box is 1.5x the
       wash, held solid for the red's full span (to 66.67%) and then eased to
       transparent across the remaining half again, which lands it on the page
       ground with nothing to see. */
    background:
        linear-gradient(to bottom,
            rgba(238, 59, 51, .89) 0%,
            rgba(238, 59, 51, .445) 50%,
            rgba(238, 59, 51, 0) 100%) no-repeat top center,
        linear-gradient(to bottom,
            #f9eaea 0%,
            #f9eaea 66.67%,
            rgba(249, 234, 234, 0) 100%) no-repeat top center,
        var(--hr-cream-400);
    background-size: 100% var(--vid-wash-h), 100% calc(var(--vid-wash-h) * 1.5);
}
/* Figma's hero asset carries a fine grain/noise baked into it, which a plain
   linear-gradient() cannot reproduce — it renders flat and plastic instead of
   "brushed". Same tiled feTurbulence overlay, same 0.85 tile, same .7 opacity
   and same decay mask as the other washed heroes (events-revamp.css carries the
   original rationale for the feComponentTransfer re-centering: without it the
   raw noise is skewed bright, so overlay tints the whole wash lighter instead
   of just adding grain). The mask stops are the wash's own alphas normalised
   against its .89 start, so the texture fades out exactly with the red. */
.video-revamp::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: var(--vid-wash-h);
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxODAnIGhlaWdodD0nMTgwJz48ZmlsdGVyIGlkPSduJz48ZmVUdXJidWxlbmNlIHR5cGU9J2ZyYWN0YWxOb2lzZScgYmFzZUZyZXF1ZW5jeT0nMC44NScgbnVtT2N0YXZlcz0nMicgc3RpdGNoVGlsZXM9J3N0aXRjaCcvPjxmZUNvbG9yTWF0cml4IHR5cGU9J3NhdHVyYXRlJyB2YWx1ZXM9JzAnLz48ZmVDb21wb25lbnRUcmFuc2Zlcj48ZmVGdW5jUiB0eXBlPSdsaW5lYXInIHNsb3BlPScxJyBpbnRlcmNlcHQ9Jy0wLjIzMDInLz48ZmVGdW5jRyB0eXBlPSdsaW5lYXInIHNsb3BlPScxJyBpbnRlcmNlcHQ9Jy0wLjIzMDInLz48ZmVGdW5jQiB0eXBlPSdsaW5lYXInIHNsb3BlPScxJyBpbnRlcmNlcHQ9Jy0wLjIzMDInLz48L2ZlQ29tcG9uZW50VHJhbnNmZXI+PC9maWx0ZXI+PHJlY3Qgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScgZmlsdGVyPSd1cmwoI24pJy8+PC9zdmc+");
    background-repeat: repeat;
    opacity: .7;
    mix-blend-mode: overlay;
    /* Retracked to the new curve: these are the wash's own alphas normalised
       against its .89 start, so the grain still cannot outlive the red beneath
       it. */
    -webkit-mask-image: linear-gradient(to bottom,
        rgba(0,0,0,1) 0%, rgba(0,0,0,.5) 50%, rgba(0,0,0,0) 100%);
    mask-image: linear-gradient(to bottom,
        rgba(0,0,0,1) 0%, rgba(0,0,0,.5) 50%, rgba(0,0,0,0) 100%);
    pointer-events: none;
    z-index: 0;
}
/* The decor box is a child of the wrapper, not of .vid-hero, so the wedges sit
   under the hero's z-index 1 content without fighting that stacking context.
   Its own overflow:hidden is what crops them to the band. */
.vid-hero-decor {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: var(--vid-hero-h);
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
}
/* Pattern-01 / Pattern-02 from Figma's "Innerpage-hero/Without" instance:
   angular cream wedges at 10% fill in the two bottom corners — two DISTINCT
   vectors, not one shape mirrored, which is what this hero used to render (a
   37%-wide press-releases-revamp/hero-decor-shape.svg flipped onto both sides).
   Same pair, same geometry and the same shared innerpage-hero/ assets as
   .evt-hero-pattern (Events), .spk-hero-pattern (Speakers), .sml-hero-pattern
   (Annual Gatherings) and .srp-hero-pattern (Search).

   Both anchored to the hero's BOTTOM edge, as Figma has them — Pattern-01 runs
   top:95.03 + height:160.658 = 255.7 against a 256px hero, Pattern-02 is
   bottom:0 outright — so they stay in the same relationship to the breadcrumb
   at the shorter 200px/160px breakpoints instead of drifting off the baseline.

   These are NOT the innerpage-hero/hero-pattern-{left,right}.svg pair the
   agenda detail hero uses: that is the taller banner variant, with its own
   geometry. */
.vid-hero-pattern {
    position: absolute;
    bottom: 0;
    z-index: 0;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    pointer-events: none;
}
.vid-hero-pattern-start {
    inset-inline-start: 0;
    width: 305.329px;
    height: 160.658px;
    background-image: url("../images/innerpage-hero/hero-pattern-nobanner-left.svg");
}
/* Figma puts mix-blend-mode:overlay on this one's container, not inside the
   SVG — as a background-image the blend has to be applied here, or it would
   composite against the SVG's own transparency and do nothing. */
.vid-hero-pattern-end {
    inset-inline-end: 0;
    width: 305.29px;
    height: 204.731px;
    background-image: url("../images/innerpage-hero/hero-pattern-nobanner-right.svg");
    mix-blend-mode: overlay;
}
/* Flip the pair under RTL so each wedge keeps its own visual side and the
   composition mirrors with the text direction. */
[dir="rtl"] .vid-hero-pattern { transform: scaleX(-1); }
/* Hidden rather than scaled below 768px, as on the sibling heroes: at 160px the
   band is shorter than Pattern-02's own 204.731px, so they would be cropped to
   a sliver anyway. */
@media (max-width: 768px) {
    .vid-hero-pattern { display: none; }
}

.vid-hero {
    position: relative;
    z-index: 1;
    /* Vertical placement copied from .vidd-hero, which reads correctly. The top is
       derived rather than picked: a single-line breadcrumb occupies its 28px line
       plus the 32px bottom, so `hero - 60px` is exactly the clear space above it,
       and it tracks --vid-hero-h across the three breakpoints (196 / 140 / 100px)
       instead of needing hand-written values. Total height is unchanged at
       256/200/160.
       min-height rather than height, for the same reason the detail hero uses it:
       if a crumb ever wraps, the hero grows downward instead of the extra line
       pushing up into the overlay header. This page's three short crumbs do not
       wrap today, so nothing moves. */
    height: auto;
    min-height: var(--vid-hero-h);
    display: flex;
    align-items: flex-end;
    padding: calc(var(--vid-hero-h) - 60px) var(--vid-gutter) 32px;
}
.vid-hero-inner { position: relative; z-index: 1; max-width: 1600px; width: 100%; margin-inline: auto; }
.vid-breadcrumb-row { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
/* 22px between crumbs and a 28px line box, both from .vidd-breadcrumb. The gap was
   12px, and with no line-height the crumbs sat in Bootstrap's 1.5 (a 30px box),
   which is what made the row read tighter horizontally and 2px taller than the
   detail page's. */
/* Type and gap scale down with the viewport instead of holding 20px/22px, which
   is what the legal pages already do (.tnc-breadcrumb / .pp-breadcrumb) and what
   kept this trail to three lines on a 320px screen. Both clamps top out at this
   page's own desktop values, so nothing changes above ~440px. */
.vid-breadcrumb { display: flex; align-items: center; gap: clamp(8px, 2.2vw, 22px); row-gap: 4px; flex-wrap: wrap; font-size: clamp(13px, calc(5vw - 3px), 20px); line-height: 28px; color: var(--hr-cream-500); text-transform: uppercase; }
/* Full strength per Figma's Breadcrumb component - only font weight marks the
   current crumb, there is no resting opacity on the others. Full note in
   press-releases-revamp.css. (Restored: this had been set to 1 across all
   breadcrumbs, and reverted to .8 here and on the Talks listing.) */
.vid-breadcrumb a,
.vid-breadcrumb span:not(.vid-breadcrumb-sep) { opacity: 1; }
.vid-breadcrumb a { color: inherit; text-decoration: none; transition: opacity .2s ease; }
.vid-breadcrumb a:hover { opacity: 1; color: inherit; text-decoration: underline; }
.vid-breadcrumb-current { font-weight: 700; opacity: 1 !important; }
.vid-breadcrumb-sep { width: 1px; height: 16px; background: rgba(249, 247, 234, .5); }
.vid-hero-divider { display: none; }
/* The line bleeds past the 160px hero padding to the true viewport edge, the
   diamonds stay put a fixed distance in — same edge-to-edge treatment used by
   the sibling heroes. 160px padding + 1600px max content width matches Figma's
   1920px frame exactly, so the pull-back cancels out flush at any viewport up
   to that width, then centres like the other sections beyond it.

   300px, not the 400px this carried: the width the Speakers, Annual Gatherings
   and Search heroes all settled on for this same 256px breadcrumb-only variant,
   so the cluster starts at the same distance from the edge on all four. */
@media (min-width: 1200px) {
    .vid-hero-divider {
        display: flex;
        align-items: center;
        flex-shrink: 0;
        width: 300px;
        /* var, not a literal -160px: the gutter is now the single source for it,
           so the rule keeps reaching the viewport edge if that value ever moves. */
        margin-inline-end: calc(-1 * var(--vid-gutter) - max(0px, (100vw - 1920px) / 2));
    }
    /* BIL-822: 20px, matching .cta-diamond on Contact and the About hero the
       ticket points at as the reference — the same correction .sml-hero-diamond
       and .srp-hero-diamond already carry. At 14px this row read visibly smaller
       than the corner patterns behind it.

       Spacing by per-diamond margin rather than a flex gap, which is how the
       corrected pages do it. Both land the tips flush — a 20px square rotated
       45deg is 20*sqrt(2) wide visually but occupies only its 20px layout box,
       and 20*(sqrt(2)-1)/2 = 4.142px per side cancels exactly that overhang —
       but the margin form also puts 4.142px on the row's leading and trailing
       ends, which lines the cluster up against the hero pattern and lets the
       rule start on the last tip with no pull-back. */
    .vid-hero-divider .smt-hero-diamond {
        width: 20px;
        height: 20px;
        margin-inline: 4.142px;
        transform: rotate(45deg);
        background: var(--hr-cream-500);
        flex-shrink: 0;
    }
    /* margin-inline-start:0, not a negative pull-back: the last diamond's own
       4.142px trailing margin already places this exactly on its rotated tip. */
    .vid-hero-divider-line { flex: 1 1 auto; height: 1px; background: rgba(249, 247, 234, .5); margin-inline-start: 0; }
}
.vid-hero::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 1px;
    background: rgba(249, 247, 234, .35);
}

/* ---------- Featured carousel ---------- */
/* 120px top, from Figma: this section's frame begins at the hero's own bottom
   edge and its heading row sits at y=120 (was 64px). That is also what puts the
   h1 at 376px — the same place the Events / Speakers / Annual Gatherings
   headings sit, and the geometry --vid-wash-h is derived from. */
.vid-featured { position: relative; z-index: 1; padding: 120px var(--vid-gutter) 24px; }
.vid-featured-inner { max-width: 1600px; margin-inline: auto; }
/* Figma's heading row (frame 40002916:19045) is a true 50/50 split of the 1600px
   column — 792 + 16 + 792 — with both columns top-aligned, so the copy runs its
   full half rather than the 480px it was capped at, and the two bases are equal
   instead of leaving the paragraph narrower than the heading. 60px down to the
   carousel, not 40 (the row ends at 272, the carousel starts at 332). The 360px
   basis keeps the pair stacking below ~750px, where 16px is also the gap the
   sibling intro sections stack at. */
.vid-featured-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 60px; }
/* Headings/H1/Bold — Almarai 700, 64/72. Was 44px on a 1.15 ratio, i.e. 50.6px
   lines: a full size step small against the design's 792x144 two-line block. */
.vid-featured-head h1 { flex: 1 1 360px; font-size: 64px; line-height: 72px; font-weight: 700; color: var(--hr-brown-500); margin: 0; }
/* Body/Body Large/Regular — Almarai 400, 24/32. Was 18px on a 1.6 ratio. */
.vid-featured-head p { flex: 1 1 360px; font-size: 24px; line-height: 32px; font-weight: 400; color: var(--hr-brown-300); margin: 0; }

.vid-carousel { position: relative; }
/* The bleed sits on the TRACK, not on .vid-carousel: it has to take the peek card
   past the section's end padding to the viewport edge, but the controls row below
   is a sibling inside .vid-carousel and must stay on the content column —
   Figma's "pagination" frame is exactly 1600 wide, arrows at x=0 and the progress
   ending at x=1600. Bleeding the wrapper dragged the progress out to the viewport
   edge with it.
   Same expression the hero divider uses: cancel the gutter, then keep cancelling
   the centring margin once the viewport clears 1920 (gutter + 1600 + gutter).
   margin-inline-end, so it bleeds to the correct side under RTL too.
   overflow:hidden is what clips the track at that bled edge. */
/* .vid-carousel .vid-swiper (not the bare .vid-swiper class): swiper-bundle
   .min.css's own base rule (loaded via CDN in head.blade.php) sets
   `.swiper { margin-left: auto; margin-right: auto; }` — the SAME
   specificity as a bare `.vid-swiper` class selector, which makes the
   winner purely a function of stylesheet load order rather than intent.
   Scoping through the ancestor bumps this to two classes' worth of
   specificity, safely beating the library's rule regardless of load order. */
.vid-carousel .vid-swiper {
    /* NOT overflow:hidden — confirmed live that it was creating a stacking
       context which visually sent the previous slide (mid-transition)
       BEHIND a sibling element instead of over it, and was also clipping
       the second (fully-visible, unscaled) peek card that should render
       without any clip at all. Removing it fixed both.
       This also means margin/padding on this element no longer serve as a
       clip boundary at all — there's nothing local left to clip, so
       whatever bounds visibility past the true viewport edge is the page's
       own horizontal overflow behavior. An earlier version of this rule
       carried a --vid-swiper-left-bleed-driven margin-inline-start +
       padding-inline-start pair (with index.blade.php's syncLeadingRoom
       measuring it live) meant to widen the clip boundary for a previous
       slide to show through — confirmed live that this had become dead
       weight once overflow went visible (margin can't reveal anything
       when nothing clips locally any more), so it's removed. The
       bidirectional-peek feature itself (a previous slide tucking in
       against the active one) is also paused for now — see the removed
       .swiper-slide-prev rule further down — so this element currently has
       nothing depending on its own left edge at all. */
    overflow: hidden;
    /* -30px, not -24. The design's own "24px spaceBetween" reasoning (peek
       card's visual right edge lands at column+24) is right, but the peek's
       true edge needs a few px more to clear the swiper's own edge with
       zero pixels cut — ~6px of rounding/scrollbar slack, confirmed live.
       This held identically at both 1920px and 1440px viewports, i.e. it
       is NOT a function of --vid-gutter or track width (the algebra
       cancels those terms out exactly), so it does not need a calc() or a
       breakpoint ladder — a flat constant is correct here. */
    margin-inline-end: -30px;
}
.vid-swiper .swiper-wrapper { align-items: center; }
/* Two-width "peek" carousel, straight off Figma's track (frame 40002916:19051):
   the active slide is 1000px and every other 600px, 24px apart, against a
   1600px content column. Taken as .625 / .375 of --vid-track-w rather than as
   those pixels, so the pair holds its ratio at every width — 1000/600 at a
   1920px viewport, 700/420 at 1440.
   Sized off the COLUMN, not off the swiper's own box: .vid-carousel bleeds past
   the end gutter (see above), so a percentage of the swiper would grow the cards
   past the design's 1000/600. With the bleed, the peek card now clears the
   gutter in full and about 112px of the third shows behind it, instead of the
   peek being cut at the content edge.
   This replaced a uniform min(760px, 68vw) box scaled to .82, which put a full
   card, a shrunken one and a sliver in view — a transform changes what you see
   but not the box Swiper lays out, so the neighbours never moved. Real widths
   are what move them, hence the update() in index.blade.php.
   The peek cards sit at 50%, which is literally the export's outermost
   `<g opacity="0.5">`. Paired with the 60% black scrim on .vid-feature-card::after
   it gives the flat grey the design has: darken hard, then halve over the cream
   page. Neither half works alone — the scrim on its own reads as a dark card, the
   opacity on its own as a washed one. */
.vid-swiper .swiper-slide {
    /* UNIFORM boxes, all at the active card's width, with the inactive ones
       scaled to .6 (= 600/1000, the design's ratio) from the leading edge. The
       visible result is the design's: card 1 at .625 of the column, card 2 at
       .375, 24px apart.
       Why not real widths of .625/.375, which is literally what Figma's track
       has? Because Swiper derives the wrapper translate from the widths it
       measured BEFORE the active class moves. Advancing therefore translated by
       the old active's full width and the slide landed short — visibly cut. The
       widths depend on which slide is active and the translate depends on the
       widths, and Swiper has no way to resolve that; it also cannot model the
       design's non-uniform pitch (1024 after the active, 624 between peeks).
       Uniform boxes remove the circularity entirely: the grid never changes, so
       every position is correct with no re-measure and no update() call. */
    width: calc(var(--vid-track-w) * .625);
    height: auto;
    transform: scale(.6);
    transform-origin: left center;
    opacity: .5;
    transition: transform .4s ease, opacity .4s ease;
    cursor: grab;
}
.vid-swiper .swiper-slide-active { transform: scale(1); opacity: 1; cursor: default; }
/* The shrink has to hug the reading-start edge, which flips with direction — the
   blade puts dir="rtl" on the swiper itself on the Arabic pages. */
.vid-swiper[dir="rtl"] .swiper-slide,
[dir="rtl"] .vid-swiper .swiper-slide { transform-origin: right center; }
/* Bidirectional peek (a previous slide tucking in via transform-origin:right
   instead of shrinking away with the default left-anchored origin) was
   built and verified working here, then deliberately paused/removed for
   now to revisit later — see git history for the .swiper-slide-prev
   transform-origin rule if picking this back up. */

.vid-feature-card {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    height: 100%;
    min-height: 320px;
    aspect-ratio: 16 / 9;
    border-radius: 32px;
    padding: 32px;
    color: var(--hr-cream-500);
    text-decoration: none;
    overflow: hidden;
    background-color: var(--hr-brown-700);
    /* The design's "overlay" layer (node 40002916:19056) — and unlike the grid
       card's, this one carries NO layer blur, so it stays a background gradient
       rather than becoming a blurred pseudo-element.
       Figma draws it as a 1032.414x357.363 rect at (-16.203, 245) on the
       1000x562.5 card, filled transparent-to-black top-down. Mapped onto the
       card's own box: it starts at 245/562.5 = 43.556% and would reach full
       black at 602.363, i.e. 7.09% BELOW the card, so the visible bottom edge
       lands at (562.5-245)/357.363 = 88.85% of the ramp. Percentages rather than
       the design's pixels because this card is aspect-ratio driven and scales.
       Replaces a three-stop ramp that ran the full height and put 35% black
       across the TOP of the card, which the design has nothing of — the badge
       is legible on its own rgba(23,21,9,.8) pill. */
    background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 43.556%, rgba(0, 0, 0, .889) 100%), var(--vid-feature-bg);
    background-size: cover;
    background-position: center;
}
.vid-feature-card:hover { color: var(--hr-cream-500); }
/* The peek card's greying, taken from the inactive slide's own export (2.svg,
   node 40002916:19078). That file settles what the effect actually is, and it is
   plainer than the paint panel suggested: a rect of FLAT BLACK at 60% over the
   artwork, with the whole card then drawn at 50% (see the slide rule below).
   No blend mode, no grayscale, no brightness — the export carries none of them.
   Black at 60% then halved over the cream page is what produces the flat, low
   contrast grey; darkening and desaturating it by other means only approximated
   this and read as shadow instead.
   Oversized by 16.67% a side, which is the export's own 800x450 rect over its
   600x337.5 card expressed proportionally, so it holds however the card scales.
   That overhang is also what gives backdrop-filter material to sample at the
   edges instead of averaging in the transparency past them; the card's own
   overflow:hidden clips it back to the 32px radius.
   The blur is the one thing the SVG cannot carry — it leaves behind a clipPath
   named bgblur_1_*, the remains of the component's backdrop blur — so the 4px
   from the paint panel is real, kept here at 12px per request.
   Rendered on every card and switched by opacity, so it cross-fades with the
   scale rather than snapping. Last in paint order, so it greys the badge, the
   copy and the play button too, as the export's layer order does. */
.vid-feature-card::after {
    content: "";
    position: absolute;
    inset: -16.67%;
    background: rgba(0, 0, 0, .6);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    opacity: 0;
    transition: opacity .4s ease;
    pointer-events: none;
}
.vid-swiper .swiper-slide:not(.swiper-slide-active) .vid-feature-card::after { opacity: 1; }
/* Figma node I40001286:70253;40000946:34606;40000923:28951. Box was already
   right (rgba(23,21,9,.8) fill, 8px gap, 12px block padding) — the design's own
   14.948px inline padding and 11.626px radius are pinned here rather than left
   at the rounded 15px/12px, and the type is the design's "Labels/Label XSmall/
   Bold" token in full: Almarai 700 16/24, UPPERCASE. The label was rendering as
   "Featured" in title case; Figma sets it uppercase, which is also what makes
   the 48px pill height come out exactly (12 + 24 + 12). nowrap because the
   design's text node is whitespace-nowrap and the pill sits over a photo where
   a second line would fold under the play button. */
.vid-feature-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    align-self: flex-start;
    padding: 12px 14.948px;
    border-radius: 11.626px;
    background: rgba(23, 21, 9, .8);
    color: var(--hr-yellow-500);
    font-size: 16px;
    font-weight: 700;
    line-height: 24px;
    text-transform: uppercase;
    white-space: nowrap;
}
/* The glyph is the brand diamond, NOT a dot: Figma draws it as two nested
   shapes inside a 14.644x16 slot (Frame 2147239163) — a SOLID yellow-500
   diamond (node ...:28953, bbox 7.961x8.397) inside a much larger one carrying
   only a 0.217px yellow-500 stroke (node ...:28954, bbox 15.441x16.286).
   This rule used to render one 8px box with a 1px border and no fill, i.e. the
   outline at the inner shape's size and no filled centre at all — the opposite
   of the design on both counts.

   Both are rotated squares here, as every other diamond in this codebase is
   (.smt-hero-diamond and friends). A rotated square's bbox is always square,
   while Figma's two boxes are each ~0.948 wide-to-tall, so the side lengths
   come from the mean of each bbox over sqrt(2): 15.8635/1.41421 = 11.217 and
   8.179/1.41421 = 5.784. The ring's ~15.86px visual span overhangs the 14.644px
   slot by ~0.6px a side, exactly as Figma's own box overhangs its parent frame.
   The 0.217px stroke is left at its literal sub-pixel width — browsers
   antialias it down to the same faint hairline Figma renders. */
.vid-feature-badge-dot {
    position: relative;
    width: 14.644px;
    height: 16px;
    flex: 0 0 auto;
}
.vid-feature-badge-dot::before,
.vid-feature-badge-dot::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(45deg);
}
.vid-feature-badge-dot::before {
    width: 11.217px;
    height: 11.217px;
    border: .217px solid var(--hr-yellow-500);
}
.vid-feature-badge-dot::after {
    width: 5.784px;
    height: 5.784px;
    background: var(--hr-yellow-500);
}
.vid-feature-bottom { display: flex; flex-direction: column; gap: 24px; }
.vid-feature-meta { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
/* Figma node I40001286:70253;40000946:34606;40000923:28945, type
   "Utility/Tag/Bold" (Almarai 700 / 14). Box, radius and type were already
   right; the pill was 37px tall instead of the design's 32 because it had no
   line-height of its own and so inherited Bootstrap's --bs-body-line-height:
   1.5, i.e. a 21px line box. The design's instance measures 120x32 with its
   text box at y=8, height 16 — 8 + 16 + 8 — so the line box is pinned to 16px
   here and the 32px comes out exact.

   Fill and text colour are deliberately left as they are: the design's own
   instance of this tag is purple-400, not this green, because the tone tracks
   the video's type. */
.vid-feature-tag {
    display: inline-flex;
    align-items: center;
    padding: 8px 16px;
    border-radius: 8px;
    background: var(--hr-green-400);
    color: #e6f0ef;
    font-size: 14px;
    line-height: 16px;
    font-weight: 700;
    text-transform: uppercase;
    white-space: nowrap;
}
/* Figma node I40001286:70253;40000946:34606;40000923:28946, type
   "Labels/Label Small/Bold" (Almarai 700 / 18, white). Same pill as the Featured
   badge above and the same fill — the design's own 14.948px inline padding and
   11.626px radius are pinned here rather than left at the rounded 15px/12px, and
   the 28px line box (which the rule had no value for, so it inherited
   Bootstrap's 1.5 = 27px) is what makes the chip's 37.97px height exact:
   4.983 + 28 + 4.983. */
.vid-feature-duration {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4.983px 14.948px;
    border-radius: 11.626px;
    background: rgba(23, 21, 9, .8);
    color: #fff;
    font-size: 18px;
    line-height: 28px;
    font-weight: 300;
    white-space: nowrap;
}
/* Headings/H6/Bold (24/32) for the title and Body/Body XSmall/Regular (16/24)
   at 70% for the line under it — both already matched the design's type, and
   the 12px between them is Figma's own. What did NOT match: the clamp. Figma
   fixes the card's content block at 920x92 — a 32px title box, i.e. ONE line,
   then 12px, then a 48px description box, i.e. two 24px lines — so the title
   truncates at one line here rather than two. That is also what keeps the
   block's height stable however long a title runs, which matters on a card
   whose text sits over a photo with the play button centred above it. */
.vid-feature-content h3 { font-size: 24px; line-height: 32px; font-weight: 700; margin: 0 0 12px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; }
.vid-feature-content p { font-size: 16px; line-height: 24px; font-weight: 400; margin: 0; opacity: .7; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
/* Figma's shared "Button" component, icon-only variant (instance node
   40002916:19073, page path I40001286:70253;40000946:34606;40000923:30011).
   72x72, not 64: the instance is a 72px frame around a 24px icon slot placed at
   (24,24), i.e. 24px of padding a side. */
.vid-feature-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    border-radius: 61px;
    background: var(--hr-yellow-500);
    /* Transparent, so layout-revamp.css's shared masked ring (the ::after on
       every button in this set) lands exactly on this 1.5px band — that rule is
       inset:-1.5px against the padding box, which is where a 1.5px border sits.
       The gradient stroke Figma specs is that shared primitive, parameterised:
       its end stop is already the design's #FFFFFF/75%, and the two vars below
       carry this node's own leading and middle stops (white at 30%, #65686F at
       39%) in place of the .1/.3 defaults. A hand-rolled copy of the same
       gradient used to live on ::before here; ::before is the shared hover glow's
       and cannot be both. */
    border: 1.5px solid transparent;
    --hr-ring-start: rgba(255, 255, 255, .3);
    --hr-ring-mid: rgba(101, 104, 111, .39);
    /* Own stacking context, so the glow's plus-lighter blends against this
       button's amber rather than whatever sits behind the card. */
    isolation: isolate;
    /* The node's full effect stack, replacing the lone 0 3px 6px drop this
       carried — on its own that read as a flat disc with no glass rim, which is
       the same thing .hr-btn-primary and .home-revamp .hr-btn-ghost-dark were
       both corrected for on this component. Figma opens the ramp with two more
       drops at alpha 0 (7px 63px 18px and 4px 40px 16px); they paint nothing, so
       they are documented, not emitted — the same call about-revamp.css's copy
       of this stack and --srp-pill-shadow both make, and about-revamp confirmed
       it against the node's SVG export, which carries no such filters. */
    box-shadow:
        0 4px 6.1px 0 rgba(255, 255, 255, .23) inset,
        2px 23px 14px 0 rgba(0, 0, 0, .02),
        1px 10px 10px 0 rgba(0, 0, 0, .03),
        0 3px 6px 0 rgba(0, 0, 0, .03);
    /* NOT overflow:hidden, which Figma's overflow-clip would suggest: the shared
       ring sits 1.5px OUTSIDE the padding box, so clipping here would eat it
       (layout-revamp.css:1545 records the same trap). Nothing needs clipping
       anyway — the node's "Ellipse 262" is the hover glow, and the shared
       recipe bakes it as a radial-gradient inside the button rather than as a
       blurred circle that has to be cropped. */
}
/* solar:play-bold, whose vector box is 19x20 inside that 24px slot (Figma inset
   8.32% 4.17% 8.35% 16.66%). bilaraby-talks-revamp/icon-play-small.svg is that
   exact export — same 18.9994x20.0006 artboard, same path, same white fill —
   already in the repo and already used on the video detail page, so it replaces
   video-play-icon.svg here: a different play glyph, cropped tight to 21x24,
   which rendered the triangle ~10% wider and 20% taller than the design's.
   The 1.5px nudge is the glyph's own optical centring — Figma pads it 4px left
   and 1px right inside the slot, so its centre sits 1.5px right of the button's.
   Physical rather than logical: the triangle isn't mirrored under RTL, so its
   offset shouldn't be either. */
.vid-feature-play img { width: 19px; height: 20px; transform: translateX(1.5px); }
.swiper-slide:not(.swiper-slide-active) .vid-feature-play { opacity: 0; }

/* 60px, from the design: its pagination frame sits at y=622.5 against a track
   that ends at 562.5. */
.vid-carousel-controls { display: flex; align-items: center; justify-content: space-between; gap: 24px; margin-top: 60px; }
.vid-carousel-arrows { display: flex; align-items: center; gap: 12px; }
/* Same glass-circle recipe as .hr-icon-btn (home-revamp.css) / the
   testimonials prev-next pair (.hr-testimonials-prev/-next reuse that same
   class) — the fill, border and masked rim already matched (shared in
   layout-revamp.css's .vid-carousel-arrow rows), but the box-shadow here was
   a single flat 0 3px 6px layer instead of .hr-icon-btn's full stack: the
   inset top highlight plus the three-layer ambient drop is what makes it
   read as a glass button instead of a plain tinted circle. */
.vid-carousel-arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 61px;
    background: rgba(255, 255, 255, .2);
    border: 1.5px solid transparent;
    box-shadow:
        inset 0 4px 6.1px rgba(255, 255, 255, .23),
        2px 23px 14px rgba(0, 0, 0, .02),
        1px 10px 10px rgba(0, 0, 0, .03),
        0 3px 6px rgba(0, 0, 0, .03);
    cursor: pointer;
    transition: background-color .2s ease, transform .2s ease;
}
.vid-carousel-arrow:hover { background: rgba(255, 255, 255, .4); }
.vid-carousel-arrow.swiper-button-disabled { opacity: .4; cursor: default; pointer-events: none; }
[dir="rtl"] .vid-carousel-arrow img { transform: scaleX(-1); }
.vid-carousel-progress { display: flex; align-items: center; gap: 24px; }
.vid-carousel-pagination { display: flex; align-items: center; gap: 4px; }
.vid-carousel-pagination .swiper-pagination-bullet {
    width: 8px;
    height: 8px;
    border-radius: 100px;
    background: var(--hr-yellow-500);
    opacity: .6;
    margin: 0;
    transition: width .25s ease, opacity .25s ease;
}
.vid-carousel-pagination .swiper-pagination-bullet-active { width: 36px; opacity: 1; }
.vid-carousel-fraction { font-size: 16px; color: var(--hr-brown-500); white-space: nowrap; }

/* ---------- Listing ---------- */
.vid-listing { position: relative; z-index: 1; padding: 60px var(--vid-gutter) 100px; }
.vid-listing-inner { position: relative; z-index: 1; max-width: 1600px; margin-inline: auto; }

/* Replaces the old bilaraby-talks-revamp/listing-decor-shape.png, which sat at
   right:-256px / bottom:-148px and so showed only a sliver of itself. Figma's
   own vector is 254.66x111.564 at x=0 — flush to the start edge and to the
   section's bottom, i.e. closing the page directly above the footer. Its fill is
   #338A81, which is --hr-green-400, so nothing new enters the palette.
   The section already carries position:relative, and app.css's global
   `section { overflow: hidden }` keeps the shape inside it. */
.vid-listing-pattern {
    position: absolute;
    inset-inline-start: 0;
    bottom: 0;
    width: 254.66px;
    height: 111.564px;
    z-index: 0;
    pointer-events: none;
}
/* Mirrored under RTL so the motif stays on the reading-start side. */
[dir="rtl"] .vid-listing-pattern { transform: scaleX(-1); }
/* Hidden on phones, as the shape it replaces was: 254px of motif at the section's
   start edge crowds a single-column grid, and the pagination sits low enough to
   collide with it. 768px rather than the old 991.98px, so it drops out at the
   same breakpoint as the hero's own wedges. */
@media (max-width: 768px) { .vid-listing-pattern { display: none; } }
/* Node 40005017:73675 — 84.0432x49.1494, its own export at this size, not the
   desktop motif scaled down. Hidden by default, shown only at the mobile
   breakpoint below (same pattern as the video detail page's
   .vidd-related-pattern-mobile, which reuses this identical asset since both
   pages share the same desktop listing-pattern.svg). */
.vid-listing-pattern-mobile {
    display: none;
    position: absolute;
    inset-inline-start: 0;
    bottom: 0;
    width: 84.0432px;
    height: 49.1494px;
    z-index: 0;
    pointer-events: none;
}
[dir="rtl"] .vid-listing-pattern-mobile { transform: scaleX(-1); }
@media (max-width: 768px) { .vid-listing-pattern-mobile { display: block; } }
.vid-listing-head { position: relative; z-index: 1; display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 40px; }
.vid-listing-title { font-size: 40px; font-weight: 700; color: var(--hr-brown-500); margin: 0; }
.vid-listing-count { font-size: 24px; color: var(--hr-brown-300); margin: 0; }

.vid-filters { position: relative; z-index: 1; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 80px; }
.vid-filters-tabs { display: flex; gap: 16px; flex-wrap: wrap; }
/* Same pill as the Search page's filter row (.srp-tab). The base already
   agreed — cream tint, grey hairline, 61px radius, 16px brown-500 — so what
   comes across is the geometry correction, the full shadow, and the hover. */
.vid-tab {
    display: inline-flex;
    align-items: center;
    /* 11px block, i.e. the design's 12px less the 1px border: Figma strokes the
       pill INSIDE its 48px box (label at y=12, 24px tall), so 11 + 24 + 11 + 2
       = 48. Same correction .srp-tab carries; at 12px these stood 50px tall. */
    padding: 11px 20px;
    border-radius: 61px;
    font-size: 16px;
    font-weight: 400;
    line-height: 24px;
    letter-spacing: 0;
    color: var(--hr-brown-500);
    background: rgba(236, 230, 211, .4);
    border: 1px solid rgba(177, 175, 165, .5);
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .2s ease, border-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.vid-tab:hover { text-decoration: none; color: var(--hr-brown-500); }
/* Hovering an inactive tab previews the active pill exactly — same cream-50
   fill, white border and shadow — plus the 2px lift, which is how the Search
   row answers the cursor. Scoped off .is-active: that one is already at the
   destination and isn't a target, so it shouldn't move. */
.vid-tab:not(.is-active):hover {
    background: var(--hr-cream-50);
    border-color: #fff;
    box-shadow: var(--vid-pill-shadow);
    transform: translateY(-2px);
}
/* Weight stays 400: the design separates the active pill by fill, border and
   shadow alone. The 700 this used to add also nudged the whole row on every tab
   change, a bold label being wider than the regular one — the same reason
   .srp-tab.is-active dropped it. */
.vid-tab.is-active {
    background: var(--hr-cream-50);
    border-color: #fff;
    box-shadow: var(--vid-pill-shadow);
}
.vid-sort-form { display: flex; }
/* The sort control is the shared <x-front.select> (select2-revamp.css), which
   carries the whole pill - fill, hairline, chevron, sizing, open panel - so
   this row has nothing left to declare. */

/* ---------- Card grid ---------- */
.vid-grid {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
    margin-bottom: 80px;
}
/* Split in two, .vid-card (shadow shell) + .vid-card-surface (blur/clip),
   because the first attempt — keeping backdrop-filter on this element and
   only moving the overflow:hidden clipping duty off it — still failed on
   real iOS Safari devices. The wider-known form of this WebKit bug isn't
   just "overflow:hidden clips the shadow": box-shadow can fail to render AT
   ALL on an element that also carries backdrop-filter on iOS, regardless of
   overflow. The only reliable fix is putting them on two different
   elements entirely. */
.vid-card {
    position: relative;
    display: block;
    border: 1px solid #fff;
    border-radius: 40px;
    background: var(--hr-cream-600, #e3e1d4);
    box-shadow: 0 3px 6px rgba(0,0,0,.03), 1px 10px 10px rgba(0,0,0,.03), 2px 23px 14px rgba(0,0,0,.02);
    text-decoration: none;
    color: inherit;
    /* iOS Safari: without its own compositing layer, box-shadow on a rounded
       element can get rasterized on a fast path that ignores border-radius
       entirely, painting a square-cornered shadow instead of following the
       curve. translateZ(0) forces that layer promotion so the shadow gets
       clipped to the same rounded rect the border is. A separate WebKit bug
       from the backdrop-filter/box-shadow split above — this element has
       neither overflow:hidden nor backdrop-filter of its own any more, so
       this is the remaining fix for the corner shape itself. */
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
}
.vid-card:hover { color: inherit; }
/* Everything that used to live directly on .vid-card: the flex layout, the
   8px padding, the blur, and the clip. A plain block child of a block
   .vid-card fills its content box exactly at 100% width with no sizing of
   its own needed, so it sits flush behind the 1px border with the same
   effective shape .vid-card-glow's bleed and .vid-card-media's corners were
   already positioned against — nothing else about the card's geometry
   changes, only which element owns which effect. */
.vid-card-surface {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 8px;
    border-radius: 40px;
    overflow: hidden;
    -webkit-backdrop-filter: blur(53px);
    backdrop-filter: blur(53px);
    /* Forces its own compositing layer, which is what makes iOS Safari
       actually respect this overflow:hidden + border-radius clip against
       .vid-card-glow below — without it, iOS fails to clip a filter:blur()'d
       child to an ancestor's rounded overflow:hidden at all, letting the
       blur render as an unclipped rectangle past the rounded corners (this
       is what actually read as a "square shadow" — .vid-card-glow's own
       escaped blur, not the card's real box-shadow). */
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
}
/* A blurred, oversized echo of the card's own thumbnail sitting behind the
   media block — bleeds into the 8px cream gap around it (clipped by
   .vid-card-surface, not this element) instead of leaving that gap a flat,
   plain colour. */
.vid-card-glow {
    position: absolute;
    inset: -16px -16px auto -16px;
    height: 65%;
    background-image: var(--vid-card-bg);
    background-size: cover;
    background-position: center;
    /* 50px, the design's own layer blur on this echo (node
       I40001286:70271;40001144:62997, an oversized copy of the thumbnail
       bleeding ~15px past the media block and clipped to its 32px radius). */
    filter: blur(50px);
    pointer-events: none;
    /* Belt-and-braces for the same iOS clipping bug the surface's
       translateZ(0) targets: a border-radius directly on the filtered
       element itself (56px ≈ the card's 40px + this element's own 16px
       outward inset, so it still nests visually under the blur) means even
       if .vid-card-surface's ancestor clip still fails to catch it on some
       iOS version, this element's OWN corners are rounded rather than
       square. Harmless on browsers where the ancestor clip already works
       correctly — invisible under 50px of blur either way. */
    border-radius: 56px;
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
}
.vid-card-media {
    position: relative;
    z-index: 1;
    /* 16/9 is a HARD constraint here, not a style choice, because of what the
       thumbnail is. Video::getThumbnailUrlAttribute() serves YouTube's
       hqdefault.jpg, which is 480x360 — a 4:3 frame with the real 16:9 image
       letterboxed inside it and a 45px black bar baked into the top and bottom.
       At this card's width `cover` scales that to 376px tall and crops 47px a
       side, which is exactly the bar: it disappears with nothing to spare. Make
       the box any taller and `cover` crops less, so the bar starts to show — 16/9
       leaves 0px of it, 16/10.28 leaves 20px.
       If the media ever does need to be taller, the fix is a 16:9 thumbnail
       (mqdefault is also letterboxed; only maxresdefault is a true 16:9, and it
       404s for many videos) or an <img> with object-fit and a negative inset to
       crop by hand. */
    aspect-ratio: 16 / 9;
    /* Bottom corners squared off, not rounded: .vid-card-body overlaps this
       block's bottom edge, well short of a 32px radius, so a rounded bottom
       corner curved out from under the (straight-edged) panel above it instead of
       being fully covered by it. */
    border-radius: 32px 32px 0 0;
    overflow: hidden;
    background-color: var(--hr-brown-700);
    /* Thumbnail only. The darkening scrim used to be a second background layer
       here, but the design draws it as its own blurred element — see ::before. */
    background-image: var(--vid-card-bg);
    background-size: cover;
    background-position: center;
}
/* The design's "Overlay" layer (node I40001286:70271;40001144:62998): the
   darkening scrim under the stats row, drawn as its OWN element with a 16px
   radius and a 50px layer blur, not as a hard gradient painted onto the
   thumbnail — which is what this was, and why the scrim had a visible straight
   edge where the ramp ended.

   Blurring only works on a separate layer, hence the pseudo-element: a
   `filter` on .vid-card-media itself would smear the thumbnail, the play button
   and the stats along with it.

   Oversized to match the design's own geometry — its 526x288 overlay against a
   496x278 media box, i.e. ~15px past each side and ~10px above the top. That
   matters here: a 50px blur samples ~150px, so any edge sitting inside the
   visible box would feather into it. The bottom is left flush, as the design
   has it, which does mean the blur averages in the transparency past that edge
   and lands softer than a flat 60% — that soft falloff is the effect. Clipped
   by .vid-card-media's own overflow, exactly as Figma clips it to the
   container. */
/* Two layers over the thumbnail, both built from things that cannot silently
   no-op: a background-image, filter, a mask and a gradient.

   This replaces two earlier attempts that each depended on a mechanism that can
   render nothing without erroring:
     - backdrop-filter on ::before, nested inside .vid-card's OWN
       backdrop-filter:blur(53px). Nested backdrop-filters resolve their backdrop
       against the ancestor group rather than the page, and engines disagree about
       what that means; it is not worth betting the effect on.
     - the Overlay.svg export as a background-image. A Figma filter export
       (feGaussianBlur inside a <g filter>, forward-referenced <defs>) is fine in
       a document but is a poor thing to rely on inside a CSS background, where
       there is no way to tell a failed render from a transparent one.

   ::before is Figma's "Image" layer done literally: a SECOND copy of the
   thumbnail, blurred, over the sharp one, masked so it fades out upward. That is
   exactly what the design does — the export's 50px belongs to this layer, not to
   a frost over the live photo. 34px rather than 50: at 50 a copy laid over the
   original erases the picture entirely, which is the harshness reported earlier;
   at 24 it was too thin to read as an effect.
   inset:-30px gives filter() material to sample at the edges, since it averages
   in the transparency past an element's own box and would otherwise thin out
   exactly where the effect is wanted. .vid-card-media's overflow:hidden clips it.

   ::after is the export's gradient, as a plain gradient: black at 0.6 up to clear
   over the bottom 51.22%, its own fill-opacity and ramp. No blur on it, because
   blurring a linear ramp does not change a linear ramp. */
.vid-card-media::before {
    content: "";
    position: absolute;
    inset: -30px;
    z-index: 0;
    background-image: var(--vid-card-bg);
    background-size: cover;
    background-position: center;
    filter: blur(12px);
    /* Held at full strength across the band, then closed off over a short 7%
       (~24px) transition rather than dissolved across the whole card — the band
       is meant to read as a defined region, not a wash.
       51% is the export's own 51.22% of the MEDIA box expressed against this
       element, which is 60px taller because of the inset:-30px runway. The two
       work out to the same figure at any card size: 51.0% at a 279px media,
       50.9% at 200px, so one value covers the whole grid. Deliberately the same
       extent as ::after's ramp below — in the design both are the one rect. */
    -webkit-mask-image: linear-gradient(to top, #000 0%, #000 44%, transparent 51%);
    mask-image: linear-gradient(to top, #000 0%, #000 44%, transparent 51%);
    pointer-events: none;
}
.vid-card-media::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(to top, rgba(0, 0, 0, .60) 0%, rgba(0, 0, 0, 0) 51.22%);
    pointer-events: none;
}
/* Above both layers so neither the blurred copy nor the scrim touches them.
   Stated explicitly rather than left to DOM order, so adding another layer here
   cannot quietly put them behind it. */
.vid-card-play,
.vid-card-media-meta {
    z-index: 2;
}
/* Same button as .vid-feature-play on the featured card — see the notes there
   for where each value comes from: the amber fill, the masked gradient ring on
   the 1.5px transparent border, the full effect stack (this had no shadow at
   all) and the hover glow. 72px, like the featured one: this card's own instance
   (node I40001286:70271;40001144:63016) is p-[24px] around the 24px icon slot,
   not the component's default p-[16px]. */
.vid-card-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    border-radius: 61px;
    background: var(--hr-yellow-500);
    border: 1.5px solid transparent;
    --hr-ring-start: rgba(255, 255, 255, .3);
    --hr-ring-mid: rgba(101, 104, 111, .39);
    box-shadow:
        0 4px 6.1px 0 rgba(255, 255, 255, .23) inset,
        2px 23px 14px 0 rgba(0, 0, 0, .02),
        1px 10px 10px 0 rgba(0, 0, 0, .03),
        0 3px 6px 0 rgba(0, 0, 0, .03);
    isolation: isolate;
}
/* solar:play-bold at its native 19x20, replacing video-play-icon.svg squeezed to
   18x21 — the same glyph correction the featured card carries. */
.vid-card-play img { width: 19px; height: 20px; transform: translateX(1.5px); }
.vid-card-media-meta {
    position: absolute;
    left: 16px;
    right: 16px;
    bottom: 43px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
/* Figma node I40001286:70271;40001144:63000. The 11px row gap and the 8px
   icon-to-count gap already matched; the type is Almarai Light 16/24 in
   cream-500, so only the line box was missing. */
.vid-card-stats { display: flex; align-items: center; gap: 11px; }
.vid-card-stat { display: inline-flex; align-items: center; gap: 8px; font-size: 16px; line-height: 24px; color: var(--hr-cream-500); font-weight: 300; }
/* Vector 2538: a 1px rule 13.734px tall, stroked white at 30% — not cream-500
   at 40%, which read slightly warm and tall against the two icons. */
.vid-card-stat-sep { width: 1px; height: 13.734px; background: rgba(255, 255, 255, .3); }
/* Matched to .vid-feature-duration on the featured card: the design's own
   14.948px/4.983px padding and 11.626px radius rather than the rounded
   15px/5px/12px, and the 28px line box that makes the chip 37.97px tall
   (it had none, so it inherited Bootstrap's 1.5 = 27px).
   Weight 300, down from the design token's 700. Almarai Light is a real face here
   (app.css declares 300/400/700/800), so this is not a synthesised thin — and it
   is the same weight as the like/views stats sitting beside it in this row, which
   the bold chip was fighting. 400 is the step in between if 300 reads too light. */
.vid-card-duration {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4.983px 14.948px;
    border-radius: 11.626px;
    background: rgba(23, 21, 9, .8);
    color: #fff;
    font-size: 18px;
    line-height: 28px;
    font-weight: 300;
    white-space: nowrap;
}
/* The same body panel as .vidd-card-body on the details page — the grid places
   the copy and the like button side by side (1fr / 56px) and the tag row spans
   both columns, with the same 8px row / 16px column gaps, the same -26px pull
   over the media and the same 24px bottom padding. The extra 40px this body
   used to add has been dropped with the --vid-card-extra-h knob: the two pages'
   cards now end at the same height. */
.vid-card-body {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: start;
    gap: 8px 16px;
    padding: 32px 24px 24px;
    margin-top: -26px;
    border-radius: 28px;
    background: linear-gradient(180deg, #fff 18%, rgba(255, 255, 255, 0) 100%);
}
.vid-card-copy { grid-column: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.vid-card-text { display: flex; flex-direction: column; gap: 8px; }
.vid-card-text h3 {
    font-size: 24px;
    line-height: 32px;
    font-weight: 700;
    color: var(--hr-brown-900);
    margin: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
}
/* 13.3px, the design's own gap between the two pills (node
   I40001286:70271;40001144:62927 "Container"). */
.vid-card-tags { grid-column: 1 / -1; display: flex; gap: 13.3px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.vid-card-tag {
    display: inline-flex;
    align-items: center;
    padding: 8px 16px;
    border-radius: 8px;
    background: var(--hr-purple-400, #a56293);
    color: #e6f0ef;
    font-size: 14px;
    /* 16px line box, so this pill is 8 + 16 + 8 = 32 tall — the design's tag row
       height, and the same as .vidd-tag on the detail page. With no line-height it
       inherited Bootstrap's 1.5 (21px) and stood 37px. */
    line-height: 16px;
    font-weight: 700;
    text-transform: uppercase;
    white-space: nowrap;
}
/* The language pill beside the category tag (Figma node
   I40001286:70271;40001144:62929): a fully rounded green-tinted chip, type
   "Labels/Label XSmall/Bold" — Almarai 700, 16/24, #12736a — on a 10% green
   fill. 8px block padding against the 24px line box gives the design's 40px
   pill; the 18.7px inline padding is its own. */
.vid-card-lang {
    display: inline-flex;
    align-items: center;
    /* 4px block / 16px inline, re-read off the node: the pill is 55x32 with its
       24px text at y=4 and x=16, so 4 + 24 + 4 = 32 and 16 + 23 + 16 = 55.
       It was 8/18.7 — a 40px pill — which is what made the tags row 40 instead of
       32, the content block 88 instead of 80, and this panel 144 instead of the
       design's 136. The panel's own 32/24 padding was never the problem; its
       height simply follows whatever the tallest pill in the row is. */
    padding: 4px 16px;
    border-radius: 999px;
    background: rgba(18, 115, 106, .1);
    color: #12736a;
    font-size: 16px;
    line-height: 24px;
    font-weight: 700;
    text-transform: uppercase;
    white-space: nowrap;
}
.vid-card-like {
    grid-column: 2;
    grid-row: 1;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 61px;
    background: rgba(255, 255, 255, .2);
    border: 1.5px solid transparent;
    box-shadow: 0 3px 6px rgba(0, 0, 0, .03);
    cursor: pointer;
    transition: background-color .2s ease, border-color .2s ease, transform .2s ease;
    padding: 0;
    /* Stated here rather than picked up from layout-revamp.css's ring list,
       which scopes its position:relative to :not(.is-active) — the hover glow
       has to work in both states. isolation keeps that glow's plus-lighter
       blending against this button's own fill. */
    position: relative;
    isolation: isolate;
}
.vid-card-like img { width: 24px; height: 24px; }
.vid-card-like.is-active { background: var(--hr-yellow-500); border-color: var(--hr-yellow-500); }
.vid-card-like.is-active img { filter: brightness(0) invert(1); }

/* ---------- Pagination ---------- */
/* Taken from .pr-page-* (press-releases-revamp.css:546), which is Figma's
   pagination component in full: every control — arrows, numbers AND the
   ellipsis — is the same 56px glass circle. This page had the circle on the
   arrows and numbers only, carried one of the stack's four shadow layers (so no
   inset white rim, the thing that makes it read as glass rather than a flat
   disc), sized its arrow glyphs off the markup's 20px attributes instead of the
   design's 24, and left the ellipsis as a bare text box. */
.vid-pagination { position: relative; z-index: 1; display: flex; align-items: center; justify-content: flex-start; gap: 8px; }
.vid-page-arrow,
.vid-page-number,
.vid-page-ellipsis {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Stated for all three states, not just the non-active ones layout-revamp's
       ring list covers: the shared hover glow is an absolutely-positioned
       ::before, so without a positioned box on .is-active too it would anchor to
       .vid-pagination and light up the whole row instead of one pill. */
    position: relative;
    width: 56px;
    height: 56px;
    border-radius: 61px;
    background: rgba(255, 255, 255, .2);
    border: 1.5px solid transparent;
    box-shadow: 2px 23px 14px rgba(0, 0, 0, .02), 1px 10px 10px rgba(0, 0, 0, .03), 0 3px 6px rgba(0, 0, 0, .03), inset 0 4px 6.1px rgba(255, 255, 255, .23);
    text-decoration: none;
    font-size: 16px;
    color: var(--hr-brown-500);
    transition: background-color .2s ease, color .2s ease, transform .2s ease;
}
.vid-page-arrow img { width: 24px; height: 24px; }
[dir="rtl"] .vid-page-arrow img { transform: scaleX(-1); }
.vid-page-arrow:hover,
.vid-page-number:hover { text-decoration: none; color: var(--hr-brown-500); background: rgba(255, 255, 255, .4); }
.vid-page-arrow.is-disabled { opacity: .35; pointer-events: none; }
.vid-page-number.is-active,
.vid-page-number.is-active:hover {
    /* Fully transparent rather than amber-on-amber: the active pill carries no
       rim in the design, and the shared gradient ring is already scoped off
       .is-active in layout-revamp.css. */
    border-color: rgba(255, 255, 255, 0);
    background: var(--hr-yellow-500);
    color: var(--hr-cream-50);
    font-weight: 700;
}

.vid-empty { padding: 60px 0; text-align: center; font-size: 18px; color: var(--hr-brown-300); }

@media (max-width: 1199.98px) {
    .vid-grid { grid-template-columns: repeat(2, 1fr); }
    /* The gutter carries the padding, the carousel's bleed and the slide widths
       with it — no per-section override needed. */
    .video-revamp { --vid-gutter: 40px; }
    /* Hero comes down with the gutters, 256 -> 200 -> 160, as on the Events,
       Speakers and Annual Gatherings heroes. The wash follows it through
       --vid-wash-h without needing its own override here. */
    .video-revamp { --vid-hero-h: 200px; }
    /* The same step down .sml-head h1 takes from this identical 64/72 token. */
    .vid-featured-head h1 { font-size: 48px; line-height: 54px; }
}
@media (max-width: 768px) {
    .vid-grid { grid-template-columns: 1fr; }
    .video-revamp {
        --vid-hero-h: 160px;
        /* .vid-featured's top padding is halved below, so the desktop +80px
           would finish 20px OVER the h1 at this breakpoint. Same override, for
           the same reason, that .summit-listing-revamp and .events-revamp carry
           on their own phone breakpoint. */
        --vid-wash-h: calc(var(--vid-hero-h) + 40px);
    }
    /* 60px, matching .evt-intro: 120px of desktop lead-in is most of a phone
       viewport before the first line of copy. */
    .vid-featured { padding-top: 60px; }
    /* Centered on phone, per the mobile layout: the 50/50 split heading row
       reads better stacked and centred than left-aligned at this width.
       flex-basis reset to auto on both children: the desktop rule's
       "flex: 1 1 360px" sets a 360px MAIN-AXIS basis, which is a width in
       the row layout but becomes a HEIGHT once flex-direction flips to
       column here — left at 360px it forced each item toward a 360px-tall
       box, which is what opened up the large gap between the heading and
       the paragraph. */
    .vid-featured-head { flex-direction: column; align-items: center; text-align: center; margin-bottom: 32px; }
    .vid-featured-head h1,
    .vid-featured-head p { flex: 0 1 auto; }
    /* 32/40, the size the other listing headers use on a phone (.tnc-title,
       .pp-title, .evt-intro-inner h1). This page sat at 36/42, the odd one out. */
    .vid-featured-head h1 { font-size: 32px; line-height: 40px; }
    .vid-featured-head p { font-size: 18px; line-height: 26px; }
    /* Was targeting a nonexistent "h2" descendant — .vid-listing-title IS the
       h2 (index.blade.php), so the old rule matched nothing and this never
       actually shrank on phone. Sizes below are the design's own tokens:
       Headings/H6/Bold (24/32) for the title, Utility/Caption/Regular
       (12, line-height 100%) for the count — both a step down from the
       desktop 40px/24px. No extra margin on the header row itself in the
       design; it's a plain space-between pair filling the section column,
       so .vid-listing-head keeps the same 40px margin-bottom at this width. */
    .vid-listing-title { font-size: 24px; line-height: 32px; }
    .vid-listing-count { font-size: 12px; line-height: normal; }
    /* Figma's own row is "items-center justify-between", not the desktop
       rule's flex-end — the count sits vertically centered against the
       title's cap-height here, not baseline-aligned to its bottom. */
    .vid-listing-head { align-items: center; margin-bottom: 16px; }

    /* Filters row goes inline and scrollable on phone instead of wrapping
       onto multiple lines: the whole row (tabs + sort) stays on one line,
       overflowing horizontally, so it doesn't eat vertical space with a
       stack of wrapped tab pills. */
    /* Scrolls, but the scrollbar itself stays hidden — Firefox/IE via the
       standard property, WebKit/Blink (Chrome, Safari) via the pseudo-element,
       since neither reads the other's rule. */
    /* overflow-x: auto forces overflow-y to compute as auto too (the spec
       ties the axes together), so the row was clipping the active/hover
       pill's box-shadow flat along the top/bottom edges — a hard line where
       the soft shadow gets cut instead of fading out.
       --vid-pill-shadow's layers are all downward-offset (23px/10px/3px),
       reaching ~37px below the pill (23px offset + 14px blur) and almost
       nothing above it, so the padding is asymmetric: 8px on top is enough
       for the 2px hover lift, 40px on the bottom clears the shadow's full
       reach. Each side's negative margin cancels its own padding (plus the
       8px extra pulled off the bottom to land the requested 32px), so
       neither the gap above this row nor the 32px gap below it moves —
       only the clipping box grows, not the visible spacing.
       The same clipping happens left/right, since this is now also a
       horizontal scroller: whichever pill sits at the start/end of the
       scrollable content has its shadow cut flat against that edge too.
       padding-inline:16px + margin-inline:-16px is the same
       padding-then-cancel-with-negative-margin trick on the other axis — the
       shadow's h-offset is tiny (2px/1px/0px) so its reach is basically just
       the largest blur radius, 14px; 16px covers that with a couple of
       pixels to spare. The 16px of clipping room comes out of this
       section's own 16px mobile gutter (--vid-gutter), so the tabs' visible
       start position doesn't move, only the invisible clip boundary
       expands to the viewport edge. */
    .vid-filters {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        -ms-overflow-style: none;
        padding-block: 8px 40px;
        padding-inline: 16px;
        margin-block: -8px -8px;
        margin-inline: -16px;
    }
    .vid-filters::-webkit-scrollbar { display: none; }
    .vid-filters-tabs { flex-wrap: nowrap; }
    .vid-tab { flex-shrink: 0; white-space: nowrap; }
    .vid-sort-form { flex-shrink: 0; }
    .vid-carousel-controls { flex-wrap: wrap; margin-top: 24px; }
    .video-revamp { --vid-gutter: 16px; }

    /* One card per slide on phone: the peek/scale treatment is a desktop
       effect, so the slide takes the full track width and stays at full
       scale/opacity instead of showing a sliver of the next card. */
    .vid-carousel .vid-swiper { margin-inline-end: 0; }
    .vid-swiper .swiper-slide {
        width: var(--vid-track-w);
        transform: none;
        opacity: 1;
    }
    .vid-swiper .swiper-slide-active { transform: none; }

    /* Mobile feature card — Figma's "Active small" variant of this component,
       not a scaled-down copy of the desktop "Active" one: card proportions,
       badge sizes and button size are all their own values in the design,
       not the desktop numbers shrunk uniformly. */
    .vid-feature-card {
        aspect-ratio: 362 / 451;
        min-height: 0;
        border-radius: 28px;
        padding: 24px;
    }
    /* Featured badge: smaller pill, smaller diamond glyph. */
    .vid-feature-badge { padding: 8px 10px; border-radius: 6px; gap: 8px; font-size: 12px; line-height: normal; }
    .vid-feature-badge-dot { width: 10.983px; height: 12px; }
    .vid-feature-badge-dot::before { width: 8.416px; height: 8.416px; border-width: .162px; }
    .vid-feature-badge-dot::after { width: 4.339px; height: 4.339px; }

    /* Duration above the category/type tag, both left-aligned and stacked —
       the mobile card reads top-to-bottom instead of the desktop's
       space-between row. */
    .vid-feature-meta { flex-direction: column; align-items: flex-start; gap: 12px; }
    .vid-feature-duration { order: -1; padding: 8px 10px 8px 8px; border-radius: 6px; font-size: 12px; line-height: normal; }
    .vid-feature-tag { padding: 6px 12px; border-radius: 6px; font-size: 10px; }

    .vid-feature-content h3 { font-size: 20px; line-height: 32px; }
    .vid-feature-content p { font-size: 14px; }

    /* Play button: 48px (16px padding + 16px icon) vs the desktop 72px.
       top is 34% here, not the desktop rule's inherited 50%: Figma pins this
       variant at "50% - 71.5px" against its 451px-tall card (71.5/451 =
       15.86%), i.e. centred on the clear photo area ABOVE the title/
       description block rather than on the card's full height — the bottom
       content block is proportionally taller on this narrower card, so a
       true 50% center sits low, over that text. */
    .vid-feature-play {
        top: 34%;
        width: 48px;
        height: 48px;
        border-width: 1px;
        box-shadow:
            0 2.667px 4.067px 0 rgba(255, 255, 255, .23) inset,
            1.333px 15.333px 9.333px 0 rgba(0, 0, 0, .02),
            .667px 6.667px 6.667px 0 rgba(0, 0, 0, .03),
            0 2px 4px 0 rgba(0, 0, 0, .03);
    }
    .vid-feature-play img { width: 12.667px; height: 13.333px; transform: translateX(1px); }

    /* ---------- Videos listing card, phone ----------
       The card carried its desktop sizes straight onto the phone; the featured
       card above (.vid-feature-* in video-revamp.css) already takes this step,
       so these follow its numbers rather than new ones. */

    /* 48px, from 72 - the same 2/3 step .vid-feature-play takes, with the
       border and the effect stack scaled by the same factor and the glyph at
       19x20 * 2/3. */
    .vid-card-play {
        width: 48px;
        height: 48px;
        border-width: 1px;
        box-shadow:
            0 2.667px 4.067px 0 rgba(255, 255, 255, .23) inset,
            1.333px 15.333px 9.333px 0 rgba(0, 0, 0, .02),
            .667px 6.667px 6.667px 0 rgba(0, 0, 0, .03),
            0 2px 4px 0 rgba(0, 0, 0, .03);
    }
    .vid-card-play img { width: 12.667px; height: 13.333px; transform: translateX(1px); }
    /* 48px from 56. The 24px heart is left alone: it reads as 50% of the
       button here against 43% at 56, which is the proportion the design shows. */
    .vid-card-like { width: 48px; height: 48px; }
    /* 20px. line-height stays at the base 32px, as .vid-feature-content h3
       keeps its 32px line box when it drops to 20px on this breakpoint. */
    .vid-card-text h3 { font-size: 20px; }
    /* 10px, with the 6px/12px padding and 6px radius .vid-feature-tag takes on
       the phone. The language pill's line box drops 24 -> 20 so the two pills
       stay the same height as each other - 28px here, the way they match at
       32px on desktop (4 + 20 + 4 against the tag's 6 + 16 + 6). */
    .vid-card-tag { padding: 6px 12px; border-radius: 6px; font-size: 10px; }
    .vid-card-lang { padding: 4px 12px; font-size: 10px; line-height: 20px; }

    /* One breadcrumb size site-wide on the phone, taken from the Events
       listing (.evt-breadcrumb in events-revamp.css): 12px type, 8px gaps,
       a 12px separator. This page had a fluid 13-20px clamp. */
    .vid-breadcrumb { font-size: 12px; gap: 8px; }
    .vid-breadcrumb-sep { height: 12px; }
}
