/* ══════════════════════════════════════════════════════════════════════════
   Styles/gb-typography.css   —   v2 (24 Aug 2026)
   Genesis Biologica — shared typography, measure and responsive behaviour

   WHY THIS FILE EXISTS
   Justification and column width were declared per page, on a handful of
   selectors (.prose p, .two-col-grid p, .preview-body p) and with three
   different hard caps — 720px on .section-lede, 760px inline on About and
   Indexing, 800px on .guide-panel .prose. Anything outside those selectors
   (list items, cards, table cells, definition text) stayed ragged, and the
   three different caps are why one page reads as a different width from the
   next. Loaded LAST in <head>, so it wins over the inline <style> blocks
   without anyone having to edit ten of them.

   ── WHAT CHANGED IN v2 ──────────────────────────────────────────────────
   1. ONE measure for the whole site (--gb-measure), overriding the 720 /
      760 / 800px caps, including the inline ones (hence !important).
   2. The measure and the body size now scale with the viewport, so a
      1900px monitor gets a proportionally larger column rather than the
      same 760px block with 500px of dead space beside it.
   3. .gb-reading — a two-column reading layout. Long-form prose keeps a
      readable line length while an "On this page" rail occupies the space
      that would otherwise sit empty on the right. This is the same shape
      the Policies page already uses, so the pages now match.
   4. The justification sweep is now structural (.section .wrap p / li)
      rather than a list of ten class names, so new sections inherit it.

   ── ON JUSTIFICATION AND SMALL SCREENS ──────────────────────────────────
   Justified text is only justified below a certain measure by torturing the
   word spaces. On a 360px phone a paragraph holds roughly 35 characters per
   line; forcing both margins flush there produces the white "rivers" that
   make text visibly harder to read, and CSS hyphenation cannot rescue it
   because browsers hyphenate conservatively.

   So: justified from 721px up, ragged-right below.

   ── ON WHY THE COLUMN IS NOT THE FULL PAGE WIDTH ────────────────────────
   A justified line longer than roughly 100 characters is measurably harder
   to read: the eye loses the return sweep to the next line. On a 1900px
   screen a full-width paragraph is about 200 characters. So the column is
   capped — and the leftover width is given to the rail (3, above) instead
   of being left blank. That is how the dead space is removed without
   wrecking the line length.
   ══════════════════════════════════════════════════════════════════════ */

/* ── 0. Tokens ────────────────────────────────────────────────────────── */
:root {
    /* Reading column. Grows with the viewport, floors at a comfortable
       tablet width, ceilings before the line gets too long to track. */
    /* 920px is not arbitrary. Inside a .gb-reading grid the prose track
       computes to 928px (1280 wrap - 56 padding - 250 rail - 46 gap), and
       the Policies page's existing .pol-layout content column computes to
       918px (1224 - 260 TOC - 46 gap). Capping the standalone measure at
       920px puts all three within ~10px of each other, so a reader moving
       between About, Indexing, Guidelines and Policies sees one column
       width rather than four. Raising this cap re-introduces the drift. */
    --gb-measure: 100%;
    --gb-rail: 250px;
    --gb-prose-size: 14px;
    --gb-prose-leading: 1.8;
}

/* From 901px the rail is present, so a standalone prose column must mirror
   the grid track exactly or Guidelines will read wider than About at the
   same window size. 352px = 56 wrap padding + 250 rail + 46 gap. Below
   901px the rail has stacked and prose takes the full wrap, uncapped.
   901px is the breakpoint Policies' own .pol-layout already uses. */
@media (min-width: 901px) {
    :root { --gb-measure: min(920px, calc(100vw - 352px)); }
}

/* The column stops growing at 920px; the type keeps growing, so a larger
   monitor gets larger text at a constant, readable line length rather than
   an ever-longer line. */
