/* ==========================================================================
   Memories & Stories listing page (Figma: QF - BilAraby - WebsiteDesign-Concept-2,
   node 40001286:70408 "Memories & Stories"). Reuses the --hr-* tokens declared
   globally in layout-revamp.css.

   Content is an aggregate of every Annual Gathering (Summit)'s event photo/
   video collections — not its own admin-managed model. See
   MemoriesStoriesController.

   NOTE: .mns-hero reproduces the same "Innerpage-hero" component as About Us
   (.abt-hero in about-revamp.css) — the painted teal banner, the two corner
   wedges and the breadcrumb row are all that page's rules verbatim, so the
   two "About >" pages open identically. This replaced a hand-built
   linear-gradient wash that ended in a hard edge partway down the band and
   painted over the decorative wedges.
   Prefix: .mns-
   ========================================================================== */
.memories-stories-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. Both
       the active filter tab and a hovered inactive one wear it, so they must
       not drift apart. Same value as --blg-pill-shadow / --vid-pill-shadow /
       --evt-pill-shadow, whose filter rows this page's is the twin of; Figma's
       ramp opens with two layers at alpha 0 (7px 63px 18px and 4px 40px 16px)
       which paint nothing, so they are documented, not emitted. */
    --mns-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);
    font-family: 'Almarai', 'Helvetica Neue', Arial, sans-serif;
}
.memories-stories-revamp .hr-accent { color: var(--hr-yellow-400); }

/* Teal banner spanning the breadcrumb hero and fading out below it — the same
   Figma "Innerpage-hero" fill About Us paints (about-revamp/hero-banner.svg),
   shared rather than re-exported so the two pages cannot drift apart.

   424px is the asset's own box: the teal sits at 89% and has faded to 0 by
   ~347px of it, so the paint dies out inside the content section below the
   256px hero instead of stopping at the band's edge. That fade is why this is
   a page-root background and not a background on .mns-hero — and why .mns-hero
   itself must stay transparent, or it would cover the wedges above it.
   preserveAspectRatio="none" on the asset stretches it to the viewport. */
.memories-stories-revamp {
    position: relative;
    background: var(--hr-cream-500) var(--mns-hero-bg) no-repeat top center;
    background-size: 100% 424px;
}
/* Figma's 402px frame paints the same banner into a 302px box over a 173px
   hero (node I40005308:76899;40004531:62357) — a taller fade relative to the
   band than the desktop 424/256, which is what keeps the teal alive behind the
   centred title below. Scaling the desktop 424px down by the band ratio would
   land at 265px and die out too early. */
@media (max-width: 767.98px) {
    .memories-stories-revamp { background-size: 100% 302px; }
}

/* Figma's angular corner wedges inside the Innerpage-hero instance: two
   DISTINCT vectors, "Pattern-01" (left, 305.329x160.658) and "Pattern-02"
   (right, 305.29x204.731, mix-blend-mode: overlay), each carrying its own
   cream(#f9f7ea)-to-transparent gradient at 10% fill-opacity baked into the
   asset. Previously this rendered one shared flourish (the press-releases
   hero-decor-shape) mirrored across both sides, which is a different shape
   entirely — and it sat *under* the hero's own gradient background, so
   neither copy was actually visible.

   Both are anchored to the decor box's bottom edge — Pattern-01's own
   y=95.03 + 160.658 lands on 255.69, i.e. flush with the 256px band — so
   they stay correctly placed when the band shortens at the tablet/mobile
   breakpoints and get clipped from the top rather than drifting off the
   baseline.

   The slight blur softens the vector edges to match how the wedges read in
   Figma's own render, where the 10% gradient dissolves into the teal rather
   than showing a hard diagonal. Same rules as .abt-hero-decor. */
.mns-hero-decor {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 256px;
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
}
.mns-hero-decor img {
    position: absolute;
    bottom: 0;
    max-width: none;
    filter: blur(1.5px);
}
.mns-hero-decor-left {
    left: 0;
    width: 305.329px;
    height: 160.658px;
}
.mns-hero-decor-right {
    right: 0;
    width: 305.29px;
    height: 204.731px;
    mix-blend-mode: overlay;
}
/* RTL keeps each pattern on its own visual side by flipping the pair, so the
   composition mirrors with the text direction instead of the taller wedge
   always sitting on the right. */
[dir="rtl"] .mns-hero-decor-left { left: auto; right: 0; transform: scaleX(-1); }
[dir="rtl"] .mns-hero-decor-right { right: auto; left: 0; transform: scaleX(-1); }
/* Phone variant, hidden until its breakpoint: Figma's 402px frame draws the
   pair as ONE full-bleed 402x134.328 export ("Intersect") whose two halves
   meet across the middle, not the desktop corner vectors shrunk. The asset
   carries preserveAspectRatio="none" and its own mix-blend-mode:overlay
   group, so it stretches to any phone width and needs no blur — the export is
   already soft at this size. Symmetrical about its centre, so RTL needs no
   flip. */
.mns-hero-decor-mobile { display: none; }
@media (max-width: 1199.98px) { .mns-hero-decor { height: 200px; } }
@media (max-width: 767.98px) {
    /* 173px, not 160px: Figma's phone band (node 40005308:76899). */
    .mns-hero-decor { height: 173px; }
    .mns-hero-decor-left,
    .mns-hero-decor-right { display: none; }
    .mns-hero-decor-mobile {
        display: block;
        left: 0;
        width: 100%;
        height: 134.328px;
        filter: none;
        /* Restated in CSS even though the export's own <g> declares it: a
           blend mode inside an SVG composites against that image's own
           backdrop, which is empty, so it never reaches the teal underneath.
           Only the element-level blend does. */
        mix-blend-mode: overlay;
    }
}

