/* ---------- Albert Sans, self-hosted (OFL 1.1) ---------- */

@font-face {
    font-family: "Albert Sans";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("/fonts/albert-sans-latin.woff2") format("woff2");
    unicode-range:
        U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
        U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
        U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Albert Sans";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("/fonts/albert-sans-latin-ext.woff2") format("woff2");
    unicode-range:
        U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
        U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
        U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "Albert Sans";
    font-style: italic;
    font-weight: 100 900;
    font-display: swap;
    src: url("/fonts/albert-sans-italic-latin.woff2") format("woff2");
    unicode-range:
        U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
        U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
        U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Albert Sans";
    font-style: italic;
    font-weight: 100 900;
    font-display: swap;
    src: url("/fonts/albert-sans-italic-latin-ext.woff2") format("woff2");
    unicode-range:
        U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
        U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
        U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    --red: #a82216;
    --red-dark: #7e190f;
    --bg: #eae4d9;
    --bg-soft: #e1dacc;
    --text: #2e2621;
    --text-muted: #6b5f55;
    --rule: #cfc5b2;
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    /* the bar's full-width band (100vw) would otherwise overflow
     horizontally; clip (not hidden) does not establish a scroll
     container, so position: sticky keeps working. */
    overflow-x: clip;
    scroll-behavior: smooth;
}

body {
    margin: 0;
    padding: 0 1.5rem;
    background: var(--bg);
    color: var(--text);
    font-family:
        "Albert Sans",
        "Helvetica Neue",
        -apple-system,
        BlinkMacSystemFont,
        "Segoe UI",
        Roboto,
        Arial,
        sans-serif;
    font-size: 17px;
    line-height: 1.65;
    font-kerning: normal;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
}

/* 38rem = 608px, i.e. ~72 characters per line: the readable measure.
   This is the single source of truth for content width — paragraphs
   have no max-width of their own and align to this frame, like the
   rules and grids. */
.page {
    max-width: 38rem;
    margin: 0 auto;
    padding: 1.5rem 0 3rem;
}

a {
    color: var(--red);
    text-decoration: underline;
    text-underline-offset: 0.18em;
    text-decoration-thickness: 1px;
    transition: color 0.12s ease;
}

@media (hover: hover) {
    a:hover {
        color: var(--red-dark);
        text-decoration-thickness: 2px;
    }
}

a:focus-visible {
    color: var(--red-dark);
    text-decoration-thickness: 2px;
    outline: 2px solid var(--red);
    outline-offset: 3px;
    border-radius: 2px;
}

h1,
h2,
h3 {
    line-height: 1.25;
    letter-spacing: -0.015em;
}

/* ---------- Header ---------- */

/* Gap between the tagline and the menu. Set here and not on .tagline:
   being the header's last child, its bottom margin is forced to 0 by
   the more specific `p:last-child` rule. So the lever for this gap is
   the header. */
header {
    margin-bottom: 1rem;
}

.brand {
    font-size: clamp(2.4rem, 7vw, 3.4rem);
    font-weight: 800;
    color: var(--red);
    margin: 0;
}

.tagline {
    font-size: clamp(1.05rem, 2.6vw, 1.3rem);
    color: var(--text-muted);
    font-style: italic;
    margin: 0;
    text-align: left;
}

/* Sticky bar across the full page height (the nav is a direct child of
   .page, not of the header, otherwise it would unstick at the header's
   end). The links stay in the column; only the background band, carried
   by the pseudo-element below, spans the full width. */
/* Real full-width sticky bar (Le Monde style): the background lives on the
   element itself — not a pseudo-element — so Safari 26 samples it to tint its
   toolbar. width: 100vw + margin break out of the 38rem column; the links are
   recentred by .menu-inner. */
nav.menu {
    position: sticky;
    top: 0;
    z-index: 5;
    width: 100vw;
    margin-left: calc(50% - 50vw);
    background: var(--bg);
    border-bottom: 1px solid transparent;
}

/* Content wrapper: realigns the links with the column. max-width 41rem =
   38rem of content + 2 x 1.5rem padding, so they line up with the text. */
.menu-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    max-width: 41rem;
    margin: 0 auto;
    padding: 0.5rem 1.5rem;
    font-size: 0.95rem;
}

/* Pill buttons: same vocabulary as the .tags chips, but in the site
   font and one notch larger, a menu having to stay legible. */
