From d90ac677b2f0c1da8d3cdb85ce1ca253d84ed01e Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Wed, 4 Jun 2025 13:13:01 -0400 Subject: [PATCH 01/18] docs: enhance core concepts and key features with GRC-20 knowledge graph details --- docs/docs/core-concepts.md | 243 +++++++++++++++++++++++++++++++++++-- docs/docs/key-features.md | 5 + 2 files changed, 235 insertions(+), 13 deletions(-) diff --git a/docs/docs/core-concepts.md b/docs/docs/core-concepts.md index 8896c19e..358cef9a 100644 --- a/docs/docs/core-concepts.md +++ b/docs/docs/core-concepts.md @@ -11,14 +11,235 @@ Hypergraph re-imagines traditional client–server apps as **local-first**, **pe ## Table of Contents +- [Knowledge Graphs and GRC-20](#knowledge-graphs-and-grc-20) - [Spaces](#spaces) - [Identities](#identities) - [Inboxes](#inboxes) -- [Knowledge Graph](#knowledge-graph) - [Events & CRDTs](#events--crdts) - [Security Model](#security-model) --- +## Knowledge Graphs and GRC-20 + +Hypergraph adopts **GRC-20** as its canonical data format. Every mutation you perform through the Hypergraph SDK—whether it's adding a note, uploading a photo, or inviting a collaborator—ultimately becomes a set of GRC-20 triples bundled into an edit. Each **[Space](#spaces)** you create is simply a scoped knowledge graph that can reference and be referenced by any other space, giving your app instant access to a global pool of interoperable data. + +### 1. The GRC-20 Standard +The GRC-20 standard defines how knowledge is structured, shared, and connected in a decentralized, composable way—enabling interoperability across web3 applications. It specifies the core building blocks: entities, types, properties, relations, and triples. Read the [GRC-20 spec on GitHub](https://github.com/graphprotocol/graph-improvement-proposals/blob/main/grcs/0020-knowledge-graph.md). + +### 2. Core Data Model Concepts + +To illustrate the core pieces of a knowledge graph, we'll break down a single sentence: + +> **"Teresa, a photographer, owns a Fujifilm camera."** + +#### The Triple Model (EAV) +At the heart of GRC-20 is the **triple**: every fact is stored as a tuple of **Entity**, **Attribute** (property or relation), and **Value** (EAV). + +**Example triple in JSON:** +```json +{ + "entity": "Teresa_ID", + "attribute": "profession", + "value": { + "type": 1, // Text + "value": "photographer" + } +} +``` + +**Example triple in code:** +```ts +Graph.createEntity({ + name: 'Teresa', + types: [PERSON_TYPE_ID], + values: [ + { property: PROFESSION_ATTR_ID, value: 'photographer' } + ] +}); +``` + +#### IDs: Where Do They Come From? +Every entity, attribute, and relation has a unique ID (usually a string, e.g. `PERSON_TYPE_ID`). These are generated per your schema or space, and are required for all operations. + +#### Entities & Types +**Entity:** A unique thing in the graph (e.g., `Teresa`, `Camera`). +**Type:** A category for entities (e.g., `Person`, `Device`). + +```ts +const PERSON_TYPE_ID = 'PERSON_TYPE_ID'; +const DEVICE_TYPE_ID = 'DEVICE_TYPE_ID'; +const PROFESSION_ATTR_ID = 'PROFESSION_ATTR_ID'; +const BRAND_ATTR_ID = 'BRAND_ATTR_ID'; + +const { id: cameraId, ops: cameraOps } = Graph.createEntity({ + name: 'Camera', + types: [DEVICE_TYPE_ID], + values: [ + { property: BRAND_ATTR_ID, value: 'Fujifilm' }, + ], +}); + +const { id: teresaId, ops: teresaOps } = Graph.createEntity({ + name: 'Teresa', + types: [PERSON_TYPE_ID], + values: [ + { property: PROFESSION_ATTR_ID, value: 'photographer' }, + ], +}); +``` + +#### Properties vs. Relations +- **Property:** Attaches data to a single entity (e.g., `Camera` → `brand` → `Fujifilm`). +- **Relation:** Connects two entities (e.g., `Teresa` → `owns` → `Camera`). Relations are themselves entities and can have their own properties (e.g., `date_acquired`). + +```ts +const OWNS_REL_TYPE_ID = 'OWNS_REL_TYPE_ID'; +const DATE_ACQUIRED_ATTR_ID = 'DATE_ACQUIRED_ATTR_ID'; + +import { getEntityRelations } from '@graphprotocol/grc-20'; + +// 1️⃣ Fetch existing owns relations for Teresa +const existingOwns = getEntityRelations(teresaId, PersonSchema, doc).owns; + +// 2️⃣ Only create if none exists pointing to this camera +if (!existingOwns.find(rel => rel.id === cameraId)) { + const { ops: ownsOps } = Graph.createRelation({ + fromEntity: teresaId, + toEntity: cameraId, + relationType: OWNS_REL_TYPE_ID, + values: [ + { property: DATE_ACQUIRED_ATTR_ID, value: Graph.serializeDate(new Date('2020-03-15')) }, + ], + }); + // add ownsOps to your edit batch… +} +``` + +**Relation as triple in JSON:** +```json +{ + "entity": "OwnsRelation_ID", + "attribute": "date_acquired", + "value": { + "type": 5, // Time + "value": "2020-03-15T00:00:00.000Z" + } +} +``` + +#### Searching and Idempotency +The SDK generates a new ID for every entity or relation you create—even if an identical relation already exists. To avoid duplicates: + +- **Query existing relations** via your GraphQL endpoint with a filter on `from`, `relationType`, and `to`. +- **Use** `getEntityRelations` (from `@graphprotocol/grc-20`) on a local handle to list current relations for an entity: + +```ts +import { getEntityRelations } from '@graphprotocol/grc-20'; + +// Returns all non-deleted owns relations from Teresa +const relations = getEntityRelations(teresaId, PersonSchema, doc).owns; +``` + +- **Check** if a relation linking the same entities already exists before calling `Graph.createRelation`. + +If you call `createRelation` without checking, you'll end up with multiple relation entities of the same type between the same entities. Deduplication is the responsibility of your application or schema governance. + +#### Minimal Edit Example +Bundle all operations into an edit: +```ts +const ops = [...cameraOps, ...teresaOps, ...ownsOps]; +// Publish ops as an edit (see SDK docs for publishing) +``` + +Let's bring together everything we've learned above—including our example sentence—into a complete GRC-20–compliant TypeScript example that is fully composable with Hypergraph. + +```ts title="example.ts" +// Example: "Teresa, a photographer, owns a Fujifilm camera." +// 1. Create a Camera entity with a brand property +// 2. Create a Teresa entity with a profession property +// 3. Create an 'owns' relation entity linking Teresa to the Camera +// 4. Bundle all operations into a single edit (ops array) + +import { Graph } from '@graphprotocol/grc-20'; +import { getEntityRelations } from '@graphprotocol/grc-20'; + +// Replace these with actual IDs from your schema/space +const PERSON_TYPE_ID = 'PERSON_TYPE_ID'; +const DEVICE_TYPE_ID = 'DEVICE_TYPE_ID'; +const PROFESSION_ATTR_ID = 'PROFESSION_ATTR_ID'; +const BRAND_ATTR_ID = 'BRAND_ATTR_ID'; +const OWNS_REL_TYPE_ID = 'OWNS_REL_TYPE_ID'; +const DATE_ACQUIRED_ATTR_ID = 'DATE_ACQUIRED_ATTR_ID'; + +// 1️⃣ Create the Camera entity with a brand property +const { id: cameraId, ops: cameraOps } = Graph.createEntity({ + name: 'Fujifilm camera', // Human-readable label + types: [DEVICE_TYPE_ID], // Device type + values: [ + { property: BRAND_ATTR_ID, value: 'Fujifilm' }, // brand property + ], +}); + +// 2️⃣ Create the Teresa entity with a profession property +const { id: teresaId, ops: teresaOps } = Graph.createEntity({ + name: 'Teresa', // Human-readable label + types: [PERSON_TYPE_ID], // Person type + values: [ + { property: PROFESSION_ATTR_ID, value: 'photographer' }, // profession property + ], +}); + +// 1️⃣ Fetch existing owns relations for Teresa +const existingOwns = getEntityRelations(teresaId, PersonSchema, doc).owns; + +// 2️⃣ Only create if none exists pointing to this camera +if (!existingOwns.find(rel => rel.id === cameraId)) { + const { ops: ownsOps } = Graph.createRelation({ + fromEntity: teresaId, + toEntity: cameraId, + relationType: OWNS_REL_TYPE_ID, + values: [ + { property: DATE_ACQUIRED_ATTR_ID, value: Graph.serializeDate(new Date('2020-03-15')) }, + ], + }); + // add ownsOps to your edit batch… +} + +// 4️⃣ Combine all ops into a single edit +const ops = [...cameraOps, ...teresaOps, ...ownsOps]; +console.log('Ops ready for publishing:', ops); + +// (Optional) Publish the edit +// Graph.publishEdit({ ops }); +``` +--- + +#### Mental Model Recap +- **Entities** are things. +- **Properties** are facts about things. +- **Relations** connect things (and can have their own properties). +- **Triples** are atomic facts (entity, attribute, value). +- **Edits** are batches of changes. + +#### Cheat Sheet Table +| Concept | Example in Sentence | GRC-20 Term | Code Snippet | +|----------|---------------------|-------------|--------------| +| Entity | Teresa, Camera | Entity | `{ id, name }` | +| Type | Person, Device | Type | `types: [PERSON_TYPE_ID]` | +| Property | profession, brand | Attribute | `{ property: BRAND_ATTR_ID, value: 'Fujifilm' }` | +| Relation | owns | Relation Entity | `createRelation()` | +| Edit | batch of all triples | Edit | `ops: [...]` | + +--- + +_All of the above is not just theory—Hypergraph puts it to work for you._ **When you call the SDK or its React hooks, Hypergraph turns your mutations into triples, bundles them into edits, encrypts them (if the Space is private), and syncs them peer-to-peer or anchors them on-chain if the data is public.** As a developer you think in entities and hooks; behind the scenes Hypergraph speaks pure GRC-20. + +--- + +All of these building blocks are specified by the GRC-20 standard and created in code with the GRC-20 SDK. + +### 3. The GRC-20 SDK +The [`@graphprotocol/grc-20`](https://www.npmjs.com/package/@graphprotocol/grc-20) SDK is a toolkit for building, reading, and writing GRC-20-compliant knowledge graphs. It provides APIs for creating entities, types, properties, and relations, and handles serialization, publishing to IPFS, and onchain anchoring—making it easy to implement the GRC-20 standard in your apps. ## Spaces @@ -63,17 +284,6 @@ Inboxes can be **public** (anyone can read) or **private** (E2EE). Auth policies type InboxSenderAuthPolicy = 'any' | 'members' | 'admins'; ``` -## Knowledge Graph - -Public data isn't shoved into a siloed SQL DB. Instead, Hypergraph publishes JSON-LD to a decentralized Knowledge Graph (IPFS + Polygon Amoy smart contracts). - -Benefits: - -* **Composability** — one app's `City` objects can be queried by another app. -* **Network effects** — each new Space or entity enriches the shared graph. - -A TypeScript codegen tool (see the _TypeSync app_ in `/apps/typesync`) maps your domain models to on-chain schemas so you can query them like regular React hooks. - ## Events & CRDTs 1. A client mutates the Automerge document (`doc.put(…​)`). @@ -97,4 +307,11 @@ When the event log grows large, a peer may emit `sendCompactedUpdate`—a snapsh ### Edit on GitHub -[✏️ Suggest changes](https://github.com/graphprotocol/hypergraph/edit/main/docs/docs/core-concepts.md) \ No newline at end of file +[✏️ Suggest changes](https://github.com/graphprotocol/hypergraph/edit/main/docs/docs/core-concepts.md) + +:::tip Best Practice +**Always check for an existing relation (by `from`, `to`, and `relationType`) before creating a new one.** + +This prevents duplicate relations, keeps your data model clean, and avoids ambiguity in queries and UI. The GRC-20 SDK will create a new relation entity every time unless you check first. +::: + diff --git a/docs/docs/key-features.md b/docs/docs/key-features.md index 62a39a05..e00e5580 100644 --- a/docs/docs/key-features.md +++ b/docs/docs/key-features.md @@ -13,6 +13,7 @@ Hypergraph is **more than a database**—it's a complete data layer for building - [Local-first by design](#local-first-by-design) - [End-to-end encryption](#end-to-end-encryption) +- [Knowledge Graph SDK](#knowledge-graph-sdk) - [Graph-based data model](#graph-based-data-model) - [Conflict-free sync (CRDTs)](#conflict-free-sync-crdts) - [Spaces & fine-grained auth](#spaces--fine-grained-auth) @@ -38,6 +39,10 @@ Every update is encrypted **on the client** using XChaCha20-Poly1305. Only membe * **Automatic key rotation** when members join/leave. * **Multi-device**: each device holds its own key pair. +## Knowledge Graph SDK + +Build, link, and publish knowledge as entities and relations using the [`@graphprotocol/grc-20`](https://www.npmjs.com/package/@graphprotocol/grc-20) Knowledge Graph SDK. It makes it easy to organize data into spaces, anchor edits onchain, and work with The Graph's knowledge graph standard. + ## Graph-based data model Under the hood, Hypergraph stores JSON-LD triples that map nicely to **knowledge graphs**. This makes it trivial to expose public data on-chain or query it with SPARQL later. From ffe132cb99578bafe604212e156d56a885092807 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Wed, 4 Jun 2025 13:19:29 -0400 Subject: [PATCH 02/18] docs: update core concepts example to clarify entity creation and relation checks --- docs/docs/core-concepts.md | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/docs/docs/core-concepts.md b/docs/docs/core-concepts.md index 358cef9a..0309479e 100644 --- a/docs/docs/core-concepts.md +++ b/docs/docs/core-concepts.md @@ -155,13 +155,14 @@ Let's bring together everything we've learned above—including our example sent ```ts title="example.ts" // Example: "Teresa, a photographer, owns a Fujifilm camera." +// This script uses the @graphprotocol/grc-20 SDK to: // 1. Create a Camera entity with a brand property // 2. Create a Teresa entity with a profession property -// 3. Create an 'owns' relation entity linking Teresa to the Camera -// 4. Bundle all operations into a single edit (ops array) +// 3. Check for an existing 'owns' relation from Teresa to the Camera +// 4. If none exists, create the 'owns' relation entity +// 5. Bundle all operations into a single edit (ops array) -import { Graph } from '@graphprotocol/grc-20'; -import { getEntityRelations } from '@graphprotocol/grc-20'; +import { Graph, getEntityRelations } from '@graphprotocol/grc-20'; // Replace these with actual IDs from your schema/space const PERSON_TYPE_ID = 'PERSON_TYPE_ID'; @@ -173,28 +174,29 @@ const DATE_ACQUIRED_ATTR_ID = 'DATE_ACQUIRED_ATTR_ID'; // 1️⃣ Create the Camera entity with a brand property const { id: cameraId, ops: cameraOps } = Graph.createEntity({ - name: 'Fujifilm camera', // Human-readable label - types: [DEVICE_TYPE_ID], // Device type + name: 'Fujifilm camera', + types: [DEVICE_TYPE_ID], values: [ - { property: BRAND_ATTR_ID, value: 'Fujifilm' }, // brand property + { property: BRAND_ATTR_ID, value: 'Fujifilm' }, ], }); // 2️⃣ Create the Teresa entity with a profession property const { id: teresaId, ops: teresaOps } = Graph.createEntity({ - name: 'Teresa', // Human-readable label - types: [PERSON_TYPE_ID], // Person type + name: 'Teresa', + types: [PERSON_TYPE_ID], values: [ - { property: PROFESSION_ATTR_ID, value: 'photographer' }, // profession property + { property: PROFESSION_ATTR_ID, value: 'photographer' }, ], }); -// 1️⃣ Fetch existing owns relations for Teresa +// 3️⃣ Fetch existing 'owns' relations for Teresa const existingOwns = getEntityRelations(teresaId, PersonSchema, doc).owns; -// 2️⃣ Only create if none exists pointing to this camera +// 4️⃣ Only create if none exists pointing to this camera +let ownsOps = []; if (!existingOwns.find(rel => rel.id === cameraId)) { - const { ops: ownsOps } = Graph.createRelation({ + const { ops } = Graph.createRelation({ fromEntity: teresaId, toEntity: cameraId, relationType: OWNS_REL_TYPE_ID, @@ -202,10 +204,10 @@ if (!existingOwns.find(rel => rel.id === cameraId)) { { property: DATE_ACQUIRED_ATTR_ID, value: Graph.serializeDate(new Date('2020-03-15')) }, ], }); - // add ownsOps to your edit batch… + ownsOps = ops; } -// 4️⃣ Combine all ops into a single edit +// 5️⃣ Combine all ops into a single edit const ops = [...cameraOps, ...teresaOps, ...ownsOps]; console.log('Ops ready for publishing:', ops); From 67564f935adb404cba6203fc182a61beed47a8d6 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Thu, 5 Jun 2025 10:44:02 -0400 Subject: [PATCH 03/18] docs: update terminology in core concepts and key features to reflect GRC-20 spec changes --- docs/docs/core-concepts.md | 47 ++++++++++++++++++++++++-------------- docs/docs/key-features.md | 2 +- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/docs/docs/core-concepts.md b/docs/docs/core-concepts.md index 0309479e..5cda01b2 100644 --- a/docs/docs/core-concepts.md +++ b/docs/docs/core-concepts.md @@ -21,10 +21,10 @@ Hypergraph re-imagines traditional client–server apps as **local-first**, **pe --- ## Knowledge Graphs and GRC-20 -Hypergraph adopts **GRC-20** as its canonical data format. Every mutation you perform through the Hypergraph SDK—whether it's adding a note, uploading a photo, or inviting a collaborator—ultimately becomes a set of GRC-20 triples bundled into an edit. Each **[Space](#spaces)** you create is simply a scoped knowledge graph that can reference and be referenced by any other space, giving your app instant access to a global pool of interoperable data. +Hypergraph adopts **GRC-20** as its canonical data format. Every mutation you perform through the Hypergraph SDK—whether it's adding a note, uploading a photo, or inviting a collaborator—ultimately becomes a set of GRC-20 values bundled into an edit. Each **[Space](#spaces)** you create is simply a scoped knowledge graph that can reference and be referenced by any other space, giving your app instant access to a global pool of interoperable data. ### 1. The GRC-20 Standard -The GRC-20 standard defines how knowledge is structured, shared, and connected in a decentralized, composable way—enabling interoperability across web3 applications. It specifies the core building blocks: entities, types, properties, relations, and triples. Read the [GRC-20 spec on GitHub](https://github.com/graphprotocol/graph-improvement-proposals/blob/main/grcs/0020-knowledge-graph.md). +The GRC-20 standard defines how knowledge is structured, shared, and connected in a decentralized, composable way—enabling interoperability across web3 applications. It specifies the core building blocks: entities, types, properties, relations, and values. Read the [GRC-20 spec on GitHub](https://github.com/graphprotocol/graph-improvement-proposals/blob/main/grcs/0020-knowledge-graph.md). ### 2. Core Data Model Concepts @@ -32,22 +32,28 @@ To illustrate the core pieces of a knowledge graph, we'll break down a single se > **"Teresa, a photographer, owns a Fujifilm camera."** -#### The Triple Model (EAV) -At the heart of GRC-20 is the **triple**: every fact is stored as a tuple of **Entity**, **Attribute** (property or relation), and **Value** (EAV). +#### The Value Model (EAV) +At the heart of GRC-20 is the **value**: every fact is stored as a tuple of **Entity**, **Property**, and **Value** (EAV). The data type is defined on the property. -**Example triple in JSON:** +**Example property definition:** ```json { - "entity": "Teresa_ID", - "attribute": "profession", - "value": { - "type": 1, // Text - "value": "photographer" - } + "id": "PROFESSION_ATTR_ID", + "data_type": "TEXT" } ``` -**Example triple in code:** +**Example entity with values:** +```json +{ + "id": "Teresa_ID", + "values": [ + { "property": "PROFESSION_ATTR_ID", "value": "photographer" } + ] +} +``` + +**Example in code:** ```ts Graph.createEntity({ name: 'Teresa', @@ -218,9 +224,9 @@ console.log('Ops ready for publishing:', ops); #### Mental Model Recap - **Entities** are things. -- **Properties** are facts about things. +- **Properties** are facts about things, and define the data type. - **Relations** connect things (and can have their own properties). -- **Triples** are atomic facts (entity, attribute, value). +- **Values** are atomic facts (entity, property, value). - **Edits** are batches of changes. #### Cheat Sheet Table @@ -228,13 +234,14 @@ console.log('Ops ready for publishing:', ops); |----------|---------------------|-------------|--------------| | Entity | Teresa, Camera | Entity | `{ id, name }` | | Type | Person, Device | Type | `types: [PERSON_TYPE_ID]` | -| Property | profession, brand | Attribute | `{ property: BRAND_ATTR_ID, value: 'Fujifilm' }` | +| Property | profession, brand | Property | `{ id: BRAND_ATTR_ID, data_type: 'TEXT' }` | | Relation | owns | Relation Entity | `createRelation()` | -| Edit | batch of all triples | Edit | `ops: [...]` | +| Value | `Teresa → profession → photographer` | Value | `{ property: PROFESSION_ATTR_ID, value: 'photographer' }` | +| Edit | batch of all values | Edit | `ops: [...]` | --- -_All of the above is not just theory—Hypergraph puts it to work for you._ **When you call the SDK or its React hooks, Hypergraph turns your mutations into triples, bundles them into edits, encrypts them (if the Space is private), and syncs them peer-to-peer or anchors them on-chain if the data is public.** As a developer you think in entities and hooks; behind the scenes Hypergraph speaks pure GRC-20. +_All of the above is not just theory—Hypergraph puts it to work for you._ **When you call the SDK or its React hooks, Hypergraph turns your mutations into values, bundles them into edits, encrypts them (if the Space is private), and syncs them peer-to-peer or anchors them on-chain if the data is public.** As a developer you think in entities and hooks; behind the scenes Hypergraph speaks pure GRC-20. --- @@ -317,3 +324,9 @@ When the event log grows large, a peer may emit `sendCompactedUpdate`—a snapsh This prevents duplicate relations, keeps your data model clean, and avoids ambiguity in queries and UI. The GRC-20 SDK will create a new relation entity every time unless you check first. ::: +:::info Terminology Update +In the latest GRC-20 spec, what were previously called "triples" are now called "values." The "value type" is now called "data type," and data types are defined on the property, not the value. This change makes the model simpler and validation more robust. +::: + +**Note:** The data service validates that each value matches the property's data type. + diff --git a/docs/docs/key-features.md b/docs/docs/key-features.md index e00e5580..e92f1241 100644 --- a/docs/docs/key-features.md +++ b/docs/docs/key-features.md @@ -45,7 +45,7 @@ Build, link, and publish knowledge as entities and relations using the [`@graphp ## Graph-based data model -Under the hood, Hypergraph stores JSON-LD triples that map nicely to **knowledge graphs**. This makes it trivial to expose public data on-chain or query it with SPARQL later. +Under the hood, Hypergraph stores JSON-LD values that map nicely to **knowledge graphs**. This makes it trivial to expose public data on-chain or query it with SPARQL later. ## Conflict-free sync (CRDTs) From b66ce3117a85b7d62a0d997d4833d496b3a85f96 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Thu, 5 Jun 2025 10:49:52 -0400 Subject: [PATCH 04/18] docs: clarify GRC-20 integration in knowledge graph section for enhanced interoperability --- docs/docs/core-concepts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/core-concepts.md b/docs/docs/core-concepts.md index 5cda01b2..f3b87704 100644 --- a/docs/docs/core-concepts.md +++ b/docs/docs/core-concepts.md @@ -21,7 +21,7 @@ Hypergraph re-imagines traditional client–server apps as **local-first**, **pe --- ## Knowledge Graphs and GRC-20 -Hypergraph adopts **GRC-20** as its canonical data format. Every mutation you perform through the Hypergraph SDK—whether it's adding a note, uploading a photo, or inviting a collaborator—ultimately becomes a set of GRC-20 values bundled into an edit. Each **[Space](#spaces)** you create is simply a scoped knowledge graph that can reference and be referenced by any other space, giving your app instant access to a global pool of interoperable data. +Hypergraph adopts **GRC-20** as its canonical data format. Every mutation you perform through the Hypergraph SDK—whether it's adding a note, uploading a photo, or inviting a collaborator—ultimately becomes a set of GRC-20 values bundled into an edit. Once the edit is posted, it becomes part of the global knowledge graph—instantly connecting your data to a world of interoperable apps, spaces, and users. ### 1. The GRC-20 Standard The GRC-20 standard defines how knowledge is structured, shared, and connected in a decentralized, composable way—enabling interoperability across web3 applications. It specifies the core building blocks: entities, types, properties, relations, and values. Read the [GRC-20 spec on GitHub](https://github.com/graphprotocol/graph-improvement-proposals/blob/main/grcs/0020-knowledge-graph.md). From 8a2779270626b6259fce952785d3ea23eb69edbd Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Thu, 5 Jun 2025 10:55:06 -0400 Subject: [PATCH 05/18] docs: refine the value model description in core concepts to clarify entity and relation structure --- docs/docs/core-concepts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/core-concepts.md b/docs/docs/core-concepts.md index f3b87704..3072b0f1 100644 --- a/docs/docs/core-concepts.md +++ b/docs/docs/core-concepts.md @@ -32,8 +32,8 @@ To illustrate the core pieces of a knowledge graph, we'll break down a single se > **"Teresa, a photographer, owns a Fujifilm camera."** -#### The Value Model (EAV) -At the heart of GRC-20 is the **value**: every fact is stored as a tuple of **Entity**, **Property**, and **Value** (EAV). The data type is defined on the property. +#### The Value Model +In GRC-20, each **entity** is a node in the graph with a list of **values**. Each value attaches a **property** (by ID) and a literal value (plus options). Properties define the data type and constraints for their values. **Relations** are first-class objects that connect entities and can have their own properties and metadata. **Example property definition:** ```json From 903faed519d6cabee96cb42297f545a61679333c Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Thu, 5 Jun 2025 11:04:19 -0400 Subject: [PATCH 06/18] docs: enhance GRC-20 knowledge graph section with immutability and queryability details --- docs/docs/core-concepts.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/docs/core-concepts.md b/docs/docs/core-concepts.md index 3072b0f1..b3837040 100644 --- a/docs/docs/core-concepts.md +++ b/docs/docs/core-concepts.md @@ -21,7 +21,7 @@ Hypergraph re-imagines traditional client–server apps as **local-first**, **pe --- ## Knowledge Graphs and GRC-20 -Hypergraph adopts **GRC-20** as its canonical data format. Every mutation you perform through the Hypergraph SDK—whether it's adding a note, uploading a photo, or inviting a collaborator—ultimately becomes a set of GRC-20 values bundled into an edit. Once the edit is posted, it becomes part of the global knowledge graph—instantly connecting your data to a world of interoperable apps, spaces, and users. +Hypergraph adopts **GRC-20** as its canonical data format. Every mutation you perform through the Hypergraph SDK—whether it's adding a note, uploading a photo, or inviting a collaborator—ultimately becomes a set of GRC-20 values bundled into an edit. Once the edit is posted, it becomes part of the global knowledge graph—instantly connecting your data to a world of interoperable apps, spaces, and users. From that moment the edit is immutable and immediately queryable via Hypergraph's hooks and GraphQL APIs. ### 1. The GRC-20 Standard The GRC-20 standard defines how knowledge is structured, shared, and connected in a decentralized, composable way—enabling interoperability across web3 applications. It specifies the core building blocks: entities, types, properties, relations, and values. Read the [GRC-20 spec on GitHub](https://github.com/graphprotocol/graph-improvement-proposals/blob/main/grcs/0020-knowledge-graph.md). @@ -121,15 +121,16 @@ if (!existingOwns.find(rel => rel.id === cameraId)) { } ``` -**Relation as triple in JSON:** +**Relation JSON example:** ```json { - "entity": "OwnsRelation_ID", - "attribute": "date_acquired", - "value": { - "type": 5, // Time - "value": "2020-03-15T00:00:00.000Z" - } + "id": "OwnsRelation_ID", + "type": "OWNS_REL_TYPE_ID", + "from_entity": "Teresa_ID", + "to_entity": "Camera_ID", + "entity": "OwnsRelationEntity_ID", // rich relation entity UUID (optional) + "position": "a", + "verified": false } ``` @@ -235,7 +236,7 @@ console.log('Ops ready for publishing:', ops); | Entity | Teresa, Camera | Entity | `{ id, name }` | | Type | Person, Device | Type | `types: [PERSON_TYPE_ID]` | | Property | profession, brand | Property | `{ id: BRAND_ATTR_ID, data_type: 'TEXT' }` | -| Relation | owns | Relation Entity | `createRelation()` | +| Relation | owns | Relation | `{ from_entity, to_entity, type }` | | Value | `Teresa → profession → photographer` | Value | `{ property: PROFESSION_ATTR_ID, value: 'photographer' }` | | Edit | batch of all values | Edit | `ops: [...]` | From 510cc693283f28788bffd8710f7708466547d267 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 08:37:21 -0400 Subject: [PATCH 07/18] docs: update Docusaurus configuration and README for improved clarity and design to look like The Graph --- docs/README.md | 10 +- docs/docusaurus.config.js | 1 + docs/src/css/custom.css | 34 +-- pnpm-lock.yaml | 449 +++++++++++++++++++++++++++----------- 4 files changed, 347 insertions(+), 147 deletions(-) diff --git a/docs/README.md b/docs/README.md index 0be3f1b9..846bcb79 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,7 +9,7 @@ This website is built using [Docusaurus](https://docusaurus.io/), a modern stati Install all dependencies from the monorepo root: ``` -$ pnpm install +pnpm install ``` ### Local Development @@ -17,7 +17,7 @@ $ pnpm install Start the Docusaurus dev server for the docs site: ``` -$ pnpm --filter docs start +pnpm --filter docs start ``` This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. @@ -27,7 +27,7 @@ This command starts a local development server and opens up a browser window. Mo Build the static site: ``` -$ pnpm --filter docs build +pnpm --filter docs build ``` This command generates static content into the `build` directory and can be served using any static content hosting service. @@ -37,13 +37,13 @@ This command generates static content into the `build` directory and can be serv Using SSH: ``` -$ USE_SSH=true pnpm --filter docs deploy +USE_SSH=true pnpm --filter docs deploy ``` Not using SSH: ``` -$ GIT_USER= pnpm --filter docs deploy +GIT_USER= pnpm --filter docs deploy ``` If you are using GitHub Pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 68174b36..42d04e1f 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -71,6 +71,7 @@ const config = { themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ + colorMode: { defaultMode: 'dark' }, // Replace with your project's social card image: 'img/docusaurus-social-card.jpg', navbar: { diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 38591401..96ea530c 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -6,25 +6,25 @@ /* You can override the default Infima variables here. */ :root { - --ifm-color-primary: #2e8555; - --ifm-color-primary-dark: #29784c; - --ifm-color-primary-darker: #277148; - --ifm-color-primary-darkest: #205d3b; - --ifm-color-primary-light: #33925d; - --ifm-color-primary-lighter: #359962; - --ifm-color-primary-lightest: #3cad6e; - --ifm-code-font-size: 95%; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); + --ifm-color-primary: #2e8555; + --ifm-color-primary-dark: #29784c; + --ifm-color-primary-darker: #277148; + --ifm-color-primary-darkest: #205d3b; + --ifm-color-primary-light: #33925d; + --ifm-color-primary-lighter: #359962; + --ifm-color-primary-lightest: #3cad6e; + --ifm-code-font-size: 95%; + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); } /* For readability concerns, you should choose a lighter palette in dark mode. */ [data-theme="dark"] { - --ifm-color-primary: #25c2a0; - --ifm-color-primary-dark: #21af90; - --ifm-color-primary-darker: #1fa588; - --ifm-color-primary-darkest: #1a8870; - --ifm-color-primary-light: #29d5b0; - --ifm-color-primary-lighter: #32d8b4; - --ifm-color-primary-lightest: #4fddbf; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); + --ifm-color-primary: #25c2a0; + --ifm-color-primary-dark: #21af90; + --ifm-color-primary-darker: #1fa588; + --ifm-color-primary-darkest: #1a8870; + --ifm-color-primary-light: #29d5b0; + --ifm-color-primary-lighter: #32d8b4; + --ifm-color-primary-lightest: #4fddbf; + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 77ec998f..eba2b444 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -371,7 +371,7 @@ importers: version: 4.1.0 effect: specifier: latest - version: 3.16.3 + version: 3.16.5 graphql: specifier: ^16.11.0 version: 16.11.0 @@ -399,28 +399,28 @@ importers: devDependencies: '@effect/cli': specifier: latest - version: 0.63.4(@effect/platform@0.84.4(effect@3.16.3))(@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3))(@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3))(effect@3.16.3) + version: 0.63.9(@effect/platform@0.84.9(effect@3.16.5))(@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5))(@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5))(effect@3.16.5) '@effect/experimental': specifier: latest - version: 0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + version: 0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) '@effect/language-service': specifier: latest - version: 0.17.1 + version: 0.19.0 '@effect/platform': specifier: latest - version: 0.84.4(effect@3.16.3) + version: 0.84.9(effect@3.16.5) '@effect/platform-node': specifier: latest - version: 0.84.2(@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(bufferutil@4.0.9)(effect@3.16.3)(utf-8-validate@5.0.10) + version: 0.85.13(@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(bufferutil@4.0.9)(effect@3.16.5)(utf-8-validate@5.0.10) '@effect/sql': specifier: latest - version: 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + version: 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) '@effect/sql-sqlite-node': specifier: latest - version: 0.38.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(effect@3.16.3) + version: 0.38.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(effect@3.16.5) '@effect/vitest': specifier: latest - version: 0.23.3(effect@3.16.3)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0)) + version: 0.23.5(effect@3.16.5)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0)) '@graphprotocol/grc-20': specifier: ^0.17.0 version: 0.17.0(bufferutil@4.0.9)(graphql@16.11.0)(ox@0.6.7(typescript@5.8.3)(zod@3.24.2))(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2) @@ -492,6 +492,21 @@ importers: '@docusaurus/types': specifier: 3.7.0 version: 3.7.0(acorn@8.14.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@tailwindcss/typography': + specifier: ^0.5.12 + version: 0.5.16(tailwindcss@3.4.17) + autoprefixer: + specifier: ^10.4.16 + version: 10.4.21(postcss@8.5.3) + postcss: + specifier: ^8.4.31 + version: 8.5.3 + tailwindcss: + specifier: ^3.4.4 + version: 3.4.17 + tailwindcss-animate: + specifier: ^1.0.0 + version: 1.0.7(tailwindcss@3.4.17) packages/hypergraph: dependencies: @@ -503,7 +518,7 @@ importers: version: 2.0.0-beta.5 '@effect/experimental': specifier: ^0.44.20 - version: 0.44.20(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + version: 0.44.20(@effect/platform@0.84.9(effect@3.16.3))(effect@3.16.3) '@noble/ciphers': specifier: ^1.3.0 version: 1.3.0 @@ -691,6 +706,10 @@ packages: resolution: {integrity: sha512-ZO0UKvDyEFvyeJQX0gmZDQEvhLZ2X10K+ps6hViMo1HgE2V8em00SwNsQ+7E/52a+YiBkVWX61pJJJE44juDMQ==} engines: {node: '>= 14.0.0'} + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -2160,13 +2179,13 @@ packages: resolution: {integrity: sha512-e7zcB6TPnVzyUaHMJyLSArKa2AG3h9+4CfvKXKKWNx6hRs+p0a+u7HHTJBgo6KW2m+vqDnuIHK4X+bhmoghAFA==} engines: {node: '>=18.0'} - '@effect/cli@0.63.4': - resolution: {integrity: sha512-c8Jfdapo9SmutXjbN1u4XDeWFKif6toe7zTUmaxXZZ44ZOs1S54REmJm6gjPyLrwSnAVhE11EegiweMH7hg/9Q==} + '@effect/cli@0.63.9': + resolution: {integrity: sha512-SKgoyDbXBra9sgpLLRAI2rDgfWvWIda5vV/ce7TaEUkIpfohJZ7yMcTZ9X4wXLbsc2pxWczkwOVn51WxAg3qng==} peerDependencies: - '@effect/platform': ^0.84.4 - '@effect/printer': ^0.44.3 - '@effect/printer-ansi': ^0.44.3 - effect: ^3.16.3 + '@effect/platform': ^0.84.9 + '@effect/printer': ^0.44.5 + '@effect/printer-ansi': ^0.44.5 + effect: ^3.16.5 '@effect/cluster@0.37.2': resolution: {integrity: sha512-9U4P/Fk8C6fN/s0e4nvA++prZmELtV7k5RwG2AOw4NgqBZqptiJMutgaT10ltwgdvddRF/77PVjgORyzNTBmbg==} @@ -2190,11 +2209,11 @@ packages: lmdb: optional: true - '@effect/experimental@0.48.4': - resolution: {integrity: sha512-sKCVpqUrBhVODpGPuZ5pgG72XjOAUs77/4LaJmSgtDrEEzKlFyFmY3vxAR6wrup3RRs+wcu3LoZwzfjk5d6JDQ==} + '@effect/experimental@0.48.10': + resolution: {integrity: sha512-B6XlTdDlh4tDl+kU2+tpKR0xmK38XXXy27+PH8ILhM8m5RB0MJDtshzVLogw3Vzq2NjYsGkrxV/yEcU1HaQoLw==} peerDependencies: - '@effect/platform': ^0.84.4 - effect: ^3.16.3 + '@effect/platform': ^0.84.9 + effect: ^3.16.5 ioredis: ^5 lmdb: ^3 peerDependenciesMeta: @@ -2203,31 +2222,31 @@ packages: lmdb: optional: true - '@effect/language-service@0.17.1': - resolution: {integrity: sha512-dA0DamelGlQtCppi8k4Bqq/Exr2L6anjtqzlj9Xf27eAyNdapvnqrwzDiQXMYD8zb4Xvul3gQuYBzvfFVz0baQ==} + '@effect/language-service@0.19.0': + resolution: {integrity: sha512-DAnV0q0EPZtB6+opqMb1BsAkQ/7AoQj/Q84rUijM8dY2bevuI870DtZYn9kpB19Q3VN8yhPE9Kgtnpocj8ysTA==} - '@effect/platform-node-shared@0.38.2': - resolution: {integrity: sha512-TiYTYH3QPJt+7M21xhTM9KgV5DlJHD3eaDDs4Vv4lXseVaAZGOvLln4RBt0+6akdPmniDhEzrSOEGS+HbOI9Jw==} + '@effect/platform-node-shared@0.39.13': + resolution: {integrity: sha512-j3XKDwmQ4P7lBd0jCUfx3fHflqhrDmBde99z2One0ZS+N2DEZjZzqqmG7K2I5b7t9GeOnngJyE0JgGp7oHYb+g==} peerDependencies: - '@effect/cluster': ^0.37.2 - '@effect/platform': ^0.84.4 - '@effect/rpc': ^0.61.4 - '@effect/sql': ^0.37.4 - effect: ^3.16.3 + '@effect/cluster': ^0.38.13 + '@effect/platform': ^0.84.9 + '@effect/rpc': ^0.61.12 + '@effect/sql': ^0.37.10 + effect: ^3.16.5 - '@effect/platform-node@0.84.2': - resolution: {integrity: sha512-iDjlK9UYOCDgNIAKUrOYYt6y3NwJkq4Ii1XWGM5PrgWPx7OzG9BCZPOFJxPDMlBTcbpqEC+WYNmDjnYQDnx3rQ==} + '@effect/platform-node@0.85.13': + resolution: {integrity: sha512-c/R4rUEY+KaLB+0817BzjtAPSnUxFMAogAfdRDqUvtE3htD25/aXIxa0DSUt4a66VAMzbdWAXr7BwV6vPE3weA==} peerDependencies: - '@effect/cluster': ^0.37.2 - '@effect/platform': ^0.84.4 - '@effect/rpc': ^0.61.4 - '@effect/sql': ^0.37.4 - effect: ^3.16.3 + '@effect/cluster': ^0.38.13 + '@effect/platform': ^0.84.9 + '@effect/rpc': ^0.61.12 + '@effect/sql': ^0.37.10 + effect: ^3.16.5 - '@effect/platform@0.84.4': - resolution: {integrity: sha512-RDs5Ju5u3xBpyEHZ6XEt5yKmAxrd/k8VyyeSyjkLVpCzecXNYeRkU8jcGdX4ex4bmH7AAe78j2OHrWoM8nBwSg==} + '@effect/platform@0.84.9': + resolution: {integrity: sha512-I1xX/dpFCyA9DlwD3kungWD0Pu7tnM2pxifUEz0U1N2GSMmdcC4EWIOsjnCaC+hd0WSIsVJVZZjGsDeQeX+r2g==} peerDependencies: - effect: ^3.16.3 + effect: ^3.16.5 '@effect/printer-ansi@0.40.10': resolution: {integrity: sha512-XMmAcHxojINGZKnNGJSrG1fMvMYLOlHGVAvvD/5pbp2Yi5Rh8PGDJjtaPmrj5PmO+WssovevLHGonrbKa8xybA==} @@ -2247,30 +2266,30 @@ packages: '@effect/platform': ^0.84.4 effect: ^3.16.3 - '@effect/sql-sqlite-node@0.38.4': - resolution: {integrity: sha512-OBr88N5KuPBZBy9q422Q/FdkXJSCGxFR9Ns/Bhz7eaY94DUisWfRfeGx4lqcr1kKp84lDanVNi2mNfGsnGGcUQ==} + '@effect/sql-sqlite-node@0.38.10': + resolution: {integrity: sha512-wNO5h33JgaaAERi8e7hz+8BxULp8YwwC4OBbXCh9vH+0dz6HVXjfD8+N8DIdaz5ZrCgBmr/pJsq/RnaQToZkig==} peerDependencies: - '@effect/experimental': ^0.48.4 - '@effect/platform': ^0.84.4 - '@effect/sql': ^0.37.4 - effect: ^3.16.3 + '@effect/experimental': ^0.48.10 + '@effect/platform': ^0.84.9 + '@effect/sql': ^0.37.10 + effect: ^3.16.5 - '@effect/sql@0.37.4': - resolution: {integrity: sha512-Ver8KV5kBkc6dNFNlOjJYHkcHUz0qcva4xyd2Ob2Xoh5CHj/JL/aJbXGhnRBsFPcV74kWc0SkPTAex2fh66tSA==} + '@effect/sql@0.37.10': + resolution: {integrity: sha512-tPnGb+JTWvtRYHyYxriMlX3ueC6hCZxAX6UgN40tSZ65pfhKtTfx2tqoEB55HnkWWrO09CbpO/S0q7RTqgFflQ==} peerDependencies: - '@effect/experimental': ^0.48.4 - '@effect/platform': ^0.84.4 - effect: ^3.16.3 + '@effect/experimental': ^0.48.10 + '@effect/platform': ^0.84.9 + effect: ^3.16.5 '@effect/typeclass@0.31.10': resolution: {integrity: sha512-mDuQ44IfyDUSnltcFS+cEQGWhMg37IwNiPmATLw/NYBYHDBkqUc77vzlCpSlBiKDzExSI8vjMVWqGjL22MLHGQ==} peerDependencies: effect: ^3.12.10 - '@effect/vitest@0.23.3': - resolution: {integrity: sha512-yIB+Cllk1txmtpdpVX95SdmM0/FHqapz4wGSWYTe0c/K9fhgL6t0t5WsLmgzlk0rGnSi0+U21AHmPynjgk6+ig==} + '@effect/vitest@0.23.5': + resolution: {integrity: sha512-cBiNyQQ+vslFnAuhjEz0NoNs/YD7hbyKPyIA1Xiu+m/jry6xVoFRQZEt5l5McIWbDfrbzBDEfEE6PpPS7U1D0Q==} peerDependencies: - effect: ^3.16.3 + effect: ^3.16.5 vitest: ^3.0.0 '@effect/workflow@0.1.2': @@ -4412,6 +4431,11 @@ packages: resolution: {integrity: sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==} engines: {node: '>= 10'} + '@tailwindcss/typography@0.5.16': + resolution: {integrity: sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' + '@tailwindcss/vite@4.1.5': resolution: {integrity: sha512-FE1stRoqdHSb7RxesMfCXE8icwI1W6zGE/512ae3ZDrpkQYTTYeSyUJPRCjZd8CwVAhpDUbi1YR8pcZioFJQ/w==} peerDependencies: @@ -5008,6 +5032,7 @@ packages: '@walletconnect/modal@2.7.0': resolution: {integrity: sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw==} + deprecated: Please follow the migration guide on https://docs.reown.com/appkit/upgrade/wcm '@walletconnect/relay-api@1.0.11': resolution: {integrity: sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==} @@ -5607,6 +5632,10 @@ packages: camel-case@4.1.2: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -6340,6 +6369,9 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + diff@7.0.0: resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} engines: {node: '>=0.3.1'} @@ -6354,6 +6386,9 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dns-packet@5.6.1: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} @@ -6431,6 +6466,9 @@ packages: effect@3.16.3: resolution: {integrity: sha512-SWndb1UavNWvet1+hnkU4qp3EHtnmDKhUeP14eB+7vf/2nCFlM77/oIjdDeZctveibNjE65P9H/sBBmF0NTy/w==} + effect@3.16.5: + resolution: {integrity: sha512-7nA+ZPMLoHItabNRV95RpMtwVw2k3BDNhILP4ffo8dG7zGR04XGjarP1JbO+jdBbTRET3eGx1Nz+hWB9kSOajw==} + electron-to-chromium@1.5.152: resolution: {integrity: sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==} @@ -8010,12 +8048,21 @@ packages: resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + lodash.castarray@4.4.0: + resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} + lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} @@ -8652,6 +8699,10 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + object-inspect@1.13.2: resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} engines: {node: '>= 0.4'} @@ -8979,6 +9030,10 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -9171,12 +9226,36 @@ packages: peerDependencies: postcss: ^8.4 + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + postcss-lab-function@7.0.9: resolution: {integrity: sha512-IGbsIXbqMDusymJAKYX+f9oakPo89wL9Pzd/qRBQOVf3EIQWT9hgvqC4Me6Dkzxp3KPuIBf6LPkjrLHe/6ZMIQ==} engines: {node: '>=18'} peerDependencies: postcss: ^8.4 + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + postcss-load-config@6.0.1: resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} engines: {node: '>= 18'} @@ -9274,6 +9353,12 @@ packages: peerDependencies: postcss: ^8.1.0 + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + postcss-nesting@13.0.1: resolution: {integrity: sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==} engines: {node: '>=18'} @@ -9404,6 +9489,10 @@ packages: peerDependencies: postcss: ^8.4 + postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + postcss-selector-parser@6.1.2: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} @@ -9744,6 +9833,9 @@ packages: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -10517,6 +10609,11 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' + tailwindcss@3.4.17: + resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} + engines: {node: '>=14.0.0'} + hasBin: true + tailwindcss@4.1.5: resolution: {integrity: sha512-nYtSPfWGDiWgCkwQG/m+aX83XCwf62sBgg3bIlNiiOcggnS1x3uVRDAuyelBFL+vJdOPPCGElxv9DjHJjRHiVA==} @@ -11651,6 +11748,8 @@ snapshots: dependencies: '@algolia/client-common': 5.25.0 + '@alloc/quick-lru@5.2.0': {} + '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.8 @@ -11800,7 +11899,7 @@ snapshots: dependencies: '@babel/compat-data': 7.26.5 '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.2 + browserslist: 4.24.5 lru-cache: 5.1.1 semver: 6.3.1 @@ -11816,7 +11915,7 @@ snapshots: dependencies: '@babel/compat-data': 7.27.2 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.24.2 + browserslist: 4.24.5 lru-cache: 5.1.1 semver: 6.3.1 @@ -14056,60 +14155,60 @@ snapshots: - uglify-js - webpack-cli - '@effect/cli@0.63.4(@effect/platform@0.84.4(effect@3.16.3))(@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3))(@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3))(effect@3.16.3)': + '@effect/cli@0.63.9(@effect/platform@0.84.9(effect@3.16.5))(@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5))(@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5))(effect@3.16.5)': dependencies: - '@effect/platform': 0.84.4(effect@3.16.3) - '@effect/printer': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3) - '@effect/printer-ansi': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3) - effect: 3.16.3 + '@effect/platform': 0.84.9(effect@3.16.5) + '@effect/printer': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5) + '@effect/printer-ansi': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5) + effect: 3.16.5 ini: 4.1.3 toml: 3.0.0 yaml: 2.7.0 - '@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3)': + '@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5)': dependencies: - '@effect/platform': 0.84.4(effect@3.16.3) - '@effect/rpc': 0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) - '@effect/sql': 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) - '@effect/workflow': 0.1.2(effect@3.16.3) - effect: 3.16.3 + '@effect/platform': 0.84.9(effect@3.16.5) + '@effect/rpc': 0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + '@effect/sql': 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + '@effect/workflow': 0.1.2(effect@3.16.5) + effect: 3.16.5 - '@effect/experimental@0.44.20(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3)': + '@effect/experimental@0.44.20(@effect/platform@0.84.9(effect@3.16.3))(effect@3.16.3)': dependencies: - '@effect/platform': 0.84.4(effect@3.16.3) + '@effect/platform': 0.84.9(effect@3.16.3) effect: 3.16.3 uuid: 11.1.0 - '@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3)': + '@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5)': dependencies: - '@effect/platform': 0.84.4(effect@3.16.3) - effect: 3.16.3 + '@effect/platform': 0.84.9(effect@3.16.5) + effect: 3.16.5 uuid: 11.1.0 - '@effect/language-service@0.17.1': {} + '@effect/language-service@0.19.0': {} - '@effect/platform-node-shared@0.38.2(@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(bufferutil@4.0.9)(effect@3.16.3)(utf-8-validate@5.0.10)': + '@effect/platform-node-shared@0.39.13(@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(bufferutil@4.0.9)(effect@3.16.5)(utf-8-validate@5.0.10)': dependencies: - '@effect/cluster': 0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3) - '@effect/platform': 0.84.4(effect@3.16.3) - '@effect/rpc': 0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) - '@effect/sql': 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + '@effect/cluster': 0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5) + '@effect/platform': 0.84.9(effect@3.16.5) + '@effect/rpc': 0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + '@effect/sql': 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) '@parcel/watcher': 2.5.1 - effect: 3.16.3 + effect: 3.16.5 multipasta: 0.2.5 ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate - '@effect/platform-node@0.84.2(@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(bufferutil@4.0.9)(effect@3.16.3)(utf-8-validate@5.0.10)': + '@effect/platform-node@0.85.13(@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(bufferutil@4.0.9)(effect@3.16.5)(utf-8-validate@5.0.10)': dependencies: - '@effect/cluster': 0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3) - '@effect/platform': 0.84.4(effect@3.16.3) - '@effect/platform-node-shared': 0.38.2(@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(bufferutil@4.0.9)(effect@3.16.3)(utf-8-validate@5.0.10) - '@effect/rpc': 0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) - '@effect/sql': 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) - effect: 3.16.3 + '@effect/cluster': 0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5) + '@effect/platform': 0.84.9(effect@3.16.5) + '@effect/platform-node-shared': 0.39.13(@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(bufferutil@4.0.9)(effect@3.16.5)(utf-8-validate@5.0.10) + '@effect/rpc': 0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + '@effect/sql': 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + effect: 3.16.5 mime: 3.0.0 undici: 7.10.0 ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) @@ -14117,58 +14216,65 @@ snapshots: - bufferutil - utf-8-validate - '@effect/platform@0.84.4(effect@3.16.3)': + '@effect/platform@0.84.9(effect@3.16.3)': dependencies: effect: 3.16.3 find-my-way-ts: 0.1.5 msgpackr: 1.11.4 multipasta: 0.2.5 - '@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3)': + '@effect/platform@0.84.9(effect@3.16.5)': dependencies: - '@effect/printer': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3) - '@effect/typeclass': 0.31.10(effect@3.16.3) - effect: 3.16.3 + effect: 3.16.5 + find-my-way-ts: 0.1.5 + msgpackr: 1.11.4 + multipasta: 0.2.5 - '@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3)': + '@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5)': dependencies: - '@effect/typeclass': 0.31.10(effect@3.16.3) - effect: 3.16.3 + '@effect/printer': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5) + '@effect/typeclass': 0.31.10(effect@3.16.5) + effect: 3.16.5 - '@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3)': + '@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5)': dependencies: - '@effect/platform': 0.84.4(effect@3.16.3) - effect: 3.16.3 + '@effect/typeclass': 0.31.10(effect@3.16.5) + effect: 3.16.5 - '@effect/sql-sqlite-node@0.38.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(effect@3.16.3)': + '@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5)': dependencies: - '@effect/experimental': 0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) - '@effect/platform': 0.84.4(effect@3.16.3) - '@effect/sql': 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + '@effect/platform': 0.84.9(effect@3.16.5) + effect: 3.16.5 + + '@effect/sql-sqlite-node@0.38.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(effect@3.16.5)': + dependencies: + '@effect/experimental': 0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + '@effect/platform': 0.84.9(effect@3.16.5) + '@effect/sql': 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) '@opentelemetry/semantic-conventions': 1.34.0 better-sqlite3: 11.10.0 - effect: 3.16.3 + effect: 3.16.5 - '@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3)': + '@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5)': dependencies: - '@effect/experimental': 0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) - '@effect/platform': 0.84.4(effect@3.16.3) + '@effect/experimental': 0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + '@effect/platform': 0.84.9(effect@3.16.5) '@opentelemetry/semantic-conventions': 1.34.0 - effect: 3.16.3 + effect: 3.16.5 uuid: 11.1.0 - '@effect/typeclass@0.31.10(effect@3.16.3)': + '@effect/typeclass@0.31.10(effect@3.16.5)': dependencies: - effect: 3.16.3 + effect: 3.16.5 - '@effect/vitest@0.23.3(effect@3.16.3)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0))': + '@effect/vitest@0.23.5(effect@3.16.5)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0))': dependencies: - effect: 3.16.3 + effect: 3.16.5 vitest: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0) - '@effect/workflow@0.1.2(effect@3.16.3)': + '@effect/workflow@0.1.2(effect@3.16.5)': dependencies: - effect: 3.16.3 + effect: 3.16.5 '@emnapi/runtime@1.4.3': dependencies: @@ -14656,7 +14762,7 @@ snapshots: dependencies: '@bufbuild/protobuf': 1.10.1 '@changesets/cli': 2.29.3 - effect: 3.16.3 + effect: 3.16.5 ethers: 5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) fflate: 0.8.2 graphql-request: 7.2.0(graphql@16.11.0) @@ -17071,6 +17177,14 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.8 '@tailwindcss/oxide-win32-x64-msvc': 4.1.8 + '@tailwindcss/typography@0.5.16(tailwindcss@3.4.17)': + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + postcss-selector-parser: 6.0.10 + tailwindcss: 3.4.17 + '@tailwindcss/vite@4.1.5(vite@6.3.5(@types/node@22.15.15)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0))': dependencies: '@tailwindcss/node': 4.1.5 @@ -18844,7 +18958,7 @@ snapshots: browserslist@4.24.2: dependencies: - caniuse-lite: 1.0.30001678 + caniuse-lite: 1.0.30001718 electron-to-chromium: 1.5.52 node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) @@ -18961,6 +19075,8 @@ snapshots: pascal-case: 3.1.2 tslib: 2.8.1 + camelcase-css@2.0.1: {} + camelcase@5.3.1: {} camelcase@6.3.0: {} @@ -18971,8 +19087,8 @@ snapshots: caniuse-api@3.0.0: dependencies: - browserslist: 4.24.2 - caniuse-lite: 1.0.30001678 + browserslist: 4.24.5 + caniuse-lite: 1.0.30001718 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 @@ -19501,7 +19617,7 @@ snapshots: cssnano-preset-advanced@6.1.2(postcss@8.5.3): dependencies: autoprefixer: 10.4.21(postcss@8.5.3) - browserslist: 4.24.2 + browserslist: 4.24.5 cssnano-preset-default: 6.1.2(postcss@8.5.3) postcss: 8.5.3 postcss-discard-unused: 6.0.5(postcss@8.5.3) @@ -19511,7 +19627,7 @@ snapshots: cssnano-preset-default@6.1.2(postcss@8.5.3): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.5 css-declaration-sorter: 7.2.0(postcss@8.5.3) cssnano-utils: 4.0.2(postcss@8.5.3) postcss: 8.5.3 @@ -19716,6 +19832,8 @@ snapshots: dependencies: dequal: 2.0.3 + didyoumean@1.2.2: {} + diff@7.0.0: {} diffie-hellman@5.0.3: @@ -19730,6 +19848,8 @@ snapshots: dependencies: path-type: 4.0.0 + dlv@1.1.3: {} + dns-packet@5.6.1: dependencies: '@leichtgewicht/ip-codec': 2.0.5 @@ -19820,6 +19940,11 @@ snapshots: '@standard-schema/spec': 1.0.0 fast-check: 3.23.2 + effect@3.16.5: + dependencies: + '@standard-schema/spec': 1.0.0 + fast-check: 3.23.2 + electron-to-chromium@1.5.152: {} electron-to-chromium@1.5.52: {} @@ -21597,10 +21722,16 @@ snapshots: dependencies: p-locate: 6.0.0 + lodash.castarray@4.4.0: {} + lodash.debounce@4.0.8: {} + lodash.isplainobject@4.0.6: {} + lodash.memoize@4.1.2: {} + lodash.merge@4.6.2: {} + lodash.sortby@4.7.0: {} lodash.startcase@4.4.0: {} @@ -22502,6 +22633,8 @@ snapshots: object-assign@4.1.1: {} + object-hash@3.0.0: {} + object-inspect@1.13.2: {} object-inspect@1.13.4: {} @@ -22865,6 +22998,8 @@ snapshots: picomatch@4.0.2: {} + pify@2.3.0: {} + pify@4.0.1: {} pino-abstract-transport@0.5.0: @@ -22987,7 +23122,7 @@ snapshots: postcss-colormin@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.5 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.5.3 @@ -22995,7 +23130,7 @@ snapshots: postcss-convert-values@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.5 postcss: 8.5.3 postcss-value-parser: 4.2.0 @@ -23081,6 +23216,18 @@ snapshots: postcss: 8.5.3 postcss-value-parser: 4.2.0 + postcss-import@15.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.10 + + postcss-js@4.0.1(postcss@8.5.3): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.5.3 + postcss-lab-function@7.0.9(postcss@8.5.3): dependencies: '@csstools/css-color-parser': 3.0.9(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) @@ -23090,6 +23237,13 @@ snapshots: '@csstools/utilities': 2.0.0(postcss@8.5.3) postcss: 8.5.3 + postcss-load-config@4.0.2(postcss@8.5.3): + dependencies: + lilconfig: 3.1.3 + yaml: 2.7.0 + optionalDependencies: + postcss: 8.5.3 + postcss-load-config@6.0.1(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.4)(yaml@2.7.0): dependencies: lilconfig: 3.1.3 @@ -23128,7 +23282,7 @@ snapshots: postcss-merge-rules@6.1.1(postcss@8.5.3): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.5 caniuse-api: 3.0.0 cssnano-utils: 4.0.2(postcss@8.5.3) postcss: 8.5.3 @@ -23148,7 +23302,7 @@ snapshots: postcss-minify-params@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.5 cssnano-utils: 4.0.2(postcss@8.5.3) postcss: 8.5.3 postcss-value-parser: 4.2.0 @@ -23179,6 +23333,11 @@ snapshots: icss-utils: 5.1.0(postcss@8.5.3) postcss: 8.5.3 + postcss-nested@6.2.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + postcss-nesting@13.0.1(postcss@8.5.3): dependencies: '@csstools/selector-resolve-nested': 3.0.0(postcss-selector-parser@7.1.0) @@ -23217,7 +23376,7 @@ snapshots: postcss-normalize-unicode@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.5 postcss: 8.5.3 postcss-value-parser: 4.2.0 @@ -23334,7 +23493,7 @@ snapshots: postcss-reduce-initial@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.5 caniuse-api: 3.0.0 postcss: 8.5.3 @@ -23352,6 +23511,11 @@ snapshots: postcss: 8.5.3 postcss-selector-parser: 7.1.0 + postcss-selector-parser@6.0.10: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 @@ -23746,6 +23910,10 @@ snapshots: react@19.1.0: {} + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.11 @@ -24658,7 +24826,7 @@ snapshots: stylehacks@6.1.1(postcss@8.5.3): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.5 postcss: 8.5.3 postcss-selector-parser: 6.1.2 @@ -24720,10 +24888,41 @@ snapshots: tailwind-merge@3.2.0: {} + tailwindcss-animate@1.0.7(tailwindcss@3.4.17): + dependencies: + tailwindcss: 3.4.17 + tailwindcss-animate@1.0.7(tailwindcss@4.1.5): dependencies: tailwindcss: 4.1.5 + tailwindcss@3.4.17: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.3 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.7 + lilconfig: 3.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.3 + postcss-import: 15.1.0(postcss@8.5.3) + postcss-js: 4.0.1(postcss@8.5.3) + postcss-load-config: 4.0.2(postcss@8.5.3) + postcss-nested: 6.2.0(postcss@8.5.3) + postcss-selector-parser: 6.1.2 + resolve: 1.22.10 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + tailwindcss@4.1.5: {} tailwindcss@4.1.8: {} @@ -25569,7 +25768,7 @@ snapshots: '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.14.0 - browserslist: 4.24.5 + browserslist: 4.24.2 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.1 es-module-lexer: 1.7.0 From 31ae2f62a4ed2fe39e2446b0d1aaf743785a44b8 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 08:38:37 -0400 Subject: [PATCH 08/18] docs: enhance global styles and typography with custom CSS for improved aesthetics and readability --- docs/src/css/custom.css | 173 +++++++++++++++++++++++++++++++++++----- 1 file changed, 153 insertions(+), 20 deletions(-) diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 96ea530c..e972fc9d 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -1,3 +1,6 @@ +/* Import Google font Poppins as fallback (free) – Euclid is paid */ +@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap"); + /** * Any CSS included here will be global. The classic template * bundles Infima by default. Infima is a CSS framework designed to @@ -6,25 +9,155 @@ /* You can override the default Infima variables here. */ :root { - --ifm-color-primary: #2e8555; - --ifm-color-primary-dark: #29784c; - --ifm-color-primary-darker: #277148; - --ifm-color-primary-darkest: #205d3b; - --ifm-color-primary-light: #33925d; - --ifm-color-primary-lighter: #359962; - --ifm-color-primary-lightest: #3cad6e; - --ifm-code-font-size: 95%; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); -} - -/* For readability concerns, you should choose a lighter palette in dark mode. */ + /* Brand Colors – “The Graph” palette */ + --graph-purple: #6f4cff; + --astro-blue: #4c66ff; + --galactic-aqua: #66dbff; + --starfield-green: #4bca81; + --nebula-pink: #ff79c6; + --solar-yellow: #ffa801; + + /* Override Infima variables with our palette */ + --ifm-color-primary: var(--graph-purple); + --ifm-color-primary-light: #8069ff; + --ifm-color-primary-lighter: #8f79ff; + --ifm-color-primary-lightest: #a999ff; + --ifm-color-primary-dark: #6544f0; + --ifm-color-primary-darker: #5c3fe4; + --ifm-color-primary-darkest: #4d34c4; + + /* Typography */ + --ifm-font-family-base: "Euclid Circular A", "Poppins", -apple-system, + BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, + "Open Sans", "Helvetica Neue", sans-serif; + --ifm-heading-font-weight: 700; + --ifm-font-weight-bold: 600; + + /* Layout tweaks */ + --ifm-spacing-horizontal: 1.2rem; + --ifm-page-width: 85rem; + + /* Code blocks */ + --docusaurus-highlighted-code-line-bg: rgba(255, 255, 255, 0.05); +} + [data-theme="dark"] { - --ifm-color-primary: #25c2a0; - --ifm-color-primary-dark: #21af90; - --ifm-color-primary-darker: #1fa588; - --ifm-color-primary-darkest: #1a8870; - --ifm-color-primary-light: #29d5b0; - --ifm-color-primary-lighter: #32d8b4; - --ifm-color-primary-lightest: #4fddbf; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); + /* Dark theme overrides keeping brand palette vibrant */ + --ifm-color-primary: var(--graph-purple); + --ifm-background-color: #0b0b13; + --ifm-background-surface-color: #14141e; + --ifm-navbar-background-color: rgba(11, 11, 19, 0.9); + --ifm-footer-background-color: #0b0b13; + --ifm-toc-border-color: rgba(255, 255, 255, 0.08); + --docusaurus-highlighted-code-line-bg: rgba(255, 255, 255, 0.05); +} + +/* ---------- Global enhancements inspired by design ---------- */ + +html { + scroll-behavior: smooth; +} + +body { + background: radial-gradient(ellipse at top, #13131f 0%, #09090e 100%); + color: var(--ifm-font-color-base); +} + +/* Smooth transition for theme switch & interactive elements */ +* { + transition: color 0.15s ease, background-color 0.15s ease, + border-color 0.15s ease; +} + +/* Custom scrollbar – slim & subtle */ +::-webkit-scrollbar { + width: 6px; + height: 6px; +} +::-webkit-scrollbar-track { + background: transparent; +} +::-webkit-scrollbar-thumb { + background: hsla(0, 0%, 100%, 0.12); + border-radius: 3px; +} +::-webkit-scrollbar-thumb:hover { + background: hsla(0, 0%, 100%, 0.25); +} + +/* Links */ +:root a { + text-decoration-color: rgba(111, 76, 255, 0.4); + text-underline-offset: 2px; +} +:root a:hover { + text-decoration-color: currentColor; +} + +/* Buttons (using Infima classes) */ +.button--primary { + background: linear-gradient( + 135deg, + var(--astro-blue) 0%, + var(--graph-purple) 100% + ); + color: #fff; + border: none; +} +.button--primary:hover { + background: linear-gradient( + 135deg, + var(--astro-blue) -20%, + var(--graph-purple) 120% + ); +} + +/* Navbar translucency & blur */ +.navbar { + backdrop-filter: blur(12px); + background-color: var(--ifm-navbar-background-color); + border-bottom: 1px solid rgba(255, 255, 255, 0.05); +} + +/* Shadow & border for code blocks */ +.theme-code-block { + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 0.75rem; + overflow: hidden; +} + +/* Card-like appearance for admonitions */ +.alert { + border-radius: 0.75rem; + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25); +} + +/* Table styling tweaks */ +.table { + border-collapse: collapse; +} +.table thead th { + font-weight: 600; +} +.table th, +.table td { + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + padding: 0.75rem 1rem; } + +/* Adjust sidebar width and typography */ +@media (min-width: 997px) { + .theme-doc-sidebar-container { + width: 16rem; + } + .theme-doc-sidebar-container .menu__link { + font-size: 0.95rem; + } +} + +/* Breadcrumb subtlety */ +.breadcrumbs__item:not(.breadcrumbs__item--active) a { + color: rgba(255, 255, 255, 0.7); +} + +/* End of custom aesthetic overrides */ From 1a4a715079c72ba6b21631c7cdd346c6e2453d6b Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 08:40:33 -0400 Subject: [PATCH 09/18] docs: update Docusaurus color mode configuration to disable theme switch --- docs/docusaurus.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 42d04e1f..50b2b66f 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -71,7 +71,7 @@ const config = { themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ - colorMode: { defaultMode: 'dark' }, + colorMode: { defaultMode: 'dark', disableSwitch: true }, // Replace with your project's social card image: 'img/docusaurus-social-card.jpg', navbar: { From bc320f0795c879515269debb8111412dce46b50e Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 10:44:54 -0400 Subject: [PATCH 10/18] docs: update custom CSS for improved brand color consistency and background aesthetics --- docs/src/css/custom.css | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index e972fc9d..9a56caf3 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -9,7 +9,7 @@ /* You can override the default Infima variables here. */ :root { - /* Brand Colors – “The Graph” palette */ + /* Brand Colors – "The Graph" palette */ --graph-purple: #6f4cff; --astro-blue: #4c66ff; --galactic-aqua: #66dbff; @@ -45,7 +45,7 @@ /* Dark theme overrides keeping brand palette vibrant */ --ifm-color-primary: var(--graph-purple); --ifm-background-color: #0b0b13; - --ifm-background-surface-color: #14141e; + --ifm-background-surface-color: #0b0b13; --ifm-navbar-background-color: rgba(11, 11, 19, 0.9); --ifm-footer-background-color: #0b0b13; --ifm-toc-border-color: rgba(255, 255, 255, 0.08); @@ -59,7 +59,7 @@ html { } body { - background: radial-gradient(ellipse at top, #13131f 0%, #09090e 100%); + background: #0b0b13; color: var(--ifm-font-color-base); } @@ -161,3 +161,9 @@ body { } /* End of custom aesthetic overrides */ + +/* Make docs wrapper background match inspected color */ +.docs-wrapper, +.plugin-docs.plugin-id-default.docs-version-current.docs-doc-page { + background: #0b0b13 !important; +} From 7244ee3016f76b130397e46f0f448966c39895f6 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 10:47:18 -0400 Subject: [PATCH 11/18] docs: add custom background color for blog pages to enhance visual consistency --- docs/src/css/custom.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 9a56caf3..a2b203a1 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -167,3 +167,8 @@ body { .plugin-docs.plugin-id-default.docs-version-current.docs-doc-page { background: #0b0b13 !important; } + +.blog-wrapper, +.plugin-blog.plugin-id-default.docs-version-current.docs-blog-page { + background: #0b0b13 !important; +} From 3c49ff886f249f498ffe8942cd96c2c3ff6c9ab7 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 11:19:14 -0400 Subject: [PATCH 12/18] docs: remove outdated blog post and update author information for consistency --- docs/blog/2019-05-28-first-blog-post.md | 12 ---- .../2025-06-10-hypergraph-alpha-released.md | 62 +++++++++++++++++++ docs/blog/authors.yml | 34 +++++----- docs/blog/tags.yml | 20 ++++-- 4 files changed, 95 insertions(+), 33 deletions(-) delete mode 100644 docs/blog/2019-05-28-first-blog-post.md create mode 100644 docs/blog/2025-06-10-hypergraph-alpha-released.md diff --git a/docs/blog/2019-05-28-first-blog-post.md b/docs/blog/2019-05-28-first-blog-post.md deleted file mode 100644 index d3032efb..00000000 --- a/docs/blog/2019-05-28-first-blog-post.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -slug: first-blog-post -title: First Blog Post -authors: [slorber, yangshun] -tags: [hola, docusaurus] ---- - -Lorem ipsum dolor sit amet... - - - -...consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet diff --git a/docs/blog/2025-06-10-hypergraph-alpha-released.md b/docs/blog/2025-06-10-hypergraph-alpha-released.md new file mode 100644 index 00000000..5a2ee4fc --- /dev/null +++ b/docs/blog/2025-06-10-hypergraph-alpha-released.md @@ -0,0 +1,62 @@ +--- +slug: hypergraph-alpha-released +title: Announcing Hypergraph Alpha—A New Chapter in Web Development +authors: [slorber, yangshun] +tags: [release, alpha, hypergraph] +--- + +After months of development and countless conversations with developers like you, we're thrilled to unveil Hypergraph Alpha. This is more than just another data layer—it's a fundamental rethinking of how we build collaborative, secure, and offline-first Web3 applications. + + + +## Why We Built Hypergraph + +The challenges of modern app development are clear: users expect real-time collaboration, bulletproof security, and apps that work flawlessly even when offline. Traditional architectures force uncomfortable trade-offs between these needs. We knew there had to be a better way. + +Enter Hypergraph Alpha, built on two core innovations: a local-first architecture that puts your data where it belongs—on the client—and our implementation of the GRC-20 standard for truly composable knowledge graphs. + + + +## What Makes Hypergraph Different + +At its heart, Hypergraph is local-first. Every piece of data is stored on the client, making reads and writes instant—no waiting for server responses. When you're online, our CRDT-based sync ensures your data flows seamlessly between devices and collaborators. When you're offline? Everything just works. + +Security isn't an afterthought—it's built into our foundation. With end-to-end encryption, your data is only readable by those you explicitly trust. No intermediaries, no compromises. + +The real magic happens with our GRC-20 Knowledge Graph. It's not just a data format; it's a new way of thinking about how information connects and flows through your applications. Every mutation, whether it's adding a note or updating a relationship, becomes part of a larger, interoperable knowledge network. + + + +## Looking Ahead + +We're launching this alpha today, June 10, 2025, and we're targeting a beta release in August. Our roadmap to a stable release in Q4 2025 is ambitious but achievable with your help. The beta will bring enhanced stability, an expanded API surface, and comprehensive documentation based on your feedback. + +## Join the Alpha Today + +Getting started is simple. Install our SDK: + +```bash +npm install @hypergraph/sdk-alpha +``` + +Head to our [Quickstart guide](/docs/quickstart) to build your first Hypergraph app, or dive deep into our [API Reference](/docs/api-reference) to explore the possibilities. We support Node.js and modern browsers, with React hooks that make integration a breeze. + +## A Note on What to Expect + +Let's be transparent: this is an alpha release. You'll see rapid changes as we iterate based on your feedback. Some features are still experimental, and you might encounter sync delays with larger graphs or limited support on mobile browsers. But that's exactly why we need you—every bug report, feature request, and question helps shape Hypergraph's future. + +## Let's Build Together + +Your voice matters in this journey. Share your experiences, report issues, or just chat with us: + +- Found a bug? [Open an issue on GitHub](https://github.com/graphprotocol/hypergraph/issues) + +- Want to chat? Find us on [Discord](https://discord.gg/graphprotocol) + +We read every message and your feedback directly shapes our roadmap. + +## Ready to Shape the Future? + +This is just the beginning. Hypergraph Alpha represents our vision for the future of Web3 development, but it's your creativity and feedback that will help us realize its full potential. [Get started with the Quickstart](/docs/quickstart), explore our [API Reference](/docs/api-reference), and join us in building the next generation of collaborative, decentralized applications. + +We can't wait to see what you'll create. diff --git a/docs/blog/authors.yml b/docs/blog/authors.yml index 8bfa5c7c..5e45372d 100644 --- a/docs/blog/authors.yml +++ b/docs/blog/authors.yml @@ -1,23 +1,23 @@ yangshun: - name: Yangshun Tay - title: Front End Engineer @ Facebook - url: https://github.com/yangshun - image_url: https://github.com/yangshun.png + name: Pablo Carranza Velez + title: Engineering Manager @ Edge & Node + url: https://github.com/pcarranzav + image_url: https://avatars.githubusercontent.com/u/2223590?v=4 + permalink: /all-pablo-articles page: true socials: - x: yangshunz - github: yangshun + x: https://x.com/pcarranzav + github: https://github.com/pcarranzav slorber: - name: Sébastien Lorber - title: Docusaurus maintainer - url: https://sebastienlorber.com - image_url: https://github.com/slorber.png + name: Nik + title: Hypergraph Lead Engineer @ Geo + # url: + image_url: https://ca.slack-edge.com/T047DS7N1PE-U07PPQ3GN7Q-gafcee4ad6e3-512 page: - # customize the url of the author page at /blog/authors/ - permalink: '/all-sebastien-lorber-articles' - socials: - x: sebastienlorber - linkedin: sebastienlorber - github: slorber - newsletter: https://thisweekinreact.com + permalink: /all-nik-articles + # socials: + # x: + # linkedin: + # github: + # newsletter: https://thisweekinreact.com diff --git a/docs/blog/tags.yml b/docs/blog/tags.yml index bfaa778f..bc544dd5 100644 --- a/docs/blog/tags.yml +++ b/docs/blog/tags.yml @@ -13,7 +13,19 @@ docusaurus: permalink: /docusaurus description: Docusaurus tag description -hola: - label: Hola - permalink: /hola - description: Hola tag description + +release: + label: Release + permalink: /release + description: Product releases and updates + +alpha: + label: Alpha + permalink: /alpha + description: Early access and alpha releases + +hypergraph: + label: Hypergraph + permalink: /hypergraph + description: Posts about Hypergraph development and features + From 32639153d55c99f2fe9c489e6f9f1d8a3240f9e1 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 12:44:22 -0400 Subject: [PATCH 13/18] docs: update blog configuration and authors, remove outdated posts, and add new content --- docs/blog/2019-05-29-long-blog-post.md | 44 --- docs/blog/2021-08-01-mdx-blog-post.mdx | 24 -- .../docusaurus-plushie-banner.jpeg | Bin 96122 -> 0 bytes docs/blog/2021-08-26-welcome/index.md | 29 -- docs/blog/2025-06-10-entities-and-types.md | 115 ++++++++ ...25-06-10-knowledge-graph-best-practices.md | 227 +++++++++++++++ .../2025-06-10-properties-and-relations.md | 160 +++++++++++ .../2025-06-10-serialization-and-encoding.md | 126 +++++++++ docs/blog/2025-06-10-spaces-and-governance.md | 267 ++++++++++++++++++ docs/blog/2025-06-10-uuids-and-identifiers.md | 168 +++++++++++ ...> 2025-06-11-hypergraph-alpha-released.md} | 11 +- docs/blog/authors.yml | 4 +- docs/blog/tags.yml | 37 ++- docs/docusaurus.config.js | 1 + 14 files changed, 1095 insertions(+), 118 deletions(-) delete mode 100644 docs/blog/2019-05-29-long-blog-post.md delete mode 100644 docs/blog/2021-08-01-mdx-blog-post.mdx delete mode 100644 docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg delete mode 100644 docs/blog/2021-08-26-welcome/index.md create mode 100644 docs/blog/2025-06-10-entities-and-types.md create mode 100644 docs/blog/2025-06-10-knowledge-graph-best-practices.md create mode 100644 docs/blog/2025-06-10-properties-and-relations.md create mode 100644 docs/blog/2025-06-10-serialization-and-encoding.md create mode 100644 docs/blog/2025-06-10-spaces-and-governance.md create mode 100644 docs/blog/2025-06-10-uuids-and-identifiers.md rename docs/blog/{2025-06-10-hypergraph-alpha-released.md => 2025-06-11-hypergraph-alpha-released.md} (84%) diff --git a/docs/blog/2019-05-29-long-blog-post.md b/docs/blog/2019-05-29-long-blog-post.md deleted file mode 100644 index eb4435de..00000000 --- a/docs/blog/2019-05-29-long-blog-post.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -slug: long-blog-post -title: Long Blog Post -authors: yangshun -tags: [hello, docusaurus] ---- - -This is the summary of a very long blog post, - -Use a `` comment to limit blog post size in the list view. - - - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet diff --git a/docs/blog/2021-08-01-mdx-blog-post.mdx b/docs/blog/2021-08-01-mdx-blog-post.mdx deleted file mode 100644 index 0c4b4a48..00000000 --- a/docs/blog/2021-08-01-mdx-blog-post.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -slug: mdx-blog-post -title: MDX Blog Post -authors: [slorber] -tags: [docusaurus] ---- - -Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/). - -:::tip - -Use the power of React to create interactive blog posts. - -::: - -{/* truncate */} - -For example, use JSX to create an interactive button: - -```js - -``` - - diff --git a/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg b/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg deleted file mode 100644 index 11bda0928456b12f8e53d0ba5709212a4058d449..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96122 zcmb4pbySp3_%AIb($d}CN{6sCNbJIblrCK=AuXwZ)Y2^7EXyvibPLiUv2=*iETNcDDZ-!M(5gfan1QF);-jEfp=>|F`_>!=WO^Jtthn$K}Goqr%0f!u{8e!-9i@ zhmU(NIR8g*@o?}7?okromonkv{J(|wy~6vi^xrZLIX*599wk2Ieb#lAbZ*fz97a4{ zJY7PbSOUsOwNy1OwNzXx4iXOC|2z)keOwmKpd-&ia_{g7{tN#ng-gPNcc1#tlkjM! zO6lT6;ZU0JB&4eA(n2(-bp-FTi8b+f7%9WKh({QCB8bELa9lXp#GSXVPIvbL=ZA)_ zoqe{#7VMtQs`;Ng5O8q3j-8IgrN#}94v)TX4^NlszBRSzdq}A`TxwFd3|y~ciPQw? z%W89mZQrCUNI$g^7Oh9(UFDIP_r7lI7lWz&hZ1*kZ$baGz-#@nL4S(s3tjnk2vk5* zGnL>!jFf8k?c!+McUT=ympT%ld*3}>E?g-5z9LI_yzT>@2o6r3i2v)t?KwGOxzsp5 z--7^Xa4<>>P6hlaW!G1-kpn0Y2dq(kdhFvvV+2FM0)3np}3GKzTt;)#GZ=Z?W z!}GMkBmSB3taZb*d{@PnL&d_l(Ks(Z2Nbb?3HFfuIKl`Y+P!9$uuAsc53|NzT!gCE z{M_rr@ucO9AC$3tNI(^d8!3^&0lCM-kw_(|g&{O!)%`pqf8E|0W;wYyy}6&z6(2B; zRYt1FlHZ2C7vc@FdKzC@n?}jobe2D9^;P-sa5`IfwpE1e6#N|6qQw8o+38045pxM* z_59Aq@8~>dJCtqhns#jEI~z0hACBNUZ;I~qj_$}bPXswGCwZz`c=)~lO#R;=sD(%9 za&bUY81NY4aNY25K5M9{QQ`EOS{V4jzXdWnDdV2b8HKe6T<|X$Q%nTAemPnPhtCab z@I(`E5U22@kW&(;Pynv}zWp62&;CfRX7N~Ze4eAlaDu!0dW=(x2_An*}x3G&V2kUsI=T|3LqH$PFPB?r*Kh zT<(BanS8n8ZL2f{u<*C=c;#&Iv3z05|BtwHPyLVX$JfSZ-nPRGyw_WdBUAS?NhDHJ zmzyA*oPZ~V;9d%;G25NPBOfQ-_D`B?F5{09Gw9nt9ehQ4_7uLZZQvbQt_P+|;LlMZ8=jss zF^Gm7)AuJd!9`>njaJZ$iVyWbd6|Twl_cKuZ2N()vsz1j@E37vPyKyt=e2GqZ^MR~ zXIy^LItyv$VNEn)MYm=|*3p-TDZIgKxoy7MI3JQa*lF%)ARPfF;fs*DQ?da`y7oEU zh_lgIWD}kW>MyGS)zaY65j&?~?T{j(I0L8nXp-HVZ_c&_z>K4Vi_<5qV_D*Pmntfm zcZuH8?M-w;z;3X$(8R`DMJ?#^m#o9ZLE0Ismu8& zDF)Q?Teh3z;(@8v6Q-&8=w`afg3mLQ85XKF=>ht;Mk<9C({@^a!<@Wn&e@#S*tGZT zflx~uFh89d7#69BINhL^;7=1nNyD(`#`N(kcJFxJH1wC-G z;3~)5?Zx+e8gBGJEGIZpXCR@*4E3T{e~F3|np7zaFTW*H$6lk=q&W<9@%|HhT)JsG zi?G)xD*Su@aGq|R2%ww6-{29RSlN?n22{r1v7(>8AqB`_W!ed6MbYgY>Lr~WdJ&67xXmBw;p)KRhD8c| zJPCE$_%TC!QMW^NN%e0n5R2!O>QuB$oNP`QHKU(-$F6g084quR%O&2C0<#jZqHNw4 zg}XntN)!#<#jr(XMe}^|UlLdeBP*t#i${&;_yuBmDs$W2O;1E|sSj=;W^ zSyF|!M=xm-QCXVU7mQ}V(~7UrsKOIK5r4^7F*g0VH)w1<|34dC_`UQC*oTu=+B`9* z4Jh>4me{%44wl;7BDJkvDDWJ6SL?-=_fdbjK&XRp5Vk`9;#>i?%Motv>V(|7;A}}O zU8%V37GK!!mZHZ`7L5Ns*ztfB%;y+ar#4rSN%qi@zDw*8HNT7L@UTW-9V>6VIrIS2`w$ZVxrD_Pvo4;!t)?he`;kX47HQS z-ZH7w(v&VJyMNj9a9hr72G+d({AQb?zG8>o3fA&C9sA)(_LXsqbK3q#_q2In;XuQA z;NKnzM$3uO)*k{JyOnxO7id4ceg~27qWT|x^KLg)9iN9N9QmA0xoo+VRJA$ z_etyG#Z~#aXRpU(?tAXq{@pX43OnVh@LXP_K@+?k9bogc$6N&(^|_I7ezWOoTLFK- zq`ji~=M!@gj*9u2?}O^~rbKuIaGHS#4~<7S&j`ui!Fw}>9T~O9Fj^ zyN};L5Oen^`4*<%c5`ifzl|RH{yv(l$yZoAGe7Vxi@NG$b$bfy@^r|37dNU}^yhDP zg3>=6>ltZV(tkMK&y2yjHjZAHEU1)`Px7LL-ApPAQyMeeb~^%^Tw+x_#AO& zwY9CqLCRqDuj8Hhori(`zOq4#X2@itHGeu;Oe8noy z;iV-)*{@MgVV=ZE;SQoB`g@sly`(oumzOeyw^%x9Ge`JZfNAQ3n*xKER#RJN$@N3` zX|n~{{3NG=HSLm3|GFI)m9jjMj&1 zi`#yIC*L7GD%~$4EPts}*Rd@VTe(M6jJF8MDif>-iGqb9>Q9zYo92egEmZacG>pIx zT3XS%Wn7uU37^#?IO>Y1N%%BY>lt24Jq!#rl0 zE|_4f751``XY#Kqndv+Y0tJc@_=K|OoS7Hcx$j7now-)jIS@SJ7Z`qR{;qwEN!yw( zrtTrDt}LdyQl>pCJEisU{ExS-0(RC(8z?xeh0uYie&4|@NL1Kt!PTFRbK~9VJLd%? zyjj}ixr`csCmc9SDb<>2>GnCHm-i(a=t69-_MDt5ksjAVU7k>i!(BOET#;8#cwKh0 zjS=YVlpYl!E7+!y;RpeY=C=*|<%&Oh2+5qCv^JIR3Of1ue9k7N`?6YW;A+{c(pyeP z^ZpjVK^#7%E}QYRtS*uaK_K$Oyoq3%xOCV3?n&qBv}Qc;N8FQ2O#u{>slaV21l1Fc)AyIlbfdX7AExO{F?eOvERYJb;Ni zckPYRgfT@0Y4PwO%7BY@l#2<^fKapIft)oU2O*-JU&?8;Z7Q467Gqyc1RGqTp3zqn z_F<{stV*oYnEE+<1}A|K7({3kbdJ=r67p>3|7YtA6(Iw>`GxKnm1Ve>A@&z9Vvu8H`OuD7{B zMq(lkGSK&awU^aqf~Hx?^P4cUl^^fU&*kPEt$t4z0-PMDv!U}pIKO<9Sv;GRJ{qnc zM#0V^%Zxa5H(Iv{@2xzz5#$zpTWxaaiu@Y4QU89(yi{9^PHM{|J_i?6y zgf4QjZLTyomqcSjIJKGS3lb zSwmVhHvq>|mo6iNA+%kh;XIm9P0(Wjl%N@e!Uo|`7fqKQ0Yb{?nwhp%!%@R7IgQ(J zLdJbRkfT+8-daWy0_~Aj4@&Z<8;^K*_MKdo=%J+qo&7AP5Y>3CZDQwLk>VrP-iE3l z8mvBgeWl{(67&r>s zolqo}wttX5$056wr+?q;8$fEMMrSIe%AQCqi$0{Qt{6t|=rBnTL`u#0;b>^^q~bHE zp{uMeEEOF+C@Bea`ih=v`oWzl`fF0@xNrw_gl78Y95SqUn_wnsHu&(x4lD7hc2>u& z+c4)a*}b=lY{4v4Y@S1w5Z2f!Jq8LAqHhf&HyFe+xH zbfYn zuHOaD(3Z44uZnBo`1Un7x{2QW9QCOpsNS-qWe%Q$F)qV<&9q&PJhD?RJ@V!6b{5RuzyJ7cBd?%j{&sd zks}NY{pGQJFNu*E%g=q^iNCa_pTISw{g5lr<;sbC9@&D4|{$QCRNde}1aaR*iIJ>SkWWj9GmQq+0=}_`Y_Ek-oPg#tRE%68|XT zB;g{AmDK0gbP&>?-)o<(f8r}>S&x@WpxLhLJ6!VHvd^8m{d!dr7T3pz$ zkn$>3T~Nk?bRK9XEGr-E(p1z!l=>NOIE93eV1Q}%M}o=Jc(kJdFI%%?IHjKWBv=F- zs0kf#$k+|N^0Kmxpqs_13OW!7mM)n&4n{0j?O}zqJVqRfO0L;*JN}9tgHPRp+@oVB zL^!D_@iZhfor|uMCvR_WYBUa3qK1;a0Sidz=3nvFUmND_0QX-%no0}PDmmBm$!Q>E22?Y^dsKW0G}?bkHM8iy?HUZJe3D3p>1 z{o>d|o2RGDul?wm_UifFO%C!~|FkRJ8a~u-1G`aKtr9TmNLt2fx<)$)zT|Y_bZ~;j zZ}|?5bT+5#t2#Z&ZjZ&(>}e~tx(OssxQ3R?$4(c{8| zA{yv+v62$*(TsZHW7*HdBc_*TZp57AA09eH5#R)*7`b!#100}{HOmdQKm_miUqlBW zZD@x|#G<>fCMXis0q5cF%MdAB0y4U4`ufgyXagAF75QILp?OQMg)oJ-I5tcXNTV3c z^LdROg=LH8OWSuduIFYH>yoIy>?K#m=7i9g&A;qZckd=Qq`Af993c<1HC+HF3?3TA z@mXTS>d{;Y^&|CQE)x8(;Ecs0QHElH1xI&d6&Uq}k*an~<;wvD&Gm?=IaRXC4_2t+ z687TAZDvFH`P_rv+O+vii*ILLDq&e;Enb4GCZxSUyr*?BG*S{dy(~hS+d8%Ae9{Q0 zDFTsg9%WffrG!4@g#5<1DSfOuyKOqS6anp;I0|{^ z)V|zlQP!t&b3wI~7AJ(b|n}V$)IB5Fya)0*qVbt^^Xy>&KoM5@G zgv~8hvW8mIQ#^U!=(x z9?eBPZ$ao`DWyTW$iz!Q`hLz+KZ&*med242vVjHA{9$>d~E!>k~8H`e}5Ob?c^7D<+;Pp*!^~!b~jcszphKaneeErmWa|Ii2Oi~ ztGB4PTrExmF%PO~Rlw{5G?R45H%J2)zC4d?gLsc0?I}+&@ z{srJv;THoXHj*l`5Q|Tga(WP!7MOqS|4vLj8TW$CZa(*>1?6`$ z@pb*I!r>YumfjryY$QPZ&5ybh7ImdJ=}jf0R&Il)Rm8;{T#`EZ(8$4xK5)i|(J2>A zM(ECw(3nO!P|NY%80nn9)0)$_wQ6EY)@tA=fiw6Ckl?6%O@ z>iR~gE<@*gj8f=2)9R#xOOTiDw+cG>OO%J1<=dA?ehZH`uc}v z5rU~T1mqht0WB?l44gV3*5~ubC7^VJ?0P zaXK-^Pxha#1TpdkU7p`ESsU|D+8lTCPuba3r1}NxZiE&_I8Tx1G@)B3Ie#b@e%d`@ znIB6?VVd@|FiiIY5+r1dt`0*7CSknIt4x^I8lcbofDCyRBVB4u4goFQzHpkSVflWC zwCjG0O1Gn0h4%24jU*=Xv{Dg1GblXO54Wq$@-$o{ecO2#8L)Ph46``+>pER>c+GW$ zM(_lX8sW#qMTjI&_xnpy7&J=2N6?X_`pi{1qV%(bZ`?B|_=-Wqy}i#QMBhD-9s2~c zy7b9>k)dilS&g_J-(ltH!~Gud%K0oYXy7WObRVqWIQWFXU?{rDV z3ggo;zJQqxIwniw*YYRCIa)*_EWpICGC#=Rny3r;`R@LdNvYW-FgcO%z3NicRCZ1~ zr^>u8=iAvGHtZ*OTiMpv9AW!t^yU%s#0J_1Jj(G-;n1NVwt|-9p@r5g=&hhj z1nyyZ3~Dv2^qB>>zG(RzSlG|YU8v?0scfBa?5rKq+S(q|BL=E&8z;zIi-JpLE}t{X zC$jXzp9eAMETY=;3mQg({0eFdgYQ^9w`8`P{pXzAibKLGsLZIHeGwLV?3;0NhcJD* zW=jF6I?uh7cnonu|01<_;8Y**Gym3BCvZ@ivavgH{8Ys)L0)!KpF3kN<)NbxWqoIg zk}H!2P(+*L^U;+}sAL7~{4z9T$5;N&FXJ@lEb!F(Tz^mLXIY+Xoa8TCE}?oMt@2dF zf>B7vRnrXYt*^{_10oHxyR&QIX*_A69}X}I)WsaK?lU?w zy$^EMqSM;=o9rGpvC;Y5hd$=({MVCGg0~qSRl?QF2fWElYI_6-(v`Ds8JXMNUh~@d zWH?o5p$-i}&}iI?V3Q`#uX{eS$DhkUlnCO>r#B_^e^(O7Q{_t^=vWq6c#OCzKhoO0 z>32c(onMuwu)W}-EUGQg%KW%{PX{kY`i8q`F3DM`^r z!$)9ld2-fLN3WUry+VwXhmA^BUOO{*tc=o0;~`%Ca<(w=m6pWoO?LAFnnITD$;4f1 zdH)T)1!-l2iUHo|F5wV+q=!``)Qy~Ut5}0LPVcL+PVN=`-kE|*wA&=vLJE}>MFf9) zLt!6O^ZQ)(vglM}uzOPd0QN`M;WPw^X&aoW#x|kYoR#)bCHgEbGjry|844*9YTYBCxxj0&FM9T;FV9bu>;C5|_XUj%`lRr>o+m|j2w35a*LG`KiegseN*Vq||f zpKo+14SwyV7d7ICZYcB%nnqii`@U>;LT4X6c&u$(mMQCPn=5W1>fVq*>-%eSmqRPC z!MqV{0CK-po#-m}|GiC9*)!(f7%0~@X2uh8`BJ~{dz*Ync9O1wkf5C)WL3naIzopG zHvd`1UOoEtlLa?}QOao@HL{F{mI*K65TO$*SkruGJ9cH}2ju9?KuX(8@a1Zyo$)6p zZyW0qF;H_NM7dV)Yj^I?H(w9Wej^ra@(z+8`+Jgw!rYedJu7|k=mo4iUFPzl(M6VS zbbu2fb6_=)UQm-WUL;&3oCNw^s!y0Hb?(x+elVSM>w^f#=jtvUb~6Iia>Q`3alZ4| z!j996r)(u@83OLDw6YetLb4iWm7+S)t#!mEva~OF7%~>=+DuYL@me!-;)J-gNC*Ur zA|;5H1@Y8rW7RV?MKh$mP_*+bS%!1)S_h2SJYQ~+R#cC`zu~d? zOI^f%5GtC|SSF%ErwSjA*`s8rtbF=>d9`-kELhy1S3P;&3;1gB$_sWdlY5=>)|YCs zaAGeo=f|WwwRBBaT#s|qO#D)%Q;5EdbB`@>l^)%EEnYRfsTcDFB&!5TF%z-b@a2FtQSU0aD;eRfc&CPic*R+ zQbd1TSU857kART6jzOmnmq^G8r~e1=S?LE$yfUi^VJk6D{f@%0hFYyxTKCqM!_Lku zY?H0EO#0bF4(UWmhPVFYySswtbAxQ}j15fDU32FbfyU}l-O@JSrLX?sX!Q*h5_tkQ zCtcr27j3zI(b3|TZI*t(-ta7BCGeIEc_ZQV{Wlg-iBLFWy!|NdWvue9$0BQj_1$Bp zr`qiuEt0~v+OhZwhq8Mi1 zIw8~;Sm0}2 z`#Z_V*`Gtl7e<#qj`xO|P7M?WmGffQxcNF+x<%-$!L__0mD(0f9Rop;vZfa(V)yz1 zE-cIPoYeHN29k7N$0WLjCYs!YP+iwDozf(gSe6H*1g^^7?82$E% zS+c>;5q8OK9qMVDD}$)M@dR40nw293G2)zguH2&?cwoLJ@+eF4v=>g#%A}>R(~ovXE-mGs73s_&xby_%f}MF1omBoV~8zG)9FCUxZl+03&8 zMo*Rg6u22p>bxtf#)@PI_~o$3n#$C2TEy|2cqEvo=<>YQ3@_0OPn8mh1#_wmn~5Yn z(=m}EIZ6e^^W+<*D*Jjsy+Jv`4jwSyeGF%ijP4W1RK5u=$1-9FkUWy?o?OtxR0Px>TvF0%+;luL8uZWYWuM&>2#N1M!zIM~ zhjVaUQF{cRG%+=sIXEzp>C($LdH*Y4BMVuE%5!^vX=7DW4mYLY6uXrMul&O?U)Dw# zT)+#OII#l7ZY~8)(sLEwpPp#0)67O3m?;PGuT61U+pnzyzr?t(-rRHH-%+c;ob;ZTF5`H3a7k^Wg8X94FwFi1kV+$_Yy zXTvfH$(d}PRhZAsIbAPRB9M;(jZWnP1ImuH&&>3^RlXX)u(sWW=FPKFU!tUjb@pL} zM|#Mo$rf7F^D~+khXrUzlW0<>wk`hb=gjg)=96tX2ReSt$^b7Zi2q0`^>L2Mr9tR% z440)8CVH`A)GyCarH4?V9@etZ*faJIXV6V}Fcnz?m-2gUUh~mrxZIeajFUNrlTk{Z zd8sQm@el1OA7qu!%gLx;NRQwm8FDb6!>VPO-c&0AgXL|~UNoYcW=DhKeWW1RH!C%o zA;q+nA4?I~DVn>yGN`g6aYj&?iA7Z#onO?v!NtxbNE^W&*y$}dlE!C{o7m@c%*fS0 zz_~2;b#I7Ri799%3IhVZ4E5H3XZZel*OWLYUV9D0Tcg>O##T|P>{`(AY+jFhL5fu` zuynS{@E;DK%W}HBYW8cB&UoQgH6{>)SrjCR^|%5U4({A*VAW|PXETk@a8a6(dRzwt z#{=^6uZG6(CCb&TCN=!S5#mZI6Qm5iRyHud%LsK8(y}cz$?%hxRVbYcSk(jQ)Hf*q zwl`RXgq%Vq2>?qiQLj(sikZ5M2--71+VIB4>t#QF5kY>+0 zvdrvFUKb|@`qYA_DY~F8uSs*wtSyZjru;0Jd3f;q2xc^|l4;ainHm0GyTBPE^x351Nfhu+U_zM%JNv5tRNY(SJLI>_cH|`_% zBv}sM>s)u6&ftbT2iCAIbVYfaUdPKoAvKRr(h$g%l=euf!4+uP{uuJ2-j;C-gh79tNgvD!v);u3L54L8bMpdHOxBezyB$J z6t|CIWiq(2k-xMuIlq+@%c*oUf)auDn&NzqLb-t?B`)P6`sEjdLaw{t=0WE!psHKgYc`L8 zG7f5fbN<5Tc|Sc;VfuD8K7LsFY}c)XgtW)}UzLZ%PN2{=X%SF}l%n5@+mX^Tghf)C zQT&=hLLvxe&MK4|eJ=aMDkZi-%i5#;LRBB}9{5$@0{+NM_YoNPz_<(gyMe8_SQH4* zYs|(<2TOk`SN+|6){TN8HLBf=AL?Q5Wca0h;$bU05=f4Q$Ce1foxm6^F#KFxsX?$Dq%n7L@)AR}- z&sp2&#EosZM2gM29vW25{lhV-Z1N)rJ*7vJCt41#dOcxI`~uT!F-f|GtYZ5$j>V<= zK@HEb<0GW9P6e=bcVm#Ty6$x8j)|034zm=W^ZG!o-(MwhvzB207jL{j#Wr zf3d4_jvjQH2}PJ^fXo642QaQa6SIkfo=`<$&eyhn3IQPVc8GcDB52|H1>8Iut^!rs zC*ZD{x=G}jXK(yQf)&(+qxcckLnigZ_sae;{8ma1@=cIYvEfv1*!;%B!dd$t&bjiX zjLpiO1-g7WV!!s2{{sGJM4)42K)c}T-{uU*qv<>aOU}lXLmg2AOHj#J zki~HRbZ)>CvNm`r6BJX`hu2KeqCd0XlcA$ofF_0`t48MYK62h`5peGP1hV>0lG|m| zgWJRC+n9plKb-fsjCaB)bz?)}0q9?6jnI+-?$-r+K$|Br+H^=3@NtAFT4l z2Pi-M&*wPOB{W@wZ-O;n;LC&fOFKV-3^r~IIPJgH(Qpu5xoI2h@Hq2uu%{?y_46MT z`3othZz2iH{As=P+;}S0rE#`E2WqQPfr4&cPe(9Ktb~6jBPFsV>h*v;I40yZ>^Xz|QmC-`*#T zuCmXO#@x)`YmiZR8qy(gIa|mxze9-8a>4X|+Ry(%r`IIcXF4{gloG(w0Zv|e)-5$B zFR9*Ql(r&d+E;8rd(IRG-B*ayI(PfB-?UL~Sow+1Y4{mk=}6!wG{<3bm8%d8uUrRX zmFS*Vz0j+ynQUc{u++Nh%~FHPUOSb49r9StxA6XyKILE2qHS&1_qO5K(7%#T@HtKcx?+ZQBOAI6 zjSor!Q1@$2J=(O_HaIy^gFP2A$xAdmljhq5dELa!}A8tv_9E>5Ol!F@<`mu)dHKWLPv8lunR z;OOt%(~^s#z~1uT!@rASj6#`Nmj}}IFv3aFcO!H^@q(MZJTTgRp^!Gf+__|qf~;VN zi>pFV$ZLa%?x)U?-2o`@C8FW}Sz-J?zzrs5rzwS@>I5oZ6ywRw%hp6$!RgmP|KjOf z!Sh%rRz+hvQp&hGy~Ukxr0p=@*{0=yDy-nJ>BKdX*G$(+(b3QMum+kWNg2&~*QLko z*W@&s%qtW~J;Y)|y`9@2H=L8(Ewaykmwe8eGoQM|69>+i-|K}6x>gKS#w+7x7QlqV zWPRPKP-iA@jC;mm8gxvChZQj)VB*g`$U?84Q`ZhG`5L zQy;))-`BdwToBd$!x@&Xywj>yJyqDa&Man!bBR~&6<*P2C(knRy+@s&_;u$^UKHfL zNBExjJ*17XN{9=moVp>;T)*+>pweV zkqpPE)($ap_+Oan)#DL9H~w}L?k(hvtBW4IV&9$Cr4Od_f)RzC^~L1!`|># z%$v-L4zH~s{FG?hm6~J@(`5 z@`I*$QL}m!U@6E;u3tZdA;Zy|LK$qFd~)|2nDUAgHx~`vsT?0SUx3qCZrY@j7kjfD*hyUc~L86s!14rk9 zgm*6%*gqkK0`bL+Zg+j~XHVFSQIBw7*$Z#)kkG2!y5a9)CjoMF^wVLI<^@ zIG0@Qu4%nMp-ild>IADcH2JQf~6e)%OI_(LGI%=;Kq6B!MtwqJ^yI{BcJTot62W z%=0 zbQhF7T1G#I`ri6IHd>meOq$Q8)X(GW#bd(F)mbI8kpinT ztcWRAGA676;jNDmc4Og6y_9kq(M=rWX@cp?m6rf0*rdu-)K<>Pl>UVBuCkK;` zE%u(=@;kY8LZ<%Va5u)$DW+4IR+nq}t^s|@&qsqC0%3oF0?sUF&WnEMCqfs>yj(5T znL-zyT3Tji@~Wl=s}l>LUS5xfJ{EDzVgjIvR62OTN4g;;v})iI#h>;DcD@91_qzDW z4k~tTj{CRg!qXZztF^-rE9H6ZkV_hxOJEk=Evxad%L7+x-rYG^W}-O~#KxuhzLF(Q zs@zanss)5G^SfRH11hS^wy?u*oxD&rZ7PiIDg?raN(ethc!mQqycn%QvGm*LuxCLD zSnd~+!|TdT&_PGUrD7M!_R2e-i#>k5rw$dZnE-)||r z{~(#lp0ApHDfmZ|v2cj{#F@HP=l}0w(_) zGeJ5XB1na1WHT-Z-S)q+lLKXa>`ib2Ks?g;6g6K7UV(DTZiQ6)YLAW~{sVO{hYd#3 zxUvg3(}g)twI|k_tgjwEIH^zN3E8*vHGATJvELu65&wMd`D?_S%K!-5w1suU8oUi` ze#ByP=JKgEAxBE((U*1&>YvH3Bymg9d5uVGeH@#^EbZs)3=vj* zwK7Csa~K^WrQcd8S1V4_4*G|KzI{^6qEcA(=|(7*p9RcL zvH#{5WVmcVY}8!{9QfO2t#ViWuM{KKGl8%<_ak8SSHNo3moDDO%2O5h$Y#+KsI|&? ze>BfDv$!X*$H?PlKE0qos)z)U-*J(|1BTX=yj(npJQR-8lIjmR~dItB?C2n@$pB!cNsR5 zK5{z!)dO;|_`@(l%_Dfkl9vsQpgZZ=+>PHA7I#=nI{A%u8aDU@(3|CE;ITiS_g}K+ z+j4HWL_5PSZR!s@B$tiWPD0Y0Z_}Fd-{&w@#=qKXeV*iq;n?4!o31ITo~peGdD6RP zL)JRZF7#(0r7Tb-Kr(K*VL&y?pk6%z%B2P3q%w?8Pi}!)7^{%(h3#lLetDvy86fV= zrzs3s^%Cwm**F+$JcQCJO8#;Rt$F>2{lVg71E1WJ5ODHmq}=-@={M!K)74q;j?S0e z{7ybdS+(1Cdd|64Th+$dym>)4mx78OKXo2~2b3+wzb|Fv(u^B4^*uj>xB}!R{kTk= z5X_rHExdjM(p>%_CNwOCEIDYjlpG%f)zddv6IYKmnwEl0@*iz!Y}9hgO_DFw*LREf zYcNJ!8GQ3yZMOKS^m=7-|Bv^A*d-P=>?-pQ$7r9g2zkL`vD&gc9(x<(oi=9c9fijw ztSC)C`wxeP^F~-QweLweujxbKcM@FW3#O~3o4dOo$jJxR>uHqeN;u!Xd-W=WMhY^4 zwzy-o=FUFO&d*6xIy=%{^8Z7(cCx}^13R{V#lww>EBP?0N)vi`_;Dcc+B3|g#X1c> z?~C|Le+_+~7RfF5=J8@31G7m zM=`oCXAzQ74^b>8J$whv-7@|-LM!YgpgMGINiCOaz`eVy+37UX05SMx+!HKgZ}EzE zXNHLfss0ZK$^>_^T_bD{@@p~lt~&2|Q+)m2Plw5B#Mq zZ%U1q1Enk~em{-#KOgChb5IgWUoza8W1|)l!K8=E_lMkx{V67XAqnBMY1pPw2~;c* z0sT#HyrV1RcXU45((e1-3Q7Au$iHSspbL&YRT&I!OI+b@jM>!dSg55jX{HyC%DIoW`z`S5PqL@5|`)uqbMf)IUiAjl;~6xqZl`ucoX92I1oFr{e5CZMaKqh zaBpKe73<%LGi-4hUkb>Ih1u==f!_p&GBIB?kIcGjBxUWhDz11}vH$R3IPQ!;Np_4V zc`ldT7@(aOVv{iUUPv>fSx-+WC|&F%{x8+j`!ebzQeg_aV(Q9*QWmnl#*CcP){tLU zR~k085wAh-AomA&?#&hkEAJCb7~%`-wDA4qci?Q~M(B+93x1=WkMj2SqdrsrWyz#} zI26mgu$dFH%geihk2g(DeoMDI4Y~kYfkO7@ozI?3bX%n19Sw~{u>@Oh+q{8R-47(q zPLm-teKi5*Hb&bS@|QZ}uC=~P+;IN6Gcs6uTs%6+Z%*d~kT(Tn)X;pA% z@}8fJt{Dg0EWPo+x@z|y_@zpXK0Y3g9X^UcDB8c`LLWjS5&h1~q00VQad&-}rYd=r zR|t2ZY8eGQI2`-Fd2P~DH1|kG4~#nixZCj|wWVA>OiyIeciM;`m~@F*R!=o31(^br*KA?tX^-F7{h&T8AWNnC z)f%$21ZI#-3XqVEC>E@qENo=z-09+Mk^O6uc5IdhslPlUAxa?+l>VvL|u z8XD#0Diu)I?e&Lmz^RRfM@}4F!fpj$Ra&D=fkE#uex+uWcBtLytOCZzVeCp4EIG&7 z1;)85WaVQ6;vBQ?O``-V{cpl;3l!E?bv8E1pf z*4-Cr;l6Of{#z-GK3{%o%^0`MZ@uHF}IQSMGprgcE&ew-Cphi;0hR`(ZS zXjyl6HW@|_ESk`<()^;l5zWoOmjChlmeTlaWRAGD=+4|^vEsmq&)?eRyTO;3nAaQVVFDfhL%CP|I)%{xfOuOruQNZ}KD?m$g{&_zMl)R6hSBpM$^)r{ zGSEAdwFY|ZtniZbSfz5I0#f(|s1rqAK!&cbO5;H%=|`e!>=D^;e5-DVZE6{8JDot5 zPP^(jzI+x|l4x$vDlpzojUBG3M8tRSD!AD?_?VtUK6@#Y|5@jUA=J!g<4Ka%)D3W4 zaxQe)eR;!hjBF(Ohl1o#rhOO%xfxh6Mpr@)NI*7@9ju()M@uy-dfJ{1!r-ie8XkRq zc3lN8jY`9c1^%QfgUb5(CJkLjFJGrmh;TNp)7GIzI0W>YRqMqn~7A3Kc3Xb6IsnPY)5Q z+NbAt(vD3^bM&3eHH$+PR@*C?l0)$&x8;|jcMH9z!9w1}p@J<{Vy#?+Yo*mKZ68Zi zOQ*bV5>6jt3`;2S68F-H0({j*N-#zP*pjnPn%$yBe-#-H5t(IuVzx~pt=_g#8m`h& zHn`MeHJo>=R$RHX=3vC}?PK(EiZJZe%liLmw7ew z9}2#c6s5xQ4=FCqY2`OF9Kk+fVaFT#SqnQ3{y)z``V!0W5K=r+9@f^Z&d3OR+R@BC z!>-!0eCND--r(&w23n6U#NDhVU_N-8L>EGvKayuTGkY!&q zNl|s@s~RtY=O}bfjBOTgE_KD80$3M)gi`Y6;DQ}4CU3gC7A>GBVk`P}KYrziiiA5l zoYydmN>Sge+r}7{Av1)H@Z)Pk95g})syE^(YU5tBWfhh z1QzZdYqg&?(|FH!XUd5POA-C77~7#x-2N$@J=T1 zxAtN;sT!ToKa`X*9?@p#UaT+ErD{tHk02)KgtND3R?u@E){-k`~{iv`-7Cb(UPvIz*x+y`H8^t|47Z4le2s+UkiDJYZ(N8!{YizpWTUjBdkS^RX z#0UJokY?3#(K)^rYgLA*6;bLp9n0oVrBfrSkkE!CcX4rXQ7&geQbxYKx(y|DO6^#F zeP-tSm8%bDDGVSh_UdE7J)o)g;ygr%tV~(CQ^|QAqE!)`$Ire055+cFm94?vrn$Gw zVw7OkDxeKLzMP37gkeu*uF$f+KSWNCew;;Fpi%Ee2-Zwiv0{fzOb8>ph#I49hDB17 zQU^_q0xWcY!4xmMc>NiFIL~vEZds67CBT72Y!0)SQ-{6bTIUuwB3SmrrNrMU= zZj%Or_i%oRoB4!V`3Jz!RqHs zEHAY2{A*C-hK+mqwCDT=T&V&gOUrd8`Hjl|*z#p4p3dM+gQH+pHoJQAs-jNHhRWMs zqNpT#bPlD^Day3yabbN^(7|1;(6Huam5Qstv@7KqlWby7UD}0w{$RVo3*2KIyiR)D zlc}-k*u-7{DBT0vF==T=``f`Kp{{YhPqThlC@>mHVZ0V$OgZ@#LrBXnGHxI{oTDyP zG`*4_{-a{R0+sLUnQ{kWEL-X?G&S?5$!GeFP{X{%El@ zN0y7Qh;!aS2Iqoa+F_UUeHxlL5w%W^yJ_G9Wq18sde^>(tP0oL85 zy5&d$<6$S|elkNp9&xGCSc2yUI3DnJ55V0|mcD&w8VXge6xo>AysBYrQ}y-y-QD}6 zq>h+>g8?R7nN$HbCC49kKanFY@ng+8Or02L?-=dYeL{+G{Fp`MH4W8CPB`lt>lf-( zpa%i&rbDjpm$y7pmyzja`=EF)UMGLW3N_V6Bq|g}8BfWI>OsYcU@>G9SolRNLa z17o9N-_<(uFKeW0MQ=(sW^qa167e-5*((q@jQWR?x7oyB>ER6>W0a6Sr~&Vk^RW%L zLf4|Cg(B&Wh{Xz@Bmu(8QNLV9(us+k?J)y5V#+aFH#T`W5OXNlG$NqGV`&Upg< z3HLO}e1}G0-4fWW|LhitCa(naUZrkxiPY5At-`?lRuX=Lx}gaB zLsmh|$EMgm$mn1Hh4Ma}2XCUl&B=Bl+Sc}Ta)~t+DoK##lYeoBG zjY>Ao4es9^4Vo%O37SozE6)u5uN9dyc58^UQCOD#^YOt>1$d0|GZOgwk3iykY3ihV zT}H^K>55;Wfb+FZePC4({9b^hMm=QUC|()QL*eZgau-W&MvCGpGaJ#t^myz)Rm7D+ zauZ>OI}GvUetbi3V>#E*W9~RUI4<{M?Dw_Dl#4qlIge~An7dAmCYj_?><4f4-0}G_ zwWY<7%pVLzk+mhDn}g#ic`fglH8=x3wN?c%i)<^P-z~oART{apnwNjty}HT{ZhH*g zYvtMh9XgSdQ;_ALz=2tfE0B;#3V>t__fEYGWCJ;)HA3k88h1>GUI$QQ2E~?N*!?~+5@A<5|!P`no!y(nP zEbQ7gl5`3>Ge9vTHnV!|^HC~9FV5Ry(X!to8(Y`;pG94H%X{6;zot{BzbgmhvdlX~ zI<&01@H(q`n~yrAtHg}%FiKBbsF3a?Y7RpA`Odlfb6xt=Gkt!_>ei6&9`~#k zX^hp@6K4!nI7vzrzprD2u-}tN6eamOC_{>uKF$vtRL>)^A5eUYhj4-7i-9baE+1fE z0LV&Mz)8&dx5^z+LJGT(>HT)~r-gj}eMqiL?bjsptZqhQN@}}mOT~M9grvZX;u@in zB-3zBZLIQvPWmx@fh0eS)R+`MicJOTeS>|>Zew4~g+oWjq^PNk%SL(7sC-=ihi;9& zIp@U3N&rN+&pJF!zhp_db*-00BPoIB#amiy+hl^>M;Q-@D+j+vQlycX^Z$(=iStnM z`I;BK%$P%*PJy5@kSj`E|aXm;pN7{3qg_jw0(b8EmBxvA~odK89odU>E? z<$q7s%0RGg`Y~uuvD#Tu6h2!W(n@kx$KVA0tHQcACy5KGK?lF@*s<0%t>5QUeN z{~O`|d7C}5CUfQPa~r1}A*@&E|ME#+C=Gw@@M?bsIKP>_aplB9CG+`T_M zfQFexK`k6JcqQ%0AVrj#D!l9iKBoqoa#=tZ$UaUz#IDxK07O?74zqa!6J353i`5;Ns zkO{}Z`qYu?e8fWPX|KuM-HzPRk=ndt*!Q<;b5Qs=B&R*V?}mn+jH^JdopCOxU~xyFVA z9^{5Lh4Sf>;5*T+0=|>Nkb&0Zzw(V4S8|-TT~rS?_G(E<0=v=ix6I58OgA2;I6tc{ zRCQSQZzz8R#!?|KpdwM8O?(a;y?ph^s6}C@aMF5Ug=VcG#kC6|lhzF%WWiW8Z!rb` zu{iZf66-I0z8Udamig4BQq;oY2S0ZGiF=a+>o=AB1uJegziiIzh&B?` z{h3qveWx{8Q3daH$@pJ`cu;>#=2Gf3t>J zwsT>#q~cLEZ4Adh8!-KDIPi$)OxyutdGl>lGQ^*`F)LPh{Cw|^Z|lWB6iXn}n@We@ zOA59NYzi@_a7vaMf*2DH#sYNs&0+K3E;}8QJl6iCsqrHZLhk}l^(arcJwH4|%<{qQ zEb+MYD(rXeshQ^Rl_VxlB&^(jv8m_uG1nxAt3|tGwm>|s{5eS2Ojz3U%yDtgIuP4& zWXJO&q%wZjU4P<3&T-l#X9x^G@LnOrptddyMrm-+?QNZ%rvi%5zEC{=wVx76O`b`7 zM=tsi`@_IuJ^xTuH&NOjWBaPbLdojE&%f-NGH*jBkb_v5_?uVa2l~Yna+=zkd-V4o z%AKYGl|pSIQ4!_U;Psl;d@@xYa^jkf+fD(;e^p?0y5(J$rP9`Hf2&dsg(&-Zs>>Sl zi|0%_ccxSHOO0DmFy|s{;?II-$=7wK^&WgdA{~}1VP;s_y>3jrTj}g)8^qJe!5K@k zR6j9EyLE{o)`AJv>NpOZOB)5DhK|Pj_2}q^4u%#S2gLngzutG7fYrDHLpsdRs44 zZ3m8$EKX(?q_qV}rgd5~0z2ndVfMkP#rOHt6qcq?pe@^QR9^71Ah+XwNQ?liVn;uP z*koOot=<3=+=<+CL-se3EH#D_bLWap{4YyTGk~A|<*yGnU*`9`deuFjO$Sfgje)=`^V|HS6u@z>eQ*WsnF~3x zy+VIFFEM-EX+x^pz%k)4i2orm9Vds8L;~o#&pdv8bnTY;=1W?T`|^V)lU6$f00`jy ztK6rq!#^lL#~^zHd9*eJq-LkK+&2BRmOfU4->hF*QD&z$S5#foEX z!L6;N?it3Qln1}!$wFvVYX;Fh5VW5_#dm)YaU!d|k^d{q;WR2L1pwrzyKK#2XAIZu zXRJw5vwzr>-q%cTYDo9xNY8?Ci4X4wFTfy?l2oCo?IlMU<>NFf*Bsey0KgU0R#BVv zt$4I~xAUNi%&U;BFl+A_#VW#CWw*M48bDd{ui(WN-*{97Hw>3pys={{K_ME&NaZEq z!S}GVpjmkrBeDQti;L%BsTg{|sa$1cCUY*yl=&j{*6v=!xV;@FnRCqK!?bfxXpLyj841U};$t1xVqn=gPpETH4SEv;qm6nDt;5hN= zK=;=I5^mLh6iGrALZrtJkUFU}C+qf{Ge8hmT3a~QU54*%x-{DAFk`?g?y>z3gMJeK+Su$@X*Vv5Vo4B$Ka$lY+0TR@;Yj-aG;x zqIzLm!CMglHkljED?|!{#iLYwY~}vzs;lXhSq2&kstw=|Dxw<13HyjRgxcBn`IJYd z9l5w&_iiR;H{W2-@)Y9E5@wfLSHW4%W-BYJApTDBs~=4bcCBghvo$L&5{}Rd_d<|@ z=(B33K<$~_Y8&!$i>gpl(~ss$UrCl|!&dkd<7ac#!2z_GF^YHzZ3&!~IU{AjsD#yo zjbHL)ZRH|>(;+FF^)ga9y7zEATvBMlehwIp1g4=Lg7*UcV4EBdKAaoA-J#tk2D=zD z%o=%Gk6pFq@s*hg$`I9$EHQ));IeWp37i|=)(mo0yV|v-^+1Oq{{SPk!=?c3=~DObIBN^b_8H}Waj9&;f3{}) zn98RvNZIj_@kfE~7_CAA`y=J`yO(z&f~cg$9iCz;9^GvD zJbUMW(BWo^z|gtixNm2I&+~?-8)sb4B?q^xBSRpp66Co+W~S@_lox2Im@ocIO#hdc zB2BiDnJE!5$tzwy8Afz|Sr{o0L(2m4zqAzfzqIsuv|9&_*x@E*H%!M&*%t z_ihG`=RoFd&h0!Mk}`8VFi7snEcN;05K^(YM|O8^$o)p?0G(hMyh=)UVWE=Eo-MPf zV>(w<_pATi;8>I}{_bp`NjZ|sa`X}IQG#Ln>u$ssFz?u56e1EPJckbAjw*i9FuNxZ zyy+*vlJ&mprb-qrfaKIKTh*y=QLFr+f=s$HIbd&Lk~^seuV!9kn*^^GlpgcEpzfpo z@Fsq(>KBbBLu(npRyW1@nZ!*^PR~yWrF+d5G_>eS z)T1Ie#uYs}gG0+`d?r=RUHb)RNK00wU*BjP4|~P^B4z^^pAvTwZ5Prwhd>T&nnSd4 z7ojq#;T?tXExMj`5my{ku<#%+NJ@2E0j+JRoBQ*QXbl6YEFfAbB7%q3UgWJ}d-+}E zPq*-}`-}-uBYHFIMSqERaB}YKycS7W3+M@uvm!D~_eg7a85wBT(# zHBf$S3cISPKi}?@70(i}fFuw7uIxUx;uu|)WEG_Yec;xT5=P-RbeQ1!ZSjE=yzClF z2KHLxi|fypEHf{oCpv_w1MJi7kI>hO0m6gW9*fCDk?tLTFk?$_3K;1FxpssHM@bk6C)*^B5v^>{;ll zUpVFO=t_a?o3}HG=;xe*S(}358(rS*i3J7~@nhNKh_Sk(0^Ny^%E$OP*>nkAuNny; z>4sn!9#`#)z{X2SB9f=No{gp~hp!!QMCY+cGNH5*FA((`yM^K#qf%yEXc_d?S5o_E z3hY#J8pawOoesHzIq;>$820+_T2o<#cT%oM><@;06Z0PCpi^F@h5jn0w%cD1<42!o zhgiY+T)=`LUCergd-Y)>7spWZHlXP`aott0c>oeGBcmrex2DU`I=C{GIXTt$eUp0! ze0&c-&rik^KeqB%!z2 zydJ{VhI6VC=OMPzGC*leTsj+L*D$$?PPX;dzD-Q`bY zCz9Y=36=*-!qaHX=$til9$e)1RX>J)@`^J((VrsaK010&qh0cAaATRD|JD6sM9Ap+ z0v#IzS^8uAzg>LD=*oyj^ooxd$jdJys|7g12YRMol{Zmn+7y%Y<0Cm6ltcYm9< z5qSPw7wxOPrDj^}5}ZS08%4!ouH);a!bIOc;#6YLR-hnS@7NV(8X`6giQCC{OYua_ zU~csVM|$cj8$~Nyd4`RPwEFkP2YyC8iKf2x=cc3w+H?t?HtJ?}J^9Vw zajDo>jX&MPj>9yOM{Kf4UE4l3>6YD#Ji-y7Vd#az?0UNQ7NjL5*vzMaQFlwe{2xkJ zxi4_)kyaz!C~c;-SY`1@OoLav7J=Zt5!6MX9q3Qgj&Epf<J#!@j{ zr^gzU)Fo5VD)(Np z%sZQqPLy9y=LJqggM9tALED^$>U^5vMd&)|AaHxhW>R~C%^B`T_dW9^DMwSJ%)UXK z-BmHoe=`C3!d6I?7swFp|cZmq3TDEZ~z#)U*hF3_xl zo-*DgX>##9sgw6r=O}^Ya*3&ocwF>i&|C}x^jD#z8(2(Gm;?F}-T>onfVdQDCD(yM zJc`u?``X8$-@)`&tjZ0AC;Q6tOzEtVTDipth=!Ss@%&s-K8BdQi~} z$*Nf2V|p~16L0(k*h+X}R&A0R;{ghF0%_lU{VPNx)^t$2*i-LMUC4PWf$xe4MKK=7 z$BnI{lvLsQQMp5I{>#prOI%i)6lpm-Y{fBaki-9D0X)m0F&CRFKkJ@dI)h2^?v<@D znP(|`mY&D*fv=PJ)e7P;B8%>|c|C}tJZH;#u$)hNE>}SHi@NWyjLF^tN5s^3NnX7^ zTa`t}Q{K7L?|wG@hL0DnXxP55_r0{a=bqU;jDj{Q1;`A)b*AJ<&gXr~W+!#`#ypNr z*F$)dsWOk&=3!^r>MO=^KZ&R&%pxjW%coNj+apkV#TU4Ix?pK+%-=>D(+v5ujq6Vz zvp+LB9LyRX*7mbmBPAhP*aYhlRUhbS!p}zp={X6>oN?|A`yGWvrbpUw)Hqg=?UO~|FfB1A z&NhSl&bzw$bVtvzC0o4r=i7m7PB_W>=}jS47uuwaXMLI*x5qmG`~pqa&4>lr3wJj~ zyIwJZcwXS*>_hnfn2UG#z4ENvhXwDPV~HCkv`49Fhmz+6^@VCSk4>MpBjZ?Wh`4m~ z1G&>v1L0G4FiF^FgFeDvMw@_tC>RF)YhlsGcpew+E{ae3zyG1YLkz+!%*-Bn{&4DE z3Y)FBy1WV119(h;q863N`sb(i7FAq%oEe+Yv+sttUs2ES-CLSIwiqS(3!wag?Q)vV z1?j05^nKo>=~u6b8`uAo|BJ@)j}h$?kvY2JYuJuU%gXYVY%y@^^J=A`k?3C*!=rm) zs{ArL+hsJG&mGBPHq#9!t3AO@6h;n&Zz~jCKkTiSMQz7K-^DQ7i~NeHa%(?FbljO; zKYV9!Aa!&RESVfS;xhG%Y!y~)785qLvXO6i%qfaS zqWip9C?u#MSvOx}EsScvh+>heH|+Cy>HQxX8mYMg^4LX8#2`#D{!){ZE;rYDgZx6s z9rvx{{8eh>m5iM>g)4HuQR1UB;hpE3Yfy^Zp-zhoabuLwDh7jrjotk1sP&jBcC$ zHXiPT(iPS_{$=lJ{D1@bXLeQ7Zl)QqRxWPVDr`SX>xf>|96 z%biHutnmDk?EJK>%<4}GblY`O?>8!9yjwN~C0)}PVXmVSb!sA4*!X$?8J)YCYuEXzGQR z?61(MkNp;5F3i-jk+X8en%X7Hg6g*&my0{=A+Gn!y0s4Fd5R5+r?|72>%I#Pe$7~8 z@#m$>Vlc0=3OLjo;(9+!si{Yhy3DmUSsBAcBaE4Nlh2IGKJ0Q}_bqrgo3%+?k>l#; z*R#_f)+zp`TPlqG3M)gmrw+bX`D9r2;%m1-Se~RWqo0-dpO-#YaI5%JZR78)k=HWo zCvuX?)r;2_g)hJUvDadENnCwsBz;=6$MxIcivR97 zqkW$2?H?R+_5x+Nyizdu^v4ZDf<*E{W>imh!>C%%Lq{;s#~rCSMRzGahYs%a6e_Nv z8M8zL64AE{-%*v*>teBEaPhV#Z71%#`AA-cAK$y9x!L^;NlkhIA4LlyloIE}@AzwK zyKMo}jjkn1TCm7c`V}H(eZ%e!a={%yYeN5cX@OLU1sgH#Bzt5Vo7$a8OG&r z2W=h^HAyHx{y`kth|EXd^)c0>6Hu8hTkvhr7f6lx+^=D2yy1LA!)i!yDS981cskt6 zwmR?XR<)DDn?n8YmSPNTiS|0*n{98ppL@+n`qSs{DevvGo%Xm4QO>s!eqZq4R-9+X zbXQ^FZa`JO|M^C{(A}<`V(;xhE6Y|f?`)#*yDsR2=0u0k)1CL>?AZH)yJL4&yq@~t zRrDtLr}~U)*F~br>MunLCnPLdKfls_&b}>;4`)lRY>P!x{6Krh?mRV?0>0}TXh<(B${6&2%$5mSf@9kBynHoD^M~e&UD>OQiJ*#3GfmIFEzesmu zdSmjJ2OF3zG88K%!LsT%5--66kAj1b0omnXGCHYoBYjmNUG6y>F06albWKM^3YzAM zLOA_T!#?f#M=n1Kc3zj3Zt#(I?1yi%Edu%fP)^8Q@4C24b|N3hVdYGvLodl?_FrtX z+KF!c^62Y9^ayo+glGKLu?4>^ zvyf3glsq-BRP&^~BK-3NF#g+88Dh)){I`1&VM{SAxWU*jyz=Es&R-@TEy>*n)+Q=}>w4j6hk6Tb3dlPf8OM)5yd7paA_**}u%{1BF0#La$^j*VR-lM-H< zAQ3}ju6h!e8b3Y?dWBqZoX=SPsB;rpws-OG2=$I7ame=*EHD_y0545{3eICGzW(}K ziM#52b_(2d>LOBuN3-nB8nhiAB?zW%*7kr*Vnxlors=s&wmm!%#a>l^E_C%gDk2IG zcrG4BT5JHA;#hRllgsQeopgu&og9+(`-NS(xg<9uTjZJoy7)f-Dop??;+%7*MRv!p zMy@-vkg{)X>4;(_MjjYZ|1I5#eD2tD$q^k0xgd$^Q~;yuu64Xg8T#;-=UbYjml3%A zuC#PN(W%^V6UEywyEy&*yTsTSk6UcbST8%^cG)J~!0%ZN_!TXeWbO?;+tA$1cLMcQ z)da~-_Ol9Q2N68Ys=ax09%h(`lP#|ih3#q-D_?k?nzxZ(ycmA+`Xu@MTO0H6w(lv}WphpkSk2R%y@a+}w%=Dj=ra|FO z9KI?qO4^(~4$j1-H{mqQ^6LL3S1!gju(NqQ#7#-NWtwkPMn+@kHQZd5U5{ckwG%w_ z{Q;b3JbT&@_I{_~A4)faQwk33oe57t!I}R*6io;3j&BK0ij2{F-`yc8f~PXSn(@Cm zO6R=zswtn_f$^E0dNEH=LZiS_dXLhlie}B)Bd89y-2iLo1>Hx?t_u$_Qg4dnq|zU! zl39PgIU%{9rpAj_0bO2%bf}o0CbNP=5NR0BKNK5P5iUESF9!~K=Qk?`;uX!+V&Ja# zvNvD1$ZR)Q4Hy2ty8TPbJX`#|5W~I0x%9l=YW@yy?}f(*x=BFZwqu!fvmu*lLIV@{ zv+jO5{z~nkH@F8TV<|{n?^vUf5Zuor%GALH`oqQd_r{iU6Br^>o(j3A5zQYn9zXr?utt7`pgFS}tHP z;>eod$#{kfkk?y?A|f_(1)1AAx@yw0c|ZOlGm=>Vx5~CkR@ac8I!@uT!@0pHAkL^= zr9S%Art?Zq*bvCWkD1ZBVYcMgqE*q{TWYU&W6(68ZBJfQKvV+`a95 z$kg?1+}?_bcy%*t>AmP`GEVu+wU}Q?MnL3h!&V;CuV4Vv-`*L;^205&)prsqngQ2C z!ZWI_cH6PFe1dAl#V-C<+2Fl-%6TI(n?7AHQ>X2@k5R*(w-JO*~_p*_8r)rEdvt)(%1opc+d;mAL6X zuE-s5WJH{OFm}$_Hcs?#Z5r$#-`2HXE76m@kkjx}GI~qHYyjEFM&Zn9U*>WYk_&V& z>JLOh)@y;+zW-3hvH$cg1g0e8x|PoXRcavO{6^;WJ=aQWI> zl@Qxl*oxEN*lX!CLxH-dSLsR)NY>RQ%=Zi2yRzt~doHvkB!dm_!b*^pT_+n^Cq6dw zePq9<`0Is)$=AtPp_w0G>|w~arFoTzMn`-BWOiG9D6cB0=2 zb|L%sOU})ZA^RVS>}#RxpAVTs&+Q8&Kb>{+u0Si|#1hgc(+h|LdWDy-7#FD_`Lq@h z#LAH8ol9vAw8sLk>u6rqy57BnFO2ITqLLT#@U~z3?QBOl8p&y$_T4<^GBa<_9+T_e zMKPDFbl|;OKY()SC^^NnH!6pTS=}sb{Y%+DluM5% zq+2E7s&WkJJr>1nvSH0QNg8L>Eh&ZOY|qkiPTUCbwH#u9e0lYR?Kt^^@L!6w*Hwmi z4r_VKx1$#^yShXaixB>dQyUVunc7?)h+>Q~Q-(5AW&0t}{HyMk`PdRIVsi;b8h`TDOn2|f0oOrC$ zFEBlF#WT=0ppub>;GlO;_BKC0zVu!z^`9i8 zD}UyS+ZB^dF?k=Zdn@s9Y3G1QF9T@zD^8YJ3ah`qH>46UrOJc8ToLJu@=xrrlX70ch-_HhY%Lo>p(GxYhWuWSgV@DB(- zxz-lO9|CKujx?}_G3T{dN!1QADJ|1Y=_W#FrST;QxOvWg?YCAA2C(qvgf9lp&SZ7^jU^RI9&##^FcmXpC}1m${*k6P)UTgRc>tUmRR?1bMvNXV=e$bWNV+9C zWOf=EQu@s%O8d!LXfBS&8c1WzOqoKRp6){dML+CIfmEJ45$WW}!kkH1Z&4F87%d>a z{8n)JnjbMn-_TNXbBF(&Rpq2-{f%|JwgIsfTCe9+Jq>pTg?3mzP;0Ug2FY1{X(4$X z_SH>mInwo`TsMy#>8RkkBaH8C=74YEF^5ajjS&-*U2!;y<=1jljylOihO)#cQwH;1 zOzt`#o6ERW+9ovaI5}>fGKMHh)LOo@Y!OtK;a>qCM;HD*kPZ;k$;$(8mry1{iAX35 zB0qIeQ{zzKV_y$t+E;(`u2hXGjs`Nq+Q@!iVeo%d%TV5qdU_Ef(r;~92r;4}2ryzX z6lQg#Y}?Lo=TyVbCt>~CPg3rJlL`NN)`~3)W?3gHOc|=o{RU!TotZ{(hU<`s5oN{y zaK?!%iCZ4)T!TLrX98UZFor^gvdC)EfsMV(k85C~m+GuFVI%)g5arsV8Gj>Tf2NhT z8RjL%}d(D883%z*1Q^w|z9+c2rYR8X*&mYd5HOgdWqHod9!4+O- z9c--@h;1K}DiJ4xZbZy4&WC@HGqY`qWke#ls@u#>G#JT3nYHYS9knaWXo)q8b2S|S zy>?YdN0rq{H%SS%Q|3&WNK~goPRDdW1z5rRfe!;IoqlkFFQ_$azb}Zf%@^BAa1MCx z6~eRa&pJGH(u}3E{x&7<9_|GQj#I`QXvB$Emf9}t6n&DaV=Adja_rzwDq{+TCaOjM zz%Je355aO$Yn*c{r(A!F@Wy6#I~mw1z2~!XT5w7~e7&otoRY3G)J{hH<$xejTa_{5 zBBtO{0Mjur+-xEghZ?t#yC}&z7ZnCHw*>kZGmtDdvqA!?Cp^?MV#MSu1Nk*6?5&jc zca~#gh>6{ySDG22$Xf&+V}m=r?ui{-R$hab_kk=<6*%mfW%!MvIP;joEJ_)>{G#(r zIi`c(NI=3CWHJL%3hOvaFOzL!!lMSQR4~6`9V8GJI2b9T1AtX>jLUHYWCLh~Xlv?P zm9ne0Y;oC4-A)ho%GOZ@Qt2d5kp>aR1P4v`lv|jT`mfB8&M(|FM@499#iBT_CU7SB z5NhT0UFuK1i+Ae02EYYuV+5^6J$-0wEB^9TwJ$EG1s}bvuM&=#OtdPGrHMTMu(+21 zt+JiEG>~s1&)XcSW;c)(kCcS~4VrP9ccThDWGdj0nD|-V*VeIC-T`zV`QA6_Y5ksz z;c$^}yULUUbg#1PHH1w-zazp*@ty6I!s4UE8^6W8`t+P)jFX&vFI5^0gEQ%JUd5#t z2g~D|h0_mbF=p(jk$yecROsSub}LgMDkx0QdS8Rd0=|-4#f@tqitZza>@)TuO`J+T z$dfTz6+Wg=>&8HWi*_-Kie(M0ev`z%hFNF$bWt&5YwN>afT1{5P*=NWywAySJ1L$JcBw^{`n+U-#An5|U zd8?3OQxeh1WO2d&m{h(g-`!D`(aI~7JVtIEA!@Ib%XE>9cU+c?i(!gY2EG~mI-mn; zPa!1^-yE}7d{0VaX&1vR0Zee$l7Qi$S1D=qvv6ala^QOjQA^~6nR7RWPDWhdZ@xLu zkwEirWBO#%7B51OE*;r2axH;l!i@?4?q9$f1ynfA@V9!NW>}^iuYUja(g6^~0N;ha zdQ5}w_Zz<7TbRSsVdh62yAJ2LK(@$J4~%@-HQ^AZdZBOmQT8RPoGzupRMgMq2nDDy zr+S*e$cX!T+4f9JVW!Z~(2-k&(T)hZ`*&p!Is4Ogc4_O)%;l0uGxBH!i!GP0O96l)v0d$r%oTK=iW>cW(`SkYIV{J z84N;GoK;qK<-?mtKd6A=qg~=GD`xM$YubvQHnZBu1u?}!1P2lhpYUJWLwy@lR0gZL zI1zd3`I$gb2$i`8PII_6`gg2U5ZgZ3S(`yndRm-1*f<>7%nD+_ihzuK;=(p!{yZzK zMGA81mm-hZms32I|Ap-cxYBUR@RoWN!9W@-_z*#0#tP@pyP~sx4OrT{f{AG51)Ta8 zDE84U%wX+K$q;a9Gvv#0>VQ zb($|PezRL|f3OaFdl?wssRqNlV_9cZ+A*XOKx-cuTT@F{PiESPE03CRE{~s8@@2<^ zD|^s>vtEjD`S}a2u7*!c;wjEGQ`ly54QUWXmM)f_VR5BtNx}i~7V(|Li^@&HHxtgr90J5Xt^1nt zsYDhvJ8`+Ngdn0T(|5(}1ed9$!z#&;0YaKHjd8&QjX#lA9$J_u&D$Zg{qQ6F^=tVk zD-#?QOPTanCrml$Oi=9i5v^14Ygn!r_lz=LyoaBR%)R-*0LFMZzORcW_D~OQR(MPj zlE+OXM76@dC?P|VB0IS^Ta-zGlrB5{5cRe=d+Suk1Wfmw=@xiz-t1?5+t7aYpJA9+ z;@dgu*ev3Phm_f}%mQQcB&IcNGH{Z&zydg193PJ*0+`aTo~Ink&B~N9$}*~)S;;Er zziZvkV3|h}jh;xZjx)Q@{hWlCoJV=pQN{UpWD9fXj_1cFUTIS-i6R8fQa$oP*8qNz zxoeFU#PJdf)98`Jy{~e>?(Ge5bSmB<3|2vHqk2EI|toYyXGB z`keTfH2DSivi&>`{yXsw^ep#CeAyFL7L{#pC0+B}|4bT|d3(fS69!TXLLdCtP7?OM z+G(3BTZ%LQE-hzh2_xuRqPnAYRgH;PdLYbvz(8kq5mK?Hh!S&!F0VjEW_NtWw$&vv z6PdqeE!pD1#b`2w)ud;$D6y5I1n+6i)tI-)`P@CkC`&L~XLs4+Njz*x#%f6ghDks; zBj0E}yEF46!o04PLBVVs2JilWWMIH?s%9NLRIjD`IFAJMv$#~Wow+uf0=0O@Ad)o| z=GN2*rdn@ctf?x$U|Yi5gD4jq9BB*9ALO!fM=YK$uSVI8GMc8a<$0AquB~10Kmdnv zJ5j~Bz~x=}RL)wugdL?kkA5z-cp%Y0RMx93=6DIBf#}5rAiaE@gs}AzE$%WRh*yF| zM$Xb!&f0^;GR~6n{l-g{E%cuW)V!1zU>lq_H0b8KwaH^WKtDN%z&zP3`WaCnU|Wfs z`&F1!<+y+VI$vQYydg(mTd-_G)%t|;BYHye1`jZ=Kv_cNs5_Edp}%irJko^N+EGej z&(P{45-}*obdTv!K=tL&y?gtKbyHPhr0gP=d@#dSen1yqsnLV;6yL#OU%I?O-^mg) zN)z5muIvSd|4wrDL|5v9ey|->r(r$VAowcrX02^GozdEA5XLD18CB9yuO<2xwj&!6 zo3?`cwVFhJ>^`w9Em~H0R?c>wbo^7sqBC><%UBBz^bDbiZ37~}wMu$#R+_faeHjtm zz>#KV&PoUo=Mv`oLW)ce?!?_A<^cL3A`=QsxX%B>(YePn`M-a>5F5r04s*8I<}{}{ z=4=}_XHroVHgXP0M29hB7&hl)hKf=-C6(lSPIIV;GEu2ilB80fpYQLV`>*@HACLDR z_x--E*ZXxnU#*((&QNyl0Iuosd?x+2YDlL=fu^ckws`d5+SCC!jQCAasaxSsF^qCw z4zEyqHD(@Ji+7cL$pNWl0g>nL*T5& zOuDk>Upu7k^-SZ)t61Xoxy`{+Kg$A6I7k$@3nJb}ox-@)^usa;IJ7pJPx^%!SnR-# z_yrRDSwH%fu~%Ah1J#24Ozxm~6dCsfd%Z%P@5mDoaypSqhqSiT=&a}d%>K?d`aeXf zY6+2Ut`Y&H6gd&L*vD!p6WT*Q#+vuq^@27?m>61H4s{APdoM-?5yY?mlo6tPV2Vb$ z-#_}wAPT8@6}ZDj-8rBZP)V<;9~#M@4N#{bRL<;0i&EYAwK@eDkv{4s3>6u{ZRr-~ zr^R7&PS&jk3Ti2zj6FawwO%=5`#VRy6-`)B+Z1;3V53n^#zI$DJ1$5c)G<6s++aB8 z_IV7Z?eCO71U=OfFe&UZl(JFd*&4&z_{KemfiuCcKmb?EyqIKIw`wjWv!Je$w{J~9J99(VL0!cqt{~Lo1S#^2gAVgg z|JVRzuH?5=ZF#g%MXbv}QJ+1BHczFa&E-QIZVT~q53mvT>tO(`H=VxV0ix^)rNPXc3b8Ub;afd z`18;Zbw8)$@~TTpLaT%pbHv&UwwGc*A+DOy8m;OHCVFSm=N33F`O!q%7f=JNtFmCN zO$-GduA4#r02IaCw95Q;I5J`}?xC`1BmA;uV?i%;WtG514-F3eD+Hc*$Um{xF>m5^ zq~N})tL*9#+=+~H_GuH*3zT*FSOKR1Gzul7`V5R&9hEXj1pCG!jrb1u-`G>53=R0u z&Sd_MpIobk(@4;pL<>K;7QL$|bpJ@vQz)yqh3Z(MKG1o1DAXx3dfofAeJX&fcu1aW zD5!rB>IX6A4%F4$H9#g}O6*Z!We7u)BG@l$IKgr7q>nrw+&Ae>?K5q;WtH1aLN|fG z_nsBBxx6}eD?uv>LmZ=wJ{98T^T``@EZi^h8ZMFJiM+cdUUSc|Z{oLvK?e7t9l5^U zU!l*x^^)3YM;fbf>^wLg&Mu~*A##A!ukv!H+wXGUuDR@_p` z3!M!aa;J=t6OG)5t`9ykE;qKVP*qf|8nIiSVtt{j91cG+ny}-8S#!p@+P2zn`w)7A z2>yVf2Qm&+cY7DZ8%TW_hckrCTpiLF4r5qg+m4Po+7~1mb4*$;W}Fo_WxY(?4_yjw%I@FYP~n4dfG??^|TLYyP{8NX97=Hn;>dOsRA9z2!dsVJ?r8d_UasGA%~s}_DdW#dF;a?~Se zQu6#=5rRss@RKB*R!ORP1i+aS=9X?>CYlA_(hGKH%g_V$(m{99f=9pRY&7Pa_Oq0< zNIaeh?`PCr?`uc}<&8;<`R1oNt33#8^(bT-K)jWHDV#$69n{U8h{rTltMMbHHW5Y} zcQjgJE~j4I*a-0DhcKa>{ipyBUk)G_wt+E61<9Kn5AQ5c3wqOOx}=7!6~94&rXNE8b13#U6)az z$u-~M(_d0|+kCXyvC|`i{gH<^g%rq*mk94q;w_bl!yK@dN6n>Gtq_lc=Y!A#*^Vv2 zIl&Y|-k0atBSFU=<-FcFJ*rpuL?T>Hd)<=_r5>rzdK>f0-2U?LV_s>Fm8pG@L%p@f zL&RWN$v|u08RaJqzOQod$~RF<>yeXY8cYSfnT!>6b_(k!M1#bolGtn+9R&?E%o5}% z#IVmiq#j6i%}z(g(qbXNAia<41=RjfZ`Dqz4fPZ?cEH%&TD0fN{tX|jmt{_sm`t9c zLxzzSabv1I!{lOc=DYOWO!O*KULnr?B*#_!G?5zP8cOTg9P-fQSjh2yD>Xs4wLE{~ z`=Sax4BfEn5ubuo{md&O=shLocm*)<<&kJ$O-b9j)!aS&N1-M5GsAH|$){pSg^aYe zxWJ0cEvg&T$yYQ<)!QReD95)+-lZBxt zIIGH;K1`a{FAuV{JL+*Swv0V-$Xr?`31l=-z*eVg!)RV(k!0YacnVp3pdWcS*AmzQ zY>`B*ouqjh4(M8Lgtq`obLku2GGW)|cFa>Rla=%jQ9)wt4Hh#qaT!=hy_6(M0G=55 zRNd*61$CE)GfS1}jVd8Tswvf)&Z)JM6n|I=VA@mauQ{;i?$Vl0sdW}r+y+#@8Z+-r zZ=MpZ%yO~|E>mk$`|UB63%N@sYk7QwtzOog*6YCe1kil(hDF*7`lUP$l9~Mjk2#;$5 z{erdi-29?`3;36z{V7H6rBC~5^xT?)Yn-t}9vi6)NCZ*;{<63r zk*Nck(#)*yv}e26;a$RvjQvapI3^hoZHJsY;_YDb= z{@cf;zg1481cl^?rn_WG@*Y?Mj~QZyW_qQO!o~5<+(`Vk(I=+HHZGEwJ4|aE1tagH zHI^N2I0LVzeJ%A2*;4&#cXebj^CbSa@-O<8G75>>KqA;p8}yHAw9Y-ARqVGv$<6H6 z0VLB6?Msyd+_F=%MM|3F2Ub;>5ENH;LP-4Qm$J z0{d&f^N-xg1iuzyl}-U+G3KGP?85jmF>=RoeO!i9flhHA&~y(haGt-RxvZeg9X~Tn z%m2k5cok9P&Hi$$Vx&XTakEj8*Xz0elZ z&R1{*vv)pJk$RH7U+TO<=m^j24A-)-U*=gZ+X1#tCOexGP}_F3V9MhmEHTm*hc1V9hoz&eRC4s^ z>N6E3=U%a7VvwHpB1ngc)##zs_#G2h_7M|Ayl(m-$^e-naE1ul!8)}XxrmR9%=E++ zwTS~*Vzl;R&l0Orf6fMaj`x?1f9}dprKTtiY#vP|;}%C?VQrD-Wrnq|pcG1f7hub> z+;9kHcJh6QTCc!X(RX|nr}by`je6+U482}I3`25-0A!9G7gW=;_%?qvS}QYj8`iUT0^5MOll@y^iX(yy zAs)<;7jaWP@_YH1CKqCoOr*X`HU*_a{xbJ&eNG*=6qdnM6y#sCNb z3IxI)2fk&B9WX?2R0j}kW^&iafBw0c8GcqMVU>(=vgodWFhhCmHALLddFY?akYXG; zG$iYqBNcJ8SEu0+PP_HEeKm`$I8dIkQ}rdT0x^1zmwA~q znxJWNK)%xpX;(i2NmXNR*7wUTHiVXCX;LOb;J0?O@k$WJY7(?#b!-&f-%gzrx`%>X zB-YnT)s2MSU?0xBCv~4+Xh}}h}KW4Vio*14ljj_ggT6X=hH1gPFnoPF~HCtV}l>OO^TZG6LFX8LuT$nLeDZx z{;lSYW*8HUZoA_U^5|@LEk;x5Z6j99El!q6=w5zrkMV8G20E2jMFLe7c!B2{oGZm-k-^NKFR`1Hsx<_9D;~hRA&^3{VC-dV7}y!1-oK3uA)!-8>HJQk$SdAn2awW55ppcuH z;R~_!PmGHbOkWObgL6|zF9>!1nx_3ooALptf8-`wdr|^nt&~CB@NQW|dCI~~5KJs% zU>W1oJ;!73(^fDY>Lg}whVR_aJiTdEm|ZmXa!(m++rg}3v>B)ib{5-a8dxx96ww9R z1(~%E`{_Q3y(=&gL(`ITFe59jo}&d!=ERI@=6@S~wGo}?R)WsX<*nfsUbe~?t$w^K z7}?`>>VZr>s!B=JB`D%crWclUIT`vB1k3U|i@v)?3XN+VW{*haH?eNTh5oV3+a zPWRRU%(bBdtxefYV%+x0`vD0smnw;9eP_7OaIA~*ycRWD5ytB#J{1w#?5jOcYnjiX zUDeGI>7}fFO^aEJ9_nn`;Ly;|fJmdKHcm$^AG|Fd%e0E&;|$f}5JPiwUnzduCuZzx zUKw`H+tAbu_}Ku& z64on&PP%m^Fj+(GYtJhPzD#vmCd&7*8tLJ6%XW(uu~q7V7kHE;oT40P82){{Wv04jhEqF6O|W=PjvBan$Gr->phV@BQ7D zAusP|u6w4Kq#y3<74X+4lUX6dmmi>friZRvqDantAZxGV>v}MbOd$KWmiD>y@NT?>SuxdX|8wH2x^m^4Qs;E=WaV$kI+DB%)9nc7#-vB^29KEeFQ>w^ohg!=N6i3)} zz>k!3w9cuB5k}tSo;LQovD$c+&mxObnBBbiTy$7dp=6 zB;gNYwKy|Qs~c{o7N6flq4WxfD!BfE9dzui+8R@FpMnf*`P^q;o7+e-fHoA!0&RQT zR#s16?$jE{^gg||q_7MklI0`#_oN8$BhPLS{Ugz1afkn1@6h>| zOEZJcVb`ZO@N(m6y`sg|;*EINqG)^rBdq;uWCbfGzYC61pEv9WSNkC&@$ZqpTAFux z&GWRAf?*y<5T<%Sxu<-0bQ?ZqH&2u2G>AtT-lIWX+~gYQP8vj+N#8?zL@*il>TY(9 z9QS=*b3c9-j2U3f?1>dp<~ZdpC+%h!t2Xx>0NeRo@_YIP^8}JWiIAe;OY;3j;lKSxXkIN5c1-;;6gb?{ZGxBrt>nJV zy8ZQE%GJ4k)YV*mdPVtZu@{?K%K>LP${o7B=n>~C23V~j z*ZJWCQj>#^%G|WXk@o&jtkr=`E?>8>rxiIM(TGe+ITG;2Mp)pQ#`%fPDa($TIb3K) zP`M_5WVO^;?QdCL%`Ij>tIFByc!2L#ogj}}d(Kc`1L0+NCk^yVj<}*mE1_zpLQ;r0282sjj4Q6ZNRm#iyVPZ={o!fxIE7 zYdJB6(h>TEcf)zVU1Q0mt;WBlg$iPaJO2S!@K@!=l2NOdEKB9mA!@^E-toB7U8U>% zD^zBM{5#-$!COOup)gWZ0#&rBF*MMK46fBBKgp4LNP(%C|MD&KI1T*mVe?I*#&mTr zz^)bL&2%0u&u@XCq-?R@gU(|kUlz<21@LJHm3t$`m7Br{+|F^qv9!}6C+Hu2+wH4_ zYBINiOzeB5;`hucQBcd!`?av<>#KwaLTvDCaRD~lpvNpUEZ<5rm>KD%d@T)Qf0s{k zr&>rqOcFfU1)nP{RXr<(>UB_m0ghfvU%OxzU{%c;Z+h-H%^QnT|JJE!ZIHfme{2*in3c3D{f$I z?whD5D{u+1YI>nnV(-8U1NkH9^Tt9BB$?2<)m~$QYs~1|m)QnovX&@Yre13cKru`Q z+))X__Vx#(`%VAbCl9-sTs-K|lzAPs(#{NqB8PL7tmSu==W+5e=p85`1R$3vCS$5$ z2hWKuM@-Cp{?RvNHUWoe93k*#DyER=`=gdxbwTkdw$sr7&sO3!BeZA^wI)As(h687 zn53`S%)^WV-#EJAZxBG=DFP=y?I0$XJKlS-c3?kl)Zjv>xd1vICTH>h=f7CVN zti4-s_9U=~*n4@(W3i>7W%1>P2b01seZ~aa=08^@J|sgVPV((jkMxmrvPy*UK;NM_ zWGTU`*|Lk-uZ2-8O`QloL@0OWdqcy|BUyG!3NjZU7XhfAX?}{(OG@&X{3crby0azH zz6^&x)#|@an=zu|*J8fon!C7(f^v9cwU&T*TSD`cGZhH-meCe1 z0mU$?STgdSYG`bk!QcpwHLsFuKpdZMnb{_54j7DYSRP@PSY<&=Us}oLr#&_3kEONz z;%|$VrY5MaL61(AKzz;L5PwA`ea#9ly@EPGo$3{5Lo`*?rNkZvmso58vhfcv~>@h&0N1OHt7A>fP%yY^|{pyU|!4W&@J^oBEYoZ=d}ru{6znBOXo z{Y0o#T}0|2jmQQ$HMuYPF`CF$kCr|hQt--wo1ynr@EfR-#fW8%OKYR%%}c-1T~A1` zAReKO0J_2j;rpViS%ft zZyiN#MBt_BKEf7oB{Ql;e%o>!$5hcb7f0)O=UNhBhuC>mk~bkw;cBDbdu)=}wrr;$)<9o~gCe zwRfyup=!Q`fZ0Ar;5P6L^!zR6FiP3vG)0tDYS156dh7v-d zooj9*L%S?tZ)2it+9ox;vZo=4zBZWYMlT+m2QP8exw&<{COPB0d`(4gkQmjQqfSI% zex!}Pq6AU?2#nsc?0pu6O8R0DGT`1O`ADsgpG`#Ef=N*uV(Q@hTKRp0NYWa^1x6@%2PIeIsQtkOmuL7CRI)Ky#0mEA5nI#= z#xNzFci>3B`?hAEf1y}DO@h$#ToKXYp}hl-^C3!Kz?#;D05mb}=JLG}{ootd}AJ&qfWu(d0)-=(MIWjm^lD6TqD~Xi4#|`$MB|{UX3ICldkN;<%%|y5_b!@}4S4 z7Gy$9T)(N0s!{s=aDmKOR->G_QwHZC&N-;xAz9jhnc5GIxOwvDT<38_&Dzsy_`A;i zez(6Pb_`=)iLJA?vr3SOqJZt0yj7iXJLISv|0a&@6S#Q7YxGjj^LNXW_T9BQI!2hgfW84SgoB z$F(*y@W0j*=s$bcnwwW@3Iw689KYoGP$YuTM+oi^y{}6>{#2;LPiNP*S*0 zHT4QN@}3ajk14)2B+8Aa+a=WGvP(2LD9?=()GoB~u3$|29Y;fChfFk5ZG?AR*vAMf z2#@Fl!g&(|eu}&tSsP7Vvz$zw7$t#Xg(d91smUeW!;QAwTV(SdsInDe!W_8xUeq|? zO2X^*;{Wy`#g_y%%`fcn7wIP9<9R%u9j`V@WON$-xq!b(ID=XWIih~79v4_#EE4Nd z*iK&@qIcS^tJW&9J@n#CHf&N9tWgC7VQGQqSS7mTaWKP1us!c?GVa|YpijENY{M>ELgzoir)r)8&@im zyUX!P+^K{6adkjZTOjJypkj_?R9OB^L{r8Xr2%ntnV+8`U`r2mi__hC1|W~o z)Ok%~BW|h=GeoWya=oOd%MFzMrV!0OK=mF@Ri)v|29!Xq6*Pel`D?F*nn>H`p0mfm z7_$~gAFtURE^F?~5AN0UnQniQ70~JHg3UN`P4HNm!bypaP>R{wsLh6Z7~y`hGRfIw z11$=GXL@_%wd+;~;$7|V$3rH7Z|F7UsOX{5$6Sv2=Mj7H|MsnO68hMs;sy$YK#QQv zY2wH|Xdi4!r9T~A-5f1b{L?z|S|yeG zid*J22A{pDn(RPph-Tc>`I?FSgFm#P!7D;S;t3<~(c#Xe@VV?wLinDrEv<&wxYh4N zh|5Y3`NFI{lCh`RxmmW#tMaBZgc?QlQDt-23p@rqW?Bq7m0ki7LT)X%_frBBgZI@> z9S<%03jmajJioK8>f%b+vt7{OHjnqAbptK4A|Z+^y3q5oz$evy$Qt%td*M+L;K=JEC}K-NZX=+SO6rkP4Ch1f;xUMa(6w&DFUo5$x0*Y+gu zyS)WpQ(Wxl1xB+JL zQI+s>XHf__>n`qKrBCHij$UtFu;5{2{7}J~pAKlQnN<4C(H@Q6xJ#OPK!Lm?r?lzQ zU5CDP=R^zGb?o-0KYv{jIzxA z3kV zkBi{v=Z{nDO8SZ5`cHIn*wd0pI~@HtchRD!waC4I@(Y!b z=hFo4A05BMAJHu>t5DVt_6e>tBI<4+!!Z04PC88#0=WBH5#gxU2tUKexKE;1YX)*3p{Q(!^Q$?k)aQ|>ZCW1g9ayrMgr-7xOgnE*`2cpqH#1ujhnsfr zyWGDPh;A#9)X$K~SoM)9rmL^(=@Qf3V_ePH1|AS;ci>+gj^X}Af(HKSb5l>vag2vK z`^mz{Fe*uOGbn@4u7;0P8dbZ#)+!uoi^4s((| z8F5V*^8gjIB2DSIA9vyMoKJchgB`y2e>cYkTMM7r2TjPLo8xn1%5CUi%VW zWnhlxu;p~Ha(}ltA}JuXT6DJ5)y)K|0EiFBQr3bbH%4v*;i4b ziOC=_6ZKfsVYPRrKoFn;4X7R&hTB^Xsw=L%1!SBNc(|!=JXq@U0fT>9pr&$_Gn1?# zmS%qa@Am}gu1vfhhDdN0xV8)A#_7=G47ct3ltupJn#f9y8ZU`vjWiW(2c5&j5L3ir zu*EKYmA4N(uHh(r?}us~xdHVcqp$N>quBz#E8u70ZFGn9$>;7D8hC|eYF*jt;*)bN zet2jusu%}djXcVao;sK-VH)r5ryd@2kRw`7GifYWyd%MEtog7D6E5UEG#!UO14=k~ z_9cribg?#O4ca$;kndegV;Dt_A<*c;)u!irqZOczWl~JQAS=CKeMtDgbK;@Z!`WU( zVrF`A4fQSjHh|PR3j~YvSBiTRmY@~4o8Q!I0y*VG6WjlGJxA3YBh*_};Fe#Ki(`4N z({0%%!x+8vK4U8L6|0j@2@#ABK=?t(8wg*j`x@TKtmjLI`4k%{W-#?f7~I<4)r#vZ z;1^o3R?3cE=Db;ZDlo;H;^eJnb2~}dM-G-6pla9ro&x3;@1Q|rjAfSdbCA%`&~Heu zAk(l#oAN<4VG63F;AuI3P<;(*g0OL)n?jxp!_rBwqzzj=K9pJ^O+vUD$NX%#X4@vW z%03PTJ%UD7O>?ZKLQq!tB98oK9TwZkD>HpNz+uK{j14eDX}}X1=^yP)>M;xk^2Nop zlf9`2VNJ0xp=Wujg*(-KWJAi;`(^w`RmG&}JXX2JUOpvUEvOO_uoN>v4-G6PsRyk)fiv$?f=gfZLycGc z>n7X={wR|=<)tL=hlF9A$<{~rBztyUHmo+_mDpQ%!T93f7DG}6@87%3`;t`C(d7z^;+F?d+=c@mD4-J6(>NI*NhWwXV?CDG)t~E4HP5T8x&7?3 z3zNdF1$P<(*z;;SW#!{oB@xX+27_PHvk>Ih22(zyJj9TfDG^L9GqTNR@aU*ME!3S;v}!NF70Pw?Uh*dq zw}AKfiXl!Q%Zv$E{6gItSsE6-5;&~SsK>Olu1mWC$msN%tU}^~c5PacOLF@l_W}5M z)VfQ3sYl)!an>4ce-3fA-*s2wX{CWn{#7K>C~%P3n-tnQm@^UXAh2rs6ZEnmP}Oxw zoYr?vfbijM&N$ge;ZpunqvWZH2^zVX5n<|523u-9V#K8GDbdH$T#(A{839$tIP8X z8kmku>;`O@Zp;2fC+Mr&ak;rug+@lIStuun+NzWtv)8t&BsYVuDLWO!EqPxHCj|j3 zk>M_`j|ylSi8iAGlfuT+_>d!KgC?a=Y>j~q9};!}O6t25+n$;u>gwY3tmPDi>cQ+a z4Te{6kMc`gxBVVi0?Z^;0Mnw7@-7AB6cpbFcLJBGHqHbChzLM6IZ?&Vj56}QU-~Y( z<_}2Y#%UWG?|Uq_rM58qJGH4T}R3u26> z>L4oX1%_Okc;$veqz`s#;cw|?ZNI>o>we;yWc!sRQY zrS?!z1ofW~om7jUJ&-*cr0?Z{1qnXEQCWa|Qn`GLvC+X?MG1OGK(JbfFG|(_Rvk15 zFimbfjRa@0xGlwn_lg*rMkz8=drbn~Y2rrXi6v_H$ZrjUhWxR=VulJX>#pMLHZF%V zH(TSn9c@+~lVh1#&s}Hu+RYW9#Rp0!?Nim{EKsLHAnI#HMwwxbF3ulB^_86^n%GIk zlk2{B-Gw4@Vv=^8xD)p5`he`~aH1I8$Py$KL+2(cY@8y6Z)0}$wiQ^}yYBh{gB|rk zt>xR)kf*;`Dm#!BIMZ|01N?B!F2)$I+YlV?sh^-4Jq(i5qZV9xj&AW0C8M0;3TbKf z^e9uooov-~h_(FnyN>2OD#s)9uy0gGka~JV&6C4d)P>kcQsSX z>1@{Zb@_gIm6~VWqke_Iq$Vp4n`pjonYWZ>&At>r7{+o+l<-`eJSntGcsn;jscAHi z@G!=E$%lLpCkuCpmdQB00&S{UzzY3BYXf(dEfn(fa?=eQ@&sIWMF&m`IXD|_wHups zuA7qNrQZmBONq!-7>g}TRHc}jS*PWfvkE&gBZqUdbDiI6FRSN z&NA!q9vB*8ANOL1wMj7070r`RxYK(xy7!EjX}VCwTzm4{ag zNghP~{x@M#&l=%-dJ{v7$hc4eX3vK~Z#G8&hT~K6lmNKyENeO|f7+_4&~|A*On=_J zwJlZbLR7K!jxU2X1;s{Lv;*VM0s6*drz32kw#saC6` zq(Vr13OwszIG0D%Q`{rq0?U>^_ljKWYqfj4F_}Mh#i7RSpnWJI!ib)gBPScERS4)z zJ1Q_@K`MUB_VVaGxU}f{)_NdYK(gI*H*<=dr?MuMcBN3i9aE$O)GAr@?0C_fd$oj} z-m|%FMUEYW}_1B%NYY3|y2_nrsaa%2L6$_Jm1d_l_XmsZFyz43$xf)Jf zi_R21x*0lRm<>B?oB*$OD6lND=NRA!d!GJNwZ}cSP&~F($tOty4jhouj~zoE5VJ&{ z@GjRt1&;nqmuHZvuQL=(Q{_Xf1r8NlSaYL4AfA{=Ux*yFgHjG!rX<)y9R|6La3Uvgej zc+}Wk%_ig$S|z zj3EMw0Ei<1PXyZu5Wx|p@=z6!?g`;gH*w;w+A;mYUJdC^MSqT5BL`A%a?s(TQ{5AY z1F#4)*c&q7AVNx0I;3W_R3Qf_#xS{+5(ekx-v~3<`vnj+x6{EjbbFRB#EVPr(}rRO zY1-1{lBc3vYf%U-?ohiuXK%L`1|aVffj@=~2E>ZSe(xbrUhWg$LthK*6WqgJg9Cv8 zA+0PDqW_=Gk8@V9{@eGj;-B%}P5XZSx9{TJpMTB!g)V&k^XGN+mTHR~w7pu>tKTx> zR`;JTwZBhgm@lvB=B=?WyU2gM9w}krWNpIX}$T4=-%j5Q+-GB|6ZkI`t$Ff z!KNzf9KX?|*LKj=+jzq=*%6_9{`<}Ka;rS6`M0GXL)SX)5?|E}N)J$fM|B{AIGq~o zTif4tg0foAyt&_X{?o<3=VpFevuwrB@%^mLg+LJ_rFZFRvd%yOeXQtudr~S`w#z`hF04T>8~vA!_V&3&Zk&%(Qdf!3+2z}PyYS%YVcgva(l19 zh(EY*{PaW%P~;NmzRERpWLnj8n>yxQBfkx7v6tCHek$NbI3+y4tE=U#;1z8HIW_<0 zvVAiH^&*B}(#mFaHS5nku-mbVyn;zpsj!Ywf7a#vDLJK{)CpWj8KyUp;9u6HW0kw5 zx+k7SE}H&4T=+QYrEk-Qy+AWUI&J3X8NZX*FVf4OV+KRWQVvq(E)e_d{r~N&fxw(D zI=0rW(Ynq(EU9un<+un~sdsJ>GeEuZpSc#hQfB1YuR(B?3i56idUrDSn)S^}fvc6R zFiE97QVjbHS+S4!$yXQju9OKBx<~Q7-DYG%>b>Fm>lY-eY{}HcT`<9S`4W7^d*Q4o zCm-x#`IVo}`SoQ{W>U)Xk7HERmop=`d?kE9&KD#vEXCj^f5Cmr>I{ahSC(Fi$=rD~ z8Jm0{grj(A|NK;bp^Jj~na?x7%)fTOS)WW7Z2Tdb>SdLG)vA##JSDE7;d-Xrdz{>T zJ67@Et(1`d`M-cischRxl=VauWI_6G-I}aeZN}1Tm&hN9cOU4TbdLP^S~PrOMd);b z|0Utay_#8+!|dBd0>_1pzD-T6b5bpX+3fE>_MBst_@eiecKhw*vyPTV-Ou+$(NhKv zMZ7TbmNCHm&Qi*K)(%pcsatryTwLDROqcFMD=Xg!vMCM8etA)zqiN&6D|IDuxTFRk z^dYVJkNCZUq%PWC9K4>1_NTO@-xjINKir2Jk0MPZmG=h>ZC_$utp2ca*zO4V8Zu8D zmEDk~`+oIL@(xD{8&I&piiNkGIsB=5)2MB+z=Kyfe1QM4{~c?y1LB`8(gJ{}2W$|@ z`!77RHa}dcerGS;d0qDb8M&K1`$n5m>)!k%?=9X0u0Auv3$Pk)~zR^KT=PlEzYTq8*vU?-&C-qC|0yRiST+=v3cpzs}DbCWt6iS zK3E^S>S!g8Kbpro>-y0PVZ>^|Ae~i0$JGxFmmfGpJ~FV% zu3KVyav;*H#Fn$smD7uFqfbSCNT}P@-wb!eHhnIfXT2|J{GMARLrT5T2Y6(8JN3%- z{$94iv!QzlGBeem9Mx~mL~U65$7uK+I-Bog`|XfU5}AGBo}OR#_B`$Jn#eVBMB~Rt zuhW*{qDOtXWTxdkF=eRf9{62*2oj?Burh6Ynwx4Ov07x?@niHcjxhv1&aOB`|QOp$1WB0tMLRKE0ZhAnL9C z1K9NRnw5$1O?{d6L@&{k#F@ghkQ>5`rU`S$l?n^~#HsnfNy5;&mj)p zY7w)EK3i)OXVR-gzeKG5^gV3-X!aBQsb%KQ4Uszhgji}FMRAUWAibS@c<8rE&)MUZ zDS)A0{#{)sY>kiJtFu>*Pq@PF-Q-#ABAwn9qsI$Zm9G{RT^oM$%bIed1#3{DeNQdw zo$e2-OvjXscTMQyL^0vZqA?`@;KbaAn|$q|LTY>?p5TMMlrB6n0h9&8NF&MF+gaOBTG`xEzIa5v}ucLVO8 zY5$x@i|D_9rpon&;+#dL;%b@W|GIle0!zN-H+Y<3%z0Z2Xj|8b?Oy1NdbaO5Kw0jM ze=+U-&1rd9qe+!hFWUI!%060*YTpTM^A2;v(gJ9gEsWTh#3=Da&Rfr)M&K0Obye}89o{9ol!(Kat#z+L2f zNSSeAhVSrK^Jl^L{MFOH7PQmNGGngoA*z%p;COa8d6`1G8oyzX2^v8L42bsbjpbd1Be;IPnaYHE4#C$s6Bx1@`Vs^1TW-?zX(q=E6>7u`($&|t>eP%85PTR)RjW<8$XDVTWUQ%T`-lkQ9Bje z8p)$ZBjbm8_|+a|4w3xRZANaz+%Ut~Y)S4&lVagb1&V3qW7jj!=T`uizGvH*$*lM+ zp8Yh4{CxJo>cGMCCx)$ilXjoBxL~H;0r-6^hug@0pM+-`uf5*cm6*}@J^uFJK0HI^ zwS>rpXStrkK4VpIDM%=xhw$m@bcxC z7x#Bxtsh}MPHVlfwqrsA3FOdAoMl9@Q>QV zm_1V5zoUD?{Bx%ZOv&PlLwn8H!leiqk;d-lIaG0UW)Nlva8E*`^!lZ%GYRSsT+c3q z)L*&_N~OO2(f_#lZt&muyf;6OJZ&pmbQw>{0Nv}`z<%j_76`nr&@|7&3Vu+(^zC!U zX34ED_x#SC?FBz}{($a6T3&e}`^3Kw>_=fnbu63~dM$KK^{0Sycc&PK&iK(EwQ7(< zlstN4eBZfCm68Q-AAwfBb-Ywx@aX9N(xgKuXgtYI{gQmnq4VYON|Ddc7av+ZRu}6d zuzng%)P)6{_-|hiH#us>cB5!nZGF_!-FIoBs}zZC%UMC#pS}btU@e+$X1)d|jJcls zykchi>())94q(N2y=%uj{}SS1!op1vhjTAqo6K#699^Bd8>THVC30yVGMYFkVYn@} zTHE~Vw8sgdKrf2sBli|zxI^C(JpTPn-U*R7%a2?0i&qf1ww5kKz~kSDQ@bjEF6t?b zp)KUxm;cg?O2a(ge!>Cr=W`~$1;=Hq7;4m|4^?}F@n-*Xq*B%!Q;UzKEo z_UG(g>wBhJ5|i;pvb$6#A?D(F7iH7*d+FJME3T)-*mt%A4-R}>-@GPN;6Wp>G`vkuD~d0($$Y zAH;Gq{!C&StyuzCHCD&o5~89Q$AkaEWEQ~BkG4%82{cU$sonf(kzef_u)KmCS3SEu zEusA7)_iM5g8j5*v)<<9CmFlm;7UuSx{<`(;yxuS4*&69S)Z(O?=S8W;7{hs@T(T+ zvxN^FkG%S{Xa)1XKr5D!E1qNDwz{=?rt0n9ceC(+lv^ zku0_R7a`|mv-uMn56Ba>{;ag*m$n!{z8(av>VF|&UvC^QaPm*Qo=a>z5JPyFb%-|4 z&X;}{oa`0RZeFWu$@VC-f!vrzImj{xZ)46`!th_g)Vsjtve}*s$Za?s%dz<_lc5-q zLGpUwvd*tKZ#`|cAG`oxW2c?`ZzB;7u8$7{OKE%Ty!UQ^XB0AbVW0Bz1cw`6Em|Se z6YxYGM1Paj_m$ziZS9|jhJBn`%VbPjWSN_<5gEw}S$X)$>PAFvbq>Y$z))&-_2FvH<^N4m` z;WNpc`5?p%pJe5`$F>GPWyZ-qM6hG8!Mn%XW&MCdKlOmNEz3;wpE=oQmCDSVX>41B z@SVd_J>}55XYpXKXRa5hm|&mr#!P?-ivJ&Ym zmt+`at1=`T63|=3TPtS9CJE)5>{wc6KlJi$ye#mx%Rhm)hGwwCZLE9BAO_1}uXa%D zWfv~q!j4}*0yr*=vhk8n8PqWGnZ%Cxg9JOgZ2HAi?bJiIP3A)x+zApFii@)G79DV% z@w+k9@XyO;i_2}?6&Z&dkE!Qn&R!V7V`mN0aKs6>BfRA{xE`UGY|nAj=!nZ__&H`1 z{pSuAVeSJS^$s_QdX3ujztkBt)=lcbfPu9#$GEn>*oqJT}Z6G5F3I;V#)2g)0Zv0(N#%cW87leQk$>CSoox$+lY@VD7{U%WRW_ zp+2LB$m3UzAZ`tpsY2_!#^^@!-@tVcK@xRlaL;V8gQ-Cl%sM6|;&^D{~=v-!c>RBFog z80%<4gO=-6TJ!0bw>-{kuK0OJ@c?z()$uva2QaF5yb=`7?(I(hh&OYJy(m+umC? zcpW@tl32jUc3Eak;z7Xm2XaGvnZSqdF7f4$)$#TV;yi_%C_}RB&L7U#ZC_hwa#m$|@Gi;By+XNaHnxFToT9reNFE*+!`w2@)pIFDjm+%#~U-#d}0DWkq={!mFJ0jXKcOvvGNz#`FdTx zkC6APA%l3&#&hoglYnxYCj(#1^=}>7_*?y?=%UE*mJ_Tk00@N7{dSrB;rzHX-!Y&` zs2I#H#QU3iE?W^2FD+{A;;rE4>i5pRK8xwl5vp8U7uK@+pALa(#tHU0Ar@G(AhU;t&V5@8+VMM@b<3e*We%JijhS|ncm;&^xP1g?P?FWMBrJoy zSrIS?oFC{UBzTuk2B!OxEV>qzZqbV*l63=vsl}38bz&KX=2<&z_T-e2O`H#PhgVT~ zY_aNl)WXLCA**DZW=SQY)w68m>aTr~?SPH8SvqzLQ{EQY!rv`|%OJXP42GRU6GWUc z-a8)NEQQ8pIpG1n+j&>dY+fNFW@L7bF8Dq9Lfh4=lGxb&SkG3G8~Y*CsY9#!S%&7{ zKkDdSxZq^4i0o$7j7dGG5^>U9vN#A&x$=F>yaxr+81_w)>BB9Z!3Bk!WH)ICQQAs7 z!^@+9nZg&rni^6D`EA?~A=4&iol7pH$UaZ-q|s((b!7Q}iw4~ekL(T4z&E6?#HNT^ z?({G7KmKKP-2V4CgQ5-UafS9cC1=a{!!c~J zm&A)x*d($R852DD5&c7E+aswh-NwPJ7kSqBP&^=(IAX>AR=+JiLHvO71ZBKq`A44- zlc(^#g(b02BE= zD(4V#;>%hYon=eoO zd*p-chwT1DFVm6)e$k&HKI0E?Ag15xZ-(;^Wc|I`@Y`*++k6mxzt#-@0775Gg1@t` z*>Bb{XBOSy#=-vIO87D9y`Azr-{IRy53D)6P{l1ewfo5XY@>lj3^(HNk_euP-{GUW#p37e~183V|B0|XisWa^NJPt7Nlj0q_ z{o17XEQR&swh#72sz^f1>=sG3OgWrq7+Debfs`|s?ukno>qry(KZ8T;AK5>X{R#Xn zKX3Gv{k{IrKkA9~Exsd6k7TraA^pGJ_zzgU6UA8z^27H0A7|9rWt}bNSM-PMYGz?6B8GSYx|F_^q}M zZ*wfHXITVIB|o&g!zpk-WsRBePdw&$`U@n*RM?P$3csyHt5(_NbGJ2%Nh_YM% z0J&)OKkEk%hIl?7_kRO1#lDemIc{H8$ChEyIFEmCdi=AGi^KRm*=6dTApZbs`y}2o zn`sXGw*0mHxBZp%uwPgw)9Tf^BuBZCgZ z4>Q#MtJCRV%=z9X**y~J5d-xy+N??MUYaXJiwNIW(eg}i@q zi2m4m;m3@SN!0FH(#t%bKAEq$1Lp(#gnYFx4+I}ze#rbldi7?y^I_uf;CYK>l1L!% z4-A4Nk5+hPgtmBiU!aUg^~a&t?_R&aaJ~@?mrMukq4E>!ZulrkePsR<`4Yae-@GQn z4}#&s+hvY1=0|cloyeOk^7)vbR&7T!e7qYZgNZXN<8SaCKJ*@McFFb=u-Cy#+LNn~(s^LX1b9iME-j^&ZzmO&BYmP~NNS%)Fm9Xau2%Pb(-jz%N+ z8!Vo;%zeaiDTJlE>u-nKB$JtE4xA!-m^fg+-H>~OfgH#`go4RCoO;-XBi0(*FAgT5 z65*T-UC%eK8Q?#8hoaT(khX6}8#dc)JUAnpo+N6_vTksNTfHw12Xo7KLyrz*oI3d^ zdh+%$d-3(~COAy><1vToVf)i5BS%gX;CMYtICIf9b0jl`553rk=G$*}8#p!$i##kTKaC)7K|gb#AqL)vG}$JzMU-bNP@eI1v#IoM7={VJZE= zt?}W$?|)Fi$LBuHwto)!KPTxu5+G0L)?$#ex@gQyvy5|i-x%NIln`Wi+B%=DqAL3c&S;00-58DGi zrhSF#{fJ8&*!3inF~hkJuNRwaG18hG;eEal0?q}f)qyz+XAt07)#^SHBaQjQ*fLz6 zbR+IymLaAP^=CfZ$%%!Q6Em-dUpCn`p3>*Z#$jf%^xn=MeBs=VF!6Zwi(&2#ggHf_ z@)f72t04Q(JOgDPY?6MLpl{A9-+UslzTt`3-bK{2x9~K^<{o@1O zjG2&qw{N?47Ed#oXLp47=MFPu$QQJ~*MSA}*pG|uwnQzrgiZG#n8>k>Fug>NP9>9j zu;XF>0Niu^N?)6M^YEK5WW&Mlct_6%>m&fXL|GPllJxY-p=1U>1sf2wmxTL_mh5Jix$hh z8*R2(d6r(Rw@3KQ&lnd7c|@7W)S?Y?5UlOA^^_{gV7`Bkj8n zch?UL_Z%|GEGH#7oC^pbvdcK^N$+eL`+_!gmRV;5VU~36Pm3J)J#3kZEaMvyA4XYx zj_lc-&TYIpI2&vM#uwO2X&h7IwsA8l!JYMW3nZUX%(K9=fzg(teV0S>ACV7S1Rm_> zM3zJx%Oi&}dgIiTpDmZZq)PmK zjQg3E5_AjW!W+x>QLF8S!pMy9ho|hXlWBfihYO?pLgOE>3nz*i!O0Koe1(zj%Pg`8 zEVH>`7FolISRsVWyxVQJo50I*{n)Z;93_(GJg))zUe}~Y)DYx)iIN@&Pfy$Ntw*X@ z$?q}=(6EFcvMz5&8ntb!(_tB5dbZyJ`|#fmCkgo+A|v=8m+bTFtnvOoi}pCg40wI? z`xnGT_0l81M^1?A{{Vyk!~iG|0RRF50s;X90|5a60RR910RRypF+ovbae)w#p|Qcy z@ZliwF#p;B2mt{A0Y4CoX5sYB{{ZXf{{Sa*iJz$d0Ok7J-X(o2>NAMF#fHD~f8}#6 zgZ}`dar$xfZ|FlmUOue(mpK0b(#yZ7eGUCD=tc~4xvB0M`f6X$htP8j{Y*(+E%~ZC zF-o>(G+y~5{{UjmrDyp;Bn61?>#`7>#e`w?BXHl;hkr-Et^WYvaXF6RxVVSVjJW*{ zrAU_sjG1t+4rlsbmsP}(EfBpn>1L?1= zVpsk%a^k`+CHRK_0QZljqra`fBr1yU)NgtnwS3ohY+?ni|StdKu771CMO~u zvf@CZyGuWYB?b?gnqvtS6}&lp*4xjZlUzA zqc0y*UrLoV1(|@?{z-lyXpCWc`qp9eKK{4#VZWtz%o$QsSMe;@F^Xp}@{-QUa_SNd ztDgZE$&_B;*NTc2Y_UnEnq|Q|BfqV}57OU>hv?E?F6F`Z1}-Wt+FR$6*Njv&P7lOx z1=bqeDFGvXBO@ZGJan$Q9}u{cNbX^_UM0(?GUbzboJ+*MK9}?s{{ZkgoK7W@@fR?g zeI5k7T*DnrM)Un9q;8%=aJsKS%!n zVjd&ErqS2cX8!>3S^AM@GVfpbU!kA;4uA8n{V)WfxpvbueGmQa5gO_S-?RWYVZdC) z#No+hVKrz75~6cpF+CHNSSQGt#0)6eXk5H^aPkw9Ebs+E3hm>#$1wRWG?Xi%dq~0% zt<9}}*mkN2oy6f`B}4wGlz*&`-emc)ZDvRYbDHr18v;0si}`9Yt8hamXjp$US1|*b zPrL%+Fo>8EK6074?uH`sJ{)}NAJmX%G=G_a&^xjlVy|+GBKO3@oX4b_W}5zxcS2V8 zG{2)sT|g4G^bUT7%)h+3ad8Z@23)w^!aA21nSbyFnLy{XMI%A+8G*YN#j8U_7dM38 zS#eVNgWWXz%LuO8VAKln2&$&DE(Vm~n|$771}EGKg}mw{7TiIXJk+}@-r}L>s93b- zR!}$G5e1_168q@88NcnHz*=>0VwdOej zx~T0*r9+wLZ_+ckU0z_$?ROmA#TF^_!2V&XVn6xc*NE%r{T)k}oP9GZ{{R;lW9!U* zmr=}N{{V{mA6cPMs?l}EdeqMq0dkwZIv*i;DJI6n|6sW@-kJQtxN z21)O5$}3hi4*|K4h&yuwE3GxS$Tul~2MvtEosd*s97I!<6v65+I=ht%B1EOO{7REJ zik1V~x8S3$|)F;WZGvGaiRIjgZtTvA4Lr6gyz< znyTH)Fyqw6phZdz^~4b|O;o+}2ISYdODROzv6UD5hWJ3x*~BHVp_l&vrc^B+)jMLa zl<_YD)xzM0IfDZu8$g%HWopx;FhXXyeaC`}2ySk9PWcTyWIqs7GjL4(SZZnX@$|2& z0Em5EL;nC5IE(atyOs61$I{N`FX&2QR^~g*+N<0v8RW&v>wv(SdLhKk+!CO00ySgs zQg0u%9JD<~M+7L2)oBx`Q7aEQRVis-cpzI6$HW-9xP5Q`04Bbxh&E0oMvncw61=N{ zs+0t$-P|XTQwmI7A~k`>gg^sPg4NLQ_u_`cf?h@m@(jYJjMeF z64Sgw<1+g-pq{6x8JQTCmlx(N5;={RQ0JTx)uWf>%m5KYFmJTn8Xj--r!Zf{f_Z%pEpeSYT<7?Y<162DX!lEnzo#rhGYwid)eqbkF zBNSnAq6S?#g$g-EfGbVGTQpU+%h9=3L7_6{7AoD6#SmU|JfM{Fy$B1%@etZSFvTa? zFb)1AyEX9)Imft$#2H1F^M2+MQ!&+$h}P~74MGqDs|6`&bU3(_U2~YuifDo@wz!o5 zvDnncRYCZVa4B^Fv^&vgnjW}ym+CDN<-`q$FFhQ77`0ETDj zafZIH(JoeEGdxFAiOe4TqfsW4)Cei?7Yce+(E~tw4902w(;U+fim#XG+G+Jd?x2|! z*$}GNc?`WJs=xU{i>=(5xNgQ}VTIDa+J&^ol*BN*I)BW3OkfG}{{YCm&Y;-OIz9d( zsurnF-ck~apxxs1^ZAafAMf)mAy=mi0CUJ`*QbAYb*o6+AbW}sT~807i|SlSDcq!F zrmIJu67NsQW&rPe#d2_QDnZCr_>R{+cFag>RF}3#8Y*24tf5{YeHbE9aI|ir3lwIX z&-sW@ZnL?P!xEk>2rxKaNMg2>OQfdEVidC9?kjPXmJ@DefUlU1r*eb2QH_~dPFrOw zrc;sxp!u0H!74WqwgA}KF<)`wh#D6aD=#n^3ohUdkyXaj+uX#{Q5nk`u|8pN(ap?= z3+gZ41sCQ8RXzkn3UchZKnI9l4Se$|ex2vEFx(53t-~$O)=aZbHe;E4$x=sf#} zAYF5a#Tz+cK%-+xtVYD`{7O-mZsP1x>4X|VSqkoR2f5jAs+n%F%|#gjjY|`_(cCWi z^BloY+QBF-&9N?+xZ8Ejut1}b)W(B)t|j4cd5U3YbpTdsCJoL3s&O8-UgJe~?}#v6 z#u~yW!u1A_j~3lQkjoIkG4U-F*(?LeMj`+e`uD#X$M_kA3VS0Wb?#H6--vEdWNiHI z0dTnhj{gAUDanGDL3r7l_#h>vP=P%7my>m`h1b8_am9Lx6x7rTbW0?NS<>PX4tK~w z{&fX8?pyRH?l<+f>h4@pZTdT(GknjKb^v+AD$07tsk7X@3+n#>`aoyhp)x9a7&rLk ztQ1)YJP}6A6^un&%p)egSVdZ(yvx{@UobA|FGHW3Ii%Wc^ti=~FX+Fbn|PZr$3`HU ztZ8(nAJ^Ivbnd`uCe7h>aQj*nGF7aP-577jlPjiDCy2dFKDSGa9sLYo**U60vB2Q& z{{Z<=iE`xgGYw=u8G=Z3aB7$+wT4V$DQKdHDJc|7QnKaluTZoQBDThP^weHft+#&S z2rkQZLNrF(Z0EQzmP~e$aJD@m-9%kn5sbN*?g-ORySk`oO3bv$xEs#n88B9-BDa^Q zBLAuukZl9MTw80X_tboQX~ zL8V-Za9GQZGbp_ROWTj;J7UX_z8ci9agZDw7vD9~dBHR@`n zp2@fp!wyF9ML^bdtNUn<(#rGy0Eb^wd5wJ=pE8c%j(CI*y<=o+*D$|mhg>AkBPxU8 z)Y-dj23Tb=GQCH$0|PR?B8AuHSmc$uZXnw!S97pInTla%B9O6z&>-d7B6}TmoYD2U zafTJoIdE1<}{u5sDECVF8x7Ns1f(V`z!0 zj2HYrXp)O)UFF_9B{D$xg#wVxG5!5ku4`2nv<5|e_>@a0AzY_>ElrkmMW%7Ti9iCk zoXSvfH=Mck6tQaMR$FjE+Q%~YB&g!zsP4%~qnFDlxT=ZKjR7T`GkU3+;km zC29jp#HDRe1U{gSE-Pk)QLwX9JXPFS0wqks++VT@&VzARS40M8EjTzya6U{L5z8q9 zRHocZx)xQ~1mAPoX^D9Ep3?C0sDqgEjT5<#3v{C5XH2`l>^Pn@6EoNR+<_;!%+cItxvANV_S6Y-iIfV+TVML(ij^|Dw=G%sW zzr0d~!7WO24HszU2|)ZsaNRnG2C6e+;8H#oXkbAxt5N#C~R8nl!0|~ z2S403x$5FJVO;H*5C#Fmt~JG9pHYkc#7@<}{=rUw8Mw_ln6qCp+LyTpbR7Ebqqee^ zd_y5EvR#*qho5rB(mF#q$58W>&^I;X`s?%T?WHYP2^g^V=7^XlB1(;h*S~xD@db3Qr8v}T3K*Wn9*sb zEpsR?R;mk{Dqw`>(TQdRR%vDBxR?wC7U|Iz%H?$e!?{aa@g3-z0*K9k7|R$#HW(@a>=;E=P)Ck%8LrG zh`9uO&ZQ?NCAaey6x2mrHbw5ia7FRdxt8?6gk?sS{$PV;3M}R~TIrPDU%WuuG7V}_ zHGjn8i)IyhnKDdY`w;N%A*Sdz9S-l9SWi|@@BIuL4Of5lXU_&WlSL4!2=U` zTimLuc$8tG?3|IALt^4o3;CB-Wqs;Z^QgK*TkZvoQEbAvses#N*iIG`H8mYf{v%{d z{!Mo=&i<7vG1R%V zeA8t%kduj0iNX&dY){Tq0Mp#Hjy%qAja*u}WI2$+&$?p^Q-qd*^v2+=*>9Pxd=^?7 zc1wFr@e@U;yP6yMim(h#VpL-3@e8=KsO_}OwcJ2v;*flhO5C)U5&j%RU!{E=M}Jhz zaK^r6N`xFkOfN)bvI|K~D*)0rgzt6siIOKo)UZl^A_NryWtEh%izTR6V_))84wHyA zV|CQVFA?Ytdx^7H(-=~BZ{{7(DLGz#mTbx?EbFt5AH=DpF;KF#m_p<45DIfX$?hW= z%aZt;VfsK1_4g96Hfmv6$=W#l!>wzM0W}=%7{*A}D|PBpD$$By9Rp;j!9ZqZVB%!J z%+L9#Wdk%f@c~;2O(HHPOJu|%(?T_Cn%s56wphmEmlVM)6U11m%u`)J z(8km#svN?lEy1vRluF<^gMvGXz?6h-G-_XPZ#>Lda|h{aMsPG>l%jx3tPO0haka-t zUQwy#jrPtVfELEv!H-==6$FblFKM7(H7&M41^YkpY%oPtw>XqmTi=LhiDQXthb#d% z@=Gt6o*>4eP@BNiO%CPJo@W=UlqfTs%oVW$VQ0*?YMwib0>whD#CY9qq9hrvqtSta z+qQ8l@p9G+TrjLES1_X#VpWEHK|2SSU?BxlX_!(!2bgvR9M)<8+1pVSuNi}ubY3`s zNrv-ram`BfOB3(z3bS$0x8`I3W;i7r!4EQvgi2gOq=2A1bDy{7Wcn=-yg6x0hEvqq z8n}7X#Ipv64xu3}(5;N50*)37rM$dF;OCyEU{e`*mKKoo#lTEs9Kl5@>A7!lv{{9a zg&PONb#4up5Zuks*HIrR3NSR=%mYi5R=9_Wd*&9dq1m4TCz2u79%bUk5h+5*?ZFiN ztmEl_TaNyT6U0_8(543AhK3U`6C`2v?J2sBf;r3l#4H?mhp+7lwg8m0QI0;FfEmYE zf*A!pj0Rm(1hFrfcEnzMedjBmM9$?!6^ux?9^l#9K(8waqXrkp`!NQMN~A;FZ!PX* zD_P=TbV~|#=23WAeT@v^80QF6gk~B}@6)|H>N*+=QPi(hoREht-eLu}TY?H2Du|5; zE3-$5pT%khpm9*D7rTPp#X^C2hK?7BQ#7E=!n{}7RAiP_lx|qS_Y`UNh9k_nLmkzZ z<`;D2f%;UitdJv47>WuYXlu+Usjg*^tz0V?#BNm^$LyB48oJLh7S197yhSe0m=^6^WU7@;pvuV~DDlJVlyl2-EhAFQ)3?SQVVH3&AQ7Z^`OgBTe@f zR1xN0GEWhqeAWo5cW_7@a|*0npmD5`S`V0taZ;w@84NaWJV0MC5UeD47016rTaHoO ztLI>~aZ(oB$`ei-&Ss$Ld4Pfq;P`=8yk<0EIg3JQ>zI~atyLvoIuT(WwO%v zmTH0j0LY`J)??*(KN8)g<2*|hk1fL+7v>WiEEv?wKd@uvl@Ri8DQTS|Y2<|(qU0;V z5d@>$aC(Romm3dq#LFk*3LMj1a}bt*OFU1@@c5Q0v*+R}F`nh&4g^sVvKvm=cXs#3 zKX~#YEh!p>u(S!l6)a16EQGtlKwxnN1zg231D)pCfLil0vAd~JrZ`^_TSnbXD$TPQ zUoPNbc;+nMGbj0uRWU~91|loVxZ|9~rN&6DD=-f81589wM($lKYWEqO;4>BkHyWT< zn3L4ndw(JBh))L9s07Z9U+f?Q;anseh)i4$%JjFrfD zy1~n6dyEwZfU6s?AMC|NHa!*5nVsEWFa_E3kFzQasYNTcjYl)GSsQIH9v~N)>~WOm zQwlgO2D=P8Hx)T)W>qpsq{~$)VNqZJ#lYM~g1neK?r3!20#X81brE^gO@SD#?WyOt zzq~-kJG)VFx3!F#frbY(;s|q}a@B$)0v>J&l|02hjm#W3&FUbax~j}}f*vDWwOGBe z6d}(LH9vWs_<$>zR@x$8cPyhW!U}&;fH;89o?>Lzlv)=L8iGM=K%7Lub_k{I)7fKG zwltFzpzoNX-JQVAKJyO1a~e^yHWaL8nARirm(VEXsMJwVAaJ8I$hZz%F>ehJUKJka z%y=1wi>iv*W-3Q86*7yb5vEe17r2xInL{&-K)Do)X5gAb!H(LOXPAJUQISp{#s2`y zxr>};BzF>2w!Vdk?FCH5W#(x4WaI4p<(-Ju`HU!+pNT@wdbwh>rUXe;!{n8zed6M& z97gDDh^zY7nDDaPPh{-0d4kRr+uHvC*luF;biFVh>n$A{{-V6UFp4!TT|)sfZ}(9e zv978rZIh^*T`J6y&DPhKCr`{Q+W@rqP3{?R;KMhFm1Jsy-anYy-Q;#|z2;Fz1wmGA z>IHkd|{Dfl(sjW6p8JwcZfsQk)KWfU)y7 zYNLPy%(!kB#ygdxWMh@wqbHa)*)>4!cT4D_X?=tVhxp}d7Hc>g<8intGo5KpY z=a%Nr1Z>?F!Axkxtw7)LMa1KSo-Z-ZBL&P=ajvHX>%_`MT<2^}2Ly8GQRr^y%bS+& z09P6R0PJ?7a^?Gk917k8H5z7vcNwFg7ay=;n_$x4jKpd+RRC)S<7IxDZq`g4z!W70 z7SHqZ0AG7Ubum!&1rdfVqfy4*^MY7%X3Yl(Jqpl@tG-BavWg}g|a^hxZJ$?b4;Ws=2)YM1TmH6VeW3xhh#X{B%MUqlvmjIV083i;Hd}S3C1*aMY%DNsO;)9g zbe3Y^0aauD{^|@Zh-527m1?H}EMOI+00Ix6Skbn1KArS)oawQ8Aa5j4jatDy2s)qjmdoeAO)?#hX!C$aOza^ScWIbQzo~> z1@x4`*`_U{-p} z?2x`X{lV6ofA$DG7!^ileBjm4#rH zSR-ha(H*r4)Wtxqi1sF~fIeA8F=DVwKoPi13AQc0SAmsSe-oye5F5TVj9LsZNrE}(tvhm16xtg-Xi$N7r8*H zlof_B&SGbY%{5BRb0es zP>7;pp-}5r9mpwK!e0JmZKJf}T*`-{_=kX8&r6M)#dQLdZ%`>h4(n0Mu_<)u!3nj; zm?Z&=5JJqx!1L55D&FP98lW**S*$(70@{EgtTdaS#U0u zvm+Rn;gy(bR2hiFGXh>em;x~zgk}Jv%o<9ULkkunS^P^&OLqB%LSfa*ma^SuVFT`H zY-xr8RS;FG#13Ub*)(+OR#w!dq6jHf8%mZDOjMPKNG^r|g~k3N2QW$vMPOa6q7vYvio zn`b=B)kJ7YMPEWJpounkz%_0-D|s;nW`SivtQl#xv_YfhI2kvptlsJ=cmr7r#Z672 zGL+h}1G^Xr=FBZyTyr!TsnX?iOzE?LV#C5q1XZTh&|ypon&4@M?@@F+M7 zcl|QdtvOQhN3h|(rE=WHU8~yW0~J`6Wk7cbA-_}ZBh0pSv{WU)1aXsa1p@13!2PBh z>luyK2RjII+hgF~#qn7MVOsEb8haP@pcWrp~Mu;v+Fo@EUv z{w2C(h`G4d%X~@#5QE<_FVhqYXpK)d3Oq!{b2>Ve8EwFKre$6w+6XHgOAKJQH2`g6 zhXG5p=bai9|aw%(PdFEMAh7wm;gJV4*2)gA(lVXljgxYUaIF-Nl-%QRWT|HCmVjuBD+e!LW9`#4Tm`Aq2cdNfs|2Hj5fTDf#+hdF~GmqRUWbTz%kxvfA; z9mFmKzz#EW0N{f06N<7Mig+SC*SO7(OOC3=N;!)I&_s=a6v>vNw6grg05a~Qu|H8I z@G*f-W=gM^Wo~98++-h#XCWCiokS6!v+*4=mSHV}V!^$&8F!H}q`hH=MYNEGs*0S) z@Cw$gJVkY3Hf>Oj2uNH_;Rh@$Ox*xo^$!9P#CH)CIa-#B!zYcll*@Y8ve2%)v}J#Y zU=O;BXk?_-l>XUFwuTp6(rfbp#}9XF9k{$rO@4HmRlFa!a=wWF0Gh{%R}}&RQW3!t zu~k)N_*qMU1vq;k&;x>0(Nd^}NYv0+f>~~eoK04~T7ms27Oc*Ee&en{EC3Eyqbu6*}05a=$1$c= zV^LcauxTT*olFCD$%}zo7%`p7bEWN`rNO`qTr<#01<>;ssbOCeJQF-hfwdq$PrU2_ z03e`M)OEnVV?xuHH3J1Ns4BJZ7Rn_qUCU@SUwFfG-RHPj0|v1$t3!Ew!p8-|iB1w4 z${r${CzdLJ-*V`9Ato@+Wom zLYH-vWqre@Hx5A#syfVW%U1IhbbOY}dkMG-ux;L23->CNDiK{)BaNSJ!Szz*pujvT z`o{RZVzQzN5{+fM@$6N=q1x?kQdHU`F$mqqP$Wpfjbc|bH}tqdDa$S}%49bfK-_3* zH0jsgauJsn_{18KV(q2D z>#3!tp~+HmV*}=Js-m}sdW}O36xJiK;rv7vRk)N4Ke%`g?q5h?L{(f8)0vaka=XTN zFws>DBdMQwm#P_9_Z;*@4DK>rrg0qQrztSek<<#{Z&;at>vt~D-O_a}gBkA9HNQrG(nh3`MYS1a4ukFrRFNs#)bilp9I!!iJZ*tW%sD4wQYz1Qu6>6 zWOsr9ps7+P5lp;6a~hOgsGR1(WpEs^ZwMNs>~_!kp`Zi;rCihP3@`+#jj?zlS!-7s za}J_Ybq5f%4%vA?m;w8!p~w^hEh%qM{{XONDP3e;XZ_T?np#@ruG+86Yz~*Wpbs4V z%~Y`5vN3)&D6r<&zr1fVzPXpLdovcwiPUIuD79MS#HpH`iXF=vCz(ONF+f{8iKiK% zC4ow#RPh6qn8e&)v_9?tBg_d%8;QkgT-dkNt`&&O6|SRiH7cS4x`Ykl3YnC`wG^g~ zD&5AkXoWVXzj2njS(RNv+kRjGL`u3mLtWbVg|%m#&7N4;#G;I1A&OQiTEQ1EQvxov zEN$i>wNkBF@e5K0`L8nR=3%2KiM5t_g;#RL=H@~o@0iEz|AHt0;iP zO;fKBnG0{96Cku)M#9L}UFeGn?{x^%CINdzM~6{-L-7#M+lqo@r@X|A^{Ci4hY^L= zI*hrXR<&7KV5^GdgwNhlcM0ji`+-OlR)8q|N(JO~{Kfmh(Q9*wY5Yu;OmPqZtUOLU z+(&%DWaY%QMUD@eiYrboF&pkNb6UHK(Kv{-o6JW_gi@EL=ii};8epmSAqo%n%0+Zz z9%YG+o+82WU;uI%x!Aep4XFieI$>;NmtQB$qWCOV%%JA4b;}M#D=WmuR|`-+@N--C z%#F0xBJ6$Q90ld-V1+9;3aCB6QO~(dLrB#{D@$EUrV531fC|JH_AuTU)|;#1a^5D4 z#8FcVT+5jtUmV%z5CB|+S9Z8R67?MkaW8n8f3h!4%nkT$kIW=E2viS@lIwEi1!!93 ztr7i+kg;33?h0l#)?9_^j`p&kfl{*2AQ!*9w|~$rVGeLrd0@Cu0Xcw0Ql$hPrpPx0 zlnlW%+Dja(#SjY^XPDM#G)&-un5@X@M*cg8EmTz)rmyBUA}sQJ{6{jW*gn$#04paM zRyS?U#G6uLZdZK~+n%DN>BU7?n~AIE_Y0RT_CpJA%zT1wxPld1>SG3oF4cTWEWD)^ z5VqG1#xgaC?RCBR+zz%y zz9F~aHJ`M2wp$P?Y>m|!%n6&DTw94^u4S~ki>L)-dXFi@TsG*$Q&z>D;wJ_(#CKJb z++wv6EyMzrh^p##>49!>Fe~qH08PgY8uJoSG5VR=Cg8yuIcCIiz0^*SCMv|3AB1l1 z<%0!!i7tir73WVdAflg{Yg(tNbRT&|s?O%JT?xQbikNUUxmm11r#OMGbBHZ1x!k*JnWwzOS?Xl_Z2QcJ z!M763T$L2E>2Ik(S&G~_3*@C&;7ZY~aPC@_?mS1N1HwIlcHQ6m%vz!axGgz(mJ*DV zm2llkOdN9>jXfgtFYhTzbK-8zXRSfgnD^M+p;%Sj#RnGgEEz|;fXZEJB2w+kh+Dp} z1icpLrUw@dORZdUP|)!eY_xL>4c9k0XP8mOFA!xbeMX}+yddWD%op_JBkSwI(GCKAy$SU9*bmu# z6>PSi&dLu5>Z5LLERhizozC?(%^~9M{avsiXrFASo`qtTc5`x>M71uO7ah^7sGxh` z`m|&ENz+nA7*d0EJ4;ZBlb#?Y$@-q838Xvi4s4;tzreTy&Y{JQn*ylYEUKyq7A6oA zO?z(104Jm}kWm~uMKmyqE&V&OUTjZ0+WL*EO-Qfg?9{W0E_$+xas@No@jiAX@RzJY zEwUo3A{FlX5h`Guq96AwUO8In@lYvFn>(($^mNR zKzSjOsH;p3Pv6Aof*H} zx#CMxxTX}FMnkn(>xR;`RYJCFy+~y3$tsw|8Rn(}Ca-S!#C*kka5* zzQWkG%UEx}bVa^@Wm#Me=}>F&rvRH)C4{a{1e}t>PC@*Opvwv))Ps%Wb0hj9Y&+tU zwY#=LMt2hvp^OX=3iVccg)0t)06!6Ae;9~Buph#^yU56nDnFb&F8RezbQwrpsxnV@HG*d=CKY z%e!R*eGfw3XJZTEIi1(Wg_>yS6c?ZmkG1u`eykT$!VL46iqE(9rjbTw(DpVZ5KA<* z%xDiL;ImNHE>LI0i#8QK}RNgVCf}h66>Q`|`=tXrUfIbU~vn9ykA|s0(`iRv@ z&@*y8y9-+Rks`hvlVs*V8dVZb)-*ax&<(_IaJ%_SJ3Ns*H2F%1egs*VJ3+G}>ga?O z(%haO1E9xY69vP=Q$rqC9JLJHcjEgmY-b6hMTNI-)JBfItg1h$eSZ$e`(}f*c-Bn$ z@aK}JN$=$fv>=D{b`6?@TG<@g0x_21R2BU+n7tb%{L>EJOvVekD)@1pU8e6IA6}a( zI0{e)iRM+3&Ks7Bg9M=Ej~a$h|B}sg4>(9$XxSESthCN)4m|N;vMxHCO@O*!guq(E z?~Ht-98)xJe1KAN6A*@*XuqW>A|DwT&nfbL!!vIIbl_&J>8K_n5!J>(ng0L;4R&lY z!Zk`4`#s4-+(!xH1*-Ir>|zFo3Y9=7|7He%+!FJ$mOZ2|VCX@2yxex`JEY;9Rya^( z6C||On|6oI5k%aOJUTl4o^Xff*NE{SC6C2)y0hI7U7g}1>;`*ko1Jg3PQp=yJhCdE zurG@vp?Ga-npYH=+5eW5ugFV-dw2+={r2SU#i<&l;hsIQV55+T&(7j`jB-kKUPuPjO<_Z6!nANLoHi@K~*m;gUNVE>&?=`=K22 z9fNCD-9Xjrqy5XKz(|&k09_c^r6<$&8SE=rw+cERA zy!QXcLP8=@KCS=?J`Nm4X$rJ3J3l*@@L zbk|m{hIFkNFNOV&6W9^Iz%{Z`2<3h3n2jly`XgzZVn<*Mts z;{nUR3f|F80tHikkHt;$=N}1s=37L@K1#i#o!j10*yHQ9$6r`@Ocm6ksg&*Rv-vGq zQHhh(71A%`C6OH1aL9q++hc^C8=V?!7C#YyT_e8x#I+2AI7H8(nl;0?+eJs`yRCi* z{|CrxW{Ojr95p%4HcP73zI!jHm*OVhuWa-1g}frvdfU}((8twvf^Ik)(~YP^DQBe^ zr&;tQGWT@9XHdhn$O7>R@Wn_njnbaiCL&0*wN5b8!NHu9`uMC6^>T;(A30@p9*oKK z9oq1I=yL!$v@Cv*OJ-aM#JYgC8^7cyyGa?RbswrxRrJq!Cc543Z%2ig|6lQN+8M)^PH}U&^sOr;=m4fsD zQ^Y(kr9^gx`hFInc99f+R&tQK+?cuwyX_yVGU@dY#`>t|#MhYj{}Q1e510c=G8`tc zF3KH1{Q%W|+Ce_~1Fkk~6;^3P!GU^TGkk(>-GHR@r;r-vI!9#y^Sup91mDKCnk^(y ze{JM&tP3SHu%@1oXgQ-Y?rH`SnI;9ssmIs9`+oQ=OU@hLw}MEqk#)A0Y~o^ec&wf2_PjvmfEl3*w2FTlLtAV8@(P z(rA8&bvMN92DTO-EGOQgM3Xltx&Y8U8>-4u2$st_DYoWd_tgd^sG3jp$3s7(p;6Hf zG5HFyNBj@sx(NWQC<@O5TR|UJoBsfPmfgB(CU%+wSgDvPFQPM3^%;)4YJ*d@lZWp} zss4b;eqH96q*LzDTi9YA2~qwVjMk?hz{Fa|&;v1Gi1WtXm-$2XZ*Z0xoR;iFm8tce z_?zZ--d}LA6QqQnT|`SLXI$_aEKgwbSkPSZq_hYUP&c5qko+|T-m}crN!SgONP`Y@ zZ5=B-zIqxAaSp`YT}V7AX4TWc6S@1PB(Mew%4I3b}*P8R)5BWWNr#-|(IcZ@Ox`;h-h9VBH zEhi*&qD=P|G8tqS^Ex)Sjg6~3tfAgWfrX`kpXP=GBe-i#zF#Qg(SfGCYat8k$F0m# z8U|bH#i_i*v1;n%A$39n_-_~_viT~%mEZKSKSFlp#tL_W=+k{`m(oEy7PBUMt`@BI zIQ-m*Sz*@t7VE+!d|(W)FOia(^iCU2r>bJ`i<)oQF@A%SS8~axe5S{IGleNcDwe*~ z2w3X?C=-2x+{wG#tS_9e#{h<#$MRMG74mSjJf2`gRAdRP($~E)$I=RThsJXR(L839 zd3tD2d<^VgqOv-qqrc~&@=KA|ST&+TLCF!NJV`%jS+tWe)r5BWO6Coo2PqA@@S%$v zTi8q!>S~;ig{#j8M@k3GFLI$LvF=;VdKhvzZQt z*SPle6Pg)(nG(d#n9aVr^GE@?D4i&v0osTL=MoJxJ5zjkzdhHQtUQo)Q8aEnB@Ssn zJK*YCXx4u6&NeWI!fds|Luz!lOT(E6(18A6W7efi&2Wkx(l?iv$+^n662i}d$%lEg3hH8mw;X>USf zo^{oa;>=Jh5DMGHLJzfhQ2m7K>zk>Us{EXV1tjH3+vZCIz`YLG~f1r zV^G+k+HP4vpk88fE?&|l`W3fl&-{J&y9KqFY8l|_Ss~xSg<;_9X8FKqE@;3XxOjQ# zQ^A0f9BlsZTy4^Qy$tBkn!4OLr|?L7enZ0nK#OVe@_^}%YnUqwSkW<6MT7*QV#g-( zW*JdcTuiubN02qiHlB`(ZeEeG$?K9|{@nk<05XZGXEI)im6TRZ7+04aP9|J@`jWhl zUuykzOS1Lyy~k}uFs3a3cbsY%5K$Os1j9v>^^?tB64FMfqRw*aQUeNwdM6Hv_4E;H zypHN26p5f5iI6}jk7LN<_ctUf?NqaObz0Xz1LBCI?^FRLP_UVgahmqkbTm^W^dD|V z#_x6*PwO@1~n3Er0LHqF_$mw(re`)Ccn4? z0;zv0D0?W&7qI)IPy`hn?;j_6p!R4+NG|67W>RbIXq@p_k$q7(#{9l#qj$d5E)m+ttYj)StP8dB9Ie6*9bYs+V+5+QBBz?E6}C&KffgP0dR5KIV-onex|`jVSF2%g(#{JiN+ZC1&3$ zSBOIMQvw7zr-Ln?l^hEFLFw{$y3d|Zy5PLSIB@g^4M%e`WY~9c2;M>`hOWRc ztb=kscT)@nX)EazqPPlS$UZoA;cJtUIE3c2BQ@sdee>du(FBQMb=*VD&nHU>abT3P z9AN<%g2}Z3bQcOK-^Q|HLibrTp{yl!Yg#S~(NrBjgbHsA+Z25gDuP67@@Ai+4NK(t zg;5vchq?~$_&=Sdn{eXSxT9I}Y?M^jB+_h&5l;|ql_ep}_ruAbv$)w06)kRke11b0 z>5eRWT2K8&=)Q33N4PQN&mrCR*^GsL-J}>NFHEmC85NV6KCMD#6m9&R*D0!ePFm!s z!{1=Z-4*oAf)Emo7;a#9e}vhfqYtP%!sx(0kGGX-A8g3cxWQ1b>kgn_Qp-d{EP)Q9 z6ghCM3DH(oBJ|ZEJ7GZO6>;fKvmVCoy-9Rp+EudDosc89O{u$!6pKD3 z!-Dn@sm3uyf1*9;=FX!+<)*gFv#Gix*q3WJ;w;_X+R2THbM38o@VWT1z(t0y;6KZ* zKl31$#h05OBXavXtM5f3w4sBFFT(<-)HyMd9mUXx%)XO7cHI*6(UH zp#<+UBi@TL{S|TRlQkk%B;Ynbsmk}IG)u7xL|=G_tNGRp61*k}ud@KJ=CkmI=Uaiw z3AKGnmRI?9&Ix{BZgK5hfr#u0=SxYanm~$oy{KZPHXEH}g;U%SAI;NuN%U3~jpCSU zw^>)6I1{>t(;Q~y_YV+zE*_{f=Yqjde1)J{rCnx{xEi7?D$=rP&!;Z^@#IHUxZ!6_ z;@Al!FIiszwD{1Y%0q9g>~ktD;kwmK_OO$JyWheLbX&;n&aW67N7=;?( zX)0KQ+QUa^BYUsunAA@7d7-cUTgof1{5p8UPqeAZAGD9co*-A9&T`D3pCklEkRkzF zwPAzv3}G6>!@rIE11hch4i)6%42{20ZdMeiuPv`rmA;y-O6UWVBqHYH(mYgy4!N4? z@J3Z}*Ek!3mVJCx!cXdAJS8^g1XX6qo>`0LK!f>r%3Sd-%9q9O9B`__Pr zXN?rfVFE=4_FWgP@#H(;cS5RLfcPOUb8LD$@<{&);^{-Ow|4l<6II?$eKeD2JkE~E z&Pa&=md_(i*9ckH+cDZ8r|d20`^qaAxkK=duQ7?bgXg_zq-ZRzV2y+~>LSd$=@$Um zara>KE#1-6Wg@%GNRN&YD1}h?iUf^8C>;=^b8#l6qLy4w`@k!c7|)WzGQQISHYdkL z#YeS{`zt_BqTO5BWk9{B8hCiRP37K;u?K;8C)f8Z{7!4FG$I|!bsM>AS!rVmLn7b@ zz4iE)^i~tKiaSJ(zxv5<7Y<_5(UsHG=uc5B_^yt%&O5e!d$hwJ&AXv&-t%XEF3vLh&g+wyn_1u}j-eSMzDs=0+VJfcor5S} zr%l2_$77TI8Xyq(1X+d1q_G+=8$M(XwtIrGe-8$)Xad_+^EwXHM!amLx%DudLb1g$ zM6Oo)Lq+?P9!?9265pu&4_^}W)WqSkHb8mzZ^WxH%BXVSoonZ=^V|Ff!-hbRZ%0Sbnxk^mXjaMJi5(twBM2duLttLrp?4=w4&Visn5`^Ah|_HvgcV?Z#DjjKElPD1iY&Jab;B*)gsa-(}@LNT>QUCP>N1i%!NC?Z4ZT zqMz4#aWykZd#XoL4|Dy2r+;96%fn`-?J}O@k7X2)>R5E^ayXgFOq8>#<;j!ZKsVc$ zQq|8G(7bmaEf7D4HhE&o9+zOe3lWaU{JWF*neuO`yqWQwR;Sz27NM=DMIzD>g2`_u zs;;r{1G#=ZGlDzDKM|+NGBl`MI6YAGnF?X@u9{?x*|nMNNWpYXzYj?4br@j^2!VQf zbuVquR-D8ZRlVUl@x9rTgtPI{M+nmIb+I<)39#AAYQw0a)Z_+iOU;^>mZIYG9Pl)^FYg|H*xL8*ciMMWeA@1zLY6Yd;az&OX+4p4h>z(t?ZJ6c~|gGl9()EDRq8 zLasK9WGxLHHogyAN357L3w{ZP*m-fUNV{7UdioVo2ge~$^?~wc(xW=AKYX+S-)j-8 zp?SJ=Iu;N^ZzemUNz};CXt4ra^|lL}s-JUYYRjkUzUh|`DzArUPo?W0Zd@bNB?cD! zxCr~wKYou~ROZ7QU~(_ZNMYF48;o=nk7A7qH89tVd2$HeBoWj#$XD)_IHH2U3^rF| zSG=)SWGDO^57p;M-WOjgp+9?cNlJln9Xww~Mub4^YcR#uDD|@>ar(oEu;)dw?WSy z*n1>taP}HgtuiZ^Y1+&)u!q(EFQv=q@xn>M=UNJfenpTrSy~$PH{GF4&E zSJB0lpFfIJ!tTpk@*N2YAHOgZ?zjMly*~!<6wK2WrCam4ouK{uIK-%QB|?OfE-Xph z*NR`*57^)@lP|}wi}?z z&VR)MPY|;9_em3&)=AAvDK#y^n>i)J!S}e}3RgJw_UONY%+zU5j%L-;(YvhKV}pjZ zyIu|1KB9pKw4ehFb~*o%sOjv&CseP^>MM{9_P*Pf0`UP=DzjXuOC&ZO-S~M({Kq=E z!d>m%_i?AsGbfB`txz7iFn$%vQgU$xx7mLH@2RgJRP74e=$=Ipz(y!BP^e7qha>k^PkwXU?HJfh_VPMFmheI zsm}#Kry^DtphKK(7M>BQ$Li~@ZPL?NKemKjlyRN1z4L75KcsmYgLZQ}$Xsi$E?vlb zUH|!YZ;(ynI65(42I3@tAZ+WdhovhD#MVuaMRLPn<~J>^1ITmm)}%=e*e?VMr7p!8 z+X}ZxOJ}?KpEeCOIXQlx9}PY?Ol6bu`c4}W98~$FE&OZJ!i4cs1U!Dpe^hPGf4{c3 z(WB2;_RA+Mjeqi7wd4d&id!dBlr_gATG=fecZmr3tpDT9ngc&D5A$^gjwRalZe68< zwfbH522N#}<+p}IoYpi+SZ?;l=pDq5j@FU-jA~JcI*oL6x)2>cMOq150L)W1hj8EXxf0 zW57Pk$8)mK^SF4Bkt4XbC+PI0OFfves@z3GlwM8EqY!uL3z>l{+%-IDcJHLtBF^E1jhGzQ{ znN~uvjYzkpW?QYWIY)?G(wTR-R;WKGm9)~ky|qPh&?@zbRr#e>_5fUY#P}lTK5}%p zQwvd7`P`I(SR^#m#V8^7`Z5zs$7mZh6wLN$HNbVvC=0G}nXrM0AYh!*M9d429d z>Fs@xvBHXvQcskC7V{>V$FY6pVn~#^SiIqt)`%>dB!C@FBRUc4NtSh-GSxi8CwU{O z_w2u7Bps%bToy!7RNeOPqw?)zuR3z@Be7>vOurVjR#q820V+5%;4jNALItK>u^aNv zQ$dw)>7F{ENK7v=e^Xh9x^hyD^_HgtFK2VK*|&MH^8Ab2WFE<)d~yY6_O&(2(zS?7 zh>_pa@LWyg)y;%-C0*y$zgf|lp)>*sQ4GD@I20RRL~95lQ-O5{LaXU(wTrroOLf77 z9HzjS(l{}3mIYr`o~oV4lg83M)A0*(dEYnCi<2nmdhpBJoP~rGz!x$%9lw~|efanv zjnM_KZhIHB+dDq}%*9H&*mzrIa!}bZl~t4IC4AT_vx$(Dy$E4?$03ORc#4p7PT(bm zJO7#?T627UJCux^>%hEs=O@|!@2NtyEJ6Lz#mQxrY&PAv!SFJ~(AqSP*rWFJiz@XM z(LsMpnsxU1(~hm$#J+AHcZzdyiIp+q&EZdX-5L=Q!DnJAJ8HsPb2yrlLf+uK}I ze=bZ-5M9JuBLtq-eIwpNNRe7oD@k6%N{%?>=x8lIz{%Gz9-+6n3wZfZ4{fHD>ThrQ zn(AT<*1I2rE@%bsZQbW%1L$)rQkgCFQao^EPkn|w!>mlzFkky z?EvkflOwZL;>s8S!Bc+m2S8o8zJT39UqJkE3 zQYfxuGaltmaJTc-ZkGMQ%c80ZvrLpvevpHy&W-oBWK<4S^+C*b9WpcZx=r6~t$HP# z@BKA1aN2WPWnST3sH!DzrwzW2?8@UpY^}dyv|wUDI=A-TsmgmY!51m*L*PeMD* zs{MZeRfR-z-i$KiE^Gs#D@f!MghPHY&{pP1;BWAOO5)%AyuvGXMNuIFOY);F74~#T zbV0)ktb?wh0d_FGg2b|rSfX`WkE0Rx?X^7RV2=43c^}rq?^mP&)A#U&i9+bz^=P2Y z`>f$qg&Fl99)u{0o{rRq+a!XEn#8XCImZHt>eh>5{8o=_E>~gu0ZCW$aFr-lY{20=~CDAo|=w5S(Mprftcb_8lY;5ySDET_ekFc1^ zW%}@u0GFw?HcxLbzd37&n$Ddj3mJLqF4jOaeWvh|F|Qy+yesnX#n5p9!YOWebT~Y= zL@_RIP=n`Nev#*)oRx#OFfF`ZF!LEqfKLo=_YUSIIyka(Z&-)MJ0ozVhUjrba7~21cfB z5B61U7ZB|z0W`xGTkCvfTEhWx#6)Iq4IwcfvpKEDYkd?*pbS(*gIc~Npw z`C-QE)lRw84M^A=&bN!}OjY@Y+UE_ZtnDVmGcayG_9QcjmSJY+VOD9QoK-;S(|HlQ zAdA5(X^^~6D?fKI?WV|SH27? zh_R{|uhcMKrmlFZT;;6(5=rF{iJ~%5$mFe%7>QLx*OQDG|9wKinqTdcZH*$Lb|sCh z1XCgc-Vo^nafUT)O@OC?ha!h~6GstqvrkGc^?jV%b;lyx^E%AZBW&mQFW)2Km}>$l zt!~FmU`PLBxe30Lw3Q?MDwlk(>W{$*(|`(5*!$@+yUyyk{{YJ=b?Ns(KcNh|gdxMd zONsff+`1AUky#KW6w%H;&h*(}K!9nte8UA%$~nl6sQTy|k|t>`0}oq&6UOJx|LWQw zJyw)^{FzW?Ou%#ntYFl#eRG3fwxiokrcwJnfQnA2XH7}`-ZhS~T#T1v)w(Km?PIh| z!E;@F4I(fPe}P@z*1_}bl?qw zL;|I<;aVU68!Se?pUtx(d`?-hl5!nTD7y#PamTV`Dbv&FYuga2^yaCOSw7aAU=ooB zT;#OeAeagc+_1x|K&!5%-d1bAQ4J&aOU@PdcCV;CcM{tKmPDXgogp@)15tB!T*}Pu z_AdT236?NJdj0NOeVRrrizt<`;yd9sqMW!>v2GeTRz2nfJ&o4+do!OJBiO&Dr0@gIY-jWv7Z9icwrk}FsPrsG7H?V%fb$=%H7FOB6q(hAlpuZA%MhL^)Y>X!ICz#qw5jzFI z&)JHA(P%PtVOl5I*?RmT0a4fGYN|R(td(Z)_7qeuwGFAQ|06_J&-@o+v+3haU$dtrbvx7T$p+qzOlV;m`X~}pRo-Sk_d_{ zv$|s~+|V(7EKucoiZ<$T*0M5-+2c&zu)gJy{~Wl>QwSfiDKb*Ky!>sSr0urUUHIee zyJ4PYpZ#vijG~UAl({uuIF8d4^Ma%hh^h^@h*R z)`0cZ?TcjNH||$Neq?P@LC3FbjE*9PT|yzsTuOW0cLnQp4&A(o@YlHZ}E+t!yms#?9fx%HOGUCxj4J zTnmntD#{rvY<*~L3I5oNc3EmJZ12p8gA}ZU*bKAdjw{bdvR!qA)iB!!0p4YAL`;pG zv=zIST`>{SGo)Rt=U`>7%&^%=>1qgx{iG<)D;}Ga4=d29M?MV%#5Gs?xPwMi&e*I7 zd(vgD(j_YY5L_u<&iS5d2#tzqUNV5{&)`SkGL$9f!qDllo%8T9Ph>@_J4N5o`vbcC zj*Y40%v)~G_oAw+vci8L&YRxSR4!}n_ogYb@{N~LW!r+>j~UbYPasi9O%wh#X+l#U@v z=PkWvEr{wGzmR(EVFUHM%828mMEALVj;}~Ko+ju>l0C{*nA|p3Up7avNU42WY|qc# z_*3ZIne95sm}OA4^}R5p#SO8+^4qZPl}fhZAo!kM!5@ed_|c@6a^q*q-*ZNtjvpI* z)kp#wB9m15fQup4B@j(U`9{?+*;DJ7?N`YW4bIYz^q_Gqz-x8mNLJZg3P^lE>6oe{ z=Rhm`x+Z?!XVkdh?{7mAO|@}T+kXJbve}NmI0>wsUaE@nXY!52LEXad#$@_4O*GQ^ zi6nGAM&>O{Q*Ms*i7JY3jeJD&AHY+&=#m7NH8}N=?Ap8T6%7iJ0zTL$QXB6mPP6p7 zoh7Vno}CW`EboCLLjwI*>7=c*bBSKO&P^_FC~_iH-9DOrw|<*d2gtKC@nlEvXli^$ z#h%^9#Z9Xf#Z4%+3>x$FX@)uyvPE(XHVy%eBG>Sovn}&gbdg?}NF)2vwrl9dpbi+b zSd;x)efnc!Snw?gD{gbH(Z05RvV~H*LKe~cOUoUfptO&2B!0V^`<%O&mFIY18Dv_X z9p#yN4cEZG41mMh_B8WO^Ie@zQZ?iepq@R3C`GO-FO7%Ghdp?0e>J;8nhVV{EU>*_ zQr4m93JVJIXfTzTwg%fj%=w>~MEM*Cz<=0Xt)SBuRy(-(){-X!Zsb247`d-jt#oc& zmFpX(SQ@_m+t{p0_-e;)(Kp_ElkC{UYVk3X@Rx?dR6Np~uQEF5xYwc|lWDg1Acr2D)J4|^}?re-Rq)2x@ro$JO$K!s3Kr|6N zH-bT;K-XFrvmgfW{#t{(RN=t;e{QcLzYc1`~CyJqUR_@ zzzzMdfsJ(-4>S2B+Zq0YBUQ=O^^k*uzC{_5fx57eTs+hU+Pg7U$U2c^y_xa`IH{uC zZXpRY1P9AL7y94Mjf=O$-IybZ;S5g@LF{;GX5Otg5rv=1t%J%wMKFZfq?9rDmA$5J zB=-D%6i!@n$y6}!Nfz+w##tDI2tf}s(w#Cu&wxFIY&+He04)-&>DrDx=g-77>?zl$ z1rftX@dR>}%ldYWg1n@H(E|U*5l7PKme&PZ`PYW3hRb&9T}Os6Kk$tf>jfpoe%J+P zittAT;ab1BwmrCNwp}3JEzClK?(HN)M(__stFptzE%i`Mlu1JM0Ea4)1{nnvF{x-5 z%$G~OKjrkVL=ar{Qs8`~1f&~C_W507lRgry~ zY&5Re{M2-VnPI-=l8fADK0)0w&e4%$8(_1+=`8Y7g{AISwl+O6NQA9SR%nmHCTQ3j zNNTk;q1y}2NSm&p%b*C@=7byzAUluOgzwpudsL>AwFJ}ym7b9pU3w@^&^zEcnl2Nbc(KNrPSzoHSe8G}BvCte0gVF#b=L?}@z0dS&ytd%%kd_AjDEY<;LgHbKB0;n~f=kk;jKBWz*j@0G ztzy|dZ4g8OCg<$xF!YK7n57OzgQ|Sm`FEY{`$+2{x-C25tuAjkR@-nEbl;LJ zSk=;x8R&Pl6yp%o5z0twiNwM1$p;J!#?UPGYmuYMxjlvAR4jMic@H`l_E+H@(Ze)0j3VaM?i`Kz?V!dK>aE5p) zXO)il?u6hc^hx5p@3yRYOl}-dA5~w8G&yUncCh)Nny>|+Tf3RFxNyNcsA5`?Ht(}> zMWdf6o-Oa*4GzEh{01Lyf!>sQ>05*G9MuJTI*htb&UD}6QPXuQB}wao5Cj!m%(Knr zT-q>VwB_!IG);Z1egEyxRPy?Or_FAm*C?1+h7N_I$jKxzS)!|2cm~>iajx z>p<$c-c>cZz|8**%LY?uUC>XTGZh!mYCbLx*8YKCF>%01Rmna=n=;2-mPsWaC^b_Q zvb>;0o?mF(eEo!KaXv}AB6RejL{+5rE7=QQOY=R1|eX0f6 z&k_w1a+e?E_4Kn?yz6R7pPocrc<_pIwwNhFqe-~9#XV1xy757m+OXLw0vh=<#dZ%X z(GBmfQsVGp6^jRj2_&{oJYIHj$=VO^r8~t~ua&1z&$6qIPO{qfjm6!P;yZ1ylm#~R zCYHaC%d6%q9)a4@VQV*!u)5TJV^g_e+g^n)8meG|%K(~=SYo8B#cF(Q2lb0}N^g4s z%KocIjuKvU*>RWLb4yZ>nxPX&==X_nLxP1>ROxb)+d-0)O-FSnJq#i-rCc)Yi=3bj zfZ5=)RXw;q6X84@b?L!l{MoI^2^oxL?t#9$_Vb=)UGF%lE%0w*+sh|5sg0fq?|g6M z@k^{S1>W0Et33vZZ850B$3XKMGFEF%GIlpKlaF-rnZ?ZiydDZz87FuFAPlu#bd%{~ zFU+H3^HIOe1jbg&j#PMHBo z`8GZ00DS{SER~Iuoe`jv1Q&a^`&U$L-DH?zO91uPs^_c^yB#wXda~rdY5WK1Q1MLH zQ3nVwtyd^mu5;*ZhP=Xx$vrGykBdz-dAPaOV)dxd26!manCmCoE2hjN=rjPa&y+_B zK!b%e<3_zY@kEw>a}*+1riIGfbkIyN`_KL_dc>C=5i@4kd|B0~q5gVx$aH0>!3X~C zswmlPgDRAE_yj>rzLy{nj0>J5YBEO?japp(1CUvU*#WnF9CM(11aVp>cmDf(Viubj zU6!wR9j!|dk{n@T$N_~|PNYl7;`STA1H0`sdUy7fn@l1h>Mk7RxBh$?OueXxR&n>h zNww=yeQYFe8CxMcy3Qr@Q#=f$u7NhFm*NLT$jKo#3tdjwH2=l701D(PmVt3Qd*Ey)M>tfE?%!=mqxQKJZXdi z<6E`9Gg>-KZB5j%kbRG=UGPK{j=D#$(~po&kC8( zC5X9>3a75!J)2BMlrbAIS5RjnpS+l?_tKB0}oM`2vAgDK^Z%uH8P_@PFFaE z*E|oFVu`V004+{-)3Xg^?{z(Xi}M z1J_aJ(8KNr2mNjpozMSD&;q^{2!7n38Xh<5FHf3yL;*CFh*7{dA0_prK`Zoxb+K%s zC_2H%o8~@_4+G?bCP*$)$kU;7yB;Dw!^8OpX^=LKIO$v%oMy|<`!`j(ZgL+A@?|D$ z6&20STiDQPe;|a0aDaZtYs)KOXG=DJxpTNaTbADsA52arD9{8hR=K%C0-gAOjtEDG z^x*1Pd$RJ~o_w5@&F(rW`q_1c^$)!@`_w-3!q884`t3cEm%2goV#HWwMbUZX%v8j# z?H$_>>OwU}n8Yye`EPu>G@u}EqCAWKye4cs$O{exC3sHSn}%5wx7G_4E8Le5TIz8V ze{b}SETa8t&Ft?F)po7eQv7_y?Bx+v@^-#G_F(9Ct!;_}V{liDPO8UtjkSr1S4ocl z+i)}X);)kzS$zQ9C_D_3>Y<{BKkW=CG4pm!2ZQ6T;lG7H>MrGcvUR<4`V_rtsHM|w zl>DV&^I;N@p4<3>l=&Y({P3FUH>xc{1w*C0uqWBG%m-%L7XTvHho|`m?=es8qbC$1 z!JWHrx&xXCrC0$CX$d}dP(|a!*Q+TlKlqr1>-p`Nz-ccJ@V=sf-=WQBDgi*JFUfES z0~zoOWtElT(Dcprbd_<&)y&RFrg}cF(*(7xOh>J6<;|qFECnZwqE;)u(-An%LyWNM z;+w-?+3;#OVvEg)c9U&(r&$vY62w-7LTv5(cvZ{izqkQhHCcZOl^pn;=XZ>!syv?+Sd2oO6{&dCRXR$-1voG6STs8i8HA zW`I<*^8{P^Qosk5H zvvBq8Wwqpyvvx+|?t24*=`?PyjT3?ycRo-y`OCAGd;p~ipcLtQj>_jz03OvIukz%_ zhCud&v_G}RKGPo8kD-+V?On`nOVmr5hF%tQj6D8}Z?K9=l?0lE8g#eFTAfnm4rl-1 z=$LHs^L}(iE;h63HhN|06495NqRDSmY&L$t6H?&8cNixxVa531P%iSduK36Z^|&L-Muv& zHHTa$8O_TtE0i{RF^PkdSJx&fR$@}ZogEpTW}fN|C=xZ4OmRnht=mU_eda&@;4AC})i?F&DU)Y#~@q(CLX79Tk4 z9r~q5-<=37IcFsjmBU$<&PNQ+Ku0v?TLO1#yh3cFR1o^6G7R_6NbeF1T8Cwsk7eii zN_{FLKMY~#fy3fjj(lO$A^{3YQKU9Iv*`^eEzs?g8Wvw!s2akeak8iG@#vmnOg6)w zDQviqBH!I%@L4M zoUStoFa2mLjGz3JKO$s7hw>}xw5pXNXlKiuc6dKNW1 zk2t9Fve}IZg8-uMN8rIJi%5GB*uw&ekb~ScAtn1GVXeU0IC7b=h$aoqGZu>$n8=`u zVbCGeIw-(ZLy>?Edwtg=m~6j}h2I9XN1~t#s<9H8p3i@hLYGCfy;fz%3gA{hp`%e0 zo9>>vxGA=Ci#L2R;zJ!mo`H#7w`8OtHzQ>Ee!d+H3MdkoQIt>2QVjvbPOWL>i}JbO zFMybayK7C-0{eVXoQOrnn#2?e;1OCPF-ptqgl6Qi1b$c%GEQ9; zrC~v}-K{OC6zYx|6mZG+x1tHUSE9?=I(|$1(N;sqfOSwq!JUhWv}ffmo*t=m1)q7l zU5YwpOKOOdZF`mM$%G=i@$g0J`AnoLs{>n|dw_jhYyNvBqr`@YAZCvadl?Oloh0fB z$p}tZ;33P4n7&ErVo^)s*D;0v(<=nNJLaBYUA=-3<0fv7eR=`GfTH~~3#0z#2<%bi zs>)UE?8{<)!Hw8NAul|kc8vA`%t*_p^~VBWm)A8_RpZT=(mgrNwc(90zHONfn{q%` zj5+>mT!(>}y2{HcriUU66js@pI_abr4c%nhD43_={#FpUkcX#Ux&+57Z!dKD8p*j& zeQw0zXGh(X{V+eNgbYY3H&7Us{~upW2%l7&)nt9rOUB{Rxj)H%=R_Fw2 zmn!kuZZZ0YDP zCLxz8mBHC{BFH70S+9P=M54E~Lkt?|iKZSTTI)VC0%lY_{tW48V0~_~7{cuORWIL! z5B@z%^|_qfq{q(!ba}0vX{B3*2xeDy3FLfav;LZ-E!hm5+2cqy5E8m^Jx&U9|i z7M72_<*}M~IXkcY6>&rRFr&o@Qq7~A|9YmU8=Tz&m38SC{|n;qUl^@udJ{e$JkSS& zvW)Smy&#KNi>xEAgS6?b#|29xl9k2H&;@U>X){?Cbo4KqHi)Lp7{#jN+M%-gGdW0smx0BQj*inTgqG)PZCr85`GGRY zC<=VlgvkOp;3fl`jg109GE!HfulDwsg@qi{Kg`cn7!FaJQ6=}mtlcCGx z7!%Kkuz+5S2M0gCpdlwh#d++i3#n2VU!rp{%9R>64LhBddCBwgnn*7;hK9*^gYHKZtl>VY;vGX1L}B zFUgOp@K&wUj?gB%ggTRYntS+bt}P!YB-oc05RUCZHf8!dN3sc1I&S6d%qId4C1zd| zSKXTd*6@B1aw8#}G>`>!^-?jD_~pTOQ*sWygO=lVNsNiTtOScfkreq_9fbJI@t&wi zgd%fK-D#@e@YkF0_X}z1{_j3V%eGF=)VgK=&I}l9=q&39=#B=K$-ccJLARYsty`84 z0G4i{;hmN>%|t|Rc@tS{YnqZkJ{7lrANT@{2+T0eUigKgE_Z<$*vWwfbi+)U8lfgo zH|j&>1l+%NVKX~`2Pb6Gxf}i=OWRtC_eE92uJhA<<518v<~qM zNGfg@f5bu6z~l%CllO{VNpe)v#T_5#a;eiE{{U<;aA8&cr zWJ?WU5~{{4GLG)EQh>o%648XbOiLiVzz9ouTGtmqN9 zsM)+g;bq>Trm!yaF2DoKxzfGWK?JLvX7wrY?Uz`rc2sl{soZ3sYFlju%+AILWwivf z@P@jV*~AnrR@cl_#u%g6neskmjU0Bx45t`PL8Za%F9waW!_;v3AyIb77}RoKUTfk4 zmWxk-H<#@VzZpP16~D~yJy>!me$tE+xI^H8Od_mMjbVOZIDUaQ%viH5rvS~hVBo%Y zH!!NmAT%l*Sr&;<7!R74V|4n3l;^2J#-BY!?f8agvRw_!IlTCa1%n}Et(XYzYzxRn zU8~$pqG0>YD$e7OMr^O{6Dx7KLZhVfsLT|~uf%9yj^{G-`-s2X1r%RUvkHpAl|xiV z7^Y;k_?3qk?l+OQ>HyRO``i#lQe~=h@d#2{%#|=PNJke;d2RWMvZ+O_4S~lQhP+vc zGu!wjvLI{O`OSyK3DP=Tv`Uo9^ZuebEm`;f094N5tavXjIGYy*T(F%u2w8wkrg2^_ z0@+wI#K|Av@8J03Ei+PY6u4)lEz< z!VPUyWz9!ms?|V87j^sn#g$f+HmQgZF}swurcMY_*6&Ozn?B$I?)`3I71qWfC?mz* zC0lnxsPuvH2Z=t>B{1wT%i*U7a^Y2P23XP^Gc~YH2p(o!D_bQam5Ex_5!I2qw^3Ub z2b$b#Xw(>TTqc3|ltk3G%XyhY9bSGTvQFxtd2{Xn1RoO9)vL%mSOREQUe9k478Tw+ z#?=eJu(+w99Whw>fi^mq<6}uvelfW~jDEWrWm-1H-O|C#w;qP#9?z0NL z&@R6sC{k;gou!=o#Y&V{nR382 zALcc3EF0cGeMCbGd!Y*;cuVbN0k~$mY?<8Eq%of{wU9bss%oE5S!JN$6apz=BWjW5 z`enTRp@IfQ&e)fVbJRmP+%_)!Ooo$d9rBi1vVk zMS~vY;^bBu$+w6gc14WB>P6D(EY-j;p}qS50BSm=yJGl>#X5i(Ri)xBOLXFziUnUa z)Eo3sbnz*o&e_Nz?g}a#tOAn9d4)ol9lMH!M7&J`9Mt5SbQLXi1O27(n4pS);ZD+N6{v|rvhSpe$j`I~QR@a$Y zg%!Y&Ay?T?a1lz%5Z|a&V;}wf#cZJmFv6(}S@81>#_ha>!v{9qx_EvXejza6FJWl# z%a@8;h~SSLOPBB&ZHuoF$-YTbTwb0Tm8#-cm>a#tvvpWbVM~Jer_8G83$~y_Ta1t{ znXSSMa-R{{Q^D?8y>kJK8k9{f!COoB;wnnLd10`!opUQ-w3L}+aREz?K4OZ{_TmIs zSXLt)tJ(yVHqFD}2Q?JwUN2DC1^q^bZ2sWDConX#E0PceS*jwCsI9XB1;;RNF#wD* z;3A7$_H`8MiDndhY6Mn((@Sm_q2Zi`XDB+Q>_Yxp3ki@_a7vgQMZ`_O?geTs%M7yy zD5Wx%V%1?L>@ecD_NHLCP!BD)2m)Vlnv&IFBqT7Ya^mr?H}3wXf^{xx>!KOXy`c4} zYz!v};_%}-rB?BWY}=WGQzS{yXsk$SFnJ;d_)qx zuA&y3>Y|jTV6IS?(yY|6Wn`$Cv+XpBzT;VVgLpG6EpFxem5%cT_!uo0^A;+}VBU~I z!e)h*RlaTE{KV)uWM23s@*ux#HBWk+HpLCpFjjQ#KY8jag8VS~)y&Cj;h9BW#LM)j z5s2ScnDTU2+Y>PrYOje;x>JZ(n3s)?ArhR9B`(aSi?qbpS7OYh5+;GQU*$2ZSic?4 z1HbArl-mx;d`hT%3v0$ouQM}86P&~zQDVZFe((vQqAkt7Kr;~T=9a+DE-GThOpHDc z*i2iq`k!ll&_|)pWtmx6C4n-mtzvGixrHuYw8X4mBxui4tIi;+9^`b605*4f zmKCV;h`F0B%^EpFL5XS<i!dp)B?vne8#9S6vW*(`CxXOnfDgLFMz6mTv2+= z@*scqW?E3rVGTIFuo`mRJ;wku6`Riz)KMDs0;@H831!;0xF`j7xaP|=QN*QKQ_Mx( zRc0}4g;n^7qGtEzS}Vq}D1|9snQRnL-NujkGqBI`D2a06fmC}hRJ2bHcLE%++Rq|E0nvB)m~%O)mIhF$ZG1EqxUKjTiuB(8mqrV<`;#TxrflQXs`+@+7se>3`Ck6?U z+|(-qk1cpS>JR~P);r_nn}z3@$mYDo0{0ZP)t)0ocYTcAqOJ<_cFYLo$k?p^01@cC zVl1vb6C-xY0l&y6O zt6ll#V5srpb4ogxXm3#AS8g-7O7U}uYU$lT2NH#c$t%Alv-3Gfi#kUrv^nk1^A;Nm z)LzMEkBR+#;kOyw*0qeq46#+>Z3U{K`F9;a&{>P71W4rHdz5X3`w(n3ajA8=Q1O~8 zyaxQt1e?XYgEbiTredE=#&H*AWDP<#W>G*?1G-h>?uAw>Jo6Ql*tXrwVE!UfR(ZZ7 zYc1Ab7n0Twa7Ed*uB9~!G{JTUIXuC>6U0WU>FH-moi~o4Y@zYFmV#d*FPVXeDYuP5 z`P{b(H8n*FtV3YrY2M+gQO!gZZuypluNaj9k>EIj6m8cLDS2~I(?-ndDrE^^arS{u z*Aeip9WQ3D0tn@p8#@-sS3&)I?3+ne!INu36fb@=9oj>@H>;!MNJy zQ04(D7lRLBpbfEVP*KpZRsGOtG@)XYWH3GqADD_plN=A2_yDxNSN)H|gACh1n;7I7 z%zFpOhufZ0)YMwJ2?`{q+dSEvLA?9&AmSzXE$TUAV=TkwLLc+7r_ z+(MT8*D+fm>|a^wwMOv9rYmN1KgDDcDv7EDmGe=r-^EGlz^{{Y0Y zc#c zQ2+{+i)CsA1;KDSRIr##&m;oYQ8=JxqA+}l^m&38CpjKp#ATT+F77r`zvQ*xS82>c zKjkt}M|D!$b8@3deKEy{xlToc7lXHOQl%auZCaGW;#F<|wWH=fwyV2Qk5Z*<75gA; zox;V8z^73(g$kuW_vo=*y{{S%rJ>&BLxF%okF`7=>9j>3xiw*D;|N3?wer7=S~2P2OH*dZetTLlUj5Y-%k+(n4WYxR%1dFcK74+@Z8OyC>Y%!A1&d1aKj4!Jh z%ZCK0T6{|JP}kA7D5#V*=C$&5?ISa4!steqv*pSUz+Sud&OEYZf|DBV>>64$ZCuD>6dh9cC) z=urv|`j(G&?6+UUO1uNEBc)YwqVN)sg=5~ifb!fRT?vDj`L@6Qz(B<-jlb-~wpjHR zM7qH)6foB$Zm-Qp9)?{5KNf!bh%L7;Xbe7M0-f#(&0^*u<_#7ATjmu)v(%_rywoF$ zm&5K{PyzFA`{o!?sMX^4`Invm1F$jtLnfv|9cA?`$;u*&A=`psy_3rWCz}3#)mVyh znvURN15vcFFbEwVsHnhODb2L>>VNedh*@9UYpC02KhyzcmywNN<0r(j;HP&Rk(ax^ zVuW6K;st?J3L{!q@WH1i^A(I#bDQH+b&}?8+l{RrC6=r&m;j(x7kP;&^F+38f##!s zEdo6b?p%Xy3B&-#j^Lm`e&1)Nzf7j$6;t~j|NfSP`ttSoI1QLR#{=>R>R|>h}twvSltBC4%0Fv1R3*lI0 zzO*rByDgZ@J9%`Dy_K8*&jH>NdEHM&kQ}Zuz_fTSx15vtO zt1_O;+Q$iXYUl1?j>##n4{;VDjeRfiF3yUd5xkHfoh*<_tg@@QWtDCslRqq4SyA%G zOD-Bm#GotZaZn{WF$JeyKF}(Hjbi1|pc-WbZ)_U?w{sDxEY}gx<0a_gHCOz?5mYNs z>ImZwPk4$J5iGATs@5Q3VCv%6h@r1ETNRIGS+FFGrhxHu)H;}?ihI)P{s&zzr-BQkKP=O5w#9yB8Z z!>PxaxWFB~!faaZGt^r7#JxJJEz6@7q3Tv#hQR*-f36!w`VMg&8PGhyaq@oYaYzgA z%&!+Y+(mfNWf#P)0kw4vmoM7}JAu~ig;3JULbrDi{h)Z(pW`re9_msvqeBy6jqRBL zJ1bsbh^ovsYSbuzTwOfND@A-%EYp01S`62BQKg(BVL;X1E+UHA!NjUJek$M%X{}q# zK%&#ja?HAeYl16KMfsG}juuOI4P9s7#LOtw zI)W4fX4!Q~W$`dCF69x7jI}b-n`H}K6?%cRVdhjVhWok5QbJmCRKa#xETY|&9Vk(l z((V`|{{T{hl6gm#(+RWGEkOY2h6P;?#I~9YuHYzfC?Uk4$qKe1)F@!$VU)cyn*cjy zfikr|-RwJ=g2gWYPVQnJsa%KNQQ5qUQp;5X02O3YW>;n6F|a}|Dp=C*{KuiDEem?o z`DYgdCBYBBFoboUM*jdZiy3PAORBu@7X&#HsGFmQ?J3x=52*Z=)67!d1W+==#6QhS z5C}RU-^4>c?=fzbh6m31C^D2N@=!e+^2Gp927;;IYzvsK?94y_H5{PJsG{#@ycm58 z_=;_LS~#03n%%*!bFq!4{6N3ga*(U_6s%Pj8n44?%O+{~zO?A(R!Bv(rn<>|nfwJ;hnSf<)@lvuSp-bQT<@f>GImf&t2&><2 zDiY32yp0sYxZS&3VbeaP%cqG-B$V@|on=lwNZl+3+A52EROE9IxuPS&SxaiN+#(T0 z0+#fh4x{>K4duvnU4@mM^-DSNw=FtVaCi@^>sE-cc>J=H(Q=?khwS znZiA~eLzMukC27RzmhisJ8|Lv%+Hrpys-c`DO*srdN&4_d4Q2{!kN5 zOPcOJtXK;!HbaZxMhN5Xe?nDVW$G=D3w^u(@VLr8u5MTZb{{2dEZs z3@5}x)1sxDP-i-eNQ!eF&)NR~c$cIFVZ`Eu=H<>put%(=FHi-img-xQb6z2A3=8Dfn%tGqQt6amdP~@mc;$mgrQl=M&QQxUp z?hm1HrLnnyA$7j>(=n=8W&~japHPMTk@_OPh>R@lvQ&dq=jKrj6}57lexb94%30=D zXjaK*!>NFnnh8e)3CATL#AVA-w|O4AwxJsljOH43bjph;7Q!tl{6tG>gH<`(isB7A zN&|qwN_i0v78QaB^mAO#1kAx1)G!Vhz~jbcySuqjy$#LHo)z&6Lj?Uqu&WnS8CMNe zRT@0SV+7c3U3h>MtK8)>=3ZE5#MrFenMH8;bfN4$K z9ba=eZhm7_v4$&TsVi*FH)x~aV*c`BD#FVw{37`8vNfepqvSxM?#LG zfi|Bo|14YzI^_b+=VG#q+^X@d|K|%ph>rvc#Eck!{ zII2_(6@9_0j=pA0(!fc6e9Y<_x^WpOFL#+;MK-I#!~oFk6NsTzZReQi*4r#oEGd5j zGdU`c)YaSfE3P8WxSV+|UmFM#<^7aU!`7(1_&?cN;3{sDs3$ z#eD=Bs8|(0kbk(C489J0^{5$T!5z6fsG?-I+jlp#QKDewzAK^P~k@QI1k*S z1Y`&I{{6}_(YBuvVIxf`1_Ei$#xms~RYF%c+%}AyjJ*r(EMaf&1n&>#TolDCrZ5Uy z69`wydy1+ud(5|Hd6Xf^<|7EzTvZqGJr%`q0l-$+IW1CucTBA4IN2F>K+Fzkg$I@*bzAMv?g7<3L&9H3ZIdJ<$P&85diMpR z?zI$*qm#Jld?+q7ETErgh=$xwZHvD3I97!)#*Xy(jVLCSb+X{|5|wG66FqF=TG>#( zMHR^urG^Y`26K!aU^&#-xpxR97Z<6IY)QId2tvg4kv5pZ9XgOHkAbY<5u^3fY*W*Ku3~qd1;I+runFjJoO| zS5d-+nG~=!eZzNHd0+;a7QH@ZGmzZh)OAaiftNXskYkvGPueGVmnU#m@!Z%{E0`E+ z*ecwD{_MHNI3=xa%HN4k1_jahxabSgjmIk6rwkvMM}fd780xqUkVG4E>RohYh6*cu z%R`Xw&UWxWcv&wOsLF;&a7r$c=5z(E?r^X-a6o$Ci~wP=P8oF=4K*27%$4&AE5F2` zPAgLqwi4hrT?>{$4XNaZ#1$yZ9snb5>Nq;W@C2ygLpf9#nQN>}(ok}Fh~P7IEZQ%u zT*@lASQ;m+wk(o=6zhBBd^B@_WJHDFk6#6^PS6uOO?wF+*J{<9k{ zLf9&@n;v4;Qc(3Osw{VlfUq}I5KILMlqD!P=2(Ub=3rNHkCb&wVJT5_AbVP)(6H%_ zd1J4cUd}7i9xIt)8?`ijiD*O5pDgZp!xJN76TH6Vrm2Hrj#eC{qp3nQdYOg5ODbA7 z<^o-Z?nF}A;FQ=XMC?Q;tO{=lBTC$JnaSPE=eRZESmY`qvGX_P zE9Cf>+6?-gFtONtl@g&AThy@_Ji=KHS^offju#TVo>_XbQOA3jeqgUNsW2Tt#YJ3h zP-loD#mvfEu^eG(!MFex+_j<^p|0iRrHZ&#AeQE$*Oi2=f(sZ5^zM}Yp&CCZtpQJ+ z#mXlk=K;#_MgV&}4tOrG54c4Ut{5nZYZB({t|RKVmqTxhjqe=J;7XuLrme+;9dlG`*_@U9Hx?F>rXz#x@3(9&7u6E8*mgRKw(-;$pmm2`s&0 z^AlQH>6o!X5mK;Qx7UzmQN?UBK^2`;Kvv706DV>ea8OG*ocU8;`o3zxyc-CTe zeX{psUS^anolC16kVKsZWt5|B5#FAqkOJGb6sw|9>bE@sTyqRodLflg4B{v&2ksOW zJsXBZG07QWlda4{B5qfDnc5sap}v$z8b(v|s zkg{@dFr^uKOUtQXC*mZx;y(pKgwe^UmZ!uPjZx2;nM`*L(aU5gL!jbiOzvyV`pi!N z#J78SgFzNp4_C|-!ZoLND$MTs+zyJ&rJ(zb^rgf{Mz;$Fv2oJsqiYCRrtn!~`w(hrxz+PdbxP}z~ zEeyW+{6QQ8j;aRLm&kV?Q3fsqN}M@`*yV=ot-{zP)^epg?Kc_)n;d>+7aY?9gaaU6 zpbE=;)DG@blJYX`U9+gq7twl;gO+nKw6*sF2Gn_tuIem}_C<8nFLBE@x*&l=c+3%_ zUCPB*)Iku#R}euQ<~eRUt|Jz=GwCi1mR!rLo`Z8ibbqlaYYV`!=ohM%4u7Q2Ys$M; zDJdwRmJC#=;}J$pO2~yozyr)c7kml3GreXY(R9S&mBT#`ZXg@4dV#&`j?c&u)cM_y z)TPZB1_Lw8NZ(SPsqShz>_sCnN1GTikzH~*lsOJP$D{#7fphajW`(w^mAJyRtBF9) zYcj;QYX&)%u;S^$LTMCc-4lqwEQTx$u7V`#9I_$}CDcv<90WCsLTCnQn2ZQU$tgA+ zO=z?}ceQZ?sOD53Yl_J}U=(eMk(~Y`%GwEZbGVolX6uL?v>Ra4Wntz8tqWfSqE(hl zus5gy(7CW~v0m>Kw|``VO@fxFH3ph*xR?VFDV#(ys<)U$r=~F@Z&9hU z5p68bC{Bu=5!`ufioX%4>R?=>;s)-YnaWrlcOA+H`MOaC zDR_u%A)VC8U+y;xa>9o!489_&yj;%((J&G{)~Zqco|wq-Eh_##(W6niy~0qPVpys~ z$QTBU$2mL1>-;12D~i}ha%rqb0m;EoUPmNmm=21K3JHrKR#Vw4_exWAS>F?RHK>g+p6QHbTJ2Jmvl%5N{skO@ZNOl`(WY#@$KWuz>W~ z{7Rrb=FGu^+LwlZpkoZ<_Y?3acvT<7E3mGjf?X9dX_y>Cx~ZE4 zB(>CP5OyXbe9+1zoK~ftIl9acG9#$|Zf` zmmzQm2bp@+LljC3*OsPWvpFBn9BKfK?LXbcA*X4@`-6x~Cp()!EGg<)V4;|>!-LtN znG5Y0hT;fz> ztNVpt%mVwZE_}qyOvkIo6N(u57CwmYX}%%`O?7c?9A-ODlv`bnCL7dI4?I)@1%DGZ z3^DB-;>Wks6QMLWG;6EsHgd5CZdXBr}W${SKp5GW%dtg%Yg<~2k4hN|woOKUC7 z-EZ7#ZvOGL)?d^Nuq_epD6v+<)K6pyrFe)Li@V0+;)!0L1gf4Pb^Dj}1;D%9#bz{m zj%Jqx{?kx5|2zfn9@ZGMJa8TERob~OMfccE&sg@2Uygzwg6pF;U0q8(TIl&moZLm}$5SSa1^& zE;mZusc)LI2A|0jfmmt7BR;;-imEo70lS(-K#4(LVC+C3d=j9?_YB@eMI`rE zr$jItF*cYR9oASCa!hrIkyi0|gh+=c20!er1azVXjbP8XE#$bwx;`@$6UjBMes?g} z2BNq(`IjA?VqJkxFH*;y(H)%Y7RwxufYMs9^GmoI(Vfz0DI)9n1}7U=MMQk6TtGFgZ5$D)scle$oJOV<=ZKqg>}oD*{OdB2qxy-l zn%rtuy&{EH!k8}Ac$U?p3WgRtmqA6yxGJvU75YIIS-n{=P7U~jWmdS9sL}bG6teV+ zmg@B{pkCu;HsPqsfnv*L#d^dHTT}auT{?r5IGJ(zWxIE&NMV$DnKS#9wzVycVra&3 z4Pl7eTbJFk<>d^p&jABMs`<84ZH+F;{6!)aE0zA(lMc*k`;D-alE+z^FYzCY2zD+| zurON)P(WLWPKn;7cTqhKBG90Lre5QoV^gTO#cNc?q)d7GKvJBL2T?Le!H$=fIr9(| z6|0*oSYtjy*if}PbIfUe8;zq?@f!uUvo8bsT+Pun3(y|pqf|f@!K01FgVW|ry&i-vBY z_yh-OntWnqr2_~cOm@nQwqnyu-f9|Z)og0V4|vyC16v!kfyyYtzS)&`VqpOLo?@$Q zfvJOZuTiVB?9^siS}x(V3h@+7G(@E}7`MxXg-1K?D~Lown&UE;gFm>bZgDM0Vc@tV z=yQl@ej13?uNRSKnp(7#4C7&$N(5!a~`2afKbeV`bP6zcLdPt8Gp|*@(+p* z`R}H^kSieb!r6^QHmOl6hCKk*POj2R{k5DEQEv&I9#@io?AnP<>paTP>8#{@~k zSehkDR;p61l&)r5sDcZ2M7>7fjZ{T5%&Xi-X=7Yg|%{xp@ z*u+~c>gsfQ=m}u0?48lhgW+Q>(;w-0l+}H(lL4ppa z_-9}0EoKF%6GmV*%MWlWWxA9NK=qlqQj|(o3Bbxbnrazq=m!3S!eaps2o9h?xm7Ln zFv|w*XF5BE(c2dQ!_)%2t1W4oC8uh%TPo2zJ7w!I$yt?DIO++u|X^d{4ah=t4y^DzTf;vD;&vC2PlaWV?)e8kRpiA=800ae2`87!LI z8I#wkg-aFPPJZzWpAyWb1qse-XHDI*s)1|^31_$nenrgi)V5=YZ6Gl`P@o_n8AurS5h+m! zsDz{ng#jqJ)|6UADiQ|~2nY&NWP^Y z=GfoNR2lVO2 z6m&+2aRHFc@isxRZC7#1&R_#wB4x`lwrXrdCEnvL7^q6aCU*o3_=VbqMkNhO5nVt$ wKpILcj-V)js1>P1Lda?XP~+)J)HMLPN~z2RY67P)Dhz!OpoHO^!co-!*$upTsQ>@~ diff --git a/docs/blog/2021-08-26-welcome/index.md b/docs/blog/2021-08-26-welcome/index.md deleted file mode 100644 index 349ea075..00000000 --- a/docs/blog/2021-08-26-welcome/index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -slug: welcome -title: Welcome -authors: [slorber, yangshun] -tags: [facebook, hello, docusaurus] ---- - -[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog). - -Here are a few tips you might find useful. - - - -Simply add Markdown files (or folders) to the `blog` directory. - -Regular blog authors can be added to `authors.yml`. - -The blog post date can be extracted from filenames, such as: - -- `2019-05-30-welcome.md` -- `2019-05-30-welcome/index.md` - -A blog post folder can be convenient to co-locate blog post images: - -![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg) - -The blog supports tags as well! - -**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config. diff --git a/docs/blog/2025-06-10-entities-and-types.md b/docs/blog/2025-06-10-entities-and-types.md new file mode 100644 index 00000000..1bcab49d --- /dev/null +++ b/docs/blog/2025-06-10-entities-and-types.md @@ -0,0 +1,115 @@ +--- +slug: understanding-entities-and-types +title: "1. Understanding Entities and Types in GRC-20" +date: 2025-06-10 +series_position: 1 +authors: [nik] +tags: [knowledge-graphs, education, grc20] +--- + +> **Series:** GRC-20 Knowledge Graph (Part 1 of 6) +> **Next:** [Properties and Relations in GRC-20 →](/blog/properties-and-relations-in-grc20) + +The GRC-20 specification introduces a standardized way to represent knowledge in The Graph ecosystem. At its core are two fundamental concepts: Entities and Types. Let's explore how these building blocks work together to create a flexible and powerful knowledge graph system. + + + +## Entities: The Foundation + +In GRC-20, entities are the fundamental building blocks that represent any identifiable thing in the knowledge graph. Each entity has: + +- A globally unique UUID4 identifier +- A set of values (key-value pairs) +- Optional relations to other entities + +For example, an entity could represent: +- A person (like Albert Einstein) +- A place (like Paris) +- An organization (like NASA) +- An abstract concept (like Relativity) + +### Entity Structure + +The core entity structure in GRC-20 is elegantly simple: + +```proto +message Entity { + bytes id = 1; // UUID4 + repeated Value values = 2; +} +``` + +Each value attached to an entity includes: +- A property reference (UUID) +- The actual value (as a UTF-8 string) +- Optional type-specific metadata + +## Types: Providing Structure + +Types in GRC-20 serve as classification mechanisms that help organize entities and define their expected properties. The type system is designed to be: + +- Flexible but structured +- Composable through inheritance +- Evolution-friendly + +### Key Features of Types + +1. **Implicit Entity Type** + - Every node automatically has the base Entity type + - No explicit declaration needed + +2. **Type Relations** + - Types are connected through "broader types" relations + - Creates a natural hierarchy of classifications + +3. **Property Inheritance** + - Types can define expected properties + - Subtypes inherit properties from their broader types + +### Built-in Type UUIDs + +The specification defines several core type identifiers: + +``` +Type (schema): e7d737c5-3676-4c60-9fa1-6aa64a8c90ad +Property Type: 808a04ce-b21c-4d88-8ad1-2e240613e5ca +Space Type: 362c1dbd-dc64-44bb-a3c4-652f38a642d7 +``` + +## Why This Matters + +The GRC-20 approach to entities and types enables: + +1. **Flexible Knowledge Representation** + - Any concept can be modeled as an entity + - Types provide structure without rigid constraints + +2. **Natural Evolution** + - New types can be added without breaking existing ones + - Properties can evolve independently + +3. **Interoperability** + - Standard UUID-based identification + - Consistent serialization format + - Cross-space references + +4. **Web3 Native Design** + - Built for decentralized networks + - No dependence on centralized authorities + - Blockchain-friendly identifiers + +## Learn More + +This post covers just the basics of entities and types in GRC-20. For the complete specification, including detailed protobuf schemas and implementation guidelines, check out the [full GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). + +## Best Practices + +When working with GRC-20 entities and types: + +1. Always use UUID4 for identifiers +2. Consider type hierarchies carefully +3. Keep entities focused and atomic +4. Use relations to express connections +5. Follow the protobuf serialization format + +The GRC-20 specification represents a major step forward in standardizing knowledge representation for Web3. By understanding entities and types, you're well on your way to building interoperable, decentralized knowledge systems. \ No newline at end of file diff --git a/docs/blog/2025-06-10-knowledge-graph-best-practices.md b/docs/blog/2025-06-10-knowledge-graph-best-practices.md new file mode 100644 index 00000000..08a90e22 --- /dev/null +++ b/docs/blog/2025-06-10-knowledge-graph-best-practices.md @@ -0,0 +1,227 @@ +--- +slug: grc20-knowledge-graph-best-practices +title: "6. Best Practices for Building GRC-20 Knowledge Graphs" +date: 2025-06-05 +series_position: 6 +authors: [nik] +tags: [knowledge-graphs, education, grc20, best-practices] +--- + +> **Series:** GRC-20 Knowledge Graph (Part 6 of 6) +> **Previous:** [← Spaces & Governance](/blog/grc20-spaces-and-governance) + +This post outlines key best practices and guidelines for implementing GRC-20 compliant systems. + + + +## Core Implementation Guidelines + +### 1. UUID Management + +GRC-20 requires UUID version 4 for all identifiers: + +- Use cryptographically secure random number generators +- Store as 16-byte arrays in wire format +- Display as 36-character lowercase hex strings with dashes +- Never reuse or manually generate UUIDs + +Example UUID format: +``` +2a5fe010-078b-4ad6-8a61-7272f33729f4 +``` + +### 2. Value Type Handling + +When working with GRC-20's native value types: + +1. **Text Values** + - Always use UTF-8 encoding + - Include language tags when relevant + - Support Markdown where appropriate + +2. **Number Values** + - Use decimal string representation + - Include unit and format metadata + - No commas or currency symbols inline + +3. **Time Values** + - Use ISO-8601 format + - Include timezone information + - Support both dates and times + +4. **URL Values** + - Validate protocol prefixes (ipfs://, https://, etc.) + - Ensure URI syntax compliance + - Handle cross-space references properly + +## Space Management + +### 1. Space Categories + +Choose the appropriate space type for your use case: + +- **Public Spaces** + - Onchain governance + - Public visibility + - Community participation + +- **Personal Spaces** + - Individual control + - Public visibility + - Centralized management + +- **Private Spaces** + - Local-first operation + - Peer-to-peer sharing + - Encrypted when needed + +### 2. Cross-Space References + +When linking across spaces: + +```proto +message Relation { + // Required fields + bytes id = 1; + bytes type = 2; + bytes from_entity = 3; + bytes to_entity = 6; + + // Cross-space reference fields + optional bytes from_space = 4; + optional bytes from_version = 5; + optional bytes to_space = 7; + optional bytes to_version = 8; +} +``` + +- Always include space IDs for external references +- Track versions when stability is important +- Use the verified flag appropriately + +## Data Evolution & Migration + +### 1. Edit Structure + +Package changes effectively: + +```proto +message Edit { + bytes id = 1; // Edit UUID + string name = 2; // Descriptive summary + repeated Op ops = 3; // Ordered operations + repeated bytes authors = 4; // Contributor IDs + optional bytes language = 5; // Default language +} +``` + +- Group related changes in single edits +- Provide clear edit descriptions +- Maintain proper operation ordering + +### 2. Import Process + +For migrating or bootstrapping spaces: + +1. Generate ImportEdit messages +2. Upload to content-addressed storage +3. Create Import manifest +4. Anchor on the target chain + +```proto +message ImportEdit { + // Standard edit fields + bytes id = 1; + string name = 2; + repeated Op ops = 3; + + // Migration metadata + bytes created_by = 5; + string created_at = 6; + bytes block_hash = 7; + string block_number = 8; + bytes transaction_hash = 9; +} +``` + +## Content Type Handling + +### 1. Image Entities + +When working with images: + +- Store binary data off-chain +- Include width and height metadata +- Use appropriate IPFS/URI references +- Follow recommended dimensions (2384 × 640 px for covers) + +### 2. Block Relations + +For rich content organization: + +- Use ordered block relations +- Maintain proper position values +- Support various content types +- Enable flexible composition + +## System Properties + +Always respect system-maintained properties: + +1. **Temporal Metadata** + - Created at + - Updated at + - Version history + +2. **Attribution** + - Created by + - Author tracking + - Space ownership + +3. **Implicit Fields** + - Name + - Description + - Types + - Cover + - Blocks + +## Serialization Best Practices + +### 1. Protobuf Usage + +- Follow proto3 syntax exactly +- Use bytes for UUIDs +- Handle optional fields appropriately +- Maintain backward compatibility + +### 2. JSON Representation + +For API endpoints and debugging: + +```json +{ + "id": "2a5fe010-078b-4ad6-8a61-7272f33729f4", + "type": "e7d737c5-3676-4c60-9fa1-6aa64a8c90ad", + "values": [ + { + "property": "a126ca53-0c8e-48d5-b888-82c734c38935", + "value": "Example Entity" + } + ] +} +``` + +- Use consistent UUID formatting +- Include only present optional fields +- Follow the specified naming conventions + +## Learn More + +For complete implementation details, refer to the [GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). The specification includes: + +- Full protobuf schemas +- UUID constants +- Serialization formats +- Implementation guidelines + +By following these best practices, you'll build robust, interoperable knowledge graphs that work seamlessly within The Graph ecosystem while maintaining compatibility with the broader web3 landscape. \ No newline at end of file diff --git a/docs/blog/2025-06-10-properties-and-relations.md b/docs/blog/2025-06-10-properties-and-relations.md new file mode 100644 index 00000000..0d0aeadd --- /dev/null +++ b/docs/blog/2025-06-10-properties-and-relations.md @@ -0,0 +1,160 @@ +--- +slug: properties-and-relations-in-grc20 +title: "2. Properties and Relations in GRC-20: Building Connected Knowledge" +date: 2025-06-09 +series_position: 2 +authors: [nik] +tags: [knowledge-graphs, education, grc20] +--- + +> **Series:** GRC-20 Knowledge Graph (Part 2 of 6) +> **Previous:** [← Entities & Types](/blog/understanding-entities-and-types) +> **Next:** [UUIDs & Identifiers →](/blog/grc20-uuids-and-identifiers) + +The GRC-20 specification defines a robust system for representing properties and relations in knowledge graphs. Let's explore how these components work together to create rich, interconnected data structures that are both flexible and standardized. + + + +## Properties in GRC-20 + +Properties in GRC-20 are first-class entities that define attributes and their characteristics. Each property entity includes: + +- A unique UUID4 identifier +- A value type specification +- Optional metadata (unit, format, language requirements) + +### Native Value Types + +GRC-20 defines six built-in value types: + +| Type | UUID | Description | +|----------|----------------------------------------|-------------------------------| +| Text | 9edb6fcc-e454-4aa5-8611-39d7f024c010 | Unicode character sequences | +| Number | 9b597aae-c31c-46c8-8565-a370da0c2a65 | Decimal numeric values | +| Checkbox | 7aa4792e-eacd-4186-8272-fa7fc18298ac | Boolean true/false | +| URL | 283127c9-6142-4684-92ed-90b0ebc7f29a | URIs with protocol prefix | +| Time | 167664f6-68f8-40e1-976b-20bd16ed8d47 | ISO-8601 timestamps | +| Point | df250d17-e364-413d-9779-2ddaae841e34 | Coordinate pairs or vectors | + +### Value Options + +Properties can specify additional metadata through options: + +```proto +message Options { + oneof value { + TextOptions text = 1; + NumberOptions number = 2; + TimeOptions time = 3; + } +} +``` + +These options enable features like: +- Language tags for text +- Formatting strings for numbers +- Timezone and format specifications for timestamps + +## Relations: The Connective Tissue + +Relations in GRC-20 are sophisticated edges that can carry their own properties and metadata. They consist of two parts: + +1. A lightweight relation record +2. An optional relation entity for additional properties + +### Relation Structure + +```proto +message Relation { + bytes id = 1; // relation UUID4 + bytes type = 2; // relation-type UUID4 + bytes from_entity = 3; // source entity UUID4 + optional bytes from_space = 4; // source Space UUID4 + optional bytes from_version = 5; // source Edit/Version UUID4 + bytes to_entity = 6; // target entity UUID4 + optional bytes to_space = 7; // target Space UUID4 + optional bytes to_version = 8; // target Edit/Version UUID4 + bytes entity = 9; // relation entity UUID4 + optional string position = 10; // ordering key + optional bool verified = 11; // trust flag +} +``` + +### Key Features + +1. **Cross-Space References** + - Relations can link entities across different spaces + - Optional space and version tracking + - Verification status for trust + +2. **Ordered Collections** + - `position` field enables stable ordering + - Useful for lists, sequences, and rankings + +3. **Rich Metadata** + - Relation entities can carry additional properties + - Full entity capabilities for relationship data + +## System Properties + +GRC-20 defines several system-level properties that are automatically maintained: + +1. **Creation Metadata** + - Created at timestamp + - Created by (blockchain address) + +2. **Update Tracking** + - Updated at timestamp + - Version history + +3. **Implicit Properties** + - Name + - Types + - Description + - Cover + - Blocks + +## Best Practices + +When working with GRC-20 properties and relations: + +1. **Property Design** + - Use native value types when possible + - Include appropriate options metadata + - Consider property reusability + +2. **Relation Management** + - Use relation entities for complex relationships + - Maintain proper ordering with position keys + - Track cross-space references carefully + +3. **Data Validation** + - Ensure values match their declared types + - Handle language tags appropriately + - Validate URIs and timestamps + +## Implementation Example + +Here's how you might represent a simple property-relation combination: + +```json +{ + "property": { + "id": "6ab0887f-b6c1-4628-9eee-2234a247c1d2", + "type": "808a04ce-b21c-4d88-8ad1-2e240613e5ca", // Property Type + "value_type": "9edb6fcc-e454-4aa5-8611-39d7f024c010" // Text Type + }, + "relation": { + "id": "29785ffb-5ce6-4a9b-b0dc-b138328ba334", + "type": "0509279a-713d-4667-a412-24fe3757f554", + "from_entity": "2a5fe010-078b-4ad6-8a61-7272f33729f4", + "to_entity": "386d9dde-4c10-4099-af42-0e946bf2f199" + } +} +``` + +## Learn More + +For complete details on properties, relations, and their implementation, refer to the [GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). The specification includes full protobuf schemas, serialization formats, and detailed guidelines for building compliant systems. + +Properties and relations form the foundation of GRC-20's ability to represent rich, interconnected knowledge in a standardized way. By following these patterns, you can build robust, interoperable knowledge graphs that work seamlessly across the decentralized web. \ No newline at end of file diff --git a/docs/blog/2025-06-10-serialization-and-encoding.md b/docs/blog/2025-06-10-serialization-and-encoding.md new file mode 100644 index 00000000..e6fc10d0 --- /dev/null +++ b/docs/blog/2025-06-10-serialization-and-encoding.md @@ -0,0 +1,126 @@ +--- +slug: grc20-serialization-and-encoding +title: "4. Serialization and Encoding in GRC-20" +date: 2025-06-07 +series_position: 4 +authors: [nik] +tags: [knowledge-graphs, education, grc20] +--- + +> **Series:** GRC-20 Knowledge Graph (Part 4 of 6) +> **Previous:** [← UUIDs & Identifiers](/blog/grc20-uuids-and-identifiers) +> **Next:** [Spaces & Governance →](/blog/grc20-spaces-and-governance) + +Let's explore the details of how data is encoded and transmitted in GRC-20. + + + +## Protocol Buffers: The Core Format + +### Why Protocol Buffers? + +GRC-20 chose Protocol Buffers for several reasons: + +1. **Efficiency**: Compact binary format +2. **Schema Evolution**: Backward/forward compatibility +3. **Language Agnostic**: Wide platform support +4. **Type Safety**: Strong typing and validation +5. **Performance**: Fast serialization/deserialization + +### Core Message Types + +Here are the fundamental protobuf messages in GRC-20: + +```proto +syntax = "proto3"; +package grc20; + +message Entity { + bytes id = 1; // UUID4 (16 bytes) + repeated Value values = 2; // Property values +} + +message Value { + bytes property = 1; // Property UUID + string value = 2; // UTF-8 literal + oneof options { + TextOptions text_options = 3; + NumberOptions number_options = 4; + TimeOptions time_options = 5; + } +} + +message Relation { + bytes id = 1; + bytes type = 2; + bytes from_entity = 3; + optional bytes from_space = 4; + optional bytes from_version = 5; + bytes to_entity = 6; + optional bytes to_space = 7; + optional bytes to_version = 8; + bytes entity = 9; + optional string position = 10; + optional bool verified = 11; +} +``` + +## JSON Representation + +While protobuf is used for wire format, JSON is useful for: +- API responses +- Debugging and inspection +- Human-readable storage +- Documentation + +### JSON Conversion Rules + +When converting protobuf messages to JSON: + +1. **UUID Fields** + - Convert 16-byte arrays to lowercase hex strings with dashes + - Example: `"2a5fe010-078b-4ad6-8a61-7272f33729f4"` + +2. **Repeated Fields** + - Represent as JSON arrays + - Preserve order exactly + +3. **Optional Fields** + - Omit if not present + - Never use null values + +4. **Oneof Fields** + - Include only the present option + - Use camelCase naming + +### Example JSON Formats + +#### Entity + +```json +{ + "id": "2a5fe010-078b-4ad6-8a61-7272f33729f4", + "values": [ + { + "property": "a126ca53-0c8e-48d5-b888-82c734c38935", + "value": "Example Entity", + "textOptions": { + "language": "en" + } + } + ] +} +``` + +#### Relation + +```json +{ + "id": "29785ffb-5ce6-4a9b-b0dc-b138328ba334", + "type": "0509279a-713d-4667-a412-24fe3757f554", + "fromEntity": "2a5fe010-078b-4ad6-8a61-7272f33729f4", + "toEntity": "386d9dde-4c10-4099-af42-0e946bf2f199", + "position": "a", + "verified": true +} +``` \ No newline at end of file diff --git a/docs/blog/2025-06-10-spaces-and-governance.md b/docs/blog/2025-06-10-spaces-and-governance.md new file mode 100644 index 00000000..e07eafee --- /dev/null +++ b/docs/blog/2025-06-10-spaces-and-governance.md @@ -0,0 +1,267 @@ +--- +slug: grc20-spaces-and-governance +title: "5. Understanding Spaces and Governance in GRC-20" +date: 2025-06-06 +series_position: 5 +authors: [nik] +tags: [knowledge-graphs, education, grc20] +--- + +> **Series:** GRC-20 Knowledge Graph (Part 5 of 6) +> **Previous:** [← Serialization & Encoding](/blog/grc20-serialization-and-encoding) +> **Next:** [Best Practices →](/blog/grc20-knowledge-graph-best-practices) + +The GRC-20 specification introduces the concept of **Spaces** as a way to organize and govern knowledge graphs. In this post, we'll explore how spaces work and how they enable different governance models for managing knowledge. + + + +## What is a Space? + +A Space in GRC-20 is a logical domain that encapsulates: +- A self-contained knowledge graph +- Governance rules and access controls +- Anchoring and versioning mechanisms + +Every space has its own UUID and can be referenced by other spaces, enabling a web of interconnected knowledge while maintaining clear boundaries and control. + +## Types of Spaces + +GRC-20 defines three categories of spaces, each serving different needs: + +### 1. Public Spaces + +- **Governance**: Onchain, community-driven +- **Visibility**: Public +- **Control**: Determined by smart contracts +- **Use Cases**: + - Open knowledge bases + - Community-curated datasets + - Public standards and specifications + +### 2. Personal Spaces + +- **Governance**: Centralized +- **Visibility**: Public +- **Control**: Individual or organization +- **Use Cases**: + - Personal blogs + - Portfolio sites + - Organization documentation + +### 3. Private Spaces + +- **Governance**: Local or group-based +- **Visibility**: Private +- **Control**: Device-level or encrypted sharing +- **Use Cases**: + - Personal notes + - Team collaboration + - Private research + +## Space Implementation + +### Core Type Definition + +Every space is an entity with the Space type: + +```typescript +const SPACE_TYPE_UUID = "362c1dbd-dc64-44bb-a3c4-652f38a642d7" +``` + +### Space Hierarchy + +Spaces can form hierarchies through relations: + +```typescript +interface SpaceRelations { + broaderSpaces: string[] // Parent space UUIDs + subspaces: string[] // Child space UUIDs +} +``` + +This enables: +- Organizing knowledge in logical trees +- Inheriting governance rules +- Maintaining context across spaces + +## Governance Models + +### Public Space Governance + +Public spaces use smart contracts to enforce: + +1. **Proposal Submission** + - Who can propose changes + - Required stake or reputation + - Proposal formats + +2. **Voting** + - Voting periods + - Quorum requirements + - Vote weight calculation + +3. **Execution** + - Automatic vs manual execution + - Timelock periods + - Emergency procedures + +Example smart contract interface: + +```solidity +interface IPublicSpace { + function propose(bytes32 editCid, string calldata description) external; + function vote(uint256 proposalId, bool support) external; + function execute(uint256 proposalId) external; + function getProposal(uint256 proposalId) external view returns (Proposal memory); +} +``` + +### Personal Space Controls + +Personal spaces use simpler control mechanisms: + +```typescript +interface PersonalSpaceControls { + owner: string // Controller address + delegates?: string[] // Optional additional writers + readAccess: "public" // Always public in personal spaces + writeAccess: "owner" // Only owner + delegates can write +} +``` + +### Private Space Security + +Private spaces focus on encryption and sharing: + +```typescript +interface PrivateSpaceConfig { + encryptionKey: CryptoKey + allowedMembers: string[] + syncMode: "p2p" | "local" + backupStrategy?: "ipfs" | "none" +} +``` + +## Space Creation and Evolution + +### Creating a New Space + +1. Generate a UUID for the space +2. Define its type (public/personal/private) +3. Set up governance structure +4. Initialize empty graph state +5. Begin accepting edits + +Example creation flow: + +```typescript +async function createPublicSpace(config: SpaceConfig): Promise { + // Generate space UUID + const spaceId = generateUuid() + + // Deploy governance contract + const contract = await deploySpaceContract(config.governance) + + // Initialize space entity + const space = { + id: spaceId, + type: SPACE_TYPE_UUID, + contract: contract.address, + values: [ + { property: "name", value: config.name }, + { property: "description", value: config.description } + ] + } + + // Anchor initial state + await anchorSpace(space) + + return space +} +``` + +### Converting Existing Entities + +Any entity can evolve into a space: + +1. Choose the target entity +2. Deploy appropriate contracts/controls +3. Bind the entity to governance +4. Migrate existing content + +```typescript +async function convertToSpace(entityId: string, config: SpaceConfig): Promise { + // Verify entity exists + const entity = await getEntity(entityId) + + // Set up governance + const governance = await setupGovernance(config) + + // Add space type + await addEntityType(entityId, SPACE_TYPE_UUID) + + // Bind to governance + await bindEntityToGovernance(entityId, governance) + + return loadSpace(entityId) +} +``` + +## Cross-Space Interactions + +### References + +When linking across spaces: + +```typescript +interface CrossSpaceReference { + fromEntity: string + fromSpace: string + toEntity: string + toSpace: string + verified: boolean +} +``` + +### Trust and Verification + +Spaces can mark cross-space references as verified: + +```typescript +async function verifyReference(ref: CrossSpaceReference) { + // Check if source space trusts target + const trusted = await checkSpaceTrust(ref.fromSpace, ref.toSpace) + + if (trusted) { + await markReferenceVerified(ref) + } +} +``` + +## Best Practices + +1. **Space Planning** + - Choose the right space type for your use case + - Plan governance structure before creation + - Consider future growth and evolution + +2. **Access Control** + - Use appropriate permission levels + - Implement proper key management + - Regular security audits + +3. **Cross-Space Relations** + - Verify external references + - Track space versions + - Handle missing spaces gracefully + +4. **Performance** + - Cache frequently accessed data + - Batch updates when possible + - Monitor space size and growth + +## Learn More + +For complete details on spaces and governance in GRC-20, including protobuf schemas and smart contract interfaces, check out the [full GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). + +Spaces are a powerful mechanism for organizing and controlling knowledge in GRC-20. By understanding their capabilities and choosing the right model for your needs, you can build robust and secure knowledge graph applications. \ No newline at end of file diff --git a/docs/blog/2025-06-10-uuids-and-identifiers.md b/docs/blog/2025-06-10-uuids-and-identifiers.md new file mode 100644 index 00000000..2ffa6a07 --- /dev/null +++ b/docs/blog/2025-06-10-uuids-and-identifiers.md @@ -0,0 +1,168 @@ +--- +slug: grc20-uuids-and-identifiers +title: "3. Working with UUIDs and Identifiers in GRC-20" +date: 2025-06-08 +series_position: 3 +authors: [nik] +tags: [knowledge-graphs, education, grc20] +--- + +> **Series:** GRC-20 Knowledge Graph (Part 3 of 6) +> **Previous:** [← Properties & Relations](/blog/properties-and-relations-in-grc20) +> **Next:** [Serialization & Encoding →](/blog/grc20-serialization-and-encoding) + +The GRC-20 specification uses UUID version 4 as the foundation for all identifiers in the knowledge graph system. Understanding how to work with these identifiers is crucial for building interoperable applications. Let's dive into the details of GRC-20's UUID implementation. + + + +## Why UUID4? + +GRC-20 chose UUID version 4 (random) for several key reasons: + +1. **Decentralization**: No central coordination needed +2. **Collision resistance**: 2⁻¹²² probability of collision +3. **Standardization**: Well-defined in RFC 4122 +4. **Efficiency**: Compact 16-byte representation +5. **Interoperability**: Wide language/platform support + +## Core UUID Constants + +GRC-20 defines several fundamental UUIDs that every implementation must know: + +```typescript +// Core Types +const TYPE_UUID = "e7d737c5-3676-4c60-9fa1-6aa64a8c90ad" +const PROPERTY_TYPE_UUID = "808a04ce-b21c-4d88-8ad1-2e240613e5ca" +const SPACE_TYPE_UUID = "362c1dbd-dc64-44bb-a3c4-652f38a642d7" + +// Native Value Types +const TEXT_TYPE = "9edb6fcc-e454-4aa5-8611-39d7f024c010" +const NUMBER_TYPE = "9b597aae-c31c-46c8-8565-a370da0c2a65" +const CHECKBOX_TYPE = "7aa4792e-eacd-4186-8272-fa7fc18298ac" +const URL_TYPE = "283127c9-6142-4684-92ed-90b0ebc7f29a" +const TIME_TYPE = "167664f6-68f8-40e1-976b-20bd16ed8d47" +const POINT_TYPE = "df250d17-e364-413d-9779-2ddaae841e34" +``` + +## Working with UUIDs + +### Binary (Wire) Format + +When transmitting UUIDs in protobuf messages, use raw 16-byte arrays: + +```proto +message Entity { + bytes id = 1; // 16 bytes, network byte order + // ... +} +``` + +### String Representation + +For human readability and JSON interfaces, use the canonical 36-character format: + +```typescript +// Example UUID string +const entityId = "2a5fe010-078b-4ad6-8a61-7272f33729f4" +``` + +### Converting Legacy IDs + +If you're migrating from an existing system with its own ID format, follow this process: + +1. Take your original ID string +2. UTF-8 encode it +3. Compute its MD5 hash +4. Use the 16-byte digest to seed a UUID4 generator +5. Set version (4) and variant bits per RFC 4122 + +This ensures deterministic, stable UUIDs for your existing identifiers. + +## Best Practices + +1. **Generation** + - Always use cryptographically secure random number generators + - Verify version 4 and variant bits are correctly set + - Don't try to generate UUIDs manually + +2. **Storage** + - Store as 16-byte arrays in databases + - Index UUID columns for efficient lookups + - Consider UUID-optimized database types + +3. **Validation** + - Check length (16 bytes or 36 chars) + - Verify version 4 bit pattern + - Validate hex digits and dash positions in strings + +4. **Cross-Space References** + - Include space IDs when referencing external entities + - Track versions for stability + - Use the verified flag appropriately + +## Implementation Example + +Here's a TypeScript example of working with GRC-20 UUIDs: + +```typescript +import { v4 as uuidv4 } from 'uuid' +import { createHash } from 'crypto' + +// Generate a new UUID4 +function generateEntityId(): string { + return uuidv4() +} + +// Convert legacy ID to UUID4 +function legacyIdToUuid(legacyId: string): string { + const hash = createHash('md5') + .update(legacyId) + .digest() + + // Set version 4 and variant bits + hash[6] = (hash[6] & 0x0f) | 0x40 + hash[8] = (hash[8] & 0x3f) | 0x80 + + return formatUuid(hash) +} + +// Format 16 bytes as UUID string +function formatUuid(bytes: Buffer): string { + const hex = bytes.toString('hex') + return [ + hex.slice(0, 8), + hex.slice(8, 12), + hex.slice(12, 16), + hex.slice(16, 20), + hex.slice(20) + ].join('-') +} +``` + +## Common Pitfalls + +1. **String vs Binary** + - Don't mix string and binary formats + - Always be explicit about which format you're using + - Convert at system boundaries only + +2. **Case Sensitivity** + - Always use lowercase for string UUIDs + - Be careful with case-sensitive comparisons + - Normalize input strings + +3. **Validation** + - Don't assume all 16-byte values are valid UUIDs + - Check version and variant bits + - Validate string format thoroughly + +4. **Performance** + - Cache UUID parsing results + - Use binary format for internal operations + - Batch UUID operations when possible + +## Learn More + +For complete details on UUID usage in GRC-20, including protobuf schemas and serialization formats, check out the [full GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). + +The proper handling of UUIDs is fundamental to building robust GRC-20 implementations. By following these guidelines and best practices, you'll ensure your application can reliably participate in the broader knowledge graph ecosystem. \ No newline at end of file diff --git a/docs/blog/2025-06-10-hypergraph-alpha-released.md b/docs/blog/2025-06-11-hypergraph-alpha-released.md similarity index 84% rename from docs/blog/2025-06-10-hypergraph-alpha-released.md rename to docs/blog/2025-06-11-hypergraph-alpha-released.md index 5a2ee4fc..f1e4dff9 100644 --- a/docs/blog/2025-06-10-hypergraph-alpha-released.md +++ b/docs/blog/2025-06-11-hypergraph-alpha-released.md @@ -1,11 +1,12 @@ --- slug: hypergraph-alpha-released -title: Announcing Hypergraph Alpha—A New Chapter in Web Development -authors: [slorber, yangshun] +title: Announcing Hypergraph - A New Chapter in Web Development +date: 2025-06-11 +authors: [nik, pablo] tags: [release, alpha, hypergraph] --- -After months of development and countless conversations with developers like you, we're thrilled to unveil Hypergraph Alpha. This is more than just another data layer—it's a fundamental rethinking of how we build collaborative, secure, and offline-first Web3 applications. +After months of development and countless conversations with developers like you, **we're thrilled to unveil the Alpha version of Hypergraph**. This is more than just another data layer—it's a fundamental rethinking of how we build collaborative, secure, and offline-first Web3 applications. @@ -13,7 +14,7 @@ After months of development and countless conversations with developers like you The challenges of modern app development are clear: users expect real-time collaboration, bulletproof security, and apps that work flawlessly even when offline. Traditional architectures force uncomfortable trade-offs between these needs. We knew there had to be a better way. -Enter Hypergraph Alpha, built on two core innovations: a local-first architecture that puts your data where it belongs—on the client—and our implementation of the GRC-20 standard for truly composable knowledge graphs. +Enter Hypergraph, built on two core innovations: a local-first architecture that puts your data where it belongs—on the client—and our implementation of the GRC-20 standard for truly composable knowledge graphs. @@ -36,7 +37,7 @@ We're launching this alpha today, June 10, 2025, and we're targeting a beta rele Getting started is simple. Install our SDK: ```bash -npm install @hypergraph/sdk-alpha +# TODO: ADD INSTALLER TO NPM npm install @hypergraph/sdk-alpha ``` Head to our [Quickstart guide](/docs/quickstart) to build your first Hypergraph app, or dive deep into our [API Reference](/docs/api-reference) to explore the possibilities. We support Node.js and modern browsers, with React hooks that make integration a breeze. diff --git a/docs/blog/authors.yml b/docs/blog/authors.yml index 5e45372d..a5d701b2 100644 --- a/docs/blog/authors.yml +++ b/docs/blog/authors.yml @@ -1,4 +1,4 @@ -yangshun: +pablo: name: Pablo Carranza Velez title: Engineering Manager @ Edge & Node url: https://github.com/pcarranzav @@ -9,7 +9,7 @@ yangshun: x: https://x.com/pcarranzav github: https://github.com/pcarranzav -slorber: +nik: name: Nik title: Hypergraph Lead Engineer @ Geo # url: diff --git a/docs/blog/tags.yml b/docs/blog/tags.yml index bc544dd5..e2eee19e 100644 --- a/docs/blog/tags.yml +++ b/docs/blog/tags.yml @@ -1,31 +1,40 @@ -facebook: - label: Facebook - permalink: /facebook - description: Facebook tag description - -hello: - label: Hello - permalink: /hello - description: Hello tag description - docusaurus: label: Docusaurus permalink: /docusaurus description: Docusaurus tag description - release: label: Release permalink: /release - description: Product releases and updates + description: Release announcements and updates alpha: label: Alpha permalink: /alpha - description: Early access and alpha releases + description: Alpha version releases and features hypergraph: label: Hypergraph permalink: /hypergraph - description: Posts about Hypergraph development and features + description: Posts about Hypergraph features and updates + +knowledge-graphs: + label: Knowledge Graphs + permalink: /knowledge-graphs + description: Articles about knowledge graph concepts, best practices, and implementation + +education: + label: Education + permalink: /education + description: Educational content and tutorials + +best-practices: + label: Best Practices + permalink: /best-practices + description: Guidelines, conventions, and recommended practices + +grc20: + label: GRC-20 + permalink: /grc20 + description: Content related to the GRC-20 knowledge graph specification diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 50b2b66f..467eddd1 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -49,6 +49,7 @@ const config = { }, blog: { showReadingTime: true, + blogSidebarCount: 'ALL', feedOptions: { type: ['rss', 'atom'], xslt: true, From fae5500a71eaf20c5f26833eeaeb9076a7aff52f Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 12:57:27 -0400 Subject: [PATCH 14/18] docs: update blog titles and content to reflect Hypergraph integration and enhance clarity --- docs/blog/2025-06-10-entities-and-types.md | 6 +++--- docs/blog/2025-06-10-knowledge-graph-best-practices.md | 6 +++--- docs/blog/2025-06-10-properties-and-relations.md | 6 +++--- docs/blog/2025-06-10-serialization-and-encoding.md | 6 +++--- docs/blog/2025-06-10-spaces-and-governance.md | 6 +++--- docs/blog/2025-06-10-uuids-and-identifiers.md | 6 +++--- docs/blog/2025-06-11-hypergraph-alpha-released.md | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/blog/2025-06-10-entities-and-types.md b/docs/blog/2025-06-10-entities-and-types.md index 1bcab49d..cddb19e5 100644 --- a/docs/blog/2025-06-10-entities-and-types.md +++ b/docs/blog/2025-06-10-entities-and-types.md @@ -1,16 +1,16 @@ --- slug: understanding-entities-and-types -title: "1. Understanding Entities and Types in GRC-20" +title: "1. Modeling Entities and Types in Hypergraph with GRC-20" date: 2025-06-10 series_position: 1 authors: [nik] -tags: [knowledge-graphs, education, grc20] +tags: [knowledge-graphs, education, grc20, hypergraph] --- > **Series:** GRC-20 Knowledge Graph (Part 1 of 6) > **Next:** [Properties and Relations in GRC-20 →](/blog/properties-and-relations-in-grc20) -The GRC-20 specification introduces a standardized way to represent knowledge in The Graph ecosystem. At its core are two fundamental concepts: Entities and Types. Let's explore how these building blocks work together to create a flexible and powerful knowledge graph system. +Hypergraph is an open-source framework that lets you build and query decentralized knowledge graphs using the GRC-20 standard. In this first tutorial, we'll see how Hypergraph represents **Entities** and **Types** and why they are the foundation of any knowledge graph you create. diff --git a/docs/blog/2025-06-10-knowledge-graph-best-practices.md b/docs/blog/2025-06-10-knowledge-graph-best-practices.md index 08a90e22..a544677b 100644 --- a/docs/blog/2025-06-10-knowledge-graph-best-practices.md +++ b/docs/blog/2025-06-10-knowledge-graph-best-practices.md @@ -1,16 +1,16 @@ --- slug: grc20-knowledge-graph-best-practices -title: "6. Best Practices for Building GRC-20 Knowledge Graphs" +title: "6. Best Practices for Building Knowledge Graphs with Hypergraph" date: 2025-06-05 series_position: 6 authors: [nik] -tags: [knowledge-graphs, education, grc20, best-practices] +tags: [knowledge-graphs, education, grc20, hypergraph, best-practices] --- > **Series:** GRC-20 Knowledge Graph (Part 6 of 6) > **Previous:** [← Spaces & Governance](/blog/grc20-spaces-and-governance) -This post outlines key best practices and guidelines for implementing GRC-20 compliant systems. +You've now seen how Hypergraph implements every facet of the GRC-20 spec. In this final article we'll summarize best practices, design tips, and performance tricks for shipping production-grade knowledge graphs with the Hypergraph toolkit. diff --git a/docs/blog/2025-06-10-properties-and-relations.md b/docs/blog/2025-06-10-properties-and-relations.md index 0d0aeadd..785664c6 100644 --- a/docs/blog/2025-06-10-properties-and-relations.md +++ b/docs/blog/2025-06-10-properties-and-relations.md @@ -1,17 +1,17 @@ --- slug: properties-and-relations-in-grc20 -title: "2. Properties and Relations in GRC-20: Building Connected Knowledge" +title: "2. Defining Properties & Relations" date: 2025-06-09 series_position: 2 authors: [nik] -tags: [knowledge-graphs, education, grc20] +tags: [knowledge-graphs, education, grc20, hypergraph] --- > **Series:** GRC-20 Knowledge Graph (Part 2 of 6) > **Previous:** [← Entities & Types](/blog/understanding-entities-and-types) > **Next:** [UUIDs & Identifiers →](/blog/grc20-uuids-and-identifiers) -The GRC-20 specification defines a robust system for representing properties and relations in knowledge graphs. Let's explore how these components work together to create rich, interconnected data structures that are both flexible and standardized. +In the previous post we learned how Hypergraph models entities and types. Now we'll see how Hypergraph attaches **Properties** to entities and creates **Relations** between them, enabling rich, connected knowledge graphs while staying compliant with the GRC-20 standard. diff --git a/docs/blog/2025-06-10-serialization-and-encoding.md b/docs/blog/2025-06-10-serialization-and-encoding.md index e6fc10d0..7bf1c19e 100644 --- a/docs/blog/2025-06-10-serialization-and-encoding.md +++ b/docs/blog/2025-06-10-serialization-and-encoding.md @@ -1,17 +1,17 @@ --- slug: grc20-serialization-and-encoding -title: "4. Serialization and Encoding in GRC-20" +title: "4. Serialization & Encoding" date: 2025-06-07 series_position: 4 authors: [nik] -tags: [knowledge-graphs, education, grc20] +tags: [knowledge-graphs, education, grc20, hypergraph] --- > **Series:** GRC-20 Knowledge Graph (Part 4 of 6) > **Previous:** [← UUIDs & Identifiers](/blog/grc20-uuids-and-identifiers) > **Next:** [Spaces & Governance →](/blog/grc20-spaces-and-governance) -Let's explore the details of how data is encoded and transmitted in GRC-20. +Under the hood, Hypergraph stores and transmits data using Protocol Buffers and JSON exactly as defined by the GRC-20 spec. This article shows you how Hypergraph handles serialization so you can interface with it from any language. diff --git a/docs/blog/2025-06-10-spaces-and-governance.md b/docs/blog/2025-06-10-spaces-and-governance.md index e07eafee..2ca4f655 100644 --- a/docs/blog/2025-06-10-spaces-and-governance.md +++ b/docs/blog/2025-06-10-spaces-and-governance.md @@ -1,17 +1,17 @@ --- slug: grc20-spaces-and-governance -title: "5. Understanding Spaces and Governance in GRC-20" +title: "5. Spaces & Governance" date: 2025-06-06 series_position: 5 authors: [nik] -tags: [knowledge-graphs, education, grc20] +tags: [knowledge-graphs, education, grc20, hypergraph] --- > **Series:** GRC-20 Knowledge Graph (Part 5 of 6) > **Previous:** [← Serialization & Encoding](/blog/grc20-serialization-and-encoding) > **Next:** [Best Practices →](/blog/grc20-knowledge-graph-best-practices) -The GRC-20 specification introduces the concept of **Spaces** as a way to organize and govern knowledge graphs. In this post, we'll explore how spaces work and how they enable different governance models for managing knowledge. +Hypergraph lets you segment knowledge graphs into **Spaces**—isolated domains with their own governance and access rules—while still allowing inter-space linking via GRC-20 UUIDs. In this post we'll explore how to create and govern spaces in Hypergraph. diff --git a/docs/blog/2025-06-10-uuids-and-identifiers.md b/docs/blog/2025-06-10-uuids-and-identifiers.md index 2ffa6a07..c04dc2dd 100644 --- a/docs/blog/2025-06-10-uuids-and-identifiers.md +++ b/docs/blog/2025-06-10-uuids-and-identifiers.md @@ -1,17 +1,17 @@ --- slug: grc20-uuids-and-identifiers -title: "3. Working with UUIDs and Identifiers in GRC-20" +title: "3. Managing UUIDs & Identifiers" date: 2025-06-08 series_position: 3 authors: [nik] -tags: [knowledge-graphs, education, grc20] +tags: [knowledge-graphs, education, grc20, hypergraph] --- > **Series:** GRC-20 Knowledge Graph (Part 3 of 6) > **Previous:** [← Properties & Relations](/blog/properties-and-relations-in-grc20) > **Next:** [Serialization & Encoding →](/blog/grc20-serialization-and-encoding) -The GRC-20 specification uses UUID version 4 as the foundation for all identifiers in the knowledge graph system. Understanding how to work with these identifiers is crucial for building interoperable applications. Let's dive into the details of GRC-20's UUID implementation. +Hypergraph relies on UUID v4 identifiers defined by GRC-20 to guarantee global uniqueness without centralized coordination. In this post we'll look at how Hypergraph generates, stores, and uses these UUIDs so your applications stay conflict-free and interoperable. diff --git a/docs/blog/2025-06-11-hypergraph-alpha-released.md b/docs/blog/2025-06-11-hypergraph-alpha-released.md index f1e4dff9..55ee5c3c 100644 --- a/docs/blog/2025-06-11-hypergraph-alpha-released.md +++ b/docs/blog/2025-06-11-hypergraph-alpha-released.md @@ -58,6 +58,6 @@ We read every message and your feedback directly shapes our roadmap. ## Ready to Shape the Future? -This is just the beginning. Hypergraph Alpha represents our vision for the future of Web3 development, but it's your creativity and feedback that will help us realize its full potential. [Get started with the Quickstart](/docs/quickstart), explore our [API Reference](/docs/api-reference), and join us in building the next generation of collaborative, decentralized applications. +This is just the beginning. Hypergraph represents our vision for the future of Web3 development, but it's your creativity and feedback that will help us realize its full potential. [Get started with the Quickstart](/docs/quickstart), explore our [API Reference](/docs/api-reference), read the [Hypergraph Knowledge Graph series](/blog/understanding-entities-and-types), and join us in building the next generation of collaborative, decentralized applications. We can't wait to see what you'll create. From 41413554647841a7dc9dc5708aea500f8c66261c Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 12:58:48 -0400 Subject: [PATCH 15/18] docs: remove outdated blog posts on serialization and entities to streamline content --- docs/blog/2025-06-10-entities-and-types.md | 115 -------- ...25-06-10-knowledge-graph-best-practices.md | 227 --------------- .../2025-06-10-properties-and-relations.md | 160 ----------- .../2025-06-10-serialization-and-encoding.md | 126 --------- docs/blog/2025-06-10-spaces-and-governance.md | 267 ------------------ docs/blog/2025-06-10-uuids-and-identifiers.md | 168 ----------- 6 files changed, 1063 deletions(-) delete mode 100644 docs/blog/2025-06-10-entities-and-types.md delete mode 100644 docs/blog/2025-06-10-knowledge-graph-best-practices.md delete mode 100644 docs/blog/2025-06-10-properties-and-relations.md delete mode 100644 docs/blog/2025-06-10-serialization-and-encoding.md delete mode 100644 docs/blog/2025-06-10-spaces-and-governance.md delete mode 100644 docs/blog/2025-06-10-uuids-and-identifiers.md diff --git a/docs/blog/2025-06-10-entities-and-types.md b/docs/blog/2025-06-10-entities-and-types.md deleted file mode 100644 index cddb19e5..00000000 --- a/docs/blog/2025-06-10-entities-and-types.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -slug: understanding-entities-and-types -title: "1. Modeling Entities and Types in Hypergraph with GRC-20" -date: 2025-06-10 -series_position: 1 -authors: [nik] -tags: [knowledge-graphs, education, grc20, hypergraph] ---- - -> **Series:** GRC-20 Knowledge Graph (Part 1 of 6) -> **Next:** [Properties and Relations in GRC-20 →](/blog/properties-and-relations-in-grc20) - -Hypergraph is an open-source framework that lets you build and query decentralized knowledge graphs using the GRC-20 standard. In this first tutorial, we'll see how Hypergraph represents **Entities** and **Types** and why they are the foundation of any knowledge graph you create. - - - -## Entities: The Foundation - -In GRC-20, entities are the fundamental building blocks that represent any identifiable thing in the knowledge graph. Each entity has: - -- A globally unique UUID4 identifier -- A set of values (key-value pairs) -- Optional relations to other entities - -For example, an entity could represent: -- A person (like Albert Einstein) -- A place (like Paris) -- An organization (like NASA) -- An abstract concept (like Relativity) - -### Entity Structure - -The core entity structure in GRC-20 is elegantly simple: - -```proto -message Entity { - bytes id = 1; // UUID4 - repeated Value values = 2; -} -``` - -Each value attached to an entity includes: -- A property reference (UUID) -- The actual value (as a UTF-8 string) -- Optional type-specific metadata - -## Types: Providing Structure - -Types in GRC-20 serve as classification mechanisms that help organize entities and define their expected properties. The type system is designed to be: - -- Flexible but structured -- Composable through inheritance -- Evolution-friendly - -### Key Features of Types - -1. **Implicit Entity Type** - - Every node automatically has the base Entity type - - No explicit declaration needed - -2. **Type Relations** - - Types are connected through "broader types" relations - - Creates a natural hierarchy of classifications - -3. **Property Inheritance** - - Types can define expected properties - - Subtypes inherit properties from their broader types - -### Built-in Type UUIDs - -The specification defines several core type identifiers: - -``` -Type (schema): e7d737c5-3676-4c60-9fa1-6aa64a8c90ad -Property Type: 808a04ce-b21c-4d88-8ad1-2e240613e5ca -Space Type: 362c1dbd-dc64-44bb-a3c4-652f38a642d7 -``` - -## Why This Matters - -The GRC-20 approach to entities and types enables: - -1. **Flexible Knowledge Representation** - - Any concept can be modeled as an entity - - Types provide structure without rigid constraints - -2. **Natural Evolution** - - New types can be added without breaking existing ones - - Properties can evolve independently - -3. **Interoperability** - - Standard UUID-based identification - - Consistent serialization format - - Cross-space references - -4. **Web3 Native Design** - - Built for decentralized networks - - No dependence on centralized authorities - - Blockchain-friendly identifiers - -## Learn More - -This post covers just the basics of entities and types in GRC-20. For the complete specification, including detailed protobuf schemas and implementation guidelines, check out the [full GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). - -## Best Practices - -When working with GRC-20 entities and types: - -1. Always use UUID4 for identifiers -2. Consider type hierarchies carefully -3. Keep entities focused and atomic -4. Use relations to express connections -5. Follow the protobuf serialization format - -The GRC-20 specification represents a major step forward in standardizing knowledge representation for Web3. By understanding entities and types, you're well on your way to building interoperable, decentralized knowledge systems. \ No newline at end of file diff --git a/docs/blog/2025-06-10-knowledge-graph-best-practices.md b/docs/blog/2025-06-10-knowledge-graph-best-practices.md deleted file mode 100644 index a544677b..00000000 --- a/docs/blog/2025-06-10-knowledge-graph-best-practices.md +++ /dev/null @@ -1,227 +0,0 @@ ---- -slug: grc20-knowledge-graph-best-practices -title: "6. Best Practices for Building Knowledge Graphs with Hypergraph" -date: 2025-06-05 -series_position: 6 -authors: [nik] -tags: [knowledge-graphs, education, grc20, hypergraph, best-practices] ---- - -> **Series:** GRC-20 Knowledge Graph (Part 6 of 6) -> **Previous:** [← Spaces & Governance](/blog/grc20-spaces-and-governance) - -You've now seen how Hypergraph implements every facet of the GRC-20 spec. In this final article we'll summarize best practices, design tips, and performance tricks for shipping production-grade knowledge graphs with the Hypergraph toolkit. - - - -## Core Implementation Guidelines - -### 1. UUID Management - -GRC-20 requires UUID version 4 for all identifiers: - -- Use cryptographically secure random number generators -- Store as 16-byte arrays in wire format -- Display as 36-character lowercase hex strings with dashes -- Never reuse or manually generate UUIDs - -Example UUID format: -``` -2a5fe010-078b-4ad6-8a61-7272f33729f4 -``` - -### 2. Value Type Handling - -When working with GRC-20's native value types: - -1. **Text Values** - - Always use UTF-8 encoding - - Include language tags when relevant - - Support Markdown where appropriate - -2. **Number Values** - - Use decimal string representation - - Include unit and format metadata - - No commas or currency symbols inline - -3. **Time Values** - - Use ISO-8601 format - - Include timezone information - - Support both dates and times - -4. **URL Values** - - Validate protocol prefixes (ipfs://, https://, etc.) - - Ensure URI syntax compliance - - Handle cross-space references properly - -## Space Management - -### 1. Space Categories - -Choose the appropriate space type for your use case: - -- **Public Spaces** - - Onchain governance - - Public visibility - - Community participation - -- **Personal Spaces** - - Individual control - - Public visibility - - Centralized management - -- **Private Spaces** - - Local-first operation - - Peer-to-peer sharing - - Encrypted when needed - -### 2. Cross-Space References - -When linking across spaces: - -```proto -message Relation { - // Required fields - bytes id = 1; - bytes type = 2; - bytes from_entity = 3; - bytes to_entity = 6; - - // Cross-space reference fields - optional bytes from_space = 4; - optional bytes from_version = 5; - optional bytes to_space = 7; - optional bytes to_version = 8; -} -``` - -- Always include space IDs for external references -- Track versions when stability is important -- Use the verified flag appropriately - -## Data Evolution & Migration - -### 1. Edit Structure - -Package changes effectively: - -```proto -message Edit { - bytes id = 1; // Edit UUID - string name = 2; // Descriptive summary - repeated Op ops = 3; // Ordered operations - repeated bytes authors = 4; // Contributor IDs - optional bytes language = 5; // Default language -} -``` - -- Group related changes in single edits -- Provide clear edit descriptions -- Maintain proper operation ordering - -### 2. Import Process - -For migrating or bootstrapping spaces: - -1. Generate ImportEdit messages -2. Upload to content-addressed storage -3. Create Import manifest -4. Anchor on the target chain - -```proto -message ImportEdit { - // Standard edit fields - bytes id = 1; - string name = 2; - repeated Op ops = 3; - - // Migration metadata - bytes created_by = 5; - string created_at = 6; - bytes block_hash = 7; - string block_number = 8; - bytes transaction_hash = 9; -} -``` - -## Content Type Handling - -### 1. Image Entities - -When working with images: - -- Store binary data off-chain -- Include width and height metadata -- Use appropriate IPFS/URI references -- Follow recommended dimensions (2384 × 640 px for covers) - -### 2. Block Relations - -For rich content organization: - -- Use ordered block relations -- Maintain proper position values -- Support various content types -- Enable flexible composition - -## System Properties - -Always respect system-maintained properties: - -1. **Temporal Metadata** - - Created at - - Updated at - - Version history - -2. **Attribution** - - Created by - - Author tracking - - Space ownership - -3. **Implicit Fields** - - Name - - Description - - Types - - Cover - - Blocks - -## Serialization Best Practices - -### 1. Protobuf Usage - -- Follow proto3 syntax exactly -- Use bytes for UUIDs -- Handle optional fields appropriately -- Maintain backward compatibility - -### 2. JSON Representation - -For API endpoints and debugging: - -```json -{ - "id": "2a5fe010-078b-4ad6-8a61-7272f33729f4", - "type": "e7d737c5-3676-4c60-9fa1-6aa64a8c90ad", - "values": [ - { - "property": "a126ca53-0c8e-48d5-b888-82c734c38935", - "value": "Example Entity" - } - ] -} -``` - -- Use consistent UUID formatting -- Include only present optional fields -- Follow the specified naming conventions - -## Learn More - -For complete implementation details, refer to the [GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). The specification includes: - -- Full protobuf schemas -- UUID constants -- Serialization formats -- Implementation guidelines - -By following these best practices, you'll build robust, interoperable knowledge graphs that work seamlessly within The Graph ecosystem while maintaining compatibility with the broader web3 landscape. \ No newline at end of file diff --git a/docs/blog/2025-06-10-properties-and-relations.md b/docs/blog/2025-06-10-properties-and-relations.md deleted file mode 100644 index 785664c6..00000000 --- a/docs/blog/2025-06-10-properties-and-relations.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -slug: properties-and-relations-in-grc20 -title: "2. Defining Properties & Relations" -date: 2025-06-09 -series_position: 2 -authors: [nik] -tags: [knowledge-graphs, education, grc20, hypergraph] ---- - -> **Series:** GRC-20 Knowledge Graph (Part 2 of 6) -> **Previous:** [← Entities & Types](/blog/understanding-entities-and-types) -> **Next:** [UUIDs & Identifiers →](/blog/grc20-uuids-and-identifiers) - -In the previous post we learned how Hypergraph models entities and types. Now we'll see how Hypergraph attaches **Properties** to entities and creates **Relations** between them, enabling rich, connected knowledge graphs while staying compliant with the GRC-20 standard. - - - -## Properties in GRC-20 - -Properties in GRC-20 are first-class entities that define attributes and their characteristics. Each property entity includes: - -- A unique UUID4 identifier -- A value type specification -- Optional metadata (unit, format, language requirements) - -### Native Value Types - -GRC-20 defines six built-in value types: - -| Type | UUID | Description | -|----------|----------------------------------------|-------------------------------| -| Text | 9edb6fcc-e454-4aa5-8611-39d7f024c010 | Unicode character sequences | -| Number | 9b597aae-c31c-46c8-8565-a370da0c2a65 | Decimal numeric values | -| Checkbox | 7aa4792e-eacd-4186-8272-fa7fc18298ac | Boolean true/false | -| URL | 283127c9-6142-4684-92ed-90b0ebc7f29a | URIs with protocol prefix | -| Time | 167664f6-68f8-40e1-976b-20bd16ed8d47 | ISO-8601 timestamps | -| Point | df250d17-e364-413d-9779-2ddaae841e34 | Coordinate pairs or vectors | - -### Value Options - -Properties can specify additional metadata through options: - -```proto -message Options { - oneof value { - TextOptions text = 1; - NumberOptions number = 2; - TimeOptions time = 3; - } -} -``` - -These options enable features like: -- Language tags for text -- Formatting strings for numbers -- Timezone and format specifications for timestamps - -## Relations: The Connective Tissue - -Relations in GRC-20 are sophisticated edges that can carry their own properties and metadata. They consist of two parts: - -1. A lightweight relation record -2. An optional relation entity for additional properties - -### Relation Structure - -```proto -message Relation { - bytes id = 1; // relation UUID4 - bytes type = 2; // relation-type UUID4 - bytes from_entity = 3; // source entity UUID4 - optional bytes from_space = 4; // source Space UUID4 - optional bytes from_version = 5; // source Edit/Version UUID4 - bytes to_entity = 6; // target entity UUID4 - optional bytes to_space = 7; // target Space UUID4 - optional bytes to_version = 8; // target Edit/Version UUID4 - bytes entity = 9; // relation entity UUID4 - optional string position = 10; // ordering key - optional bool verified = 11; // trust flag -} -``` - -### Key Features - -1. **Cross-Space References** - - Relations can link entities across different spaces - - Optional space and version tracking - - Verification status for trust - -2. **Ordered Collections** - - `position` field enables stable ordering - - Useful for lists, sequences, and rankings - -3. **Rich Metadata** - - Relation entities can carry additional properties - - Full entity capabilities for relationship data - -## System Properties - -GRC-20 defines several system-level properties that are automatically maintained: - -1. **Creation Metadata** - - Created at timestamp - - Created by (blockchain address) - -2. **Update Tracking** - - Updated at timestamp - - Version history - -3. **Implicit Properties** - - Name - - Types - - Description - - Cover - - Blocks - -## Best Practices - -When working with GRC-20 properties and relations: - -1. **Property Design** - - Use native value types when possible - - Include appropriate options metadata - - Consider property reusability - -2. **Relation Management** - - Use relation entities for complex relationships - - Maintain proper ordering with position keys - - Track cross-space references carefully - -3. **Data Validation** - - Ensure values match their declared types - - Handle language tags appropriately - - Validate URIs and timestamps - -## Implementation Example - -Here's how you might represent a simple property-relation combination: - -```json -{ - "property": { - "id": "6ab0887f-b6c1-4628-9eee-2234a247c1d2", - "type": "808a04ce-b21c-4d88-8ad1-2e240613e5ca", // Property Type - "value_type": "9edb6fcc-e454-4aa5-8611-39d7f024c010" // Text Type - }, - "relation": { - "id": "29785ffb-5ce6-4a9b-b0dc-b138328ba334", - "type": "0509279a-713d-4667-a412-24fe3757f554", - "from_entity": "2a5fe010-078b-4ad6-8a61-7272f33729f4", - "to_entity": "386d9dde-4c10-4099-af42-0e946bf2f199" - } -} -``` - -## Learn More - -For complete details on properties, relations, and their implementation, refer to the [GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). The specification includes full protobuf schemas, serialization formats, and detailed guidelines for building compliant systems. - -Properties and relations form the foundation of GRC-20's ability to represent rich, interconnected knowledge in a standardized way. By following these patterns, you can build robust, interoperable knowledge graphs that work seamlessly across the decentralized web. \ No newline at end of file diff --git a/docs/blog/2025-06-10-serialization-and-encoding.md b/docs/blog/2025-06-10-serialization-and-encoding.md deleted file mode 100644 index 7bf1c19e..00000000 --- a/docs/blog/2025-06-10-serialization-and-encoding.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -slug: grc20-serialization-and-encoding -title: "4. Serialization & Encoding" -date: 2025-06-07 -series_position: 4 -authors: [nik] -tags: [knowledge-graphs, education, grc20, hypergraph] ---- - -> **Series:** GRC-20 Knowledge Graph (Part 4 of 6) -> **Previous:** [← UUIDs & Identifiers](/blog/grc20-uuids-and-identifiers) -> **Next:** [Spaces & Governance →](/blog/grc20-spaces-and-governance) - -Under the hood, Hypergraph stores and transmits data using Protocol Buffers and JSON exactly as defined by the GRC-20 spec. This article shows you how Hypergraph handles serialization so you can interface with it from any language. - - - -## Protocol Buffers: The Core Format - -### Why Protocol Buffers? - -GRC-20 chose Protocol Buffers for several reasons: - -1. **Efficiency**: Compact binary format -2. **Schema Evolution**: Backward/forward compatibility -3. **Language Agnostic**: Wide platform support -4. **Type Safety**: Strong typing and validation -5. **Performance**: Fast serialization/deserialization - -### Core Message Types - -Here are the fundamental protobuf messages in GRC-20: - -```proto -syntax = "proto3"; -package grc20; - -message Entity { - bytes id = 1; // UUID4 (16 bytes) - repeated Value values = 2; // Property values -} - -message Value { - bytes property = 1; // Property UUID - string value = 2; // UTF-8 literal - oneof options { - TextOptions text_options = 3; - NumberOptions number_options = 4; - TimeOptions time_options = 5; - } -} - -message Relation { - bytes id = 1; - bytes type = 2; - bytes from_entity = 3; - optional bytes from_space = 4; - optional bytes from_version = 5; - bytes to_entity = 6; - optional bytes to_space = 7; - optional bytes to_version = 8; - bytes entity = 9; - optional string position = 10; - optional bool verified = 11; -} -``` - -## JSON Representation - -While protobuf is used for wire format, JSON is useful for: -- API responses -- Debugging and inspection -- Human-readable storage -- Documentation - -### JSON Conversion Rules - -When converting protobuf messages to JSON: - -1. **UUID Fields** - - Convert 16-byte arrays to lowercase hex strings with dashes - - Example: `"2a5fe010-078b-4ad6-8a61-7272f33729f4"` - -2. **Repeated Fields** - - Represent as JSON arrays - - Preserve order exactly - -3. **Optional Fields** - - Omit if not present - - Never use null values - -4. **Oneof Fields** - - Include only the present option - - Use camelCase naming - -### Example JSON Formats - -#### Entity - -```json -{ - "id": "2a5fe010-078b-4ad6-8a61-7272f33729f4", - "values": [ - { - "property": "a126ca53-0c8e-48d5-b888-82c734c38935", - "value": "Example Entity", - "textOptions": { - "language": "en" - } - } - ] -} -``` - -#### Relation - -```json -{ - "id": "29785ffb-5ce6-4a9b-b0dc-b138328ba334", - "type": "0509279a-713d-4667-a412-24fe3757f554", - "fromEntity": "2a5fe010-078b-4ad6-8a61-7272f33729f4", - "toEntity": "386d9dde-4c10-4099-af42-0e946bf2f199", - "position": "a", - "verified": true -} -``` \ No newline at end of file diff --git a/docs/blog/2025-06-10-spaces-and-governance.md b/docs/blog/2025-06-10-spaces-and-governance.md deleted file mode 100644 index 2ca4f655..00000000 --- a/docs/blog/2025-06-10-spaces-and-governance.md +++ /dev/null @@ -1,267 +0,0 @@ ---- -slug: grc20-spaces-and-governance -title: "5. Spaces & Governance" -date: 2025-06-06 -series_position: 5 -authors: [nik] -tags: [knowledge-graphs, education, grc20, hypergraph] ---- - -> **Series:** GRC-20 Knowledge Graph (Part 5 of 6) -> **Previous:** [← Serialization & Encoding](/blog/grc20-serialization-and-encoding) -> **Next:** [Best Practices →](/blog/grc20-knowledge-graph-best-practices) - -Hypergraph lets you segment knowledge graphs into **Spaces**—isolated domains with their own governance and access rules—while still allowing inter-space linking via GRC-20 UUIDs. In this post we'll explore how to create and govern spaces in Hypergraph. - - - -## What is a Space? - -A Space in GRC-20 is a logical domain that encapsulates: -- A self-contained knowledge graph -- Governance rules and access controls -- Anchoring and versioning mechanisms - -Every space has its own UUID and can be referenced by other spaces, enabling a web of interconnected knowledge while maintaining clear boundaries and control. - -## Types of Spaces - -GRC-20 defines three categories of spaces, each serving different needs: - -### 1. Public Spaces - -- **Governance**: Onchain, community-driven -- **Visibility**: Public -- **Control**: Determined by smart contracts -- **Use Cases**: - - Open knowledge bases - - Community-curated datasets - - Public standards and specifications - -### 2. Personal Spaces - -- **Governance**: Centralized -- **Visibility**: Public -- **Control**: Individual or organization -- **Use Cases**: - - Personal blogs - - Portfolio sites - - Organization documentation - -### 3. Private Spaces - -- **Governance**: Local or group-based -- **Visibility**: Private -- **Control**: Device-level or encrypted sharing -- **Use Cases**: - - Personal notes - - Team collaboration - - Private research - -## Space Implementation - -### Core Type Definition - -Every space is an entity with the Space type: - -```typescript -const SPACE_TYPE_UUID = "362c1dbd-dc64-44bb-a3c4-652f38a642d7" -``` - -### Space Hierarchy - -Spaces can form hierarchies through relations: - -```typescript -interface SpaceRelations { - broaderSpaces: string[] // Parent space UUIDs - subspaces: string[] // Child space UUIDs -} -``` - -This enables: -- Organizing knowledge in logical trees -- Inheriting governance rules -- Maintaining context across spaces - -## Governance Models - -### Public Space Governance - -Public spaces use smart contracts to enforce: - -1. **Proposal Submission** - - Who can propose changes - - Required stake or reputation - - Proposal formats - -2. **Voting** - - Voting periods - - Quorum requirements - - Vote weight calculation - -3. **Execution** - - Automatic vs manual execution - - Timelock periods - - Emergency procedures - -Example smart contract interface: - -```solidity -interface IPublicSpace { - function propose(bytes32 editCid, string calldata description) external; - function vote(uint256 proposalId, bool support) external; - function execute(uint256 proposalId) external; - function getProposal(uint256 proposalId) external view returns (Proposal memory); -} -``` - -### Personal Space Controls - -Personal spaces use simpler control mechanisms: - -```typescript -interface PersonalSpaceControls { - owner: string // Controller address - delegates?: string[] // Optional additional writers - readAccess: "public" // Always public in personal spaces - writeAccess: "owner" // Only owner + delegates can write -} -``` - -### Private Space Security - -Private spaces focus on encryption and sharing: - -```typescript -interface PrivateSpaceConfig { - encryptionKey: CryptoKey - allowedMembers: string[] - syncMode: "p2p" | "local" - backupStrategy?: "ipfs" | "none" -} -``` - -## Space Creation and Evolution - -### Creating a New Space - -1. Generate a UUID for the space -2. Define its type (public/personal/private) -3. Set up governance structure -4. Initialize empty graph state -5. Begin accepting edits - -Example creation flow: - -```typescript -async function createPublicSpace(config: SpaceConfig): Promise { - // Generate space UUID - const spaceId = generateUuid() - - // Deploy governance contract - const contract = await deploySpaceContract(config.governance) - - // Initialize space entity - const space = { - id: spaceId, - type: SPACE_TYPE_UUID, - contract: contract.address, - values: [ - { property: "name", value: config.name }, - { property: "description", value: config.description } - ] - } - - // Anchor initial state - await anchorSpace(space) - - return space -} -``` - -### Converting Existing Entities - -Any entity can evolve into a space: - -1. Choose the target entity -2. Deploy appropriate contracts/controls -3. Bind the entity to governance -4. Migrate existing content - -```typescript -async function convertToSpace(entityId: string, config: SpaceConfig): Promise { - // Verify entity exists - const entity = await getEntity(entityId) - - // Set up governance - const governance = await setupGovernance(config) - - // Add space type - await addEntityType(entityId, SPACE_TYPE_UUID) - - // Bind to governance - await bindEntityToGovernance(entityId, governance) - - return loadSpace(entityId) -} -``` - -## Cross-Space Interactions - -### References - -When linking across spaces: - -```typescript -interface CrossSpaceReference { - fromEntity: string - fromSpace: string - toEntity: string - toSpace: string - verified: boolean -} -``` - -### Trust and Verification - -Spaces can mark cross-space references as verified: - -```typescript -async function verifyReference(ref: CrossSpaceReference) { - // Check if source space trusts target - const trusted = await checkSpaceTrust(ref.fromSpace, ref.toSpace) - - if (trusted) { - await markReferenceVerified(ref) - } -} -``` - -## Best Practices - -1. **Space Planning** - - Choose the right space type for your use case - - Plan governance structure before creation - - Consider future growth and evolution - -2. **Access Control** - - Use appropriate permission levels - - Implement proper key management - - Regular security audits - -3. **Cross-Space Relations** - - Verify external references - - Track space versions - - Handle missing spaces gracefully - -4. **Performance** - - Cache frequently accessed data - - Batch updates when possible - - Monitor space size and growth - -## Learn More - -For complete details on spaces and governance in GRC-20, including protobuf schemas and smart contract interfaces, check out the [full GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). - -Spaces are a powerful mechanism for organizing and controlling knowledge in GRC-20. By understanding their capabilities and choosing the right model for your needs, you can build robust and secure knowledge graph applications. \ No newline at end of file diff --git a/docs/blog/2025-06-10-uuids-and-identifiers.md b/docs/blog/2025-06-10-uuids-and-identifiers.md deleted file mode 100644 index c04dc2dd..00000000 --- a/docs/blog/2025-06-10-uuids-and-identifiers.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -slug: grc20-uuids-and-identifiers -title: "3. Managing UUIDs & Identifiers" -date: 2025-06-08 -series_position: 3 -authors: [nik] -tags: [knowledge-graphs, education, grc20, hypergraph] ---- - -> **Series:** GRC-20 Knowledge Graph (Part 3 of 6) -> **Previous:** [← Properties & Relations](/blog/properties-and-relations-in-grc20) -> **Next:** [Serialization & Encoding →](/blog/grc20-serialization-and-encoding) - -Hypergraph relies on UUID v4 identifiers defined by GRC-20 to guarantee global uniqueness without centralized coordination. In this post we'll look at how Hypergraph generates, stores, and uses these UUIDs so your applications stay conflict-free and interoperable. - - - -## Why UUID4? - -GRC-20 chose UUID version 4 (random) for several key reasons: - -1. **Decentralization**: No central coordination needed -2. **Collision resistance**: 2⁻¹²² probability of collision -3. **Standardization**: Well-defined in RFC 4122 -4. **Efficiency**: Compact 16-byte representation -5. **Interoperability**: Wide language/platform support - -## Core UUID Constants - -GRC-20 defines several fundamental UUIDs that every implementation must know: - -```typescript -// Core Types -const TYPE_UUID = "e7d737c5-3676-4c60-9fa1-6aa64a8c90ad" -const PROPERTY_TYPE_UUID = "808a04ce-b21c-4d88-8ad1-2e240613e5ca" -const SPACE_TYPE_UUID = "362c1dbd-dc64-44bb-a3c4-652f38a642d7" - -// Native Value Types -const TEXT_TYPE = "9edb6fcc-e454-4aa5-8611-39d7f024c010" -const NUMBER_TYPE = "9b597aae-c31c-46c8-8565-a370da0c2a65" -const CHECKBOX_TYPE = "7aa4792e-eacd-4186-8272-fa7fc18298ac" -const URL_TYPE = "283127c9-6142-4684-92ed-90b0ebc7f29a" -const TIME_TYPE = "167664f6-68f8-40e1-976b-20bd16ed8d47" -const POINT_TYPE = "df250d17-e364-413d-9779-2ddaae841e34" -``` - -## Working with UUIDs - -### Binary (Wire) Format - -When transmitting UUIDs in protobuf messages, use raw 16-byte arrays: - -```proto -message Entity { - bytes id = 1; // 16 bytes, network byte order - // ... -} -``` - -### String Representation - -For human readability and JSON interfaces, use the canonical 36-character format: - -```typescript -// Example UUID string -const entityId = "2a5fe010-078b-4ad6-8a61-7272f33729f4" -``` - -### Converting Legacy IDs - -If you're migrating from an existing system with its own ID format, follow this process: - -1. Take your original ID string -2. UTF-8 encode it -3. Compute its MD5 hash -4. Use the 16-byte digest to seed a UUID4 generator -5. Set version (4) and variant bits per RFC 4122 - -This ensures deterministic, stable UUIDs for your existing identifiers. - -## Best Practices - -1. **Generation** - - Always use cryptographically secure random number generators - - Verify version 4 and variant bits are correctly set - - Don't try to generate UUIDs manually - -2. **Storage** - - Store as 16-byte arrays in databases - - Index UUID columns for efficient lookups - - Consider UUID-optimized database types - -3. **Validation** - - Check length (16 bytes or 36 chars) - - Verify version 4 bit pattern - - Validate hex digits and dash positions in strings - -4. **Cross-Space References** - - Include space IDs when referencing external entities - - Track versions for stability - - Use the verified flag appropriately - -## Implementation Example - -Here's a TypeScript example of working with GRC-20 UUIDs: - -```typescript -import { v4 as uuidv4 } from 'uuid' -import { createHash } from 'crypto' - -// Generate a new UUID4 -function generateEntityId(): string { - return uuidv4() -} - -// Convert legacy ID to UUID4 -function legacyIdToUuid(legacyId: string): string { - const hash = createHash('md5') - .update(legacyId) - .digest() - - // Set version 4 and variant bits - hash[6] = (hash[6] & 0x0f) | 0x40 - hash[8] = (hash[8] & 0x3f) | 0x80 - - return formatUuid(hash) -} - -// Format 16 bytes as UUID string -function formatUuid(bytes: Buffer): string { - const hex = bytes.toString('hex') - return [ - hex.slice(0, 8), - hex.slice(8, 12), - hex.slice(12, 16), - hex.slice(16, 20), - hex.slice(20) - ].join('-') -} -``` - -## Common Pitfalls - -1. **String vs Binary** - - Don't mix string and binary formats - - Always be explicit about which format you're using - - Convert at system boundaries only - -2. **Case Sensitivity** - - Always use lowercase for string UUIDs - - Be careful with case-sensitive comparisons - - Normalize input strings - -3. **Validation** - - Don't assume all 16-byte values are valid UUIDs - - Check version and variant bits - - Validate string format thoroughly - -4. **Performance** - - Cache UUID parsing results - - Use binary format for internal operations - - Batch UUID operations when possible - -## Learn More - -For complete details on UUID usage in GRC-20, including protobuf schemas and serialization formats, check out the [full GRC-20 specification](https://forum.thegraph.com/t/grc-20-knowledge-graph/6161). - -The proper handling of UUIDs is fundamental to building robust GRC-20 implementations. By following these guidelines and best practices, you'll ensure your application can reliably participate in the broader knowledge graph ecosystem. \ No newline at end of file From 6b1b494fa4a5b4e19d19c26dbc439404a66cf3f3 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Tue, 10 Jun 2025 12:59:05 -0400 Subject: [PATCH 16/18] docs: refine closing paragraph for clarity and flow in Hypergraph release blog post --- docs/blog/2025-06-11-hypergraph-alpha-released.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blog/2025-06-11-hypergraph-alpha-released.md b/docs/blog/2025-06-11-hypergraph-alpha-released.md index 55ee5c3c..6c70074d 100644 --- a/docs/blog/2025-06-11-hypergraph-alpha-released.md +++ b/docs/blog/2025-06-11-hypergraph-alpha-released.md @@ -58,6 +58,6 @@ We read every message and your feedback directly shapes our roadmap. ## Ready to Shape the Future? -This is just the beginning. Hypergraph represents our vision for the future of Web3 development, but it's your creativity and feedback that will help us realize its full potential. [Get started with the Quickstart](/docs/quickstart), explore our [API Reference](/docs/api-reference), read the [Hypergraph Knowledge Graph series](/blog/understanding-entities-and-types), and join us in building the next generation of collaborative, decentralized applications. +This is just the beginning. Hypergraph represents our vision for the future of Web3 development, but it's your creativity and feedback that will help us realize its full potential. [Get started with the Quickstart](/docs/quickstart), and explore our [API Reference](/docs/api-reference), and join us in building the next generation of collaborative, decentralized applications. We can't wait to see what you'll create. From 00e60404b662fce46af8225ac5e7332e5bf02b6e Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Wed, 11 Jun 2025 09:00:47 -0400 Subject: [PATCH 17/18] Revert pnpm-lock.yaml to match main branch --- pnpm-lock.yaml | 449 ++++++++++++++----------------------------------- 1 file changed, 125 insertions(+), 324 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eba2b444..77ec998f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -371,7 +371,7 @@ importers: version: 4.1.0 effect: specifier: latest - version: 3.16.5 + version: 3.16.3 graphql: specifier: ^16.11.0 version: 16.11.0 @@ -399,28 +399,28 @@ importers: devDependencies: '@effect/cli': specifier: latest - version: 0.63.9(@effect/platform@0.84.9(effect@3.16.5))(@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5))(@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5))(effect@3.16.5) + version: 0.63.4(@effect/platform@0.84.4(effect@3.16.3))(@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3))(@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3))(effect@3.16.3) '@effect/experimental': specifier: latest - version: 0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + version: 0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) '@effect/language-service': specifier: latest - version: 0.19.0 + version: 0.17.1 '@effect/platform': specifier: latest - version: 0.84.9(effect@3.16.5) + version: 0.84.4(effect@3.16.3) '@effect/platform-node': specifier: latest - version: 0.85.13(@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(bufferutil@4.0.9)(effect@3.16.5)(utf-8-validate@5.0.10) + version: 0.84.2(@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(bufferutil@4.0.9)(effect@3.16.3)(utf-8-validate@5.0.10) '@effect/sql': specifier: latest - version: 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + version: 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) '@effect/sql-sqlite-node': specifier: latest - version: 0.38.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(effect@3.16.5) + version: 0.38.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(effect@3.16.3) '@effect/vitest': specifier: latest - version: 0.23.5(effect@3.16.5)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0)) + version: 0.23.3(effect@3.16.3)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0)) '@graphprotocol/grc-20': specifier: ^0.17.0 version: 0.17.0(bufferutil@4.0.9)(graphql@16.11.0)(ox@0.6.7(typescript@5.8.3)(zod@3.24.2))(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2) @@ -492,21 +492,6 @@ importers: '@docusaurus/types': specifier: 3.7.0 version: 3.7.0(acorn@8.14.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@tailwindcss/typography': - specifier: ^0.5.12 - version: 0.5.16(tailwindcss@3.4.17) - autoprefixer: - specifier: ^10.4.16 - version: 10.4.21(postcss@8.5.3) - postcss: - specifier: ^8.4.31 - version: 8.5.3 - tailwindcss: - specifier: ^3.4.4 - version: 3.4.17 - tailwindcss-animate: - specifier: ^1.0.0 - version: 1.0.7(tailwindcss@3.4.17) packages/hypergraph: dependencies: @@ -518,7 +503,7 @@ importers: version: 2.0.0-beta.5 '@effect/experimental': specifier: ^0.44.20 - version: 0.44.20(@effect/platform@0.84.9(effect@3.16.3))(effect@3.16.3) + version: 0.44.20(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) '@noble/ciphers': specifier: ^1.3.0 version: 1.3.0 @@ -706,10 +691,6 @@ packages: resolution: {integrity: sha512-ZO0UKvDyEFvyeJQX0gmZDQEvhLZ2X10K+ps6hViMo1HgE2V8em00SwNsQ+7E/52a+YiBkVWX61pJJJE44juDMQ==} engines: {node: '>= 14.0.0'} - '@alloc/quick-lru@5.2.0': - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -2179,13 +2160,13 @@ packages: resolution: {integrity: sha512-e7zcB6TPnVzyUaHMJyLSArKa2AG3h9+4CfvKXKKWNx6hRs+p0a+u7HHTJBgo6KW2m+vqDnuIHK4X+bhmoghAFA==} engines: {node: '>=18.0'} - '@effect/cli@0.63.9': - resolution: {integrity: sha512-SKgoyDbXBra9sgpLLRAI2rDgfWvWIda5vV/ce7TaEUkIpfohJZ7yMcTZ9X4wXLbsc2pxWczkwOVn51WxAg3qng==} + '@effect/cli@0.63.4': + resolution: {integrity: sha512-c8Jfdapo9SmutXjbN1u4XDeWFKif6toe7zTUmaxXZZ44ZOs1S54REmJm6gjPyLrwSnAVhE11EegiweMH7hg/9Q==} peerDependencies: - '@effect/platform': ^0.84.9 - '@effect/printer': ^0.44.5 - '@effect/printer-ansi': ^0.44.5 - effect: ^3.16.5 + '@effect/platform': ^0.84.4 + '@effect/printer': ^0.44.3 + '@effect/printer-ansi': ^0.44.3 + effect: ^3.16.3 '@effect/cluster@0.37.2': resolution: {integrity: sha512-9U4P/Fk8C6fN/s0e4nvA++prZmELtV7k5RwG2AOw4NgqBZqptiJMutgaT10ltwgdvddRF/77PVjgORyzNTBmbg==} @@ -2209,11 +2190,11 @@ packages: lmdb: optional: true - '@effect/experimental@0.48.10': - resolution: {integrity: sha512-B6XlTdDlh4tDl+kU2+tpKR0xmK38XXXy27+PH8ILhM8m5RB0MJDtshzVLogw3Vzq2NjYsGkrxV/yEcU1HaQoLw==} + '@effect/experimental@0.48.4': + resolution: {integrity: sha512-sKCVpqUrBhVODpGPuZ5pgG72XjOAUs77/4LaJmSgtDrEEzKlFyFmY3vxAR6wrup3RRs+wcu3LoZwzfjk5d6JDQ==} peerDependencies: - '@effect/platform': ^0.84.9 - effect: ^3.16.5 + '@effect/platform': ^0.84.4 + effect: ^3.16.3 ioredis: ^5 lmdb: ^3 peerDependenciesMeta: @@ -2222,31 +2203,31 @@ packages: lmdb: optional: true - '@effect/language-service@0.19.0': - resolution: {integrity: sha512-DAnV0q0EPZtB6+opqMb1BsAkQ/7AoQj/Q84rUijM8dY2bevuI870DtZYn9kpB19Q3VN8yhPE9Kgtnpocj8ysTA==} + '@effect/language-service@0.17.1': + resolution: {integrity: sha512-dA0DamelGlQtCppi8k4Bqq/Exr2L6anjtqzlj9Xf27eAyNdapvnqrwzDiQXMYD8zb4Xvul3gQuYBzvfFVz0baQ==} - '@effect/platform-node-shared@0.39.13': - resolution: {integrity: sha512-j3XKDwmQ4P7lBd0jCUfx3fHflqhrDmBde99z2One0ZS+N2DEZjZzqqmG7K2I5b7t9GeOnngJyE0JgGp7oHYb+g==} + '@effect/platform-node-shared@0.38.2': + resolution: {integrity: sha512-TiYTYH3QPJt+7M21xhTM9KgV5DlJHD3eaDDs4Vv4lXseVaAZGOvLln4RBt0+6akdPmniDhEzrSOEGS+HbOI9Jw==} peerDependencies: - '@effect/cluster': ^0.38.13 - '@effect/platform': ^0.84.9 - '@effect/rpc': ^0.61.12 - '@effect/sql': ^0.37.10 - effect: ^3.16.5 + '@effect/cluster': ^0.37.2 + '@effect/platform': ^0.84.4 + '@effect/rpc': ^0.61.4 + '@effect/sql': ^0.37.4 + effect: ^3.16.3 - '@effect/platform-node@0.85.13': - resolution: {integrity: sha512-c/R4rUEY+KaLB+0817BzjtAPSnUxFMAogAfdRDqUvtE3htD25/aXIxa0DSUt4a66VAMzbdWAXr7BwV6vPE3weA==} + '@effect/platform-node@0.84.2': + resolution: {integrity: sha512-iDjlK9UYOCDgNIAKUrOYYt6y3NwJkq4Ii1XWGM5PrgWPx7OzG9BCZPOFJxPDMlBTcbpqEC+WYNmDjnYQDnx3rQ==} peerDependencies: - '@effect/cluster': ^0.38.13 - '@effect/platform': ^0.84.9 - '@effect/rpc': ^0.61.12 - '@effect/sql': ^0.37.10 - effect: ^3.16.5 + '@effect/cluster': ^0.37.2 + '@effect/platform': ^0.84.4 + '@effect/rpc': ^0.61.4 + '@effect/sql': ^0.37.4 + effect: ^3.16.3 - '@effect/platform@0.84.9': - resolution: {integrity: sha512-I1xX/dpFCyA9DlwD3kungWD0Pu7tnM2pxifUEz0U1N2GSMmdcC4EWIOsjnCaC+hd0WSIsVJVZZjGsDeQeX+r2g==} + '@effect/platform@0.84.4': + resolution: {integrity: sha512-RDs5Ju5u3xBpyEHZ6XEt5yKmAxrd/k8VyyeSyjkLVpCzecXNYeRkU8jcGdX4ex4bmH7AAe78j2OHrWoM8nBwSg==} peerDependencies: - effect: ^3.16.5 + effect: ^3.16.3 '@effect/printer-ansi@0.40.10': resolution: {integrity: sha512-XMmAcHxojINGZKnNGJSrG1fMvMYLOlHGVAvvD/5pbp2Yi5Rh8PGDJjtaPmrj5PmO+WssovevLHGonrbKa8xybA==} @@ -2266,30 +2247,30 @@ packages: '@effect/platform': ^0.84.4 effect: ^3.16.3 - '@effect/sql-sqlite-node@0.38.10': - resolution: {integrity: sha512-wNO5h33JgaaAERi8e7hz+8BxULp8YwwC4OBbXCh9vH+0dz6HVXjfD8+N8DIdaz5ZrCgBmr/pJsq/RnaQToZkig==} + '@effect/sql-sqlite-node@0.38.4': + resolution: {integrity: sha512-OBr88N5KuPBZBy9q422Q/FdkXJSCGxFR9Ns/Bhz7eaY94DUisWfRfeGx4lqcr1kKp84lDanVNi2mNfGsnGGcUQ==} peerDependencies: - '@effect/experimental': ^0.48.10 - '@effect/platform': ^0.84.9 - '@effect/sql': ^0.37.10 - effect: ^3.16.5 + '@effect/experimental': ^0.48.4 + '@effect/platform': ^0.84.4 + '@effect/sql': ^0.37.4 + effect: ^3.16.3 - '@effect/sql@0.37.10': - resolution: {integrity: sha512-tPnGb+JTWvtRYHyYxriMlX3ueC6hCZxAX6UgN40tSZ65pfhKtTfx2tqoEB55HnkWWrO09CbpO/S0q7RTqgFflQ==} + '@effect/sql@0.37.4': + resolution: {integrity: sha512-Ver8KV5kBkc6dNFNlOjJYHkcHUz0qcva4xyd2Ob2Xoh5CHj/JL/aJbXGhnRBsFPcV74kWc0SkPTAex2fh66tSA==} peerDependencies: - '@effect/experimental': ^0.48.10 - '@effect/platform': ^0.84.9 - effect: ^3.16.5 + '@effect/experimental': ^0.48.4 + '@effect/platform': ^0.84.4 + effect: ^3.16.3 '@effect/typeclass@0.31.10': resolution: {integrity: sha512-mDuQ44IfyDUSnltcFS+cEQGWhMg37IwNiPmATLw/NYBYHDBkqUc77vzlCpSlBiKDzExSI8vjMVWqGjL22MLHGQ==} peerDependencies: effect: ^3.12.10 - '@effect/vitest@0.23.5': - resolution: {integrity: sha512-cBiNyQQ+vslFnAuhjEz0NoNs/YD7hbyKPyIA1Xiu+m/jry6xVoFRQZEt5l5McIWbDfrbzBDEfEE6PpPS7U1D0Q==} + '@effect/vitest@0.23.3': + resolution: {integrity: sha512-yIB+Cllk1txmtpdpVX95SdmM0/FHqapz4wGSWYTe0c/K9fhgL6t0t5WsLmgzlk0rGnSi0+U21AHmPynjgk6+ig==} peerDependencies: - effect: ^3.16.5 + effect: ^3.16.3 vitest: ^3.0.0 '@effect/workflow@0.1.2': @@ -4431,11 +4412,6 @@ packages: resolution: {integrity: sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==} engines: {node: '>= 10'} - '@tailwindcss/typography@0.5.16': - resolution: {integrity: sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==} - peerDependencies: - tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' - '@tailwindcss/vite@4.1.5': resolution: {integrity: sha512-FE1stRoqdHSb7RxesMfCXE8icwI1W6zGE/512ae3ZDrpkQYTTYeSyUJPRCjZd8CwVAhpDUbi1YR8pcZioFJQ/w==} peerDependencies: @@ -5032,7 +5008,6 @@ packages: '@walletconnect/modal@2.7.0': resolution: {integrity: sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw==} - deprecated: Please follow the migration guide on https://docs.reown.com/appkit/upgrade/wcm '@walletconnect/relay-api@1.0.11': resolution: {integrity: sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==} @@ -5632,10 +5607,6 @@ packages: camel-case@4.1.2: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - camelcase-css@2.0.1: - resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} - engines: {node: '>= 6'} - camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -6369,9 +6340,6 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - didyoumean@1.2.2: - resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - diff@7.0.0: resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} engines: {node: '>=0.3.1'} @@ -6386,9 +6354,6 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - dlv@1.1.3: - resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - dns-packet@5.6.1: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} @@ -6466,9 +6431,6 @@ packages: effect@3.16.3: resolution: {integrity: sha512-SWndb1UavNWvet1+hnkU4qp3EHtnmDKhUeP14eB+7vf/2nCFlM77/oIjdDeZctveibNjE65P9H/sBBmF0NTy/w==} - effect@3.16.5: - resolution: {integrity: sha512-7nA+ZPMLoHItabNRV95RpMtwVw2k3BDNhILP4ffo8dG7zGR04XGjarP1JbO+jdBbTRET3eGx1Nz+hWB9kSOajw==} - electron-to-chromium@1.5.152: resolution: {integrity: sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==} @@ -8048,21 +8010,12 @@ packages: resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - lodash.castarray@4.4.0: - resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} - lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - lodash.isplainobject@4.0.6: - resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} @@ -8699,10 +8652,6 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-hash@3.0.0: - resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} - engines: {node: '>= 6'} - object-inspect@1.13.2: resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} engines: {node: '>= 0.4'} @@ -9030,10 +8979,6 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} - pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -9226,36 +9171,12 @@ packages: peerDependencies: postcss: ^8.4 - postcss-import@15.1.0: - resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} - engines: {node: '>=14.0.0'} - peerDependencies: - postcss: ^8.0.0 - - postcss-js@4.0.1: - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} - engines: {node: ^12 || ^14 || >= 16} - peerDependencies: - postcss: ^8.4.21 - postcss-lab-function@7.0.9: resolution: {integrity: sha512-IGbsIXbqMDusymJAKYX+f9oakPo89wL9Pzd/qRBQOVf3EIQWT9hgvqC4Me6Dkzxp3KPuIBf6LPkjrLHe/6ZMIQ==} engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - postcss-load-config@6.0.1: resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} engines: {node: '>= 18'} @@ -9353,12 +9274,6 @@ packages: peerDependencies: postcss: ^8.1.0 - postcss-nested@6.2.0: - resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.2.14 - postcss-nesting@13.0.1: resolution: {integrity: sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==} engines: {node: '>=18'} @@ -9489,10 +9404,6 @@ packages: peerDependencies: postcss: ^8.4 - postcss-selector-parser@6.0.10: - resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} - engines: {node: '>=4'} - postcss-selector-parser@6.1.2: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} @@ -9833,9 +9744,6 @@ packages: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} - read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -10609,11 +10517,6 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@3.4.17: - resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} - engines: {node: '>=14.0.0'} - hasBin: true - tailwindcss@4.1.5: resolution: {integrity: sha512-nYtSPfWGDiWgCkwQG/m+aX83XCwf62sBgg3bIlNiiOcggnS1x3uVRDAuyelBFL+vJdOPPCGElxv9DjHJjRHiVA==} @@ -11748,8 +11651,6 @@ snapshots: dependencies: '@algolia/client-common': 5.25.0 - '@alloc/quick-lru@5.2.0': {} - '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.8 @@ -11899,7 +11800,7 @@ snapshots: dependencies: '@babel/compat-data': 7.26.5 '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.5 + browserslist: 4.24.2 lru-cache: 5.1.1 semver: 6.3.1 @@ -11915,7 +11816,7 @@ snapshots: dependencies: '@babel/compat-data': 7.27.2 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.24.5 + browserslist: 4.24.2 lru-cache: 5.1.1 semver: 6.3.1 @@ -14155,60 +14056,60 @@ snapshots: - uglify-js - webpack-cli - '@effect/cli@0.63.9(@effect/platform@0.84.9(effect@3.16.5))(@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5))(@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5))(effect@3.16.5)': + '@effect/cli@0.63.4(@effect/platform@0.84.4(effect@3.16.3))(@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3))(@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3))(effect@3.16.3)': dependencies: - '@effect/platform': 0.84.9(effect@3.16.5) - '@effect/printer': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5) - '@effect/printer-ansi': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5) - effect: 3.16.5 + '@effect/platform': 0.84.4(effect@3.16.3) + '@effect/printer': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3) + '@effect/printer-ansi': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3) + effect: 3.16.3 ini: 4.1.3 toml: 3.0.0 yaml: 2.7.0 - '@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5)': + '@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3)': dependencies: - '@effect/platform': 0.84.9(effect@3.16.5) - '@effect/rpc': 0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) - '@effect/sql': 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) - '@effect/workflow': 0.1.2(effect@3.16.5) - effect: 3.16.5 + '@effect/platform': 0.84.4(effect@3.16.3) + '@effect/rpc': 0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + '@effect/sql': 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + '@effect/workflow': 0.1.2(effect@3.16.3) + effect: 3.16.3 - '@effect/experimental@0.44.20(@effect/platform@0.84.9(effect@3.16.3))(effect@3.16.3)': + '@effect/experimental@0.44.20(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3)': dependencies: - '@effect/platform': 0.84.9(effect@3.16.3) + '@effect/platform': 0.84.4(effect@3.16.3) effect: 3.16.3 uuid: 11.1.0 - '@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5)': + '@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3)': dependencies: - '@effect/platform': 0.84.9(effect@3.16.5) - effect: 3.16.5 + '@effect/platform': 0.84.4(effect@3.16.3) + effect: 3.16.3 uuid: 11.1.0 - '@effect/language-service@0.19.0': {} + '@effect/language-service@0.17.1': {} - '@effect/platform-node-shared@0.39.13(@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(bufferutil@4.0.9)(effect@3.16.5)(utf-8-validate@5.0.10)': + '@effect/platform-node-shared@0.38.2(@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(bufferutil@4.0.9)(effect@3.16.3)(utf-8-validate@5.0.10)': dependencies: - '@effect/cluster': 0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5) - '@effect/platform': 0.84.9(effect@3.16.5) - '@effect/rpc': 0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) - '@effect/sql': 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + '@effect/cluster': 0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3) + '@effect/platform': 0.84.4(effect@3.16.3) + '@effect/rpc': 0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + '@effect/sql': 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) '@parcel/watcher': 2.5.1 - effect: 3.16.5 + effect: 3.16.3 multipasta: 0.2.5 ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate - '@effect/platform-node@0.85.13(@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(bufferutil@4.0.9)(effect@3.16.5)(utf-8-validate@5.0.10)': + '@effect/platform-node@0.84.2(@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(bufferutil@4.0.9)(effect@3.16.3)(utf-8-validate@5.0.10)': dependencies: - '@effect/cluster': 0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5) - '@effect/platform': 0.84.9(effect@3.16.5) - '@effect/platform-node-shared': 0.39.13(@effect/cluster@0.37.2(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/workflow@0.1.2(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(bufferutil@4.0.9)(effect@3.16.5)(utf-8-validate@5.0.10) - '@effect/rpc': 0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) - '@effect/sql': 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) - effect: 3.16.5 + '@effect/cluster': 0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3) + '@effect/platform': 0.84.4(effect@3.16.3) + '@effect/platform-node-shared': 0.38.2(@effect/cluster@0.37.2(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/workflow@0.1.2(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(bufferutil@4.0.9)(effect@3.16.3)(utf-8-validate@5.0.10) + '@effect/rpc': 0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + '@effect/sql': 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + effect: 3.16.3 mime: 3.0.0 undici: 7.10.0 ws: 8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) @@ -14216,65 +14117,58 @@ snapshots: - bufferutil - utf-8-validate - '@effect/platform@0.84.9(effect@3.16.3)': + '@effect/platform@0.84.4(effect@3.16.3)': dependencies: effect: 3.16.3 find-my-way-ts: 0.1.5 msgpackr: 1.11.4 multipasta: 0.2.5 - '@effect/platform@0.84.9(effect@3.16.5)': + '@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3)': dependencies: - effect: 3.16.5 - find-my-way-ts: 0.1.5 - msgpackr: 1.11.4 - multipasta: 0.2.5 - - '@effect/printer-ansi@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5)': - dependencies: - '@effect/printer': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5) - '@effect/typeclass': 0.31.10(effect@3.16.5) - effect: 3.16.5 + '@effect/printer': 0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3) + '@effect/typeclass': 0.31.10(effect@3.16.3) + effect: 3.16.3 - '@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.5))(effect@3.16.5)': + '@effect/printer@0.40.10(@effect/typeclass@0.31.10(effect@3.16.3))(effect@3.16.3)': dependencies: - '@effect/typeclass': 0.31.10(effect@3.16.5) - effect: 3.16.5 + '@effect/typeclass': 0.31.10(effect@3.16.3) + effect: 3.16.3 - '@effect/rpc@0.61.4(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5)': + '@effect/rpc@0.61.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3)': dependencies: - '@effect/platform': 0.84.9(effect@3.16.5) - effect: 3.16.5 + '@effect/platform': 0.84.4(effect@3.16.3) + effect: 3.16.3 - '@effect/sql-sqlite-node@0.38.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(effect@3.16.5)': + '@effect/sql-sqlite-node@0.38.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(effect@3.16.3)': dependencies: - '@effect/experimental': 0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) - '@effect/platform': 0.84.9(effect@3.16.5) - '@effect/sql': 0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) + '@effect/experimental': 0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + '@effect/platform': 0.84.4(effect@3.16.3) + '@effect/sql': 0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) '@opentelemetry/semantic-conventions': 1.34.0 better-sqlite3: 11.10.0 - effect: 3.16.5 + effect: 3.16.3 - '@effect/sql@0.37.10(@effect/experimental@0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5))(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5)': + '@effect/sql@0.37.4(@effect/experimental@0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3))(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3)': dependencies: - '@effect/experimental': 0.48.10(@effect/platform@0.84.9(effect@3.16.5))(effect@3.16.5) - '@effect/platform': 0.84.9(effect@3.16.5) + '@effect/experimental': 0.48.4(@effect/platform@0.84.4(effect@3.16.3))(effect@3.16.3) + '@effect/platform': 0.84.4(effect@3.16.3) '@opentelemetry/semantic-conventions': 1.34.0 - effect: 3.16.5 + effect: 3.16.3 uuid: 11.1.0 - '@effect/typeclass@0.31.10(effect@3.16.5)': + '@effect/typeclass@0.31.10(effect@3.16.3)': dependencies: - effect: 3.16.5 + effect: 3.16.3 - '@effect/vitest@0.23.5(effect@3.16.5)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0))': + '@effect/vitest@0.23.3(effect@3.16.3)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0))': dependencies: - effect: 3.16.5 + effect: 3.16.3 vitest: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0) - '@effect/workflow@0.1.2(effect@3.16.5)': + '@effect/workflow@0.1.2(effect@3.16.3)': dependencies: - effect: 3.16.5 + effect: 3.16.3 '@emnapi/runtime@1.4.3': dependencies: @@ -14762,7 +14656,7 @@ snapshots: dependencies: '@bufbuild/protobuf': 1.10.1 '@changesets/cli': 2.29.3 - effect: 3.16.5 + effect: 3.16.3 ethers: 5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) fflate: 0.8.2 graphql-request: 7.2.0(graphql@16.11.0) @@ -17177,14 +17071,6 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.8 '@tailwindcss/oxide-win32-x64-msvc': 4.1.8 - '@tailwindcss/typography@0.5.16(tailwindcss@3.4.17)': - dependencies: - lodash.castarray: 4.4.0 - lodash.isplainobject: 4.0.6 - lodash.merge: 4.6.2 - postcss-selector-parser: 6.0.10 - tailwindcss: 3.4.17 - '@tailwindcss/vite@4.1.5(vite@6.3.5(@types/node@22.15.15)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.1)(tsx@4.19.4)(yaml@2.7.0))': dependencies: '@tailwindcss/node': 4.1.5 @@ -18958,7 +18844,7 @@ snapshots: browserslist@4.24.2: dependencies: - caniuse-lite: 1.0.30001718 + caniuse-lite: 1.0.30001678 electron-to-chromium: 1.5.52 node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) @@ -19075,8 +18961,6 @@ snapshots: pascal-case: 3.1.2 tslib: 2.8.1 - camelcase-css@2.0.1: {} - camelcase@5.3.1: {} camelcase@6.3.0: {} @@ -19087,8 +18971,8 @@ snapshots: caniuse-api@3.0.0: dependencies: - browserslist: 4.24.5 - caniuse-lite: 1.0.30001718 + browserslist: 4.24.2 + caniuse-lite: 1.0.30001678 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 @@ -19617,7 +19501,7 @@ snapshots: cssnano-preset-advanced@6.1.2(postcss@8.5.3): dependencies: autoprefixer: 10.4.21(postcss@8.5.3) - browserslist: 4.24.5 + browserslist: 4.24.2 cssnano-preset-default: 6.1.2(postcss@8.5.3) postcss: 8.5.3 postcss-discard-unused: 6.0.5(postcss@8.5.3) @@ -19627,7 +19511,7 @@ snapshots: cssnano-preset-default@6.1.2(postcss@8.5.3): dependencies: - browserslist: 4.24.5 + browserslist: 4.24.2 css-declaration-sorter: 7.2.0(postcss@8.5.3) cssnano-utils: 4.0.2(postcss@8.5.3) postcss: 8.5.3 @@ -19832,8 +19716,6 @@ snapshots: dependencies: dequal: 2.0.3 - didyoumean@1.2.2: {} - diff@7.0.0: {} diffie-hellman@5.0.3: @@ -19848,8 +19730,6 @@ snapshots: dependencies: path-type: 4.0.0 - dlv@1.1.3: {} - dns-packet@5.6.1: dependencies: '@leichtgewicht/ip-codec': 2.0.5 @@ -19940,11 +19820,6 @@ snapshots: '@standard-schema/spec': 1.0.0 fast-check: 3.23.2 - effect@3.16.5: - dependencies: - '@standard-schema/spec': 1.0.0 - fast-check: 3.23.2 - electron-to-chromium@1.5.152: {} electron-to-chromium@1.5.52: {} @@ -21722,16 +21597,10 @@ snapshots: dependencies: p-locate: 6.0.0 - lodash.castarray@4.4.0: {} - lodash.debounce@4.0.8: {} - lodash.isplainobject@4.0.6: {} - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} - lodash.sortby@4.7.0: {} lodash.startcase@4.4.0: {} @@ -22633,8 +22502,6 @@ snapshots: object-assign@4.1.1: {} - object-hash@3.0.0: {} - object-inspect@1.13.2: {} object-inspect@1.13.4: {} @@ -22998,8 +22865,6 @@ snapshots: picomatch@4.0.2: {} - pify@2.3.0: {} - pify@4.0.1: {} pino-abstract-transport@0.5.0: @@ -23122,7 +22987,7 @@ snapshots: postcss-colormin@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.5 + browserslist: 4.24.2 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.5.3 @@ -23130,7 +22995,7 @@ snapshots: postcss-convert-values@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.5 + browserslist: 4.24.2 postcss: 8.5.3 postcss-value-parser: 4.2.0 @@ -23216,18 +23081,6 @@ snapshots: postcss: 8.5.3 postcss-value-parser: 4.2.0 - postcss-import@15.1.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.10 - - postcss-js@4.0.1(postcss@8.5.3): - dependencies: - camelcase-css: 2.0.1 - postcss: 8.5.3 - postcss-lab-function@7.0.9(postcss@8.5.3): dependencies: '@csstools/css-color-parser': 3.0.9(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) @@ -23237,13 +23090,6 @@ snapshots: '@csstools/utilities': 2.0.0(postcss@8.5.3) postcss: 8.5.3 - postcss-load-config@4.0.2(postcss@8.5.3): - dependencies: - lilconfig: 3.1.3 - yaml: 2.7.0 - optionalDependencies: - postcss: 8.5.3 - postcss-load-config@6.0.1(jiti@2.4.2)(postcss@8.5.3)(tsx@4.19.4)(yaml@2.7.0): dependencies: lilconfig: 3.1.3 @@ -23282,7 +23128,7 @@ snapshots: postcss-merge-rules@6.1.1(postcss@8.5.3): dependencies: - browserslist: 4.24.5 + browserslist: 4.24.2 caniuse-api: 3.0.0 cssnano-utils: 4.0.2(postcss@8.5.3) postcss: 8.5.3 @@ -23302,7 +23148,7 @@ snapshots: postcss-minify-params@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.5 + browserslist: 4.24.2 cssnano-utils: 4.0.2(postcss@8.5.3) postcss: 8.5.3 postcss-value-parser: 4.2.0 @@ -23333,11 +23179,6 @@ snapshots: icss-utils: 5.1.0(postcss@8.5.3) postcss: 8.5.3 - postcss-nested@6.2.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-selector-parser: 6.1.2 - postcss-nesting@13.0.1(postcss@8.5.3): dependencies: '@csstools/selector-resolve-nested': 3.0.0(postcss-selector-parser@7.1.0) @@ -23376,7 +23217,7 @@ snapshots: postcss-normalize-unicode@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.5 + browserslist: 4.24.2 postcss: 8.5.3 postcss-value-parser: 4.2.0 @@ -23493,7 +23334,7 @@ snapshots: postcss-reduce-initial@6.1.0(postcss@8.5.3): dependencies: - browserslist: 4.24.5 + browserslist: 4.24.2 caniuse-api: 3.0.0 postcss: 8.5.3 @@ -23511,11 +23352,6 @@ snapshots: postcss: 8.5.3 postcss-selector-parser: 7.1.0 - postcss-selector-parser@6.0.10: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 @@ -23910,10 +23746,6 @@ snapshots: react@19.1.0: {} - read-cache@1.0.0: - dependencies: - pify: 2.3.0 - read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.11 @@ -24826,7 +24658,7 @@ snapshots: stylehacks@6.1.1(postcss@8.5.3): dependencies: - browserslist: 4.24.5 + browserslist: 4.24.2 postcss: 8.5.3 postcss-selector-parser: 6.1.2 @@ -24888,41 +24720,10 @@ snapshots: tailwind-merge@3.2.0: {} - tailwindcss-animate@1.0.7(tailwindcss@3.4.17): - dependencies: - tailwindcss: 3.4.17 - tailwindcss-animate@1.0.7(tailwindcss@4.1.5): dependencies: tailwindcss: 4.1.5 - tailwindcss@3.4.17: - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.3 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.7 - lilconfig: 3.1.3 - micromatch: 4.0.8 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.1.1 - postcss: 8.5.3 - postcss-import: 15.1.0(postcss@8.5.3) - postcss-js: 4.0.1(postcss@8.5.3) - postcss-load-config: 4.0.2(postcss@8.5.3) - postcss-nested: 6.2.0(postcss@8.5.3) - postcss-selector-parser: 6.1.2 - resolve: 1.22.10 - sucrase: 3.35.0 - transitivePeerDependencies: - - ts-node - tailwindcss@4.1.5: {} tailwindcss@4.1.8: {} @@ -25768,7 +25569,7 @@ snapshots: '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.14.0 - browserslist: 4.24.2 + browserslist: 4.24.5 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.1 es-module-lexer: 1.7.0 From ef2209505942c9c53e8d8e7fa6f9ba473552f7f2 Mon Sep 17 00:00:00 2001 From: Marcus Rein Date: Wed, 11 Jun 2025 09:05:53 -0400 Subject: [PATCH 18/18] docs: fixed linting and build errors --- docs/src/css/custom.css | 160 +++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 85 deletions(-) diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index a2b203a1..a6d82f9d 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -9,155 +9,145 @@ /* You can override the default Infima variables here. */ :root { - /* Brand Colors – "The Graph" palette */ - --graph-purple: #6f4cff; - --astro-blue: #4c66ff; - --galactic-aqua: #66dbff; - --starfield-green: #4bca81; - --nebula-pink: #ff79c6; - --solar-yellow: #ffa801; - - /* Override Infima variables with our palette */ - --ifm-color-primary: var(--graph-purple); - --ifm-color-primary-light: #8069ff; - --ifm-color-primary-lighter: #8f79ff; - --ifm-color-primary-lightest: #a999ff; - --ifm-color-primary-dark: #6544f0; - --ifm-color-primary-darker: #5c3fe4; - --ifm-color-primary-darkest: #4d34c4; - - /* Typography */ - --ifm-font-family-base: "Euclid Circular A", "Poppins", -apple-system, - BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, - "Open Sans", "Helvetica Neue", sans-serif; - --ifm-heading-font-weight: 700; - --ifm-font-weight-bold: 600; - - /* Layout tweaks */ - --ifm-spacing-horizontal: 1.2rem; - --ifm-page-width: 85rem; - - /* Code blocks */ - --docusaurus-highlighted-code-line-bg: rgba(255, 255, 255, 0.05); + /* Brand Colors – "The Graph" palette */ + --graph-purple: #6f4cff; + --astro-blue: #4c66ff; + --galactic-aqua: #66dbff; + --starfield-green: #4bca81; + --nebula-pink: #ff79c6; + --solar-yellow: #ffa801; + + /* Override Infima variables with our palette */ + --ifm-color-primary: var(--graph-purple); + --ifm-color-primary-light: #8069ff; + --ifm-color-primary-lighter: #8f79ff; + --ifm-color-primary-lightest: #a999ff; + --ifm-color-primary-dark: #6544f0; + --ifm-color-primary-darker: #5c3fe4; + --ifm-color-primary-darkest: #4d34c4; + + /* Typography */ + --ifm-font-family-base: "Euclid Circular A", "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, + Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + --ifm-heading-font-weight: 700; + --ifm-font-weight-bold: 600; + + /* Layout tweaks */ + --ifm-spacing-horizontal: 1.2rem; + --ifm-page-width: 85rem; + + /* Code blocks */ + --docusaurus-highlighted-code-line-bg: rgba(255, 255, 255, 0.05); } [data-theme="dark"] { - /* Dark theme overrides keeping brand palette vibrant */ - --ifm-color-primary: var(--graph-purple); - --ifm-background-color: #0b0b13; - --ifm-background-surface-color: #0b0b13; - --ifm-navbar-background-color: rgba(11, 11, 19, 0.9); - --ifm-footer-background-color: #0b0b13; - --ifm-toc-border-color: rgba(255, 255, 255, 0.08); - --docusaurus-highlighted-code-line-bg: rgba(255, 255, 255, 0.05); + /* Dark theme overrides keeping brand palette vibrant */ + --ifm-color-primary: var(--graph-purple); + --ifm-background-color: #0b0b13; + --ifm-background-surface-color: #0b0b13; + --ifm-navbar-background-color: rgba(11, 11, 19, 0.9); + --ifm-footer-background-color: #0b0b13; + --ifm-toc-border-color: rgba(255, 255, 255, 0.08); + --docusaurus-highlighted-code-line-bg: rgba(255, 255, 255, 0.05); } /* ---------- Global enhancements inspired by design ---------- */ html { - scroll-behavior: smooth; + scroll-behavior: smooth; } body { - background: #0b0b13; - color: var(--ifm-font-color-base); + background: #0b0b13; + color: var(--ifm-font-color-base); } /* Smooth transition for theme switch & interactive elements */ * { - transition: color 0.15s ease, background-color 0.15s ease, - border-color 0.15s ease; + transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease; } /* Custom scrollbar – slim & subtle */ ::-webkit-scrollbar { - width: 6px; - height: 6px; + width: 6px; + height: 6px; } ::-webkit-scrollbar-track { - background: transparent; + background: transparent; } ::-webkit-scrollbar-thumb { - background: hsla(0, 0%, 100%, 0.12); - border-radius: 3px; + background: hsla(0, 0%, 100%, 0.12); + border-radius: 3px; } ::-webkit-scrollbar-thumb:hover { - background: hsla(0, 0%, 100%, 0.25); + background: hsla(0, 0%, 100%, 0.25); } /* Links */ :root a { - text-decoration-color: rgba(111, 76, 255, 0.4); - text-underline-offset: 2px; + text-decoration-color: rgba(111, 76, 255, 0.4); + text-underline-offset: 2px; } :root a:hover { - text-decoration-color: currentColor; + text-decoration-color: currentColor; } /* Buttons (using Infima classes) */ .button--primary { - background: linear-gradient( - 135deg, - var(--astro-blue) 0%, - var(--graph-purple) 100% - ); - color: #fff; - border: none; + background: linear-gradient(135deg, var(--astro-blue) 0%, var(--graph-purple) 100%); + color: #fff; + border: none; } .button--primary:hover { - background: linear-gradient( - 135deg, - var(--astro-blue) -20%, - var(--graph-purple) 120% - ); + background: linear-gradient(135deg, var(--astro-blue) -20%, var(--graph-purple) 120%); } /* Navbar translucency & blur */ .navbar { - backdrop-filter: blur(12px); - background-color: var(--ifm-navbar-background-color); - border-bottom: 1px solid rgba(255, 255, 255, 0.05); + backdrop-filter: blur(12px); + background-color: var(--ifm-navbar-background-color); + border-bottom: 1px solid rgba(255, 255, 255, 0.05); } /* Shadow & border for code blocks */ .theme-code-block { - border: 1px solid rgba(255, 255, 255, 0.06); - border-radius: 0.75rem; - overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 0.75rem; + overflow: hidden; } /* Card-like appearance for admonitions */ .alert { - border-radius: 0.75rem; - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25); + border-radius: 0.75rem; + box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25); } /* Table styling tweaks */ .table { - border-collapse: collapse; + border-collapse: collapse; } .table thead th { - font-weight: 600; + font-weight: 600; } .table th, .table td { - border-bottom: 1px solid rgba(255, 255, 255, 0.08); - padding: 0.75rem 1rem; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + padding: 0.75rem 1rem; } /* Adjust sidebar width and typography */ @media (min-width: 997px) { - .theme-doc-sidebar-container { - width: 16rem; - } - .theme-doc-sidebar-container .menu__link { - font-size: 0.95rem; - } + .theme-doc-sidebar-container { + width: 16rem; + } + .theme-doc-sidebar-container .menu__link { + font-size: 0.95rem; + } } /* Breadcrumb subtlety */ .breadcrumbs__item:not(.breadcrumbs__item--active) a { - color: rgba(255, 255, 255, 0.7); + color: rgba(255, 255, 255, 0.7); } /* End of custom aesthetic overrides */ @@ -165,10 +155,10 @@ body { /* Make docs wrapper background match inspected color */ .docs-wrapper, .plugin-docs.plugin-id-default.docs-version-current.docs-doc-page { - background: #0b0b13 !important; + background: #0b0b13 !important; } .blog-wrapper, .plugin-blog.plugin-id-default.docs-version-current.docs-blog-page { - background: #0b0b13 !important; + background: #0b0b13 !important; }