diff --git a/.agents/instructions/ArchieML/ARCHIEML-BETTY.md b/.agents/instructions/ArchieML/ARCHIEML-BETTY.md
new file mode 100644
index 0000000..77e603f
--- /dev/null
+++ b/.agents/instructions/ArchieML/ARCHIEML-BETTY.md
@@ -0,0 +1,647 @@
+# ArchieML-Veronica Language Reference
+
+Veronica is a more specific dialect of [ArchieML](https://archieml.org) designed for newsrooms and content editors. While ArchieML is "forgiving," Veronica makes some syntax more explicit to prevent common parsing errors, especially when working with multiline content and nested structures.
+
+## Table of Contents
+
+- [Keys and Values](#keys-and-values)
+- [Objects](#objects)
+ - [Nested Objects](#nested-objects)
+ - [Named Closures](#named-closures-veronica-extension)
+- [Arrays](#arrays)
+ - [Arrays of Objects](#arrays-of-objects)
+ - [Arrays of Strings (Simple Arrays)](#arrays-of-strings-simple-arrays)
+ - [Freeform Arrays](#freeform-arrays)
+ - [Nested Arrays](#nested-arrays)
+ - [Named Array Closures](#named-array-closures-veronica-extension)
+ - [Repeating Keys in Arrays](#repeating-keys-in-arrays-veronica-extension)
+- [Multiline Values](#multiline-values)
+ - [Veronica Multiline Syntax](#veronica-multiline-syntax-veronica-extension)
+ - [ArchieML Multiline Syntax](#archieml-multiline-syntax)
+- [Comments and Ignored Content](#comments-and-ignored-content)
+- [Escaping](#escaping)
+- [Hooks and Customization](#hooks-and-customization)
+
+## Keys and Values
+
+The simplest form of ArchieML is a key-value pair. Keys are defined by a colon, with the key on the left and the value on the right.
+
+```
+title: My Article
+author: Jane Smith
+published: 2024-01-15
+```
+
+**Result:**
+```json
+{
+ "title": "My Article",
+ "author": "Jane Smith",
+ "published": "2024-01-15"
+}
+```
+
+### Key Rules
+
+- Keys can contain letters, numbers, underscores, hyphens, and Unicode characters
+- Keys **cannot** contain: whitespace, `{`, `}`, `[`, `]`, `:`, `.`, or `+`
+- Keys are case-sensitive (`Title` and `title` are different)
+- Whitespace around keys and values is automatically trimmed
+
+### Ignored Content
+
+Any text that doesn't match ArchieML syntax is ignored, allowing you to include notes and comments freely:
+
+```
+This is just a note that will be ignored.
+
+title: My Article
+Here's another note about the article.
+author: Jane Smith
+```
+
+## Objects
+
+### Dot Notation
+
+You can create nested objects using dot notation:
+
+```
+colors.red: #ff0000
+colors.green: #00ff00
+colors.blue: #0000ff
+```
+
+**Result:**
+```json
+{
+ "colors": {
+ "red": "#ff0000",
+ "green": "#00ff00",
+ "blue": "#0000ff"
+ }
+}
+```
+
+### Object Blocks
+
+For more complex objects, use curly braces:
+
+```
+{colors}
+red: #ff0000
+green: #00ff00
+blue: #0000ff
+{}
+```
+
+**Result:** Same as above.
+
+### Nested Objects
+
+Prepend a period (`.`) to a block name to nest it within the current object:
+
+```
+{author}
+name: Jane Smith
+email: jane@example.com
+
+{.social}
+twitter: @janesmith
+github: janesmith
+{}
+
+bio: Award-winning journalist
+{}
+```
+
+**Result:**
+```json
+{
+ "author": {
+ "name": "Jane Smith",
+ "email": "jane@example.com",
+ "social": {
+ "twitter": "@janesmith",
+ "github": "janesmith"
+ },
+ "bio": "Award-winning journalist"
+ }
+}
+```
+
+### Closing Objects
+
+You can close an object in several ways:
+
+1. **Empty braces** `{}` - closes the current object
+2. **Opening a new object** at the same level
+3. **Named closure** (Veronica extension) - see below
+
+### Named Closures (Veronica Extension)
+
+Veronica extends ArchieML with named closures, allowing you to close a specific object by name, even if you're nested several levels deep:
+
+```
+{outer}
+value: test
+
+{.middle}
+value: nested
+
+{.inner}
+value: deep
+{/middle}
+
+This closes middle and inner, returning to outer scope.
+stillOuter: yes
+{}
+```
+
+**Result:**
+```json
+{
+ "outer": {
+ "value": "test",
+ "middle": {
+ "value": "nested",
+ "inner": {
+ "value": "deep"
+ }
+ },
+ "stillOuter": "yes"
+ }
+}
+```
+
+**Important:** The slash must be flush with the opening brace: `{/name}` works, but `{ /name }` does not.
+
+## Arrays
+
+### Arrays of Objects
+
+Arrays are defined using square brackets. The first key that repeats signals the start of a new item:
+
+```
+[people]
+name: Alice
+age: 30
+
+name: Bob
+age: 25
+[]
+```
+
+**Result:**
+```json
+{
+ "people": [
+ {"name": "Alice", "age": 30},
+ {"name": "Bob", "age": 25}
+ ]
+}
+```
+
+### Arrays of Strings (Simple Arrays)
+
+For simple lists of strings, use asterisks:
+
+```
+[tags]
+* news
+* technology
+* AI
+[]
+```
+
+**Result:**
+```json
+{
+ "tags": ["news", "technology", "AI"]
+}
+```
+
+### Freeform Arrays
+
+Freeform arrays (marked with `[+arrayName]`) preserve the order of different types of content. They're useful for mixed content like articles with text, images, and pull quotes:
+
+```
+[+content]
+This is a paragraph of text.
+
+Another paragraph here.
+
+{.image}
+src: photo.jpg
+caption: A beautiful photo
+{}
+
+More text after the image.
+
+{.quote}
+text: An inspiring quotation
+author: Famous Person
+{}
+[]
+```
+
+**Result:**
+```json
+{
+ "content": [
+ {"type": "text", "value": "This is a paragraph of text."},
+ {"type": "text", "value": "Another paragraph here."},
+ {"type": "image", "value": {"src": "photo.jpg", "caption": "A beautiful photo"}},
+ {"type": "text", "value": "More text after the image."},
+ {"type": "quote", "value": {"text": "An inspiring quotation", "author": "Famous Person"}}
+ ]
+}
+```
+
+### Nested Arrays
+
+Prepend a period to an array name to nest it:
+
+```
+[sections]
+title: Introduction
+
+[.subsections]
+heading: Background
+content: Context here
+[]
+
+heading: Methodology
+content: How we did it
+[]
+
+[/sections]
+```
+
+**Result:**
+```json
+{
+ "sections": [
+ {
+ "title": "Introduction",
+ "subsections": [
+ {"heading": "Background", "content": "Context here"},
+ {"heading": "Methodology", "content": "How we did it"}
+ ]
+ }
+ ]
+}
+```
+
+### Named Array Closures (Veronica Extension)
+
+Like objects, arrays support named closures to jump out of nested structures:
+
+```
+[parent]
+value: test
+
+[.nested]
+* one
+* two
+[/parent]
+
+This is outside the parent array.
+```
+
+This is especially useful when you have deeply nested arrays and want to exit multiple levels at once.
+
+### Repeating Keys in Arrays (Veronica Extension)
+
+**This is a key difference from standard ArchieML.**
+
+In Veronica, arrays start a new item when **any** key is redefined, not just the first key:
+
+```
+[items]
+name: First
+description: First item
+color: red
+
+description: Second item
+name: Second
+color: blue
+[]
+```
+
+**Result:**
+```json
+{
+ "items": [
+ {"name": "First", "description": "First item", "color": "red"},
+ {"name": "Second", "description": "Second item", "color": "blue"}
+ ]
+}
+```
+
+In standard ArchieML, the second item would need to redefine `name` (the first key) to start a new item. Veronica is more flexible: redefining `description` also triggers a new item.
+
+## Multiline Values
+
+### Veronica Multiline Syntax (Veronica Extension)
+
+Veronica introduces an explicit multiline syntax that's less ambiguous than ArchieML's `:end` syntax:
+
+```
+description::
+This is the first line of my description.
+
+This is the second paragraph.
+
+This can contain [brackets] and {braces} safely.
+::description
+```
+
+**Result:**
+```json
+{
+ "description": "This is the first line of my description.\n\nThis is the second paragraph.\n\nThis can contain [brackets] and {braces} safely."
+}
+```
+
+**Syntax:**
+- Open with `key::` (key followed by double colon)
+- Write your content on following lines
+- Close with `::key` (double colon followed by the same key name)
+
+This syntax is more explicit and helps prevent accidentally consuming subsequent content.
+
+### ArchieML Multiline Syntax
+
+Veronica still supports the traditional ArchieML multiline syntax with `:end`:
+
+```
+description:
+This is a multiline value.
+It continues until :end is found.
+:end
+```
+
+**Important:** Within multiline blocks, ArchieML syntax is **not** parsed. To include literal backslashes or the `:end` marker, use a backslash escape:
+
+```
+code:
+To end a multiline, use \:end
+A literal backslash: \\
+:end
+```
+
+## Comments and Ignored Content
+
+### Block Comments
+
+Use `:skip` and `:endskip` to comment out entire sections:
+
+```
+title: My Article
+
+:skip
+This entire section is ignored.
+author: Will Not Parse
+{test}
+{}
+:endskip
+
+published: 2024-01-15
+```
+
+**Result:**
+```json
+{
+ "title": "My Article",
+ "published": "2024-01-15"
+}
+```
+
+### Stop Parsing
+
+Use `:ignore` to immediately stop parsing. Everything after `:ignore` is ignored:
+
+```
+title: My Article
+author: Jane Smith
+
+:ignore
+
+This and everything below is completely ignored.
+Nothing here will be parsed.
+```
+
+**Result:**
+```json
+{
+ "title": "My Article",
+ "author": "Jane Smith"
+}
+```
+
+## Escaping
+
+Use a backslash (`\`) to escape special ArchieML characters when they appear at the start of a line in a multiline context:
+
+```
+description:
+\[This is not an array]
+\{This is not an object}
+\:end is not the end marker
+The real end:
+:end
+```
+
+**Note:** Escaping only works in multiline contexts and only for characters at the start of a line. Outside of multiline blocks, special characters are generally ignored if they don't form valid syntax.
+
+## Hooks and Customization
+
+Veronica provides several hooks for customizing parsing behavior:
+
+### `onFieldName(name: string) => string`
+
+Transform field names during parsing. Useful for normalizing keys:
+
+```javascript
+const result = parse(text, {
+ onFieldName: (name) => name.toLowerCase()
+});
+```
+
+This is particularly helpful when working with Google Docs, which may capitalize the first word of a line.
+
+### `onValue(value: any, key: string) => any`
+
+Transform values during parsing. Useful for type coercion:
+
+```javascript
+const result = parse(text, {
+ onValue: (value, key) => {
+ // Auto-convert boolean strings
+ if (value === "true") return true;
+ if (value === "false") return false;
+
+ // Auto-convert numbers
+ if (/^\d+$/.test(value)) return parseInt(value);
+ if (/^\d+\.\d+$/.test(value)) return parseFloat(value);
+
+ // Auto-parse ISO dates
+ if (/^\d{4}-\d{2}-\d{2}/.test(value)) {
+ return new Date(value);
+ }
+
+ return value;
+ }
+});
+```
+
+### `onEnter(keypath: string[], item: any) => void`
+
+Called when entering an object or array. The `keypath` is an array of strings representing the path from the root:
+
+```javascript
+const result = parse(text, {
+ onEnter: (keypath, item) => {
+ console.log(`Entering: ${keypath.join('.')}`);
+ console.log(`Type: ${Array.isArray(item) ? 'array' : 'object'}`);
+ }
+});
+```
+
+### `onExit(keypath: string[], item: any) => any`
+
+Called when exiting an object or array. This is ideal for validation and adding computed properties. If you return a value, it replaces the item in the output:
+
+```javascript
+const result = parse(text, {
+ onExit: (keypath, item) => {
+ // Validate required fields
+ if (keypath[0] === "person" && !item.name) {
+ throw new Error("Person must have a name");
+ }
+
+ // Add computed properties
+ if (keypath[0] === "person" && item.firstName && item.lastName) {
+ item.fullName = `${item.firstName} ${item.lastName}`;
+ }
+
+ return item; // Return the modified item
+ }
+});
+```
+
+**Example with validation:**
+
+```javascript
+const text = `
+{author}
+firstName: Jane
+lastName: Smith
+{/author}
+`;
+
+const result = parse(text, {
+ onExit: (keypath, item) => {
+ if (keypath[0] === "author") {
+ if (!item.firstName || !item.lastName) {
+ throw new Error("Author must have both firstName and lastName");
+ }
+ // Add computed fullName
+ item.fullName = `${item.firstName} ${item.lastName}`;
+ }
+ return item;
+ }
+});
+
+// Result: { author: { firstName: "Jane", lastName: "Smith", fullName: "Jane Smith" } }
+```
+
+### `verbose: boolean`
+
+Enable verbose logging to see detailed parsing information:
+
+```javascript
+const result = parse(text, {
+ verbose: true
+});
+```
+
+## Complete Example
+
+Here's a comprehensive example showing many Veronica features:
+
+```
+title: Understanding Veronica
+subtitle: A Guide to Structured Content
+published: 2024-01-15
+
+{metadata}
+tags.primary: archieml
+tags.secondary: parsing
+wordCount: 1500
+{/metadata}
+
+intro::
+This is a multiline introduction to Veronica.
+
+It supports multiple paragraphs and preserves formatting.
+::intro
+
+[sections]
+heading: Introduction
+body: Welcome to Veronica, a dialect of ArchieML.
+
+heading: Features
+body: Veronica adds several improvements over standard ArchieML.
+
+[.examples]
+* Named closures
+* Explicit multiline syntax
+* Better array handling
+[/sections]
+
+[+mixedContent]
+This is a text paragraph.
+
+{.callout}
+type: warning
+message: Remember to close your arrays!
+{}
+
+Another text paragraph here.
+[]
+
+{author}
+firstName: Jane
+lastName: Smith
+email: jane@example.com
+
+{.social}
+twitter: @janesmith
+github: janesmith
+{/author}
+
+footer: Copyright 2024
+```
+
+This example demonstrates:
+- Simple key-value pairs
+- Object blocks with nested objects
+- Dot notation for nested keys
+- Veronica multiline syntax (`key::` / `::key`)
+- Arrays of objects with nested arrays
+- Freeform arrays with mixed content
+- Named closures (`{/author}`, `[/sections]`)
+
+## Summary of Veronica Extensions
+
+Veronica extends ArchieML with these key features:
+
+1. **Named closures** - `{/name}` and `[/name]` to exit specific nesting levels
+2. **Explicit multiline syntax** - `key::` / `::key` delimiters for unambiguous multiline values
+3. **Flexible array items** - Any redefined key starts a new array item, not just the first key
+4. **Lifecycle hooks** - `onEnter` and `onExit` callbacks for validation and transformation
+5. **Value transformation** - `onFieldName` and `onValue` hooks for custom processing
+
+These changes make Veronica more predictable and robust when working with complex structured content, especially in collaborative editing environments like Google Docs.
diff --git a/.agents/instructions/graphics-components/llms.md b/.agents/instructions/graphics-components/llms.md
new file mode 100644
index 0000000..143584e
--- /dev/null
+++ b/.agents/instructions/graphics-components/llms.md
@@ -0,0 +1,483 @@
+---
+applyTo: "**/*.svelte"
+---
+
+## Graphics components
+
+The `@reuters-graphics/graphics-components` library includes pre-styled components for easily adding graphics or other elements to a page.
+
+### Adding new components to a page
+
+Components from the `@reuters-graphics/graphics-components` library are often added to the `#each` loop in `src/lib/App.svelte` that loops over `content.blocks`.
+
+`content` represents text content pulled from our CMS as JSON that is passed into components via props.
+
+Each block in `content.blocks` (i.e., "content block") is usually an object with a `type` property and additional properties specific to the block type. For example:
+
+- **Text Block**:
+ ```json
+ {
+ "type": "text",
+ "text": "This is a text block."
+ }
+ ```
+- **AI Graphic Block**
+ ```json
+ {
+ "type": "ai-graphic",
+ "chart": "AiMap",
+ "width": "normal",
+ "textWidth": "normal",
+ "title": "Optional title of the graphic",
+ "description": "Optional chatter describes more about the graphic.",
+ "notes": "Note: Optional note clarifying something in the data.\r\n\r\nSource: Optional source of the data.",
+ "altText": "Add a description of the graphic for screen readers. This is invisible on the page."
+ }
+ ```
+
+To add a new component to the loop:
+
+1. Import the component in the script portion of the Svelte component.
+2. Add a new `else if` condition in the `{#each content.blocks as block}` loop to handle the new block type.
+3. Pass the required props to the component, ensuring they match the structure of the content block object.
+
+For example, to add a new FeaturePhoto:
+
+```svelte
+
+
+{#each content.blocks as block}
+
+ {#if block.type === 'text'}
+
+
+
+
+
+ {:else if block.type === 'feature-photo'}
+
+ {:else}
+
+ {/if}
+{/each}
+```
+
+### Paths to multimedia files
+
+Notice in the example above, we append the `assets` variable from SvelteKit's `$app/paths` module to the `src` path we got from the content block.
+
+Always assume that paths to local multimedia files including images and videos specified in content blocks are relative and must be prefixed with the `assets` variable to make them absolute. For example:
+
+```svelte
+
+```
+
+### Adding AI Graphics
+
+AI (i.e., Adobe Illustrator) graphics are added to the page by importing a component from the `src/lib/ai2svelte/` directory and then adding that graphic to the `aiCharts` object in `src/lib/App.svelte`. Then the object key for that chart is included in the content block's `chart` property.
+
+For example, to use an AI graphic from `src/lib/ai2svelte/map.svelte`:
+
+- The AI graphic component is imported and added to the `aiCharts` object in `src/lib/App.svelte`:
+
+ ```svelte
+
+ ```
+
+- Now the content block will specify the key to the chart in `aiCharts` in the `chart` property:
+
+ ```json
+ {
+ "type": "ai-graphic",
+ "chart": "Map",
+ "width": "normal",
+ "textWidth": "normal",
+ "title": "My map",
+ "description": "A map of the area",
+ "notes": "Source: DataSource.org",
+ "altText": "A map of a specific area showing something interesting"
+ }
+ ```
+
+- Now the `{:else if block.type === 'ai-graphic'}` block in `src/lib/App.svelte` uses that key to get the component:
+
+ ```svelte
+ {#each content.blocks as block}
+
+ {#if block.type === 'text'}
+
+
+
+ {:else if block.type === 'ai-graphic'}
+ {#if !aiCharts[block.chart]}
+
+ {:else}
+ {@const AiChart = aiCharts[block.chart]}
+
+
+
+ {/if}
+
+
+ {/if}
+ {/each}
+ ```
+
+### Refer to graphics components Storybook
+
+If you're unsure how to implement a particular graphics component, suggest the user check the Storybook documentation site, which is hosted on GitHub at https://reuters-graphics.github.io/graphics-components/.
+
+### Writing content blocks in our CMS
+
+While the text content in the `content` object is formatted as JSON, that data is written into our CMS (which is called "RNGS.io") using ArchieML syntax.
+
+**When suggesting what content blocks to add for components, please also suggest how to write that content in our CMS (RNGS.io) using ArchieML.**
+
+#### ArchieML
+
+ArchieML is a lightweight and intuitive markup language that allows for easy structuring of data within text documents. It is designed to be human-readable, very flexible, and is particularly useful for creating structured data by users who may never have seen ArchieML or any other markup language before.
+
+##### Basic Syntax
+
+- **Keys and Values**
+
+ - Definition: Key-value pairs are defined by a line starting with a key followed by a colon. Keys can include any unicode character except whitespace and specific characters used within ArchieML ({ } [ ] : . +).
+
+ - Example:
+
+ ```
+ key: This is a value
+ ☃: Unicode Snowman for you and you and you!
+ ```
+
+ - Parsed JSON:
+
+ ```json
+ {
+ "key": "This is a value",
+ "☃": "Unicode Snowman for you and you and you!"
+ }
+ ```
+
+ - Whitespace around keys and values is ignored. Keys are case-sensitive.
+
+- **Multi-line Values**: Multi-line values are anchored with `:end`. All whitespace is preserved.
+
+ - Example:
+
+ ```
+ key: value
+ More value
+
+ Even more value
+ :end
+ ```
+
+ - Parsed JSON:
+ ```json
+ {
+ "key": "value\n More value\n\nEven more value"
+ }
+ ```
+ - Escape Characters: Lines that would be interpreted as keys or commands can be escaped with a backslash `\`.
+ - Example:
+ ```
+ key: value
+ \:end
+ :end
+ ```
+ - Parsed JSON:
+ ```json
+ {
+ "key": "value\n:end"
+ }
+ ```
+
+- **Nested Structures**
+
+ - **Dot-Notation**: Use dot-notation for creating nested objects.
+ - Example:
+ ```
+ colors.red: #f00
+ colors.green: #0f0
+ colors.blue: #00f
+ ```
+ - Parsed JSON:
+ ```json
+ {
+ "colors": {
+ "red": "#f00",
+ "green": "#0f0",
+ "blue": "#00f"
+ }
+ }
+ ```
+ - **Object Blocks**: Group keys using object blocks defined by {}. Close an object with {} or by starting a new object.
+
+ - Example:
+
+ ```
+ {colors}
+ red: #f00
+ green: #0f0
+ blue: #00f
+ {}
+
+ {numbers}
+ one: 1
+ ten: 10
+ one-hundred: 100
+ {}
+ ```
+
+ - Parsed JSON:
+ ```json
+ {
+ "colors": {
+ "red": "#f00",
+ "green": "#0f0",
+ "blue": "#00f"
+ },
+ "numbers": {
+ "one": "1",
+ "ten": "10",
+ "one-hundred": "100"
+ }
+ }
+ ```
+
+- **Arrays**
+
+ - **Arrays of Objects**: Define arrays with brackets [arrayName]. New objects start when the first key is re-encountered.
+
+ - Example:
+
+ ```
+ [arrayName]
+ name: Amanda
+ age: 26
+
+ name: Tessa
+ age: 30
+ []
+ ```
+
+ - Parsed JSON:
+ ```json
+ {
+ "arrayName": [
+ {
+ "name": "Amanda",
+ "age": "26"
+ },
+ {
+ "name": "Tessa",
+ "age": "30"
+ }
+ ]
+ }
+ ```
+
+ - **Arrays of Strings**: Simple arrays use _ for elements. If _ is first, the array ignores key-value pairs.
+ - Example:
+ ```
+ [days]
+ * Sunday
+ * Monday
+ * Tuesday
+ * Wednesday
+ * Thursday
+ * Friday
+ * Saturday
+ []
+ ```
+ - Parsed JSON:
+ ```json
+ {
+ "days": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ]
+ }
+ ```
+ - **Nested Arrays**: Nested arrays use dot notation and are closed with `[]`.
+
+ - Example:
+
+ ```
+ [days]
+ name: Monday
+ [.tasks]
+ * Clean dishes
+ * Pick up room
+ []
+
+ name: Tuesday
+ [.tasks]
+ * Buy milk
+ []
+ ```
+
+ - Parsed JSON:
+ ```json
+ {
+ "days": [
+ {
+ "name": "Monday",
+ "tasks": ["Clean dishes", "Pick up room"]
+ },
+ {
+ "name": "Tuesday",
+ "tasks": ["Buy milk"]
+ }
+ ]
+ }
+ ```
+
+#### ArchieML conventions in our CMS
+
+Usually, content blocks are written in our CMS as objects inside an ArchieML array called `blocks` and always start with a `type:` key/value pair that defines the type of the content block object.
+
+For example, a user adding a content block for a FeaturePhoto component, might add the following to the existing `[blocks]` array in our CMS:
+
+```
+[blocks]
+
+type: feature-photo
+src: images/myPhoto.jpg
+alt: Alt text for my photo...
+
+... which extends over multiple lines.
+:end
+caption: A photo of something interesting.
+credit: Jane Doe
+
+[]
+```
+
+### Graphics components style tokens
+
+As well as Svelte components, the graphics components library includes a tailwind-like style system that can be used to style components and other page elements by adding a class or through SCSS mixins.
+
+These classes and mixins are defined as individual "tokens" representing the value for an individual style rule, like `font-size` or `color`. Each token sets just one style rule, and multiple tokens are combined together to style an element, like a `
`.
+
+Each set of tokens has several levels that represent the different values a style rule can take in our design system and are grouped in how they're named to make them easier to remember.
+
+For example, font weight tokens include `font-thin`, `font-light`, and `font-bold` which correspond to the style rules `font-weight: 100;`, `font-weight: 300;`, and `font-weight: 700;`, respectively. And those tokens can be applied via class name or SCSS mixin. For example:
+
+```svelte
+
+
Here is some bold text with some thin text in it!
+
+
+```
+
+Not all our style tokens have both class names as well as SCSS mixins available to apply them.
+
+**Please use the tokens defined in the SCSS partials in the [@reuters-graphics/graphics-components/dist/scss/tokens/ directory](./../../../node_modules/@reuters-graphics/graphics-components/dist/scss/tokens/) liberally in instructions and code samples, BUT be sure the token exists before suggesting it. DO NOT MAKE UP TOKENS, CLASS NAMES OR SCSS MIXINS!**
+
+If you're not sure if there is a token to apply a particular style, you can refer the user to our Storybook documentation site for them at: https://reuters-graphics.github.io/graphics-components/?path=/docs/styles-intro--docs.
+
+#### Using style tokens
+
+To use a token to style an element, you can apply it directly to the element through a class name. For example, to apply the `text-primary` token (controlling font colour) you can apply it like this:
+
+```svelte
+
Lorem ipsum...
+```
+
+OR you can apply some tokens via an SCSS mixin. For example:
+
+```svelte
+
Lorem ipsum...
+
+
+```
+
+**Be sure to always include the `@use` line that imports the SCSS mixins from the library in your SCSS/styling suggestions.**
+
+Please consider the SCSS mixins and classes defined in the [@reuters-graphics/graphics-components/dist/scss/tokens/ directory](./../../../node_modules/@reuters-graphics/graphics-components/dist/scss/tokens/).
+
+#### Spacing tokens
+
+We have a special set of tokens to control spacing, i.e., paddings and margins. They operate like tailwind's padding and margin system. For example, `mt-1` represents `margin-top: 0.25rem;` and `px-2` represents `padding-right: 0.5rem; padding-left: 0.5rem;`, etc. These tokens can be applied only through a class.
+
+These tokens are all defined as a combination of a prefix and a level. The prefix is something like `mb` for bottom margin or `py` for padding top and bottom. The level is a number representing how large the padding are margin should be. The levels go like this: 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, then increasing by 4 each time up to 96. For example, the full token set for top margin would be `mt-0`, `mt-0.5`, `mt-1`, `mt-1.5`, and so on.
+
+We also have a set of spacing tokens designed to work with _fluid_ typography. These are prefixed beginning with the letter `f`, for example, `fmb-1` represents a _fluid_ margin bottom, `margin-bottom: clamp(0.31rem, 0.31rem + 0vw, 0.31rem);`. These tokens can be applied through a class AND an SCSS mixin. For example:
+
+```svelte
+
Some text with margin and padding
+
+
+```
+
+You should recommend fluid margin and padding tokens for spacing fluidly-sized typographical elements or elements that are spaced _next to_ fluidly-sized typographical elements. Typographical elements include page headings, paragraphs or elements containing text, generally.
diff --git a/.agents/skills/svelte-code-writer/SKILL.md b/.agents/skills/svelte-code-writer/SKILL.md
new file mode 100644
index 0000000..f90b996
--- /dev/null
+++ b/.agents/skills/svelte-code-writer/SKILL.md
@@ -0,0 +1,66 @@
+---
+name: svelte-code-writer
+description: CLI tools for Svelte 5 documentation lookup and code analysis. MUST be used whenever creating, editing or analyzing any Svelte component (.svelte) or Svelte module (.svelte.ts/.svelte.js). If possible, this skill should be executed within the svelte-file-editor agent for optimal results.
+---
+
+# Svelte 5 Code Writer
+
+## CLI Tools
+
+You have access to `@sveltejs/mcp` CLI for Svelte-specific assistance. Use these commands via `npx`:
+
+### List Documentation Sections
+
+```bash
+npx @sveltejs/mcp list-sections
+```
+
+Lists all available Svelte 5 and SvelteKit documentation sections with titles and paths.
+
+### Get Documentation
+
+```bash
+npx @sveltejs/mcp get-documentation ",,..."
+```
+
+Retrieves full documentation for specified sections. Use after `list-sections` to fetch relevant docs.
+
+**Example:**
+
+```bash
+npx @sveltejs/mcp get-documentation "$state,$derived,$effect"
+```
+
+### Svelte Autofixer
+
+```bash
+npx @sveltejs/mcp svelte-autofixer "" [options]
+```
+
+Analyzes Svelte code and suggests fixes for common issues.
+
+**Options:**
+
+- `--async` - Enable async Svelte mode (default: false)
+- `--svelte-version` - Target version: 4 or 5 (default: 5)
+
+**Examples:**
+
+```bash
+# Analyze inline code (escape $ as \$)
+npx @sveltejs/mcp svelte-autofixer ''
+
+# Analyze a file
+npx @sveltejs/mcp svelte-autofixer ./src/lib/Component.svelte
+
+# Target Svelte 4
+npx @sveltejs/mcp svelte-autofixer ./Component.svelte --svelte-version 4
+```
+
+**Important:** When passing code with runes (`$state`, `$derived`, etc.) via the terminal, escape the `$` character as `\$` to prevent shell variable substitution.
+
+## Workflow
+
+1. **Uncertain about syntax?** Run `list-sections` then `get-documentation` for relevant topics
+2. **Reviewing/debugging?** Run `svelte-autofixer` on the code to detect issues
+3. **Always validate** - Run `svelte-autofixer` before finalizing any Svelte component
\ No newline at end of file
diff --git a/.github/agents/Svelte.agent.md b/.github/agents/Svelte.agent.md
new file mode 100644
index 0000000..9f81164
--- /dev/null
+++ b/.github/agents/Svelte.agent.md
@@ -0,0 +1,201 @@
+---
+name: Svelte
+description: "Use when: building Svelte components, writing SvelteKit routes, debugging Svelte reactivity, migrating from Svelte 4 to 5, using runes ($state, $derived, $effect, $props), creating stores, animations, transitions, form actions, or any Svelte/SvelteKit question."
+argument-hint: "Describe the Svelte component or SvelteKit feature you want to build, fix, or explain."
+tools: [read, edit, search, todo, mcp_svelte_offici/*]
+---
+
+You are a Svelte expert tasked to build components and utilities for Svelte developers. If you need documentation for anything related to Svelte you can invoke the tool `get-documentation` with one of the following paths. However: before invoking the `get-documentation` tool, try to answer the users query using your own knowledge and the `svelte-autofixer` tool. Be mindful of how many section you request, since it is token-intensive!
+
+
+- title: Overview, use_cases: use title and path to estimate use case, path: ai/overview
+- title: Local setup, use_cases: use title and path to estimate use case, path: ai/local-setup
+- title: Remote setup, use_cases: use title and path to estimate use case, path: ai/remote-setup
+- title: Tools, use_cases: use title and path to estimate use case, path: ai/tools
+- title: Resources, use_cases: use title and path to estimate use case, path: ai/resources
+- title: Prompts, use_cases: use title and path to estimate use case, path: ai/prompts
+- title: Overview, use_cases: use title and path to estimate use case, path: ai/plugin
+- title: Subagent, use_cases: use title and path to estimate use case, path: ai/subagent
+- title: Overview, use_cases: use title and path to estimate use case, path: ai/opencode-plugin
+- title: Subagent, use_cases: use title and path to estimate use case, path: ai/opencode-subagent
+- title: Overview, use_cases: use title and path to estimate use case, path: ai/skills
+- title: Overview, use_cases: project setup, creating new svelte apps, scaffolding, cli tools, initializing projects, path: cli/overview
+- title: Frequently asked questions, use_cases: project setup, initializing new svelte projects, troubleshooting cli installation, package manager configuration, path: cli/faq
+- title: sv create, use_cases: project setup, starting new sveltekit app, initializing project, creating from playground, choosing project template, path: cli/sv-create
+- title: sv add, use_cases: project setup, adding features to existing projects, integrating tools, testing setup, styling setup, authentication, database setup, deployment adapters, path: cli/sv-add
+- title: sv check, use_cases: code quality, ci/cd pipelines, error checking, typescript projects, pre-commit hooks, finding unused css, accessibility auditing, production builds, path: cli/sv-check
+- title: sv migrate, use_cases: migration, upgrading svelte versions, upgrading sveltekit versions, modernizing codebase, svelte 3 to 4, svelte 4 to 5, sveltekit 1 to 2, adopting runes, refactoring deprecated apis, path: cli/sv-migrate
+- title: devtools-json, use_cases: development setup, chrome devtools integration, browser-based editing, local development workflow, debugging setup, path: cli/devtools-json
+- title: drizzle, use_cases: database setup, sql queries, orm integration, data modeling, postgresql, mysql, sqlite, server-side data access, database migrations, type-safe queries, path: cli/drizzle
+- title: eslint, use_cases: code quality, linting, error detection, project setup, code standards, team collaboration, typescript projects, path: cli/eslint
+- title: better-auth, use_cases: use title and path to estimate use case, path: cli/better-auth
+- title: mcp, use_cases: use title and path to estimate use case, path: cli/mcp
+- title: mdsvex, use_cases: blog, content sites, markdown rendering, documentation sites, technical writing, cms integration, article pages, path: cli/mdsvex
+- title: paraglide, use_cases: internationalization, multi-language sites, i18n, translation, localization, language switching, global apps, multilingual content, path: cli/paraglide
+- title: playwright, use_cases: browser testing, e2e testing, integration testing, test automation, quality assurance, ci/cd pipelines, testing user flows, path: cli/playwright
+- title: prettier, use_cases: code formatting, project setup, code style consistency, team collaboration, linting configuration, path: cli/prettier
+- title: storybook, use_cases: component development, design systems, ui library, isolated component testing, documentation, visual testing, component showcase, path: cli/storybook
+- title: sveltekit-adapter, use_cases: deployment, production builds, hosting setup, choosing deployment platform, configuring adapters, static site generation, node server, vercel, cloudflare, netlify, path: cli/sveltekit-adapter
+- title: tailwindcss, use_cases: project setup, styling, css framework, rapid prototyping, utility-first css, design systems, responsive design, adding tailwind to svelte, path: cli/tailwind
+- title: vitest, use_cases: testing, unit tests, component testing, test setup, quality assurance, ci/cd pipelines, test-driven development, path: cli/vitest
+- title: add-on, use_cases: use title and path to estimate use case, path: cli/add-on
+- title: sv-utils, use_cases: use title and path to estimate use case, path: cli/sv-utils
+- title: Introduction, use_cases: learning sveltekit, project setup, understanding framework basics, choosing between svelte and sveltekit, getting started with full-stack apps, path: kit/introduction
+- title: Creating a project, use_cases: project setup, starting new sveltekit app, initial development environment, first-time sveltekit users, scaffolding projects, path: kit/creating-a-project
+- title: Project types, use_cases: deployment, project setup, choosing adapters, ssg, spa, ssr, serverless, mobile apps, desktop apps, pwa, offline apps, browser extensions, separate backend, docker containers, path: kit/project-types
+- title: Project structure, use_cases: project setup, understanding file structure, organizing code, starting new project, learning sveltekit basics, path: kit/project-structure
+- title: Web standards, use_cases: always, any sveltekit project, data fetching, forms, api routes, server-side rendering, deployment to various platforms, path: kit/web-standards
+- title: Routing, use_cases: routing, navigation, multi-page apps, project setup, file structure, api endpoints, data loading, layouts, error pages, always, path: kit/routing
+- title: Loading data, use_cases: data fetching, api calls, database queries, dynamic routes, page initialization, loading states, authentication checks, ssr data, form data, content rendering, path: kit/load
+- title: Form actions, use_cases: forms, user input, data submission, authentication, login systems, user registration, progressive enhancement, validation errors, path: kit/form-actions
+- title: Page options, use_cases: prerendering static sites, ssr configuration, spa setup, client-side rendering control, url trailing slash handling, adapter deployment config, build optimization, path: kit/page-options
+- title: State management, use_cases: sveltekit, server-side rendering, ssr, state management, authentication, data persistence, load functions, context api, navigation, component lifecycle, path: kit/state-management
+- title: Remote functions, use_cases: data fetching, server-side logic, database queries, type-safe client-server communication, forms, user input, mutations, authentication, crud operations, optimistic updates, path: kit/remote-functions
+- title: Building your app, use_cases: production builds, deployment preparation, build process optimization, adapter configuration, preview before deployment, path: kit/building-your-app
+- title: Adapters, use_cases: deployment, production builds, hosting setup, choosing deployment platform, configuring adapters, path: kit/adapters
+- title: Zero-config deployments, use_cases: deployment, production builds, hosting setup, choosing deployment platform, ci/cd configuration, path: kit/adapter-auto
+- title: Node servers, use_cases: deployment, production builds, node.js hosting, custom server setup, environment configuration, reverse proxy setup, docker deployment, systemd services, path: kit/adapter-node
+- title: Static site generation, use_cases: static site generation, ssg, prerendering, deployment, github pages, spa mode, blogs, documentation sites, marketing sites, path: kit/adapter-static
+- title: Single-page apps, use_cases: spa mode, single-page apps, client-only rendering, static hosting, mobile app wrappers, no server-side logic, adapter-static setup, fallback pages, path: kit/single-page-apps
+- title: Cloudflare, use_cases: deployment, cloudflare workers, cloudflare pages, hosting setup, production builds, serverless deployment, edge computing, path: kit/adapter-cloudflare
+- title: Cloudflare Workers, use_cases: deploying to cloudflare workers, cloudflare workers sites deployment, legacy cloudflare adapter, wrangler configuration, cloudflare platform bindings, path: kit/adapter-cloudflare-workers
+- title: Netlify, use_cases: deployment, netlify hosting, production builds, serverless functions, edge functions, static site hosting, path: kit/adapter-netlify
+- title: Vercel, use_cases: deployment, vercel hosting, production builds, serverless functions, edge functions, isr, image optimization, environment variables, path: kit/adapter-vercel
+- title: Writing adapters, use_cases: custom deployment, building adapters, unsupported platforms, adapter development, custom hosting environments, path: kit/writing-adapters
+- title: Advanced routing, use_cases: advanced routing, dynamic routes, file viewers, nested paths, custom 404 pages, url validation, route parameters, multi-level navigation, path: kit/advanced-routing
+- title: Hooks, use_cases: authentication, logging, error tracking, request interception, api proxying, custom routing, internationalization, database initialization, middleware logic, session management, path: kit/hooks
+- title: Errors, use_cases: error handling, custom error pages, 404 pages, api error responses, production error logging, error tracking, type-safe errors, path: kit/errors
+- title: Link options, use_cases: routing, navigation, multi-page apps, performance optimization, link preloading, forms with get method, search functionality, focus management, scroll behavior, path: kit/link-options
+- title: Service workers, use_cases: offline support, pwa, caching strategies, performance optimization, precaching assets, network resilience, progressive web apps, path: kit/service-workers
+- title: Server-only modules, use_cases: api keys, environment variables, sensitive data protection, backend security, preventing data leaks, server-side code isolation, path: kit/server-only-modules
+- title: Snapshots, use_cases: forms, user input, preserving form data, multi-step forms, navigation state, preventing data loss, textarea content, input fields, comment systems, surveys, path: kit/snapshots
+- title: Shallow routing, use_cases: modals, dialogs, image galleries, overlays, history-driven ui, mobile-friendly navigation, photo viewers, lightboxes, drawer menus, path: kit/shallow-routing
+- title: Observability, use_cases: performance monitoring, debugging, observability, tracing requests, production diagnostics, analyzing slow requests, finding bottlenecks, monitoring server-side operations, path: kit/observability
+- title: Packaging, use_cases: building component libraries, publishing npm packages, creating reusable svelte components, library development, package distribution, path: kit/packaging
+- title: Auth, use_cases: authentication, login systems, user management, session handling, jwt tokens, protected routes, user credentials, authorization checks, path: kit/auth
+- title: Performance, use_cases: performance optimization, slow loading pages, production deployment, debugging performance issues, reducing bundle size, improving load times, path: kit/performance
+- title: Icons, use_cases: icons, ui components, styling, css frameworks, tailwind, unocss, performance optimization, dependency management, path: kit/icons
+- title: Images, use_cases: image optimization, responsive images, performance, hero images, product photos, galleries, cms integration, cdn setup, asset management, path: kit/images
+- title: Accessibility, use_cases: always, any sveltekit project, screen reader support, keyboard navigation, multi-page apps, client-side routing, internationalization, multilingual sites, path: kit/accessibility
+- title: SEO, use_cases: seo optimization, search engine ranking, content sites, blogs, marketing sites, public-facing apps, sitemaps, amp pages, meta tags, performance optimization, path: kit/seo
+- title: Frequently asked questions, use_cases: troubleshooting package imports, library compatibility issues, client-side code execution, external api integration, middleware setup, database configuration, view transitions, yarn configuration, path: kit/faq
+- title: Integrations, use_cases: project setup, css preprocessors, postcss, scss, sass, less, stylus, typescript setup, adding integrations, tailwind, testing, auth, linting, formatting, path: kit/integrations
+- title: Breakpoint Debugging, use_cases: debugging, breakpoints, development workflow, troubleshooting issues, vscode setup, ide configuration, inspecting code execution, path: kit/debugging
+- title: Migrating to SvelteKit v2, use_cases: migration, upgrading from sveltekit 1 to 2, breaking changes, version updates, path: kit/migrating-to-sveltekit-2
+- title: Migrating from Sapper, use_cases: migrating from sapper, upgrading legacy projects, sapper to sveltekit conversion, project modernization, path: kit/migrating
+- title: Additional resources, use_cases: troubleshooting, getting help, finding examples, learning sveltekit, project templates, common issues, community support, path: kit/additional-resources
+- title: Glossary, use_cases: rendering strategies, performance optimization, deployment configuration, seo requirements, static sites, spas, server-side rendering, prerendering, edge deployment, pwa development, path: kit/glossary
+- title: @sveltejs/kit, use_cases: forms, form actions, server-side validation, form submission, error handling, redirects, json responses, http errors, server utilities, path: kit/@sveltejs-kit
+- title: @sveltejs/kit/hooks, use_cases: middleware, request processing, authentication chains, logging, multiple hooks, request/response transformation, path: kit/@sveltejs-kit-hooks
+- title: @sveltejs/kit/node/polyfills, use_cases: node.js environments, custom servers, non-standard runtimes, ssr setup, web api compatibility, polyfill requirements, path: kit/@sveltejs-kit-node-polyfills
+- title: @sveltejs/kit/node, use_cases: node.js adapter, custom server setup, http integration, streaming files, node deployment, server-side rendering with node, path: kit/@sveltejs-kit-node
+- title: @sveltejs/kit/vite, use_cases: project setup, vite configuration, initial sveltekit setup, build tooling, path: kit/@sveltejs-kit-vite
+- title: $app/environment, use_cases: always, conditional logic, client-side code, server-side code, build-time logic, prerendering, development vs production, environment detection, path: kit/$app-environment
+- title: $app/forms, use_cases: forms, user input, data submission, progressive enhancement, custom form handling, form validation, path: kit/$app-forms
+- title: $app/navigation, use_cases: routing, navigation, multi-page apps, programmatic navigation, data reloading, preloading, shallow routing, navigation lifecycle, scroll handling, view transitions, path: kit/$app-navigation
+- title: $app/paths, use_cases: static assets, images, fonts, public files, base path configuration, subdirectory deployment, cdn setup, asset urls, links, navigation, path: kit/$app-paths
+- title: $app/server, use_cases: remote functions, server-side logic, data fetching, form handling, api endpoints, client-server communication, prerendering, file reading, batch queries, path: kit/$app-server
+- title: $app/state, use_cases: routing, navigation, multi-page apps, loading states, url parameters, form handling, error states, version updates, page metadata, shallow routing, path: kit/$app-state
+- title: $app/stores, use_cases: legacy projects, sveltekit pre-2.12, migration from stores to runes, maintaining older codebases, accessing page data, navigation state, app version updates, path: kit/$app-stores
+- title: $app/types, use_cases: routing, navigation, type safety, route parameters, dynamic routes, link generation, pathname validation, multi-page apps, path: kit/$app-types
+- title: $env/dynamic/private, use_cases: api keys, secrets management, server-side config, environment variables, backend logic, deployment-specific settings, private data handling, path: kit/$env-dynamic-private
+- title: $env/dynamic/public, use_cases: environment variables, client-side config, runtime configuration, public api keys, deployment-specific settings, multi-environment apps, path: kit/$env-dynamic-public
+- title: $env/static/private, use_cases: server-side api keys, backend secrets, database credentials, private configuration, build-time optimization, server endpoints, authentication tokens, path: kit/$env-static-private
+- title: $env/static/public, use_cases: environment variables, public config, client-side data, api endpoints, build-time configuration, public constants, path: kit/$env-static-public
+- title: $lib, use_cases: project setup, component organization, importing shared components, reusable ui elements, code structure, path: kit/$lib
+- title: $service-worker, use_cases: offline support, pwa, service workers, caching strategies, progressive web apps, offline-first apps, path: kit/$service-worker
+- title: Configuration, use_cases: project setup, configuration, adapters, deployment, build settings, environment variables, routing customization, prerendering, csp security, csrf protection, path configuration, typescript setup, path: kit/configuration
+- title: Command Line Interface, use_cases: project setup, typescript configuration, generated types, ./$types imports, initial project configuration, path: kit/cli
+- title: Types, use_cases: typescript, type safety, route parameters, api endpoints, load functions, form actions, generated types, jsconfig setup, path: kit/types
+- title: Overview, use_cases: always, any svelte project, getting started, learning svelte, introduction, project setup, understanding framework basics, path: svelte/overview
+- title: Getting started, use_cases: project setup, starting new svelte project, initial installation, choosing between sveltekit and vite, editor configuration, path: svelte/getting-started
+- title: .svelte files, use_cases: always, any svelte project, component creation, project setup, learning svelte basics, path: svelte/svelte-files
+- title: .svelte.js and .svelte.ts files, use_cases: shared reactive state, reusable reactive logic, state management across components, global stores, custom reactive utilities, path: svelte/svelte-js-files
+- title: What are runes?, use_cases: always, any svelte 5 project, understanding core syntax, learning svelte 5, migration from svelte 4, path: svelte/what-are-runes
+- title: $state, use_cases: always, any svelte project, core reactivity, state management, counters, forms, todo apps, interactive ui, data updates, class-based components, path: svelte/$state
+- title: $derived, use_cases: always, any svelte project, computed values, reactive calculations, derived data, transforming state, dependent values, path: svelte/$derived
+- title: $effect, use_cases: canvas drawing, third-party library integration, dom manipulation, side effects, intervals, timers, network requests, analytics tracking, path: svelte/$effect
+- title: $props, use_cases: always, any svelte project, passing data to components, component communication, reusable components, component props, path: svelte/$props
+- title: $bindable, use_cases: forms, user input, two-way data binding, custom input components, parent-child communication, reusable form fields, path: svelte/$bindable
+- title: $inspect, use_cases: debugging, development, tracking state changes, reactive state monitoring, troubleshooting reactivity issues, path: svelte/$inspect
+- title: $host, use_cases: custom elements, web components, dispatching custom events, component library, framework-agnostic components, path: svelte/$host
+- title: Basic markup, use_cases: always, any svelte project, basic markup, html templating, component structure, attributes, events, props, text rendering, path: svelte/basic-markup
+- title: {#if ...}, use_cases: always, conditional rendering, showing/hiding content, dynamic ui, user permissions, loading states, error handling, form validation, path: svelte/if
+- title: {#each ...}, use_cases: always, lists, arrays, iteration, product listings, todos, tables, grids, dynamic content, shopping carts, user lists, comments, feeds, path: svelte/each
+- title: {#key ...}, use_cases: animations, transitions, component reinitialization, forcing component remount, value-based ui updates, resetting component state, path: svelte/key
+- title: {#await ...}, use_cases: async data fetching, api calls, loading states, promises, error handling, lazy loading components, dynamic imports, path: svelte/await
+- title: {#snippet ...}, use_cases: reusable markup, component composition, passing content to components, table rows, list items, conditional rendering, reducing duplication, path: svelte/snippet
+- title: {@render ...}, use_cases: reusable ui patterns, component composition, conditional rendering, fallback content, layout components, slot alternatives, template reuse, path: svelte/@render
+- title: {@html ...}, use_cases: rendering html strings, cms content, rich text editors, markdown to html, blog posts, wysiwyg output, sanitized html injection, dynamic html content, path: svelte/@html
+- title: {@attach ...}, use_cases: tooltips, popovers, dom manipulation, third-party libraries, canvas drawing, element lifecycle, interactive ui, custom directives, wrapper components, path: svelte/@attach
+- title: {@const ...}, use_cases: computed values in loops, derived calculations in blocks, local variables in each iterations, complex list rendering, path: svelte/@const
+- title: {@debug ...}, use_cases: debugging, development, troubleshooting, tracking state changes, monitoring variables, reactive data inspection, path: svelte/@debug
+- title: bind:, use_cases: forms, user input, two-way data binding, interactive ui, media players, file uploads, checkboxes, radio buttons, select dropdowns, contenteditable, dimension tracking, path: svelte/bind
+- title: use:, use_cases: custom directives, dom manipulation, third-party library integration, tooltips, click outside, gestures, focus management, element lifecycle hooks, path: svelte/use
+- title: transition:, use_cases: animations, interactive ui, modals, dropdowns, notifications, conditional content, show/hide elements, smooth state changes, path: svelte/transition
+- title: in: and out:, use_cases: animation, transitions, interactive ui, conditional rendering, independent enter/exit effects, modals, tooltips, notifications, path: svelte/in-and-out
+- title: animate:, use_cases: sortable lists, drag and drop, reorderable items, todo lists, kanban boards, playlist editors, priority queues, animated list reordering, path: svelte/animate
+- title: style:, use_cases: dynamic styling, conditional styles, theming, dark mode, responsive design, interactive ui, component styling, path: svelte/style
+- title: class, use_cases: always, conditional styling, dynamic classes, tailwind css, component styling, reusable components, responsive design, path: svelte/class
+- title: await, use_cases: async data fetching, loading states, server-side rendering, awaiting promises in components, async validation, concurrent data loading, path: svelte/await-expressions
+- title: Scoped styles, use_cases: always, styling components, scoped css, component-specific styles, preventing style conflicts, animations, keyframes, path: svelte/scoped-styles
+- title: Global styles, use_cases: global styles, third-party libraries, css resets, animations, styling body/html, overriding component styles, shared keyframes, base styles, path: svelte/global-styles
+- title: Custom properties, use_cases: theming, custom styling, reusable components, design systems, dynamic colors, component libraries, ui customization, path: svelte/custom-properties
+- title: Nested
diff --git a/src/components/AdSlot/InlineAd.mdx b/src/components/AdSlot/InlineAd.mdx
new file mode 100644
index 0000000..ef65d15
--- /dev/null
+++ b/src/components/AdSlot/InlineAd.mdx
@@ -0,0 +1,56 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as InlineAdStories from './InlineAd.stories.svelte';
+
+
+
+# InlineAd
+
+Add programmatic ads inline on your page.
+
+> **IMPORTANT!** Make sure ads are only used on dotcom pages, never on embeds.
+
+```svelte
+
+
+
+
+
+```
+
+```svelte
+
+
+
+{#each content.blocks as block}
+
+
+ {#if block.Type === 'inline-ad'}
+
+ {#if !embedded}
+
+ {/if}
+ {/if}
+
+
+{/each}
+```
+
+You may add **up to three** inline ads per page, but must set the `n` prop on multiple ads in sequential order, 1 - 3.
+
+```svelte
+
+
+
+
+
+
+```
+
+
diff --git a/src/components/AdSlot/InlineAd.stories.svelte b/src/components/AdSlot/InlineAd.stories.svelte
new file mode 100644
index 0000000..cac455c
--- /dev/null
+++ b/src/components/AdSlot/InlineAd.stories.svelte
@@ -0,0 +1,20 @@
+
+
+{#snippet template()}
+
+
+
diff --git a/src/components/ClockWall/ClockWall.mdx b/src/components/ClockWall/ClockWall.mdx
new file mode 100644
index 0000000..a005021
--- /dev/null
+++ b/src/components/ClockWall/ClockWall.mdx
@@ -0,0 +1,27 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as ClockWallStories from './ClockWall.stories.svelte';
+
+
+
+# ClockWall
+
+The `ClockWall` component displays a row of analog clocks for different cities and timezones. Use it paired with the overall headline of a graphics blog page to show the time of multiple cities involved in a breaking news event.
+
+Use the [IANA tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) to find valid `tzIdentifier` strings.
+
+```svelte
+
+
+
+```
+
+
diff --git a/src/components/ClockWall/ClockWall.stories.svelte b/src/components/ClockWall/ClockWall.stories.svelte
new file mode 100644
index 0000000..328ffd5
--- /dev/null
+++ b/src/components/ClockWall/ClockWall.stories.svelte
@@ -0,0 +1,21 @@
+
+
+
diff --git a/src/components/ClockWall/ClockWall.svelte b/src/components/ClockWall/ClockWall.svelte
new file mode 100644
index 0000000..5d90005
--- /dev/null
+++ b/src/components/ClockWall/ClockWall.svelte
@@ -0,0 +1,61 @@
+
+
+
+
+ {#each cities as city (city.tzIdentifier)}
+
+ {/each}
+
+
+
+
diff --git a/src/components/DatawrapperChart/DatawrapperChart.mdx b/src/components/DatawrapperChart/DatawrapperChart.mdx
new file mode 100644
index 0000000..e444f37
--- /dev/null
+++ b/src/components/DatawrapperChart/DatawrapperChart.mdx
@@ -0,0 +1,45 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as DatawrapperChartStories from './DatawrapperChart.stories.svelte';
+
+
+
+# DatawrapperChart
+
+Easily add a responsive Datawrapper embed on your page.
+
+```svelte
+
+
+
+```
+
+##### Getting the chart URL for `src`
+
+Copy the source url for the Datawrapper chart in the `src` prop.
+You can get this from the published url on Reuters Graphics.
+
+- Publish the chart on Datawrapper.
+- Go to the **Datawrapper charts** Teams channel, wait for the graphic to finish publishing.
+- Inside **Embed code (for developers only)**, find and copy the url inside the `src` prop. (It ends in `media-embed.html`.)
+
+**Note:** There is no need to update the url if you update the chart inside Datawrapper. Any changes will be automatically reflected.
+
+
+
+## With chatter
+
+By default, Datawrapper will export your chart with the chart chatter like title, description and notes.
+
+At the moment, these don't _exactly_ match our styles and can't be made to fit into the article well.
+
+Instead, it's often better to remove all the text from your Datawrapper chart before publishing it and add that text back via the component props.
+
+
diff --git a/src/components/DatawrapperChart/DatawrapperChart.stories.svelte b/src/components/DatawrapperChart/DatawrapperChart.stories.svelte
new file mode 100644
index 0000000..412d1ad
--- /dev/null
+++ b/src/components/DatawrapperChart/DatawrapperChart.stories.svelte
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/src/components/DatawrapperChart/DatawrapperChart.svelte b/src/components/DatawrapperChart/DatawrapperChart.svelte
new file mode 100644
index 0000000..b2fd86d
--- /dev/null
+++ b/src/components/DatawrapperChart/DatawrapperChart.svelte
@@ -0,0 +1,117 @@
+
+
+
+
+ {#if titleSnippet}
+
+ {@render titleSnippet()}
+ {/if}
+
+
+
+
+
+ {#if notesSnippet}
+ {@render notesSnippet()}
+ {/if}
+
diff --git a/src/components/DocumentCloud/DocumentCloud.mdx b/src/components/DocumentCloud/DocumentCloud.mdx
new file mode 100644
index 0000000..88dec3d
--- /dev/null
+++ b/src/components/DocumentCloud/DocumentCloud.mdx
@@ -0,0 +1,26 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as DocumentCloudStories from './DocumentCloud.stories.svelte';
+
+
+
+# DocumentCloud
+
+The `DocumentCloud` component embeds a document hosted by [DocumentCloud](https://documentcloud.org).
+
+The document must have its access level set to **public** before it can be embedded. The `slug` can be found after the final slash in the document's URL.
+
+For instance, the document included in the example is found at [documentcloud.org/documents/3259984-Trump-Intelligence-Allegations](https://www.documentcloud.org/documents/3259984-Trump-Intelligence-Allegations). The `slug` is `3259984-Trump-Intelligence-Allegations`.
+
+```svelte
+
+
+
+```
+
+
diff --git a/src/components/DocumentCloud/DocumentCloud.stories.svelte b/src/components/DocumentCloud/DocumentCloud.stories.svelte
new file mode 100644
index 0000000..22f69e6
--- /dev/null
+++ b/src/components/DocumentCloud/DocumentCloud.stories.svelte
@@ -0,0 +1,23 @@
+
+
+
diff --git a/src/components/DocumentCloud/DocumentCloud.svelte b/src/components/DocumentCloud/DocumentCloud.svelte
new file mode 100644
index 0000000..01a86cc
--- /dev/null
+++ b/src/components/DocumentCloud/DocumentCloud.svelte
@@ -0,0 +1,41 @@
+
+
+
+
+
+
diff --git a/src/components/EmbedPreviewerLink/EmbedPreviewerLink.mdx b/src/components/EmbedPreviewerLink/EmbedPreviewerLink.mdx
new file mode 100644
index 0000000..12693e2
--- /dev/null
+++ b/src/components/EmbedPreviewerLink/EmbedPreviewerLink.mdx
@@ -0,0 +1,19 @@
+import { Meta } from '@storybook/blocks';
+
+import * as EmbedPreviewerLinkStories from './EmbedPreviewerLink.stories.svelte';
+
+
+
+# EmbedPreviewerLink
+
+The `EmbedPreviewerLink` component is a tool for previewing the embeds in development. It adds an icon at the bottom of the page that, when clicked, opens a previewer with the embeds.
+
+```svelte
+
+
+
+```
diff --git a/src/components/EmbedPreviewerLink/EmbedPreviewerLink.stories.svelte b/src/components/EmbedPreviewerLink/EmbedPreviewerLink.stories.svelte
new file mode 100644
index 0000000..80f2fa4
--- /dev/null
+++ b/src/components/EmbedPreviewerLink/EmbedPreviewerLink.stories.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/components/EmbedPreviewerLink/EmbedPreviewerLink.svelte b/src/components/EmbedPreviewerLink/EmbedPreviewerLink.svelte
new file mode 100644
index 0000000..365fa22
--- /dev/null
+++ b/src/components/EmbedPreviewerLink/EmbedPreviewerLink.svelte
@@ -0,0 +1,32 @@
+
+
+{#if dev}
+
+{/if}
+
+
diff --git a/src/components/EndNotes/EndNotes.mdx b/src/components/EndNotes/EndNotes.mdx
new file mode 100644
index 0000000..90e8bf9
--- /dev/null
+++ b/src/components/EndNotes/EndNotes.mdx
@@ -0,0 +1,67 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as EndNotesStories from './EndNotes.stories.svelte';
+
+
+
+# EndNotes
+
+The `EndNotes` component adds notes such as sources, clarifiying notes and minor corrections that come at the end of a story.
+
+```svelte
+
+
+
+```
+
+
+
+## Using with ArchieML docs
+
+With the graphics kit, you'll likely get your text value from an ArchieML doc...
+
+```yaml
+# ArchieML doc
+[endNotes]
+title: Note
+text: Data is current as of today
+
+title: Sources
+text: Data, Inc.
+
+title: Edited by
+text: Editor, Copyeditor
+[]
+```
+
+... which you'll pass to the `EndNotes` component.
+
+```svelte
+
+
+
+
+```
+
+
diff --git a/src/components/EndNotes/EndNotes.stories.svelte b/src/components/EndNotes/EndNotes.stories.svelte
new file mode 100644
index 0000000..1979205
--- /dev/null
+++ b/src/components/EndNotes/EndNotes.stories.svelte
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/src/components/EndNotes/EndNotes.svelte b/src/components/EndNotes/EndNotes.svelte
new file mode 100644
index 0000000..71d3818
--- /dev/null
+++ b/src/components/EndNotes/EndNotes.svelte
@@ -0,0 +1,58 @@
+
+
+
+
+ {#each notes as note}
+
+
+
+
+
+
+ {/each}
+
+
+
diff --git a/src/components/FeaturePhoto/FeaturePhoto.mdx b/src/components/FeaturePhoto/FeaturePhoto.mdx
new file mode 100644
index 0000000..71d90e5
--- /dev/null
+++ b/src/components/FeaturePhoto/FeaturePhoto.mdx
@@ -0,0 +1,72 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as FeaturePhotoStories from './FeaturePhoto.stories.svelte';
+
+
+
+# FeaturePhoto
+
+The `FeaturePhoto` component adds a full-width photo.
+
+```svelte
+
+
+
+```
+
+
+
+## Using with ArchieML docs
+
+With the graphics kit, you'll likely get your text value from an ArchieML doc...
+
+```yaml
+# ArchieML doc
+[blocks]
+
+type: photo
+width: normal
+src: images/shark.jpg
+altText: The king of the sea
+caption: Carcharodon carcharias - REUTERS
+
+[]
+```
+
+... which you'll parse out of a ArchieML block object before passing to the `FeaturePhoto` component.
+
+```svelte
+
+
+
+{#each content.blocks as block}
+ {#if block.Type === 'text'}
+
+ {:else if block.type === 'photo'}
+
+ {/if}
+{/each}
+```
+
+## Missing alt text
+
+`altText` is required in this component. If your photo is missing it, a small red text box will overlay the image.
+
+
diff --git a/src/components/FeaturePhoto/FeaturePhoto.stories.svelte b/src/components/FeaturePhoto/FeaturePhoto.stories.svelte
new file mode 100644
index 0000000..5576996
--- /dev/null
+++ b/src/components/FeaturePhoto/FeaturePhoto.stories.svelte
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
diff --git a/src/components/FeaturePhoto/FeaturePhoto.svelte b/src/components/FeaturePhoto/FeaturePhoto.svelte
new file mode 100644
index 0000000..a750d23
--- /dev/null
+++ b/src/components/FeaturePhoto/FeaturePhoto.svelte
@@ -0,0 +1,145 @@
+
+
+
+
+
+ {#if !lazy || (intersectable && intersecting)}
+
+ {:else}
+
+ {/if}
+ {#if caption}
+
+
+
+ {caption}
+
+
+
+ {/if}
+ {#if !altText}
+
altText
+ {/if}
+
+
+
+
diff --git a/src/components/FeaturePhoto/images/shark.jpg b/src/components/FeaturePhoto/images/shark.jpg
new file mode 100644
index 0000000..5b54e9f
Binary files /dev/null and b/src/components/FeaturePhoto/images/shark.jpg differ
diff --git a/src/components/Framer/Dropdown/index.svelte b/src/components/Framer/Dropdown/index.svelte
index 8798d5b..c3393be 100644
--- a/src/components/Framer/Dropdown/index.svelte
+++ b/src/components/Framer/Dropdown/index.svelte
@@ -21,7 +21,7 @@
diff --git a/src/components/Headpile/Headshot.svelte b/src/components/Headpile/Headshot.svelte
new file mode 100644
index 0000000..dd2afff
--- /dev/null
+++ b/src/components/Headpile/Headshot.svelte
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/src/components/Headpile/images/abdel.png b/src/components/Headpile/images/abdel.png
new file mode 100644
index 0000000..dcaef5c
Binary files /dev/null and b/src/components/Headpile/images/abdel.png differ
diff --git a/src/components/Headpile/images/hemedti.png b/src/components/Headpile/images/hemedti.png
new file mode 100644
index 0000000..c432113
Binary files /dev/null and b/src/components/Headpile/images/hemedti.png differ
diff --git a/src/components/HeroHeadline/HeroHeadline.mdx b/src/components/HeroHeadline/HeroHeadline.mdx
new file mode 100644
index 0000000..1091015
--- /dev/null
+++ b/src/components/HeroHeadline/HeroHeadline.mdx
@@ -0,0 +1,329 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as HeroHeadlineStories from './HeroHeadline.stories.svelte';
+
+
+
+# HeroHeadline
+
+The `HeroHeadline` component creates a Reuters Graphics headline with a hero media, which can be a graphic, photo, video or other media.
+
+By default, the hero is in the background, i.e., the headline and dek are stacked on top of the hero. You can unstack and insert the hero media inline -- i.e., before or after the headline -- by setting `stacked: false`. [Read more.](?/iframe.html?viewMode=docs&id=components-text-elements-heroheadline--docs&globals=&args=#inline-hero)
+
+## Photo hero
+
+To use a photo as the hero, simply pass the image source to the `img` prop.
+
+```svelte
+
+
+
+
+```
+
+
+
+## Transparent site header
+
+In the graphics kit, set styles in `global.scss` to make the Reuters site header transparent and make the hero go all the way to the top of the page:
+
+```scss
+// global.scss
+.nav-container {
+ background-color: transparent !important;
+}
+.nav-container .inner {
+ background-color: transparent !important;
+ border: none !important;
+}
+.hero-wrapper {
+ margin-block-start: -64px;
+}
+```
+
+
+
+## Ai2svelte hero
+
+To use an ai2svelte graphic as the hero, wrap your ai2svelte component in a `GraphicBlock` component and insert it inside `HeroHeadline`.
+
+To customise styles, use CSS to target the class passed to `HeroHeadline`.
+
+> **Note:** Pass `notes` and `ariaDescription` to the `GraphicBlock` component to provide additional information about the ai2svelte graphic.
+
+```svelte
+
+
+
+
+
+
+
+
+
+```
+
+Add styles in `global.scss`:
+
+```scss
+// global.scss
+// Customise styles using the class (e.g. `custom-hero` here) passed to `HeroHeadline`
+.hero-wrapper {
+ .custom-hero.headline {
+ // Adjust vertical positioning
+ align-items: flex-end !important;
+
+ @media (max-width: 1100px) {
+ // Adjust line length of title
+ max-width: var(--normal-column-width) !important;
+ }
+ }
+
+ // Make hero shorter than 100vh
+ --heroHeight: 85svh;
+
+ @media (max-width: 960px) {
+ --heroHeight: 65svh;
+ }
+
+ // For small height
+ @media (max-height: 850px) {
+ --heroHeight: 100svh;
+ }
+
+ // Custom hero sizing for landscape mobile
+ @media (max-width: 960px) and (orientation: landscape) {
+ --heroHeight: 200svh;
+ }
+}
+
+// Override default fixed height for hero layout in embeds
+.hero-wrapper.embedded {
+ --heroHeight: 1000px;
+}
+```
+
+
+
+## Video hero
+
+To add a video as the hero, use the [Video](?path=/docs/components-multimedia-video--docs) component. To customise styles, use CSS to target the class passed to `HeroHeadline`.
+
+> **Note:** Pass `notes` and `ariaDescription` to the `GraphicBlock` component to provide additional information about the video.
+
+```svelte
+
+
+
+
+
+```
+
+Add styles in `global.scss`:
+
+```scss
+// global.scss
+// Customise styles using the class (e.g. `video-hero` here) passed to `HeroHeadline`
+.hero-wrapper {
+ --heroHeight: calc(100svh - 60px);
+ .video-hero.headline {
+ header {
+ // Adjust vertical position as offset from default center
+ top: calc(50svh - 250px);
+ }
+
+ h1 {
+ color: #ffd430;
+ text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8);
+ }
+ }
+}
+```
+
+
+
+## Inline hero
+
+To use a photo, graphic, video, etc. as an inline hero -- i.e., to make the hero appear _after_ the headline and dek, instead of stacked underneath -- set `stacked` to `false`. Otherwise, add your hero media in the same way as documented above.
+
+```svelte
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+## Custom hed, dek and byline
+
+The `HeroHeadline` component internally uses the [Headline](?path=/docs/components-text-elements-headline--docs) component to render the headline and dek, which lets you to customise the headline and dek by passing [snippets](https://svelte.dev/docs/svelte/snippet) into the `hed` and `dek` props.
+
+Since `Headline` internally uses the [Byline](?path=/docs/components-text-elements-headline--docs) component, you can also customise the author page hyperlink and bylines with the `getAuthorPage`, `byline`, `published` and `updated` props.
+
+```svelte
+
+ {
+ return `mailto:${author.replace(' ', '')}@example.com`;
+ }}
+>
+
+ {#snippet hed()}
+
+
A visual guide to
+
EUROVISION
+
+ {/snippet}
+
+
+ {#snippet dek()}
+
+
+ Performers from 37 countries are coming together May 9-13 in Liverpool,
+ England, for the 67th annual Eurovision Song Contest. The winner gets
+ the trophy and their country gets the right to host next year’s event,
+ produced by the European Broadcasting Union (EBU).
+
+ Performers from 37 countries are coming together May 9-13 in
+ Liverpool, England, for the 67th annual Eurovision Song Contest. The
+ winner gets the trophy and their country gets the right to host next
+ year’s event, produced by the European Broadcasting Union (EBU).
+
+
+
+
+
+
+
+
diff --git a/src/components/HeroHeadline/demo/polar.jpg b/src/components/HeroHeadline/demo/polar.jpg
new file mode 100644
index 0000000..fe7cac6
Binary files /dev/null and b/src/components/HeroHeadline/demo/polar.jpg differ
diff --git a/src/components/InfoBox/InfoBox.mdx b/src/components/InfoBox/InfoBox.mdx
new file mode 100644
index 0000000..1704e58
--- /dev/null
+++ b/src/components/InfoBox/InfoBox.mdx
@@ -0,0 +1,122 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as InfoBoxStories from './InfoBox.stories.svelte';
+
+
+
+# InfoBox
+
+The `InfoBox` component creates a stylised text box that provides additional information that needs to be visually separate from the main content flow, such as methodology, detailed notes about data and extra context.
+
+```svelte
+
+
+
+```
+
+
+
+## Using with ArchieML docs
+
+With the graphics kit, you'll likely get your text value from an ArchieML doc...
+
+```yaml
+# Archie ML doc
+[blocks]
+
+type: info-box
+title: What you need to know about the war
+text: Reuters is collecting daily COVID-19 infections and deaths data for 240 countries and territories around the world, updated regularly throughout each day.
+
+Every country reports those figures a little differently and, inevitably, misses undiagnosed infections and deaths. With this project we are focusing on the trends within countries as they try to contain the virus’ spread, whether they are approaching or past peak infection rates, or if they are seeing a resurgence of infections or deaths.
+:end
+notes: [Read more about our methodology](https://www.reuters.com/world-coronavirus-tracker-and-maps/en/methodology/)
+[]
+```
+
+... which you'll parse out of a ArchieML block object before passing to the `InfoBox` component.
+
+```svelte
+
+
+
+# Graphics kit
+{#each content.blocks as block}
+ {#if block.type === 'info-box'}
+
+
+ {/if}
+{/each}
+```
+
+
+
+## Lists
+
+Use markdown to add lists to `InfoBox`.
+
+```svelte
+
+
+
+```
+
+
+## Customisation
+
+Use [snippets](https://svelte.dev/docs/svelte/snippet) to customise the `InfoBox`, such as adding tables, icons and thumbnail images.
+
+```svelte
+
+
+ {#snippet header()}
+
+ {/snippet}
+
+
+
+
diff --git a/src/components/InfoBox/InfoBox.svelte b/src/components/InfoBox/InfoBox.svelte
new file mode 100644
index 0000000..6a9674a
--- /dev/null
+++ b/src/components/InfoBox/InfoBox.svelte
@@ -0,0 +1,160 @@
+
+
+
+
+
+
diff --git a/src/components/KinesisLogo/KinesisLogo.mdx b/src/components/KinesisLogo/KinesisLogo.mdx
new file mode 100644
index 0000000..83bdafd
--- /dev/null
+++ b/src/components/KinesisLogo/KinesisLogo.mdx
@@ -0,0 +1,19 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as KinesisLogoStories from './KinesisLogo.stories.svelte';
+
+
+
+# KinesisLogo
+
+The `KinesisLogo` component contains the official Kinesis logo.
+
+```svelte
+
+
+
+```
+
+
diff --git a/src/components/KinesisLogo/KinesisLogo.stories.svelte b/src/components/KinesisLogo/KinesisLogo.stories.svelte
new file mode 100644
index 0000000..1d14157
--- /dev/null
+++ b/src/components/KinesisLogo/KinesisLogo.stories.svelte
@@ -0,0 +1,14 @@
+
+
+
diff --git a/src/components/KinesisLogo/KinesisLogo.svelte b/src/components/KinesisLogo/KinesisLogo.svelte
new file mode 100644
index 0000000..52f527b
--- /dev/null
+++ b/src/components/KinesisLogo/KinesisLogo.svelte
@@ -0,0 +1,140 @@
+
+
+
+
+
+
diff --git a/src/components/LanguageButton/LanguageButton.mdx b/src/components/LanguageButton/LanguageButton.mdx
new file mode 100644
index 0000000..c7d4ef8
--- /dev/null
+++ b/src/components/LanguageButton/LanguageButton.mdx
@@ -0,0 +1,118 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as LanguageButtonStories from './LanguageButton.stories.svelte';
+
+
+
+# LanguageButton
+
+The `LanguageButton` component creates a button that switches between an article written in English and another language.
+
+> 💡**NOTE:** If a translated embed page does not exist, add `LanguageButton` conditionally so it only renders when `embedded` is `false`. This prevents a toggle button from appearing on the English embed page.
+
+```svelte
+
+
+
+
+```
+
+
+
+## Customise language and button label
+
+By default, the toggle button will switch between English and Spanish, and the `buttonOptions` prop does not need to be passed. To customise the language and button label, pass the `locale` and the button `label` for the translation language as an object to the `buttonOptions` prop.
+
+```svelte
+
+
+
+
+```
+
+
+
+## Styling
+
+Use global CSS to style the toggle button. The container div has the class `language-button` and the nested button has an id of `translate-button`.
+
+```scss
+:global(div.language-button) {
+ /* Custom styles for the container div */
+
+ button#translate-button {
+ /* Custom styles for the toggle button */
+ }
+}
+
+
+
+```
+
+## Customising URLs
+
+By default, the `LanguageButton` component will switch from English to the translated version of the main article by appending `/{locale}/` to the base URL. For example, if the English version of the article is at `www.example.com/article/`, the translated version will be at `www.example.com/article/{locale}/`.
+
+If `embedded` is passed, it will switch between English and translated versions of the embed page by appending `/embeds/{locale}/page/` to the base URL. For example, if the English version of the embed page is at `www.example.com/article/embeds/en/page/`, the translated version will be at `www.example.com/article/embeds/{locale}/page/`.
+
+To customise this, pass a function to the `setUrl` prop that returns the URLs you want to link to.
+
+```svelte
+
+
+
+```
diff --git a/src/components/LanguageButton/LanguageButton.stories.svelte b/src/components/LanguageButton/LanguageButton.stories.svelte
new file mode 100644
index 0000000..113d5c7
--- /dev/null
+++ b/src/components/LanguageButton/LanguageButton.stories.svelte
@@ -0,0 +1,167 @@
+
+
+{#snippet demoToggle(
+ locale: string,
+ translatedLocale: string,
+ translatedLabel: string,
+ ariaLabel: string,
+ onToggle: () => void
+)}
+
+
+
Demo control
+
+ Use this toggle to simulate a locale switch in the demo
+