/* Classic — magazine layout (PRD §6.1, §6.2, WEB-09).
 *
 * Built entirely on the tokens in base/base.css, so switching a colour is a token change and
 * never a rule change. Mobile first: one column until 48rem, cards two-up to 64rem, and the
 * sidebar only appears when there is room for it beside a readable measure.
 */

:root {
    --header-height: 3.5rem;
    --card-gap: var(--space-5);
}

/* --- Header ------------------------------------------------------------------------------ */

.site-header {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--bg);
    border-bottom: 1px solid var(--line);
}

/* One row when everything fits. Otherwise the tools drop below and a long menu wraps rather
 * than scrolling sideways, which would clip its sub-items; below 48rem base.css folds both into
 * the ☰ panel. Sticky elements read the real height from --header-offset (base.js). */
.site-header__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    min-height: var(--header-height);
    padding-block: var(--space-2);
}

.site-header__brand {
    font-family: var(--font-heading);
    font-size: var(--step-2);
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--fg);
    text-decoration: none;
    white-space: nowrap;
}

.site-nav {
    flex: 1 1 auto;
    min-width: 0;
}

/* Up to 64rem the menu takes a row of its own under the brand and the tools: two rows, never
 * the three that brand, menu and tools would each claim on a tablet. */
@media (max-width: 63.99rem) {
    .site-nav {
        order: 1;
        flex-basis: 100%;
    }
}

.menu {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
}

.menu__item {
    white-space: nowrap;
}

.menu a,
.menu__group,
.menu__expand {
    color: var(--fg-muted);
    text-decoration: none;
    font-weight: 600;
    font-size: 0.95rem;
}

.menu a:hover,
.menu a:focus-visible,
.menu__group:hover,
.menu__group:focus-visible,
.menu__expand:hover,
.menu__expand:focus-visible {
    color: var(--accent);
}

/* One level of sub-items; base.css decides when they open. */
.menu__children {
    position: absolute;
    z-index: 1;
    left: 0;
    top: 100%;
    min-width: 12rem;
    margin: 0;
    padding: var(--space-2);
    list-style: none;
    background: var(--bg-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: 0 0.5rem 1.5rem rgb(0 0 0 / 12%);
}

.menu__children a {
    display: block;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius);
}

.menu__children a:hover,
.menu__children a:focus-visible {
    background: var(--bg-sunken);
}

/* --- Page frame -------------------------------------------------------------------------- */

.layout {
    display: grid;
    gap: var(--space-6);
    padding-block: var(--space-6);
    align-items: start;
}

@media (min-width: 64rem) {
    .layout {
        grid-template-columns: minmax(0, 1fr) 20rem;
    }

    .layout--single {
        grid-template-columns: minmax(0, 1fr);
        max-width: 48rem;
    }

    /* The article draws the same two columns itself (see "Article"), so the frame hands it the
     * full width instead of a sidebar track of its own. */
    .layout--article {
        grid-template-columns: minmax(0, 1fr);
    }
}

.layout__main {
    min-width: 0;
}

.listing__header {
    margin-bottom: var(--space-5);
    padding-bottom: var(--space-4);
    border-bottom: 2px solid var(--fg);
}

.listing__header h1 {
    margin: 0;
    font-family: var(--font-heading);
    font-size: var(--step-4);
    line-height: 1.1;
    letter-spacing: -0.02em;
}

.listing__description {
    color: var(--fg-muted);
}

.empty {
    grid-column: 1 / -1;
    color: var(--fg-muted);
}

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

.grid {
    display: grid;
    gap: var(--card-gap);
    grid-template-columns: 1fr;
}

/* In one column a card's byline sits straight on the next card's picture, and a reader scrolling
 * a phone cannot tell where one article ends (owner, 2026-10-04): a hairline, as under the
 * featured card. From two columns the gap between the rows says it. */
.grid > .card:not(:first-child) {
    padding-top: var(--card-gap);
    border-top: 1px solid var(--line);
}

