/* ---------------------------------------------------------------------------
   Blog — app/Views/website/blog/index.php and show.php.

   Pairs with site.css, which supplies the tokens, buttons, section shell,
   header, footer and request tray. Nothing here restates them.

   Prefix is gq-bl-, matching story.css (gq-st-), vibe.css (gq-vb-) and
   guides.css: gqv2- is the design system carried over from the mockup, and a
   page built after it does not pretend to have come from it.

   WHY THE PROSE RULES ARE NOT SHARED WITH story.css. They look similar and are
   deliberately not the same class. A cover story is 100 to 150 words — that
   page is built around the shortage, which is why it opens with a drop cap and
   sets the lead paragraph large. A blog article here averages 1,322 words with
   eight headings, so it needs the opposite: a steady measure, a real heading
   hierarchy, and no ornament at the top that the reader has to get past eight
   times a page. Same job description, different problem.

   The index is a card grid rather than a list because every imported post has a
   featured image and nothing else to distinguish it — no author, no category.
   A list of 59 title-and-date rows is a directory, not something anyone browses.
   --------------------------------------------------------------------------- */

.gqv2 {
    /* Narrower than story.css's 46rem. Its measure is set for 19px over a few
       short paragraphs; at 1,300 words the line wants to be shorter, or the
       eye loses its place on the return sweep. */
    --gq-bl-measure: 42rem;
}


/* ==================== BAND ==================== */

.gqv2 .gq-bl-band {
    position: relative;
    overflow: hidden;
    background: var(--gq-sand);
    border-bottom: 1px solid var(--gq-line);
    padding: 46px 0;
}

.gqv2 .gq-bl-band-inner {
    display: flex;
    align-items: center;
    gap: 22px;
}

.gqv2 .gq-bl-band-mark {
    flex: none;
    width: 62px;
    height: 62px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--gq-white);
    color: var(--gq-blue);
    font-size: 25px;
    box-shadow: var(--gq-shadow-sm);
}

.gqv2 .gq-bl-band h1 {
    font-family: var(--gq-head-font);
    font-weight: 800;
    color: var(--gq-navy);
    font-size: clamp(28px, 4vw, 40px);
    line-height: 1.12;
    letter-spacing: -0.015em;
    margin: 2px 0 8px;
}

.gqv2 .gq-bl-band p {
    margin: 0;
    color: var(--gq-slate);
    font-size: 16px;
    max-width: 62ch;
}

.gqv2 .gq-bl-band p a {
    color: var(--gq-blue);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 3px;
}


/* ==================== RAIL: LAYOUT ====================

   The house filter-rail geometry: 260px column, 34px gap, align-items:start,
   collapsing at 900px. guides.css, vibe.css and legal.css already agree on
   those numbers and this is the fourth page to want them.

   NO MARGINS OF ITS OWN. guides.css can set margin-top:56px because its layout
   is a bare wrap; this one sits inside .gqv2-section, which already pays 78px
   of padding. Copying the guides margins would stack the two and open 134px of
   air above the rail.

   ONE ROW, ONE COLUMN EACH, and that is what makes sticky work. A grid item can
   only stick inside its own grid area, so the search and the note as two
   separate items would each be pinned in a row barely taller than themselves
   and travel nowhere. Wrapping them in .gq-bl-rail leaves the grid with a
   single row, so the wrapper's area is the full height of the grid and it has
   the whole article column to move through.
   ==================== */

.gqv2 .gqv2-wrap.gq-bl-layout {
    display: grid;
    grid-template-columns: 260px minmax(0, 1fr);
    gap: 34px;
    align-items: start;
}

.gqv2 .gq-bl-main { min-width: 0; }


/* ==================== RAIL: SEARCH ==================== */

.gqv2 .gq-bl-search {
    display: flex;
    gap: 10px;
    margin-bottom: 26px;
}

.gqv2 .gq-bl-search-field {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
}

.gqv2 .gq-bl-search-field > i {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--gq-mist);
    font-size: 13px;
    pointer-events: none;
}

.gqv2 .gq-bl-search input {
    width: 100%;
    /* Right padding clears the clear button, which sits inside the field. */
    padding: 12px 40px 12px 38px;
    border: 1px solid var(--gq-line);
    border-radius: var(--gq-radius);
    background: var(--gq-white);
    font-family: var(--gq-font);
    font-size: 14.5px;
    color: var(--gq-charcoal);
    box-shadow: var(--gq-shadow-sm);
}

