Sync third-party and MCP marketplace plugins
Constraint: Public skills are published only by explicit administrator action unless they are tracked third-party market sources. Confidence: high Scope-risk: narrow Directive: Keep private/internal skills out of the public marketplace and preserve normal incremental market Git history. Tested: Marketplace validation passed.
@@ -96,8 +96,8 @@
|
|||||||
"repo": "https://github.com/hugohe3/ppt-master.git",
|
"repo": "https://github.com/hugohe3/ppt-master.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"adapter": "claude-skill",
|
"adapter": "claude-skill",
|
||||||
"commit": "eb095bfcc6b625fd8754e9f5d053ec4220865370",
|
"commit": "108b4b82db1b6076284bd68f603422044899eaf2",
|
||||||
"syncedAt": "2026-08-08T16:00:01Z"
|
"syncedAt": "2026-08-09T16:00:00Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "next-skills",
|
"id": "next-skills",
|
||||||
@@ -105,8 +105,8 @@
|
|||||||
"repo": "https://github.com/vercel/next.js.git",
|
"repo": "https://github.com/vercel/next.js.git",
|
||||||
"ref": "canary",
|
"ref": "canary",
|
||||||
"adapter": "skill-collection",
|
"adapter": "skill-collection",
|
||||||
"commit": "a677cf66af002fbdcf49a982ef435b03554817cc",
|
"commit": "62d9b8e03160727191bdcecd96c2284575621501",
|
||||||
"syncedAt": "2026-08-08T16:00:01Z"
|
"syncedAt": "2026-08-09T16:00:00Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@
|
|||||||
"name": "playwright浏览器自动化操作",
|
"name": "playwright浏览器自动化操作",
|
||||||
"version": "20260605",
|
"version": "20260605",
|
||||||
"keySource": "none",
|
"keySource": "none",
|
||||||
"syncedAt": "2026-08-08T16:02:04Z"
|
"syncedAt": "2026-08-09T16:02:07Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"sourceId": "next-skills",
|
"sourceId": "next-skills",
|
||||||
"repo": "https://github.com/vercel/next.js.git",
|
"repo": "https://github.com/vercel/next.js.git",
|
||||||
"ref": "canary",
|
"ref": "canary",
|
||||||
"commit": "a677cf66af002fbdcf49a982ef435b03554817cc",
|
"commit": "62d9b8e03160727191bdcecd96c2284575621501",
|
||||||
"adapter": "skill-collection",
|
"adapter": "skill-collection",
|
||||||
"sourcePath": "skills",
|
"sourcePath": "skills",
|
||||||
"syncedAt": "2026-08-08T16:00:01Z"
|
"syncedAt": "2026-08-09T16:00:00Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,6 +387,8 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
|
|||||||
|
|
||||||
[SVG Repo](https://www.svgrepo.com/) · [Tabler Icons](https://github.com/tabler/tabler-icons) · [Simple Icons](https://github.com/simple-icons/simple-icons) · [Phosphor Icons](https://github.com/phosphor-icons/core) · [Robin Williams](https://en.wikipedia.org/wiki/Robin_Williams_(author)) (CRAP principles)
|
[SVG Repo](https://www.svgrepo.com/) · [Tabler Icons](https://github.com/tabler/tabler-icons) · [Simple Icons](https://github.com/simple-icons/simple-icons) · [Phosphor Icons](https://github.com/phosphor-icons/core) · [Robin Williams](https://en.wikipedia.org/wiki/Robin_Williams_(author)) (CRAP principles)
|
||||||
|
|
||||||
|
See [third-party icon notices](./skills/ppt-master/templates/icons/THIRD_PARTY_NOTICES.md) for pinned versions, licenses, attribution, compatibility overlays, and trademark boundaries.
|
||||||
|
|
||||||
## Related Tools
|
## Related Tools
|
||||||
|
|
||||||
[cc-switch](https://github.com/farion1231/cc-switch) — one-click switching of API providers across Claude Code / Codex / Gemini CLI and more.
|
[cc-switch](https://github.com/farion1231/cc-switch) — one-click switching of API providers across Claude Code / Codex / Gemini CLI and more.
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"sourceId": "ppt-master",
|
"sourceId": "ppt-master",
|
||||||
"repo": "https://github.com/hugohe3/ppt-master.git",
|
"repo": "https://github.com/hugohe3/ppt-master.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"commit": "eb095bfcc6b625fd8754e9f5d053ec4220865370",
|
"commit": "108b4b82db1b6076284bd68f603422044899eaf2",
|
||||||
"adapter": "claude-skill",
|
"adapter": "claude-skill",
|
||||||
"sourcePath": "skills/ppt-master",
|
"sourcePath": "skills/ppt-master",
|
||||||
"syncedAt": "2026-08-08T16:00:01Z"
|
"syncedAt": "2026-08-09T16:00:00Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name: ppt-master
|
name: ppt-master
|
||||||
description: "多格式源文档到高质量 SVG 页面再导出 PPTX 的多阶段演示文稿生成工作流。"
|
description: "多格式源文档到高质量 SVG 页面再导出 PPTX 的多阶段演示文稿生成工作流。"
|
||||||
metadata:
|
metadata:
|
||||||
version: "4.4.0"
|
version: "4.5.0"
|
||||||
copyright: "Copyright (c) 2025-2026 Hugo He"
|
copyright: "Copyright (c) 2025-2026 Hugo He"
|
||||||
license: "MIT"
|
license: "MIT"
|
||||||
official_repository: "https://github.com/hugohe3/ppt-master"
|
official_repository: "https://github.com/hugohe3/ppt-master"
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Always-loaded Executor authority for flat SVG page authoring and behavior shared
|
|||||||
|
|
||||||
Evaluate branches from each object's actual information model, not only from a Chart/Table reference. A catalog family selects construction guidance but never native readiness; `Native-ready` is an independent object-level decision. Page-local qualitative geometry also never implies package-level `pptx_structure.mode: structured`.
|
Evaluate branches from each object's actual information model, not only from a Chart/Table reference. A catalog family selects construction guidance but never native readiness; `Native-ready` is an independent object-level decision. Page-local qualitative geometry also never implies package-level `pptx_structure.mode: structured`.
|
||||||
|
|
||||||
> Narrative skeleton and visual aesthetic come from this deck's locked files under [`modes/`](./modes/_index.md) and [`visual-styles/`](./visual-styles/_index.md). [`shared-standards-core.md`](./shared-standards-core.md) supplies the technical boundary plus the fallback visual-quality and leading defaults when those authorities are silent.
|
> Narrative skeleton and visual aesthetic come from the locked values routed through the [`modes/`](./modes/_index.md) and [`visual-styles/`](./visual-styles/_index.md) indexes. Executor reads one locked preset file or only the exact `*_references` of a custom synthesis; an unreferenced novel custom reads none. [`shared-standards-core.md`](./shared-standards-core.md) supplies the technical boundary plus the fallback visual-quality and leading defaults when those authorities are silent.
|
||||||
|
|
||||||
**Hard rule — Shape-first page authority**: Every visible object intended for the exported slide MUST exist in the final page SVG or be explicitly referenced by it. Templates and `spec_lock.md` guide construction; they are not export-time overlays for missing visible content. Optional native Chart/Table metadata belongs to an independently selected object and never replaces this visible fallback during authoring; [`native-data-interface.md`](./native-data-interface.md) alone defines that metadata and its export activation.
|
**Hard rule — Shape-first page authority**: Every visible object intended for the exported slide MUST exist in the final page SVG or be explicitly referenced by it. Templates and `spec_lock.md` guide construction; they are not export-time overlays for missing visible content. Optional native Chart/Table metadata belongs to an independently selected object and never replaces this visible fallback during authoring; [`native-data-interface.md`](./native-data-interface.md) alone defines that metadata and its export activation.
|
||||||
|
|
||||||
|
|||||||
@@ -32,17 +32,17 @@ Combine atoms as needed; never force a named business model. Numbers used only a
|
|||||||
| Role | Job |
|
| Role | Job |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `field` | Page/local region where a relationship operates |
|
| `field` | Page/local region where a relationship operates |
|
||||||
| `node` | Semantic unit, state, actor, item, or group |
|
| `node` | Semantic unit, state, actor, item, or group; may punctuate a drawn carrier as a stop, turn, junction, or bridge |
|
||||||
| `spine` | Explicit/implied scaffold establishing reading direction |
|
| `spine` | Explicit/implied scaffold or continuous carrier establishing reading direction |
|
||||||
| `edge` | Necessary connection, branch, dependency, or transition |
|
| `edge` | Necessary semantic connection, branch, dependency, or transition |
|
||||||
| `label` | Text attached to a node, edge, region, or relationship |
|
| `label` | Text/evidence attached directly or by a non-relational leader/tether to a node, edge, region, or relationship |
|
||||||
| `garnish` | Non-semantic accent added after the relationship works |
|
| `garnish` | Non-semantic accent added after the relationship works |
|
||||||
|
|
||||||
| Operation | Job |
|
| Operation | Job |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `repeat` | Create peers from one role |
|
| `repeat` | Create peers from one visual family; clone the full contour only when their structural states match |
|
||||||
| `arrange` | Establish order, alignment, rhythm, rank, comparison |
|
| `arrange` | Establish order, alignment, rhythm, rank, comparison |
|
||||||
| `transform` | Vary scale, rotation, crop, fill, or emphasis meaningfully |
|
| `transform` | Vary scale, rotation, crop, fill, emphasis, or entry/continuation/turn/terminal port state meaningfully |
|
||||||
| `connect` | Add an edge when layout/containment is insufficient |
|
| `connect` | Add an edge when layout/containment is insufficient |
|
||||||
| `region` | Partition, contain, intersect, band, or layer fields |
|
| `region` | Partition, contain, intersect, band, or layer fields |
|
||||||
| `attach` | Bind labels, badges, annotations, or evidence to an owner |
|
| `attach` | Bind labels, badges, annotations, or evidence to an owner |
|
||||||
@@ -61,24 +61,25 @@ invent a relationship.
|
|||||||
|
|
||||||
Choose the field and map required atoms, then follow:
|
Choose the field and map required atoms, then follow:
|
||||||
|
|
||||||
**Mandatory — spine → nodes → connectors → labels → garnish**:
|
**Mandatory — spine/topology → nodes → connectors → labels → garnish**:
|
||||||
|
|
||||||
| Layer | Completion evidence |
|
| Layer | Completion evidence |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `spine` | Entry, direction, and organizing path are clear |
|
| `spine` | Entry, direction, and organizing path are clear; reversal, cycle, split/merge, or stage change reshapes a continuous carrier before node placement |
|
||||||
| `nodes` | Every required unit has one home and intentional weight; each is direct content or a §2-approved carrier |
|
| `nodes` | Every required unit has one home and intentional weight; each is direct content or a §2-approved carrier; carrier-crossing nodes intentionally continue, stop, turn, join, or bridge its visible path |
|
||||||
| `connectors` (`edge`) | Only unresolved links become edges; route/source/target is clear; every drawn edge passes §2 |
|
| `connectors` (`edge`) | Only unresolved semantic links become edges; route/source/target is clear; every drawn edge passes §2 |
|
||||||
| `labels` | Copy and caveats visibly attach to what they explain |
|
| `labels` | Copy and caveats visibly attach directly or by leader/tether to what they explain; when a node has multiple text roles, cue → claim/value → support → note remains perceptibly descending and absent roles stay absent |
|
||||||
| `garnish` | Removing accents leaves all meaning intact |
|
| `garnish` | Removing accents leaves all meaning intact |
|
||||||
|
|
||||||
**Hard rule — relationship before styling**: establish atoms, field, spine, nodes, and necessary edges before palette, type, effects, or containers. Prefer containment, alignment, baselines, and proximity; add lines/Connectors only for real edges, never to make a page look process-like.
|
**Hard rule — relationship before styling**: establish atoms, field, spine, nodes, and necessary edges before palette, type, effects, or containers. Prefer containment, alignment, baselines, and proximity; add lines/Connectors only for real edges, never to make a page look process-like.
|
||||||
|
|
||||||
**Default — visible structural move (may override for naked-text rhythm/style)**:
|
**Default — visible structural composition (may override for naked-text
|
||||||
Make one relationship-bearing field, spine, node carrier, or directional shape
|
rhythm/style)**: Make one relationship-bearing field, spine, node carrier, or
|
||||||
the page-scale move; never add geometry merely because Structure is `yes`.
|
directional shape the page-scale move; never add geometry merely because
|
||||||
|
Structure is `yes`. When drawn roles interact, resolve relationship-bearing
|
||||||
> Note: spatial encoding may remove the need for a new object; any drawn node
|
parent contour/direction → contact → joint or intentional void →
|
||||||
> carrier, spine, or edge still passes §2.
|
z-order/occlusion → canvas-edge behavior before labels/garnish. Skip
|
||||||
|
inapplicable operations; implicit/direct roles remain container-free.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -93,5 +94,6 @@ the page-scale move; never add geometry merely because Structure is `yes`.
|
|||||||
| Removal | Without color/effects/icons/garnish, placement still communicates |
|
| Removal | Without color/effects/icons/garnish, placement still communicates |
|
||||||
| Fidelity | All required units, qualifiers, values, and caveats remain |
|
| Fidelity | All required units, qualifiers, values, and caveats remain |
|
||||||
| Construction | Drawn fields/spines/node carriers/edges pass §2; implicit/direct roles need no carrier; freeform follows failed primitive/preset/Boolean tiers |
|
| Construction | Drawn fields/spines/node carriers/edges pass §2; implicit/direct roles need no carrier; freeform follows failed primitive/preset/Boolean tiers |
|
||||||
|
| Composition | Every used contact, void, overlap, cutout, occlusion, or canvas-edge crossing maps to an atom/role or remains removable garnish; none obscures ownership or reading path |
|
||||||
|
|
||||||
Load Chart/Table branches independently for embedded objects. Keep one dominant reading path while allowing secondary atoms whose ownership stays clear.
|
Load Chart/Table branches independently for embedded objects. Keep one dominant reading path while allowing secondary atoms whose ownership stays clear.
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ This section applies only when a deck/layout template's AI-derived lock records
|
|||||||
|
|
||||||
**Layout identity**: Different keys differ in fixed Layout atoms or slot topology/default bounds/binding modes. Identical contracts should share one key. Current wording, imagery, crop, and Slide-local geometry never define identity.
|
**Layout identity**: Different keys differ in fixed Layout atoms or slot topology/default bounds/binding modes. Identical contracts should share one key. Current wording, imagery, crop, and Slide-local geometry never define identity.
|
||||||
|
|
||||||
**Template adherence**: Strict preserves reusable Master/Layout atoms and slot ids/types/indices/default bounds/bindings. Under `layout`, the application plan may still change current text/tspans, line height, crop, and carrier-local geometry inside those bounds; `mirror` remains topology-frozen. Adaptive keeps the prototype Master and changes reusable atoms or slots only under a new explicit Layout key/name, written to `spec_lock.md pptx_layouts` while authoring the first affected page. Changing only content is not a new Layout.
|
**Template adherence**: Strict preserves reusable Master/Layout atoms and slot ids/types/indices/default bounds/bindings. Under `layout`, the application plan may still change current text/tspans, line height, crop, and carrier-local geometry inside those bounds; `mirror` remains topology-frozen. Adaptive keeps the prototype Master and realizes only the Layout definition and page assignment already declared in `spec_lock.md`. If reusable atoms or slot topology/default bounds/bindings must change, stop before completing the page and return to Strategist to declare a new Layout key/name, update its definition and affected assignments, then read back and validate those planning fragments before resuming. Changing only content is not a new Layout.
|
||||||
|
|
||||||
**Layout-content boundary**: Mark only genuinely reusable fixed framing as a Master/Layout atom. Concrete titles, body copy, metrics, chart marks, images, and page-specific groups remain inside slot groups or ordinary Slide-local content groups. The exporter never infers or clusters structure.
|
**Layout-content boundary**: Mark only genuinely reusable fixed framing as a Master/Layout atom. Concrete titles, body copy, metrics, chart marks, images, and page-specific groups remain inside slot groups or ordinary Slide-local content groups. The exporter never infers or clusters structure.
|
||||||
|
|
||||||
|
|||||||
@@ -306,6 +306,48 @@ python3 scripts/slice_images.py <project>/images/illus_sheet.png --grid 2x3 \
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### 4.4 Registered subject/base pairs
|
||||||
|
|
||||||
|
Use this preparation when a person, product, creature, or other foreground
|
||||||
|
subject must cross native titles, panels, frames, cards, or shapes while the
|
||||||
|
original scene remains behind them. The final pair is one compositional asset:
|
||||||
|
|
||||||
|
| Output | Required content |
|
||||||
|
|---|---|
|
||||||
|
| Clean base | Full original canvas with the foreground subject removed and the hidden background reconstructed |
|
||||||
|
| Subject cutout | The same full canvas and subject position, with only the foreground subject visible on RGBA transparency |
|
||||||
|
|
||||||
|
**Mandatory — preserve registration**: Start both derivatives from the same
|
||||||
|
source. Preserve canvas dimensions, subject pose, scale, and position; do not
|
||||||
|
trim or independently crop either final output. Record the shared source and
|
||||||
|
pair relationship in the owning §VIII rows or Quick active-context resources.
|
||||||
|
|
||||||
|
**Preparation procedure**:
|
||||||
|
|
||||||
|
1. Use the active image-editing path to remove the subject and inpaint the clean base.
|
||||||
|
2. Use the same source to isolate the subject. Prefer a direct RGBA result.
|
||||||
|
3. When the active path cannot return transparency, place the isolated subject on one exact flat key color, then run `slice_images.py` as a `1x1` sheet with `--alpha` and without `--trim` so the full-canvas coordinates remain unchanged.
|
||||||
|
4. Save both final files under `<project>/images/` and mark them `no-crop` in the active resource authority.
|
||||||
|
|
||||||
|
Path A may use the existing single-image edit mode for each derivative; Path B
|
||||||
|
may perform the same edits with the host-native image tool:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 scripts/image_gen.py "Remove the foreground subject and reconstruct the hidden background; preserve the exact canvas" \
|
||||||
|
--reference-image <project>/images/<source>.png -o <project>/images -f <pair>_base
|
||||||
|
python3 scripts/image_gen.py "Isolate the same foreground subject at the exact original pose, scale, and position on a flat #00FF00 background" \
|
||||||
|
--reference-image <project>/images/<source>.png -o <project>/images -f <pair>_subject_key
|
||||||
|
python3 scripts/slice_images.py <project>/images/<pair>_subject_key.png --grid 1x1 \
|
||||||
|
--names <pair>_subject --alpha --bg "#00FF00"
|
||||||
|
```
|
||||||
|
|
||||||
|
The positional edit commands are allowed here as the declared derivation step
|
||||||
|
for already-planned pair rows; keep the final pair in the ordinary resource
|
||||||
|
authority and operational sidecar. SVG realization follows
|
||||||
|
[`image-layout-patterns.md`](./image-layout-patterns.md) `#A2-03`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 5. Global Hard Rules
|
## 5. Global Hard Rules
|
||||||
|
|
||||||
These rules apply to **every** prompt regardless of dimension choices. Append them as a closing sentence to every assembled prompt.
|
These rules apply to **every** prompt regardless of dimension choices. Append them as a closing sentence to every assembled prompt.
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ The following three patterns are topologically different and are not interchange
|
|||||||
|
|
||||||
- **#A2-01 · Transparent sticker or cutout** — use a prepared RGBA asset and preserve its open silhouette.
|
- **#A2-01 · Transparent sticker or cutout** — use a prepared RGBA asset and preserve its open silhouette.
|
||||||
- **#A2-02 · Subject breaking out of a container** — register a prepared foreground subject across its frame boundary.
|
- **#A2-02 · Subject breaking out of a container** — register a prepared foreground subject across its frame boundary.
|
||||||
- **#A2-03 · Registered subject/base pair** — align a base photo with its prepared transparent subject cutout in one coordinate system; optionally place a native title, panel, or shape between them so the subject crosses that middle layer.
|
- **#A2-03 · Registered subject/base pair** — align a clean base with its prepared transparent subject cutout in one coordinate system. Draw the base first, the native title/panel/shape second, and the cutout last. Give both images the same `x`, `y`, `width`, `height`, and aspect mapping; never trim or independently crop either layer.
|
||||||
|
|
||||||
### 5.3 A3 · Registered Derivatives
|
### 5.3 A3 · Registered Derivatives
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ A **rendering** is a visual style family: line quality, texture, depth, material
|
|||||||
|
|
||||||
## 1. Catalog (20 renderings)
|
## 1. Catalog (20 renderings)
|
||||||
|
|
||||||
Each rendering has its own file with: style paragraph, line / texture / depth notes, deck HEX usage, and a fewshot prompt snippet. A preset lock reads that one file. A catalog-based `custom` reads every preset named in `image_rendering_references`; a novel `custom` may omit references. Never glob the directory.
|
Each rendering keeps its own authoritative file with: style paragraph, line / texture / depth notes, deck HEX usage, and a fewshot prompt snippet. Read this index alone while choosing a direction. Only after a preset or custom bases are fixed may the active role read the selected sibling files: one file for a preset, every exact `image_rendering_references` file for a catalog-based custom, and none for a novel custom. Never glob the directory or read an unselected sibling. Whether AI imagery is recommended remains a separate source decision; Image_Generator follows the same selected-only rule.
|
||||||
|
|
||||||
### 1.1 Modern / commercial (the corporate-PPT main field)
|
### 1.1 Modern / commercial (the corporate-PPT main field)
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ Each rendering has its own file with: style paragraph, line / texture / depth no
|
|||||||
|
|
||||||
### 1.5 Escape hatch — `custom`
|
### 1.5 Escape hatch — `custom`
|
||||||
|
|
||||||
Whenever proposed image usage includes `ai`, Stage 2 authors one separate, visible custom rendering proposal in addition to the preset cards. It uses `rendering: custom` plus a complete behavior paragraph, remains initially unselected, and enters the confirmed contract only when the user chooses it. A template-backed proposal must honor inherited identity and the confirmed template-application plan.
|
Every coordinated Stage-2 direction carries one complete `rendering: custom` candidate even when `recommend.image_usage` does not include `ai`. The UI keeps rendering controls hidden until the current source selection includes AI, then exposes the three already-authored project candidates without another backend recommendation. The 20 fixed renderings remain lower-level single-select alternatives. A template-backed proposal must honor inherited identity and the confirmed template-application plan.
|
||||||
|
|
||||||
**Hard rule — `rendering_behavior` prose**:
|
**Hard rule — `rendering_behavior` prose**:
|
||||||
|
|
||||||
@@ -62,16 +62,16 @@ Whenever proposed image usage includes `ai`, Stage 2 authors one separate, visib
|
|||||||
|---|---|
|
|---|---|
|
||||||
| Length | One paragraph, 2-5 sentences |
|
| Length | One paragraph, 2-5 sentences |
|
||||||
| Axes covered | line / texture / depth / material / mood (same as preset files) |
|
| Axes covered | line / texture / depth / material / mood (same as preset files) |
|
||||||
| Catalog basis | When existing renderings are combined or borrowed, name every exact id and read every named file before synthesis |
|
| Catalog basis | Freeze every exact id from this index, then read only those named files before synthesis |
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- image_rendering: custom
|
- image_rendering: custom
|
||||||
- image_rendering_behavior: "Hand-screened poster aesthetic — slightly misregistered halftone overlays, 3 flat ink colors with visible dot pattern at 12% opacity, no gradients, no anti-aliased edges; reads as silkscreen print."
|
- image_rendering_behavior: "Hand-screened poster aesthetic — slightly misregistered halftone overlays, 3 flat ink colors with visible dot pattern at 12% opacity, no gradients, no anti-aliased edges; reads as silkscreen print."
|
||||||
```
|
```
|
||||||
|
|
||||||
**Hard rule**: the custom candidate is mandatory when AI images are proposed; selecting `custom` is a tail-case, not the default. See [`strategist-image.md`](../strategist-image.md) for the Stage-2 carrier and downstream lock behavior.
|
**Hard rule**: three complete rendering candidates are mandatory in every fresh Stage-2 direction set; AI source recommendation remains independent. See [`strategist-image.md`](../strategist-image.md) for the Stage-2 carrier and downstream lock behavior.
|
||||||
|
|
||||||
Write `image_rendering_references` only when the custom direction actually uses catalog material. Keep the list exact: a blend of `screen-print` and `watercolor` reads both files and lists both ids. A genuinely new rendering with no catalog source omits the field and proceeds from its standalone behavior; never invent a reference merely to legitimize `custom`.
|
Write `image_rendering_references` only when the confirmed custom direction actually uses catalog material. Keep the list exact: a blend of `screen-print` and `watercolor` lists both ids. A genuinely new rendering with no catalog source omits the field and proceeds from its standalone behavior; never invent a reference merely to legitimize `custom`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ A **mode** is the deck's **narrative + persuasion skeleton** — how the argumen
|
|||||||
|
|
||||||
## 1. Catalog (5 modes)
|
## 1. Catalog (5 modes)
|
||||||
|
|
||||||
Each mode has its own file with: narrative skeleton, page-structure tendencies, speaker-notes register, and a page skeleton example. Default reads the locked preset file; Quick reads the preset it resolves in active context. A catalog-based `custom` reads every preset actually used as a basis; a novel `custom` reads none. Never glob the directory.
|
Each mode keeps its own authoritative file with: narrative skeleton, page-structure tendencies, speaker-notes register, and a page skeleton example. Read this index alone while choosing a direction. Only after a preset or custom bases are fixed may the active role read the selected sibling files: one file for a preset, every exact `mode_references` file for a catalog-based custom, and none for a novel custom. Never glob the directory or read an unselected sibling.
|
||||||
|
|
||||||
| Mode | Narrative skeleton | Best for |
|
| Mode | Narrative skeleton | Best for |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -18,7 +18,7 @@ Each mode has its own file with: narrative skeleton, page-structure tendencies,
|
|||||||
| [`showcase`](./showcase.md) | Visual-led impact; big imagery / numbers; emotional rhythm | Launches, brand reveals, event / promo decks |
|
| [`showcase`](./showcase.md) | Visual-led impact; big imagery / numbers; emotional rhythm | Launches, brand reveals, event / promo decks |
|
||||||
| [`briefing`](./briefing.md) | Neutral, complete, scannable; topic titles, even weight, no thesis | Status updates, reference decks, catalogs, meeting packs, FAQs |
|
| [`briefing`](./briefing.md) | Neutral, complete, scannable; topic titles, even weight, no thesis | Status updates, reference decks, catalogs, meeting packs, FAQs |
|
||||||
|
|
||||||
> The five are **argument strategies, not a taxonomy of communication purposes**. A presentation may inform + align + request a decision at once; that composite intent stays as open prose in Default's Stage-1 communication contract or Quick's active brief. Default Stage 2 or the Quick main agent chooses the mode that best carries the dominant body-page spine, or one concrete `custom` act sequence when no preset can serve the stated priority / sequence.
|
> The five are **argument strategies, not a taxonomy of communication purposes**. A presentation may inform + align + request a decision at once; that composite intent stays as open prose in Default's Stage-1 communication contract or Quick's active brief. Default uses this index to map each whole solution intent into one project-specific custom behavior; Quick resolves one preset or custom direction directly.
|
||||||
>
|
>
|
||||||
> **A mode is a lens, not a mandate over an explicitly preserved structure.** Default applies the confirmed `content_divergence`; Quick applies the equivalent user-stated or active-context boundary to a supplied outline. An ordinary source outline is a Reference that the mode may regroup, reorder, or retitle while preserving its facts and intended relationships. Preserve page order, titles, or wording only when the user presents the outline as the final page plan or explicitly requests that boundary. When the user gives no structure, the mode does the structural lifting. To keep reshaping light, `briefing` imposes the least skeleton.
|
> **A mode is a lens, not a mandate over an explicitly preserved structure.** Default applies the confirmed `content_divergence`; Quick applies the equivalent user-stated or active-context boundary to a supplied outline. An ordinary source outline is a Reference that the mode may regroup, reorder, or retitle while preserving its facts and intended relationships. Preserve page order, titles, or wording only when the user presents the outline as the final page plan or explicitly requests that boundary. When the user gives no structure, the mode does the structural lifting. To keep reshaping light, `briefing` imposes the least skeleton.
|
||||||
|
|
||||||
@@ -53,8 +53,8 @@ Each mode has its own file with: narrative skeleton, page-structure tendencies,
|
|||||||
|
|
||||||
| Active profile | Use |
|
| Active profile | Use |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Default Generate | Strategist reads this index at confirmation `d. Layer 1`, authors the required candidate set, records the confirmed mode in `design_spec.md`, and projects it to `spec_lock.md`; Executor reads the locked preset or exact custom references |
|
| Default Generate | Strategist reads only this index while mapping three whole solution intents, freezes each custom direction's exact bases, then reads only their deduplicated detail files. Executor reads the confirmed preset file or exact custom references. |
|
||||||
| Quick Generate | The current main agent reads this index, resolves the best-fit preset or one warranted custom behavior without interaction, reads only the exact preset source(s) actually used, and keeps the result in active context without Design Spec/lock |
|
| Quick Generate | The current main agent reads only this index while deciding, then reads the resolved preset or exact custom bases and keeps that one direction in active context without Design Spec/lock. |
|
||||||
|
|
||||||
**Resolution scope**: deck-wide (one mode per deck). The five are the catalog you select from; if the structure is genuinely mixed, pick the mode of the body pages and let pages vary within it, or use a warranted `custom` blend (§4). Default recommends and confirms; Quick decides directly.
|
**Resolution scope**: deck-wide (one mode per deck). The five are the catalog you select from; if the structure is genuinely mixed, pick the mode of the body pages and let pages vary within it, or use a warranted `custom` blend (§4). Default recommends and confirms; Quick decides directly.
|
||||||
|
|
||||||
@@ -64,14 +64,14 @@ Each mode has its own file with: narrative skeleton, page-structure tendencies,
|
|||||||
|
|
||||||
`custom` holds **any bespoke narrative direction the five don't give as-is** — and what *kind* of thing it is doesn't matter. It might be a nameable cadence (dialectic 正反合, myth-vs-reality, countdown / Top-N, Socratic), a deliberate multi-act fusion of several modes, or the user's own feel for how the deck should carry (confrontational here, detached there). Don't try to taxonomize it.
|
`custom` holds **any bespoke narrative direction the five don't give as-is** — and what *kind* of thing it is doesn't matter. It might be a nameable cadence (dialectic 正反合, myth-vs-reality, countdown / Top-N, Socratic), a deliberate multi-act fusion of several modes, or the user's own feel for how the deck should carry (confrontational here, detached there). Don't try to taxonomize it.
|
||||||
|
|
||||||
**Default candidate**: Stage 2 includes one visible, non-empty AI custom proposal beside the five presets, spelling out the cadence / fusion / posture in plain language. It is initially unselected and does not replace the best-fit preset recommendation unless the user already supplied that exact custom direction; with a template, it must fit available prototype capacity. When the user selects it, the editable prose is saved as `mode: custom` plus `mode_behavior`; otherwise it remains recommendation-only. The Strategist crystallizes a selected custom direction in the Design Spec first, then projects the behavior and any actual catalog basis to `spec_lock.md`. The Executor reads every listed basis file before following that prose, or follows it directly when the direction is novel.
|
**Default candidates**: All three coordinated Stage-2 directions use literal `custom` plus a visible, non-empty `mode_behavior`. A direction may specialize one preset, fuse several modes, or define a novel cadence; it fits any installed template capacity. The fixed five remain lower-level single-select alternatives. Strategist crystallizes the confirmed current value in the Design Spec first, then projects its behavior and actual catalog basis to `spec_lock.md`.
|
||||||
|
|
||||||
**Quick custom**: do not author or display a candidate set. Use `custom` only when no single preset supplies the dominant spine, resolve its behavior directly in active context, and read every catalog source actually used as a basis. Persist nothing.
|
**Quick custom**: do not display a candidate set. Use `custom` only when a project-specific specialization or fusion serves the deck better than one preset; retain the behavior and exact bases in active context and persist nothing.
|
||||||
|
|
||||||
**Mandatory — read every catalog source actually used**: If a custom direction combines or borrows an existing mode, name its exact catalog id and read that mode file before writing the synthesis. A `pyramid` + `narrative` fusion therefore reads both [`pyramid.md`](./pyramid.md) and [`narrative.md`](./narrative.md). Default writes `mode_references: pyramid, narrative` beside `mode_behavior`; Quick retains those bases only in active context. Do not add loosely related references after the fact. A genuinely new cadence reads no catalog source.
|
**Mandatory — select before detail reading**: Use this index to freeze every catalog source actually used, then read only those exact files before writing the behavior. A `pyramid` + `narrative` fusion therefore reads those two files and writes `mode_references: pyramid, narrative` beside `mode_behavior`; Quick retains those bases only in active context. Do not open candidates for comparison after this gate or add loosely related references after the fact. A genuinely new cadence names and reads no catalog source.
|
||||||
|
|
||||||
> **One value per deck — fusion is *one* `custom`, not several modes.** A deck always resolves a single `mode`. A multi-mode blend is expressed as **one** custom behavior whose paragraph describes the acts — never as several simultaneous modes.
|
> **One value per deck — fusion is *one* `custom`, not several modes.** A deck always resolves a single `mode`. A multi-mode blend is expressed as **one** custom behavior whose paragraph describes the acts — never as several simultaneous modes.
|
||||||
>
|
>
|
||||||
> **First ask whether it's really fusion.** A resolved mode is a *tendency*, not a cage: a `narrative` deck can still carry one analytical (pyramid-style) page, an `instructional` deck one showcase reveal — that is leaning within a dominant mode, and needs **no** `custom`. Reach for `custom` only when there is genuinely no single dominant spine.
|
> **Custom need not mean fusion.** A Default recommendation can specialize one dominant preset for this project's act sequence, title voice, rhythm, and register. Quick or a lower-level manual choice may still use the fixed preset directly.
|
||||||
|
|
||||||
**The one thing to avoid**: selecting `custom` as a *dodge* — defaulting to it because picking among the five takes judgment. Default's custom candidate is mandatory; selecting it is not. Quick creates no candidate. When a preset genuinely fits, keep that preset selected. A user-stated direction remains authoritative the same way a user-supplied outline is — see the lens-not-mandate note in §1.
|
**Forbidden — empty customization**: Do not relabel an index row as `custom`. The behavior must state the project-specific cadence, posture, title voice, page rhythm, or act sequence that the fixed preset alone does not encode. A user-stated direction remains authoritative the same way a user-supplied outline is — see the lens-not-mandate note in §1.
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ Mandatory reference for every route that authors or regenerates slide visuals th
|
|||||||
| Concern | Shared default |
|
| Concern | Shared default |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Text-block rhythm | Use §4.2 leading. Make the baseline step into a new paragraph visibly larger than the intra-paragraph line step; keep the extra gap between list items smaller than paragraph separation but large enough to scan each item. Repeated peer blocks share one rhythm unless their hierarchy differs. |
|
| Text-block rhythm | Use §4.2 leading. Make the baseline step into a new paragraph visibly larger than the intra-paragraph line step; keep the extra gap between list items smaller than paragraph separation but large enough to scan each item. Repeated peer blocks share one rhythm unless their hierarchy differs. |
|
||||||
|
| Typography roles | Use the fewest semantic text roles that preserve hierarchy, and make their differences legible at slide-thumbnail scale. Consolidate near-neighbor sizes that serve the same role; otherwise distinguish roles through a deliberate combination of size, weight, color, position, and surrounding space. |
|
||||||
| Natural wrapping | Break at semantic phrase or punctuation boundaries where possible. Reflow the text frame or adjust neighboring geometry before using any permitted local size reduction. Let the final line run naturally shorter; avoid mechanically equal lines or a stranded single-character / single-word line when an earlier natural break preserves meaning. |
|
| Natural wrapping | Break at semantic phrase or punctuation boundaries where possible. Reflow the text frame or adjust neighboring geometry before using any permitted local size reduction. Let the final line run naturally shorter; avoid mechanically equal lines or a stranded single-character / single-word line when an earlier natural break preserves meaning. |
|
||||||
|
| Content field | Establish the usable body frame before placing modules. Divide it into a small set of unequal-weight macro-regions from information weight and reading order, then give each region its own local axes / micro-grid while retaining only the cross-region anchors the composition needs. On a dense page, let the planned content system organize that frame; create breathing room through gutters, module spacing, and intentional voids between semantic clusters. Unorganized residual space that leaves content stranded in one part of the frame is leftover blank, not negative space. |
|
||||||
| Alignment and proximity | Establish shared axes from the current composition. Align related titles, copy, labels, images, and diagram nodes to those edges, centers, or baselines; group related elements more tightly than unrelated groups so spacing carries hierarchy. Break an axis only when the offset performs hierarchy, direction, or tension. |
|
| Alignment and proximity | Establish shared axes from the current composition. Align related titles, copy, labels, images, and diagram nodes to those edges, centers, or baselines; group related elements more tightly than unrelated groups so spacing carries hierarchy. Break an axis only when the offset performs hierarchy, direction, or tension. |
|
||||||
| Visual weight | Judge weight from area, darkness, saturation, density, stroke, image detail, and elevation together. Distribute it to support the focal path; symmetry is optional, and deliberate imbalance may create direction. |
|
| Visual weight | Judge weight from area, darkness, saturation, density, stroke, image detail, and elevation together. Distribute it to support the focal path; symmetry is optional, and deliberate imbalance may create direction. |
|
||||||
| Containers | Use a card or panel when it expresses grouping, hierarchy, boundary, capacity, or a distinct material plane. Otherwise prefer spacing, rules, or direct text / geometry; peer containers share treatment unless a semantic difference justifies contrast. |
|
| Containers | Use a card or panel when it expresses grouping, hierarchy, boundary, capacity, or a distinct material plane. Otherwise prefer spacing, rules, or direct text / geometry; peer containers share treatment unless a semantic difference justifies contrast. |
|
||||||
|
|||||||
@@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
# Strategist Image Planning
|
# Strategist Image Planning
|
||||||
|
|
||||||
Conditional extension for formula assets, proposed / confirmed image elaboration, AI rendering selection, and `design_spec.md §VIII` resource planning.
|
Always-on Stage-2 rendering-candidate extension plus conditional formula assets, confirmed image elaboration, and `design_spec.md §VIII` resource planning.
|
||||||
|
|
||||||
**Trigger**: Load before Stage-2 directions for a proposed non-`none` source, an explicit non-`none` constraint, or formulas. If confirmed `none` becomes non-`none`, load after Stage 2 without backfilling candidates. Confirmed `none` without formulas stops before resources. A formula-only path reads §3 and §4 formula rows only. [`strategist.md`](./strategist.md) owns source recommendation; this module owns image-dependent candidates, production detail, and §VIII rows.
|
**Trigger**: Load before every fresh Stage-2 direction set. Apply §2 first from the rendering index, freeze each direction's exact bases, and only then read the deduplicated selected detail files before completing its behavior. [`strategist.md`](./strategist.md) independently owns source recommendation. A confirmed non-`none` source activates the applicable resource-planning sections; confirmed `none` without formulas stops before resources, while a formula-only path applies §3 and §4 formula rows only. Rendering candidates are authored once before confirmation and never backfilled from a later source toggle.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Proposed and Confirmed Image Plan
|
## 1. Proposed and Confirmed Image Plan
|
||||||
|
|
||||||
Before Stage 2, use proposed sources only for candidate construction. After confirmation, discard candidate-only sources, map the confirmed set through [`strategist.md`](./strategist.md) §h, and honor explicit `image_notes` roles; this module never adds a source. The confirmed non-`none` set is an allowed acquisition boundary, not coverage: use a suitable subset and leave irrelevant sources unused. Explicit must-use sources, assets, or page roles remain required. Asset inventory and judgment determine unconfirmed count, subject, placement, and composition without substituting an unconfirmed source.
|
Before Stage 2, construct rendering candidates independently of the proposed source set. After confirmation, map the confirmed source set through [`strategist.md`](./strategist.md) §h and honor explicit `image_notes` roles; this module never adds a source. The confirmed non-`none` set is an allowed acquisition boundary, not coverage: use a suitable subset and leave irrelevant sources unused. Explicit must-use sources, assets, or page roles remain required. Asset inventory and judgment determine unconfirmed count, subject, placement, and composition without substituting an unconfirmed source.
|
||||||
|
|
||||||
For illustration, apply this precedence: confirmed `none` → explicit user intent → the locked visual style's `Illus.` propensity (`core` / `supportive` / `sparse`) → none. Propensity controls the lean, not the source or a page quota. When illustration is active, prefer one coherent motif family across hero/section anchors and local spots, but only when the confirmed assets can form that family.
|
For illustration, apply this precedence: confirmed `none` → explicit user intent → the locked visual style's `Illus.` propensity (`core` / `supportive` / `sparse`) → none. Propensity controls the lean, not the source or a page quota. When illustration is active, prefer one coherent motif family across hero/section anchors and local spots, but only when the confirmed assets can form that family.
|
||||||
|
|
||||||
@@ -18,13 +18,15 @@ For illustration, apply this precedence: confirmed `none` → explicit user inte
|
|||||||
|
|
||||||
**Default — one coherent sheet for compatible same-family spots (may override when aspect, detail, quality, or semantic needs differ)**: prefer one Illustration Sheet when several AI-generated spots can share a useful cell shape and production treatment; generate them independently when forcing one sheet would weaken a planned element. When a sheet is chosen, plan one unplaced `ai` Illustration Sheet row plus one placed `slice` row per used element; only slice rows enter `spec_lock.md images`. State the intended placement shape family in the sheet reference and use separate sheets for incompatible shapes. [`image-generator.md`](./image-generator.md) §4.3 owns grid, ratio, slicing, and execution details. Final Stage 2 chooses the AI execution path under `image-generator.md` §7; do not pre-empt or re-pick it here.
|
**Default — one coherent sheet for compatible same-family spots (may override when aspect, detail, quality, or semantic needs differ)**: prefer one Illustration Sheet when several AI-generated spots can share a useful cell shape and production treatment; generate them independently when forcing one sheet would weaken a planned element. When a sheet is chosen, plan one unplaced `ai` Illustration Sheet row plus one placed `slice` row per used element; only slice rows enter `spec_lock.md images`. State the intended placement shape family in the sheet reference and use separate sheets for incompatible shapes. [`image-generator.md`](./image-generator.md) §4.3 owns grid, ratio, slicing, and execution details. Final Stage 2 chooses the AI execution path under `image-generator.md` §7; do not pre-empt or re-pick it here.
|
||||||
|
|
||||||
## 2. AI Image Strategy — propose only for recommended `ai`; lock any confirmed `ai`
|
**Mandatory — subject-layer capability scan**: When a supplied reference or the intended composition shows a subject crossing a native title, panel, frame, or shape, plan a registered subject/base pair before writing §VIII. Add one clean full-canvas base row and one same-canvas RGBA subject row, give both `Crop Policy: no-crop`, name their shared source and registration relationship in `Reference`, and suggest `#A2-03` for the subject row. Use `Acquire Via: user` only when both final assets are already supplied; otherwise use `ai` for the prepared derivatives. [`image-generator.md`](./image-generator.md) §4.4 owns preparation. A simple floating cutout that does not re-layer over its source may use `#A2-01` instead.
|
||||||
|
|
||||||
When proposed sources include `ai`, read [`image-renderings/_index.md`](./image-renderings/_index.md) before constructing Stage 2. Unless the user or active template already names a rendering, place at least three credible, distinct preset renderings across the coordinated safe/shifted/bold directions; a genuine compatibility shortfall may return fewer with a reason. Each preset `image_strategy` carries localized `rendering`, `visual`, and `mood` only. Mood includes a recognizable real-world analogy. Image colors always inherit that direction's deck HEX roles; never add an image palette or alter deck colors to rescue a rendering.
|
## 2. AI Image Strategy — always propose three; lock only for confirmed `ai`
|
||||||
|
|
||||||
Also write one `custom_candidates.image_strategy` under the Confirm UI contract: localized `name` / `visual` / `mood`, `rendering: custom`, and non-empty localized `behavior` satisfying the catalog grammar. If it combines or borrows existing renderings, name every exact id in the visible proposal and read every corresponding `image-renderings/<id>.md` before writing the synthesis. If it is genuinely novel, read no preset file and name no catalog basis. Keep it unselected unless the user supplied it (`recommend.image_strategy: custom`); under a template it obeys inherited identity and application. Only a selected custom locks its edited behavior as `image_rendering_behavior`; when catalog material is actually used, also project the exact ids as `image_rendering_references`, otherwise omit that field. Discard an unselected candidate downstream. Ignore legacy `image_palette`.
|
Before any rendering detail, read only [`image-renderings/_index.md`](./image-renderings/_index.md). First author exactly three complete, project-fit solution intents; use the index to freeze each intent's exact rendering bases, then read once only the deduplicated referenced sibling files. Project one complete `image_strategy` into each direction regardless of `recommend.image_usage`. Every candidate carries localized `name`, `rendering: custom`, `visual`, `mood`, and non-empty localized `behavior`. Mood includes a recognizable real-world analogy. All three must credibly serve their owning whole solution, but they need not use different bases or span artificial safe / shifted / bold extremes. Image colors always inherit that direction's deck HEX roles; never add an image palette or alter deck colors to rescue a rendering.
|
||||||
|
|
||||||
Post-confirmation AI activation creates no candidates: read the selected preset, or consume custom behavior/references.
|
Every direction is a `custom` rendering. If it specializes, combines, or borrows existing renderings, name every exact index-selected id in its visible behavior and read only those files after selection; if it is genuinely novel, name no basis and read none. Under a template it obeys inherited identity and application. Only a confirmed custom locks its edited behavior as `image_rendering_behavior`; when catalog material is actually used, also project the exact ids as `image_rendering_references`, otherwise omit that field. Unselected candidates remain recommendation-only. Do not write a separate fourth `custom_candidates.image_strategy`; ignore legacy `image_palette`.
|
||||||
|
|
||||||
|
The UI hides these candidates while AI is not selected. If the user adds AI, it reveals the already-authored three without another backend recommendation; source selection never creates or rewrites rendering candidates. After confirmation, Image_Generator reads only the selected preset or exact custom references and must not blend unselected candidate identities.
|
||||||
|
|
||||||
For specialized or regulated paper-figure subjects, preserve the prompt depth required by [`image-generator.md`](./image-generator.md) §4.2 rather than shortening to a generic brief. Scan the outline for genuine image-led pages, list the proposed hero pages in Stage-2 `image_notes` so the user can retain, edit, or remove them in the same confirmation, then mark only the confirmed pages' AI rows `page_role: hero_page`; local is the default. `text_policy: embedded` is reserved for stable figure-internal identifiers or lettering deliberately fused into the artwork; page titles, editable data values/labels, and prose remain SVG. Resolve confirmed provided assets through the context-first boundary above before writing §VIII.
|
For specialized or regulated paper-figure subjects, preserve the prompt depth required by [`image-generator.md`](./image-generator.md) §4.2 rather than shortening to a generic brief. Scan the outline for genuine image-led pages, list the proposed hero pages in Stage-2 `image_notes` so the user can retain, edit, or remove them in the same confirmation, then mark only the confirmed pages' AI rows `page_role: hero_page`; local is the default. `text_policy: embedded` is reserved for stable figure-internal identifiers or lettering deliberately fused into the artwork; page titles, editable data values/labels, and prose remain SVG. Resolve confirmed provided assets through the context-first boundary above before writing §VIII.
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ When the communication contract conflicts with the workspace, choose and state t
|
|||||||
|
|
||||||
> Internal note: `content_divergence` controls source reorganization; the AI-derived `template_reuse_scope` records the reused layer; `template_adherence` records whether a structured plan keeps or extends existing Layout identities.
|
> Internal note: `content_divergence` controls source reorganization; the AI-derived `template_reuse_scope` records the reused layer; `template_adherence` records whether a structured plan keeps or extends existing Layout identities.
|
||||||
|
|
||||||
**Template design precedence**: Explicit current user instructions and final confirmation win. Brand identity overrides Deck identity, Layout structure overrides Deck structure, and Deck retains only its non-overridden integrated segments plus reusable application context. Style owns Direction / method only: its color, typography, icon, and image values are candidate defaults and never override resolved Brand/Deck identity or become official facts. Preferred Mode / Visual Style values seed Stage 2; the Style overlay must resolve into the final single `mode` and `visual_style` lock rather than create a parallel narrative or aesthetic authority. Style takes this segment ahead of ordinary Stage-2 defaults; actual Deck prototypes and Signature facts remain compatibility constraints, not a second method owner. Library/explicit provenance never changes this order. Each of ≥3 directions still carries six palette roles and complete fonts: repeat fixed Brand/Deck values with `typography.fixed: true`; adapt Style candidates to that identity and vary only open roles. Keep resolved icon and image constraints. Style Review Focus never activates [`visual-review`](../workflows/stages/visual-review.md); only an explicit user request does.
|
**Template design precedence**: Explicit current user instructions and final confirmation win. Brand identity overrides Deck identity, Layout structure overrides Deck structure, and Deck retains only its non-overridden integrated segments plus reusable application context. Style owns Direction / method only: its color, typography, icon, and image values are candidate defaults and never override resolved Brand/Deck identity or become official facts. Preferred Mode / Visual Style values seed Stage 2; the Style overlay must resolve into the final single `mode` and `visual_style` lock rather than create a parallel narrative or aesthetic authority. Style takes this segment ahead of ordinary Stage-2 defaults; actual Deck prototypes and Signature facts remain compatibility constraints, not a second method owner. Library/explicit provenance never changes this order. Each of the three directions still carries six palette roles and complete fonts: repeat fixed Brand/Deck values with `typography.fixed: true`; adapt Style candidates to that identity and vary only open roles. Keep resolved icon and image constraints. Style Review Focus never activates [`visual-review`](../workflows/stages/visual-review.md); only an explicit user request does.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -36,15 +36,15 @@ solution + production gate:
|
|||||||
| **1 — communication contract + template choice** | `primary_language` · `c` audience · open-ended communication intent · audience outcome · core message / delivery context (primary + optional secondary) / artifact afterlife · `content_divergence` (all prose fields may be blank) · `a` canvas · explicit `free_design` or `templates` choice and selected roots | confirmed together; candidate workspaces do not influence the communication recommendation |
|
| **1 — communication contract + template choice** | `primary_language` · `c` audience · open-ended communication intent · audience outcome · core message / delivery context (primary + optional secondary) / artifact afterlife · `content_divergence` (all prose fields may be blank) · `a` canvas · explicit `free_design` or `templates` choice and selected roots | confirmed together; candidate workspaces do not influence the communication recommendation |
|
||||||
| **2 — final solution + production** (authored once from the user's *actual* Stage 1) | reading mode (`delivery_purpose`, PPT only) · `d` mode + visual style · `b` page count · `e` color · `f` icon · `g` typography · `h` image source + generated-image rendering · conditional natural-language template application · formula policy · conditional AI-image acquisition path · generation mode · refine-spec toggle · proactive speaker notes / custom animations / narration audio | derived as one coherent plan from the confirmed contract; internal template exporter modes remain hidden |
|
| **2 — final solution + production** (authored once from the user's *actual* Stage 1) | reading mode (`delivery_purpose`, PPT only) · `d` mode + visual style · `b` page count · `e` color · `f` icon · `g` typography · `h` image source + generated-image rendering · conditional natural-language template application · formula policy · conditional AI-image acquisition path · generation mode · refine-spec toggle · proactive speaker notes / custom animations / narration audio | derived as one coherent plan from the confirmed contract; internal template exporter modes remain hidden |
|
||||||
|
|
||||||
Do not force communication intent into one catalog label; Stage 1 records composite intent in prose. Editable prose fields are recommendation drafts, not required inputs: confirmation preserves current text and blanks; never repopulate a cleared field. Stage 2 confirms narrative spine, reading density, page budget, visual system, image direction, production mechanics, and how any installed template should be used. It never chooses or installs a template. Inspect only project-local template spec/prototypes, present one editable application plan, and keep exporter reuse/adherence internal. Present ≥3 coordinated safe / shifted / bold directions so color, type, icons, and generated-image rendering begin coherent; the user may override each component. Generated images inherit deck colors—there is no second image palette. Proactive defaults are speaker notes `true`, custom animations `false`, and narration audio `false`; a prior explicit user instruction overrides the matching recommendation, and effective narration audio requires effective speaker notes. Author each stage once; same-stage edits update only visible browser state through documented deterministic dependencies, without another AI/backend recommendation. Launch/derive/wait mechanics live in [`generate-pptx.md`](../workflows/generate-pptx.md) Step 4; item specs keep `a`–`h`.
|
Do not force communication intent into one catalog label; Stage 1 records composite intent in prose. Editable prose fields are recommendation drafts, not required inputs: confirmation preserves current text and blanks; never repopulate a cleared field. Stage 2 confirms narrative spine, reading density, page budget, visual system, image direction, production mechanics, and how any installed template should be used. It never chooses or installs a template. Inspect only project-local template spec/prototypes, present one editable application plan, and keep exporter reuse/adherence internal. First author exactly three complete, project-fit solution directions from the confirmed contract and source; only then project each direction into mode, visual style, color, type, icons, and generated-image rendering for lower-level adjustment. Every direction projects a project-specific `custom` mode, `custom` visual style, and `custom` generated-image rendering; the fixed catalogs remain conservative lower-level single-select alternatives. All three must be viable and distinguishable as whole solutions, but do not force safe / shifted / bold archetypes, different catalog bases, or artificial extremes. Every direction carries a complete generated-image rendering candidate even when AI imagery is not recommended; `recommend.image_usage` independently decides whether AI is proposed. Generated images inherit deck colors—there is no second image palette. Proactive defaults are speaker notes `true`, custom animations `false`, and narration audio `false`; a prior explicit user instruction overrides the matching recommendation, and effective narration audio requires effective speaker notes. Author each stage once; same-stage edits update only visible browser state through documented deterministic dependencies, without another AI/backend recommendation. Launch/derive/wait mechanics live in [`generate-pptx.md`](../workflows/generate-pptx.md) Step 4; item specs keep `a`–`h`.
|
||||||
|
|
||||||
**Hard rule — Stage-1 source boundary**: Build the communication recommendation only from the current user request, source facts, conversation constraints, and project-initialization state. Author it before loading index summaries for a chat listing, and do not read any candidate spec, prototype, asset, or template-owned canvas. The same Stage-1 surface may display template controls, but their values are confirmation state, not recommendation evidence. Do not load or apply [`strategist-template.md`](./strategist-template.md) until Stage 1 is confirmed and the selected workspace has been installed for Stage 2.
|
**Hard rule — Stage-1 source boundary**: Build the communication recommendation only from the current user request, source facts, conversation constraints, and project-initialization state. Author it before loading index summaries for a chat listing, and do not read any candidate spec, prototype, asset, or template-owned canvas. The same Stage-1 surface may display template controls, but their values are confirmation state, not recommendation evidence. Do not load or apply [`strategist-template.md`](./strategist-template.md) until Stage 1 is confirmed and the selected workspace has been installed for Stage 2.
|
||||||
|
|
||||||
> **Execution discipline**: Step 3 is non-interactive candidate preparation. Stage 1 is the first BLOCKING checkpoint and closes communication plus template/free-design choice in one confirmation. Install/fuse any selection and complete its handoff before authoring final Stage 2. After final confirmation, proceed without another pause unless spec refinement is enabled.
|
> **Execution discipline**: Step 3 is non-interactive candidate preparation. Stage 1 is the first BLOCKING checkpoint and closes communication plus template/free-design choice in one confirmation. Its receipt is intermediate and MUST NOT end the task or produce a final chat reply. In the same active run, install/fuse any selection, complete its handoff, author fresh Stage 2, and enter the final confirmation wait. After final confirmation, proceed without another pause unless spec refinement is enabled.
|
||||||
>
|
>
|
||||||
> **One opt-in exception**: present the refinement line with the split-mode note ([`generate-pptx.md`](../workflows/generate-pptx.md) Step 4). Only explicit opt-in runs [`refine-spec`](../workflows/stages/refine-spec.md): write the Design Spec once, pass Gate 1, then stop before the lock for unrestricted chat revision. Never enter it unprompted.
|
> **One opt-in exception**: present the refinement line with the split-mode note ([`generate-pptx.md`](../workflows/generate-pptx.md) Step 4). Only explicit opt-in runs [`refine-spec`](../workflows/stages/refine-spec.md): write the Design Spec once, pass Gate 1, then stop before the lock for unrestricted chat revision. Never enter it unprompted.
|
||||||
|
|
||||||
> **Default presentation surface — Confirm UI.** Before the first actual confirmation phase, apply [`confirm_ui.md`](../scripts/docs/confirm_ui.md)'s sticky per-run surface decision; its explicit chat branch skips every UI command, and a chat selection after UI launch follows its in-run switch procedure. Chat-question tools alone do not select a branch. In the UI branch, `template_options.json` and `recommendations.stage1.json` open one Stage-1 page; its single submission writes the pure Strategist `result.json` plus the sidecar `template_selection.json`. After installation/free-design closure, `template_handoff.json` gates `.stage2.json`. The chat/delegated branch keeps equivalent state without fabricating those receipts. Replace only the active unconfirmed stage and print the URL plus combined Stage-1 summary/fallback without treating that handoff as confirmation. Stage 1 writes canonical BCP-47 `primary_language` apart from UI `lang`; Strategist projects it through Design Spec §I to lock communication. Stage 2 carries ≥3 safe / shifted / bold `design_directions`, each bundling visual style, a six-role HEX palette, primary-language heading/body typography plus an English companion only for non-English decks, icons, and conditional image rendering, plus the production fields above. Step 4 retains final confirmation from the selected channel for Design Spec authoring. `confirm_ui.md` owns selection-surface and staged-confirmation lifecycle.
|
> **Default presentation surface — Confirm UI.** Before the first actual confirmation phase, apply [`confirm_ui.md`](../scripts/docs/confirm_ui.md)'s sticky per-run surface decision; its explicit chat branch skips every UI command, and a chat selection after UI launch follows its in-run switch procedure. Chat-question tools alone do not select a branch. In the UI branch, `template_options.json` and `recommendations.stage1.json` open one Stage-1 page; its single submission writes the pure Strategist `result.json` plus the sidecar `template_selection.json`. After installation/free-design closure, `template_handoff.json` gates `.stage2.json`. The chat/delegated branch keeps equivalent state without fabricating those receipts. Replace only the active unconfirmed stage and print the URL plus combined Stage-1 summary/fallback without treating that handoff as confirmation. Stage 1 writes canonical BCP-47 `primary_language` apart from UI `lang`; Strategist projects it through Design Spec §I to lock communication. Stage 2 carries exactly three immutable `design_directions`, each with a unique stable id, `custom` mode, `custom` visual style, six-role HEX palette, primary-language heading/body typography plus an English companion only for non-English decks, icons, and `custom` generated-image rendering. A direction card applies its whole bundle; lower controls may then diverge through the three projected custom candidates or the fixed single-select catalogs, and clicking that card again restores the authored bundle. The final result stores only the current component values, never the direction id as execution authority. Step 4 retains final confirmation from the selected channel for Design Spec authoring. `confirm_ui.md` owns selection-surface and staged-confirmation lifecycle.
|
||||||
|
|
||||||
**Confirmed-value semantics**: confirmation preserves both the value and the owning field's semantic type. Apply the type to the affected property, not automatically to the whole object:
|
**Confirmed-value semantics**: confirmation preserves both the value and the owning field's semantic type. Apply the type to the affected property, not automatically to the whole object:
|
||||||
|
|
||||||
@@ -123,37 +123,37 @@ When authoring §IX, translate every purpose named in `communication_intent` int
|
|||||||
|
|
||||||
Two independent layers, each locks one preset or `custom`. Output: `d. Mode: <mode> + Visual style: <visual_style>`.
|
Two independent layers, each locks one preset or `custom`. Output: `d. Mode: <mode> + Visual style: <visual_style>`.
|
||||||
|
|
||||||
> **Mandatory AI custom candidates.** Every `recommendations.stage2.json` carries visible, non-empty `custom_candidates.mode` and `.visual_style`, initially unselected unless the user supplied that exact direction. If a proposal combines or borrows catalog entries, read every named entry file before authoring the synthesis and name those exact ids in the visible proposal; a genuinely novel proposal needs no catalog reference. If selected, spell the proposal out in plain language and save literal `custom` plus the edited `mode_behavior` / `visual_style_behavior`; otherwise it remains recommendation-only. Never write bespoke prose as the enum value.
|
> **Top-down custom direction construction.** Author three complete solution intents from the confirmed project contract and source before selecting any catalog basis; do not assemble three apparent solutions from independent mode/style/rendering picks. At that point only the three indexes may be in context. Use their summaries to freeze the exact reference ids for each direction, then read once only the deduplicated union of those referenced detail files and author the final behaviors. Every direction MUST serialize `mode: custom`, `visual_style: custom`, and `image_strategy.rendering: custom`, each with visible, non-empty behavior prose. A catalog-based custom names only its actual bases; a genuinely novel custom names none and reads no detail file. These three projections are the project-specific choices above the conservative fixed catalogs, not a fourth Custom proposal. Never glob a catalog, read an unselected sibling, or write bespoke prose as an enum value.
|
||||||
|
|
||||||
#### Layer 1 — Communication mode
|
#### Layer 1 — Communication mode
|
||||||
|
|
||||||
🚧 **GATE**: read [`modes/_index.md`](./modes/_index.md) before recommending.
|
🚧 **GATE**: before choosing a basis, read only [`modes/_index.md`](./modes/_index.md). After the three direction intents exist and their mode reference ids are frozen, read only those exact sibling files once; a novel mode reads none.
|
||||||
|
|
||||||
The deck's **narrative + persuasion skeleton** — how the argument is organized and advanced. Lock one preset from `pyramid` / `narrative` / `instructional` / `showcase` / `briefing`, or `custom` with behavior.
|
The deck's **narrative + persuasion skeleton** — how the argument is organized and advanced. Lock one preset from `pyramid` / `narrative` / `instructional` / `showcase` / `briefing`, or `custom` with behavior.
|
||||||
|
|
||||||
**Source**:
|
**Source**:
|
||||||
- User supplied their own outline / structure → preserve its facts and intended relationships, then apply the confirmed `content_divergence`. Treat an ordinary source outline as a Reference: regroup, reorder, or retitle when the communication contract benefits. Treat it as authoritative only when the user presents it as the final page plan or explicitly asks to preserve page order, titles, or wording; record that promoted boundary in `design_spec.md`. Still lock a mode for register, voice, and any permitted reshaping. `briefing` imposes the least if no particular "讲法" is intended.
|
- User supplied their own outline / structure → preserve its facts and intended relationships, then apply the confirmed `content_divergence`. Treat an ordinary source outline as a Reference: regroup, reorder, or retitle when the communication contract benefits. Treat it as authoritative only when the user presents it as the final page plan or explicitly asks to preserve page order, titles, or wording; record that promoted boundary in `design_spec.md`. Still lock a mode for register, voice, and any permitted reshaping. `briefing` imposes the least if no particular "讲法" is intended.
|
||||||
- Beautify / re-layout profile ([`beautify-pptx.md`](../workflows/profiles/beautify-pptx.md)) → the extracted source content is authoritative and **verbatim**, one step stricter than the user-outline case above. Each source slide becomes exactly one `§IX` page in source order; transcribe every content block word-for-word — never reshape / re-primary / condense / merge / split / reword. Lock `mode: briefing`; color (e) and typography (g) are whatever the user confirmed in the beautify plan — the source identity (theme or observed) by default, or a content / brand-aware alternative the beautify plan offered and the user picked — locked as truth (the beautify plan already ran the recommendation through the confirm UI, so do not re-recommend here). Charts / tables / images are regenerated from their extracted data in the inherited style: record only selected catalog references in §VII, keep unmatched chart/table plans in their §IX page blocks, and route pictures to §VIII. Data values stay frozen and the rendering is the deck's own; visuals are never carried over verbatim. Layout, hierarchy, rhythm, and visual rendering are what gets redesigned.
|
- Beautify / re-layout profile ([`beautify-pptx.md`](../workflows/profiles/beautify-pptx.md)) → the extracted source content is authoritative and **verbatim**, one step stricter than the user-outline case above. Each source slide becomes exactly one `§IX` page in source order; transcribe every content block word-for-word — never reshape / re-primary / condense / merge / split / reword. All three custom mode behaviors preserve that 1:1 boundary and may share `briefing` as their sole basis; do not manufacture narrative variation. Color (e) and typography (g) are whatever the user confirmed in the beautify plan — the source identity (theme or observed) by default, or a content / brand-aware alternative the beautify plan offered and the user picked — locked as truth. Charts / tables / images are regenerated from their extracted data in the inherited style: record only selected catalog references in §VII, keep unmatched chart/table plans in their §IX page blocks, and route pictures to §VIII. Data values stay frozen and the rendering is the deck's own; visuals are never carried over verbatim. Layout, hierarchy, rhythm, and visual rendering are what gets redesigned.
|
||||||
- A bespoke direction the five don't give — a nameable cadence (dialectic 正反合, myth-vs-reality, countdown, Socratic), a multi-act fusion of modes, or the user's own feel (confrontational here, detached there). Either the user asks, **or you recommend it** when a fusion / bespoke direction genuinely serves the deck better than a single preset (a recommendation the user confirms, like every lock). The *kind* doesn't matter → `mode: custom` + a `mode_behavior:` paragraph that **crystallizes the intent** (act sequence or posture shifts, title voice, page rhythm, register) concretely enough for the Executor to follow per page; it reads only `spec_lock.md`, never the chat. If the direction uses existing modes, read every corresponding `modes/<id>.md` before synthesis and retain those exact ids as its catalog basis; if it is genuinely new, do not invent a basis. One deck locks **one** value — a fusion is one `custom` describing the acts, never several modes. Avoid only the *dodge*: don't default to `custom` when a preset genuinely fits, and prefer a dominant mode + page-level variation when one mode leads.
|
- Each direction crystallizes one project-specific cadence / posture in `mode_behavior`: it may specialize one preset, fuse several modes into a multi-act sequence, or be genuinely novel. A catalog-based direction retains only the exact ids it actually uses; a novel direction invents no basis. One deck locks one `custom` value, never several simultaneous modes.
|
||||||
- No user structure or cadence → recommend from the confirmed `communication_intent`, `audience_outcome`, source texture, and delivery context using the index's auto-selection table. Composite intent does not automatically require `custom`: choose the dominant spine of the body pages when one exists; use a concrete `custom` act sequence only when no single spine can serve the stated priority / sequence. Present as a recommendation; the user may override.
|
- No user structure or cadence → derive each whole solution from the confirmed `communication_intent`, `audience_outcome`, source texture, and delivery context, then project its custom mode. The three directions may share a catalog basis when that is honestly best; distinguish them through project-specific behavior or other fields instead of forcing different bases.
|
||||||
|
|
||||||
Record the confirmed mode and rationale in `design_spec.md` first, including the exact catalog basis when a selected custom uses one. Then project `- mode:` to `spec_lock.md`; for `custom`, also project `- mode_behavior:` and, only when catalog material is actually used, `- mode_references: <id>, <id>`. Executor reads one file for a preset. For `custom`, it reads every listed reference before applying the behavior; an unreferenced novel custom follows the behavior directly.
|
Record the confirmed mode and rationale in `design_spec.md` first, including the exact catalog basis when a selected custom uses one. Then project `- mode:` to `spec_lock.md`; for `custom`, also project `- mode_behavior:` and, only when catalog material is actually used, `- mode_references: <id>, <id>`. Executor reads only those exact references; an unreferenced novel custom follows the behavior directly.
|
||||||
|
|
||||||
#### Layer 2 — Visual style
|
#### Layer 2 — Visual style
|
||||||
|
|
||||||
🚧 **GATE**: read [`visual-styles/_index.md`](./visual-styles/_index.md) before recommending.
|
🚧 **GATE**: before choosing a basis, read only [`visual-styles/_index.md`](./visual-styles/_index.md). After the three direction intents exist and their style reference ids are frozen, read only those exact sibling files once; a novel style reads none.
|
||||||
|
|
||||||
The deck's **visual aesthetic** — shape language, decoration density, whitespace rhythm, typographic character, texture. Anchors downstream fields e (Color), f (Icon), g (Typography), h (Image). Lock one preset from the catalog, or `custom`.
|
The deck's **visual aesthetic** — shape language, decoration density, whitespace rhythm, typographic character, texture. Anchors downstream fields e (Color), f (Icon), g (Typography), h (Image). Lock one preset from the catalog, or `custom`.
|
||||||
|
|
||||||
**Source**:
|
**Source**:
|
||||||
- User named a style (chat / template / beautify) → it is truth: map to the closest preset (or `custom` with a `visual_style_behavior` paragraph) and lock directly. **Skip the spectrum below** — do not re-offer choice they already made.
|
- User named a style (chat / template / beautify) → it is truth: retain it as the required basis or inherited anchor in every custom behavior. Keep the three whole solutions meaningful by varying only fields the user left open; when visual variation is forbidden, the three style behaviors may be identical.
|
||||||
- No user description → **present a personality spectrum, not one safe pick** (this is the lever against "every deck looks the same" — the visual style is what most determines a deck's character, so it gets real choice, like the alternative-set rule used for image rendering). Author **≥3 distinct styles** from the index's auto-selection table spanning *safe* (the industry-norm recommendation) → *shifted* (an alternate one tick more expressive) → *bold* (a characterful style that challenges the default — `brutalist` / `zine` / `memphis` / `ink-wash` / `vintage-poster` etc., whenever the content can carry it). Give each a one-line **temperament tag + real-world analogy** (for example, "like an Economist feature"). Write the three to `recommendations.stage2.json` `visual_style_spectrum` (each `{id, tag_zh/en/ja, note_zh/en/ja}` — include the `_ja` variants whenever the page `lang` is `ja`) **and present the same three in chat** as the always-valid fallback; set `recommend.visual_style` to the *safe* pick as the pre-selected default. The user may pick any of the three or the separate full-copy Custom proposal. Honest-shortfall may reduce the preset set, never remove Custom.
|
- No user description → author three project-fit whole solutions first, then project one complete custom aesthetic for each. Directions may share catalog bases when their overall systems still differ meaningfully. Do not force different bases, a safe-to-bold ladder, or one deliberately extreme option merely to manufacture variety. Give each direction a localized name and concise real-world outcome note; the Confirm UI exposes the three project-specific styles above all 18 fixed manual alternatives.
|
||||||
|
|
||||||
**Forbidden — a non-catalog name as `visual_style`**: the value MUST be an `id` from the visual-styles catalog or literal `custom`; bespoke prose belongs only in `visual_style_behavior`. A name that is **not** in that catalog is not a visual style — most often it is an image-rendering name from the `_index` "Paired rendering" column (`flat`, `vector-illustration`, `digital-dashboard`, `3d-isometric`, `corporate-photo`, …), which names the §h *illustration* family, not the deck's layout aesthetic. Do not borrow it. (Names that are intentionally **both** a style and its paired rendering — `glassmorphism`, `blueprint`, `editorial`, `dark-tech` — are valid styles because they *are* in the catalog.) Generic baseline words — `flat` / flat-design / 扁平 / modern / clean / simple / minimal — are **not** custom-worthy either: the whole system is flat by default (shadows discouraged), so map them to the closest preset (flat + grid → `swiss-minimal`; flat + rounded → `soft-rounded`; flat + dense → `brutalist`). Reserve a custom lock for an aesthetic no preset covers; the mandatory candidate does not make it the default.
|
**Forbidden — a non-catalog name as `visual_style`**: every direction recommendation uses literal `custom` for `visual_style`; bespoke prose belongs only in `visual_style_behavior`, while optional `visual_style_references` contain only first-column catalog ids. A name from the `_index` "Paired rendering" column (`flat`, `vector-illustration`, `digital-dashboard`, `3d-isometric`, `corporate-photo`, …) is an image-rendering id, not a style reference. Generic words such as flat / modern / clean / simple / minimal are also insufficient behavior: use the index to choose an exact basis when applicable, then state the project-specific shape language, composition, density, whitespace, typography, and texture.
|
||||||
|
|
||||||
**Carries no color.** A visual style governs how the deck's HEX (locked at `e`) is *used* — never which colors, same discipline as [`image-renderings`](./image-renderings/_index.md). When the deck has AI images, prefer the style's paired rendering so layout and illustration share one aesthetic.
|
**Carries no color.** A visual style governs how the deck's HEX (locked at `e`) is *used* — never which colors, same discipline as [`image-renderings`](./image-renderings/_index.md). When the deck has AI images, prefer the style's paired rendering so layout and illustration share one aesthetic.
|
||||||
|
|
||||||
Record the confirmed visual style and rationale in `design_spec.md` first, including the exact catalog basis when a selected custom uses one. Then project `- visual_style:` to `spec_lock.md`; for `custom`, also project `- visual_style_behavior:` and, only when catalog material is actually used, `- visual_style_references: <id>, <id>`. Executor reads one file for a preset. For `custom`, it reads every listed reference before applying the behavior; an unreferenced novel custom follows the behavior directly.
|
Record the confirmed visual style and rationale in `design_spec.md` first, including the exact catalog basis when a selected custom uses one. Then project `- visual_style:` to `spec_lock.md`; for `custom`, also project `- visual_style_behavior:` and, only when catalog material is actually used, `- visual_style_references: <id>, <id>`. Executor reads only those exact references; an unreferenced novel custom follows the behavior directly.
|
||||||
|
|
||||||
**Conditional template workspace**: When the Stage-1 template choice has been installed into `<project_path>/templates/`, read [`strategist-template.md`](./strategist-template.md) before completing Stage 2. Read the installed project-local spec and prototypes only; never reopen the library/external source root. The module owns the editable natural-language application plan, confirmed-value consumption, AI-authored prototype selection, internal reuse/adherence derivation, inherited design precedence, and structured-lock planning. This plan decides how to use the installed template, never which template to select. Bare names, style words, and free-design projects do not trigger it.
|
**Conditional template workspace**: When the Stage-1 template choice has been installed into `<project_path>/templates/`, read [`strategist-template.md`](./strategist-template.md) before completing Stage 2. Read the installed project-local spec and prototypes only; never reopen the library/external source root. The module owns the editable natural-language application plan, confirmed-value consumption, AI-authored prototype selection, internal reuse/adherence derivation, inherited design precedence, and structured-lock planning. This plan decides how to use the installed template, never which template to select. Bare names, style words, and free-design projects do not trigger it.
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ Record the confirmed visual style and rationale in `design_spec.md` first, inclu
|
|||||||
|
|
||||||
### e. Color Scheme Recommendation
|
### e. Color Scheme Recommendation
|
||||||
|
|
||||||
**Hard rule**: User-specified colors are truth. Lock supplied HEX, brand colors, or natural-language directives; templates follow inherited-design precedence. Even direct locks fill all six roles (`background`, `secondary_bg`, `primary`, `accent`, `secondary_accent`, `body_text`) in each of ≥3 directions: repeat fixed roles and vary only open ones. Never emit an empty palette. Keep body-text contrast at least 4.5:1 and preserve confirmed/brand semantic roles.
|
**Hard rule**: User-specified colors are truth. Lock supplied HEX, brand colors, or natural-language directives; templates follow inherited-design precedence. Even direct locks fill all six roles (`background`, `secondary_bg`, `primary`, `accent`, `secondary_accent`, `body_text`) in each of the three directions: repeat fixed roles and vary only open ones. Never emit an empty palette. Keep body-text contrast at least 4.5:1 and preserve confirmed/brand semantic roles.
|
||||||
|
|
||||||
**Reference — not a constraint**: Without user/template colors, propose project-specific directions from content and style. `scripts/config.py` industry colors and dominant/support/accent hierarchy are recall aids, never default locks, ratios, or color-count quotas.
|
**Reference — not a constraint**: Without user/template colors, propose project-specific directions from content and style. `scripts/config.py` industry colors and dominant/support/accent hierarchy are recall aids, never default locks, ratios, or color-count quotas.
|
||||||
|
|
||||||
@@ -214,11 +214,11 @@ See [`../templates/icons/README.md`](../templates/icons/README.md) for the curre
|
|||||||
|
|
||||||
### g. Typography Plan Confirmation (Font + Size)
|
### g. Typography Plan Confirmation (Font + Size)
|
||||||
|
|
||||||
🚧 **GATE**: Read the locked preset visual-style file's §2 Typography character before recommending type. For a custom style, first read every file in `visual_style_references` when present, then resolve their typography character under `visual_style_behavior`; a novel custom uses the behavior directly. The title carries the character; the body may remain neutral.
|
🚧 **GATE**: Apply the chosen custom behavior and only the detail files already loaded from its exact `visual_style_references`. The title carries the character; the body may remain neutral.
|
||||||
|
|
||||||
**Family selection**:
|
**Family selection**:
|
||||||
|
|
||||||
- User/template typography is authoritative. Repeat fixed stacks with `typography.fixed: true` in every direction; never vary them for diversity. Keep ≥3 directions distinct as full bundles; reasonable font repetition is non-blocking, with no extra font round.
|
- User/template typography is authoritative. Repeat fixed stacks with `typography.fixed: true` in every direction; never vary them for diversity. Keep the three directions distinguishable as full bundles; reasonable font repetition is non-blocking, with no extra font round.
|
||||||
- Every Stage-2 direction carries `heading` / `body` `primary`, `css`, and positive `body_size`; add `english` only when the deck's main language is not English.
|
- Every Stage-2 direction carries `heading` / `body` `primary`, `css`, and positive `body_size`; add `english` only when the deck's main language is not English.
|
||||||
- Use concrete, target-installed PowerPoint faces. The Confirm UI font catalog supplies additional manual dropdown choices, not a recommendation whitelist.
|
- Use concrete, target-installed PowerPoint faces. The Confirm UI font catalog supplies additional manual dropdown choices, not a recommendation whitelist.
|
||||||
- Keep stacks to four families or fewer. A brand/web face may lead only after user-confirmed target installation/approved install; PPT Master does not embed fonts. Otherwise export a safe face and keep the unavailable face as Design Spec reference.
|
- Keep stacks to four families or fewer. A brand/web face may lead only after user-confirmed target installation/approved install; PPT Master does not embed fonts. Otherwise export a safe face and keep the unavailable face as Design Spec reference.
|
||||||
@@ -251,7 +251,7 @@ Other canvases use the body baseline in [`canvas-formats.md`](canvas-formats.md)
|
|||||||
Scan §IX before locking. Declare every recurring role, including `lead`, `footnote`, and chart annotations when used; a lead is always at least body size. Give each role one deck-wide anchor and snap derived anchors to clean even px (for body 24, a sound set is title 42, subtitle 32, lead 30, annotation 18, footnote 16). Executor may vary one occurrence within that role's anchor ±2px while preserving hierarchy and readability. A short non-structural Hero/Display size planned for at most two occurrences may remain undeclared; the third planned occurrence makes it recurring and requires an explicit named slot. Structural text never uses this sparse exception.
|
Scan §IX before locking. Declare every recurring role, including `lead`, `footnote`, and chart annotations when used; a lead is always at least body size. Give each role one deck-wide anchor and snap derived anchors to clean even px (for body 24, a sound set is title 42, subtitle 32, lead 30, annotation 18, footnote 16). Executor may vary one occurrence within that role's anchor ±2px while preserving hierarchy and readability. A short non-structural Hero/Display size planned for at most two occurrences may remain undeclared; the third planned occurrence makes it recurring and requires an explicit named slot. Structural text never uses this sparse exception.
|
||||||
#### Formula Planning Trigger
|
#### Formula Planning Trigger
|
||||||
|
|
||||||
Formula policy and formula-asset planning are conditional. If the source contains formula-worthy expressions, or the user explicitly requests formula handling, read [`strategist-image.md`](./strategist-image.md) §3 before confirming the production policy or writing formula rows. Load it even when `image_usage` is `none`; otherwise omit formula planning from the core path.
|
Formula policy and formula-asset planning are conditional. [`strategist-image.md`](./strategist-image.md) is already loaded for Stage-2 rendering candidates; if the source contains formula-worthy expressions, or the user explicitly requests formula handling, apply its §3 before confirming the production policy or writing formula rows. Otherwise omit formula planning from the core path.
|
||||||
|
|
||||||
### h. Image Source Recommendation
|
### h. Image Source Recommendation
|
||||||
|
|
||||||
@@ -267,12 +267,12 @@ Formula policy and formula-asset planning are conditional. If the source contain
|
|||||||
|
|
||||||
**Recommendation output**: Write `recommend.image_usage` as one source id or an array for mixed sources. Put page roles, authoritative assets, preferred/avoided imagery, and placeholder tolerance in `image_notes.value`. `none` is exclusive. Human-scale topics such as family life, education, wellness, or children lean `ai` when no supplied asset carries the story; regulated investor decks, B2B finance reports, and data-only dashboards remain eligible for `none` by judgment.
|
**Recommendation output**: Write `recommend.image_usage` as one source id or an array for mixed sources. Put page roles, authoritative assets, preferred/avoided imagery, and placeholder tolerance in `image_notes.value`. `none` is exclusive. Human-scale topics such as family life, education, wellness, or children lean `ai` when no supplied asset carries the story; regulated investor decks, B2B finance reports, and data-only dashboards remain eligible for `none` by judgment.
|
||||||
|
|
||||||
**Confirmed value wins**: Accept the confirmed legacy string or multi-select array. Map `ai→ai`, `web→web`, `provided→user`, and `placeholder→placeholder` into §VIII `Acquire Via`. Until confirmation, a coordinated direction that proposes AI may use the visual style's paired rendering; generated images inherit the deck colors and never introduce a second image-palette choice.
|
**Confirmed value wins**: Accept the confirmed legacy string or multi-select array. Map `ai→ai`, `web→web`, `provided→user`, and `placeholder→placeholder` into §VIII `Acquire Via`. Every direction already carries a rendering candidate whether or not AI is proposed; generated images inherit the deck colors and never introduce a second image-palette choice.
|
||||||
|
|
||||||
**Conditional module — two-stage trigger**:
|
**Always-on decision module; conditional resource extension**:
|
||||||
|
|
||||||
1. First derive the proposed `recommend.image_usage` in core. If it contains any non-`none` source—especially `ai`—read [`strategist-image.md`](./strategist-image.md) **before authoring the Stage-2 design directions** so rendering and other image-dependent candidate details are real, not backfilled after confirmation. An explicit non-`none` image constraint or the formula trigger from §g activates the module at the same point.
|
1. Before authoring Stage-2 directions, read [`strategist-image.md`](./strategist-image.md) plus only [`image-renderings/_index.md`](./image-renderings/_index.md). After the three whole-direction intents exist and their rendering reference ids are frozen, read only those exact sibling files once and author one complete custom rendering inside each direction before deciding whether `recommend.image_usage` includes AI.
|
||||||
2. Confirmed sources bound production. Non-`none` loads or retains [`strategist-image.md`](./strategist-image.md) for resource planning without backfilling candidates; `none` without formulas writes no image rows.
|
2. Independently derive `recommend.image_usage` from source needs. Confirmed non-`none` sources activate the module's resource-planning sections and the image layout references; formulas activate the formula sections even when usage is `none`. Confirmed `none` without formulas writes no image rows, but does not erase the three recommendation-only rendering candidates.
|
||||||
|
|
||||||
The module owns formula policy, AI rendering alternatives, acquisition paths, resource rows, prompt depth, page roles, and placement intent.
|
The module owns formula policy, AI rendering alternatives, acquisition paths, resource rows, prompt depth, page roles, and placement intent.
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ user/template requirements bind.
|
|||||||
|
|
||||||
| Capability | Opportunity signal | Design Spec handoff |
|
| Capability | Opportunity signal | Design Spec handoff |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Image composition | Image-as-canvas, editorial crop, collage, cutout, or meaningful focus / comparison / evidence units carry the page better than an adjacent rectangle | Propose a permitted source; when selected, load [`strategist-image.md`](./strategist-image.md), record a concise §VIII `Layout pattern` suggestion, and describe page-level image/overlay relationships in §IX `Layout` / `Images` |
|
| Image composition | Image-as-canvas, editorial crop, collage, cutout, or meaningful focus / comparison / evidence units carry the page better than an adjacent rectangle | Propose a permitted source; when selected, apply the already-loaded [`strategist-image.md`](./strategist-image.md) resource contract plus the conditional image-layout references, record a concise §VIII `Layout pattern` suggestion, and describe page-level image/overlay relationships in §IX `Layout` / `Images` |
|
||||||
| Native paint / overlay | Gradient, translucency, scrim, vignette, or wash supports focus, hierarchy, depth, legibility, or image integration | Record purpose/layering in §IX `Layout`, plus `Images` when imagery participates; no new field or type/stops/opacity/coordinates—Executor chooses realization |
|
| Native paint / overlay | Gradient, translucency, scrim, vignette, or wash supports focus, hierarchy, depth, legibility, or image integration | Record purpose/layering in §IX `Layout`, plus `Images` when imagery participates; no new field or type/stops/opacity/coordinates—Executor chooses realization |
|
||||||
| Native shape / Merge Shapes | A literal Office symbol, a stock bent/curved relationship contour, or a compound silhouette, negative-space cutout, overlap-only region, or meaningful fragmentation strengthens the visual idea | Add an optional §IX `Native shape suggestion` with the semantic result plus a candidate preset/Connector family or Boolean operation/operands |
|
| Native shape / Merge Shapes | A literal Office symbol, a stock bent/curved relationship contour, or a compound silhouette, negative-space cutout, overlap-only region, or meaningful fragmentation strengthens the visual idea | Add an optional §IX `Native shape suggestion` with the semantic result plus a candidate preset/Connector family or Boolean operation/operands |
|
||||||
| Page transition | A section/state change, spatial continuity, recorded/self-running flow, or the same semantic object changing position, scale, crop, or state across adjacent pages benefits from motion | Add an optional §IX `Motion suggestion` describing the communication job and any continuing object's initial state → action → end state; leave effect, ids, pairing names, and timing to Executor |
|
| Page transition | A section/state change, spatial continuity, recorded/self-running flow, or the same semantic object changing position, scale, crop, or state across adjacent pages benefits from motion | Add an optional §IX `Motion suggestion` describing the communication job and any continuing object's initial state → action → end state; leave effect, ids, pairing names, and timing to Executor |
|
||||||
@@ -393,7 +393,7 @@ Confirmation `d` locks two independent catalog items:
|
|||||||
- **Mode** — narrative skeleton: [`modes/_index.md`](./modes/_index.md) → `pyramid` / `narrative` / `instructional` / `showcase` / `briefing`.
|
- **Mode** — narrative skeleton: [`modes/_index.md`](./modes/_index.md) → `pyramid` / `narrative` / `instructional` / `showcase` / `briefing`.
|
||||||
- **Visual style** — aesthetic: [`visual-styles/_index.md`](./visual-styles/_index.md) → presets + `custom`.
|
- **Visual style** — aesthetic: [`visual-styles/_index.md`](./visual-styles/_index.md) → presets + `custom`.
|
||||||
|
|
||||||
Read the relevant `_index.md` at confirmation `d` (Layer 1 / Layer 2) for its catalog table and auto-selection. Executor loads one locked file per preset, or every exact custom reference before applying its behavior (see [`generate-pptx`](../workflows/generate-pptx.md) Step 6).
|
Strategist first reads only the three indexes, freezes the bases for the three whole directions, then reads only the deduplicated referenced detail files before authoring their custom behaviors. Executor reads one locked preset file or the exact references of a selected custom; neither role globs a catalog (see [`generate-pptx`](../workflows/generate-pptx.md) Step 6).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -504,7 +504,7 @@ includes transitions.
|
|||||||
- **Custom behavior is concise and executable**: For confirmed `custom` mode or visual style, project one resolved `mode_behavior` / `visual_style_behavior` sentence or short paragraph. When the direction actually combines or borrows catalog entries, also project the exact, comma-separated `mode_references` / `visual_style_references`; omit the field for a genuinely novel direction and never fabricate a nearby reference. Preserve the confirmed direction, reference locked role names such as `colors.primary` when needed, and omit selection history, contradictions, precedence explanations, or other Design Spec provenance. Executor reads these fields from the retained lock and loads every referenced catalog entry once per valid context.
|
- **Custom behavior is concise and executable**: For confirmed `custom` mode or visual style, project one resolved `mode_behavior` / `visual_style_behavior` sentence or short paragraph. When the direction actually combines or borrows catalog entries, also project the exact, comma-separated `mode_references` / `visual_style_references`; omit the field for a genuinely novel direction and never fabricate a nearby reference. Preserve the confirmed direction, reference locked role names such as `colors.primary` when needed, and omit selection history, contradictions, precedence explanations, or other Design Spec provenance. Executor reads these fields from the retained lock and loads every referenced catalog entry once per valid context.
|
||||||
- **page_rhythm is mandatory**: Based on the page list in §IX Content Outline, assign each page one of `anchor` / `dense` / `breathing`. This is what breaks the uniform "every page is a card grid" feel. New locks may not omit the section; consumer omission behavior is owned by [`executor-base.md`](executor-base.md) §2.1.
|
- **page_rhythm is mandatory**: Based on the page list in §IX Content Outline, assign each page one of `anchor` / `dense` / `breathing`. This is what breaks the uniform "every page is a card grid" feel. New locks may not omit the section; consumer omission behavior is owned by [`executor-base.md`](executor-base.md) §2.1.
|
||||||
- **Fact IDs and scenario labels are mandatory when applicable**: Read any `sources/*.facts.json`. For each §IX page, list the stable IDs actually used; never cite an ID whose claim is absent from the page. Mark invented KPIs/targets/internal ratios as `Data class: scenario` and state which values are scenario data. Executor carries external sources into notes/footnotes and renders a visible scenario label for scenario figures.
|
- **Fact IDs and scenario labels are mandatory when applicable**: Read any `sources/*.facts.json`. For each §IX page, list the stable IDs actually used; never cite an ID whose claim is absent from the page. Mark invented KPIs/targets/internal ratios as `Data class: scenario` and state which values are scenario data. Executor carries external sources into notes/footnotes and renders a visible scenario label for scenario figures.
|
||||||
- **Rhythm follows narrative, not quota**: `breathing` pages mark natural pauses — chapter transitions, standalone emphasis (hero quote / big number), SCQA bridges. Dense decks may legitimately be all `dense`. **Do NOT invent filler pages** ("Thank you", empty dividers) to pad rhythm — every `breathing` page must say something independent. Consumption mode biases the overall lean (`presentation` toward more `anchor` / `breathing`, `text` toward `dense`; see §6.1) — a bias, never a quota.
|
- **Mandatory — whole-roster rhythm check**: During the same §IX composition, compare neighbors and section arcs to judge whether chapter entries visibly reset, extended same-density runs are intentional, extended same-carrier or same-topology runs form an intentional semantic sub-arc, repeated dominant geometry carries a continuity job, each section follows a mode-fitting progression—including framework → explanation/evidence → judgment/action when it serves the objective—and the final arc resolves the communication objective before a genuine ending lowers information load. Repair the existing roster, `Layout`, and `page_rhythm` choices in place. This is judgment, not quota; preserve intentional continuity, legitimately all-`dense` material, and 1:1/literal order. Do not invent filler pages to manufacture rhythm; a `breathing` page marks a meaningful pause—chapter transition, standalone emphasis, or SCQA bridge—and must stand alone. Create no field, lock row, artifact, or second review/execution pass.
|
||||||
- **Cover impact is mandatory**: In `design_spec.md §IX`, give `P01` one concrete hook from the source's strongest claim, metaphor, number, moment, or conflict plus a recommended composition. The hook binds; Executor may adapt the composition to prepared assets and explicit constraints. With no suitable image, recommend a native-SVG hook instead of a generic title treatment. Beautify / template-fill preservation paths are exempt.
|
- **Cover impact is mandatory**: In `design_spec.md §IX`, give `P01` one concrete hook from the source's strongest claim, metaphor, number, moment, or conflict plus a recommended composition. The hook binds; Executor may adapt the composition to prepared assets and explicit constraints. With no suitable image, recommend a native-SVG hook instead of a generic title treatment. Beautify / template-fill preservation paths are exempt.
|
||||||
- **Cover rhythm lock**: `P01` remains `anchor`. Default away from generic content-page templates; a card grid, agenda, or equal-weight columns remains valid when content, user direction, or the template makes it the clearest cover.
|
- **Cover rhythm lock**: `P01` remains `anchor`. Default away from generic content-page templates; a card grid, agenda, or equal-weight columns remains valid when content, user direction, or the template makes it the clearest cover.
|
||||||
- **Closing impact (only when the deck closes)**: For a genuine conclusion / CTA / final takeaway, name the binding takeaway plus a recommended composition; Executor may adapt the latter. Do not default to an information-empty "Thank you", contact-only slide, or cover reprise; an explicit contact/event CTA may serve the purpose. **Do NOT invent a closing page to satisfy this**. Preservation paths are exempt.
|
- **Closing impact (only when the deck closes)**: For a genuine conclusion / CTA / final takeaway, name the binding takeaway plus a recommended composition; Executor may adapt the latter. Do not default to an information-empty "Thank you", contact-only slide, or cover reprise; an explicit contact/event CTA may serve the purpose. **Do NOT invent a closing page to satisfy this**. Preservation paths are exempt.
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ visual job.
|
|||||||
| Surface / select | Name the target, confirm its owning subsection and fidelity, then use the Router. Choose a compatible technique that fully performs the job; prefer simpler/native-stable alternatives only when communication is equal. `Approximate` requires review, not automatic rejection. |
|
| Surface / select | Name the target, confirm its owning subsection and fidelity, then use the Router. Choose a compatible technique that fully performs the job; prefer simpler/native-stable alternatives only when communication is equal. `Approximate` requires review, not automatic rejection. |
|
||||||
| Integrate / stop | Align paint, contour, light, hierarchy, and z-order; combine only techniques with different jobs. Check legibility, editability, density, fidelity, and style; simplify failures, use legal alternatives, and bake only the smallest pixel-dependent layer. Keep authoritative text/data native. |
|
| Integrate / stop | Align paint, contour, light, hierarchy, and z-order; combine only techniques with different jobs. Check legibility, editability, density, fidelity, and style; simplify failures, use legal alternatives, and bake only the smallest pixel-dependent layer. Keep authoritative text/data native. |
|
||||||
|
|
||||||
|
**Default — one dominant composition scaffold (may override when a second
|
||||||
|
scaffold performs an independent communication job)**: Integrate the page-scale
|
||||||
|
move and every active Structure / Image / Chart / Table branch into one dominant
|
||||||
|
system, sharing direction, contour, baseline, and z-order as applicable. Make a
|
||||||
|
branch-local system visibly subordinate when it cannot share that scaffold;
|
||||||
|
simplify any competing scaffold without a separate communication job.
|
||||||
|
|
||||||
#### Visual Job Router
|
#### Visual Job Router
|
||||||
|
|
||||||
**Reference — not a quota**: route diagnosed problems through this table. A
|
**Reference — not a quota**: route diagnosed problems through this table. A
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ A **visual style** is how the deck **looks** — shape language, decoration dens
|
|||||||
|
|
||||||
## 1. Catalog
|
## 1. Catalog
|
||||||
|
|
||||||
Each style has its own file with: shape & decoration, typography character, color-usage discipline (no HEX), texture / elevation, and the paired image-rendering. Default reads the locked preset file; Quick reads the preset it resolves in active context. A catalog-based `custom` reads every preset actually used as a basis; a novel `custom` reads none. Never glob the directory. The catalog mirrors [`image-renderings`](../image-renderings/_index.md): each style's "Paired rendering" names the illustration family that shares its aesthetic.
|
Each style keeps its own authoritative file with: shape & decoration, typography character, color-usage discipline (no HEX), texture / elevation, and the paired image-rendering. Read this index alone while choosing a direction. Only after a preset or custom bases are fixed may the active role read the selected sibling files: one file for a preset, every exact `visual_style_references` file for a catalog-based custom, and none for a novel custom. Never glob the directory or read an unselected sibling. The catalog mirrors [`image-renderings`](../image-renderings/_index.md): each style's "Paired rendering" names the illustration family that shares its aesthetic.
|
||||||
|
|
||||||
> The **`visual_style` value is only ever a first-column `id`** (`swiss-minimal`, `editorial`, …). The "Paired rendering" column lists **image-rendering** names (`flat`, `minimalist-swiss`, `digital-dashboard`, …) — never treat one of those as the `visual_style`. Default records rendering under confirmation h; Quick keeps the selected rendering only in active context and any required image manifest.
|
> The **`visual_style` value is only ever a first-column `id`** (`swiss-minimal`, `editorial`, …). The "Paired rendering" column lists **image-rendering** names (`flat`, `minimalist-swiss`, `digital-dashboard`, …) — never treat one of those as the `visual_style`. Default records rendering under confirmation h; Quick keeps the selected rendering only in active context and any required image manifest.
|
||||||
>
|
>
|
||||||
@@ -92,11 +92,11 @@ Each style has its own file with: shape & decoration, typography character, colo
|
|||||||
|
|
||||||
## 3. Escape hatch — `custom`
|
## 3. Escape hatch — `custom`
|
||||||
|
|
||||||
Default Stage 2 always authors one visible, non-empty AI custom proposal beside the preset spectrum. Its paragraph names shape language, composition geometry (page-scale moves), decoration density, whitespace, typographic character, and texture — **no HEX, no color names as values**. The proposal is initially unselected and remains recommendation-only unless the user chooses it; a template-backed proposal must stay inside the inherited identity and confirmed application plan. When selected, record the edited aesthetic in the Design Spec first, then project `- visual_style: custom` plus `- visual_style_behavior:` to `spec_lock.md`. The candidate is mandatory; selecting `custom` remains a tail-case, not the default.
|
Each coordinated Default Stage-2 direction authors one visible, non-empty `custom` aesthetic whose paragraph names project-specific shape language, composition geometry, decoration density, whitespace, typographic character, and texture — **no HEX, no color names as values**. Use this index to freeze any catalog bases before reading their detail files. A template-backed synthesis stays inside the inherited identity and confirmed application plan. Record the confirmed current aesthetic in the Design Spec first, then project `- visual_style: custom` plus `- visual_style_behavior:`. The 18 fixed styles remain lower-level single-select alternatives; do not create a fourth AI-custom proposal.
|
||||||
|
|
||||||
Quick does not author or display a candidate spectrum. It resolves the best-fit preset directly, or one custom behavior only when no preset fits, reads every catalog source actually used as a basis, and persists nothing.
|
Quick does not display a candidate spectrum. It reads this index, resolves one preset or custom behavior, then reads only the selected detail files and persists nothing.
|
||||||
|
|
||||||
**Mandatory — read every catalog source actually used**: If a custom direction combines or borrows existing styles, name their exact ids and read each corresponding file before synthesizing its shape, composition, typography, whitespace, and texture rules. Default persists those ids as `visual_style_references`; Quick retains them only in active context. Do not attach references merely because they are adjacent in the catalog. A genuinely new aesthetic reads no catalog source.
|
**Mandatory — select before detail reading**: Freeze every catalog source actually used from this index, then read only those exact files before writing the behavior. Default persists those ids as `visual_style_references`; Quick retains them only in active context. Do not open candidates for comparison after this gate or attach references merely because they are adjacent. A genuinely new aesthetic names and reads no catalog source.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ Quick does not author or display a candidate spectrum. It resolves the best-fit
|
|||||||
|
|
||||||
| Active profile | Use |
|
| Active profile | Use |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Default Generate | Strategist reads this index at confirmation `d. Layer 2`, authors the required spectrum/custom candidate, records the confirmed style in `design_spec.md`, and projects it to `spec_lock.md`; Executor reads the locked preset or exact custom references |
|
| Default Generate | Strategist reads only this index while mapping three whole solution intents, freezes each custom direction's exact bases, then reads only their deduplicated detail files. Executor reads the confirmed preset file or exact custom references. |
|
||||||
| Quick Generate | The current main agent reads this index, resolves the best-fit preset or one warranted custom behavior without interaction, reads only the exact preset source(s) actually used, and keeps the result in active context without Design Spec/lock |
|
| Quick Generate | The current main agent reads only this index while deciding, then reads the resolved preset or exact custom bases and retains that one direction without Design Spec/lock. |
|
||||||
|
|
||||||
**Resolution scope**: deck-wide (one style per deck). It anchors taste as a **reference**, not a whitelist — pages may deviate with reason.
|
**Resolution scope**: deck-wide (one style per deck). It anchors taste as a **reference**, not a whitelist — pages may deviate with reason.
|
||||||
|
|||||||
@@ -1520,23 +1520,41 @@ def _stage2_design_directions_error(
|
|||||||
*,
|
*,
|
||||||
main_language: object = '',
|
main_language: object = '',
|
||||||
) -> Optional[str]:
|
) -> Optional[str]:
|
||||||
"""Require three complete coordinated Stage 2 design systems."""
|
"""Require exactly three complete top-down custom Stage 2 design systems."""
|
||||||
main_language = main_language or _recommendation_language(recommendations)
|
main_language = main_language or _recommendation_language(recommendations)
|
||||||
directions = recommendations.get('design_directions')
|
directions = recommendations.get('design_directions')
|
||||||
if isinstance(directions, dict):
|
if isinstance(directions, dict):
|
||||||
candidates = _candidate_list(directions)
|
candidates = _candidate_list(directions)
|
||||||
if len(candidates) < 3:
|
if len(candidates) != 3:
|
||||||
return 'Stage 2 design_directions must include at least 3 candidates'
|
return 'Stage 2 design_directions must include exactly 3 candidates'
|
||||||
typography_candidates = []
|
typography_candidates = []
|
||||||
|
direction_ids = set()
|
||||||
for index, candidate in enumerate(candidates, start=1):
|
for index, candidate in enumerate(candidates, start=1):
|
||||||
label = f'design_directions.candidates[{index - 1}]'
|
label = f'design_directions.candidates[{index - 1}]'
|
||||||
if not isinstance(candidate, dict):
|
if not isinstance(candidate, dict):
|
||||||
return f'{label} must be an object'
|
return f'{label} must be an object'
|
||||||
|
direction_id = str(candidate.get('id') or '').strip()
|
||||||
|
if not direction_id:
|
||||||
|
return f'{label}.id must be non-empty'
|
||||||
|
if direction_id in direction_ids:
|
||||||
|
return f'{label}.id must be unique'
|
||||||
|
direction_ids.add(direction_id)
|
||||||
if not _localized_text_present(candidate, 'name'):
|
if not _localized_text_present(candidate, 'name'):
|
||||||
return f'{label} requires a non-empty localized name'
|
return f'{label} requires a non-empty localized name'
|
||||||
for field in ('visual_style', 'icons'):
|
for field in ('mode', 'visual_style', 'icons'):
|
||||||
if not isinstance(candidate.get(field), str) or not candidate[field].strip():
|
if not isinstance(candidate.get(field), str) or not candidate[field].strip():
|
||||||
return f'{label}.{field} must be non-empty'
|
return f'{label}.{field} must be non-empty'
|
||||||
|
if candidate['mode'] != 'custom':
|
||||||
|
return f'{label}.mode must be custom'
|
||||||
|
if not _localized_text_present(candidate, 'mode_behavior'):
|
||||||
|
return f'{label}.mode=custom requires non-empty localized mode_behavior'
|
||||||
|
if candidate['visual_style'] != 'custom':
|
||||||
|
return f'{label}.visual_style must be custom'
|
||||||
|
if not _localized_text_present(candidate, 'visual_style_behavior'):
|
||||||
|
return (
|
||||||
|
f'{label}.visual_style=custom requires non-empty localized '
|
||||||
|
'visual_style_behavior'
|
||||||
|
)
|
||||||
error = _palette_error(candidate.get('color'), f'{label}.color')
|
error = _palette_error(candidate.get('color'), f'{label}.color')
|
||||||
if error:
|
if error:
|
||||||
return error
|
return error
|
||||||
@@ -1549,12 +1567,25 @@ def _stage2_design_directions_error(
|
|||||||
if error:
|
if error:
|
||||||
return error
|
return error
|
||||||
typography_candidates.append(candidate['typography'])
|
typography_candidates.append(candidate['typography'])
|
||||||
if _uses_ai_images(recommendations):
|
|
||||||
image_strategy = candidate.get('image_strategy')
|
image_strategy = candidate.get('image_strategy')
|
||||||
if not isinstance(image_strategy, dict) or not str(
|
if not isinstance(image_strategy, dict):
|
||||||
image_strategy.get('rendering') or ''
|
return f'{label}.image_strategy must be an object'
|
||||||
).strip():
|
rendering = str(image_strategy.get('rendering') or '').strip()
|
||||||
|
if not rendering:
|
||||||
return f'{label}.image_strategy.rendering must be non-empty'
|
return f'{label}.image_strategy.rendering must be non-empty'
|
||||||
|
if rendering != 'custom':
|
||||||
|
return f'{label}.image_strategy.rendering must be custom'
|
||||||
|
for prose_field in ('name', 'visual', 'mood'):
|
||||||
|
if not _localized_text_present(image_strategy, prose_field):
|
||||||
|
return (
|
||||||
|
f'{label}.image_strategy requires non-empty localized '
|
||||||
|
f'{prose_field}'
|
||||||
|
)
|
||||||
|
if not _localized_text_present(image_strategy, 'behavior'):
|
||||||
|
return (
|
||||||
|
f'{label}.image_strategy.rendering=custom requires non-empty '
|
||||||
|
'localized behavior'
|
||||||
|
)
|
||||||
return _typography_candidates_fixed_error(
|
return _typography_candidates_fixed_error(
|
||||||
typography_candidates,
|
typography_candidates,
|
||||||
main_language=main_language,
|
main_language=main_language,
|
||||||
@@ -1592,13 +1623,17 @@ def _stage2_design_directions_error(
|
|||||||
|
|
||||||
|
|
||||||
def _stage2_custom_candidates_error(recommendations: dict) -> Optional[str]:
|
def _stage2_custom_candidates_error(recommendations: dict) -> Optional[str]:
|
||||||
"""Require visible AI-authored custom alternatives in new Stage 2 files."""
|
"""Validate optional legacy standalone custom alternatives."""
|
||||||
candidates = recommendations.get('custom_candidates')
|
candidates = recommendations.get('custom_candidates')
|
||||||
|
if candidates is None:
|
||||||
|
return None
|
||||||
if not isinstance(candidates, dict):
|
if not isinstance(candidates, dict):
|
||||||
return 'Stage 2 recommendations must include custom_candidates'
|
return 'custom_candidates must be an object when present'
|
||||||
|
|
||||||
for field in ('mode', 'visual_style'):
|
for field in ('mode', 'visual_style'):
|
||||||
candidate = candidates.get(field)
|
candidate = candidates.get(field)
|
||||||
|
if candidate is None:
|
||||||
|
continue
|
||||||
if not isinstance(candidate, dict):
|
if not isinstance(candidate, dict):
|
||||||
return f'custom_candidates.{field} must be an object'
|
return f'custom_candidates.{field} must be an object'
|
||||||
for prose_field in ('name', 'behavior'):
|
for prose_field in ('name', 'behavior'):
|
||||||
@@ -1608,12 +1643,11 @@ def _stage2_custom_candidates_error(recommendations: dict) -> Optional[str]:
|
|||||||
f'{prose_field}'
|
f'{prose_field}'
|
||||||
)
|
)
|
||||||
|
|
||||||
if not _uses_ai_images(recommendations):
|
|
||||||
return None
|
|
||||||
|
|
||||||
image_candidate = candidates.get('image_strategy')
|
image_candidate = candidates.get('image_strategy')
|
||||||
|
if image_candidate is None:
|
||||||
|
return None
|
||||||
if not isinstance(image_candidate, dict):
|
if not isinstance(image_candidate, dict):
|
||||||
return 'custom_candidates.image_strategy must be an object when image_usage includes ai'
|
return 'custom_candidates.image_strategy must be an object'
|
||||||
if image_candidate.get('rendering') != 'custom':
|
if image_candidate.get('rendering') != 'custom':
|
||||||
return 'custom_candidates.image_strategy.rendering must be custom'
|
return 'custom_candidates.image_strategy.rendering must be custom'
|
||||||
for prose_field in ('name', 'visual', 'mood', 'behavior'):
|
for prose_field in ('name', 'visual', 'mood', 'behavior'):
|
||||||
@@ -2170,6 +2204,11 @@ def _wait_result_status(
|
|||||||
)
|
)
|
||||||
return 2
|
return 2
|
||||||
logger.info('confirmation stage=%s received: %s', target_stage, result_file)
|
logger.info('confirmation stage=%s received: %s', target_stage, result_file)
|
||||||
|
if target_stage == 'stage1':
|
||||||
|
logger.info(
|
||||||
|
'[NEXT] Stage 1 is intermediate: complete the template handoff, '
|
||||||
|
'author fresh Stage 2, then wait for final confirmation.'
|
||||||
|
)
|
||||||
return 0
|
return 0
|
||||||
if _result_stage_number(current_stage) > _result_stage_number(target_stage):
|
if _result_stage_number(current_stage) > _result_stage_number(target_stage):
|
||||||
logger.error(
|
logger.error(
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
* choice together. Stage 2 combines the coherent deck solution and production
|
* choice together. Stage 2 combines the coherent deck solution and production
|
||||||
* mechanics, then writes the final result.
|
* mechanics, then writes the final result.
|
||||||
* Finite fields use /static/catalogs.json; coordinated design directions seed
|
* Finite fields use /static/catalogs.json; coordinated design directions seed
|
||||||
* color, typography, icons, generated-image rendering, and conditional
|
* mode, visual style, color, typography, icons, and generated-image rendering,
|
||||||
* template-application prose. Final confirm saves result.json.
|
* while template-application prose stays conditional. Final confirm saves the
|
||||||
|
* flattened current values to result.json.
|
||||||
*/
|
*/
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -63,7 +64,11 @@
|
|||||||
sec_mode: "Generation mode",
|
sec_mode: "Generation mode",
|
||||||
sec_refine: "Review the Design Spec first",
|
sec_refine: "Review the Design Spec first",
|
||||||
sec_design_directions: "Coherent design directions",
|
sec_design_directions: "Coherent design directions",
|
||||||
design_directions_hint: "Each direction coordinates style, color, typography, icons, and generated-image rendering. You can fine-tune every field below.",
|
design_directions_hint: "Choose a complete direction first, then fine-tune the projected fields below. Clicking a direction again restores its authored bundle.",
|
||||||
|
direction_active: "Applied",
|
||||||
|
direction_adjusted: "Adjusted",
|
||||||
|
direction_reset_hint: "Click to apply or restore this complete direction.",
|
||||||
|
scheme_component_options: "Project-specific custom choices · select a card to edit",
|
||||||
sec_template_application: "Template application",
|
sec_template_application: "Template application",
|
||||||
template_application_hint: "The AI recommends how to apply the installed template to this deck. Revise the plan directly in natural language.",
|
template_application_hint: "The AI recommends how to apply the installed template to this deck. Revise the plan directly in natural language.",
|
||||||
placeholder_template_application: "Describe which template pages or prototypes to use, skip, repeat, or reorder; what must stay; and what may be replaced or reorganized.",
|
placeholder_template_application: "Describe which template pages or prototypes to use, skip, repeat, or reorder; what must stay; and what may be replaced or reorganized.",
|
||||||
@@ -241,7 +246,11 @@
|
|||||||
sec_mode: "生成モード",
|
sec_mode: "生成モード",
|
||||||
sec_refine: "先に設計仕様を確認",
|
sec_refine: "先に設計仕様を確認",
|
||||||
sec_design_directions: "統合デザイン方針",
|
sec_design_directions: "統合デザイン方針",
|
||||||
design_directions_hint: "各案はスタイル、配色、書体、アイコン、生成画像のレンダリングを一体で提案します。下の各項目で微調整できます。",
|
design_directions_hint: "まず全体案を選び、その下に反映された各項目を微調整します。同じ全体案をもう一度押すと、元の組み合わせに戻ります。",
|
||||||
|
direction_active: "適用中",
|
||||||
|
direction_adjusted: "調整済み",
|
||||||
|
direction_reset_hint: "クリックすると、この全体案を適用または元の状態に戻します。",
|
||||||
|
scheme_component_options: "プロジェクト専用カスタム案 · カードを選んで編集",
|
||||||
sec_template_application: "テンプレートの適用方法",
|
sec_template_application: "テンプレートの適用方法",
|
||||||
template_application_hint: "AIが現在の内容に合わせたテンプレートの使い方を提案します。自然言語で直接修正できます。",
|
template_application_hint: "AIが現在の内容に合わせたテンプレートの使い方を提案します。自然言語で直接修正できます。",
|
||||||
placeholder_template_application: "使用・省略・反復・並べ替えするページやプロトタイプ、保持する要素、差し替え・再構成できる内容を記述します。",
|
placeholder_template_application: "使用・省略・反復・並べ替えするページやプロトタイプ、保持する要素、差し替え・再構成できる内容を記述します。",
|
||||||
@@ -419,7 +428,11 @@
|
|||||||
sec_mode: "生成模式",
|
sec_mode: "生成模式",
|
||||||
sec_refine: "先审核设计规范",
|
sec_refine: "先审核设计规范",
|
||||||
sec_design_directions: "成套设计方向",
|
sec_design_directions: "成套设计方向",
|
||||||
design_directions_hint: "每套方向会一起协调风格、配色、字体、图标和生成图渲染;你仍可在下方逐项微调。",
|
design_directions_hint: "先选择一套完整方案,再在下方微调各项;再次点击同一方案会恢复它原本的整套预设。",
|
||||||
|
direction_active: "已应用",
|
||||||
|
direction_adjusted: "已调整",
|
||||||
|
direction_reset_hint: "点击可应用或恢复这套完整方案。",
|
||||||
|
scheme_component_options: "项目专属自定义方案 · 选中卡片后可编辑",
|
||||||
sec_template_application: "模板应用方式",
|
sec_template_application: "模板应用方式",
|
||||||
template_application_hint: "AI 会根据当前内容推荐如何使用已安装模板;你可以直接用自然语言修改。",
|
template_application_hint: "AI 会根据当前内容推荐如何使用已安装模板;你可以直接用自然语言修改。",
|
||||||
placeholder_template_application: "说明使用、跳过、重复或重排哪些模板页面/原型,哪些内容必须保留,哪些可以替换或重组。",
|
placeholder_template_application: "说明使用、跳过、重复或重排哪些模板页面/原型,哪些内容必须保留,哪些可以替换或重组。",
|
||||||
@@ -673,6 +686,15 @@
|
|||||||
var ICON_PREVIEWS = {}; // /api/icon-previews — real SVG samples from templates/icons
|
var ICON_PREVIEWS = {}; // /api/icon-previews — real SVG samples from templates/icons
|
||||||
var AI_IMAGE_COMPARISON = {}; // /api/ai-image-comparison — preset rendering catalog
|
var AI_IMAGE_COMPARISON = {}; // /api/ai-image-comparison — preset rendering catalog
|
||||||
var STATE = {};
|
var STATE = {};
|
||||||
|
var ACTIVE_DIRECTION_ID = "";
|
||||||
|
var ACTIVE_DIRECTION_BASELINE = "";
|
||||||
|
var ACTIVE_COMPONENT_DIRECTION_IDS = {};
|
||||||
|
var refreshDesignDirectionState = function () {};
|
||||||
|
var DIRECTION_COMPONENT_PAINTERS = [];
|
||||||
|
|
||||||
|
function refreshDirectionComponentStates() {
|
||||||
|
DIRECTION_COMPONENT_PAINTERS.forEach(function (paint) { paint(); });
|
||||||
|
}
|
||||||
var TEMPLATE_KINDS = ["brand", "style", "layout", "deck"];
|
var TEMPLATE_KINDS = ["brand", "style", "layout", "deck"];
|
||||||
var TEMPLATE_OPTIONS = null;
|
var TEMPLATE_OPTIONS = null;
|
||||||
var TEMPLATE_CANDIDATES = [];
|
var TEMPLATE_CANDIDATES = [];
|
||||||
@@ -1160,9 +1182,8 @@
|
|||||||
var grouped = list.length && list[0] && list[0].items;
|
var grouped = list.length && list[0] && list[0].items;
|
||||||
var flat = grouped ? list.reduce(function (a, g) { return a.concat(g.items || []); }, []) : list;
|
var flat = grouped ? list.reduce(function (a, g) { return a.concat(g.items || []); }, []) : list;
|
||||||
var ids = flat.map(function (o) { return o.id; });
|
var ids = flat.map(function (o) { return o.id; });
|
||||||
// Optional personality spectrum: instead of a single ★ recommendation,
|
// Optional legacy spectrum: marks several catalog ids with localized
|
||||||
// the AI marks a few catalog ids (safe / shifted / bold) each with a
|
// tags and notes instead of one recommendation badge.
|
||||||
// temperament tag + a real-world analogy note. Replaces the single badge.
|
|
||||||
var spectrum = (opts2.spectrum && opts2.spectrum.length) ? opts2.spectrum : null;
|
var spectrum = (opts2.spectrum && opts2.spectrum.length) ? opts2.spectrum : null;
|
||||||
var specById = {};
|
var specById = {};
|
||||||
if (spectrum) spectrum.forEach(function (s) {
|
if (spectrum) spectrum.forEach(function (s) {
|
||||||
@@ -1175,7 +1196,7 @@
|
|||||||
var cur = getVal();
|
var cur = getVal();
|
||||||
var isCustom = cur != null && cur !== "" &&
|
var isCustom = cur != null && cur !== "" &&
|
||||||
(cur === customSentinel || ids.indexOf(cur) === -1);
|
(cur === customSentinel || ids.indexOf(cur) === -1);
|
||||||
if (!allowCustom && isCustom) {
|
if (!allowCustom && isCustom && opts2.preserveCustom !== true) {
|
||||||
// closed field with an out-of-catalog value → snap to recommended/first
|
// closed field with an out-of-catalog value → snap to recommended/first
|
||||||
cur = ids.indexOf(recommendedId) >= 0 ? recommendedId : ids[0];
|
cur = ids.indexOf(recommendedId) >= 0 ? recommendedId : ids[0];
|
||||||
setVal(cur);
|
setVal(cur);
|
||||||
@@ -1604,6 +1625,11 @@
|
|||||||
return spec.candidates || spec.options || [];
|
return spec.candidates || spec.options || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function designDirectionId(candidate, index) {
|
||||||
|
var value = candidate && candidate.id;
|
||||||
|
return String(value || ("direction-" + (Number(index) + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
function selectedDesignDirection() {
|
function selectedDesignDirection() {
|
||||||
var candidates = designDirectionCandidates();
|
var candidates = designDirectionCandidates();
|
||||||
var selected = Number(designDirectionSpec().selected || 0);
|
var selected = Number(designDirectionSpec().selected || 0);
|
||||||
@@ -1616,6 +1642,59 @@
|
|||||||
return candidate[field] != null ? candidate[field] : null;
|
return candidate[field] != null ? candidate[field] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function directionBehavior(candidate, field) {
|
||||||
|
return String(localized(candidate, field + "_behavior") ||
|
||||||
|
(candidate && candidate[field + "_behavior"]) || "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function directionStateSignature(candidate) {
|
||||||
|
candidate = candidate || {};
|
||||||
|
var out = {};
|
||||||
|
if (candidate.mode) {
|
||||||
|
out.mode = STATE.mode || "";
|
||||||
|
out.mode_behavior = STATE.mode === "custom" ? (STATE.mode_behavior || "") : "";
|
||||||
|
}
|
||||||
|
if (candidate.visual_style) {
|
||||||
|
out.visual_style = STATE.visual_style || "";
|
||||||
|
out.visual_style_behavior = STATE.visual_style === "custom" ?
|
||||||
|
(STATE.visual_style_behavior || "") : "";
|
||||||
|
}
|
||||||
|
if (candidate.color) {
|
||||||
|
var palette = normPalette(STATE.color || {});
|
||||||
|
out.color = {
|
||||||
|
custom: (STATE.color && STATE.color.custom) || "",
|
||||||
|
palette: {}
|
||||||
|
};
|
||||||
|
PALETTE_ROLES.forEach(function (role) {
|
||||||
|
out.color.palette[role] = normHex(palette[role]) || "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (candidate.typography) {
|
||||||
|
var typography = normTypography(STATE.typography || {});
|
||||||
|
out.typography = {
|
||||||
|
heading: typography.heading || {},
|
||||||
|
body: typography.body || {},
|
||||||
|
body_size: String(typography.body_size || ""),
|
||||||
|
sizes: {}
|
||||||
|
};
|
||||||
|
["title", "subtitle", "annotation"].forEach(function (role) {
|
||||||
|
out.typography.sizes[role] = String(
|
||||||
|
(STATE.typography && STATE.typography.sizes && STATE.typography.sizes[role]) || ""
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (candidate.icons) out.icons = STATE.icons || "";
|
||||||
|
if (candidate.image_strategy) {
|
||||||
|
out.image_strategy = comparableImageStrategy(STATE.image_strategy || {});
|
||||||
|
}
|
||||||
|
return JSON.stringify(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
function activeDirectionAdjusted(candidate, index) {
|
||||||
|
return designDirectionId(candidate, index) === ACTIVE_DIRECTION_ID &&
|
||||||
|
directionStateSignature(candidate) !== ACTIVE_DIRECTION_BASELINE;
|
||||||
|
}
|
||||||
|
|
||||||
function customCandidateSpec(field) {
|
function customCandidateSpec(field) {
|
||||||
var candidates = REC && REC.custom_candidates;
|
var candidates = REC && REC.custom_candidates;
|
||||||
var candidate = candidates && candidates[field];
|
var candidate = candidates && candidates[field];
|
||||||
@@ -1703,11 +1782,7 @@
|
|||||||
|
|
||||||
function imageStrategyCustomCandidate() {
|
function imageStrategyCustomCandidate() {
|
||||||
var candidate = customCandidateSpec("image_strategy");
|
var candidate = customCandidateSpec("image_strategy");
|
||||||
if (!customCandidateBehavior("image_strategy")) {
|
if (!customCandidateBehavior("image_strategy")) return null;
|
||||||
candidate = imageStrategyCandidates().filter(function (item) {
|
|
||||||
return item && item.rendering === "custom";
|
|
||||||
})[0] || {};
|
|
||||||
}
|
|
||||||
if (!candidate || typeof candidate !== "object") candidate = {};
|
if (!candidate || typeof candidate !== "object") candidate = {};
|
||||||
candidate = Object.assign({}, candidate, { rendering: "custom" });
|
candidate = Object.assign({}, candidate, { rendering: "custom" });
|
||||||
return normalizedImageStrategy(candidate);
|
return normalizedImageStrategy(candidate);
|
||||||
@@ -1726,6 +1801,16 @@
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function comparableImageStrategy(candidate) {
|
||||||
|
var strategy = normalizedImageStrategy(candidate);
|
||||||
|
return {
|
||||||
|
rendering: strategy.rendering || "",
|
||||||
|
visual: strategy.visual || "",
|
||||||
|
mood: strategy.mood || "",
|
||||||
|
behavior: strategy.behavior || ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function usesCustomImagePlanValue(value) {
|
function usesCustomImagePlanValue(value) {
|
||||||
var ids = (CAT.image_usage || []).map(function (item) { return item.id; });
|
var ids = (CAT.image_usage || []).map(function (item) { return item.id; });
|
||||||
if (Array.isArray(value)) return false;
|
if (Array.isArray(value)) return false;
|
||||||
@@ -1880,19 +1965,20 @@
|
|||||||
host.appendChild(sec);
|
host.appendChild(sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyDesignDirection(candidate) {
|
function applyDesignDirection(candidate, index, shouldRender) {
|
||||||
candidate = candidate || {};
|
candidate = candidate || {};
|
||||||
|
var directionId = designDirectionId(candidate, index);
|
||||||
if (candidate.mode) {
|
if (candidate.mode) {
|
||||||
STATE.mode = candidate.mode;
|
STATE.mode = candidate.mode;
|
||||||
if (candidate.mode === "custom" && candidate.mode_behavior) {
|
STATE.mode_behavior = candidate.mode === "custom" ?
|
||||||
STATE.mode_behavior = candidate.mode_behavior;
|
directionBehavior(candidate, "mode") : "";
|
||||||
}
|
ACTIVE_COMPONENT_DIRECTION_IDS.mode = directionId;
|
||||||
}
|
}
|
||||||
if (candidate.visual_style) {
|
if (candidate.visual_style) {
|
||||||
STATE.visual_style = candidate.visual_style;
|
STATE.visual_style = candidate.visual_style;
|
||||||
if (candidate.visual_style === "custom" && candidate.visual_style_behavior) {
|
STATE.visual_style_behavior = candidate.visual_style === "custom" ?
|
||||||
STATE.visual_style_behavior = candidate.visual_style_behavior;
|
directionBehavior(candidate, "visual_style") : "";
|
||||||
}
|
ACTIVE_COMPONENT_DIRECTION_IDS.visual_style = directionId;
|
||||||
}
|
}
|
||||||
if (candidate.color) {
|
if (candidate.color) {
|
||||||
STATE.color = {
|
STATE.color = {
|
||||||
@@ -1902,27 +1988,22 @@
|
|||||||
}
|
}
|
||||||
if (candidate.typography) {
|
if (candidate.typography) {
|
||||||
var typography = normTypography(candidate.typography);
|
var typography = normTypography(candidate.typography);
|
||||||
var previousTypography = STATE.typography || {};
|
resetTypographySizeOverrides();
|
||||||
STATE.typography = {
|
STATE.typography = typography;
|
||||||
name: localized(typography, "name") || typography.name || "",
|
STATE.typography.name = localized(candidate.typography, "name") || typography.name || "";
|
||||||
heading: typography.heading || {},
|
STATE.typography.body_size = typography.body_size ||
|
||||||
body: typography.body || {},
|
defaultBodySizeForCanvas(STATE.canvas, STATE.delivery_purpose);
|
||||||
// A direction changes font character, not the already-visible
|
STATE.typography.sizes = Object.assign({}, typography.sizes || {});
|
||||||
// reading-mode sizing state.
|
syncUnpinnedTypographySizes(true);
|
||||||
body_size: previousTypography.body_size ||
|
|
||||||
defaultBodySizeForCanvas(STATE.canvas, STATE.delivery_purpose),
|
|
||||||
sizes: Object.assign({}, previousTypography.sizes || {})
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
if (candidate.icons) STATE.icons = normalizeRecId("icons", candidate.icons);
|
if (candidate.icons) STATE.icons = normalizeRecId("icons", candidate.icons);
|
||||||
if (candidate.image_strategy) {
|
if (candidate.image_strategy) {
|
||||||
STATE.image_strategy = normalizedImageStrategy(candidate.image_strategy);
|
STATE.image_strategy = normalizedImageStrategy(candidate.image_strategy);
|
||||||
|
ACTIVE_COMPONENT_DIRECTION_IDS.image_strategy = directionId;
|
||||||
}
|
}
|
||||||
if (candidate.image_usage) {
|
ACTIVE_DIRECTION_ID = directionId;
|
||||||
var usage = selectedImageUsageIds(candidate.image_usage);
|
ACTIVE_DIRECTION_BASELINE = directionStateSignature(candidate);
|
||||||
if (usage.length) STATE.image_usage = usage;
|
if (shouldRender !== false) renderAll();
|
||||||
}
|
|
||||||
renderAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderDesignDirections(host) {
|
function renderDesignDirections(host) {
|
||||||
@@ -1930,11 +2011,16 @@
|
|||||||
if (!candidates.length) return;
|
if (!candidates.length) return;
|
||||||
var sec = section("B", "sec_design_directions", t("design_directions_hint"));
|
var sec = section("B", "sec_design_directions", t("design_directions_hint"));
|
||||||
var grid = el("div", "font-grid design-direction-grid");
|
var grid = el("div", "font-grid design-direction-grid");
|
||||||
|
var cardStates = [];
|
||||||
candidates.forEach(function (candidate, idx) {
|
candidates.forEach(function (candidate, idx) {
|
||||||
var card = el("div", "font-card design-direction-card");
|
var card = el("div", "font-card design-direction-card");
|
||||||
|
card.title = t("direction_reset_hint");
|
||||||
var head = el("div", "font-card-head");
|
var head = el("div", "font-card-head");
|
||||||
head.appendChild(el("span", "font-card-name",
|
head.appendChild(el("span", "font-card-name",
|
||||||
localized(candidate, "name") || (t("option_prefix") + " " + (idx + 1))));
|
localized(candidate, "name") || (t("option_prefix") + " " + (idx + 1))));
|
||||||
|
var status = el("span", "rec-badge direction-status");
|
||||||
|
status.style.display = "none";
|
||||||
|
head.appendChild(status);
|
||||||
card.appendChild(head);
|
card.appendChild(head);
|
||||||
if (candidate.visual_style) {
|
if (candidate.visual_style) {
|
||||||
var preview = el("div", "design-direction-preview");
|
var preview = el("div", "design-direction-preview");
|
||||||
@@ -1942,7 +2028,10 @@
|
|||||||
card.appendChild(preview);
|
card.appendChild(preview);
|
||||||
}
|
}
|
||||||
var meta = [];
|
var meta = [];
|
||||||
if (candidate.visual_style) meta.push(humanizeId(candidate.visual_style));
|
if (candidate.mode) meta.push(directionComponentValueLabel(candidate, "mode"));
|
||||||
|
if (candidate.visual_style) {
|
||||||
|
meta.push(directionComponentValueLabel(candidate, "visual_style"));
|
||||||
|
}
|
||||||
if (candidate.icons) meta.push(humanizeId(candidate.icons));
|
if (candidate.icons) meta.push(humanizeId(candidate.icons));
|
||||||
if (candidate.image_strategy && candidate.image_strategy.rendering) {
|
if (candidate.image_strategy && candidate.image_strategy.rendering) {
|
||||||
meta.push(comparisonValueLabel("rendering", candidate.image_strategy.rendering));
|
meta.push(comparisonValueLabel("rendering", candidate.image_strategy.rendering));
|
||||||
@@ -1961,76 +2050,301 @@
|
|||||||
if (swatches.childElementCount) card.appendChild(swatches);
|
if (swatches.childElementCount) card.appendChild(swatches);
|
||||||
var note = localized(candidate, "note");
|
var note = localized(candidate, "note");
|
||||||
if (note) card.appendChild(el("div", "color-note", note));
|
if (note) card.appendChild(el("div", "color-note", note));
|
||||||
card.addEventListener("click", function () { applyDesignDirection(candidate); });
|
card.addEventListener("click", function () { applyDesignDirection(candidate, idx); });
|
||||||
|
cardStates.push({ candidate: candidate, index: idx, card: card, status: status });
|
||||||
grid.appendChild(card);
|
grid.appendChild(card);
|
||||||
});
|
});
|
||||||
|
refreshDesignDirectionState = function () {
|
||||||
|
cardStates.forEach(function (entry) {
|
||||||
|
var active = designDirectionId(entry.candidate, entry.index) === ACTIVE_DIRECTION_ID;
|
||||||
|
var adjusted = active && activeDirectionAdjusted(entry.candidate, entry.index);
|
||||||
|
entry.card.classList.toggle("selected", active && !adjusted);
|
||||||
|
entry.card.classList.toggle("adjusted", adjusted);
|
||||||
|
entry.status.style.display = active ? "inline-block" : "none";
|
||||||
|
entry.status.textContent = adjusted ? t("direction_adjusted") : t("direction_active");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
refreshDesignDirectionState();
|
||||||
sec.appendChild(grid);
|
sec.appendChild(grid);
|
||||||
host.appendChild(sec);
|
host.appendChild(sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function directionComponentMatchesAuthored(candidate, field) {
|
||||||
|
if (field === "mode") {
|
||||||
|
return STATE.mode === candidate.mode &&
|
||||||
|
(candidate.mode !== "custom" ||
|
||||||
|
String(STATE.mode_behavior || "") === directionBehavior(candidate, "mode"));
|
||||||
|
}
|
||||||
|
if (field === "visual_style") {
|
||||||
|
return STATE.visual_style === candidate.visual_style &&
|
||||||
|
(candidate.visual_style !== "custom" ||
|
||||||
|
String(STATE.visual_style_behavior || "") ===
|
||||||
|
directionBehavior(candidate, "visual_style"));
|
||||||
|
}
|
||||||
|
if (field === "image_strategy") {
|
||||||
|
return JSON.stringify(comparableImageStrategy(STATE.image_strategy || {})) ===
|
||||||
|
JSON.stringify(comparableImageStrategy(candidate.image_strategy || {}));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function directionComponentSelected(candidate, field, index) {
|
||||||
|
var activeId = ACTIVE_COMPONENT_DIRECTION_IDS[field];
|
||||||
|
if (activeId) return activeId === designDirectionId(candidate, index);
|
||||||
|
return directionComponentMatchesAuthored(candidate, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyDirectionComponent(candidate, field, index) {
|
||||||
|
if (field === "mode") {
|
||||||
|
STATE.mode = candidate.mode;
|
||||||
|
STATE.mode_behavior = candidate.mode === "custom" ?
|
||||||
|
directionBehavior(candidate, "mode") : "";
|
||||||
|
} else if (field === "visual_style") {
|
||||||
|
STATE.visual_style = candidate.visual_style;
|
||||||
|
STATE.visual_style_behavior = candidate.visual_style === "custom" ?
|
||||||
|
directionBehavior(candidate, "visual_style") : "";
|
||||||
|
} else if (field === "image_strategy") {
|
||||||
|
STATE.image_strategy = normalizedImageStrategy(candidate.image_strategy || {});
|
||||||
|
}
|
||||||
|
ACTIVE_COMPONENT_DIRECTION_IDS[field] = designDirectionId(candidate, index);
|
||||||
|
renderAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
function directionComponentIsCustom(candidate, field) {
|
||||||
|
if (field === "image_strategy") {
|
||||||
|
return candidate && candidate.image_strategy &&
|
||||||
|
candidate.image_strategy.rendering === "custom";
|
||||||
|
}
|
||||||
|
return candidate && candidate[field] === "custom";
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDirectionComponentBehavior(field, value) {
|
||||||
|
if (field === "mode") {
|
||||||
|
STATE.mode = "custom";
|
||||||
|
STATE.mode_behavior = value;
|
||||||
|
} else if (field === "visual_style") {
|
||||||
|
STATE.visual_style = "custom";
|
||||||
|
STATE.visual_style_behavior = value;
|
||||||
|
} else if (field === "image_strategy") {
|
||||||
|
STATE.image_strategy = normalizedImageStrategy(STATE.image_strategy || {});
|
||||||
|
STATE.image_strategy.rendering = "custom";
|
||||||
|
STATE.image_strategy.behavior = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function directionComponentValueLabel(candidate, field) {
|
||||||
|
var value = candidate && candidate[field];
|
||||||
|
if (field === "image_strategy") {
|
||||||
|
value = value && value.rendering;
|
||||||
|
return comparisonValueLabel("rendering", value);
|
||||||
|
}
|
||||||
|
var catalog = field === "mode" ? CAT.modes : CAT.visual_styles;
|
||||||
|
var option = findCatalogOption(catalog, value);
|
||||||
|
return option ? optionLabel(option) : (value === "custom" ? t("custom") : humanizeId(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function directionComponentNote(candidate, field) {
|
||||||
|
if (field === "image_strategy") {
|
||||||
|
var strategy = normalizedImageStrategy(candidate.image_strategy || {});
|
||||||
|
return [strategy.visual, strategy.mood, strategy.behavior].filter(Boolean).join(" · ");
|
||||||
|
}
|
||||||
|
if (candidate[field] === "custom") return directionBehavior(candidate, field);
|
||||||
|
return localized(candidate, "note") || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function directionComponentEditableBehavior(candidate, field) {
|
||||||
|
if (field === "image_strategy") {
|
||||||
|
return normalizedImageStrategy(candidate.image_strategy || {}).behavior || "";
|
||||||
|
}
|
||||||
|
return directionBehavior(candidate, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderDirectionComponentCandidates(parent, field) {
|
||||||
|
var candidates = designDirectionCandidates().filter(function (candidate) {
|
||||||
|
return candidate && candidate[field];
|
||||||
|
});
|
||||||
|
if (!candidates.length) return;
|
||||||
|
var block = el("div", "subfield scheme-component-options");
|
||||||
|
block.appendChild(el("div", "subfield-label", t("scheme_component_options")));
|
||||||
|
var grid = el("div", "font-grid scheme-component-grid");
|
||||||
|
var entries = [];
|
||||||
|
candidates.forEach(function (candidate, index) {
|
||||||
|
var card = el("div", "font-card scheme-component-card");
|
||||||
|
card.dataset.candidateId = designDirectionId(candidate, index) + ":" + field;
|
||||||
|
var head = el("div", "font-card-head");
|
||||||
|
head.appendChild(el("span", "font-card-name",
|
||||||
|
localized(candidate, "name") || (t("option_prefix") + " " + (index + 1))));
|
||||||
|
head.appendChild(el("span", "font-card-meta",
|
||||||
|
directionComponentValueLabel(candidate, field)));
|
||||||
|
card.appendChild(head);
|
||||||
|
if (field === "visual_style" && candidate.visual_style !== "custom") {
|
||||||
|
var preview = el("div", "design-direction-preview");
|
||||||
|
appendVisualStyleImage(preview, candidate.visual_style);
|
||||||
|
card.appendChild(preview);
|
||||||
|
}
|
||||||
|
var note = directionComponentNote(candidate, field);
|
||||||
|
var noteNode = note ? el("div", "color-note", note) : null;
|
||||||
|
if (noteNode) card.appendChild(noteNode);
|
||||||
|
var editor = null;
|
||||||
|
if (directionComponentIsCustom(candidate, field)) {
|
||||||
|
editor = el("textarea", "text-input scheme-component-editor");
|
||||||
|
setNaturalInputDirection(editor);
|
||||||
|
editor.rows = 4;
|
||||||
|
editor.value = directionComponentEditableBehavior(candidate, field);
|
||||||
|
editor.placeholder = t(field === "mode" ? "mode_behavior_placeholder" :
|
||||||
|
(field === "visual_style" ? "visual_style_behavior_placeholder" :
|
||||||
|
"image_strategy_custom_placeholder"));
|
||||||
|
editor.style.display = "none";
|
||||||
|
editor.addEventListener("click", function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
});
|
||||||
|
editor.addEventListener("input", function () {
|
||||||
|
setDirectionComponentBehavior(field, editor.value);
|
||||||
|
if (field === "image_strategy") refreshImageStrategyPreview();
|
||||||
|
refreshDesignDirectionState();
|
||||||
|
refreshDirectionComponentStates();
|
||||||
|
});
|
||||||
|
card.appendChild(editor);
|
||||||
|
}
|
||||||
|
card.addEventListener("click", function () {
|
||||||
|
applyDirectionComponent(candidate, field, index);
|
||||||
|
});
|
||||||
|
entries.push({
|
||||||
|
candidate: candidate,
|
||||||
|
index: index,
|
||||||
|
card: card,
|
||||||
|
note: noteNode,
|
||||||
|
editor: editor
|
||||||
|
});
|
||||||
|
grid.appendChild(card);
|
||||||
|
});
|
||||||
|
var paint = function () {
|
||||||
|
entries.forEach(function (entry) {
|
||||||
|
var selected = directionComponentSelected(
|
||||||
|
entry.candidate, field, entry.index
|
||||||
|
);
|
||||||
|
var adjusted = selected &&
|
||||||
|
!directionComponentMatchesAuthored(entry.candidate, field);
|
||||||
|
entry.card.classList.toggle("selected", selected);
|
||||||
|
entry.card.classList.toggle("adjusted", adjusted);
|
||||||
|
if (entry.editor) {
|
||||||
|
entry.editor.style.display = selected ? "block" : "none";
|
||||||
|
if (selected && document.activeElement !== entry.editor) {
|
||||||
|
var current = field === "mode" ? STATE.mode_behavior :
|
||||||
|
(field === "visual_style" ? STATE.visual_style_behavior :
|
||||||
|
((STATE.image_strategy || {}).behavior || ""));
|
||||||
|
entry.editor.value = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entry.note) entry.note.style.display = selected ? "none" : "block";
|
||||||
|
});
|
||||||
|
};
|
||||||
|
DIRECTION_COMPONENT_PAINTERS.push(paint);
|
||||||
|
paint();
|
||||||
|
block.appendChild(grid);
|
||||||
|
parent.appendChild(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
function currentDirectionCustomCandidate(field, stateKey) {
|
||||||
|
if (STATE[field] !== "custom") return null;
|
||||||
|
return designDirectionCandidates().filter(function (candidate) {
|
||||||
|
return candidate && candidate[field] === "custom" &&
|
||||||
|
directionBehavior(candidate, field) === String(STATE[stateKey] || "");
|
||||||
|
})[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderCurrentDirectionCustomEditor(parent, field, stateKey, placeholderKey) {
|
||||||
|
if (STATE[field] !== "custom") return null;
|
||||||
|
if (ACTIVE_COMPONENT_DIRECTION_IDS[field]) return null;
|
||||||
|
var source = currentDirectionCustomCandidate(field, stateKey);
|
||||||
|
if (!source && customCandidateBehavior(field)) return null;
|
||||||
|
var block = el("div", "subfield direction-custom-editor");
|
||||||
|
var label = t("custom");
|
||||||
|
if (source && localized(source, "name")) {
|
||||||
|
label = localized(source, "name") + " · " + label;
|
||||||
|
}
|
||||||
|
block.appendChild(el("div", "subfield-label", label));
|
||||||
|
var input = el("textarea", "text-input custom-input");
|
||||||
|
setNaturalInputDirection(input);
|
||||||
|
input.rows = 4;
|
||||||
|
input.placeholder = t(placeholderKey);
|
||||||
|
input.value = STATE[stateKey] || "";
|
||||||
|
input.style.display = "block";
|
||||||
|
input.addEventListener("input", function () {
|
||||||
|
STATE[stateKey] = input.value;
|
||||||
|
refreshDesignDirectionState();
|
||||||
|
refreshDirectionComponentStates();
|
||||||
|
});
|
||||||
|
block.appendChild(input);
|
||||||
|
parent.appendChild(block);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
function renderNarrativeDirection(host) {
|
function renderNarrativeDirection(host) {
|
||||||
var sec = section(4, "sec_narrative");
|
var sec = section(4, "sec_narrative");
|
||||||
var custom = creativeCustomOptions("mode", "mode_behavior", "mode_behavior_placeholder");
|
renderDirectionComponentCandidates(sec, "mode");
|
||||||
|
var directionCustomEditor = null;
|
||||||
|
var custom = currentDirectionCustomCandidate("mode", "mode_behavior") ? null :
|
||||||
|
creativeCustomOptions("mode", "mode_behavior", "mode_behavior_placeholder");
|
||||||
enumField(sec, CAT.modes, recOrFirst("mode", CAT.modes),
|
enumField(sec, CAT.modes, recOrFirst("mode", CAT.modes),
|
||||||
function () { return STATE.mode; }, function (v) { STATE.mode = v; },
|
function () { return STATE.mode; }, function (v) {
|
||||||
|
STATE.mode = v;
|
||||||
|
ACTIVE_COMPONENT_DIRECTION_IDS.mode = "";
|
||||||
|
if (v !== "custom") STATE.mode_behavior = "";
|
||||||
|
refreshDesignDirectionState();
|
||||||
|
refreshDirectionComponentStates();
|
||||||
|
if (directionCustomEditor) {
|
||||||
|
directionCustomEditor.style.display = v === "custom" ? "block" : "none";
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
allowCustom: !!custom,
|
allowCustom: !!custom,
|
||||||
customOnOwnRow: true,
|
customOnOwnRow: true,
|
||||||
customSentinel: "custom",
|
customSentinel: "custom",
|
||||||
|
preserveCustom: true,
|
||||||
placeholder: t("mode_behavior_placeholder"),
|
placeholder: t("mode_behavior_placeholder"),
|
||||||
aiCustom: custom
|
aiCustom: custom
|
||||||
});
|
});
|
||||||
|
directionCustomEditor = renderCurrentDirectionCustomEditor(
|
||||||
|
sec, "mode", "mode_behavior", "mode_behavior_placeholder"
|
||||||
|
);
|
||||||
host.appendChild(sec);
|
host.appendChild(sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
function visualStyleRecommendationSpectrum() {
|
|
||||||
var raw = (REC && Array.isArray(REC.visual_style_spectrum)) ? REC.visual_style_spectrum : [];
|
|
||||||
if (!raw.length) {
|
|
||||||
raw = designDirectionCandidates().map(function (candidate) {
|
|
||||||
return {
|
|
||||||
id: candidate && candidate.visual_style,
|
|
||||||
tag_zh: candidate && candidate.name_zh,
|
|
||||||
tag_en: candidate && candidate.name_en,
|
|
||||||
tag_ja: candidate && candidate.name_ja,
|
|
||||||
note_zh: candidate && candidate.note_zh,
|
|
||||||
note_en: candidate && candidate.note_en,
|
|
||||||
note_ja: candidate && candidate.note_ja
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var spectrum = [];
|
|
||||||
var seen = {};
|
|
||||||
raw.some(function (item) {
|
|
||||||
var id = normalizeRecId("visual_style", item && item.id);
|
|
||||||
if (!id || seen[id]) return false;
|
|
||||||
seen[id] = true;
|
|
||||||
spectrum.push(Object.assign({}, item, { id: id }));
|
|
||||||
return spectrum.length === 3;
|
|
||||||
});
|
|
||||||
if (!spectrum.length) {
|
|
||||||
var fallbackId = recId("visual_style") || normalizeRecId("visual_style", directionField("visual_style"));
|
|
||||||
if (fallbackId) spectrum.push({ id: fallbackId });
|
|
||||||
}
|
|
||||||
return spectrum;
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderVisualDirection(host) {
|
function renderVisualDirection(host) {
|
||||||
var sec = section(5, "sec_visual");
|
var sec = section(5, "sec_visual");
|
||||||
var custom = creativeCustomOptions(
|
renderDirectionComponentCandidates(sec, "visual_style");
|
||||||
|
var directionCustomEditor = null;
|
||||||
|
var custom = currentDirectionCustomCandidate(
|
||||||
|
"visual_style", "visual_style_behavior"
|
||||||
|
) ? null : creativeCustomOptions(
|
||||||
"visual_style", "visual_style_behavior", "visual_style_behavior_placeholder"
|
"visual_style", "visual_style_behavior", "visual_style_behavior_placeholder"
|
||||||
);
|
);
|
||||||
enumField(sec, CAT.visual_styles, recOrFirst("visual_style", CAT.visual_styles),
|
enumField(sec, CAT.visual_styles, recOrFirst("visual_style", CAT.visual_styles),
|
||||||
function () { return STATE.visual_style; }, function (v) { STATE.visual_style = v; },
|
function () { return STATE.visual_style; }, function (v) {
|
||||||
|
STATE.visual_style = v;
|
||||||
|
ACTIVE_COMPONENT_DIRECTION_IDS.visual_style = "";
|
||||||
|
if (v !== "custom") STATE.visual_style_behavior = "";
|
||||||
|
refreshDesignDirectionState();
|
||||||
|
refreshDirectionComponentStates();
|
||||||
|
if (directionCustomEditor) {
|
||||||
|
directionCustomEditor.style.display = v === "custom" ? "block" : "none";
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
allowCustom: !!custom,
|
allowCustom: !!custom,
|
||||||
customOnOwnRow: true,
|
customOnOwnRow: true,
|
||||||
customSentinel: "custom",
|
customSentinel: "custom",
|
||||||
|
preserveCustom: true,
|
||||||
placeholder: t("visual_style_behavior_placeholder"),
|
placeholder: t("visual_style_behavior_placeholder"),
|
||||||
aiCustom: custom,
|
aiCustom: custom,
|
||||||
spectrum: visualStyleRecommendationSpectrum(),
|
|
||||||
preview: "visual_style",
|
preview: "visual_style",
|
||||||
chipsClass: "visual-style-grid"
|
chipsClass: "visual-style-grid"
|
||||||
});
|
});
|
||||||
|
directionCustomEditor = renderCurrentDirectionCustomEditor(
|
||||||
|
sec, "visual_style", "visual_style_behavior",
|
||||||
|
"visual_style_behavior_placeholder"
|
||||||
|
);
|
||||||
host.appendChild(sec);
|
host.appendChild(sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2960,6 +3274,7 @@
|
|||||||
var strategySub = el("div", "subfield image-strategy-subfield");
|
var strategySub = el("div", "subfield image-strategy-subfield");
|
||||||
strategySub.appendChild(el("div", "subfield-label", t("image_strategy")));
|
strategySub.appendChild(el("div", "subfield-label", t("image_strategy")));
|
||||||
strategySub.appendChild(el("div", "toggle-desc", t("image_strategy_reference_hint")));
|
strategySub.appendChild(el("div", "toggle-desc", t("image_strategy_reference_hint")));
|
||||||
|
renderDirectionComponentCandidates(strategySub, "image_strategy");
|
||||||
var recommendedStrategies = imageStrategyRecommendationCandidates();
|
var recommendedStrategies = imageStrategyRecommendationCandidates();
|
||||||
var strategyCands = imageStrategySelectableCandidates();
|
var strategyCands = imageStrategySelectableCandidates();
|
||||||
var hasRecommendedStrategies = recommendedStrategies.length > 0;
|
var hasRecommendedStrategies = recommendedStrategies.length > 0;
|
||||||
@@ -2967,22 +3282,32 @@
|
|||||||
var presetPicker = el("div", "image-strategy-picker");
|
var presetPicker = el("div", "image-strategy-picker");
|
||||||
var presetSelect = el("select", "font-select image-strategy-select");
|
var presetSelect = el("select", "font-select image-strategy-select");
|
||||||
var customCard = null;
|
var customCard = null;
|
||||||
|
var currentCustomEditor = null;
|
||||||
var syncCustomStrategy = function () {};
|
var syncCustomStrategy = function () {};
|
||||||
var selectCustomImageStrategy = function () {};
|
var selectCustomImageStrategy = function () {};
|
||||||
|
|
||||||
function selectImageStrategy(idx) {
|
function selectImageStrategy(idx) {
|
||||||
if (!strategyCands[idx]) return;
|
if (!strategyCands[idx]) return;
|
||||||
STATE.image_strategy = normalizedImageStrategy(strategyCands[idx]);
|
STATE.image_strategy = normalizedImageStrategy(strategyCands[idx]);
|
||||||
|
ACTIVE_COMPONENT_DIRECTION_IDS.image_strategy = "";
|
||||||
presetSelect.value = String(idx);
|
presetSelect.value = String(idx);
|
||||||
if (customCard) customCard.classList.remove("selected");
|
if (customCard) customCard.classList.remove("selected");
|
||||||
|
if (currentCustomEditor) currentCustomEditor.style.display = "none";
|
||||||
syncCustomStrategy(false);
|
syncCustomStrategy(false);
|
||||||
refreshImageStrategyPreview();
|
refreshImageStrategyPreview();
|
||||||
|
refreshDesignDirectionState();
|
||||||
|
refreshDirectionComponentStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
function imageStrategyCandidateIndex(strategy) {
|
function imageStrategyCandidateIndex(strategy) {
|
||||||
if (!strategy) return -1;
|
if (!strategy) return -1;
|
||||||
|
var normalized = JSON.stringify(comparableImageStrategy(strategy));
|
||||||
for (var i = 0; i < strategyCands.length; i += 1) {
|
for (var i = 0; i < strategyCands.length; i += 1) {
|
||||||
if (strategyCands[i] && strategyCands[i].rendering === strategy.rendering) return i;
|
if (JSON.stringify(comparableImageStrategy(strategyCands[i])) === normalized) return i;
|
||||||
|
}
|
||||||
|
for (var fallback = 0; fallback < strategyCands.length; fallback += 1) {
|
||||||
|
if (strategyCands[fallback] &&
|
||||||
|
strategyCands[fallback].rendering === strategy.rendering) return fallback;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -3063,10 +3388,13 @@
|
|||||||
|
|
||||||
selectCustomImageStrategy = function () {
|
selectCustomImageStrategy = function () {
|
||||||
STATE.image_strategy = normalizedImageStrategy(customStrategy);
|
STATE.image_strategy = normalizedImageStrategy(customStrategy);
|
||||||
|
ACTIVE_COMPONENT_DIRECTION_IDS.image_strategy = "";
|
||||||
presetSelect.value = "";
|
presetSelect.value = "";
|
||||||
customCard.classList.add("selected");
|
customCard.classList.add("selected");
|
||||||
syncCustomStrategy(true);
|
syncCustomStrategy(true);
|
||||||
refreshImageStrategyPreview();
|
refreshImageStrategyPreview();
|
||||||
|
refreshDesignDirectionState();
|
||||||
|
refreshDirectionComponentStates();
|
||||||
};
|
};
|
||||||
|
|
||||||
customInput.addEventListener("click", function (event) { event.stopPropagation(); });
|
customInput.addEventListener("click", function (event) { event.stopPropagation(); });
|
||||||
@@ -3083,6 +3411,26 @@
|
|||||||
strategySub.appendChild(customCard);
|
strategySub.appendChild(customCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!customCard && !ACTIVE_COMPONENT_DIRECTION_IDS.image_strategy &&
|
||||||
|
STATE.image_strategy &&
|
||||||
|
STATE.image_strategy.rendering === "custom") {
|
||||||
|
var customEditorField = el("div", "subfield image-strategy-current-custom");
|
||||||
|
customEditorField.appendChild(el("div", "subfield-label", t("custom")));
|
||||||
|
currentCustomEditor = el("textarea", "text-input image-strategy-custom-input");
|
||||||
|
setNaturalInputDirection(currentCustomEditor);
|
||||||
|
currentCustomEditor.rows = 4;
|
||||||
|
currentCustomEditor.placeholder = t("image_strategy_custom_placeholder");
|
||||||
|
currentCustomEditor.value = STATE.image_strategy.behavior || "";
|
||||||
|
currentCustomEditor.addEventListener("input", function () {
|
||||||
|
STATE.image_strategy.behavior = currentCustomEditor.value;
|
||||||
|
refreshImageStrategyPreview();
|
||||||
|
refreshDesignDirectionState();
|
||||||
|
refreshDirectionComponentStates();
|
||||||
|
});
|
||||||
|
customEditorField.appendChild(currentCustomEditor);
|
||||||
|
strategySub.appendChild(customEditorField);
|
||||||
|
}
|
||||||
|
|
||||||
var recommendedIds = selectedImageUsageIds(recValue("image_usage"));
|
var recommendedIds = selectedImageUsageIds(recValue("image_usage"));
|
||||||
if (!recommendedIds.length) recommendedIds = [defaultImageUsageId()];
|
if (!recommendedIds.length) recommendedIds = [defaultImageUsageId()];
|
||||||
var usageChipById = {};
|
var usageChipById = {};
|
||||||
@@ -3129,11 +3477,17 @@
|
|||||||
sec.appendChild(usageNote);
|
sec.appendChild(usageNote);
|
||||||
sec.appendChild(strategySub);
|
sec.appendChild(strategySub);
|
||||||
|
|
||||||
|
var currentStrategyIndex = imageStrategyCandidateIndex(STATE.image_strategy);
|
||||||
if (STATE.image_strategy && STATE.image_strategy.rendering === "custom" && customCard) {
|
if (STATE.image_strategy && STATE.image_strategy.rendering === "custom" && customCard) {
|
||||||
selectCustomImageStrategy();
|
selectCustomImageStrategy();
|
||||||
} else if (STATE.image_strategy && imageStrategyCandidateIndex(STATE.image_strategy) >= 0) {
|
} else if (STATE.image_strategy && STATE.image_strategy.rendering === "custom") {
|
||||||
selectImageStrategy(imageStrategyCandidateIndex(STATE.image_strategy));
|
presetSelect.value = "";
|
||||||
} else if (needsGeneratedImagesForUsage(STATE.image_usage) &&
|
} else if (currentStrategyIndex >= 0) {
|
||||||
|
presetSelect.value = String(currentStrategyIndex);
|
||||||
|
if (customCard) customCard.classList.remove("selected");
|
||||||
|
syncCustomStrategy(false);
|
||||||
|
} else if ((!STATE.image_strategy || !STATE.image_strategy.rendering) &&
|
||||||
|
needsGeneratedImagesForUsage(STATE.image_usage) &&
|
||||||
hasRecommendedStrategies && strategyCands.length) {
|
hasRecommendedStrategies && strategyCands.length) {
|
||||||
selectImageStrategy(imageStrategySelectedIndex());
|
selectImageStrategy(imageStrategySelectedIndex());
|
||||||
}
|
}
|
||||||
@@ -3264,6 +3618,7 @@
|
|||||||
refreshImageProduction = function () {};
|
refreshImageProduction = function () {};
|
||||||
refreshBodySizeHint = function () {};
|
refreshBodySizeHint = function () {};
|
||||||
refreshSizeInputs = function () {};
|
refreshSizeInputs = function () {};
|
||||||
|
DIRECTION_COMPONENT_PAINTERS = [];
|
||||||
var previewHost = document.getElementById("topbar-preview");
|
var previewHost = document.getElementById("topbar-preview");
|
||||||
if (previewHost) previewHost.innerHTML = "";
|
if (previewHost) previewHost.innerHTML = "";
|
||||||
if (stage === 1) {
|
if (stage === 1) {
|
||||||
@@ -3296,6 +3651,15 @@
|
|||||||
renderProactiveExecution(host);
|
renderProactiveExecution(host);
|
||||||
renderMode(host);
|
renderMode(host);
|
||||||
renderRefine(host);
|
renderRefine(host);
|
||||||
|
var refreshDirectionIndicators = function () {
|
||||||
|
window.setTimeout(function () {
|
||||||
|
refreshDesignDirectionState();
|
||||||
|
refreshDirectionComponentStates();
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
host.oninput = refreshDirectionIndicators;
|
||||||
|
host.onchange = refreshDirectionIndicators;
|
||||||
|
host.onclick = refreshDirectionIndicators;
|
||||||
}
|
}
|
||||||
updateActionBar(stage);
|
updateActionBar(stage);
|
||||||
}
|
}
|
||||||
@@ -3413,7 +3777,7 @@
|
|||||||
// A freshly authored Stage 2 starts from one deterministic reading-mode
|
// A freshly authored Stage 2 starts from one deterministic reading-mode
|
||||||
// baseline.
|
// baseline.
|
||||||
if (stageNumber(REC) === 2) syncUnpinnedTypographySizes(true);
|
if (stageNumber(REC) === 2) syncUnpinnedTypographySizes(true);
|
||||||
var rawImageUsage = recValue("image_usage") || directionField("image_usage");
|
var rawImageUsage = recValue("image_usage");
|
||||||
STATE.image_usage = selectedImageUsageIds(rawImageUsage);
|
STATE.image_usage = selectedImageUsageIds(rawImageUsage);
|
||||||
if (!STATE.image_usage.length) {
|
if (!STATE.image_usage.length) {
|
||||||
STATE.image_usage = [defaultImageUsageId()];
|
STATE.image_usage = [defaultImageUsageId()];
|
||||||
@@ -3423,16 +3787,21 @@
|
|||||||
var strategyCandidates = imageStrategyRecommendationCandidates();
|
var strategyCandidates = imageStrategyRecommendationCandidates();
|
||||||
var directionStrategy = directionField("image_strategy");
|
var directionStrategy = directionField("image_strategy");
|
||||||
var customStrategyRecommended = recId("image_strategy") === "custom";
|
var customStrategyRecommended = recId("image_strategy") === "custom";
|
||||||
if ((customStrategyRecommended ||
|
if (customStrategyRecommended && STATE.image_strategy_custom) {
|
||||||
(directionStrategy && directionStrategy.rendering === "custom")) &&
|
|
||||||
STATE.image_strategy_custom) {
|
|
||||||
STATE.image_strategy = normalizedImageStrategy(STATE.image_strategy_custom);
|
STATE.image_strategy = normalizedImageStrategy(STATE.image_strategy_custom);
|
||||||
|
} else if (directionStrategy) {
|
||||||
|
STATE.image_strategy = normalizedImageStrategy(directionStrategy);
|
||||||
} else if (strategyCandidates.length) {
|
} else if (strategyCandidates.length) {
|
||||||
STATE.image_strategy = normalizedImageStrategy(
|
STATE.image_strategy = normalizedImageStrategy(
|
||||||
strategyCandidates[imageStrategySelectedIndex()] || strategyCandidates[0]
|
strategyCandidates[imageStrategySelectedIndex()] || strategyCandidates[0]
|
||||||
);
|
);
|
||||||
} else if (directionStrategy) {
|
}
|
||||||
STATE.image_strategy = normalizedImageStrategy(directionStrategy);
|
var directions = designDirectionCandidates();
|
||||||
|
if (directions.length) {
|
||||||
|
var selected = Number(designDirectionSpec().selected || 0);
|
||||||
|
if (!isFinite(selected) || selected < 0) selected = 0;
|
||||||
|
selected = Math.min(selected, directions.length - 1);
|
||||||
|
applyDesignDirection(directions[selected], selected, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -478,6 +478,34 @@ textarea.text-input { resize: vertical; line-height: 1.5; }
|
|||||||
flex: 1 0 calc((100% - 20px) / 3);
|
flex: 1 0 calc((100% - 20px) / 3);
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
.design-direction-card.adjusted {
|
||||||
|
border-color: #d97706;
|
||||||
|
background: #fffbeb;
|
||||||
|
}
|
||||||
|
.direction-status { margin-left: auto; }
|
||||||
|
.scheme-component-options { margin-bottom: 14px; }
|
||||||
|
.scheme-component-grid {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: stretch;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
.scheme-component-card {
|
||||||
|
flex: 1 0 calc((100% - 20px) / 3);
|
||||||
|
min-width: 190px;
|
||||||
|
}
|
||||||
|
.scheme-component-card.adjusted {
|
||||||
|
border-color: #d97706;
|
||||||
|
background: #fffbeb;
|
||||||
|
}
|
||||||
|
.scheme-component-editor {
|
||||||
|
margin-top: 8px;
|
||||||
|
min-height: 84px;
|
||||||
|
resize: vertical;
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
.scheme-component-card .design-direction-preview { margin-top: 8px; }
|
||||||
.design-direction-preview {
|
.design-direction-preview {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: 16 / 9;
|
aspect-ratio: 16 / 9;
|
||||||
|
|||||||
@@ -307,15 +307,17 @@ its file time is newer than the handoff.
|
|||||||
The following fields belong to the Strategist stages, not to the
|
The following fields belong to the Strategist stages, not to the
|
||||||
template-selection receipt.
|
template-selection receipt.
|
||||||
|
|
||||||
- **Enumerable + custom** — canvas / icons retain blank manual inputs; mode / visual_style instead show a mandatory AI-authored proposal in full, initially unselected and editable after selection. Selected mode / style writes literal `custom` plus its behavior sibling.
|
- **Enumerable + custom** — canvas / icons retain blank manual inputs. Mode and visual style first show three project-specific `custom` values projected from the complete directions, then the full fixed base catalog as conservative single-select alternatives. Selecting a projected card expands its behavior editor in place; edits change only the current value, while clicking the owning whole-direction card restores the authored text.
|
||||||
- **Visual examples for hard-to-name choices** — the full-screen confirmation page loads real SVG page samples from `static/style_previews/` for `visual_style`, and renders real sample SVGs from `templates/icons` for `icons`. These thumbnails make style and icon-library choices visually comparable before the user locks them. Preview copy is fixed role text (big title / section title / body / points), not project content from recommendation files, so users compare visual treatment rather than copywriting. These previews are a confirmation aid only: they do not add fields to recommendation stage files or `result.json`, and they do not replace the later Step 6 live preview.
|
- **Visual examples for hard-to-name choices** — the full-screen confirmation page loads real SVG page samples from `static/style_previews/` for `visual_style`, and renders real sample SVGs from `templates/icons` for `icons`. These thumbnails make style and icon-library choices visually comparable before the user locks them. Preview copy is fixed role text (big title / section title / body / points), not project content from recommendation files, so users compare visual treatment rather than copywriting. These previews are a confirmation aid only: they do not add fields to recommendation stage files or `result.json`, and they do not replace the later Step 6 live preview.
|
||||||
- **Image usage multi-select** — image sources are selected as one or more catalog ids: `ai` = AI-generated, `web` = Web-sourced, `provided` = User-provided, `placeholder` = Placeholder, `none` = No images. `none` is exclusive. A confirmed non-`none` set is the allowed acquisition-source boundary, not a requirement to use every selected source; only explicit `image_notes` wording can require a source, asset, or page role. Recommendation and result values may be a legacy single string, but new files should use an array. When several sources are recommended, write the source ids to `recommend.image_usage` and write the actual usage strategy to `image_notes`, not a custom prose value.
|
- **Image usage multi-select** — image sources are selected as one or more catalog ids: `ai` = AI-generated, `web` = Web-sourced, `provided` = User-provided, `placeholder` = Placeholder, `none` = No images. `none` is exclusive. A confirmed non-`none` set is the allowed acquisition-source boundary, not a requirement to use every selected source; only explicit `image_notes` wording can require a source, asset, or page role. Recommendation and result values may be a legacy single string, but new files should use an array. When several sources are recommended, write the source ids to `recommend.image_usage` and write the actual usage strategy to `image_notes`, not a custom prose value.
|
||||||
- **Closed enumerable** — PPT reading mode (`delivery_purpose` compatibility key), formula policy / generation mode / refine spec, plus AI source only when image usage includes `ai`. These have no Custom box; out-of-catalog values snap back to the recommended option.
|
- **Closed enumerable** — PPT reading mode (`delivery_purpose` compatibility key), formula policy / generation mode / refine spec, plus AI source only when image usage includes `ai`. These have no Custom box; out-of-catalog values snap back to the recommended option.
|
||||||
- **Proactive execution booleans** — Final Stage 2 carries top-level `proactive_speaker_notes`, `proactive_custom_animations`, and `proactive_narration_audio` values. Defaults are `true`, `false`, and `false`, respectively. They control what the Agent does proactively only when the user has not explicitly instructed otherwise; the latest explicit user instruction always wins. These three values are raw confirmation evidence: the UI and server neither couple nor rewrite them, and every boolean combination is valid. When narration audio is enabled, Strategist later resolves the effective Speaker Notes outcome to enabled and records `Narration Audio dependency` as its Design Spec provenance. Disabling proactive custom animation does not suppress the Strategist's advisory motion recommendations.
|
- **Proactive execution booleans** — Final Stage 2 carries top-level `proactive_speaker_notes`, `proactive_custom_animations`, and `proactive_narration_audio` values. Defaults are `true`, `false`, and `false`, respectively. They control what the Agent does proactively only when the user has not explicitly instructed otherwise; the latest explicit user instruction always wins. These three values are raw confirmation evidence: the UI and server neither couple nor rewrite them, and every boolean combination is valid. When narration audio is enabled, Strategist later resolves the effective Speaker Notes outcome to enabled and records `Narration Audio dependency` as its Design Spec provenance. Disabling proactive custom animation does not suppress the Strategist's advisory motion recommendations.
|
||||||
- **Open prose** — `audience`, `communication_intent`, `audience_outcome`, `core_message`, `delivery_context`, `artifact_afterlife`, `content_divergence`, and `page_count`. `communication_intent` may carry several purposes plus priority / sequence; common paths appear only as help text. `delivery_context` states one primary presenter-led / reader-led / hybrid / recorded-self-running context plus optional secondary use; a hybrid recommendation names which context leads. `content_divergence` is the source-treatment axis. `page_count` may be a range here; Strategist resolves the exact §IX roster, leaving Executor no pagination latitude.
|
- **Open prose** — `audience`, `communication_intent`, `audience_outcome`, `core_message`, `delivery_context`, `artifact_afterlife`, `content_divergence`, and `page_count`. `communication_intent` may carry several purposes plus priority / sequence; common paths appear only as help text. `delivery_context` states one primary presenter-led / reader-led / hybrid / recorded-self-running context plus optional secondary use; a hybrid recommendation names which context leads. `content_divergence` is the source-treatment axis. `page_count` may be a range here; Strategist resolves the exact §IX roster, leaving Executor no pagination latitude.
|
||||||
- **Coordinated generative directions** — `design_directions` carries ≥3 safe / shifted / bold candidates. Each candidate bundles visual style, color, typography, icon id, and conditional generated-image rendering. The page can still render legacy top-level `color`, `typography`, and `image_strategy` candidates, but new staged recommendations use the coordinated bundle.
|
- **Coordinated generative directions** — `design_directions` carries exactly three complete candidates authored top-down from the project contract. Each has a unique stable id and bundles `custom` mode, `custom` visual style, color, typography, icon id, and `custom` generated-image rendering regardless of recommended image source. All three must be viable as whole solutions; they do not need different catalog bases or forced safe / shifted / bold archetypes. The page can still render legacy top-level `color`, `typography`, and `image_strategy` candidates, but new staged recommendations use the coordinated bundle.
|
||||||
|
|
||||||
AI-authored custom proposals apply only to mode, visual style, and conditional AI-image rendering; a selected proposal cannot be blank. Color / typography keep their existing manual Custom cards. Image usage uses source ids plus `image_notes`; closed sets have no Custom path.
|
Direction-local custom projections apply to mode, visual style, and generated-image rendering; all three are editable after selection and a selected custom value cannot be blank. The original recommendation remains immutable so a whole-direction click can reset every edited component. Legacy standalone `custom_candidates` remain readable but are optional and are not authored in new files. Color / typography keep their existing manual Custom cards. Image usage uses source ids plus `image_notes`; closed sets have no Custom path.
|
||||||
|
|
||||||
|
**Stage-2 catalog read gate.** Before choosing component bases, Strategist reads only `modes/_index.md`, `visual-styles/_index.md`, and `image-renderings/_index.md`. It authors the three whole solution intents first, freezes every basis id from those indexes, and only then reads the deduplicated selected detail files before completing the custom behaviors. Unselected sibling files never enter context; a novel custom reads none.
|
||||||
|
|
||||||
**Stage-1 current-value contract.** Each editable prose box starts with the Strategist's recommendation, if one exists. The user may retain, revise, or clear it; no Stage-1 prose field has a non-empty validation gate. On confirmation, the browser submits the current strings and the server preserves them through every later stage and the final `result.json`, including `""`. Blank means no explicit user constraint and may cause downstream default judgment, but it never causes the initial recommendation to be restored. A profile-declared `locked: true` field is read-only and remains the sole exception.
|
**Stage-1 current-value contract.** Each editable prose box starts with the Strategist's recommendation, if one exists. The user may retain, revise, or clear it; no Stage-1 prose field has a non-empty validation gate. On confirmation, the browser submits the current strings and the server preserves them through every later stage and the final `result.json`, including `""`. Blank means no explicit user constraint and may cause downstream default judgment, but it never causes the initial recommendation to be restored. A profile-declared `locked: true` field is read-only and remains the sole exception.
|
||||||
|
|
||||||
@@ -446,8 +448,9 @@ corresponding direct values (`formula_policy`, `generation_mode`, boolean
|
|||||||
"lang": "zh",
|
"lang": "zh",
|
||||||
"recommend": {
|
"recommend": {
|
||||||
"delivery_purpose": "balanced",
|
"delivery_purpose": "balanced",
|
||||||
"mode": "pyramid",
|
"mode": "custom",
|
||||||
"visual_style": "swiss-minimal",
|
"visual_style": "custom",
|
||||||
|
"image_strategy": "custom",
|
||||||
"image_usage": ["ai", "provided"],
|
"image_usage": ["ai", "provided"],
|
||||||
"image_ai_path": "auto",
|
"image_ai_path": "auto",
|
||||||
"formula_policy": "mixed",
|
"formula_policy": "mixed",
|
||||||
@@ -459,30 +462,17 @@ corresponding direct values (`formula_policy`, `generation_mode`, boolean
|
|||||||
"proactive_custom_animations": { "value": false },
|
"proactive_custom_animations": { "value": false },
|
||||||
"proactive_narration_audio": { "value": false },
|
"proactive_narration_audio": { "value": false },
|
||||||
"refine_spec": { "value": false },
|
"refine_spec": { "value": false },
|
||||||
"custom_candidates": {
|
|
||||||
"mode": {
|
|
||||||
"name_zh": "冲突到决策",
|
|
||||||
"behavior_zh": "先建立业务冲突,再用结论先行结构推动决策。"
|
|
||||||
},
|
|
||||||
"visual_style": {
|
|
||||||
"name_zh": "编辑批注风",
|
|
||||||
"behavior_zh": "严格栅格配合边注和证据强调。"
|
|
||||||
},
|
|
||||||
"image_strategy": {
|
|
||||||
"name_zh": "证据拼贴",
|
|
||||||
"rendering": "custom",
|
|
||||||
"visual_zh": "纸面证据拼贴",
|
|
||||||
"mood_zh": "审慎可信",
|
|
||||||
"behavior_zh": "裁切纸面配少量批注,保持平面深度并继承演示色板。"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"design_directions": {
|
"design_directions": {
|
||||||
"selected": 0,
|
"selected": 0,
|
||||||
"candidates": [
|
"candidates": [
|
||||||
{
|
{
|
||||||
|
"id": "executive-clarity",
|
||||||
"name_zh": "稳妥专业",
|
"name_zh": "稳妥专业",
|
||||||
"note_zh": "像成熟咨询简报",
|
"note_zh": "像成熟咨询简报",
|
||||||
"visual_style": "swiss-minimal",
|
"mode": "custom",
|
||||||
|
"mode_behavior_zh": "以 pyramid 的结论先行为主轴,在风险段引入 narrative 的局势—张力—解法转折;标题保持判断句,每章以可执行结论收束。",
|
||||||
|
"visual_style": "custom",
|
||||||
|
"visual_style_behavior_zh": "以 swiss-minimal 的精确栅格和大留白为基底,融入 editorial 的细规则、边注与证据层级;标题锐利,正文中性,装饰只用于标记推理关系。",
|
||||||
"icons": "tabler-outline",
|
"icons": "tabler-outline",
|
||||||
"color": { "name_zh": "冷静专业", "palette": {
|
"color": { "name_zh": "冷静专业", "palette": {
|
||||||
"background": "#FFFFFF", "secondary_bg": "#F4F6F8",
|
"background": "#FFFFFF", "secondary_bg": "#F4F6F8",
|
||||||
@@ -496,10 +486,11 @@ corresponding direct values (`formula_policy`, `generation_mode`, boolean
|
|||||||
"body_size": 24
|
"body_size": 24
|
||||||
},
|
},
|
||||||
"image_strategy": {
|
"image_strategy": {
|
||||||
"name_zh": "克制矢量",
|
"name_zh": "编辑式证据图",
|
||||||
"rendering": "vector-illustration",
|
"rendering": "custom",
|
||||||
"visual_zh": "扁平矢量、实色块、少阴影",
|
"visual_zh": "简化矢量主体配合编辑式注释与局部材质对比",
|
||||||
"mood_zh": "稳定、可信、克制"
|
"mood_zh": "审慎、可信,像调查报道中的证据插图",
|
||||||
|
"behavior_zh": "融合 vector-illustration 的清晰轮廓与 editorial 的证据编排;使用平面色块、细规则和局部纸张纹理,避免写实景深与装饰性渐变,颜色继承当前演示文稿角色。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -507,11 +498,11 @@ corresponding direct values (`formula_policy`, `generation_mode`, boolean
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The example abbreviates the required ≥3 directions. Custom mode/style candidates remain mandatory; only a recommendation containing AI requires the custom image candidate. Final Stage 2 rejects fewer than three bundles, incomplete six-role palettes, or incomplete heading/body stacks. Legacy grids remain readable only with three complete palettes and complete typography.
|
The example shows one candidate's complete shape; the actual array repeats that shape for exactly three candidates. Every candidate requires a unique stable `id`, literal `custom` mode/style/rendering with localized behavior, an icon value, complete six-role palette, complete heading/body stack, and complete image strategy even when `recommend.image_usage` excludes AI. The server rejects any fixed mode/style/rendering inside a new direction. Legacy grids remain readable only with three complete palettes and complete typography.
|
||||||
|
|
||||||
- `recommend.*` names each recommended id. New mode / style values use a catalog id or literal `custom`; arbitrary prose values are legacy-only. Use `recommend.image_strategy: "custom"` only when an explicit user-supplied image direction should start selected. Missing recommendations fall back to the normal preset. Legacy aliases remain accepted; new files write canonical ids.
|
- `design_directions.selected` owns the initial complete bundle. New direction mode/style/rendering values are always literal `custom`; prose stays in the required behavior sibling. `recommend.*` remains a compatibility hint and may mirror `custom`, but it never replaces the selected direction. Legacy aliases remain accepted; new files write canonical ids.
|
||||||
- The three proactive-execution fields are top-level boolean `{ "value": ... }` objects, not catalog ids. Omitted fields use `true / false / false` for notes / custom animation / narration audio. These are absence-of-instruction defaults, not permission to override the user's latest explicit request. Preserve all three raw values independently through `result.json`; do not couple or rewrite them. Strategist derives effective Speaker Notes as enabled when audio is `true` and records `Narration Audio dependency` as provenance in the Design Spec. `proactive_custom_animations: false` leaves Strategist animation suggestions unchanged; it only prevents unrequested custom-animation execution.
|
- The three proactive-execution fields are top-level boolean `{ "value": ... }` objects, not catalog ids. Omitted fields use `true / false / false` for notes / custom animation / narration audio. These are absence-of-instruction defaults, not permission to override the user's latest explicit request. Preserve all three raw values independently through `result.json`; do not couple or rewrite them. Strategist derives effective Speaker Notes as enabled when audio is `true` and records `Narration Audio dependency` as provenance in the Design Spec. `proactive_custom_animations: false` leaves Strategist animation suggestions unchanged; it only prevents unrequested custom-animation execution.
|
||||||
- `custom_candidates` is recommendation-only. Mode / style carry localized `name` + `behavior`; conditional image strategy also carries `rendering: "custom"`, `visual`, and `mood`. When a proposal combines or borrows existing catalog entries, the visible behavior names every exact id and Strategist reads every corresponding file before authoring it; a genuinely novel proposal names none. The server rejects missing required candidates; the UI shows full copy, edits it only after selection, rejects a selected blank, and omits unselected candidates from `result.json`. Template-backed proposals obey inherited identity, prototype capacity, and `template_application`.
|
- `custom_candidates` is an optional legacy recommendation-only shape. New files place all three project-specific variants inside `design_directions`; each remains separately selectable and becomes editable in place. A custom behavior names exact catalog ids only when it actually uses them as synthesis bases. The UI rejects a selected blank and submits only the edited current value. Template-backed variants obey inherited identity, prototype capacity, and `template_application`.
|
||||||
- Seed `audience`, `communication_intent`, `audience_outcome`, and `delivery_context` when evidence supports them; users need not supply them, and every Stage-1 prose field may end blank. The contract and `primary_language` stay in `result.json` and `design_spec.md`; `spec_lock.md communication` receives `primary_language`, compact `audience` / `objective` / `core_message`, and reading mode. `communication_intent` may preserve multiple purposes and priority/sequence; never add a `primary_job` enum.
|
- Seed `audience`, `communication_intent`, `audience_outcome`, and `delivery_context` when evidence supports them; users need not supply them, and every Stage-1 prose field may end blank. The contract and `primary_language` stay in `result.json` and `design_spec.md`; `spec_lock.md communication` receives `primary_language`, compact `audience` / `objective` / `core_message`, and reading mode. `communication_intent` may preserve multiple purposes and priority/sequence; never add a `primary_job` enum.
|
||||||
- Do not write `recommend.template_reuse_scope` or `recommend.template_adherence`. Strategist records those internal exporter values later in `spec_lock.md` after inspecting the actual template and current content.
|
- Do not write `recommend.template_reuse_scope` or `recommend.template_adherence`. Strategist records those internal exporter values later in `spec_lock.md` after inspecting the actual template and current content.
|
||||||
- For a confirmed templates-mode handoff, write one editable prose field as top-level `template_application.value`. It summarizes **how to use** the already selected project-local template: actual page/prototype use and preservation/reorganization decisions. It never chooses, changes, or reinstalls a workspace. Omit it for free design. The UI returns the current string through final Stage 2; Strategist then persists the final effective plan as `- **Template Application**: ...` in `design_spec.md §I`, which Executor reads from the retained Design Spec. Never replace it with internal reuse/adherence ids or a fixed option menu.
|
- For a confirmed templates-mode handoff, write one editable prose field as top-level `template_application.value`. It summarizes **how to use** the already selected project-local template: actual page/prototype use and preservation/reorganization decisions. It never chooses, changes, or reinstalls a workspace. Omit it for free design. The UI returns the current string through final Stage 2; Strategist then persists the final effective plan as `- **Template Application**: ...` in `design_spec.md §I`, which Executor reads from the retained Design Spec. Never replace it with internal reuse/adherence ids or a fixed option menu.
|
||||||
@@ -532,11 +523,11 @@ Template-mode-only Stage-2 fragment:
|
|||||||
- **Color candidates carry the user-facing core `palette`**: `background`, `secondary_bg`, `primary`, `accent`, `secondary_accent`, and `body_text`. The page renders every role as a labelled swatch with its HEX value visible, and offers per-role override inputs for precise single-role edits, plus a **Custom color card with a free-text box** — the user can describe the palette in words or paste HEX values instead of filling each role; this writes `color: { "name": "custom", "custom": "<text>" }` to `result.json` for the AI to interpret. Legacy `text` is accepted as an alias for `body_text`, but new files should write `body_text`. Strategist derives secondary text, borders, state colors, and visual-style neutral tiers while writing `design_spec.md`, then projects the machine values to `spec_lock.md`; those are not user-facing confirmation choices.
|
- **Color candidates carry the user-facing core `palette`**: `background`, `secondary_bg`, `primary`, `accent`, `secondary_accent`, and `body_text`. The page renders every role as a labelled swatch with its HEX value visible, and offers per-role override inputs for precise single-role edits, plus a **Custom color card with a free-text box** — the user can describe the palette in words or paste HEX values instead of filling each role; this writes `color: { "name": "custom", "custom": "<text>" }` to `result.json` for the AI to interpret. Legacy `text` is accepted as an alias for `body_text`, but new files should write `body_text`. Strategist derives secondary text, borders, state colors, and visual-style neutral tiers while writing `design_spec.md`, then projects the machine values to `spec_lock.md`; those are not user-facing confirmation choices.
|
||||||
- **Candidate display text may be multilingual**: color / typography candidates can provide `name_zh` / `name_en` / `name_ja` and `note_zh` / `note_en` / `note_ja`; the page falls back to legacy `name` / `note`. Labels resolve in the page language first, then fall back across the others (a `ja` page: ja → en → zh; zh/en pages keep their zh↔en fallback and try `_ja` last), so when `lang` is `ja` always include the `_ja` variants — otherwise the candidate labels render in English.
|
- **Candidate display text may be multilingual**: color / typography candidates can provide `name_zh` / `name_en` / `name_ja` and `note_zh` / `note_en` / `note_ja`; the page falls back to legacy `name` / `note`. Labels resolve in the page language first, then fall back across the others (a `ja` page: ja → en → zh; zh/en pages keep their zh↔en fallback and try `_ja` last), so when `lang` is `ja` always include the `_ja` variants — otherwise the candidate labels render in English.
|
||||||
- **Typography candidates** use concrete heading/body `primary`; non-English decks also use `english`, while English-primary decks omit it. `cjk` / `latin` remain legacy aliases. Localized `name` labels the pair and `css` only previews. Bundles differ overall; font pairs may repeat without blocking. Fixed pairs require `fixed: true`. Catalog `fonts` supplies language-filtered dropdowns plus Other without limiting recommendations; edits mark Custom and refresh the preview. Include topic samples. PPT baselines are `text` 20 · `balanced` 24 · `presentation` 32 px; cards preserve sizes and submit px.
|
- **Typography candidates** use concrete heading/body `primary`; non-English decks also use `english`, while English-primary decks omit it. `cjk` / `latin` remain legacy aliases. Localized `name` labels the pair and `css` only previews. Bundles differ overall; font pairs may repeat without blocking. Fixed pairs require `fixed: true`. Catalog `fonts` supplies language-filtered dropdowns plus Other without limiting recommendations; edits mark Custom and refresh the preview. Include topic samples. PPT baselines are `text` 20 · `balanced` 24 · `presentation` 32 px; cards preserve sizes and submit px.
|
||||||
- **Per-role size override** (parallel to color's per-role HEX override): besides `body_size`, the page exposes editable inputs for `title` / `subtitle` / `annotation`. The browser applies one documented deterministic dependency chain: `reading mode → body baseline → unpinned role sizes` (role ramp: `body ×` the §g ratios). Changing reading mode updates the body and all unpinned roles locally; changing body updates unpinned roles locally. Editing body or a role pins that value, so later reading-mode changes do not overwrite it. Font / direction-card selection preserves all current sizes. This is a browser-only state update: it performs no fetch, asks the backend to author no new recommendations, and a re-render preserves exactly what the user sees. Each role input is labelled as px and shows an approximate pt equivalent (`1px = 0.75pt`) for orientation. The final values are written to `result.json` as `typography.sizes: { "title", "subtitle", "annotation" }` in **px** — every canvas, no pt and no `sizes_pt` provenance. These confirmed values are Strategist input anchors: the completed page plan may add recurring roles, and downstream execution owns bounded per-occurrence treatment. Candidate `sizes` remain accepted for compatibility, but the fresh Stage-2 baseline is normalized through the same local ramp before first render.
|
- **Per-role size override** (parallel to color's per-role HEX override): besides `body_size`, the page exposes editable inputs for `title` / `subtitle` / `annotation`. The browser applies one documented deterministic dependency chain: `reading mode → body baseline → unpinned role sizes` (role ramp: `body ×` the §g ratios). Changing reading mode updates the body and all unpinned roles locally; changing body updates unpinned roles locally. Editing body or a role pins that value, so later reading-mode changes do not overwrite it. A font-only selection preserves current sizes; applying a complete direction restores that direction's typography baseline and derived unpinned sizes, because the top card is an explicit reset action. This is a browser-only state update: it performs no fetch and asks the backend to author no new recommendations. Each role input is labelled as px and shows an approximate pt equivalent (`1px = 0.75pt`) for orientation. The final values are written to `result.json` as `typography.sizes: { "title", "subtitle", "annotation" }` in **px** — every canvas, no pt and no `sizes_pt` provenance. These confirmed values are Strategist input anchors: the completed page plan may add recurring roles, and downstream execution owns bounded per-occurrence treatment. Candidate `sizes` remain accepted for compatibility, but the fresh Stage-2 baseline is normalized through the same local ramp before first render.
|
||||||
- **`delivery_purpose` compatibility key / Reading mode** (enumerable, PPT only) decides where meaning is carried, not merely how large type is: `text` makes pages self-contained with complete sentences, short prose, captions, tables, and necessary detail; `balanced` shares explanation between page and presenter; `presentation` uses one idea, concise claims, and visual evidence while speech / notes carry the detail. It therefore governs page grammar, granularity, density / rhythm, and note burden. Reading-mode cards intentionally show **no px value**; the typography section owns the separately visible body / role sizes and applies any local default. It is surfaced in Stage 2 beside the visual system, separate from communication intent. `recommend.delivery_purpose` pre-selects one; `result.json` retains the key, while `spec_lock.md` uses canonical `consumption_mode`. Non-PPT canvases omit it.
|
- **`delivery_purpose` compatibility key / Reading mode** (enumerable, PPT only) decides where meaning is carried, not merely how large type is: `text` makes pages self-contained with complete sentences, short prose, captions, tables, and necessary detail; `balanced` shares explanation between page and presenter; `presentation` uses one idea, concise claims, and visual evidence while speech / notes carry the detail. It therefore governs page grammar, granularity, density / rhythm, and note burden. Reading-mode cards intentionally show **no px value**; the typography section owns the separately visible body / role sizes and applies any local default. It is surfaced in Stage 2 beside the visual system, separate from communication intent. `recommend.delivery_purpose` pre-selects one; `result.json` retains the key, while `spec_lock.md` uses canonical `consumption_mode`. Non-PPT canvases omit it.
|
||||||
- **Combined style preview** — a compact live "overall impression" strip sits just above the color section and is **sticky**: it pins under the topbar so it stays visible while the user scrolls through the color / icon / typography sections, keeping the picking controls and their combined effect on screen together. It applies the currently selected color palette **and** typography (heading sample in `primary` over `background`, body sample in `body_text`, an `accent` bar, a `secondary_bg` chip) and repaints on every color / HEX-override / font / `body_size` change. It does not replace the per-candidate swatches or font samples (those stay for picking); it is deliberately an abstract style chip, **not** a slide-layout preview — page layout preview remains the live-preview server's job (Step 6). No schema field; it derives entirely from the existing color + typography selections.
|
- **Combined style preview** — a compact live "overall impression" strip sits just above the color section and is **sticky**: it pins under the topbar so it stays visible while the user scrolls through the color / icon / typography sections, keeping the picking controls and their combined effect on screen together. It applies the currently selected color palette **and** typography (heading sample in `primary` over `background`, body sample in `body_text`, an `accent` bar, a `secondary_bg` chip) and repaints on every color / HEX-override / font / `body_size` change. It does not replace the per-candidate swatches or font samples (those stay for picking); it is deliberately an abstract style chip, **not** a slide-layout preview — page layout preview remains the live-preview server's job (Step 6). No schema field; it derives entirely from the existing color + typography selections.
|
||||||
- **Generated-image direction** appears only for `image_usage: ai`. One preset dropdown contains project recommendations when present plus the 20 system styles; Custom remains a separate card and is blank when AI was added manually. A preset submits its id; Custom submits `rendering: "custom"` + non-empty `behavior`; closing AI omits `image_strategy`. Catalog-based custom behavior names exact ids for optional `image_rendering_references`; a novel behavior has none. The left preview follows selection. No image palette is written; deck colors remain authoritative, and legacy `image_strategy.palette` is ignored.
|
- **Generated-image direction** appears only for current `image_usage: ai`, but all three custom project candidates already exist in `design_directions` before that toggle. Turning AI on reveals those candidates immediately without a backend rerun, followed by the 20 fixed system styles. Selecting a project candidate expands its behavior editor in that card; a fixed preset submits its id, while a project candidate submits `rendering: "custom"` + edited non-empty `behavior`. Turning AI off omits `image_strategy` from the final result without deleting the authored recommendation candidates. Catalog-based custom behavior names exact ids for optional `image_rendering_references`; a novel behavior has none. The left preview follows selection. No image palette is written; deck colors remain authoritative, and legacy `image_strategy.palette` is ignored.
|
||||||
- **`design_directions`** is the canonical Stage-2 spectrum: ≥3 meaningfully different safe / shifted / bold bundles with localized copy, style, icons, conditional image strategy, complete language-aware typography, and HEX `background`, `secondary_bg`, `primary`, `accent`, `secondary_accent`, `body_text`. Selection applies the bundle; component controls override it. `result.json` stores components, not a direction id.
|
- **`design_directions`** is the canonical Stage-2 starting set: exactly three top-down, project-fit bundles with stable ids, localized copy, custom mode/style/rendering, icons, complete language-aware typography, and HEX `background`, `secondary_bg`, `primary`, `accent`, `secondary_accent`, `body_text`. Clicking a card applies every field it owns; projected custom fields can then be edited in place and all lower controls may diverge. The card shows an adjusted state, while clicking the same or another whole direction reapplies its immutable authored bundle. `result.json` stores the edited current components, never a direction id.
|
||||||
- `recommend.generation_mode` and `refine_spec` mirror [`generate-pptx`](../../workflows/generate-pptx.md) Step 4. `split` / `true` are explicit opt-ins. Refinement adds no UI stage: after Gate 1 it stops before the lock for unrestricted chat revision until approval.
|
- `recommend.generation_mode` and `refine_spec` mirror [`generate-pptx`](../../workflows/generate-pptx.md) Step 4. `split` / `true` are explicit opt-ins. Refinement adds no UI stage: after Gate 1 it stops before the lock for unrestricted chat revision until approval.
|
||||||
- `content_divergence` is a **free-text** Stage-1 source-treatment field. Blank means a balanced default; facts stay sourced at every level. Strategist consumes it while authoring §IX and records it in `design_spec.md §I`; it is not written to `spec_lock.md`. Beautify sends `{ "value": "keep source wording and page structure verbatim", "locked": true }`, so the UI displays it read-only and the server restores it on every staged submit. Template-fill does not use this confirmation flow and does not surface it.
|
- `content_divergence` is a **free-text** Stage-1 source-treatment field. Blank means a balanced default; facts stay sourced at every level. Strategist consumes it while authoring §IX and records it in `design_spec.md §I`; it is not written to `spec_lock.md`. Beautify sends `{ "value": "keep source wording and page structure verbatim", "locked": true }`, so the UI displays it read-only and the server restores it on every staged submit. Template-fill does not use this confirmation flow and does not surface it.
|
||||||
- `lang` is the soft UI-language default (`zh` / `en` / `ja`); the persisted user choice wins. It never sets `primary_language`.
|
- `lang` is the soft UI-language default (`zh` / `en` / `ja`); the persisted user choice wins. It never sets `primary_language`.
|
||||||
@@ -555,8 +546,10 @@ Template-mode-only Stage-2 fragment:
|
|||||||
"delivery_context": "Primary: presenter-led 20-minute leadership review; secondary: reader-led approval copy shared afterward",
|
"delivery_context": "Primary: presenter-led 20-minute leadership review; secondary: reader-led approval copy shared afterward",
|
||||||
"artifact_afterlife": "Approval record, hand-off reference, and audit trail",
|
"artifact_afterlife": "Approval record, hand-off reference, and audit trail",
|
||||||
"content_divergence": "freely restructure and expand within the source",
|
"content_divergence": "freely restructure and expand within the source",
|
||||||
"mode": "pyramid",
|
"mode": "custom",
|
||||||
"visual_style": "swiss-minimal",
|
"mode_behavior": "...",
|
||||||
|
"visual_style": "custom",
|
||||||
|
"visual_style_behavior": "...",
|
||||||
"color": { "name": "...", "palette": { "background": "#...", "secondary_bg": "#...", "primary": "#...", "accent": "#...", "secondary_accent": "#...", "body_text": "#..." } },
|
"color": { "name": "...", "palette": { "background": "#...", "secondary_bg": "#...", "primary": "#...", "accent": "#...", "secondary_accent": "#...", "body_text": "#..." } },
|
||||||
"icons": "tabler-outline",
|
"icons": "tabler-outline",
|
||||||
"typography": { "name": "...", "heading": { "primary": "...", "english": "...", "css": "..." }, "body": { "primary": "...", "english": "...", "css": "..." }, "body_size": 24, "body_size_unit": "px", "sizes": { "title": 42, "subtitle": 32, "annotation": 18 } },
|
"typography": { "name": "...", "heading": { "primary": "...", "english": "...", "css": "..." }, "body": { "primary": "...", "english": "...", "css": "..." }, "body_size": 24, "body_size_unit": "px", "sizes": { "title": 42, "subtitle": 32, "annotation": 18 } },
|
||||||
@@ -565,7 +558,7 @@ Template-mode-only Stage-2 fragment:
|
|||||||
"image_usage": ["ai", "provided"],
|
"image_usage": ["ai", "provided"],
|
||||||
"image_notes": "封面和章节页用 AI 主视觉;产品页优先用户素材,缺口页可用占位符。",
|
"image_notes": "封面和章节页用 AI 主视觉;产品页优先用户素材,缺口页可用占位符。",
|
||||||
"image_ai_path": "auto",
|
"image_ai_path": "auto",
|
||||||
"image_strategy": { "name": "方案 A", "rendering": "vector-illustration", "visual": "...", "mood": "..." },
|
"image_strategy": { "name": "方案 A", "rendering": "custom", "visual": "...", "mood": "...", "behavior": "..." },
|
||||||
"proactive_speaker_notes": true,
|
"proactive_speaker_notes": true,
|
||||||
"proactive_custom_animations": false,
|
"proactive_custom_animations": false,
|
||||||
"proactive_narration_audio": false,
|
"proactive_narration_audio": false,
|
||||||
@@ -596,7 +589,7 @@ The Stage-1 intermediate write retains the communication contract for Stage 2.
|
|||||||
|
|
||||||
- Bespoke mode / style prose lives only in the required behavior sibling; image custom prose lives in `image_strategy.behavior`. Canvas / icons retain free-text edge cases, color / typography retain `name: "custom"`, and image usage remains a source-id array plus `image_notes`.
|
- Bespoke mode / style prose lives only in the required behavior sibling; image custom prose lives in `image_strategy.behavior`. Canvas / icons retain free-text edge cases, color / typography retain `name: "custom"`, and image usage remains a source-id array plus `image_notes`.
|
||||||
- `image_ai_path` and `image_strategy` appear only with `image_usage: ai` and remain confirmed downstream. The page is default; explicit/failure chat fallback keeps identical fields. `image_ai_path` selects the Step 5 path, and [`strategist-image.md`](../../references/strategist-image.md) §2 retains the selected rendering or custom behavior as the deck-level image identity anchor; individual prompts still adapt subject, composition, and atmosphere within it.
|
- `image_ai_path` and `image_strategy` appear only with `image_usage: ai` and remain confirmed downstream. The page is default; explicit/failure chat fallback keeps identical fields. `image_ai_path` selects the Step 5 path, and [`strategist-image.md`](../../references/strategist-image.md) §2 retains the selected rendering or custom behavior as the deck-level image identity anchor; individual prompts still adapt subject, composition, and atmosphere within it.
|
||||||
- Stage-1 **Confirm contract & template choice** writes the Stage-1 `result.json` and `template_selection.json` together, then keeps the page open while the agent installs the selection. The agent runs `--complete-template-selection`, writes fresh Stage 2 only after that handoff, and the page keeps polling. Stage-2 **Confirm final plan** saves the final `result.json` and shuts the server down (auto-close). The AI reads each receipt at its owning boundary; chat fallback mirrors the same decisions without UI artifacts. Either way, Step 4 ends with `--shutdown` so a never-confirmed page cannot retain its selected port ahead of Step 6 live preview.
|
- Stage-1 **Confirm contract & template choice** writes the Stage-1 `result.json` and `template_selection.json` together, then keeps the page open while the agent installs the selection. A successful Stage-1 wait is explicitly intermediate and cannot end the task. In the same active run, the agent runs `--complete-template-selection`, writes fresh Stage 2 only after that handoff, and enters the final wait while the page keeps polling. Stage-2 **Confirm final plan** saves the final `result.json` and shuts the server down (auto-close). The AI reads each receipt at its owning boundary; chat fallback mirrors the same decisions without UI artifacts. Either way, Step 4 ends with `--shutdown` so a never-confirmed page cannot retain its selected port ahead of Step 6 live preview.
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Requires `tiktoken` (not part of `requirements.txt` — end users never need it)
|
|||||||
pip install 'tiktoken>=0.7.0'
|
pip install 'tiktoken>=0.7.0'
|
||||||
```
|
```
|
||||||
|
|
||||||
Exit code `1` on any deterministic error; advisory duplicate/schema candidates stay warnings. With `--json`, setup failures also use a stable `AUDIT_SETUP_ERROR` JSON envelope instead of a traceback or plain-text error.
|
Exit code `1` on any deterministic error. An unaccepted exact duplicate or schema projection is an actionable warning; heuristic near-duplicate candidates remain report-only information and do not enter `findings`. With `--json`, setup failures also use a stable `AUDIT_SETUP_ERROR` JSON envelope instead of a traceback or plain-text error.
|
||||||
|
|
||||||
## What It Checks
|
## What It Checks
|
||||||
|
|
||||||
@@ -26,14 +26,42 @@ Exit code `1` on any deterministic error; advisory duplicate/schema candidates s
|
|||||||
| Load coverage | error when a corpus file is in no load set and has no `coverage.exempt` entry |
|
| Load coverage | error when a corpus file is in no load set and has no `coverage.exempt` entry |
|
||||||
| Registry claims (layout patterns, modes, styles, renderings, types, charts) | error on ID/count/index drift |
|
| Registry claims (layout patterns, modes, styles, renderings, types, charts) | error on ID/count/index drift |
|
||||||
| Markdown references and declared authority edges | error on broken links or unreferenced edges |
|
| Markdown references and declared authority edges | error on broken links or unreferenced edges |
|
||||||
| Cross-file exact/near duplicates | warning; intentional cases are adjudicated via `duplicates.accepted` |
|
| Cross-file exact duplicates | warning until adjudicated via `duplicates.accepted` |
|
||||||
| Schema multi-definition | warning when an owner field also has grammar-like text in any non-owner file |
|
| Cross-file near duplicates | informational candidates in the report; no finding |
|
||||||
|
| Schema multi-definition | warning for each unaccepted owner-field / projection-path pair; accepted projections stay visible in the report |
|
||||||
|
| Accepted duplicate/schema drift | error when an accepted source or projection no longer matches |
|
||||||
|
|
||||||
## Manifest Maintenance — `prompt_audit_manifest.json`
|
## Manifest Maintenance — `prompt_audit_manifest.json`
|
||||||
|
|
||||||
The manifest is audit-only (`audit_only: true`, `runtime_consumed: false`); it is a lint fixture, never prompt context. It hand-transcribes the load rules stated in `SKILL.md` and the role/workflow docs, so **every change to read instructions in those docs must update the matching load set in the same change** — the coverage check catches unclassified files, but only humans can catch a changed read rule for an existing file.
|
The manifest is audit-only (`audit_only: true`, `runtime_consumed: false`); it is a lint fixture, never prompt context. It hand-transcribes the load rules stated in `SKILL.md` and the role/workflow docs, so **every change to read instructions in those docs must update the matching load set in the same change** — the coverage check catches unclassified files, but only humans can catch a changed read rule for an existing file.
|
||||||
|
|
||||||
- **New corpus file** → when no existing category exemption matches it, the audit fails with `LOAD_COVERAGE_GAP` until you add it to the load sets that read it or exempt it with a one-line reason. Exempt only material that never enters role context (for example, a legacy tombstone, generated maintenance asset, maintainer-only doc, or license notice); represent conditional runtime reads as incremental load sets.
|
- **New corpus file** → when no existing category exemption matches it, the audit fails with `LOAD_COVERAGE_GAP` until you add it to the load sets that read it or exempt it with a one-line reason. Exempt only material that never enters role context (for example, a legacy tombstone, generated maintenance asset, maintainer-only doc, or license notice); represent conditional runtime reads as incremental load sets.
|
||||||
- **Intentional duplicate** → run `--json`, copy the finding's `kind`, `fingerprint`, and `paths` into `duplicates.accepted` with a reason. The acceptance identity is all three values, so separate path pairs with identical prose remain independently reviewable. Editing either reported raw block changes its fingerprint; stale acceptance fails with `DUPLICATE_ACCEPTED_STALE`. `--skip-near-duplicates` deliberately leaves accepted near pairs unchecked because that scan did not run.
|
- **Intentional exact duplicate** → run `--json`, copy the candidate's `kind`, `fingerprint`, and `paths` into `duplicates.accepted` with a reason. The acceptance identity is all three values, so separate path pairs with identical prose remain independently reviewable. Editing either reported raw block changes its fingerprint; stale acceptance fails with `DUPLICATE_ACCEPTED_STALE`.
|
||||||
- **Schema owner** → every configured field must have a definition signal in its declared owner. One grammar-like non-owner is enough to surface a candidate; split fields into separate owner entries when they belong to different artifacts.
|
- **Near duplicate** → inspect `duplicates.near` as heuristic maintenance information. It produces no warning. A maintainer may still record a stable intentional pair in `duplicates.accepted`; `--skip-near-duplicates` deliberately leaves accepted near pairs unchecked because that scan did not run.
|
||||||
|
- **Schema owner** → every configured field must have a field-local definition signal in its declared owner. Split fields into separate owner entries when they belong to different artifacts. Generic `key` / `value` prose elsewhere on a long line is not a grammar signal; explicit assignments, field-local grammar/format language, and forms such as `field ... one of ...` are.
|
||||||
|
- **Intentional schema projection** → run `--json`, then copy the field's `owner_fingerprint` and each reviewed projection's `path` / `fingerprint` into that `schema_grammars[]` entry. Classify every projection as `producer`, `consumer`, `reference`, or `compatibility`, and record a one-line reason:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"source": "skills/ppt-master/templates/schemas/spec_lock.schema.json",
|
||||||
|
"fields": ["page_rhythm"],
|
||||||
|
"scan": ["skills/ppt-master/**/*.md"],
|
||||||
|
"accepted": [
|
||||||
|
{
|
||||||
|
"field": "page_rhythm",
|
||||||
|
"owner_fingerprint": "0123456789ab",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-base.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "abcdef012345",
|
||||||
|
"reason": "Executor needs the selected page-rhythm key and closed values."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Acceptance is exact, not a path exemption. The owner fingerprint covers the configured field's owner contract; a projection fingerprint covers every current grammar-like line for that field in that path. Owner edits, projection edits, or projection removal fail with `SCHEMA_ACCEPTED_STALE`; a new field/path projection remains `SCHEMA_MULTIDEF_CANDIDATE`. The JSON report separates `schema_grammars[].open`, `.accepted`, and `.stale`, so adjudicated projections and drift remain auditable without turning stale accepted paths into duplicate warnings.
|
||||||
- **Budget ceilings** (`budget_policy: fixed_upper_bound`): budgets are stable, deliberately rounded limits rather than mirrors of the current token count. Establish a new ceiling with roughly 10% working headroom and round it up in 250-token increments below 10k, 1k increments below 100k, or 5k increments from 100k upward; the manifest loader enforces those increments. Once set, do not raise or lower a passing ceiling, including to restore headroom after prompt growth. Raise it only after the current audit reports `BUDGET_CORPUS`, `BUDGET_FILE`, or `BUDGET_LOAD_SET` against that exact ceiling; then choose the next rounded limit with comparable headroom, record the overflow-triggering scope in the same change, and leave it unchanged until another actual overflow.
|
- **Budget ceilings** (`budget_policy: fixed_upper_bound`): budgets are stable, deliberately rounded limits rather than mirrors of the current token count. Establish a new ceiling with roughly 10% working headroom and round it up in 250-token increments below 10k, 1k increments below 100k, or 5k increments from 100k upward; the manifest loader enforces those increments. Once set, do not raise or lower a passing ceiling, including to restore headroom after prompt growth. Raise it only after the current audit reports `BUDGET_CORPUS`, `BUDGET_FILE`, or `BUDGET_LOAD_SET` against that exact ceiling; then choose the next rounded limit with comparable headroom, record the overflow-triggering scope in the same change, and leave it unchanged until another actual overflow.
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ _AUTHORITY_TERMS_RE = re.compile(
|
|||||||
)
|
)
|
||||||
_EXTERNAL_SCHEMES = ("http://", "https://", "mailto:", "data:", "javascript:")
|
_EXTERNAL_SCHEMES = ("http://", "https://", "mailto:", "data:", "javascript:")
|
||||||
_SEVERITY_ORDER = {"error": 0, "warning": 1}
|
_SEVERITY_ORDER = {"error": 0, "warning": 1}
|
||||||
|
_SCHEMA_PROJECTION_ROLES = frozenset(
|
||||||
|
{"producer", "consumer", "reference", "compatibility"}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AuditError(RuntimeError):
|
class AuditError(RuntimeError):
|
||||||
@@ -190,6 +193,76 @@ def load_manifest(path: Path) -> dict[str, Any]:
|
|||||||
raise AuditError(
|
raise AuditError(
|
||||||
f"{label}.scan must be a non-empty array of path patterns"
|
f"{label}.scan must be a non-empty array of path patterns"
|
||||||
)
|
)
|
||||||
|
accepted = config.get("accepted", [])
|
||||||
|
if not isinstance(accepted, list):
|
||||||
|
raise AuditError(f"{label}.accepted must be an array")
|
||||||
|
accepted_fields: set[str] = set()
|
||||||
|
for accepted_index, entry in enumerate(accepted):
|
||||||
|
accepted_label = f"{label}.accepted[{accepted_index}]"
|
||||||
|
field_name = entry.get("field") if isinstance(entry, dict) else None
|
||||||
|
owner_fingerprint = (
|
||||||
|
entry.get("owner_fingerprint") if isinstance(entry, dict) else None
|
||||||
|
)
|
||||||
|
projections = entry.get("projections") if isinstance(entry, dict) else None
|
||||||
|
if (
|
||||||
|
not isinstance(entry, dict)
|
||||||
|
or not isinstance(field_name, str)
|
||||||
|
or not field_name.strip()
|
||||||
|
or not isinstance(owner_fingerprint, str)
|
||||||
|
or re.fullmatch(r"[0-9a-f]{12}", owner_fingerprint) is None
|
||||||
|
or not isinstance(projections, list)
|
||||||
|
or not projections
|
||||||
|
):
|
||||||
|
raise AuditError(
|
||||||
|
f"{accepted_label} requires field, a 12-hex owner_fingerprint, "
|
||||||
|
"and non-empty projections"
|
||||||
|
)
|
||||||
|
if field_name in accepted_fields:
|
||||||
|
raise AuditError(
|
||||||
|
f"{label}.accepted repeats field {field_name!r}"
|
||||||
|
)
|
||||||
|
accepted_fields.add(field_name)
|
||||||
|
projection_paths: set[str] = set()
|
||||||
|
for projection_index, projection in enumerate(projections):
|
||||||
|
projection_label = (
|
||||||
|
f"{accepted_label}.projections[{projection_index}]"
|
||||||
|
)
|
||||||
|
reason = (
|
||||||
|
projection.get("reason")
|
||||||
|
if isinstance(projection, dict)
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
projection_path = (
|
||||||
|
projection.get("path")
|
||||||
|
if isinstance(projection, dict)
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
not isinstance(projection, dict)
|
||||||
|
or not isinstance(projection_path, str)
|
||||||
|
or not projection_path.strip()
|
||||||
|
or projection.get("role") not in _SCHEMA_PROJECTION_ROLES
|
||||||
|
or not isinstance(projection.get("fingerprint"), str)
|
||||||
|
or re.fullmatch(
|
||||||
|
r"[0-9a-f]{12}", projection["fingerprint"]
|
||||||
|
)
|
||||||
|
is None
|
||||||
|
or not isinstance(reason, str)
|
||||||
|
or not reason.strip()
|
||||||
|
or "\n" in reason
|
||||||
|
or "\r" in reason
|
||||||
|
):
|
||||||
|
raise AuditError(
|
||||||
|
f"{projection_label} requires path, role "
|
||||||
|
"(producer|consumer|reference|compatibility), a 12-hex "
|
||||||
|
"fingerprint, and a one-line reason"
|
||||||
|
)
|
||||||
|
if projection_path in projection_paths:
|
||||||
|
raise AuditError(
|
||||||
|
f"{accepted_label}.projections repeats path "
|
||||||
|
f"{projection_path!r}"
|
||||||
|
)
|
||||||
|
projection_paths.add(projection_path)
|
||||||
|
|
||||||
exempt_entries = raw.get("coverage", {}).get("exempt", [])
|
exempt_entries = raw.get("coverage", {}).get("exempt", [])
|
||||||
if not isinstance(exempt_entries, list):
|
if not isinstance(exempt_entries, list):
|
||||||
@@ -1379,24 +1452,207 @@ def audit_registries(
|
|||||||
return sorted(reports, key=lambda item: item["name"]), findings
|
return sorted(reports, key=lambda item: item["name"]), findings
|
||||||
|
|
||||||
|
|
||||||
def _has_schema_grammar_signal(line: str, schema_field: str) -> bool:
|
def _schema_fingerprint(payload: Any) -> str:
|
||||||
heading = _SCHEMA_HEADING_RE.match(line)
|
serialized = json.dumps(
|
||||||
return bool(
|
payload,
|
||||||
(heading and heading.group(1) == schema_field)
|
ensure_ascii=False,
|
||||||
or re.search(r"\b(formats?|grammars?|schemas?|syntaxes?|keys?|values?)\b", line, re.I)
|
sort_keys=True,
|
||||||
or re.search(r"P<NN>\s*:", line)
|
separators=(",", ":"),
|
||||||
or re.search(rf"{re.escape(schema_field)}\s*[:=]", line)
|
|
||||||
or re.search(rf'"{re.escape(schema_field)}"\s*:', line)
|
|
||||||
or (" | " in line and re.search(r"<[^>]+>", line))
|
|
||||||
)
|
)
|
||||||
|
return hashlib.sha1(serialized.encode("utf-8")).hexdigest()[:12]
|
||||||
|
|
||||||
|
|
||||||
|
def _schema_field_pattern(schema_field: str) -> re.Pattern[str]:
|
||||||
|
return re.compile(
|
||||||
|
rf"(?<![A-Za-z0-9_]){re.escape(schema_field)}(?![A-Za-z0-9_])"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _schema_owner_fragments(value: Any, schema_field: str) -> list[dict[str, Any]]:
|
||||||
|
"""Extract stable, field-local fragments from a JSON schema owner."""
|
||||||
|
field_re = _schema_field_pattern(schema_field)
|
||||||
|
negative_field_re = re.compile(
|
||||||
|
rf"\(\?!{re.escape(schema_field)}(?:\\?\$)?\)"
|
||||||
|
)
|
||||||
|
fragments: list[dict[str, Any]] = []
|
||||||
|
|
||||||
|
def walk(item: Any, path: tuple[str, ...]) -> None:
|
||||||
|
if isinstance(item, dict):
|
||||||
|
direct_rule = any(
|
||||||
|
isinstance(child, str)
|
||||||
|
and field_re.search(negative_field_re.sub("", child))
|
||||||
|
for key, child in item.items()
|
||||||
|
if key != schema_field
|
||||||
|
)
|
||||||
|
if direct_rule:
|
||||||
|
fragments.append(
|
||||||
|
{
|
||||||
|
"kind": "rule",
|
||||||
|
"path": "/".join(path),
|
||||||
|
"value": item,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
for key, child in item.items():
|
||||||
|
child_path = (*path, str(key))
|
||||||
|
if key == schema_field:
|
||||||
|
fragments.append(
|
||||||
|
{
|
||||||
|
"kind": "definition",
|
||||||
|
"path": "/".join(child_path),
|
||||||
|
"value": child,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
walk(child, child_path)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not isinstance(item, list):
|
||||||
|
return
|
||||||
|
for child in item:
|
||||||
|
if isinstance(child, str) and child == schema_field:
|
||||||
|
fragments.append(
|
||||||
|
{
|
||||||
|
"kind": "membership",
|
||||||
|
"path": "/".join(path),
|
||||||
|
"value": child,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
child_path = path
|
||||||
|
if isinstance(child, dict):
|
||||||
|
semantic_id = child.get("id")
|
||||||
|
if isinstance(semantic_id, str) and semantic_id:
|
||||||
|
child_path = (*path, f"id={semantic_id}")
|
||||||
|
walk(child, child_path)
|
||||||
|
|
||||||
|
walk(value, ())
|
||||||
|
unique = {
|
||||||
|
json.dumps(
|
||||||
|
fragment,
|
||||||
|
ensure_ascii=False,
|
||||||
|
sort_keys=True,
|
||||||
|
separators=(",", ":"),
|
||||||
|
): fragment
|
||||||
|
for fragment in fragments
|
||||||
|
}
|
||||||
|
return [unique[key] for key in sorted(unique)]
|
||||||
|
|
||||||
|
|
||||||
|
def _schema_owner_fingerprint(
|
||||||
|
source_path: Path,
|
||||||
|
source_text: str,
|
||||||
|
schema_field: str,
|
||||||
|
) -> str:
|
||||||
|
"""Fingerprint only the owner's field-related contract fragments."""
|
||||||
|
if source_path.suffix.casefold() == ".json":
|
||||||
|
try:
|
||||||
|
payload = json.loads(source_text)
|
||||||
|
except json.JSONDecodeError as exc:
|
||||||
|
raise AuditError(f"Invalid JSON schema owner {source_path}: {exc}") from exc
|
||||||
|
|
||||||
|
fragments = _schema_owner_fragments(payload, schema_field)
|
||||||
|
if not fragments:
|
||||||
|
raise AuditError(
|
||||||
|
f"Schema owner {source_path} has no fingerprintable contract "
|
||||||
|
f"for {schema_field}"
|
||||||
|
)
|
||||||
|
return _schema_fingerprint(fragments)
|
||||||
|
|
||||||
|
field_re = _schema_field_pattern(schema_field)
|
||||||
|
lines: list[str] = []
|
||||||
|
in_fence = False
|
||||||
|
for line in source_text.splitlines():
|
||||||
|
if _FENCE_RE.match(line):
|
||||||
|
in_fence = not in_fence
|
||||||
|
continue
|
||||||
|
if not in_fence and field_re.search(line):
|
||||||
|
lines.append(line.strip())
|
||||||
|
if not lines:
|
||||||
|
raise AuditError(
|
||||||
|
f"Schema owner {source_path} has no fingerprintable contract "
|
||||||
|
f"for {schema_field}"
|
||||||
|
)
|
||||||
|
return _schema_fingerprint(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def _has_schema_grammar_signal(line: str, schema_field: str) -> bool:
|
||||||
|
"""Detect field-local grammar text without treating unrelated key prose as syntax."""
|
||||||
|
heading = _SCHEMA_HEADING_RE.match(line)
|
||||||
|
if heading and heading.group(1) == schema_field:
|
||||||
|
return True
|
||||||
|
|
||||||
|
field_re = _schema_field_pattern(schema_field)
|
||||||
|
for match in field_re.finditer(line):
|
||||||
|
before = line[max(0, match.start() - 160) : match.start()]
|
||||||
|
after = line[match.end() : match.end() + 240]
|
||||||
|
context = f"{before} {schema_field} {after}"
|
||||||
|
if re.match(r'''\s*[`*'\"]*\s*[:=]''', after):
|
||||||
|
return True
|
||||||
|
if re.search(
|
||||||
|
r"\b(?:"
|
||||||
|
r"grammars?|syntaxes?|formats?|schemas?|key formats?|"
|
||||||
|
r"allowed values?|one of|uses? one|accepts? only|followed by"
|
||||||
|
r")\b",
|
||||||
|
context,
|
||||||
|
re.I,
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
if re.search(r"\bas\s+`?<[^>]+>", context, re.I):
|
||||||
|
return True
|
||||||
|
if re.search(r"(?:P<NN>|<[^>\n]+>)\s*:", context):
|
||||||
|
return True
|
||||||
|
if re.search(
|
||||||
|
r"\b(?:writes?|written|records?|recorded|declares?|declared|"
|
||||||
|
r"projects?|projected|assigns?|assigned|emits?|emitted|authors?|"
|
||||||
|
r"authored)\b.{0,140}$",
|
||||||
|
before,
|
||||||
|
re.I,
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
if re.search(
|
||||||
|
r"^.{0,140}\b(?:is|are|must be|may be)?\s*(?:written|recorded|"
|
||||||
|
r"declared|projected|assigned|emitted|authored)\b",
|
||||||
|
after,
|
||||||
|
re.I,
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _schema_projection(
|
||||||
|
schema_field: str,
|
||||||
|
path: str,
|
||||||
|
sites: list[dict[str, Any]],
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
fingerprint = _schema_fingerprint(
|
||||||
|
{
|
||||||
|
"field": schema_field,
|
||||||
|
"path": path,
|
||||||
|
"lines": [site["text"] for site in sites],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
"path": path,
|
||||||
|
"fingerprint": fingerprint,
|
||||||
|
"definition_candidates": [
|
||||||
|
{
|
||||||
|
"line": site["line"],
|
||||||
|
"excerpt": site["text"].strip()[:240],
|
||||||
|
}
|
||||||
|
for site in sites
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def audit_schema_grammars(
|
def audit_schema_grammars(
|
||||||
root: Path,
|
root: Path,
|
||||||
configs: list[dict[str, Any]],
|
configs: list[dict[str, Any]],
|
||||||
documents: list[Document],
|
documents: list[Document],
|
||||||
|
manifest_label: str,
|
||||||
) -> tuple[list[dict[str, Any]], list[Finding]]:
|
) -> tuple[list[dict[str, Any]], list[Finding]]:
|
||||||
"""Surface fields with grammar-like definitions in multiple non-owner files."""
|
"""Surface open grammar projections and validate accepted projections."""
|
||||||
findings: list[Finding] = []
|
findings: list[Finding] = []
|
||||||
results: list[dict[str, Any]] = []
|
results: list[dict[str, Any]] = []
|
||||||
document_map = {document.path: document for document in documents}
|
document_map = {document.path: document for document in documents}
|
||||||
@@ -1414,6 +1670,10 @@ def audit_schema_grammars(
|
|||||||
else:
|
else:
|
||||||
raise AuditError("schema_grammars fields must be a list when present")
|
raise AuditError("schema_grammars fields must be a list when present")
|
||||||
scan_patterns = config.get("scan", ["skills/ppt-master/**/*.md"])
|
scan_patterns = config.get("scan", ["skills/ppt-master/**/*.md"])
|
||||||
|
accepted_by_field = {
|
||||||
|
str(entry["field"]): entry for entry in config.get("accepted", [])
|
||||||
|
}
|
||||||
|
processed_accepted_fields: set[str] = set()
|
||||||
|
|
||||||
for schema_field in fields:
|
for schema_field in fields:
|
||||||
owner_defines_field = any(
|
owner_defines_field = any(
|
||||||
@@ -1428,7 +1688,12 @@ def audit_schema_grammars(
|
|||||||
raise AuditError(
|
raise AuditError(
|
||||||
f"Schema owner {source} does not define configured field {schema_field}"
|
f"Schema owner {source} does not define configured field {schema_field}"
|
||||||
)
|
)
|
||||||
sites: list[dict[str, Any]] = []
|
owner_fingerprint = _schema_owner_fingerprint(
|
||||||
|
root / source,
|
||||||
|
source_text,
|
||||||
|
schema_field,
|
||||||
|
)
|
||||||
|
sites_by_path: dict[str, list[dict[str, Any]]] = defaultdict(list)
|
||||||
field_re = re.compile(rf"(?<![A-Za-z0-9_]){re.escape(schema_field)}(?![A-Za-z0-9_])")
|
field_re = re.compile(rf"(?<![A-Za-z0-9_]){re.escape(schema_field)}(?![A-Za-z0-9_])")
|
||||||
for path, document in sorted(document_map.items()):
|
for path, document in sorted(document_map.items()):
|
||||||
if path == source or not _matches_any(path, scan_patterns):
|
if path == source or not _matches_any(path, scan_patterns):
|
||||||
@@ -1442,34 +1707,166 @@ def audit_schema_grammars(
|
|||||||
continue
|
continue
|
||||||
if not _has_schema_grammar_signal(line, schema_field):
|
if not _has_schema_grammar_signal(line, schema_field):
|
||||||
continue
|
continue
|
||||||
sites.append(
|
sites_by_path[path].append(
|
||||||
{
|
{
|
||||||
"path": path,
|
|
||||||
"line": line_number,
|
"line": line_number,
|
||||||
"excerpt": line.strip()[:240],
|
"text": line,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
unique_files = sorted({site["path"] for site in sites})
|
projections = {
|
||||||
if not unique_files:
|
path: _schema_projection(schema_field, path, sites)
|
||||||
continue
|
for path, sites in sorted(sites_by_path.items())
|
||||||
results.append(
|
}
|
||||||
|
accepted_config = accepted_by_field.get(schema_field)
|
||||||
|
if accepted_config is not None:
|
||||||
|
processed_accepted_fields.add(schema_field)
|
||||||
|
owner_matches = bool(
|
||||||
|
accepted_config is not None
|
||||||
|
and accepted_config["owner_fingerprint"] == owner_fingerprint
|
||||||
|
)
|
||||||
|
if accepted_config is not None and not owner_matches:
|
||||||
|
findings.append(
|
||||||
|
Finding(
|
||||||
|
severity="error",
|
||||||
|
code="SCHEMA_ACCEPTED_STALE",
|
||||||
|
message=(
|
||||||
|
f"schema_grammars accepted owner fingerprint for "
|
||||||
|
f"{schema_field} is stale; expected "
|
||||||
|
f"{accepted_config['owner_fingerprint']}, current "
|
||||||
|
f"{owner_fingerprint}"
|
||||||
|
),
|
||||||
|
path=manifest_label,
|
||||||
|
related=[source],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
configured_projections = {
|
||||||
|
projection["path"]: projection
|
||||||
|
for projection in (
|
||||||
|
accepted_config.get("projections", [])
|
||||||
|
if accepted_config is not None
|
||||||
|
else []
|
||||||
|
)
|
||||||
|
}
|
||||||
|
open_projections: list[dict[str, Any]] = []
|
||||||
|
accepted_projections: list[dict[str, Any]] = []
|
||||||
|
stale_projections: list[dict[str, Any]] = []
|
||||||
|
for path, projection in projections.items():
|
||||||
|
configured = configured_projections.get(path)
|
||||||
|
projection_matches = bool(
|
||||||
|
configured is not None
|
||||||
|
and configured["fingerprint"] == projection["fingerprint"]
|
||||||
|
)
|
||||||
|
if owner_matches and projection_matches:
|
||||||
|
accepted_projections.append(
|
||||||
{
|
{
|
||||||
"field": schema_field,
|
**projection,
|
||||||
"owner": source,
|
"role": configured["role"],
|
||||||
"definition_candidates": sites,
|
"reason": configured["reason"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if configured is None:
|
||||||
|
open_projections.append(projection)
|
||||||
|
first_line = projection["definition_candidates"][0]["line"]
|
||||||
findings.append(
|
findings.append(
|
||||||
Finding(
|
Finding(
|
||||||
severity="warning",
|
severity="warning",
|
||||||
code="SCHEMA_MULTIDEF_CANDIDATE",
|
code="SCHEMA_MULTIDEF_CANDIDATE",
|
||||||
message=(
|
message=(
|
||||||
f"owns {schema_field}, but {len(unique_files)} non-owner "
|
f"{source} owns {schema_field}, but this file carries "
|
||||||
"files carry grammar-like text for it"
|
"an unaccepted grammar-like projection"
|
||||||
),
|
),
|
||||||
path=source,
|
path=path,
|
||||||
related=unique_files,
|
line=first_line,
|
||||||
|
related=[source],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
stale_projections.append(
|
||||||
|
{
|
||||||
|
**projection,
|
||||||
|
"role": configured["role"],
|
||||||
|
"reason": configured["reason"],
|
||||||
|
"expected_fingerprint": configured["fingerprint"],
|
||||||
|
"stale_reason": (
|
||||||
|
"owner_fingerprint" if not owner_matches else "fingerprint"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if owner_matches and not projection_matches:
|
||||||
|
findings.append(
|
||||||
|
Finding(
|
||||||
|
severity="error",
|
||||||
|
code="SCHEMA_ACCEPTED_STALE",
|
||||||
|
message=(
|
||||||
|
f"schema_grammars accepted projection fingerprint "
|
||||||
|
f"for {schema_field} at {path} is stale; expected "
|
||||||
|
f"{configured['fingerprint']}, current "
|
||||||
|
f"{projection['fingerprint']}"
|
||||||
|
),
|
||||||
|
path=manifest_label,
|
||||||
|
related=[source, path],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if owner_matches:
|
||||||
|
for path, configured in configured_projections.items():
|
||||||
|
if path in projections:
|
||||||
|
continue
|
||||||
|
stale_projections.append(
|
||||||
|
{
|
||||||
|
"path": path,
|
||||||
|
"fingerprint": None,
|
||||||
|
"definition_candidates": [],
|
||||||
|
"role": configured["role"],
|
||||||
|
"reason": configured["reason"],
|
||||||
|
"expected_fingerprint": configured["fingerprint"],
|
||||||
|
"stale_reason": "missing",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
findings.append(
|
||||||
|
Finding(
|
||||||
|
severity="error",
|
||||||
|
code="SCHEMA_ACCEPTED_STALE",
|
||||||
|
message=(
|
||||||
|
f"schema_grammars accepted projection for "
|
||||||
|
f"{schema_field} at {path} no longer exists"
|
||||||
|
),
|
||||||
|
path=manifest_label,
|
||||||
|
related=[source, path],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not projections and accepted_config is None:
|
||||||
|
continue
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"field": schema_field,
|
||||||
|
"owner": source,
|
||||||
|
"owner_fingerprint": owner_fingerprint,
|
||||||
|
"open": open_projections,
|
||||||
|
"accepted": accepted_projections,
|
||||||
|
"stale": stale_projections,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
for schema_field in sorted(
|
||||||
|
set(accepted_by_field) - processed_accepted_fields
|
||||||
|
):
|
||||||
|
findings.append(
|
||||||
|
Finding(
|
||||||
|
severity="error",
|
||||||
|
code="SCHEMA_ACCEPTED_STALE",
|
||||||
|
message=(
|
||||||
|
f"schema_grammars accepted field {schema_field} is no "
|
||||||
|
"longer configured for this owner"
|
||||||
|
),
|
||||||
|
path=manifest_label,
|
||||||
|
related=[source],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
results.sort(key=lambda item: item["field"])
|
results.sort(key=lambda item: item["field"])
|
||||||
@@ -1603,14 +2000,6 @@ def run_audit(
|
|||||||
message=f"Found {exact_total} cross-file exact paragraph groups",
|
message=f"Found {exact_total} cross-file exact paragraph groups",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if near_total:
|
|
||||||
findings.append(
|
|
||||||
Finding(
|
|
||||||
severity="warning",
|
|
||||||
code="DUPLICATE_NEAR_CANDIDATES",
|
|
||||||
message=f"Found {near_total} cross-file near-duplicate paragraph pairs",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
references, reference_findings = extract_references(root, documents)
|
references, reference_findings = extract_references(root, documents)
|
||||||
findings.extend(reference_findings)
|
findings.extend(reference_findings)
|
||||||
@@ -1654,6 +2043,7 @@ def run_audit(
|
|||||||
root,
|
root,
|
||||||
manifest.get("schema_grammars", []),
|
manifest.get("schema_grammars", []),
|
||||||
documents,
|
documents,
|
||||||
|
manifest_label,
|
||||||
)
|
)
|
||||||
findings.extend(schema_findings)
|
findings.extend(schema_findings)
|
||||||
|
|
||||||
@@ -1742,6 +2132,11 @@ def render_text(report: dict[str, Any]) -> str:
|
|||||||
|
|
||||||
references = report["references"]
|
references = report["references"]
|
||||||
duplicates = report["duplicates"]
|
duplicates = report["duplicates"]
|
||||||
|
schema_open = sum(len(item["open"]) for item in report["schema_grammars"])
|
||||||
|
schema_accepted = sum(
|
||||||
|
len(item["accepted"]) for item in report["schema_grammars"]
|
||||||
|
)
|
||||||
|
schema_stale = sum(len(item["stale"]) for item in report["schema_grammars"])
|
||||||
near_summary = (
|
near_summary = (
|
||||||
(
|
(
|
||||||
f"{duplicates['near_total']} near pair(s) + "
|
f"{duplicates['near_total']} near pair(s) + "
|
||||||
@@ -1767,7 +2162,10 @@ def render_text(report: dict[str, Any]) -> str:
|
|||||||
f" authority candidates: {len(references['authority_candidates'])} edge(s), "
|
f" authority candidates: {len(references['authority_candidates'])} edge(s), "
|
||||||
f"{len(references['authority_candidate_cycles'])} candidate cycle(s)"
|
f"{len(references['authority_candidate_cycles'])} candidate cycle(s)"
|
||||||
),
|
),
|
||||||
f" schema multi-definition candidates: {len(report['schema_grammars'])}",
|
(
|
||||||
|
f" schema grammar projections: {schema_open} open + "
|
||||||
|
f"{schema_accepted} accepted + {schema_stale} stale"
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
if duplicates["exact"]:
|
if duplicates["exact"]:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"skills/ppt-master/references/executor-structured.md": 5500,
|
"skills/ppt-master/references/executor-structured.md": 5500,
|
||||||
"skills/ppt-master/references/executor-chart.md": 3500,
|
"skills/ppt-master/references/executor-chart.md": 3500,
|
||||||
"skills/ppt-master/references/executor-visualization.md": 1250,
|
"skills/ppt-master/references/executor-visualization.md": 1250,
|
||||||
"skills/ppt-master/references/executor-structure.md": 1250,
|
"skills/ppt-master/references/executor-structure.md": 1500,
|
||||||
"skills/ppt-master/references/executor-table.md": 1000,
|
"skills/ppt-master/references/executor-table.md": 1000,
|
||||||
"skills/ppt-master/references/executor-image.md": 2000,
|
"skills/ppt-master/references/executor-image.md": 2000,
|
||||||
"skills/ppt-master/references/executor-web-image.md": 750,
|
"skills/ppt-master/references/executor-web-image.md": 750,
|
||||||
@@ -154,7 +154,7 @@
|
|||||||
"max_tokens": 13000
|
"max_tokens": 13000
|
||||||
},
|
},
|
||||||
"route.generate.planning": {
|
"route.generate.planning": {
|
||||||
"description": "Generate-PPTX planning through Strategist, including reference-first whole-document authoring and representative multi-source custom mode/style synthesis; schemas and optional scaffolds are tool-consumed.",
|
"description": "Generate-PPTX planning through Strategist, including reference-first whole-document authoring, the three compact decision indexes, and a conservative audit envelope for only the exact custom bases selected after those indexes; schemas and optional scaffolds are tool-consumed.",
|
||||||
"scope": "cumulative",
|
"scope": "cumulative",
|
||||||
"include": [
|
"include": [
|
||||||
"bootstrap.routing"
|
"bootstrap.routing"
|
||||||
@@ -163,10 +163,12 @@
|
|||||||
"skills/ppt-master/workflows/generate-pptx.md",
|
"skills/ppt-master/workflows/generate-pptx.md",
|
||||||
"skills/ppt-master/references/artifact-ownership.md",
|
"skills/ppt-master/references/artifact-ownership.md",
|
||||||
"skills/ppt-master/references/strategist.md",
|
"skills/ppt-master/references/strategist.md",
|
||||||
|
"skills/ppt-master/references/strategist-image.md",
|
||||||
"skills/ppt-master/templates/design_spec_reference.md",
|
"skills/ppt-master/templates/design_spec_reference.md",
|
||||||
"skills/ppt-master/templates/spec_lock_reference.md",
|
"skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
"skills/ppt-master/references/modes/_index.md",
|
"skills/ppt-master/references/modes/_index.md",
|
||||||
"skills/ppt-master/references/visual-styles/_index.md",
|
"skills/ppt-master/references/visual-styles/_index.md",
|
||||||
|
"skills/ppt-master/references/image-renderings/_index.md",
|
||||||
"skills/ppt-master/scripts/docs/confirm_ui.md",
|
"skills/ppt-master/scripts/docs/confirm_ui.md",
|
||||||
"skills/ppt-master/templates/icons/README.md",
|
"skills/ppt-master/templates/icons/README.md",
|
||||||
{
|
{
|
||||||
@@ -174,8 +176,8 @@
|
|||||||
"exclude": [
|
"exclude": [
|
||||||
"*/_index.md"
|
"*/_index.md"
|
||||||
],
|
],
|
||||||
"select": 3,
|
"select": 5,
|
||||||
"load_event": "strategist-custom",
|
"load_event": "strategist-selected-mode-bases",
|
||||||
"registry": "modes"
|
"registry": "modes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -183,15 +185,24 @@
|
|||||||
"exclude": [
|
"exclude": [
|
||||||
"*/_index.md"
|
"*/_index.md"
|
||||||
],
|
],
|
||||||
"select": 3,
|
"select": 18,
|
||||||
"load_event": "strategist-custom",
|
"load_event": "strategist-selected-visual-style-bases",
|
||||||
"registry": "visual-styles"
|
"registry": "visual-styles"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"glob": "skills/ppt-master/references/image-renderings/*.md",
|
||||||
|
"exclude": [
|
||||||
|
"*/_index.md"
|
||||||
|
],
|
||||||
|
"select": 20,
|
||||||
|
"load_event": "strategist-selected-image-rendering-bases",
|
||||||
|
"registry": "image-renderings"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"max_tokens": 70000
|
"max_tokens": 110000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate": {
|
"route.generate.quick-generate": {
|
||||||
"description": "Self-contained one-pass Generate profile with source intake, active-context mode/style selection, conditional resource preparation, and complete flat SVG visual-construction authorities.",
|
"description": "Self-contained one-pass Generate profile with source intake, the three compact decision indexes, a conservative audit envelope for only the resolved preset or exact custom bases, conditional resource preparation, and complete flat SVG visual-construction authorities.",
|
||||||
"scope": "cumulative",
|
"scope": "cumulative",
|
||||||
"include": [
|
"include": [
|
||||||
"bootstrap.routing"
|
"bootstrap.routing"
|
||||||
@@ -206,13 +217,14 @@
|
|||||||
"skills/ppt-master/references/executor-structure.md",
|
"skills/ppt-master/references/executor-structure.md",
|
||||||
"skills/ppt-master/references/modes/_index.md",
|
"skills/ppt-master/references/modes/_index.md",
|
||||||
"skills/ppt-master/references/visual-styles/_index.md",
|
"skills/ppt-master/references/visual-styles/_index.md",
|
||||||
|
"skills/ppt-master/references/image-renderings/_index.md",
|
||||||
{
|
{
|
||||||
"glob": "skills/ppt-master/references/modes/*.md",
|
"glob": "skills/ppt-master/references/modes/*.md",
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"*/_index.md"
|
"*/_index.md"
|
||||||
],
|
],
|
||||||
"select": 3,
|
"select": 5,
|
||||||
"load_event": "quick-mode",
|
"load_event": "quick-selected-mode-bases",
|
||||||
"registry": "modes"
|
"registry": "modes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -220,12 +232,21 @@
|
|||||||
"exclude": [
|
"exclude": [
|
||||||
"*/_index.md"
|
"*/_index.md"
|
||||||
],
|
],
|
||||||
"select": 3,
|
"select": 18,
|
||||||
"load_event": "quick-visual-style",
|
"load_event": "quick-selected-visual-style-bases",
|
||||||
"registry": "visual-styles"
|
"registry": "visual-styles"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"glob": "skills/ppt-master/references/image-renderings/*.md",
|
||||||
|
"exclude": [
|
||||||
|
"*/_index.md"
|
||||||
|
],
|
||||||
|
"select": 20,
|
||||||
|
"load_event": "quick-selected-image-rendering-bases",
|
||||||
|
"registry": "image-renderings"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"max_tokens": 80000
|
"max_tokens": 92000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate.beautify": {
|
"route.generate.quick-generate.beautify": {
|
||||||
"description": "Quick Generate with the shared strict 1:1 Beautify profile.",
|
"description": "Quick Generate with the shared strict 1:1 Beautify profile.",
|
||||||
@@ -235,7 +256,7 @@
|
|||||||
"profile.generate.beautify-pptx"
|
"profile.generate.beautify-pptx"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 70000
|
"max_tokens": 100000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate.template-fusion": {
|
"route.generate.quick-generate.template-fusion": {
|
||||||
"description": "Quick Generate with the maximum Brand, Style, Layout, and Deck exact-root fusion loaded for flat authoring.",
|
"description": "Quick Generate with the maximum Brand, Style, Layout, and Deck exact-root fusion loaded for flat authoring.",
|
||||||
@@ -245,7 +266,7 @@
|
|||||||
"stage.generate.template.fusion-brand-style-layout-deck"
|
"stage.generate.template.fusion-brand-style-layout-deck"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 88000
|
"max_tokens": 115000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate.topic-research": {
|
"route.generate.quick-generate.topic-research": {
|
||||||
"description": "Quick Generate with gap-targeted factual research before direct resource preparation and SVG authoring.",
|
"description": "Quick Generate with gap-targeted factual research before direct resource preparation and SVG authoring.",
|
||||||
@@ -255,7 +276,7 @@
|
|||||||
"stage.generate.topic-research"
|
"stage.generate.topic-research"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 74000
|
"max_tokens": 94000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate.icon": {
|
"route.generate.quick-generate.icon": {
|
||||||
"description": "Quick Generate with project-local bundled icon selection and synchronization.",
|
"description": "Quick Generate with project-local bundled icon selection and synchronization.",
|
||||||
@@ -266,7 +287,7 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"skills/ppt-master/templates/icons/README.md"
|
"skills/ppt-master/templates/icons/README.md"
|
||||||
],
|
],
|
||||||
"max_tokens": 74000
|
"max_tokens": 94000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate.in-hand-image": {
|
"route.generate.quick-generate.in-hand-image": {
|
||||||
"description": "Quick Generate with supplied, extracted, or placeholder image resources prepared before SVG authoring.",
|
"description": "Quick Generate with supplied, extracted, or placeholder image resources prepared before SVG authoring.",
|
||||||
@@ -276,7 +297,7 @@
|
|||||||
"stage.generate.executor.image"
|
"stage.generate.executor.image"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 84000
|
"max_tokens": 110000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate.formula": {
|
"route.generate.quick-generate.formula": {
|
||||||
"description": "Quick Generate with manifest-driven formula rendering and formula-image realization.",
|
"description": "Quick Generate with manifest-driven formula rendering and formula-image realization.",
|
||||||
@@ -288,7 +309,7 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"skills/ppt-master/scripts/docs/image.md"
|
"skills/ppt-master/scripts/docs/image.md"
|
||||||
],
|
],
|
||||||
"max_tokens": 87000
|
"max_tokens": 110000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate.ai-two-types": {
|
"route.generate.quick-generate.ai-two-types": {
|
||||||
"description": "Quick Generate with AI resource preparation, representative rendering inputs, and two local image types.",
|
"description": "Quick Generate with AI resource preparation, representative rendering inputs, and two local image types.",
|
||||||
@@ -299,7 +320,7 @@
|
|||||||
"stage.generate.executor.image"
|
"stage.generate.executor.image"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 110000
|
"max_tokens": 135000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate.web-image": {
|
"route.generate.quick-generate.web-image": {
|
||||||
"description": "Quick Generate with web resource preparation, provenance, attribution, and image execution.",
|
"description": "Quick Generate with web resource preparation, provenance, attribution, and image execution.",
|
||||||
@@ -310,7 +331,7 @@
|
|||||||
"stage.generate.executor.web-image"
|
"stage.generate.executor.web-image"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 92000
|
"max_tokens": 115000
|
||||||
},
|
},
|
||||||
"route.generate.quick-generate.visualization": {
|
"route.generate.quick-generate.visualization": {
|
||||||
"description": "Quick Generate with bounded Chart/Table recall, their data-object branches, optional native-data metadata, and chart-coordinate verification before the final checker; the fixed Quick context already carries Shape Composition Grammar.",
|
"description": "Quick Generate with bounded Chart/Table recall, their data-object branches, optional native-data metadata, and chart-coordinate verification before the final checker; the fixed Quick context already carries Shape Composition Grammar.",
|
||||||
@@ -336,7 +357,7 @@
|
|||||||
"stage.generate.strategist.image"
|
"stage.generate.strategist.image"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 81000
|
"max_tokens": 115000
|
||||||
},
|
},
|
||||||
"route.generate.planning-formula": {
|
"route.generate.planning-formula": {
|
||||||
"description": "Formula-only planning context, including the shared image/formula layout math and vocabulary.",
|
"description": "Formula-only planning context, including the shared image/formula layout math and vocabulary.",
|
||||||
@@ -346,27 +367,16 @@
|
|||||||
"stage.generate.strategist.image"
|
"stage.generate.strategist.image"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 81000
|
"max_tokens": 115000
|
||||||
},
|
},
|
||||||
"route.generate.planning-ai": {
|
"route.generate.planning-ai": {
|
||||||
"description": "Generate-PPTX planning when AI image direction is available, including representative multi-source custom rendering synthesis.",
|
"description": "Generate-PPTX planning after AI imagery is confirmed, adding image-layout and resource-planning authorities to the rendering index and already-selected rendering bases.",
|
||||||
"scope": "cumulative",
|
"scope": "cumulative",
|
||||||
"include": [
|
"include": [
|
||||||
"route.generate.planning-image"
|
"route.generate.planning-image"
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [],
|
||||||
"skills/ppt-master/references/image-renderings/_index.md",
|
"max_tokens": 115000
|
||||||
{
|
|
||||||
"glob": "skills/ppt-master/references/image-renderings/*.md",
|
|
||||||
"exclude": [
|
|
||||||
"*/_index.md"
|
|
||||||
],
|
|
||||||
"select": 3,
|
|
||||||
"load_event": "strategist-image-custom",
|
|
||||||
"registry": "image-renderings"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"max_tokens": 86000
|
|
||||||
},
|
},
|
||||||
"stage.generate.apply-template-workspace": {
|
"stage.generate.apply-template-workspace": {
|
||||||
"description": "Post-Stage-1 Default or Quick exact-root workspace validation, installation, and fusion framework.",
|
"description": "Post-Stage-1 Default or Quick exact-root workspace validation, installation, and fusion framework.",
|
||||||
@@ -500,10 +510,10 @@
|
|||||||
"stage.generate.executor.notes"
|
"stage.generate.executor.notes"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 120000
|
"max_tokens": 165000
|
||||||
},
|
},
|
||||||
"route.generate.flat-ai-two-types": {
|
"route.generate.flat-ai-two-types": {
|
||||||
"description": "Generate-PPTX context with AI images, representative multi-source custom rendering, and two local types.",
|
"description": "Generate-PPTX context with AI images, the selected preset or exact custom rendering bases, and two local types.",
|
||||||
"scope": "cumulative",
|
"scope": "cumulative",
|
||||||
"include": [
|
"include": [
|
||||||
"route.generate.planning-ai",
|
"route.generate.planning-ai",
|
||||||
@@ -513,7 +523,7 @@
|
|||||||
"stage.generate.image.ai-two-types"
|
"stage.generate.image.ai-two-types"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 165000
|
"max_tokens": 205000
|
||||||
},
|
},
|
||||||
"route.generate.flat-in-hand-image": {
|
"route.generate.flat-in-hand-image": {
|
||||||
"description": "Generate-PPTX context with provided, placeholder, or formula images and no acquisition role.",
|
"description": "Generate-PPTX context with provided, placeholder, or formula images and no acquisition role.",
|
||||||
@@ -525,7 +535,7 @@
|
|||||||
"stage.generate.executor.notes"
|
"stage.generate.executor.notes"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 135000
|
"max_tokens": 180000
|
||||||
},
|
},
|
||||||
"route.generate.flat-web-image": {
|
"route.generate.flat-web-image": {
|
||||||
"description": "Generate-PPTX context with web image acquisition.",
|
"description": "Generate-PPTX context with web image acquisition.",
|
||||||
@@ -538,7 +548,7 @@
|
|||||||
"stage.generate.image.web"
|
"stage.generate.image.web"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 145000
|
"max_tokens": 190000
|
||||||
},
|
},
|
||||||
"route.enhance-native-pptx.audio": {
|
"route.enhance-native-pptx.audio": {
|
||||||
"description": "Enhance Native PPTX with the shared narration-audio stage.",
|
"description": "Enhance Native PPTX with the shared narration-audio stage.",
|
||||||
@@ -558,7 +568,7 @@
|
|||||||
"profile.generate.beautify-pptx"
|
"profile.generate.beautify-pptx"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 130000
|
"max_tokens": 175000
|
||||||
},
|
},
|
||||||
"route.generate.flat-no-image-visualization": {
|
"route.generate.flat-no-image-visualization": {
|
||||||
"description": "Default flat Generate-PPTX path with visualization-reference consumption, all three information-model branches, optional native-data replacement, and chart verification.",
|
"description": "Default flat Generate-PPTX path with visualization-reference consumption, all three information-model branches, optional native-data replacement, and chart verification.",
|
||||||
@@ -573,7 +583,7 @@
|
|||||||
"stage.generate.verify-charts"
|
"stage.generate.verify-charts"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 145000
|
"max_tokens": 185000
|
||||||
},
|
},
|
||||||
"route.generate.brand-flat-no-image": {
|
"route.generate.brand-flat-no-image": {
|
||||||
"description": "Brand-preset flat Generate-PPTX path without image acquisition.",
|
"description": "Brand-preset flat Generate-PPTX path without image acquisition.",
|
||||||
@@ -585,7 +595,7 @@
|
|||||||
"stage.generate.template.brand"
|
"stage.generate.template.brand"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 130000
|
"max_tokens": 180000
|
||||||
},
|
},
|
||||||
"route.generate.style-flat-no-image": {
|
"route.generate.style-flat-no-image": {
|
||||||
"description": "Style-workspace flat Generate-PPTX path without image acquisition.",
|
"description": "Style-workspace flat Generate-PPTX path without image acquisition.",
|
||||||
@@ -597,7 +607,7 @@
|
|||||||
"stage.generate.template.style"
|
"stage.generate.template.style"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 130000
|
"max_tokens": 180000
|
||||||
},
|
},
|
||||||
"route.generate.deck-structured-no-image": {
|
"route.generate.deck-structured-no-image": {
|
||||||
"description": "Deck-preset structured Generate-PPTX path without image acquisition.",
|
"description": "Deck-preset structured Generate-PPTX path without image acquisition.",
|
||||||
@@ -609,7 +619,7 @@
|
|||||||
"stage.generate.template.deck"
|
"stage.generate.template.deck"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 140000
|
"max_tokens": 190000
|
||||||
},
|
},
|
||||||
"route.generate.layout-structured-no-image": {
|
"route.generate.layout-structured-no-image": {
|
||||||
"description": "Layout-preset structured Generate-PPTX path without image acquisition.",
|
"description": "Layout-preset structured Generate-PPTX path without image acquisition.",
|
||||||
@@ -621,7 +631,7 @@
|
|||||||
"stage.generate.template.layout"
|
"stage.generate.template.layout"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 140000
|
"max_tokens": 190000
|
||||||
},
|
},
|
||||||
"route.generate.topic-only-flat-no-image": {
|
"route.generate.topic-only-flat-no-image": {
|
||||||
"description": "Topic research followed by the default flat no-image Generate-PPTX path.",
|
"description": "Topic research followed by the default flat no-image Generate-PPTX path.",
|
||||||
@@ -631,10 +641,10 @@
|
|||||||
"route.generate.flat-no-image"
|
"route.generate.flat-no-image"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 120000
|
"max_tokens": 170000
|
||||||
},
|
},
|
||||||
"stage.generate.executor.flat": {
|
"stage.generate.executor.flat": {
|
||||||
"description": "Incremental flat Executor core with complete visual-construction authorities and representative multi-source custom mode/style execution.",
|
"description": "Incremental flat Executor core with complete visual-construction authorities, the compact mode/style indexes, and a conservative audit envelope for only the locked preset or exact custom references.",
|
||||||
"scope": "incremental",
|
"scope": "incremental",
|
||||||
"files": [
|
"files": [
|
||||||
"skills/ppt-master/references/executor-base.md",
|
"skills/ppt-master/references/executor-base.md",
|
||||||
@@ -642,13 +652,15 @@
|
|||||||
"skills/ppt-master/references/svg-effects.md",
|
"skills/ppt-master/references/svg-effects.md",
|
||||||
"skills/ppt-master/references/native-shape-authoring.md",
|
"skills/ppt-master/references/native-shape-authoring.md",
|
||||||
"skills/ppt-master/references/semantic-svg.md",
|
"skills/ppt-master/references/semantic-svg.md",
|
||||||
|
"skills/ppt-master/references/modes/_index.md",
|
||||||
|
"skills/ppt-master/references/visual-styles/_index.md",
|
||||||
{
|
{
|
||||||
"glob": "skills/ppt-master/references/modes/*.md",
|
"glob": "skills/ppt-master/references/modes/*.md",
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"*/_index.md"
|
"*/_index.md"
|
||||||
],
|
],
|
||||||
"select": 3,
|
"select": 5,
|
||||||
"load_event": "executor",
|
"load_event": "executor-selected-mode-bases",
|
||||||
"registry": "modes",
|
"registry": "modes",
|
||||||
"allow_repeat": true
|
"allow_repeat": true
|
||||||
},
|
},
|
||||||
@@ -657,13 +669,13 @@
|
|||||||
"exclude": [
|
"exclude": [
|
||||||
"*/_index.md"
|
"*/_index.md"
|
||||||
],
|
],
|
||||||
"select": 3,
|
"select": 18,
|
||||||
"load_event": "executor",
|
"load_event": "executor-selected-visual-style-bases",
|
||||||
"registry": "visual-styles",
|
"registry": "visual-styles",
|
||||||
"allow_repeat": true
|
"allow_repeat": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"max_tokens": 48000
|
"max_tokens": 64000
|
||||||
},
|
},
|
||||||
"stage.generate.executor.structured": {
|
"stage.generate.executor.structured": {
|
||||||
"description": "Structured template execution layered on the flat/shared core.",
|
"description": "Structured template execution layered on the flat/shared core.",
|
||||||
@@ -675,10 +687,10 @@
|
|||||||
"skills/ppt-master/references/executor-structured.md",
|
"skills/ppt-master/references/executor-structured.md",
|
||||||
"skills/ppt-master/references/pptx-structure-interface.md"
|
"skills/ppt-master/references/pptx-structure-interface.md"
|
||||||
],
|
],
|
||||||
"max_tokens": 58000
|
"max_tokens": 74000
|
||||||
},
|
},
|
||||||
"stage.generate.image.ai-two-types": {
|
"stage.generate.image.ai-two-types": {
|
||||||
"description": "Incremental AI-image role with representative multi-source custom rendering and two selected local types.",
|
"description": "Incremental AI-image role with the selected preset or exact custom rendering bases and two selected local types.",
|
||||||
"scope": "incremental",
|
"scope": "incremental",
|
||||||
"files": [
|
"files": [
|
||||||
"skills/ppt-master/references/image-base.md",
|
"skills/ppt-master/references/image-base.md",
|
||||||
@@ -733,7 +745,7 @@
|
|||||||
"skills/ppt-master/workflows/stages/resume-execute.md",
|
"skills/ppt-master/workflows/stages/resume-execute.md",
|
||||||
"skills/ppt-master/references/artifact-ownership.md"
|
"skills/ppt-master/references/artifact-ownership.md"
|
||||||
],
|
],
|
||||||
"max_tokens": 77000
|
"max_tokens": 97000
|
||||||
},
|
},
|
||||||
"stage.generate.resume-execute-image": {
|
"stage.generate.resume-execute-image": {
|
||||||
"description": "Fresh-session resume when the locked resource plan contains image rows.",
|
"description": "Fresh-session resume when the locked resource plan contains image rows.",
|
||||||
@@ -743,7 +755,7 @@
|
|||||||
"stage.generate.executor.image"
|
"stage.generate.executor.image"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 89000
|
"max_tokens": 115000
|
||||||
},
|
},
|
||||||
"stage.generate.topic-research": {
|
"stage.generate.topic-research": {
|
||||||
"description": "Gap-targeted factual intake stage.",
|
"description": "Gap-targeted factual intake stage.",
|
||||||
@@ -880,7 +892,7 @@
|
|||||||
"stage.generate.strategist.template"
|
"stage.generate.strategist.template"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 73000
|
"max_tokens": 110000
|
||||||
},
|
},
|
||||||
"route.generate.planning-template-ai": {
|
"route.generate.planning-template-ai": {
|
||||||
"description": "Explicit template workspace plus confirmed AI-image planning.",
|
"description": "Explicit template workspace plus confirmed AI-image planning.",
|
||||||
@@ -890,7 +902,7 @@
|
|||||||
"route.generate.planning-ai"
|
"route.generate.planning-ai"
|
||||||
],
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
"max_tokens": 88000
|
"max_tokens": 120000
|
||||||
},
|
},
|
||||||
"stage.generate.executor.chart": {
|
"stage.generate.executor.chart": {
|
||||||
"description": "Conditional value-driven chart execution rules.",
|
"description": "Conditional value-driven chart execution rules.",
|
||||||
@@ -914,7 +926,7 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"skills/ppt-master/references/executor-structure.md"
|
"skills/ppt-master/references/executor-structure.md"
|
||||||
],
|
],
|
||||||
"max_tokens": 1250
|
"max_tokens": 1500
|
||||||
},
|
},
|
||||||
"stage.generate.executor.table": {
|
"stage.generate.executor.table": {
|
||||||
"description": "Conditional semantic cell-grid construction rules.",
|
"description": "Conditional semantic cell-grid construction rules.",
|
||||||
@@ -925,10 +937,9 @@
|
|||||||
"max_tokens": 1000
|
"max_tokens": 1000
|
||||||
},
|
},
|
||||||
"stage.generate.strategist.image": {
|
"stage.generate.strategist.image": {
|
||||||
"description": "Conditional Strategist image/formula policy with the always-read layout math and compact composition vocabulary.",
|
"description": "Conditional Strategist image/formula layout math and compact composition vocabulary; the rendering decision core is already in base planning.",
|
||||||
"scope": "incremental",
|
"scope": "incremental",
|
||||||
"files": [
|
"files": [
|
||||||
"skills/ppt-master/references/strategist-image.md",
|
|
||||||
"skills/ppt-master/references/image-layout-spec.md",
|
"skills/ppt-master/references/image-layout-spec.md",
|
||||||
"skills/ppt-master/references/image-layout-patterns.md"
|
"skills/ppt-master/references/image-layout-patterns.md"
|
||||||
],
|
],
|
||||||
@@ -1044,6 +1055,228 @@
|
|||||||
"skills/ppt-master/references/ai-image-comparison/type/_manifest.md"
|
"skills/ppt-master/references/ai-image-comparison/type/_manifest.md"
|
||||||
],
|
],
|
||||||
"reason": "Generated comparison-asset manifests share an identical header by construction."
|
"reason": "Generated comparison-asset manifests share an identical header by construction."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "890890f28896",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/bain/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/mckinsey/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Consulting brand presets keep the same no-bundled-logo trademark safeguard by design."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "83e5480404c3",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/alibaba/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/aws/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/huawei/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/microsoft/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/tencent/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/xiaomi/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Corporate brand presets share the same proprietary-font fallback contract by design."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "13dd086d3977",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/accenture/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/bain/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/deloitte/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/mckinsey/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/pwc/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Consulting brand presets share the same proprietary-font fallback contract by design."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "f2572d50249b",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/deloitte/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/pwc/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Sibling consulting presets share the same evidence-writing convention by design."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "141b0d6205da",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/accenture/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/bain/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/bcg/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/deloitte/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/jpmorgan/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/mckinsey/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/pwc/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Consulting brand presets share the same restrained icon convention by design."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "c5b068fe89b0",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/alibaba/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/huawei/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/ibm/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/microsoft/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/nvidia/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/tencent/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/xiaomi/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Corporate brand presets share the same consistent icon convention by design."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "da38ec6c641e",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/SPONSORS.md",
|
||||||
|
"skills/ppt-master/SPONSORS_CN.md"
|
||||||
|
],
|
||||||
|
"reason": "English and Chinese sponsor pages intentionally reuse the same sponsor badge markup."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "fcc902f6644a",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/SPONSORS.md",
|
||||||
|
"skills/ppt-master/SPONSORS_CN.md"
|
||||||
|
],
|
||||||
|
"reason": "English and Chinese sponsor pages intentionally reuse the same sponsor badge markup."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "092a8a1f88e9",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/SPONSORS.md",
|
||||||
|
"skills/ppt-master/SPONSORS_CN.md"
|
||||||
|
],
|
||||||
|
"reason": "English and Chinese sponsor pages intentionally reuse the same sponsor badge markup."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "6a432b0cc1df",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/decks/README.md",
|
||||||
|
"skills/ppt-master/templates/layouts/README.md"
|
||||||
|
],
|
||||||
|
"reason": "Sibling Deck and Layout docs keep the shared replication-mode explanation in lockstep."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "aa6e1929dd49",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/SPONSORS.md",
|
||||||
|
"skills/ppt-master/SPONSORS_CN.md"
|
||||||
|
],
|
||||||
|
"reason": "English and Chinese sponsor pages intentionally reuse the same sponsor badge markup."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "286b55cb84d7",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/styles/academic-research/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/consulting-decision/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/creative-pitch/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/incident-postmortem/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/investor-pitch/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/narrative-keynote/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/operating-review/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/product-launch/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/science-explainer/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/solution-proposal/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/technical-deepdive/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/workshop-teaching/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Style preset specs share the same explicit-only visual-review trigger by design."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "ea999949f34d",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/accenture/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/alibaba/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/anthropic/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/aws/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/bain/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/bcg/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/deloitte/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/huawei/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/ibm/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/jpmorgan/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/mckinsey/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/microsoft/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/nvidia/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/pwc/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/tencent/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/xiaomi/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Brand preset specs share the same portable fallback typography table by design."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "1ad663619aa4",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/alibaba/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/tencent/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Sibling corporate brand presets intentionally share the same voice defaults."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "d21d5ba8b91e",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/aws/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/microsoft/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/nvidia/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/xiaomi/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Sibling corporate brand presets intentionally share the same voice defaults."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "211e050e37d1",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/brands/accenture/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/bain/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/bcg/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/deloitte/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/huawei/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/ibm/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/jpmorgan/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/mckinsey/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/brands/pwc/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Sibling formal brand presets intentionally share the same voice defaults."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "1136fd17656e",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/templates/styles/academic-research/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/consulting-decision/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/creative-pitch/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/incident-postmortem/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/investor-pitch/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/narrative-keynote/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/operating-review/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/product-launch/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/science-explainer/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/solution-proposal/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/technical-deepdive/templates/design_spec.md",
|
||||||
|
"skills/ppt-master/templates/styles/workshop-teaching/templates/design_spec.md"
|
||||||
|
],
|
||||||
|
"reason": "Style preset specs share the same method-only scope boundary by design."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exact",
|
||||||
|
"fingerprint": "99d8baf1be58",
|
||||||
|
"paths": [
|
||||||
|
"skills/ppt-master/workflows/create-template/create-brand.md",
|
||||||
|
"skills/ppt-master/workflows/create-template/create-style.md"
|
||||||
|
],
|
||||||
|
"reason": "Mutually exclusive child workflows share the same resolved-workspace handoff contract."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -1381,6 +1614,344 @@
|
|||||||
"skills/ppt-master/workflows/*.md",
|
"skills/ppt-master/workflows/*.md",
|
||||||
"skills/ppt-master/workflows/**/*.md",
|
"skills/ppt-master/workflows/**/*.md",
|
||||||
"skills/ppt-master/templates/*.md"
|
"skills/ppt-master/templates/*.md"
|
||||||
|
],
|
||||||
|
"accepted": [
|
||||||
|
{
|
||||||
|
"field": "font_family",
|
||||||
|
"owner_fingerprint": "e33850f3053a",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-base.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "d937b965024b",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/strategist.md",
|
||||||
|
"role": "producer",
|
||||||
|
"fingerprint": "4c133143e2f2",
|
||||||
|
"reason": "This producer projects the owner field into the planning contract."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "90feed81f021",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/workflows/routing.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "a287404b8f1e",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "image_rendering",
|
||||||
|
"owner_fingerprint": "819d948a3087",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/image-generator.md",
|
||||||
|
"role": "compatibility",
|
||||||
|
"fingerprint": "5a6f2f95be38",
|
||||||
|
"reason": "This site documents a legacy or omission compatibility boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "3d0b27f3d979",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "page_charts",
|
||||||
|
"owner_fingerprint": "0edfe64300c1",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-structured.md",
|
||||||
|
"role": "compatibility",
|
||||||
|
"fingerprint": "a6ae3dfb6e6a",
|
||||||
|
"reason": "This site documents a legacy or omission compatibility boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-visualization.md",
|
||||||
|
"role": "compatibility",
|
||||||
|
"fingerprint": "055ab59c533e",
|
||||||
|
"reason": "This site documents a legacy or omission compatibility boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/strategist-template.md",
|
||||||
|
"role": "compatibility",
|
||||||
|
"fingerprint": "b0f9494f710a",
|
||||||
|
"reason": "This site documents a legacy or omission compatibility boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/strategist.md",
|
||||||
|
"role": "compatibility",
|
||||||
|
"fingerprint": "ba50ab71bc88",
|
||||||
|
"reason": "This site documents a legacy or omission compatibility boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "compatibility",
|
||||||
|
"fingerprint": "39d5baf1e189",
|
||||||
|
"reason": "This site documents a legacy or omission compatibility boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/workflows/stages/resume-execute.md",
|
||||||
|
"role": "compatibility",
|
||||||
|
"fingerprint": "023cf4d8ecbd",
|
||||||
|
"reason": "This site documents a legacy or omission compatibility boundary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "page_layouts",
|
||||||
|
"owner_fingerprint": "64d28e112785",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/artifact-ownership.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "be5e3881ee0d",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-structured.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "f77d8a752b85",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/pptx-structure-interface.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "60f4c8b8d08a",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "c35477d35410",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/workflows/create-template.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "b26d839b24b9",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/workflows/stages/apply-template-workspace.md",
|
||||||
|
"role": "compatibility",
|
||||||
|
"fingerprint": "1c393e47c311",
|
||||||
|
"reason": "This site documents a legacy or omission compatibility boundary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "page_pptx_layouts",
|
||||||
|
"owner_fingerprint": "f436e6ae4bb8",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/artifact-ownership.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "f91ef56378bb",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-structured.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "70d500bb46dc",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/pptx-structure-interface.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "b4596417aeec",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/shared-standards-core.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "8afb713e37e8",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/strategist-template.md",
|
||||||
|
"role": "producer",
|
||||||
|
"fingerprint": "fb6d05bac6e4",
|
||||||
|
"reason": "This producer projects the owner field into the planning contract."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "a67117d67b3e",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/workflows/create-template.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "40b13ab57503",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "page_rhythm",
|
||||||
|
"owner_fingerprint": "9d8344e389b1",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-base.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "4925a1ead978",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/strategist.md",
|
||||||
|
"role": "producer",
|
||||||
|
"fingerprint": "c326f18fa7c3",
|
||||||
|
"reason": "This producer projects the owner field into the planning contract."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "25aabdb0ee04",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "page_visualizations",
|
||||||
|
"owner_fingerprint": "b3cdf822635a",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-structured.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "105f5e4ce2ce",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-visualization.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "8b173848afa7",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/strategist.md",
|
||||||
|
"role": "producer",
|
||||||
|
"fingerprint": "1c8aa960c9e4",
|
||||||
|
"reason": "This producer projects the owner field into the planning contract."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "f45f26b4d11c",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/workflows/profiles/beautify-pptx.md",
|
||||||
|
"role": "producer",
|
||||||
|
"fingerprint": "308c0a3ef9d9",
|
||||||
|
"reason": "This producer projects the owner field into the planning contract."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "pptx_layouts",
|
||||||
|
"owner_fingerprint": "1037e878eaa1",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/artifact-ownership.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "447cd531facc",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-structured.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "5174447ee0a8",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/pptx-structure-interface.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "6f93a0561460",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/strategist-template.md",
|
||||||
|
"role": "producer",
|
||||||
|
"fingerprint": "f97c538adf92",
|
||||||
|
"reason": "This producer projects the owner field into the planning contract."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "2d6dba6c449e",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "pptx_masters",
|
||||||
|
"owner_fingerprint": "7cbe6ec7056e",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/artifact-ownership.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "7eba0fa766a6",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-structured.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "e5dcb49a9a61",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/pptx-structure-interface.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "92a978e5d229",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/strategist-template.md",
|
||||||
|
"role": "producer",
|
||||||
|
"fingerprint": "29a9e58295a9",
|
||||||
|
"reason": "This producer projects the owner field into the planning contract."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "89b01fc1b354",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "stroke_width",
|
||||||
|
"owner_fingerprint": "6683d97fc796",
|
||||||
|
"projections": [
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/executor-base.md",
|
||||||
|
"role": "consumer",
|
||||||
|
"fingerprint": "96e0f7380de0",
|
||||||
|
"reason": "This consumer needs the field contract for deterministic execution."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/references/strategist.md",
|
||||||
|
"role": "producer",
|
||||||
|
"fingerprint": "feb2b322c7ce",
|
||||||
|
"reason": "This producer projects the owner field into the planning contract."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/ppt-master/templates/spec_lock_reference.md",
|
||||||
|
"role": "reference",
|
||||||
|
"fingerprint": "9d35b546fb2d",
|
||||||
|
"reason": "This reference mirrors the owner field grammar or ownership boundary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1456,6 +2027,10 @@
|
|||||||
"glob": "skills/ppt-master/scripts/pptx_shapes/data/NOTICE.md",
|
"glob": "skills/ppt-master/scripts/pptx_shapes/data/NOTICE.md",
|
||||||
"reason": "License notice; never loaded as prompt context."
|
"reason": "License notice; never loaded as prompt context."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"glob": "skills/ppt-master/templates/icons/THIRD_PARTY_NOTICES.md",
|
||||||
|
"reason": "Third-party icon license and provenance notice; distributed for compliance, never loaded as prompt context."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"glob": "skills/ppt-master/references/shared-standards.md",
|
"glob": "skills/ppt-master/references/shared-standards.md",
|
||||||
"reason": "Compatibility router only; runtime load sets select the core and triggered modules directly."
|
"reason": "Compatibility router only; runtime load sets select the core and triggered modules directly."
|
||||||
|
|||||||
@@ -135,15 +135,16 @@ types, slots, and placeholders.
|
|||||||
|
|
||||||
## Icon Library
|
## Icon Library
|
||||||
|
|
||||||
The `icons/` directory contains 11,600+ vector icons across five libraries:
|
The `icons/` directory contains 12,027 vector icons across five libraries:
|
||||||
|
|
||||||
| Library | Style | Count |
|
| Library | Style | Count |
|
||||||
|---------|-------|-------|
|
|---------|-------|-------|
|
||||||
| `chunk-filled` | fill / straight-line geometry | 640 |
|
| `chunk-filled` | fill / compact, chunky 16px silhouettes | 641 |
|
||||||
| `tabler-filled` | fill / bezier-curve forms | 1000+ |
|
| `tabler-filled` | fill / bezier-curve forms | 1,055 |
|
||||||
| `tabler-outline` | stroke / line | 5000+ |
|
| `tabler-outline` | stroke / line | 5,138 |
|
||||||
| `phosphor-duotone` | duotone / single color + 0.2 opacity backplate | 1200+ |
|
| `phosphor-duotone` | duotone / single color + 0.2 opacity backplate | 1,518 |
|
||||||
| `simple-icons` | brand logos (company / product marks) | 3400+ |
|
| `simple-icons` | brand logos (company / product marks) | 3,675 |
|
||||||
|
|
||||||
- **Usage & style rules**: [icons/README.md](./icons/README.md)
|
- **Usage & style rules**: [icons/README.md](./icons/README.md)
|
||||||
|
- **Versions, licenses & attribution**: [icons/THIRD_PARTY_NOTICES.md](./icons/THIRD_PARTY_NOTICES.md)
|
||||||
- **Search icons**: `rg --files skills/ppt-master/templates/icons/<library>/ | rg <keyword>`
|
- **Search icons**: `rg --files skills/ppt-master/templates/icons/<library>/ | rg <keyword>`
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
# SVG Icon Library
|
# SVG Icon Library
|
||||||
|
|
||||||
This directory provides **11,600+ high-quality SVG icons** across five libraries that can be directly embedded into SVG files generated by PPT Master. Default Strategist or the Quick Generate main agent chooses at most one primary library from the four stylistic libraries; the brand-logo library (`simple-icons`) may be selected alone or alongside it.
|
This directory provides **12,027 high-quality SVG icons** across five libraries that can be directly embedded into SVG files generated by PPT Master. Default Strategist or the Quick Generate main agent chooses at most one primary library from the four stylistic libraries; the brand-logo library (`simple-icons`) may be selected alone or alongside it.
|
||||||
|
|
||||||
|
Upstream versions, compatibility overlays, licenses, attribution, and trademark boundaries are recorded in [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md).
|
||||||
|
|
||||||
## Libraries
|
## Libraries
|
||||||
|
|
||||||
| Library | Style | Count | viewBox | Prefix |
|
| Library | Style | Count | viewBox | Prefix |
|
||||||
|---------|-------|-------|---------|--------|
|
|---------|-------|-------|---------|--------|
|
||||||
| `chunk-filled` | fill · straight-line geometry (sharp corners, rectilinear) | 640 | `0 0 16 16` | `chunk-filled/` |
|
| `chunk-filled` | fill · compact, chunky 16px silhouettes | 641 | primarily `0 0 16 16` | `chunk-filled/` |
|
||||||
| `tabler-filled` | fill · bezier-curve forms (smooth, rounded contours) | 1000+ | `0 0 24 24` | `tabler-filled/` |
|
| `tabler-filled` | fill · bezier-curve forms (smooth, rounded contours) | 1,055 | `0 0 24 24` | `tabler-filled/` |
|
||||||
| `tabler-outline` | stroke / line | 5000+ | `0 0 24 24` | `tabler-outline/` |
|
| `tabler-outline` | stroke / line | 5,138 | `0 0 24 24` | `tabler-outline/` |
|
||||||
| `phosphor-duotone` | duotone · single color + 0.2 opacity backplate (soft depth) | 1200+ | `0 0 256 256` | `phosphor-duotone/` |
|
| `phosphor-duotone` | duotone · single color + 0.2 opacity backplate (soft depth) | 1,518 | `0 0 256 256` | `phosphor-duotone/` |
|
||||||
| `simple-icons` | **brand logos** (real company / product marks) — single-color silhouettes, color in via `fill` | 3400+ | `0 0 24 24` | `simple-icons/` |
|
| `simple-icons` | **brand logos** (real company / product marks) — single-color silhouettes, color in via `fill` | 3,675 | `0 0 24 24` | `simple-icons/` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -37,7 +39,7 @@ namespace. Each extracted vector lives once at
|
|||||||
Use placeholder syntax **during SVG generation**:
|
Use placeholder syntax **during SVG generation**:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- chunk-filled (sharp, geometric — tech/engineering/enterprise tone) -->
|
<!-- chunk-filled (compact, chunky — strong small-size legibility) -->
|
||||||
<use data-icon="chunk-filled/home" x="100" y="200" width="48" height="48" fill="#0076A8"/>
|
<use data-icon="chunk-filled/home" x="100" y="200" width="48" height="48" fill="#0076A8"/>
|
||||||
|
|
||||||
<!-- tabler-filled (rounded, organic — lifestyle/health/home tone) -->
|
<!-- tabler-filled (rounded, organic — lifestyle/health/home tone) -->
|
||||||
@@ -88,13 +90,13 @@ Do not load a full index or enumerate broad keyword families. Re-pick from the n
|
|||||||
|
|
||||||
**No default library — actively choose based on the deck's visual needs.** Read the source material first, then pick the library whose visual character best serves the presentation. Each library has a distinct visual personality:
|
**No default library — actively choose based on the deck's visual needs.** Read the source material first, then pick the library whose visual character best serves the presentation. Each library has a distinct visual personality:
|
||||||
|
|
||||||
- **`chunk-filled`** — **fill** style, built from straight-line commands only (M/L/H/V/Z). Sharp, precise right angles; rectilinear geometry; structured and highly legible at small sizes. Visual weight: heavy, solid, architectural.
|
- **`chunk-filled`** — **fill** style, designed as compact 16px silhouettes. Bold forms may combine rectilinear and curved geometry while staying highly legible at small sizes. Visual weight: heavy, solid, compact.
|
||||||
- **`tabler-filled`** — **fill** style, built from bezier curves and arcs (C/A). Smooth, rounded, organic contours; warmer and softer than `chunk-filled`. Visual weight: medium, approachable.
|
- **`tabler-filled`** — **fill** style, built from bezier curves and arcs (C/A). Smooth, rounded, organic contours; warmer and softer than `chunk-filled`. Visual weight: medium, approachable.
|
||||||
- **`tabler-outline`** — **stroke** style (line art, default stroke-width 2). Airy, refined, lightweight; uses negative space. Visual weight: light, elegant. Best for screen-only viewing since thin strokes may become hard to read when printed or projected.
|
- **`tabler-outline`** — **stroke** style (line art, default stroke-width 2). Airy, refined, lightweight; uses negative space. Visual weight: light, elegant. Best for screen-only viewing since thin strokes may become hard to read when printed or projected.
|
||||||
- **`phosphor-duotone`** — **duotone** style; main shape at full opacity plus a backplate of the same color at 20% opacity, producing a soft sense of depth. Visual weight: medium, layered, contemporary.
|
- **`phosphor-duotone`** — **duotone** style; main shape at full opacity plus a backplate of the same color at 20% opacity, producing a soft sense of depth. Visual weight: medium, layered, contemporary.
|
||||||
|
|
||||||
> **Two axes to consider when choosing**:
|
> **Two axes to consider when choosing**:
|
||||||
> 1. **Geometry**: straight lines (`chunk-filled`) vs. curves (`tabler-filled` / `phosphor-duotone`) vs. open strokes (`tabler-outline`)
|
> 1. **Geometry**: compact silhouettes (`chunk-filled`) vs. rounded curves (`tabler-filled` / `phosphor-duotone`) vs. open strokes (`tabler-outline`)
|
||||||
> 2. **Visual weight**: heavy solid (`chunk-filled`) → medium solid (`tabler-filled`) → medium layered (`phosphor-duotone`) → light stroke (`tabler-outline`)
|
> 2. **Visual weight**: heavy solid (`chunk-filled`) → medium solid (`tabler-filled`) → medium layered (`phosphor-duotone`) → light stroke (`tabler-outline`)
|
||||||
|
|
||||||
**One primary bundled stylistic library per deck selection.** Pick one of `chunk-filled` / `tabler-filled` / `tabler-outline` / `phosphor-duotone` for generic icons (home, chart, users, etc.). If it lacks an exact icon, find the closest available alternative within that library instead of selecting from another bundled stylistic library. This is a catalog-selection rule, not a prohibition on combining assets that already exist in the project's `icons/` directory.
|
**One primary bundled stylistic library per deck selection.** Pick one of `chunk-filled` / `tabler-filled` / `tabler-outline` / `phosphor-duotone` for generic icons (home, chart, users, etc.). If it lacks an exact icon, find the closest available alternative within that library instead of selecting from another bundled stylistic library. This is a catalog-selection rule, not a prohibition on combining assets that already exist in the project's `icons/` directory.
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# Third-Party Icon Notices
|
||||||
|
|
||||||
|
The SVG files under this directory include third-party assets. PPT Master's
|
||||||
|
MIT license covers PPT Master itself; it does not replace the licenses,
|
||||||
|
attribution requirements, brand guidelines, or trademark rights that apply to
|
||||||
|
these assets.
|
||||||
|
|
||||||
|
## Bundled snapshots
|
||||||
|
|
||||||
|
Snapshot date: **2026-08-09**.
|
||||||
|
|
||||||
|
| Directory | Upstream baseline | Bundled files | Compatibility boundary |
|
||||||
|
|---|---|---:|---|
|
||||||
|
| `chunk-filled` | [CHUNK Icons](https://www.figma.com/community/file/1327310800295849271/chunk-icons), versionless snapshot cross-checked against the [SVG Repo collection](https://www.svgrepo.com/collection/chunk-16px-thick-interface-icons/) and [Wikimedia Commons category](https://commons.wikimedia.org/wiki/Category:Chunk_Icons) | 641 | PPT Master-normalized files; historical local basenames remain stable |
|
||||||
|
| `tabler-filled` | [Tabler Icons v3.46.0](https://github.com/tabler/tabler-icons/releases/tag/v3.46.0), commit `8ac7d81b72ece11072ef25ea9fd92e80c6f3c9fc` | 1,055 | 1,054 upstream files plus 1 legacy spelling alias |
|
||||||
|
| `tabler-outline` | [Tabler Icons v3.46.0](https://github.com/tabler/tabler-icons/releases/tag/v3.46.0), commit `8ac7d81b72ece11072ef25ea9fd92e80c6f3c9fc` | 5,138 | 5,130 upstream files plus 8 legacy spelling aliases |
|
||||||
|
| `phosphor-duotone` | [`@phosphor-icons/core@2.1.1`](https://www.npmjs.com/package/@phosphor-icons/core/v/2.1.1), npm integrity `sha512-v4ARvrip4qBCImOE5rmPUylOEK4iiED9ZyKjcvzuezqMaiRASCHKcRIuvvxL/twvLpkfnEODCOJp5dM4eZilxQ==` | 1,518 | 1,512 upstream files plus 6 legacy aliases; upstream `-duotone` filename suffixes are removed locally |
|
||||||
|
| `simple-icons` | [Simple Icons 16.28.0](https://github.com/simple-icons/simple-icons/releases/tag/16.28.0), commit `fc91ef03ec113d06627b2d47c1f9644ca202b6f9` | 3,675 | 3,453 current files plus 222 compatibility files matching the 12.4.0 snapshot at commit `32b07a5b798b84b97f2cbbb5b69ec7cb80472f73` |
|
||||||
|
|
||||||
|
The Tabler compatibility aliases are `mood-confuzed` in `tabler-filled`, plus
|
||||||
|
`brand-adobe-after-effect`, `brand-kako-talk`, `currency-rubel`,
|
||||||
|
`gender-trasvesti`, `ikosaedr`, `mood-confuzed`, `physotherapist`, and
|
||||||
|
`sport-billard` in `tabler-outline`.
|
||||||
|
|
||||||
|
The Phosphor compatibility aliases are `archive-box`, `archive-tray`,
|
||||||
|
`folder-notch`, `folder-notch-minus`, `folder-notch-open`, and
|
||||||
|
`folder-notch-plus`. Their current upstream equivalents are respectively
|
||||||
|
`box-arrow-down`, `tray-arrow-down`, `folder`, `folder-minus`, `folder-open`,
|
||||||
|
and `folder-plus`.
|
||||||
|
|
||||||
|
Simple Icons compatibility files are retained because existing templates,
|
||||||
|
examples, and user projects may still reference removed brand IDs. Their
|
||||||
|
presence here does not mean that the current Simple Icons project still ships
|
||||||
|
or recommends those marks.
|
||||||
|
|
||||||
|
## CHUNK Icons attribution
|
||||||
|
|
||||||
|
**CHUNK Icons** by **Noah Jacobus** is licensed under
|
||||||
|
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
|
||||||
|
|
||||||
|
PPT Master modifications: root dimensions were normalized to 24 by 24,
|
||||||
|
hard-coded black fills were changed to `currentColor`, SVG Repo wrapper
|
||||||
|
metadata was removed, and historical local filenames were retained. The icon
|
||||||
|
geometry remains sourced from CHUNK. The `r` glyph was restored from the
|
||||||
|
public Wikimedia mirror during the 2026-08-09 reconciliation.
|
||||||
|
|
||||||
|
## Simple Icons license and trademark notice
|
||||||
|
|
||||||
|
The Simple Icons project is released under
|
||||||
|
[CC0 1.0](https://github.com/simple-icons/simple-icons/blob/16.28.0/LICENSE.md),
|
||||||
|
but that does not imply that every individual brand icon is CC0. Brand marks
|
||||||
|
may have separate licenses, usage guidelines, or trademark restrictions.
|
||||||
|
Before using a bundled brand icon, check its current Simple Icons metadata,
|
||||||
|
the brand owner's guidelines, and the upstream
|
||||||
|
[disclaimer](https://github.com/simple-icons/simple-icons/blob/16.28.0/DISCLAIMER.md).
|
||||||
|
Neither CC0 nor inclusion in this repository grants trademark permission.
|
||||||
|
|
||||||
|
## MIT notices
|
||||||
|
|
||||||
|
The following copyright notices and MIT terms apply to the Tabler and
|
||||||
|
Phosphor assets described above.
|
||||||
|
|
||||||
|
### Tabler Icons
|
||||||
|
|
||||||
|
Copyright (c) 2020-2026 Paweł Kuna
|
||||||
|
|
||||||
|
### Phosphor Icons
|
||||||
|
|
||||||
|
Copyright (c) 2023 Phosphor Icons
|
||||||
|
|
||||||
|
### MIT License terms
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
## Update policy
|
||||||
|
|
||||||
|
- Pin a released upstream version, or record the audit date for a versionless
|
||||||
|
source, before copying files.
|
||||||
|
- Overwrite files that still exist upstream, but do not automatically delete
|
||||||
|
local-only names. Review removals and renames as compatibility changes.
|
||||||
|
- Recheck the Simple Icons disclaimer and per-brand metadata whenever that
|
||||||
|
library is refreshed; an upstream removal is not merely a file-sync detail.
|
||||||
|
- Recount the directories and validate every SVG after each refresh. Update
|
||||||
|
this notice and the two icon-library README tables in the same change.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 0v16h3v-6h3.073l3 6h3.354l-3.09-6.18A5 5 0 0 0 10 0zm8 7H5V3h5a2 2 0 1 1 0 4" fill="currentColor"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 263 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,112v16c0,53-88,88-88,112,0-24-88-59-88-112V112Z" opacity="0.2"/><path d="M232,104a56.06,56.06,0,0,0-56-56H136a24,24,0,0,1,24-24,8,8,0,0,0,0-16,40,40,0,0,0-40,40H80a56.06,56.06,0,0,0-56,56,16,16,0,0,0,8,13.83V128c0,35.53,33.12,62.12,59.74,83.49C103.66,221.07,120,234.18,120,240a8,8,0,0,0,16,0c0-5.82,16.34-18.93,28.26-28.51C190.88,190.12,224,163.53,224,128V117.83A16,16,0,0,0,232,104ZM80,64h96a40.06,40.06,0,0,1,40,40H40A40,40,0,0,1,80,64Zm74.25,135c-10.62,8.52-20,16-26.25,23.37-6.25-7.32-15.63-14.85-26.25-23.37C77.8,179.79,48,155.86,48,128v-8H208v8C208,155.86,178.2,179.79,154.25,199Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 691 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M48,40a8,8,0,0,0-8,8V208a8,8,0,0,0,8,8H184V40Zm64,104a24,24,0,1,1,24-24A24,24,0,0,1,112,144Z" opacity="0.2"/><path d="M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm-16,72h16v48H192Zm16-16H192V48h16ZM48,48H176V208H48ZM208,208H192V168h16v40Zm-56.25-42a39.76,39.76,0,0,0-17.19-23.34,32,32,0,1,0-45.12,0A39.84,39.84,0,0,0,72.25,166a8,8,0,0,0,15.5,4c2.64-10.25,13.06-18,24.25-18s21.62,7.73,24.25,18a8,8,0,1,0,15.5-4ZM96,120a16,16,0,1,1,16,16A16,16,0,0,1,96,120Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 606 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M223.51,74.73l-26.18,72a8,8,0,0,1-7.52,5.27H66.19a8,8,0,0,1-7.52-5.27l-26.18-72A8,8,0,0,1,40,64H216A8,8,0,0,1,223.51,74.73Z" opacity="0.2"/><path d="M229.11,62.82A16,16,0,0,0,216,56H136V24h16a8,8,0,0,0,0-16H104a8,8,0,0,0,0,16h16V56H40A16,16,0,0,0,25,77.47l26.19,72a16,16,0,0,0,15,10.53H96v64a8,8,0,0,0,16,0V160h32v64a8,8,0,0,0,16,0V160h29.82a16,16,0,0,0,15-10.53l26.19-72A16,16,0,0,0,229.11,62.82ZM110.68,144,97.58,72h60.84l-13.1,72ZM40,72H81.32l13.09,72H66.18Zm149.82,72H161.59l13.09-72H216Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M223.51,82.73l-26.18,72a8,8,0,0,1-7.52,5.27H66.19a8,8,0,0,1-7.52-5.27l-26.18-72A8,8,0,0,1,40,72H216A8,8,0,0,1,223.51,82.73Z" opacity="0.2"/><path d="M229.11,70.82A16,16,0,0,0,216,64H136V32h16a8,8,0,0,0,0-16H104a8,8,0,0,0,0,16h16V64H40A16,16,0,0,0,25,85.47l26.19,72a16,16,0,0,0,15,10.53H96v64a8,8,0,0,0,16,0V168h32v64a8,8,0,0,0,16,0V168h29.82a16,16,0,0,0,15-10.53l26.19-72A16,16,0,0,0,229.11,70.82ZM110.68,152,97.58,80h60.84l-13.1,72ZM40,80H81.32l13.09,72H66.18Zm149.82,72H161.59l13.09-72H216Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 592 B After Width: | Height: | Size: 592 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,148.32V184L47.37,134.54A32,32,0,0,1,24,103.73V48a8,8,0,0,1,10.53-7.59L40,42.24,52,75.46,96,88V48a8,8,0,0,1,10.53-7.59L112,42.24l24,57.2,64.56,18A32,32,0,0,1,224,148.32Z" opacity="0.2"/><path d="M248,216a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16H240A8,8,0,0,1,248,216Zm-26.16-24.3L45.21,142.24A40.12,40.12,0,0,1,16,103.72V48A16,16,0,0,1,37.06,32.82l5.47,1.82a8,8,0,0,1,5,4.87L58.13,68.88,88,77.39V48a16,16,0,0,1,21.06-15.18l5.47,1.82a8,8,0,0,1,4.85,4.5l22.5,53.63,60.84,17A40.13,40.13,0,0,1,232,148.32V184a8,8,0,0,1-10.16,7.7ZM216,148.32a24.09,24.09,0,0,0-17.58-23.13l-64.57-18a8,8,0,0,1-5.23-4.61L106,48.67,104,48V88a8,8,0,0,1-10.19,7.7l-44-12.54a8,8,0,0,1-5.33-5L33.79,48.59,32,48v55.72a24.09,24.09,0,0,0,17.53,23.12L216,173.45Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,148.32V184L55.37,134.54A32,32,0,0,1,32,103.73V48a8,8,0,0,1,10.53-7.59L48,42.24,60,75.46,104,88V48a8,8,0,0,1,10.53-7.59L120,42.24l24,57.2,64.56,18A32,32,0,0,1,232,148.32Z" opacity="0.2"/><path d="M256,216a8,8,0,0,1-8,8H104a8,8,0,0,1,0-16H248A8,8,0,0,1,256,216Zm-26.16-24.3L53.21,142.24A40.12,40.12,0,0,1,24,103.72V48A16,16,0,0,1,45.06,32.82l5.47,1.82a8,8,0,0,1,5,4.87L66.13,68.88,96,77.39V48a16,16,0,0,1,21.06-15.18l5.47,1.82a8,8,0,0,1,4.85,4.5l22.5,53.63,60.84,17A40.13,40.13,0,0,1,240,148.32V184a8,8,0,0,1-10.16,7.7ZM224,148.32a24.09,24.09,0,0,0-17.58-23.13l-64.57-18a8,8,0,0,1-5.23-4.61L114,48.67,112,48V88a8,8,0,0,1-10.19,7.7l-44-12.54a8,8,0,0,1-5.33-5L41.79,48.59,40,48v55.72a24.09,24.09,0,0,0,17.53,23.12L224,173.45Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 824 B After Width: | Height: | Size: 826 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,136v24H61.06a32,32,0,0,1-30.65-22.8L16.34,90.3A8,8,0,0,1,24,80h8l24,24H92.91L80.42,66.53A8,8,0,0,1,88,56h8l48,48h64A32,32,0,0,1,240,136Z" opacity="0.2"/><path d="M208,96H147.32L101.66,50.34A8,8,0,0,0,96,48H88A16,16,0,0,0,72.83,69.06l9,26.94H59.32L37.66,74.34A8,8,0,0,0,32,72H24A16,16,0,0,0,8.69,92.6l14.07,46.89A39.75,39.75,0,0,0,61.07,168H240a8,8,0,0,0,8-8V136A40,40,0,0,0,208,96Zm24,56H61.07a23.85,23.85,0,0,1-23-17.1L24,88h4.68l21.66,21.66A8,8,0,0,0,56,112h36.9a8,8,0,0,0,7.59-10.53L88,64h4.68l45.66,45.66A8,8,0,0,0,144,112h64a24,24,0,0,1,24,24Zm-8,48a16,16,0,1,1-16-16A16,16,0,0,1,224,200Zm-96,0a16,16,0,1,1-16-16A16,16,0,0,1,128,200Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 743 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,64V176a16,16,0,0,1-16,16H155.43L128,160l-27.43,32H48a16,16,0,0,1-16-16V64A16,16,0,0,1,48,48H208A16,16,0,0,1,224,64Z" opacity="0.2"/><path d="M134.08,154.79a8,8,0,0,0-12.15,0l-48,56A8,8,0,0,0,80,224h96a8,8,0,0,0,6.07-13.21ZM97.39,208,128,172.29,158.61,208ZM232,64V176a24,24,0,0,1-24,24H192a8,8,0,0,1,0-16h16a8,8,0,0,0,8-8V64a8,8,0,0,0-8-8H48a8,8,0,0,0-8,8V176a8,8,0,0,0,8,8H64a8,8,0,0,1,0,16H48a24,24,0,0,1-24-24V64A24,24,0,0,1,48,40H208A24,24,0,0,1,232,64Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,64V176a16,16,0,0,1-16,16H155.43L128,160l-27.43,32H48a16,16,0,0,1-16-16V64A16,16,0,0,1,48,48H208A16,16,0,0,1,224,64Z" opacity="0.2"/><path d="M134.08,154.79a8,8,0,0,0-12.15,0l-48,56A8,8,0,0,0,80,224h96a8,8,0,0,0,6.07-13.21ZM97.39,208,128,172.29,158.61,208ZM232,64V176a24,24,0,0,1-24,24h-8a8,8,0,0,1,0-16h8a8,8,0,0,0,8-8V64a8,8,0,0,0-8-8H48a8,8,0,0,0-8,8V176a8,8,0,0,0,8,8h8a8,8,0,0,1,0,16H48a24,24,0,0,1-24-24V64A24,24,0,0,1,48,40H208A24,24,0,0,1,232,64Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 561 B After Width: | Height: | Size: 558 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,128a88,88,0,1,1-88-88A88,88,0,0,1,216,128Z" opacity="0.2"/><path d="M128,32a96,96,0,1,0,96,96A96.11,96.11,0,0,0,128,32Zm0,176a80,80,0,1,1,80-80A80.09,80.09,0,0,1,128,208ZM61.66,29.66l-32,32A8,8,0,0,1,18.34,50.34l32-32A8,8,0,1,1,61.66,29.66Zm176,32a8,8,0,0,1-11.32,0l-32-32a8,8,0,0,1,11.32-11.32l32,32A8,8,0,0,1,237.66,61.66ZM184,120a8,8,0,0,1,0,16H128a8,8,0,0,1-8-8V72a8,8,0,0,1,16,0v48Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,136a88,88,0,1,1-88-88A88,88,0,0,1,216,136Z" opacity="0.2"/><path d="M128,40a96,96,0,1,0,96,96A96.11,96.11,0,0,0,128,40Zm0,176a80,80,0,1,1,80-80A80.09,80.09,0,0,1,128,216ZM61.66,37.66l-32,32A8,8,0,0,1,18.34,58.34l32-32A8,8,0,0,1,61.66,37.66Zm176,32a8,8,0,0,1-11.32,0l-32-32a8,8,0,0,1,11.32-11.32l32,32A8,8,0,0,1,237.66,69.66ZM184,128a8,8,0,0,1,0,16H128a8,8,0,0,1-8-8V80a8,8,0,0,1,16,0v48Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 492 B After Width: | Height: | Size: 492 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M248,120v64a8,8,0,0,1-8,8H216a24,24,0,0,0-32-22.63h0A24,24,0,0,0,168,192H104a24,24,0,0,0-48,0H32a8,8,0,0,1-8-8V72a8,8,0,0,1,8-8H184v56Z" opacity="0.2"/><path d="M80,120a8,8,0,0,1,8-8h16V96a8,8,0,0,1,16,0v16h16a8,8,0,0,1,0,16H120v16a8,8,0,0,1-16,0V128H88A8,8,0,0,1,80,120Zm176,0v64a16,16,0,0,1-16,16H223a32,32,0,0,1-62,0H111a32,32,0,0,1-62,0H32a16,16,0,0,1-16-16V72A16,16,0,0,1,32,56H184a8,8,0,0,1,8,8v8h34.58a15.93,15.93,0,0,1,14.86,10.06l14,35A7.92,7.92,0,0,1,256,120ZM192,88v24h44.18l-9.6-24ZM32,184H49a32,32,0,0,1,62,0h50a32.11,32.11,0,0,1,15-19.69V72H32Zm64,8a16,16,0,1,0-16,16A16,16,0,0,0,96,192Zm112,0a16,16,0,1,0-16,16A16,16,0,0,0,208,192Zm32-8V128H192v32a32.06,32.06,0,0,1,31,24Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 787 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M152,56a24,24,0,1,1-24-24A24,24,0,0,1,152,56Z" opacity="0.2"/><path d="M216,136a8,8,0,0,0-8,8,40,40,0,0,1-40,40,47.79,47.79,0,0,0-32,12.27V128h32a8,8,0,0,0,0-16H136V87a32,32,0,1,0-16,0v25H88a8,8,0,0,0,0,16h32v68.27A47.79,47.79,0,0,0,88,184a40,40,0,0,1-40-40,8,8,0,0,0-16,0,56.06,56.06,0,0,0,56,56,32,32,0,0,1,32,32,8,8,0,0,0,16,0,32,32,0,0,1,32-32,56.06,56.06,0,0,0,56-56A8,8,0,0,0,216,136ZM112,56a16,16,0,1,1,16,16A16,16,0,0,1,112,56Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M152,56a24,24,0,1,1-24-24A24,24,0,0,1,152,56Z" opacity="0.2"/><path d="M216,136a8,8,0,0,0-8,8c0,24.69-13.77,29.64-38.1,36.28-11.36,3.1-24.12,6.6-33.9,14.34V128h32a8,8,0,0,0,0-16H136V87a32,32,0,1,0-16,0v25H88a8,8,0,0,0,0,16h32v66.62c-9.78-7.74-22.54-11.24-33.9-14.34C61.77,173.64,48,168.69,48,144a8,8,0,0,0-16,0c0,38.11,27.67,45.66,49.9,51.72C106.23,202.36,120,207.31,120,232a8,8,0,0,0,16,0c0-24.69,13.77-29.64,38.1-36.28C196.33,189.66,224,182.11,224,144A8,8,0,0,0,216,136ZM112,56a16,16,0,1,1,16,16A16,16,0,0,1,112,56Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 535 B After Width: | Height: | Size: 617 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,168v24a8,8,0,0,1-8,8H32a8,8,0,0,1-8-8V169.13C24,111.65,70.15,64.2,127.63,64A104,104,0,0,1,232,168Z" opacity="0.2"/><path d="M176,156a12,12,0,1,1-12-12A12,12,0,0,1,176,156ZM92,144a12,12,0,1,0,12,12A12,12,0,0,0,92,144Zm148,24v24a16,16,0,0,1-16,16H32a16,16,0,0,1-16-16V169.13A113.38,113.38,0,0,1,51.4,86.72L26.34,61.66A8,8,0,0,1,37.66,50.34L63.82,76.5a111.4,111.4,0,0,1,128.55-.18l26-26a8,8,0,0,1,11.32,11.32L204.82,86.5c.75.71,1.5,1.43,2.24,2.17A111.25,111.25,0,0,1,240,168Zm-16,0a96,96,0,0,0-96-96h-.34C74.91,72.18,32,115.75,32,169.13V192H224Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,160v24a8,8,0,0,1-8,8H32a8,8,0,0,1-8-8V161.13C24,103.65,70.15,56.2,127.63,56A104,104,0,0,1,232,160Z" opacity="0.2"/><path d="M176,148a12,12,0,1,1-12-12A12,12,0,0,1,176,148ZM92,136a12,12,0,1,0,12,12A12,12,0,0,0,92,136Zm148,24v24a16,16,0,0,1-16,16H32a16,16,0,0,1-16-16V161.13A113.38,113.38,0,0,1,51.4,78.72L26.34,53.66A8,8,0,0,1,37.66,42.34L63.82,68.5a111.4,111.4,0,0,1,128.55-.18l26-26a8,8,0,0,1,11.32,11.32L204.82,78.5c.75.71,1.5,1.43,2.24,2.17A111.25,111.25,0,0,1,240,160Zm-16,0a96,96,0,0,0-96-96h-.34C74.91,64.18,32,107.75,32,161.13V184H224Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 647 B After Width: | Height: | Size: 647 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M200,168v32H72V72h32A96,96,0,0,1,200,168Z" opacity="0.2"/><path d="M96,72a8,8,0,0,1,8-8A104.11,104.11,0,0,1,208,168a8,8,0,0,1-16,0,88.1,88.1,0,0,0-88-88A8,8,0,0,1,96,72ZM240,192H80V32a8,8,0,0,0-16,0V64H32a8,8,0,0,0,0,16H64V200a8,8,0,0,0,8,8H240a8,8,0,0,0,0-16Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 360 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M104,120a24,24,0,1,1,24,24A24,24,0,0,1,104,120Zm39.75,24h-31.5a16.06,16.06,0,0,0-15.76,19.88l12.19,48A16.2,16.2,0,0,0,124.44,224h7.12a16.2,16.2,0,0,0,15.76-12.12l12.19-48A16.06,16.06,0,0,0,143.75,144Z" opacity="0.2"/><path d="M154.2,138.33a32,32,0,1,0-52.4,0,24.18,24.18,0,0,0-8.76,7,23.68,23.68,0,0,0-4.3,20.49l12.18,48A24.18,24.18,0,0,0,124.44,232h7.12a24.18,24.18,0,0,0,23.52-18.15l12.18-48a23.68,23.68,0,0,0-4.3-20.49A24.18,24.18,0,0,0,154.2,138.33ZM128,104a16,16,0,1,1-16,16A16,16,0,0,1,128,104Zm23.75,57.91-12.18,48a8.18,8.18,0,0,1-8,6.09h-7.12a8.18,8.18,0,0,1-8-6.09l-12.18-48a7.71,7.71,0,0,1,1.42-6.73,8.26,8.26,0,0,1,6.58-3.18h31.5a8.26,8.26,0,0,1,6.58,3.18A7.71,7.71,0,0,1,151.75,161.91ZM72,128a56.27,56.27,0,0,0,1.76,14,8,8,0,1,1-15.49,4,72,72,0,1,1,139.46,0,8,8,0,0,1-7.74,6,8.12,8.12,0,0,1-2-.25,8,8,0,0,1-5.75-9.74A56,56,0,1,0,72,128Zm160,0a103.86,103.86,0,0,1-46.49,86.66,8,8,0,0,1-8.86-13.32,88,88,0,1,0-97.31,0A8,8,0,0,1,74.91,216a7.92,7.92,0,0,1-4.42-1.34A104,104,0,1,1,232,128Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M104,120a24,24,0,1,1,24,24A24,24,0,0,1,104,120Zm39.75,24h-31.5a16.06,16.06,0,0,0-15.76,19.88l12.19,48A16.2,16.2,0,0,0,124.44,224h7.12a16.2,16.2,0,0,0,15.76-12.12l12.19-48A16.06,16.06,0,0,0,143.75,144Z" opacity="0.2"/><path d="M154.2,138.33a32,32,0,1,0-52.4,0,24.18,24.18,0,0,0-8.76,7,23.68,23.68,0,0,0-4.3,20.49l12.18,48A24.18,24.18,0,0,0,124.44,232h7.12a24.18,24.18,0,0,0,23.52-18.15l12.18-48a23.68,23.68,0,0,0-4.3-20.49A24.18,24.18,0,0,0,154.2,138.33ZM128,104a16,16,0,1,1-16,16A16,16,0,0,1,128,104Zm23.75,57.91-12.18,48a8.18,8.18,0,0,1-8,6.09h-7.12a8.18,8.18,0,0,1-8-6.09l-12.18-48a7.71,7.71,0,0,1,1.42-6.73,8.26,8.26,0,0,1,6.58-3.18h31.5a8.26,8.26,0,0,1,6.58,3.18A7.71,7.71,0,0,1,151.75,161.91ZM72,128a56.31,56.31,0,0,0,2,15,8,8,0,0,1-15.41,4.29,72,72,0,1,1,138.74,0A8,8,0,0,1,182,143,56,56,0,1,0,72,128Zm160,0a103.92,103.92,0,0,1-46.18,86.46,8,8,0,0,1-8.9-13.3,88,88,0,1,0-97.84,0,8,8,0,0,1-8.9,13.3A104,104,0,1,1,232,128Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,56V200a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V56A16,16,0,0,1,56,40H200A16,16,0,0,1,216,56Z" opacity="0.2"/><path d="M222.16,153.26a8,8,0,0,1-1,11.25c-17.36,14.38-32.86,19.49-47,19.49-18.58,0-34.82-8.81-49.93-17-25.35-13.75-47.24-25.63-79.07.74a8,8,0,1,1-10.22-12.3c40.17-33.27,70.32-16.92,96.93-2.48,25.35,13.75,47.24,25.62,79.07-.75A8,8,0,0,1,222.16,153.26Zm-177-49.46c31.83-26.37,53.72-14.5,79.07-.75,15.11,8.2,31.35,17,49.93,17,14.14,0,29.64-5.11,47-19.49a8,8,0,1,0-10.22-12.3c-31.83,26.37-53.72,14.49-79.07.74-26.61-14.43-56.76-30.79-96.93,2.48A8,8,0,0,0,45.11,103.8Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 676 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,56v48H184Z" opacity="0.2"/><path d="M235.06,48.57a8,8,0,0,0-8.72,1.73L206.68,70,195.75,60a96,96,0,1,0-69.07,164H128a95.44,95.44,0,0,0,65.88-26.19,8,8,0,0,0-11-11.63A80,80,0,1,1,184.56,71.4l.25.24,10.55,9.65-17,17A8,8,0,0,0,184,112h48a8,8,0,0,0,8-8V56A8,8,0,0,0,235.06,48.57ZM224,96H203.31L224,75.28Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,128a88,88,0,1,1-88-88A88,88,0,0,1,216,128Z" opacity="0.2"/><path d="M240,56v48a8,8,0,0,1-8,8H184a8,8,0,0,1,0-16H211.4L184.81,71.64l-.25-.24a80,80,0,1,0-1.67,114.78,8,8,0,0,1,11,11.63A95.44,95.44,0,0,1,128,224h-1.32A96,96,0,1,1,195.75,60L224,85.8V56a8,8,0,1,1,16,0Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 404 B After Width: | Height: | Size: 369 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M72,104H24V56Z" opacity="0.2"/><path d="M195.88,60.08A96.08,96.08,0,0,0,60.25,60L49.31,70,29.66,50.3A8,8,0,0,0,16,56v48a8,8,0,0,0,8,8H72a8,8,0,0,0,5.66-13.66l-17-17,10.54-9.65a3.07,3.07,0,0,0,.26-.25,80,80,0,1,1,1.65,114.78,8,8,0,0,0-11,11.63A95.38,95.38,0,0,0,128,224h1.32A96,96,0,0,0,195.88,60.08ZM32,96V75.28L52.69,96Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,128a88,88,0,1,1-88-88A88,88,0,0,1,216,128Z" opacity="0.2"/><path d="M224,128a96,96,0,0,1-94.71,96H128A95.38,95.38,0,0,1,62.1,197.8a8,8,0,0,1,11-11.63A80,80,0,1,0,71.43,71.39a3.07,3.07,0,0,1-.26.25L44.59,96H72a8,8,0,0,1,0,16H24a8,8,0,0,1-8-8V56a8,8,0,0,1,16,0V85.8L60.25,60A96,96,0,0,1,224,128Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 421 B After Width: | Height: | Size: 398 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,176l-48,48V128Z" opacity="0.2"/><path d="M213.66,170.34l-48-48A8,8,0,0,0,152,128v40H72V32a8,8,0,0,0-16,0V176a8,8,0,0,0,8,8h88v40a8,8,0,0,0,13.66,5.66l48-48A8,8,0,0,0,213.66,170.34ZM168,204.69V147.31L196.69,176Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,176l-48,48V128Z" opacity="0.2"/><path d="M221.66,170.34l-48-48A8,8,0,0,0,160,128v40H80V32a8,8,0,0,0-16,0V176a8,8,0,0,0,8,8h88v40a8,8,0,0,0,13.66,5.66l48-48A8,8,0,0,0,221.66,170.34ZM176,204.69V147.31L204.69,176Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 315 B After Width: | Height: | Size: 315 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,160,80,208,32,160Z" opacity="0.2"/><path d="M224,56H80a8,8,0,0,0-8,8v88H32a8,8,0,0,0-5.66,13.66l48,48a8,8,0,0,0,11.32,0l48-48A8,8,0,0,0,128,152H88V72H224a8,8,0,0,0,0-16ZM80,196.69,51.31,168h57.38Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M136,168,88,216,40,168Z" opacity="0.2"/><path d="M232,64H88a8,8,0,0,0-8,8v88H40a8,8,0,0,0-5.66,13.66l48,48a8,8,0,0,0,11.32,0l48-48A8,8,0,0,0,136,160H96V80H232a8,8,0,0,0,0-16ZM88,204.69,59.31,176h57.38Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 301 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,96H32L80,48Z" opacity="0.2"/><path d="M224,184H88V104h40a8,8,0,0,0,5.66-13.66l-48-48a8,8,0,0,0-11.32,0l-48,48A8,8,0,0,0,32,104H72v88a8,8,0,0,0,8,8H224a8,8,0,0,0,0-16ZM80,59.31,108.69,88H51.31Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M136,96H40L88,48Z" opacity="0.2"/><path d="M232,184H96V104h40a8,8,0,0,0,5.66-13.66l-48-48a8,8,0,0,0-11.32,0l-48,48A8,8,0,0,0,40,104H80v88a8,8,0,0,0,8,8H232a8,8,0,0,0,0-16ZM88,59.31,116.69,88H59.31Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 297 B After Width: | Height: | Size: 297 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,96H128l48-48Z" opacity="0.2"/><path d="M229.66,90.34l-48-48a8,8,0,0,0-11.32,0l-48,48A8,8,0,0,0,128,104h40v80H32a8,8,0,0,0,0,16H176a8,8,0,0,0,8-8V104h40a8,8,0,0,0,5.66-13.66ZM147.31,88,176,59.31,204.69,88Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,96H120l48-48Z" opacity="0.2"/><path d="M221.66,90.34l-48-48a8,8,0,0,0-11.32,0l-48,48A8,8,0,0,0,120,104h40v80H24a8,8,0,0,0,0,16H168a8,8,0,0,0,8-8V104h40a8,8,0,0,0,5.66-13.66ZM139.31,88,168,59.31,196.69,88Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 309 B After Width: | Height: | Size: 309 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,80l-48,48V32Z" opacity="0.2"/><path d="M213.66,74.34l-48-48A8,8,0,0,0,152,32V72H64a8,8,0,0,0-8,8V224a8,8,0,0,0,16,0V88h80v40a8,8,0,0,0,13.66,5.66l48-48A8,8,0,0,0,213.66,74.34ZM168,108.69V51.31L196.69,80Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,80l-48,48V32Z" opacity="0.2"/><path d="M221.66,74.34l-48-48A8,8,0,0,0,160,32V72H72a8,8,0,0,0-8,8V224a8,8,0,0,0,16,0V88h80v40a8,8,0,0,0,13.66,5.66l48-48A8,8,0,0,0,221.66,74.34ZM176,108.69V51.31L204.69,80Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 308 B After Width: | Height: | Size: 308 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M160,200H64V104Z" opacity="0.2"/><path d="M224,40a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,40ZM181.66,82.34a8,8,0,0,1,0,11.32L123.31,152l42.35,42.34A8,8,0,0,1,160,208H64a8,8,0,0,1-8-8V104a8,8,0,0,1,13.66-5.66L112,140.69l58.34-58.35A8,8,0,0,1,181.66,82.34ZM140.69,192l-34.34-34.34h0L72,123.31V192Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M168,208H72V112Z" opacity="0.2"/><path d="M232,48a8,8,0,0,1-8,8H48a8,8,0,0,1,0-16H224A8,8,0,0,1,232,48ZM189.66,90.34a8,8,0,0,1,0,11.32L131.31,160l42.35,42.34A8,8,0,0,1,168,216H72a8,8,0,0,1-8-8V112a8,8,0,0,1,13.66-5.66L120,148.69l58.34-58.35A8,8,0,0,1,189.66,90.34ZM148.69,200l-34.34-34.34h0L80,131.31V200Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 405 B After Width: | Height: | Size: 405 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><g opacity="0.2"><polygon points="192 104 192 200 96 200 192 104"/></g><path d="M224,40a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,40Zm-24,64v96a8,8,0,0,1-8,8H96a8,8,0,0,1-5.66-13.66L132.69,152,74.34,93.66A8,8,0,0,1,85.66,82.34L144,140.69l42.34-42.35A8,8,0,0,1,200,104Zm-16,19.31-34.34,34.35h0L115.31,192H184Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M192,104v96H96Z" opacity="0.2"/><path d="M224,40a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,40Zm-24,64v96a8,8,0,0,1-8,8H96a8,8,0,0,1-5.66-13.66L132.69,152,74.34,93.66A8,8,0,0,1,85.66,82.34L144,140.69l42.34-42.35A8,8,0,0,1,200,104Zm-16,19.31-34.34,34.35h0L115.31,192H184Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 377 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M160,56,64,152V56Z" opacity="0.2"/><path d="M224,216a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,216ZM56,152V56a8,8,0,0,1,8-8h96a8,8,0,0,1,5.66,13.66L123.31,104l58.35,58.34a8,8,0,0,1-11.32,11.32L112,115.31,69.66,157.66A8,8,0,0,1,56,152Zm16-19.31,34.34-34.35h0L140.69,64H72Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M168,48,72,144V48Z" opacity="0.2"/><path d="M232,208a8,8,0,0,1-8,8H48a8,8,0,0,1,0-16H224A8,8,0,0,1,232,208ZM64,144V48a8,8,0,0,1,8-8h96a8,8,0,0,1,5.66,13.66L131.31,96l58.35,58.34a8,8,0,0,1-11.32,11.32L120,107.31,77.66,149.66A8,8,0,0,1,64,144Zm16-19.31,34.34-34.35h0L148.69,56H80Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 379 B After Width: | Height: | Size: 378 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,48V96H168ZM40,208l48-48H40Z" opacity="0.2"/><path d="M219.06,40.61a8,8,0,0,0-8.72,1.73L194.28,58.41C174.13,41.1,151.36,32,128,32,85.18,32,59.42,57.27,58.34,58.34A8,8,0,0,0,69.66,69.66C69.87,69.44,91.73,48,128,48c23.17,0,41.92,10.85,54.92,21.76L162.34,90.34A8,8,0,0,0,168,104h48a8,8,0,0,0,8-8V48A8,8,0,0,0,219.06,40.61ZM208,88H187.31L208,67.31Zm-21.66,98.34c-.21.22-22.07,21.66-58.34,21.66-23.17,0-41.92-10.85-54.92-21.76l20.58-20.58A8,8,0,0,0,88,152H40a8,8,0,0,0-8,8v48a8,8,0,0,0,13.66,5.66l16.06-16.07C81.87,214.9,104.64,224,128,224c42.82,0,68.58-25.27,69.66-26.34a8,8,0,0,0-11.32-11.32ZM48,168H68.69L48,188.69Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,128a88,88,0,1,1-88-88A88,88,0,0,1,216,128Z" opacity="0.2"/><path d="M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1,0-16h28.69L182.06,73.37a79.56,79.56,0,0,0-56.13-23.43h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27a96,96,0,0,1,135,.79L208,76.69V48a8,8,0,0,1,16,0ZM186.41,183.29a80,80,0,0,1-112.47-.66L59.31,168H88a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V179.31l14.63,14.63A95.43,95.43,0,0,0,130,222.06h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 717 B After Width: | Height: | Size: 576 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M40,48,88,96H40ZM168,160l48,48V160Z" opacity="0.2"/><path d="M95.39,99.06a8,8,0,0,0-1.73-8.72L73.08,69.76C86.08,58.85,104.83,48,128,48c35.95,0,58.13,21.44,58.36,21.68a8,8,0,0,0,11.3-11.34C196.58,57.27,170.82,32,128,32c-23.36,0-46.13,9.1-66.28,26.41L45.66,42.34A8,8,0,0,0,32,48V96a8,8,0,0,0,8,8H88A8,8,0,0,0,95.39,99.06ZM48,88V67.31L68.69,88Zm168,64H168a8,8,0,0,0-5.66,13.66l20.58,20.58C169.92,197.15,151.17,208,128,208c-35.84,0-58-21.32-58.36-21.67a8,8,0,0,0-11.3,11.33C59.42,198.73,85.18,224,128,224c23.36,0,46.13-9.1,66.28-26.41l16.06,16.07A8,8,0,0,0,224,208V160A8,8,0,0,0,216,152Zm-8,36.69L187.31,168H208Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,128a88,88,0,1,1-88-88A88,88,0,0,1,216,128Z" opacity="0.2"/><path d="M88,104H40a8,8,0,0,1-8-8V48a8,8,0,0,1,16,0V76.69L62.63,62.06A95.43,95.43,0,0,1,130,33.94h.53a95.36,95.36,0,0,1,67.07,27.33,8,8,0,0,1-11.18,11.44,79.52,79.52,0,0,0-55.89-22.77h-.45A79.56,79.56,0,0,0,73.94,73.37L59.31,88H88a8,8,0,0,1,0,16Zm128,48H168a8,8,0,0,0,0,16h28.69l-14.63,14.63a79.56,79.56,0,0,1-56.13,23.43h-.45a79.52,79.52,0,0,1-55.89-22.77,8,8,0,1,0-11.18,11.44,95.36,95.36,0,0,0,67.07,27.33H126a95.43,95.43,0,0,0,67.36-28.12L208,179.31V208a8,8,0,0,0,16,0V160A8,8,0,0,0,216,152Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 708 B After Width: | Height: | Size: 659 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,80H144l32-32ZM80,208l32-32H48Z" opacity="0.2"/><path d="M112,168H88V48a8,8,0,0,0-16,0V168H48a8,8,0,0,0-5.66,13.66l32,32a8,8,0,0,0,11.32,0l32-32A8,8,0,0,0,112,168ZM80,196.69,67.31,184H92.69ZM213.66,74.34l-32-32a8,8,0,0,0-11.32,0l-32,32A8,8,0,0,0,144,88h24V208a8,8,0,0,0,16,0V88h24a8,8,0,0,0,5.66-13.66ZM163.31,72,176,59.31,188.69,72Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M176,48V208H80V48Z" opacity="0.2"/><path d="M117.66,170.34a8,8,0,0,1,0,11.32l-32,32a8,8,0,0,1-11.32,0l-32-32a8,8,0,0,1,11.32-11.32L72,188.69V48a8,8,0,0,1,16,0V188.69l18.34-18.35A8,8,0,0,1,117.66,170.34Zm96-96-32-32a8,8,0,0,0-11.32,0l-32,32a8,8,0,0,0,11.32,11.32L168,67.31V208a8,8,0,0,0,16,0V67.31l18.34,18.35a8,8,0,0,0,11.32-11.32Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 437 B After Width: | Height: | Size: 431 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M24,128,56,96v64ZM200,96v64l32-32Z" opacity="0.2"/><path d="M237.66,122.34l-32-32A8,8,0,0,0,192,96v24H64V96a8,8,0,0,0-13.66-5.66l-32,32a8,8,0,0,0,0,11.32l32,32A8,8,0,0,0,64,160V136H192v24a8,8,0,0,0,13.66,5.66l32-32A8,8,0,0,0,237.66,122.34ZM48,140.69,35.31,128,48,115.31Zm160,0V115.31L220.69,128Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,128l-32,32H56L24,128,56,96H200Z" opacity="0.2"/><path d="M237.66,133.66l-32,32a8,8,0,0,1-11.32-11.32L212.69,136H43.31l18.35,18.34a8,8,0,0,1-11.32,11.32l-32-32a8,8,0,0,1,0-11.32l32-32a8,8,0,0,1,11.32,11.32L43.31,120H212.69l-18.35-18.34a8,8,0,0,1,11.32-11.32l32,32A8,8,0,0,1,237.66,133.66Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 395 B After Width: | Height: | Size: 392 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,96,96,64h64ZM96,192h64l-32-32Zm64-64,32,32V96ZM64,96v64l32-32Z" opacity="0.2"/><path d="M122.34,101.66a8,8,0,0,0,11.32,0l32-32A8,8,0,0,0,160,56H136V24a8,8,0,0,0-16,0V56H96a8,8,0,0,0-5.66,13.66ZM140.69,72,128,84.69,115.31,72Zm-7,82.34a8,8,0,0,0-11.32,0l-32,32A8,8,0,0,0,96,200h24v32a8,8,0,0,0,16,0V200h24a8,8,0,0,0,5.66-13.66ZM115.31,184,128,171.31,140.69,184ZM232,120H200V96a8,8,0,0,0-13.66-5.66l-32,32a8,8,0,0,0,0,11.32l32,32A8,8,0,0,0,200,160V136h32a8,8,0,0,0,0-16Zm-48,20.69L171.31,128,184,115.31Zm-82.34-18.35-32-32A8,8,0,0,0,56,96v24H24a8,8,0,0,0,0,16H56v24a8,8,0,0,0,13.66,5.66l32-32A8,8,0,0,0,101.66,122.34ZM72,140.69V115.31L84.69,128Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48Z" opacity="0.2"/><path d="M90.34,69.66a8,8,0,0,1,11.32-11.32L120,76.69V24a8,8,0,0,1,16,0V76.69l18.34-18.35a8,8,0,0,1,11.32,11.32l-32,32a8,8,0,0,1-11.32,0Zm43.32,84.68a8,8,0,0,0-11.32,0l-32,32a8,8,0,0,0,11.32,11.32L120,179.31V232a8,8,0,0,0,16,0V179.31l18.34,18.35a8,8,0,0,0,11.32-11.32ZM232,120H179.31l18.35-18.34a8,8,0,0,0-11.32-11.32l-32,32a8,8,0,0,0,0,11.32l32,32a8,8,0,0,0,11.32-11.32L179.31,136H232a8,8,0,0,0,0-16Zm-130.34,2.34-32-32a8,8,0,0,0-11.32,11.32L76.69,120H24a8,8,0,0,0,0,16H76.69L58.34,154.34a8,8,0,0,0,11.32,11.32l32-32A8,8,0,0,0,101.66,122.34Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 747 B After Width: | Height: | Size: 754 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M64,96l32,32L64,160Zm96,32,32,32V96Z" opacity="0.2"/><path d="M136,40V216a8,8,0,0,1-16,0V40a8,8,0,0,1,16,0Zm-34.34,82.34a8,8,0,0,1,0,11.32l-32,32A8,8,0,0,1,56,160V136H16a8,8,0,0,1,0-16H56V96a8,8,0,0,1,13.66-5.66Zm-17,5.66L72,115.31v25.38ZM248,128a8,8,0,0,1-8,8H200v24a8,8,0,0,1-13.66,5.66l-32-32a8,8,0,0,1,0-11.32l32-32A8,8,0,0,1,200,96v24h40A8,8,0,0,1,248,128Zm-64-12.69L171.31,128,184,140.69Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,56V200a16,16,0,0,1-16,16H32a16,16,0,0,1-16-16V56A16,16,0,0,1,32,40H224A16,16,0,0,1,240,56Z" opacity="0.2"/><path d="M136,40V216a8,8,0,0,1-16,0V40a8,8,0,0,1,16,0ZM69.66,90.34a8,8,0,0,0-11.32,11.32L76.69,120H16a8,8,0,0,0,0,16H76.69L58.34,154.34a8,8,0,0,0,11.32,11.32l32-32a8,8,0,0,0,0-11.32ZM240,120H179.31l18.35-18.34a8,8,0,0,0-11.32-11.32l-32,32a8,8,0,0,0,0,11.32l32,32a8,8,0,0,0,11.32-11.32L179.31,136H240a8,8,0,0,0,0-16Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 527 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,96,96,64h64ZM96,192h64l-32-32Z" opacity="0.2"/><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM90.34,69.66A8,8,0,0,1,96,56h24V16a8,8,0,0,1,16,0V56h24a8,8,0,0,1,5.66,13.66l-32,32a8,8,0,0,1-11.32,0Zm25,2.34L128,84.69,140.69,72Zm50.35,114.34A8,8,0,0,1,160,200H136v40a8,8,0,0,1-16,0V200H96a8,8,0,0,1-5.66-13.66l32-32a8,8,0,0,1,11.32,0Zm-25-2.34L128,171.31,115.31,184Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,32V224a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V32A16,16,0,0,1,56,16H200A16,16,0,0,1,216,32Z" opacity="0.2"/><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM122.34,101.66a8,8,0,0,0,11.32,0l32-32a8,8,0,0,0-11.32-11.32L136,76.69V16a8,8,0,0,0-16,0V76.69L101.66,58.34A8,8,0,0,0,90.34,69.66Zm11.32,52.68a8,8,0,0,0-11.32,0l-32,32a8,8,0,0,0,11.32,11.32L120,179.31V240a8,8,0,0,0,16,0V179.31l18.34,18.35a8,8,0,0,0,11.32-11.32Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 493 B After Width: | Height: | Size: 545 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M192,112H144V64Zm-80,80V144H64Z" opacity="0.2"/><path d="M213.66,42.34a8,8,0,0,0-11.32,0L168,76.69,149.66,58.34A8,8,0,0,0,136,64v48a8,8,0,0,0,8,8h48a8,8,0,0,0,5.66-13.66L179.31,88l34.35-34.34A8,8,0,0,0,213.66,42.34ZM152,104V83.31L172.69,104Zm-40,32H64a8,8,0,0,0-5.66,13.66L76.69,168,42.34,202.34a8,8,0,0,0,11.32,11.32L88,179.31l18.34,18.35A8,8,0,0,0,120,192V144A8,8,0,0,0,112,136Zm-8,36.69L83.31,152H104Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48Z" opacity="0.2"/><path d="M213.66,53.66,163.31,104H192a8,8,0,0,1,0,16H144a8,8,0,0,1-8-8V64a8,8,0,0,1,16,0V92.69l50.34-50.35a8,8,0,0,1,11.32,11.32ZM112,136H64a8,8,0,0,0,0,16H92.69L42.34,202.34a8,8,0,0,0,11.32,11.32L104,163.31V192a8,8,0,0,0,16,0V144A8,8,0,0,0,112,136Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 504 B After Width: | Height: | Size: 461 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M192,104H152V64Zm-88,88V152H64Zm48,0,40-40H152Zm-48-88V64L64,104Z" opacity="0.2"/><path d="M152,112h40a8,8,0,0,0,5.66-13.66L183.31,84l30.35-30.34a8,8,0,0,0-11.32-11.32L172,72.69,157.66,58.34A8,8,0,0,0,144,64v40A8,8,0,0,0,152,112Zm8-28.69L172.69,96H160ZM104,144H64a8,8,0,0,0-5.66,13.66L72.69,172,42.34,202.34a8,8,0,0,0,11.32,11.32L84,183.31l14.34,14.35A8,8,0,0,0,112,192V152A8,8,0,0,0,104,144Zm-8,28.69L83.31,160H96Zm87.31-.69,14.35-14.34A8,8,0,0,0,192,144H152a8,8,0,0,0-8,8v40a8,8,0,0,0,13.66,5.66L172,183.31l30.34,30.35a8,8,0,0,0,11.32-11.32Zm-23.31.69V160h12.69ZM107.06,56.61a8,8,0,0,0-8.72,1.73L84,72.69,53.66,42.34A8,8,0,0,0,42.34,53.66L72.69,84,58.34,98.34A8,8,0,0,0,64,112h40a8,8,0,0,0,8-8V64A8,8,0,0,0,107.06,56.61ZM96,96H83.31L96,83.31Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48Z" opacity="0.2"/><path d="M144,104V64a8,8,0,0,1,16,0V84.69l42.34-42.35a8,8,0,0,1,11.32,11.32L171.31,96H192a8,8,0,0,1,0,16H152A8,8,0,0,1,144,104Zm-40,40H64a8,8,0,0,0,0,16H84.69L42.34,202.34a8,8,0,0,0,11.32,11.32L96,171.31V192a8,8,0,0,0,16,0V152A8,8,0,0,0,104,144Zm67.31,16H192a8,8,0,0,0,0-16H152a8,8,0,0,0-8,8v40a8,8,0,0,0,16,0V171.31l42.34,42.35a8,8,0,0,0,11.32-11.32ZM104,56a8,8,0,0,0-8,8V84.69L53.66,42.34A8,8,0,0,0,42.34,53.66L84.69,96H64a8,8,0,0,0,0,16h40a8,8,0,0,0,8-8V64A8,8,0,0,0,104,56Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 844 B After Width: | Height: | Size: 689 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,176l-32,32V144ZM80,112V48L48,80Z" opacity="0.2"/><path d="M213.66,170.34l-32-32A8,8,0,0,0,168,144v24H48a8,8,0,0,0,0,16H168v24a8,8,0,0,0,13.66,5.66l32-32A8,8,0,0,0,213.66,170.34ZM184,188.69V163.31L196.69,176Zm-109.66-71A8,8,0,0,0,88,112V88H208a8,8,0,0,0,0-16H88V48a8,8,0,0,0-13.66-5.66l-32,32a8,8,0,0,0,0,11.32ZM72,67.31V92.69L59.31,80Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,80v96H48V80Z" opacity="0.2"/><path d="M213.66,181.66l-32,32a8,8,0,0,1-11.32-11.32L188.69,184H48a8,8,0,0,1,0-16H188.69l-18.35-18.34a8,8,0,0,1,11.32-11.32l32,32A8,8,0,0,1,213.66,181.66Zm-139.32-64a8,8,0,0,0,11.32-11.32L67.31,88H208a8,8,0,0,0,0-16H67.31L85.66,53.66A8,8,0,0,0,74.34,42.34l-32,32a8,8,0,0,0,0,11.32Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 440 B After Width: | Height: | Size: 415 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M160,200l-32,32L96,200Z" opacity="0.2"/><path d="M184,32a8,8,0,0,0-8,8v60.69l-48,48-48-48V40a8,8,0,0,0-16,0v64a8,8,0,0,0,2.34,5.66L120,163.31V192H96a8,8,0,0,0-5.66,13.66l32,32a8,8,0,0,0,11.32,0l32-32A8,8,0,0,0,160,192H136V163.31l53.66-53.65A8,8,0,0,0,192,104V40A8,8,0,0,0,184,32ZM128,220.69,115.31,208h25.38Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M184,40v64l-56,56L72,104V40Z" opacity="0.2"/><path d="M192,40v64a8,8,0,0,1-2.34,5.66L136,163.31v49.38l18.34-18.35a8,8,0,0,1,11.32,11.32l-32,32a8,8,0,0,1-11.32,0l-32-32a8,8,0,0,1,11.32-11.32L120,212.69V163.31L66.34,109.66A8,8,0,0,1,64,104V40a8,8,0,0,1,16,0v60.69l48,48,48-48V40a8,8,0,0,1,16,0Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 408 B After Width: | Height: | Size: 392 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,24l32,32H96Zm0,208,32-32H96ZM200,96v64l32-32ZM24,128l32,32V96Z" opacity="0.2"/><path d="M96,64h24V96a8,8,0,0,0,16,0V64h24a8,8,0,0,0,5.66-13.66l-32-32a8,8,0,0,0-11.32,0l-32,32A8,8,0,0,0,96,64Zm32-28.69L140.69,48H115.31ZM160,192H136V160a8,8,0,0,0-16,0v32H96a8,8,0,0,0-5.66,13.66l32,32a8,8,0,0,0,11.32,0l32-32A8,8,0,0,0,160,192Zm-32,28.69L115.31,208h25.38Zm109.66-98.35-32-32A8,8,0,0,0,192,96v24H160a8,8,0,0,0,0,16h32v24a8,8,0,0,0,13.66,5.66l32-32A8,8,0,0,0,237.66,122.34ZM208,140.69V115.31L220.69,128ZM96,136a8,8,0,0,0,0-16H64V96a8,8,0,0,0-13.66-5.66l-32,32a8,8,0,0,0,0,11.32l32,32A8,8,0,0,0,64,160V136Zm-48,4.69L35.31,128,48,115.31Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,128,128,232,24,128,128,24Z" opacity="0.2"/><path d="M90.34,61.66a8,8,0,0,1,0-11.32l32-32a8,8,0,0,1,11.32,0l32,32a8,8,0,0,1-11.32,11.32L136,43.31V96a8,8,0,0,1-16,0V43.31L101.66,61.66A8,8,0,0,1,90.34,61.66Zm64,132.68L136,212.69V160a8,8,0,0,0-16,0v52.69l-18.34-18.35a8,8,0,0,0-11.32,11.32l32,32a8,8,0,0,0,11.32,0l32-32a8,8,0,0,0-11.32-11.32Zm83.32-72-32-32a8,8,0,0,0-11.32,11.32L212.69,120H160a8,8,0,0,0,0,16h52.69l-18.35,18.34a8,8,0,0,0,11.32,11.32l32-32A8,8,0,0,0,237.66,122.34ZM43.31,136H96a8,8,0,0,0,0-16H43.31l18.35-18.34A8,8,0,0,0,50.34,90.34l-32,32a8,8,0,0,0,0,11.32l32,32a8,8,0,0,0,11.32-11.32Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 736 B After Width: | Height: | Size: 704 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M16,128,48,96v64ZM208,96v64l32-32Z" opacity="0.2"/><path d="M136,40V216a8,8,0,0,1-16,0V40a8,8,0,0,1,16,0Zm-32,88a8,8,0,0,1-8,8H56v24a8,8,0,0,1-13.66,5.66l-32-32a8,8,0,0,1,0-11.32l32-32A8,8,0,0,1,56,96v24H96A8,8,0,0,1,104,128ZM40,115.31,27.31,128,40,140.69Zm205.66,18.35-32,32A8,8,0,0,1,200,160V136H160a8,8,0,0,1,0-16h40V96a8,8,0,0,1,13.66-5.66l32,32A8,8,0,0,1,245.66,133.66Zm-17-5.66L216,115.31v25.38Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,56V200a16,16,0,0,1-16,16H32a16,16,0,0,1-16-16V56A16,16,0,0,1,32,40H224A16,16,0,0,1,240,56Z" opacity="0.2"/><path d="M136,40V216a8,8,0,0,1-16,0V40a8,8,0,0,1,16,0ZM96,120H35.31l18.35-18.34A8,8,0,0,0,42.34,90.34l-32,32a8,8,0,0,0,0,11.32l32,32a8,8,0,0,0,11.32-11.32L35.31,136H96a8,8,0,0,0,0-16Zm149.66,2.34-32-32a8,8,0,0,0-11.32,11.32L220.69,120H160a8,8,0,0,0,0,16h60.69l-18.35,18.34a8,8,0,0,0,11.32,11.32l32-32A8,8,0,0,0,245.66,122.34Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 537 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M160,48H96l32-32ZM128,240l32-32H96Z" opacity="0.2"/><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM88.61,51.06a8,8,0,0,1,1.73-8.72l32-32a8,8,0,0,1,11.32,0l32,32A8,8,0,0,1,160,56H136V96a8,8,0,0,1-16,0V56H96A8,8,0,0,1,88.61,51.06ZM115.31,40h25.38L128,27.31Zm52.08,164.94a8,8,0,0,1-1.73,8.72l-32,32a8,8,0,0,1-11.32,0l-32-32A8,8,0,0,1,96,200h24V160a8,8,0,0,1,16,0v40h24A8,8,0,0,1,167.39,204.94ZM140.69,216H115.31L128,228.69Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,32V224a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V32A16,16,0,0,1,56,16H200A16,16,0,0,1,216,32Z" opacity="0.2"/><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM101.66,53.66,120,35.31V96a8,8,0,0,0,16,0V35.31l18.34,18.35a8,8,0,0,0,11.32-11.32l-32-32a8,8,0,0,0-11.32,0l-32,32a8,8,0,0,0,11.32,11.32Zm52.68,148.68L136,220.69V160a8,8,0,0,0-16,0v60.69l-18.34-18.35a8,8,0,0,0-11.32,11.32l32,32a8,8,0,0,0,11.32,0l32-32a8,8,0,0,0-11.32-11.32Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 546 B After Width: | Height: | Size: 557 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,48V96L160,48ZM48,208H96L48,160Z" opacity="0.2"/><path d="M208,40H160a8,8,0,0,0-5.66,13.66L172.69,72l-34.35,34.34a8,8,0,0,0,11.32,11.32L184,83.31l18.34,18.35A8,8,0,0,0,216,96V48A8,8,0,0,0,208,40Zm-8,36.69L179.31,56H200Zm-93.66,61.65L72,172.69,53.66,154.34A8,8,0,0,0,40,160v48a8,8,0,0,0,8,8H96a8,8,0,0,0,5.66-13.66L83.31,184l34.35-34.34a8,8,0,0,0-11.32-11.32ZM56,200V179.31L76.69,200Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48Z" opacity="0.2"/><path d="M216,48V96a8,8,0,0,1-16,0V67.31l-50.34,50.35a8,8,0,0,1-11.32-11.32L188.69,56H160a8,8,0,0,1,0-16h48A8,8,0,0,1,216,48ZM106.34,138.34,56,188.69V160a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8H96a8,8,0,0,0,0-16H67.31l50.35-50.34a8,8,0,0,0-11.32-11.32Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 487 B After Width: | Height: | Size: 456 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,48V96L160,48ZM48,208H96L48,160Zm160,0V160l-48,48ZM48,96,96,48H48Z" opacity="0.2"/><path d="M98.34,146.34,72,172.69,53.66,154.34A8,8,0,0,0,40,160v48a8,8,0,0,0,8,8H96a8,8,0,0,0,5.66-13.66L83.31,184l26.35-26.34a8,8,0,0,0-11.32-11.32ZM56,200V179.31L76.69,200ZM83.31,72l18.35-18.34A8,8,0,0,0,96,40H48a8,8,0,0,0-8,8V96a8,8,0,0,0,13.66,5.66L72,83.31l26.34,26.35a8,8,0,0,0,11.32-11.32ZM56,76.69V56H76.69ZM208,40H160a8,8,0,0,0-5.66,13.66L172.69,72,146.34,98.34a8,8,0,0,0,11.32,11.32L184,83.31l18.34,18.35A8,8,0,0,0,216,96V48A8,8,0,0,0,208,40Zm-8,36.69L179.31,56H200Zm11.06,75.92a8,8,0,0,0-8.72,1.73L184,172.69l-26.34-26.35a8,8,0,0,0-11.32,11.32L172.69,184l-18.35,18.34A8,8,0,0,0,160,216h48a8,8,0,0,0,8-8V160A8,8,0,0,0,211.06,152.61ZM200,200H179.31L200,179.31Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,48V208H48V48Z" opacity="0.2"/><path d="M216,48V96a8,8,0,0,1-16,0V67.31l-42.34,42.35a8,8,0,0,1-11.32-11.32L188.69,56H160a8,8,0,0,1,0-16h48A8,8,0,0,1,216,48ZM98.34,146.34,56,188.69V160a8,8,0,0,0-16,0v48a8,8,0,0,0,8,8H96a8,8,0,0,0,0-16H67.31l42.35-42.34a8,8,0,0,0-11.32-11.32ZM208,152a8,8,0,0,0-8,8v28.69l-42.34-42.35a8,8,0,0,0-11.32,11.32L188.69,200H160a8,8,0,0,0,0,16h48a8,8,0,0,0,8-8V160A8,8,0,0,0,208,152ZM67.31,56H96a8,8,0,0,0,0-16H48a8,8,0,0,0-8,8V96a8,8,0,0,0,16,0V67.31l42.34,42.35a8,8,0,0,0,11.32-11.32Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 855 B After Width: | Height: | Size: 614 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M32,184H96L64,216Zm128,0,32,32,32-32Z" opacity="0.2"/><path d="M231.39,180.94A8,8,0,0,0,224,176H200V136a8,8,0,0,0-2.34-5.66L136,68.69V24a8,8,0,0,0-16,0V68.69L58.34,130.34A8,8,0,0,0,56,136v40H32a8,8,0,0,0-5.66,13.66l32,32a8,8,0,0,0,11.32,0l32-32A8,8,0,0,0,96,176H72V139.31l56-56,56,56V176H160a8,8,0,0,0-5.66,13.66l32,32a8,8,0,0,0,11.32,0l32-32A8,8,0,0,0,231.39,180.94ZM64,204.69,51.31,192H76.69Zm128,0L179.31,192h25.38Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M192,136v80H64V136l64-64Z" opacity="0.2"/><path d="M229.66,189.66l-32,32a8,8,0,0,1-11.32,0l-32-32a8,8,0,0,1,11.32-11.32L184,196.69V139.31l-56-56-56,56v57.38l18.34-18.35a8,8,0,0,1,11.32,11.32l-32,32a8,8,0,0,1-11.32,0l-32-32a8,8,0,0,1,11.32-11.32L56,196.69V136a8,8,0,0,1,2.34-5.66L120,68.69V24a8,8,0,0,1,16,0V68.69l61.66,61.65A8,8,0,0,1,200,136v60.69l18.34-18.35a8,8,0,0,1,11.32,11.32Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 518 B After Width: | Height: | Size: 483 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M160,56H96l32-32ZM128,232l32-32H96Z" opacity="0.2"/><path d="M160,192H136V64h24a8,8,0,0,0,5.66-13.66l-32-32a8,8,0,0,0-11.32,0l-32,32A8,8,0,0,0,96,64h24V192H96a8,8,0,0,0-5.66,13.66l32,32a8,8,0,0,0,11.32,0l32-32A8,8,0,0,0,160,192ZM128,35.31,140.69,48H115.31Zm0,185.38L115.31,208h25.38Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M160,56V200l-32,32L96,200V56l32-32Z" opacity="0.2"/><path d="M165.66,194.34a8,8,0,0,1,0,11.32l-32,32a8,8,0,0,1-11.32,0l-32-32a8,8,0,0,1,11.32-11.32L120,212.69V43.31L101.66,61.66A8,8,0,0,1,90.34,50.34l32-32a8,8,0,0,1,11.32,0l32,32a8,8,0,0,1-11.32,11.32L136,43.31V212.69l18.34-18.35A8,8,0,0,1,165.66,194.34Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 405 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,104v96H72V168h96V104Z" opacity="0.2"/><path d="M56,136a8,8,0,0,1-8,8H24a8,8,0,0,1,0-16h8V64H24a8,8,0,0,1,0-16H40v0a8,8,0,0,1,6.78,3.74L80,104.91l33.22-53.15A8,8,0,0,1,120,48v0h16a8,8,0,0,1,0,16h-8v64h8a8,8,0,0,1,0,16H112a8,8,0,0,1,0-16V83.89L86.78,124.24a8,8,0,0,1-13.56,0L48,83.89V128A8,8,0,0,1,56,136Zm112-24h72a8,8,0,0,0,0-16H168a8,8,0,0,0,0,16Zm72,16H168a8,8,0,0,0,0,16h72a8,8,0,0,0,0-16Zm0,32H72a8,8,0,0,0,0,16H240a8,8,0,0,0,0-16Zm0,32H72a8,8,0,0,0,0,16H240a8,8,0,0,0,0-16Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,104v96H80V168h88V104Z" opacity="0.2"/><path d="M56,136a8,8,0,0,1-8,8H24a8,8,0,0,1,0-16h8V64H24a8,8,0,0,1,0-16H40v0a8,8,0,0,1,6.78,3.74L80,104.91l33.22-53.15A8,8,0,0,1,120,48v0h16a8,8,0,0,1,0,16h-8v64h8a8,8,0,0,1,0,16H112a8,8,0,0,1,0-16V83.89L86.78,124.24a8,8,0,0,1-13.56,0L48,83.89V128A8,8,0,0,1,56,136Zm112-24h64a8,8,0,0,0,0-16H168a8,8,0,0,0,0,16Zm64,16H168a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Zm0,32H80a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16Zm0,32H80a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 583 B After Width: | Height: | Size: 583 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,104v96H160V104Z" opacity="0.2"/><path d="M152,104a8,8,0,0,1,8-8h80a8,8,0,0,1,0,16H160A8,8,0,0,1,152,104Zm88,24H160a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Zm0,32H160a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Zm0,32H72a8,8,0,0,0,0,16H240a8,8,0,0,0,0-16ZM80,176a56.06,56.06,0,0,1-56-56,55.49,55.49,0,0,1,4.11-21A28,28,0,0,1,44,48a8,8,0,0,1,3.89,1l69.93,38.85A12,12,0,0,0,116,64a8,8,0,0,1,0-16,28,28,0,0,1,0,56,8,8,0,0,1-3.89-1l-40-22.21A40,40,0,0,0,72,159.2V120a8,8,0,0,1,16,0v39.19a40.09,40.09,0,0,0,29.73-25.86,8,8,0,0,1,15.08,5.34A56.09,56.09,0,0,1,80,176ZM36.23,85.14a56.33,56.33,0,0,1,17.5-14.58L42.18,64.14a12,12,0,0,0-6,21Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,104v96H80V168h48V104Z" opacity="0.2"/><path d="M128,96H232a8,8,0,0,1,0,16H128a8,8,0,0,1,0-16Zm104,32H128a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16Zm0,32H80a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16Zm0,32H80a8,8,0,0,0,0,16H232a8,8,0,0,0,0-16ZM96,144a8,8,0,0,0,0-16H88V64h32v8a8,8,0,0,0,16,0V56a8,8,0,0,0-8-8H32a8,8,0,0,0-8,8V72a8,8,0,0,0,16,0V64H72v64H64a8,8,0,0,0,0,16Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 715 B After Width: | Height: | Size: 458 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M88,48v8A32,32,0,0,1,56,88H32V80A32,32,0,0,1,64,48Z" opacity="0.2"/><path d="M216,79v1a40,40,0,0,1-40,40H136v80h8a16,16,0,0,0,10.67-27.93,8,8,0,0,1,10.66-11.92A32,32,0,0,1,144,216h-8v16a8,8,0,0,1-16,0V216H96a8,8,0,0,1,0-16h24V120H96a16,16,0,0,0,0,32,8,8,0,0,1,0,16,32,32,0,0,1,0-64h24V24a8,8,0,0,1,16,0v80h40a24,24,0,0,0,24-24V79a23,23,0,0,0-23-23H160a8,8,0,0,1,0-16h17a39,39,0,0,1,39,39ZM56,96H32a8,8,0,0,1-8-8V80A40,40,0,0,1,64,40H96a8,8,0,0,1,0,16A40,40,0,0,1,56,96ZM80,56H64A24,24,0,0,0,40,80H56A24,24,0,0,0,80,56Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 618 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M203.45,133.33,173.63,49.05a48,48,0,0,0-90.9-1L53.19,131.59a80,80,0,1,0,150.26,1.74ZM128,200a40,40,0,1,1,40-40A40,40,0,0,1,128,200Z" opacity="0.2"/><path d="M128,112a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,112Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,192Zm83-61.34L181.2,46.47a56,56,0,0,0-106-1.14h0l-29.51,83.5A88,88,0,1,0,211,130.66ZM128,232a72.05,72.05,0,0,1-67.33-97.57,1.34,1.34,0,0,1,.07-.18L90.28,50.66h0a40,40,0,0,1,75.74.88l.06.18L195.9,136A72.05,72.05,0,0,1,128,232Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 575 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M245.65,108.46l-81.19,81.19A8,8,0,0,1,150.87,185c-7.09-53.14-42.41-87.8-59.45-99.76A8,8,0,0,1,90.33,73L129,34.33a8,8,0,0,1,12.2,1.09c12,17,46.62,52.36,99.76,59.45A8,8,0,0,1,245.65,108.46Z" opacity="0.2"/><path d="M255.15,97.72A16,16,0,0,0,242,86.94a136.46,136.46,0,0,1-51.65-18l10.31-10.3a25,25,0,0,0-35.32-35.32l-13.2,13.21c-2.33-2.8-3.81-4.84-4.41-5.69a16,16,0,0,0-24.41-2.15L84.68,67.36a16,16,0,0,0,2.14,24.4c.86.6,2.9,2.08,5.7,4.41L7.31,181.37a25,25,0,0,0,35.32,35.32l82.3-82.31a136.63,136.63,0,0,1,18,51.65,16,16,0,0,0,10.77,13.12,16.21,16.21,0,0,0,5.15.85,15.88,15.88,0,0,0,11.26-4.69l81.18-81.19A15.86,15.86,0,0,0,255.15,97.72ZM176.69,34.63a9,9,0,1,1,12.68,12.68L176.82,59.86A152.5,152.5,0,0,1,163.1,48.21ZM31.31,205.37a9,9,0,1,1-12.68-12.68l85.58-85.58a150.89,150.89,0,0,1,11.65,13.71ZM158.8,183.92C150,118.29,101.52,82.52,96,78.67L134.66,40c3.86,5.5,39.63,54,105.25,62.78Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 981 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,112H144V48a8,8,0,0,1,8-8h8A72,72,0,0,1,232,112Z" opacity="0.2"/><path d="M160,32h-8a16,16,0,0,0-16,16v56H55.2A40.07,40.07,0,0,0,16,72a8,8,0,0,0,0,16,24,24,0,0,1,24,24,80.09,80.09,0,0,0,80,80h40a80,80,0,0,0,0-160Zm63.48,72H166.81l41.86-33.49A63.73,63.73,0,0,1,223.48,104ZM160,48a63.59,63.59,0,0,1,36.69,11.61L152,95.35V48Zm0,128H120a64.09,64.09,0,0,1-63.5-56h167A64.09,64.09,0,0,1,160,176Zm-56,48a16,16,0,1,1-16-16A16,16,0,0,1,104,224Zm104,0a16,16,0,1,1-16-16A16,16,0,0,1,208,224Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 584 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M184,120v80H72V120Z" opacity="0.2"/><path d="M240,192h-8V130.57l1.49,2.08a8,8,0,1,0,13-9.3l-40-56a8,8,0,0,0-2-1.94L137,18.77l-.1-.07a16,16,0,0,0-17.76,0l-.1.07L51.45,65.42a8,8,0,0,0-2,1.94l-40,56a8,8,0,1,0,13,9.3L24,130.57V192H16a8,8,0,0,0,0,16H240a8,8,0,0,0,0-16ZM40,108.17,61.7,77.79,128,32l66.3,45.78L216,108.17V192H192V120a8,8,0,0,0-8-8H72a8,8,0,0,0-8,8v72H40Zm88,42L97,128H159Zm48-14.62v48.91L141.76,160ZM114.24,160,80,184.46V135.55ZM128,169.83,159,192H97ZM104,88a8,8,0,0,1,8-8h32a8,8,0,1,1,0,16H112A8,8,0,0,1,104,88Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 622 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M88,176a20,20,0,1,1,20-20A20,20,0,0,1,88,176Zm64-48v24a64,64,0,0,1-64,64h40a64,64,0,0,0,64-64V128Z" opacity="0.2"/><path d="M88,128a28,28,0,1,0,28,28A28,28,0,0,0,88,128Zm0,40a12,12,0,1,1,12-12A12,12,0,0,1,88,168Zm160-48H223.7A104,104,0,0,0,16,128v24a72.08,72.08,0,0,0,72,72h40a72.08,72.08,0,0,0,72-72V136h48a8,8,0,0,0,0-16Zm-64,32a56.06,56.06,0,0,1-50.46,55.72A71.87,71.87,0,0,0,160,152V136h24Zm-32-32a8,8,0,0,0-8,8v24a56,56,0,0,1-112,0V128a88,88,0,0,1,175.64-8Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 562 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M231.93,97.06l-13.87,104a8,8,0,0,1-7.93,6.94H45.87a8,8,0,0,1-7.93-6.94l-13.87-104A8,8,0,0,1,32,88H224A8,8,0,0,1,231.93,97.06Z" opacity="0.2"/><path d="M136,120v56a8,8,0,0,1-16,0V120a8,8,0,0,1,16,0ZM239.86,98.11,226,202.12A16,16,0,0,1,210.13,216H45.87A16,16,0,0,1,30,202.12l-13.87-104A16,16,0,0,1,32,80H68.37L122,18.73a8,8,0,0,1,12,0L187.63,80H224a16,16,0,0,1,15.85,18.11ZM89.63,80h76.74L128,36.15ZM224,96H32L45.87,200H210.13Zm-51.16,23.2-5.6,56A8,8,0,0,0,174.4,184a7.44,7.44,0,0,0,.81,0,8,8,0,0,0,7.95-7.2l5.6-56a8,8,0,0,0-15.92-1.6Zm-89.68,0a8,8,0,0,0-15.92,1.6l5.6,56a8,8,0,0,0,8,7.2,7.44,7.44,0,0,0,.81,0,8,8,0,0,0,7.16-8.76Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,88,216.93,201.06A8,8,0,0,1,209,208H47a8,8,0,0,1-7.93-6.94L24,88Z" opacity="0.2"/><path d="M136,120v56a8,8,0,0,1-16,0V120a8,8,0,0,1,16,0Zm36.84-.8-5.6,56A8,8,0,0,0,174.4,184a7.32,7.32,0,0,0,.81,0,8,8,0,0,0,7.95-7.2l5.6-56a8,8,0,0,0-15.92-1.6Zm-89.68,0a8,8,0,0,0-15.92,1.6l5.6,56a8,8,0,0,0,8,7.2,7.32,7.32,0,0,0,.81,0,8,8,0,0,0,7.16-8.76ZM239.93,89.06,224.86,202.12A16.06,16.06,0,0,1,209,216H47a16.06,16.06,0,0,1-15.86-13.88L16.07,89.06A8,8,0,0,1,24,80H68.37L122,18.73a8,8,0,0,1,12,0L187.63,80H232a8,8,0,0,1,7.93,9.06ZM89.63,80h76.74L128,36.15ZM222.86,96H33.14L47,200H209Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 728 B After Width: | Height: | Size: 675 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,112v32a48,48,0,0,1-48,48H64a48,48,0,0,1-48-48V112a8,8,0,0,1,8-8H136v40h64V104h32A8,8,0,0,1,240,112Z" opacity="0.2"/><path d="M232,96H208a8,8,0,0,0-8-8H136a8,8,0,0,0-8,8H64V52A12,12,0,0,1,76,40a12.44,12.44,0,0,1,12.16,9.59,8,8,0,0,0,15.68-3.18A28.32,28.32,0,0,0,76,24,28,28,0,0,0,48,52V96H24A16,16,0,0,0,8,112v32a56.06,56.06,0,0,0,56,56v16a8,8,0,0,0,16,0V200h96v16a8,8,0,0,0,16,0V200a56.06,56.06,0,0,0,56-56V112A16,16,0,0,0,232,96Zm-40,8v32H144V104Zm40,40a40,40,0,0,1-40,40H64a40,40,0,0,1-40-40V112H128v32a8,8,0,0,0,8,8h64a8,8,0,0,0,8-8V112h24Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,104v40a48,48,0,0,1-48,48H64a48,48,0,0,1-48-48V104H136v40h64V104Z" opacity="0.2"/><path d="M240,96H208a8,8,0,0,0-8-8H136a8,8,0,0,0-8,8H64V52A12,12,0,0,1,76,40a12.44,12.44,0,0,1,12.16,9.59,8,8,0,0,0,15.68-3.18A28.32,28.32,0,0,0,76,24,28,28,0,0,0,48,52V96H16a8,8,0,0,0-8,8v40a56.06,56.06,0,0,0,56,56v16a8,8,0,0,0,16,0V200h96v16a8,8,0,0,0,16,0V200a56.06,56.06,0,0,0,56-56V104A8,8,0,0,0,240,96Zm-48,8v32H144V104Zm40,40a40,40,0,0,1-40,40H64a40,40,0,0,1-40-40V112H128v32a8,8,0,0,0,8,8h64a8,8,0,0,0,8-8V112h24Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 648 B After Width: | Height: | Size: 607 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M161.23,93.36a191.07,191.07,0,0,0-82-48.09,96.4,96.4,0,0,1,68.68-11.2A191.91,191.91,0,0,1,161.23,93.36Zm60.7,14.7a192.2,192.2,0,0,0-59.29-13.29,191,191,0,0,1,48.09,82,96.37,96.37,0,0,0,11.2-68.67ZM32.27,135.19a96,96,0,0,0,88.54,88.54,191.56,191.56,0,0,0,40.5-129A191.61,191.61,0,0,0,32.27,135.19Z" opacity="0.2"/><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm81.7,71.3a199.77,199.77,0,0,0-40.94-8.06A199.77,199.77,0,0,0,160.7,46.3,88.57,88.57,0,0,1,209.7,95.3ZM216,128a87.83,87.83,0,0,1-4.28,27.12,200.28,200.28,0,0,0-29.16-49.93,183.12,183.12,0,0,1,32.31,8.75A88.14,88.14,0,0,1,216,128ZM142.06,41.13a183.12,183.12,0,0,1,8.75,32.31,200.28,200.28,0,0,0-49.93-29.16,88.05,88.05,0,0,1,41.18-3.15ZM80.44,54a183.88,183.88,0,0,1,61.25,32.64A200.21,200.21,0,0,0,40.41,119.5,88.11,88.11,0,0,1,80.44,54ZM40.67,138.86a184.08,184.08,0,0,1,112.88-36.41,184.08,184.08,0,0,1-36.41,112.88A88.18,88.18,0,0,1,40.67,138.86Zm95.83,76.73a200.21,200.21,0,0,0,32.87-101.28A183.88,183.88,0,0,1,202,175.56,88.11,88.11,0,0,1,136.5,215.59Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,144v24H40V144a88,88,0,0,1,176,0Z" opacity="0.2"/><path d="M224,162.16V144a96.18,96.18,0,0,0-72.34-93,28,28,0,1,0-47.32,0A96.18,96.18,0,0,0,32,144v18.16A16,16,0,0,0,24,176v32a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V176A16,16,0,0,0,224,162.16ZM116,36a12,12,0,1,1,12,12A12,12,0,0,1,116,36Zm12,28a80.09,80.09,0,0,1,80,80v16H48V144A80.09,80.09,0,0,1,128,64Zm-8,112v32H80V176Zm16,0h40v32H136Zm-96,0H64v32H40Zm176,32H192V176h24v32Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 529 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,112v56H104V80H208A32,32,0,0,1,240,112Z" opacity="0.2"/><path d="M208,72H24V48A8,8,0,0,0,8,48V208a8,8,0,0,0,16,0V176H232v32a8,8,0,0,0,16,0V112A40,40,0,0,0,208,72ZM24,88H96v72H24Zm88,72V88h96a24,24,0,0,1,24,24v48Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M248,112v56H112V80H216A32,32,0,0,1,248,112Z" opacity="0.2"/><path d="M216,72H32V48a8,8,0,0,0-16,0V208a8,8,0,0,0,16,0V176H240v32a8,8,0,0,0,16,0V112A40,40,0,0,0,216,72ZM32,88h72v72H32Zm88,72V88h96a24,24,0,0,1,24,24v48Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 316 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M8,88h96v80H8Zm176,0v80h64V88Z" opacity="0.2"/><path d="M248,160H192V96h56a8,8,0,0,0,0-16H189.84A16,16,0,0,0,176,72H112a16,16,0,0,0-13.84,8H64a8,8,0,0,0-16,0H8A8,8,0,0,0,8,96H48v64H8a8,8,0,0,0,0,16H48a8,8,0,0,0,16,0H98.16A16,16,0,0,0,112,184h64a16,16,0,0,0,13.84-8H248a8,8,0,0,0,0-16ZM64,96H96v64H64Zm48,72V88h64v32H144a8,8,0,0,0,0,16h32v31.8c0,.07,0,.13,0,.2Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 460 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48Z" opacity="0.2"/><path d="M94,24C71.63,24,56,43.74,56,72s15.63,48,38,48,38-19.74,38-48S116.37,24,94,24Zm0,80c-17.37,0-22-20.11-22-32s4.63-32,22-32,22,20.11,22,32S111.37,104,94,104Zm72,32c-22.37,0-38,19.74-38,48s15.63,48,38,48,38-19.74,38-48S188.37,136,166,136Zm0,80c-17.37,0-22-20.11-22-32s4.63-32,22-32,22,20.11,22,32S183.37,216,166,216ZM145,49.22a8,8,0,0,1,3.11-10.88l24-13.33A8,8,0,0,1,184,32v80a8,8,0,0,1-16,0V45.6l-12.12,6.73A8,8,0,0,1,145,49.22ZM104,144v80a8,8,0,0,1-16,0V157.6l-12.12,6.73a8,8,0,0,1-7.76-14l24-13.33A8,8,0,0,1,104,144Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 736 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M184,132a56,56,0,1,1-56-56A56,56,0,0,1,184,132Z" opacity="0.2"/><path d="M185.68,104.28q-1.4-2.88-3.06-5.6a60,60,0,0,0-26.92-78,8,8,0,0,0-7.4,14.19A44,44,0,0,1,170.72,84.4a63.85,63.85,0,0,0-85.46,0A44,44,0,0,1,107.7,34.87a8,8,0,1,0-7.4-14.19,60,60,0,0,0-26.93,78,62.59,62.59,0,0,0-3.05,5.58A60.07,60.07,0,0,0,16,164a8,8,0,0,0,16,0,44.09,44.09,0,0,1,32.89-42.58A63.94,63.94,0,0,0,109,193.11a44,44,0,0,1-56.65,8,8,8,0,1,0-8.62,13.47A60,60,0,0,0,126.74,196l1.26,0,1.26,0a60,60,0,0,0,83.05,18.59,8,8,0,1,0-8.62-13.47,44,44,0,0,1-56.65-8,63.94,63.94,0,0,0,44.07-71.69A44.09,44.09,0,0,1,224,164a8,8,0,0,0,16,0A60.07,60.07,0,0,0,185.68,104.28ZM128,84a47.91,47.91,0,0,1,35.56,15.79,44,44,0,0,1-71.13,0A47.89,47.89,0,0,1,128,84Zm.12,49.92-.12.2-.12-.2h.24ZM80,132a47.6,47.6,0,0,1,1.44-11.65,44,44,0,0,1,36,58.46A48.07,48.07,0,0,1,80,132Zm58.57,46.81a44,44,0,0,1,36-58.46,48,48,0,0,1-36,58.46Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 983 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,80,208,96v24a96,96,0,0,1-96,96H8L104,96V76A52,52,0,0,1,206.33,62.89Z" opacity="0.2"/><path d="M176,68a12,12,0,1,1-12-12A12,12,0,0,1,176,68Zm-50.88,61.85a8,8,0,0,0-11.27,1l-40,48a8,8,0,0,0,12.3,10.24l40-48A8,8,0,0,0,125.12,129.85ZM240,80a8,8,0,0,1-3.56,6.66L216,100.28V120A104.11,104.11,0,0,1,112,224H8a8,8,0,0,1-6.25-13L96,93.19V76A60,60,0,0,1,213.21,57.86l23.23,15.48A8,8,0,0,1,240,80Zm-22.42,0L201.9,69.54a8,8,0,0,1-3.31-4.64A44,44,0,0,0,112,76V96a8,8,0,0,1-1.75,5L24.64,208H112a88.1,88.1,0,0,0,88-88V96a8,8,0,0,1,3.56-6.66Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,80,208,96v24a96,96,0,0,1-96,96H24a8,8,0,0,1-6.25-13L104,99.52V76.89c0-28.77,23-52.75,51.74-52.89a52,52,0,0,1,50.59,38.89Z" opacity="0.2"/><path d="M176,68a12,12,0,1,1-12-12A12,12,0,0,1,176,68Zm64,12a8,8,0,0,1-3.56,6.66L216,100.28V120A104.11,104.11,0,0,1,112,224H24a16,16,0,0,1-12.49-26l.1-.12L96,96.63V76.89C96,43.47,122.79,16.16,155.71,16H156a60,60,0,0,1,57.21,41.86l23.23,15.48A8,8,0,0,1,240,80Zm-22.42,0L201.9,69.54a8,8,0,0,1-3.31-4.64A44,44,0,0,0,156,32h-.22C131.64,32.12,112,52.25,112,76.89V99.52a8,8,0,0,1-1.85,5.13L24,208h26.9l70.94-85.12a8,8,0,1,1,12.29,10.24L71.75,208H112a88.1,88.1,0,0,0,88-88V96a8,8,0,0,1,3.56-6.66Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 631 B After Width: | Height: | Size: 732 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,64V200H48a24,24,0,0,1,0-48H64V64Z" opacity="0.2"/><path d="M232,56H72V40a8,8,0,0,0-8-8H48A32,32,0,0,0,16,64V176a32,32,0,0,0,32,32H232a8,8,0,0,0,8-8V64A8,8,0,0,0,232,56ZM32,64A16,16,0,0,1,48,48h8v96H48a31.82,31.82,0,0,0-16,4.29ZM224,192H48a16,16,0,0,1,0-32H64a8,8,0,0,0,8-8V72H224ZM104,136a8,8,0,0,0,0,16h16v8a8,8,0,0,0,16,0v-8h24v8a8,8,0,0,0,16,0v-8h16a8,8,0,0,0,0-16H176V120h16a8,8,0,0,0,0-16H176V96a8,8,0,0,0-16,0v8H136V96a8,8,0,0,0-16,0v8H104a8,8,0,0,0,0,16h16v16Zm32-16h24v16H136Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 589 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M184,80l-64,48V32ZM120,224l64-48-64-48Z" opacity="0.2"/><path d="M188.8,169.6,133.33,128,188.8,86.4a8,8,0,0,0,0-12.8l-64-48A8,8,0,0,0,112,32v80L60.8,73.6a8,8,0,0,0-9.6,12.8L106.67,128,51.2,169.6a8,8,0,1,0,9.6,12.8L112,144v80a8,8,0,0,0,12.8,6.4l64-48a8,8,0,0,0,0-12.8ZM128,48l42.67,32L128,112Zm0,160V144l42.67,32ZM52,140a12,12,0,1,1,12-12A12,12,0,0,1,52,140Zm156-12a12,12,0,1,1-12-12A12,12,0,0,1,208,128Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M192,80l-64,48V32ZM128,224l64-48-64-48Z" opacity="0.2"/><path d="M196.8,169.6,141.33,128,196.8,86.4a8,8,0,0,0,0-12.8l-64-48A8,8,0,0,0,120,32v80L68.8,73.6a8,8,0,0,0-9.6,12.8L114.67,128,59.2,169.6a8,8,0,1,0,9.6,12.8L120,144v80a8,8,0,0,0,12.8,6.4l64-48a8,8,0,0,0,0-12.8ZM136,48l42.67,32L136,112Zm0,160V144l42.67,32ZM60,140a12,12,0,1,1,12-12A12,12,0,0,1,60,140Zm156-12a12,12,0,1,1-12-12A12,12,0,0,1,216,128Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 503 B After Width: | Height: | Size: 503 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M120,128l64,48-64,48Zm0-96v96l64-48Z" opacity="0.2"/><path d="M213.92,210.62l-160-176A8,8,0,1,0,42.08,45.38l70.84,77.93L51.2,169.6a8,8,0,1,0,9.6,12.8L112,144v80a8,8,0,0,0,12.8,6.4l50.83-38.12,26.45,29.1a8,8,0,1,0,11.84-10.76ZM128,208V144l11.73,8.8,25.08,27.59ZM112,71.63V32a8,8,0,0,1,12.8-6.4l64,48a8,8,0,0,1,0,12.8l-33.53,25.15a8,8,0,0,1-9.6-12.8l25-18.75L128,48V71.63a8,8,0,0,1-16,0Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,128l64,48-64,48Zm0-96v96l64-48Z" opacity="0.2"/><path d="M221.92,210.62l-160-176A8,8,0,0,0,50.08,45.38l70.84,77.93L59.2,169.6a8,8,0,1,0,9.6,12.8L120,144v80a8,8,0,0,0,12.8,6.4l50.83-38.12,26.45,29.1a8,8,0,1,0,11.84-10.76ZM136,208V144l11.73,8.8,25.08,27.59ZM120,71.63V32a8,8,0,0,1,12.8-6.4l64,48a8,8,0,0,1,0,12.8l-33.53,25.15a8,8,0,0,1-9.6-12.8l25-18.75L136,48V71.63a8,8,0,0,1-16,0Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 485 B After Width: | Height: | Size: 485 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M120,128l64,48-64,48Zm0-96v96l55.47-41.6a8,8,0,0,0,0-12.8Z" opacity="0.2"/><path d="M188.8,169.6,133.33,128l23.47-17.6a8,8,0,0,0-9.6-12.8L128,112V48l19.2,14.4a8,8,0,1,0,9.6-12.8l-32-24A8,8,0,0,0,112,32v80L60.8,73.6a8,8,0,0,0-9.6,12.8L106.67,128,51.2,169.6a8,8,0,1,0,9.6,12.8L112,144v80a8,8,0,0,0,12.8,6.4l64-48a8,8,0,0,0,0-12.8ZM128,208V144l42.67,32ZM237.66,98.34a8,8,0,0,1-11.32,11.32L208,91.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L196.69,80,178.34,61.66a8,8,0,0,1,11.32-11.32L208,68.69l18.34-18.35a8,8,0,0,1,11.32,11.32L219.31,80Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M176,176l-64,48V128ZM167.47,73.6,112,32v96l55.47-41.6A8,8,0,0,0,167.47,73.6Z" opacity="0.2"/><path d="M180.8,169.6,125.33,128l23.47-17.6a8,8,0,0,0-9.6-12.8L120,112V48l19.2,14.4a8,8,0,1,0,9.6-12.8l-32-24A8,8,0,0,0,104,32v80L52.8,73.6a8,8,0,0,0-9.6,12.8L98.67,128,43.2,169.6a8,8,0,1,0,9.6,12.8L104,144v80a8,8,0,0,0,12.8,6.4l64-48a8,8,0,0,0,0-12.8ZM120,208V144l42.67,32ZM237.66,98.34a8,8,0,0,1-11.32,11.32L208,91.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L196.69,80,178.34,61.66a8,8,0,0,1,11.32-11.32L208,68.69l18.34-18.35a8,8,0,0,1,11.32,11.32L219.31,80Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 630 B After Width: | Height: | Size: 647 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M184,80l-64,48V32ZM120,224l64-48-64-48Z" opacity="0.2"/><path d="M188.8,169.6,133.33,128,188.8,86.4a8,8,0,0,0,0-12.8l-64-48A8,8,0,0,0,112,32v80L60.8,73.6a8,8,0,0,0-9.6,12.8L106.67,128,51.2,169.6a8,8,0,1,0,9.6,12.8L112,144v80a8,8,0,0,0,12.8,6.4l64-48a8,8,0,0,0,0-12.8ZM128,48l42.67,32L128,112Zm0,160V144l42.67,32Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M192,80l-64,48V32ZM128,224l64-48-64-48Z" opacity="0.2"/><path d="M196.8,169.6,141.33,128,196.8,86.4a8,8,0,0,0,0-12.8l-64-48A8,8,0,0,0,120,32v80L68.8,73.6a8,8,0,0,0-9.6,12.8L114.67,128,59.2,169.6a8,8,0,1,0,9.6,12.8L120,144v80a8,8,0,0,0,12.8,6.4l64-48a8,8,0,0,0,0-12.8ZM136,48l42.67,32L136,112Zm0,160V144l42.67,32Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 412 B After Width: | Height: | Size: 412 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,125.82V160.1c-14.57,51.07-82.23,68.91-94.19,71.69a7.91,7.91,0,0,1-3.62,0C114.23,229,46.57,211.17,32,160.1V125.82a8,8,0,0,1,5.47-7.6L128,88l90.53,30.22A8,8,0,0,1,224,125.82Z" opacity="0.2"/><path d="M221.06,110.63,208,106.27V56a16,16,0,0,0-16-16H136V24a8,8,0,0,0-16,0V40H64A16,16,0,0,0,48,56v50.27l-13.06,4.36A16,16,0,0,0,24,125.82V160.1a7.73,7.73,0,0,0,.31,2.19c15.72,55.09,86.12,74.06,100.07,77.3a16.19,16.19,0,0,0,7.24,0c13.95-3.24,84.35-22.21,100.07-77.3a7.73,7.73,0,0,0,.31-2.19V125.82A16,16,0,0,0,221.06,110.63ZM64,56H192v44.93L130.53,80.41a8,8,0,0,0-5.06,0L64,100.93ZM216,158.94c-5.78,19-20.55,35.17-43.95,48.12A181.7,181.7,0,0,1,128,224a181.7,181.7,0,0,1-44-16.94C60.56,194.11,45.78,177.93,40,158.94V125.81l80-26.7V168a8,8,0,0,0,16,0V99.11l80,26.71Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,125.77V152c0,56-96,80-96,80s-96-24-96-80V125.77a8,8,0,0,1,5.47-7.59L128,88l90.53,30.18A8,8,0,0,1,224,125.77Z" opacity="0.2"/><path d="M221.06,110.59,208,106.23V56a16,16,0,0,0-16-16H136V24a8,8,0,0,0-16,0V40H64A16,16,0,0,0,48,56v50.23l-13.06,4.36A16,16,0,0,0,24,125.77V152c0,61.54,97.89,86.72,102.06,87.76a8,8,0,0,0,3.88,0C134.11,238.72,232,213.54,232,152V125.77A16,16,0,0,0,221.06,110.59ZM64,56H192v44.9L130.53,80.41a8,8,0,0,0-5.06,0L64,100.9Zm152,96c0,24.91-23.68,43-43.55,53.83A228.13,228.13,0,0,1,128,223.72,226.85,226.85,0,0,1,83.81,206C47.6,186.35,40,165.79,40,152V125.77L120,99.1V168a8,8,0,0,0,16,0V99.1l80,26.67Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 861 B After Width: | Height: | Size: 723 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M192,160A80,80,0,1,1,80,86.66V72a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8V86.66A80,80,0,0,1,192,160Z" opacity="0.2"/><path d="M248,32h0a8,8,0,0,0-8,8,52.66,52.66,0,0,1-3.57,17.39C232.38,67.22,225.7,72,216,72c-11.06,0-18.85-9.76-29.49-24.65C176,32.66,164.12,16,144,16c-16.39,0-29,8.89-35.43,25a66.07,66.07,0,0,0-3.9,15H88A16,16,0,0,0,72,72v9.59A88,88,0,0,0,112,248h1.59A88,88,0,0,0,152,81.59V72a16,16,0,0,0-16-16H120.88a46.76,46.76,0,0,1,2.69-9.37C127.62,36.78,134.3,32,144,32c11.06,0,18.85,9.76,29.49,24.65C184,71.34,195.88,88,216,88c16.39,0,29-8.89,35.43-25A68.69,68.69,0,0,0,256,40,8,8,0,0,0,248,32ZM140.8,94a72,72,0,1,1-57.6,0A8,8,0,0,0,88,86.66V72h48V86.66A8,8,0,0,0,140.8,94ZM111.89,209.32A8,8,0,0,1,104,216a8.52,8.52,0,0,1-1.33-.11,57.5,57.5,0,0,1-46.57-46.57,8,8,0,1,1,15.78-2.64,41.29,41.29,0,0,0,33.43,33.43A8,8,0,0,1,111.89,209.32Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 931 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,64V192a8,8,0,0,1-8,8H160a32,32,0,0,0-32,32V88a32,32,0,0,1,32-32h64A8,8,0,0,1,232,64Z" opacity="0.2"/><path d="M224,48H160a40,40,0,0,0-32,16A40,40,0,0,0,96,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H96a24,24,0,0,1,24,24,8,8,0,0,0,16,0,24,24,0,0,1,24-24h64a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48ZM96,192H32V64H96a24,24,0,0,1,24,24V200A39.81,39.81,0,0,0,96,192Zm128,0H160a39.81,39.81,0,0,0-24,8V88a24,24,0,0,1,24-24h64ZM160,88h40a8,8,0,0,1,0,16H160a8,8,0,0,1,0-16Zm48,40a8,8,0,0,1-8,8H160a8,8,0,0,1,0-16h40A8,8,0,0,1,208,128Zm0,32a8,8,0,0,1-8,8H160a8,8,0,0,1,0-16h40A8,8,0,0,1,208,160Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,56V200H160a32,32,0,0,0-32,32V88a32,32,0,0,1,32-32Z" opacity="0.2"/><path d="M232,48H160a40,40,0,0,0-32,16A40,40,0,0,0,96,48H24a8,8,0,0,0-8,8V200a8,8,0,0,0,8,8H96a24,24,0,0,1,24,24,8,8,0,0,0,16,0,24,24,0,0,1,24-24h72a8,8,0,0,0,8-8V56A8,8,0,0,0,232,48ZM96,192H32V64H96a24,24,0,0,1,24,24V200A39.81,39.81,0,0,0,96,192Zm128,0H160a39.81,39.81,0,0,0-24,8V88a24,24,0,0,1,24-24h64ZM160,88h40a8,8,0,0,1,0,16H160a8,8,0,0,1,0-16Zm48,40a8,8,0,0,1-8,8H160a8,8,0,0,1,0-16h40A8,8,0,0,1,208,128Zm0,32a8,8,0,0,1-8,8H160a8,8,0,0,1,0-16h40A8,8,0,0,1,208,160Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 691 B After Width: | Height: | Size: 643 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,80V200H160a32,32,0,0,0-32,32,32,32,0,0,0-32-32H24V80H96a32,32,0,0,1,32,32,32,32,0,0,1,32-32Z" opacity="0.2"/><path d="M232,72H160a40,40,0,0,0-32,16A40,40,0,0,0,96,72H24a8,8,0,0,0-8,8V200a8,8,0,0,0,8,8H96a24,24,0,0,1,24,24,8,8,0,0,0,16,0,24,24,0,0,1,24-24h72a8,8,0,0,0,8-8V80A8,8,0,0,0,232,72ZM96,192H32V88H96a24,24,0,0,1,24,24v88A39.81,39.81,0,0,0,96,192Zm128,0H160a39.81,39.81,0,0,0-24,8V112a24,24,0,0,1,24-24h64ZM89.6,43.19a48,48,0,0,1,76.8,0,8,8,0,0,1-12.79,9.62,32,32,0,0,0-51.22,0A8,8,0,1,1,89.6,43.19Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 612 B |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,64V192a8,8,0,0,1-8,8H160a32,32,0,0,0-32,32,32,32,0,0,0-32-32H32a8,8,0,0,1-8-8V64a8,8,0,0,1,8-8H96a32,32,0,0,1,32,32,32,32,0,0,1,32-32h64A8,8,0,0,1,232,64Z" opacity="0.2"/><path d="M224,48H160a40,40,0,0,0-32,16A40,40,0,0,0,96,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H96a24,24,0,0,1,24,24,8,8,0,0,0,16,0,24,24,0,0,1,24-24h64a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48ZM96,192H32V64H96a24,24,0,0,1,24,24V200A39.81,39.81,0,0,0,96,192Zm128,0H160a39.81,39.81,0,0,0-24,8V88a24,24,0,0,1,24-24h64Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,56V200H160a32,32,0,0,0-32,32,32,32,0,0,0-32-32H24V56H96a32,32,0,0,1,32,32,32,32,0,0,1,32-32Z" opacity="0.2"/><path d="M232,48H160a40,40,0,0,0-32,16A40,40,0,0,0,96,48H24a8,8,0,0,0-8,8V200a8,8,0,0,0,8,8H96a24,24,0,0,1,24,24,8,8,0,0,0,16,0,24,24,0,0,1,24-24h72a8,8,0,0,0,8-8V56A8,8,0,0,0,232,48ZM96,192H32V64H96a24,24,0,0,1,24,24V200A39.81,39.81,0,0,0,96,192Zm128,0H160a39.81,39.81,0,0,0-24,8V88a24,24,0,0,1,24-24h64Z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 595 B After Width: | Height: | Size: 519 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M215.52,88.48l-127,127a96.47,96.47,0,0,1-48-48l127-127A96.47,96.47,0,0,1,215.52,88.48Z" opacity="0.2"/><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm56.28,36.41L60.4,184.28A88.33,88.33,0,0,1,50.21,169.1L169.1,50.21A87.8,87.8,0,0,1,184.28,60.41Zm11.31,11.31a87.8,87.8,0,0,1,10.2,15.18L86.9,205.79a87.8,87.8,0,0,1-15.18-10.2ZM128,40a87.81,87.81,0,0,1,25.05,3.64L43.64,153.05A88,88,0,0,1,128,40Zm0,176a87.81,87.81,0,0,1-25-3.64L212.36,103A88,88,0,0,1,128,216Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 577 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,120a96,96,0,0,1-56,87.3V216a8,8,0,0,1-8,8H96a8,8,0,0,1-8-8v-8.7A96,96,0,0,1,32,120Z" opacity="0.2"/><path d="M81.77,55c5.35-6.66,6.67-11.16,6.12-13.14-.42-1.49-2.41-2.26-2.43-2.26A8,8,0,0,1,88,24a8.11,8.11,0,0,1,2.38.36c1,.31,9.91,3.33,12.79,12.76,2.46,8.07-.55,17.45-8.94,27.89-5.35,6.66-6.67,11.16-6.12,13.14.42,1.49,2.37,2.24,2.39,2.25A8,8,0,0,1,88,96a8.11,8.11,0,0,1-2.38-.36c-1-.31-9.91-3.33-12.79-12.76C70.37,74.81,73.38,65.43,81.77,55Zm31.06,27.89c2.88,9.43,11.79,12.45,12.79,12.76A8.11,8.11,0,0,0,128,96a8,8,0,0,0,2.5-15.6s-2-.76-2.39-2.25c-.55-2,.77-6.48,6.12-13.14,8.39-10.44,11.4-19.82,8.94-27.89-2.88-9.43-11.78-12.45-12.79-12.76A8.11,8.11,0,0,0,128,24a8,8,0,0,0-2.54,15.59s2,.77,2.43,2.26c.55,2-.77,6.48-6.12,13.14C113.38,65.43,110.37,74.81,112.83,82.88Zm40,0c2.88,9.43,11.79,12.45,12.79,12.76A8.11,8.11,0,0,0,168,96a8,8,0,0,0,2.5-15.6s-2-.76-2.39-2.25c-.55-2,.77-6.48,6.12-13.14,8.39-10.44,11.4-19.82,8.94-27.89-2.88-9.43-11.78-12.45-12.79-12.76A8.11,8.11,0,0,0,168,24a8,8,0,0,0-2.54,15.59s2,.77,2.43,2.26c.55,2-.77,6.48-6.12,13.14C153.38,65.43,150.37,74.81,152.83,82.88ZM232,120a104.35,104.35,0,0,1-56,92.28V216a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-3.72A104.35,104.35,0,0,1,24,120a8,8,0,0,1,8-8H224A8,8,0,0,1,232,120Zm-16.37,8H40.37a88.29,88.29,0,0,0,51,72A8,8,0,0,1,96,207.29V216h64v-8.71a8,8,0,0,1,4.66-7.27A88.29,88.29,0,0,0,215.63,128Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |