/* =================================================================
   Listing pages -- blog and news, index and their sub-pages.

   The companion to article-page.css, and deliberately its junior: the
   token names below are copied from `.article-page` rather than
   reinvented, so a reader moving from a listing to the article it links
   to stays inside one design rather than crossing between two.

   This replaces 603 lines of inline CSS in blog/index.blade.php and 672
   in news/index.blade.php -- two copies of the same design that had
   already drifted 373 lines apart, one green and one purple, with the
   responsive rules duplicated two to four times over from repeated
   copy-paste.

   Everything is scoped to `.listing-page` and every class is prefixed
   `lst-`. That is not decoration either: `.post-card`, `.hero-swiper`
   and `.trending-card` are still live class names on the homepage, the
   admin campaign editors and the newsletter editors, and nothing here
   may reach them.
   ================================================================= */

.listing-page {
    /* Neutral */
    --n-base:      #C4C4C4;   /* hairlines, dividers, disabled */
    --n-secondary: #FFFFFF;   /* surfaces: cards, the dock, the ad frame */
    --n-ground:    #F8F8F8;   /* the page itself, one step off the surfaces */
    --n-tertiary:  #3E3E3E;   /* body text */
    --n-wash:      #F5F5F5;   /* the one recessed fill */

    /* Cosmic Purple - Hewa+ */
    --p-base:      #8063FF;   /* the accent */
    --p-secondary: #C2BAFC;   /* hover, soft fills, focus ring */
    --p-tertiary:  #1A1637;   /* headline, and the dark surface */

    /* Derived */
    --rule:  rgba(62, 62, 62, 0.14);
    --muted: #6B6B72;

    /* Blog used to be green and news purple. One accent now, the same
       one the article page uses -- the section a reader is in is told
       by the page they are on, not by recolouring the furniture. */

    --radius: 8px;

    /* Cover images sit at 2px, not the 8px the article page gives its
       framed things. A grid of thumbnails reads as photography with a
       hard edge; the same corner that suits one large cover makes
       twelve small ones look like app icons. */
    --card-img-radius: 2px;

    /* The public nav is sticky at 3.8rem. The toolbar pins under it, so
       it has to know how tall it is -- same value the article page uses. */
    --nav-h: 3.8rem;

    background: var(--n-ground);
    color: var(--n-tertiary);
    font-family: 'Raleway', 'Google Sans', sans-serif;
}

/* Black and white, not a tinted near-black -- same reasoning as the
   article page: the moment the ground is also purple, the accent stops
   being one. */
html.dark .listing-page {
    --n-secondary: #262626;   /* surfaces lift off the ground */
    --n-ground:    #1D1D1D;   /* not pure black */
    --n-tertiary:  #F5F5F5;
    --n-wash:      #141414;
    --n-base:      #3E3E3E;

    /* #8063FF on black is under 4.5:1. */
    --p-base:      #C2BAFC;
    --p-tertiary:  #FFFFFF;

    --rule:  rgba(255, 255, 255, 0.16);
    --muted: #9B9BA6;
}

/* The homepage wants the cards without the page.
 *
 * It has its own ground (gray-50, and a near-black with a grid pattern over
 * it in dark) and its own hero, so `.listing-page` alone would paint a white
 * or black panel behind every grid it wrapped. .lst-bare keeps the tokens,
 * the grid and the cards, and drops the surface -- which is the whole reason
 * the tokens live on a class rather than on :root. */
.listing-page.lst-bare {
    background: transparent;
    color: inherit;
}

/* :not(.lst-bare) so a card grid borrowed by another page does not drag the
   listing page's body treatment along with it. */
body:has(.listing-page:not(.lst-bare)) {
    background: #F8F8F8;
}

html.dark body:has(.listing-page:not(.lst-bare)) {
    background: #1D1D1D;
}

/* What makes the pinned toolbar possible.
 *
 * The layout wraps every page in <main class="overflow-x-hidden">, and
 * overflow-x: hidden computes overflow-y to auto -- which makes <main> a
 * scroll container, and a sticky child then sticks to that rather than to
 * the viewport. In practice it simply never sticks.
 *
 * overflow-x: clip clips exactly the same way without creating a scroll
 * container. Scoped to listing pages rather than changed in the layout,
 * so no other page's overflow behaviour moves. A browser too old to know
 * `clip` ignores this and gets today's behaviour.
 */
body:has(.listing-page:not(.lst-bare)) main {
    overflow-x: clip;
}

/* -----------------------------------------------------------------
   Page head

   A block that says what the section is for, in place of the carousel
   that used to lead these pages. The carousel showed five stories the
   reader had not asked for and pushed everything else below the fold;
   this says what they will find and gets out of the way.

   Neutral rather than a saturated fill: the accent is purple, and a
   block of colour at the top of every listing would out-shout the
   photography in the grid underneath it.
   ----------------------------------------------------------------- */

.listing-page .lst-head {
    background: var(--n-wash);
    border-radius: var(--radius);
    padding: 56px 48px;
    margin-bottom: 40px;
    text-align: center;
}

.listing-page .lst-eyebrow {
    display: inline-block;
    padding: 6px 14px;
    margin-bottom: 18px;
    border-radius: 999px;
    background: var(--p-secondary);
    color: #1A1637;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.09em;
}

.listing-page .lst-head .lst-title {
    font-size: 4.5rem;
    line-height: 1.02;
    letter-spacing: -0.035em;
    margin: 0 auto 18px;
    max-width: 16ch;
}