.gqv2 .gq-bl-search input::placeholder { color: var(--gq-mist); }

.gqv2 .gq-bl-search input:focus {
    outline: none;
    border-color: var(--gq-blue);
    box-shadow: 0 0 0 3px var(--gq-blue-tint);
}

/* Safari draws its own X on type=search, on top of ours. */
.gqv2 .gq-bl-search input::-webkit-search-cancel-button { display: none; }

.gqv2 .gq-bl-search-x {
    position: absolute;
    right: 5px;
    top: 50%;
    transform: translateY(-50%);
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    color: var(--gq-mist);
    text-decoration: none;
    font-size: 12px;
}

.gqv2 .gq-bl-search-x:hover {
    background: var(--gq-cloud);
    color: var(--gq-charcoal);
}


/* ==================== RAIL: TOPICS ====================

   MOBILE FIRST, and deliberately so. The chip is the BASE rule and the rail row
   is the override, because the other way round means undoing a dozen
   declarations inside a media query — border, radius, background, padding,
   nowrap, the badge pill, the icon width — and two complete opposed
   appearances of one class is how a rule ends up half-undone.
   ==================== */

.gqv2 .gq-bl-rail-head {
    margin: 0 0 10px;
    font-family: var(--gq-head-font);
    font-size: 13px;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--gq-mist);
}

.gqv2 .gq-bl-topics { margin-bottom: 26px; }

.gqv2 .gq-bl-topic-list {
    display: flex;
    gap: 8px;

    /* One scrolling row on a phone, rather than four rows of chips pushing the
       first card off the screen with the least of it to spare. This is why the
       four-topic cap below is a DESKTOP rule: a horizontal row costs the same
       height whether it holds four chips or ten. */
    overflow-x: auto;
    scrollbar-width: none;

    /* 24px, the real .gqv2-wrap padding. This was --gqv2-wrap-pad with a 20px
       fallback, and that custom property is declared nowhere in the repo — so
       the fallback always won and the row sat 4px inside the gutter. */
    margin-inline: -24px;
    padding-inline: 24px;
}

.gqv2 .gq-bl-topic-list::-webkit-scrollbar { display: none; }

/* Both belong to the rail. Above a scrolling chip row the heading labels
   something that plainly labels itself, and the modal is unreachable because
   every topic is already one swipe away. */
.gqv2 .gq-bl-topics .gq-bl-rail-head,
.gqv2 .gq-bl-more,
.gqv2 .gq-bl-modal { display: none; }

.gqv2 .gq-bl-topic {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    padding: 8px 14px;
    border: 1px solid var(--gq-line);
    border-radius: 999px;
    background: var(--gq-white);
    color: var(--gq-slate);
    font-size: 13.5px;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    transition: border-color .15s ease, color .15s ease, background .15s ease;
}

.gqv2 .gq-bl-topic > i { font-size: 12px; color: var(--gq-mist); }

.gqv2 .gq-bl-topic:hover { border-color: var(--gq-blue); color: var(--gq-blue); }
.gqv2 .gq-bl-topic:hover > i { color: var(--gq-blue); }

/* The chosen one, and it has to survive :hover — a reader whose pointer rests
   on the active row should still be able to see that it is active. guides.css
   does not do this, and the state flickers away under the cursor. */
.gqv2 .gq-bl-topic.is-on,
.gqv2 .gq-bl-topic.is-on:hover {
    background: var(--gq-navy);
    border-color: var(--gq-navy);
    color: var(--gq-white);
}

.gqv2 .gq-bl-topic.is-on > i,
.gqv2 .gq-bl-topic.is-on:hover > i { color: var(--gq-white); }

.gqv2 .gq-bl-topic-n { font-size: 11.5px; font-weight: 700; color: var(--gq-mist); }
.gqv2 .gq-bl-topic.is-on .gq-bl-topic-n { color: rgba(255, 255, 255, .7); }

/* In the article column, not the rail. Only rendered with a topic chosen. */
.gqv2 .gq-bl-topic-note {
    margin: 0 0 14px;
    color: var(--gq-mist);
    font-size: 12.5px;
    line-height: 1.5;
}


/* ==================== RAIL: THE NOTE ====================

   .gq-gd-note geometry, which guides.css and vibe.css already share. A third
   copy is the point at which this wants promoting into site.css as a gqv2-
   rail note; left here for now so this change stays inside the blog.
   ==================== */

.gqv2 .gq-bl-note {
    padding: 14px 16px;
    border: 1px solid var(--gq-line);
    border-radius: 12px;
    background: var(--gq-blue-tint);
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--gq-mist);
}

.gqv2 .gq-bl-note .gq-bl-rail-head {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-bottom: 6px;
    color: var(--gq-blue);
}

.gqv2 .gq-bl-note p { margin: 0 0 8px; }

.gqv2 .gq-bl-note a {
    color: var(--gq-blue);
    font-weight: 700;
    text-decoration: none;
}

.gqv2 .gq-bl-note a:hover { text-decoration: underline; }


/* ==================== RAIL: THE ACTUAL RAIL ====================

   Everything above describes the phone. From here up it becomes a column.
   ==================== */

@media (min-width: 901px) {
    .gqv2 .gq-bl-rail {
        position: sticky;
        top: calc(var(--gq-header-h) + 20px);

        /* Never taller than the space it has. The topic cap below is what keeps
           it from reaching this, so the scrollbar is a backstop for a window
           shorter than any breakpoint anticipates rather than the normal case —
           and it is thin and unobtrusive because on a correctly sized window it
           should never be seen at all. */
        max-height: calc(100vh - var(--gq-header-h) - 40px);
        overflow-y: auto;
        scrollbar-width: thin;

        /* Room for the scrollbar when one does appear, so its arrival does not
           shove the whole rail sideways. */
        scrollbar-gutter: stable;
    }

    /* Stacked, not side by side: at 260px a field beside a button leaves about
       forty typable pixels. */
    .gqv2 .gq-bl-search {
        flex-direction: column;
        gap: 8px;
    }

    .gqv2 .gq-bl-search .gqv2-btn { width: 100%; justify-content: center; }

    .gqv2 .gq-bl-topic-list {
        flex-direction: column;
        gap: 4px;
        overflow-x: visible;
        margin-inline: 0;
        padding-inline: 0;
    }

    .gqv2 .gq-bl-topics .gq-bl-rail-head { display: block; }

    /* .gq-vb-item geometry — the vibes rail row, which is the one that already
       carries an icon, a label and a count. */
    .gqv2 .gq-bl-topic {
        display: flex;
        width: 100%;
        gap: 11px;
        padding: 9px 12px;
        border: 0;
        border-radius: 11px;
        background: none;
        font-size: 14px;
        font-weight: 700;
        color: var(--gq-navy);

        /* Off, and it matters: "Mountains & Small Towns" would otherwise run
           straight through the right edge of a 260px column. */
        white-space: normal;
        line-height: 1.3;
    }

    /* Fixed width, or nine glyphs of nine different advance widths leave the
       label column ragged. */
    .gqv2 .gq-bl-topic > i {
        width: 18px;
        text-align: center;
        flex: 0 0 18px;
    }

    .gqv2 .gq-bl-topic-name { flex: 1 1 auto; }

    .gqv2 .gq-bl-topic:hover {
        background: var(--gq-cloud);
        border-color: transparent;
        color: var(--gq-navy);
    }

    .gqv2 .gq-bl-topic:hover > i { color: var(--gq-mist); }

    /* margin-left:auto is what forms the right-hand number column that is the
       visual signature of both existing rails. */
    .gqv2 .gq-bl-topic-n {
        margin-left: auto;
        padding: 2px 9px;
        border-radius: 999px;
        background: var(--gq-cloud);
        font-size: 12px;
    }

    .gqv2 .gq-bl-topic.is-on,
    .gqv2 .gq-bl-topic.is-on:hover { border-color: transparent; }

    .gqv2 .gq-bl-topic.is-on .gq-bl-topic-n,
    .gqv2 .gq-bl-topic.is-on:hover .gq-bl-topic-n {
        background: rgba(255, 255, 255, .2);
        color: var(--gq-white);
    }

    /* ---- how many rows fit ----

       "All stories" plus four topics by default, and fewer as the window gets
       shorter, so the rail always fits the height it has. Every topic is in the
       DOM either way — how many are shown is a question about the reader's
       window, which only a media query can answer, and the rest are one click
       away in the modal.

       nth-child counts from 1 and "All stories" is row 1, so n+6 hides the
       sixth row onward, leaving All plus four. */
    .gqv2 .gq-bl-topic-list > .gq-bl-topic:nth-child(n + 6) { display: none; }

    .gqv2 .gq-bl-more {
        display: flex;
        align-items: center;
        gap: 8px;
        margin-top: 6px;
        padding: 9px 12px;
        border-radius: 11px;
        color: var(--gq-blue);
        font-size: 13px;
        font-weight: 700;
        text-decoration: none;
    }

    .gqv2 .gq-bl-more > i { width: 18px; text-align: center; font-size: 12px; }
    .gqv2 .gq-bl-more:hover { background: var(--gq-cloud); }

    /* THE CHOSEN TOPIC IS ALWAYS SHOWN, whatever the cap. Filter by Mountains &
       Small Towns — the ninth row — and without this the rail would highlight
       nothing and look as though the filter had not applied. One extra row on
       those pages is the right price for the control telling the truth. */
    .gqv2 .gq-bl-topic-list > .gq-bl-topic.is-on { display: flex; }
}




