A sample structure for an afternoon around the table.
Starting stack
20,000 chips
Table size
6 players
Registration
Through level 4
The rotation
Levels, stakes and scheduled breaks
Level
Minutes
Game
Blinds / bets
Ante
1
20
No-limit hold’em
100 / 200
200
2
20
Pot-limit Omaha
100 / 200
—
3
20
Limit hold’em
300 / 600
—
4
20
Seven-card stud
300 / 600
75
First interval · registration closes · 15 minute break
5
20
No-limit hold’em
200 / 400
400
6
20
Pot-limit Omaha
200 / 400
—
7
20
Limit hold’em
600 / 1,200
—
8
20
Seven-card stud
600 / 1,200
150
Second interval · 10 minute break
9
20
No-limit hold’em
400 / 800
800
10
20
Pot-limit Omaha
400 / 800
—
11
20
Limit hold’em
1,200 / 2,400
—
12
20
Seven-card stud
1,200 / 2,400
300
Before you begin
This is fictional layout data, not an event announcement or a complete set of tournament rules.
Blinds are shown for no-limit and pot-limit games; small and big bets are shown for limit games.
Provide your own event settings, break policy and complete rules before using a structure sheet.
diff --git a/docs/assets/yew-starter/preview/fonts/DMSerifDisplay-OFL.txt b/docs/assets/yew-starter/preview/fonts/DMSerifDisplay-OFL.txt
new file mode 100644
index 0000000..be384f0
--- /dev/null
+++ b/docs/assets/yew-starter/preview/fonts/DMSerifDisplay-OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. Copyright 2019 Google LLC.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/docs/assets/yew-starter/preview/fonts/DMSerifDisplay-Regular.ttf b/docs/assets/yew-starter/preview/fonts/DMSerifDisplay-Regular.ttf
new file mode 100644
index 0000000..bc5ed0c
Binary files /dev/null and b/docs/assets/yew-starter/preview/fonts/DMSerifDisplay-Regular.ttf differ
diff --git a/docs/assets/yew-starter/preview/fonts/Inter-OFL.txt b/docs/assets/yew-starter/preview/fonts/Inter-OFL.txt
new file mode 100644
index 0000000..21f6aff
--- /dev/null
+++ b/docs/assets/yew-starter/preview/fonts/Inter-OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+https://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/docs/assets/yew-starter/preview/fonts/Inter-Variable.ttf b/docs/assets/yew-starter/preview/fonts/Inter-Variable.ttf
new file mode 100644
index 0000000..047c92f
Binary files /dev/null and b/docs/assets/yew-starter/preview/fonts/Inter-Variable.ttf differ
diff --git a/docs/assets/yew-starter/preview/style.css b/docs/assets/yew-starter/preview/style.css
new file mode 100644
index 0000000..537b87a
--- /dev/null
+++ b/docs/assets/yew-starter/preview/style.css
@@ -0,0 +1,57 @@
+@font-face { font-family: Inter; src: url('fonts/Inter-Variable.ttf') format('truetype'); font-weight: 100 900; }
+@font-face { font-family: 'DM Serif Display'; src: url('fonts/DMSerifDisplay-Regular.ttf') format('truetype'); }
+@page { size: A4; margin: 16mm 17mm; }
+* { box-sizing: border-box; }
+body { margin: 0; color: #213436; font-family: Inter, sans-serif; font-size: 9pt; line-height: 1.4; }
+.masthead { background: #183b3f; color: #fffaf1; padding: 7mm 8mm; border-top: 2mm solid #c47d4e; }
+.eyebrow { margin: 0 0 3mm; font-size: 8pt; text-transform: uppercase; letter-spacing: 2pt; color: #edd4b0; }
+h1 { margin: 0 0 2mm; font-family: 'DM Serif Display', serif; font-size: 27pt; font-weight: 400; line-height: 1.1; }
+.subtitle { margin: 0; color: #e0e8df; font-size: 9pt; }
+.facts { display: flex; gap: 7mm; padding: 5mm 0; margin: 0 0 3mm; border-bottom: 0.3mm solid #c9d5d0; }
+.facts div { flex: 1; }
+dt { font-size: 7.5pt; color: #5f7270; text-transform: uppercase; letter-spacing: 0.6pt; }
+dd { margin: 1mm 0 0; font-weight: 700; font-size: 11pt; }
+h2 { margin: 0 0 2mm; font-size: 13pt; font-weight: 700; }
+table { width: 100%; border-collapse: collapse; font-size: 8.6pt; }
+caption { text-align: left; color: #5f7270; margin-bottom: 3mm; font-size: 8pt; }
+th, td { text-align: left; padding: 2.2mm 2.4mm; border-bottom: 0.2mm solid #d4dcd7; vertical-align: top; }
+thead { display: table-header-group; }
+thead th { background: #e7eee8; font-size: 7.5pt; color: #254b49; font-weight: 700; }
+tbody th { color: #254b49; font-weight: 700; }
+tbody tr { break-inside: avoid; }
+.numeric { text-align: right; white-space: nowrap; }
+.break th { background: #f8eee0; color: #7a4d31; font-size: 8pt; font-weight: 400; padding-top: 2mm; padding-bottom: 2mm; }
+.break-label { font-weight: 700; }
+.notes { margin-top: 5mm; padding-left: 4mm; border-left: 0.8mm solid #c47d4e; }
+.notes h2 { font-size: 10pt; }
+.notes ul { margin: 0; padding-left: 4mm; font-size: 8pt; }
+.notes li { margin-bottom: 1.2mm; }
+footer { margin-top: 5mm; border-top: 0.2mm solid #c9d5d0; padding-top: 2mm; color: #5f7270; font-size: 7pt; }
+footer p { margin: 0; }
+@media screen {
+ body { background: #e7e9e3; padding: 24px; font-size: 14px; }
+ .sheet { background: #fffdf8; max-width: 850px; margin: 0 auto; padding: 32px; }
+ .table-scroll { overflow-x: auto; }
+ table { min-width: 560px; font-size: 13px; }
+ th, td { padding: 10px; }
+ caption, .notes ul { font-size: 12px; }
+ footer { font-size: 11px; }
+}
+@media screen and (max-width: 600px) {
+ body { padding: 0; }
+ .sheet { padding: 16px; }
+ .masthead { padding: 24px; }
+ .facts { flex-wrap: wrap; gap: 16px; }
+ .facts div { flex-basis: 42%; }
+}
+@media print {
+ body { background: #fff; padding: 0; font-size: 9pt; }
+ .sheet { margin: 0; padding: 0; max-width: none; }
+ .table-scroll { overflow: visible; }
+ table { min-width: 0; font-size: 8.6pt; }
+ th, td { padding: 2.2mm 2.4mm; }
+ caption, .notes ul { font-size: 8pt; }
+ footer { font-size: 7pt; }
+ .facts { flex-wrap: nowrap; gap: 7mm; }
+ .facts div { flex-basis: auto; }
+}
diff --git a/docs/assets/yew-starter/preview/unstyled.html b/docs/assets/yew-starter/preview/unstyled.html
new file mode 100644
index 0000000..56f82a4
--- /dev/null
+++ b/docs/assets/yew-starter/preview/unstyled.html
@@ -0,0 +1,2 @@
+
+Saturday mixed-game rotation
Riverstone / Community Series
Saturday mixed-game rotation
A sample structure for an afternoon around the table.
Starting stack
20,000 chips
Table size
6 players
Registration
Through level 4
The rotation
Levels, stakes and scheduled breaks
Level
Minutes
Game
Blinds / bets
Ante
1
20
No-limit hold’em
100 / 200
200
2
20
Pot-limit Omaha
100 / 200
—
3
20
Limit hold’em
300 / 600
—
4
20
Seven-card stud
300 / 600
75
First interval · registration closes · 15 minute break
5
20
No-limit hold’em
200 / 400
400
6
20
Pot-limit Omaha
200 / 400
—
7
20
Limit hold’em
600 / 1,200
—
8
20
Seven-card stud
600 / 1,200
150
Second interval · 10 minute break
9
20
No-limit hold’em
400 / 800
800
10
20
Pot-limit Omaha
400 / 800
—
11
20
Limit hold’em
1,200 / 2,400
—
12
20
Seven-card stud
1,200 / 2,400
300
Before you begin
This is fictional layout data, not an event announcement or a complete set of tournament rules.
Blinds are shown for no-limit and pot-limit games; small and big bets are shown for limit games.
Provide your own event settings, break policy and complete rules before using a structure sheet.
diff --git a/docs/assets/yew-starter/project.zip b/docs/assets/yew-starter/project.zip
new file mode 100644
index 0000000..1c54647
Binary files /dev/null and b/docs/assets/yew-starter/project.zip differ
diff --git a/docs/assets/yew-starter/source.json b/docs/assets/yew-starter/source.json
new file mode 100644
index 0000000..d7c7453
--- /dev/null
+++ b/docs/assets/yew-starter/source.json
@@ -0,0 +1,73 @@
+{
+ "schema": "fullbleed.yew-starter.v1",
+ "prefix": "fullbleed-yew-sheet/",
+ "packages": {
+ "fullbleed": "2.5.34",
+ "yew": "0.23.0",
+ "tokio": "1.54.1"
+ },
+ "files": [
+ {
+ "path": "Cargo.lock",
+ "bytes": 25365,
+ "sha256": "ed41ad2e25af6f936f387d41d52e02090175cf7f1c74420bffb488955e1b1183"
+ },
+ {
+ "path": "Cargo.toml",
+ "bytes": 456,
+ "sha256": "d0e1b775abdd443a40c42e25dd8a1a8d4a2d91db8b6f30bc92a29d24bafccdf9"
+ },
+ {
+ "path": "LICENSE",
+ "bytes": 1079,
+ "sha256": "36a2115938f6e68cf0d87eccff7a6a3e57c17017e909cbd640d51aff1fa0c5a9"
+ },
+ {
+ "path": "README.md",
+ "bytes": 3971,
+ "sha256": "62f09f6ed13546f7f93d8deb5cd858ea1bf87ee66f970aa1e4b4b74a42dd3ee5"
+ },
+ {
+ "path": "data.json",
+ "bytes": 2035,
+ "sha256": "7044cade66216475b5ea370426513a50a6331b3f91ec4a8c45a50728281b68b2"
+ },
+ {
+ "path": "fonts/DMSerifDisplay-OFL.txt",
+ "bytes": 4605,
+ "sha256": "a3e5cdd67d4571dd0a24fcc968de0efde7ae97ef752daf0906e4767619dd7231"
+ },
+ {
+ "path": "fonts/DMSerifDisplay-Regular.ttf",
+ "bytes": 76580,
+ "sha256": "8cc3643535edf039aa5d95440a8542735e9197e4f4b8d9303e980fefbf5ab616"
+ },
+ {
+ "path": "fonts/Inter-OFL.txt",
+ "bytes": 4377,
+ "sha256": "5b9321a4298cfeb6b34354164a1c3afc3db114569984c502b9b35d988fd58c57"
+ },
+ {
+ "path": "fonts/Inter-Variable.ttf",
+ "bytes": 876576,
+ "sha256": "29160a80ff49ddcab2c97711247e08b1fab27a484a329ce8b813d820dc559031"
+ },
+ {
+ "path": "src/document.rs",
+ "bytes": 4425,
+ "sha256": "7e4a2abb11dc1145a8ed437ab1d92d873e7a98129bcd1c1e6f95fe4719ede928"
+ },
+ {
+ "path": "src/main.rs",
+ "bytes": 2695,
+ "sha256": "8820dcd75983f6eb3b88352d0d89681065a5eb5b92c2ea15adcbf3f5a5f3ea39"
+ },
+ {
+ "path": "style.css",
+ "bytes": 3079,
+ "sha256": "f3564d1aa13f211d46365c51a16e891b59ccc0f10bf91f7082f48492302a56d5"
+ }
+ ],
+ "zip_bytes": 1007023,
+ "zip_sha256": "b88f585df911ad274aaf13177f68a1b3eeaf11aeb81186f46a21224af01f0201"
+}
diff --git a/docs/examples.md b/docs/examples.md
index d379c7a..8381a57 100644
--- a/docs/examples.md
+++ b/docs/examples.md
@@ -160,6 +160,8 @@ For Cloudflare Workers, try the [invoice endpoint with local runtime checks](gui
For C# web applications, try the [ASP.NET Core download starter](guides/aspnet-pdf.md).
For Rust applications, use the [Axum PDF download starter](guides/axum-pdf.md)
with an editable invoice template and bounded rendering work.
+For component authoring, the optional [Yew schedule example](getting-started/rust.md#use-yew-components)
+exports PDF and styled or plain HTML from typed Rust props.
For PHP applications, use the [Laravel Blade and queue starter](guides/laravel-pdf.md)
with automatic rendering, private downloads, retries and expiry cleanup.
For a tagged document, use the [editable C# library notice](guides/csharp-tagged-pdf.md)
diff --git a/docs/getting-started/rust.md b/docs/getting-started/rust.md
index 37bcfa4..c33d409 100644
--- a/docs/getting-started/rust.md
+++ b/docs/getting-started/rust.md
@@ -145,6 +145,55 @@ for (index, png) in engine.render_finalized_pdf_image_pages("invoice.pdf", 96)?.
This previews the finalized PDF, including its supported gradient fills. The
designed example and downloaded playground projects use the same path.
+## Use Yew components
+
+If your application already uses Yew, you can author a document with typed
+props and its `html!` macro. This optional example renders a fictional event
+schedule to PDF and exports the same content as styled or plain HTML.
+
+[](../assets/yew-starter/document.pdf)
+
+[Download the Yew project](../assets/yew-starter/project.zip){ .md-button .md-button--primary }
+[Open the PDF](../assets/yew-starter/document.pdf){ .md-button }
+
+[Styled HTML](../assets/yew-starter/preview/document.html)
+· [HTML without styles](../assets/yew-starter/preview/unstyled.html)
+· [Source checksums](../assets/yew-starter/source.json)
+
+Extract the ZIP, open a terminal in `fullbleed-yew-sheet`, and run:
+
+```bash
+cargo run --release --locked -- data.json output
+```
+
+Open `output/document.pdf`, `output/document.html`, or `output/unstyled.html`.
+Edit `data.json` for the content and `style.css` for the design. Choose a new
+output directory after edits; the program refuses to overwrite one.
+
+The public `StructureSheet` component and its `SheetData` and `ScheduleRow`
+types live in `src/document.rs`. Its `class="masthead"` attribute selects
+`.masthead` in `style.css`; styling follows ordinary CSS class rules. Text
+passed through component props is escaped by Yew. The native
+`to_html(data, true).await` helper includes a link to `style.css`;
+`to_html(data, false).await` leaves out that link and preserves the content
+and classes. Keep the CSS and bundled `fonts/` directory beside styled HTML
+when copying the export.
+
+The component module depends on Yew and Serde. `src/main.rs` handles fonts,
+files, and Fullbleed PDF rendering. The native helper is excluded from WASM
+builds, allowing the shared component to compile with Yew's `csr` feature in
+a browser application and `ssr` in the native renderer. PDF generation uses
+static HTML; it does not execute a client-side application.
+
+This separate example pins Fullbleed **2.5.34**, Yew **0.23.0**, and Tokio
+**1.54.1**. [Yew describes SSR as experimental](https://yew.rs/docs/advanced-topics/server-side-rendering).
+The downloadable project is built and run in documentation CI on Linux with
+Rust 1.85.0 and Windows with Rust 1.97.0. Checks cover the one-page fixture,
+a longer schedule, escaped text, repeated output, static HTML in Chromium,
+and compilation of the shared component with Yew's browser feature. This is
+a standalone example, not a tested integration with an existing application.
+Review browser and paginated PDF layout independently when changing a design.
+
## Keep building
For a Rust web application, [download the Axum PDF starter](../guides/axum-pdf.md).
diff --git a/examples/yew-sheet/Cargo.lock b/examples/yew-sheet/Cargo.lock
new file mode 100644
index 0000000..cd5731b
--- /dev/null
+++ b/examples/yew-sheet/Cargo.lock
@@ -0,0 +1,1021 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "base64ct"
+version = "1.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
+
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bincode"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
+dependencies = [
+ "bincode_derive",
+ "serde",
+ "unty",
+]
+
+[[package]]
+name = "bincode_derive"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
+dependencies = [
+ "virtue",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
+
+[[package]]
+name = "bytes"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
+
+[[package]]
+name = "console_error_panic_hook"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "fullbleed"
+version = "2.5.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f966cd06546d726c4ebbead2b7206d990ea06ed62a88e183e6e8d2a3b40c587"
+dependencies = [
+ "fullbleed_audit_contract",
+ "subsetter",
+ "unicode-bidi",
+]
+
+[[package]]
+name = "fullbleed-yew-sheet"
+version = "0.1.0"
+dependencies = [
+ "fullbleed",
+ "serde",
+ "serde_json",
+ "tokio",
+ "yew",
+]
+
+[[package]]
+name = "fullbleed_audit_contract"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61400ea6ceb63537e5089dd945823a33c293d7aa0765b76239f2d8ec2ef96127"
+
+[[package]]
+name = "futures"
+version = "0.3.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
+
+[[package]]
+name = "futures-io"
+version = "0.3.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.9",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d"
+
+[[package]]
+name = "futures-task"
+version = "0.3.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
+
+[[package]]
+name = "futures-util"
+version = "0.3.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "slab",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "wasi",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "gloo"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d15282ece24eaf4bd338d73ef580c6714c8615155c4190c781290ee3fa0fd372"
+dependencies = [
+ "gloo-console",
+ "gloo-dialogs",
+ "gloo-events",
+ "gloo-file",
+ "gloo-history",
+ "gloo-net",
+ "gloo-render",
+ "gloo-storage",
+ "gloo-timers",
+ "gloo-utils",
+ "gloo-worker",
+]
+
+[[package]]
+name = "gloo-console"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a17868f56b4a24f677b17c8cb69958385102fa879418052d60b50bc1727e261"
+dependencies = [
+ "gloo-utils",
+ "js-sys",
+ "serde",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-dialogs"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf4748e10122b01435750ff530095b1217cf6546173459448b83913ebe7815df"
+dependencies = [
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-events"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27c26fb45f7c385ba980f5fa87ac677e363949e065a083722697ef1b2cc91e41"
+dependencies = [
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-file"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97563d71863fb2824b2e974e754a81d19c4a7ec47b09ced8a0e6656b6d54bd1f"
+dependencies = [
+ "gloo-events",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-history"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "903f432be5ba34427eac5e16048ef65604a82061fe93789f2212afc73d8617d6"
+dependencies = [
+ "getrandom",
+ "gloo-events",
+ "gloo-utils",
+ "serde",
+ "serde-wasm-bindgen",
+ "serde_urlencoded",
+ "thiserror 1.0.69",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-net"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43aaa242d1239a8822c15c645f02166398da4f8b5c4bae795c1f5b44e9eee173"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-sink",
+ "gloo-utils",
+ "http",
+ "js-sys",
+ "pin-project",
+ "serde",
+ "serde_json",
+ "thiserror 1.0.69",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-render"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56008b6744713a8e8d98ac3dcb7d06543d5662358c9c805b4ce2167ad4649833"
+dependencies = [
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-storage"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a"
+dependencies = [
+ "gloo-utils",
+ "js-sys",
+ "serde",
+ "serde_json",
+ "thiserror 1.0.69",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-timers"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "gloo-utils"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa"
+dependencies = [
+ "js-sys",
+ "serde",
+ "serde_json",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-worker"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "085f262d7604911c8150162529cefab3782e91adb20202e8658f7275d2aefe5d"
+dependencies = [
+ "bincode 1.3.3",
+ "futures",
+ "gloo-utils",
+ "gloo-worker-macros",
+ "js-sys",
+ "pinned",
+ "serde",
+ "thiserror 1.0.69",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+]
+
+[[package]]
+name = "gloo-worker-macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "956caa58d4857bc9941749d55e4bd3000032d8212762586fa5705632967140e7"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+
+[[package]]
+name = "hermit-abi"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284"
+
+[[package]]
+name = "html-escape"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9356095b4b41197bba32173600e1582792cda618f65d12f68e2e77d273413c5"
+
+[[package]]
+name = "http"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "implicit-clone"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1689b939ee35e3a075b0834b5672efd43aec8a6e81a1c6002b76a5ca2f211ae0"
+dependencies = [
+ "implicit-clone-derive",
+ "indexmap",
+]
+
+[[package]]
+name = "implicit-clone-derive"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "699c1b6d335e63d0ba5c1e1c7f647371ce989c3bcbe1f7ed2b85fa56e3bd1a21"
+dependencies = [
+ "quote",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
+name = "js-sys"
+version = "0.3.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5"
+dependencies = [
+ "cfg-if",
+ "futures-util",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.191"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
+
+[[package]]
+name = "memchr"
+version = "2.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
+
+[[package]]
+name = "num_cpus"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+
+[[package]]
+name = "pin-project"
+version = "1.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
+
+[[package]]
+name = "pinned"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b"
+dependencies = [
+ "futures",
+ "rustversion",
+ "thiserror 1.0.69",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
+dependencies = [
+ "proc-macro2",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "proc-macro-crate"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
+dependencies = [
+ "once_cell",
+ "toml_edit",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.107"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
+
+[[package]]
+name = "rustversion"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
+
+[[package]]
+name = "ryu"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
+
+[[package]]
+name = "serde"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
+dependencies = [
+ "serde_core",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde-wasm-bindgen"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
+dependencies = [
+ "js-sys",
+ "serde",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.9",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
+
+[[package]]
+name = "subsetter"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38803281d1c23166c5ebcb455439a5d2afe711cc909cf88af72448c297756ad6"
+dependencies = [
+ "rustc-hash",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.119"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "3.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl 1.0.69",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e"
+dependencies = [
+ "thiserror-impl 2.0.21",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.9",
+]
+
+[[package]]
+name = "tokio"
+version = "1.54.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b52fd3255258d26fac7264ab5a76b53c13367136dc011d3d6ad4f8ed070396a3"
+dependencies = [
+ "pin-project-lite",
+ "tokio-macros",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.9",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokise"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba44a1b36f42a95bd21b5e4acc1468547f75a73e7cf619312408d1f74c7fb687"
+dependencies = [
+ "futures",
+ "gloo",
+ "num_cpus",
+ "once_cell",
+ "pin-project",
+ "pinned",
+ "tokio",
+ "tokio-stream",
+ "wasm-bindgen-futures",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+
+[[package]]
+name = "toml_edit"
+version = "0.19.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
+dependencies = [
+ "indexmap",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
+
+[[package]]
+name = "unty"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "virtue"
+version = "0.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.129"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cbab34de2d982e9b48e18d216d04c4a6f641066ff19ffb699980f591ee3610e"
+dependencies = [
+ "js-sys",
+ "tokio",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.129"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.129"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7"
+dependencies = [
+ "bumpalo",
+ "proc-macro2",
+ "quote",
+ "syn 3.0.9",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.129"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88261b9deccee56594c11a3460c462c41f58d148598fe70ad77070126a68aba4"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "winnow"
+version = "0.5.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "yew"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c154fadfa97eabdd3f3b79345ceeb9c05ee8f13f76d3d881d17fba618bf558d"
+dependencies = [
+ "base64ct",
+ "bincode 2.0.1",
+ "console_error_panic_hook",
+ "futures",
+ "gloo",
+ "html-escape",
+ "implicit-clone",
+ "indexmap",
+ "js-sys",
+ "rustversion",
+ "serde",
+ "slab",
+ "thiserror 2.0.21",
+ "tokio",
+ "tokise",
+ "tracing",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+ "yew-macro",
+]
+
+[[package]]
+name = "yew-macro"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08b883d84a035f57519d057f65a2a07ae25f1884ad485e1a9a523c9d880c1ad"
+dependencies = [
+ "prettyplease",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "zmij"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
diff --git a/examples/yew-sheet/Cargo.toml b/examples/yew-sheet/Cargo.toml
new file mode 100644
index 0000000..fe6d88f
--- /dev/null
+++ b/examples/yew-sheet/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "fullbleed-yew-sheet"
+version = "0.1.0"
+edition = "2024"
+rust-version = "1.85"
+license = "MIT"
+publish = false
+
+[dependencies]
+fullbleed = { version = "=2.5.34", features = ["svg_raster"] }
+serde = { version = "=1.0.229", features = ["derive"] }
+serde_json = "=1.0.151"
+tokio = { version = "=1.54.1", features = ["macros", "rt-multi-thread"] }
+yew = { version = "=0.23.0", features = ["ssr"] }
+
+[profile.dev]
+debug = 0
+incremental = false
diff --git a/examples/yew-sheet/LICENSE b/examples/yew-sheet/LICENSE
new file mode 100644
index 0000000..4c99bbd
--- /dev/null
+++ b/examples/yew-sheet/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Fullbleed Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/examples/yew-sheet/README.md b/examples/yew-sheet/README.md
new file mode 100644
index 0000000..e6c300b
--- /dev/null
+++ b/examples/yew-sheet/README.md
@@ -0,0 +1,78 @@
+# Yew components to PDF and HTML
+
+Write a document as Rust components, then export a PDF, styled browser HTML,
+or HTML without a stylesheet. The sample is a fictional event schedule with
+levels and break rows. It is useful for learning the rendering path; supply
+your own event data and rules for an actual structure sheet.
+
+The example pins Fullbleed 2.5.34, Yew 0.23.0 and Tokio 1.54.1. Its fonts and
+their license notices are included. PDF rendering does not launch a browser
+or use system fonts. Yew is a dependency of this example, not of Fullbleed.
+
+## Run
+
+With a native Rust toolchain installed, run from this directory:
+
+```sh
+cargo run --release --locked -- data.json output
+```
+
+The first build needs internet access to download Cargo dependencies. Open:
+
+- `output/document.pdf`: the print document.
+- `output/document.html`: the styled browser document.
+- `output/unstyled.html`: the same content and classes without a stylesheet.
+- `output/page-1.png`: a preview of the finalized PDF; longer documents have
+ one PNG per page.
+
+Keep `style.css` and the `fonts` directory beside the styled HTML when copying
+the export. Keep font license notices when redistributing the fonts. Choose a
+new output directory for each run; the program refuses to overwrite one.
+
+## Change the content and design
+
+Edit `data.json` to change the title, event settings, levels, breaks and notes.
+`SheetData` and `ScheduleRow` in `src/document.rs` define the input types. Text is
+passed through Yew's ordinary text nodes, which escape HTML markup.
+
+`StructureSheet` is the reusable component. For example, its
+`class="masthead"` attribute selects `.masthead` in `style.css`. Edit that
+rule to change the title panel, or add your own classes and CSS rules. The
+stylesheet is read at run time, so design edits do not require recompiling
+the Rust component. Screen rules provide a responsive page and a horizontally
+scrollable table on narrow displays; print rules supply the paper layout.
+
+The `to_html(data, styled)` function renders `SheetDocument` through
+`yew::ServerRenderer`, with hydration disabled. `styled = true` includes a link
+to `style.css`; `false` leaves that link out while preserving the content and
+classes. Fullbleed receives the unstyled HTML and the CSS separately to create
+the PDF. The browser HTML works without Fullbleed or JavaScript after export.
+
+When adding a font, register its bytes in the `AssetBundle`, add the matching
+browser `@font-face` rule, and include its license notice. This example checks
+the renderer's missing-glyph report before writing its outputs.
+
+## Reuse in an application
+
+The public `StructureSheet` component and native `to_html` function live in
+`src/document.rs`, which depends on Yew and Serde, independently of Fullbleed.
+`src/main.rs` handles files, fonts and PDF rendering. The document component
+can be shared with an existing Yew application when
+it can render from props without browser-only APIs. The PDF path needs the
+resulting static HTML; it does not execute a client-side Yew application or
+load a live webpage. In a web service, run synchronous PDF rendering outside
+the asynchronous request executor and apply the service's own input limits.
+
+The `to_html` helper is excluded from browser WASM builds. The shared document
+module can therefore use Yew's `csr` feature in a browser project and its `ssr`
+feature in the native renderer. Yew currently describes SSR as experimental;
+the checks for this sample cover its pinned versions and fixtures.
+
+See [Yew's server-rendering guide](https://yew.rs/docs/advanced-topics/server-side-rendering)
+and [Fullbleed's Rust guide](https://docs.fullbleed.dev/getting-started/rust/)
+for the two APIs involved. Browser layout and paginated PDF layout should be
+reviewed independently when changing a design.
+
+This example was authored and checked by an AI coding agent for the Fullbleed
+project. Its data is synthetic; it is not an integration with a third-party
+application.
diff --git a/examples/yew-sheet/data.json b/examples/yew-sheet/data.json
new file mode 100644
index 0000000..25f4bfb
--- /dev/null
+++ b/examples/yew-sheet/data.json
@@ -0,0 +1,29 @@
+{
+ "series": "Riverstone / Community Series",
+ "title": "Saturday mixed-game rotation",
+ "subtitle": "A sample structure for an afternoon around the table.",
+ "starting_stack": "20,000 chips",
+ "table_size": "6 players",
+ "registration": "Through level 4",
+ "rows": [
+ {"kind":"level","number":1,"minutes":20,"game":"No-limit hold’em","stakes":"100 / 200","ante":"200"},
+ {"kind":"level","number":2,"minutes":20,"game":"Pot-limit Omaha","stakes":"100 / 200","ante":"—"},
+ {"kind":"level","number":3,"minutes":20,"game":"Limit hold’em","stakes":"300 / 600","ante":"—"},
+ {"kind":"level","number":4,"minutes":20,"game":"Seven-card stud","stakes":"300 / 600","ante":"75"},
+ {"kind":"break","minutes":15,"label":"First interval · registration closes"},
+ {"kind":"level","number":5,"minutes":20,"game":"No-limit hold’em","stakes":"200 / 400","ante":"400"},
+ {"kind":"level","number":6,"minutes":20,"game":"Pot-limit Omaha","stakes":"200 / 400","ante":"—"},
+ {"kind":"level","number":7,"minutes":20,"game":"Limit hold’em","stakes":"600 / 1,200","ante":"—"},
+ {"kind":"level","number":8,"minutes":20,"game":"Seven-card stud","stakes":"600 / 1,200","ante":"150"},
+ {"kind":"break","minutes":10,"label":"Second interval"},
+ {"kind":"level","number":9,"minutes":20,"game":"No-limit hold’em","stakes":"400 / 800","ante":"800"},
+ {"kind":"level","number":10,"minutes":20,"game":"Pot-limit Omaha","stakes":"400 / 800","ante":"—"},
+ {"kind":"level","number":11,"minutes":20,"game":"Limit hold’em","stakes":"1,200 / 2,400","ante":"—"},
+ {"kind":"level","number":12,"minutes":20,"game":"Seven-card stud","stakes":"1,200 / 2,400","ante":"300"}
+ ],
+ "notes": [
+ "This is fictional layout data, not an event announcement or a complete set of tournament rules.",
+ "Blinds are shown for no-limit and pot-limit games; small and big bets are shown for limit games.",
+ "Provide your own event settings, break policy and complete rules before using a structure sheet."
+ ]
+}
diff --git a/examples/yew-sheet/fonts/DMSerifDisplay-OFL.txt b/examples/yew-sheet/fonts/DMSerifDisplay-OFL.txt
new file mode 100644
index 0000000..be384f0
--- /dev/null
+++ b/examples/yew-sheet/fonts/DMSerifDisplay-OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. Copyright 2019 Google LLC.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/examples/yew-sheet/fonts/DMSerifDisplay-Regular.ttf b/examples/yew-sheet/fonts/DMSerifDisplay-Regular.ttf
new file mode 100644
index 0000000..bc5ed0c
Binary files /dev/null and b/examples/yew-sheet/fonts/DMSerifDisplay-Regular.ttf differ
diff --git a/examples/yew-sheet/fonts/Inter-OFL.txt b/examples/yew-sheet/fonts/Inter-OFL.txt
new file mode 100644
index 0000000..21f6aff
--- /dev/null
+++ b/examples/yew-sheet/fonts/Inter-OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+https://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/examples/yew-sheet/fonts/Inter-Variable.ttf b/examples/yew-sheet/fonts/Inter-Variable.ttf
new file mode 100644
index 0000000..047c92f
Binary files /dev/null and b/examples/yew-sheet/fonts/Inter-Variable.ttf differ
diff --git a/examples/yew-sheet/src/document.rs b/examples/yew-sheet/src/document.rs
new file mode 100644
index 0000000..b4bdd13
--- /dev/null
+++ b/examples/yew-sheet/src/document.rs
@@ -0,0 +1,121 @@
+use serde::Deserialize;
+use yew::prelude::*;
+
+#[derive(Clone, PartialEq, Deserialize)]
+#[serde(deny_unknown_fields)]
+pub struct SheetData {
+ pub series: String,
+ pub title: String,
+ pub subtitle: String,
+ pub starting_stack: String,
+ pub table_size: String,
+ pub registration: String,
+ pub rows: Vec,
+ pub notes: Vec,
+}
+
+#[derive(Clone, PartialEq, Deserialize)]
+#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
+pub enum ScheduleRow {
+ Level {
+ number: u16,
+ minutes: u16,
+ game: String,
+ stakes: String,
+ ante: String,
+ },
+ Break {
+ minutes: u16,
+ label: String,
+ },
+}
+
+#[derive(Clone, PartialEq, Properties)]
+pub struct SheetProps {
+ pub data: SheetData,
+}
+
+#[component]
+pub fn StructureSheet(props: &SheetProps) -> Html {
+ let data = &props.data;
+ html! {
+
+
+