/* ==========================================================================
   Speakers listing page (Figma: QF - BilAraby - WebsiteDesign-Concept-2,
   node 40000567:26844 "SPEAKERs List"). Reuses the --hr-* tokens already
   declared globally in layout-revamp.css.
   ========================================================================== */

.speakers-revamp .hr-accent { color: var(--hr-yellow-400); }

/* Per Figma the blue-to-cream wash spans BOTH the 256px breadcrumb hero AND
   the top of the listing section below it — the heading/filters sit on its
   lower, cream-ward half. So it lives on this wrapper at its natural height
   rather than on .spk-hero (where `cover` on a 256px box crushed the whole
   fade into half the space); cream fills the rest of the page beneath it.
   Same flat CSS gradient wash technique as events-revamp.css / event-detail-
   revamp.css (no photo banner) — a raster gradient asset here rendered
   noticeably darker/harsher than Figma's smooth blend. */
.speakers-revamp {
    position: relative;
    /* Hero height as a variable so the wash can be derived from it (see
       --spk-wash-h below) instead of the two drifting apart. */
    --spk-hero-h: 256px;
    /* Wash ends 64px past the hero, on BOTH pages. It was 704px here and only
       shortened on the listing; the two are now deliberately identical.
       See the note on ::before about what that costs the detail page. */
    --spk-wash-h: calc(var(--spk-hero-h) + 80px);
    /* Curve borrowed from About Us, which is the one that reads as a liquid
       flow into the cream rather than a band that stops - same change as
       .summit-listing-revamp, which carries the full derivation. In short: its
       wash is a Figma SVG export (about-revamp/hero-banner.svg) whose alpha,
       sampled down its 424px box, runs .91 / .84 / .75 / .59 / .42 / .23 / .01
       at 0 / 42 / 106 / 170 / 233 / 297 / 348px and is spent by 82% of the box;
       those samples are renormalised onto 0-100% here (each position over that
       0.82). The four stops this replaces held .55 all the way to 80% and then
       fell to zero inside the last 64px - the whole transition happened at the
       end, at roughly twice About Us's rate, which is the hard edge.
       Colour is untouched; only the falloff is borrowed. */
    background: var(--hr-cream-400) linear-gradient(to bottom,
        rgba(0, 80, 135, .91) 0%,
        rgba(0, 80, 135, .84) 12.2%,
        rgba(0, 80, 135, .75) 30.5%,
        rgba(0, 80, 135, .59) 48.8%,
        rgba(0, 80, 135, .42) 67.1%,
        rgba(0, 80, 135, .23) 85.4%,
        rgba(0, 80, 135, 0) 100%) no-repeat top center;
    background-size: 100% var(--spk-wash-h);
}

/* Figma's wash carries a grain baked into it, which a plain linear-gradient()
   cannot reproduce - it renders flat and plastic instead of "brushed". Tiled
   feTurbulence overlay, as the other washed pages already
   use (events-revamp.css .events-revamp::before carries the original rationale
   for the feComponentTransfer re-centering and the .5 opacity).

   Grain is the shared 0.85 tile, same as the other washed heroes. A coarser 0.3
   was trialled when this read as "shiny" in review and rejected; the fix was
   strength, not size, so the opacity below is .7 rather than the .5 the other
   pages use.

   It lives on this wrapper rather than on .spk-hero so the LISTING and the
   DETAIL page get an identical brush - both render this same element.

   The mask decays the grain at the same rate as the wash beneath it - the
   stops are the gradient's own alphas normalised against its .91 start.
   Without it the texture would keep speckling at full strength past the point
   where the blue has gone and there is only flat cream. (The two masks below
   also used to disagree on their final stop, 100% vs 92%, so the prefixed and
   unprefixed rules faded the grain over different spans.) */
.speakers-revamp::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: var(--spk-wash-h);
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxODAnIGhlaWdodD0nMTgwJz48ZmlsdGVyIGlkPSduJz48ZmVUdXJidWxlbmNlIHR5cGU9J2ZyYWN0YWxOb2lzZScgYmFzZUZyZXF1ZW5jeT0nMC44NScgbnVtT2N0YXZlcz0nMicgc3RpdGNoVGlsZXM9J3N0aXRjaCcvPjxmZUNvbG9yTWF0cml4IHR5cGU9J3NhdHVyYXRlJyB2YWx1ZXM9JzAnLz48ZmVDb21wb25lbnRUcmFuc2Zlcj48ZmVGdW5jUiB0eXBlPSdsaW5lYXInIHNsb3BlPScxJyBpbnRlcmNlcHQ9Jy0wLjIzMDInLz48ZmVGdW5jRyB0eXBlPSdsaW5lYXInIHNsb3BlPScxJyBpbnRlcmNlcHQ9Jy0wLjIzMDInLz48ZmVGdW5jQiB0eXBlPSdsaW5lYXInIHNsb3BlPScxJyBpbnRlcmNlcHQ9Jy0wLjIzMDInLz48L2ZlQ29tcG9uZW50VHJhbnNmZXI+PC9maWx0ZXI+PHJlY3Qgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScgZmlsdGVyPSd1cmwoI24pJy8+PC9zdmc+");
    background-repeat: repeat;
    opacity: .7;
    mix-blend-mode: overlay;
    -webkit-mask-image: linear-gradient(to bottom,
        rgba(0,0,0,1) 0%,
        rgba(0,0,0,.923) 12.2%,
        rgba(0,0,0,.824) 30.5%,
        rgba(0,0,0,.648) 48.8%,
        rgba(0,0,0,.462) 67.1%,
        rgba(0,0,0,.253) 85.4%,
        rgba(0,0,0,0) 100%);
    mask-image: linear-gradient(to bottom,
        rgba(0,0,0,1) 0%,
        rgba(0,0,0,.923) 12.2%,
        rgba(0,0,0,.824) 30.5%,
        rgba(0,0,0,.648) 48.8%,
        rgba(0,0,0,.462) 67.1%,
        rgba(0,0,0,.253) 85.4%,
        rgba(0,0,0,0) 100%);
    pointer-events: none;
    z-index: 0;
}

/* ---------- Hero / breadcrumb banner ---------- */
/* Figma's Innerpage-hero/Without carries a pattern at each end of the hero,
   which this hero was missing entirely - no markup, no rule - so the band read
   as a plain flat wash. Same assets and same geometry as .sml-hero-pattern on
   the Gatherings listing: both are the 256px breadcrumb-only hero variant, so
   the two stay in step. (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.)
   Anchored to the bottom, not the top: Figma has Pattern-01 at top:95.03 +
   height:160.658 = 255.7 against a 256px hero and Pattern-02 at bottom:0, so
   bottom-anchoring keeps both in the same relationship to the breadcrumb even
   where this hero is shorter (200px/160px at the lower breakpoints). */