/* ---- shorter windows, fewer rows ----

   THESE NUMBERS WERE MEASURED, NOT ESTIMATED. Rendered at 1528x747 the rail
   costs 382px before any topic row, and each row is 42px including its gap. So
   the height a rail needs is 382 + (topics + 1) x 42 — the +1 being "All
   stories", which is never hidden because it is the way back out. Against an
   available height of 100vh minus the 76px header minus the 40px offset, that
   gives the minimum viewport for each count:

       4 topics -> 590px of rail, needs a 706px window
       3 topics -> 548px,         needs 664px
       2 topics -> 506px,         needs 622px
       1 topic  -> 465px,         needs 581px

   The steps below sit above each of those with room to spare, because a chosen
   topic also renders its description underneath and that costs another ~42px.
   A first guess at 800/720/640 was wrong in the useful direction — it dropped
   to three topics on a 747px window that had room for four. */

@media (min-width: 901px) and (max-height: 730px) {
    .gqv2 .gq-bl-topic-list > .gq-bl-topic:nth-child(n + 5) { display: none; }
    .gqv2 .gq-bl-topic-list > .gq-bl-topic.is-on { display: flex; }
}

@media (min-width: 901px) and (max-height: 670px) {
    .gqv2 .gq-bl-topic-list > .gq-bl-topic:nth-child(n + 4) { display: none; }
    .gqv2 .gq-bl-topic-list > .gq-bl-topic.is-on { display: flex; }
}

@media (min-width: 901px) and (max-height: 630px) {
    .gqv2 .gq-bl-topic-list > .gq-bl-topic:nth-child(n + 3) { display: none; }
    .gqv2 .gq-bl-topic-list > .gq-bl-topic.is-on { display: flex; }
}


/* ---- the chosen topic always shows, and pays for its own row ----

   Filter by Mountains & Small Towns — the ninth topic — and the cap above would
   hide the one row the reader most needs to see, leaving the rail highlighting
   nothing and looking as though the filter had not applied. The .is-on rules
   already force it back into view.

   On its own that makes the rail one row TALLER on exactly the pages where a
   topic is chosen, which is how it came to overflow its own max-height. These
   pay for it: when the active row is one the cap would have hidden, one fewer
   ORDINARY row is shown and the total stays where it was.

   :not(.is-on) is load-bearing. Without it the range n+5 also covers the active
   row itself, and this rule — being more specific than the .is-on override —
   would hide the very row it exists to make room for.
   ==================== */

@media (min-width: 901px) {
    .gqv2 .gq-bl-topic-list:has(> .gq-bl-topic.is-on:nth-child(n + 6))
        > .gq-bl-topic:nth-child(n + 5):not(.is-on) { display: none; }
}

@media (min-width: 901px) and (max-height: 730px) {
    .gqv2 .gq-bl-topic-list:has(> .gq-bl-topic.is-on:nth-child(n + 5))
        > .gq-bl-topic:nth-child(n + 4):not(.is-on) { display: none; }
}

@media (min-width: 901px) and (max-height: 670px) {
    .gqv2 .gq-bl-topic-list:has(> .gq-bl-topic.is-on:nth-child(n + 4))
        > .gq-bl-topic:nth-child(n + 3):not(.is-on) { display: none; }
}

@media (min-width: 901px) and (max-height: 630px) {
    .gqv2 .gq-bl-topic-list:has(> .gq-bl-topic.is-on:nth-child(n + 3))
        > .gq-bl-topic:nth-child(n + 2):not(.is-on) { display: none; }
}