@media (min-width: 40rem) {
    .grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .grid > .card:not(:first-child) {
        padding-top: 0;
        border-top: 0;
    }
}

@media (min-width: 80rem) {
    .grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

/* An advertisement between the cards is a row of its own, never a third of one (MON-02). */
.grid > .ad-slot {
    grid-column: 1 / -1;
}

.card {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
}

.card__media {
    display: block;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--bg-sunken);
}

.card__media img {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

.card__body {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: var(--space-2);
}

.card__kicker,
.card__meta {
    display: flex;
    flex-wrap: wrap;
    /* A small row gap: a byline that wraps must not open a hole above the reading time. */
    gap: var(--space-1) var(--space-3);
    margin: 0;
    font-size: 0.8rem;
    color: var(--fg-muted);
}

.card__kicker a {
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    text-decoration: none;
}

.card__title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: var(--step-2);
    line-height: 1.25;
    letter-spacing: -0.01em;
}

.card__title a {
    color: var(--fg);
    text-decoration: none;
}

.card__title a:hover,
.card__title a:focus-visible {
    color: var(--accent);
}

.card__lead {
    margin: 0;
    color: var(--fg-muted);
}

/* In the grid the lead is a taster: three lines at most, so cards in a row stay even, and the
 * byline sits at the bottom of every card whatever the title and lead lengths. */
.grid .card__lead {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    font-size: 0.95rem;
    line-height: 1.5;
}

.grid .card__meta {
    margin-top: auto;
}

/* Compact density is for scanning many titles; the lead would undo it. */
:root[data-density="compact"] .grid .card__lead {
    display: none;
}

/* The featured item runs the width of the grid and gets the largest headline on the page. */
.card--featured {
    margin-bottom: var(--space-6);
    padding-bottom: var(--space-6);
    border-bottom: 1px solid var(--line);
}

.card--featured .card__title {
    font-size: var(--step-4);
}

@media (min-width: 64rem) {
    .card--featured .card__title {
        font-size: var(--step-5);
    }
}

/* --- Spotlight (ADR-66) -------------------------------------------------------------------
 * The featured articles one picture at a time, every title in a rail below. Each slide is a
 * Classic card, so a phone gets the card's own layout; wider up the text lies on the picture.
 * The row is a native scroll-snap strip, so a swipe and a page without JavaScript work for free;
 * spotlight.js moves it and keeps the time with the progress bar's own animation, so whatever
 * pauses that animation pauses the clock. The picture side stays dark in both schemes. The section is also
 * `.card--featured`, which gives it the featured card's spacing and its phone headline. */

.spotlight {
    --spotlight-interval: 7s;
    position: relative;
}

.spotlight__track {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    transition: opacity 0.2s;
}

/* With the script the bars and the buttons say where you are; without it the scrollbar must. */
:root[data-js="on"] .spotlight__track {
    scrollbar-width: none;
}

.spotlight__track.is-fading {
    opacity: 0;
}

.spotlight__slide {
    position: relative;
    flex: 0 0 100%;
    scroll-snap-align: start;
    scroll-snap-stop: always;
}

/* Keeps its height when an article has no picture at all, or the text would float over nothing. */
.spotlight .card__media {
    aspect-ratio: 16 / 9;
}

/* The slow zoom while a slide is shown: 7% over a little more than its time. For a reader who
 * asked for less motion base.css cuts it to one frame, which leaves a still, slightly closer crop. */
.is-zooming .card__media img {
    animation: spotlight-zoom calc(var(--spotlight-interval) + 2s) ease-out forwards;
}

@keyframes spotlight-zoom {
    to {
        transform: scale(1.07);
    }
}

.spotlight .card__lead {
    display: none;
}

/* Three lines at most, so the slides of a row stay close in height: the row is as tall as its
 * tallest slide, and a phone would otherwise show a hole under a short headline. */