.listing-page .lst-lede {
    /* The measure, borrowed from the article page. Three lines of intro
       across a 1280px page is a single unreadable band. */
    max-width: 62ch;
    margin: 0 auto;
    font-size: 1rem;
    line-height: 1.65;
    color: var(--muted);
}

.listing-page .lst-title {
    font-size: 2.25rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--p-tertiary);
    margin: 0 0 20px;
}

/* -----------------------------------------------------------------
   Toolbar: category tabs, search, view switch
   ----------------------------------------------------------------- */

/* Pinned under the site nav.
 *
 * On a phone the topics scroll off the top after one card and there is no
 * way back to them without returning to the top of the page, which on a
 * long index is most of the way back through it. Pinned, the filter is
 * always the thing you can reach.
 *
 * It needs its own background: the grid scrolls underneath it, and
 * without one the cards read straight through the bar. */
.listing-page .lst-toolbar {
    position: sticky;
    top: var(--nav-h);
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 32px;
    padding-top: 12px;
    padding-bottom: 14px;
    background: var(--n-ground);
    border-bottom: 1px solid var(--rule);
}

.listing-page .lst-toolbar .lst-tabs {
    flex: 1 1 auto;
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
    min-width: 0;
}

.listing-page .lst-tools {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 10px;
}

/* No topics to filter by -- newsletters. The tools go right rather than
   sitting oddly alone on the left. */
.listing-page .lst-toolbar--tools-only {
    justify-content: flex-end;
}

/* Search. Filters the cards already on the page as you type -- a
   refinement of what is shown, not a search of the archive, which is
   what the placeholder has to convey. */
.listing-page .lst-search {
    position: relative;
    display: flex;
    align-items: center;
}

.listing-page .lst-search i {
    position: absolute;
    left: 12px;
    font-size: 0.75rem;
    color: var(--muted);
    pointer-events: none;
}

.listing-page .lst-search input {
    width: 210px;
    padding: 7px 12px 7px 30px;
    border: 1px solid var(--rule);
    border-radius: 2px;
    background: transparent;
    color: var(--n-tertiary);
    font-size: 0.8125rem;
    font-family: inherit;
}

.listing-page .lst-search input:focus {
    outline: none;
    border-color: var(--p-base);
}

.listing-page .lst-search input::placeholder {
    color: var(--muted);
}

.listing-page .lst-view {
    display: flex;
    gap: 4px;
}

.listing-page .lst-view-btn {
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 2px;
    background: transparent;
    color: var(--muted);
    font-size: 0.875rem;
    cursor: pointer;
}

.listing-page .lst-view-btn:hover {
    color: var(--p-tertiary);
}

.listing-page .lst-view-btn.is-active {
    color: var(--p-base);
}

.listing-page .lst-tabs {
    display: flex;
    gap: 26px;
    overflow-x: auto;
    padding-bottom: 10px;
    margin-bottom: 30px;
    border-bottom: 1px solid var(--rule);
    /* The bar scrolls on a phone; the scrollbar itself is noise. */
    scrollbar-width: none;
}

.listing-page .lst-tabs::-webkit-scrollbar {
    display: none;
}

/* Plain text, not pills. A row of outlined capsules turns a list of
   topics into a row of buttons competing with each other; as text the
   active one is the only thing marked, which is all the bar has to say. */
.listing-page .lst-tab {
    flex: 0 0 auto;
    padding: 4px 0;
    border: none;
    border-radius: 0;
    background: transparent;
    color: var(--muted);
    font-size: 0.9375rem;
    font-weight: 500;
    white-space: nowrap;
    /* The about page uses the same bar for in-page anchors, so a tab is
       sometimes an <a> rather than a <button>. */
    text-decoration: none;
    cursor: pointer;
    transition: color 0.15s;
}

.listing-page .lst-tab:hover {
    color: var(--p-tertiary);
}

.listing-page .lst-tab.is-active {
    color: var(--p-base);
    font-weight: 700;
}

/* -----------------------------------------------------------------
   Section headers
   ----------------------------------------------------------------- */

.listing-page .lst-section {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding-top: 32px;
    margin-bottom: 24px;
    border-top: 1px solid var(--rule);
}

.listing-page .lst-section h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 1.375rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--p-tertiary);
    margin: 0;
}

.listing-page .lst-section-link {
    flex: 0 0 auto;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--p-base);
    text-decoration: none;
}

.listing-page .lst-section-link:hover {
    text-decoration: underline;
}

/* The homepage centres its section headings.
 *
 * A listing is a single stream and its headings sit at the left margin
 * where the reading starts. The homepage is a stack of unrelated blocks,
 * and a centred heading over each one is what separates them -- which is
 * the job the coloured bar and the chip beside it were doing badly: one
 * accent bar and one uppercase pill per section, in a different colour
 * each time, competing with the photographs underneath.
 *
 * Scoped to .lst-bare, so the blog and news listings keep their left
 * margin and their "view all" on the right. */
.listing-page.lst-bare .lst-section {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 12px;
    padding-top: 56px;
    margin-bottom: 32px;
}

/* The size Explore Topics already used, which is the one that reads as the
   start of a block rather than as a label on top of one. clamp() rather than
   a breakpoint pair so it moves with the viewport, same as the hero. */
.listing-page.lst-bare .lst-section h2 {
    justify-content: center;
    /* text-4xl to text-5xl, which is what Explore Topics is. */
    font-size: clamp(2.25rem, 4vw, 3rem);
    font-weight: 900;
    letter-spacing: -0.03em;
    line-height: 1.05;
}

