- Website built with Zola and the Julia programming language.
- Website built with Zola and the Julia programming language.
- with inline colors from the theme in zola.toml. The executed REPL - fences arrive from MoJuWoPreprocessor as- (REPL modes) or(`!` fence output) and are - colored by the .sgrNN palette below. -================================================================== */ - -pre { - position: relative; - font-size: var(--small); - line-height: 1.35em; - border-radius: 10px; - padding: 1em; - overflow-x: auto; -} - -/* franklin.css gives inline `code` a light background; undo it inside blocks. */ -pre code { - background: transparent; - padding: 0; - font-size: inherit; -} - -/* Language label chips, like the highlight.js setup had. */ -pre[data-lang]::before, -pre.julia-repl.ansi::before { - position: absolute; - top: 0; - left: 0; - padding: 0.2rem 0.5rem 0.1rem; - background-color: #27303c; /* brighter than the code background */ - color: #adbac7; - border-bottom-right-radius: 10px; - border-top-left-radius: 10px; - font-size: 0.7rem; - font-weight: 700; - text-transform: uppercase; -} - -/* Reserve room for the chip so it doesn't overlap the first code line. */ -pre[data-lang]:not([data-lang="plain"]), -pre.julia-repl.ansi { - padding-top: 2.4em; -} - -pre[data-lang]::before { content: attr(data-lang); } -/* Giallo reports canonical grammar names; keep the labels the site used. */ -pre[data-lang="shellscript"]::before { content: "Shell"; } -/* Fences without a recognized language get no chip. */ -pre[data-lang="plain"]::before { content: none; } -pre.julia-repl.ansi::before { content: "Julia REPL"; } - -/* ================================================================== - ANSI COLORS (ANSIColoredPrinters.jl .sgrNN spans) - - REPL blocks are dark like the github-dark highlighting theme; the - palette is the VS Code dark terminal palette. The current Franklin - site ships no CSS for .sgr spans at all, so any styling here is an - improvement. -================================================================== */ - -pre.julia-repl.ansi { - background-color: #24292e; /* match giallo's github-dark background */ - color: #e1e4e8; -} - -/* `!` fence output stays light, like Franklin's .code-output blocks. */ -pre.code-output.ansi { - color: #24292e; -} - -.ansi .sgr1 { font-weight: bold; } -.ansi .sgr2 { opacity: 0.8; } -.ansi .sgr3 { font-style: italic; } -.ansi .sgr4 { text-decoration: underline; } -.ansi .sgr9 { text-decoration: line-through; } - -.ansi .sgr30 { color: #666666; } -.ansi .sgr31 { color: #cd3131; } -.ansi .sgr32 { color: #0dbc79; } -.ansi .sgr33 { color: #e5c516; } -.ansi .sgr34 { color: #4886d0; } -.ansi .sgr35 { color: #bc3fbc; } -.ansi .sgr36 { color: #11a8cd; } -.ansi .sgr37 { color: #e5e5e5; } -.ansi .sgr90 { color: #8b949e; } -.ansi .sgr91 { color: #f14c4c; } -.ansi .sgr92 { color: #23d18b; } -.ansi .sgr93 { color: #d7ba21; } -.ansi .sgr94 { color: #3b8eea; } -.ansi .sgr95 { color: #d670d6; } -.ansi .sgr96 { color: #29b8db; } -.ansi .sgr97 { color: #ffffff; } diff --git a/static/css/code.css b/static/css/code.css new file mode 100644 index 0000000..ed62cc8 --- /dev/null +++ b/static/css/code.css @@ -0,0 +1,200 @@ +/* ================================================================== + Code styling: block chrome, language chips, ANSI colors. + + Zola emits highlighted fences aswith `z-*` classes; the token colors come + from the generated giallo-light.css / giallo-dark.css, which + base.html loads through theme-controlled media attributes. The + executed REPL fences arrive from MoJuWoPreprocessor as +(REPL modes) or +(`!` fence output) and are colored + by the .sgrNN palettes below (GitHub Primer's ANSI palettes, one + per theme, matching the giallo token themes). +================================================================== */ + +:root { + --code-text: #24292e; /* match giallo's github-light */ + --chip-bg: #e6e9ed; + --chip-text: #57606a; + --chip-julia: #82489e; /* Julia purple, darkened for light chips */ + --chip-repl: #2f7d1f; /* Julia green, darkened, like the julia> prompt */ + + --sgr30: #24292f; + --sgr31: #cf222e; + --sgr32: #1a7f37; + --sgr33: #4d2d00; + --sgr34: #0969da; + --sgr35: #8250df; + --sgr36: #1b7c83; + --sgr37: #6e7781; + --sgr90: #57606a; + --sgr91: #a40e26; + --sgr92: #1a7f37; + --sgr93: #633c01; + --sgr94: #218bff; + --sgr95: #a475f9; + --sgr96: #3192aa; + --sgr97: #8c959f; +} + +@media (prefers-color-scheme: dark) { + :root:not([data-theme="light"]) { + --code-text: #e1e4e8; /* match giallo's github-dark */ + --chip-bg: #2f3742; + --chip-text: #adbac7; + --chip-julia: #c79fe0; + --chip-repl: #7ecb6f; + + --sgr30: #484f58; + --sgr31: #ff7b72; + --sgr32: #3fb950; + --sgr33: #d29922; + --sgr34: #58a6ff; + --sgr35: #bc8cff; + --sgr36: #39c5cf; + --sgr37: #b1bac4; + --sgr90: #6e7681; + --sgr91: #ffa198; + --sgr92: #56d364; + --sgr93: #e3b341; + --sgr94: #79c0ff; + --sgr95: #d2a8ff; + --sgr96: #56d4dd; + --sgr97: #ffffff; + } +} + +:root[data-theme="dark"] { + --code-text: #e1e4e8; + --chip-bg: #2f3742; + --chip-text: #adbac7; + --chip-julia: #c79fe0; + --chip-repl: #7ecb6f; + + --sgr30: #484f58; + --sgr31: #ff7b72; + --sgr32: #3fb950; + --sgr33: #d29922; + --sgr34: #58a6ff; + --sgr35: #bc8cff; + --sgr36: #39c5cf; + --sgr37: #b1bac4; + --sgr90: #6e7681; + --sgr91: #ffa198; + --sgr92: #56d364; + --sgr93: #e3b341; + --sgr94: #79c0ff; + --sgr95: #d2a8ff; + --sgr96: #56d4dd; + --sgr97: #ffffff; +} + +/* ------------------------------------------------------------------ + Inline code +------------------------------------------------------------------ */ + +code { + font-family: var(--font-mono); + font-size: 0.82rem; + background-color: var(--bg-hover); + padding: 0.1em 0.25em; + border-radius: 3px; +} + +/* ------------------------------------------------------------------ + Block chrome +------------------------------------------------------------------ */ + +pre { + position: relative; + font-family: var(--font-mono); + font-size: 0.8rem; + line-height: 1.45; + border: 1px solid var(--border); + border-radius: 10px; + padding: 1em; + overflow-x: auto; +} + +pre code { + background: transparent; + padding: 0; + font-size: inherit; +} + +/* giallo-light paints blocks white; use the inset gray so they read as + blocks on the white page. In dark mode the token matches github-dark. */ +pre.giallo, +pre.julia-repl.ansi { + background-color: var(--bg-inset); + color: var(--code-text); +} + +/* `!` fence output: page background and a dashed border, so results + read as distinct from the code that produced them. */ +pre.code-output.ansi { + color: var(--code-text); +} + +/* ------------------------------------------------------------------ + Language label chips +------------------------------------------------------------------ */ + +pre[data-lang]::before, +pre.julia-repl.ansi::before { + position: absolute; + top: 0; + left: 0; + padding: 0.2rem 0.5rem 0.1rem; + background-color: var(--chip-bg); + color: var(--chip-text); + border-bottom-right-radius: 10px; + border-top-left-radius: 10px; + font-size: 0.7rem; + font-weight: 700; + text-transform: uppercase; +} + +/* Reserve room for the chip so it doesn't overlap the first code line. */ +pre[data-lang]:not([data-lang="plain"]), +pre.julia-repl.ansi { + padding-top: 2.4em; +} + +pre[data-lang]::before { content: attr(data-lang); } +/* Giallo reports canonical grammar names; keep the labels the site used. */ +pre[data-lang="shellscript"]::before { content: "Shell"; } +/* Fences without a recognized language get no chip. */ +pre[data-lang="plain"]::before { content: none; } +pre.julia-repl.ansi::before { content: "Julia REPL"; } + +/* The rationed Julia-color accents: tinted label text, neutral chip. */ +pre[data-lang="julia"]::before { color: var(--chip-julia); } +pre.julia-repl.ansi::before { color: var(--chip-repl); } + +/* ------------------------------------------------------------------ + ANSI colors (ANSIColoredPrinters.jl .sgrNN spans) +------------------------------------------------------------------ */ + +.ansi .sgr1 { font-weight: bold; } +.ansi .sgr2 { opacity: 0.8; } +.ansi .sgr3 { font-style: italic; } +.ansi .sgr4 { text-decoration: underline; } +.ansi .sgr9 { text-decoration: line-through; } + +.ansi .sgr30 { color: var(--sgr30); } +.ansi .sgr31 { color: var(--sgr31); } +.ansi .sgr32 { color: var(--sgr32); } +.ansi .sgr33 { color: var(--sgr33); } +.ansi .sgr34 { color: var(--sgr34); } +.ansi .sgr35 { color: var(--sgr35); } +.ansi .sgr36 { color: var(--sgr36); } +.ansi .sgr37 { color: var(--sgr37); } +.ansi .sgr90 { color: var(--sgr90); } +.ansi .sgr91 { color: var(--sgr91); } +.ansi .sgr92 { color: var(--sgr92); } +.ansi .sgr93 { color: var(--sgr93); } +.ansi .sgr94 { color: var(--sgr94); } +.ansi .sgr95 { color: var(--sgr95); } +.ansi .sgr96 { color: var(--sgr96); } +.ansi .sgr97 { color: var(--sgr97); } diff --git a/static/css/custom.css b/static/css/custom.css deleted file mode 100644 index 1736e4b..0000000 --- a/static/css/custom.css +++ /dev/null @@ -1,41 +0,0 @@ -/* ================================================================== - Badges -================================================================== */ - -/* Custom CSS required to display the docs|stable badge on the landing page */ -img[alt=badge] { - height: 1em; - width: auto; - display: inline; - margin: 0; - padding: 0 0.5ex; -} - -/* ================================================================== - Admonitions -================================================================== */ - -.tldr { - background-color: rgba(34, 139, 34, 0.291); - border-radius: 10px; - padding: 0.5em; - margin-bottom: 1em; -} - -.tldr p { - margin-bottom: 0em; -} - -.advanced { - background: #cb3d337a; - border-radius: 10px; - padding: 0.5em; - margin-bottom: 1em; -} - -.vscode { - background-color: #9558b248; - border-radius: 10px; - padding: 0.5em; - margin-bottom: 1em; -} diff --git a/static/css/franklin.css b/static/css/franklin.css deleted file mode 100644 index 50900a4..0000000 --- a/static/css/franklin.css +++ /dev/null @@ -1,188 +0,0 @@ -/* ================================================================== - VARIABLES -================================================================== */ - -:root { - --block-background: hsl(0, 0%, 94%); - --output-background: hsl(0, 0%, 98%); - --small: 14px; - --normal: 19px; -} - -/* ================================================================== - DEFAULT FONT AND LAYOUT -================================================================== */ - -html { - font-family: Helvetica, Arial, sans-serif; - font-size: var(--normal); -} - -/* ================================================================== - FOOT / COPYRIGHT -================================================================== */ - -.franklin-content .page-foot a { - text-decoration: none; - color: #a6a2a0; - text-decoration: underline; -} - -.page-foot { - font-size: 80%; - font-family: Arial, serif; - color: #a6a2a0; - text-align: center; - margin-top: 6em; - border-top: 1px solid lightgrey; - padding-top: 2em; - margin-bottom: 4em; -} - -/* ================================================================== - TEXT GEOMETRY -================================================================== */ - -.franklin-content { - position: relative; - padding-left: 12.5%; - padding-right: 12.5%; - line-height: 1.35em; -} - -/* On wide screens, fix content width to a max value. */ -@media (min-width: 940px) { - .franklin-content { - width: 705px; - margin-left: auto; - margin-right: auto; - } -} - -/* On narrow device, reduce margins. */ -@media (max-width: 480px) { - .franklin-content { - padding-left: 6%; - padding-right: 6%; - } -} - -/* ================================================================== - TITLES -================================================================== */ - -.franklin-content h1 { font-size: 24px; } -.franklin-content h2 { font-size: 22px; } -.franklin-content h3 { font-size: 20px; } - -.franklin-content h1, -h2, -h3, -h4, -h5, -h6 { - text-align: left; -} - -.franklin-content h1 { - padding-bottom: 0.5em; - border-bottom: 3px double lightgrey; - margin-top: 1.5em; - margin-bottom: 1em; -} - -.franklin-content h2 { - padding-bottom: 0.3em; - border-bottom: 1px solid lightgrey; - margin-top: 2em; - margin-bottom: 1em; -} - -.franklin-content h1 a { color: inherit; } -.franklin-content h1 a:hover { text-decoration: none; } -.franklin-content h2 a { color: inherit; } -.franklin-content h2 a:hover { text-decoration: none; } -.franklin-content h3 a { color: inherit; } -.franklin-content h3 a:hover { text-decoration: none; } -.franklin-content h4 a { color: inherit; } -.franklin-content h4 a:hover { text-decoration: none; } -.franklin-content h5 a { color: inherit; } -.franklin-content h5 a:hover { text-decoration: none; } -.franklin-content h6 a { color: inherit; } -.franklin-content h6 a:hover { text-decoration: none; } - -.franklin-content table { - margin-left: auto; - margin-right: auto; - border-collapse: collapse; - text-align: center; -} - -.franklin-content th, -td { - font-size: var(--small); - padding: 10px; - border: 1px solid black; -} - -.franklin-content blockquote { - background: var(--block-background); - border-left: 7px solid #a8a8a8; - margin: 1.5em 10px; - padding: 0.5em 10px; - font-style: italic; -} - -.franklin-content blockquote p { - display: inline; -} - -/* ================================================================== - GENERAL FORMATTING -================================================================== */ - -/* Spacing between bullet points. */ -.franklin-content li p { - margin: 10px 0; -} - -.franklin-content a { - color: #004de6; - text-decoration: none; -} - -.franklin-content a:hover { - text-decoration: underline; -} - -/* ================================================================== - IMAGES in CONTENT -================================================================== */ - -.franklin-content img { - width: 70%; - text-align: center; - padding-left: 10%; -} - -/* ================================================================== - KATEX -================================================================== */ - -.katex { font-size: 1em !important; } - -/* ================================================================== - CODE -================================================================== */ - -code { - background-color: var(--block-background); - padding: 0.1em 0.2em; - border-radius: 2px; - font-size: var(--small); -} - -.code-output { - background: var(--output-background); - border: 1px dashed #dbdbdb; -} diff --git a/static/css/poole_hyde.css b/static/css/poole_hyde.css deleted file mode 100644 index dedc206..0000000 --- a/static/css/poole_hyde.css +++ /dev/null @@ -1,391 +0,0 @@ -/* - * ___ - * /\_ \ - * _____ ___ ___\//\ \ __ - * /\ '__`\ / __`\ / __`\\ \ \ /'__`\ - * \ \ \_\ \/\ \_\ \/\ \_\ \\_\ \_/\ __/ - * \ \ ,__/\ \____/\ \____//\____\ \____\ - * \ \ \/ \/___/ \/___/ \/____/\/____/ - * \ \_\ - * \/_/ - * - * Designed, built, and released under MIT license by @mdo. Learn more at - * https://github.com/poole/poole. - */ - - -/* - * Contents - * - * Body resets - * Custom type - * Messages - * Container - * Masthead - * Posts and pages - * Pagination - * Reverse layout - * Themes - */ - - -/* - * Body resets - * - * Update the foundational and global aspects of the page. - */ - -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -html, -body { - margin: 0; - padding: 0; -} - -html { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 1.5; -} - -@media (min-width: 38em) { - html { - font-size: 20px; - } -} - -body { - color: #515151; - background-color: #fff; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -/* No `:visited` state is required by default (browsers will use `a`) */ -a { - color: #268bd2; - text-decoration: none; -} - -a strong { - color: inherit; -} - -/* `:focus` is linked to `:hover` for basic accessibility */ -a:hover, -a:focus { - text-decoration: underline; -} - -/* Headings */ -h1, -h2, -h3, -h4, -h5, -h6 { - margin-bottom: 0.5rem; - font-weight: bold; - line-height: 1.25; - color: #313131; - text-rendering: optimizeLegibility; -} - -h1 { - font-size: 2rem; -} - -h2 { - margin-top: 1rem; - font-size: 1.5rem; -} - -h3 { - margin-top: 1.5rem; - font-size: 1.25rem; -} - -h4, -h5, -h6 { - margin-top: 1rem; - font-size: 1rem; -} - -/* Body text */ -p { - margin-top: 0; - margin-bottom: 1rem; -} - -strong { - color: #303030; -} - - -/* Lists */ -ul, -ol, -dl { - margin-top: 0; - margin-bottom: 1rem; -} - -dt { - font-weight: bold; -} - -dd { - margin-bottom: 0.5rem; -} - -/* Misc */ -hr { - position: relative; - margin: 1.5rem 0; - border: 0; - border-top: 1px solid #eee; - border-bottom: 1px solid #fff; -} - -abbr { - font-size: 85%; - font-weight: bold; - color: #555; - text-transform: uppercase; -} - -abbr[title] { - cursor: help; - border-bottom: 1px dotted #e5e5e5; -} - -/* Quotes */ -blockquote { - padding: 0.5rem 1rem; - margin: 0.8rem 0; - color: #7a7a7a; - border-left: 0.25rem solid #e5e5e5; -} - -blockquote p:last-child { - margin-bottom: 0; -} - -@media (min-width: 30em) { - blockquote { - padding-right: 5rem; - padding-left: 1.25rem; - } -} - -img { - display: block; - max-width: 100%; - margin: 0 0 1rem; - border-radius: 5px; -} - -/* Tables */ -table { - margin-bottom: 1rem; - width: 100%; - border: 1px solid #e5e5e5; - border-collapse: collapse; -} - -td, -th { - padding: 0.25rem 0.5rem; - border: 1px solid #e5e5e5; -} - -tbody tr:nth-child(odd) td, -tbody tr:nth-child(odd) th { - background-color: #f9f9f9; -} - -/* - * __ __ - * /\ \ /\ \ - * \ \ \___ __ __ \_\ \ __ - * \ \ _ `\/\ \/\ \ /'_` \ /'__`\ - * \ \ \ \ \ \ \_\ \/\ \_\ \/\ __/ - * \ \_\ \_\/`____ \ \___,_\ \____\ - * \/_/\/_/`/___/> \/__,_ /\/____/ - * /\___/ - * \/__/ - * - * Designed, built, and released under MIT license by @mdo. Learn more at - * https://github.com/poole/hyde. - */ - - -/* - * Contents - * - * Global resets - * Sidebar - * Container - * Reverse layout - * Themes - */ - - -/* - * Global resets - * - * Update the foundational and global aspects of the page. - */ - -html { - font-family: "PT Sans", Helvetica, Arial, sans-serif; -} - -/* - * Sidebar - * - * Flexible banner for housing site name, intro, and "footer" content. Starts - * out above content in mobile and later moves to the side with wider viewports. - */ - -.sidebar { - text-align: center; - color: rgba(255, 255, 255, 0.5); - background-color: #202020; -} - -@media (min-width: 768px) { - .sidebar { - position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 15rem; - text-align: left; - overflow-y: scroll; - } -} - -/* Sidebar links */ -.sidebar a { - color: #fff; -} - -/* About section */ -.sidebar-about h1 { - color: #fff; - margin-top: 0; - font-size: 40px; -} - -/* Sidebar nav */ -.sidebar-nav { - margin-bottom: 1rem; -} - -.sidebar-nav-item { - display: block; - line-height: 1.75; -} - -a.sidebar-nav-item:hover, -a.sidebar-nav-item:focus { - text-decoration: underline; -} - -.sidebar-nav-item.active { - font-weight: bold; -} - -.copyright-notice a { - text-decoration: none; - color: rgba(255, 255, 255, 0.5) !important; -} - -.github-link { - display: flex; - justify-content: center; - align-items: center; -} - -.github-link a { - color: rgba(255, 255, 255, 0.5) !important; -} - -/* Hide submenu by default */ -.menu-list-child-list { - display: none; - padding-left: 1.5rem; -} - -/* Show submenu when parent item has 'active' class */ -.sidebar-nav-item.active+.menu-list-child-list { - display: block; -} - -.menu-list-link { - color: rgba(255, 255, 255, 0.5) !important; - font-size: var(--small); -} - -/* Sticky sidebar - * - * Add the `sidebar-sticky` class to the sidebar's container to affix it the - * contents to the top of the sidebar in tablets and up. - */ - -.sidebar-sticky { - padding-top: 1rem; - padding-left: 1.5rem; - padding-right: 1.5rem; - padding-bottom: 0.5rem; -} - -@media (min-width: 768px) { - .sidebar-sticky { - position: relative; - } -} - -/* Container - * - * Align the contents of the site above the proper threshold with some margin-fu - * with a 25%-wide `.sidebar`. - */ - -.content { - padding-top: 4rem; - padding-bottom: 4rem; -} - -@media (min-width: 768px) { - .content { - max-width: 45rem; - margin-left: 15rem; - margin-right: 2rem; - } -} - -/* Hide the logo and submenu on screens with width less than 768px */ -@media (max-width: 767px) { - .logo-container { - display: none; - } - .sidebar-nav-item.active+.menu-list-child-list { - display: none; - } -} - -/* Center the logo within the logo container */ -.logo-img { - display: block; - margin-bottom: 15px; - margin-left: 20px; - width: 150px; -} diff --git a/static/css/search.css b/static/css/search.css deleted file mode 100644 index 447c410..0000000 --- a/static/css/search.css +++ /dev/null @@ -1,129 +0,0 @@ -/* ================================================================== - Site search: sidebar launcher button and results dialog - (templates/partials/search.html, js/search.js) -================================================================== */ - -/* Launcher, styled like an input to match the dark sidebar */ - -.search-open { - display: flex; - align-items: center; - gap: 0.5rem; - width: 100%; - max-width: 20rem; - margin: 0 auto 1rem; - padding: 0.35rem 0.6rem; - font: inherit; - color: rgba(255, 255, 255, 0.5); - background-color: rgba(255, 255, 255, 0.08); - border: 1px solid rgba(255, 255, 255, 0.25); - border-radius: 6px; - cursor: pointer; -} - -.search-open:hover, -.search-open:focus { - color: #fff; - border-color: rgba(255, 255, 255, 0.5); -} - -.search-open kbd { - margin-left: auto; - padding: 0 0.35em; - font-size: 0.8em; - border: 1px solid rgba(255, 255, 255, 0.25); - border-radius: 4px; -} - -/* No keyboard on most narrow viewports, so hide the shortcut hint */ -@media (max-width: 767px) { - .search-open kbd { - display: none; - } -} - -/* Dialog */ - -#search-dialog { - width: min(34rem, 92vw); - margin: 10vh auto auto; - padding: 0; - border: none; - border-radius: 10px; - box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3); -} - -#search-dialog::backdrop { - background: rgba(0, 0, 0, 0.45); -} - -#search-input { - width: 100%; - padding: 0.8rem 1rem; - font: inherit; - font-size: 1.1rem; - border: none; - border-bottom: 1px solid #ddd; - border-radius: 10px 10px 0 0; - outline: none; -} - -/* Results */ - -#search-results { - max-height: 60vh; - overflow-y: auto; -} - -#search-results:not(:empty) { - padding-bottom: 0.4rem; -} - -.search-group-label { - padding: 0.6rem 1rem 0.2rem; - font-size: 0.7rem; - font-weight: bold; - text-transform: uppercase; - letter-spacing: 0.05em; - color: #999; -} - -.search-empty { - padding: 0.8rem 1rem; - color: #7a7a7a; -} - -a.search-result { - display: block; - padding: 0.4rem 1rem; - color: inherit; - text-decoration: none; -} - -a.search-result:hover, -a.search-result.selected { - background-color: #eaf3fa; -} - -.search-crumb { - color: #999; -} - -.search-result-title b { - color: #268bd2; -} - -.search-teaser { - font-size: 0.85rem; - line-height: 1.4; - color: #7a7a7a; - overflow-wrap: anywhere; -} - -/* Pagefind wraps matched terms in ; render them like the in titles - instead of the browser's yellow highlight */ -.search-teaser mark { - background: none; - color: #268bd2; - font-weight: bold; -} diff --git a/static/css/site.css b/static/css/site.css new file mode 100644 index 0000000..98eafb2 --- /dev/null +++ b/static/css/site.css @@ -0,0 +1,728 @@ +/* ================================================================== + Site stylesheet. + + Everything except code-block styling (css/code.css). One light and + one dark theme, driven by the custom properties below: the default + follows the system preference, and js/ui.js pins `data-theme` on + when the reader uses the toggle. Julia's four brand colors + are reserved for admonitions, links/active nav, and code chips. +================================================================== */ + +/* ------------------------------------------------------------------ + Theme tokens +------------------------------------------------------------------ */ + +:root { + --bg: #ffffff; + --bg-sidebar: #f6f7f8; + --bg-inset: #f6f8fa; /* code blocks, table stripes */ + --bg-hover: #eef1f4; + --text: #515151; + --text-strong: #313131; + --text-muted: #82878f; + --border: #e2e4e8; + --border-strong: #cfd3d8; + + --julia-green: #389826; + --julia-red: #cb3c33; + --julia-purple: #9558b2; + --julia-blue: #4063d8; + --link: var(--julia-blue); + + --font-body: Helvetica, Arial, sans-serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + + /* Admonition header knobs: wash opacity, and title-text blend toward ink */ + --adm-tint: 9%; + --adm-ink: #1c1c1c; + --adm-ink-mix: 75%; +} + +@media (prefers-color-scheme: dark) { + :root:not([data-theme="light"]) { + --bg: #14171a; + --bg-sidebar: #1c2025; + --bg-inset: #24292e; + --bg-hover: #2a3038; + --text: #b9c1c9; + --text-strong: #e8ebee; + --text-muted: #8b939c; + --border: #30363d; + --border-strong: #3d444d; + --link: #91a9f0; /* Julia blue, lightened for dark backgrounds */ + --adm-tint: 16%; + --adm-ink: #ffffff; + --adm-ink-mix: 55%; + } +} + +:root[data-theme="dark"] { + --bg: #14171a; + --bg-sidebar: #1c2025; + --bg-inset: #24292e; + --bg-hover: #2a3038; + --text: #b9c1c9; + --text-strong: #e8ebee; + --text-muted: #8b939c; + --border: #30363d; + --border-strong: #3d444d; + --link: #91a9f0; + --adm-tint: 16%; + --adm-ink: #ffffff; + --adm-ink-mix: 55%; +} + +/* ------------------------------------------------------------------ + Base +------------------------------------------------------------------ */ + +* { + box-sizing: border-box; +} + +html { + margin: 0; + font-family: var(--font-body); + font-size: 16px; + line-height: 1.5; +} + +body { + margin: 0; + color: var(--text); + background-color: var(--bg); + -webkit-text-size-adjust: 100%; +} + +a { + color: var(--link); + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin-top: 1.5em; + margin-bottom: 0.6em; + font-weight: bold; + line-height: 1.25; + color: var(--text-strong); +} + +h1 { + font-size: 1.6rem; + padding-bottom: 0.4em; + border-bottom: 1.5px solid var(--border-strong); +} + +h2 { + font-size: 1.35rem; + padding-bottom: 0.25em; + border-bottom: 1px solid var(--border-strong); +} + +h3 { + font-size: 1.15rem; +} + +h4, +h5, +h6 { + font-size: 1rem; +} + +/* Section links land right at the heading, not under the mobile top bar. */ +h1, +h2, +h3, +h4 { + scroll-margin-top: 1rem; +} + +h1 a, +h2 a, +h3 a, +h4 a { + color: inherit; +} + +p, +ul, +ol, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +li p { + margin: 0.5rem 0; +} + +strong { + color: var(--text-strong); +} + +hr { + margin: 1.5rem 0; + border: 0; + border-top: 1px solid var(--border); +} + +blockquote { + margin: 1rem 0; + padding: 0.25rem 1rem; + color: var(--text-muted); + border-left: 3px solid var(--border-strong); +} + +blockquote p:last-child { + margin-bottom: 0; +} + +img { + display: block; + max-width: 100%; + margin: 0 auto 1rem; + border-radius: 5px; +} + +/* Inline docs|stable badges on the landing page flow with the text. */ +img[alt="badge"] { + height: 1em; + width: auto; + display: inline; + margin: 0; + padding: 0 0.5ex; + vertical-align: text-bottom; +} + +table { + margin-bottom: 1rem; + width: 100%; + border: 1px solid var(--border); + border-collapse: collapse; + font-size: 0.9rem; +} + +td, +th { + padding: 0.3rem 0.6rem; + border: 1px solid var(--border); + text-align: left; +} + +th { + color: var(--text-strong); +} + +tbody tr:nth-child(odd) td, +tbody tr:nth-child(odd) th { + background-color: var(--bg-inset); +} + +kbd { + padding: 0 0.35em; + font-family: inherit; /* no monospace outside code */ + font-size: 0.8em; + border: 1px solid var(--border-strong); + border-radius: 4px; +} + +.katex { + font-size: 1em !important; +} + +/* ------------------------------------------------------------------ + Layout: fixed sidebar on the left, one reading column +------------------------------------------------------------------ */ + +.sidebar { + position: fixed; + top: 0; + left: 0; + bottom: 0; + z-index: 20; + width: 15rem; + overflow-y: auto; + background-color: var(--bg-sidebar); + border-right: 1px solid var(--border); +} + +.content { + margin-left: 15rem; +} + +.page { + max-width: 45rem; + margin: 0 auto; + padding: 2.5rem 2rem 1.5rem; +} + +.page > div > h1:first-child { + margin-top: 0; +} + +/* ------------------------------------------------------------------ + Sidebar +------------------------------------------------------------------ */ + +.sidebar-inner { + display: flex; + flex-direction: column; + min-height: 100%; + padding: 1.5rem 1.25rem 1rem; +} + +.sidebar-brand { + display: block; + text-align: center; + color: inherit; +} + +.sidebar-brand:hover, +.sidebar-brand:focus { + text-decoration: none; +} + +.sidebar-wordmark { + display: block; + font-size: 1.6rem; + font-weight: bold; + color: var(--text-strong); + line-height: 1.2; +} + +.sidebar-tagline { + display: block; + margin-top: 0.2rem; + font-size: 1rem; + color: var(--text-muted); +} + +.sidebar-logo { + width: 105px; + margin: 1rem auto; +} + +/* Search launcher, styled like an input */ + +.search-open { + display: flex; + align-items: center; + gap: 0.5rem; + width: 100%; + margin: 0.25rem 0 1.25rem; + padding: 0.35rem 0.6rem; + font: inherit; + color: var(--text-muted); + background-color: var(--bg); + border: 1px solid var(--border); + border-radius: 6px; + cursor: pointer; +} + +.search-open:hover, +.search-open:focus { + color: var(--text-strong); + border-color: var(--border-strong); +} + +.search-open kbd { + margin-left: auto; +} + +/* Navigation: page links, with the active page's sections below it */ + +.sidebar-nav { + flex-grow: 1; +} + +.sidebar-nav-item { + display: block; + padding: 0.15rem 0; + color: var(--text); + line-height: 1.6; +} + +.sidebar-nav-item.active { + color: var(--link); + font-weight: bold; +} + +.menu-list-child-list { + display: none; + list-style: none; + margin: 0.2rem 0 0.4rem; + padding-left: 0.75rem; + border-left: 1px solid var(--border-strong); +} + +.sidebar-nav-item.active + .menu-list-child-list { + display: block; +} + +.menu-list-item { + margin: 0; +} + +.menu-list-link { + display: block; + padding: 0.1rem 0; + font-size: 0.8rem; + color: var(--text-muted); +} + +.menu-list-link:hover, +.menu-list-link:focus { + color: var(--text-strong); + text-decoration: none; +} + +/* Section currently on screen, tracked by the scrollspy in js/ui.js */ +.menu-list-link.current { + color: var(--link); +} + +/* Footer: theme toggle, GitHub, license */ + +.sidebar-foot { + margin-top: 1.5rem; +} + +.sidebar-foot-icons { + display: flex; + justify-content: center; + gap: 1rem; + margin-bottom: 0.5rem; +} + +.sidebar-foot-icons a, +.theme-toggle { + display: flex; + align-items: center; + padding: 0.3rem; + color: var(--text-muted); + background: none; + border: none; + cursor: pointer; +} + +.sidebar-foot-icons a:hover, +.sidebar-foot-icons a:focus, +.theme-toggle:hover, +.theme-toggle:focus { + color: var(--text-strong); +} + +.copyright-notice { + margin: 0; + text-align: center; + font-size: 0.8rem; +} + +.copyright-notice a { + color: var(--text-muted); +} + +/* The toggle shows the mode it switches to: a moon in light mode, a sun + in dark mode. "Auto" (no data-theme) resolves via the media query. */ + +.theme-toggle .icon-sun { + display: none; +} + +@media (prefers-color-scheme: dark) { + :root:not([data-theme="light"]) .theme-toggle .icon-sun { + display: inline; + } + + :root:not([data-theme="light"]) .theme-toggle .icon-moon { + display: none; + } +} + +:root[data-theme="dark"] .theme-toggle .icon-sun { + display: inline; +} + +:root[data-theme="dark"] .theme-toggle .icon-moon { + display: none; +} + +:root[data-theme="light"] .theme-toggle .icon-sun { + display: none; +} + +:root[data-theme="light"] .theme-toggle .icon-moon { + display: inline; +} + +/* ------------------------------------------------------------------ + Admonitions: light wash of the accent, title inline with the body +------------------------------------------------------------------ */ + +.admonition { + margin: 1.5rem 0 1rem; + padding: 0.75rem 1rem; + font-size: 1rem; + border: 1px solid color-mix(in srgb, var(--adm) 45%, transparent); + background-color: color-mix(in srgb, var(--adm) var(--adm-tint), transparent); + border-radius: 8px; +} + +/* A quiet lead-in: the accent tinted toward the ink, run into the first + sentence after a colon. --adm-* knobs are set per theme. */ +.admonition-title { + color: color-mix(in srgb, var(--adm) var(--adm-ink-mix), var(--adm-ink)); + font-weight: bold; +} + +/* The box's own padding provides the spacing the outer margins would. */ +.admonition-body > :first-child { + margin-top: 0; +} + +.admonition-body > :last-child { + margin-bottom: 0; +} + +.tldr { + --adm: var(--julia-green); +} + +.advanced { + --adm: var(--julia-red); +} + +.vscode { + --adm: var(--julia-purple); +} + +.note { + --adm: var(--julia-blue); +} + +/* ------------------------------------------------------------------ + In-content table of contents +------------------------------------------------------------------ */ + +/* The sidebar lists the current page's headings whenever it is on screen, + so the in-content copy only earns its place in the mobile layout, where + the sidebar is hidden behind the hamburger drawer. */ +.toc { + display: none; +} + +.toc ol { + margin: 1rem 0; +} + +/* ------------------------------------------------------------------ + Page foot +------------------------------------------------------------------ */ + +.page-foot { + margin-top: 5rem; + padding-top: 1.5rem; + border-top: 1px solid var(--border); + font-size: 0.8rem; + color: var(--text-muted); + text-align: center; +} + +.page-foot a { + color: var(--text-muted); + text-decoration: underline; +} + +/* ------------------------------------------------------------------ + Search dialog +------------------------------------------------------------------ */ + +#search-dialog { + width: min(34rem, 92vw); + margin: 10vh auto auto; + padding: 0; + color: var(--text); + background-color: var(--bg); + border: 1px solid var(--border); + border-radius: 10px; + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3); +} + +#search-dialog::backdrop { + background: rgba(0, 0, 0, 0.45); +} + +#search-input { + width: 100%; + padding: 0.8rem 1rem; + font: inherit; + color: inherit; + background: none; + border: none; + border-bottom: 1px solid var(--border); + border-radius: 10px 10px 0 0; + outline: none; +} + +#search-results { + max-height: 60vh; + overflow-y: auto; +} + +#search-results:not(:empty) { + padding-bottom: 0.4rem; +} + +.search-group-label { + padding: 0.6rem 1rem 0.2rem; + font-size: 0.7rem; + font-weight: bold; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--text-muted); +} + +.search-empty { + padding: 0.8rem 1rem; + color: var(--text-muted); +} + +a.search-result { + display: block; + padding: 0.4rem 1rem; + color: inherit; + text-decoration: none; +} + +a.search-result:hover, +a.search-result.selected { + background-color: var(--bg-hover); +} + +.search-crumb { + color: var(--text-muted); +} + +.search-result-title b { + color: var(--link); +} + +.search-teaser { + font-size: 0.85rem; + line-height: 1.4; + color: var(--text-muted); + overflow-wrap: anywhere; +} + +/* Pagefind wraps matched terms in ; render them like the in + titles instead of the browser's yellow highlight */ +.search-teaser mark { + background: none; + color: var(--link); + font-weight: bold; +} + +/* ------------------------------------------------------------------ + Mobile: top bar and slide-in drawer +------------------------------------------------------------------ */ + +.topbar { + display: none; +} + +@media (max-width: 767px) { + .topbar { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 10; + display: flex; + align-items: center; + gap: 0.75rem; + height: 3.25rem; + padding: 0 0.75rem; + background-color: var(--bg-sidebar); + border-bottom: 1px solid var(--border); + } + + .topbar button { + display: flex; + align-items: center; + padding: 0.4rem; + color: var(--text); + background: none; + border: none; + cursor: pointer; + } + + .topbar-title { + font-weight: bold; + color: var(--text-strong); + } + + .topbar-search { + margin-left: auto; + } + + .sidebar { + width: 16rem; + transform: translateX(-100%); + transition: transform 0.2s ease; + visibility: hidden; + } + + body.sidebar-open .sidebar { + transform: none; + visibility: visible; + } + + .sidebar-backdrop { + position: fixed; + inset: 0; + z-index: 15; + background: rgba(0, 0, 0, 0.45); + opacity: 0; + visibility: hidden; + transition: opacity 0.2s ease; + } + + body.sidebar-open .sidebar-backdrop { + opacity: 1; + visibility: visible; + } + + body.sidebar-open { + overflow: hidden; + } + + .content { + margin-left: 0; + padding-top: 3.25rem; + } + + .toc { + display: block; + } + + .page { + padding: 1.5rem 1.25rem 1rem; + } + + h1, + h2, + h3, + h4 { + scroll-margin-top: 4.25rem; + } +} diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..0112e57 Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/favicon.svg b/static/favicon.svg new file mode 100644 index 0000000..5e387c3 --- /dev/null +++ b/static/favicon.svg @@ -0,0 +1 @@ + diff --git a/static/js/search.js b/static/js/search.js index e523fcf..78dc264 100644 --- a/static/js/search.js +++ b/static/js/search.js @@ -32,7 +32,10 @@ loadPagefind(); } - document.getElementById("search-open").addEventListener("click", openDialog); + // Launchers: the sidebar button and the mobile top-bar button. + document.querySelectorAll("[data-search-open]").forEach(function (b) { + b.addEventListener("click", openDialog); + }); document.addEventListener("keydown", function (e) { if (dialog.open) return; var typing = /^(INPUT|TEXTAREA|SELECT)$/.test(document.activeElement.tagName); diff --git a/static/js/ui.js b/static/js/ui.js new file mode 100644 index 0000000..9d3f281 --- /dev/null +++ b/static/js/ui.js @@ -0,0 +1,91 @@ +// Theme toggle and mobile drawer (markup in templates/base.html and +// templates/partials/sidebar.html). The saved theme is applied before +// first paint by the inline script in base.html's ; this file +// only handles interaction. +(function () { + // Point the generated giallo stylesheets at the active theme. With no + // explicit choice they follow the system preference on their own. + function syncHighlight() { + var t = document.documentElement.dataset.theme || ""; + document.getElementById("hl-light").media = + t ? (t === "light" ? "all" : "not all") : "(prefers-color-scheme: light)"; + document.getElementById("hl-dark").media = + t ? (t === "dark" ? "all" : "not all") : "(prefers-color-scheme: dark)"; + } + + document.getElementById("theme-toggle").addEventListener("click", function () { + var explicit = document.documentElement.dataset.theme; + var effective = explicit || + (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"); + var next = effective === "dark" ? "light" : "dark"; + document.documentElement.dataset.theme = next; + try { + localStorage.setItem("theme", next); + } catch (e) {} // private browsing: the choice just won't persist + syncHighlight(); + }); + + // Mobile drawer: the sidebar slides in over a backdrop. + var body = document.body; + function closeDrawer() { + body.classList.remove("sidebar-open"); + } + document.getElementById("menu-open").addEventListener("click", function () { + body.classList.toggle("sidebar-open"); + }); + document.getElementById("sidebar-backdrop").addEventListener("click", closeDrawer); + // Close on any nav click: same-page anchors don't trigger a page load, + // so the drawer would otherwise stay open over the scrolled content. + document.querySelector(".sidebar").addEventListener("click", function (e) { + if (e.target.closest("a")) closeDrawer(); + }); + document.addEventListener("keydown", function (e) { + if (e.key === "Escape" && body.classList.contains("sidebar-open")) closeDrawer(); + }); + + // Scrollspy: mark the section currently being read in the sidebar list. + // Current is the last heading above the reading line — the heading's own + // scroll-margin-top plus some slack, so following a section link also + // highlights the section it jumps to. + var spyLinks = []; + var spyHeadings = []; + document.querySelectorAll(".menu-list-child-list.active .menu-list-link") + .forEach(function (link) { + var heading = document.getElementById(decodeURIComponent(link.hash.slice(1))); + if (heading) { + spyLinks.push(link); + spyHeadings.push(heading); + } + }); + if (spyHeadings.length) { + var currentLink = null; + var updateSpy = function () { + var line = parseFloat(getComputedStyle(spyHeadings[0]).scrollMarginTop) + 8; + var current = null; + for (var i = 0; i < spyHeadings.length; i++) { + if (spyHeadings[i].getBoundingClientRect().top <= line) current = spyLinks[i]; + } + // A short final section may never reach the reading line; count it + // once the page is scrolled to the bottom. + if (window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 2) { + current = spyLinks[spyLinks.length - 1]; + } + if (current !== currentLink) { + if (currentLink) currentLink.classList.remove("current"); + if (current) current.classList.add("current"); + currentLink = current; + } + }; + var spyPending = false; + window.addEventListener("scroll", function () { + if (spyPending) return; + spyPending = true; + requestAnimationFrame(function () { + spyPending = false; + updateSpy(); + }); + }, { passive: true }); + window.addEventListener("resize", updateSpy); + updateSpy(); + } +})(); diff --git a/templates/base.html b/templates/base.html index bf37f53..f541807 100644 --- a/templates/base.html +++ b/templates/base.html @@ -4,40 +4,64 @@ - - - - - - - - + + + + + + + + {%- block head_extra %}{% endblock %}{% block title %}{{ config.title }}{% endblock %} ++ + Modern Julia Workflows + + + {% include "partials/sidebar.html" %} --+ + {% include "partials/search.html" %} + {%- block foot_extra %}{% endblock %} diff --git a/templates/components.html b/templates/components.html index ddbc3f5..b71cd2b 100644 --- a/templates/components.html +++ b/templates/components.html @@ -1,31 +1,36 @@ {# Admonition components, invoked from markdown as e.g. #} {# {%+-+ {% block content %}{% endblock %} CC BY-SA 4.0 {{ config.extra.author }}. Last built: {{ now() | date(format="%B %d, %Y") }}.-
- Website built with Zola and the Julia programming language.%} ... {% %} #} {# Content is Tera-templated before the markdown pass (Zola 0.23), so the #} -{# component output lands in the markdown source: the body stays markdown #} -{# and the surrounding blank lines make thea proper HTML block. The #} -{# bold prefix merges into the body's first paragraph, like Franklin's #} -{# \tldr{...} commands did. #} +{# component output lands in the markdown source: the wrappers are HTML #} +{# blocks, and the blank lines around the body keep it regular markdown. #} +{# The title is a span glued to the front of the body so that markdown folds #} +{# both into one paragraph, reading "Title: body ...". Styles live in #} +{# css/site.css (.admonition); each type maps to one of the four Julia brand #} +{# colors. The title is marked data-pagefind-ignore so searching for e.g. #} +{# "advanced" doesn't return every box. #} -{% component tldr() %} -+{% component admonition(class, title, content) %} +++{% endcomponent admonition %} + +{% component tldr() %} +{{-**TLDR**: {{ body | trim | safe }} +{{ title }}: {{ content | trim | safe }}+}} {% endcomponent tldr %} {% component advanced() %} - - -**Advanced**: {{ body | trim | safe }} - -+{{}} {% endcomponent advanced %} {% component vscode() %} - - -**VSCode**: {{ body | trim | safe }} - -+{{}} {% endcomponent vscode %} + +{% component note() %} +{{ }} +{% endcomponent note %} diff --git a/templates/partials/sidebar.html b/templates/partials/sidebar.html index 9c240dc..812e752 100644 --- a/templates/partials/sidebar.html +++ b/templates/partials/sidebar.html @@ -2,7 +2,8 @@ so anchors never go stale. `.menu-list-child-list` is shown by the CSS sibling selector `.sidebar-nav-item.active + .menu-list-child-list`, so each