.spk-hero-pattern {
    position: absolute;
    bottom: 0;
    z-index: 0;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    pointer-events: none;
}
.spk-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. */
.spk-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;
}
[dir="rtl"] .spk-hero-pattern { transform: scaleX(-1); }
@media (max-width: 767.98px) {
    .spk-hero-pattern { display: none; }
}
.spk-hero {
    position: relative;
    height: var(--spk-hero-h);
    display: flex;
    align-items: flex-end;
    padding: 0 160px 24px;
}
/* Gutter lives on .spk-hero (above), matching how .spk-listing/.spk-listing-inner
   are structured — putting the inline padding on the inner element instead
   pushed the breadcrumb right of the heading and cards below it. */
.spk-hero-inner {
    position: relative;
    z-index: 1;
    max-width: 1600px;
    width: 100%;
    margin-inline: auto;
}
.spk-breadcrumb-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
}
.spk-breadcrumb {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
    font-size: 20px;
    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. */
.spk-breadcrumb a,
.spk-breadcrumb span:not(.spk-breadcrumb-sep) { opacity: 1; }
.spk-breadcrumb a {
    color: inherit;
    text-decoration: none;
    transition: opacity .2s ease;
}
.spk-breadcrumb a:hover { opacity: 1; color: inherit; text-decoration: underline; }
.spk-breadcrumb-current { font-weight: 700; opacity: 1 !important; }
/* On the speaker details page this row can carry up to 4 crumbs (Home /
   Gathering title / Speakers / Speaker Details), and the gathering title is
   admin-controlled and can run long — without this, narrow viewports wrap
   it across lines and push the later crumbs off the edge of the screen
   instead of eliding, same issue the Blogs detail breadcrumb had. */
.spk-breadcrumb a,
.spk-breadcrumb-current {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.spk-breadcrumb-sep {
    width: 1px;
    height: 16px;
    flex-shrink: 0;
    background: rgba(249, 247, 234, .5);
}
/* Below the desktop breakpoint the row has no room for four crumbs on one
   20px line — every crumb collapsed to an ellipsis ("H… | BILARABY ANNU… |
   SPE… | SPEAK…"), which tells the reader nothing. Stepping the type down and
   letting the row wrap shows the words in full instead. The elision above is
   kept for desktop, where it still earns its place: the gathering title is
   admin-controlled and has to stay on one line beside the other crumbs. */
@media (max-width: 1199.98px) {
    .spk-breadcrumb {
        flex-wrap: wrap;
        font-size: 14px;
        gap: 8px;
    }
    .spk-breadcrumb a,
    .spk-breadcrumb-current {
        overflow: visible;
        white-space: normal;
        text-overflow: clip;
    }
    .spk-breadcrumb-sep { height: 12px; }
}
/* Phone: the artboard's own breadcrumb size. */
@media (max-width: 767.98px) {
    .spk-breadcrumb { font-size: 12px; }
}
.spk-hero-divider { display: none; }
@media (min-width: 1200px) {
    /* Fixed-width group pinned to the row's right end (the row is
       justify-content: space-between), NOT flex-grow from the breadcrumb —
       growing it parked the diamonds right next to the breadcrumb text with a
       long trailing line, whereas the design has them out near the right edge
       with only a short line finishing the run. */
    .spk-hero-divider {
        display: flex;
        align-items: center;
        flex-shrink: 0;
        width: 300px;
        /* Bleeds the line past .spk-hero-inner all the way to the true viewport
           edge: that inner is a 1600px box centred inside .spk-hero's 160px
           gutters, so its edge sits 160px + half the leftover width in. */
        margin-inline-end: calc(-160px - max(0px, (100vw - 1920px) / 2));
    }
    .spk-hero-divider .smt-hero-diamond {
        /* 20 * (sqrt(2) - 1) / 2. A rotated 20px square is 28.28px wide visually
           but still occupies a 20px layout box, so the 4.142px overhang per side
           would make neighbours merge into one continuous zigzag. This margin
           separates the boxes by exactly that overhang, so adjacent tips just
           touch - corner to corner, 0px visible gap, no merge. Carried on the
           diamond rather than as a `gap` on the row so the last one also spaces
           itself off the line. Matches .abt-diamond / .tnc-diamond / .sml-*. */
        width: 20px;
        height: 20px;
        margin-inline: 4.142px;
        transform: rotate(45deg);
        background: var(--hr-cream-500);
        flex-shrink: 0;
    }
    /* Negative start margin = the last diamond's own overhang past its layout
       box (14 * (sqrt(2)-1) / 2), so the rule begins exactly at that tip rather
       than a gap's width beyond it. */
    .spk-hero-divider-line { flex: 1 1 auto; height: 1px; background: rgba(249, 247, 234, .5);        /* The last diamond's own 4.142px slot margin supplies the gap now, so a
           negative offset here would eat into it. */
        margin-inline-start: 0; }
}
/* Full-bleed hairline closing the hero, directly under the breadcrumb row. */
.spk-hero::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 1px;
    background: rgba(249, 247, 234, .35);
}

/* ---------- Listing section ---------- */
/* Transparent, not cream: the wrapper's gradient (which continues past the
   hero into this section's upper area) has to remain visible behind the
   heading and filters. */
.spk-listing {
    position: relative;
    /* 100px top, not 64: the hero's gradient runs right up to this section, so
       64px left the h1 sitting almost on the breadcrumb. Matches the 100px the
       summit listing gives the same hero/title pair. Stepped back down on
       phones below, where 100px is a lot of dead space above the fold. */
    padding: 100px 160px 100px;
    overflow: hidden;
}
.spk-listing-inner {
    position: relative;
    z-index: 1;
    max-width: 1600px;
    margin-inline: auto;
}
.spk-head { margin-bottom: 40px; }
.spk-head h1 { font-size: 40px; font-weight: 700; color: var(--hr-brown-500); margin: 0 0 12px; }
.spk-head p { font-size: 20px; color: var(--hr-brown-300); margin: 0; }

/* ---------- Filters ---------- */
.spk-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 40px;
}
/* Inert above the phone breakpoint: the wrapper exists only so the tabs and the
   two selects can scroll as one row down there (see the <=767 block), and
   display:contents leaves this row the same flat flex it has always been. */
.spk-filter-row { display: contents; }
/* The auto end-margin absorbs the row's free space, which is what keeps the two
   selects and the search box grouped together at the end of it. justify-content
   did that on its own while .spk-filters had exactly two children; the search
   box is now a third, having moved out of .spk-filters-fields so it can sit on
   its own row on a phone - without this it would be spaced out to the middle. */
.spk-filters-tabs { display: flex; gap: 16px; flex-wrap: wrap; margin-inline-end: auto; }
.spk-tab {
    display: inline-flex;
    align-items: center;
    padding: 12px 20px;
    border-radius: 61px;
    font-size: 16px;
    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;
}
.spk-tab:hover { text-decoration: none; color: var(--hr-brown-500); }
.spk-tab.is-active {
    background: var(--hr-cream-50, #fefefd);
    border-color: #fff;
    box-shadow: 0 3px 6px rgba(0, 0, 0, .03);
    font-weight: 700;
}
.spk-filters-fields { display: flex; gap: 16px; flex-wrap: wrap; align-items: center; }
.spk-select {
    appearance: none;
    padding: 12px 40px 12px 20px;
    border-radius: 61px;
    font-size: 16px;
    color: var(--hr-brown-500) !important;
    background: rgba(236, 230, 211, .4) url("../images/press-releases-revamp/icon-chevron-down.svg") no-repeat;
    background-size: 11px;
    background-position: right 20px center;
    border: 1px solid rgba(177, 175, 165, .5);
    cursor: pointer;
}
[dir="rtl"] .spk-select { background-position: left 20px center; padding: 12px 20px 12px 40px; }
.spk-search {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 20px 12px 16px;
    border-radius: 61px;
    background: rgba(236, 230, 211, .4);
    border: 1px solid rgba(177, 175, 165, .5);
}
.spk-search img { flex-shrink: 0; }
.spk-search input {
    border: 0;
    background: none;
    font-size: 16px;
    color: var(--hr-brown-500);
    min-width: 180px;
    outline: none;
}
.spk-search input::placeholder { color: var(--hr-brown-500); opacity: .7; }

/* ---------- Card grid ---------- */
.spk-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
    margin-bottom: 48px;
}
@media (max-width: 1299.98px) { .spk-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 991.98px) { .spk-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 575.98px) { .spk-grid { grid-template-columns: 1fr; } }

.spk-card {
    position: relative;
    aspect-ratio: 382 / 507;
    border-radius: 30px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 24px;
    color: var(--hr-cream-500);
    isolation: isolate;
}
/* Large logo-mark motif behind the photo — same asset and Figma geometry as
   .smt-speaker-card-pattern on the summit page, so both surfaces match. Per
   Figma the speaker photos are cut-outs (transparent background) and this
   shows through around the subject; a full-background rectangular photo
   covers it instead. */
/* Geometry is now the SAME derivation .smt-speaker-card-pattern uses on the
   summit page — percentages of the 382x507 card rather than the fixed px this
   carried before. Fixed px only lands correctly at one card width: the grid is
   fluid, so at every other breakpoint the motif slid out of position and the
   card showed a random crop of it instead of the design's placement.
   The art's own box is 557.424 x 240.982 (145.923% x 47.531%) and rotate()
   pivots about the centre, so placing that box's centre at Figma's
   (70.509, 105.212) = (18.46%, 20.75%) puts the rotated result exactly where
   the design has it — hence the negative offsets (centre minus half the box).

   `left`, deliberately PHYSICAL, and the [dir="rtl"] override that used to sit
   here is gone: this motif is meant to render identically in Arabic instead of
   mirroring with the layout, which is how the summit page already treats it.

   Opacity stays 1 — the exported asset already carries Figma's own 0.3 on the
   path, so dimming it here would double-apply it. */
/* NOTE the `.spk-card` scope on the geometry below. The percentages are of the
   382x507 PORTRAIT listing card, and .spk-profile-card — which is 16:9
   landscape — reuses this same class. Unscoped, the motif resolved to a
   120x652 band on a 447x251 card, overhanging it by 274px and covering 69% of
   its area, which washed the solid blue out to a pale field. The detail card
   keeps its own geometry further down. */
.spk-card-pattern {
    position: absolute;
    background: url("../images/summit-revamp/speaker-card-pattern.svg") no-repeat center / contain;
    transform: rotate(90deg) scaleY(-1);
    /* Sits BEHIND the speaker photo, as in Figma. Note this means it is only
       visible where the photo doesn't cover it — Figma's speaker images are
       background-removed cut-outs, so the motif shows around the subject.
       With a full-background rectangular upload the photo hides it. */
    opacity: 1;
    pointer-events: none;
    z-index: -3;
}
.spk-card .spk-card-pattern {
    top: -3.014%;
    left: -54.503%;
    width: 145.923%;
    height: 47.531%;
}
/* Second placement. Figma alternates the SAME asset between two placements
   across the row (cards 1/3 use the rule above, cards 2/4 use this one), so
   four cards never repeat the same background — the grid previously gave every
   card placement A, which is why the motif read as one repeated crop.
   Art box 894.174 x 386.564 (234.077% x 76.245%) with its centre at Figma's
   (190.998, 55.798) = (50%, 11.005%) of the card — dead centre horizontally,
   hence the symmetric offset. It reads as a wide band across the top with a
   large diamond under it, rather than a vertical band down the leading edge. */
.spk-card .spk-card-pattern-alt {
    top: -27.117%;
    left: -67.039%;
    width: 234.077%;
    height: 76.245%;
    transform: rotate(-179.43deg) scaleY(-1);
}
/* Matches .smt-speaker-card-bg on the summit page. contain + bottom, not the
   22%-inset cover this used to run: cover crops whatever doesn't fit, and on a
   portrait cut-out that means slicing the head off, while the reserved top band
   forced the motif into a strip instead of letting it read around the subject.
   contain guarantees the whole subject is visible at any upload dimension while
   still standing on the card's bottom edge, matching the design's framing.
   Per the agreed content rule these uploads are background-removed PNGs
   (subject only) — that is what lets the card's colour and motif show around
   the person rather than being covered by a photo's own rectangle. */
.spk-card-bg {
    position: absolute;
    inset: 0;
    background-size: contain;
    background-position: bottom center;
    background-repeat: no-repeat;
    z-index: -2;
}
/* No headshot uploaded: the generic avatar is a square icon, not a
   full-bleed photo — `cover` would crop most of it away, so it's shown at
   a fixed size, centred, over the card's own background colour instead. */
.spk-card-bg-placeholder {
    background-size: 140px !important;
    background-repeat: no-repeat;
    background-position: center !important;
}
/* Figma (node 40001144:66834): transparent to rgba(0,0,0,.65) over the bottom
   285.661px of the 507px card - 56.343%. Figma draws it 603.324px wide on a
   382px card and centres it, but it is a purely vertical gradient so the
   overhang is invisible; inset-inline:0 is equivalent.
   This used to run rgba(11,11,5,.85) over the bottom 75%, i.e. both darker and
   taller than the design. */
.spk-card-scrim {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 56.343%;
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .65) 100%);
    z-index: -1;
}
.spk-card-body { display: flex; flex-direction: column; gap: 8px; }
.spk-card-body strong { font-size: 24px; font-weight: 700; line-height: 32px; }
.spk-card-body span { font-size: 20px; line-height: 28px; opacity: .9; }
.spk-card-location { font-weight: 700 !important; opacity: 1 !important; }
/* Whole-card link, under the arrow and over everything else. Rendered on video
   cards only (see grid.blade.php): their arrow fades out while the preview
   plays, so the card has to carry the click; a card with no preview keeps its
   arrow, and its arrow alone, as the click target. The photo, motif, scrim and
   preview all sit at or below z-index 0 in this card's own stacking context
   (.spk-card isolates), and the name block is unpositioned, so one z-index:1
   overlay covers the lot; the arrow is lifted past it below so it keeps its own
   hover state and click. */
