/* ========================================
   RPG / CHARACTER SHEET
   personal.php: the Projects & Blog pane (php/personal/) and the
   Strange Frontiers pane (php/rpg/). Loaded from php/head-loads.php.
   ======================================== */

/* Keyword spans injected by the bold-keywords script in php/javascript-loads.php */
.mechanic-text {
    font-weight: 500;
}

/* php/rpg/rpg-stats.php, php/rpg/rpg-character.php */
.tiny-text {
    font-size: .75rem;
}

/* Level circle on the character sheet, php/rpg/rpg-character.php */
.level-badge {
    position: absolute;
    top: -35px;
    left: -35px;
    font-size: 2.5rem;
    font-weight: 600;
    padding: 1.5rem;
    background-color: var(--portfolio-black);
    color: var(--portfolio-white);
    border-radius: 50%;
    text-align: center;
    aspect-ratio: 1/1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: min-content;
    line-height: 0;
}

/* Spacer between blocks in the Mechanics and Setting partials (php/rpg/rpg-*.php)
   and between lore entries in php/rpg/lore.php */
.bumper {
    height: 48px;
    width: 100%;
}

/* php/rpg/rpg-stats.php */
.column-image {
    width: 100%;
    padding: 0 48px;
    object-fit: contain;
}

/* Trait cards, php/rpg/rpg-traits.php */
.trait-box {
    padding: 0 1rem 1rem 1rem;
    color: var(--portfolio-black);
    background-color: var(--portfolio-light-gray);
    border: 1px solid var(--portfolio-gray);
    border-radius: 4px;
    overflow: hidden;
    display: flex;
    gap: 0.5rem;
    flex-direction: column;
    width: 100%;
    font-size: 14px;

    .trait-name {
        font-size: 1rem;
        font-weight: 600;
        margin-left: -1rem;
        margin-right: -1rem;
        background-color: var(--portfolio-gray);
        padding: .5rem 1rem;
        color: var(--portfolio-white);
        .mechanic-text {
            font-weight: 600;
        }
    }

    .badge {
        width: fit-content;
        font-weight: 600;
        padding: .5rem 1rem;
        .mechanic-text {
            font-weight: 600;
        }

        .bg-dark {
            background-color: var(--portfolio-gray);
        }
    }
}

strong .mechanic-text {
    font-weight: 600;
}

/* Strange Frontiers side nav, rendered by php/rpg/rpg-links.php. The rail
   sits in personal.php's Setting and Mechanics panels; white invert copies are
   included in the black sections of rpg-traits, rpg-items, rpg-technologies
   and rpg-spacecraft. The dot is positioned by php/javascript-loads.php. */

/* Sticky side nav in a full-height rail so it travels with the panel,
   then pins at top: 134px. Invert copies stay viewport-fixed and clipped
   to black breakouts. */
.rpg-links-rail {
    position: absolute;
    top: 100px;
    bottom: 100px;
    left: 60px;
    z-index: 3;
    width: max-content;
    pointer-events: none;
}

.rpg-links-clip {
    z-index: 4;
    pointer-events: none;
    clip-path: inset(0);
}

.rpg-links-clip .logo-bug,
.rpg-links-clip .section-logo-bug,
.rpg-links-clip .section-about-social-container {
    pointer-events: auto;
}

.breakout:has(> .rpg-links-clip) {
    position: relative;
    z-index: 4;
}

.rpg-links {
    position: sticky;
    top: 134px;
    display: flex;
    gap: .5rem;
    flex-direction: column;
    align-self: flex-start;
    padding-right: 14px;
    pointer-events: auto;

    a {
        display: inline-block;
        width: fit-content;
    }

    .badge {
        background-color: var(--portfolio-black);
        color: var(--portfolio-white);
        padding: .25rem .5rem;
        transition: background-color 200ms;
    }

    /* Opaque blend instead of opacity: the black and white navs are stacked,
       so a translucent link would show the other nav through it. */
    a:hover .badge {
        background-color: color-mix(in srgb, var(--portfolio-black) 66%, var(--portfolio-white));
    }

    &.white a:hover .badge {
        background-color: color-mix(in srgb, var(--portfolio-white) 66%, var(--portfolio-black));
    }

    &.white .badge {
        background-color: var(--portfolio-white);
        color: var(--portfolio-black);
    }
}

.rpg-links-clip .rpg-links {
    position: fixed;
    top: 134px;
    left: 60px;
}

