summaryrefslogtreecommitdiff
path: root/docs/site
diff options
context:
space:
mode:
Diffstat (limited to 'docs/site')
-rw-r--r--docs/site/README24
-rw-r--r--docs/site/fonts/CrimsonPro-VF-italic.woff2bin0 -> 52448 bytes
-rw-r--r--docs/site/fonts/CrimsonPro-VF-normal.woff2bin0 -> 49660 bytes
-rw-r--r--docs/site/fonts/DepartureMono-Regular.woff2bin0 -> 22496 bytes
-rw-r--r--docs/site/fonts/LICENSE-CrimsonPro.txt93
-rw-r--r--docs/site/fonts/LICENSE-DepartureMono.txt93
-rw-r--r--docs/site/media/clips.toml24
-rw-r--r--docs/site/media/placeholder.svg1
-rw-r--r--docs/site/site.css142
-rw-r--r--docs/site/site.typ161
10 files changed, 538 insertions, 0 deletions
diff --git a/docs/site/README b/docs/site/README
new file mode 100644
index 00000000..76c2973f
--- /dev/null
+++ b/docs/site/README
@@ -0,0 +1,24 @@
+docs/site: the pardes website, built from docs/typ
+
+ site.typ the wrapper: every page, the shared tag-line header and
+ chapter nav, the landing page, and the files it ships.
+ Pages come from `chapters` in ../typ/style.typ, so a new
+ chapter is a new page; #doc links resolve across pages.
+ site.css the whole look (lapis layout from 0x4200.cafe in
+ pardes's orchard greens; forestbones_light when the
+ reader prefers light).
+ fonts/ Departure Mono and Crimson Pro, both SIL OFL, licences
+ alongside.
+ media/clips.toml the landing page's recordings, in order: name, caption,
+ ready. For a clip named N the site ships media/N.webm,
+ media/N.mp4 and media/N.png (the poster); until `ready`
+ is true it shows placeholder.svg instead.
+
+Build (from the repo root):
+
+ typst compile --root . --format bundle --features bundle,html docs/site/site.typ OUT
+ zig build site -Dplatform=tty --prefix DIR # DIR/share/doc/pardes/site/
+
+Every page sits at the top of OUT and every link is relative, so the site
+works from file:// and from any static server. The only prose of the
+site's own is the landing page; everything else is included from docs/typ.
diff --git a/docs/site/fonts/CrimsonPro-VF-italic.woff2 b/docs/site/fonts/CrimsonPro-VF-italic.woff2
new file mode 100644
index 00000000..59923684
--- /dev/null
+++ b/docs/site/fonts/CrimsonPro-VF-italic.woff2
Binary files differ
diff --git a/docs/site/fonts/CrimsonPro-VF-normal.woff2 b/docs/site/fonts/CrimsonPro-VF-normal.woff2
new file mode 100644
index 00000000..7fd174a4
--- /dev/null
+++ b/docs/site/fonts/CrimsonPro-VF-normal.woff2
Binary files differ
diff --git a/docs/site/fonts/DepartureMono-Regular.woff2 b/docs/site/fonts/DepartureMono-Regular.woff2
new file mode 100644
index 00000000..b4a23dc1
--- /dev/null
+++ b/docs/site/fonts/DepartureMono-Regular.woff2
Binary files differ
diff --git a/docs/site/fonts/LICENSE-CrimsonPro.txt b/docs/site/fonts/LICENSE-CrimsonPro.txt
new file mode 100644
index 00000000..6a7d97cd
--- /dev/null
+++ b/docs/site/fonts/LICENSE-CrimsonPro.txt
@@ -0,0 +1,93 @@
+Copyright 2018 The Crimson Pro Project Authors (https://github.com/Fonthausen/CrimsonPro)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/docs/site/fonts/LICENSE-DepartureMono.txt b/docs/site/fonts/LICENSE-DepartureMono.txt
new file mode 100644
index 00000000..de524761
--- /dev/null
+++ b/docs/site/fonts/LICENSE-DepartureMono.txt
@@ -0,0 +1,93 @@
+Copyright 2022–2024 Helena Zhang (helenazhang.com).
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+https://openfontlicense.org
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/docs/site/media/clips.toml b/docs/site/media/clips.toml
new file mode 100644
index 00000000..f927450f
--- /dev/null
+++ b/docs/site/media/clips.toml
@@ -0,0 +1,24 @@
+# The landing page's recordings, in the order shown. For each clip the
+# site ships media/<name>.webm and media/<name>.mp4, with media/<name>.png
+# as the poster. While `ready` is false the clip shows placeholder.svg and
+# no video, so the site builds before the recordings exist.
+
+[[clip]]
+name = "look-and-execute"
+caption = "Right-click opens what you point at; middle-click runs it."
+ready = false
+
+[[clip]]
+name = "terminals"
+caption = "Terminal panes: type to the program, or move around its output."
+ready = false
+
+[[clip]]
+name = "scripting"
+caption = "A script drives the session by reading and writing files."
+ready = false
+
+[[clip]]
+name = "diff-review"
+caption = "Right-click a diff line to open that line of the file."
+ready = false
diff --git a/docs/site/media/placeholder.svg b/docs/site/media/placeholder.svg
new file mode 100644
index 00000000..0b0efde0
--- /dev/null
+++ b/docs/site/media/placeholder.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 400"><rect width="640" height="400" fill="#121c16"/><rect x="24" y="24" width="592" height="28" fill="#1d2824"/><rect x="24" y="24" width="28" height="28" fill="#add38a"/><rect x="24" y="64" width="592" height="312" fill="none" stroke="#486152" stroke-width="2"/><text x="320" y="230" fill="#b2c3b8" font-family="monospace" font-size="22" text-anchor="middle">recording to come</text></svg>
diff --git a/docs/site/site.css b/docs/site/site.css
new file mode 100644
index 00000000..bbb1140f
--- /dev/null
+++ b/docs/site/site.css
@@ -0,0 +1,142 @@
+/* pardes docs site. The 0x4200.cafe lapis layout (framed panels, hard
+ shadows, a tag-line trail, pixel headings over a book hand) in pardes's
+ orchard greens; light mode follows forestbones_light. Fonts are OFL and
+ shipped in fonts/. */
+
+@font-face { font-family:"Crimson Pro"; src:url("fonts/CrimsonPro-VF-normal.woff2") format("woff2"); font-weight:200 900; font-display:swap; }
+@font-face { font-family:"Crimson Pro"; src:url("fonts/CrimsonPro-VF-italic.woff2") format("woff2"); font-weight:200 900; font-style:italic; font-display:swap; }
+@font-face { font-family:"Departure Mono"; src:url("fonts/DepartureMono-Regular.woff2") format("woff2"); font-display:swap; size-adjust:72%; }
+
+/* orchard: field, panel, ink, leaf, amber, plum */
+:root {
+ --field:#0d1410; --deep:#070c09; --panel:#121c16; --tag:#1d2824; --tag-hi:#26362d;
+ --ink:#e5eee5; --dim:#b2c3b8; --leaf:#add38a; --leaf-hi:#b9f480; --amber:#f4c086; --plum:#d3b0d9;
+ --rule:#486152; --shadow:#000c; --stripe:#3c614a;
+ --hand:"Crimson Pro", Georgia, serif; --pixel:"Departure Mono", ui-monospace, monospace;
+ --mono:ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;
+}
+/* forestbones_light: paper, butter tags, green ink */
+@media (prefers-color-scheme: light) {
+ :root {
+ --field:#f3ead2; --deep:#e9dcb8; --panel:#faf3e1; --tag:#f3e2aa; --tag-hi:#e8d48e;
+ --ink:#2f3b33; --dim:#56645b; --leaf:#3c6b56; --leaf-hi:#2c7a3e; --amber:#9a5810; --plum:#6e4774;
+ --rule:#b1a26f; --shadow:#4f5b6233; --stripe:#cdd9b0;
+ }
+}
+
+* { box-sizing:border-box; }
+html { background:var(--deep); color:var(--ink); scrollbar-color:var(--leaf) var(--deep); }
+body { margin:0; min-height:100vh; background:var(--field) radial-gradient(color-mix(in srgb, var(--leaf) 14%, transparent) 1px, transparent 1.5px) 0 0/22px 22px; }
+.shell { max-width:980px; margin:0 auto; padding:24px 16px 40px; display:grid; gap:26px; }
+
+/* --- the trail: a pane's tag line ------------------------------------------- */
+.trail {
+ display:flex; flex-wrap:wrap; align-items:baseline; gap:6px 12px; padding:9px 14px;
+ background:var(--tag); border:2px solid var(--leaf); box-shadow:5px 5px 0 var(--amber);
+ font:20px/1.3 var(--pixel);
+}
+.trail .grip { width:.8em; height:.8em; background:var(--leaf); align-self:center; }
+.trail a { color:var(--leaf); text-decoration:none; }
+.trail a:hover, .trail a[aria-current] { color:var(--amber); }
+.trail .home { color:var(--plum); }
+.trail .sep { color:var(--amber); }
+.trail .here { color:var(--dim); }
+.trail .words { display:flex; flex-wrap:wrap; gap:4px 14px; margin-left:auto; font-size:17px; }
+
+/* --- the folio --------------------------------------------------------------- */
+.panel { min-width:0; padding:14px; background:repeating-linear-gradient(45deg, var(--stripe) 0 2px, var(--panel) 2px 7px); border:2px solid var(--leaf); box-shadow:6px 6px 0 var(--shadow); }
+.content {
+ background:var(--panel); padding:22px clamp(14px, 4vw, 40px) 30px;
+ box-shadow:inset 0 0 0 2px var(--leaf), inset 0 0 0 5px var(--panel), inset 0 0 0 6px var(--amber);
+ font:420 20px/1.55 var(--hand); overflow-wrap:break-word;
+}
+.content p, .content li { hyphens:auto; text-wrap:pretty; }
+.content a { color:var(--amber); }
+.content a:hover { color:var(--leaf-hi); }
+.content strong { color:var(--leaf); font-weight:640; }
+.content h2, .content h1 { font:clamp(30px, 5vw, 44px)/1.1 var(--pixel); color:var(--leaf); text-transform:uppercase; margin:.3em 0 .6em; text-shadow:3px 3px 0 var(--shadow); }
+.content h3 { font:26px/1.2 var(--pixel); color:var(--amber); text-transform:uppercase; border-bottom:2px dotted var(--leaf); padding-bottom:4px; margin:1.6em 0 .6em; }
+.content h3::before { content:"¶ "; color:var(--leaf); }
+.content h4 { font:italic 600 23px/1.25 var(--hand); color:var(--leaf); margin:1.3em 0 .4em; }
+.content h5 { font:600 20px var(--hand); color:var(--dim); margin:1em 0 .3em; }
+
+/* code: a window on the machine, titled in stripes */
+.content code, .content pre, .content kbd, .tag { font-family:var(--mono); }
+.content code { font-size:.82em; overflow-wrap:break-word; hyphens:none; }
+.content pre {
+ font-size:15px; line-height:1.45; padding:12px 14px; margin:1em 0; overflow-x:auto;
+ background:var(--deep); border:2px solid var(--leaf); border-top-width:8px; box-shadow:5px 5px 0 var(--shadow);
+}
+.content pre code { font-size:inherit; overflow-wrap:normal; }
+@media (prefers-color-scheme: dark) { .content pre span { color:inherit !important; } }
+.content pre.tutor { font-size:14px; }
+
+/* tables: rows on alternating tints, a pardes #pairs */
+.content table { width:100%; border-collapse:collapse; margin:1em 0; font-size:.92em; display:block; overflow-x:auto; }
+.content tbody, .content thead { display:table; width:100%; }
+.content td, .content th { padding:5px 9px; vertical-align:top; text-align:left; }
+.content tr:nth-child(odd) td { background:color-mix(in srgb, var(--tag) 70%, transparent); }
+.content th { font:17px var(--pixel); color:var(--leaf); }
+
+/* --- the semantic elements (docs/typ/style.typ) ------------------------------ */
+.key { display:inline-block; padding:0 .3em; border-radius:4px; background:color-mix(in srgb, var(--leaf) 20%, transparent); color:var(--ink); font-size:.82em; white-space:nowrap; line-height:1.4; }
+.key .plus, .key .then { color:var(--leaf); opacity:.8; padding:0 .12em; }
+.word { background:var(--tag); padding:0 .25em; color:var(--dim); }
+.word code { font-size:.82em; color:var(--ink); }
+.addr code { color:var(--plum); }
+.file code { color:var(--leaf); }
+.btn, .chord { display:inline-flex; align-items:center; gap:2px; vertical-align:-.38em; margin-block:-.3em; }
+.mouse { width:1.15em; height:1.55em; }
+.mouse .off { fill:none; stroke:var(--dim); stroke-width:8; }
+.mouse .on { fill:var(--amber); stroke:var(--amber); stroke-width:8; }
+.mouse .halo { fill:var(--panel); }
+.mouse .wheel.off { fill:var(--panel); stroke-width:5; }
+.mouse .wheel.on { stroke-width:5; }
+.btn .shift { font-size:.9em; color:var(--amber); }
+.chord .then { font-size:.9em; color:var(--dim); }
+.tag { margin:.6em 0; padding:4px 8px; background:var(--tag); color:var(--dim); font-size:15px; line-height:1.5; }
+.tag .grip { display:inline-block; width:.8em; height:.8em; background:var(--leaf); margin-right:.5em; vertical-align:-.05em; }
+.tag .path { color:var(--plum); }
+.tag code { font-size:inherit; }
+
+/* --- contents, landing, footer ---------------------------------------------- */
+.toc { margin:0 0 1.6em; border:2px solid var(--leaf); background:var(--deep); box-shadow:5px 5px 0 var(--amber); }
+.toc-bar { padding:2px 10px; font:17px var(--pixel); color:var(--leaf); background:repeating-linear-gradient(0deg, var(--leaf) 0 2px, var(--tag) 2px 4px); }
+.toc-bar span { background:var(--tag); padding:0 8px; }
+.toc-bar, .toc ol { margin:0; }
+.toc ol { padding:8px 14px 10px 2.4em; columns:2 14em; font-size:18px; }
+.masthead { font:clamp(56px, 12vw, 104px)/1 var(--pixel) !important; text-shadow:5px 5px 0 var(--amber) !important; margin:.1em 0 .1em !important; }
+.pitch { font-style:italic; font-size:22px; color:var(--dim); margin-top:0; }
+.clips { display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%, 380px), 1fr)); gap:22px; margin:1.4em 0; }
+.clip { margin:0; border:2px solid var(--leaf); background:var(--deep); box-shadow:5px 5px 0 var(--shadow); }
+.clip video, .clip img { display:block; width:100%; height:auto; aspect-ratio:16/10; background:var(--deep); }
+.clip figcaption { padding:8px 12px; font-size:18px; color:var(--dim); border-top:2px solid var(--leaf); }
+.lead { font-size:23px; line-height:1.5; hyphens:manual; margin:.2em 0 .5em; }
+.pitch { font-style:italic; font-size:19px; hyphens:manual; color:var(--dim); margin:0 0 .3em; }
+.runs { font-size:18px; color:var(--dim); margin:0 0 1.2em; }
+.hero { display:block; width:100%; height:auto; margin:0 0 1.4em; border:2px solid var(--leaf); box-shadow:6px 6px 0 var(--shadow); }
+.start { display:flex; flex-wrap:wrap; gap:14px; margin:0 0 .8em; }
+.start .go { display:inline-block; padding:8px 16px; font:20px var(--pixel); text-decoration:none; color:var(--leaf); background:var(--tag); border:2px solid var(--leaf); box-shadow:4px 4px 0 var(--amber); }
+.start .go:first-child { font-size:24px; color:var(--panel); background:var(--leaf); }
+.start .go span { font-size:.75em; opacity:.85; }
+.start .go:hover { color:var(--amber); }
+.rest { display:flex; flex-wrap:wrap; gap:4px 16px; font:17px var(--pixel); margin:0 0 1.2em; }
+.rest a { color:var(--leaf); }
+.content h2.install { font-size:30px; }
+.glossary { margin:1.4em 0; }
+.glossary summary { cursor:pointer; list-style-position:inside; }
+.glossary summary h3, .glossary summary p { display:inline; margin:0; }
+.glossary summary .count { font:20px var(--pixel); color:var(--dim); margin-left:.4em; }
+.vh { position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; }
+.colophon { font:15px var(--pixel); color:var(--dim); text-align:center; }
+.colophon a { color:var(--leaf); }
+.colophon code { font:inherit; }
+
+@media (max-width:600px) {
+ .shell { padding:14px 10px 30px; gap:18px; }
+ .trail { font-size:17px; padding:8px 10px; }
+ .trail .words { margin-left:0; font-size:15px; }
+ .panel { padding:7px; }
+ .content { font-size:18px; }
+ .content pre { font-size:13px; }
+}
diff --git a/docs/site/site.typ b/docs/site/site.typ
new file mode 100644
index 00000000..03d9a15d
--- /dev/null
+++ b/docs/site/site.typ
@@ -0,0 +1,161 @@
+// The website: one Typst bundle run writes every page, the stylesheet, the
+// fonts and the media. Pages come from `chapters` in ../typ/style.typ, so a
+// new chapter is a new page; the only prose of its own is the landing page.
+// typst compile --root . --format bundle --features bundle,html docs/site/site.typ OUT
+// Every link is relative and every page sits at the top of OUT, so the site
+// works from file:// and from any static server.
+#import "../typ/style.typ": chapters, tutor-path, doc-links, tagline, project
+
+#let clips = toml("media/clips.toml").clip
+#let pages = (
+ (id: "index", title: "pardes"),
+ ..chapters.filter(c => c.file != none).map(c => (id: c.id, title: c.title, file: c.file)),
+ (id: "tutor", title: "The tutor"),
+)
+#let href(id) = id + ".html"
+
+// --- the files that are not pages --------------------------------------------
+
+#asset("site.css", read("site.css", encoding: none))
+#for f in ("DepartureMono-Regular.woff2", "CrimsonPro-VF-normal.woff2", "CrimsonPro-VF-italic.woff2",
+ "LICENSE-DepartureMono.txt", "LICENSE-CrimsonPro.txt") {
+ asset("fonts/" + f, read("fonts/" + f, encoding: none))
+}
+#asset("media/placeholder.svg", read("media/placeholder.svg", encoding: none))
+#for c in clips.filter(c => c.ready) {
+ for ext in ("webm", "mp4", "png") {
+ asset("media/" + c.name + "." + ext, read("media/" + c.name + "." + ext, encoding: none))
+ }
+}
+
+// --- the shell every page sits in ---------------------------------------------
+
+/// An HTML element: el("a", (href: "x.html"))[text], or el("li")[text].
+#let el(tag, ..args) = {
+ let p = args.pos()
+ html.elem(tag, attrs: if p.len() > 1 { p.first() } else { (:) }, p.last())
+}
+
+/// The running head: a tagline, the way a pane's tag reads, with the path
+/// of this page and the chapters as its words.
+#let trail(id, title) = el("header", (class: "trail"))[
+ #el("span", (class: "grip", "aria-hidden": "true"))[]
+ #el("a", (class: "home", href: href("index")))[pardes]
+ #if id != "index" {
+ el("span", (class: "sep", "aria-hidden": "true"))[/]
+ el("span", (class: "here", "aria-current": "page"))[#title]
+ }
+ #el("nav", (class: "words", "aria-label": "Chapters"))[
+ #for p in pages.slice(1) {
+ if p.id == id { el("a", (href: href(p.id), "aria-current": "page"))[#p.title] }
+ else { el("a", (href: href(p.id)))[#p.title] }
+ }
+ ]
+]
+
+#let shell(id, title, body) = html.html(lang: "en", {
+ html.head({
+ html.meta(charset: "utf-8")
+ el("meta", (name: "viewport", content: "width=device-width, initial-scale=1"))[]
+ el("meta", (name: "color-scheme", content: "dark light"))[]
+ html.title(if id == "index" { "pardes" } else { title + " · pardes" })
+ el("link", (rel: "stylesheet", href: "site.css"))[]
+ })
+ html.body({
+ el("div", (class: "shell"))[
+ #trail(id, title)
+ #el("main", (class: "panel", "data-page": id))[
+ #el("article", (class: "content"))[#body]
+ ]
+ #el("footer", (class: "colophon"))[
+ pardes ·
+ #if project.source != none [#el("a", (href: project.source))[source] · ]
+ #if project.license != none [#project.license · ]
+ built from `docs/typ` with Typst ·
+ #el("a", (href: "fonts/LICENSE-DepartureMono.txt"))[fonts] (OFL)
+ ]
+ ]
+ })
+})
+
+/// The headings of this page only, as a contents list, when there are
+/// enough of them to need one.
+#let toc(id) = context {
+ let hs = query(selector(heading.where(level: 2)).after(label("start-" + id)).before(label("end-" + id)))
+ if hs.len() >= 4 {
+ el("nav", (class: "toc", "aria-label": "On this page"))[
+ #el("div", (class: "toc-bar"))[#el("span")[On this page]]
+ #el("ol")[#for h in hs { el("li")[#link(h.location(), h.body)] }]
+ ]
+ }
+}
+
+// --- the pages ------------------------------------------------------------------
+
+#doc-links.update(true)
+
+#let ready = clips.filter(c => c.ready)
+#let start = (
+ (id: "guide", label: [Start: the guide], note: [about 15 min]),
+ (id: "tutor", label: [Hands on: the tutor], note: none),
+)
+
+#document(href("index"), title: "pardes", shell("index", "pardes")[
+ #el("h1", (class: "masthead"))[pardes]
+ #el("p", (class: "lead"))[pardes is an editor and terminal in columns of panes, each
+ a file, a terminal, a PDF or an image. Click any text to run it or open
+ it; the keys are helix's; scripts drive it through files.]
+ #el("p", (class: "pitch"))[#tagline.]
+ #el("p", (class: "runs"))[It runs in a terminal or in its own window (SDL), on Linux;
+ macOS and browser builds are in the tree.]
+ #if ready.len() > 0 {
+ el("img", (class: "hero", src: "media/" + ready.first().name + ".png", alt: ready.first().caption))[]
+ }
+ #el("div", (class: "start"))[
+ #for s in start {
+ el("a", (class: "go", href: href(s.id)))[#s.label#if s.note != none [ #el("span")[(#s.note)]]]
+ }
+ ]
+ #el("p", (class: "rest"))[
+ #for p in pages.slice(1).filter(p => p.id not in start.map(s => s.id)) {
+ el("a", (href: href(p.id)))[#p.title]
+ }
+ ]
+ #el("div", (class: "clips"))[
+ #for c in clips {
+ el("figure", (class: "clip"))[
+ #if c.ready {
+ el("video", (poster: "media/" + c.name + ".png", muted: "", loop: "", playsinline: "",
+ controls: "", preload: "none"))[
+ #el("source", (src: "media/" + c.name + ".webm", type: "video/webm"))[]
+ #el("source", (src: "media/" + c.name + ".mp4", type: "video/mp4"))[]
+ ]
+ } else {
+ el("img", (src: "media/placeholder.svg", alt: "", width: "640", height: "400"))[]
+ }
+ #el("figcaption")[#c.caption]
+ ]
+ }
+ ]
+ #el("h2", (class: "install"))[Install]
+ #include "../typ/install.typ"
+])
+
+#for p in pages.slice(1, -1) {
+ document(href(p.id), title: p.title, shell(p.id, p.title)[
+ #metadata(none) #label("start-" + p.id)
+ #heading(level: 1, p.title) #label("ch-" + p.id)
+ #toc(p.id)
+ #{
+ set heading(offset: 1)
+ include "../typ/" + p.file
+ }
+ #metadata(none) #label("end-" + p.id)
+ ])
+}
+
+#document(href("tutor"), title: "The tutor", shell("tutor", "The tutor")[
+ #heading(level: 1)[The tutor] <tutor>
+ The tutor as the editor shows it (#raw("Tutor"), or #raw("SPC h t")).
+ #el("pre", (class: "tutor"))[#read(tutor-path)]
+])