.spk-card-link {
    position: absolute;
    inset: 0;
    z-index: 1;
}
.spk-card-arrow {
    position: absolute;
    inset-inline-end: 24px;
    bottom: 24px;
    z-index: 2;
    width: 56px;
    height: 56px;
    border-radius: 61px;
    border: 1.5px solid transparent;
    background: rgba(255, 255, 255, .2);
    display: flex;
    align-items: center;
    justify-content: center;
}
.spk-card-arrow img { width: 24px; height: 24px; }
[dir="rtl"] .spk-card-arrow img { transform: scaleX(-1); }
/* The arrow steps aside while the preview is running — it sits right over the
   video's bottom corner. Faded, not hidden: this arrow is the card's only link,
   so its target has to stay clickable for as long as the pointer is on the
   card. Same .25s as the video's own cross-fade above, so the two move
   together. Scoped to has-video, so a card without a preview keeps its arrow.
   Hover only, and the keyboard focus ring wins outright: focus lands ON this
   link (the delegated focusin handler in index.blade.php starts the preview
   from the keyboard too), and a focused control must never be the invisible
   one. */
.spk-card-arrow { transition: opacity .25s ease, transform .2s ease; }
.spk-card-has-video:hover .spk-card-arrow { opacity: 0; }
.spk-card-has-video .spk-card-arrow:focus-visible { opacity: 1; }

/* ---------- Load more ---------- */
/* Figma closes the grid with a sliver of the next row peeking out and fading
   into the page, with the button riding over it — the cue that there's more
   behind the button. The sliver is decorative only (no speaker data), so the
   markup drops it as soon as the last page is in. */
.spk-grid-peek {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
    /* .spk-grid keeps its 48px gap to whatever follows it on the last page;
       pull the sliver back up to a normal 24px row gap when it is shown. */
    margin-top: -24px;
    /* Negative, so the button overlaps the faded-out tail of the sliver. */
    margin-bottom: -56px;
    pointer-events: none;
}
/* Grey, not white: Figma fills the sliver with its neutral placeholder grey,
   and white on the cream page read as an almost-invisible ghost box rather
   than a row of cards sitting behind the button. */
.spk-grid-peek span {
    height: 112px;
    border-radius: 30px 30px 0 0;
    background: linear-gradient(to bottom, rgba(217, 217, 217, .9), rgba(217, 217, 217, 0));
}
/* One sliver per column — the extras would otherwise wrap onto a stray
   second row once the grid drops below four columns. */
@media (max-width: 1299.98px) {
    .spk-grid-peek { grid-template-columns: repeat(3, 1fr); }
    .spk-grid-peek span:nth-child(n+4) { display: none; }
}
@media (max-width: 991.98px) {
    .spk-grid-peek { grid-template-columns: repeat(2, 1fr); }
    .spk-grid-peek span:nth-child(n+3) { display: none; }
}
@media (max-width: 575.98px) {
    .spk-grid-peek { grid-template-columns: 1fr; }
    .spk-grid-peek span:nth-child(n+2) { display: none; }
}

.spk-load-more-wrap {
    position: relative;
    z-index: 1;
    display: flex;
    justify-content: center;
}
.spk-load-more-wrap .hr-btn.is-loading { opacity: .6; pointer-events: none; }

/* Same pill as the rest of the site — each page's stylesheet carries its own
   scoped copy (cf. .home-revamp .hr-btn in home-revamp.css). */
.speakers-revamp .hr-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14.5px 22.5px;
    border-radius: 61px;
    font-weight: 700;
    font-size: 16px;
    line-height: 24px;
    border: 1.5px solid transparent;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: transform .2s ease, box-shadow .2s ease;
}
.speakers-revamp .hr-btn:hover { transform: translateY(-2px); text-decoration: none; }
/* "Load More" - the only .hr-btn on these pages - given the home hero's
   "Culture" treatment. Its ring was a solid #fff, which draws an even hard
   edge all the way round; Culture's is 61% white with border-bottom-width:0,
   lighting the top and sides and leaving the bottom to run straight from
   #d98500 into the page. The 2px/0 border also makes the pill 55px rather
   than 56, which is Culture's own intrinsic height (it only reads 56 on the
   home page, where a flex sibling stretches it). Padding and the five-layer
   shadow already matched. */
.speakers-revamp .hr-btn-primary {
    background: var(--hr-yellow-500);
    color: var(--hr-cream-50);
    border: 2px outset #ffffff9c;
    border-bottom-width: 0;
    box-shadow:
        inset 0 4px 6.1px rgba(255,255,255,.23),
        7px 63px 18px rgba(0,0,0,.02),
        2px 23px 14px rgba(0,0,0,.02),
        1px 10px 10px rgba(0,0,0,.03),
        0 3px 6px rgba(0,0,0,.03);
}
/* Culture holds its resting shadow and lights the shared ::before ellipse
   instead of swapping in an amber drop-shadow (home-revamp.css records that one
   as invented). The translateY(-2px) above stays - home's .hr-btn:hover lifts. */
.speakers-revamp .hr-btn-primary:hover { color: var(--hr-cream-50); }

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

/* Decorative diamond + teal wave hugging the section's bottom-right corner
   and bleeding past the right edge (Figma's own exported asset, not a
   recreation). The raw file has the teal mass at top-left; a 180deg turn
   puts it bottom-right with the diamond above-left, matching the design.
   (Deriving this from Figma's own rotate(180deg)+scaleY(-100%) wrapper gave
   a horizontal-only flip, which rendered upside down — the nested wrapper
   transforms don't compose the way a single <img> does, so this is set from
   the rendered result instead.) */
/* Its markup is commented out in speakers/index.blade.php per request, so these
   rules currently style nothing on the listing. Kept intact so restoring that one
   line brings the motif back at every breakpoint. */
.spk-decor-diamond {
    position: absolute;
    inset-inline-end: -12px;
    bottom: 0;
    width: 240px;
    height: auto;
    pointer-events: none;
    transform: rotate(180deg);
}
[dir="rtl"] .spk-decor-diamond { transform: rotate(180deg) scaleX(-1); }
/* Scaled down step by step so the motif never grows into the last row of
   cards or sits behind the Load More button on a laptop or a phone, where a
   fixed 280px is a third of the screen. .spk-listing's overflow:hidden keeps
   the deliberate right-edge bleed from opening a horizontal scrollbar. */
@media (max-width: 1199.98px) { .spk-decor-diamond { width: 200px; } }
@media (max-width: 991.98px) { .spk-decor-diamond { width: 160px; } }
@media (max-width: 767.98px) { .spk-decor-diamond { width: 120px; } }

/* ==========================================================================
   Speaker detail page (Figma: node 40000567:26514 "SPEAKER PROFILE").
   Reuses the hero/breadcrumb, card and tab styles above.
   ========================================================================== */