/* ---------- Hero / breadcrumb ---------- */
/* No background of its own: the teal comes from the page-root paint above, so
   the hero is a transparent 256px box that only positions the breadcrumb row
   against the band's bottom edge. Fixed height rather than min-height +
   padding-top, so the band measures exactly the same as About Us at every
   breakpoint. */
.mns-hero {
    position: relative;
    height: 256px;
    display: flex;
    align-items: flex-end;
    padding: 0 160px 24px;
}
.mns-hero-inner {
    position: relative;
    z-index: 1;
    max-width: 1600px;
    width: 100%;
    margin-inline: auto;
}
.mns-breadcrumb-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
}
/* Typography is Figma's two named breadcrumb styles verbatim:
   "Navigation/Nav Item/Regular" (Almarai 400, 20/28, letter-spacing 0) for
   the trail and "Navigation/Nav Item Active/Bold" (the same at 700) for the
   current crumb. line-height and font-weight were both left to inherit
   before, so the row picked up the ambient body leading and whatever weight
   the anchor reset applied rather than the 28px/400 the style specifies.

   All three crumbs are painted at FULL #f9f7ea and separated by weight alone
   — there is no resting opacity on the trail, so hover shifts the underline
   only. */
.mns-breadcrumb {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 20px;
    font-weight: 400;
    line-height: 28px;
    letter-spacing: 0;
    color: #f9f7ea;
    text-transform: uppercase;
}
.mns-breadcrumb a {
    color: inherit;
    font-weight: inherit;
    text-decoration: none;
}
.mns-breadcrumb a:hover { color: inherit; text-decoration: underline; }
.mns-breadcrumb-current { font-weight: 700; }
.mns-breadcrumb-sep {
    width: 1px;
    height: 16px;
    background: rgba(249, 247, 234, .5);
}
/* 20px with its own 4.142px slot margin (tip-to-tip), matching .abt-diamond. */
.mns-hero-diamond { width: 20px; height: 20px; margin-inline: 4.142px; transform: rotate(45deg); background: var(--hr-cream-500); flex-shrink: 0; }
.mns-hero-divider { display: none; }
@media (min-width: 1200px) {
    /* 300px wide and bled out through the hero's own 160px gutter (plus any
       margin beyond the 1920px design width), so the rule runs to the
       viewport edge exactly as it does on About Us. */
    .mns-hero-divider {
        display: flex;
        align-items: center;
        flex-shrink: 0;
        width: 300px;
        margin-inline-end: calc(-160px - max(0px, (100vw - 1920px) / 2));
    }
    .mns-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;
    }
}
.mns-hero::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 1px;
    background: rgba(249, 247, 234, .35);
}
/* The band steps down with .mns-hero-decor at the same two breakpoints About
   Us uses, so the wedges stay flush with the bottom edge. Kept next to the
   hero rather than in a trailing responsive block: the gutter, the height and
   the decor box all have to move together. */
@media (max-width: 1199.98px) {
    .mns-hero { height: 200px; padding-inline: 40px; }
}
@media (max-width: 767.98px) {
    /* Figma's 402px frame: a 173px band with 24px gutters (its Navbar and
       Breadcrumb both sit in a 355px column inside 402px). The content section
       below keeps its own narrower 20px gutter, which is what the design does
       too. */
    .mns-hero { height: 173px; padding-inline: 24px; }
}

/* ---------- Content shell ---------- */
.mns-content { position: relative; padding: 120px 160px 80px; overflow: hidden; }
@media (max-width: 1399.98px) { .mns-content { padding: 100px 40px 64px; } }
/* 60px top AND bottom with a 20px gutter, per Figma's phone frame (node
   40005308:76900, px-20 py-60) — the bottom was 48px, so the Load More button
   sat closer to the footer than the title does to the hero. */
@media (max-width: 767.98px) { .mns-content { padding: 60px 20px; } }
/* No gradient continuation pseudo here any more. It existed to carry the old
   hand-built hero wash down into this section, but the hero is now the About
   Us painted banner, whose asset is 424px tall and already fades to nothing
   ~168px into this section. Keeping both stacked a second teal ramp on top of
   the first, which read as a hard darker band right below the hero rule —
   exactly the seam the pseudo was meant to avoid. --mns-sage-100 was its only
   consumer and is gone with it. */
.mns-content-inner { position: relative; z-index: 1; max-width: 1600px; margin-inline: auto; display: flex; flex-direction: column; gap: 80px; }
/* 32px between the three stacks (head / filters / grid) on a phone, per
   Figma's phone frame. The desktop 80px left a dead band roughly the height of
   the title between the description and the search field. */
@media (max-width: 767.98px) { .mns-content-inner { gap: 32px; } }

.mns-head { display: flex; flex-direction: column; gap: 16px; }
.mns-head h1 { font-size: 64px; line-height: 1.125; font-weight: 700; color: var(--hr-brown-500); margin: 0; }
.mns-head p { font-size: 24px; line-height: 1.35; color: var(--hr-brown-300); margin: 0; }
@media (max-width: 1399.98px) { .mns-head h1 { font-size: 44px; } }
/* Figma's phone frame centres this pair and drops both a step down the type
   ramp — title Headings/H5/Bold 32/40, description Body/Body XSmall/Regular
   16/24 (nodes 40005308:76902 / :76904) — where the desktop pair is
   left-aligned at 64/72 and 24/32. The 24px stack gap is the design's too;
   16px was carried over from desktop. The h1 also needs its line-height
   restated: the base rule's unitless 1.125 computes to 36px at this size, not
   the 40px the named style specifies. */