nav.menu a {
    padding: 0.25rem 0.8rem;
    border: 1px solid var(--rule);
    border-radius: 999px;
    background: var(--bg-soft);
    color: var(--text);
    text-decoration: none;
    transition:
        background-color 0.12s ease,
        border-color 0.12s ease,
        color 0.12s ease;
}

@media (hover: hover) {
    nav.menu a:hover {
        background: var(--red);
        border-color: var(--red);
        color: var(--bg);
    }
}

nav.menu a:focus-visible {
    background: var(--red);
    border-color: var(--red);
    color: var(--bg);
}

/* The bar's compact "Relkian": hidden and zero-width at rest, it
   unfolds to the left of the links when the bar sticks. The negative
   margin cancels the flex gap while collapsed, so the first link stays
   flush with the column's left edge. Hidden below 40rem: with four
   links, showing it would push the bar onto two lines on mobile. */
.nav-brand {
    overflow: hidden;
    max-width: 0;
    margin-right: -0.5rem;
    opacity: 0;
    color: var(--red);
    font-weight: 800;
    white-space: nowrap;
}

@media (max-width: 40rem) {
    .nav-brand {
        display: none;
    }
}

/* Scroll-driven reveal: pure CSS, no JavaScript.
   Where animation-timeline is unsupported (Firefox stable mid-2026, ~17%),
   nothing runs: the bar stays sticky and functional, without the logo. */
@supports (animation-timeline: scroll()) {
    nav.menu {
        animation: reveal-bar linear both;
        animation-timeline: scroll(root block);
        animation-range: 10rem 14rem;
    }

    .nav-brand {
        animation: reveal-brand linear both;
        animation-timeline: scroll(root block);
        animation-range: 10rem 14rem;
    }
}

/* The "About" menu item folds like .nav-brand: collapsed while the bar is at
   rest, unfolded past the same range. Where animation-timeline is unsupported,
   the link stays visible and the anchor keeps the default offset. */
@supports (animation-timeline: scroll()) {
    nav.menu .nav-about {
        overflow: hidden;
        max-width: 0;
        padding-inline: 0;
        border-inline-width: 0;
        margin-right: -0.5rem;
        opacity: 0;
        white-space: nowrap;
        animation: reveal-about linear both;
        animation-timeline: scroll(root block);
        animation-range: 10rem 14rem;
    }

    /* The pill only folds below the range start, an offset the #about
       anchor can overshoot depending on header height and line
       wrapping. Land the anchor at the very top of the page instead:
       always before the range, so the pill is folded on arrival. */
    #about {
        scroll-margin-top: 100vh;
    }
}

@keyframes reveal-bar {
    to {
        border-bottom-color: var(--rule);
    }
}

@keyframes reveal-brand {
    to {
        max-width: 7rem;
        margin-right: 0.5rem;
        opacity: 1;
    }
}

@keyframes reveal-about {
    to {
        max-width: 8rem;
        padding-inline: 0.8rem;
        border-inline-width: 1px;
        margin-right: 0;
        opacity: 1;
    }
}

/* ---------- Sections ---------- */

section {
    padding: 2.5rem 0 0;
    /* offset anchor targets so they don't land under the sticky bar
       (~3.25rem tall), on top of the section's own 2.5rem padding-top. */
    scroll-margin-top: 2.5em;
}

h2 {
    font-size: 0.8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--red);
    margin: 0 0 1.1rem;
}

p {
    margin: 0 0 1.15rem;
}

/* Justification reserved for wide-enough columns: without hyphenation,
   below ~65 characters per line the spaces stretch into rivers.
   38rem viewport = 560px column (padding deducted) = ~66 chars. */
@media (min-width: 38rem) {
    p {
        text-align: justify;
    }
}

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

/* The About section no longer has a heading: it sits closer to the menu than
   the titled sections, whose rhythm is unchanged. */
.about {
    padding-top: 1.5rem;
}

.about p {
    font-size: 1.1rem;
}

/* GitHub mark next to the profile link. Masked SVG so it takes the link
   color through currentColor (matching it at rest and on hover). */
.icon-github {
    display: inline-block;
    width: 1em;
    height: 1em;
    margin-left: 0.3em;
    vertical-align: -0.15em;
    background-color: currentColor;
    -webkit-mask: url("/images/github.svg") center / contain no-repeat;
    mask: url("/images/github.svg") center / contain no-repeat;
}