.spotlight .card__title {
    font-size: clamp(var(--step-2), 3.2vw, var(--step-4));
    line-height: 1.12;
}

.spotlight .card__title,
.spotlight__rail a > span:last-child {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
}

/* Progress: segments over the picture on a phone, a bar above each rail title wider up. */
.spotlight__bars {
    position: absolute;
    inset: var(--space-3) var(--space-3) auto;
    display: flex;
    gap: 4px;
}

.spotlight__bar {
    flex: 1;
    height: 3px;
    overflow: hidden;
    border-radius: 2px;
    background: var(--line);
}

.spotlight__fill {
    display: block;
    height: 100%;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: left;
}

.spotlight__bars .spotlight__bar {
    background: rgb(255 255 255 / 0.4);
}

.spotlight__bars .spotlight__fill {
    background: #fff;
}

.spotlight[data-state="playing"] .is-current .spotlight__fill {
    animation: spotlight-progress var(--spotlight-interval) linear forwards;
}

.spotlight[data-state="stopped"] .is-current .spotlight__fill,
.is-past > .spotlight__fill {
    transform: none;
}

@keyframes spotlight-progress {
    to {
        transform: none;
    }
}

/* A mouse resting on the spotlight holds it; so does a hidden tab or the spotlight scrolled away.
 * `!important`, because the rules that start the bar and the zoom use the `animation` shorthand,
 * which sets the play state back to running and outranks a selector this short. */
@media (hover: hover) {
    .spotlight:hover * {
        animation-play-state: paused !important;
    }
}

.spotlight[data-hold] * {
    animation-play-state: paused !important;
}

.spotlight__controls {
    position: absolute;
    top: 1.5rem;
    right: var(--space-3);
    z-index: 1;
    display: flex;
    gap: var(--space-1);
}

.spotlight__controls button {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 1px solid rgb(255 255 255 / 0.3);
    border-radius: 50%;
    background: rgb(10 12 16 / 0.65);
    color: #fff;
    cursor: pointer;
}

.spotlight__controls button:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* The rotation button carries both pictures; the state shows one. */
.spotlight[data-state="playing"] .spotlight__play,
.spotlight:not([data-state="playing"]) .spotlight__pause {
    display: none;
}

.spotlight__rail {
    display: none;
}

/* Wider than a phone: the text lies on the picture and every title stands in the rail. */
@media (min-width: 48rem) {
    .spotlight__bars {
        display: none;
    }

    .spotlight .card__body {
        position: absolute;
        inset: auto 0 0;
        padding: 5rem var(--space-6) var(--space-5);
        border-radius: 0 0 var(--radius) var(--radius);
        background: linear-gradient(to top, rgb(10 12 16 / 0.92), rgb(10 12 16 / 0.7) 45%, transparent);
    }

    .spotlight .card__body p,
    .spotlight .card__body a {
        color: #fff;
    }

    .spotlight__rail {
        display: grid;
        grid-auto-columns: minmax(0, 1fr);
        grid-auto-flow: column;
        gap: var(--space-4);
        margin: var(--space-4) 0 0;
        padding: 0;
        font-size: 0.875rem;
        line-height: 1.3;
        list-style: none;
    }

    .spotlight__rail a {
        display: grid;
        gap: var(--space-1);
        color: var(--fg-muted);
        font-weight: 600;
        text-decoration: none;
    }

    .spotlight__rail a:hover,
    .spotlight__rail .is-current {
        color: var(--fg);
    }
}

/* The lead only where it fits under the title: two lines, never the whole. */
@media (min-width: 64rem) {
    .spotlight .card__lead {
        display: -webkit-box;
        overflow: hidden;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        max-width: 60ch;
    }
}

.badge--sponsored {
    padding: 0.1rem 0.4rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.7rem;
}