.rpg-links-dot {
    position: absolute;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: var(--portfolio-black);
    pointer-events: none;
    opacity: 0;

    .white & {
        background-color: var(--portfolio-white);
    }

    &.is-ready {
        opacity: 1;
        transition: top 200ms ease, left 200ms ease, opacity 200ms ease;
    }
}

/* overflow-x: hidden on body creates a scroll container that traps sticky.
   clip keeps horizontal overflow hidden without breaking the side nav. */
body:has(.rpg-links-rail),
body:has(.personal-shell) {
    overflow-x: clip;
}

/* The slide shrinks the page to one viewport, which drops the scrollbar and
   nudges the right-aligned chrome sideways. */
html:has(.personal-shell) {
    scrollbar-gutter: stable;
}

/* Two-pane slider in personal.php (Projects & Blog and Strange Frontiers).
   is-personal, is-frontiers, is-sliding and is-revealing are toggled by
   showPersonalPage in php/javascript-loads.php. */
.personal-shell {
    position: relative;
    width: 100%;
    overflow: clip;
}

/* One hero chrome for both panes. It lives outside the track so the slide
   transform can't carry it, and it's clipped to the hero height like the
   per-section copies elsewhere. */
.personal-hero-clip {
    bottom: auto;
    height: 75vh;
    z-index: 5;
    pointer-events: none;
    clip-path: inset(0 0 -1px 0);
}

.personal-hero-clip > * {
    pointer-events: auto;
}

.personal-hero-clip .logo-bug {
    background-color: var(--portfolio-white);
    color: var(--portfolio-black);
}

.personal-hero-clip .social-link svg {
    fill: var(--portfolio-black);
}

.personal-shell.is-personal .nav-bullet-frontiers,
.personal-shell.is-frontiers .nav-bullet-personal {
    display: none;
}

.personal-track {
    display: flex;
    width: 200vw;
    align-items: flex-start;
    position: relative;
    left: 0;
}

.personal-shell.transitions-on.is-sliding .personal-track {
    transition: transform 700ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
}

.personal-shell.is-frontiers:not(.is-sliding) .personal-track {
    left: -100vw;
}

.personal-pane {
    width: 100vw;
    flex: 0 0 100vw;
    min-height: 100vh;
}

.personal-shell.is-personal:not(.is-sliding) .pane-frontiers,
.personal-shell.is-frontiers:not(.is-sliding) .pane-personal {
    height: 0;
    min-height: 0;
    overflow: hidden;
    pointer-events: none;
    visibility: hidden;
}

/* Only the two heroes move. Full-page `left` animation was laying out both
   documents every frame; transform is compositor-only and the rest stays out. */
.personal-shell.is-sliding .personal-pane {
    height: 100vh;
    min-height: 100vh;
    max-height: 100vh;
    overflow: hidden;
    visibility: visible;
}

.personal-shell.is-sliding .personal-pane > :not(.short-section) > * {
    visibility: hidden;
    opacity: 0;
}

/* Transform on the track creates a stacking context, so the page-level black
   EW would paint over the heroes. Hide it during the slide. */
body:has(.personal-shell.is-sliding) > .section-logo-bug,
body:has(.personal-shell.is-sliding) > .section-about-social-container {
    visibility: hidden;
}

/* Fade what's inside each section, not the sections, so panel whites and the
   footer tint land immediately instead of fading up from the night sky. */
.personal-shell.transitions-on.is-revealing .personal-pane.is-visible > :not(.short-section) > * {
    opacity: 0;
    transition: opacity 350ms ease;
}

.personal-shell.transitions-on.is-revealing.is-revealed .personal-pane.is-visible > :not(.short-section) > * {
    opacity: 1;
}

.personal-shell.is-revealing:not(.is-revealed) .personal-pane.is-visible > :not(.short-section) {
    pointer-events: none;
}

/* Hero nav (Projects & Blog / Strange Frontiers), php/personal/page-nav.php */
.personal-page-nav a {
    display: inline-block;
    position: relative;
}

.personal-page-nav .nav-bullet {
    left: auto;
    right: -18px;
}

/* Green Strange Frontiers accent: hero title in personal.php and its nav link */
.frontiers-accent,
.personal-page-nav a.frontiers-accent,
.personal-page-nav a.frontiers-accent .nav-bullet {
    color: #2dfc64;
}