/* Ethiopic sets wider and carries marks above and below the baseline. */
html[lang="am"] .listing-page.lst-bare .lst-section h2 {
    font-size: clamp(1.625rem, 3.2vw, 2.375rem);
    letter-spacing: 0;
    line-height: 1.3;
}

.listing-page .lst-section-lede {
    max-width: 54ch;
    margin: 0;
    color: var(--muted);
    font-size: 1.0625rem;
    line-height: 1.55;
}

.listing-page.lst-bare .lst-section-lede {
    margin-inline: auto;
}

/* The icon went with the chip. It was a star, a flame, a padlock and a
   feather -- four different marks saying the same thing the heading
   already says. */
.listing-page.lst-bare .lst-section h2 > i {
    display: none;
}

/* -----------------------------------------------------------------
   Cards

   The article page's rec-card, which carries no border, no fill, no
   shadow and no hover lift. The picture and the whitespace do the
   separating; a grid of boxes competes with the photography it exists
   to show.
   ----------------------------------------------------------------- */

/* The column count arrives as data-cols, and every width is spelled out
   with a literal integer.
 *
 * It used to be `repeat(var(--cols, 4), minmax(0, 1fr))`, which reads
 * better and is the reason the blog and news listings rendered as an
 * unstyled pile in Chrome while looking correct in Firefox. A var() as
 * the repeat COUNT is substituted after parsing; a browser that will not
 * take an integer from a custom property there throws the whole
 * declaration out at computed-value time, and grid-template-columns
 * falls back to `none` -- one implicit column, cards on top of each
 * other. Firefox has accepted it for years, so the bug is invisible to
 * half the people looking for it.
 *
 * Three literal values is a small price for a layout that cannot fail
 * this way. Keep them literal. */
.listing-page .lst-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 28px;
    margin-bottom: 48px;
}

.listing-page .lst-grid[data-cols="2"] {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.listing-page .lst-grid[data-cols="3"] {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.listing-page .lst-card {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    min-width: 0;
}

.listing-page .lst-card-img {
    width: 100%;
    aspect-ratio: 3 / 2;
    object-fit: cover;
    display: block;
    background: var(--n-wash);
    border-radius: var(--card-img-radius);
    margin-bottom: 12px;
}

/* No cover. Keeps the fill and the exact shape of a real one, so a row
   of cards never goes ragged, and centres the publication mark in it. */
.listing-page .lst-card-img--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.listing-page .lst-card-img--empty img {
    width: 38%;
    max-width: 130px;
    height: auto;
    /* A watermark, not a logo placement. Slightly stronger on black,
       where the same value reads fainter. */
    opacity: 0.13;
}

html.dark .listing-page .lst-card-img--empty img {
    opacity: 0.2;
}

/* Always present, in both arrangements, so the card has one shape in the
   markup. flex:1 is what pushes the meta line to the bottom, which is
   what keeps the meta of every card in a row on the same line. */
.listing-page .lst-card-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
}

.listing-page .lst-card-cat {
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--p-base);
    margin-bottom: 6px;
}

.listing-page .lst-card-title {
    font-size: 1.0625rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--n-tertiary);
    margin: 0 0 10px;
}

.listing-page .lst-card:hover .lst-card-title {
    color: var(--p-base);
}

.listing-page .lst-card-meta {
    margin-top: auto;
    font-size: 0.8125rem;
    color: var(--muted);
}

/* A locked article says so in words. The old page used an amber
   gradient card, a lock chip and a second gradient tag, which made
   members-only content the loudest thing in the grid. */
.listing-page .lst-card-lock {
    color: var(--muted);
}

/* The wide variant: image beside text, for the two-up rows (deep dives,
   trending). Same card, different arrangement -- not a second card. */
.listing-page .lst-card--wide {
    flex-direction: row;
    gap: 18px;
    align-items: flex-start;
}

/* min-width: 0 is not tidying. Without it this rule does nothing and the
   picture eats the whole card.
 *
 * A flex item defaults to min-width: auto, and for a replaced element the
 * automatic minimum size is floored by the "specified size suggestion" --
 * which here is `width: 100%` from .lst-card-img, i.e. the entire card.
 * So the image cannot go below full width, flex-basis: 42% is overruled,
 * and .lst-card-body is squeezed to zero: a title wrapping one word per
 * line beside a cover blown up to four times its slot. Chrome and Firefox
 * disagree about this for replaced items, which is why the Trending and
 * Deep Dives rows looked correct to anyone checking in Firefox.
 *
 * It only shows when the cover actually loads. A local database whose
 * cover_image URLs 404 has no intrinsic size to floor against and lays
 * out perfectly, so this cannot be reproduced without real images. */
.listing-page .lst-card--wide .lst-card-img {
    flex: 0 0 42%;
    min-width: 0;
    margin-bottom: 0;
}