/* A preview served from a signed link (NR-05); readers never see this. */
.preview-banner {
    margin-bottom: var(--space-4);
    padding: var(--space-2) var(--space-3);
    border: 1px dashed var(--line);
    border-left: 4px solid var(--accent);
    border-radius: 0.25rem;
    color: var(--fg-muted);
    font-size: 0.9rem;
}

/* --- Article ----------------------------------------------------------------------------- */

.breadcrumbs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    font-size: 0.8rem;
    color: var(--fg-muted);
}

.breadcrumbs a {
    text-decoration: none;
}

.breadcrumbs a + a::before {
    content: "›";
    margin-right: var(--space-2);
    color: var(--fg-muted);
}

.article__header {
    margin-block: var(--space-4) var(--space-5);
}

.article__badges {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin: 0 0 var(--space-3);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.article__badges a {
    color: var(--accent);
    text-decoration: none;
}

.article__title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: var(--step-4);
    line-height: 1.1;
    letter-spacing: -0.025em;
}

@media (min-width: 48rem) {
    .article__title {
        font-size: var(--step-5);
    }
}

.article__lead {
    margin: var(--space-4) 0 0;
    font-size: var(--step-1);
    color: var(--fg-muted);
}

/* What "Sponsored" means here, in the portal's own words (MON-04). */
.article__disclosure {
    margin: var(--space-3) 0 0;
    font-size: 0.875rem;
    color: var(--fg-muted);
}

.article__translations {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin: var(--space-3) 0 0;
    font-size: 0.85rem;
    color: var(--fg-muted);
}

.article__translations a {
    color: var(--accent);
    font-weight: 600;
}

.article__byline {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin: var(--space-4) 0 0;
    font-size: 0.85rem;
    color: var(--fg-muted);
}

.article__hero {
    margin: 0 0 var(--space-5);
}

.article__hero img {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: var(--radius);
    background: var(--bg-sunken);
}

.article__hero figcaption {
    margin-top: var(--space-2);
    font-size: 0.8rem;
    color: var(--fg-muted);
}

/* Only a separator when there is something on both sides of it. */
.article__hero .caption + .credit::before {
    content: "· ";
}

.article__sources,
.article__tags,
.share,
.author-box,
.related {
    margin-top: var(--space-6);
    padding-top: var(--space-4);
    border-top: 1px solid var(--line);
}

.article__sources h2,
.article__tags-title,
.share__title,
.related__title {
    margin: 0 0 var(--space-2);
    font-size: var(--step-0);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--fg-muted);
}

.article__sources ul {
    margin: 0;
    padding-left: var(--space-5);
}

.article__tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0;
}

.article__tags a {
    padding: 0.15rem 0.6rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    font-size: 0.85rem;
    text-decoration: none;
}

.share__list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.share__link {
    display: inline-block;
    padding: 0.3rem 0.8rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--bg-raised);
    color: var(--fg);
    font: inherit;
    font-size: 0.85rem;
    text-decoration: none;
    cursor: pointer;
}

.share__link:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.author-box {
    display: flex;
    gap: var(--space-4);
    align-items: flex-start;
}

.author-box__avatar {
    flex: none;
    border-radius: 50%;
}

.author-box__text p {
    margin: 0 0 var(--space-2);
}

.author-box__name {
    font-weight: 700;
}

.author-box__bio,
.author-box__more {
    font-size: 0.9rem;
    color: var(--fg-muted);
}

.related__list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.related__item {
    padding: var(--space-2) 0;
}

.related__item + .related__item {
    border-top: 1px solid var(--line);
}

.related__item a {
    display: block;
    font-weight: 600;
    text-decoration: none;
}

.related__meta {
    font-size: 0.85rem;
    color: var(--fg-muted);
}

/* Wide screens give the article the listings' columns: text and what follows it on the left, its
 * tags and share buttons in a column that follows the reader like the listings' sidebar does.
 * The widths and gap are the ones `.layout` uses, so the text lines up with the header. */
