/*
 * The post card, its pictures, and its actions menu.
 *
 * The card is the unit the whole social side is built from: it is what a feed is a list of, what a profile
 * timeline is a list of, and what a post's own page is one of. So it must look right in a narrow column and
 * on its own, and it must not depend on its container for anything but width.
 *
 * ### It is an `<article>`, not a `.card`
 *
 * `cards.css` styles a container of prose on a raised surface. A post is that plus a header of identity, a
 * footer of actions and a conversation, and the padding it needs differs per region — pictures go edge to
 * edge, text does not. Inheriting `.card` and then overriding its padding four times would be worse than
 * one honest set of rules, so the visual language (surface, border, radius, shadow) is shared through the
 * tokens rather than through the class.
 *
 * ### Pictures
 *
 * `post-media--count-N` gives the grid, so the arrangement is decided by how many there are: one fills the
 * width, two sit side by side, three make a large one with two stacked beside it, four make a square. The
 * count comes from the server, so the layout is settled before the first byte of any image arrives — and the
 * template emits the stored width and height, so nothing reflows as they load.
 *
 * `aspect-ratio` with `object-fit: cover` means a portrait photograph is cropped rather than allowed to make
 * one cell three times taller than its neighbours. The full picture is one press away on the post's page.
 *
 * ### The actions menu is a `<details>`
 *
 * No script, no focus trap, no ARIA to get wrong, and it works before the JavaScript loads — which matters,
 * because "delete" living behind a control that needs a script to open is a control that can disappear. The
 * panel is absolutely positioned so opening it does not push the post below it down the page.
 */

.post-card {
    background-color: var(--colour-surface-raised);
    border: var(--border-width) solid var(--colour-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-raised);
    padding: var(--space-5);
    transition:
        border-color var(--duration-base) var(--easing),
        box-shadow var(--duration-base) var(--easing);
}

/* A card deepens its shadow under the pointer rather than moving: feedback that the feed is made of
   objects, without anything shifting under the eye. */
.post-card:hover {
    border-color: var(--colour-border-strong);
    box-shadow: var(--shadow-md);
}

.post-card__header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--space-4);
}

.post-card__author {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
    color: inherit;
    text-decoration: none;
}

.post-card__author:hover .post-card__name,
.post-card__author:focus-visible .post-card__name {
    color: var(--colour-primary);
    text-decoration: underline;
}