.listing-page .lst-card-excerpt {
    font-size: 0.875rem;
    line-height: 1.55;
    color: var(--muted);
    margin: 0 0 10px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* -----------------------------------------------------------------
   List view

   The same cards, laid on their side. One switch on the container
   rather than a second set of card classes, so every grid on the page
   turns over together and there is only one card to maintain.
   ----------------------------------------------------------------- */

.listing-page [data-view="list"] .lst-grid {
    grid-template-columns: 1fr;
    gap: 0;
}

.listing-page [data-view="list"] .lst-card {
    flex-direction: row;
    gap: 20px;
    align-items: flex-start;
    padding: 20px 0;
    border-bottom: 1px solid var(--rule);
}

/* Same reasoning as the wide card above: a fixed flex-basis on a
   replaced item is only honoured once min-width: auto is off it. */
.listing-page [data-view="list"] .lst-card-img {
    flex: 0 0 168px;
    min-width: 0;
    aspect-ratio: 16 / 10;
    margin-bottom: 0;
}

.listing-page [data-view="list"] .lst-card-title {
    font-size: 1.1875rem;
}

/* Hidden by the search box. A class rather than an inline style so a
   card can be shown again without having to remember what its display
   used to be. */
.listing-page .lst-card.is-filtered {
    display: none;
}

/* A section whose every card was filtered out should take its heading
   with it, rather than leaving a rule and a title over nothing. */
.listing-page .lst-section.is-filtered,
.listing-page .lst-grid.is-filtered {
    display: none;
}

.listing-page .lst-no-match {
    padding: 48px 0;
    text-align: center;
    color: var(--muted);
}

/* -----------------------------------------------------------------
   Community page

   Not a listing, but it is a public page and it now speaks the same
   vocabulary, so its handful of pieces live here rather than in a file
   of their own. Everything is inside `.listing-page`, so it inherits the
   tokens like everything else above.
   ----------------------------------------------------------------- */

/* Was a sentence of body copy under the cards, carrying a ":title"
   placeholder nothing ever filled in -- so the page literally read
   `weekly threads like ":title"`. It is a heading now, and short enough
   to be one. */
.listing-page .cmy-heading {
    margin: 0 0 20px;
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--p-tertiary);
    text-align: center;
}

/* Centred: it introduces the three columns beneath it rather than
   labelling a row, so left-aligning it left the description stranded
   across the full width. */
.listing-page .cmy-section {
    max-width: 60ch;
    margin: 48px auto 28px;
    text-align: center;
}

.listing-page .cmy-section h2 {
    margin: 0 0 8px;
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--p-tertiary);
}

.listing-page .cmy-section p {
    margin: 0;
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--muted);
}

/* The teaser on a locked issue. Faded out rather than cut off: enough to
   judge whether the issue is worth joining for, and obvious that there is
   more rather than looking like a short one. */
.listing-page .lkd-teaser {
    max-width: 68ch;
    margin: 0 auto;
    padding-bottom: 8px;
    -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent);
    mask-image: linear-gradient(to bottom, #000 45%, transparent);
}

.listing-page .lkd-teaser p {
    margin: 0;
    font-size: 1rem;
    line-height: 1.75;
    color: var(--n-tertiary);
}

.listing-page .lkd-note {
    font-weight: 600;
    color: var(--n-tertiary) !important;
}

/* The one thing the guest newsletter page is asking for. Centred and on
   its own, rather than a gradient panel with a second heading inside it. */
.listing-page .pmo-cta {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 8px 0 40px;
    text-align: center;
}

.listing-page .pmo-cta p {
    margin: 0;
    font-size: 0.875rem;
    color: var(--muted);
}

.listing-page .pmo-cta a:not(.cmy-btn) {
    color: var(--p-base);
    font-weight: 700;
    text-decoration: none;
}

.listing-page .pmo-cta a:not(.cmy-btn):hover {
    text-decoration: underline;
}

.listing-page .cmy-list {
    display: flex;
    flex-direction: column;
    margin-bottom: 8px;
    border-top: 1px solid var(--rule);
}

/* A row, not a raised card. These are a list of three choices; boxing
   each one made the page read as three competing adverts. */
.listing-page .cmy-row {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 24px 0;
    border-bottom: 1px solid var(--rule);
}

.listing-page .cmy-icon {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--card-img-radius);
    background: var(--n-wash);
    color: var(--p-base);
    font-size: 1.25rem;
}

.listing-page .cmy-body {
    flex: 1 1 auto;
    min-width: 0;
}

.listing-page .cmy-body h3 {
    margin: 0 0 4px;
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--p-tertiary);
}

.listing-page .cmy-body p {
    margin: 0;
    font-size: 0.875rem;
    line-height: 1.55;
    color: var(--muted);
}

.listing-page .cmy-stats {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 8px;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
}

.listing-page .cmy-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--n-base);
}

.listing-page .cmy-dot--live {
    background: #10b981;
}

.listing-page .cmy-dot + span {
    margin-right: 10px;
}

/* One accent for every action on the site. The icons above keep their
   platform colours -- a Telegram row that is not Telegram blue is harder
   to scan -- but the button that does the thing is always Hewa+. */
.listing-page .cmy-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 18px;
    border-radius: var(--card-img-radius);
    background: var(--p-base);
    color: var(--n-secondary);
    font-size: 0.8125rem;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
    transition: filter 0.15s;
}

html.dark .listing-page .cmy-btn {
    color: #000000;
}

.listing-page .cmy-btn:hover {
    filter: brightness(1.08);
}

.listing-page .cmy-feature h3 {
    margin: 14px 0 6px;
    font-size: 1rem;
    font-weight: 700;
    color: var(--p-tertiary);
}

.listing-page .cmy-feature p {
    margin: 0;
    font-size: 0.875rem;
    line-height: 1.55;
    color: var(--muted);
}

@media (max-width: 640px) {
    .listing-page .cmy-row {
        flex-wrap: wrap;
        gap: 14px;
    }

    .listing-page .cmy-body {
        flex: 1 1 60%;
    }

    /* Full width once it has dropped to its own line, so it does not sit
       marooned against one edge. */
    .listing-page .cmy-btn {
        flex: 1 1 100%;
    }
}