@media (max-width: 767.98px) {
    .mns-head { gap: 24px; text-align: center; }
    .mns-head h1 { font-size: 32px; line-height: 40px; }
    .mns-head p { font-size: 16px; line-height: 24px; }
}

/* ---------- Filters ----------
   This row is the twin of the Blogs listing's (.blg-filters in
   blogs-revamp.css): same pill geometry, same shadow token, same hover, same
   date pill, same two responsive steps. It had drifted — no hover state at
   all, a single-layer active shadow, 50px tabs against 48px fields, and a sort
   pill Blogs does not carry — so the rules below track that page deliberately.
   Change one, change both.

   flex-start, not space-between: .mns-tabs' auto end-margin below is what
   holds the date pill and the search box at the end of the row, and an auto
   margin neutralises justify-content on the line it sits on — so on the ONE
   line case the two spellings are identical. They stop being identical the
   moment the row wraps, which it does as soon as a few years are in the tab
   list (that list is DB-driven): the tabs take line one, and line two holds
   .mns-fields and .mns-search with no auto margin between them, where
   space-between drove them to opposite ends of the row. */
.mns-filters { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 16px; }
/* Inert above the phone breakpoint: the wrapper exists only so the tabs and the
   date pill can scroll as one row down there (see the <=767.98 block), and
   display:contents leaves this row the same flat flex it has always been. */
.mns-filter-row { display: contents; }
/* The auto end-margin absorbs the row's free space, which is what keeps the
   date pill and the search box grouped together at the end of it.
   justify-content did that on its own while .mns-filters had exactly two
   children; the search box is now a third, having moved out of .mns-fields so it
   can sit on its own row on a phone. */
.mns-tabs { display: flex; gap: 16px; flex-wrap: wrap; margin-inline-end: auto; }
.mns-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 — which is also what .mns-field measures, so the tabs and the
       date/search pills sit level in the same row. At 12px with no line-height
       these stood 50px and the row was 2px out of true. Same correction
       .blg-tab / .vid-tab / .srp-tab carry. */
    padding: 11px 20px;
    border-radius: 61px;
    font-size: 16px;
    font-weight: 400;
    line-height: 24px;
    color: var(--hr-brown-500);
    background: rgba(236, 230, 211, .4);
    border: 1px solid rgba(177, 175, 165, .5);
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    /* Named longhands rather than a bare `all`: these are <button>s and app.css
       carries blanket transitions, so an `all` here would animate colour and
       layout along with the fill. */
    transition: background-color .2s ease, border-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
/* 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 Blogs
   (.blg-tab), Videos (.vid-tab) and Events (.evt-tab) rows answer the cursor.
   Scoped off .is-active: that one is already at the destination and isn't a
   target, so it shouldn't move. */