.post-card__identity {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.post-card__name {
    font-weight: var(--weight-medium);
    line-height: var(--leading-tight);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.post-card__handle {
    color: var(--colour-ink-quiet);
    font-size: var(--text-sm);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Time, edit note and visibility badge, pushed to the trailing edge and allowed to wrap under each other on
   a narrow screen rather than squeezing the name. */
.post-card__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-inline-start: auto;
}

.post-card__permalink {
    color: inherit;
    text-decoration: none;
}

.post-card__permalink:hover .post-card__time,
.post-card__permalink:focus-visible .post-card__time {
    color: var(--colour-primary);
    text-decoration: underline;
}

.post-card__edited {
    font-style: italic;
}

.post-card__body {
    margin-top: var(--space-4);
    max-width: var(--measure);
    line-height: var(--leading-body);
    /* Posts are written by people, not typeset: a pasted URL or an unbroken run of characters has to be
       allowed to break, or it widens the card and the column it is in. */
    overflow-wrap: break-word;
}

.post-media {
    display: grid;
    gap: var(--space-2);
    margin: var(--space-4) 0 0;
    padding: 0;
    list-style: none;
}

.post-media__item {
    margin: 0;
    overflow: hidden;
    border-radius: var(--radius-md);
    background-color: var(--colour-surface-sunken);
}

.post-media__image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.post-media--count-1 .post-media__item {
    aspect-ratio: 16 / 10;
}

.post-media--count-2,
.post-media--count-4 {
    grid-template-columns: 1fr 1fr;
}

.post-media--count-2 .post-media__item,
.post-media--count-4 .post-media__item {
    aspect-ratio: 1 / 1;
}

/* One tall picture leading, two stacked beside it. The first item spans both rows, so the block stays a
   rectangle whatever the three pictures are shaped like. */
.post-media--count-3 {
    grid-template-columns: 2fr 1fr;
    grid-template-rows: 1fr 1fr;
}

.post-media--count-3 .post-media__item:first-child {
    grid-row: span 2;
}

.post-media--count-3 .post-media__item {
    aspect-ratio: auto;
    min-height: 6rem;
}

/* A Blink, the published 30-second video. A post carries at most one, so the item always fills the
   single-media shape — its own ratio, because a video's stored dimensions are unknown (the probe
   measures duration, not frames). The element renders paused: `controls` and `preload="metadata"`,
   never `autoplay` — nothing on this platform plays without a press. */
.post-media__item--blink {
    aspect-ratio: 16 / 9;
    background-color: #000;
}

.post-media__blink {
    position: relative;
    width: 100%;
    height: 100%;
}

.post-media__video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    background-color: #000;
}

/* The badge naming the Blink and the server-measured length, out of the controls' way at the top
   corner. Letters the server sent; the shape is the only thing the stylesheet adds. */
.post-media__badge {
    position: absolute;
    top: var(--space-2);
    inset-inline-end: var(--space-2);
    padding: var(--space-1) var(--space-2);
    background: color-mix(in srgb, #000 65%, transparent);
    border-radius: var(--radius-full);
    color: #fff;
    font-size: var(--text-sm);
    line-height: 1;
    pointer-events: none;
}

.post-card__footer {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    margin-top: var(--space-4);
    padding-top: var(--space-3);
    border-top: var(--border-width) solid var(--colour-border);
}

.post-card__comments-link {
    color: var(--colour-ink-quiet);
    font-size: var(--text-sm);
}

.post-card__comments {
    margin-top: var(--space-4);
}

.post-card__more-comments {
    display: inline-block;
    margin-top: var(--space-2);
    font-size: var(--text-sm);
}

.post-menu {
    position: relative;
}

/* The default marker is removed on both spellings: one is the standard, the other is what WebKit still
   uses, and a stray triangle beside a word that is already a button reads as a bullet. */
.post-menu__toggle {
    display: inline-flex;
    align-items: center;
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    color: var(--colour-ink-quiet);
    cursor: pointer;
    font-size: var(--text-sm);
    list-style: none;
}

.post-menu__toggle::-webkit-details-marker {
    display: none;
}

.post-menu__toggle::marker {
    content: "";
}

.post-menu__toggle:hover {
    background-color: var(--colour-surface-sunken);
    color: var(--colour-ink);
}

.post-menu__toggle {
    transition:
        background-color var(--duration-fast) var(--easing),
        color var(--duration-fast) var(--easing);
}

.post-menu__panel {
    position: absolute;
    inset-inline-end: 0;
    z-index: var(--layer-overlay);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 14rem;
    margin-top: var(--space-1);
    padding: var(--space-3);
    background-color: var(--colour-surface-overlay);
    border: var(--border-width) solid var(--colour-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-overlay);
}

.post-menu__item {
    font-size: var(--text-sm);
}

.post-menu__form {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0;
}

.post-menu__form + .post-menu__form {
    padding-top: var(--space-3);
    border-top: var(--border-width) solid var(--colour-border);
}

/* The panel is narrower than the page, and a `<select>` sizes itself to its widest option: "Followers only"
   in a long translation would otherwise push the panel wider than the card it hangs off. */
.post-menu__select {
    width: 100%;
}

.post-menu__submit {
    align-self: flex-start;
}

/* ---- The link card --------------------------------------------------------------------------- */

/*
 * The page the author named. It reads as furniture of the post: sunken surface, hairline border, the
 * host first and small, then the title, then a short description. A preview without an image is still
 * a card worth drawing; one with an image lays it along the leading edge, sized to a square so a page's
 * own banner cannot dictate the card's height.
 *
 * In a published post the card is an `<a>`; while staged in the composer it is a `<div>` with a dismiss
 * control instead, so only the link form answers to hover.
 */
.link-card {
    position: relative;
    display: flex;
    gap: var(--space-3);
    margin-top: var(--space-4);
    padding: var(--space-3);
    background-color: var(--colour-surface-sunken);
    border: var(--border-width) solid var(--colour-border);
    border-radius: var(--radius-md);
    color: inherit;
    text-decoration: none;
    overflow: hidden;
    transition:
        border-color var(--duration-fast) var(--easing),
        background-color var(--duration-fast) var(--easing);
}

a.link-card:hover,
a.link-card:focus-visible {
    border-color: var(--colour-border-strong);
    background-color: color-mix(in srgb, var(--colour-surface-sunken) 72%, var(--colour-primary-surface));
}

.link-card__image {
    flex: none;
    width: 5.5rem;
    height: 5.5rem;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background-color: var(--colour-surface);
}

.link-card__text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.link-card__host {
    font-size: var(--text-xs);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--colour-ink-faint);
}

.link-card__title {
    font-weight: var(--weight-medium);
    line-height: var(--leading-tight);
    /* Two lines are enough to recognise a page; more would let the card compete with the post. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

a.link-card:hover .link-card__title,
a.link-card:focus-visible .link-card__title {
    color: var(--colour-primary);
}

.link-card__description {
    font-size: var(--text-sm);
    color: var(--colour-ink-quiet);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Staged in the composer: the staging band apportions the spacing, and the text keeps clear of the
   dismiss disc above its corner. */
.link-card--staged {
    margin-top: 0;
}

.link-card--staged .link-card__text {
    padding-inline-end: var(--space-6);
}

/* ---- Truncation and "read more" -------------------------------------------------------------- */

/*
 * A list card shows roughly two lines of a long body and leaves the rest one press away. The clamp
 * is the browser's line clamp, so the cut happens at a line boundary whatever the language or the
 * width; the server decides which bodies are long enough to clamp, and the class arrives with the
 * markup — nothing here measures.
 *
 * Expanding removes the class and nothing re-applies it: a card a reader has opened stays open.
 */
.post-card__body--clamped {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.post-card__read-more {
    display: inline-block;
    margin-top: var(--space-2);
    color: var(--colour-primary);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    text-decoration: none;
}

.post-card__read-more:hover,
.post-card__read-more:focus-visible {
    text-decoration: underline;
}

/* ---- Hashtags in the body --------------------------------------------------------------------- */

/* A tag reads as part of the sentence until the pointer reaches it: colour alone, no underline. */
.post-hashtag {
    color: var(--colour-primary);
    text-decoration: none;
}

.post-hashtag:hover,
.post-hashtag:focus-visible {
    text-decoration: underline;
}

/* ---- Readership in the footer ------------------------------------------------------------------ */

/* The view count sits at the trailing edge: reactions and comments invite action, the count merely
   reports, so it is the quietest thing in the row and the furthest from the actions. */
.post-card__views {
    margin-inline-start: auto;
    color: var(--colour-ink-faint);
    font-size: var(--text-sm);
    white-space: nowrap;
}