/* Pane tab bars along the bottom of each hero in personal.php
   (Blog / Projects / Photos and Setting / Mechanics / Change Log) */
.rpg-tabs {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 3;

    .container {
        height: auto;
    }
}

.rpg-tab-list {
    display: flex;
    align-items: stretch;
    gap: .5rem;
}

.rpg-tab {
    appearance: none;
    font-family: 'bebas_neueregular', sans-serif;
    font-size: 1.5rem;
    letter-spacing: 1px;
    line-height: 1;
    padding: .75rem 1.5rem;
    background: var(--portfolio-gray);
    color: var(--portfolio-white);
    border: 0;
    border-radius: 4px 4px 0 0;
    cursor: pointer;
    transition: background-color 200ms;
}

.rpg-tab.is-active {
    background: var(--portfolio-white);
    color: var(--portfolio-black) !important;
    /* Cover the subpixel gap so the white tab meets the white panel */
    box-shadow: 0 1px 0 var(--portfolio-white);
}

/* Phones: the Change Log tab doesn't fit beside the other three */
@media (max-width: 575px) {
    #tab-changelog {
        display: none;
    }
}

/* Boxed sub-tabs inside Setting: php/rpg/rpg-setting.php (Timeline),
   rpg-technologies, rpg-planes, rpg-spacecraft and rpg-parabiology.
   tech-fields-light is the black-on-white version used in rpg-setting,
   rpg-planes and rpg-parabiology. */
.tech-fields {
    padding: 0 24px 36px;
    border: 1px solid var(--portfolio-white);
    border-radius: 10px;
    overflow: hidden;
}

.tech-field-tab-list {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: .5rem;
    margin-bottom: 36px;
}

.tech-field-tab {
    appearance: none;
    font-family: 'bebas_neueregular', sans-serif;
    font-size: 1.25rem;
    letter-spacing: 1px;
    line-height: 1;
    padding: .6rem 1.1rem;
    background: var(--portfolio-gray);
    color: var(--portfolio-white);
    border: 0;
    border-radius: 0 0 4px 4px;
    cursor: pointer;
    transition: background-color 200ms;
}

@media (hover: hover) {
    .rpg-tab:not(.is-active):hover,
    .tech-field-tab:not(.is-active):hover {
        background-color: color-mix(in srgb, var(--portfolio-gray) 66%, transparent);
    }
}

.tech-field-tab.is-active {
    background: var(--portfolio-white);
    color: var(--portfolio-black);
}

.tech-fields-light {
    border-color: var(--portfolio-black);
}

.tech-fields-light .tech-field-tab.is-active {
    background: var(--portfolio-black);
    color: var(--portfolio-white);
}

.rpg-tab:focus,
.tech-field-tab:focus {
    outline: none;
}

.rpg-tab:focus-visible,
.tech-field-tab:focus-visible {
    outline: 2px solid #2dfc64;
    outline-offset: -2px;
}

/* Inline lore links built by sf_lore_link() in php/rpg/lore.php, used
   throughout the Strange Frontiers copy */
.lore-link {
    color: #884ddc;
    font-weight: 600;
    text-decoration: underline dotted;
    text-underline-offset: 3px;
    cursor: pointer;
}

.lore-link:hover {
    color: #884ddc;
    text-decoration-style: solid;
}

/* #884ddc is 3.18:1 on #212121; this lighter purple clears 4.5:1. */
.black-bg .lore-link,
.black-bg .lore-link:hover {
    color: #a67bf0;
}

.lore-link:focus {
    outline: none;
}

.lore-link:focus-visible,
.lore-modal-close:focus-visible {
    outline: 2px solid #2dfc64;
    outline-offset: 2px;
    border-radius: 2px;
}

/* Lore popup, php/rpg/lore-modal.php (included by personal.php). Opened and
   filled from the hidden lore store by php/javascript-loads.php. */
html.lore-modal-open {
    overflow: hidden;
}

.lore-modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 64px 24px;
    background: rgba(0, 0, 0, .75);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s ease, visibility .2s ease;
}

.lore-modal.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity .2s ease, visibility 0s;
}

.lore-modal-panel {
    position: relative;
    width: 100%;
    max-width: 720px;
    max-height: 100%;
    overflow-y: auto;
    padding: 32px;
    border-radius: 8px;
    background: var(--portfolio-white);
    color: var(--portfolio-black);
    box-shadow: 0 12px 40px rgba(0, 0, 0, .4);
}