.mns-tab:not(.is-active):hover {
    background: var(--hr-cream-50, #fefefd);
    border-color: #fff;
    box-shadow: var(--mns-pill-shadow);
    transform: translateY(-2px);
}
/* Weight stays 400: the design separates the active pill by fill, border and
   shadow alone. The 700 this carried also re-flowed the whole row on every tab
   change, a bold label being wider than the regular one — the same reason
   .blg-tab.is-active and .vid-tab.is-active dropped it. The shadow is the full
   stack, not the single `0 3px 6px` layer it had, so all these rows read
   alike. */
.mns-tab.is-active {
    background: var(--hr-cream-50, #fefefd);
    border-color: #fff;
    box-shadow: var(--mns-pill-shadow);
}
.mns-fields { display: flex; gap: 16px; flex-wrap: wrap; align-items: center; }
/* The shared 48px pill worn by both the date filter and the search box, so the
   two can never drift out of line with each other or with the tabs. Mirrors
   .blg-field; the two page-specific classes below add only what differs. */
.mns-field {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 48px;
    padding: 0 20px;
    border-radius: 61px;
    background: rgba(236, 230, 211, .4);
    border: 1px solid rgba(177, 175, 165, .5);
    font-size: 16px;
    line-height: 24px;
    color: var(--hr-brown-500);
}
/* No opacity here: the icons in this row are stroked brown-500 glyphs, the same
   colour as the labels beside them, so a .7 would only grey them out against
   their own text. */
.mns-field img { flex-shrink: 0; }
.mns-field input {
    border: 0;
    background: none;
    outline: none;
    font-size: 16px;
    color: var(--hr-brown-500);
    font-family: inherit;
}
.mns-field input::placeholder { color: var(--hr-brown-500); opacity: 1; }
/* app.css has a sitewide, unscoped `input:-webkit-autofill` rule that paints a
   solid green inset behind autofilled text on EVERY input. Overridden here the
   same way blogs-revamp.css and events-revamp.css do it. */
.mns-field input:-webkit-autofill,
.mns-field input:-webkit-autofill:hover,
.mns-field input:-webkit-autofill:focus,
.mns-field input:-webkit-autofill:active {
    -webkit-text-fill-color: var(--hr-brown-500) !important;
    box-shadow: 0 0 0 1000px transparent inset !important;
    -webkit-box-shadow: 0 0 0 1000px transparent inset !important;
    transition: background-color 5000s ease-in-out 0s !important;
}
/* A 300px cap that it GROWS into, rather than a width sized by the input's
   200px floor: on a line with room the box reaches the same 300 the Blogs and
   Events listings hold. max-width is what keeps flex-grow from eating the free
   space .mns-tabs' auto end-margin needs — grow resolves first, then auto
   margins take whatever is left. */
.mns-search { flex: 1 1 auto; max-width: 300px; min-width: 0; }
.mns-search input { flex: 1 1 auto; min-width: 200px; }

/* ---- Date pill --------------------------------------------------------
   A native <input type="date"> paints its own "dd/mm/yyyy" hint while empty:
   the wrong string (no other filter on the site shows a format mask), in the
   UA's own styling, and unreachable by __() so it never localises. So the pill
   renders its OWN label — "Select Date", or the picked date formatted by the
   script below — and the real input is laid over the whole pill at opacity 0 to
   catch the click and open the native picker.

   Exactly the pattern .blg-date and .pr-date-wrap use; the three are kept in
   step. */
.mns-date {
    position: relative;
    /* 16px trailing against the base 20px: the icon/clear glyph is 16px wide and
       sits closer to the edge than a text label would. */
    padding-inline: 20px 16px;
    cursor: pointer;
    white-space: nowrap;
}
.mns-date-icon { flex-shrink: 0; pointer-events: none; }
/* Once a date is picked this is an APPLIED filter, and the design marks one.
   Empty, it stays the translucent resting pill so "Select Date" reads as the
   invitation it is.

   No drop shadow, unlike the tabs' active pill: the field pills sit beside each
   other here, and a shadow on only the applied one puts a soft halo below it
   that reads as extra HEIGHT against its flat neighbour — the row looks unequal
   even though both measure exactly 48px. Fill, rim and weight mark the state on
   their own. Same call .blg-date.has-value documents. */
.mns-date.has-value {
    background-color: var(--hr-cream-50, #fefefd);
    border-color: #fff;
}
.mns-date.has-value .mns-date-label { font-weight: 700; }
/* Takes the calendar icon's spot once a date is picked. Needs its own stacking
   context (position + z-index) to actually receive the click: .mns-date-input
   covers the whole pill, so without this the invisible input would swallow
   it. */
.mns-date-clear {
    position: relative;
    z-index: 1;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    line-height: 1;
    font-size: 18px;
    color: var(--hr-brown-300);
    text-decoration: none;
}
.mns-date-clear:hover { color: var(--hr-brown-500); text-decoration: none; }
/* Both the clear link and the icon are always in the DOM with .is-hidden
   deciding which shows, so an AJAX results refresh can swap them without this
   row being re-rendered (see memories_stories/index). */
.mns-date-clear.is-hidden,
.mns-date-icon.is-hidden { display: none; }
.mns-date-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    opacity: 0;
    cursor: pointer;
    appearance: none;
}
/* Stretched over the pill so a click anywhere on it opens the picker, not just
   on Chrome's own little calendar button. */
.mns-date-input::-webkit-calendar-picker-indicator { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }

/* ---- Laptop / small-desktop step --------------------------------------
   Tightens the gaps and the pill padding between the phone scroller and the
   full desktop row, so the tabs, the date pill and the search box stay on one
   line for longer before wrapping. The thresholds move with the year list,
   which is DB-driven. Mirrors the same block in blogs-revamp.css. */
@media (min-width: 768px) and (max-width: 1599.98px) {
    .mns-filters,
    .mns-tabs,
    .mns-fields { gap: 10px; }
    .mns-tab { padding-inline: 12px; }
    /* .mns-field before .mns-date: the date pill restates its own asymmetric
       values, and at equal specificity the later rule wins. */
    .mns-field { padding-inline: 12px; }
    .mns-date { padding-inline: 12px 10px; }
    /* 120px comfortably clears the "Search" hint, so the box compresses without
       its own label being cut — it just stops being the item that forces the
       break. flex-grow off with it: at these widths the slack on the line
       belongs to .mns-tabs' auto end-margin, and grow resolves first. */
    .mns-search { flex-grow: 0; }
    .mns-search input { min-width: 120px; }
}
/* Search on its own full-width row, then All/2024/2023/.../Photos/Videos plus
   the date and sort pills as ONE horizontally-scrolling line — the same shape
   the Events listing already ships (BIL-906: the filter row has to read the
   same on every listing page instead of wrapping differently on each).
   .mns-filter-row is the scroller; .mns-fields collapses into it so the date
   and sort pills share that scrolling line with the tabs instead of forming a
   second flex row inside it. Replaces the two wrapping blocks this used to
   stack, which on a 375px phone ran to four or five ragged rows once a few
   years were in the tab list. */
@media (max-width: 767.98px) {
    /* 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 below would size itself to its own content width instead of
       stretching to the column and would never scroll. */
    /* 12px between the search field and the pill row, per this page's own
       phone frame (node 40005308:76907) — it was 10px, borrowed from the
       Events artboard before this frame existed. */
    .mns-filters { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 12px; }
    /* order, not DOM order: the search box has to stay last in the markup so
       the desktop row still groups it with the date pill at the end.
       flex:none resets the desktop `flex: 1 1 auto` — .mns-filters is
       flex-direction:column down here, so a main-axis grow would stretch this
       pill's HEIGHT rather than its width. Full width comes from the
       container's align-items:stretch instead, and max-width goes with it or
       the 300px cap would hold the box short of the column. */
    .mns-search { order: -1; flex: none; max-width: none; }
    /* Releases the 200px min-width the input holds on desktop so it can fill
       the full-width row instead of forcing the pill wider than the viewport. */
    .mns-search input { flex: 1 1 auto; min-width: 0; width: 100%; }
    .mns-filter-row {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
        gap: 8px;
        overflow-x: auto;
        /* Room for the active pill's shadow inside the scroll box, cancelled
           again on the outside so the layout does not move. `overflow-x: auto`
           makes overflow-y compute to auto as well, so this box clips
           vertically too and was slicing the shadow off flat along its bottom
           edge. Same clearance .vid-filters / .tlk-filters / .evt-filter-row
           carry. */
        padding-block: 8px 40px;
        margin-block: -8px -40px;
        /* 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;
    }
    .mns-filter-row::-webkit-scrollbar { display: none; }
    .mns-fields { display: contents; }
    /* margin-inline-end back to 0: the desktop rule's `auto` would push the
       date pill to the far end of the scroll content whenever the tabs happen
       to be narrower than the viewport. nowrap for the same reason the
       container needs it — a wrapped tab would start a second line inside the
       scroller. */
    .mns-tabs { flex: none; flex-wrap: nowrap; gap: 8px; margin-inline-end: 0; }
    /* flex:none on every pill in the row: it is meant to overflow and scroll,
       not to squeeze its controls down until they fit the viewport. */
    .mns-tab { flex: none; padding: 12px 16px; font-size: 14px; line-height: 20px; }
    /* 46px = the .mns-tab pill's 12 + 20 + 12 plus its 1px borders (everything
       is border-box here), so the two pill families line up in the one
       scrolling row; the base 48px was picked against the larger desktop
       type. Same step .blg-field takes. */
    .mns-field { flex: none; height: 46px; padding: 0 16px; font-size: 14px; }
    .mns-field input { font-size: 14px; }
    /* The date pill's own trailing padding, restated because the `padding`
       shorthand on .mns-field just above is later in the file at equal
       specificity and would otherwise take it back to a symmetric 16px. */
    .mns-date { padding-inline: 16px 12px; }

    /* One breadcrumb size site-wide on the phone, taken from the Events
       listing (.evt-breadcrumb in events-revamp.css) and matching
       .abt-breadcrumb's own phone step: 12px type, 8px gaps, a 12px
       separator. This page had no phone step at all. */
    .mns-breadcrumb { font-size: 12px; gap: 8px; }
    .mns-breadcrumb-sep { height: 12px; }
    /* The full three-crumb trail stays on the phone: HOME > ABOUT > MEMORIES &
       STORIES.

       Figma's 402px frame (node I40005308:76899;40004531:62362) does draw only
       two crumbs, and this used to drop the "About" pair to match. Reinstated
       deliberately: this page sits under About in the nav, and About Us — the
       sibling under the same parent, on the same Innerpage-hero component —
       keeps all three of its crumbs at this size (.abt-breadcrumb has no such
       rule). Two pages one click apart were describing their position in the
       site differently. Wrapping below covers the width the design was
       avoiding. */
    .mns-breadcrumb { flex-wrap: wrap; row-gap: 4px; }
    /* Utility/Caption/ExtraBold (Almarai 800) marks the current crumb at this
       size, not the 700 the desktop style uses. Almarai-ExtraBold is
       registered globally in layout-revamp.css, so 800 resolves to the real
       face rather than a synthesised one. */
    .mns-breadcrumb-current { font-weight: 800; }
}

/* ---------- Masonry grid ---------- */
.mns-grid-wrap { position: relative; }
.mns-grid { column-count: 4; column-gap: 32px; }
@media (max-width: 1399.98px) { .mns-grid { column-count: 3; } }
@media (max-width: 991.98px) { .mns-grid { column-count: 2; } }
@media (max-width: 575.98px) { .mns-grid { column-count: 1; } }
/* Figma's phone frame stacks the cards in one column at 32px, with 16px
   between each photo and its caption and the caption a step down the type
   ramp — Labels/Label Small/Regular 18/28 on a 20px inset (nodes
   40005308:76930 through :76937). Desktop runs 24/24/20px-type/24px-inset. */
@media (max-width: 767.98px) {
    .mns-item { margin-bottom: 32px; }
    .mns-caption { margin-top: 16px; padding-inline-start: 20px; font-size: 18px; }
}
.mns-item {
    display: block;
    break-inside: avoid;
    margin-bottom: 24px;
    text-decoration: none;
}
.mns-item:hover { text-decoration: none; }
.mns-media {
    position: relative;
    display: block;
    width: 100%;
    border-radius: 16px;
    background: #fff;
    background-color: var(--hr-cream-600, #e3e1d4);
    overflow: hidden;
    padding: 0;
    border: 0;
    cursor: pointer;
}
/* The cards carry loading="lazy", so the ones below the fold sit empty until
   they scroll in — and an empty card was a flat cream slab, which is what made
   the bottom of the grid read as broken placeholders rather than as content
   still arriving. A slow cream-on-cream sweep says "loading" instead.

   Carried on the <img>'s own background, not a pseudo-element on .mns-media:
   an <img> paints its background until its bitmap arrives and object-fit:cover
   then fills the box completely, so the sweep disappears on load with no JS
   and no z-index juggling against the play badge. It also cannot appear on a
   video card that has no poster at all (there is no <img> to carry it), where
   a pseudo-element would have shimmered forever over the brown fallback. */
.mns-media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    background: linear-gradient(100deg,
        var(--hr-cream-600, #e3e1d4) 30%,
        rgba(255, 255, 255, .6) 50%,
        var(--hr-cream-600, #e3e1d4) 70%) no-repeat;
    background-size: 300% 100%;
    animation: mns-media-shimmer 1.6s ease-in-out infinite;
}
@keyframes mns-media-shimmer {
    from { background-position: 150% 0; }
    to { background-position: -150% 0; }
}
/* The placeholder tone stays, the sweep stops. */
@media (prefers-reduced-motion: reduce) {
    .mns-media img { animation: none; }
}
/* The play glyph is a small transparent PNG-style SVG inside the badge, and
   the badge's own <img> would otherwise inherit the sweep and show it through
   the transparent parts of the triangle. */
.mns-play-badge img,
.mns-multi-badge img { background: none; animation: none; }
/* Figma's masonry rhythm (node 40001286:70408) uses a handful of fixed
   placeholder heights per card — 214.88px / 382px / 477.5px — not organic
   heights derived from each photo's own aspect ratio. Real uploaded photos
   have unpredictable aspect ratios, so without this every card would be a
   different, unbalanced height; cropping any image into one of these three
   fixed boxes (cycled per card in grid.blade.php) reproduces Figma's rhythm
   regardless of what gets uploaded. */
.mns-h-sm { height: 215px; }
.mns-h-md { height: 382px; }
.mns-h-lg { height: 478px; }
.mns-item-video .mns-media { min-height: 160px; }
/* Figma's shared "Button" component, icon-only variant — the same 72x72 glass
   play circle the Videos listing renders (.vid-feature-play / .vid-card-play in
   video-revamp.css). 72px is a 72px frame around a 24px icon slot placed at
   (24,24), i.e. 24px of padding a side.

   This carried a flat `border: 1.5px solid #fff` and no hover at all, so it
   read as a plain amber disc with a hard white ring: none of the gradient rim,
   none of the bottom bloom. The three additions below are what opt it into the
   shared recipe in layout-revamp.css. */
.mns-play-badge {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: inline-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 this
       is now listed in) 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 two vars carry this node's own leading and middle stops (white at
       30%, #65686F at 39%) in place of the .1/.3 defaults, matching the Videos
       play circles exactly. */
    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 bloom's plus-lighter blends against this
       button's amber rather than whatever photo sits behind the card. */
    isolation: isolate;
    /* NOT overflow:hidden: the shared ring sits 1.5px OUTSIDE the padding box,
       so clipping here would eat it (layout-revamp.css records the same trap). */
    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);
}
/* solar:play-bold at its real 19x20 inside the 24px slot — .mns-media img's
   `width: 100%` would otherwise stretch it to fill the whole circle. 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. Replaces video-play-icon.svg, a different play
   glyph cropped tight to 21x24 which rendered the triangle ~10% wider and 20%
   taller than the design's; video-revamp.css made the same correction. */
.mns-play-badge img { width: 19px; height: 20px; transform: translateX(1.5px); }
.mns-multi-badge {
    position: absolute;
    top: 16px;
    inset-inline-end: 16px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 61px;
    background: rgba(27, 25, 12, .55);
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    backdrop-filter: blur(2px);
}
.mns-caption {
    display: block;
    margin-top: 24px;
    padding-inline-start: 24px;
    border-inline-start: 5px solid var(--hr-blue-500);
    font-size: 20px;
    line-height: 28px;
    color: var(--hr-brown-300);
    text-decoration: none;
}
.mns-caption:hover { color: var(--hr-brown-500); text-decoration: underline; }
.mns-accent-blue { border-color: var(--hr-blue-500); }
.mns-accent-purple { border-color: #8e3b78; }
.mns-accent-green { border-color: var(--hr-green-500); }

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

/* ---------- "More behind the button" sliver ----------
   Figma closes the grid with a sliver of the next row peeking out and fading
   into the page, the button riding over it. Ported from the Speakers listing
   (.spk-grid-peek in speakers-revamp.css) — same 112px sliver, same
   .9-to-0 gradient, same half-overlap with the button. Only the grid geometry
   is this page's: a 32px gutter, the 16px card radius, its own column steps,
   and the cream-600 placeholder tone the cards themselves use rather than
   Speakers' neutral #d9d9d9.

   This replaces a backdrop-filter band that was laid over the real bottom row.
   That approach could not work: the band had to hide something to read as a
   fade, and the only thing under it was loaded content — so it blurred real
   photos and sliced the last row's captions in half. A sliver that was never
   content can fade to nothing at no cost, which is exactly why the design (and
   Speakers) does it this way.

   Decorative: aria-hidden in the markup and pointer-events:none here. */
.mns-grid-peek { display: none; }
.mns-grid-wrap.has-more .mns-grid-peek {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    /* Matches .mns-grid's column-gap so the slivers line up under the cards. */
    gap: 32px;
    /* No negative pull-up here, unlike .spk-grid-peek. Speakers pulls up 24px
       into .spk-grid's own 48px bottom margin — dead space. This grid has no
       bottom margin: its box ends on the balanced column height, so the last
       caption of the tallest column sits right at that edge and a -24px pull
       slices straight through it. The 24px each .mns-item already carries
       below itself is the row gap. */
    margin-top: 0;
    pointer-events: none;
}
/* Top corners only — it is the TOP of a card coming into view, so the bottom
   never resolves into a corner; it dissolves instead.

   align-self:start so a negative margin-top actually moves the sliver instead
   of being absorbed by the grid row's stretch. The script sets that margin per
   sliver: `column-count` balances the columns only roughly and each caption
   wraps to its own number of lines, so the columns end at different heights and
   a flat row of slivers left ragged gaps above them. Each one is pulled up to
   sit 24px under ITS OWN column's last card, so the masonry stagger carries on
   through the sliver row (see positionPeek() in index.blade.php).

   The flat row is the no-JS fallback, which is what this rule alone renders. */
.mns-grid-wrap.has-more .mns-grid-peek span {
    align-self: start;
    height: 112px;
    border-radius: 16px 16px 0 0;
    background: linear-gradient(to bottom, rgba(227, 225, 212, .9), rgba(227, 225, 212, 0));
}
/* The button rides over the sliver's faded-out lower half. .mns-content-inner
   is a flex column with an 80px gap, and a negative margin here nets against
   that gap: 80 - 136 = -56px, i.e. half of the 112px sliver. */
.mns-grid-wrap.has-more { margin-bottom: -136px; }
/* One sliver per column — the extras would otherwise wrap onto a stray second
   row once the grid drops below four columns. Steps match .mns-grid's own. */
@media (max-width: 1399.98px) {
    .mns-grid-wrap.has-more .mns-grid-peek { grid-template-columns: repeat(3, 1fr); }
    .mns-grid-wrap.has-more .mns-grid-peek span:nth-child(n+4) { display: none; }
}
@media (max-width: 991.98px) {
    .mns-grid-wrap.has-more .mns-grid-peek { grid-template-columns: repeat(2, 1fr); }
    .mns-grid-wrap.has-more .mns-grid-peek span:nth-child(n+3) { display: none; }
}
/* No sliver on a phone — the design closes the grid with the button alone.
   Down here the button goes full-width, so a single full-width sliver behind it
   read as the button sitting inside a grey box rather than as a card coming
   into view: the cue only works when the sliver is narrower than the row and
   there are several of them staggered. The negative margin goes with it, so the
   button keeps the section's normal 32px stack gap. */
@media (max-width: 767.98px) {
    .mns-grid-wrap.has-more .mns-grid-peek { display: none; }
    .mns-grid-wrap.has-more { margin-bottom: 0; }
}

/* ---------- Load more ---------- */
/* Lifted above .mns-grid-peek, which the negative margin above pulls this row
   up over. The sliver is pointer-events:none, so this is purely paint order —
   without it the sliver's grey would sit on top of the button. */
.mns-load-more-wrap { position: relative; z-index: 1; display: flex; justify-content: center; }
.mns-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 16px 24px;
    border-radius: 61px;
    font-weight: 700;
    font-size: 16px;
    cursor: pointer;
    white-space: nowrap;
    transition: transform .2s ease, box-shadow .2s ease;
}
.mns-btn:hover { transform: translateY(-2px); }
/* Full-width 48px bar on a phone, per Figma's phone frame (node
   40005308:76938): 14px bold type on 24px/14px padding, stretched across the
   column instead of the desktop pill hugging its label. */
@media (max-width: 767.98px) {
    .mns-load-more-wrap .mns-btn {
        width: 100%;
        height: 48px;
        padding: 14px 24px;
        font-size: 14px;
        line-height: 24px;
    }
}
/* Fill, outset rim, inset highlight, the four ambient layers and the hover
   bloom all come from the shared Button/primary registry in layout-revamp.css,
   which .mns-btn-primary is now listed in — the same component as the footer's
   Subscribe, so the two cannot drift. Only the label colour on hover is
   restated here, to stop app.css's anchor/button hover from recolouring it. */
.mns-btn-primary:hover { color: var(--hr-cream-50); }

/* ---------- Lightbox shell (video + photo) ----------
   One dark surface shared by both dialogs. Replaces the legacy .custom-modal
   shell they used to borrow, which is the sign-in popup's design: a
   main-popup.svg wash over near-black and a 180px-inset content column, with
   the media then dropped into a bare white card that had nothing but a close
   button above it.

   Dark rather than the page's cream: the stage is a photo or a video frame, and
   a cream surround throws its own colour back into the image. The header,
   footer and rims are cream-tinted whites so the shell still reads as this
   site's and not as a generic player chrome. */
.mns-modal .modal-dialog {
    max-width: 1000px;
    width: calc(100% - 32px);
    margin-inline: auto;
}
.mns-modal .modal-content {
    background: #14130c;
    border: 1px solid rgba(249, 247, 234, .14);
    border-radius: 24px;
    overflow: hidden;
    color: var(--hr-cream-500);
    /* Deeper than the site's ambient button ramp: this sits over a dimmed page
       and needs to read as lifted off it, not resting on it. */
    box-shadow: 0 32px 80px rgba(0, 0, 0, .55), 0 4px 12px rgba(0, 0, 0, .35);
}
.mns-modal .modal-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    padding: 20px 24px;
    border-bottom: 1px solid rgba(249, 247, 234, .12);
}
.mns-modal-heading { min-width: 0; }
/* Says which kind of item is open — "Video", or the photo count — above the
   title, so the title itself never has to carry that. */
.mns-modal-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 6px;
    font-size: 13px;
    font-weight: 700;
    line-height: 16px;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--hr-yellow-400);
}
.mns-modal-eyebrow img { display: block; flex-shrink: 0; }
/* One line with an ellipsis: these captions are admin-authored and unbounded,
   and a wrapped title would push the stage down and reflow the dialog. */
.mns-modal-title {
    margin: 0;
    font-size: 22px;
    line-height: 30px;
    font-weight: 700;
    color: var(--hr-cream-500);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Hand-rolled rather than Bootstrap's .btn-close: that one paints a dark SVG
   cross, invisible on this surface, and .custom-close (app.css) hard-codes a
   white FILLED circle that reads as a bright blob against the dark header. */
.mns-modal-close {
    position: relative;
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid rgba(249, 247, 234, .18);
    border-radius: 50%;
    background: rgba(249, 247, 234, .08);
    cursor: pointer;
    transition: background-color .2s ease, border-color .2s ease, transform .2s ease;
}
.mns-modal-close::before,
.mns-modal-close::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 14px;
    height: 1.5px;
    background: var(--hr-cream-500);
    border-radius: 2px;
}
.mns-modal-close::before { transform: translate(-50%, -50%) rotate(45deg); }
.mns-modal-close::after { transform: translate(-50%, -50%) rotate(-45deg); }
.mns-modal-close:hover {
    background: rgba(249, 247, 234, .16);
    border-color: rgba(249, 247, 234, .34);
    transform: translateY(-2px);
}
/* Edge to edge: the media is the point, so the stage carries no padding and
   the black behind it does the letterboxing for any aspect ratio. */
.mns-modal .modal-body {
    padding: 0;
    background: #000;
}
.mns-modal .modal-footer {
    justify-content: flex-start;
    padding: 14px 24px;
    border-top: 1px solid rgba(249, 247, 234, .12);
}
/* Turns the lightbox from a dead end into a way through to the gathering the
   item belongs to — the same destination the card's caption links to. */
.mns-modal-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 15px;
    font-weight: 700;
    color: var(--hr-yellow-400);
    text-decoration: none;
}
.mns-modal-link:hover { color: var(--hr-yellow-400); text-decoration: underline; }
.mns-modal-link img { display: block; }
@media (max-width: 767.98px) {
    .mns-modal .modal-dialog { width: calc(100% - 16px); }
    .mns-modal .modal-header { padding: 16px; }
    .mns-modal .modal-footer { padding: 12px 16px; }
    .mns-modal-title { font-size: 17px; line-height: 24px; }
    .mns-modal-close { width: 34px; height: 34px; }
}