/* ==================== THE ALL-TOPICS MODAL ====================

   NO JAVASCRIPT. It is shown by :target — the trigger is a plain link to its
   id — so it opens and closes with scripting off, which is the rule the rest of
   this page follows. Hidden entirely below 901px, where the chip row already
   puts every topic one swipe away.
   ==================== */

@media (min-width: 901px) {
    .gqv2 .gq-bl-modal {
        display: none;
        position: fixed;
        inset: 0;
        z-index: 1200;
        align-items: center;
        justify-content: center;
        padding: 24px;
    }

    .gqv2 .gq-bl-modal:target { display: flex; }

    .gqv2 .gq-bl-modal-veil {
        position: absolute;
        inset: 0;
        background: rgba(18, 59, 99, .55);
    }

    .gqv2 .gq-bl-modal-card {
        position: relative;
        width: min(680px, 100%);
        max-height: min(80vh, 640px);
        overflow-y: auto;
        padding: 22px 24px 24px;
        border-radius: 16px;
        background: var(--gq-white);
        box-shadow: 0 30px 70px -20px rgba(18, 59, 99, .5);
    }

    .gqv2 .gq-bl-modal-head {
        display: flex;
        align-items: center;
        gap: 12px;
        margin-bottom: 16px;
    }

    .gqv2 .gq-bl-modal-head h2 {
        margin: 0;
        font-family: var(--gq-head-font);
        font-size: 19px;
        color: var(--gq-navy);
    }

    .gqv2 .gq-bl-modal-x {
        margin-left: auto;
        width: 32px;
        height: 32px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 50%;
        color: var(--gq-mist);
        text-decoration: none;
    }

    .gqv2 .gq-bl-modal-x:hover { background: var(--gq-cloud); color: var(--gq-charcoal); }

    /* Two columns, because nine rows in one column is the rail again — and the
       reader opened this precisely to see them all at once. */
    .gqv2 .gq-bl-modal-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
        gap: 6px 14px;
    }

    /* Every row visible here, whatever the rail's cap hid. */
    .gqv2 .gq-bl-modal-grid > .gq-bl-topic { display: flex; }
}

@media (max-width: 900px) {
    .gqv2 .gqv2-wrap.gq-bl-layout {
        grid-template-columns: minmax(0, 1fr);
        gap: 0;
    }

    /* display:contents dissolves the wrapper and hands its two halves back to
       the grid as items in their own right, so each can be placed on its own —
       controls above the articles, note below them. A plain div with no role of
       its own loses nothing by disappearing from the box tree; the asides
       inside it keep their landmarks. */
    .gqv2 .gq-bl-rail { display: contents; }

    .gqv2 .gq-bl-side   { order: 1; }
    .gqv2 .gq-bl-main   { order: 2; }
    .gqv2 .gq-bl-extras { order: 3; margin-top: 34px; }
}

@media (max-width: 560px) {
    /* Still side by side rather than stacked: a full-width button under the
       field costs about 54px directly above the first card, on the screen with
       the least room, and the field is still comfortable at this width. */
    .gqv2 .gq-bl-search .gqv2-btn { flex: 0 0 auto; }
}


/* ==================== CARD GRID ==================== */

.gqv2 .gq-bl-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
    gap: 24px;
}

.gqv2 .gq-bl-card {
    display: flex;
    border-radius: var(--gq-radius);
    background: var(--gq-white);
    border: 1px solid var(--gq-line);
    box-shadow: var(--gq-shadow-sm);
    overflow: hidden;
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}

.gqv2 .gq-bl-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--gq-shadow);
    border-color: #cfdae6;
}

/* The whole card is the link, so the hit area matches what looks clickable. */
.gqv2 .gq-bl-card-link {
    display: flex;
    flex-direction: column;
    width: 100%;
    color: inherit;
    text-decoration: none;
}

.gqv2 .gq-bl-card-link:focus-visible {
    outline: 3px solid var(--gq-blue);
    outline-offset: -3px;
    border-radius: var(--gq-radius);
}

.gqv2 .gq-bl-card-img {
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: var(--gq-cloud);
}

.gqv2 .gq-bl-card-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform .35s ease;
}

.gqv2 .gq-bl-card:hover .gq-bl-card-img img {
    transform: scale(1.04);
}

.gqv2 .gq-bl-card-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 18px 20px 20px;
    flex: 1;
}