/* ---------- Profile: bio + large speaker card ---------- */
/* Transparent like .spk-listing — the wrapper's gradient continues past the
   hero into this section's upper area and must stay visible behind the name. */
.spk-profile {
    position: relative;
    padding: 100px 160px 60px;
}
.spk-profile-inner {
    max-width: 1600px;
    margin-inline: auto;
    display: grid;
    grid-template-columns: minmax(0, 770fr) minmax(0, 770fr);
    gap: 60px;
    align-items: center;
}
.spk-profile-copy h1 {
    font-size: 56px;
    line-height: 72px;
    font-weight: 700;
    color: var(--hr-brown-500);
    margin: 0;
}
.spk-profile-country {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    font-size: 20px;
    line-height: 28px;
    color: var(--hr-brown-500);
}
.spk-profile-country img { flex-shrink: 0; }
/* Circular, per the design — the source assets are 4:3/3:2 rectangles, so
   object-fit:cover crops them to the centre square rather than squashing the
   flag into the circle. */
.spk-flag {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid rgba(60, 50, 30, .12);
}
.spk-profile-bio {
    margin-top: 40px;
    font-size: 20px;
    line-height: 32px;
    color: var(--hr-brown-300);
}
.spk-profile-bio p { margin: 0 0 16px; }
.spk-profile-bio p:last-child { margin-bottom: 0; }
/* Rich-text bios can carry a blank line (an empty `<p>` or a `<p><br></p>`)
   left over from the editor — collapse it instead of showing it as a gap
   between paragraphs. */
.spk-profile-bio p:empty,
.spk-profile-bio p:has(> br:only-child) { display: none; }

/* Same construction as .spk-card (listing) but landscape, and with a play
   control. Base colour matches Figma's blue profile card. */
.spk-profile-card {
    position: relative;
    aspect-ratio: 16 / 9;
    border-radius: 30px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 24px;
    color: var(--hr-cream-500);
    background-color: var(--hr-blue-500);
    isolation: isolate;
}
/* Landscape frame (unlike the portrait listing card). Uploaded headshots are
   ordinary rectangular photos in all sorts of aspect ratios (square, portrait,
   landscape) — `cover` on this wide/short frame zoomed square and portrait
   photos in tight, cropping off the top of the head. `contain` always shows
   the whole photo instead, letterboxed on the card's own colour + motif
   (which is what they're there for in the first place). */
.spk-profile-card .spk-card-bg {
    inset: 0;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
/* The motif is a CORNER ACCENT on this card, not a field wash: it reads in the
   top-leading corner beside the photo column and the rest of the card stays
   solid --hr-blue-500. Sized in px off the landscape frame rather than
   inheriting the listing card's portrait percentages (see the note on
   .spk-card-pattern above for what that produced here).
   The asset's own fill already carries a low opacity, so no extra dimming
   (that made it near-invisible on the blue). */
.spk-profile-card .spk-card-pattern {
    opacity: 1;
    /* Matched to the LISTING card's motif at its rendered size rather than
       being sized independently: there the percentages resolve to 557.4 x 241.0
       on a 382x507 card, and this was 278 x 120 - almost exactly half, which is
       why it read as a small corner mark next to the listing's. Rotated 90deg
       the footprint is 241 wide x 557 tall, so on this 770x433 card it runs from
       the top-leading corner down to y=384, finishing just above the name block
       instead of stopping a third of the way down. */
    /* Percentages, not px. The card is fluid (16/9 of whatever the column
       gives it), so fixed px sized the motif for one viewport only and it
       swamped the card everywhere narrower. These are the same 557 x 241 / -15
       / -208 measured against the 770 x 433 card they were taken from, so the
       motif now scales with the card at every width. */
    /* Scaled to the space ABOVE the name, not to the card.

       The name block sits a CONSTANT 128px off the card's bottom at every size
       (fluid card, fixed caption type), so the usable height is cardH - 144
       (128 plus 16px clear). Sizing the motif against the card instead left the
       bottom pinned but the top clipped by an ever-growing share - 48% of the
       artwork hidden at a 433px card against 68% at 201px - which is why the
       diamonds read as cut off on a laptop but whole on a large monitor.

       Tying every value to that usable height instead keeps the SAME fraction
       of the artwork on screen at any size, so it always looks like the same
       shape. Rotated 90deg the vertical extent is the box's width, hence the
       width/top/left below; aspect-ratio carries the height so the artwork
       cannot skew. Verified: 48.2% clipped and 16px clear of the name at 1930,
       1434 and 390 alike. */
    /* Placed by the DIAMONDS, not by the artwork's bounds.

       In Figma this vector is 754 x 613 against a much smaller card: the band
       deliberately bleeds off the top and runs down behind the caption, and
       only the diamonds sit wholly inside. Rasterising our own 557.424x240.982
       export shows the same split - a solid band across the top half, with the
       diamonds occupying x 179-398, y 120-241.

       transform: rotate(90deg) scaleY(-1) transposes, so an artwork point
       (ex,ey) lands at (ey - H/2, ex - W/2) from the box's centre. Feeding the
       diamond bounds through that puts them at cx -0.002H..+0.5H and
       cy -0.179W..+0.215W, which is what the sizes below solve against: the
       diamonds land ~11-23% across and ~6-44% down the card, clear of the
       caption, while the band still runs off the top and past the name as
       designed.

       All four values are percentages, so this holds identically at any size,
       and 54.4/41.8 keeps the box at the artwork's own 2.313 ratio (the card is
       a fixed 16/9) so `contain` fills it without letterboxing. */
    width: 54.4%;
    height: 41.8%;
    top: 2.37%;
    left: -15.85%;
}
/* Video fills the whole card, unlike the photo: footage is inherently
   rectangular, so boxing it into the cut-out's narrow column would just letter-
   box it with dead colour either side. */
.spk-profile-card-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    opacity: 0;
    transition: opacity .25s ease;
    z-index: -1;
    pointer-events: none;
}
.spk-profile-card.is-playing .spk-profile-card-video { opacity: 1; }
/* Listing-grid preview. Same treatment as the profile card's video above, but
   driven by hover rather than a play toggle, and the card keeps its size — the
   grid has fixed columns, so there is nothing to expand into. (The summit
   page's speakers carousel does widen its slide; that is a carousel, not a
   grid.) */
.spk-card-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    opacity: 0;
    transition: opacity .25s ease;
    pointer-events: none;
}
.spk-card-has-video:hover .spk-card-video,
.spk-card-has-video:focus-within .spk-card-video { opacity: 1; }
.spk-card-play {
    position: absolute;
    inset-inline-end: 24px;
    bottom: 24px;
    width: 56px;
    height: 56px;
    border-radius: 61px;
    border: 1.5px solid transparent;
    background: rgba(255, 255, 255, .2);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    transition: background-color .2s ease, transform .2s ease;
}
.spk-card-play:hover { background: rgba(255, 255, 255, .35); }
.spk-card-play img { width: 24px; height: 24px; }
/* BIL-802: while the video is actually running — the silent hover preview
   included — the button turns into a working Pause. Nothing in the project's
   icon set is a pause mark and the play glyph is a 1.5px outlined one, so the
   two bars are drawn here in that same language rather than borrowed from a
   different family; swap them for a real asset if the design ships one.
   ::after on this button is already the shared glass rim (layout-revamp.css),
   hence the span of its own rather than the button's own pseudo-elements. */