.lore-modal-title {
    margin-bottom: 16px;
    padding-right: 48px;
}

.lore-modal-body > :last-child {
    margin-bottom: 0;
}

.lore-modal-body .d-flex.flex-wrap {
    flex-direction: column;
    gap: 24px;
}

.lore-modal-close {
    appearance: none;
    position: absolute;
    top: 20px;
    right: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--portfolio-black);
    color: var(--portfolio-white);
    cursor: pointer;
    transition: background-color 200ms;
}

.lore-modal-close:hover {
    background-color: color-mix(in srgb, var(--portfolio-black) 66%, var(--portfolio-white));
}

@media (max-width: 767px) {
    .lore-modal {
        padding: 24px 16px;
    }

    .lore-modal-panel {
        padding: 24px;
    }

    .lore-modal-close {
        top: 14px;
        right: 14px;
    }
}

/* Strange Frontiers search, personal.php. Indexed and filled by
   php/javascript-loads.php; results open in the lore popup. */
.rpg-search {
    position: fixed;
    top: 32px;
    left: 50%;
    z-index: 5;
    display: none;
    width: 320px;
    transform: translateX(-50%);
}

body:has(.personal-shell.is-frontiers:not(.is-sliding)) .rpg-search {
    display: block;
}

.rpg-search-icon {
    position: absolute;
    top: 50%;
    left: 14px;
    width: 15px;
    height: 15px;
    color: #9a9a9a;
    transform: translateY(-50%);
    pointer-events: none;
}

.rpg-search-input {
    display: block;
    width: 100%;
    height: 35px;
    padding: 0 16px 0 38px;
    border: 1px solid rgba(255, 255, 255, .35);
    border-radius: 18px;
    background: var(--portfolio-black);
    color: var(--portfolio-white);
    font-family: 'Open Sans', sans-serif;
    font-size: 14px;
    transition: border-color 200ms;
}

.rpg-search-input::placeholder {
    color: #9a9a9a;
    opacity: 1;
}

.rpg-search-input:focus {
    outline: none;
    border-color: #2dfc64;
}

.rpg-search-results {
    position: absolute;
    top: calc(100% + 8px);
    left: 50%;
    width: 440px;
    max-width: calc(100vw - 40px);
    max-height: min(60vh, 520px);
    overflow-y: auto;
    margin: 0;
    padding: 6px;
    list-style: none;
    border-radius: 8px;
    background: var(--portfolio-white);
    color: var(--portfolio-black);
    box-shadow: 0 12px 40px rgba(0, 0, 0, .4);
    transform: translateX(-50%);
}

.rpg-search-result {
    padding: 8px 12px;
    border-radius: 6px;
    cursor: pointer;
}

.rpg-search-result:hover,
.rpg-search-result.is-active {
    background: #ececec;
}

.rpg-search-result-title {
    display: block;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.3;
}

.rpg-search-result-context {
    display: block;
    margin-top: 2px;
    color: #6b6b6b;
    font-size: 11px;
    letter-spacing: .02em;
    text-transform: uppercase;
}

.rpg-search-result-snippet {
    display: block;
    margin-top: 4px;
    color: #444;
    font-size: 12px;
    line-height: 1.45;
}

.rpg-search-result mark {
    padding: 0;
    background: color-mix(in srgb, #2dfc64 45%, transparent);
    color: inherit;
}

.rpg-search-empty {
    padding: 8px 12px;
    color: #6b6b6b;
    font-size: 13px;
}

@media (max-width: 991px) {
    body:has(.personal-shell.is-frontiers:not(.is-sliding)) .rpg-search {
        display: none;
    }
}

/* Panels switched by the .tech-field-tab buttons above */
.tech-field-panel {
    display: none;
}

.tech-field-panel.is-active {
    display: block;
}

/* Info box columns in the plane, Ark, nation, and corporation lore entries, php/rpg/lore/ */
.info-cols {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 24px;
    margin: 2rem 0 0;
}

.info-cols > * {
    flex: 0 0 auto;
    width: max-content;
    max-width: 100%;
}

/* Nation attribute columns (rpg-setting.php) share the row equally */
.info-cols > .flex-1 {
    flex: 1;
    width: auto;
    min-width: 160px;
}

@media (min-width: 768px) {
    #plane-known .info-cols > :nth-child(1) {
        width: 128px;
    }

    #plane-known .info-cols > :nth-child(2) {
        flex: 0 1 256px;
        width: auto;
    }
}