.gqv2 .gq-bl-card-title {
    font-family: var(--gq-head-font);
    font-weight: 700;
    color: var(--gq-navy);
    font-size: 18px;
    line-height: 1.3;
    letter-spacing: -0.01em;
    margin: 0;
}

.gqv2 .gq-bl-card-blurb {
    margin: 0;
    color: var(--gq-slate);
    font-size: 14.5px;
    line-height: 1.55;

    /* Three lines, then stop. The excerpts run to 320 characters and cards in
       one row must end level, or the grid looks broken rather than varied. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.gqv2 .gq-bl-card-meta {
    margin: auto 0 0;
    padding-top: 4px;
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--gq-mist);
    font-size: 12.5px;
    font-weight: 500;
}


/* ==================== PAGER ==================== */

.gqv2 .gq-bl-pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    margin-top: 36px;
    flex-wrap: wrap;
}

.gqv2 .gq-bl-pager-count {
    color: var(--gq-mist);
    font-size: 14px;
    font-weight: 500;
}



/* The topic printed on a card. Not a link: the whole card already is one, and
   an anchor inside an anchor is invalid HTML that browsers repair unevenly. */
.gqv2 .gq-bl-card-topic {
    display: block;
    margin-bottom: 6px;
    color: var(--gq-blue);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}

/* ==================== EMPTY ==================== */

.gqv2 .gq-bl-empty {
    text-align: center;
    padding: 60px 20px;
    color: var(--gq-slate);
}

.gqv2 .gq-bl-empty i {
    font-size: 40px;
    color: #b9c6d4;
    margin-bottom: 14px;
    display: block;
}

.gqv2 .gq-bl-empty h2 {
    font-family: var(--gq-head-font);
    color: var(--gq-navy);
    font-weight: 800;
    margin: 0 0 8px;
}

.gqv2 .gq-bl-empty p {
    margin: 0 0 20px;
}


/* ==================== POST ==================== */

.gqv2 .gq-bl-article {
    max-width: var(--gq-bl-measure);
}

.gqv2 .gq-bl-post-head {
    padding: 44px 0 8px;
}

.gqv2 .gq-bl-crumb {
    margin: 0 0 16px;
    font-size: 14px;
    font-weight: 600;
}

.gqv2 .gq-bl-crumb a {
    color: var(--gq-blue);
    text-decoration: none;
}

.gqv2 .gq-bl-crumb a:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

.gqv2 .gq-bl-post-head h1 {
    font-family: var(--gq-head-font);
    font-weight: 800;
    color: var(--gq-navy);
    font-size: clamp(30px, 4.4vw, 44px);
    line-height: 1.14;
    letter-spacing: -0.02em;
    margin: 0 0 14px;
    text-wrap: balance;
}

.gqv2 .gq-bl-post-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    color: var(--gq-mist);
    font-size: 13.5px;
    font-weight: 500;
}

/* The radius and the shadow belong to the IMAGE, not the figure. The figure now
   also holds the credit line, and a rounded, overflow-hidden box around both
   clipped the corners of the text sitting at its foot. */
.gqv2 .gq-bl-hero {
    margin: 26px 0 6px;
}

.gqv2 .gq-bl-hero img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: var(--gq-radius);
    box-shadow: var(--gq-shadow-sm);
}

/* The photographer's credit, under the picture and pushed to the right.
   Right-aligned because that is where a credit is looked for and where it stays
   out of the way of the opening line — set left, it sits directly above the
   first paragraph and reads as a caption introducing the article. Small and
   muted for the same reason: it is an acknowledgement, not a caption. */
.gqv2 .gq-bl-credit {
    padding: 7px 2px 0;
    text-align: right;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--gq-mist);
}

.gqv2 .gq-bl-credit a {
    color: var(--gq-slate);
    text-decoration: underline;
    text-underline-offset: 2px;
    text-decoration-color: var(--gq-line);
}

.gqv2 .gq-bl-credit a:hover,
.gqv2 .gq-bl-credit a:focus-visible {
    color: var(--gq-blue);
    text-decoration-color: var(--gq-blue);
}


/* ==================== POST PROSE ====================
   Targets tags rather than classes: the body is stored HTML and carries none.
   Internal links arrive already resolved by App\Libraries\BlogLinker. */

.gqv2 .gq-bl-body {
    padding: 30px 0 56px;
    font-size: 18px;
    line-height: 1.75;
    color: #3b434c;
}

.gqv2 .gq-bl-body > *:first-child { margin-top: 0; }
.gqv2 .gq-bl-body > *:last-child { margin-bottom: 0; }