/* -----------------------------------------------------------------
   Pagination

   The one block in this file NOT scoped to `.listing-page`. It is used
   on public pages that have not been brought into this design yet --
   author profiles, topics -- so it has to stand on its own, and every
   colour below falls back to a literal when the tokens are absent.

   Replaces Laravel's Tailwind default, which draws a bordered segmented
   capsule: the heaviest object on a page whose cards have no borders at
   all.
   ----------------------------------------------------------------- */

.lst-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px 20px;
    margin: 8px 0;
}

.lst-pager-count {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--muted, #6B6B72);
}

.lst-pager-count span {
    font-weight: 600;
    color: var(--n-tertiary, inherit);
}

.lst-pager-links {
    display: flex;
    align-items: center;
    gap: 2px;
}

.lst-pager-page,
.lst-pager-arrow {
    min-width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 6px;
    border-radius: 2px;
    color: var(--muted, #6B6B72);
    font-size: 0.8125rem;
    font-weight: 600;
    text-decoration: none;
    transition: color 0.15s, background 0.15s;
}

.lst-pager-page:hover,
.lst-pager-arrow:not(.is-off):hover {
    color: var(--p-base, #8063FF);
    background: var(--n-wash, rgba(128, 99, 255, 0.08));
}

.lst-pager-page.is-current {
    color: var(--p-base, #8063FF);
    /* Weight and colour, not a filled chip. A single highlighted cell in a
       row of plain numbers is enough to say which page you are on. */
    font-weight: 800;
}

.lst-pager-arrow.is-off {
    opacity: 0.35;
    cursor: default;
}

.lst-pager-gap {
    padding: 0 4px;
    color: var(--muted, #6B6B72);
    font-size: 0.8125rem;
}

@media (max-width: 640px) {
    .lst-pager {
        gap: 6px 12px;
    }

    /* The count is the first thing to go when there is no room -- the
       controls are what a reader is reaching for. */
    .lst-pager-count {
        display: none;
    }
}

/* -----------------------------------------------------------------
   Empty state, footer link
   ----------------------------------------------------------------- */

.listing-page .lst-empty {
    padding: 64px 0;
    text-align: center;
    color: var(--muted);
}

.listing-page .lst-foot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    padding-top: 32px;
    border-top: 1px solid var(--rule);
}

.listing-page .lst-archive-link {
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--p-tertiary);
    text-decoration: none;
}

.listing-page .lst-archive-link:hover {
    color: var(--p-base);
}

/* While a category is loading. Opacity only -- swapping in a skeleton
   would move the page under a reader who is already reading it. */
.listing-page .lst-content.is-loading {
    opacity: 0.45;
    pointer-events: none;
}

.listing-page .lst-content {
    transition: opacity 0.2s ease;
}

/* =================================================================
   Homepage shapes

   Four arrangements the listings do not need but the homepage does.
   They live here rather than in home.blade.php because they are made
   of the same cards and the same tokens -- a second stylesheet would
   be a second design inside a week.

   Everything below draws with --rule, --muted, --n-* and --p-base and
   nothing else. The homepage previously reached for blue-600,
   emerald-500, teal-600, yellow-600, orange-600, indigo-500, #FC4646
   and #6366f1, roughly one accent per section, so the page read as
   eight publications stacked on top of each other.
   ================================================================= */

/* -----------------------------------------------------------------
   Feature block -- one lead story beside a stack of the next few.
   Latest News and Latest Articles & Blogs are the same arrangement;
   they used to be two copies of it, 90 lines each.
   ----------------------------------------------------------------- */
.listing-page .lst-feature {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 32px;
    margin-bottom: 48px;
}

.listing-page .lst-feature-lead {
    position: relative;
    display: block;
    min-height: 420px;
    border-radius: var(--radius);
    overflow: hidden;
    text-decoration: none;
    background: var(--n-wash);
}

.listing-page .lst-feature-lead img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Dark enough for white text at the bottom, clear enough that the
   photograph is still the photograph. */
.listing-page .lst-feature-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(
        to top,
        rgba(0, 0, 0, 0.88) 0%,
        rgba(0, 0, 0, 0.45) 42%,
        rgba(0, 0, 0, 0.05) 100%
    );
}

.listing-page .lst-feature-text {
    position: absolute;
    inset: auto 0 0 0;
    padding: 28px;
    color: #FFFFFF;
}

.listing-page .lst-feature-cat {
    display: block;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    /* The one place the accent is used on a photograph. Purple-secondary
       rather than purple-base: base is under 4.5:1 on a dark scrim. */
    color: var(--p-secondary);
    margin-bottom: 10px;
}

/* Spans, not headings: the whole lead is one <a>, and an <a> may not
   contain block-level content. display: block does the layout. */
.listing-page .lst-feature-title {
    display: block;
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.2;
    margin: 0 0 10px;
    color: #FFFFFF;
}

.listing-page .lst-feature-meta {
    display: block;
    font-size: 0.8125rem;
    color: rgba(255, 255, 255, 0.72);
}

.listing-page .lst-feature-lead:hover .lst-feature-title {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* The stack beside it. Rules rather than cards: three bordered boxes
   next to one big photograph reads as a form, not a page. */
.listing-page .lst-feature-list {
    display: flex;
    flex-direction: column;
    border-top: 1px solid var(--rule);
}

.listing-page .lst-feature-item {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 18px 0;
    border-bottom: 1px solid var(--rule);
    text-decoration: none;
    color: inherit;
}

.listing-page .lst-feature-item-body {
    flex: 1;
    min-width: 0;
}

/* min-width: 0 for the same reason as the wide card: without it the
   automatic minimum size of a replaced flex item is its own width and
   the thumbnail takes the row. */
.listing-page .lst-feature-item img {
    flex: 0 0 92px;
    min-width: 0;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: var(--card-img-radius);
    background: var(--n-wash);
}

.listing-page .lst-feature-item-title {
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.35;
    margin: 0 0 6px;
    color: var(--n-tertiary);
}

.listing-page .lst-feature-item:hover .lst-feature-item-title {
    color: var(--p-base);
}

.listing-page .lst-feature-item-meta {
    font-size: 0.8125rem;
    color: var(--muted);
}

/* -----------------------------------------------------------------
   Rail -- cards that scroll sideways. For You.
   ----------------------------------------------------------------- */
.listing-page .lst-rail {
    display: flex;
    gap: 24px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    margin-bottom: 48px;
    padding-bottom: 4px;
    scrollbar-width: none;
}

.listing-page .lst-rail::-webkit-scrollbar {
    display: none;
}

.listing-page .lst-rail .lst-card {
    flex: 0 0 264px;
    scroll-snap-align: start;
}

/* -----------------------------------------------------------------
   Rank list -- Trending Now. A numbered list, because that is what a
   ranking is; it does not need a panel around it.
   ----------------------------------------------------------------- */
.listing-page .lst-rank {
    border-top: 1px solid var(--rule);
    margin-bottom: 48px;
}

.listing-page .lst-rank-item {
    display: flex;
    align-items: center;
    gap: 24px;
    padding: 18px 0;
    border-bottom: 1px solid var(--rule);
    text-decoration: none;
    color: inherit;
}

.listing-page .lst-rank-num {
    flex: 0 0 auto;
    width: 2.5ch;
    text-align: right;
    font-size: 1.5rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--n-base);
}

.listing-page .lst-rank-item:hover .lst-rank-num {
    color: var(--p-base);
}

.listing-page .lst-rank-body {
    flex: 1;
    min-width: 0;
}

.listing-page .lst-rank-title {
    font-size: 1.0625rem;
    font-weight: 600;
    line-height: 1.35;
    margin: 0 0 4px;
    color: var(--n-tertiary);
}

.listing-page .lst-rank-item:hover .lst-rank-title {
    color: var(--p-base);
}

.listing-page .lst-rank-meta {
    font-size: 0.8125rem;
    color: var(--muted);
}

/* -----------------------------------------------------------------
   Promo -- the newsletter showcase. One outlined block, not a
   gradient panel with a shadow under it.
   ----------------------------------------------------------------- */
.listing-page .lst-promo {
    position: relative;
    overflow: hidden;
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    padding: 56px 28px;
    text-align: center;
    margin-bottom: 48px;
}

/* The issue cover, faint. It is the only thing that says which issue
   this is before the reader gets to the title. */
.listing-page .lst-promo-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0.06;
}

html.dark .listing-page .lst-promo-bg {
    opacity: 0.12;
}

.listing-page .lst-promo-inner {
    position: relative;
}

.listing-page .lst-promo-eyebrow {
    display: inline-block;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.11em;
    color: var(--p-base);
    margin-bottom: 16px;
}

.listing-page .lst-promo-title {
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.15;
    margin: 0 0 12px;
    color: var(--n-tertiary);
}

.listing-page .lst-promo-lede {
    max-width: 48ch;
    margin: 0 auto 20px;
    color: var(--muted);
    line-height: 1.6;
}

.listing-page .lst-promo-meta {
    font-size: 0.8125rem;
    color: var(--muted);
    margin-bottom: 24px;
}

.listing-page .lst-promo-cta {
    display: inline-block;
    padding: 12px 28px;
    border-radius: var(--radius);
    background: var(--p-base);
    color: #FFFFFF;
    font-weight: 700;
    text-decoration: none;
}

html.dark .listing-page .lst-promo-cta {
    /* --p-base is the light purple on dark, so the label has to flip. */
    color: var(--p-tertiary);
}

.listing-page .lst-promo-cta:hover {
    background: var(--p-secondary);
    color: var(--p-tertiary);
}

/* -----------------------------------------------------------------
   Responsive

   Written once. The pages this replaces had these rules two to four
   times over, which is how blog and news came to disagree about what a
   phone should look like.
   ----------------------------------------------------------------- */

@media (max-width: 1024px) {
    /* Four across is a filmstrip at this width. Two is the cap, and a
       grid already asking for two keeps it.
     *
       [data-cols] rather than a bare .lst-grid so this matches the
       specificity of the [data-cols="2"] and [data-cols="3"] rules above
       -- a media query adds no weight of its own, so without the
       attribute this would lose to them and never apply. */
    .listing-page .lst-grid[data-cols] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* List view is one card per row at every width; the cap above must
       not drag it back to two. */
    .listing-page [data-view="list"] .lst-grid[data-cols] {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 900px) {
    /* The tabs need the full width to scroll in, so the tools drop below
       them rather than squeezing the bar.
     *
     * Everything here is tighter than the desktop bar because the bar is
     * pinned: two stacked rows plus the site nav is a lot of a phone
     * screen to spend on furniture. */
    .listing-page .lst-toolbar {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        padding-top: 8px;
        padding-bottom: 10px;
        margin-bottom: 24px;
    }

    /* The topics run past the right edge, and a row of text with no
       affordance looks like the whole list. The fade says otherwise. */
    .listing-page .lst-toolbar .lst-tabs {
        -webkit-mask-image: linear-gradient(to right, #000 88%, transparent);
        mask-image: linear-gradient(to right, #000 88%, transparent);
    }

    .listing-page .lst-tab {
        font-size: 0.875rem;
    }

    .listing-page .lst-search input {
        padding-top: 6px;
        padding-bottom: 6px;
    }

    .listing-page .lst-view-btn {
        width: 28px;
        height: 28px;
    }

    .listing-page .lst-tools {
        justify-content: space-between;
    }

    .listing-page .lst-search {
        flex: 1 1 auto;
    }

    .listing-page .lst-search input {
        width: 100%;
    }
}

@media (max-width: 768px) {
    .listing-page .lst-title {
        font-size: 1.75rem;
    }

    .listing-page .lst-head {
        padding: 36px 20px;
    }

    .listing-page .lst-head .lst-title {
        font-size: 2.75rem;
        max-width: none;
    }

    .listing-page .lst-lede {
        font-size: 0.9375rem;
    }

    .listing-page [data-view="list"] .lst-card-img {
        flex: 0 0 108px;
    }

    .listing-page [data-view="list"] .lst-card-title {
        font-size: 1rem;
    }


    .listing-page .lst-grid[data-cols] {
        grid-template-columns: 1fr;
        gap: 24px;
    }

    .listing-page .lst-card--wide {
        flex-direction: column;
        gap: 12px;
    }

    .listing-page .lst-card--wide .lst-card-img {
        flex: none;
        width: 100%;
    }

    .listing-page .lst-section {
        padding-top: 24px;
        margin-bottom: 18px;
    }

    .listing-page .lst-section h2 {
        font-size: 1.125rem;
    }

    /* The lead story goes above its stack rather than beside it, and
       stops being 420px tall on a screen that is 660. */
    .listing-page .lst-feature {
        grid-template-columns: 1fr;
        gap: 24px;
    }

    .listing-page .lst-feature-lead {
        min-height: 0;
        aspect-ratio: 3 / 2;
    }

    .listing-page .lst-feature-text {
        padding: 20px;
    }

    .listing-page .lst-feature-title {
        font-size: 1.25rem;
    }

    .listing-page .lst-feature-item img {
        flex-basis: 76px;
    }

    .listing-page .lst-rail .lst-card {
        flex-basis: 232px;
    }

    .listing-page .lst-rank-item {
        gap: 16px;
    }

    .listing-page .lst-rank-num {
        font-size: 1.125rem;
    }

    .listing-page .lst-promo {
        padding: 36px 20px;
    }

    .listing-page .lst-promo-title {
        font-size: 1.5rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .listing-page .lst-content {
        transition: none;
    }
}

/* -----------------------------------------------------------------
   About

   The last public page still carrying its own design. Same content,
   same 50 translation keys, on the vocabulary above.

   The globe stays -- it is the one piece of the old page worth keeping
   -- but it moves. It used to be `position: fixed`, pinned 5% from the
   right edge at 80vh tall, drifting behind every section of the page
   and faded out by a scroll listener; on a phone it was pushed 20% off
   the right edge at 60% opacity, which is a WebGL scene rendering
   continuously to show a sliver. Now it is centred inside the head
   block and contained by it, so it is a hero rather than wallpaper.

   Its particles are neutral rather than purple and indigo. A page whose
   largest object is purple has no accent left for the buttons that
   matter, and the previous colours were picked per theme at init, so
   toggling to dark left them stranded. One mid-grey ramp reads on both
   grounds and needs no theme reactivity at all.
   ----------------------------------------------------------------- */

.listing-page .lst-head--globe {
    position: relative;
    overflow: hidden;
    /* Flush against the bar below it, so the two read as one block:
       the globe, the copy over it, and the sections it leads into. */
    margin-bottom: 0;
    min-height: 32rem;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 72px 48px;
}

.listing-page .abt-globe {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

.listing-page .abt-globe canvas {
    display: block;
}

/* The copy sits on the globe, so the globe has to give way underneath
   it. A wash-to-transparent ellipse rather than a flat overlay: the
   particles thin out towards the middle instead of the panel gaining a
   visible rectangle. */
.listing-page .lst-head--globe::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: radial-gradient(ellipse 58% 50% at 50% 50%, var(--n-wash) 0%, transparent 72%);
}

.listing-page .abt-hero {
    position: relative;
    z-index: 2;
    max-width: 46rem;
}

.listing-page .abt-brand {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 20px;
}

.listing-page .abt-brand img {
    height: 28px;
    width: auto;
}

.listing-page .abt-brand .lst-eyebrow {
    margin-bottom: 0;
}

.listing-page .abt-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 16px;
    margin-top: 26px;
}

.listing-page .abt-link {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--muted);
    text-decoration: none;
}

.listing-page .abt-link:hover {
    color: var(--p-base);
}

/* The section bar. The listing toolbar, pinned the same way under the
   same nav, but its tabs are anchors into this page rather than
   category filters -- so it is centred under the globe and reads as the
   base of the hero rather than a control strip above a grid. */
.listing-page .abt-bar {
    justify-content: center;
}

.listing-page .abt-bar .lst-tabs {
    flex: 0 0 auto;
    justify-content: center;
}

/* Cleared by the site nav plus the bar itself, or the heading a reader
   just jumped to lands underneath both. */
.listing-page .abt-anchor {
    scroll-margin-top: calc(var(--nav-h) + 4.5rem);
}

/* -- Sections --------------------------------------------------- */

/* One rhythm for the whole page, and its own class rather than reusing
   `.cmy-section`: that one is shared with the community and newsletter
   pages, and this page needs a bigger step between the 4.5rem hero and
   the headings under it than those pages do. */
.listing-page .abt-section {
    max-width: 62ch;
    margin: 88px auto 36px;
    text-align: center;
}

.listing-page .abt-section:first-of-type {
    margin-top: 64px;
}

.listing-page .abt-section .lst-eyebrow {
    margin-bottom: 14px;
}

.listing-page .abt-section h2 {
    margin: 0;
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    line-height: 1.15;
    color: var(--p-tertiary);
}

.listing-page .abt-section p {
    margin: 14px 0 0;
    font-size: 1.0625rem;
    line-height: 1.65;
    color: var(--muted);
}

/* -- Mission ---------------------------------------------------- */

/* Centred, with no emblem panel beside it. The panel was a square of
   wash holding a rocket and the society's name -- an illustration of a
   thing whose full name was already the line underneath it -- and it
   forced a two-column block into a page that is otherwise one centred
   column. Removing it also collapses "Our Mission" and "Inspiring
   Africa's Space Future" from two competing headings into an eyebrow
   over one. */
.listing-page .abt-checks {
    list-style: none;
    /* Centred as a block, left-aligned as text: a centred list with
       ragged left edges has nothing for the eye to run down. */
    width: fit-content;
    max-width: 100%;
    margin: 26px auto 28px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    text-align: left;
}

.listing-page .abt-checks li {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    font-size: 1rem;
    line-height: 1.55;
    color: var(--n-tertiary);
}

.listing-page .abt-checks i {
    flex: 0 0 auto;
    margin-top: 6px;
    font-size: 0.6875rem;
    color: var(--p-base);
}

/* -- FAQ -------------------------------------------------------- */

/* Eight questions that were eight glass cards: backdrop-blur over a
   3%-white fill, a 2xl radius, a border that lit indigo on hover and a
   shadow that lit indigo with it. Hairlines between rows say the same
   thing and let the questions read as a list. */
.listing-page .abt-faq {
    border-top: 1px solid var(--rule);
}

.listing-page .abt-faq-item {
    position: relative;
    border-bottom: 1px solid var(--rule);
}

/* Covers the question row only. The old hit area was the whole card, so
   once an answer was open, clicking anywhere in the text you were
   reading closed it again. */
.listing-page .abt-faq-item > input {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 62px;
    margin: 0;
    opacity: 0;
    cursor: pointer;
    z-index: 2;
}

.listing-page .abt-faq-q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding: 20px 0;
}

.listing-page .abt-faq-q h3 {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--p-tertiary);
    transition: color 0.15s;
}