/* ---------- Video stage ---------- */
/* 70vh less the header and footer, so a tall viewport does not push the
   footer off-screen while a short one still shows the whole player. */
.mns-modal-video {
    display: block;
    width: 100%;
    max-height: min(70vh, 620px);
    background: #000;
}

/* ---------- Photo stage (multi-image slider) ---------- */
.mns-photo-swiper { width: 100%; background: #000; }
.mns-photo-swiper .swiper-slide { display: flex; align-items: center; justify-content: center; }
/* contain, not cover: these are whole photographs, so the frame letterboxes
   them rather than cropping. */
.mns-photo-swiper .swiper-slide img { width: 100%; max-height: min(70vh, 620px); object-fit: contain; }
.mns-photo-swiper .swiper-pagination { position: absolute; bottom: 16px; }
/* Cream at rest, solid on the active dot — Bootstrap-free, and legible over a
   photo of any brightness because the bullets sit on their own dark scrim. */
.mns-photo-swiper .swiper-pagination-bullet {
    width: 8px;
    height: 8px;
    background: var(--hr-cream-500);
    opacity: .45;
}
.mns-photo-swiper .swiper-pagination-bullet-active { opacity: 1; background: var(--hr-yellow-400); }
/* The same glass circle as the Videos listing's carousel arrows
   (.vid-carousel-arrow) and the site's other 56px icon buttons: a translucent
   white fill, the shared masked gradient rim (this is now in that list in
   layout-revamp.css) and the full four-layer ambient stack.

   It used to be an OPAQUE cream disc with a hard `1.5px solid #fff` ring and a
   single flat `0 3px 6px` drop — a solid blob sitting on the photo rather than
   glass over it, and the one carousel control on the site not wearing this
   treatment. Translucent is what lets the photograph read through it, which is
   the whole point of the effect over a media stage. */
.mns-photo-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 61px;
    background: rgba(255, 255, 255, .2);
    /* Transparent so the shared rim lands on this 1.5px band - see the note on
       .mns-play-badge, same mechanism. */
    border: 1.5px solid transparent;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    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;
}
/* The lift has to be composed into the translateY(-50%) this already carries,
   or hovering would drop the centring - the same reason the play circles are
   handled separately from the generic lift list. */
