/* blogs.css — the blog page and the blogs index.
   Page-scoped: referenced from those views' @section Styles, never from _Layout
   (Systems/StaticAssets.md §4.1).

   Class naming follows UI/ClassNaming.md: component-scoped names carry the `blog-` prefix rather
   than `gp-`, because they are specific to this feature. Every `js-` class in these views is a
   JS-only hook and MUST NOT appear in this file. */

/* ---------------------------------------------------------------- header */

/* Pairs with .page-head on the same element (UI/PageHeading.md). .page-head owns the bottom margin;
   this only adds the flex row, so the page controls can sit to the right of the heading block.
   NO margin-bottom here — it would be a second source for a value .page-head already sets. */
.blog-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
}

.blog-header-titles {
    min-width: 0;
}

/* SUPERSEDED 2026-08-06 — the <h1> carries the section name ("Blog") now and takes the standard
   heading styles untouched. This class existed to zero the h1's margin while it held the blog's
   name, which is exactly the override that made the title not match the standard.
   The blog's name moved to .gp-page-subtitle, per UI/PageHeading.md.
.blog-title {
    margin: 0;
    overflow-wrap: anywhere;
}
*/

/* The <h1> is the blog's name, in a flex row so the standing badge and the rename control sit beside
   it (UI/PageHeading.md records this page's departure and why).

   THE 0.25rem THE STANDARD h1 CARRIES IS MOVED TO THE ROW, NOT DELETED. Inside a flex row with
   align-items: center the heading's own bottom margin offsets it against the badge beside it, so the
   row holds the spacing instead and the vertical rhythm below the heading is unchanged. This is not
   the old `.blog-title { margin: 0 }` — that removed the gap entirely. */
.blog-title-row {
    margin-bottom: 0.25rem;
}

.blog-title-row h1 {
    margin-bottom: 0;
    overflow-wrap: anywhere;
}

/* SUPERSEDED 2026-08-06 — the identity line uses the standard .page-sub now (0.813rem, --ink-3,
   margin-top 0.25rem). This was a third bespoke variant of the same muted line and differed from the
   standard only by drift.
.blog-author {
    margin: 0.15rem 0 0;
    color: var(--ink-3);
    font-size: 0.9rem;
}
*/

/* Card controls are right-aligned by default — .action-cell handles the spacing, and this must not
   override justify-content on it. */
.blog-header-controls {
    flex-shrink: 0;
}

/* ---------------------------------------------------------------- split proportions */

/* The blog page's two columns are 2/8 and 6/8 of the row, per specification.

   The SHARED .gp-split-left is a fixed 13rem with flex-shrink: 0 — correct for the pages that use
   it as a narrow picker, and depended on by them — so this overrides it here rather than changing
   the shared rule. Both children are given flex-basis 0 so the 2:6 ratio governs the whole row
   rather than being applied to leftover space after content sizing.

   Specificity 0,2,0 beats the shared 0,1,0 regardless of file order, so this cannot be defeated by
   a change to the cascade. Everything else .gp-split-left provides — sticky positioning, the
   max-height cap, gp-split.js's runtime measurement — is deliberately left intact. */
.blog-split > .gp-split-left {
    width: auto;
    flex: 2 1 0;
}

.blog-split > .gp-split-right {
    flex: 6 1 0;
}

/* ---------------------------------------------------------------- standing badge */

/* SUPERSEDED 2026-08-06 — the standing badges now use the shared .gp-badge with .gp-badge-accent
   (Featured) and .gp-badge-bad (Suspended). See UI/Badges.md.

   The premise of the original comment below was already wrong when written and is worth keeping as
   the reason this was replaced: it says there is no reusable badge class in this project, so each
   component defines its own. .gp-tag existed at the time; it was simply not found. That is exactly
   how the fourth private badge gets written, and it is why the standard is now documented rather
   than merely present.

   Both colours survive the move intact — .gp-badge-accent was added to the shared set specifically
   so Featured keeps following the 7 theme palettes instead of being pinned to a fixed hex.

   WHAT CHANGED VISUALLY: the badges are no longer uppercase, bold or letter-spaced, and they are
   0.688rem at 0.188rem radius rather than 0.65rem at 0.375rem. That is the standard, and matching it
   is the point — the shout now comes from the colour rather than the casing.

.blog-standing-badge {
    display: inline-block;
    padding: 0.15rem 0.45rem;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03rem;
    line-height: 1;
    white-space: nowrap;
}

.blog-standing-featured {
    color: var(--accent-glow);
    border-color: var(--accent);
}

.blog-standing-suspended {
    color: var(--bad);
    border-color: var(--bad);
}
*/

/* ---------------------------------------------------------------- inline rename */

/* Mirrors the survey entry rename (survey-results.css) — same structure, same 0.875rem masked
   icons, and the same three existing SVGs rather than new artwork. The name is edited in place
   beside the heading; there is no separate panel. */

.blog-title-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.blog-title-edit {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.blog-title-input {
    max-width: 18rem;
}

.blog-rename-error {
    margin-bottom: 1rem;
}

.blog-rename-icon,
.blog-tick-icon,
.blog-cancel-icon {
    display: inline-block;
    width: 0.875rem;
    height: 0.875rem;
    background-color: currentColor;
}

.blog-rename-icon { mask: url('/img/rename.svg') no-repeat center / contain; -webkit-mask: url('/img/rename.svg') no-repeat center / contain; }
.blog-tick-icon { mask: url('/img/tick.svg') no-repeat center / contain; -webkit-mask: url('/img/tick.svg') no-repeat center / contain; }
.blog-cancel-icon { mask: url('/img/cancel.svg') no-repeat center / contain; -webkit-mask: url('/img/cancel.svg') no-repeat center / contain; }

/* ---------------------------------------------------------------- fields */

.blog-field-label {
    display: block;
    margin-bottom: 0.25rem;
    font-size: 0.85rem;
    color: var(--ink-3);
}

.blog-text-input,
.blog-select {
    width: 100%;
    max-width: 30rem;
}

/* Separates the title field from the audience controls beneath it. On the RELATIONSHIP rather than
   on either element: .blog-field-label carries a bottom margin and no top one, so a label following
   a field sits flush against it. Putting the gap here means neither the input nor the label ends up
   with a margin that only makes sense when the other is present. */
.blog-text-input + .blog-field-label {
    margin-top: 1rem;
}

/* The selected audience's description, under the picker. Smaller than the field it explains, and in
   the informational colour — var(--accent-2) is the project's semantic "info" (UI/Notices.md's
   colour reference), the same token .gp-notice-info is built on. Not a fixed hex, so it follows
   every theme. */
.blog-visibility-help {
    margin: 0.25rem 0 0.75rem;
    font-size: 0.75rem;
    color: var(--accent-2);
}

/* ---------------------------------------------------------------- sidebar list */

/* SUPERSEDED 2026-08-06 — the sidebar no longer wraps its rows in a list.
   The rows are flat <button> children of .gp-split-left-body now, matching Loot Distribution and
   Roster/Manage. This rule reset the <ul>'s own margin and padding, but it could not reach the one
   that mattered: site.css's global `ol li, ul li { margin-bottom: 0.4rem }` put a gap under every
   row, which is the whole reason those two pages use divs. See UI/Layout.md.
.blog-publication-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
*/

/* The button reset plus the STANDARD left-panel row metrics (UI/Layout.md → "Left panel — row
   metrics"). Interaction — cursor, hover and the .is-active highlight — comes from the shared
   .gp-split-left-row alongside it.

   CORRECTED 2026-08-06. These rows were 0.5rem/1rem padding over a `var(--line)` divider, which is
   the LIGHT line (#292e48) rather than the soft one (#1d2138) the two existing panels use. Against
   the card background that reads as a visible separation between rows instead of a divider, and the
   taller padding widened it further. Now matched to Loot Distribution's boss column and the
   Roster/Manage roster list exactly:
     - --line-soft divider, and none on the last row (it would double with the card edge)
     - 0.438rem vertical padding
     - 1.625rem left padding, which leaves room for the selected accent

   NO TRANSPARENT LEFT BORDER HERE, unlike the two reference rows. They draw their accent with
   border-left-color, so they must reserve the 2px up front or the text jumps when a row is selected.
   This row takes its accent from .gp-split-left-row.is-active, which is an INSET box-shadow drawn
   inside the padding box — it occupies no layout space, so a transparent border would only push the
   content 2px further in than the panels it is meant to match.

   `background: none` is safe against the shared states: .gp-split-left-row.is-active is 0,2,0 and
   wins, and its :hover is 0,1,1 and wins. A bespoke cursor and a flat :hover used to live here —
   both deleted rather than kept in step, since this file loads after site.css and would silently
   have beaten the shared gradient. */
.blog-publication-link {
    display: block;
    width: 100%;
    padding: 0.438rem 0.875rem 0.438rem 1.625rem;
    background: none;
    border: none;
    border-bottom: 1px solid var(--line-soft);
    text-align: left;
    color: inherit;
    transition: background 0.12s;

    /* Added 2026-08-07 with UI/Layout.md's new font-size row metric.

       These rows are <button> elements and had NO font declaration at all, so they were falling
       through to the UA default — Arial at about 13.3px — rather than to anything on the page.
       There is no global `button { font: inherit }` in this project; the only two such rules are
       scoped to .toggle-pill .seg and to textarea/input. So the sidebar was rendering in the wrong
       TYPEFACE, which is the more visible half of the problem and easy to misread as a size issue.

       `font: inherit` first for the family and weight, then the size — 0.781rem is the panel-row
       metric shared with .loot-boss-row and .roster-list-date.

       .blog-publication-title is a span inside this button and inherits both; .blog-publication-date
       keeps its own smaller 0.688rem as the secondary line. */
    font: inherit;
    font-size: 0.781rem;
}

/* The last divider would otherwise sit directly on the card's own edge and read as a double line.
   The rows are direct children of .gp-split-left-body now, so :last-child selects the real last row
   — while they were wrapped in <li> it was true of every one of them. */
.blog-publication-link:last-child {
    border-bottom: none;
}

.blog-publication-title {
    display: block;
    overflow-wrap: anywhere;
}

/* A SIDEBAR/LIST ROW's meta line, under the title: date left, tags right, on one row. space-between
   rather than a margin on either child, so the date still sits left when a reader receives no tags
   at all. align-items: flex-end keeps the date's baseline with the badges when the tags wrap.

   RENAMED from .blog-publication-meta 2026-08-06 — that name was already taken by the article card's
   own meta strip further down this file, and the two rules were merging into each other. Both are
   "meta", but one belongs to a list row and the other to the card. */
.blog-row-meta {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.4rem;
    margin-top: 0.25rem;
}

/* .gp-badge-row is already a flex container; this only stops it stretching and lets it keep its
   natural width so space-between can push it right. It sets no justify-content of its own, so
   flex-end adds to the shared class rather than fighting it — it matters when the tags wrap. */
.blog-publication-tags {
    justify-content: flex-end;
    min-width: 0;
}

/* Modelled on .roster-list-time from the Roster/Manage sidebar item (--ink-3, nowrap, secondary to the
   line beside it), one step larger at 0.688rem — the project's most common small-text size — and with
   a little space before the title beneath.

   NOT the Roster list's DATE style: .roster-list-date is 0.781rem/--ink-2 and is that row's primary
   value, while here the title is primary and the date is the secondary line, which is the job
   .roster-list-time does there.

   Values copied rather than the class reused: .roster-list-time is component-scoped to the roster
   sidebar (UI/ClassNaming.md), and a fifth unrelated page borrowing a roster- name is the problem
   already recorded against .roster-list-item — RENAMED .gp-panel-row 2026-08-18 — in
   UI/Layout.md. Both collapse together when that
   consolidation happens. */
/* Left of the meta line, with the tags pushed to the right of the same row. Modelled on
   .roster-list-time from the Roster/Manage sidebar item (--ink-3, nowrap, secondary to the line above
   it), one step larger at 0.688rem — the project's most common small-text size.

   flex-shrink: 0 so a long run of tags never squeezes the date into wrapping; it is the fixed value
   on the row and the tags are the ones that should wrap. */
.blog-publication-date {
    font-size: 0.688rem;
    color: var(--ink-3);
    white-space: nowrap;
    flex-shrink: 0;
}

.blog-empty {
    padding: 0.75rem 1rem;
}

/* ---------------------------------------------------------------- manage tabs */

/* Tab panels on ManageBlogs. Only the active one is shown; blog-manage.js owns which.
   Tab content sits flush with the bottom of the tabs (UI/TabsAndPanels.md), so the
   panel adds no top margin of its own — same rule the Archives page follows. */
.blog-manage-panel {
    display: none;
}

.blog-manage-panel-active {
    display: block;
}

/* ---------------------------------------------------------------- publication */

/* The card's header region. It is a <header> element, so it inherits the SITE header's styling from
   site.css's bare `header` rule — a gradient background, a bottom border, and `position: sticky;
   top: 0; z-index: 100`. All of that belongs to the page bar at the top of the window and none of it
   belongs inside a card, so it is reset here.

   Reset on the card rather than by narrowing the global rule: the global one is the page chrome's
   and is left alone deliberately. */
/* No margin-bottom: the .gp-card-divider that follows carries its own 0.5rem above and below, and
   two sources of the same gap is how the spacing drifts. */
.blog-publication-header {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    background: none;
    border-bottom: none;
    position: static;
    z-index: auto;
}

/* Top right of the card. margin-left: auto rather than justify-content: space-between on the header,
   because the meta group beside it is often EMPTY — an ordinary reader gets no badges and no "edited"
   — and space-between would then leave the date sitting on the left. An auto margin puts it right
   whether or not it has a sibling. */
.blog-publication-card-date {
    margin-left: auto;
    flex-shrink: 0;
    font-size: 0.688rem;
    color: var(--ink-3);
    white-space: nowrap;
}

.blog-publication-heading {
    margin: 0 0 0.35rem;
    overflow-wrap: anywhere;
}

/* The card's own meta group — the left half of the header strip, beside the date. Distinct from
   .blog-row-meta above, which is a list row's. */
.blog-publication-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    font-size: 0.85rem;
    color: var(--ink-3);
}

/* Sits under the title now, so it carries its own size and colour — it used to inherit both from
   .blog-publication-meta in the header strip. margin-bottom: 0 because the global `p` rule would
   otherwise add a rem beneath it (UI/Notices.md records the same trap for notices). */
.blog-publication-edited {
    margin: 0 0 0.35rem;
    font-style: italic;
    font-size: 0.85rem;
    color: var(--ink-3);
}

/* The "For" label and its .gp-badge-row of target teams. A row rather than badges inline in prose
   (UI/Badges.md), so the label sits on the same line as the badges and the row's gap replaces the
   comma separators this used to carry. */
/* Superseded 2026-08-07 — the target teams are badges in the header meta strip now, and
   .blog-publication-meta already supplies the flex row, wrapping and gap this duplicated.

   Its `margin: 0.4rem 0 0` is why it moved: no bottom margin, sitting directly above a post body
   whose first paragraph has no top margin either, so the badges ran into the prose.

.blog-publication-teams {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin: 0.4rem 0 0;
    font-size: 0.85rem;
    color: var(--ink-3);
}
*/

/* Superseded 2026-08-07 with the rule above — it existed only to stop the "For" label taking its
   own line beside the team badges, and both the label and its container went when the badges moved
   into the header meta strip.

.blog-publication-teams .role-detail-label {
    display: inline;
    margin-top: 0;
}
*/

/* The card's footer region — same story as the header above. As a <footer> element it inherits the
   SITE footer from site.css: a gradient background, a top border, centred text, 1rem 2rem padding
   and 0.75rem muted type. The action row needs none of it, and the centring and padding would fight
   .action-cell's right alignment. */
.blog-publication-footer {
    margin-top: 0;
    background: none;
    border-top: none;
    text-align: left;
    padding: 0;
    font-size: inherit;
    color: inherit;
    position: static;
    z-index: auto;
}

/* SUPERSEDED 2026-08-06 — all three are now the shared .gp-badge (UI/Badges.md). They carried no
   styling of their own beyond the shape, so nothing was lost by dropping them entirely rather than
   keeping three aliases.

   These were the furthest-out badges in the project, off on three dimensions at once: a 0.875rem
   radius against a house value of 0.188rem — the CARD radius on an inline chip, which is why they
   read as a different design language — the largest badge text anywhere at 0.75rem, and no
   font-weight where every other badge sets one.

   The context they render in is unchanged and still worth knowing: these are author- and
   moderator-facing only. An ordinary reader never sees one, because to them an unapproved
   publication does not exist at all (Concepts/Blogs.md B29).

.blog-status-tag,
.blog-visibility-tag,
.blog-team-tag {
    display: inline-block;
    padding: 0.05rem 0.4rem;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    font-size: 0.75rem;
    white-space: nowrap;
}
*/

/* ---------------------------------------------------------------- editor */

/* ---------------------------------------------------------------- mirrored control rows */

/* The copies of the footer control rows that sit ABOVE the content, so a long publication does not
   have to be scrolled past to be acted on (UI/RichTextEditor.md rule 1, the mirrored pair).

   .action-cell already spaces and right-aligns the buttons — these rules only supply the gap to the
   content below, which is the one thing a footer's margin cannot do from the other side. */
.blog-publication-topbar {
    margin-bottom: 0.75rem;
}

/* The editor's copy shares its line with the "Post" label, so the row is a flex line rather than a
   block: label left, controls right. .action-cell is display:flex, so it needs no width of its own
   and space-between does the separating — never margin-left:auto on the controls, which would drag
   the whole set left (UI/Cards.md). */
.blog-editor-labelrow {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.25rem;
}

/* The label carries its own bottom margin as a block; inside the flex row that margin would push
   the two sides out of line. */
.blog-editor-labelrow .blog-field-label {
    margin-bottom: 0;
}

.blog-editor-footer {
    margin-top: 1rem;
}

.blog-team-options {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    margin-bottom: 0.75rem;
}

/* Superseded 2026-08-07 — each team is now a toggle button, so `.btn` supplies the whole box:
   inline-flex, centring, border, background, border-radius and cursor. Every declaration below had
   an exact counterpart there.

.blog-team-option {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    cursor: pointer;
}
*/

/* The checkbox is HIDDEN, not removed — it is still the state that collectTeamIds() reads, and the
   <label> wrapper is what makes the button clickable. This is the only rule the pattern needs;
   `.btn` and `.btn-active` supply the rest and are not restated. */
.blog-team-option input[type="checkbox"] { display: none; }

/* ---------------------------------------------------------------- index cards */

/* ---------------------------------------------------------------- home page cards */

/* The hero's card row: survey and blogs, two columns, filled in document order.

   AUTO-PLACEMENT IS THE FEATURE. "Blog card second when a survey is open, first otherwise" needs no
   condition anywhere — the survey card is not emitted when no survey is open, so the blog card
   becomes the first grid item and lands in column one by itself.

   align-items: start so a short card keeps its own height instead of stretching to match the taller
   one beside it. */
.welcome-cards {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
    gap: 1.25rem;
    margin-top: 1.75rem;
}

/* .welcome-survey-card carries its own max-width and top margin for the single-column layout it was
   built for; inside the grid the column decides both. */
.welcome-cards > .welcome-survey-card {
    max-width: none;
    margin-top: 0;
    min-width: 0;
}

.welcome-blog-card {
    min-width: 0;
}

/* The B29.1 audience totals, sitting together under the title rather than spread across the card.
   NOT .survey-card-meta-row — that one is space-between, which pushes four short values to the four
   corners of the row. The type matches .survey-card-deadline (0.813rem, --ink-3) so the two cards
   still read alike; the values are repeated rather than the class borrowed, because that class is
   the survey card's.

   margin-bottom separates the totals from the list of posts beneath them. */
.blog-audience-counts {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 1rem;
    font-size: 0.813rem;
    color: var(--ink-3);
}

/* Dot between items, never after the last — the same `+ ::before` separator the project already uses
   for .clock-date and .gc-team-tag. The margin pairs with the row's gap so the dot sits centred
   between two values rather than hugging one. */
.blog-audience-count + .blog-audience-count::before {
    content: "·";
    margin-right: 0.5rem;
    color: var(--ink-4);
}

/* ---------------------------------------------------------------- publication line

   One publication as a row: title (and optionally its author) on the left, date on the right.
   SHARED by the front-page card and the blogs index card, which is why the names are blog-scoped
   rather than welcome- scoped — a class used by a second, unrelated page has outgrown a name that
   points at the first (UI/ClassNaming.md). */

.blog-post-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Each row is an <li>, so it takes the global `ol li, ul li { margin-bottom: 0.4rem }` — zeroed
   here, with the divider between rows doing the separating instead (UI/Layout.md records the same
   trap for panel rows). */
.blog-post-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--line-soft);
}

.blog-post-item:last-child {
    border-bottom: none;
}

/* Fixed-width so the four audiences form a COLUMN and every title starts at the same x, rather than
   each row's title being indented by however long its badge happens to be. min-width, not width, so
   a longer label would push the column wider rather than overflow it.
   justify-content centres the label inside that width — .gp-badge is already inline-flex. */
.blog-post-audience {
    flex-shrink: 0;
    min-width: 4.75rem;
    justify-content: center;
}

/* flex: 1 so the link claims the space between the badge and the date, which is what keeps the date
   hard right. Without it the row's space-between would centre the link instead. */
.blog-post-link {
    flex: 1;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* NO colour of its own — it inherits the global link colour, var(--accent-2), which is the same
   semantic "info" blue used elsewhere, and gets a:hover's --accent-glow with it. It used to set
   var(--ink), which overrode both and left the title reading as plain text rather than as the row's
   call to action. Setting --accent-2 here instead would restore the colour but not the hover. */
.blog-post-title {
    font-size: 0.875rem;
}

.blog-post-by {
    font-size: 0.875rem;
    color: var(--ink-3);
}

.blog-post-date {
    flex-shrink: 0;
    font-size: 0.813rem;
    color: var(--ink-3);
    white-space: nowrap;
}

/* ---------------------------------------------------------------- blogs index cards */

/* Two columns — each card now carries an audience badge, a title and a date on every row, which
   needs the width. minmax(0,1fr) rather than 1fr so a long title wraps inside its column instead of
   stretching the track. */
.blog-card-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
}

.blog-card {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-width: 0;
}

/* No rule above the footer on these cards. The publication rows already separate themselves with
   --line-soft dividers, and .gp-card-footer-padded's --line border is heavier than those — it read
   as a second, stronger division inside a card that only has one list in it.

   The CLASS stays: it also supplies margin-top: auto, which is what keeps every card's View all
   aligned along the bottom of the grid row regardless of how many publications each one lists
   (UI/Cards.md). Only the border is dropped. Specificity 0,2,0, so it wins wherever site.css sits. */
.blog-card .gp-card-footer-padded {
    border-top: none;
}

/* Blog name and author on one line: name left, author right. align-items: baseline so the two sit on
   a common baseline despite their different sizes — centre would float the smaller one. */
.blog-card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
}

/* min-width: 0 so a long blog name wraps inside its share of the row rather than pushing the author
   off the right edge — a flex item will not shrink below its content without it. */
.blog-card-name {
    margin: 0;
    min-width: 0;
    font-size: 1rem;
    overflow-wrap: anywhere;
}

/* flex-shrink: 0 and nowrap: the author is the short, fixed half of the row, so the name is the one
   that gives way. Size and colour unchanged. */
.blog-card-author {
    margin: 0;
    flex-shrink: 0;
    font-size: 0.85rem;
    color: var(--ink-3);
    white-space: nowrap;
}

/* SUPERSEDED 2026-08-06 — the index card's latest publication is now the shared .blog-post-item row,
   the same one the front-page card uses, so the two surfaces render a publication identically.
.blog-card-latest {
    padding-top: 0.5rem;
    font-size: 0.85rem;
    overflow-wrap: anywhere;
}
*/

/* The card footer pushes itself down via margin-top:auto (UI/Cards.md), so the cards in a row end
   with their controls aligned regardless of how long the titles above them run. Nothing else in the
   card may claim that auto margin. */

/* The split panel's header holds a title and, on the blog page, the View all control.
   Targets a styling class on the header, NOT the button's js- hook: a rule written for a js- class
   is a mistake by UI/ClassNaming.md, because removing that class would then break layout as well as
   behaviour. */
.blog-sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

/* Bleeds the rows to the card edges, cancelling the padded card's own inset — the same technique
   .gp-card-divider uses, and via the same token rather than a repeated literal.
   Retargeted 2026-08-06 from the <ul> that used to wrap these rows to the rows themselves; the list
   markup was dropped because a global `ul li` margin was gapping them apart (UI/Layout.md). */
.blog-publication-list-panel .blog-publication-link {
    margin-left: calc(-1 * var(--pad));
    margin-right: calc(-1 * var(--pad));
    width: auto;
}

.blog-pager {
    align-items: center;
    margin-top: 1rem;
}

.blog-pager-position {
    font-size: 0.85rem;
    color: var(--ink-3);
}

/* The shared phone breakpoint (48em), per Systems/StaticAssets.md. */
@media (max-width: 48em) {
    .blog-card-grid {
        grid-template-columns: 1fr;
    }

    .blog-header {
        flex-direction: column;
    }

    /* 2/8 + 6/8 side by side is unusable at phone width — a quarter of a narrow screen fits almost
       no title. The columns stack, and the sidebar drops its sticky cap so it scrolls with the page
       rather than becoming a short scroll region inside one. */
    .blog-split {
        flex-direction: column;
    }

    .blog-split > .gp-split-left {
        position: static;
        max-height: none;
        flex: none;
        width: 100%;
    }
}