.info-cols > .flex-1:first-child {
    max-width: 360px;
}

.info-cols > :last-child {
    flex: 1 1 0;
    width: auto;
    min-width: 0;
}

@media (max-width: 767px) {
    .info-cols {
        flex-direction: column;
        gap: 12px;
    }

    .info-cols > *,
    .info-cols > :last-child {
        flex: 0 0 auto;
        width: auto;
        max-width: none;
    }

    .info-cols > .attr-list {
        margin-bottom: 0;
    }

    .info-cols > :last-child {
        margin-bottom: 1rem;
    }
}

/* Info box entries: small label stacked above its value */
.attr-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin: 0 0 1rem;
    padding-inline-start: 0;

    dt {
        font-size: 0.75rem;
        font-weight: 400;
        letter-spacing: 0.04em;
        line-height: 1.2;
        opacity: 0.6;
    }

    dd {
        margin: 0;
    }

    dd:empty::before {
        content: "\2014";
        opacity: 0.4;
    }
}

/* Collapsible "Details" section under an attribute block: plane, Ark, and
   corporation lore entries in php/rpg/lore/, the Nations tab in rpg-setting.php, and
   the Starships tab in rpg-spacecraft.php.
   Boxed whether open or closed; border matches .line. */
.lore-details {
    border: 1px solid rgb(0 0 0 / 15%);
    border-radius: var(--portfolio-radius);
    padding: 16px;

    .black-bg & {
        border-color: rgb(255 255 255 / 25%);
    }

    > summary {
        display: block;
        list-style: none;
        cursor: pointer;
        margin-bottom: 0;

        &::-webkit-details-marker {
            display: none;
        }

        .line {
            display: none;
        }

        h5 > strong,
        h5::after {
            font-weight: 300;
        }

        /* Fade the text, not the h5: its background is what covers the .line */
        h5 > strong,
        h5::after {
            transition: opacity 0.2s ease;
        }

        h5::after {
            content: "+";
            display: inline-block;
            width: 1em;
            margin-left: 6px;
            font-size: 1.6em;
            line-height: 0;
            vertical-align: -0.12em;
            text-align: center;
        }

        &:hover h5 > strong,
        &:hover h5::after {
            opacity: 0.6;
        }

        &:focus-visible {
            outline: 2px solid #2dfc64;
            outline-offset: 2px;
        }
    }

    &[open] > summary {
        margin-bottom: 20px;

        h5::after {
            content: "\2212";
        }
    }

    > :last-child {
        margin-bottom: 0;
    }

    /* Overview / History / Geography / Territories columns: plain bold
       titles instead of the ruled heading. */
    > .d-flex {
        gap: 20px 40px;

        @media (max-width: 959px) {
            column-gap: 24px;
        }

        > :is(.flex-6, .flex-7) {
            > :last-child {
                margin-bottom: 0;
            }
        }

        .line-container {
            margin-bottom: 12px;

            h5 {
                padding: 0;
            }

            .line {
                display: none;
            }
        }
    }
}

.personal-pane .section-clip {
    /* Let that 1px seam cover paint; keep the rest of the hero clip */
    clip-path: inset(0 0 -1px 0);
}

/* Tab panels for both panes in personal.php, switched by .rpg-tab */
.rpg-panel {
    display: none;
}

.rpg-panel.is-active {
    display: flex;
    flex-direction: column;
}

/* Setting and Mechanics sections in personal.php */
#rpg-setting.section.unlimited {
    padding-bottom: 0;
}

/* Keep setting/mechanics section rows full-width inside the flex container
   so short placeholder blocks cannot sit side-by-side. */
#rpg-setting > .container > .d-flex,
#rpg-setting > .container > .w-100,
#rpg-mechanics > .container > .d-flex,
#rpg-mechanics > .container > .w-100,
#rpg-mechanics > .container > .separator,
#rpg-setting > .container > .separator {
    flex: 0 0 100%;
    width: 100%;
    max-width: 100%;
}

.personal-pane .black-section {
    color: var(--portfolio-white);
}

@media (prefers-reduced-motion: reduce) {
    .personal-shell.transitions-on.is-sliding .personal-track {
        transition: none;
        will-change: auto;
    }

    .personal-shell.transitions-on.is-revealing .personal-pane.is-visible > :not(.short-section) > * {
        transition: none;
        opacity: 1;
    }
}