@media (min-width: 64rem) {
    .article--with-aside {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 20rem;
        grid-template-areas:
            "main aside"
            "after aside";
        column-gap: var(--space-6);
        align-items: start;
    }

    .article--with-aside > .article__main {
        grid-area: main;
        min-width: 0;
    }

    .article--with-aside > .article__after {
        grid-area: after;
        min-width: 0;
    }

    .article--with-aside > .article__aside {
        grid-area: aside;
        position: sticky;
        top: calc(var(--header-offset, var(--header-height)) + var(--space-4));
        display: flex;
        flex-direction: column;
        gap: var(--space-5);
    }

    /* Boxed like the listings' widgets rather than ruled like the sections under the text. */
    .article__aside > .article__tags,
    .article__aside > .share {
        margin-top: 0;
        padding: var(--space-4);
        background: var(--bg-raised);
        border: 1px solid var(--line);
        border-radius: var(--radius);
    }

    .article__aside .article__tags-title,
    .article__aside .share__title {
        margin-bottom: var(--space-3);
        font-size: 0.8rem;
        letter-spacing: 0.08em;
    }
}

/* --- Sidebar ----------------------------------------------------------------------------- */

.sidebar {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    min-width: 0;
}

@media (min-width: 64rem) {
    /* Short today — two of its widgets belong to the newsletter and monetization stages — so it
     * follows the reader rather than leaving a column of nothing beside a long listing. */
    .sidebar {
        position: sticky;
        top: calc(var(--header-offset, var(--header-height)) + var(--space-4));
    }
}

.widget {
    padding: var(--space-4);
    background: var(--bg-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius);
}

.widget__title {
    margin: 0 0 var(--space-3);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--fg-muted);
}

/* Support us (MON-08): a link in the theme's widget frame, not a payment widget. */
.support-link {
    font-weight: 600;
}

.widget--support p {
    margin: 0;
}

/* The newsletter box (ADR-41 §15) wears the same `.widget` frame: a link, never a form. Under an
 * article it stands away from the text, where finishing the article leads. */
.newsletter-box p {
    margin: 0 0 var(--space-2);
}

.newsletter-box__link {
    font-weight: 600;
}

.article__after > .newsletter-box {
    margin-top: var(--space-6);
}

/* Most read (MON-06). A numbered list, because the order is the whole point of it; the numbers
 * sit inside so a long headline wraps under itself rather than under the number. */
.most-read {
    margin: 0;
    padding: 0 0 0 1.25rem;
    display: grid;
    gap: var(--space-3);
}

.most-read__item {
    font-size: 0.9rem;
    line-height: 1.35;
}

.most-read__item a {
    text-decoration: none;
    font-weight: 600;
}

.most-read__item a:hover {
    text-decoration: underline;
}

.tag-cloud {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0;
}

.tag {
    padding: 0.15rem 0.6rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--bg);
    text-decoration: none;
    font-size: 0.85rem;
}

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

.pagination {
    grid-column: 1 / -1;
    display: flex;
    justify-content: center;
    margin-top: var(--space-5);
}

.pagination__more {
    padding: var(--space-3) var(--space-6);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--bg-raised);
    color: var(--fg);
    font-weight: 600;
    text-decoration: none;
}

.pagination__more:hover,
.pagination__more:focus-visible {
    border-color: var(--accent);
    color: var(--accent);
}

/* --- Author page ------------------------------------------------------------------------- */

.author {
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

.author__avatar {
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    object-fit: cover;
}

.author__bio {
    margin: var(--space-2) 0 0;
    color: var(--fg-muted);
}

/* --- Footer ------------------------------------------------------------------------------ */

.site-footer {
    margin-top: var(--space-7);
    padding-block: var(--space-6);
    border-top: 1px solid var(--line);
    background: var(--bg-sunken);
    color: var(--fg-muted);
    font-size: 0.9rem;
}

.site-footer .menu {
    flex-wrap: wrap;
}

.site-footer__text,
.site-footer__legal {
    margin: var(--space-3) 0 0;
}
