/* ─────────────────────────────────────────────────────────────────────────
   article.css — the single-post reading surface.

   Loaded only on is_single() (see functions.php). Everything is scoped under
   .ub-article or .ub-related so nothing here can reach the homepage or the
   program pages.

   The column is deliberately narrower than the site's --measure (1384px).
   That width is right for a landing page built from section blocks and wrong
   for body copy: at 1384px a line of 16px text runs past 200 characters, and
   the eye loses the line return. --article-measure below is set so the body
   lands in the 65–75ch range this content actually reads at.
   ───────────────────────────────────────────────────────────────────────── */

.ub-article {
    /* The reading column. Measured, not guessed: at the 17px body size below,
       46rem renders ~68 characters per line — inside the 65–75ch range that
       long-form copy reads at. The sidebar now balances the page, so the
       column no longer has to carry the whole width on its own. */
    --article-measure: 46rem;
    --article-hero: 64rem;      /* header and hero — the wide band above the body */
    --article-side: 19rem;      /* sidebar track */
    --article-gap: 3.5rem;

    --article-ink: #1d2430;     /* darker than --text-main for long reading */
    --article-ink-soft: #55606d;
    --article-rule: #e2e6ea;

    padding-block: clamp(2rem, 5vw, 4rem) clamp(3rem, 7vw, 5.5rem);
}

/* ── Header ─────────────────────────────────────────────────────────── */

/* Header and hero share the grid's own geometry rather than being centred on
   their own widths. Three independently centred blocks gave the page three
   different left edges — 288px, 224px and 188px on a 1440px screen — so the
   top of the article read as misaligned against the columns beneath it.
   They now start on the same line as the body and run wider by spanning into
   the sidebar track. */
.ub-article__head,
.ub-article__hero {
    max-width: 78rem;
    margin-inline: auto;
    padding-inline: 1.5rem;
}

/* Header and hero share one width. Holding the header narrower boxed the
   headline at 832px above a 1024px image — the title read as pinched against
   the picture directly beneath it, and the longest headline wrapped to four
   lines with ~190px of the row unused. Matched to the hero it wraps to three
   at ~35 characters a line, which is still well short of the ~90 the full
   grid width would give a 3.5rem face. */
.ub-article__head-inner,
.ub-article__hero-inner {
    max-width: var(--article-hero);
}

/* ── Two-column layout ──────────────────────────────────────────────── */

/* Above 1100px the article runs beside a sidebar. Before this existed the
   body sat alone in a 41rem column and left 392px of dead margin on each side
   of a 1440px screen — 54% of the viewport carrying nothing. The sidebar puts
   that space to work with navigation rather than filler. */
.ub-article__layout {
    display: grid;
    /* 1fr on the body track, not a fixed measure: with justify-content:center
       the columns were centred inside the container and the body started 68px
       right of the headline above it. Letting the body absorb the slack keeps
       every left edge on the same line. */
    grid-template-columns: minmax(0, 1fr) var(--article-side);
    gap: var(--article-gap);
    max-width: 78rem;
    margin-inline: auto;
    padding-inline: 1.5rem;
}

/* The reading measure is applied to the copy itself rather than the track, so
   the column can be wide while the line length stays right. */
.ub-article__content,
.ub-article__tags {
    max-width: var(--article-measure);
}

.ub-article__main { min-width: 0; }

.ub-article__side { min-width: 0; }

/* The sidebar tracks the reader down a 1,000-word article. top offsets the
   sticky site header; max-height plus overflow keeps a long contents list
   from running past the viewport. */
