diff --git a/website/content/_index.md b/website/content/_index.md index 1ec67278..3ca4e6b5 100644 --- a/website/content/_index.md +++ b/website/content/_index.md @@ -3,7 +3,7 @@ title = "Free online vector editor & procedural design tool" template = "section.html" [extra] -css = ["/index.css", "/balance-text.css"] +css = ["/page/index.css", "/component/carousel.css", "/component/feature-icons.css", "/component/feature-box.css", "/component/youtube-embed.css", "/layout/balance-text.css"] js = ["/js/carousel.js", "/js/youtube-embed.js", "/js/video-autoplay.js"] linked_js = ["https://static.graphite.rs/text-balancer/text-balancer.js"] meta_description = "Open source free software. A vector graphics creativity suite with a clean, intuitive interface. Opens instantly (no signup) and runs locally in a browser. Exports SVG, PNG, JPG." @@ -456,8 +456,8 @@ Get started with Graphite by following along to a hands-on quickstart tutorial.
-
- Graphite Tutorial 1 - Hands-On Quickstart +
+ Graphite Tutorial 1 - Hands-On Quickstart
@@ -493,8 +493,8 @@ Get started with Graphite by following along to a hands-on quickstart tutorial.
Watch this timelapse showing the process of mixing traditional vector art (tracing a physical sketch and colorizing it, first two minutes) with using Imaginate to generate a background (last 45 seconds). -
- Graphite - Vector Editing: "Commander Basstronaut" Artwork (25x Timelapse) +
+ Graphite - Vector Editing: "Commander Basstronaut" Artwork (25x Timelapse)
(Recorded in an older version of Graphite from early 2023.)
diff --git a/website/content/about.md b/website/content/about.md index 5684efb6..a82dd7be 100644 --- a/website/content/about.md +++ b/website/content/about.md @@ -2,7 +2,7 @@ title = "About Graphite" [extra] -css = ["/about.css"] +css = ["/page/about.css", "/component/feature-box.css"] linked_css = ["https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap"] +++ @@ -117,7 +117,7 @@ It's easy to learn and teach, yet Graphite's accessible design does not sacrific Photo of Keavon Chambers -## Keavon Chambers (@Keavon) 🇺🇸 +## Keavon Chambers (@Keavon) 🇺🇸 ***Founder, UI & product design, frontend, editor systems*** @@ -128,7 +128,7 @@ Keavon is a creative generalist with a love for the fusion of arts and technolog Photo of Dennis Kobert -## Dennis Kobert (@TrueDoctor) 🇩🇪 +## Dennis Kobert (@TrueDoctor) 🇩🇪 ***Graphene node engine, research, architecture*** @@ -143,7 +143,7 @@ Dennis is a mix between a mathematician and a mad scientist. While still enjoyin Photo of Hypercube -## "Hypercube" (@0Hypercube) 🇬🇧 +## "Hypercube" (@0Hypercube) 🇬🇧 ***Editor systems, nodes, tools, architecture*** @@ -155,7 +155,7 @@ Dennis is a mix between a mathematician and a mad scientist. While still enjoyin Photo of Adam Gerhant -## Adam Gerhant (@pendapia) 🇺🇸 +## Adam Gerhant (@pendapia) 🇺🇸 ***Editor graph tooling, node data formats*** diff --git a/website/content/blog/2024-01-01-looking-back-on-2023-and-what's-next.md b/website/content/blog/2024-01-01-looking-back-on-2023-and-what's-next.md index 8397096d..cd50523e 100644 --- a/website/content/blog/2024-01-01-looking-back-on-2023-and-what's-next.md +++ b/website/content/blog/2024-01-01-looking-back-on-2023-and-what's-next.md @@ -11,6 +11,7 @@ reddit = "https://www.reddit.com/r/graphite/comments/18xmoti/blog_post_looking_b twitter = "https://twitter.com/GraphiteEditor/status/1742576805532577937" js = ["/js/youtube-embed.js"] +css = ["/component/youtube-embed.css"] +++ The new year is here, and with so many accomplishments to share from the past twelve months, let's revisit the highlights of 2023 for the Graphite project. Now that winter has entered, let's swing back to the spring, summarize the summer, and follow this fall's noteworthy developments that brought another year of fruitful progress to Graphite's mission of re-envisioning artists' 2D creative workflows with the best free software we can build for the open source community. This past year as a team, we all got closer— to one another from continents apart; to visiting and connecting with our industry peers; and to reaching exciting new development milestones. @@ -92,8 +93,8 @@ The next big news of August was my formation of [Graphite Labs, LLC](https://www I allocated my time at several points throughout the year into growing and evolving this website with a refreshed and more visually-appealing home page, dedicated pages for information [about](/about) the project and its [features](/features), an area providing resources and help for [volunteers](/volunteer) and [code contributors](/volunteer/guide), and just this month— a [user manual](/learn) complete with an introductory tutorial series. The first video went up yesterday: -
- Graphite Tutorial 1 - Hands-On Quickstart +
+ Graphite Tutorial 1 - Hands-On Quickstart
The user manual and tutorial series will continue expanding throughout the coming weeks. Additional website features including user accounts, forums, and other community features are being planned. diff --git a/website/content/blog/2024-05-09-graphite-progress-report-q1-2024.md b/website/content/blog/2024-05-09-graphite-progress-report-q1-2024.md index 8070e05e..bac4e449 100644 --- a/website/content/blog/2024-05-09-graphite-progress-report-q1-2024.md +++ b/website/content/blog/2024-05-09-graphite-progress-report-q1-2024.md @@ -8,6 +8,7 @@ author = "Keavon Chambers & Hypercube" summary = "Graphite's Q1 2024 update introduces a precise snapping system and a customizable grid for enhanced design control. The update also includes improved procedural scattering with the 'Copy to Points' node, demonstrated in new demo artwork." reddit = "https://www.reddit.com/r/graphite/comments/1coa0if/blog_post_graphite_progress_report_q1_2024/" twitter = "https://twitter.com/GraphiteEditor/status/1788698448348266946" +css = ["/component/demo-artwork.css"] +++ [Graphite](/) is a new 2D vector graphics editor bringing a modern, nondestructive approach to creative workflows with node-based procedural generation. The project is currently three years into development, with a focus on streamlining the creative process for procedural vector artwork. See the [roadmap](/features#roadmap) for a more in-depth summary of the goals for 2024 and beyond. diff --git a/website/content/blog/2024-07-31-graphite-progress-report-q2-2024.md b/website/content/blog/2024-07-31-graphite-progress-report-q2-2024.md index 406d5997..e2a468f3 100644 --- a/website/content/blog/2024-07-31-graphite-progress-report-q2-2024.md +++ b/website/content/blog/2024-07-31-graphite-progress-report-q2-2024.md @@ -8,6 +8,7 @@ author = "Keavon Chambers & Hypercube" summary = "Graphite's Q2 2024 update introduces boolean path operations, a new gradient picker, layer locking, and more improvements." reddit = "https://www.reddit.com/r/graphite/comments/1ei9ps2/blog_post_graphite_progress_report_q2_2024/" twitter = "https://x.com/GraphiteEditor/status/1819360794028462569" +css = ["/component/demo-artwork.css"] +++ [Graphite](/), a new open source 2D procedural graphics editor, has spent April–June introducing **boolean path operations, a new gradient picker, layer locking**, and more improvements. diff --git a/website/content/blog/2024-10-15-graphite-progress-report-q3-2024.md b/website/content/blog/2024-10-15-graphite-progress-report-q3-2024.md index c4df3202..e07b83fc 100644 --- a/website/content/blog/2024-10-15-graphite-progress-report-q3-2024.md +++ b/website/content/blog/2024-10-15-graphite-progress-report-q3-2024.md @@ -8,6 +8,7 @@ author = "Keavon Chambers & Hypercube" summary = "Graphite's Q3 2024 update introduces improvements to performance, node graph organization, nondestructive path editing, a new render engine, and more helpful nodes." reddit = "https://www.reddit.com/r/graphite/comments/1g4h6ya/blog_post_graphite_progress_report_q3_2024/" twitter = "https://x.com/GraphiteEditor/status/1846283664562573344" +css = ["/component/demo-artwork.css"] +++ [Graphite](/), a new open source 2D procedural graphics editor, has spent July–September building major improvements to **performance, node graph organization, nondestructive path editing, a new render engine, and more helpful nodes**, amongst over 100 other features and fixes. diff --git a/website/content/contact.md b/website/content/contact.md index c8e91e5e..ddbe16fa 100644 --- a/website/content/contact.md +++ b/website/content/contact.md @@ -1,5 +1,8 @@ +++ title = "Contact the team" + +[extra] +css = ["/layout/reading-material.css"] +++
diff --git a/website/content/donate.md b/website/content/donate.md index c50c622d..6885ae33 100644 --- a/website/content/donate.md +++ b/website/content/donate.md @@ -2,7 +2,7 @@ title = "Donate" [extra] -# css = ["/donate.css", "/balance-text.css"] +# css = ["/page/donate.css", "/component/feature-box.css", "/layout/balance-text.css"] # js = ["/js/fundraising.js"] # linked_js = ["https://static.graphite.rs/text-balancer/text-balancer.js"] +++ diff --git a/website/content/features.md b/website/content/features.md index c70a036e..c0c72b97 100644 --- a/website/content/features.md +++ b/website/content/features.md @@ -2,7 +2,7 @@ title = "Graphite features" [extra] -css = ["/features.css"] +css = ["/page/features.css", "/component/feature-box.css", "/component/feature-icons.css"] +++
diff --git a/website/content/learn/_index.md b/website/content/learn/_index.md index ab80d056..2d789598 100644 --- a/website/content/learn/_index.md +++ b/website/content/learn/_index.md @@ -6,6 +6,7 @@ page_template = "book.html" [extra] book = true js = ["/js/youtube-embed.js"] +css = ["/component/youtube-embed.css"] +++ Welcome to the Graphite user manual. Keep reading to to learn how the software can help bring your 2D creative ideas to life. @@ -26,6 +27,6 @@ If you're ever stuck or confused, ask your questions in the `#🧭user-help` cha The fastest way to get started is to watch and follow along steps-by-step in the hands-on quickstart video: -
- Graphite Tutorial 1 - Hands-On Quickstart +
+ Graphite Tutorial 1 - Hands-On Quickstart
diff --git a/website/content/learn/_unpublished/workflows/imaginate.md b/website/content/learn/_unpublished/workflows/imaginate.md index 2473d052..7f005200 100644 --- a/website/content/learn/_unpublished/workflows/imaginate.md +++ b/website/content/learn/_unpublished/workflows/imaginate.md @@ -4,6 +4,7 @@ title = "Imaginate" [extra] order = 2 js = ["/js/carousel.js"] +css = ["/component/carousel.css"] +++ Imaginate is a useful tool at every stage in the artistic process. Early on it provides inspiration for styles, color palettes, subjects, and composition. It lets you quickly test ideas and explore artistic directions. It's also a useful way to generate placeholder images and content for kit bashing. diff --git a/website/content/learn/introduction/_index.md b/website/content/learn/introduction/_index.md index b331b168..a4c8d41b 100644 --- a/website/content/learn/introduction/_index.md +++ b/website/content/learn/introduction/_index.md @@ -6,6 +6,7 @@ page_template = "book.html" [extra] order = 1 js = ["/js/youtube-embed.js"] +css = ["/component/youtube-embed.css"] +++ @@ -20,8 +21,8 @@ One is available now, and more will be released on a regular basis throughout ea -
- Graphite Tutorial 1 - Hands-On Quickstart +
+ Graphite Tutorial 1 - Hands-On Quickstart
### Video 2 diff --git a/website/content/license.md b/website/content/license.md index c3f777e8..98043dd0 100644 --- a/website/content/license.md +++ b/website/content/license.md @@ -1,5 +1,8 @@ +++ title = "Graphite license" + +[extra] +css = ["/layout/reading-material.css"] +++
diff --git a/website/content/logo.md b/website/content/logo.md index 92982cb4..c4ab5698 100644 --- a/website/content/logo.md +++ b/website/content/logo.md @@ -2,7 +2,7 @@ title = "Graphite logo" [extra] -css = ["/logo.css"] +css = ["/page/logo.css", "/component/feature-box.css", "/layout/reading-material.css"] +++
@@ -40,8 +40,6 @@ Download the complete [logo kit](https://static.graphite.rs/logos/graphite-logo-
-
-
diff --git a/website/content/press.md b/website/content/press.md index ecc6e469..614c6da5 100644 --- a/website/content/press.md +++ b/website/content/press.md @@ -1,5 +1,8 @@ +++ title = "Press resources" + +[extra] +css = ["/layout/reading-material.css"] +++
diff --git a/website/content/volunteer/_index.md b/website/content/volunteer/_index.md index ea39c641..6d92fcac 100644 --- a/website/content/volunteer/_index.md +++ b/website/content/volunteer/_index.md @@ -2,8 +2,7 @@ title = "Volunteer" [extra] -css = ["/volunteer.css"] -linked_css = ["https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap"] +css = ["/page/volunteer.css", "/component/feature-box.css"] +++
@@ -62,7 +61,7 @@ The Graphite editor is built much like a game engine, split across user interfac Flavor graphic depicting a fountain pen, ink pots, and a book -Assign yourself the *"🙌 Interested in helping with art or marketing"* role in the *#welcome* Discord channel. Then mention your experience and how you'd like to help in the *#introductions* channel. +Assign yourself the *"🙌 Interested in helping with art or marketing"* role in the *#welcome* Discord channel. Then mention your experience and how you'd like to help in the *#introductions* channel. Volunteer on Discord @@ -97,7 +96,7 @@ Help write, edit, and design content for this website, social media, newsletters Flavor graphic depicting a magnifying glass on the search for a software bug -Assign yourself the *"🐒 Volunteer to get pinged regularly for QA testing"* or *"🤖 Interested in contributing code"* roles in the *#welcome* Discord channel. In the latter case, drop by the *#development* channel to get advice writing your first node. +Assign yourself the *"🐒 Volunteer to get pinged regularly for QA testing"* or *"🤖 Interested in contributing code"* roles in the *#welcome* Discord channel. In the latter case, drop by the *#development* channel to get advice writing your first node. Volunteer on Discord diff --git a/website/content/volunteer/guide/_index.md b/website/content/volunteer/guide/_index.md index 737049e6..a3d1518f 100644 --- a/website/content/volunteer/guide/_index.md +++ b/website/content/volunteer/guide/_index.md @@ -6,12 +6,11 @@ aliases = ["/contribute"] [extra] book = true -linked_css = ["https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap"] +++ Welcome, potential contributor! We're excited to have you join the Graphite project and it's our goal to make the process as smooth as possible. This guide will serve as your library of knowledge to help you get started contributing to the project. If you find any information missing or unclear, please let us know through Discord or submit a pull request to help document the process for future contributors. -The next page will cover how to compile the Graphite source code. But first, make sure you've joined our [Discord server](https://discord.graphite.rs) and assigned yourself the *"🤖 Interested in contributing code"* role from the `#🙂welcome` channel. Done that? Alright, proceed! +The next page will cover how to compile the Graphite source code. But first, make sure you've joined our [Discord server](https://discord.graphite.rs) and assigned yourself the *"🤖 Interested in contributing code"* role from the `#🙂welcome` channel. Done that? Alright, proceed!

Flavor graphic depicting a library of knowledge in a digital realm diff --git a/website/content/volunteer/guide/codebase-overview/_index.md b/website/content/volunteer/guide/codebase-overview/_index.md index 5b823d98..33b1d6a4 100644 --- a/website/content/volunteer/guide/codebase-overview/_index.md +++ b/website/content/volunteer/guide/codebase-overview/_index.md @@ -6,12 +6,13 @@ page_template = "book.html" [extra] order = 2 # Chapter number js = ["/js/youtube-embed.js"] +css = ["/component/youtube-embed.css"] +++ The best introduction for getting up-to-speed with Graphite contribution comes from watching this webcast recording. Before asking questions in Discord, please watch the full video because it gives a comprehensive overview of most things you will need to know. -

- Workshop: Intro to Coding for Graphite +
+ Workshop: Intro to Coding for Graphite
diff --git a/website/content/volunteer/guide/starting-a-task/_index.md b/website/content/volunteer/guide/starting-a-task/_index.md index 427716e4..85483d03 100644 --- a/website/content/volunteer/guide/starting-a-task/_index.md +++ b/website/content/volunteer/guide/starting-a-task/_index.md @@ -7,7 +7,7 @@ page_template = "book.html" order = 3 # Chapter number +++ -There are two places to look for beginner-friendly development tasks. Usually, the best option is to select one of the many bite-sized task descriptions marked with a ‼️ reaction in the `#✅code-todo-list` channel of the [Discord server](https://discord.graphite.rs). You may also browse the [task board](https://github.com/orgs/GraphiteEditor/projects/1/views/1), which lists [beginner issues](https://github.com/orgs/GraphiteEditor/projects/1/views/6) to pick from. The Discord option usually has the more approachable tasks compared to the GitHub issues, which tend to have more variability in complexity. +There are two places to look for beginner-friendly development tasks. Usually, the best option is to select one of the many bite-sized task descriptions marked with a ‼️ reaction in the `#✅code-todo-list` channel of the [Discord server](https://discord.graphite.rs). You may also browse the [task board](https://github.com/orgs/GraphiteEditor/projects/1/views/1), which lists [beginner issues](https://github.com/orgs/GraphiteEditor/projects/1/views/6) to pick from. The Discord option usually has the more approachable tasks compared to the GitHub issues, which tend to have more variability in complexity. If you're unsure about which task to pick, feel free to ask in the `#📄development` channel. diff --git a/website/content/volunteer/guide/starting-a-task/submitting-a-contribution.md b/website/content/volunteer/guide/starting-a-task/submitting-a-contribution.md index e6293bf2..471f4756 100644 --- a/website/content/volunteer/guide/starting-a-task/submitting-a-contribution.md +++ b/website/content/volunteer/guide/starting-a-task/submitting-a-contribution.md @@ -3,7 +3,6 @@ title = "Submitting a contribution" [extra] order = 3 # Page number after chapter intro -linked_css = ["https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap"] +++ Collaboration is a key part of real-world software engineering. Graphite follows some basic procedures to keep the process smooth and efficient. You will want to familiarize yourself with these guidelines to save yourself and Graphite maintainers time and confusion. @@ -72,7 +71,7 @@ Upon pushing a commit to your PR's branch, CI will need to build and test your c You also have to pass `cargo fmt` and `cargo clippy` locally before your PR can be merged. -Your goal is for the check called "Editor: Dev & CI / build (pull_request)" to pass with a . If it fails with a , you will need to investigate. If you need access to the build logs, ask a maintainer to provide them. Occasionally, other checks may fail, but you likely won't be responsible for fixing those and they can be ignored. +Your goal is for the check called "Editor: Dev & CI / build (pull_request)" to pass with a ✅. If it fails with a ❌, you will need to investigate. If you need access to the build logs, ask a maintainer to provide them. Occasionally, other checks may fail, but you likely won't be responsible for fixing those and they can be ignored. ## Keeping your work up-to-date diff --git a/website/sass/base.scss b/website/sass/base.scss index f16f45ff..00366761 100644 --- a/website/sass/base.scss +++ b/website/sass/base.scss @@ -3,8 +3,6 @@ // ================================ :root { - --color-black: #000000; - --color-white: #ffffff; --color-fog: #eeeeee; --color-parchment: #faefe2; --color-cloud: #d9e1e4; @@ -22,8 +20,8 @@ --color-seaside: #b0d6cb; --color-seaside-rgb: 176, 214, 203; // --color-cove: #83c0b9; - --color-sage: #91b99a; - --color-storm: #627088; + // --color-sage: #91b99a; + // --color-storm: #627088; --max-width: 1200px; --max-width-plus-padding: calc(var(--max-width) + 40px * 2); @@ -39,7 +37,7 @@ html, body { color: var(--color-navy); - background: var(--color-white); + background: white; font-family: "Inter", sans-serif; line-height: 1.5; font-weight: 500; @@ -107,6 +105,9 @@ body > .page { display: flex; align-items: center; gap: 40px; + --height: 60px; + --button-padding: 24px; + --nav-font-size: 28px; // Keep up to date with `NAV_BUTTON_INITIAL_FONT_SIZE` in navbar.js a { font-family: "Bona Nova", Palatino, serif; @@ -114,9 +115,6 @@ body > .page { line-height: 1.25; font-weight: 700; text-decoration: none; - --height: 60px; - --button-padding: 24px; - --nav-font-size: 28px; // Keep up to date with `NAV_BUTTON_INITIAL_FONT_SIZE` in navbar.js font-size: var(--nav-font-size); &.button { @@ -150,103 +148,70 @@ body > .page { @media screen and (max-width: 1200px) { gap: 30px; - - a { - --height: 50px; - --button-padding: 16px; - --nav-font-size: 24px; - } + --height: 50px; + --button-padding: 16px; + --nav-font-size: 24px; } @media screen and (max-width: 1000px) { gap: 30px; - - a { - --button-padding: 14px; - --nav-font-size: 20px; - } + --button-padding: 14px; + --nav-font-size: 20px; } @media print, screen and (max-width: 900px) { gap: 20px; - - a { - --height: 40px; - --button-padding: 13px; - --nav-font-size: 18px; - } + --height: 40px; + --button-padding: 13px; + --nav-font-size: 18px; } @media print, screen and (max-width: 780px) { gap: 20px; - - a { - --button-padding: 12px; - --nav-font-size: 16px; - } + --button-padding: 12px; + --nav-font-size: 16px; } @media screen and (max-width: 680px) { gap: 16px; - - a { - --height: 30px; - --button-padding: 8px; - --nav-font-size: 14px; - } + --height: 30px; + --button-padding: 8px; + --nav-font-size: 14px; } @media screen and (max-width: 580px) { gap: 12px; - - a { - --height: 24px; - --nav-font-size: 13px; - } + --height: 24px; + --nav-font-size: 13px; } @media screen and (max-width: 520px) { gap: 10px; - - a { - --height: 22px; - --button-padding: 6px; - --nav-font-size: 12px; - } + --height: 22px; + --button-padding: 6px; + --nav-font-size: 12px; } @media screen and (max-width: 460px) { gap: 8px; - - a { - --height: 20px; - --button-padding: 4px; - --nav-font-size: 11px; - } + --height: 20px; + --button-padding: 4px; + --nav-font-size: 11px; } @media screen and (max-width: 420px) { gap: 6px; - - a { - --nav-font-size: 10px; - } + --nav-font-size: 10px; } @media screen and (max-width: 380px) { gap: 6px; - - a { - --nav-font-size: 9px; - } + --nav-font-size: 9px; } @media screen and (max-width: 350px) { gap: 6px; - - a { - --nav-font-size: 8px; - } + --nav-font-size: 8px; } } } @@ -377,8 +342,8 @@ body > .page { :is(h1, h2, h3, h4, article > :first-child) ~ :is(p, ul, ol, ol li p, img, a:has(> img:only-child)), :is(h1, h2, h3, h4, article > :first-child) ~ :is(ul, ol) li p + img, :is(h1, h2, h3, h4, p) ~ .feature-icons, -p ~ :is(h1, h2, h3, h4, details summary, blockquote, .image-comparison, .video-background, .video-embed), -.video-embed + :is(p, .link, .button), +p ~ :is(h1, h2, h3, h4, details summary, blockquote, .image-comparison, .video-background, .youtube-embed), +.youtube-embed + :is(p, .link, .button), p + p > .button, p + :is(.link, section), table td p ~ p, @@ -526,7 +491,7 @@ hr { } code { - color: var(--color-black); + color: black; background: var(--color-fog); padding: 0 4px; overflow-wrap: anywhere; @@ -538,113 +503,6 @@ code { } } -pre { - display: flex; - max-width: 100%; - color: var(--color-fog); - // This zero transform sets this element as the root for `position: fixed` - transform: translate(0); - - // Color overrides - &, - &.z-code { - background: var(--color-navy); - - .z-path { - color: #679f70; - - span { - color: #e6e1dc; - } - } - } - - // Container for the element (span or table) containing the lines of code - code { - background: initial; - color: inherit; - display: block; - overflow-x: auto; - padding: 20px; - width: 0; - flex: 1 1 auto; - } - - // Language name in top right corner - &[data-lang] { - padding-top: 28px; - - &::before { - content: attr(data-lang); - color: rgba(var(--color-seaside-rgb), 0.5); - text-transform: lowercase; - font-family: "Inter", sans-serif; - font-size: 0.75em; - font-weight: 700; - font-style: italic; - -webkit-user-select: none; - user-select: none; - pointer-events: none; - position: fixed; - top: 0; - line-height: 28px; - display: block; - width: 100%; - text-indent: 20px; - background: rgba(0, 0, 0, 0.25); - - &[data-lang="sh"] { - content: "Shell"; - } - - &[data-lang="rs"] { - content: "Rust"; - } - - &[data-lang="js"] { - content: "JavaScript"; - } - - &[data-lang="ts"] { - content: "TypeScript"; - } - } - } - - // Code blocks with line numbers - &[data-linenos] table { - border-spacing: 0; - margin: -20px; - - tr { - &:first-child td { - padding-top: 20px; - } - - &:last-child td { - padding-bottom: 20px; - } - - td { - &:first-child { - padding-left: 20px; - padding-right: 10px; - -webkit-user-select: none; - user-select: none; - vertical-align: top; - text-align: right; - background: rgba(0, 0, 0, 0.25); - } - - &:last-child { - padding-left: 10px; - padding-right: 20px; - } - } - } - } -} - kbd { outline: calc(var(--border-thickness) / 2) solid var(--color-navy); padding: 0 8px; @@ -692,86 +550,9 @@ hr, } } -// Using this requires adding this line to the page's frontmatter: -// linked_css = ["https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap"] -.emoji { - font-family: "Noto Color Emoji", sans-serif; - font-style: normal; -} - -// ======= -// LAYOUTS -// ======= - -.reading-material.reading-material { - max-width: var(--max-width-reading-material); - - article { - width: 100%; - - h2 { - margin-top: 80px; - } - - h3 { - margin-top: 40px; - } - - h4 { - margin-top: 20px; - } - - h1, - h2, - h3, - h4, - h5, - h6 { - display: block; - - &:first-child { - margin-top: 0; - } - } - - // Captions below images in blog posts - p:has(> img) + center:has(> em) { - margin-top: 10px; - } - - p ~ img { - width: auto; - max-width: 100%; - } - - hr { - margin-top: 40px; - margin-bottom: 40px; - } - - + hr { - margin-top: calc(80 * var(--variable-px)); - margin-bottom: calc(40 * var(--variable-px)); - } - } -} - -// .graphic { -// max-width: 200px; -// flex: 1 1 100%; -// display: flex; - -// img { -// display: block; -// width: 100%; -// object-fit: contain; - -// @media screen and (max-width: 800px) { -// width: auto; -// height: 120px; -// } -// } -// } +// ======================== +// COMMON SIMPLE COMPONENTS +// ======================== .block { display: flex; @@ -782,122 +563,12 @@ hr, &.centered { align-items: center; } -} -:not(.diptych, .triptych) > :is(.block, .diptych, .triptych) + :is(.block, .diptych, .triptych) { - margin-top: calc(120 * var(--variable-px)); -} - -.feature-box-narrow, -.feature-box-outer { - padding: calc(80 * var(--variable-px)); - background-image: url("https://static.graphite.rs/textures/noise.png"); - background-blend-mode: overlay; - background-position: center; -} - -:where(h1, h2, h3, h4, p) + .feature-box-narrow { - margin-top: calc(40 * var(--variable-px)); -} - -.feature-box-full-image { - width: calc(100% + 2 * 80 * var(--variable-px)); - height: auto; - margin-left: calc(-80 * var(--variable-px)); - margin-top: calc(-80 * var(--variable-px)); - margin-bottom: calc(40 * var(--variable-px)); - display: block; -} - -.feature-box-outer { - @media screen and (max-width: 1000px) { - &.feature-box-outer { - margin-left: calc(-1 * var(--page-edge-padding)); - margin-right: calc(-1 * var(--page-edge-padding)); - padding-left: var(--page-edge-padding); - padding-right: var(--page-edge-padding); - } - } - - &.feature-box-outer { - max-width: unset; - } - - .feature-box-inner { - max-width: var(--max-width); - margin: 0 auto; + :not(.diptych, .triptych) > .block + & { + margin-top: calc(120 * var(--variable-px)); } } -h1.feature-box-header.feature-box-header { - &, - & a { - font-family: "Inter", sans-serif; - line-height: 1.5; - font-weight: 800; - text-transform: uppercase; - font-size: calc(1rem * 14 / 9); - } - - span { - white-space: pre; - } - - ~ hr { - margin-top: 20px; - margin-bottom: 40px; - - + p { - margin-top: 0; - } - } -} - -.diptych, -.triptych { - display: flex; - flex-wrap: wrap; - gap: calc(80 * var(--variable-px)); - - .block { - flex: 1 1 0; - } - - img[alt=""] { - display: block; - - &::after { - content: ""; - display: block; - width: 100%; - height: 240px; - background: var(--color-crimson); - } - } -} - -.diptych .block { - min-width: 320px; -} - -.triptych .block { - min-width: 280px; -} - -@media screen and (max-width: 520px) { - .diptych .block { - min-width: 200px; - } - - .triptych .block { - min-width: 280px; - } -} - -// ======================== -// COMMON SIMPLE COMPONENTS -// ======================== - .link { display: inline-block; font-size: var(--font-size-link); @@ -944,54 +615,6 @@ h1.feature-box-header.feature-box-header { font-family: "Inter", sans-serif; } -.demo-artwork { - display: flex; - align-items: center; - justify-content: center; - margin-top: 20px; - - > a { - flex: 0 0 auto; - - img { - height: 128px; - border: 12px solid var(--color-walnut); - vertical-align: top; - flex: 0 0 auto; - } - } - - p { - display: flex; - flex-direction: column; - max-width: 300px; - margin-left: 40px; - text-align: left; - } -} - -.video-embed { - position: relative; - width: 100%; - - &.aspect-16x9 { - padding-top: calc(100% / (16 / 9)); - } - - img, - iframe { - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; - } - - img { - cursor: pointer; - } -} - .video-background { position: relative; font-size: 0; @@ -1038,404 +661,3 @@ h1.feature-box-header.feature-box-header { // right: 16px; // } // } - -// ========================= -// COMMON COMPLEX COMPONENTS -// ========================= - -.image-comparison { - position: relative; - touch-action: pan-y pinch-zoom; - max-width: Min(100%, 512px); - - .crop-container { - height: 100%; - - &:nth-child(2) { - overflow: hidden; - width: calc(100% - var(--comparison-percent)); - - &, - img { - position: absolute; - top: 0; - right: 0; - } - } - - &.crop-container.crop-container { - img { - display: block; - width: auto; - height: 100%; - } - - &:first-child img { - width: 100%; - } - } - } - - .slide-bar { - position: absolute; - background: var(--color-navy); - margin-left: -2px; - width: 4px; - height: 100%; - top: 0; - left: var(--comparison-percent); - box-shadow: 0 0 2px rgba(255, 255, 255, 0.5); - - .arrows { - position: absolute; - top: calc(50% - (40px / 2)); - left: calc(4px / 2); - width: 0; - height: 0; - opacity: 1; - transition: opacity 0.25s; - - svg { - position: absolute; - width: 6.5px; - height: 11px; - top: calc(-11px / 2); - fill: var(--color-white); - - @keyframes pulse-left { - from { transform: translateX(3px); } - to { transform: translateX(-3px); } - } - - @keyframes pulse-right { - from { transform: scaleX(-1) translateX(3px); } - to { transform: scaleX(-1) translateX(-3px); } - } - - @keyframes pulse-opacity { - 0% { opacity: 0; } - 40% { opacity: 1; } - 90% { opacity: 1; } - 100% { opacity: 0; } - } - - &:nth-of-type(1) { - right: 6px; - animation: 3s infinite ease-out pulse-left, 3s infinite ease-out pulse-opacity; - } - - &:nth-of-type(2) { - left: 6px; - animation: 3s infinite ease-out pulse-right, 3s infinite ease-out pulse-opacity; - } - } - - div { - content: ""; - position: absolute; - background: var(--color-navy); - top: 0; - left: 0; - width: 32px; - height: 32px; - transform: translate(-50%, -50%) rotate(45deg); - box-shadow: 0 0 2px rgba(255, 255, 255, 0.5); - } - - // Cover up the box-shadow at the top and bottom of the circle so it connects to the vertical line - &::after { - content: ""; - position: absolute; - background: var(--color-navy); - left: -2px; - top: -24px; - width: 4px; - height: 48px; - } - } - } - - &:hover .slide-bar .arrows { - opacity: 0; - } -} - -.carousel { - margin-top: calc(80 * var(--variable-px)); - transform: translate(0); - - .carousel-slide { - display: flex; - white-space: nowrap; - touch-action: pan-y pinch-zoom; - cursor: grab; - - img { - position: relative; - display: inline-block; - user-select: none; - flex: 0 0 auto; - height: auto; - padding: 0 20px; - - &:first-child, - &:last-child { - --fade-factor: Min(calc(var(--over-slide-factor, 0) / 1.5 + 0.5), 1); - // Fade to white (combining invert and brightness, see ) and desaturate - filter: Invert(calc(var(--fade-factor) / 2)) Brightness(calc(1 + var(--fade-factor))) Grayscale(var(--fade-factor)); - } - - &:first-child { - margin-left: -20px; - } - - &:last-child { - margin-right: -20px; - } - } - } - - &:not(.dragging, .jostling) .carousel-slide img { - transition: transform 500ms; - } - - .carousel-slide:not(.torn) { - overflow: hidden; - } - - .carousel-slide.torn { - position: fixed; - top: 0; - z-index: -1; - // Torn edge mask - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; - -webkit-mask-size: contain; - mask-size: contain; - - &.left { - padding-left: 160px; - margin-left: -160px; - -webkit-mask-image: url("https://static.graphite.rs/textures/torn-edge-left__2.png"); - mask-image: url("https://static.graphite.rs/textures/torn-edge-left__2.png"); - -webkit-mask-position: top left; - mask-position: top left; - } - - &.right { - padding-right: 160px; - margin-right: -160px; - -webkit-mask-image: url("https://static.graphite.rs/textures/torn-edge-right__2.png"); - mask-image: url("https://static.graphite.rs/textures/torn-edge-right__2.png"); - -webkit-mask-position: top right; - mask-position: top right; - } - } - - .screenshot-details { - display: flex; - margin: 20px 0; - gap: 20px 40px; - - @media screen and (max-width: 800px) { - flex-wrap: wrap; - justify-content: center; - } - - .carousel-controls { - display: flex; - align-items: center; - flex: 0 0 auto; - - button { - outline: none; - background: none; - border: none; - padding: 0; - color: inherit; - cursor: pointer; - - svg { - display: block; - } - - + button { - margin-left: 20px; - } - } - - .direction { - fill: currentColor; - } - - .dot { - width: 16px; - height: 16px; - box-sizing: border-box; - border-radius: 50%; - border: 2px solid currentColor; - - &.active { - border: none; - background: var(--color-crimson); - } - } - } - - .screenshot-description { - display: flex; - align-items: center; - min-height: calc(2em * 1.5); - - p + p { - margin: 0; - } - - p:not(.active) { - display: none; - } - } - } - - &.center { - .screenshot-details { - justify-content: center; - } - } - - &.window-size-1 .carousel-slide img { - width: 100%; - } - - &.window-size-2 .carousel-slide img { - width: calc((100% / 2) - 10px); - padding: 0 10px; - - &:first-child { - margin-left: -10px; - } - - &:last-child { - margin-right: -10px; - } - } - - &.window-size-3 .carousel-slide img { - width: calc((100% / 3) - 10px * (4 / 3)); - padding: 0 10px; - - &:first-child { - margin-left: -10px; - } - - &:last-child { - margin-right: -10px; - } - } - - @media screen and (max-width: 1000px) { - margin-left: calc(-1 * var(--page-edge-padding)); - margin-right: calc(-1 * var(--page-edge-padding)); - - .screenshot-details { - margin-left: var(--page-edge-padding); - margin-right: var(--page-edge-padding); - } - } - - @media screen and (max-width: /* The value of --max-width-plus-padding: */ 1280px) { - .carousel-slide.torn { - display: none; - } - } -} - -.atlas { - object-fit: cover; - object-position: calc(-48px * var(--atlas-index)) 0; - width: 48px; - height: 48px; -} - -.feature-icons { - display: flex; - flex-wrap: wrap; - margin-bottom: 20px; - width: 100%; - gap: 16px; - - .feature-icon { - display: flex; - align-items: center; - - img { - flex: 0 0 auto; - } - } - - &:not(.stacked) .feature-icon { - padding: 16px; - gap: 16px; - // Half width, minus own padding on both sides, minus half a gap - flex: 1 0 calc(50% - (16px * 2) - (16px / 2)); - - @media screen and (max-width: 1100px) { - // Quarter width, minus own padding on both sides - flex: 1 0 calc(100% - (16px * 2)); - } - } - - &:not(.no-background) .feature-icon { - background: rgba(0, 0, 0, 0.0625); - } - - &.four-wide .feature-icon { - flex: 1 0 calc(25% - (16px * 4) - (16px / 4)); - - @media screen and (max-width: 1200px) { - // Half width, minus own padding on both sides, minus half a gap - flex: 1 0 calc(50% - (16px * 2) - (16px / 2)); - } - - @media screen and (max-width: 840px) { - // Quarter width, minus own padding on both sides - flex: 1 0 calc(100% - (16px * 2)); - } - } - - &.stacked { - justify-content: space-between; - margin: 0 -10px; - width: calc(100% + 20px); - gap: 0; - - .feature-icon { - flex-direction: column; - flex: 0 1 auto; - margin: 0 10px; - - @media screen and (max-width: 1100px) { - width: calc(100% / 3 - 40px); - } - - @media screen and (max-width: 400px) { - width: calc(100% / 2 - 20px); - } - - img { - width: 72px; - height: 72px; - object-position: calc(-72px * var(--atlas-index)) 0; - margin-bottom: 8px; - } - - span { - text-align: center; - } - } - } -} - -p + .feature-icons .feature-icon.feature-icon { - margin-top: calc(40 * var(--variable-px)); -} diff --git a/website/sass/component/carousel.scss b/website/sass/component/carousel.scss new file mode 100644 index 00000000..6bf3e950 --- /dev/null +++ b/website/sass/component/carousel.scss @@ -0,0 +1,189 @@ +.carousel { + margin-top: calc(80 * var(--variable-px)); + transform: translate(0); + + .carousel-slide { + display: flex; + white-space: nowrap; + touch-action: pan-y pinch-zoom; + cursor: grab; + + img { + position: relative; + display: inline-block; + user-select: none; + flex: 0 0 auto; + height: auto; + padding: 0 20px; + + &:first-child, + &:last-child { + --fade-factor: Min(calc(var(--over-slide-factor, 0) / 1.5 + 0.5), 1); + // Fade to white (combining invert and brightness, see ) and desaturate + filter: Invert(calc(var(--fade-factor) / 2)) Brightness(calc(1 + var(--fade-factor))) Grayscale(var(--fade-factor)); + } + + &:first-child { + margin-left: -20px; + } + + &:last-child { + margin-right: -20px; + } + } + } + + &:not(.dragging, .jostling) .carousel-slide img { + transition: transform 500ms; + } + + .carousel-slide:not(.torn) { + overflow: hidden; + } + + .carousel-slide.torn { + position: fixed; + top: 0; + z-index: -1; + // Torn edge mask + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-size: contain; + mask-size: contain; + + &.left { + padding-left: 160px; + margin-left: -160px; + -webkit-mask-image: url("https://static.graphite.rs/textures/torn-edge-left__2.png"); + mask-image: url("https://static.graphite.rs/textures/torn-edge-left__2.png"); + -webkit-mask-position: top left; + mask-position: top left; + } + + &.right { + padding-right: 160px; + margin-right: -160px; + -webkit-mask-image: url("https://static.graphite.rs/textures/torn-edge-right__2.png"); + mask-image: url("https://static.graphite.rs/textures/torn-edge-right__2.png"); + -webkit-mask-position: top right; + mask-position: top right; + } + } + + .screenshot-details { + display: flex; + margin: 20px 0; + gap: 20px 40px; + + @media screen and (max-width: 800px) { + flex-wrap: wrap; + justify-content: center; + } + + .carousel-controls { + display: flex; + align-items: center; + flex: 0 0 auto; + + button { + outline: none; + background: none; + border: none; + padding: 0; + color: inherit; + cursor: pointer; + + svg { + display: block; + } + + + button { + margin-left: 20px; + } + } + + .direction { + fill: currentColor; + } + + .dot { + width: 16px; + height: 16px; + box-sizing: border-box; + border-radius: 50%; + border: 2px solid currentColor; + + &.active { + border: none; + background: var(--color-crimson); + } + } + } + + .screenshot-description { + display: flex; + align-items: center; + min-height: calc(2em * 1.5); + + p + p { + margin: 0; + } + + p:not(.active) { + display: none; + } + } + } + + &.center { + .screenshot-details { + justify-content: center; + } + } + + &.window-size-1 .carousel-slide img { + width: 100%; + } + + &.window-size-2 .carousel-slide img { + width: calc((100% / 2) - 10px); + padding: 0 10px; + + &:first-child { + margin-left: -10px; + } + + &:last-child { + margin-right: -10px; + } + } + + &.window-size-3 .carousel-slide img { + width: calc((100% / 3) - 10px * (4 / 3)); + padding: 0 10px; + + &:first-child { + margin-left: -10px; + } + + &:last-child { + margin-right: -10px; + } + } + + @media screen and (max-width: 1000px) { + margin-left: calc(-1 * var(--page-edge-padding)); + margin-right: calc(-1 * var(--page-edge-padding)); + + .screenshot-details { + margin-left: var(--page-edge-padding); + margin-right: var(--page-edge-padding); + } + } + + @media screen and (max-width: /* The value of --max-width-plus-padding: */ 1280px) { + .carousel-slide.torn { + display: none; + } + } +} diff --git a/website/sass/component/code-snippet.scss b/website/sass/component/code-snippet.scss new file mode 100644 index 00000000..f95fc637 --- /dev/null +++ b/website/sass/component/code-snippet.scss @@ -0,0 +1,106 @@ +pre { + display: flex; + max-width: 100%; + color: var(--color-fog); + // This zero transform sets this element as the root for `position: fixed` + transform: translate(0); + + // Color overrides + &, + &.z-code { + background: var(--color-navy); + + .z-path { + color: #679f70; + + span { + color: #e6e1dc; + } + } + } + + // Container for the element (span or table) containing the lines of code + code { + background: initial; + color: inherit; + display: block; + overflow-x: auto; + padding: 20px; + width: 0; + flex: 1 1 auto; + } + + // Language name in top right corner + &[data-lang] { + padding-top: 28px; + + &::before { + content: attr(data-lang); + color: rgba(var(--color-seaside-rgb), 0.5); + text-transform: lowercase; + font-family: "Inter", sans-serif; + font-size: 0.75em; + font-weight: 700; + font-style: italic; + -webkit-user-select: none; + user-select: none; + pointer-events: none; + position: fixed; + top: 0; + line-height: 28px; + display: block; + width: 100%; + text-indent: 20px; + background: rgba(0, 0, 0, 0.25); + + &[data-lang="sh"] { + content: "Shell"; + } + + &[data-lang="rs"] { + content: "Rust"; + } + + &[data-lang="js"] { + content: "JavaScript"; + } + + &[data-lang="ts"] { + content: "TypeScript"; + } + } + } + + // Code blocks with line numbers + &[data-linenos] table { + border-spacing: 0; + margin: -20px; + + tr { + &:first-child td { + padding-top: 20px; + } + + &:last-child td { + padding-bottom: 20px; + } + + td { + &:first-child { + padding-left: 20px; + padding-right: 10px; + -webkit-user-select: none; + user-select: none; + vertical-align: top; + text-align: right; + background: rgba(0, 0, 0, 0.25); + } + + &:last-child { + padding-left: 10px; + padding-right: 20px; + } + } + } + } +} diff --git a/website/sass/component/demo-artwork.scss b/website/sass/component/demo-artwork.scss new file mode 100644 index 00000000..61f34055 --- /dev/null +++ b/website/sass/component/demo-artwork.scss @@ -0,0 +1,25 @@ +.demo-artwork { + display: flex; + align-items: center; + justify-content: center; + margin-top: 20px; + + > a { + flex: 0 0 auto; + + img { + height: 128px; + border: 12px solid var(--color-walnut); + vertical-align: top; + flex: 0 0 auto; + } + } + + p { + display: flex; + flex-direction: column; + max-width: 300px; + margin-left: 40px; + text-align: left; + } +} diff --git a/website/sass/component/feature-box.scss b/website/sass/component/feature-box.scss new file mode 100644 index 00000000..3c84a85b --- /dev/null +++ b/website/sass/component/feature-box.scss @@ -0,0 +1,109 @@ +:not(.diptych, .triptych) > :is(.block, .diptych, .triptych) + :is(.block, .diptych, .triptych) { + margin-top: calc(120 * var(--variable-px)); +} + +.feature-box-narrow, +.feature-box-outer { + padding: calc(80 * var(--variable-px)); + background-image: url("https://static.graphite.rs/textures/noise.png"); + background-blend-mode: overlay; + background-position: center; +} + +:where(h1, h2, h3, h4, p) + .feature-box-narrow { + margin-top: calc(40 * var(--variable-px)); +} + +.feature-box-full-image { + width: calc(100% + 2 * 80 * var(--variable-px)); + height: auto; + margin-left: calc(-80 * var(--variable-px)); + margin-top: calc(-80 * var(--variable-px)); + margin-bottom: calc(40 * var(--variable-px)); + display: block; +} + +.feature-box-outer { + @media screen and (max-width: 1000px) { + &.feature-box-outer { + margin-left: calc(-1 * var(--page-edge-padding)); + margin-right: calc(-1 * var(--page-edge-padding)); + padding-left: var(--page-edge-padding); + padding-right: var(--page-edge-padding); + } + } + + &.feature-box-outer { + max-width: unset; + } + + .feature-box-inner { + max-width: var(--max-width); + margin: 0 auto; + } +} + +h1.feature-box-header.feature-box-header { + &, + & a { + font-family: "Inter", sans-serif; + line-height: 1.5; + font-weight: 800; + text-transform: uppercase; + font-size: calc(1rem * 14 / 9); + } + + span { + white-space: pre; + } + + ~ hr { + margin-top: 20px; + margin-bottom: 40px; + + + p { + margin-top: 0; + } + } +} + +.diptych, +.triptych { + display: flex; + flex-wrap: wrap; + gap: calc(80 * var(--variable-px)); + + .block { + flex: 1 1 0; + } + + img[alt=""] { + display: block; + + &::after { + content: ""; + display: block; + width: 100%; + height: 240px; + background: var(--color-crimson); + } + } +} + +.diptych .block { + min-width: 320px; +} + +.triptych .block { + min-width: 280px; +} + +@media screen and (max-width: 520px) { + .diptych .block { + min-width: 200px; + } + + .triptych .block { + min-width: 280px; + } +} diff --git a/website/sass/component/feature-icons.scss b/website/sass/component/feature-icons.scss new file mode 100644 index 00000000..2fc8edba --- /dev/null +++ b/website/sass/component/feature-icons.scss @@ -0,0 +1,89 @@ +.feature-icons { + display: flex; + flex-wrap: wrap; + margin-bottom: 20px; + width: 100%; + gap: 16px; + + .atlas { + object-fit: cover; + object-position: calc(-48px * var(--atlas-index)) 0; + width: 48px; + height: 48px; + } + + .feature-icon { + display: flex; + align-items: center; + + img { + flex: 0 0 auto; + } + + p + &.feature-icon { + margin-top: calc(40 * var(--variable-px)); + } + } + + &:not(.stacked) .feature-icon { + padding: 16px; + gap: 16px; + // Half width, minus own padding on both sides, minus half a gap + flex: 1 0 calc(50% - (16px * 2) - (16px / 2)); + + @media screen and (max-width: 1100px) { + // Quarter width, minus own padding on both sides + flex: 1 0 calc(100% - (16px * 2)); + } + } + + &:not(.no-background) .feature-icon { + background: rgba(0, 0, 0, 0.0625); + } + + &.four-wide .feature-icon { + flex: 1 0 calc(25% - (16px * 4) - (16px / 4)); + + @media screen and (max-width: 1200px) { + // Half width, minus own padding on both sides, minus half a gap + flex: 1 0 calc(50% - (16px * 2) - (16px / 2)); + } + + @media screen and (max-width: 840px) { + // Quarter width, minus own padding on both sides + flex: 1 0 calc(100% - (16px * 2)); + } + } + + &.stacked { + justify-content: space-between; + margin: 0 -10px; + width: calc(100% + 20px); + gap: 0; + + .feature-icon { + flex-direction: column; + flex: 0 1 auto; + margin: 0 10px; + + @media screen and (max-width: 1100px) { + width: calc(100% / 3 - 40px); + } + + @media screen and (max-width: 400px) { + width: calc(100% / 2 - 20px); + } + + img { + width: 72px; + height: 72px; + object-position: calc(-72px * var(--atlas-index)) 0; + margin-bottom: 8px; + } + + span { + text-align: center; + } + } + } +} diff --git a/website/sass/component/image-comparison.scss b/website/sass/component/image-comparison.scss new file mode 100644 index 00000000..7bd90baf --- /dev/null +++ b/website/sass/component/image-comparison.scss @@ -0,0 +1,116 @@ +.image-comparison { + position: relative; + touch-action: pan-y pinch-zoom; + max-width: Min(100%, 512px); + + .crop-container { + height: 100%; + + &:nth-child(2) { + overflow: hidden; + width: calc(100% - var(--comparison-percent)); + + &, + img { + position: absolute; + top: 0; + right: 0; + } + } + + &.crop-container.crop-container { + img { + display: block; + width: auto; + height: 100%; + } + + &:first-child img { + width: 100%; + } + } + } + + .slide-bar { + position: absolute; + background: var(--color-navy); + margin-left: -2px; + width: 4px; + height: 100%; + top: 0; + left: var(--comparison-percent); + box-shadow: 0 0 2px rgba(255, 255, 255, 0.5); + + .arrows { + position: absolute; + top: calc(50% - (40px / 2)); + left: calc(4px / 2); + width: 0; + height: 0; + opacity: 1; + transition: opacity 0.25s; + + svg { + position: absolute; + width: 6.5px; + height: 11px; + top: calc(-11px / 2); + fill: white; + + @keyframes pulse-left { + from { transform: translateX(3px); } + to { transform: translateX(-3px); } + } + + @keyframes pulse-right { + from { transform: scaleX(-1) translateX(3px); } + to { transform: scaleX(-1) translateX(-3px); } + } + + @keyframes pulse-opacity { + 0% { opacity: 0; } + 40% { opacity: 1; } + 90% { opacity: 1; } + 100% { opacity: 0; } + } + + &:nth-of-type(1) { + right: 6px; + animation: 3s infinite ease-out pulse-left, 3s infinite ease-out pulse-opacity; + } + + &:nth-of-type(2) { + left: 6px; + animation: 3s infinite ease-out pulse-right, 3s infinite ease-out pulse-opacity; + } + } + + div { + content: ""; + position: absolute; + background: var(--color-navy); + top: 0; + left: 0; + width: 32px; + height: 32px; + transform: translate(-50%, -50%) rotate(45deg); + box-shadow: 0 0 2px rgba(255, 255, 255, 0.5); + } + + // Cover up the box-shadow at the top and bottom of the circle so it connects to the vertical line + &::after { + content: ""; + position: absolute; + background: var(--color-navy); + left: -2px; + top: -24px; + width: 4px; + height: 48px; + } + } + } + + &:hover .slide-bar .arrows { + opacity: 0; + } +} diff --git a/website/sass/component/youtube-embed.scss b/website/sass/component/youtube-embed.scss new file mode 100644 index 00000000..63e962e6 --- /dev/null +++ b/website/sass/component/youtube-embed.scss @@ -0,0 +1,21 @@ +.youtube-embed { + position: relative; + width: 100%; + + &.aspect-16x9 { + padding-top: calc(100% / (16 / 9)); + } + + img, + iframe { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + } + + img { + cursor: pointer; + } +} diff --git a/website/sass/balance-text.scss b/website/sass/layout/balance-text.scss similarity index 100% rename from website/sass/balance-text.scss rename to website/sass/layout/balance-text.scss diff --git a/website/sass/layout/reading-material.scss b/website/sass/layout/reading-material.scss new file mode 100644 index 00000000..976e5c65 --- /dev/null +++ b/website/sass/layout/reading-material.scss @@ -0,0 +1,52 @@ +.reading-material.reading-material { + max-width: var(--max-width-reading-material); + + article { + width: 100%; + + h2 { + margin-top: 80px; + } + + h3 { + margin-top: 40px; + } + + h4 { + margin-top: 20px; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + display: block; + + &:first-child { + margin-top: 0; + } + } + + // Captions below images in blog posts + p:has(> img) + center:has(> em) { + margin-top: 10px; + } + + p ~ img { + width: auto; + max-width: 100%; + } + + hr { + margin-top: 40px; + margin-bottom: 40px; + } + + + hr { + margin-top: calc(80 * var(--variable-px)); + margin-bottom: calc(40 * var(--variable-px)); + } + } +} diff --git a/website/sass/about.scss b/website/sass/page/about.scss similarity index 88% rename from website/sass/about.scss rename to website/sass/page/about.scss index 166d7ab5..f3bedd59 100644 --- a/website/sass/about.scss +++ b/website/sass/page/about.scss @@ -33,9 +33,11 @@ color: var(--color-slate); } - .emoji { - font-size: 0.8em; + .flag { + font-family: "Noto Color Emoji", sans-serif; + font-style: normal; vertical-align: middle; + font-size: 0.8em; cursor: default; } } diff --git a/website/sass/blog.scss b/website/sass/page/blog.scss similarity index 77% rename from website/sass/blog.scss rename to website/sass/page/blog.scss index d45f1f03..82f784ec 100644 --- a/website/sass/blog.scss +++ b/website/sass/page/blog.scss @@ -1,35 +1,33 @@ -#intro { - .block { - flex: 1 1 100%; +#intro .block { + flex: 1 1 100%; + width: 100%; + + .left-right-split { width: 100%; + margin-top: 20px; + display: flex; + gap: 20px; + justify-content: space-between; + flex-wrap: wrap; + } - .left-right-split { - width: 100%; - margin-top: 20px; + .feed { + margin-top: -4px; + + a { + text-decoration: none; display: flex; - gap: 20px; - justify-content: space-between; - flex-wrap: wrap; - } + gap: 8px; - .feed { - margin-top: -4px; + .icon { + vertical-align: top; + width: calc(var(--font-size-link) * 1.5); + height: calc(var(--font-size-link) * 1.5); + } - a { - text-decoration: none; - display: flex; - gap: 8px; - - .icon { - vertical-align: top; - width: calc(var(--font-size-link) * 1.5); - height: calc(var(--font-size-link) * 1.5); - } - - .link { - vertical-align: top; - margin-top: 0; - } + .link { + vertical-align: top; + margin-top: 0; } } } diff --git a/website/sass/donate.scss b/website/sass/page/donate.scss similarity index 100% rename from website/sass/donate.scss rename to website/sass/page/donate.scss diff --git a/website/sass/features.scss b/website/sass/page/features.scss similarity index 100% rename from website/sass/features.scss rename to website/sass/page/features.scss diff --git a/website/sass/index.scss b/website/sass/page/index.scss similarity index 99% rename from website/sass/index.scss rename to website/sass/page/index.scss index 3dc09490..80a70d74 100644 --- a/website/sass/index.scss +++ b/website/sass/page/index.scss @@ -118,11 +118,11 @@ // ▛ PROCEDURALISM ▜ #proceduralism { background-color: var(--color-slate); - color: var(--color-white); + color: white; margin-top: 0; .diptych { - background: var(--color-black); + background: black; color: var(--color-fog); overflow: hidden; // Clip off a 1px overflow beneath the video which appears at some screen widths align-items: stretch; diff --git a/website/sass/logo.scss b/website/sass/page/logo.scss similarity index 83% rename from website/sass/logo.scss rename to website/sass/page/logo.scss index e14baff8..b68ae2ab 100644 --- a/website/sass/logo.scss +++ b/website/sass/page/logo.scss @@ -2,16 +2,12 @@ display: flex; margin: 0 auto; - &.logo-view.logo-view { + + .logo-view.logo-view { margin-top: 0; - - &:first-of-type { - margin-top: 20px; - } } &.color { - background-color: var(--color-white); + background-color: white; background-blend-mode: hard-light; } @@ -54,8 +50,4 @@ } } } - - + h3 { - margin-top: 20px; - } } diff --git a/website/sass/volunteer.scss b/website/sass/page/volunteer.scss similarity index 100% rename from website/sass/volunteer.scss rename to website/sass/page/volunteer.scss diff --git a/website/sass/article.scss b/website/sass/template/article.scss similarity index 100% rename from website/sass/article.scss rename to website/sass/template/article.scss diff --git a/website/sass/book.scss b/website/sass/template/book.scss similarity index 100% rename from website/sass/book.scss rename to website/sass/template/book.scss diff --git a/website/static/js/youtube-embed.js b/website/static/js/youtube-embed.js index 9ce9ea9e..5ceea180 100644 --- a/website/static/js/youtube-embed.js +++ b/website/static/js/youtube-embed.js @@ -1,7 +1,7 @@ window.addEventListener("DOMContentLoaded", () => { - document.querySelectorAll("[data-video-embed]").forEach((placeholder) => { + document.querySelectorAll("[data-youtube-embed]").forEach((placeholder) => { placeholder.addEventListener("click", () => { - const videoId = placeholder.attributes["data-video-embed"].value; + const videoId = placeholder.attributes["data-youtube-embed"].value; placeholder.outerHTML = ``; }); }); diff --git a/website/templates/article.html b/website/templates/article.html index 21966bc1..78e49988 100644 --- a/website/templates/article.html +++ b/website/templates/article.html @@ -6,7 +6,7 @@ {%- set meta_image = page.extra.banner_png | safe -%} {%- set meta_article_type = true -%} {%- set meta_description = page.extra.summary | default(value = page.content | striptags | safe | linebreaksbr | replace(from = "
", to = " ") | replace(from = " ", to = " ") | trim | truncate(length = 200)) -%} -{%- set css = ["/article.css"] -%} +{%- set css = ["/template/article.css", "/layout/reading-material.css"] -%} {%- endblock head -%} {%- block content -%}{%- set page = page | default(value = section) -%} diff --git a/website/templates/base.html b/website/templates/base.html index 69b398ba..aa938452 100644 --- a/website/templates/base.html +++ b/website/templates/base.html @@ -32,9 +32,9 @@ {#- ON EVERY PAGE OF THE SITE: CSS AND JS TO LOAD EITHER AS A LINK OR INLINE -#} {#- ======================================================================== -#} - {%- set global_linked_css = ["/base.css", "https://fonts.googleapis.com/css2?family=Bona+Nova:wght@700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"] -%} + {%- set global_linked_css = ["https://fonts.googleapis.com/css2?family=Bona+Nova:wght@700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"] -%} {%- set global_linked_js = [] -%} - {%- set global_css = [] -%} + {%- set global_css = ["/base.css"] -%} {%- set global_js = ["/js/text-justification.js", "/js/navbar.js"] -%} {#- RETRIEVE FROM TEMPLATES AND PAGES: CSS AND JS TO LOAD EITHER AS A LINK OR INLINE -#} @@ -74,11 +74,13 @@ {#- INSERT INLINE CSS CODE -#} {#- ====================== -#} - {%- for path in css_list %} + {%- if css_list | length > 0 %} {{ "<" ~ "style>" | safe }} + {% for path in css_list -%} {{ load_data(path = path) | safe }} + {% endfor -%} {{ "" | safe }} - {%- endfor %} + {%- endif %} {#- INSERT INLINE JS CODE -#} {#- ===================== -#} diff --git a/website/templates/blog.html b/website/templates/blog.html index 438584a0..4581be35 100644 --- a/website/templates/blog.html +++ b/website/templates/blog.html @@ -3,7 +3,7 @@ {%- block head -%}{%- set page = page | default(value = section) -%} {%- set title = page.title -%} {%- set meta_title = "Graphite Blog" -%} -{%- set css = ["/blog.css"] -%} +{%- set css = ["/page/blog.css"] -%} {%- endblock head -%} {%- block content -%}{%- set page = page | default(value = section) -%} diff --git a/website/templates/book.html b/website/templates/book.html index b438ed7a..12c54c7e 100644 --- a/website/templates/book.html +++ b/website/templates/book.html @@ -5,7 +5,7 @@ {%- set meta_article_type = true -%} {%- set meta_description = page.extra.summary | default(value = page.content | striptags | safe | linebreaksbr | replace(from = "
", to = " ") | replace(from = " ", to = " ") | trim | truncate(length = 200)) -%} {%- set linked_css = ["/syntax-highlighting.css"] -%} -{%- set css = ["/book.css"] -%} +{%- set css = ["/template/book.css", "/layout/reading-material.css", "/component/code-snippet.css"] -%} {%- set js = ["/js/book.js"] -%} {%- endblock head -%}