.spk-card-pause {
    display: none;
    align-items: center;
    gap: 4px;
}
.spk-card-pause::before,
.spk-card-pause::after {
    content: "";
    width: 6px;
    height: 16px;
    border: 1.5px solid #fff;
    /* 3px rounds a 6px bar into a capsule at this size; 2px keeps a rounded
       rectangle that still reads as a pause bar next to the play glyph. */
    border-radius: 2px;
}
.spk-card-play.is-pause img { display: none; }
.spk-card-play.is-pause .spk-card-pause { display: flex; }

/* ---------- Sessions ---------- */
.spk-sessions {
    position: relative;
    padding: 60px 160px 0;
}
/* The divider below normally supplies the section's bottom spacing (margin-
   top + padding-bottom) — but it's only rendered when a "Talks by" rail
   follows. Without it this section had 0 bottom padding and butted straight
   into whatever comes next. */
.spk-sessions:not(:has(.spk-sessions-divider)) { padding-bottom: 100px; }
.spk-sessions-inner {
    max-width: 1600px;
    margin-inline: auto;
}
.spk-sessions-inner h2 {
    font-size: 40px;
    line-height: 48px;
    font-weight: 700;
    color: var(--hr-brown-500);
    margin: 0 0 40px;
}
.spk-accent-green { color: var(--hr-green-500); }
.spk-sessions-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 40px;
}
.spk-sessions-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 24px;
}
@media (max-width: 991.98px) { .spk-sessions-grid { grid-template-columns: 1fr; } }

/* Frosted white card — the gradient + blur is what Figma uses, so it reads as
   glass over the cream section rather than a flat white block. */
.spk-session-card {
    display: flex;
    align-items: center;
    gap: 40px;
    /* Logical, not physical: the extra breathing room belongs on the END side
       (where the arrow sits) so it follows the arrow to the other edge in
       RTL instead of staying pinned to the physical right and crowding it. */
    padding-block: 24px;
    padding-inline: 24px 34px;
    border: 1px solid #fff;
    border-radius: 20px;
    background: linear-gradient(to top, rgba(255,255,255,.45) 0%, rgba(255,255,255,.6) 76%, rgba(255,255,255,.6) 100%);
    -webkit-backdrop-filter: blur(53px);
    backdrop-filter: blur(53px);
    box-shadow: 0 3px 3px rgba(0,0,0,.03), 1px 10px 5px rgba(0,0,0,.03), 2px 23px 7px rgba(0,0,0,.02);
    /* Kept from when this was a real link to the video, so the styling still
       holds if it is restored (see the note in speakers/partials/sessions
       .blade.php). Harmless on the <div> it currently renders as. */
    color: inherit;
    text-decoration: none;
    transition: box-shadow .2s ease;
}
/* TEMPORARY: no hover lift while the card is inert - a shadow that responds to
   the pointer reads as "this is clickable", which it is not right now. Restore
   this alongside the link. */
.spk-session-card:hover {
    box-shadow: 0 3px 3px rgba(0,0,0,.03), 1px 10px 5px rgba(0,0,0,.03), 2px 23px 7px rgba(0,0,0,.02);
}
/* Two overlapping squares — one filled, one outlined — rotated/skewed into the
   brand's diamond motif (drawn in Figma as shapes, not an exported asset). */
.spk-session-diamond {
    position: relative;
    width: 54px;
    height: 30px;
    flex-shrink: 0;
}
.spk-session-diamond-fill,
.spk-session-diamond-outline {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(133.47deg) skewX(-3.05deg);
}
.spk-session-diamond-fill {
    width: 21.33px;
    height: 21.33px;
    background: #8e3b78;
}
.spk-session-diamond-outline {
    width: 41.38px;
    height: 41.38px;
    border: .8px solid #8e3b78;
}
.spk-session-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.spk-session-body h3 {
    font-size: 24px;
    line-height: 32px;
    font-weight: 700;
    color: var(--hr-brown-700);
    margin: 0;
}
.spk-session-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}
.spk-session-meta-item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 20px;
    line-height: 28px;
    color: var(--hr-brown-700);
}
.spk-session-meta-item img { flex-shrink: 0; }
.spk-session-arrow {
    flex-shrink: 0;
    width: 56px;
    height: 56px;
    border-radius: 61px;
    /* This button sits on the light cream page (via the frosted session
       card), not a dark photo overlay like .spk-card-arrow/.spk-card-play —
       a white border there is invisible; same neutral pill border used for
       .spk-tab/.spk-select/.spk-search on this page. */
    border: 1.5px solid rgba(177, 175, 165, .5);
    background: rgba(255, 255, 255, .6);
    display: flex;
    align-items: center;
    justify-content: center;
}
[dir="rtl"] .spk-session-arrow img { transform: scaleX(-1); }

/* Diamond clusters at each end of a full-bleed orange rule, closing the
   section — only shown when there's a "Talks by" rail below to lead into,
   otherwise it dangles into nothing. */
.spk-sessions-divider {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 20px;
    margin-top: 80px;
    /* margin, not padding-bottom: under border-box sizing, padding eats into
       the 20px content box, collapsing it to 0 and pinning the diamonds to
       the top edge while the line (positioned off the full padded box) sits
       20px+ lower — reads as the diamonds floating above the line. */
    margin-bottom: 40px;
}
.spk-sessions-divider::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100vw;
    height: 1px;
    transform: translate(-50%, -50%);
    background: var(--hr-yellow-400);
}
.spk-sessions-divider-cluster { position: relative; z-index: 1; display: flex; gap: 2px; flex-shrink: 0; }
.spk-sessions-divider-cluster .smt-hero-diamond {
    width: 14px;
    height: 14px;
    transform: rotate(45deg);
    background: #f3d9b0;
    flex-shrink: 0;
}

/* ---------- Talks by {Speaker} ---------- */
/* Rebuilt to match the "Talks by Sara" mockup: one larger featured card (the
   speaker's most recent BilAraby Talk, with a duotone thumbnail on a brand-
   purple base) plus the remaining talks as narrow, solid-colour "spine" cards
   with bottom-to-top rotated titles — cycling green / blue / orange. This
   rail is a separate section from "Sessions at the Gathering" above (a talk
   can appear in both if it's also given a date/time/location as a session).
   Every card opens the shared #spkTalkVideoModal instead of navigating away. */