@media (min-width: 1400px) { :root { --gb-prose-size: 15px; } }
@media (min-width: 1700px) { :root { --gb-prose-size: 15.5px; } }

/* ── 1. One measure everywhere ────────────────────────────────────────── */
/* !important is deliberate: About.aspx and Indexing.aspx carry an inline
   style="max-width:760px" on the .prose div, and inline styles beat any
   external rule that is not !important. Removing those attributes as well
   is harmless — this rule then simply has nothing to override. */
.prose,
.guide-panel .prose,
.section-lede,
.about-body,
.block-body,
.preview-body {
    max-width: min(100%, var(--gb-measure)) !important;
}

/* Inside a .gb-reading grid the column is already constrained by the grid
   track, so let it fill its cell. */
.gb-reading .prose,
.gb-reading .section-lede { max-width: 100% !important; }

/* ── 2. Consistent justification for running prose ────────────────────── */
/* Structural, so a new section inherits it without being added to a list. */
.section .wrap p,
.section .wrap li,
.prose p,
.prose li,
.two-col-grid p,
.preview-body p,
.pol-block p,
.pol-block li,
.guide-panel p,
.guide-panel li,
.section-lede,
.about-body p,
.card-body p,
.block-body p,
.abstract-text,
.issue-note,
.article-body p {
    text-align: justify;
    text-justify: inter-word;
    -webkit-hyphens: auto;
    -moz-hyphens: auto;
    -ms-hyphens: auto;
    hyphens: auto;
    /* Stops a long DOI, URL or accession number from forcing a horizontal
       scrollbar, which is the commonest way a justified layout breaks. */
    overflow-wrap: break-word;
    word-wrap: break-word;
}

.prose p,
.guide-panel p,
.two-col-grid p {
    font-size: var(--gb-prose-size);
    line-height: var(--gb-prose-leading);
}

/* Things that must never be justified: a two-word list item stretched to
   both margins looks like a fault, not a style. */
.prose li:not(:has(> p)),
.tpl-desc,
.tpl-strip-links span,
.tpl-strip-links a,
.board-card .affil,
.board-card .designation,
.board-card p,
.quick-card p,
.quick-card h5,
.pol-meta,
.pol-toc,
.pol-toc li,
.gb-rail,
.gb-rail li,
.gb-rail p,
.timeline-list li,
.hint,
.metric-label,
figcaption,
.caption,
small,
.footnote,
th, td {
    text-align: left !important;
    hyphens: manual;
}

/* Centred blocks stay centred — the sweep above would otherwise justify
   them into the left margin. */
.callout p,
.callout h3,
.page-hero p,
.metric-label { text-align: center !important; hyphens: manual; }

/* Headings are never justified. */
h1, h2, h3, h4, h5, h6,
.section-title,
.block-heading,
.page-hero h1 {
    text-align: inherit;
    hyphens: manual;
}

/* ── 3. Reading layout: prose + rail ──────────────────────────────────── */
/* Fills the width that a capped prose column would otherwise leave blank,
   and gives every long page the same in-page navigation. */
.gb-reading {
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--gb-rail);
    gap: 46px;
    align-items: start;
}

.gb-rail {
    position: sticky;
    top: 110px;
    border-left: 2px solid #e2e6ed;
    padding-left: 18px;
    font-size: 13px;
}

.gb-rail h2,
.gb-rail .gb-rail-title {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: #6b7a99;
    margin-bottom: 12px;
}

