From d995094b5251f1e5ab443e644d07aa6e6a145bb4 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 12 Sep 2026 04:17:27 +0700 Subject: [PATCH] Put the contents beside the text instead of above it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nineteen entries at the top of a long page are scrolled past once and then unreachable. A fixed column stays put and scrolls on its own. Below 66rem there is not room for two columns, so it collapses to a bar with a toggle — a checkbox, so the page still needs no script to navigate. The wordmark's dot was a circle at a guessed x, which drifted from the n whenever the reader's serif was not the one it was measured against. It is a full stop in the same text run now. --- web/index.html | 119 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 30 deletions(-) diff --git a/web/index.html b/web/index.html index c042f21..d99fb28 100644 --- a/web/index.html +++ b/web/index.html @@ -67,6 +67,7 @@ body { color: var(--text); font: 17px/1.65 "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif; } +main { display: block; } .wrap { max-width: 44rem; margin: 0 auto; padding: 0 1.25rem 6rem; } header { padding: 3.5rem 0 2rem; } @@ -117,12 +118,63 @@ th { font-weight: 600; color: var(--muted); } .lede { font-size: 1.1rem; } .note { color: var(--muted); font-size: .94rem; } -nav.toc { background: var(--panel); border-radius: 5px; padding: 1rem 1.25rem; margin: 2rem 0 0; } -nav.toc ul { list-style: none; padding: 0; margin: 0; columns: 2; column-gap: 2rem; } -nav.toc li { margin: .18rem 0; font-size: .93rem; break-inside: avoid; } + +/* The table of contents: a bar with a toggle when the window is narrow, a + fixed column beside the text when there is room for one. The toggle is a + checkbox so that no script is needed to open it. */ +.toc-toggle { position: absolute; width: 1px; height: 1px; opacity: 0; } +.toc-button { + display: block; cursor: pointer; user-select: none; + position: sticky; top: 0; z-index: 2; + padding: .6rem 1.25rem; + background: var(--panel); border-bottom: 1px solid var(--rule); + color: var(--muted); font-size: .92rem; letter-spacing: .02em; +} +.toc-button::before { content: "\2261\00a0\00a0"; } +.toc-toggle:focus-visible + .toc-button { outline: 2px solid var(--accent); outline-offset: -2px; } +nav.toc { + display: none; + background: var(--panel); border-bottom: 1px solid var(--rule); + padding: .75rem 1.25rem 1.1rem; +} +.toc-toggle:checked ~ nav.toc { display: block; } +.toc-title { + display: none; /* the toggle already says "Contents" */ + margin: 0 0 .5rem; font-size: .78rem; letter-spacing: .09em; + text-transform: uppercase; color: var(--muted); +} +nav.toc ul { list-style: none; padding: 0; margin: 0; } +nav.toc li { margin: 0; font-size: .93rem; } +nav.toc a { + display: block; padding: .2rem 0; color: var(--muted); + text-decoration: none; border-left: 2px solid transparent; padding-left: .6rem; +} +nav.toc a:hover { color: var(--link); border-left-color: var(--accent); } +h2, h3 { scroll-margin-top: 3.5rem; } + +/* Nineteen entries one to a line fills a phone screen, so the opened panel + goes to two columns as soon as there is room for them. */ +@media (min-width: 30rem) and (max-width: 65.99rem) { + nav.toc ul { columns: 2; column-gap: 1.5rem; } + nav.toc li { break-inside: avoid; } +} footer { margin-top: 3.5rem; padding-top: 1.5rem; border-top: 1px solid var(--rule); color: var(--muted); font-size: .92rem; } -@media (max-width: 34rem) { nav.toc ul { columns: 1; } } +/* Wide enough for both: the contents become a column of their own, scrolling + independently of the page, and the text moves over to sit beside it. */ +@media (min-width: 66rem) { + .toc-button { display: none; } + nav.toc { + display: block; + position: fixed; top: 0; left: 0; bottom: 0; + width: 15rem; overflow-y: auto; overscroll-behavior: contain; + background: none; border-bottom: 0; border-right: 1px solid var(--rule); + padding: 3.6rem 1rem 2rem 1.5rem; + } + main { margin-left: 15rem; } + .toc-title { display: block; } + h2, h3 { scroll-margin-top: 1rem; } +} .c { color: var(--c-comment); font-style: italic; } .s { color: var(--c-string); } @@ -133,34 +185,11 @@ footer { margin-top: 3.5rem; padding-top: 1.5rem; border-top: 1px solid var(--ru -
- -
- - flan - - -

A statically typed Lisp for game development. Clojure's brackets, - C's memory and value model, no garbage collector.

-
- -

Flan compiles s-expressions to LLVM IR and then to a native binary. -There are no object headers, so a Flan struct is exactly its C struct. There is no -collector, so nothing runs between frames that you did not write. And a running -program can be edited: a function recompiled in Emacs is installed into the live -process at its next frame boundary, in about twenty milliseconds.

- -

This page describes the compiler as it is, not as it is planned. Where -something is designed but not built, it says so and gives the message the compiler -prints for it. Every Flan program on this page is a file in web/examples/ -with its output recorded beside it; sh web/examples/check.sh runs them all -and compares, and quotes.sh re-derives the blocks that are transcripts -rather than programs. If the page and the compiler disagree, one of those two goes -red.

+ + +
+
+ +
+ + + flan. + +

A statically typed Lisp for game development. Clojure's brackets, + C's memory and value model, no garbage collector.

+
+ +

Flan compiles s-expressions to LLVM IR and then to a native binary. +There are no object headers, so a Flan struct is exactly its C struct. There is no +collector, so nothing runs between frames that you did not write. And a running +program can be edited: a function recompiled in Emacs is installed into the live +process at its next frame boundary, in about twenty milliseconds.

+ +

This page describes the compiler as it is, not as it is planned. Where +something is designed but not built, it says so and gives the message the compiler +prints for it. Every Flan program on this page is a file in web/examples/ +with its output recorded beside it; sh web/examples/check.sh runs them all +and compares, and quotes.sh re-derives the blocks that are transcripts +rather than programs. If the page and the compiler disagree, one of those two goes +red.

+

What Flan is

A minimal Lisp for games. In one line: Odin with a Lisp frontend and a live REPL. @@ -1304,6 +1362,7 @@ macro is a function from Form to Form, which needs

+