.ub-article__side-inner {
    position: sticky;
    top: 5.5rem;
    display: flex;
    flex-direction: column;
    gap: 1.75rem;
    max-height: calc(100vh - 7rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

.ub-article__cats {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1.25rem;
}

.ub-article__cat {
    display: inline-block;
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    background: #f1ecf7;
    color: var(--ub-purple, #592d82);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    text-decoration: none;
    transition: background 0.18s ease, color 0.18s ease;
}

.ub-article__cat:hover,
.ub-article__cat:focus-visible {
    background: var(--ub-purple, #592d82);
    color: #fff;
}

.ub-article__title {
    margin: 0;
    /* Sized against the 64rem header band, not the reading measure. The source
       headlines run long — "Advancing the Future of Patient-Centered Care: UB
       PAI Earns ACLM Partial Academic Pathway Designation" is 96 characters —
       so the ceiling stays moderate and the width does the work. That worst
       case now sets in three lines; it was five before the header got its own
       column, and four while the header was narrower than the hero. */
    font-size: clamp(2rem, 1.25rem + 2.6vw, 3.5rem);
    line-height: 1.09;
    letter-spacing: -0.025em;
    font-weight: 700;
    color: var(--article-ink);
    text-wrap: balance;
}

/* Only rendered when the post has a real excerpt. Most migrated posts do not
   yet, so this must degrade to nothing rather than leave a gap. */
.ub-article__standfirst {
    margin: 1.1rem 0 0;
    font-size: clamp(1.1rem, 1.02rem + 0.4vw, 1.3rem);
    line-height: 1.55;
    color: var(--article-ink-soft);
    text-wrap: pretty;
}

.ub-article__meta {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 1.5rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--article-rule);
    font-size: 0.875rem;
    color: var(--article-ink-soft);
}

.ub-article__dot {
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: currentColor;
    opacity: 0.55;
}

/* ── Hero image ─────────────────────────────────────────────────────── */

.ub-article__hero {
    margin-block: clamp(2rem, 4vw, 3rem);
}

/* Width comes from the shared header/hero rule above. The 16:9 crop keeps a
   tall source image from pushing the first paragraph off the screen; the
   migrated headers are all 1280x720, so this is their native ratio rather
   than an imposed one. */
.ub-article__hero-img {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    height: auto;
    object-fit: cover;
    border-radius: 12px;
    /* Offset and blur, so the image sits on the page rather than glowing. */
    box-shadow: 0 14px 34px rgba(29, 36, 48, 0.16);
}

.ub-article__hero figcaption {
    margin-top: 0.7rem;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--article-ink-soft);
}

/* ── Reading progress ───────────────────────────────────────────────── */

/* A hairline that fills as the article scrolls. On a 2,000-word guide it is
   the difference between "how much of this is left?" and finding out by
   scrolling. Driven by scroll-timeline where supported and simply absent
   where not — no JavaScript, and nothing to fail. */
.ub-article__progress {
    position: fixed;
    inset-block-start: 0;
    inset-inline: 0;
    height: 3px;
    z-index: 60;
    background: transparent;
    pointer-events: none;
}

.ub-article__progress-bar {
    height: 100%;
    width: 100%;
    transform-origin: 0 50%;
    transform: scaleX(0);
    background: linear-gradient(90deg, var(--ub-purple, #592d82), var(--ub-blue, #00a7e0));
}

/* The scroller is .main-content-wrapper, not the document: the theme sets
   body { overflow: hidden } and scrolls that inner element instead. A
   scroll(root) timeline therefore has zero range and the bar never moves, so
   the timeline is named on the real scroller and referenced from here. */
@supports (animation-timeline: scroll()) {
    .main-content-wrapper {
        scroll-timeline: --ub-article-scroll block;
    }

    .ub-article__progress-bar {
        animation: ub-article-progress linear both;
        animation-timeline: --ub-article-scroll;
    }
}

@keyframes ub-article-progress {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

@media (prefers-reduced-motion: reduce) {
    .ub-article__progress { display: none; }
}

/* ── Body copy ──────────────────────────────────────────────────────── */

.ub-article__content {
    font-size: 1.0625rem;
    line-height: 1.75;
    color: var(--article-ink);
}

/* The opening paragraph is set larger, so the eye lands somewhere deliberate
   after the hero rather than at the top of an even grey block. Scoped to a
   bare first paragraph: if the post opens with a figure or a heading, nothing
   is promoted. */
.ub-article__content > p:first-child {
    font-size: clamp(1.15rem, 1.06rem + 0.4vw, 1.35rem);
    line-height: 1.6;
    color: #333c49;
}

.ub-article__content > * + * {
    margin-top: 1.35em;
}

/* More space above a heading than below it: the gap belongs to the section
   the heading opens, not to the paragraph it follows. */
.ub-article__content h2,
.ub-article__content h3,
.ub-article__content h4 {
    margin-top: 2.4em;
    margin-bottom: 0.65em;
    line-height: 1.25;
    letter-spacing: -0.015em;
    color: var(--article-ink);
    text-wrap: balance;
}

/* Jumping from the contents list must not park the heading under the sticky
   site header. */
.ub-article__content :is(h2, h3)[id] {
    scroll-margin-top: 6rem;
}

.ub-article__content h2 { font-size: clamp(1.45rem, 1.2rem + 0.9vw, 1.9rem); font-weight: 700; }
.ub-article__content h3 { font-size: clamp(1.2rem, 1.08rem + 0.5vw, 1.4rem);  font-weight: 700; }
.ub-article__content h4 { font-size: 1.1rem; font-weight: 600; }

.ub-article__content h2 + *,
.ub-article__content h3 + *,
.ub-article__content h4 + * {
    margin-top: 0;
}

.ub-article__content a {
    color: var(--ub-blue-text, #0a6e8f);
    text-decoration: underline;
    text-underline-offset: 0.15em;
    text-decoration-thickness: 1px;
    transition: color 0.15s ease;
}

.ub-article__content a:hover,
.ub-article__content a:focus-visible {
    color: var(--ub-purple, #592d82);
    text-decoration-thickness: 2px;
}

.ub-article__content strong { font-weight: 700; }

.ub-article__content ul,
.ub-article__content ol {
    padding-left: 1.3em;
}

.ub-article__content li + li {
    margin-top: 0.5em;
}

.ub-article__content li::marker {
    color: var(--ub-purple, #592d82);
}

/* Inline images break out of the reading measure to the wider rail, so they
   read as illustrations rather than as text-width interruptions. The negative
   margin is bounded by the viewport at narrow widths via the clamp, so this
   never causes a horizontal scrollbar. */
.ub-article__content :is(figure, .wp-block-image) {
    --figure-bleed: clamp(0rem, (var(--article-measure) - 100vw + 3rem) * -0.5, 5rem);

    margin-block: 2.4em;
    margin-inline: calc(var(--figure-bleed) * -1);
}

.ub-article__content :is(img, iframe, video) {
    max-width: 100%;
    height: auto;
    border-radius: 8px;
}

.ub-article__content figcaption {
    margin-top: 0.6rem;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--article-ink-soft);
    text-align: left;
}

/* A pulled quote, set rather than bracketed: it steps outside the measure,
   changes size and colour, and opens on a hanging quote mark. The usual
   coloured left rule does the same job by decoration instead of typography. */
.ub-article__content blockquote {
    position: relative;
    margin-block: 2.6em;
    margin-inline: 0;
    padding-top: 2.2rem;
    font-size: clamp(1.25rem, 1.12rem + 0.55vw, 1.5rem);
    line-height: 1.45;
    letter-spacing: -0.01em;
    color: var(--ub-purple-dark, #3f1d61);
    text-wrap: pretty;
}

.ub-article__content blockquote::before {
    content: "\201C";
    position: absolute;
    top: -0.35em;
    left: -0.06em;
    font-size: 4.5rem;
    line-height: 1;
    color: var(--ub-purple, #592d82);
    opacity: 0.22;
    pointer-events: none;
}

.ub-article__content blockquote p { margin: 0; }
.ub-article__content blockquote p + p { margin-top: 0.8em; }

.ub-article__content hr {
    margin-block: 2.6em;
    border: 0;
    border-top: 1px solid var(--article-rule);
}

.ub-article__content table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.95rem;
}

.ub-article__content :is(th, td) {
    padding: 0.6rem 0.8rem;
    border-bottom: 1px solid var(--article-rule);
    text-align: left;
}

.ub-article__content th { font-weight: 600; }

/* ── Tags ───────────────────────────────────────────────────────────── */

.ub-article__tags {
    margin-top: clamp(2.5rem, 5vw, 3.5rem);
    padding-top: 1.5rem;
    border-top: 1px solid var(--article-rule);
}

.ub-article__tags-label {
    margin: 0 0 0.85rem;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--article-ink-soft);
}

.ub-article__tags ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ub-article__tags a {
    display: inline-block;
    padding: 0.35rem 0.75rem;
    border: 1px solid var(--article-rule);
    border-radius: 999px;
    font-size: 0.8125rem;
    color: var(--article-ink-soft);
    text-decoration: none;
    transition: border-color 0.18s ease, color 0.18s ease, background 0.18s ease;
}

.ub-article__tags a:hover,
.ub-article__tags a:focus-visible {
    border-color: var(--ub-purple, #592d82);
    background: #f1ecf7;
    color: var(--ub-purple, #592d82);
}

/* ── Sidebar blocks ─────────────────────────────────────────────────── */

.ub-side-block + .ub-side-block {
    padding-top: 1.6rem;
    border-top: 1px solid var(--article-rule);
}

.ub-side-block__title {
    margin: 0 0 0.85rem;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--article-ink-soft);
}

/* Contents list ------------------------------------------------------ */

.ub-toc__list {
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: none;
}

.ub-toc__item a {
    display: block;
    padding: 0.32rem 0 0.32rem 0.85rem;
    /* A 2px rail on the list edge, not a tab on a card: it marks the reading
       position the way a margin rule does. */
    border-left: 2px solid var(--article-rule);
    font-size: 0.875rem;
    line-height: 1.45;
    color: var(--article-ink-soft);
    text-decoration: none;
    transition: color 0.15s ease, border-color 0.15s ease;
}

.ub-toc__item--h3 a {
    padding-left: 1.6rem;
    font-size: 0.8125rem;
}

.ub-toc__item a:hover,
.ub-toc__item a:focus-visible {
    border-left-color: var(--ub-purple, #592d82);
    color: var(--ub-purple, #592d82);
}

/* Scroll-spy: the heading currently in view. Set by article.js; the list is
   fully usable without it. */
.ub-toc__item.is-active > a {
    border-left-color: var(--ub-purple, #592d82);
    color: var(--article-ink);
    font-weight: 600;
}

/* Side story list ---------------------------------------------------- */

.ub-side-list {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ub-side-list__link {
    display: grid;
    grid-template-columns: 4rem 1fr;
    gap: 0.75rem;
    align-items: start;
    text-decoration: none;
    color: inherit;
}

.ub-side-list__thumb {
    display: block;
    width: 4rem;
    height: 4rem;
    overflow: hidden;
    border-radius: 6px;
    background: #eef1f4;
}

.ub-side-list__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.ub-side-list__text {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-width: 0;
}

.ub-side-list__title {
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--article-ink);
    text-wrap: pretty;
    transition: color 0.15s ease;
}

.ub-side-list__link:hover .ub-side-list__title,
.ub-side-list__link:focus-visible .ub-side-list__title {
    color: var(--ub-purple, #592d82);
}

.ub-side-list__date {
    font-size: 0.75rem;
    color: var(--article-ink-soft);
}

/* Topic list --------------------------------------------------------- */

.ub-side-cats {
    margin: 0;
    padding: 0;
    list-style: none;
}

.ub-side-cats__link {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.4rem 0;
    font-size: 0.875rem;
    color: var(--article-ink);
    text-decoration: none;
    border-bottom: 1px solid var(--article-rule);
    transition: color 0.15s ease;
}

.ub-side-cats li:last-child .ub-side-cats__link { border-bottom: 0; }

.ub-side-cats__link:hover,
.ub-side-cats__link:focus-visible {
    color: var(--ub-purple, #592d82);
}

.ub-side-cats__link.is-current {
    font-weight: 650;
    color: var(--ub-purple, #592d82);
}

.ub-side-cats__count {
    flex: none;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    color: var(--article-ink-soft);
}

/* ── Related posts ──────────────────────────────────────────────────── */

.ub-related {
    margin-top: clamp(3rem, 7vw, 5rem);
    padding-block: clamp(2.5rem, 5vw, 4rem);
    background: #f7f8f9;
    border-top: 1px solid var(--article-rule, #e2e6ea);
}

.ub-related__inner {
    max-width: 68rem;
    margin-inline: auto;
    padding-inline: 1.5rem;
}

.ub-related__title {
    margin: 0 0 1.75rem;
    font-size: clamp(1.35rem, 1.15rem + 0.8vw, 1.75rem);
    font-weight: 700;
    letter-spacing: -0.015em;
    color: #1d2430;
}

.ub-related__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ub-related__link {
    display: flex;
    flex-direction: column;
    height: 100%;
    background: #fff;
    border-radius: 10px;
    overflow: hidden;
    text-decoration: none;
    box-shadow: 0 1px 2px rgba(29, 36, 48, 0.06);
    transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.3, 1),
                box-shadow 0.22s cubic-bezier(0.2, 0.7, 0.3, 1);
}

.ub-related__link:hover,
.ub-related__link:focus-visible {
    transform: translateY(-3px);
    box-shadow: 0 14px 30px rgba(29, 36, 48, 0.14);
}

.ub-related__thumb {
    display: block;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: #e9edf0;
}

.ub-related__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.4s cubic-bezier(0.2, 0.7, 0.3, 1);
}

.ub-related__link:hover .ub-related__img {
    transform: scale(1.04);
}

.ub-related__text {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    padding: 1.1rem 1.2rem 1.3rem;
}

.ub-related__cat {
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--ub-purple, #592d82);
}

.ub-related__headline {
    font-size: 1.0625rem;
    font-weight: 650;
    line-height: 1.35;
    color: #1d2430;
    text-wrap: pretty;
}

.ub-related__link:hover .ub-related__headline {
    color: var(--ub-purple, #592d82);
}

.ub-related__date {
    margin-top: auto;
    padding-top: 0.3rem;
    font-size: 0.8125rem;
    color: #55606d;
}

/* ── Responsive ─────────────────────────────────────────────────────── */

/* Below this the two columns cannot both hold their content: the sidebar is
   dropped rather than stacked. A contents list placed under the article it
   indexes has stopped being navigation, and the related rail after the body
   already covers "what next". */
@media (max-width: 1100px) {
    .ub-article__layout {
        display: block;
        max-width: var(--article-measure);
        padding-inline: 1.5rem;
    }

    .ub-article__side { display: none; }
}

@media (max-width: 900px) {
    .ub-related__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 600px) {
    .ub-article {
        /* The body size drops with the viewport, so the measure follows.
           Left at 44rem the column would simply be the screen width. */
        padding-block: 1.5rem 2.5rem;
    }

    .ub-article__content {
        font-size: 1rem;
        line-height: 1.7;
    }

    .ub-article__meta {
        flex-wrap: wrap;
        row-gap: 0.35rem;
    }

    .ub-related__grid {
        grid-template-columns: 1fr;
        gap: 1rem;
    }

    /* On one column the cards become a list: a 16:9 image above every headline
       makes the reader scroll past three near-identical blocks. Side-by-side
       keeps three items in view. */
    .ub-related__link {
        flex-direction: row;
        align-items: stretch;
    }

    .ub-related__thumb {
        flex: 0 0 38%;
        aspect-ratio: 1 / 1;
    }

    .ub-related__text {
        padding: 0.85rem 1rem;
    }

    .ub-related__headline {
        font-size: 0.9875rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .ub-related__link,
    .ub-related__img {
        transition: none;
    }

    .ub-related__link:hover {
        transform: none;
    }

    .ub-related__link:hover .ub-related__img {
        transform: none;
    }
}