.gqv2 .gq-bl-body p {
    margin: 0 0 1.3em;
}

/* The lead only. No drop cap: these run to eight headings, and an ornament
   that says "the article starts here" is noise when the reader can see that. */
.gqv2 .gq-bl-body > p:first-child {
    font-size: 20px;
    line-height: 1.65;
    color: #2f373f;
}

.gqv2 .gq-bl-body h2,
.gqv2 .gq-bl-body h3,
.gqv2 .gq-bl-body h4 {
    font-family: var(--gq-head-font);
    color: var(--gq-navy);
    font-weight: 800;
    line-height: 1.22;
    letter-spacing: -0.012em;

    /* Asymmetric: a heading belongs to what follows it, so it sits closer to
       its own section than to the paragraph it interrupts. */
    margin: 1.85em 0 .55em;
}

.gqv2 .gq-bl-body h2 { font-size: 26px; }
.gqv2 .gq-bl-body h3 { font-size: 21px; }
.gqv2 .gq-bl-body h4 { font-size: 17.5px; }

.gqv2 .gq-bl-body strong,
.gqv2 .gq-bl-body b {
    color: var(--gq-navy);
    font-weight: 700;
}

.gqv2 .gq-bl-body a {
    color: var(--gq-blue);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1.5px;
    text-decoration-color: rgba(36, 116, 166, .38);
}

.gqv2 .gq-bl-body a:hover {
    text-decoration-color: var(--gq-blue);
}

.gqv2 .gq-bl-body ul,
.gqv2 .gq-bl-body ol {
    margin: 0 0 1.3em;
    padding-left: 1.35em;
}

.gqv2 .gq-bl-body li {
    margin-bottom: .5em;
}

.gqv2 .gq-bl-body li::marker {
    color: var(--gq-blue);
}

.gqv2 .gq-bl-body blockquote {
    margin: 1.6em 0;
    padding: 4px 0 4px 20px;
    border-left: 3px solid var(--gq-gold);
    color: var(--gq-navy);
    font-size: 19px;
    font-style: italic;
}

.gqv2 .gq-bl-body img {
    max-width: 100%;
    height: auto;
    border-radius: 10px;
    margin: 1.4em 0;
}

/* A wide table must scroll inside itself rather than widening the page. */
.gqv2 .gq-bl-body table {
    width: 100%;
    border-collapse: collapse;
    margin: 1.5em 0;
    font-size: 15.5px;
    display: block;
    overflow-x: auto;
}

.gqv2 .gq-bl-body th,
.gqv2 .gq-bl-body td {
    border: 1px solid var(--gq-line);
    padding: 9px 12px;
    text-align: left;
}

.gqv2 .gq-bl-body th {
    background: var(--gq-cloud);
    color: var(--gq-navy);
    font-weight: 700;
}


/* ==================== MORE ==================== */

.gqv2 .gq-bl-more-head {
    font-family: var(--gq-head-font);
    font-weight: 800;
    color: var(--gq-navy);
    font-size: 24px;
    letter-spacing: -0.01em;
    margin: 0 0 22px;
}


/* ==================== SMALL SCREENS ==================== */

@media (max-width: 767.98px) {
    .gqv2 .gq-bl-band {
        padding: 32px 0;
    }

    .gqv2 .gq-bl-band-inner {
        gap: 16px;
    }

    .gqv2 .gq-bl-band-mark {
        width: 48px;
        height: 48px;
        font-size: 19px;
    }

    .gqv2 .gq-bl-grid {
        grid-template-columns: 1fr;
        gap: 18px;
    }

    .gqv2 .gq-bl-post-head {
        padding: 28px 0 4px;
    }

    .gqv2 .gq-bl-body {
        font-size: 17px;
        padding: 24px 0 40px;
    }

    .gqv2 .gq-bl-body > p:first-child {
        font-size: 18px;
    }

    .gqv2 .gq-bl-body h2 { font-size: 23px; }
    .gqv2 .gq-bl-body h3 { font-size: 19px; }
}

@media (prefers-reduced-motion: reduce) {
    .gqv2 .gq-bl-card,
    .gqv2 .gq-bl-card-img img {
        transition: none;
    }

    .gqv2 .gq-bl-card:hover {
        transform: none;
    }

    .gqv2 .gq-bl-card:hover .gq-bl-card-img img {
        transform: none;
    }
}