/* php/personal/blog.php, php/personal/projects.php */
.blog-content {
    max-width: 640px;
    width: 100%;
}

/* php/rpg/rpg-changelog.php, rpg-setting, rpg-technologies, rpg-planes, rpg-spacecraft */
.single-column-content {
    max-width: 768px;
    width: 100%;
}

/* Intro copy columns (Setting, Rebirth of Science, The Planes, The Stars, Parabiology)
   with a placeholder image beside it. The copy column is 768px, so the placeholder only shows
   from 1500px up, where it gets at least ~260px. */
.intro-with-image {
    display: flex;
    gap: 40px;

    > .single-column-content {
        flex: 0 1 768px;
    }
}

.image-placeholder {
    display: none;
    flex: 1 1 0;
    min-width: 0;
    align-items: center;
    justify-content: center;
    background-color: var(--portfolio-light-gray);
    border-radius: var(--portfolio-radius);
    color: var(--portfolio-medium-gray);
    font-family: 'bebas_neueregular', sans-serif;
    font-size: 1.5rem;
    letter-spacing: 1px;

    /* Inverted over dark sections (Rebirth of Science, The Stars). */
    .black-bg & {
        background-color: var(--portfolio-gray);
        color: var(--portfolio-white);
    }
}

/* A real image in the placeholder's spot. The planet GIFs are 100px pixel art,
   so they scale up in whole steps without smoothing. */
.intro-image {
    display: none;
    flex: 1 1 0;
    min-width: 0;
    align-items: center;
    justify-content: center;

    img {
        width: 100%;
        max-width: 400px;
        height: auto;
        image-rendering: pixelated;
    }
}

@media (min-width: 1500px) {
    .image-placeholder,
    .intro-image {
        display: flex;
    }
}

/* php/personal/blog.php */
.blog-posts {
    display: flex;
    flex-direction: column;
    gap: 24px;
}

/* php/rpg/rpg-changelog.php */
.changelog-entries {
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.changelog-list {
    margin: 0;
    padding-left: 1.25rem;
}

.changelog-list li + li {
    margin-top: 0.5rem;
}

/* Bordered cards: php/personal/blog.php, php/personal/projects.php,
   php/rpg/rpg-changelog.php, and the intro vignette in php/rpg/rpg-setting.php */
.blog-post {
    border: 1px solid var(--portfolio-light-gray);
    border-radius: 8px;
    padding: 1.5rem;
}

.blog-post .copy:last-child {
    margin-bottom: 0;
}

/* php/personal/blog.php */
.blog-post-images {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;

    img {
        display: block;
        width: 100%;
        height: auto;
        border-radius: 8px;
    }
}

/* php/personal/projects.php */
.project-entries {
    display: flex;
    flex-direction: column;
    gap: 48px;
}

.project-title {
    padding-bottom: .75rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--portfolio-light-gray);
}

.project-images {
    display: flex;
    flex-direction: column;
    gap: 16px;

    img {
        display: block;
        width: 100%;
        height: auto;
        border-radius: 8px;
    }
}

.project-images-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    align-content: start;
}

/* Opening story card in the Introduction, php/rpg/rpg-setting.php */
.intro-vignette .copy {
    font-style: italic;
}

/* Model photos tab, php/personal/photos.php */
.model-photo-gallery {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 30px;
    width: 100%;

    > * {
        position: relative;
        min-width: 0;
        min-height: 0;
        aspect-ratio: 1 / 1;
        overflow: hidden;
        border-radius: 8px;
    }

    img {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        object-position: center;
        display: block;
    }

    .is-featured {
        grid-column: 1 / -1;
        aspect-ratio: 16 / 9;
    }

    .is-hero {
        grid-column: span 2;
        grid-row: span 2;
        aspect-ratio: auto;
    }
}

/* Heading with a rule running off to the right (.line-container + .line).
   Used across php/rpg/ partials and the lore entries in php/rpg/lore/. */
.line-container {
    position: relative;
    margin-bottom: 20px;

    h4, h5, h6 {
        background-color: var(--portfolio-white);
        z-index: 2;
        position: relative;
        display: inline-block;
        margin: 0;
        padding: 0 20px 0 0;
    }

    .black-bg & {
        h4, h5, h6 {
            background-color: var(--portfolio-black);
        }
    }
}