.gb-rail ul { list-style: none; margin: 0; padding: 0; }
.gb-rail li { margin-bottom: 7px; line-height: 1.35; }
.gb-rail a { color: #40567d; text-decoration: none; }
.gb-rail a:hover { color: #2563a8; text-decoration: underline; }
.gb-rail .gb-rail-note { color: #6b7a99; line-height: 1.55; margin-top: 14px; font-size: 12.5px; }

/* Anchor targets must clear the sticky header. */
.prose [id],
.pol-block[id],
h4.block-heading[id] { scroll-margin-top: 120px; }

@media (max-width: 900px) {
    .gb-reading { grid-template-columns: 1fr; gap: 24px; }
    .gb-rail {
        position: static;
        border-left: none;
        border-top: 1px solid #e2e6ed;
        padding-left: 0;
        padding-top: 16px;
        order: 2;
    }
    .gb-rail ul { display: flex; flex-wrap: wrap; gap: 6px 16px; }
    .gb-rail li { margin-bottom: 0; }
}

/* ── 4. Below 720 px: ragged right ────────────────────────────────────── */
@media (max-width: 720px) {
    .section .wrap p,
    .section .wrap li,
    .prose p,
    .prose li,
    .two-col-grid p,
    .preview-body p,
    .pol-block p,
    .pol-block li,
    .guide-panel p,
    .guide-panel li,
    .section-lede,
    .about-body p,
    .card-body p,
    .block-body p,
    .abstract-text,
    .issue-note,
    .article-body p {
        text-align: left;
        hyphens: manual;   /* no hyphenation once ragged — nothing to gain */
    }
}

/* ── 5. Mobile hardening ──────────────────────────────────────────────── */

/* A single wide element — a table, a pre block, a long URL — pushes the
   whole page sideways and every other element then looks misaligned. This
   is usually the real cause of "the alignment is different on my phone". */
html, body {
    overflow-x: hidden;
    max-width: 100%;
}

img, svg, video, iframe {
    max-width: 100%;
    height: auto;
}

table { max-width: 100%; }

@media (max-width: 860px) {
    table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        white-space: nowrap;
    }
    /* Three-line article tables keep their rules when scrolled. */
    table.gb-table { white-space: normal; min-width: 520px; }
}

@media (max-width: 720px) {
    /* Comfortable reading measure and touch targets. Anything below 16px
       makes iOS Safari zoom on focus, which then breaks the layout. */
    .prose p, .pol-block p, .guide-panel p, .two-col-grid p {
        font-size: 15px;
        line-height: 1.72;
    }

    .prose ul, .prose ol,
    .pol-block ul, .pol-block ol,
    .guide-panel ul, .guide-panel ol {
        padding-left: 20px;
        margin-left: 0;
    }

    /* Multi-column grids collapse to one column. */
    .two-col-grid,
    .tpl-grid,
    .tpl-strip-links,
    .quick-grid,
    .board-grid,
    .pol-layout,
    .gb-reading {
        grid-template-columns: 1fr !important;
        display: grid;
    }

    /* Links and buttons reach the 44px touch target Apple and Google both
       recommend; below that, mis-taps are frequent. */
    .nav-cta,
    .btn,
    .tpl-card,
    .tpl-strip-links a,
    .ps-open {
        min-height: 44px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .tpl-card { flex-direction: column; align-items: flex-start; }

    /* Content should not touch the screen edge. */
    .wrap, .container, .prose, .guide-panel {
        padding-left: 16px;
        padding-right: 16px;
        box-sizing: border-box;
    }
}

@media (max-width: 480px) {
    .page-hero h1, .hero h1 { font-size: 24px; line-height: 1.25; }
    .section-title { font-size: 19px; }
    .block-heading { font-size: 15px; }
}

/* ── 6. Print ─────────────────────────────────────────────────────────── */
@media print {
    .site-nav, .site-header, .nav-cta, .site-footer, .gb-rail { display: none; }
    .gb-reading { display: block; }
    .prose, .section-lede { max-width: 100% !important; }
    .prose p, .pol-block p { text-align: justify; hyphens: auto; }
    a[href^="http"]:after { content: " (" attr(href) ")"; font-size: 10px; }
}

/* ── 7. Accessibility ─────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Keyboard focus must stay visible; several inline blocks remove outlines. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
    outline: 2px solid #2563a8;
    outline-offset: 2px;
}