.spk-talks {
    position: relative;
    padding: 60px 160px 80px;
}
.spk-talks-inner {
    max-width: 1600px;
    margin-inline: auto;
}
.spk-talks-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    margin-bottom: 40px;
}
.spk-talks-heading h2 {
    font-size: 40px;
    line-height: 48px;
    font-weight: 700;
    color: var(--hr-brown-500);
    margin: 0 0 8px;
}
.spk-accent-yellow { color: var(--hr-yellow-500); }
.spk-talks-heading p {
    font-size: 18px;
    line-height: 26px;
    color: var(--hr-brown-300);
    margin: 0;
    max-width: 560px;
}
/* Same frosted-glass recipe as .spk-session-card, just on a pill — a flat
   opaque fill here read as a plain button rather than matching the glass
   look used for every other surface on this page. */
.spk-talks-viewall {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    padding: 14px 24px;
    border-radius: 999px;
    border: 1px solid #fff;
    background: linear-gradient(to top, rgba(255,255,255,.45) 0%, rgba(255,255,255,.6) 76%, rgba(255,255,255,.6) 100%);
    -webkit-backdrop-filter: blur(53px);
    backdrop-filter: blur(53px);
    color: var(--hr-brown-700);
    font-size: 16px;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
    box-shadow: 0 3px 3px rgba(0,0,0,.03), 1px 10px 5px rgba(0,0,0,.03), 2px 23px 7px rgba(0,0,0,.02);
    transition: box-shadow .2s ease;
}
.spk-talks-viewall:hover {
    box-shadow: 0 6px 12px rgba(0, 0, 0, .1);
    color: var(--hr-brown-700);
    text-decoration: none;
}

/* A horizontally-scrollable rail rather than a wrapping grid — the spine
   cards' rotated text and fixed width don't reflow sensibly, so narrow
   viewports scroll the row instead (see the mobile override below). */
.spk-talks-row {
    display: flex;
    align-items: stretch;
    gap: 20px;
    height: 420px;
    overflow-x: auto;
    scrollbar-width: none;
}
.spk-talks-row::-webkit-scrollbar { display: none; }

.spk-talk-card {
    position: relative;
    flex-shrink: 0;
    border: none;
    padding: 0;
    margin: 0;
    background: none;
    border-radius: 24px;
    overflow: hidden;
    cursor: pointer;
    box-shadow: 0 3px 3px rgba(0,0,0,.05), 1px 10px 5px rgba(0,0,0,.03);
    transition: box-shadow .2s ease, transform .2s ease;
}
.spk-talk-card:hover,
.spk-talk-card:focus-visible {
    box-shadow: 0 6px 10px rgba(0,0,0,.08), 1px 14px 10px rgba(0,0,0,.05);
    transform: translateY(-2px);
}

.spk-talk-title {
    display: block;
    font-weight: 700;
    color: #fff;
    line-height: 1.3;
}
.spk-talk-category {
    display: block;
    font-size: 14px;
    font-weight: 500;
    color: rgba(255, 255, 255, .72);
}
.spk-talk-duration {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
    padding: 4px 10px;
    border-radius: 999px;
    background: rgba(0, 0, 0, .35);
    font-size: 13px;
    font-weight: 600;
    color: #fff;
}
.spk-talk-play {
    flex-shrink: 0;
    width: 48px;
    height: 48px;
    border-radius: 61px;
    border: 1.5px solid rgba(255, 255, 255, .8);
    background: rgba(255, 255, 255, .15);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color .2s ease;
}
.spk-talk-card:hover .spk-talk-play,
.spk-talk-card:focus-visible .spk-talk-play { background: rgba(255, 255, 255, .3); }

/* Featured card — first talk, wide, duotone thumbnail on brand purple. */
.spk-talk-featured {
    flex: 1 1 480px;
    min-width: 320px;
    background-color: #8e3b78;
}
.spk-talk-featured-photo {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    filter: grayscale(1) contrast(1.05);
    mix-blend-mode: luminosity;
    opacity: .9;
}
.spk-talk-featured-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(0deg, rgba(20, 8, 17, .7) 0%, rgba(20, 8, 17, .15) 45%, rgba(20, 8, 17, 0) 65%);
}
/* Decorative triangle + diamond in the corner, echoing the diamond motif used
   for session cards (#8e3b78 brand purple) elsewhere on this page — drawn in
   CSS since the mockup's exact vector shapes aren't available as an asset. */
.spk-talk-featured-pattern {
    position: absolute;
    top: 0;
    inset-inline-start: 0;
    width: 220px;
    height: 220px;
    pointer-events: none;
}
.spk-talk-featured-pattern::before {
    content: "";
    position: absolute;
    top: 0;
    inset-inline-start: 0;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 220px 170px 0;
    border-color: transparent rgba(255, 255, 255, .12) transparent transparent;
}
[dir="rtl"] .spk-talk-featured-pattern::before { transform: scaleX(-1); }
.spk-talk-featured-pattern::after {
    content: "";
    position: absolute;
    top: 128px;
    inset-inline-start: 54px;
    width: 18px;
    height: 18px;
    background: rgba(255, 255, 255, .32);
    transform: rotate(45deg);
    box-shadow: 11px 11px 0 -3px rgba(255, 255, 255, .18);
}
.spk-talk-featured-body {
    position: absolute;
    inset-inline-start: 0;
    bottom: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    max-width: 70%;
    padding: 28px 32px;
}
.spk-talk-featured-body .spk-talk-title { font-size: 26px; line-height: 34px; }
.spk-talk-play {
    z-index: 1;
}
.spk-talk-featured > .spk-talk-play {
    position: absolute;
    inset-inline-end: 24px;
    bottom: 24px;
    width: 56px;
    height: 56px;
}

/* Spine cards — remaining talks, narrow, solid colour, rotated text. */
/* Absolutely-positioned (not flex-distributed) on purpose: a flex column
   here left the title/category block's size dependent on flex-grow
   resolution, which combined with the rotated writing-mode and long titles
   could push the body and play button out of their intended stacking order.
   Pinning both to fixed offsets makes the layout deterministic regardless of
   title length or viewport width. */