/* Alternating timeline: Setting > Timeline tab, php/rpg/rpg-setting.php.
   Each direct child is one entry (.line-container year + ul.copy). */
.sf-timeline {
    --sf-timeline-marker: 11px;
    --sf-timeline-gutter: 32px;

    position: relative;
    display: flex;
    flex-direction: column;
    row-gap: 20px;

    &::before {
        content: "";
        position: absolute;
        top: 0;
        bottom: 0;
        left: 50%;
        width: 1px;
        background-color: rgb(0 0 0 / 15%);
        transform: translateX(-50%);
    }

    > div {
        position: relative;
        width: 50%;
        padding-right: var(--sf-timeline-gutter);
        text-align: right;

        &::before {
            content: "";
            position: absolute;
            top: 5px;
            right: calc(var(--sf-timeline-marker) / -2);
            width: var(--sf-timeline-marker);
            height: var(--sf-timeline-marker);
            border-radius: 50%;
            background-color: var(--portfolio-black);
            z-index: 1;
        }
    }

    > div:nth-child(even) {
        align-self: flex-end;
        padding-right: 0;
        padding-left: var(--sf-timeline-gutter);
        text-align: left;

        &::before {
            right: auto;
            left: calc(var(--sf-timeline-marker) / -2);
        }
    }

    .line-container {
        margin-bottom: 4px;

        h6 {
            padding: 0;
        }

        .line {
            display: none;
        }
    }

    ul.copy {
        list-style: none;
        padding-left: 0;
        margin-bottom: 0;
    }

    @media (max-width: 767px) {
        &::before {
            left: calc(var(--sf-timeline-marker) / 2);
        }

        > div,
        > div:nth-child(even) {
            align-self: stretch;
            width: 100%;
            padding-right: 0;
            padding-left: var(--sf-timeline-gutter);
            text-align: left;

            &::before {
                right: auto;
                left: 0;
            }
        }
    }
}

/* php/rpg/rpg-setting.php, rpg-planes, rpg-spacecraft */
.content-stack {
    display: flex;
    flex-direction: column;
    gap: 48px;

    > * > :last-child {
        margin-bottom: 0;
    }
}

/* Two-column content rows in Strange Frontiers, php/rpg/ and php/rpg/lore/ */
.split-cols {
    gap: 48px 40px;

    @media (max-width: 959px) {
        column-gap: 24px;
    }
}

/* Timeline (rpg-setting.php), starship classes (rpg-spacecraft.php) */
.content-stack-sm {
    gap: 20px;
}

.lore-body > :last-child {
    margin-bottom: 0;
}

.fst-italic {
    font-style: italic;
}

.line {
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%; 
    height: 1px;
    background-color: rgb(0 0 0 / 15%);
    transform: translateY(-50%); 
    z-index: 1; 

    .black-bg & {
        background-color: rgb(255 255 255 / 25%);
    }
}

/* Character sheet, php/rpg/rpg-character.php (through .c-variables below).
   .stat-line, .stat and .stat-badge are also used in rpg-stats, rpg-skills
   and rpg-traits. */
.empty-list {
    list-style-type: none;
    padding-left: 0;
    margin-left: 0;
}

.empty-list.call-response {
    li {
        margin-bottom: .5rem;
        font-weight: 600;
    }
    li:nth-child(odd) {
        margin-bottom: 0;
        font-weight: 300;
    }
}

.c-sheet {
    background-color: var(--portfolio-near-white);
    border: 1px solid var(--portfolio-light-gray);
    padding: 1rem;
    border-radius: 24px;
}

.c-sheet-box {
    padding: 2rem;
    background-color: var(--portfolio-white);
    border: 1px solid var(--portfolio-light-gray);
    border-radius: 4px;
}

/* The whole pixel-art portrait fits in the square, unsmoothed. */
.c-sheet-image {
    width: 100%;
    object-fit: contain;
    aspect-ratio: 1/1;
    image-rendering: pixelated;
}

.stat-line {
    display: grid;
    width: 100%;
    grid-template-columns: repeat(20, 1fr);
    gap: 1.5%;
}

