mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Update the website layout with narrower default width and better typography (#1753)
- Reduces the default width from 1600px to 1200px of the web page and reduce the size of various elements and text. This fixes the problem that I designed the website assuming everyone is viewing from the same 2560px wide screen as I used to design it, which is a bad assumption. Most websites are around the 1200px mark. - Removes the use of the EB Garamond font, replacing more headers with a bold Inter instead, leaving only Bona Nova for h1 headers at the tops of pages (except the home page, which might have further revamp soon). - Adds nice flavor graphics to a redesigned volunteer page. - Cleans up and organizes the Zola templating code and CSS style sheets. - Improves image carousel to fade out images when dragged past the start or end.
This commit is contained in:
@@ -9,24 +9,40 @@ js = ["image-interaction.js", "video-embed.js"]
|
||||
|
||||
<!-- ▛ LOGO ▜ -->
|
||||
<section id="logo">
|
||||
<div class="block">
|
||||
<img src="https://static.graphite.rs/logos/graphite-logotype-color.svg" alt="Graphite Logo" />
|
||||
</div>
|
||||
</section>
|
||||
<!-- ▙ LOGO ▟ -->
|
||||
|
||||
<img class="pencil-texture" src="https://static.graphite.rs/textures/pencil-texture.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" />
|
||||
<!-- ▛ TAGLINE ▜ -->
|
||||
<section id="tagline">
|
||||
<div class="block">
|
||||
|
||||
<h1 class="balance-text">Redefining state‑of‑the‑art graphics editing</h1>
|
||||
|
||||
<p class="balance-text"><strong>Graphite</strong> is an in-development vector and raster graphics editor that's free and open source. It is powered by a node graph compositor that fuses layers with nodes and brings a unique procedural approach to your 2D design workflow.</p>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- ▙ TAGLINE ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▛ QUICK LINKS ▜ -->
|
||||
<section id="quick-links">
|
||||
<div>
|
||||
<a href="#community" class="button arrow">Subscribe to the newsletter</a>
|
||||
<a href="/donate" class="button arrow">♥ Support the mission</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://github.com/GraphiteEditor/Graphite" target="_blank">
|
||||
<div class="call-to-action-buttons">
|
||||
<a href="https://github.com/GraphiteEditor/Graphite" class="button github-stars">
|
||||
<img src="https://static.graphite.rs/icons/github.svg" alt="GitHub" />
|
||||
<span class="arrow">Star</span>
|
||||
<div data-github-stars></div>
|
||||
</a>
|
||||
<a href="#newsletter" class="button arrow">Subscribe to newsletter</a>
|
||||
</div>
|
||||
<div class="social-media-buttons">
|
||||
<a href="https://discord.graphite.rs" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/discord__2.svg" alt="Discord" />
|
||||
</a>
|
||||
<a href="https://www.reddit.com/r/graphite/" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/reddit.svg" alt="Reddit" />
|
||||
<img src="https://static.graphite.rs/icons/reddit__2.svg" alt="Reddit" />
|
||||
</a>
|
||||
<a href="https://twitter.com/graphiteeditor" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/twitter.svg" alt="Twitter" />
|
||||
@@ -34,23 +50,25 @@ js = ["image-interaction.js", "video-embed.js"]
|
||||
<a href="https://www.youtube.com/@GraphiteEditor" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/youtube.svg" alt="YouTube" />
|
||||
</a>
|
||||
<a href="https://discord.graphite.rs" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/discord.svg" alt="Discord" />
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<script>
|
||||
(async () => {
|
||||
const element = document.querySelector("[data-github-stars]");
|
||||
try {
|
||||
const response = await fetch("https://api.github.com/repos/graphiteeditor/graphite?per_page=1");
|
||||
const json = await response.json();
|
||||
const stars = parseInt(json.stargazers_count);
|
||||
if (!stars) throw new Error();
|
||||
let quantity = stars.toLocaleString("en-US");
|
||||
if (quantity.length === 5) quantity = quantity.replace(",", "");
|
||||
element.innerText = quantity;
|
||||
} catch {
|
||||
element.remove();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<!-- ▙ QUICK LINKS ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▛ TAGLINE ▜ -->
|
||||
<section id="tagline">
|
||||
|
||||
<h1 class="balance-text">Redefining state‑of‑the‑art graphics editing</h1>
|
||||
|
||||
<p class="balance-text"><strong>Graphite</strong> is an in-development raster and vector graphics package that's free and open source. It is powered by a node graph compositing engine that fuses layers with nodes, bringing a procedural approach to your design workflow.</p>
|
||||
<!-- <p class="balance-text"><strong>Graphite</strong> is an in-development raster and vector graphics package that's free and open source. It is powered by a node graph compositing engine that fuses layers with nodes, providing a fully nondestructive editing experience.</p> -->
|
||||
|
||||
</section>
|
||||
<!-- ▙ TAGLINE ▟ -->
|
||||
|
||||
<div class="hexagons">
|
||||
<div>
|
||||
@@ -66,27 +84,17 @@ js = ["image-interaction.js", "video-embed.js"]
|
||||
|
||||
<!-- ▛ SCREENSHOTS ▜ -->
|
||||
<section id="screenshots" class="carousel window-size-1" data-carousel data-carousel-jostle-hint>
|
||||
<div class="carousel-slide">
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-red-dress.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #1" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-valley-of-spires__4.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #2" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-procedural-string-lights.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #3" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-nodes__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #4" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-viewport__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #5" data-carousel-image />
|
||||
</div>
|
||||
<div class="carousel-slide torn left">
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-red-dress.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-valley-of-spires__4.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-procedural-string-lights.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-nodes__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-viewport__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
</div>
|
||||
<div class="carousel-slide torn right">
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-red-dress.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-valley-of-spires__4.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-procedural-string-lights.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-nodes__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-viewport__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<div class="carousel-slide" data-carousel-slide>
|
||||
<!-- Copy of last --><img src="https://static.graphite.rs/content/index/gui-mockup-viewport__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" style="transform: translateX(-100%)" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-red-dress.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #1" style="transform: translateX(-100%)" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-valley-of-spires__4.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #2" style="transform: translateX(-100%)" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-procedural-string-lights.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #3" style="transform: translateX(-100%)" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-nodes__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #4" style="transform: translateX(-100%)" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-viewport__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #5" style="transform: translateX(-100%)" data-carousel-image />
|
||||
<!-- Copy of first --><img src="https://static.graphite.rs/content/index/gui-demo-red-dress.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" style="transform: translateX(-100%)" data-carousel-image />
|
||||
</div>
|
||||
<div class="carousel-slide torn left" data-carousel-slide-torn-left></div>
|
||||
<div class="carousel-slide torn right" data-carousel-slide-torn-right></div>
|
||||
<div class="screenshot-details">
|
||||
<div class="carousel-controls">
|
||||
<button class="direction prev" data-carousel-prev>
|
||||
@@ -109,10 +117,10 @@ js = ["image-interaction.js", "video-embed.js"]
|
||||
</div>
|
||||
<div class="screenshot-description">
|
||||
<p class="active" data-carousel-description>
|
||||
<a href="https://editor.graphite.rs/#demo/red-dress"><em>Red Dress</em></a> — Illustration made with the help of procedurally generating hundreds of circles in the node graph.
|
||||
<a href="https://editor.graphite.rs/#demo/red-dress"><em>Red Dress</em></a> — Illustration made with the help of procedurally placing hundreds of circles.
|
||||
</p>
|
||||
<p data-carousel-description>
|
||||
<a href="https://editor.graphite.rs/#demo/valley-of-spires"><em>Valley of Spires</em></a> — Vector art made with the Pen and Gradient tools without needing to touch the node graph.
|
||||
<a href="https://editor.graphite.rs/#demo/valley-of-spires"><em>Valley of Spires</em></a> — Vector art made with the Pen and Gradient tools without touching the node graph.
|
||||
</p>
|
||||
<p data-carousel-description>
|
||||
<a href="https://editor.graphite.rs/#demo/procedural-string-lights"><em>Procedural String Lights</em></a> — Drawing of a tree adorned by reusable, auto-placed light bulbs along the wire path made using this node graph.
|
||||
@@ -133,55 +141,56 @@ js = ["image-interaction.js", "video-embed.js"]
|
||||
<section id="today-and-tomorrow">
|
||||
<div class="diptych">
|
||||
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Graphite today <span class="status-flag">alpha release</span>
|
||||
# Graphite today <span class="status-flag">public alpha</span>
|
||||
|
||||
<div class="informational-group features">
|
||||
<div class="informational">
|
||||
<div class="feature-icons">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 0" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Vector graphics editing</span>
|
||||
<span>Vector art editing</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 8" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Node-based layers</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<!-- TODO: Reenable when Imaginate is properly working again -->
|
||||
<!-- <img class="atlas" style="--atlas-index: 2" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" /> -->
|
||||
<!-- <span>AI-assisted art creation</span> -->
|
||||
<img class="atlas" style="--atlas-index: 10" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Procedural design workflow</span>
|
||||
<span>Procedural graphic design workflow</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 3" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Open source and free forever</span>
|
||||
<span>Forever free and open source</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Graphite is a lightweight vector graphics editor that runs offline in your browser (no sign up required) and offers the unique feature of a node-driven procedural vector workflow.
|
||||
<!-- Presently, Graphite is a lightweight vector graphics editor that runs offline in your browser (no sign up or download required). -->
|
||||
Presently, Graphite is a lightweight offline web app with features primarily oriented around procedural vector graphics editing.
|
||||
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Graphite tomorrow
|
||||
|
||||
<div class="informational-group features">
|
||||
<div class="informational">
|
||||
<div class="feature-icons">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 4" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>All-in-one creative tools for animation, art, and design</span>
|
||||
<span>All-in-one creative tool for all things 2D</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 5" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Clean, familiar interface built by designers, for designers</span>
|
||||
<span>Clean, familiar, designer-centric UI</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 7" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Multiplatform desktop app</span>
|
||||
<span>Multiplatform app for desktop + iPad</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 6" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Real-time collaborative editing</span>
|
||||
<span>Live collaborative editing</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -195,34 +204,34 @@ Graphite is a lightweight vector graphics editor that runs offline in your brows
|
||||
<!-- -->
|
||||
<!-- ▛ DISCIPLINES ▜ -->
|
||||
<section id="disciplines">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# One app to rule them all
|
||||
|
||||
**Stop jumping between programs. Planned features will make Graphite a first-class design tool for all these disciplines** *(listed by priority)*.
|
||||
**Stop jumping between programs. Planned features will make Graphite a first-class design tool for all these disciplines.** <small>*(Listed by priority.)*</small>
|
||||
|
||||
<div class="informational-group concepts">
|
||||
<div class="informational">
|
||||
<div class="feature-icons stacked no-background">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 12" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Graphic Design</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 13" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Image Editing</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 17" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Motion Graphics</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 14" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Digital Painting</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 16" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>VFX Compositing</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 15" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Desktop Publishing</span>
|
||||
</div>
|
||||
@@ -232,83 +241,78 @@ Graphite is a lightweight vector graphics editor that runs offline in your brows
|
||||
</section>
|
||||
<!-- ▙ DISCIPLINES ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▛ COMMUNITY ▜ -->
|
||||
<section id="community" class="feature-box">
|
||||
<div class="box">
|
||||
<!-- ▛ NEWSLETTER ▜ -->
|
||||
<section id="newsletter" class="feature-box-outer">
|
||||
<div id="newsletter-success"><!-- Used only as a URL hash fragment anchor --></div>
|
||||
<div class="feature-box-inner">
|
||||
|
||||
<h1 class="feature-box-header">Stay in the loop</h1>
|
||||
|
||||
---
|
||||
|
||||
<div class="diptych">
|
||||
|
||||
<div id="newsletter" class="section">
|
||||
<div class="block newsletter-signup">
|
||||
|
||||
# Stay in the loop
|
||||
**Subscribe to the newsletter** for quarterly updates on major development progress. And follow along—or join the conversation—on social media.
|
||||
|
||||
Subscribe to the newsletter for quarterly updates on major development progress.
|
||||
|
||||
<div id="newsletter-success">
|
||||
<div class="newsletter-success">
|
||||
|
||||
## Thanks!
|
||||
|
||||
You'll receive your first newsletter email with the next major Graphite news.
|
||||
|
||||
</div>
|
||||
|
||||
<form action="https://graphite.rs/newsletter-signup" method="post">
|
||||
<div class="same-line">
|
||||
<div class="column name">
|
||||
<div class="input-column name">
|
||||
<label for="newsletter-name">First + last name:</label>
|
||||
<input id="newsletter-name" name="name" type="text" required />
|
||||
</div>
|
||||
<div class="column phone">
|
||||
<div class="input-column phone">
|
||||
<label for="newsletter-phone">Phone:</label>
|
||||
<input id="newsletter-phone" name="phone" type="text" tabindex="-1" autocomplete="off" />
|
||||
</div>
|
||||
<div class="column email">
|
||||
<div class="input-column email">
|
||||
<label for="newsletter-email">Email address:</label>
|
||||
<input id="newsletter-email" name="email" type="email" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="column submit">
|
||||
<div class="input-column submit">
|
||||
<input type="submit" value="Subscribe" class="button" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div id="social" class="section">
|
||||
<div class="block social-media-links">
|
||||
|
||||
# Follow along
|
||||
|
||||
<div class="social-links">
|
||||
<div class="column">
|
||||
<a href="https://discord.graphite.rs" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/discord.svg" alt="Discord" />
|
||||
<span class="link arrow">Join on Discord</span>
|
||||
</a>
|
||||
<a href="https://www.reddit.com/r/graphite/" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/reddit.svg" alt="Reddit" />
|
||||
<span class="link not-uppercase arrow">/r/Graphite</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="column">
|
||||
<a href="https://github.com/GraphiteEditor/Graphite" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/github.svg" alt="GitHub" />
|
||||
<span class="link arrow">Star on GitHub</span>
|
||||
</a>
|
||||
<a href="https://twitter.com/graphiteeditor" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/twitter.svg" alt="Twitter" />
|
||||
<span class="link not-uppercase arrow">@GraphiteEditor</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://discord.graphite.rs" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/discord__2.svg" alt="Discord" />
|
||||
<span class="link not-uppercase arrow">Discord</span>
|
||||
</a>
|
||||
<a href="https://www.reddit.com/r/graphite/" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/reddit__2.svg" alt="Reddit" />
|
||||
<span class="link not-uppercase arrow">/r/Graphite</span>
|
||||
</a>
|
||||
<a href="https://twitter.com/graphiteeditor" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/twitter.svg" alt="Twitter" />
|
||||
<span class="link not-uppercase arrow">@GraphiteEditor</span>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@GraphiteEditor" target="_blank">
|
||||
<img src="https://static.graphite.rs/icons/youtube.svg" alt="YouTube" />
|
||||
<span class="link not-uppercase arrow">YouTube</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- ▙ COMMUNITY ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▙ NEWSLETTER ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▛ JUMP RIGHT IN ▜ -->
|
||||
<!-- <section id="jump-right-in">
|
||||
<div class="section"> -->
|
||||
<div class="block"> -->
|
||||
|
||||
<!-- # Jump right in -->
|
||||
|
||||
@@ -324,21 +328,19 @@ You'll receive your first newsletter email with the next major Graphite news.
|
||||
<!-- -->
|
||||
<!-- ▛ PROCEDURALISM ▜ -->
|
||||
<section id="proceduralism">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Powerful proceduralism
|
||||
|
||||
**Graphite is the first and only graphic design app to offer procedural vector editing.**
|
||||
|
||||
This new capability has just recently shown its potential. Now, expanding Graphite's procedural powers is the focus of development in 2024.
|
||||
**Graphite is the first and only graphic design package to offer procedural vector editing.**
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="proceduralism-demo">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
Proceduralism lets you create sophisticated design elements that are easy to edit and reuse. The holiday string lights shown below are built from a simple group of nodes, allowing you to effortlessly reshape the wire and update the bulb appearance and spacing. <a href="https://editor.graphite.rs/#demo/procedural-string-lights">Click here to explore this demo</a> and try dragging the wire layer's points with the Path tool (<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" style="vertical-align: middle"><polygon fill="#aaa" points="5,0 5,17 10,12 17,12" /><path fill="#78bae5" d="M20.77,14.36c-0.35-0.42-0.98-0.48-1.41-0.13c-1.04,0.87-2.19,1.6-3.36,2.24V16h-6v2.9c-2.88,0.84-5.07,1.1-5.11,1.11c-0.55,0.06-0.94,0.56-0.88,1.11C4.06,21.62,4.5,22,5,22c0.04,0,0.07,0,0.11-0.01c0.17-0.02,2.18-0.26,4.89-1.01V22h6v-3.28c1.6-0.79,3.2-1.75,4.64-2.95C21.06,15.42,21.12,14.78,20.77,14.36z M14,20h-2v-2h2V20z" /></svg>).
|
||||
Proceduralism lets you create sophisticated design elements that are easy to edit and reuse. The holiday string lights shown below are built from a simple group of nodes, allowing you to effortlessly reshape the wire and update the bulb appearance and spacing. <a href="https://editor.graphite.rs/#demo/procedural-string-lights">Click here to explore this demo</a> and try dragging the wire layer's points with the Path tool <span style="white-space: nowrap">(<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" style="vertical-align: middle"><polygon fill="#aaa" points="5,0 5,17 10,12 17,12" /><path fill="#78bae5" d="M20.77,14.36c-0.35-0.42-0.98-0.48-1.41-0.13c-1.04,0.87-2.19,1.6-3.36,2.24V16h-6v2.9c-2.88,0.84-5.07,1.1-5.11,1.11c-0.55,0.06-0.94,0.56-0.88,1.11C4.06,21.62,4.5,22,5,22c0.04,0,0.07,0,0.11-0.01c0.17-0.02,2.18-0.26,4.89-1.01V22h6v-3.28c1.6-0.79,3.2-1.75,4.64-2.95C21.06,15.42,21.12,14.78,20.77,14.36z M14,20h-2v-2h2V20z" /></svg>).</span>
|
||||
|
||||
<div class="video-background">
|
||||
<video loop muted playsinline disablepictureinpicture disableremoteplayback data-auto-play>
|
||||
@@ -365,25 +367,24 @@ Proceduralism lets you create sophisticated design elements that are easy to edi
|
||||
</section>
|
||||
|
||||
<section id="proceduralism-features">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
Graphite's procedural, data-driven approach to graphic design affords unique capabilities *(while in alpha, these remain a work in progress)*:
|
||||
|
||||
<div class="informational-group features four-wide">
|
||||
<div class="informational">
|
||||
<div class="feature-icons four-wide">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 1" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span class="balance-text">Fully nondestructive editing with node-driven layers</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 9" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span class="balance-text">Infinitely scalable raster content with no pixelation</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<!-- <img class="atlas" style="--atlas-index: 10" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" /> -->
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 2" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span class="balance-text">Versatile modularity of node-based generative AI models</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 11" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span class="balance-text">Procedural pipelines for studio production environments</span>
|
||||
</div>
|
||||
@@ -392,53 +393,33 @@ Graphite's procedural, data-driven approach to graphic design affords unique cap
|
||||
</div>
|
||||
</section>
|
||||
<!-- ▙ PROCEDURALISM ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▛ FUNDRAISING ▜ -->
|
||||
<section id="fundraising" class="feature-box">
|
||||
<div class="box">
|
||||
<div>
|
||||
<!-- -->
|
||||
<!-- ▛ DONATE ▜ -->
|
||||
<section id="donate" class="feature-box-outer">
|
||||
<div class="feature-box-inner">
|
||||
|
||||
<div class="section">
|
||||
<h1 class="feature-box-header">Support the mission</h1>
|
||||
|
||||
# Support the mission
|
||||
---
|
||||
|
||||
<div class="block">
|
||||
|
||||
<p class="balance-text">
|
||||
You can help realize Graphite's ambitious vision of building the ultimate 2D creative tool.
|
||||
Graphite is built by a small, dedicated crew of volunteers in need of resources to grow.
|
||||
Graphite is built by a small, dedicated crew of volunteers in need of the resources to grow.
|
||||
</p>
|
||||
|
||||
<!-- [Re-include the import for `"fundraising.js"` when re-enabling this.]
|
||||
|
||||
### Summer 2023 fundraising goal:
|
||||
|
||||
<div class="fundraising loading" data-fundraising>
|
||||
<div class="fundraising-bar" data-fundraising-bar style="--fundraising-percent: 0%">
|
||||
<div class="fundraising-bar-progress"></div>
|
||||
</div>
|
||||
<div class="goal-metrics">
|
||||
<span data-fundraising-percent>Progress: <span data-dynamic>0</span>%</span>
|
||||
<span data-fundraising-goal>Goal: $<span data-dynamic>0</span>/month</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
[Become a monthly supporter](https://github.com/sponsors/GraphiteEditor) this summer to collect an exclusive 💚 badge. Each season you support, a new heart design is yours to keep. In the future, they'll be shown on Graphite account profiles and community areas like forums and in-app collaboration. -->
|
||||
|
||||
<a href="https://github.com/sponsors/GraphiteEditor" class="button arrow">Donate</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- <div class="graphic">
|
||||
<a href="https://github.com/sponsors/GraphiteEditor"><img src="https://files.keavon.com/-/OtherDroopyBoto/Spring_Heart.png" /></a>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- ▙ FUNDRAISING ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▙ DONATE ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▛ VECTOR ART ▜ -->
|
||||
<section id="vector-art">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Taking shape
|
||||
|
||||
@@ -484,7 +465,7 @@ Style shapes with strokes, fills, and gradients. Mix layers with blend modes. Th
|
||||
|
||||
<section id="imaginate">
|
||||
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
<h1><span class="alternating-text"><span>Co-create</span><span>Ideate</span><span>Illustrate</span><span>Generate</span><span>Iterate</span></span> with Imaginate</h1>
|
||||
|
||||
@@ -494,7 +475,7 @@ Style shapes with strokes, fills, and gradients. Mix layers with blend modes. Th
|
||||
</div>
|
||||
<div class="diptych">
|
||||
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
<h2 class="balance-text">Add a touch of style</h2>
|
||||
|
||||
@@ -523,7 +504,7 @@ Style shapes with strokes, fills, and gradients. Mix layers with blend modes. Th
|
||||
<blockquote class="balance-text require-polyfill"><strong>Watercolor painting</strong> of a light bulb gleaming with an exclamation mark inside</blockquote>
|
||||
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Work fast and sloppy
|
||||
|
||||
@@ -563,7 +544,7 @@ Style shapes with strokes, fills, and gradients. Mix layers with blend modes. Th
|
||||
<!-- -->
|
||||
<!-- ▛ DEMO VIDEO ▜ -->
|
||||
<section id="demo-video">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
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).
|
||||
|
||||
@@ -576,26 +557,19 @@ Watch this timelapse showing the process of mixing traditional vector art (traci
|
||||
</div>
|
||||
</section>
|
||||
<!-- ▙ DEMO VIDEO ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▛ GET INVOLVED ▜ -->
|
||||
<section id="get-involved-box" class="feature-box">
|
||||
<div class="box">
|
||||
<!-- -->
|
||||
<!-- ▛ RECENT NEWS ▜ -->
|
||||
<section id="recent-news" class="feature-box-outer">
|
||||
<div class="feature-box-inner">
|
||||
|
||||
<h1 class="feature-box-header">Recent news <span> / </span> <a href="/blog" class="link arrow">More in the blog</a></h1>
|
||||
|
||||
---
|
||||
|
||||
<div class="diptych">
|
||||
|
||||
<div class="section">
|
||||
|
||||
# Get involved
|
||||
|
||||
<p class="balance-text">The Graphite project could not exist without its community. Building its ambitious and versatile feature set will require contributions from artists, designers, developers, technical experts, and eagle-eyed bug hunters. Help build the future of digital art.</p>
|
||||
|
||||
<a href="/volunteer" class="button arrow">Volunteer</a>
|
||||
|
||||
</div>
|
||||
<div class="graphic">
|
||||
<img src="https://static.graphite.rs/content/index/volunteer.svg" alt="" />
|
||||
<!-- replacements::blog_posts(count = 2) -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- ▙ GET INVOLVED ▟ -->
|
||||
<!-- ▙ RECENT NEWS ▟ -->
|
||||
|
||||
@@ -6,17 +6,17 @@ css = ["about.css"]
|
||||
+++
|
||||
|
||||
<section>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# About Graphite
|
||||
|
||||
Graphite is a community-built, open source software project that is free to use for any purpose. If you find Graphite valuable, consider [supporting financially](/donate) or [getting involved](/volunteer).
|
||||
Graphite is a community-built free software project. If you find it valuable, consider [donating](/donate) or [getting involved](/volunteer) to keep it sustainable.
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Project
|
||||
|
||||
@@ -29,7 +29,7 @@ The idea for Graphite began with a desire to create artwork and edit photos usin
|
||||
|
||||
<div class="diptych">
|
||||
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Mission
|
||||
|
||||
@@ -38,11 +38,13 @@ Graphite strives to unshackle the creativity of every budding artist and seasone
|
||||
Mission success will come when Graphite is an industry standard. A cohesive product vision and focus on innovation over imitation is the strategy that will make that possible.
|
||||
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Commitment
|
||||
## Funding
|
||||
|
||||
As an independent community-driven software project, Graphite will always remain free. It has no investors to answer to. Its founder keeps costs low and relies on [your support](/donate) while he works full-time bringing Graphite to life. To sustainably grow, the long-term funding model will pair donations with paid accounts that provide optional online services like document storage/syncing and render acceleration via cloud GPUs.
|
||||
Graphite has no investors to answer to and will always be free and open source. [Keavon](#keavon), the project founder, has been personally funding all expenses out-of-pocket and turning down a tech industry salary to work full-time bringing Graphite to life. He asks for [your support](/donate) bearing a small fraction of that cost.
|
||||
|
||||
Long-term, donations will be supplemented by revenue from cloud storage/sync and multi-GPU render acceleration services.
|
||||
|
||||
</div>
|
||||
|
||||
@@ -50,8 +52,6 @@ As an independent community-driven software project, Graphite will always remain
|
||||
|
||||
</section>
|
||||
|
||||
<!-- A batteries-included creative app for every kind of digital artist where -->
|
||||
|
||||
<!-- ## Statistics
|
||||
|
||||
- [GitHub stars](https://github.com/GraphiteEditor/Graphite/stargazers): <span class="loading-data" data-github-stars></span>
|
||||
@@ -91,7 +91,7 @@ As an independent community-driven software project, Graphite will always remain
|
||||
</script> -->
|
||||
|
||||
<!-- <section id="opener-message">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## A 2D creative tool made for everyone
|
||||
|
||||
@@ -107,56 +107,50 @@ It's easy to learn and teach, yet Graphite's accessible design does not sacrific
|
||||
</div>
|
||||
</section> -->
|
||||
|
||||
<section id="core-team" class="feature-box">
|
||||
<div class="box">
|
||||
<section id="core-team" class="feature-box-outer">
|
||||
<div class="feature-box-inner">
|
||||
|
||||
<h1 class="box-header">Meet the core team</h1>
|
||||
<h1 class="feature-box-header">Meet the core team</h1>
|
||||
|
||||
---
|
||||
|
||||
<div class="triptych">
|
||||
|
||||
<div class="section" id="keavon">
|
||||
<div class="block" id="keavon">
|
||||
|
||||
<img src="https://static.graphite.rs/content/about/core-team-photo-keavon-chambers.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Photo of Keavon Chambers" />
|
||||
|
||||
## Keavon Chambers <span class="flag" title="American">🇺🇸</span>
|
||||
## Keavon Chambers
|
||||
|
||||
*@Keavon*
|
||||
*@Keavon* <span class="flag" title="American">🇺🇸</span>
|
||||
|
||||
### Founder
|
||||
*Founder, UI & product design, frontend engineering*
|
||||
|
||||
*UI & product design, frontend engineering*
|
||||
|
||||
Keavon is a creative generalist with a love for the fusion of arts and technology. Photographer, UX and graphic designer, technical artist, game developer, and everything in-between— he is equal parts designer and engineer. His multidisciplinary background in the digital arts is aptly suited for concocting the unique vision needed to bring Graphite to fruition.
|
||||
Keavon is a creative generalist with a love for the fusion of arts and technology. UX and graphic designer, photographer, game developer, technical artist, and everything in between— he is equal parts designer and engineer. His multidisciplinary background in the digital arts is aptly suited for concocting the unique vision needed to bring Graphite to fruition.
|
||||
|
||||
</div>
|
||||
<div class="section" id="dennis">
|
||||
<div class="block" id="dennis">
|
||||
|
||||
<img src="https://static.graphite.rs/content/about/core-team-photo-dennis-kobert.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Photo of Dennis Kobert" />
|
||||
|
||||
## Dennis Kobert <span class="flag" title="German">🇩🇪</span>
|
||||
## Dennis Kobert
|
||||
|
||||
*@TrueDoctor*
|
||||
|
||||
### Lead Engineer
|
||||
*@TrueDoctor* <span class="flag" title="German">🇩🇪</span>
|
||||
|
||||
*Graphene node engine, research, architecture*
|
||||
|
||||
Dennis is a mix between a mathematician and a mad scientist. While still enjoying the art of photography and image editing (which drew him to the project early on), he thrives when challenged with designing complex systems and pushing boundaries. His method of building generalized solutions wrapped in elegant layers of abstraction led to his creation of the Graphene engine.
|
||||
|
||||
</div>
|
||||
<div class="section" id="hypercube">
|
||||
<div class="block" id="hypercube">
|
||||
|
||||
<img src="https://static.graphite.rs/content/about/core-team-photo-hypercube.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Photo of Hypercube" />
|
||||
|
||||
## "Hypercube" <span class="flag" title="British">🇬🇧</span>
|
||||
## "Hypercube"
|
||||
|
||||
*@0Hypercube*
|
||||
*@0Hypercube* <span class="flag" title="British">🇬🇧</span>
|
||||
|
||||
### Software Engineer
|
||||
|
||||
*Editor systems, nodes, architecture*
|
||||
*Editor systems, nodes, tools, architecture*
|
||||
|
||||
"Hypercube" is a light speed code monkey who excels at developing, refactoring, and maintaining the editor code base. With an unmatched ability to comprehend intricate code, he delivers lasting and efficient solutions at an impressive pace. He takes ownership of many central editor systems including tools, typography, transforms, layers, and node graph integration.
|
||||
|
||||
@@ -172,25 +166,25 @@ Dennis is a mix between a mathematician and a mad scientist. While still enjoyin
|
||||
|
||||
<div class="triptych">
|
||||
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Credits
|
||||
|
||||
In addition to the work of the Core Team listed above, dozens of contributors have written code that makes Graphite what it is today:
|
||||
In addition to the work of the Core Team listed above, over a hundred other contributors have written code that makes Graphite what it is today:
|
||||
|
||||
<a href="https://github.com/GraphiteEditor/Graphite/graphs/contributors" class="button arrow">Credits</a>
|
||||
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## License
|
||||
|
||||
The Graphite editor and source code are provided under the Apache License 2.0 terms. See below for details and exclusions:
|
||||
The Graphite editor source code is published under the terms of the Apache License 2.0. See below for details and exclusions:
|
||||
|
||||
<a href="/license" class="button arrow">License</a>
|
||||
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Logo
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ twitter = "https://twitter.com/GraphiteEditor/status/1788698448348266946"
|
||||
|
||||
<!-- more -->
|
||||
|
||||
Starting in 2024, we are now publishing quarterly reports to summarize the new features and improvements made to Graphite. If you missed the [2023 year in review](../looking-back-on-2023-and-what-s-next), be sure to check it out after this. We anticipate sending our first email newsletter (with more to follow roughly quarterly) in the near future as well, so be sure to [subscribe](/#community) if you haven't already.
|
||||
Starting in 2024, we are now publishing quarterly reports to summarize the new features and improvements made to Graphite. If you missed the [2023 year in review](../looking-back-on-2023-and-what-s-next), be sure to check it out after this. We anticipate sending our first email newsletter (with more to follow roughly quarterly) in the near future as well, so be sure to [subscribe](/#newsletter) if you haven't already.
|
||||
|
||||
Over the first three months of the year, we are delighted to have seen many contributions both from new and recurrent contributors, including substantial interest by students through [Google Summer of Code](/blog/graphite-internships-announcing-participation-in-gsoc-2024/). We would like to send a big thanks to all of the contributors who made this progress happen. If you are interested in getting involved or just following development, see the [contributor guide](/volunteer/guide) and join [our Discord](https://discord.graphite.rs).
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ generate_feed = true
|
||||
+++
|
||||
|
||||
<section id="intro">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Blog
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title = "Contact the team"
|
||||
+++
|
||||
|
||||
<section class="reading-material">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Contact the team
|
||||
|
||||
@@ -12,7 +12,7 @@ title = "Contact the team"
|
||||
- Members of the press, please see the [press resources](/press) page.
|
||||
- For general discussions, reach out on [Discord](https://discord.graphite.rs) or [Reddit](https://www.reddit.com/r/graphite/).
|
||||
- To report a bug or request a feature, please [file an issue](https://github.com/GraphiteEditor/Graphite/issues/new) on GitHub.
|
||||
- For other inquiries, get in touch by email at <contact@graphite.rs>.
|
||||
- For other inquiries, get in touch by email at [contact<wbr>@graphite<wbr>.rs](mailto:contact@graphite.rs).
|
||||
|
||||
</article>
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
title = "Donate"
|
||||
|
||||
[extra]
|
||||
css = ["donate.css"]
|
||||
# css = ["donate.css"]
|
||||
# js = ["fundraising.js"]
|
||||
+++
|
||||
|
||||
<section>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Donate
|
||||
|
||||
@@ -24,11 +24,11 @@ Your monthly support (or one-off contribution) helps provide the resources neede
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- <section id="fundraising" class="feature-box">
|
||||
<div class="box">
|
||||
<!-- <section id="fundraising" class="feature-box-outer">
|
||||
<div class="feature-box-inner">
|
||||
<div>
|
||||
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Support the mission
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ css = ["features.css"]
|
||||
+++
|
||||
|
||||
<section>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Graphite features
|
||||
|
||||
@@ -21,9 +21,9 @@ Stay tuned for major performance uplifts, a multiplatform native desktop app, an
|
||||
|
||||
<div class="diptych">
|
||||
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Layers & nodes: hybrid compositing
|
||||
## Layers & nodes: hybrid editing
|
||||
|
||||
Graphite combines the best ideas from multiple categories of digital content creation software to redefine the workflows of 2D graphics editing. It is influenced by the core editing experience of traditional layer-based raster and vector apps, the nondestructive approaches of VFX compositing programs used by film studios, and the boundless creative possibilities of procedural production tools daily-driven by the 3D industry.
|
||||
|
||||
@@ -32,17 +32,17 @@ Classic layer-based image editing is easy to understand, with collapsable folder
|
||||
The hybrid workflow of Graphite offers a classic tool-centric, layer-based editing experience built around a procedural, node-based compositor. Users can ignore the node graph, use it exclusively, or switch back and forth with the press of a button while creating content. Interacting with the canvas using tools will manipulate the nodes behind the scenes. And the layer panel and node graph provide two equivalent, interchangeable views of the same document structure.
|
||||
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Raster & vector: sharp at all sizes <span class="status-flag">not fully implemented yet</span>
|
||||
## Raster & vector: sharp at all sizes
|
||||
|
||||
Digital 2D art commonly takes two forms. Raster artwork is made out of pixels which means it can look like anything imaginable, but it becomes blurry or pixelated when upscaling to a higher resolution. Vector artwork is made out of curved shapes which is perfect for some art styles but limiting to others. The magic of vector is that its mathematically-described curves can be enlarged to any size and remain crisp.
|
||||
|
||||
Other apps usually focus on just raster or vector, forcing artists to buy and learn both products. Mixing art styles requires shuttling content back and forth between programs. And since picking a raster document resolution is a one-time deal, artists may choose to start really big, resulting in sluggish editing performance and multi-gigabyte documents.
|
||||
Other apps usually focus on just raster or vector, forcing artists to buy and learn both products. Mixing art styles requires shuttling content back and forth between programs. And since picking a raster document resolution is a one-time deal, artists often choose to start really big, resulting in sluggish editing performance and multi-gigabyte documents.
|
||||
|
||||
Graphite reinvents raster rendering so it stays sharp at any scale. Artwork is treated as data, not pixels, and is always redrawn at the current viewing resolution. Zoom the viewport and export images at any size— the document's paint brushes, masks, filters, and effects will all be rendered at the native resolution.
|
||||
Graphite reinvents raster rendering so it stays sharp at any scale. Artwork is treated as data, not pixels, and is always redrawn at the current viewing resolution. Zoom the viewport and export images at any size— the document's paint brushes, masks, filters, and effects will all be rendered at the current native resolution.
|
||||
|
||||
Marrying vector and raster under one roof enables both art forms to complement each other in a cohesive content creation workflow.
|
||||
Marrying vector and raster under one roof enables both art forms to complement each other in a cohesive content creation workflow. *(Scalable raster compositing is still in-development.)*
|
||||
|
||||
</div>
|
||||
|
||||
@@ -54,7 +54,7 @@ Marrying vector and raster under one roof enables both art forms to complement e
|
||||
|
||||
<div class="diptych">
|
||||
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Powered by Graphene
|
||||
|
||||
@@ -63,7 +63,7 @@ Marrying vector and raster under one roof enables both art forms to complement e
|
||||
<!-- Rust programmers may find the following technical details to be of interest. Graphene node graphs are programs built out of reusable Rust functions using Graphite as a visual "code" editor. New nodes and data types can be implemented by writing custom Rust code with a built-in text editor. `no_std` code also gets compiled to GPU compute shaders using [`rust-gpu`](https://github.com/EmbarkStudios/rust-gpu). Each node is independently pre-compiled by `rustc` into portable WASM binaries and linked at runtime. Groups of nodes may be compiled into one unit of execution, utilizing Rust's zero-cost abstractions and optimizations to run with less overhead. And whole node graphs can be compiled into standalone executables for use outside Graphite. -->
|
||||
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
<!-- ## Proudly written in Rust -->
|
||||
## Written in Rust
|
||||
@@ -79,265 +79,265 @@ Always on the bleeding edge and built to last— Graphite is written on a robust
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
## Roadmap
|
||||
|
||||
<div class="roadmap">
|
||||
<div class="informational-group features">
|
||||
<div class="feature-icons">
|
||||
<!-- Pre-Alpha -->
|
||||
<div class="informational complete heading" title="Began February 2021" data-year="2021">
|
||||
<div class="feature-icon complete heading" title="Began February 2021" data-year="2021">
|
||||
<h3>— Pre-Alpha —</h3>
|
||||
</div>
|
||||
<div class="informational complete" title="Development Complete">
|
||||
<div class="feature-icon complete" title="Development Complete">
|
||||
<img class="atlas" style="--atlas-index: 1" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Editor systems; basic vector art tools</span>
|
||||
</div>
|
||||
<!-- Alpha 1 -->
|
||||
<div class="informational complete heading" title="Began February 2022" data-year="2022">
|
||||
<div class="feature-icon complete heading" title="Began February 2022" data-year="2022">
|
||||
<h3>— Alpha 1 —</h3>
|
||||
</div>
|
||||
<div class="informational complete" title="Development Complete">
|
||||
<div class="feature-icon complete" title="Development Complete">
|
||||
<img class="atlas" style="--atlas-index: 2" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Better tools; node graph prototyping</span>
|
||||
</div>
|
||||
<!-- Alpha 2 -->
|
||||
<div class="informational complete heading" title="Began February 2023" data-year="2023">
|
||||
<div class="feature-icon complete heading" title="Began February 2023" data-year="2023">
|
||||
<h3>— Alpha 2 —</h3>
|
||||
</div>
|
||||
<div class="informational complete" title="Development Complete">
|
||||
<div class="feature-icon complete" title="Development Complete">
|
||||
<img class="atlas" style="--atlas-index: 6" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Fully node graph-driven documents</span>
|
||||
</div>
|
||||
<!-- Alpha 3 -->
|
||||
<div class="informational ongoing heading" title="Began February 2024" data-year="2024">
|
||||
<div class="feature-icon ongoing heading" title="Began February 2024" data-year="2024">
|
||||
<h3>— Alpha 3 —</h3>
|
||||
</div>
|
||||
<div class="informational complete" title="Development Complete">
|
||||
<div class="feature-icon complete" title="Development Complete">
|
||||
<img class="atlas" style="--atlas-index: 3" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Stackable adjustment layers</span>
|
||||
</div>
|
||||
<div class="informational ongoing" title="Development Ongoing">
|
||||
<div class="feature-icon ongoing" title="Development Ongoing">
|
||||
<img class="atlas" style="--atlas-index: 10" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Procedurally alterable vector data</span>
|
||||
</div>
|
||||
<div class="informational ongoing" title="Development Ongoing">
|
||||
<div class="feature-icon ongoing" title="Development Ongoing">
|
||||
<img class="atlas" style="--atlas-index: 0" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Imaginate (Stable Diffusion node/tool)</span>
|
||||
</div>
|
||||
<div class="informational ongoing" title="Development Ongoing">
|
||||
<div class="feature-icon ongoing" title="Development Ongoing">
|
||||
<img class="atlas" style="--atlas-index: 8" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Editable nested node subgraphs</span>
|
||||
</div>
|
||||
<div class="informational ongoing" title="Development Ongoing">
|
||||
<div class="feature-icon ongoing" title="Development Ongoing">
|
||||
<img class="atlas" style="--atlas-index: 7" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Native desktop app (with <a target="_blank" href="https://tauri.app/">Tauri</a>)</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 51" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Boolean operations for shapes</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 12" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>WebGPU accelerated rendering</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 14" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Adaptive resolution raster rendering</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 26" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Interactive graph auto-layout</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 19" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Imported RAW photo processing</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 49" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>AI nodes and tools (e.g. magic wand)</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 13" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>New vector 2D renderer (with <a target="_blank" href="https://github.com/linebender/vello">Vello</a>)</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 5" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Fully-supported brush tool</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 41" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Timeline with animation channels</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 9" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Graph data attribute spreadsheet</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 54" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Local file browser for saving/loading</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 53" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Local fonts access</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 17" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Stable document format</span>
|
||||
</div>
|
||||
<!-- Alpha 4 -->
|
||||
<div class="informational heading" title="Expected to begin February 2025" data-year="2025">
|
||||
<div class="feature-icon heading" title="Expected to begin February 2025" data-year="2025">
|
||||
<h3>— Alpha 4 —</h3>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 21" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Select mode (marquee masking)</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 52" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Command palette and context menus</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 4" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Outliner panel (node graph tree view)</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 56" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Variable color swatches</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 48" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Mesh vector format</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 50" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Shape builder tool</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 28" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Guide mode (construction geometry)</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 29" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>CAD-like constraint relationships</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 15" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Hosted compile/render server</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 16" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Code editor for custom nodes</span>
|
||||
</div>
|
||||
<!-- Beta -->
|
||||
<div class="informational heading">
|
||||
<div class="feature-icon heading">
|
||||
<h3>— Beta —</h3>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 18" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Document history management</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 23" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Internationalization and accessibility</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 22" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Frozen-in-time graph references</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 25" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Liquify and non-affine rendering</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 24" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Reconfigurable workspace panels</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 27" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Automation and batch processing</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 33" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>HDR and WCG color handling</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 55" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>CMYK and other color spaces</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 34" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Node manager and marketplace</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 45" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Portable, embeddable render engine</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 35" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Predictive graph rendering/caching</span>
|
||||
</div>
|
||||
<!-- 1.0 Release -->
|
||||
<div class="informational heading">
|
||||
<div class="feature-icon heading">
|
||||
<h3>— 1.0 Release —</h3>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 20" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Procedural styling of paint brushes</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 30" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Constraint models for UI layouts</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 31" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Advanced typography and typesetting</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 32" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>PDF export</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 11" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Finer-grain control over SVG export</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 36" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Distributed graph rendering</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 37" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Cloud document storage</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 38" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Multiplayer collaborative editing</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 39" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Offline edit resolution with CRDTs</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 40" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Native UI rewrite (no HTML frontend)</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 46" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>SVG animation authorship</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 42" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Live video compositing</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 43" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>Pen and touch-only interaction</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 44" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span>iPad app</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<div class="feature-icon">
|
||||
<img class="atlas" style="--atlas-index: 47" src="https://static.graphite.rs/icons/icon-atlas-roadmap__2.png" alt="" />
|
||||
<span><em>…and that's all just the beginning…</em></span>
|
||||
</div>
|
||||
|
||||
@@ -8,11 +8,7 @@ book = true
|
||||
js = ["video-embed.js"]
|
||||
+++
|
||||
|
||||
<br />
|
||||
|
||||

|
||||
|
||||
Welcome to the Graphite user manual. Get ready to learn how the software can help bring your 2D creative ideas to life.
|
||||
**Welcome to the Graphite user manual.** Get ready to learn how the software can help bring your 2D creative ideas to life.
|
||||
|
||||
You may choose to read this sequentially and learn from the structured introduction and sample projects. Or you may jump to chapters of interest that also serve as quick reference.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title = "Graphite license"
|
||||
+++
|
||||
|
||||
<section class="reading-material">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Graphite license
|
||||
|
||||
@@ -15,7 +15,7 @@ The source code [available on GitHub](https://github.com/GraphiteEditor/Graphite
|
||||
|
||||
Visual assets, including but not limited to logos, icons, SVG code, branding imagery, and sample artwork are excluded from this license and held under copyright by their respective owners. Learn about the [Graphite brand](/logo) for more information.
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
|
||||
@@ -6,7 +6,7 @@ css = ["logo.css"]
|
||||
+++
|
||||
|
||||
<section class="reading-material">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Graphite logo
|
||||
|
||||
@@ -42,8 +42,8 @@ Download the complete [logo kit](https://static.graphite.rs/logos/graphite-logo-
|
||||
|
||||
<br />
|
||||
|
||||
<section class="feature-box logo-view color">
|
||||
<div class="box">
|
||||
<section class="feature-box-outer logo-view color">
|
||||
<div class="feature-box-inner">
|
||||
<div>
|
||||
<img src="https://static.graphite.rs/logos/graphite-logotype-color.svg" height="160" />
|
||||
<span>Graphite Logotype (Color)</span>
|
||||
@@ -61,8 +61,8 @@ Download the complete [logo kit](https://static.graphite.rs/logos/graphite-logo-
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="feature-box logo-view light">
|
||||
<div class="box">
|
||||
<section class="feature-box-outer logo-view light">
|
||||
<div class="feature-box-inner">
|
||||
<div>
|
||||
<img src="https://static.graphite.rs/logos/graphite-logotype-solid.svg" height="160" />
|
||||
<span>Graphite Logotype (Solid)</span>
|
||||
@@ -80,8 +80,8 @@ Download the complete [logo kit](https://static.graphite.rs/logos/graphite-logo-
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="feature-box logo-view dark">
|
||||
<div class="box">
|
||||
<section class="feature-box-outer logo-view dark">
|
||||
<div class="feature-box-inner">
|
||||
<div>
|
||||
<img src="https://static.graphite.rs/logos/graphite-logotype-solid-white.svg" height="160" />
|
||||
<span>Graphite Logotype (Solid, White)</span>
|
||||
|
||||
@@ -3,7 +3,7 @@ title = "Press resources"
|
||||
+++
|
||||
|
||||
<section class="reading-material">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Press resources
|
||||
|
||||
@@ -15,7 +15,7 @@ Materials for journalists and creators looking to share Graphite with their audi
|
||||
|
||||
Please get in touch if you'd like to conduct an interview or have questions answered.
|
||||
|
||||
Send an email to <contact@graphite.rs> and you can usually expect a quick reply.
|
||||
Send an email to [contact<wbr>@graphite<wbr>.rs](mailto:contact@graphite.rs) and you can usually expect a quick reply.
|
||||
|
||||
## Logo
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ css = ["volunteer.css"]
|
||||
+++
|
||||
|
||||
<section>
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
|
||||
# Volunteer
|
||||
|
||||
@@ -17,22 +17,67 @@ css = ["volunteer.css"]
|
||||
|
||||
<section>
|
||||
|
||||
<div class="diptych">
|
||||
## Code contributions
|
||||
|
||||
<div class="section creative-contributions">
|
||||
<div class="info-box">
|
||||
|
||||
<a href="/volunteer/guide">
|
||||
<img src="https://static.graphite.rs/content/volunteer/code-contributions.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.jpg')" alt="Flavor graphic depicting a library of knowledge in a digital realm" />
|
||||
</a>
|
||||
|
||||
**Get started by reading the contributor guide:**
|
||||
|
||||
<a href="/volunteer/guide" class="button arrow">Contributor guide</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="diptych code-contributions">
|
||||
|
||||
<div class="block info-box">
|
||||
|
||||
### EDITOR TEAM
|
||||
|
||||
Write code to build and maintain the Graphite editor itself, ranging from the TypeScript/Svelte frontend UI to the tooling business logic written in Rust.
|
||||
|
||||
</div>
|
||||
<div class="block info-box">
|
||||
|
||||
### GRAPHENE TEAM
|
||||
|
||||
Develop the engine that powers Graphite's node graph and rendering. Graphene is a programming language, compiler, and distributed runtime ecosystem built upon Rust.
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
||||
## Creative contributions
|
||||
|
||||
<a href="https://discord.graphite.rs" class="button arrow">Ask how to begin (Discord)</a>
|
||||
|
||||
<div class="info-box">
|
||||
|
||||
<a href="https://discord.graphite.rs">
|
||||
<img src="https://static.graphite.rs/content/volunteer/creative-contributions.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.jpg')" alt="Flavor graphic depicting a fountain pen, ink pots, and a book" />
|
||||
</a>
|
||||
|
||||
**Ask how to get started by reaching out to a [core team member](/about#core-team) on Discord:**
|
||||
|
||||
<a href="https://discord.graphite.rs" class="button arrow">Reach out on Discord</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="diptych creative-contributions">
|
||||
|
||||
<div class="block info-box">
|
||||
|
||||
### ART TEAM
|
||||
|
||||
Use your artistic talents to plan and produce ambitious open art projects published by the Graphite project to stress-test and showcase the editor's capabilities.
|
||||
|
||||
</div>
|
||||
<div class="info-box">
|
||||
<div class="block info-box">
|
||||
|
||||
### PUBLICITY TEAM
|
||||
|
||||
@@ -40,30 +85,6 @@ Become the author of release notes, feature announcements, blog posts, website c
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="section code-contributions">
|
||||
|
||||
## Code contributions
|
||||
|
||||
<a href="/volunteer/guide" class="button arrow">Contributor guide</a>
|
||||
|
||||
<div class="info-box">
|
||||
|
||||
### EDITOR TEAM
|
||||
|
||||
Write code to build and maintain the Graphite editor itself, ranging from the Svelte/TypeScript frontend UI to the tooling business logic written in Rust.
|
||||
|
||||
</div>
|
||||
<div class="info-box">
|
||||
|
||||
### GRAPHENE TEAM
|
||||
|
||||
Develop the core engine that powers Graphite's node graph and rendering. Graphene is a programming language, compiler, and distributed runtime ecosystem built upon Rust.
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
@@ -16,31 +16,32 @@
|
||||
background-color: var(--color-parchment);
|
||||
background-blend-mode: color-burn;
|
||||
|
||||
h2,
|
||||
h2 + p,
|
||||
h3,
|
||||
h3 + p {
|
||||
width: 100%;
|
||||
h2 {
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h2 + p {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
h3 + p {
|
||||
margin-top: 0;
|
||||
h2 + p + p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2 .flag {
|
||||
.flag {
|
||||
font-family: "Noto Color Emoji", sans-serif;
|
||||
font-size: 0.8em;
|
||||
margin-left: 0.2em;
|
||||
vertical-align: middle;
|
||||
font-size: 1.5em;
|
||||
margin-left: 0.25em;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.section {
|
||||
.block {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.reading-material {
|
||||
max-width: 800px;
|
||||
width: 100%;
|
||||
flex: 0 1 auto;
|
||||
|
||||
.details {
|
||||
@@ -19,6 +19,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
article {
|
||||
margin-top: calc(80 * var(--variable-px));
|
||||
}
|
||||
|
||||
.social {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
#intro {
|
||||
.section {
|
||||
.block {
|
||||
flex: 1 1 100%;
|
||||
width: 100%;
|
||||
|
||||
@@ -60,6 +60,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
~ section {
|
||||
margin-top: calc(120 * var(--variable-px));
|
||||
}
|
||||
|
||||
.banner {
|
||||
width: 400px;
|
||||
flex: 0 0 auto;
|
||||
@@ -79,8 +83,9 @@
|
||||
|
||||
.headline {
|
||||
margin-top: -0.5em;
|
||||
|
||||
|
||||
a {
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
color: var(--color-navy);
|
||||
}
|
||||
@@ -103,7 +108,7 @@
|
||||
-webkit-line-clamp: 3;
|
||||
|
||||
// Safari workaround: https://stackoverflow.com/a/72170897/775283
|
||||
// There is still an issue where the ellipsis is rendered inside the text but there doesn't appear to be a fix, or even a way to disable the ellipsis in Safari
|
||||
// But there remains an issue where the ellipsis is rendered inside the text. There doesn't appear to be a fix, or even a way to disable the ellipsis in Safari.
|
||||
p {
|
||||
display: inline;
|
||||
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
.three-column-layout {
|
||||
--aside-gap: 40px;
|
||||
--aside-width: 300px;
|
||||
--align-with-article-title-letter-cap-heights: 0.4em;
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 40px;
|
||||
justify-content: space-between;
|
||||
gap: var(--aside-gap);
|
||||
// Creates a stacking context for the left popout sidebar's sticky positioning
|
||||
transform: translate(0);
|
||||
|
||||
&.three-column-layout {
|
||||
max-width: var(--max-extended-width);
|
||||
}
|
||||
|
||||
.close-chapter-selection,
|
||||
.open-chapter-selection {
|
||||
display: none;
|
||||
flex: 0 0 auto;
|
||||
fill: var(--color-navy);
|
||||
background: none;
|
||||
border: none;
|
||||
@@ -23,7 +32,6 @@
|
||||
}
|
||||
|
||||
.reading-material {
|
||||
width: 800px;
|
||||
flex: 1 2 100%;
|
||||
|
||||
article {
|
||||
@@ -102,8 +110,8 @@
|
||||
border-right: var(--border-thickness) solid var(--color-walnut);
|
||||
box-sizing: border-box;
|
||||
transition: left 0.25s ease-in-out;
|
||||
left: calc(-1 * (300px + 10px));
|
||||
width: 300px;
|
||||
left: calc(-1 * (var(--aside-width) + 10px));
|
||||
width: var(--aside-width);
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
@@ -120,10 +128,9 @@
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
padding-right: var(--page-edge-padding);
|
||||
padding-bottom: calc(-120 * var(--variable-px));
|
||||
|
||||
ul:first-of-type {
|
||||
margin-top: calc(120 * var(--variable-px));
|
||||
margin-top: calc(120 * var(--variable-px) + var(--align-with-article-title-letter-cap-heights));
|
||||
}
|
||||
|
||||
.close-chapter-selection {
|
||||
@@ -145,54 +152,91 @@
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
|
||||
.open-chapter-selection {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
height: calc(var(--font-size-heading-h1) * 1.25);
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-left: -6px;
|
||||
margin-right: calc(20px - 6px);
|
||||
}
|
||||
|
||||
h1 {
|
||||
white-space: normal;
|
||||
display: flex;
|
||||
|
||||
.open-chapter-selection {
|
||||
display: inline-block;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-left: -6px;
|
||||
margin-right: calc(20px - 6px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
aside {
|
||||
position: sticky;
|
||||
align-self: flex-start;
|
||||
overflow-y: auto;
|
||||
top: 0;
|
||||
width: 300px;
|
||||
width: var(--aside-width);
|
||||
max-height: 100vh;
|
||||
margin-top: -40px;
|
||||
flex: 0 1 auto;
|
||||
|
||||
li {
|
||||
margin-top: 0.5em;
|
||||
|
||||
a {
|
||||
color: var(--color-walnut);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-crimson);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.title) a {
|
||||
text-decoration: none;
|
||||
&.contents > ul,
|
||||
.wrapper-inner > ul {
|
||||
&:first-of-type {
|
||||
margin-top: calc(40px + var(--align-with-article-title-letter-cap-heights));
|
||||
}
|
||||
|
||||
&.title,
|
||||
&.chapter {
|
||||
font-weight: bold;
|
||||
&:last-of-type {
|
||||
margin-bottom: calc(40 * var(--variable-px));
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 40px;
|
||||
|
||||
ul {
|
||||
margin-top: 0;
|
||||
margin-left: 1em;
|
||||
|
||||
ul {
|
||||
margin-left: 2em;
|
||||
|
||||
ul {
|
||||
margin-left: 3em;
|
||||
|
||||
ul {
|
||||
margin-left: 4em;
|
||||
|
||||
ul {
|
||||
margin-left: 5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
margin-top: 0.5em;
|
||||
|
||||
a {
|
||||
color: var(--color-walnut);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-crimson);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.title) a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.title,
|
||||
&.chapter {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.chapters {
|
||||
li.active,
|
||||
@@ -227,33 +271,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 40px;
|
||||
|
||||
ul {
|
||||
margin-top: 0;
|
||||
margin-left: 1em;
|
||||
|
||||
ul {
|
||||
margin-left: 2em;
|
||||
|
||||
ul {
|
||||
margin-left: 3em;
|
||||
|
||||
ul {
|
||||
margin-left: 4em;
|
||||
|
||||
ul {
|
||||
margin-left: 5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,51 @@
|
||||
#fundraising {
|
||||
background-color: var(--color-seaside);
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
// #fundraising {
|
||||
// background-color: var(--color-seaside);
|
||||
// color: rgba(0, 0, 0, 0.9);
|
||||
|
||||
.graphic {
|
||||
max-width: 400px;
|
||||
}
|
||||
}
|
||||
// .graphic {
|
||||
// max-width: 400px;
|
||||
// }
|
||||
|
||||
// .fundraising {
|
||||
// margin-top: 20px;
|
||||
// width: 100%;
|
||||
|
||||
// .fundraising-bar {
|
||||
// width: 100%;
|
||||
// height: 32px;
|
||||
// border-radius: 10000px;
|
||||
// background: var(--color-fog);
|
||||
// overflow: hidden;
|
||||
|
||||
// .fundraising-bar-progress {
|
||||
// width: calc(var(--fundraising-percent) - (4px * 2) - (32px - 4px * 2));
|
||||
// padding-left: calc(32px - 4px * 2);
|
||||
// height: calc(100% - 4px * 2);
|
||||
// margin: 4px;
|
||||
// border-radius: 10000px;
|
||||
// background: linear-gradient(to right, var(--color-navy), var(--color-crimson));
|
||||
// transition: opacity 1s, width 2s;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .goal-metrics {
|
||||
// display: flex;
|
||||
// justify-content: space-between;
|
||||
// font-weight: 800;
|
||||
// margin-top: 8px;
|
||||
// margin-left: 20px;
|
||||
// width: calc(100% - 40px);
|
||||
|
||||
// > span {
|
||||
// transition: opacity 1s;
|
||||
// }
|
||||
// }
|
||||
|
||||
// &.fundraising.loading {
|
||||
// .goal-metrics > span,
|
||||
// .fundraising-bar .fundraising-bar-progress {
|
||||
// opacity: 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
margin-top: 20px;
|
||||
padding: 0 16px;
|
||||
|
||||
.informational-group {
|
||||
.feature-icons {
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
|
||||
.informational {
|
||||
.feature-icon {
|
||||
position: relative;
|
||||
padding-left: calc(16px + 8px);
|
||||
|
||||
|
||||
@@ -4,69 +4,6 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// ▛ LOGO ▜
|
||||
#logo {
|
||||
display: flex;
|
||||
|
||||
img {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
max-height: 240px;
|
||||
}
|
||||
}
|
||||
// ▙ LOGO ▟
|
||||
|
||||
.pencil-texture {
|
||||
position: absolute;
|
||||
--remaining-width-to-full: calc(var(--max-width-plus-padding) - min(calc(100vw - 100px), var(--max-width-plus-padding)));
|
||||
left: Max(calc(-1 * var(--remaining-width-to-full)), -50px);
|
||||
width: 100px;
|
||||
mix-blend-mode: multiply;
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
width: 40px;
|
||||
top: 400px;
|
||||
left: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
// ▛ QUICK LINKS ▜
|
||||
#quick-links {
|
||||
margin-top: calc(80 * var(--variable-px));
|
||||
display: flex;
|
||||
gap: calc(var(--font-size-link) * 0.8);
|
||||
flex-wrap: wrap;
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
gap: calc(var(--font-size-link) * 0.8);
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
img {
|
||||
width: calc(var(--font-size-link) * 2);
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ▙ QUICK LINKS ▟
|
||||
|
||||
// ▛ TAGLINE ▜
|
||||
#tagline {
|
||||
h1 {
|
||||
font-size: var(--font-size-intro-heading);
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: var(--font-size-intro-body);
|
||||
|
||||
@media screen and (max-width: 1400px) {
|
||||
max-width: unset !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ▙ TAGLINE ▟
|
||||
|
||||
.hexagons {
|
||||
max-width: var(--max-width);
|
||||
margin: auto;
|
||||
@@ -87,18 +24,109 @@
|
||||
left: 0;
|
||||
transform: translate(-50%) rotate(347deg);
|
||||
opacity: 0.25;
|
||||
width: Max(1000px, Min(1400px, calc(100vw * 1400 / 1920)));
|
||||
--hexagon-max-size: 1100;
|
||||
--mexagon-min-size: 900;
|
||||
--hexagon-shrink-start-viewport-width: 1640;
|
||||
width: Max(
|
||||
Min(
|
||||
calc(var(--hexagon-max-size) * 1px),
|
||||
calc(var(--hexagon-max-size) / var(--hexagon-shrink-start-viewport-width) * 100vw)
|
||||
),
|
||||
calc(var(--mexagon-min-size) * 1px)
|
||||
);
|
||||
height: auto;
|
||||
|
||||
polygon {
|
||||
fill: none;
|
||||
stroke: gray;
|
||||
stroke: #aaa;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ▛ LOGO ▜
|
||||
#logo {
|
||||
img {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
max-height: 160px;
|
||||
}
|
||||
}
|
||||
// ▙ LOGO ▟
|
||||
|
||||
// ▛ TAGLINE ▜
|
||||
#tagline {
|
||||
p {
|
||||
font-size: calc(1rem * 10 / 9);
|
||||
|
||||
@media screen and (max-width: 1400px) {
|
||||
max-width: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ▙ TAGLINE ▟
|
||||
|
||||
// ▛ QUICK LINKS ▜
|
||||
#quick-links {
|
||||
margin-top: calc(40 * var(--variable-px));
|
||||
gap: calc(var(--font-size-link) * 0.8) calc(var(--font-size-link) * 0.8 * 2);
|
||||
|
||||
&,
|
||||
.social-media-buttons,
|
||||
.call-to-action-buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.social-media-buttons,
|
||||
.call-to-action-buttons {
|
||||
gap: calc(var(--font-size-link) * 0.8);
|
||||
}
|
||||
|
||||
.social-media-buttons img {
|
||||
width: calc(var(--font-size-link) * 2);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.call-to-action-buttons .github-stars {
|
||||
display: inline-flex;
|
||||
padding-left: calc(var(--font-size-link) / 2);
|
||||
padding-right: 0;
|
||||
|
||||
img {
|
||||
margin: auto;
|
||||
width: calc(var(--font-size-link) * 4 / 3);
|
||||
height: calc(var(--font-size-link) * 4 / 3);
|
||||
}
|
||||
|
||||
span {
|
||||
margin: auto calc(var(--font-size-link) / 2);
|
||||
}
|
||||
|
||||
div {
|
||||
display: inline-flex;
|
||||
background: var(--color-fog);
|
||||
padding: 0 calc(var(--font-size-link) / 2);
|
||||
border-left: var(--border-thickness) solid var(--color-crimson);
|
||||
align-items: center;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hide all these buttons while waiting for the number of stars to be fetched.
|
||||
// Otherwise the width of the star count will cause a jump upon loading with the layout of all subsequent buttons changing.
|
||||
// If it fails to load, the div will be removed, allowing the buttons to be displayed (with the star count omitted).
|
||||
&:has(.github-stars div:empty) {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
// ▙ QUICK LINKS ▟
|
||||
|
||||
// ▛ SCREENSHOTS ▜
|
||||
// ▙ SCREENSHOTS ▟
|
||||
|
||||
@@ -106,144 +134,152 @@
|
||||
// ▙ TODAY AND TOMORROW ▟
|
||||
|
||||
// ▛ DISCIPLINES ▜
|
||||
#disciplines .section {
|
||||
#disciplines .block {
|
||||
align-items: center;
|
||||
|
||||
.informational-group .informational {
|
||||
.feature-icons .feature-icon {
|
||||
margin-top: 40px;
|
||||
}
|
||||
}
|
||||
// ▙ DISCIPLINES ▟
|
||||
|
||||
// ▛ COMMUNITY ▜
|
||||
#community {
|
||||
// ▛ NEWSLETTER ▜
|
||||
#newsletter {
|
||||
background-color: var(--color-mustard);
|
||||
position: relative;
|
||||
|
||||
#newsletter {
|
||||
#newsletter-success {
|
||||
background: var(--color-crimson);
|
||||
margin-top: 40px;
|
||||
padding: 40px;
|
||||
width: 100%;
|
||||
color: var(--color-fog);
|
||||
box-sizing: border-box;
|
||||
#newsletter-success {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
||||
&:not(:target) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#newsletter-success:target ~ form {
|
||||
&:not(:target) ~ .feature-box-inner .diptych .newsletter-success,
|
||||
&:target ~ .feature-box-inner .diptych form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
margin-top: 40px;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.same-line {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex: 100000 1 0;
|
||||
flex-wrap: wrap;
|
||||
min-width: Min(100%, calc(240px + 20px + 240px));
|
||||
|
||||
div {
|
||||
min-height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
--input-focus-color: var(--color-ale);
|
||||
|
||||
&.name {
|
||||
flex: 1 0 0;
|
||||
min-width: 240px;
|
||||
}
|
||||
|
||||
&.phone {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.email {
|
||||
flex: 1 0 0;
|
||||
min-width: 240px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 400px) {
|
||||
&.name,
|
||||
&.email {
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.submit {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
label,
|
||||
input {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: var(--font-size-link);
|
||||
font-weight: 800;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
input:not([type="submit"]) {
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
height: calc(var(--font-size-link) * 2);
|
||||
font-size: calc(var(--font-size-link) * 0.9);
|
||||
color: inherit;
|
||||
border: var(--border-thickness) solid currentColor;
|
||||
border-radius: 0; // Required for iOS Safari
|
||||
outline: none;
|
||||
margin: 0;
|
||||
padding: 0 var(--font-size-link);
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--input-focus-color);
|
||||
}
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
background: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
border-radius: 0; // Required for iOS Safari
|
||||
|
||||
&:focus {
|
||||
border-color: var(--input-focus-color);
|
||||
color: var(--input-focus-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#social .social-links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px 80px;
|
||||
margin-top: 40px;
|
||||
.diptych {
|
||||
justify-content: center;
|
||||
|
||||
.column {
|
||||
.newsletter-signup {
|
||||
.newsletter-success {
|
||||
margin-top: 40px;
|
||||
padding: 40px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background: var(--color-ale);
|
||||
border: 2px solid var(--color-navy);
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
margin-top: 40px;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.same-line {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
flex: 100000 1 0;
|
||||
flex-wrap: wrap;
|
||||
min-width: Min(100%, 700px);
|
||||
|
||||
div {
|
||||
min-height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.input-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
--input-focus-color: var(--color-ale);
|
||||
|
||||
&.name {
|
||||
flex: 1 0 0;
|
||||
min-width: 240px;
|
||||
}
|
||||
|
||||
&.phone {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.email {
|
||||
flex: 1 0 0;
|
||||
min-width: 240px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 400px) {
|
||||
&.name,
|
||||
&.email {
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.submit {
|
||||
flex: 1 0 auto;
|
||||
|
||||
.button {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
label,
|
||||
input {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: var(--font-size-link);
|
||||
font-weight: 800;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
input:not([type="submit"]) {
|
||||
flex: 0 0 auto;
|
||||
width: 100%;
|
||||
height: calc(var(--font-size-link) * 2);
|
||||
font-size: calc(var(--font-size-link) * 0.9);
|
||||
color: inherit;
|
||||
border: var(--border-thickness) solid currentColor;
|
||||
border-radius: 0; // Required for iOS Safari
|
||||
outline: none;
|
||||
margin: 0;
|
||||
padding: 0 var(--font-size-link);
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--input-focus-color);
|
||||
}
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
background: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
border-radius: 0; // Required for iOS Safari
|
||||
|
||||
&:focus {
|
||||
border-color: var(--input-focus-color);
|
||||
color: var(--input-focus-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.social-media-links {
|
||||
display: flex;
|
||||
flex: 0 1 fit-content;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
gap: 20px 80px;
|
||||
min-width: 0;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
@@ -263,39 +299,39 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
// ▙ COMMUNITY ▟
|
||||
// ▙ NEWSLETTER ▟
|
||||
|
||||
// ▛ JUMP RIGHT IN ▜
|
||||
// #jump-right-in {
|
||||
// max-width: 1000px;
|
||||
|
||||
// .section {
|
||||
// .block {
|
||||
// align-items: center;
|
||||
// }
|
||||
// }
|
||||
// ▙ JUMP RIGHT IN ▟
|
||||
|
||||
// ▛ PROCEDURALISM ▜
|
||||
#proceduralism .section,
|
||||
#proceduralism-demo .section,
|
||||
#proceduralism-features .section {
|
||||
#proceduralism .block,
|
||||
#proceduralism-demo .block,
|
||||
#proceduralism-features .block {
|
||||
align-items: center;
|
||||
}
|
||||
// ▙ PROCEDURALISM ▟
|
||||
|
||||
// ▛ FUNDRAISING ▜
|
||||
#fundraising {
|
||||
background-color: var(--color-cove);
|
||||
// ▛ DONATE ▜
|
||||
#donate {
|
||||
background-color: var(--color-lilac);
|
||||
|
||||
.graphic {
|
||||
max-width: 400px;
|
||||
}
|
||||
}
|
||||
// ▙ FUNDRAISING ▟
|
||||
// ▙ DONATE ▟
|
||||
|
||||
// ▛ VECTOR ART ▜
|
||||
#vector-art {
|
||||
.section {
|
||||
.block {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@@ -303,7 +339,7 @@
|
||||
|
||||
// ▛ IMAGINATE ▜
|
||||
// #imaginate {
|
||||
// > .section {
|
||||
// > .block {
|
||||
// align-items: center;
|
||||
|
||||
// h1 {
|
||||
@@ -348,7 +384,7 @@
|
||||
// > .diptych {
|
||||
// margin-top: calc(80 * var(--variable-px));
|
||||
|
||||
// .section {
|
||||
// .block {
|
||||
// align-items: center;
|
||||
|
||||
// h2 {
|
||||
@@ -377,13 +413,49 @@
|
||||
}
|
||||
// ▙ DEMO VIDEO ▟
|
||||
|
||||
// ▛ GET INVOLVED ▜
|
||||
#get-involved-box {
|
||||
background-color: var(--color-sage);
|
||||
// ▛ RECENT NEWS ▜
|
||||
#recent-news {
|
||||
background-color: var(--color-walnut);
|
||||
color: var(--color-white);
|
||||
|
||||
a {
|
||||
color: var(--color-mustard);
|
||||
}
|
||||
|
||||
.graphic img {
|
||||
mix-blend-mode: hard-light;
|
||||
.banner img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.headline a {
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.summary {
|
||||
margin: 20px 0;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
text-align: justify;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 6;
|
||||
|
||||
// Safari workaround: https://stackoverflow.com/a/72170897/775283
|
||||
// But there remains an issue where the ellipsis is rendered inside the text. There doesn't appear to be a fix, or even a way to disable the ellipsis in Safari.
|
||||
p {
|
||||
display: inline;
|
||||
|
||||
&::after {
|
||||
content: "\A\A"; // Double new line
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ▙ GET INVOLVED ▟
|
||||
|
||||
// ▙ RECENT NEWS ▟
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.box {
|
||||
.feature-box-inner {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 80px 160px;
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
.creative-contributions .info-box {
|
||||
&:nth-of-type(1) {
|
||||
background-color: var(--color-seaside);
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
background-color: var(--color-cove);
|
||||
}
|
||||
.code-contributions,
|
||||
.creative-contributions {
|
||||
gap: 0 calc(80* var(--variable-px));
|
||||
}
|
||||
|
||||
.code-contributions .info-box {
|
||||
&:nth-of-type(1) {
|
||||
background-color: var(--color-mustard);
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
background-color: var(--color-ale);
|
||||
}
|
||||
background-color: var(--color-seaside);
|
||||
}
|
||||
|
||||
.creative-contributions,
|
||||
.code-contributions {
|
||||
.button.button.button {
|
||||
height: auto;
|
||||
text-align: left;
|
||||
white-space: normal;
|
||||
.creative-contributions .info-box {
|
||||
background-color: var(--color-lemon);
|
||||
}
|
||||
|
||||
.info-box {
|
||||
margin-top: calc(40 * var(--variable-px));
|
||||
|
||||
> img:first-child,
|
||||
> a:first-child > img:only-child {
|
||||
width: calc(100% + 2 * 80 * var(--variable-px));
|
||||
margin-left: calc(-80 * var(--variable-px));
|
||||
margin-top: calc(-80 * var(--variable-px));
|
||||
margin-bottom: calc(40 * var(--variable-px));
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// ================================================================================================
|
||||
// ========
|
||||
// CAROUSEL
|
||||
// ================================================================================================
|
||||
// ========
|
||||
|
||||
const FLING_VELOCITY_THRESHOLD = 10;
|
||||
const FLING_VELOCITY_WINDOW_SIZE = 20;
|
||||
@@ -16,6 +16,17 @@ function initializeCarousel() {
|
||||
const carouselContainers = document.querySelectorAll("[data-carousel]");
|
||||
|
||||
carouselContainers.forEach((carouselContainer) => {
|
||||
const slideImages = carouselContainer.querySelectorAll("[data-carousel-slide] [data-carousel-image]");
|
||||
const tornLeft = carouselContainer.querySelector("[data-carousel-slide-torn-left]");
|
||||
const tornRight = carouselContainer.querySelector("[data-carousel-slide-torn-right]");
|
||||
[tornLeft, tornRight].forEach((insertInsideElement) => {
|
||||
slideImages.forEach((image) => {
|
||||
const clonedImage = image.cloneNode(true);
|
||||
if (clonedImage instanceof HTMLImageElement) clonedImage.alt = "";
|
||||
insertInsideElement.insertAdjacentElement("beforeend", clonedImage);
|
||||
});
|
||||
});
|
||||
|
||||
const images = carouselContainer.querySelectorAll("[data-carousel-image]");
|
||||
const directionPrev = carouselContainer.querySelector("[data-carousel-prev]");
|
||||
const directionNext = carouselContainer.querySelector("[data-carousel-next]");
|
||||
@@ -36,6 +47,7 @@ function initializeCarousel() {
|
||||
dragLastClientX,
|
||||
velocityDeltaWindow,
|
||||
jostleNoLongerNeeded,
|
||||
requestAnimationFrameActive: false,
|
||||
};
|
||||
carousels.push(carousel);
|
||||
|
||||
@@ -62,7 +74,10 @@ function initializeCarousel() {
|
||||
|
||||
let startTime;
|
||||
const buildUp = (timeStep) => {
|
||||
if (carousel.jostleNoLongerNeeded) return;
|
||||
if (carousel.jostleNoLongerNeeded) {
|
||||
carousel.carouselContainer.classList.remove("jostling");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!startTime) startTime = timeStep;
|
||||
const elapsedTime = timeStep - startTime;
|
||||
@@ -75,10 +90,12 @@ function initializeCarousel() {
|
||||
if (elapsedTime < JOSTLE_TIME) {
|
||||
requestAnimationFrame(buildUp);
|
||||
} else {
|
||||
carousel.carouselContainer.classList.remove("jostling");
|
||||
carousel.jostleNoLongerNeeded = true;
|
||||
slideTo(carousel, 0, true);
|
||||
}
|
||||
};
|
||||
carousel.carouselContainer.classList.add("jostling")
|
||||
requestAnimationFrame(buildUp);
|
||||
};
|
||||
});
|
||||
@@ -115,27 +132,65 @@ function slideTo(carousel, index, smooth) {
|
||||
}
|
||||
|
||||
function currentTransform(carousel) {
|
||||
const currentTransformMatrix = window.getComputedStyle(carousel.images[0]).transform;
|
||||
// Grab the X value from the format that looks like: `matrix(1, 0, 0, 1, -1332.13, 0)` or `none`
|
||||
return Number(currentTransformMatrix.split(",")[4] || "0");
|
||||
const currentTransformMatrix = window.getComputedStyle(carousel.images[1]).transform;
|
||||
// Grab the X value from the format that looks like either of: `matrix(1, 0, 0, 1, -1332.13, 0)` or `none`
|
||||
const xValue = Number(currentTransformMatrix.split(",")[4] || "0");
|
||||
|
||||
return xValue + carousel.images[1].getBoundingClientRect().width;
|
||||
}
|
||||
|
||||
function setCurrentTransform(carousel, x, unit, smooth, doNotTerminateJostle = false) {
|
||||
const xInitial = currentTransform(carousel);
|
||||
|
||||
let xValue = x;
|
||||
if (unit === "%") xValue = x - 100;
|
||||
if (unit === "px") xValue = x - carousel.images[1].getBoundingClientRect().width;
|
||||
|
||||
Array.from(carousel.images).forEach((image) => {
|
||||
image.style.transitionTimingFunction = smooth ? "ease-in-out" : "cubic-bezier(0, 0, 0.2, 1)";
|
||||
image.style.transform = `translateX(${x}${unit})`;
|
||||
image.style.transform = `translateX(${xValue}${unit})`;
|
||||
});
|
||||
|
||||
// If the user caused the carousel to move, we can assume they know how to use it and don't need the jostle hint anymore
|
||||
if (!doNotTerminateJostle && x !== xInitial) carousel.jostleNoLongerNeeded = true;
|
||||
if (!doNotTerminateJostle && x - xInitial < 0.0001) carousel.jostleNoLongerNeeded = true;
|
||||
|
||||
const distance = unit === "%" ? x : x / carousel.images[1].getBoundingClientRect().width * 100;
|
||||
const overSlidingLeft = distance > 0;
|
||||
const overSlidingRight = distance < (carousel.dots.length - 1) * -100;
|
||||
|
||||
if ((overSlidingLeft || overSlidingRight) && !carousel.requestAnimationFrameActive) updateOverSlide(carousel);
|
||||
}
|
||||
|
||||
function updateOverSlide(carousel) {
|
||||
const paddingLeft = parseInt(getComputedStyle(carousel.images[1]).paddingLeft);
|
||||
const paddingRight = parseInt(getComputedStyle(carousel.images[carousel.images.length - 2]).paddingRight);
|
||||
const slidLeftDistance = carousel.images[1].getBoundingClientRect().left + paddingLeft - carousel.images[1].parentElement.getBoundingClientRect().left;
|
||||
const slidRightDistance = -(carousel.images[carousel.images.length - 2].getBoundingClientRect().right - paddingRight - carousel.images[1].parentElement.getBoundingClientRect().right);
|
||||
const imageWidth = carousel.images[1].getBoundingClientRect().width;
|
||||
const overSlideFactor = Math.min(1, Math.max(0, (Math.max(slidLeftDistance, slidRightDistance) / imageWidth)));
|
||||
|
||||
const images = carousel.images[0].closest("[data-carousel]").querySelectorAll("[data-carousel-image]:first-child, [data-carousel-image]:last-child");
|
||||
|
||||
// Call again the next frame if we're still sliding past the edge
|
||||
if (overSlideFactor > 0) {
|
||||
images.forEach((image) => {
|
||||
image.style.setProperty("--over-slide-factor", overSlideFactor);
|
||||
});
|
||||
|
||||
carousel.requestAnimationFrameActive = true;
|
||||
requestAnimationFrame(() => updateOverSlide(carousel));
|
||||
} else {
|
||||
images.forEach((image) => {
|
||||
image.style.removeProperty("--over-slide-factor");
|
||||
});
|
||||
|
||||
carousel.requestAnimationFrameActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
function currentClosestImageIndex(carousel) {
|
||||
const currentTransformX = -currentTransform(carousel);
|
||||
|
||||
const imageWidth = carousel.images[0].getBoundingClientRect().width;
|
||||
const imageWidth = carousel.images[1].getBoundingClientRect().width;
|
||||
return Math.round(currentTransformX / imageWidth);
|
||||
}
|
||||
|
||||
@@ -148,7 +203,7 @@ function dragBegin(event) {
|
||||
const carouselContainer = event.target.closest("[data-carousel]");
|
||||
const carousel = carousels.find((carousel) => carousel.carouselContainer === carouselContainer);
|
||||
if (!carousel) return;
|
||||
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
carousel.dragLastClientX = event.clientX;
|
||||
@@ -160,7 +215,7 @@ function dragBegin(event) {
|
||||
function dragEnd(dropWithoutVelocity) {
|
||||
const carousel = carousels.find((carousel) => carousel.dragLastClientX !== undefined);
|
||||
if (!carousel) return;
|
||||
|
||||
|
||||
if (!carousel.images) return;
|
||||
|
||||
carousel.dragLastClientX = undefined;
|
||||
@@ -235,9 +290,9 @@ function clamp(value, min, max) {
|
||||
return Math.min(Math.max(value, min), max);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ================
|
||||
// IMAGE COMPARISON
|
||||
// ================================================================================================
|
||||
// ================
|
||||
|
||||
const RECENTER_DELAY = 1;
|
||||
const RECENTER_ANIMATION_DURATION = 0.25;
|
||||
@@ -279,7 +334,7 @@ function initializeImageComparison() {
|
||||
element.dataset.lastInteraction = "";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const factor = smootherstep(completionFactor);
|
||||
const newLocation = lerp(element.dataset.recenterStartValue, 50, factor);
|
||||
element.style.setProperty("--comparison-percent", `${newLocation}%`);
|
||||
@@ -289,7 +344,7 @@ function initializeImageComparison() {
|
||||
|
||||
const lerp = (a, b, t) => (1 - t) * a + t * b;
|
||||
const smootherstep = (x) => x * x * x * (x * (x * 6 - 15) + 10);
|
||||
|
||||
|
||||
element.addEventListener("pointermove", moveHandler);
|
||||
element.addEventListener("pointerenter", moveHandler);
|
||||
element.addEventListener("pointerleave", leaveHandler);
|
||||
@@ -297,9 +352,10 @@ function initializeImageComparison() {
|
||||
});
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
// ==================
|
||||
// AUTO-PLAYING VIDEO
|
||||
// ================================================================================================
|
||||
// ==================
|
||||
|
||||
window.addEventListener("DOMContentLoaded", initializeVideoAutoPlay);
|
||||
|
||||
function initializeVideoAutoPlay() {
|
||||
@@ -310,12 +366,12 @@ function initializeVideoAutoPlay() {
|
||||
if (!(player instanceof HTMLVideoElement)) return;
|
||||
|
||||
let loaded = false;
|
||||
|
||||
|
||||
new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (!loaded && entry.intersectionRatio > VISIBILITY_COVERAGE_FRACTION) {
|
||||
player.play();
|
||||
|
||||
|
||||
loaded = true;
|
||||
};
|
||||
});
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
{%- block content -%}
|
||||
<section id="404">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
<h1>Page not found</h1>
|
||||
<p>Or as the machines like to say it: <code>404</code>.</p>
|
||||
<br />
|
||||
<a href="/" class="button arrow">Home Page</a>
|
||||
<a href="/" class="button arrow">Return home</a>
|
||||
</div>
|
||||
</section>
|
||||
{%- endblock content -%}
|
||||
|
||||
@@ -11,13 +11,12 @@
|
||||
|
||||
{%- block content -%}{%- set page = page | default(value = section) -%}
|
||||
<section class="reading-material">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
<div class="details">
|
||||
<h1 class="headline">{{ page.title }}</h2>
|
||||
<span class="publication">By {{ page.extra.author }}. {{ page.date | date(format = "%B %d, %Y", timezone="America/Los_Angeles") }}.</span>
|
||||
<img class="banner" src="{{ page.extra.banner | safe }}" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" />
|
||||
</div>
|
||||
<hr />
|
||||
<article>
|
||||
{{ page.content | safe }}
|
||||
</article>
|
||||
@@ -26,7 +25,7 @@
|
||||
<div class="social">
|
||||
{% if page.extra.reddit %}
|
||||
<a href="{{ page.extra.reddit | safe }}" target="_blank" class="button arrow">
|
||||
<img src="https://static.graphite.rs/icons/reddit.svg" /><span>Comment on Reddit</span>
|
||||
<img src="https://static.graphite.rs/icons/reddit__2.svg" /><span>Comment on Reddit</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if page.extra.twitter %}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{% import "macros/replacements.html" as replacements %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
@@ -91,14 +92,13 @@
|
||||
<hr />
|
||||
</header>
|
||||
<main>
|
||||
<div class="content">
|
||||
{%- block content -%}{%- endblock -%}
|
||||
</div>
|
||||
{%- filter replace(from = "<!-- replacements::blog_posts(count = 2) -->", to = replacements::blog_posts(count = 2)) -%}
|
||||
{%- block content -%}{%- endblock -%}
|
||||
{%- endfilter -%}
|
||||
</main>
|
||||
<footer>
|
||||
<hr />
|
||||
<nav class="balance-text require-polyfill">
|
||||
<a href="https://github.com/GraphiteEditor/Graphite/graphs/contributors" class="link not-uppercase">Credits</a>
|
||||
<a href="/license" class="link not-uppercase">License</a>
|
||||
<a href="/logo" class="link not-uppercase">Logo</a>
|
||||
<a href="/press" class="link not-uppercase">Press</a>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
{%- block content -%}{%- set page = page | default(value = section) -%}
|
||||
{{ page.content | safe }}
|
||||
|
||||
<section id="articles" class="section">
|
||||
<section id="articles" class="block">
|
||||
{% for page in page.pages %}
|
||||
<section>
|
||||
<div class="banner">
|
||||
|
||||
@@ -72,16 +72,18 @@
|
||||
</aside>
|
||||
|
||||
<section class="reading-material">
|
||||
<div class="section">
|
||||
<div class="block">
|
||||
<div class="article-title">
|
||||
<button title="Open chapter selection" class="open-chapter-selection" data-open-chapter-selection>
|
||||
<svg viewBox="0 0 24 24">
|
||||
<rect x="2" y="4" width="20" height="2"/>
|
||||
<rect x="2" y="18" width="20" height="2"/>
|
||||
<rect x="2" y="11" width="20" height="2"/>
|
||||
</svg>
|
||||
</button>
|
||||
<h1>{{ page.title }}</h1>
|
||||
<h1>
|
||||
<button title="Open chapter selection" class="open-chapter-selection" data-open-chapter-selection>
|
||||
<svg viewBox="0 0 24 24">
|
||||
<rect x="2" y="4" width="20" height="2"/>
|
||||
<rect x="2" y="18" width="20" height="2"/>
|
||||
<rect x="2" y="11" width="20" height="2"/>
|
||||
</svg>
|
||||
</button>
|
||||
<span>{{ page.title }}</span>
|
||||
</h1>
|
||||
</div>
|
||||
<article>
|
||||
{{ page.content | safe }}
|
||||
|
||||
14
website/templates/macros/replacements.html
Normal file
14
website/templates/macros/replacements.html
Normal file
@@ -0,0 +1,14 @@
|
||||
{% macro blog_posts(count) %}
|
||||
{% set articles = get_section(path="blog/_index.md") %}
|
||||
{% set latest = articles.pages | slice(end = count) %}
|
||||
{% for article in latest %}
|
||||
<div class="block">
|
||||
<a class="banner" href="{{ article.permalink | safe }}"><img src="{{ article.extra.banner | safe }}" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" /></a>
|
||||
<h2 class="headline"><a href="{{ article.permalink | safe }}">{{ article.title }}</a></h2>
|
||||
<div class="summary">
|
||||
{{ article.summary | safe }}
|
||||
</div>
|
||||
<a href="{{ article.permalink | safe }}" class="link arrow">Keep reading</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endmacro blog_posts %}
|
||||
Reference in New Issue
Block a user