.mns-photo-arrow:hover {
    background: rgba(255, 255, 255, .4);
    transform: translateY(calc(-50% - 2px));
}
/* One asset for both directions. home-revamp/icon-arrow-left.svg is stroked
   #0B0B05 and the right one #FEFEFD - they are a pair built for opposite
   backgrounds, not a matched set, which is why the "next" arrow was invisible
   here: a white glyph on a near-white disc. Over this dark stage both arrows
   want to be light, so the cream RIGHT arrow is used twice and the prev button
   mirrors it. Mirroring again under RTL would cancel that out, so each
   direction is restated there. */
.mns-photo-prev img { transform: scaleX(-1); }
[dir="rtl"] .mns-photo-prev img { transform: scaleX(1); }
[dir="rtl"] .mns-photo-next img { transform: scaleX(-1); }
@media (max-width: 767.98px) {
    .mns-photo-arrow { width: 44px; height: 44px; }
    .mns-photo-arrow img { width: 16px; height: 16px; }
}
.mns-photo-prev { inset-inline-start: 20px; }
.mns-photo-next { inset-inline-end: 20px; }
@media (max-width: 767.98px) {
    .mns-photo-prev { inset-inline-start: 12px; }
    .mns-photo-next { inset-inline-end: 12px; }
}
.mns-photo-swiper-single .mns-photo-arrow,
.mns-photo-swiper-single .mns-photo-pagination { display: none; }