.spk-talk-bar {
    flex: 0 0 128px;
}
.spk-talk-bar-green { background: var(--hr-green-400); }
.spk-talk-bar-blue { background: var(--hr-blue-400); }
.spk-talk-bar-orange { background: var(--hr-yellow-500); }
.spk-talk-bar-body {
    position: absolute;
    inset-inline: 0;
    top: 24px;
    bottom: 88px; /* clears the play button (48px) + its margin (16px) + 24px gap */
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
/* Vertical "spine" text — two genuinely separate lines (title, then
   category), stacked with a completely ORDINARY vertical flex column. That
   outer stacking never touches writing-mode, so there's no block/inline
   axis to split it into side-by-side columns — the bug every earlier
   attempt kept running into. Instead, EACH span gets its OWN
   writing-mode:vertical-rl, independently, to turn just that one line's
   characters sideways. Since a vertical-rl context here only ever holds a
   single run of text, there's nothing for it to split — title stays the
   top line, category stays the bottom line, always, regardless of length
   or locale. */
/* ROW, not column: Figma puts the two vertical runs SIDE BY SIDE — bold title
   with the category alongside it — whereas stacking them in a column put the
   category below the title, reading as one long broken line. Flex order gives
   title-then-category, which lands the title on the leading side as designed
   (the per-span rotation below doesn't affect flex ordering). */
.spk-talk-bar-text {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 8px;
    max-height: 100%;
}
.spk-talk-bar-text .spk-talk-title,
.spk-talk-bar-text .spk-talk-category {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* Was a fixed 200px/100px, which ellipsised any title longer than that —
       "Interview — On Belonging" needs 216px. Each run may now use the full
       height of .spk-talk-bar-body, which is already bounded and clipped. */
    max-height: 100%;
}
.spk-talk-bar-text .spk-talk-category { font-size: 13px; }
.spk-talk-bar-text .spk-talk-title { font-size: 18px; }
.spk-talk-bar > .spk-talk-play {
    position: absolute;
    inset-inline-start: 50%;
    bottom: 24px;
    transform: translateX(-50%);
}

/* ---------- Talk video popup ---------- */
.spk-talk-modal .modal-dialog { max-width: 900px; }
.spk-talk-modal .modal-content {
    border: none;
    border-radius: 16px;
    overflow: hidden;
    background: #000;
}
/* This app's Bootstrap CSS is a hand-trimmed build that doesn't include the
   `.ratio`/`.ratio-16x9` utility — using it here left the iframe at the
   browser's 300x150 default inside a big black box (looked like the modal
   was just "blocking" the page with no video). Size it explicitly instead. */
.spk-talk-modal-video {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #000;
}
.spk-talk-modal-video iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}
.spk-talk-modal-close {
    position: absolute;
    top: -40px;
    inset-inline-end: 0;
    filter: invert(1);
    z-index: 5;
}

@media (max-width: 1199.98px) {
    .spk-hero, .spk-listing, .spk-profile, .spk-sessions, .spk-talks { padding-inline: 40px; }
    .speakers-revamp { --spk-hero-h: 200px; }
}
@media (max-width: 991.98px) {
    .spk-profile { padding-top: 60px; }
    .spk-profile-inner { grid-template-columns: 1fr; gap: 32px; }
    .spk-profile-copy h1 { font-size: 36px; line-height: 48px; }
    .spk-profile-bio { margin-top: 24px; font-size: 18px; line-height: 28px; }
    .spk-sessions-inner h2 { font-size: 30px; line-height: 40px; }
    .spk-session-card { gap: 20px; padding: 20px; }
    .spk-session-body h3 { font-size: 20px; line-height: 28px; }
    .spk-session-meta-item { font-size: 16px; }
    .spk-sessions-divider { margin-top: 48px; }
    .spk-talks-heading h2 { font-size: 30px; line-height: 40px; }
    /* The cards themselves (row height, featured card, spine bars) stay at
       full/wide desktop size on every breakpoint — same "no shrinking"
       treatment as the home page stat cards. Narrow viewports scroll the
       row horizontally (see .spk-talks-row's overflow-x) instead. */
}
@media (max-width: 767.98px) {
    .spk-hero, .spk-listing, .spk-profile, .spk-sessions, .spk-talks { padding-inline: 16px; }
    .speakers-revamp { --spk-hero-h: 160px; }
    /* The desktop 100px breathing room above the h1 costs too much of a phone's
       first screen — back to the tighter 64px here. */
    .spk-listing { padding-top: 64px; }

    /* ---------- Filters ---------- */
    /* Search on its own full-width row, then All/Gatherings/Events/Year/Country
       as ONE horizontally-scrolling line, matching the events listing (BIL-906:
       every listing page has to run its filters the same way, and this page was
       wrapping them into a stack). .spk-filter-row is the scroller;
       .spk-filters-fields collapses into it so the two selects share that
       scrolling line with the tabs instead of forming a second flex row inside
       it.
       nowrap matters here: the base rule wraps, and in a WRAPPING column
       container a flex line takes its cross size from its widest item, so the
       scrolling row would size itself to its own content width instead of
       stretching to the phone column. 10px is the gap the events row uses
       between its search field and its pill row; the 40px bottom margin is
       inherited from the base rule unchanged. */
    .spk-filters { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 10px; }
    /* The search box is last in the DOM so the desktop row keeps it at the end;
       order pulls it above the scroller here without a second markup order. */
    .spk-search { order: -1; padding: 12px 16px; }
    /* The desktop input is a fixed 180px sitting inside a shrink-to-fit pill. On
       a full-width row that leaves dead space to the right of the caret, so it
       grows into the row instead (min-width:0 lets it shrink back under 180 on a
       320px screen rather than pushing the pill past the viewport). */
    .spk-search input { flex: 1 1 auto; min-width: 0; font-size: 14px; }
    .spk-filter-row {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
        gap: 8px;
        overflow-x: auto;
        /* The row is meant to run past the edge, so the bar would only add noise
           on the platforms that draw a persistent one. */
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    .spk-filter-row::-webkit-scrollbar { display: none; }
    .spk-filters-fields { display: contents; }
    /* margin-inline-end back to 0: the desktop rule's `auto` would push the two
       selects to the far end of the scroll content whenever the five pills
       happen to be narrower than the viewport. */
    .spk-filters-tabs { flex: none; gap: 8px; margin-inline-end: 0; }
    /* Scoped to the filter row on purpose: .spk-tab is also the year pill in
       .spk-sessions-tabs on the speaker DETAIL page, which is a plain wrapping
       row and must keep its full 16/20 sizing. flex:none stops the pills being
       squeezed to fit — the row is meant to overflow and scroll. */
    .spk-filters-tabs .spk-tab { flex: none; padding: 12px 16px; font-size: 14px; line-height: 20px; }
    /* A fixed width, because a bare <select> is sized by its widest OPTION: a
       long country name ("United Arab Emirates") would otherwise blow the pill
       out in a row that no longer has a container width to hold it in check.
       162px is the longer of the two labels ("Select Country", ~106px at 14px)
       inside the 16/40 padding, which keeps the pair a matched set. */
    .spk-select {
        flex: none;
        width: 162px;
        /* The width is fixed, so a long selected value ("United Arab Emirates")
           has to be trimmed rather than clipped mid-glyph - the same treatment
           .evt-select carries on the events row. */
        text-overflow: ellipsis;
        white-space: nowrap;
        overflow: hidden;
        padding: 12px 40px 12px 16px;
        font-size: 14px;
        line-height: 20px;
        background-position: right 16px center;
    }
    /* Restates the swap at the phone's figures. The base [dir="rtl"] .spk-select
       outranks the LTR rule above it (0,2,0 against 0,1,0), so without this
       Arabic would keep the desktop 20/40 padding and a 20px caret offset while
       every other pill in the row had stepped down to 16. */
    [dir="rtl"] .spk-select { padding: 12px 16px 12px 40px; background-position: left 16px center; }
}