/* Plus and minus rather than a rotating chevron. A chevron points
   somewhere; these open and close, and every reader already knows what
   a + does. Two icons stacked in one slot so the row never reflows as
   they swap. */
.listing-page .abt-faq-sign {
    position: relative;
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    color: var(--muted);
}

.listing-page .abt-faq-sign i {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8125rem;
}

.listing-page .abt-faq-sign .abt-faq-minus,
.listing-page .abt-faq-item > input:checked ~ .abt-faq-q .abt-faq-plus {
    display: none;
}

.listing-page .abt-faq-item > input:checked ~ .abt-faq-q .abt-faq-minus {
    display: flex;
}

.listing-page .abt-faq-item > input:checked ~ .abt-faq-q h3,
.listing-page .abt-faq-item > input:checked ~ .abt-faq-q .abt-faq-sign {
    color: var(--p-base);
}

.listing-page .abt-faq-a {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.35s ease;
}

.listing-page .abt-faq-item > input:checked ~ .abt-faq-a {
    max-height: 60rem;
}

.listing-page .abt-faq-a > div {
    max-width: 68ch;
    padding-bottom: 22px;
    font-size: 0.9375rem;
    line-height: 1.7;
    color: var(--muted);
}

/* The answers are rendered unescaped and some of them carry links. */
.listing-page .abt-faq-a a {
    color: var(--p-base);
    font-weight: 600;
}

/* -- Secondary action ------------------------------------------- */

/* "Explore content" next to "Join now": two solid purple buttons side
   by side ask the same question twice. Declared after the dark-mode
   rule for .cmy-btn, which sets black text at the same specificity --
   source order is what keeps this one legible. */
.listing-page .cmy-btn--ghost {
    background: transparent;
    color: var(--p-tertiary);
    box-shadow: inset 0 0 0 1px var(--rule);
}

html.dark .listing-page .cmy-btn--ghost {
    color: var(--p-tertiary);
}

.listing-page .cmy-btn--ghost:hover {
    filter: none;
    color: var(--p-base);
    box-shadow: inset 0 0 0 1px var(--p-base);
}

@media (max-width: 768px) {
    .listing-page .lst-head--globe {
        min-height: 26rem;
        padding: 44px 20px;
    }

    .listing-page .abt-section {
        margin: 56px auto 28px;
    }

    .listing-page .abt-section h2 {
        font-size: 1.5rem;
    }

    .listing-page .abt-section p {
        font-size: 0.9375rem;
    }

    .listing-page .abt-checks li {
        font-size: 0.9375rem;
    }

    .listing-page .abt-faq-q h3 {
        font-size: 0.9375rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .listing-page .abt-faq-a {
        transition: none;
    }
}
