/* The page of one post of the blog, after studio.css. A white sheet on the
   porcelain page holds the hero, the head and the text; the contents stand
   beside it on wide screens, the other posts and the footer follow. Faint
   code glyphs drift in the margins (post.ts places them from the slug), a
   soft glow follows the mouse under the text, a thin bar shows how far the
   reader is. A long-read adds its own stylesheet (txm.css and the like) for
   its figures; the prose, the glossary words and the glossary itself are
   styled here.

   Layers. The glyphs sit on a fixed layer at z-index 0. The white of the
   sheet is its ::before at z-index -1 and the glow under the pointer is at
   -1 too, so both lie under the glyphs; the sheet itself is positioned
   without a z-index, so its text paints over the glyphs. The bar, the
   contents, the other posts and the footer are positioned for the same
   reason. Nothing between the sheet and the page may start a stacking
   context, or the glyphs would hide behind the white. */

html[data-page="post"] { scroll-padding-top: 24px; }
.post-page { background: var(--porcelain); }
.post-page ::selection { background: color-mix(in srgb, var(--magenta) 20%, #fff); color: var(--ink); }

.post-bar, .post-page .footer { position: relative; }
/* The bar and the footer line up with the sheet. */
.post-bar .container, .post-page .footer .container { max-width: calc(1100px + 2 * var(--gutter)); }

/* Reading progress */

.post-progress {
    position: fixed;
    inset: 0 0 auto;
    z-index: 60;
    height: 3px;
    pointer-events: none;
    opacity: 0;
    transition: opacity .4s var(--ease);
}
.post-progress.is-on { opacity: 1; }
.post-progress span {
    display: block;
    height: 100%;
    border-radius: 0 3px 3px 0;
    background: linear-gradient(90deg, var(--magenta), color-mix(in srgb, var(--magenta) 55%, var(--teal)));
    transform: scaleX(0);
    transform-origin: 0 50%;
}

/* Layout: one column, and on wide screens the sheet between two margins,
   the right one holding the contents. */

.post {
    --sheet-pad: clamp(10px, 1.8vw, 24px);
    --prose-pad: clamp(8px, 2.6vw, 34px);
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    padding: clamp(2px, 1vw, 10px) var(--gutter) clamp(64px, 8vw, 112px);
}

.post-article {
    position: relative;
    width: min(100%, 1100px);
    padding: var(--sheet-pad) var(--sheet-pad) clamp(44px, 6vw, 88px);
    border-radius: var(--radius-xl);
    border: 1px solid var(--hairline);
    box-shadow: 0 50px 90px -70px rgba(40, 10, 50, .35);
    overflow: clip;
}
.post-article::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: var(--paper);
}

/* Hero: the icon on a backdrop of its own colour, a poster, or the stage of
   a long-read (styled by its own stylesheet). */

.post-hero--icon, .post-hero--poster {
    position: relative;
    border-radius: calc(var(--radius-xl) - var(--sheet-pad) * .5);
}
.post-hero--icon { aspect-ratio: 16 / 7; min-height: 220px; }
.post-hero--icon .post-cover {
    position: absolute;
    inset: 0;
    overflow: hidden;
    border-radius: inherit;
    background: radial-gradient(70% 100% at 50% 50%,
        color-mix(in srgb, var(--accent) 34%, #fff) 0%,
        color-mix(in srgb, var(--accent) 12%, #fff) 100%);
}
/* The hexagon lattice of the project tiles, faint, fading at the edges. */
.post-hero--icon .post-cover::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: url("/static/studio/img/brand/hex-grid.svg") center / 46px auto;
    opacity: .3;
    -webkit-mask-image: radial-gradient(75% 100% at 50% 50%, #000, transparent 80%);
    mask-image: radial-gradient(75% 100% at 50% 50%, #000, transparent 80%);
}
.post-hero--icon img {
    position: absolute;
    left: 50%;
    top: 50%;
    z-index: 1;
    width: auto;
    height: 55%;
    aspect-ratio: 1;
    object-fit: contain;
    translate: -50% -50%;
    filter: drop-shadow(0 18px 22px color-mix(in srgb, var(--accent) 34%, rgba(23, 18, 28, .24)));
    transition: transform .6s var(--spring);
}
@media (hover: hover) {
    .post-hero--icon:hover img { transform: scale(1.04); }
}
.post-hero--poster .post-cover { overflow: hidden; border-radius: inherit; background: var(--porcelain); }
.post-hero--poster img { width: 100%; height: auto; }

/* Head: where the post sits, its title, the teaser as the lead, the author. */

.post-head {
    max-width: 920px;
    margin: clamp(30px, 4.6vw, 60px) auto 0;
    padding-inline: var(--prose-pad);
    text-align: center;
}
.post-head .eyebrow { text-wrap: balance; }
.post-head .eyebrow a { color: var(--magenta); text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 3px; transition: text-decoration-color .2s; }
.post-head .eyebrow a:hover { text-decoration-color: currentColor; }
.post-title {
    margin-top: 16px;
    font: 600 clamp(32px, 5vw, 60px)/1.05 var(--font-display);
    letter-spacing: -.035em;
    color: var(--ink);
    text-wrap: balance;
    overflow-wrap: break-word;
}
.post-lead {
    max-width: 640px;
    margin: 20px auto 0;
    font-size: clamp(18px, 1.55vw, 21px);
    line-height: 1.55;
    color: var(--slate);
    text-wrap: pretty;
}
.post-byline {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-top: 24px;
    padding: 6px 16px 6px 7px;
    border-radius: 999px;
    border: 1px solid var(--hairline);
    background: var(--porcelain);
    font: 500 14px/1.3 var(--font-body);
    color: var(--ink);
    text-align: left;
}
/* The founder's card: the avatar of the studio page, the name, the role. */
.post-byline .avatar { width: 32px; height: 32px; box-shadow: 0 0 0 2px var(--accent, transparent); }
.post-byline-name { font-weight: 600; }
.post-byline-role { color: var(--slate); }

/* Body: the text at a reading measure, figures wider (the long-read's own
   stylesheet keeps its sections to the same measure). */

.post-body {
    --measure: 700px;
    margin-top: clamp(40px, 6vw, 76px);
    padding-inline: var(--prose-pad);
    font-size: 18px;
    line-height: 1.7;
    color: #3b3542;
}
.post-body:not(:has(> *)) { display: none; }
.post-body > :not(.txm) { max-width: var(--measure); margin-inline: auto; }
.post-body > * + * { margin-top: 1.1em; }
.post-body > h2 { margin-top: 2em; }
.post-body > h3 { margin-top: 1.6em; }
.post-body > h2 + *, .post-body > h3 + * { margin-top: .7em; }
.post-body p { text-wrap: pretty; }
.post-body h2 {
    font: 600 clamp(22px, 2.6vw, 30px)/1.12 var(--font-display);
    letter-spacing: -.03em;
    color: var(--ink);
    text-wrap: balance;
    scroll-margin-top: 28px;
}
.post-body h3 { font: 600 19px/1.3 var(--font-body); color: var(--ink); text-wrap: balance; }
.post-body a:not([class]) {
    color: var(--magenta);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}
.post-body a:not([class]):hover { text-decoration-thickness: 2px; }
.post-body :is(b, strong) { font-weight: 600; color: var(--ink); }
.post-body :is(ul, ol):not([class]) { display: grid; gap: .4em; padding-left: 1.3em; }
.post-body li::marker { color: var(--magenta); }
.post-body code { padding: .12em .38em; border-radius: 6px; background: var(--porcelain); font: 500 .84em/1 var(--font-mono); color: var(--ink); }
.post-body blockquote { padding: 4px 0 4px 20px; border-left: 3px solid var(--magenta); color: var(--ink); }
.post-body img { height: auto; }

/* Glossary words: bold, on a soft teal highlight, with a dotted teal
   underline, so they stand out from the paragraph; they work as plain links
   without the script. Near the mouse the underline brightens (--near, set
   by post.ts, from 0 far away to 1 on the word). */
.post-body a.term {
    color: var(--ink);
    font-weight: 600;
    padding: 0 .16em;
    background: color-mix(in srgb, var(--teal) 9%, transparent);
    text-decoration: underline dotted;
    text-decoration-thickness: 2px;
    text-underline-offset: 4px;
    text-decoration-color: color-mix(in srgb, var(--teal) calc(42% + var(--near, 0) * 58%), transparent);
    border-radius: 4px;
    cursor: help;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    transition: text-decoration-color .3s var(--ease), background-color .2s var(--ease);
}
.post-body a.term:hover, .post-body a.term:focus-visible, .post-body a.term.is-open {
    background: color-mix(in srgb, var(--teal) 20%, transparent);
    text-decoration-color: var(--teal);
}

/* The glossary at the end of a post: every word with its plain meaning. */
.post-glossary {
    padding: clamp(22px, 3.4vw, 38px);
    border-radius: var(--radius-l);
    border: 1px solid var(--hairline);
    background: #FAF9FC;
}
.post-body .post-glossary h2 { font-size: clamp(21px, 2.3vw, 27px); }
.post-glossary dl {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr));
    gap: 4px 12px;
    margin-top: 18px;
}
.g-entry {
    padding: 11px 14px 12px;
    border-radius: 16px;
    scroll-margin-top: 80px;
    transition: background-color .4s var(--ease), box-shadow .4s var(--ease);
}
.g-entry:target { background: #fff; box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--teal) 45%, transparent); }
.g-entry dt { font: 600 15.5px/1.35 var(--font-body); color: var(--ink); }
.g-entry dt::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    margin: 0 9px .12em 0;
    border-radius: 2px;
    background: var(--teal);
    rotate: 45deg;
}
.g-entry dd { margin-top: 4px; font-size: 15px; line-height: 1.55; color: #3b3542; text-wrap: pretty; }

/* The glossary popover: on the page's top layer (post.ts puts it on the
   body and moves it with transform), so no box clips it. */
.post-gloss {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 80;
    width: max-content;
    max-width: min(21rem, calc(100vw - 16px));
    padding: 12px 16px 14px;
    border-radius: 16px;
    border: 1px solid var(--hairline);
    background: #fff;
    box-shadow: 0 18px 40px -8px rgba(23, 18, 28, .2), 0 2px 6px rgba(23, 18, 28, .06);
    color: var(--ink);
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    translate: 0 5px;
    transition: opacity .16s var(--ease), translate .16s var(--ease), visibility 0s linear .16s;
}
.post-gloss[data-side="below"] { translate: 0 -5px; }
/* Once shown it takes the pointer, so the mouse can rest on it and a click
   on it does not fall through to the text under it. */
.post-gloss.is-on { opacity: 1; visibility: visible; translate: 0 0; transition-delay: 0s; pointer-events: auto; }
.post-gloss-term { font: 600 14.5px/1.3 var(--font-body); color: var(--ink); }
.post-gloss-term::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    margin: 0 8px .12em 1px;
    border-radius: 2px;
    background: var(--teal);
    rotate: 45deg;
}
.post-gloss-text { margin-top: 5px; font: 400 14px/1.5 var(--font-body); color: #3b3542; }
.post-gloss-arrow {
    position: absolute;
    left: var(--arrow, 50%);
    width: 12px;
    height: 12px;
    background: #fff;
    border: 1px solid var(--hairline);
    transform: translateX(-50%) rotate(45deg);
}
.post-gloss[data-side="above"] .post-gloss-arrow { bottom: -7px; border-top: 0; border-left: 0; }
.post-gloss[data-side="below"] .post-gloss-arrow { top: -7px; border-right: 0; border-bottom: 0; }

/* The contents: only on wide screens, in the right margin, following the
   reader down the article. post.ts fills it and marks the section being
   read; it fades in once the first section heading comes near. */
.post-toc { display: none; }
.post-toc-title { margin-bottom: 8px; padding-left: 14px; font: 500 11px/1.4 var(--font-mono); text-transform: uppercase; letter-spacing: .09em; color: var(--slate); }
.post-toc-list { display: grid; gap: 1px; margin: 0; padding: 0; list-style: none; }
.post-toc-link {
    position: relative;
    display: block;
    padding: 6px 8px 6px 14px;
    border-radius: 10px;
    font: 500 13px/1.38 var(--font-body);
    color: var(--slate);
    text-wrap: pretty;
    transition: color .25s var(--ease), background-color .25s var(--ease);
}
.post-toc-link::before {
    content: "";
    position: absolute;
    left: 4px;
    top: 7px;
    bottom: 7px;
    width: 2px;
    border-radius: 2px;
    background: #DCD8E3;
    transition: background-color .3s var(--ease), transform .3s var(--ease);
}
.post-toc-link:hover { color: var(--ink); background: rgba(23, 18, 28, .045); }
.post-toc-link.is-active { color: var(--ink); }
.post-toc-link.is-active::before { background: var(--magenta); transform: scaleY(1.15); }

/* More from the blog: the same cards as the home page. */
.post-more {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: 22px 24px;
    width: min(100%, 1100px);
    margin-top: clamp(56px, 8vw, 104px);
}
.post-more-title { font: 600 clamp(26px, 3.4vw, 44px)/1.06 var(--font-display); letter-spacing: -.035em; text-wrap: balance; }
.post-more .more-link { grid-column: 2; grid-row: 1; margin: 0 0 2px; }
.post-more-grid {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
    gap: 20px;
}

@media (min-width: 1240px) {
    .post {
        grid-template-columns: minmax(200px, 1fr) minmax(0, 1100px) minmax(200px, 1fr);
        column-gap: 20px;
        padding-inline: 0;
    }
    .post-article { grid-column: 2; grid-row: 1; width: 100%; }
    .post-more { grid-column: 2; }
    .post-bar .container, .post-page .footer .container { max-width: none; padding-inline: max(220px, (100% - 1100px) / 2); }
    .post-toc:not([hidden]) {
        display: block;
        grid-column: 3;
        grid-row: 1;
        align-self: start;
        justify-self: start;
        position: sticky;
        top: 28px;
        width: min(100% - 16px, 236px);
        max-height: calc(100vh - 56px);
        overflow-y: auto;
        scrollbar-width: none;
        padding: 16px 10px 12px 6px;
        border-radius: 22px;
        border: 1px solid var(--hairline);
        background: color-mix(in srgb, #fff 84%, transparent);
        opacity: 0;
        visibility: hidden;
        translate: 0 10px;
        transition: opacity .45s var(--ease), translate .45s var(--ease), visibility 0s linear .45s;
    }
    .post-toc.is-shown { opacity: 1; visibility: visible; translate: 0 0; transition-delay: 0s; }
    .post-toc::-webkit-scrollbar { display: none; }
}

/* The code glyphs behind the page. post.ts sizes, colours and moves each
   one; here they only drift, slowly, by transform. */
.post-bg {
    position: fixed;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
    contain: strict;
}
.post-glyph {
    position: absolute;
    left: 0;
    top: 0;
    display: grid;
    place-items: center;
    color: var(--magenta);
    will-change: transform;
}
.post-glyph--t1 { color: var(--teal); }
.post-glyph--t2 { color: #6E4BE0; }
.post-glyph--t3 { color: #D9822B; }
.post-glyph--t4 { color: var(--ink); }
.post-glyph-in {
    display: block;
    animation: post-drift var(--d, 40s) ease-in-out var(--delay, 0s) infinite;
}
span.post-glyph-in { font-family: var(--font-mono); font-weight: 600; line-height: 1; letter-spacing: -.02em; white-space: nowrap; }
svg.post-glyph-in { width: 100%; height: 100%; overflow: visible; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
@keyframes post-drift {
    0%, 100% { transform: translate(0, 0) rotate(0deg); }
    25% { transform: translate(var(--dx), calc(var(--dy) * -.5)) rotate(var(--turn)); }
    50% { transform: translate(calc(var(--dx) * .4), var(--dy)) rotate(calc(var(--turn) * -.5)); }
    75% { transform: translate(calc(var(--dx) * -.6), calc(var(--dy) * .3)) rotate(calc(var(--turn) * .4)); }
}

/* The mouse over the text (post.ts sets .post-fx on the page only for a
   fine pointer with motion on): a soft magenta glow under the text, and the
   plain paragraph under the pointer turns full ink. Only colour changes,
   so nothing moves. The low specificity lets every paragraph a long-read
   colours itself (kickers, captions) keep its colour. */
.post-glow { display: none; }
.post-fx .post-glow {
    position: absolute;
    left: 0;
    top: 0;
    z-index: -1;
    display: block;
    width: 680px;
    height: 680px;
    margin: -340px 0 0 -340px;
    border-radius: 50%;
    pointer-events: none;
    background: radial-gradient(closest-side, rgba(180, 24, 156, .1), rgba(180, 24, 156, .045) 48%, rgba(180, 24, 156, 0));
    opacity: 0;
    transition: opacity .6s var(--ease), transform .3s var(--ease);
}
.post-fx .post-glow.is-on { opacity: 1; }
:where(.post-fx .post-body) :where(p, li) { transition: color .35s var(--ease); }
:where(.post-fx .post-body) :where(p, li):hover { color: var(--ink); }

/* Blocks below the first screen rise into place. post.ts marks only what
   it will reveal, so without the script nothing waits hidden. */
.js [data-post-reveal] {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity .8s var(--ease), transform .8s var(--ease);
    transition-delay: var(--reveal-delay, 0ms);
}
.js [data-post-reveal].is-in { opacity: 1; transform: none; }

@media (max-width: 1100px) {
    .post-hero--icon { aspect-ratio: 16 / 8; }
}
@media (max-width: 860px) {
    .post-article { border-radius: 32px; }
    .post-hero--icon { aspect-ratio: 16 / 9; }
}
@media (max-width: 640px) {
    .post-more { grid-template-columns: minmax(0, 1fr); }
    .post-more .more-link { grid-column: 1; grid-row: 3; }
}
@media (max-width: 560px) {
    .post { padding-inline: 10px; }
    .post-article { border-radius: var(--radius-l); }
    .post-hero--icon { aspect-ratio: 4 / 3; min-height: 0; }
    /* On a phone the head reads from the left edge, like the text under it. */
    .post-head { margin-top: 26px; text-align: left; }
    /* Tighter, so the date and the reading time stay on one line. */
    .post-head .eyebrow { font-size: 11.5px; letter-spacing: .05em; }
    .post-title { margin-top: 12px; }
    .post-lead { margin-top: 16px; font-size: 17.5px; }
    .post-glossary { padding: 20px 12px 14px; border-radius: 22px; }
    .post-body .post-glossary h2 { padding-inline: 8px; }
    .g-entry { padding: 10px 8px; }
    .post-byline { font-size: 13.5px; }
    .post-body { font-size: 17px; }
    .post-more { padding-inline: 6px; }
    .post-gloss { padding: 11px 14px 12px; }
}

/* Still: no drift, no glow, no reveal. */
@media (prefers-reduced-motion: reduce) {
    .post-glyph-in { animation: none; }
    [data-post-reveal] { opacity: 1 !important; transform: none !important; }
    .post-hero--icon:hover img { transform: none; }
}
.motion-off .post-glyph-in { animation: none; }
.motion-off [data-post-reveal] { opacity: 1; transform: none; }
.motion-off .post-hero--icon:hover img { transform: none; }

@media (forced-colors: active) {
    .post-bg, .post-glow, .post-progress { display: none; }
    .post-body a.term { text-decoration-color: LinkText; }
    .post-gloss, .post-toc { border: 1px solid CanvasText; }
    .post-toc-link.is-active::before { background: Highlight; }
}

/* Paper: the text and its figures, nothing that moves or links around. */
@media print {
    .post-bg, .post-progress, .post-toc, .post-more, .post-glow, .post-gloss, .skip-link, .bar-links, .post-page .footer { display: none !important; }
    .post-page { background: #fff; }
    .post { display: block; padding: 0; }
    .post-article { width: auto; padding: 0; border: 0; border-radius: 0; box-shadow: none; overflow: visible; }
    .post-article::before { display: none; }
    .post-hero--icon { aspect-ratio: auto; min-height: 0; height: 5.5cm; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    .post-head { margin-top: 12pt; }
    .post-title { font-size: 26pt; }
    .post-lead { font-size: 13pt; color: #333; }
    .post-body { font-size: 11pt; line-height: 1.55; color: #111; }
    .post-body h2, .post-body h3 { break-after: avoid; }
    .post-body :is(figure, img, .g-entry, li, blockquote) { break-inside: avoid; }
    .post-body a:not([class])[href^="http"]::after { content: " (" attr(href) ")"; font-size: .85em; color: #555; }
    .post-body a.term { color: inherit; text-decoration: none; background: none; }
    .post-glossary { border: 0; padding: 0; background: none; }
    [data-post-reveal] { opacity: 1 !important; transform: none !important; }
}