.stat {
    grid-column: span 1;
    aspect-ratio: 1/1;
    /* min-width: 16px;
    min-height: 16px; */
    width: 100%;

    
    &.dot {
        border-radius: 50%;
    }
    
    &.square {
        border-radius: 4px;
    }
    
    &.default {
        background-color: var(--portfolio-medium-gray);
    }
    
    &.filled {
        background-color: var(--portfolio-black);
    }
    
    &.empty {
        border: 2px solid var(--portfolio-gray);
    }
    
    &.unavailable {
        border: 2px solid var(--portfolio-red);
    }
}

.stat-badge {
    font-size: 1.25rem;
    font-weight: 600;
    background-color: var(--portfolio-black);
    color: var(--portfolio-white);
    padding: .75rem;
    border-radius: 50%;
    text-align: center;
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: min-content;
    line-height: 0;
}

/* Sample character sheet: a ruled stat heading sits beside its badge, so drop
   .line-container's bottom margin to keep the rule on the badge's center line */
.stat-badge + .line-container {
    margin-bottom: 0;
}

.c-variables {
    column-gap: 12px;
}

/* ========================================
   RPG MEDIA QUERIES
   1199px: the side gutters collapse, so the side nav moves to the right edge
           with its dot on the left to keep clear of headings and opening copy.
   992px: side nav and character sheet tighten.
   767px: side nav moves to the bottom-right corner, tabs and gallery shrink.
   ======================================== */

@media only screen and (max-width: 1199px) {
    .rpg-links-rail {
        left: auto;
        right: 60px;
    }

    /* The rail is measured from the panel, which spans the full 100vw, but the
       fixed copy is measured from the viewport inside the scrollbar. Pull it
       back by the scrollbar's width (100vw - 100%) so the two navs line up. */
    .rpg-links-clip .rpg-links {
        left: auto;
        right: calc(60px - (100vw - 100%));
    }

    .rpg-links-rail .rpg-links,
    .rpg-links-clip .rpg-links {
        align-items: end;
        padding-right: 0;
        padding-left: 14px;
    }
}

@media only screen and (max-width: 992px) {
    .rpg-links-rail {
        right: 5vw;
    }

    .rpg-links-clip .rpg-links {
        right: calc(5vw - (100vw - 100%));
    }

    .c-sheet {
        padding: .5rem;
        border-radius: 4px;
    }

    .c-sheet-box {
        padding: 1rem;
    }

    .column-image {
        padding: 0;
    }
}

@media only screen and (max-width: 767px) {
    .rpg-links-rail {
        position: fixed;
        top: auto;
        bottom: 24px;
        right: 24px;
        z-index: 4;
    }

    .rpg-links-rail .rpg-links {
        position: static;
    }

    .rpg-links-clip .rpg-links {
        top: auto;
        bottom: 24px;
        right: 24px;
    }

    .rpg-tab {
        font-size: 1.25rem;
        padding: .6rem 1rem;
    }

    .tech-field-tab {
        font-size: 1.1rem;
        padding: .5rem .85rem;
    }

    .model-photo-gallery {
        grid-template-columns: 1fr;
        gap: 30px;

        .is-featured,
        .is-hero {
            grid-column: auto;
            grid-row: auto;
            aspect-ratio: 1 / 1;
        }
    }

    .section-scroll-links.personal-page-nav {
        display: block;
        font-size: 1.25rem;
    }

    .c-variables {
        column-gap: 4px
    }

    .c-variables, .c-variables h5 {
        font-size:3.6vw;
        margin-bottom: 0;
        align-self: center;
    }

    .level-badge {
        position: absolute;
        top: -15px;
        left: -15px;
        font-size: 1.5rem;
        padding: .75rem;
    }
}

/* Hero image pulled 48px past both sides of its column (Isekai map, personal.php) */
.breakout-img {
    width: calc(100% + 96px);
    max-width: none;
    margin-left: -48px;
    margin-right: -48px;

    /* Up to 992px the container is 90vw, so the gutter is 5vw: never pull past it */
    @media (max-width: 992px) {
        width: calc(100% + min(96px, 10vw));
        margin-left: max(-48px, -5vw);
        margin-right: max(-48px, -5vw);
    }

    /* Below 768px the page gutter is only 20px: go edge to edge */
    @media (max-width: 767px) {
        width: calc(100% + 40px);
        margin-left: -20px;
        margin-right: -20px;
    }
}

/* Starter Kinds, Origins, Professions, Pasts (php/rpg/dreftian-starters.php) */
.starter-entry + .starter-entry {
    margin-top: 1.5rem;
}

.starter-entry h6 {
    margin-bottom: .5rem;
}