strong {
    font-weight: 650;
    color: var(--text);
}

/* ---------- Services ---------- */

.services {
    list-style: none;
    margin: 0;
    padding: 0;
}

.services li {
    padding: 0.65rem 0;
}

.services li:first-child {
    padding-top: 0;
}

.services li:last-child {
    padding-bottom: 0;
}

.services h3 {
    font-size: 1.08rem;
    font-weight: 650;
    margin: 0 0 0.35rem;
}

.services p {
    color: var(--text-muted);
    margin: 0;
}

/* ---------- Skills ---------- */

.skills {
    display: grid;
    gap: 1.6rem 2.5rem;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.skills h3 {
    font-size: 0.95rem;
    font-weight: 650;
    margin: 0 0 0.5rem;
}

.tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.tags li {
    font-family:
        ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.8rem;
    color: var(--text-muted);
    background: var(--bg-soft);
    border: 1px solid var(--rule);
    border-radius: 3px;
    padding: 0.1rem 0.45rem;
    white-space: nowrap;
}

/* ---------- Contact ---------- */

/* minmax at 10.5rem and not 13rem: within 608px, three columns need
   3 x 10.5rem + 2 x 2.5rem = 584px, i.e. 24px of margin. At 13rem it
   would need 704 and the grid would wrap to 2 + 1. */
.contact {
    display: grid;
    gap: 1.4rem 2.5rem;
    grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
}

.contact dt {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
    margin-bottom: 0.3rem;
}

.contact dd {
    margin: 0;
    font-size: 1.02rem;
}

.contact dd address {
    font-style: normal;
}

/* ---------- Legal notice ---------- */

.legal {
    font-size: 0.92rem;
    color: var(--text-muted);
}

.legal h3 {
    font-size: 0.95rem;
    font-weight: 650;
    color: var(--text);
    margin: 1.7rem 0 0.4rem;
}

.legal h3:first-of-type {
    margin-top: 0;
}

.legal p {
    margin: 0 0 0.7rem;
}

/* The two buttons only make sense if the Popover API responds. Without
   it, the popover attribute is ignored: the section stays shown inline
   in place, just before the footer, exactly as before — and these
   inert buttons must then disappear.
   The test is safe: no browser knows popover without knowing
   selector(). Popover ships in Chrome 114 / Safari 17 / Firefox 125,
   selector() as early as Chrome 83 / Safari 14.1 / Firefox 69. */
.legal-open,
.legal-close {
    display: none;
}

@supports selector(:popover-open) {
    .legal-open {
        display: inline-block;
        padding: 0;
        border: 0;
        background: none;
        font: inherit;
        color: var(--red);
        text-decoration: underline;
        text-underline-offset: 0.18em;
        cursor: pointer;
    }

    @media (hover: hover) {
        .legal-open:hover {
            color: var(--red-dark);
        }
    }

    .legal-open:focus-visible {
        color: var(--red-dark);
    }

    /* Beats the `section` padding (specificity 1,1,0 vs 0,0,1). */
    #legal[popover] {
        max-width: 34rem;
        max-height: 80vh;
        overflow: auto;
        padding: 2.5rem 2rem 2rem;
        border: 1px solid var(--rule);
        border-radius: 4px;
        background: var(--bg);
    }

    #legal[popover]::backdrop {
        background: rgb(46 38 33 / 0.5);
    }

    /* The popover is position: fixed (UA stylesheet), so it acts as the
     containing block for this absolute button. */
    .legal-close {
        display: block;
        position: absolute;
        top: 0.5rem;
        right: 0.7rem;
        padding: 0.1rem 0.4rem;
        border: 0;
        background: none;
        color: var(--text-muted);
        font: inherit;
        font-size: 1.5rem;
        line-height: 1;
        cursor: pointer;
    }

    @media (hover: hover) {
        .legal-close:hover {
            color: var(--red);
        }
    }

    .legal-close:focus-visible {
        color: var(--red);
    }
}

/* ---------- Footer ---------- */

footer {
    margin-top: 2.5rem;
    padding: 0.75rem 0 0;
    border-top: 1px solid var(--rule);
    font-size: 0.9rem;
    line-height: 1.4;
    color: var(--text-muted);
}

footer p {
    margin: 0;
    text-align: left;
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    * {
        transition: none !important;
    }
}
